Skip to content

[ENG-10080] Create global_file_updated, global_reviews and node_file_updated subscriptions if missing#11556

Open
cslzchen wants to merge 20 commits intoCenterForOpenScience:feature/notifications-refactor-post-releasefrom
cslzchen:feature/create-missing-subscriptions-otf
Open

[ENG-10080] Create global_file_updated, global_reviews and node_file_updated subscriptions if missing#11556
cslzchen wants to merge 20 commits intoCenterForOpenScience:feature/notifications-refactor-post-releasefrom
cslzchen:feature/create-missing-subscriptions-otf

Conversation

@cslzchen
Copy link
Collaborator

@cslzchen cslzchen commented Jan 19, 2026

Ticket

https://openscience.atlassian.net/browse/ENG-10080

Purpose

Create global_file_updated, global_reviews and node_file_updated subscriptions if missing

  • Use USER_FILE_UPDATED for group _global_file_updated
  • Use REVIEWS_SUBMISSION_STATUS for group _global_reviews
  • Use NODE_FILE_UPDATED for group _node_file_updated

Changes

  • API now creates global_file_updated, global_reviews and node_file_updated subscriptions if missing
  • Added _is_digest=True for newly created OSF user and node default subscriptions
  • Annotate with legacy_id for serializer to handle newly created subscriptions
  • Enforce and improve permission check for subscriptions
  • Fixed annotated_obj_qs for node_file_updated and global_reviews
  • Fixed duplicate and mismatched type NODE_FILE(S)_UPDATED
  • Refactored unit tests

Side Effects

N/A

QE Notes

N/A

CE Notes

N/A

Documentation

N/A

Copy link
Collaborator

@Ostap-Zherebetskyi Ostap-Zherebetskyi left a comment

Choose a reason for hiding this comment

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

LGTM 🎆

@cslzchen cslzchen changed the title [ENG-10080] Create global_file_updated and global_reviews subscriptions if missing [ENG-10080] Create global_file_updated, global_reviews and node_files_updated subscriptions if missing Jan 20, 2026
@cslzchen cslzchen changed the title [ENG-10080] Create global_file_updated, global_reviews and node_files_updated subscriptions if missing [ENG-10080] Create global_file_updated, global_reviews and node_file_updated subscriptions if missing Jan 23, 2026
Comment on lines 198 to 237
if not existing_subscriptions.exists():
# `global_file_updated` and `global_reviews` should exist by default for every user.
# If not found, create them with `none` frequency and `_is_digest=True` as default.
if subscription_id == f'{user_guid}_global_file_updated':
notification_type = user_file_updated_nt
content_type = user_ct
object_id = self.request.user.id
elif subscription_id == f'{user_guid}_global_reviews':
notification_type = reviews_submission_status_nt
content_type = user_ct
object_id = self.request.user.id
elif subscription_id.endswith('_global_file_updated') or subscription_id.endswith('_global_reviews'):
# Mismatched request user and subscription user
sentry.log_message(f'Permission denied: [user={user_guid}, legacy_id={subscription_id}]')
raise PermissionDenied
elif subscription_id.endswith('_files_updated'):
notification_type = node_file_updated_nt
content_type = node_ct
node_guid = subscription_id[:-len('_files_updated')]
node = AbstractNode.objects.filter(guids___id=node_guid, is_deleted=False, type='osf.node').first()
if not node:
# The node in the legacy subscription ID does not exist or is invalid
sentry.log_message(f'Node not found in legacy subscription ID: [user={user_guid}, legacy_id={subscription_id}]')
raise NotFound
if not node.is_contributor(self.request.user):
# The request user is not a contributor of the node
sentry.log_message(f'Permission denied: [user={user_guid}], node={node_guid}, legacy_id={subscription_id}]')
raise PermissionDenied
object_id = node.id
else:
sentry.log_message(f'Subscription not found: [user={user_guid}, legacy_id={subscription_id}]')
raise NotFound
missing_subscription_created = NotificationSubscription.objects.create(
notification_type=notification_type,
user=self.request.user,
content_type=content_type,
object_id=object_id,
_is_digest=True,
message_frequency='none',
)
Copy link
Collaborator

Choose a reason for hiding this comment

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

This needs to be moved to the SubscriptionList API view because users must have subscriptions before they can edit them.

notification_id = res.json['data']['id']
assert res.status_code == 200
assert notification_id == f'{user._id}_global_file_updated'
res = app.get(url_user_global_reviews, auth=user.auth)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Ditto

object_id=user_missing_subscriptions.id,
content_type=ContentType.objects.get_for_model(OSFUser)
).exists()
res = app.get(url_user_global_file_updated_missing, auth=user_missing_subscriptions.auth)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Ditto

@cslzchen cslzchen force-pushed the feature/create-missing-subscriptions-otf branch from 8a9fee8 to 8d9658f Compare February 3, 2026 04:47
Note: only works for when filter on "legacy id"; logs message to
sentry for tracking purpose when filter on "event names".
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants