| | @@ -0,0 +1,62 @@ |
| 1 | +"""Notification system for Fossilrepo.
|
| 2 | +
|
| 3 | +Simple SMTP-based notifications for self-hosted deployments.
|
| 4 | +Users watch projects and get emails on checkins, tickets, wiki, forum changes.
|
| 5 | +"""
|
| 6 | +
|
| 7 | +import logging
|
| 8 | +
|
| 9 | +from django.conf import settings
|
| 10 | +from django.contrib.auth.models import User
|
| 11 | +from django.core.mail import send_mail
|
| 12 | +from django.db import models
|
| 13 | +
|
| 14 | +from core.models import ActiveManager, Tracking
|
| 15 | +
|
| 16 | +logger = logging.getLogger(__name__)
|
| 17 | +
|
| 18 | +
|
| 19 | +class ProjectWatch(Tracking):
|
| 20 | + """User's subscription to project notifications."""
|
| 21 | +
|
| 22 | + class EventType(models.TextChoices):
|
| 23 | + ALL = "all", "All Events"
|
| 24 | + CHECKINS = "checkins", "Checkins Only"
|
| 25 | + TICKETS = "tickets", "Tickets Only"
|
| 26 | + WIKI = "wiki", "Wiki Only"
|
| 27 | +
|
| 28 | + user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="project_watches")
|
| 29 | + project = models.ForeignKey("projects.Project", on_delete=models.CASCADE, related_name="watchers")
|
| 30 | + event_filter = models.CharField(max_length=20, choices=EventType.choices, default=EventType.ALL)
|
| 31 | + email_enabled = models.BooleanField(default=True)
|
| 32 | +
|
| 33 | + objects = ActiveManager()
|
| 34 | + all_objects = models.Manager()
|
| 35 | +
|
| 36 | + class Meta:
|
| 37 | + unique_together = ("user", "project")
|
| 38 | +
|
| 39 | + def __str__(self):
|
| 40 | + return f"{self.user.username} watching {self.project.name}"
|
| 41 | +
|
| 42 | +
|
| 43 | +class Notification(models.Model):
|
| 44 | + """Individual notification entry."""
|
| 45 | +
|
| 46 | + user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="notifications")
|
| 47 | + project = models.ForeignKey("projects.Project", on_delete=models.CASCADE, related_name="notifications")
|
| 48 | + event_type = models.CharField(max_length=20) # checkin, ticket, wiki, forum
|
| 49 | + title = models.CharField(max_length=300)
|
| 50 | + body = models.TextField(blank=True, default="")
|
| 51 | + url = models.CharField(max_length=500, blank=True, default="")
|
| 52 | + read = models.BooleanField(default=False)
|
| 53 | + emailed = models.BooleanField(default=False)
|
| 54 | + created_at = models.DateTimeField(auto_now_add=True)
|
| 55 | +
|
| 56 | + class Meta:
|
| 57 | + ordering = ["-created_at"]
|
| 58 | +
|
| 59 | + def __str__(self):
|
| 60 | + return f"{self.title} �ion entry."""
|
| 61 | +
|
| 62 | + user = models.ForeignKey(User, on_delete=models |