diff --git a/taiga/base/notifications/models.py b/taiga/base/notifications/models.py index 435271c3..f64b456f 100644 --- a/taiga/base/notifications/models.py +++ b/taiga/base/notifications/models.py @@ -10,7 +10,6 @@ import reversion class WatcherMixin(models.Model): NOTIFY_LEVEL_CHOICES = ( ("all_owned_projects", _(u"All events on my projects")), - ("only_watching", _(u"Only events for objects i watch")), ("only_assigned", _(u"Only events for objects assigned to me")), ("only_owner", _(u"Only events for objects owned by me")), ("no_events", _(u"No events")), @@ -48,11 +47,7 @@ class WatcherMixin(models.Model): ]) def allow_notify_project(self, project): - return self.notify_level == "all_owned_projects" and project.owner.pk == self.pk - - def allow_notify_by_me(self, changer): - return (changer.pk != self.pk) or self.notify_changes_by_me - + return self.notify_level == "all_owned_projects" class WatchedMixin(models.Model): notifiable_fields = [] @@ -91,30 +86,30 @@ class WatchedMixin(models.Model): watchers_by_role = self._get_watchers_by_role() owner = watchers_by_role.get("owner", None) - if (owner and owner.allow_notify_owned() - and owner.allow_notify_by_me(changer)): + if owner and owner.allow_notify_owned(): watchers_to_notify.add(owner) assigned_to = watchers_by_role.get("assigned_to", None) - if (assigned_to and assigned_to.allow_notify_assigned_to() - and assigned_to.allow_notify_by_me(changer)): + if assigned_to and assigned_to.allow_notify_assigned_to(): watchers_to_notify.add(assigned_to) suscribed_watchers = watchers_by_role.get("suscribed_watchers", None) if suscribed_watchers: for suscribed_watcher in suscribed_watchers: - if (suscribed_watcher and suscribed_watcher.allow_notify_suscribed() - and suscribed_watcher.allow_notify_by_me(changer)): + if suscribed_watcher and suscribed_watcher.allow_notify_suscribed(): watchers_to_notify.add(suscribed_watcher) - (project, project_owner) = watchers_by_role.get("project_owner", (None, None)) - if (project_owner - and project_owner.allow_notify_project(project) - and project_owner.allow_notify_by_me(changer)): - watchers_to_notify.add(project_owner) + project = watchers_by_role.get("project", None) + if project: + for member in project.members.all(): + if member and member.allow_notify_project(project): + watchers_to_notify.add(member) if changer.notify_changes_by_me: watchers_to_notify.add(changer) + else: + if changer in watchers_to_notify: + watchers_to_notify.remove(changer) return watchers_to_notify diff --git a/taiga/projects/issues/models.py b/taiga/projects/issues/models.py index 5e53d34a..c1d275fe 100644 --- a/taiga/projects/issues/models.py +++ b/taiga/projects/issues/models.py @@ -258,7 +258,7 @@ class Issue(NeighborsMixin, WatchedMixin, BlockedMixin): "owner": self.owner, "assigned_to": self.assigned_to, "suscribed_watchers": self.watchers.all(), - "project_owner": (self.project, self.project.owner), + "project": self.project, } diff --git a/taiga/projects/milestones/models.py b/taiga/projects/milestones/models.py index aa40b29c..d4a76fe7 100644 --- a/taiga/projects/milestones/models.py +++ b/taiga/projects/milestones/models.py @@ -123,7 +123,7 @@ class Milestone(WatchedMixin, models.Model): def _get_watchers_by_role(self): return { "owner": self.owner, - "project_owner": (self.project, self.project.owner), + "project": self.project, } def closed_points_by_date(self, date): diff --git a/taiga/projects/questions/models.py b/taiga/projects/questions/models.py index 90da1298..df986137 100644 --- a/taiga/projects/questions/models.py +++ b/taiga/projects/questions/models.py @@ -77,7 +77,7 @@ class Question(WatchedMixin): "owner": self.owner, "assigned_to": self.assigned_to, "suscribed_watchers": self.watchers.all(), - "project_owner": (self.project, self.project.owner), + "project": self.project, } diff --git a/taiga/projects/tasks/models.py b/taiga/projects/tasks/models.py index 5f54201f..d5cfa216 100644 --- a/taiga/projects/tasks/models.py +++ b/taiga/projects/tasks/models.py @@ -91,7 +91,7 @@ class Task(WatchedMixin, BlockedMixin): "owner": self.owner, "assigned_to": self.assigned_to, "suscribed_watchers": self.watchers.all(), - "project_owner": (self.project, self.project.owner), + "project": self.project, } diff --git a/taiga/projects/tests/tests_notifications.py b/taiga/projects/tests/tests_notifications.py new file mode 100644 index 00000000..b889637a --- /dev/null +++ b/taiga/projects/tests/tests_notifications.py @@ -0,0 +1,205 @@ +# -*- coding: utf-8 -*- + +import json + +from django import test +from django.core.urlresolvers import reverse +from django.core import mail +from django.db.models import get_model + +from taiga.base.users.tests import create_user +from taiga.projects.models import Project, Membership +from taiga.projects.issues.tests import create_issue +from taiga.projects.tasks.tests import create_task + +from . import create_project, add_membership + +class AllProjectEventsNotificationsTestCase(test.TestCase): + fixtures = ["initial_domains.json"] + + def setUp(self): + self.user1 = create_user(1) + self.user2 = create_user(2) + self.user3 = create_user(3) + self.user4 = create_user(4) + self.user5 = create_user(5) + + self.user1.notify_level = "all_owned_projects" + self.user1.save() + self.user2.notify_level = "all_owned_projects" + self.user2.save() + self.user3.notify_level = "all_owned_projects" + self.user3.save() + self.user4.notify_level = "all_owned_projects" + self.user4.save() + self.user5.notify_level = "all_owned_projects" + self.user5.save() + + self.project1 = create_project(1, self.user1) + + add_membership(self.project1, self.user1, "back") + add_membership(self.project1, self.user2, "back") + add_membership(self.project1, self.user3, "back") + add_membership(self.project1, self.user4, "back") + add_membership(self.project1, self.user5, "back") + + def test_issue(self): + issue = create_issue(1, self.user1, self.project1) + notified = issue.get_watchers_to_notify(self.user1) + expected_notified = [self.user2, self.user3, self.user4, self.user5] + + self.assertEqual(notified,set(expected_notified)) + issue.delete() + + def test_issue_with_owner_notification(self): + self.user1.notify_changes_by_me = True + self.user1.save() + + issue = create_issue(1, self.user1, self.project1) + notified = issue.get_watchers_to_notify(self.user1) + expected_notified = [self.user1, self.user2, self.user3, self.user4, self.user5] + + self.assertEqual(notified,set(expected_notified)) + issue.delete() + self.user1.notify_changes_by_me = False + self.user1.save() + +class OnlyAssigendNotificationsTestCase(test.TestCase): + fixtures = ["initial_domains.json"] + + def setUp(self): + self.user1 = create_user(1) + self.user2 = create_user(2) + self.user3 = create_user(3) + self.user4 = create_user(4) + self.user5 = create_user(5) + + self.user1.notify_level = "only_assigned" + self.user1.save() + self.user2.notify_level = "only_assigned" + self.user2.save() + self.user3.notify_level = "only_assigned" + self.user3.save() + self.user4.notify_level = "only_assigned" + self.user4.save() + self.user5.notify_level = "only_assigned" + self.user5.save() + + self.project1 = create_project(1, self.user1) + + add_membership(self.project1, self.user1, "back") + add_membership(self.project1, self.user2, "back") + add_membership(self.project1, self.user3, "back") + add_membership(self.project1, self.user4, "back") + add_membership(self.project1, self.user5, "back") + + def test_issue(self): + issue = create_issue(1, self.user1, self.project1) + notified = issue.get_watchers_to_notify(self.user1) + expected_notified = [] + self.assertEqual(notified,set(expected_notified)) + + issue.assigned_to = self.user1 + notified = issue.get_watchers_to_notify(self.user1) + expected_notified = [] + self.assertEqual(notified,set(expected_notified)) + + issue.assigned_to = self.user2 + notified = issue.get_watchers_to_notify(self.user1) + expected_notified = [self.user2] + self.assertEqual(notified,set(expected_notified)) + + issue.delete() + + def test_issue_with_owner_notification(self): + self.user1.notify_changes_by_me = True + self.user1.save() + + issue = create_issue(1, self.user1, self.project1) + notified = issue.get_watchers_to_notify(self.user1) + expected_notified = [self.user1] + self.assertEqual(notified,set(expected_notified)) + + issue.assigned_to = self.user1 + notified = issue.get_watchers_to_notify(self.user1) + expected_notified = [self.user1] + self.assertEqual(notified,set(expected_notified)) + + issue.assigned_to = self.user2 + notified = issue.get_watchers_to_notify(self.user1) + expected_notified = [self.user1, self.user2] + self.assertEqual(notified,set(expected_notified)) + + issue.delete() + + self.user1.notify_changes_by_me = False + self.user1.save() + +class OnlyOwnerNotificationsTestCase(test.TestCase): + fixtures = ["initial_domains.json"] + + def setUp(self): + self.user1 = create_user(1) + self.user2 = create_user(2) + self.user3 = create_user(3) + self.user4 = create_user(4) + self.user5 = create_user(5) + + self.user1.notify_level = "only_owner" + self.user1.save() + self.user2.notify_level = "only_owner" + self.user2.save() + self.user3.notify_level = "only_owner" + self.user3.save() + self.user4.notify_level = "only_owner" + self.user4.save() + self.user5.notify_level = "only_owner" + self.user5.save() + + self.project1 = create_project(1, self.user1) + + add_membership(self.project1, self.user1, "back") + add_membership(self.project1, self.user2, "back") + add_membership(self.project1, self.user3, "back") + add_membership(self.project1, self.user4, "back") + add_membership(self.project1, self.user5, "back") + + def test_issue(self): + issue = create_issue(1, self.user1, self.project1) + notified = issue.get_watchers_to_notify(self.user2) + expected_notified = [self.user1] + self.assertEqual(notified,set(expected_notified)) + + notified = issue.get_watchers_to_notify(self.user1) + expected_notified = [] + self.assertEqual(notified,set(expected_notified)) + + issue.owner = self.user2 + notified = issue.get_watchers_to_notify(self.user2) + expected_notified = [] + self.assertEqual(notified,set(expected_notified)) + + issue.delete() + + def test_issue_with_owner_notification(self): + self.user1.notify_changes_by_me = True + self.user1.save() + + issue = create_issue(1, self.user1, self.project1) + notified = issue.get_watchers_to_notify(self.user2) + expected_notified = [self.user1] + self.assertEqual(notified,set(expected_notified)) + + notified = issue.get_watchers_to_notify(self.user1) + expected_notified = [self.user1] + self.assertEqual(notified,set(expected_notified)) + + issue.owner = self.user2 + notified = issue.get_watchers_to_notify(self.user2) + expected_notified = [] + self.assertEqual(notified,set(expected_notified)) + + issue.delete() + + self.user1.notify_changes_by_me = False + self.user1.save() diff --git a/taiga/projects/userstories/models.py b/taiga/projects/userstories/models.py index cb725b98..b1ba0dd9 100644 --- a/taiga/projects/userstories/models.py +++ b/taiga/projects/userstories/models.py @@ -155,7 +155,7 @@ class UserStory(NeighborsMixin, WatchedMixin, BlockedMixin, models.Model): "owner": self.owner, "assigned_to": self.assigned_to, "suscribed_watchers": self.watchers.all(), - "project_owner": (self.project, self.project.owner), + "project": self.project, }