Compare commits
2 Commits
cff1a183cf
...
0ea54a5ee2
Author | SHA1 | Date |
---|---|---|
Brian S. Stephan | 0ea54a5ee2 | |
Brian S. Stephan | ffcdc3f8d8 |
|
@ -0,0 +1,18 @@
|
||||||
|
# Generated by Django 3.2.18 on 2023-03-01 00:26
|
||||||
|
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('dispatch', '0006_xmlrpc_settings'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RenameField(
|
||||||
|
model_name='dispatcheraction',
|
||||||
|
old_name='type',
|
||||||
|
new_name='action_type',
|
||||||
|
),
|
||||||
|
]
|
|
@ -38,10 +38,10 @@ class DispatcherAction(models.Model):
|
||||||
)
|
)
|
||||||
|
|
||||||
dispatcher = models.ForeignKey('Dispatcher', related_name='actions', on_delete=models.CASCADE)
|
dispatcher = models.ForeignKey('Dispatcher', related_name='actions', on_delete=models.CASCADE)
|
||||||
type = models.CharField(max_length=16, choices=TYPE_CHOICES)
|
action_type = models.CharField(max_length=16, choices=TYPE_CHOICES)
|
||||||
destination = models.CharField(max_length=200)
|
destination = models.CharField(max_length=200)
|
||||||
include_key = models.BooleanField(default=False)
|
include_key = models.BooleanField(default=False)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
"""Provide string representation."""
|
"""Provide string representation."""
|
||||||
return "{0:s} -> {1:s} {2:s}".format(self.dispatcher.key, self.type, self.destination)
|
return "{0:s} -> {1:s} {2:s}".format(self.dispatcher.key, self.action_type, self.destination)
|
||||||
|
|
|
@ -12,7 +12,7 @@ class DispatcherActionSerializer(serializers.ModelSerializer):
|
||||||
"""Meta options."""
|
"""Meta options."""
|
||||||
|
|
||||||
model = DispatcherAction
|
model = DispatcherAction
|
||||||
fields = ('id', 'dispatcher', 'type', 'destination')
|
fields = ('id', 'dispatcher', 'action_type', 'destination')
|
||||||
|
|
||||||
|
|
||||||
class DispatcherSerializer(serializers.ModelSerializer):
|
class DispatcherSerializer(serializers.ModelSerializer):
|
||||||
|
|
|
@ -12,5 +12,5 @@ urlpatterns = [
|
||||||
path('api/dispatchers/<key>/message', DispatchMessageByKey.as_view(), name='dispatch_api_dispatch_message'),
|
path('api/dispatchers/<key>/message', DispatchMessageByKey.as_view(), name='dispatch_api_dispatch_message'),
|
||||||
|
|
||||||
path('api/actions/', DispatcherActionList.as_view(), name='dispatch_api_actions'),
|
path('api/actions/', DispatcherActionList.as_view(), name='dispatch_api_actions'),
|
||||||
path('api/actions/<pk>/', DispatcherActionDetail.as_view(), name='dispatch_api_action_detail'),
|
path('api/actions/<int:pk>/', DispatcherActionDetail.as_view(), name='dispatch_api_action_detail'),
|
||||||
]
|
]
|
||||||
|
|
|
@ -28,6 +28,8 @@ class HasSendMessagePermission(IsAuthenticated):
|
||||||
class DispatcherList(generics.ListAPIView):
|
class DispatcherList(generics.ListAPIView):
|
||||||
"""List all dispatchers."""
|
"""List all dispatchers."""
|
||||||
|
|
||||||
|
permission_classes = (IsAuthenticated,)
|
||||||
|
|
||||||
queryset = Dispatcher.objects.all()
|
queryset = Dispatcher.objects.all()
|
||||||
serializer_class = DispatcherSerializer
|
serializer_class = DispatcherSerializer
|
||||||
|
|
||||||
|
@ -35,6 +37,8 @@ class DispatcherList(generics.ListAPIView):
|
||||||
class DispatcherDetail(generics.RetrieveAPIView):
|
class DispatcherDetail(generics.RetrieveAPIView):
|
||||||
"""Detail the given dispatcher."""
|
"""Detail the given dispatcher."""
|
||||||
|
|
||||||
|
permission_classes = (IsAuthenticated,)
|
||||||
|
|
||||||
queryset = Dispatcher.objects.all()
|
queryset = Dispatcher.objects.all()
|
||||||
serializer_class = DispatcherSerializer
|
serializer_class = DispatcherSerializer
|
||||||
|
|
||||||
|
@ -71,19 +75,19 @@ class DispatchMessage(generics.GenericAPIView):
|
||||||
else:
|
else:
|
||||||
text = message.data['message']
|
text = message.data['message']
|
||||||
|
|
||||||
if action.type == DispatcherAction.PRIVMSG_TYPE:
|
if action.action_type == DispatcherAction.PRIVMSG_TYPE:
|
||||||
# connect over XML-RPC and send
|
# connect over XML-RPC and send
|
||||||
try:
|
try:
|
||||||
bot_url = 'http://{0:s}:{1:d}/'.format(dispatcher.bot_xmlrpc_host, dispatcher.bot_xmlrpc_port)
|
bot_url = 'http://{0:s}:{1:d}/'.format(dispatcher.bot_xmlrpc_host, dispatcher.bot_xmlrpc_port)
|
||||||
bot = xmlrpc.client.ServerProxy(bot_url, allow_none=True)
|
bot = xmlrpc.client.ServerProxy(bot_url, allow_none=True)
|
||||||
log.debug("sending '%s' to channel %s", text, action.destination)
|
log.debug("sending '%s' to channel %s", text, action.destination)
|
||||||
bot.reply(None, text, False, action.destination)
|
bot.reply(None, text, False, action.destination)
|
||||||
except Exception as e:
|
except xmlrpc.client.Fault as xmlex:
|
||||||
new_data = copy.deepcopy(message.data)
|
new_data = copy.deepcopy(message.data)
|
||||||
new_data['status'] = "FAILED - {0:s}".format(str(e))
|
new_data['status'] = "FAILED - {0:s}".format(str(xmlex))
|
||||||
new_message = self.serializer_class(data=new_data)
|
new_message = self.serializer_class(data=new_data)
|
||||||
return Response(new_message.initial_data)
|
return Response(new_message.initial_data)
|
||||||
elif action.type == DispatcherAction.FILE_TYPE:
|
elif action.action_type == DispatcherAction.FILE_TYPE:
|
||||||
# write to file
|
# write to file
|
||||||
filename = os.path.abspath(action.destination)
|
filename = os.path.abspath(action.destination)
|
||||||
log.debug("sending '%s' to file %s", text, filename)
|
log.debug("sending '%s' to file %s", text, filename)
|
||||||
|
@ -107,6 +111,8 @@ class DispatchMessageByKey(DispatchMessage):
|
||||||
class DispatcherActionList(generics.ListAPIView):
|
class DispatcherActionList(generics.ListAPIView):
|
||||||
"""List all dispatchers."""
|
"""List all dispatchers."""
|
||||||
|
|
||||||
|
permission_classes = (IsAuthenticated,)
|
||||||
|
|
||||||
queryset = DispatcherAction.objects.all()
|
queryset = DispatcherAction.objects.all()
|
||||||
serializer_class = DispatcherActionSerializer
|
serializer_class = DispatcherActionSerializer
|
||||||
|
|
||||||
|
@ -114,5 +120,7 @@ class DispatcherActionList(generics.ListAPIView):
|
||||||
class DispatcherActionDetail(generics.RetrieveAPIView):
|
class DispatcherActionDetail(generics.RetrieveAPIView):
|
||||||
"""Detail the given dispatcher."""
|
"""Detail the given dispatcher."""
|
||||||
|
|
||||||
|
permission_classes = (IsAuthenticated,)
|
||||||
|
|
||||||
queryset = DispatcherAction.objects.all()
|
queryset = DispatcherAction.objects.all()
|
||||||
serializer_class = DispatcherActionSerializer
|
serializer_class = DispatcherActionSerializer
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
"""Test the dispatch package's webservice."""
|
"""Test the dispatch package's webservice."""
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
from rest_framework.status import HTTP_200_OK
|
from rest_framework.status import HTTP_200_OK, HTTP_403_FORBIDDEN
|
||||||
from rest_framework.test import APITestCase
|
from rest_framework.test import APITestCase
|
||||||
|
|
||||||
from dispatch.models import Dispatcher, DispatcherAction
|
from dispatch.models import Dispatcher, DispatcherAction
|
||||||
|
@ -27,3 +27,18 @@ class DispatchAPITest(APITestCase):
|
||||||
resp = self.client.get('/dispatch/api/actions/')
|
resp = self.client.get('/dispatch/api/actions/')
|
||||||
self.assertEqual(resp.status_code, HTTP_200_OK)
|
self.assertEqual(resp.status_code, HTTP_200_OK)
|
||||||
self.assertEqual(len(resp.json()), DispatcherAction.objects.count())
|
self.assertEqual(len(resp.json()), DispatcherAction.objects.count())
|
||||||
|
|
||||||
|
def test_unauthed_dispatch_object_retrieval(self):
|
||||||
|
"""Test that the list endpoints require authentication."""
|
||||||
|
client = self.client_class()
|
||||||
|
resp = client.get('/dispatch/api/dispatchers/')
|
||||||
|
self.assertEqual(resp.status_code, HTTP_403_FORBIDDEN)
|
||||||
|
resp = client.get('/dispatch/api/dispatchers/111/')
|
||||||
|
self.assertEqual(resp.status_code, HTTP_403_FORBIDDEN)
|
||||||
|
resp = client.get('/dispatch/api/dispatchers/fake/')
|
||||||
|
self.assertEqual(resp.status_code, HTTP_403_FORBIDDEN)
|
||||||
|
|
||||||
|
resp = client.get('/dispatch/api/actions/')
|
||||||
|
self.assertEqual(resp.status_code, HTTP_403_FORBIDDEN)
|
||||||
|
resp = client.get('/dispatch/api/actions/111/')
|
||||||
|
self.assertEqual(resp.status_code, HTTP_403_FORBIDDEN)
|
||||||
|
|
Loading…
Reference in New Issue