src/notes/api/views/sync.py
author ymh <ymh.work@gmail.com>
Fri, 30 Nov 2018 10:53:15 +0100
changeset 183 f8f3af9e5c83
parent 132 906a6c7c7943
permissions -rw-r--r--
Change the settings to avoid using Session authentication for rest framework as it raise exceptions in case client and backend are on the same domain On the filter, adapt to take into account new version of django_filters

import datetime
import logging

from auditlog.models import LogEntry
from django.utils import timezone
from notes.models import Note, Session
from rest_framework import permissions
from rest_framework.response import Response
from rest_framework.views import APIView

logger = logging.getLogger(__name__)

class ListLogsView(APIView):
    """
    View to list tle log of changes on Note and Sessions.

    * Only registered users are able to access this view.
    * the results are filtered by connected user
    """
    permission_classes = (permissions.IsAuthenticated,)

    def __filter_object(self, model, user, modified_since, client_id):
        """
        Log entries are filtered by model, actor and timestamp.
        If a client id is given, log entries from this client are ignored.
        """
        log_entries = LogEntry.objects.get_for_model(model).filter(actor=user)
        if modified_since:
            log_entries = log_entries.filter(timestamp__gte=modified_since)
        if client_id:
            log_entries = log_entries.exclude(client=client_id)
        return log_entries.order_by('timestamp')

    def __process_log_entries(self, model, user, modified_since, client_id):
        '''
        Process log entries
        '''
        log_entries = self.__filter_object(model, user, modified_since, client_id)

        res = {}
        for log_entry in log_entries:
            ext_id = log_entry.additional_data.get('ext_id')
            if not ext_id:
                continue
            sync_entry = res.get(ext_id, {})
            new_action = {
                (None                  , LogEntry.Action.CREATE): LogEntry.Action.CREATE,
                (LogEntry.Action.CREATE, LogEntry.Action.CREATE): LogEntry.Action.CREATE,
                (LogEntry.Action.UPDATE, LogEntry.Action.CREATE): LogEntry.Action.UPDATE,
                (LogEntry.Action.DELETE, LogEntry.Action.CREATE): LogEntry.Action.UPDATE,

                (None                  , LogEntry.Action.UPDATE): LogEntry.Action.UPDATE,
                (LogEntry.Action.CREATE, LogEntry.Action.UPDATE): LogEntry.Action.CREATE,
                (LogEntry.Action.UPDATE, LogEntry.Action.UPDATE): LogEntry.Action.UPDATE,
                (LogEntry.Action.DELETE, LogEntry.Action.UPDATE): LogEntry.Action.DELETE,

                (None                  , LogEntry.Action.DELETE): LogEntry.Action.DELETE,
                (LogEntry.Action.CREATE, LogEntry.Action.DELETE): None,
                (LogEntry.Action.UPDATE, LogEntry.Action.DELETE): LogEntry.Action.DELETE,
                (LogEntry.Action.DELETE, LogEntry.Action.DELETE): LogEntry.Action.DELETE,

            } [(sync_entry.get('action'), log_entry.action)]
            if new_action is None:
                del res[ext_id]
            else:
                res[ext_id] = {
                    'type': log_entry.content_type.model,
                    'ext_id': ext_id,
                    'action': new_action,
                    'timestamp': log_entry.timestamp
                }
        return res

    def get(self, request, format=None):
        """
        Return an aggregations of all changes.
        """
        modified_since_str = request.query_params.get('modified_since', None)
        modified_since = None
        if modified_since_str is not None:
            modified_since = datetime.datetime.fromtimestamp(
                float(modified_since_str),
                timezone.utc
            )

        user = request.user
        client_id = request.META.get('HTTP_AUDITLOG_CLIENT', None)
        res_sessions = self.__process_log_entries(Session, user, modified_since, client_id)
        res_notes = self.__process_log_entries(Note, user, modified_since, client_id)

        return Response({
            'sessions': res_sessions.values(),
            'notes': res_notes.values()
        })