From c634caa8846537b73dcae80f8a6d33e7943c1d95 Mon Sep 17 00:00:00 2001 From: Zambom Date: Thu, 29 Dec 2016 18:17:56 -0200 Subject: [PATCH] Adding Log app --- log/admin.py | 8 +++++++- log/decorators.py | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ log/middleware.py | 47 +++++++++++++++++++++++++++++++++++++++++++++++ log/migrations/0001_initial.py | 36 ++++++++++++++++++++++++++++++++++++ log/mixins.py | 24 ++++++++++++++++++++++++ log/models.py | 19 ++++++++++++++++++- 6 files changed, 210 insertions(+), 2 deletions(-) create mode 100644 log/decorators.py create mode 100644 log/middleware.py create mode 100644 log/migrations/0001_initial.py create mode 100644 log/mixins.py diff --git a/log/admin.py b/log/admin.py index 8c38f3f..40cae4c 100644 --- a/log/admin.py +++ b/log/admin.py @@ -1,3 +1,9 @@ from django.contrib import admin -# Register your models here. +from .models import Log + +class LogAdmin(admin.ModelAdmin): + list_display = ['datetime', 'user', 'action', 'resource', 'context'] + search_fields = ['user', 'action', 'resource'] + +admin.site.register(Log, LogAdmin) \ No newline at end of file diff --git a/log/decorators.py b/log/decorators.py new file mode 100644 index 0000000..3f061cb --- /dev/null +++ b/log/decorators.py @@ -0,0 +1,78 @@ +import json +import time +from functools import wraps +from django.shortcuts import get_object_or_404 + +from .models import Log + +def log_decorator(log_component = '', log_action = '', log_resource = ''): + + def _log_decorator(view_function): + + def _decorator(request, *args, **kwargs): + + response = view_function(request, *args, **kwargs) + + if request.user.is_authenticated: + + log = Log() + log.user = request.user + log.component = log_component + log.context = request.log_context + log.action = log_action + log.resource = log_resource + + log.save() + + return response + + return wraps(view_function)(_decorator) + + return _log_decorator + +def log_decorator_ajax(log_component = '', log_action = '', log_resource = ''): + + def _log_decorator_ajax(view_function): + + def _decorator(request, *args, **kwargs): + view_action = request.GET.get("action") + + if view_action == 'open': + if request.user.is_authenticated: + + log = Log() + log.user = request.user + log.component = log_component + log.context = "" + log.action = log_action + log.resource = log_resource + + log.save() + + response = view_function(request, *args, **kwargs) + + log = Log.objects.latest('id') + log.context = request.log_context + log.save() + elif view_action == 'close': + if request.user.is_authenticated: + log = get_object_or_404(Log, id = request.GET.get('log_id')) + + if type(log.context) == dict: + log_context = log.context + else: + log_context = json.loads(log.context) + + log_context['timestamp_end'] = str(int(time.time())) + + log.context = log_context + + log.save() + + response = view_function(request, *args, **kwargs) + + return response + + return wraps(view_function)(_decorator) + + return _log_decorator_ajax \ No newline at end of file diff --git a/log/middleware.py b/log/middleware.py new file mode 100644 index 0000000..7d878cb --- /dev/null +++ b/log/middleware.py @@ -0,0 +1,47 @@ +import time +import json +from django.core.urlresolvers import resolve +from django.shortcuts import get_object_or_404 + +from .models import Log + +class TimeSpentMiddleware(object): + def __init__(self, get_response = None): + self.get_response = get_response + + def process_request(self, request): + app_names = resolve(request.path).app_names + + if not 'admin' in app_names: + if not request.is_ajax(): + log_id = request.session.get('log_id', None) + + if not log_id is None: + log = get_object_or_404(Log, id = log_id) + + if type(log.context) == dict: + log_context = log.context + else: + log_context = json.loads(log.context) + + log_context['timestamp_end'] = str(int(time.time())) + + log.context = log_context + + log.save() + + request.session['log_id'] = None + + oppened_logs = Log.objects.filter(user = request.user, context__contains={'timestamp_end': '-1'}) + + for op_log in oppened_logs: + if type(op_log.context) == dict: + log_context = op_log.context + else: + log_context = json.loads(op_log.context) + + log_context['timestamp_end'] = str(int(time.time())) + + op_log.context = log_context + + op_log.save() \ No newline at end of file diff --git a/log/migrations/0001_initial.py b/log/migrations/0001_initial.py new file mode 100644 index 0000000..fa29e89 --- /dev/null +++ b/log/migrations/0001_initial.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10 on 2016-12-29 20:07 +from __future__ import unicode_literals + +from django.conf import settings +import django.contrib.postgres.fields.jsonb +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name='Log', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('component', models.TextField(verbose_name='Component (Module / App)')), + ('context', django.contrib.postgres.fields.jsonb.JSONField(blank=True, verbose_name='Context')), + ('action', models.TextField(verbose_name='Action')), + ('resource', models.TextField(verbose_name='Resource')), + ('datetime', models.DateTimeField(auto_now_add=True, verbose_name='Date and Time of action')), + ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Actor')), + ], + options={ + 'verbose_name_plural': 'Logs', + 'verbose_name': 'Log', + }, + ), + ] diff --git a/log/mixins.py b/log/mixins.py new file mode 100644 index 0000000..65ca20a --- /dev/null +++ b/log/mixins.py @@ -0,0 +1,24 @@ +import json + +from .models import Log + +from users.models import User + +class LogMixin(object): + log_component = "" + log_context = {} + log_action = "" + log_resource = "" + + def createLog(self, actor = None, component = '', log_action = '', log_resource = '', context = {}): + log = Log() + log.user = actor + log.context = context + log.component = component + log.action = log_action + log.resource = log_resource + + log.save() + + def dispatch(self, request, *args, **kwargs): + return super(LogMixin, self).dispatch(request, *args, **kwargs) \ No newline at end of file diff --git a/log/models.py b/log/models.py index 71a8362..4791023 100644 --- a/log/models.py +++ b/log/models.py @@ -1,3 +1,20 @@ from django.db import models +from django.contrib.postgres.fields import JSONField +from django.utils.translation import ugettext_lazy as _ -# Create your models here. +from users.models import User + +class Log(models.Model): + component = models.TextField(_('Component (Module / App)')) + context = JSONField(_('Context'), blank = True) + action = models.TextField(_('Action')) + resource = models.TextField(_('Resource')) + user = models.ForeignKey(User, verbose_name = _('Actor')) + datetime = models.DateTimeField(_("Date and Time of action"), auto_now_add = True) + + class Meta: + verbose_name = _('Log') + verbose_name_plural = _('Logs') + + def __str__(self): + return str(self.user) + ' / ' + self.component \ No newline at end of file -- libgit2 0.21.2