src/notes/api/views/sync.py
author ymh <ymh.work@gmail.com>
Thu, 03 Aug 2017 19:11:06 +0200
changeset 135 b5aafa462956
parent 132 906a6c7c7943
permissions -rw-r--r--
Cleaning session form. The group and protocol are no longer editable. Removing cruft

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()
        })