Skip to content

Commit

Permalink
feat(estela-api) add notification support for user actions
Browse files Browse the repository at this point in the history
  • Loading branch information
Jgaldos committed Jan 29, 2023
1 parent cd417e6 commit 78c753b
Show file tree
Hide file tree
Showing 5 changed files with 105 additions and 12 deletions.
26 changes: 24 additions & 2 deletions estela-api/api/mixins.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from django.conf import settings
from django.core.mail import EmailMessage
from rest_framework import viewsets
from rest_framework.authentication import TokenAuthentication
from rest_framework.pagination import PageNumberPagination
Expand All @@ -24,10 +25,31 @@ class BaseViewSet(viewsets.GenericViewSet):

class NotificationsHandler(viewsets.GenericViewSet):

def saveNotfication(self, user, message, notify_to = None):
def get_users_email(self, project):
email_list = []
for user in project.users.all():
email_list.append(user.email)

return email_list

def save_notfication(self, user, message, project):
email_list = self.get_users_email(project)
email_body = f"""
Dear User
{message}
Estela Notification Service.
"""
notification = Notification(
message=message,
user=user,
notify_to="",
notify_to=", ".join(email_list),
)
notification.save()
email = EmailMessage(
subject=f"NO REPLY: Notification alert on {project.name} project.",
body=email_body,
from_email=settings.VERIFICATION_EMAIL,
to=email_list,
)
email.send()
43 changes: 41 additions & 2 deletions estela-api/api/views/cronjob.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,19 @@
from rest_framework.response import Response

from api.filters import SpiderCronJobFilter
from api.mixins import BaseViewSet
from api.mixins import BaseViewSet, NotificationsHandler
from api.serializers.cronjob import (
SpiderCronJobCreateSerializer,
SpiderCronJobSerializer,
SpiderCronJobUpdateSerializer,
)
from core.cronjob import create_cronjob, disable_cronjob, run_cronjob_once
from core.models import Spider, SpiderCronJob
from core.models import Project, Spider, SpiderCronJob


class SpiderCronJobViewSet(
BaseViewSet,
NotificationsHandler,
mixins.CreateModelMixin,
mixins.RetrieveModelMixin,
mixins.UpdateModelMixin,
Expand Down Expand Up @@ -93,6 +94,15 @@ def create(self, request, *args, **kwargs):
cronjob.schedule,
data_expiry_days=data_expiry_days,
)

# Send action notification
project = get_object_or_404(Project, pid=self.kwargs["pid"])
self.save_notfication(
user=request.user,
message=f"{request.user} has scheduled a new job at {spider.name} spider",
project=project,
)

headers = self.get_success_headers(serializer.data)
return Response(
serializer.data, status=status.HTTP_201_CREATED, headers=headers
Expand All @@ -109,6 +119,35 @@ def update(self, request, *args, **kwargs):
instance, data=request.data, partial=partial
)
serializer.is_valid(raise_exception=True)

status_changed = (
True
if "status" in request.data or instance.status == request.data["status"]
else False
)
schedule_changed = (
True
if "schedule" in request.data or instance.schedule != request.data["schedule"]
else False
)

# Send action notification
project = get_object_or_404(Project, pid=self.kwargs["pid"])
if status_changed:
message = f"{request.user.get_username()} has updated the status of a cronjob at {instance.spider.name} spider: {request.data['status']}"
self.save_notfication(
user=request.user,
message=message,
project=project,
)
if schedule_changed:
message = f"{request.user.get_username()} has updated the schedule of a cronjob at {instance.spider.name} spider: {request.data['schedule']}"
self.save_notfication(
user=request.user,
message=message,
project=project,
)

self.perform_update(serializer)

if getattr(instance, "_prefetched_objects_cache", None):
Expand Down
10 changes: 6 additions & 4 deletions estela-api/api/views/deploy.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,10 @@ def create(self, request, *args, **kwargs):
)

# Send action notification
self.saveNotfication(
self.save_notfication(
user=user,
message=f"{request.user}has made a new deployment for {project.name} Project."
message=f"{request.user} has made a new deployment for {project.name} Project.",
project=project,
)

headers = self.get_success_headers(serializer.data)
Expand Down Expand Up @@ -100,9 +101,10 @@ def update(self, request, *args, **kwargs):

# Send action notification
project = get_object_or_404(Project, pid=self.kwargs["pid"])
self.saveNotfication(
self.save_notfication(
user=request.user,
message=f"{request.user}has made an update for {project.name} Project."
message=f"{request.user} has made an update for {project.name} Project.",
project=project,
)

headers = self.get_success_headers(serializer.data)
Expand Down
13 changes: 11 additions & 2 deletions estela-api/api/views/job.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,19 @@
from rest_framework.exceptions import ParseError

from api.filters import SpiderJobFilter
from api.mixins import BaseViewSet
from api.mixins import BaseViewSet, NotificationsHandler
from api.serializers.job import (
SpiderJobSerializer,
SpiderJobCreateSerializer,
SpiderJobUpdateSerializer,
)
from config.job_manager import job_manager
from core.models import Spider, SpiderJob
from core.models import Project, Spider, SpiderJob


class SpiderJobViewSet(
BaseViewSet,
NotificationsHandler,
mixins.CreateModelMixin,
mixins.RetrieveModelMixin,
mixins.UpdateModelMixin,
Expand Down Expand Up @@ -144,6 +145,14 @@ def create(self, request, *args, **kwargs):
data_expiry_days=data_expiry_days,
)

# Send action notification
project = get_object_or_404(Project, pid=self.kwargs["pid"])
self.save_notfication(
user=request.user,
message=f"{request.user} has scheduled a new scheduled job at {spider.name} spider.",
project=project,
)

headers = self.get_success_headers(serializer.data)
return Response(
serializer.data, status=status.HTTP_201_CREATED, headers=headers
Expand Down
25 changes: 23 additions & 2 deletions estela-api/api/views/project.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
from datetime import datetime, timedelta
from django.shortcuts import get_object_or_404

from api import errors
from api.mixins import BaseViewSet
from api.mixins import BaseViewSet, NotificationsHandler
from api.serializers.job import ProjectJobSerializer, SpiderJobSerializer
from api.serializers.cronjob import ProjectCronJobSerializer, SpiderCronJobSerializer
from api.serializers.project import (
Expand All @@ -28,7 +29,7 @@
from rest_framework.exceptions import NotFound, ParseError


class ProjectViewSet(BaseViewSet, viewsets.ModelViewSet):
class ProjectViewSet(BaseViewSet, NotificationsHandler, viewsets.ModelViewSet):
model_class = Project
queryset = Project.objects.all()
serializer_class = ProjectSerializer
Expand Down Expand Up @@ -85,6 +86,14 @@ def update(self, request, *args, **kwargs):

if name:
instance.name = name
# Send action notification
project = get_object_or_404(Project, pid=self.kwargs["pid"])
self.save_notfication(
user=request.user,
message=f"{request.user} created a new Project: {instance.name}.",
project=project,
)
notification_name = None
if user_email and user_email != user_permision:
user = User.objects.filter(email=user_email)
user_instance = User.objects.filter(email=user_permision)
Expand All @@ -99,19 +108,31 @@ def update(self, request, *args, **kwargs):
instance.users.add(
user, through_defaults={"permission": permission}
)
notification_name = f"{request.user} added {user.get_username()} as a new member of {instance.name} project, as {permission}."
elif action == "remove":
instance.users.remove(user)
notification_name = f"{request.user} removed {user.get_username()} from {instance.name} project."
elif action == "update":
instance.users.remove(user)
instance.users.add(
user, through_defaults={"permission": permission}
)
notification_name = f"{request.user} changed {user.get_username()}'s role of {instance.name} project, to {permission}.",
else:
raise ParseError({"error": "Action not supported."})
else:
raise NotFound({"email": "User does not exist."})
serializer.save()

if notification_name:
# Send action notification
project = get_object_or_404(Project, pid=self.kwargs["pid"])
self.save_notfication(
user=request.user,
message=notification_name,
project=project,
)

headers = self.get_success_headers(serializer.data)
return Response(serializer.data, status=status.HTTP_200_OK, headers=headers)

Expand Down

0 comments on commit 78c753b

Please sign in to comment.