diff options
Diffstat (limited to 'src/notifier')
-rw-r--r-- | src/notifier/admin.py | 5 | ||||
-rw-r--r-- | src/notifier/manager.py | 162 | ||||
-rw-r--r-- | src/notifier/migrations/0008_auto_20230608_1913.py | 30 | ||||
-rw-r--r-- | src/notifier/models.py | 48 | ||||
-rw-r--r-- | src/notifier/tasks.py | 51 | ||||
-rw-r--r-- | src/notifier/tests/test_dispatcher.py | 15 | ||||
-rw-r--r-- | src/notifier/tests/test_models.py | 30 | ||||
-rw-r--r-- | src/notifier/urls.py | 13 | ||||
-rw-r--r-- | src/notifier/views.py | 50 |
9 files changed, 31 insertions, 373 deletions
diff --git a/src/notifier/admin.py b/src/notifier/admin.py index f6dbfd1..c7e20d6 100644 --- a/src/notifier/admin.py +++ b/src/notifier/admin.py @@ -8,8 +8,3 @@ ############################################################################## from django.contrib import admin - -from notifier.models import Notification, Emailed - -admin.site.register(Notification) -admin.site.register(Emailed) diff --git a/src/notifier/manager.py b/src/notifier/manager.py deleted file mode 100644 index e2afdec..0000000 --- a/src/notifier/manager.py +++ /dev/null @@ -1,162 +0,0 @@ -############################################################################## -# Copyright (c) 2018 Parker Berberian, Sawyer Bergeron and others. -# Copyright (c) 2020 Sawyer Bergeron, Sean Smith, and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -############################################################################## -import os -from notifier.models import Notification, Emailed, Email - -from django.template.loader import render_to_string -from django.utils import timezone - - -class NotificationHandler(object): - - @classmethod - def notify_new_booking(cls, booking): - template = "notifier/new_booking.html" - titles = ["You have a new booking (" + str(booking.id) + ")", "You have been added to a booking (" + str(booking.id) + ")"] - cls.booking_notify(booking, template, titles) - - @classmethod - def notify_booking_end(cls, booking): - template = "notifier/end_booking.html" - titles = ["Your booking (" + str(booking.id) + ") has ended", "A booking (" + str(booking.id) + ") that you collaborate on has ended"] - cls.booking_notify(booking, template, titles) - - @classmethod - def notify_booking_expiring(cls, booking): - template = "notifier/expiring_booking.html" - titles = ["Your booking (" + str(booking.id) + ") is about to expire", "A booking (" + str(booking.id) + ") that you collaborate on is about to expire"] - cls.booking_notify(booking, template, titles) - cls.email_booking_expiring(booking) - - @classmethod - def booking_notify(cls, booking, template, titles): - """ - Create a notification for a booking owner and collaborators using the template. - - titles is a list - the first is the title for the owner's notification, - the last is the title for the collaborators' - """ - owner_notif = Notification.objects.create( - title=titles[0], - content=render_to_string( - template, - context={ - "booking": booking, - "owner": True - } - ) - ) - owner_notif.recipients.add(booking.owner.userprofile) - if not booking.collaborators.all().exists(): - return # no collaborators - were done - - collab_notif = Notification.objects.create( - title=titles[-1], - content=render_to_string( - template, - context={ - "booking": booking, - "owner": False - } - ) - ) - for c in booking.collaborators.all(): - collab_notif.recipients.add(c.userprofile) - - @classmethod - def email_job_fulfilled(cls, job): - template_name = "notifier/email_fulfilled.txt" - all_tasks = job.get_tasklist() - users = list(job.booking.collaborators.all()) - users.append(job.booking.owner) - for user in users: - user_tasklist = [] - # gather up all the relevant messages from the lab - for task in all_tasks: - if (not hasattr(task.config, "user")) or task.config.user == user: - user_tasklist.append( - { - "title": task.type_str() + " Message: ", - "content": task.message - } - ) - # gather up all the other needed info - context = { - "owner": user == job.booking.owner, - "user_name": user.userprofile.full_name, - "messages": user_tasklist, - "booking_url": os.environ.get("DASHBOARD_URL", "<Dashboard url>") + "/booking/detail/" + str(job.booking.id) + "/" - } - - # render email template - message = render_to_string(template_name, context) - - # finally, queue email for sending - Email.objects.create(title="Your Booking is Ready", message=message, recipient=user.userprofile.email_addr) - - @classmethod - def email_booking_over(cls, booking): - template_name = "notifier/email_ended.txt" - hostnames = [host.name for host in booking.resource.get_resources()] - users = list(booking.collaborators.all()) - users.append(booking.owner) - for user in users: - context = { - "user_name": user.userprofile.full_name, - "booking": booking, - "hosts": hostnames, - "booking_url": os.environ.get("DASHBOARD_URL", "<Dashboard url>") + "/booking/detail/" + str(booking.id) + "/" - } - - message = render_to_string(template_name, context) - - Email.objects.create(title="Your Booking has Expired", message=message, recipient=user.userprofile.email_addr) - - @classmethod - def email_booking_expiring(cls, booking): - template_name = "notifier/email_expiring.txt" - hostnames = [host.name for host in booking.resource.get_resources()] - users = list(booking.collaborators.all()) - users.append(booking.owner) - for user in users: - context = { - "user_name": user.userprofile.full_name, - "booking": booking, - "hosts": hostnames, - "booking_url": os.environ.get("DASHBOARD_URL", "<Dashboard url>") + "/booking/detail/" + str(booking.id) + "/" - } - - message = render_to_string(template_name, context) - - Email.objects.create(title="Your Booking is Expiring", message=message, recipient=user.userprofile.email_addr) - - @classmethod - def task_updated(cls, task): - """ - Notification of task changing. - - called every time a lab updated info about a task. - sends an email when 'task' changing state means a booking has - just been fulfilled (all tasks done, servers ready to use) - or is over. - """ - if task.job is None or task.job.booking is None: - return - if task.job.is_fulfilled(): - if task.job.booking.end < timezone.now(): - if Emailed.objects.filter(end_booking=task.job.booking).exists(): - return - Emailed.objects.create(end_booking=task.job.booking) - cls.email_booking_over(task.job.booking) - if task.job.booking.end > timezone.now() and task.job.booking.start < timezone.now(): - if Emailed.objects.filter(begin_booking=task.job.booking).exists(): - return - Emailed.objects.create(begin_booking=task.job.booking) - cls.email_job_fulfilled(task.job) diff --git a/src/notifier/migrations/0008_auto_20230608_1913.py b/src/notifier/migrations/0008_auto_20230608_1913.py new file mode 100644 index 0000000..898c300 --- /dev/null +++ b/src/notifier/migrations/0008_auto_20230608_1913.py @@ -0,0 +1,30 @@ +# Generated by Django 2.2 on 2023-06-08 19:13 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('notifier', '0007_email'), + ] + + operations = [ + migrations.DeleteModel( + name='Email', + ), + migrations.RemoveField( + model_name='notification', + name='read_by', + ), + migrations.RemoveField( + model_name='notification', + name='recipients', + ), + migrations.DeleteModel( + name='Emailed', + ), + migrations.DeleteModel( + name='Notification', + ), + ] diff --git a/src/notifier/models.py b/src/notifier/models.py index 03e23b3..f903394 100644 --- a/src/notifier/models.py +++ b/src/notifier/models.py @@ -6,51 +6,3 @@ # which accompanies this distribution, and is available at # http://www.apache.org/licenses/LICENSE-2.0 ############################################################################## - -from django.db import models -from account.models import UserProfile -from booking.models import Booking - - -class Notification(models.Model): - title = models.CharField(max_length=150) - content = models.TextField() - recipients = models.ManyToManyField(UserProfile, related_name='notifications') - is_html = models.BooleanField(default=True) - read_by = models.ManyToManyField(UserProfile, related_name='read_notifications') - - def __str__(self): - return self.title - - def to_preview_html(self): - return "<h3>" + self.title + "</h3>" # TODO - template? - - -class Emailed(models.Model): - """A simple record to remember who has already gotten an email to avoid resending.""" - - begin_booking = models.OneToOneField( - Booking, - null=True, - on_delete=models.CASCADE, - related_name="begin_mail" - ) - almost_end_booking = models.OneToOneField( - Booking, - null=True, - on_delete=models.CASCADE, - related_name="warning_mail" - ) - end_booking = models.OneToOneField( - Booking, - null=True, - on_delete=models.CASCADE, - related_name="over_mail" - ) - - -class Email(models.Model): - sent = models.BooleanField(default=False) - title = models.CharField(max_length=150) - message = models.TextField() - recipient = models.CharField(max_length=150) diff --git a/src/notifier/tasks.py b/src/notifier/tasks.py deleted file mode 100644 index 64d7574..0000000 --- a/src/notifier/tasks.py +++ /dev/null @@ -1,51 +0,0 @@ -############################################################################## -# Copyright (c) 2016 Max Breitenfeldt and others. -# Copyright (c) 2018 Parker Berberian, Sawyer Bergeron, and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -############################################################################## - - -from celery import shared_task -from django.utils import timezone -from django.conf import settings -from booking.models import Booking -from notifier.models import Emailed, Email -from notifier.manager import NotificationHandler -from django.core.mail import send_mail - -import os - - -@shared_task -def notify_expiring(): - """Notify users if their booking is within 48 hours of expiring.""" - expire_time = timezone.now() + timezone.timedelta(hours=settings.EXPIRE_HOURS) - # Don't email people about bookings that have started recently - start_time = timezone.now() - timezone.timedelta(hours=settings.EXPIRE_LIFETIME) - bookings = Booking.objects.filter( - end__lte=expire_time, - end__gte=timezone.now(), - start__lte=start_time - ) - for booking in bookings: - if Emailed.objects.filter(almost_end_booking=booking).exists(): - continue - NotificationHandler.notify_booking_expiring(booking) - Emailed.objects.create(almost_end_booking=booking) - - -@shared_task -def dispatch_emails(): - for email in Email.objects.filter(sent=False): - email.sent = True - email.save() - send_mail( - email.title, - email.message, - os.environ.get("DEFAULT_FROM_EMAIL", "opnfv@laas-dashboard"), - [email.recipient], - fail_silently=False) diff --git a/src/notifier/tests/test_dispatcher.py b/src/notifier/tests/test_dispatcher.py deleted file mode 100644 index 086f621..0000000 --- a/src/notifier/tests/test_dispatcher.py +++ /dev/null @@ -1,15 +0,0 @@ -############################################################################## -# Copyright (c) 2018 Sawyer Bergeron and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -############################################################################## - -from django.test import TestCase - - -class DispatchTestCase(TestCase): - # This is a stub, it will be filled out as this feature is remade with saner practices. - pass diff --git a/src/notifier/tests/test_models.py b/src/notifier/tests/test_models.py deleted file mode 100644 index d332254..0000000 --- a/src/notifier/tests/test_models.py +++ /dev/null @@ -1,30 +0,0 @@ -############################################################################## -# Copyright (c) 2018 Sawyer Bergeron and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -############################################################################## - - -from django.test import TestCase -from notifier.models import Notifier -from django.contrib.auth.models import User - - -class NotifierTestCase(TestCase): - - def test_valid_notifier_saves(self): - - sender = User.objects.create() - recipient = User.objects.create() - self.assertTrue( - Notifier.objects.create( - title='notification title', - content='notification body', - user=recipient, - sender=sender, - message_type='email' - ) - ) diff --git a/src/notifier/urls.py b/src/notifier/urls.py index 923cc33..f69ee85 100644 --- a/src/notifier/urls.py +++ b/src/notifier/urls.py @@ -5,15 +5,4 @@ # are made available under the terms of the Apache License, Version 2.0 # which accompanies this distribution, and is available at # http://www.apache.org/licenses/LICENSE-2.0 -############################################################################## - - -from django.conf.urls import url - -from notifier.views import InboxView, NotificationView - -app_name = 'notifier' -urlpatterns = [ - url(r'^$', InboxView, name='messages'), - url(r'^notification/(?P<notification_id>[0-9]+)/$', NotificationView, name='notifier_single') -] +##############################################################################
\ No newline at end of file diff --git a/src/notifier/views.py b/src/notifier/views.py index 3a85eda..d65b13a 100644 --- a/src/notifier/views.py +++ b/src/notifier/views.py @@ -6,53 +6,3 @@ # which accompanies this distribution, and is available at # http://www.apache.org/licenses/LICENSE-2.0 ############################################################################## - -from django.shortcuts import render -from notifier.models import Notification -from django.db.models import Q - - -def InboxView(request): - if request.user.is_authenticated: - user = request.user - else: - return render(request, "dashboard/login.html", - {'title': 'Authentication Required'}) - - return render(request, - "notifier/inbox.html", - {'unread_notifications': Notification.objects.filter(recipients=user.userprofile).order_by('-id').filter(~Q(read_by=user.userprofile)), - 'read_notifications': Notification.objects.filter(recipients=user.userprofile).order_by('-id').filter(read_by=user.userprofile)}) - - -def NotificationView(request, notification_id): - - if request.user.is_authenticated: - user = request.user - else: - return render(request, - "dashboard/login.html", - {'title': 'Authentication Required'}) - - notification = Notification.objects.get(id=notification_id) - if user.userprofile not in notification.recipients.all(): - return render(request, - "dashboard/login.html", {'title': 'Access Denied'}) - - notification.read_by.add(user.userprofile) - notification.save() - if request.method == 'POST': - if 'delete' in request.POST: - # handle deleting - notification.recipients.remove(user.userprofile) - if not notification.recipients.exists(): - notification.delete() - else: - notification.save() - - if 'unread' in request.POST: - notification.read_by.remove(user.userprofile) - notification.save() - - return render(request, - "notifier/notification.html", {'notification': notification}) |