Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: restrict email notifications for removed users #6100

Merged
merged 1 commit into from
Nov 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions apiserver/plane/app/views/notification/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,10 @@ def list(self, request, slug):
Notification.objects.filter(
workspace__slug=slug, receiver_id=request.user.id
)
.filter(
project__project_projectmember__member=request.user,
project__project_projectmember__is_active=True,
)
Comment on lines +65 to +68
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codebase verification

The active member check is not consistently applied across all notification queries

The verification revealed that while the main list endpoint properly filters for active project members, other notification endpoints like UnreadNotificationEndpoint and MarkAllReadNotificationViewSet don't include the same active member check:

  • UnreadNotificationEndpoint.get() (lines 245-263): Missing active member check
  • MarkAllReadNotificationViewSet.create() (lines 284-286): Missing active member check

These endpoints should also include the same filtering to maintain consistency with the PR's objective of restricting notifications for removed users.

🔗 Analysis chain

LGTM! The changes effectively restrict notifications to active project members.

The added filters ensure that notifications are only shown to active project members, which aligns with the PR objective of restricting notifications for removed users.

Let's verify that the filters work as expected:


Let me gather more information to verify if there are any potential notification queries that might bypass the active member check.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify that notifications are properly filtered for inactive project members

# Check if there are any notifications being sent to inactive project members
ast-grep --pattern 'Notification.objects.filter($$$).exclude(project__project_projectmember__is_active=True)' \
  --pattern 'Notification.objects.filter($$$).exclude(project__project_projectmember__member=True)'

# Check for any other notification queries that might bypass these filters
rg -l "Notification.objects" | xargs ast-grep --pattern 'Notification.objects.filter($$$)'

Length of output: 2374


Script:

#!/bin/bash
# Let's check the content of the notification base file to understand the context of these queries
cat apiserver/plane/app/views/notification/base.py

Length of output: 13739

.filter(entity_name="issue")
.annotate(is_inbox_issue=Exists(intake_issue))
.annotate(is_intake_issue=Exists(intake_issue))
Expand Down
1 change: 1 addition & 0 deletions apiserver/plane/app/views/workspace/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,7 @@ def post(self, request, slug, user_id):
workspace__slug=slug,
created_at__date=request.data.get("date"),
project__project_projectmember__member=request.user,
project__project_projectmember__is_active=True,
actor_id=user_id,
).select_related("actor", "workspace", "issue", "project")[:10000]

Expand Down
29 changes: 21 additions & 8 deletions apiserver/plane/bgtasks/notification_task.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,9 @@
IssueComment,
IssueActivity,
UserNotificationPreference,
ProjectMember
ProjectMember,
)
from django.db.models import Subquery

# Third Party imports
from celery import shared_task
Expand Down Expand Up @@ -95,7 +96,8 @@ def extract_mentions_as_subscribers(project_id, issue_id, mentions):
).exists()
and not Issue.objects.filter(
project_id=project_id, pk=issue_id, created_by_id=mention_id
).exists() and ProjectMember.objects.filter(
).exists()
and ProjectMember.objects.filter(
pablohashescobar marked this conversation as resolved.
Show resolved Hide resolved
project_id=project_id, member_id=mention_id, is_active=True
).exists()
):
Expand Down Expand Up @@ -242,14 +244,19 @@ def notifications(
2. From the latest set of mentions, extract the users which are not a subscribers & make them subscribers
"""

# get the list of active project members
project_members = ProjectMember.objects.filter(
project_id=project_id, is_active=True
).values_list("member_id", flat=True)

# Get new mentions from the newer instance
new_mentions = get_new_mentions(
requested_instance=requested_data, current_instance=current_instance
)
new_mentions = list(ProjectMember.objects.filter(
project_id=project_id, member_id__in=new_mentions, is_active=True
).values_list("member_id", flat=True))
new_mentions = [str(member_id) for member_id in new_mentions]

new_mentions = [
str(mention) for mention in new_mentions if mention in new_mentions
]
Comment on lines +257 to +259
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix redundant and incorrect filtering of new mentions

The condition if mention in new_mentions in the list comprehension is redundant because each mention is inherently from new_mentions. This does not filter the mentions as intended. If the goal is to filter new_mentions to include only active project members, you should update the code to:

new_mentions = [
    str(mention) for mention in new_mentions if mention in project_member_ids
]

removed_mention = get_removed_mentions(
requested_instance=requested_data, current_instance=current_instance
)
Expand Down Expand Up @@ -293,7 +300,11 @@ def notifications(

# ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- #
issue_subscribers = list(
IssueSubscriber.objects.filter(project_id=project_id, issue_id=issue_id, project__project_projectmember__is_active=True,)
IssueSubscriber.objects.filter(
project_id=project_id,
issue_id=issue_id,
subscriber__in=Subquery(project_members),
)
pablohashescobar marked this conversation as resolved.
Show resolved Hide resolved
.exclude(
subscriber_id__in=list(new_mentions + comment_mentions + [actor_id])
)
Expand All @@ -314,7 +325,9 @@ def notifications(
project = Project.objects.get(pk=project_id)

issue_assignees = IssueAssignee.objects.filter(
issue_id=issue_id, project_id=project_id
issue_id=issue_id,
project_id=project_id,
assignee__in=Subquery(project_members),
).values_list("assignee", flat=True)
pablohashescobar marked this conversation as resolved.
Show resolved Hide resolved

issue_subscribers = list(set(issue_subscribers) - {uuid.UUID(actor_id)})
Expand Down
Loading