Skip to content
Snippets Groups Projects
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
views.py 5.68 KiB
"""
Handles GET / POST requests by users.
"""


from rest_framework import viewsets
from rest_framework import views
from rest_framework.response import Response
from rest_framework import status
#from serializers import TriggerSerializer
from rest_framework.renderers import JSONRenderer
from rest_framework.parsers import JSONParser
from rest_framework_xml.parsers import XMLParser
from rest_framework_xml.renderers import XMLRenderer

from io import BytesIO
from rest_framework.fields import CurrentUserDefault
from lxml import etree
from StringIO import StringIO

from lofar.triggerservices.trigger_service_rpc import TriggerRPC
from lofar.specificationservices.specification_service_rpc import SpecificationRPC

from lofar.messaging import ToBus, EventMessage

import logging
import traceback
logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger(__name__)

triggerrpc = TriggerRPC()
specrpc = SpecificationRPC()

from config import TRIGGER_SUBMISSION_NOTIFICATION_BUSNAME, TRIGGER_SUBMISSION_NOTIFICATION_SUBJECT
notification_bus = ToBus(address=TRIGGER_SUBMISSION_NOTIFICATION_BUSNAME, broker=None)


class TriggerListView(views.APIView):

    def __init__(self, **kwargs):
        super(TriggerListView, self).__init__(**kwargs)
        notification_bus.open()

    def get(self,request, format=None, **kwargs):
        logger.debug('got GET from -> '+str(request.META['REMOTE_ADDR']))
        return Response("Listing not implemented yet, sorry! Post trigger XML on this URL to add a new trigger.", status=status.HTTP_501_NOT_IMPLEMENTED)



    def post(self, request, format=None, **kwargs):
        IP = str(request.META['REMOTE_ADDR'])
        logger.debug('got POST from -> '+IP)
        #logger.debug('received text -> '+str(request.body))
        #logger.debug('received data -> '+str(request.data))
        logger.debug('from user -> '+str( request.user))
        self._sendNotification(str(request.user), IP)


        # OPTIONALLY USE DATA MODEL:
        #serializer = TriggerSerializer(data=request.data)
        #logger.debug('data is valid -> ' +str(serializer.is_valid()))
        #if serializer.is_valid():
        #    id = serializer.save(request.user)
        #    #r = serializer.validated_data
        #    #r["trigger_id"]=id

        # EITHER: RENDER FRESH XML FROM PARSED DATA:
        #xml = XMLRenderer().render(request.data) # ! django replaces the root element
        #xml = self._renameXMLroot(xml, "lofar:trigger")
        #print xml

        # OR: USE RECEIVED XML DIRECTLY:
        xml = str(request.body)

        logger.debug('calling trigger handler')
        try:
            id = self._handle_trigger(str(request.user), IP, xml)
        except Exception as err:
            traceback.print_exc()
            return Response('Provided data has some issues! (Details: '+str(err)+")",  status=status.HTTP_400_BAD_REQUEST)
            # for use with data model:  return Response('Provided data has some issues: ' +str(serializer.errors)+" (Accepted were: "+str(serializer.data)+")", status=status.HTTP_400_BAD_REQUEST)


        return Response(id, status=status.HTTP_201_CREATED)

    def _renameXMLroot(self, xml, newname):
        root = etree.parse(StringIO(xml))
        root.tag = newname
        return etree.tostring(root)

    def _handle_trigger(self, user, host, xml):
        return triggerrpc.handle_trigger(user, host, xml)

    def _sendNotification(self, user, IP):
        msg = EventMessage(context=TRIGGER_SUBMISSION_NOTIFICATION_SUBJECT, content="Trigger received by "+str(user)+" (IP:"+IP+")")
        try:
            notification_bus.send(msg)
        except Exception as err:
            logger.error("Could not send notification ->" + str(err))




class TriggerView(views.APIView):


    #def post(self, request, format=None, **kwargs):
    #    return Response("It is not possible to alter an existing trigger (i.e. POST for an existing trigger ID), sorry!", status=status.HTTP_405_METHOD_NOT_ALLOWED)


    def get(self,request, format=None, **kwargs):
        logger.debug('got GET from: '+str(request.META['REMOTE_ADDR']))
        try:
            if 'pk' in kwargs:
                identifier = kwargs.get('pk')
                logger.info('requested id is: '+str(identifier))
                logger.info('requesting user is:'+ str(request.user))

                xml = self._get_specification(str(request.user), str(identifier))

                # EITHER DIRECT RESPONSE:
                return Response(xml)

                # OR USE DATA MODEL:
                # data = XMLParser().parse(BytesIO(xml))

                # example: data injection with validation:
                # data['view_injected_get'] = 'pre-serializing'

                #serializer = TriggerSerializer(data=data)
                #logger.debug('returning valid data:' + str(serializer.is_valid()))
                #r = serializer.validated_data

                # example: data injection after validation:
                # r['view_injected_get_2'] = 'post-validation'

                #return Response(r)
            else:
                return Response("No ID provided!")
        except Exception as err:
            print err
            return Response("Unable to retrieve the requested trigger, sorry!", status=status.HTTP_404_NOT_FOUND)


    def _get_specification(self, user, identifier):

        logger.info("Getting spec from specification service")

        response = specrpc.get_specification(user, identifier)
        return response

        # test json data:
        #json = '{"project_id": "p1", "triggerid": "t1", "triggerxml": "<trigger />", "status": "new", "momid": "m1", "sasid": "s1", "submittedby":"user"}'
        #stream = BytesIO(json)
        #data = JSONParser().parse(stream)
        # return XMLRenderer().render(data)