From 1d99ef69d1cc8c9074e58c242d911b9e7dcc63d1 Mon Sep 17 00:00:00 2001 From: Adarnof Date: Sat, 13 Feb 2016 05:25:57 +0000 Subject: [PATCH] Front-end notification model Context processor to count notifications for display in base template Logging handler to generate notifications for users with permission --- README.md | 3 ++- alliance_auth/settings.py.example | 2 ++ notifications/__init__.py | 0 notifications/admin.py | 3 +++ notifications/context_processors.py | 4 ++++ notifications/handlers.py | 14 ++++++++++++++ notifications/models.py | 28 ++++++++++++++++++++++++++++ notifications/tests.py | 3 +++ notifications/views.py | 26 ++++++++++++++++++++++++++ util/__init__.py | 1 + 10 files changed, 83 insertions(+), 1 deletion(-) create mode 100644 notifications/__init__.py create mode 100644 notifications/admin.py create mode 100644 notifications/context_processors.py create mode 100644 notifications/handlers.py create mode 100644 notifications/models.py create mode 100644 notifications/tests.py create mode 100644 notifications/views.py diff --git a/README.md b/README.md index d38b8bd6..d23a57bf 100755 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ Join us in-game in the channel allianceauth for help and feature requests. Special Thanks: - Thanking [Nikdoof](https://github.com/nikdoof), without his old auth + Thanking Nikdoof, without his old auth implementation this project wouldn't be as far as it is now. Thanks to Raynaldo for his original work on this system and getting it as far as it is today. @@ -74,6 +74,7 @@ Special Permissions In Admin: auth | user | sigtracker_view ( Allows for an individual view signitures) auth | user | optimer_management ( Allows for an individual to create and remove fleet operations) auth | user | optimer_view ( Allows for an individual view fleet operations) + auth | user | logging_notifications ( Generate notifications from logging) Active Developers diff --git a/alliance_auth/settings.py.example b/alliance_auth/settings.py.example index 56ea232b..ed91e333 100755 --- a/alliance_auth/settings.py.example +++ b/alliance_auth/settings.py.example @@ -61,6 +61,7 @@ INSTALLED_APPS = ( 'sigtracker', 'optimer', 'corputils', + 'notifications', ) MIDDLEWARE_CLASSES = ( @@ -126,6 +127,7 @@ TEMPLATE_CONTEXT_PROCESSORS = ( 'util.context_processors.domain_url', 'util.context_processors.member_api_mask', 'util.context_processors.blue_api_mask', + 'notifications.context_processors.user_notification_count', ) TEMPLATE_DIRS = ( diff --git a/notifications/__init__.py b/notifications/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/notifications/admin.py b/notifications/admin.py new file mode 100644 index 00000000..8c38f3f3 --- /dev/null +++ b/notifications/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/notifications/context_processors.py b/notifications/context_processors.py new file mode 100644 index 00000000..d5985eff --- /dev/null +++ b/notifications/context_processors.py @@ -0,0 +1,4 @@ +from .models import Notification + +def user_notification_count(request): + return len(Notification.objects.filter(user=request.user).filter(viewed=False)) diff --git a/notifications/handlers.py b/notifications/handlers.py new file mode 100644 index 00000000..a047e279 --- /dev/null +++ b/notifications/handlers.py @@ -0,0 +1,14 @@ +import logging +from django.contrib.auth.models import User +from .models import Notification + +def NotificationHandler(logging.Handler): + def emit(self, record): + for user in User.objects.all(): + if user.has_perm('auth.logging_notifications'): + notif = Notification() + notif.user = user + notif.title = "%s [%s:%s]" % (record.levelname, record.funcName, record.lineno) + notif.level = str([item[0] for item in Notification.LEVEL_CHOICES if item[1] == record.levelname]) + notif.message = record.getMessage() + notif.save() diff --git a/notifications/models.py b/notifications/models.py new file mode 100644 index 00000000..f92c6852 --- /dev/null +++ b/notifications/models.py @@ -0,0 +1,28 @@ +from django.db import models +from django.contrib.auth.models import User + +class Notification(models.Model): + + LEVEL_CHOICES = ( + ('danger', 'CRITICAL'), + ('danger', 'ERROR'), + ('warning', 'WARN'), + ('info', 'INFO'), + ('success', 'DEBUG'), + ) + + user = models.ForeignKey(User, on_delete=models.CASCADE) + level = models.CharField(choices=LEVEL_CHOICES, max_length=10) + title = models.CharField(max_length=254) + message = models.TextField() + created = models.DateTimeField(auto_now_add=True) + viewed = models.BooleanField() + + def view(self): + logger.info("Marking notification as viewed: %s" % self) + self.viewed = True + self.save() + + def __unicode__(self): + output = "%s: %s" % (self.user, self.title) + return output.encode('utf-8') diff --git a/notifications/tests.py b/notifications/tests.py new file mode 100644 index 00000000..7ce503c2 --- /dev/null +++ b/notifications/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/notifications/views.py b/notifications/views.py new file mode 100644 index 00000000..63076dd6 --- /dev/null +++ b/notifications/views.py @@ -0,0 +1,26 @@ +from django.shortcuts import render, get_object_or_404 +from .models import Notification + +@login_required +def notification_list(request): + logger.debug("notification_list called by user %s" % request.user) + new_notifs = Notification.objects.filter(user=request.user).filter(read=False) + old_notifs = Notification.objects.filter(user=request.user).filter(read=True) + logger.debug("User %s has %s unread and %s read notifications" % (request.user, len(new_notifs), len(old_notifs))) + context = { + 'read': old_notifs, + 'unread': new_notifs, + } + return render(request, 'registered/notification_list.html', context) + +@login_required +def notification_view(request, notif_id): + logger.debug("notification_view called by user %s for notif_id %s" % (request.user, notif_id)) + notif = get_object_or_404(notification, pk=notif_id) + if notif.user == request.user: + logger.debug("Providing notification for user %s" % request.user) + context = {'notification': notif} + notif.view() + return render(request, 'registered/notification_view.html', context) + else: + logger.warn("User %s not authorized to view notif_id %s belonging to user %s" % (request.user, notif_id, notif.user)) diff --git a/util/__init__.py b/util/__init__.py index 6f90971a..339b36bb 100755 --- a/util/__init__.py +++ b/util/__init__.py @@ -27,6 +27,7 @@ def bootstrap_permissions(): Permission.objects.get_or_create(codename="signature_view", content_type=ct, name="signature_view") Permission.objects.get_or_create(codename="optimer_management", content_type=ct, name="optimer_management") Permission.objects.get_or_create(codename="optimer_view", content_type=ct, name="optimer_view") + Permission.objects.get_or_create(codename="logging_notifications", content_type=ct, name="logging_notifications") Group.objects.get_or_create(name=settings.DEFAULT_AUTH_GROUP) Group.objects.get_or_create(name=settings.DEFAULT_BLUE_GROUP) logger.info("Bootstrapped permissions for auth and created default groups.")