Skip to content

Commit 7b09dc4

Browse files
authored
Merge pull request #11405 from Johnetordoff/fix-node-subscriptions-on-demand
[ENG-9664] Fix node subscriptions API filtering
2 parents e421342 + aab8aa6 commit 7b09dc4

File tree

4 files changed

+53
-12
lines changed

4 files changed

+53
-12
lines changed

api/subscriptions/views.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ def get_queryset(self):
5656
id=Cast(OuterRef('object_id'), IntegerField()),
5757
).values('guids___id')[:1]
5858

59-
return NotificationSubscription.objects.filter(
59+
qs = NotificationSubscription.objects.filter(
6060
notification_type__in=[
6161
NotificationType.Type.USER_FILE_UPDATED.instance,
6262
NotificationType.Type.NODE_FILE_UPDATED.instance,
@@ -91,6 +91,13 @@ def get_queryset(self):
9191
),
9292
)
9393

94+
# Apply manual filter for legacy_id if requested
95+
filter_id = self.request.query_params.get('filter[id]')
96+
if filter_id:
97+
qs = qs.filter(legacy_id=filter_id)
98+
# convert to list comprehension because legacy_id is an annotation, not in DB
99+
100+
return qs
94101

95102
class AbstractProviderSubscriptionList(SubscriptionList):
96103
def get_queryset(self):

api_tests/subscriptions/views/test_subscriptions_list.py

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,6 @@ def test_list_complete(
6666
user,
6767
provider,
6868
node,
69-
file_updated_notification,
7069
url
7170
):
7271
res = app.get(url, auth=user.auth)
@@ -91,8 +90,37 @@ def test_cannot_post_patch_put_or_delete(self, app, url, user):
9190
assert put_res.status_code == 405
9291
assert delete_res.status_code == 405
9392

94-
def test_multiple_values_filter(self, app, url, file_updated_notification, user):
93+
def test_multiple_values_filter(self, app, url, user):
9594
res = app.get(url + '?filter[event_name]=comments,file_updated', auth=user.auth)
9695
assert len(res.json['data']) == 2
9796
for subscription in res.json['data']:
9897
subscription['attributes']['event_name'] in ['global', 'comments']
98+
99+
def test_value_filter_id(
100+
self,
101+
app,
102+
url,
103+
user,
104+
node,
105+
):
106+
# Request all subscriptions first, to confirm all are visible
107+
res = app.get(url, auth=user.auth)
108+
all_ids = [sub['id'] for sub in res.json['data']]
109+
assert len(all_ids) == 2
110+
assert f'{node._id}_file_updated' in all_ids
111+
assert f'{user._id}_global_file_updated' in all_ids
112+
113+
# Now filter by a specific annotated legacy_id (the node file_updated one)
114+
target_id = f'{node._id}_file_updated'
115+
filtered_res = app.get(f'{url}?filter[id]={target_id}', auth=user.auth)
116+
117+
# Response should contain exactly one record matching that legacy_id
118+
assert filtered_res.status_code == 200
119+
data = filtered_res.json['data']
120+
assert len(data) == 1
121+
assert data[0]['id'] == target_id
122+
123+
# Confirm it’s the expected subscription object
124+
attributes = data[0]['attributes']
125+
assert attributes['event_name'] is None # event names are legacy
126+
assert attributes['frequency'] in ['instantly', 'daily', 'none']

notifications/listeners.py

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,17 +21,24 @@ def subscribe_creator(resource):
2121
NotificationSubscription.objects.get_or_create(
2222
user=user,
2323
notification_type=NotificationType.Type.USER_FILE_UPDATED.instance,
24+
object_id=user.id,
25+
content_type=ContentType.objects.get_for_model(user),
2426
_is_digest=True,
27+
message_frequency='instantly',
28+
)
29+
except NotificationSubscription.MultipleObjectsReturned:
30+
pass
31+
try:
32+
NotificationSubscription.objects.get_or_create(
33+
user=user,
34+
notification_type=NotificationType.Type.NODE_FILE_UPDATED.instance,
35+
object_id=resource.id,
36+
content_type=ContentType.objects.get_for_model(resource),
37+
_is_digest=True,
38+
message_frequency='instantly',
2539
)
2640
except NotificationSubscription.MultipleObjectsReturned:
2741
pass
28-
NotificationSubscription.objects.get_or_create(
29-
user=user,
30-
notification_type=NotificationType.Type.FILE_UPDATED.instance,
31-
object_id=resource.id,
32-
content_type=ContentType.objects.get_for_model(resource),
33-
_is_digest=True,
34-
)
3542

3643
@contributor_added.connect
3744
def subscribe_contributor(resource, contributor, auth=None, *args, **kwargs):
@@ -54,7 +61,7 @@ def subscribe_contributor(resource, contributor, auth=None, *args, **kwargs):
5461
),
5562
NotificationSubscription(
5663
user=contributor,
57-
notification_type=NotificationType.Type.FILE_UPDATED.instance,
64+
notification_type=NotificationType.Type.NODE_FILE_UPDATED.instance,
5865
object_id=resource.id,
5966
content_type=ContentType.objects.get_for_model(resource),
6067
_is_digest=True,

osf_tests/management_commands/test_migrate_notifications.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,6 @@ def test_migrate_provider_subscription(self, users, provider, provider2):
105105
assert subs.filter(object_id=obj.id, content_type=content_type).exists()
106106

107107
def test_migrate_node_subscription(self, users, user, node):
108-
self.create_legacy_sub('file_updated', users, user=user, node=node)
109108
migrate_legacy_notification_subscriptions()
110109
nt = NotificationType.objects.get(name=NotificationType.Type.NODE_FILE_UPDATED)
111110
assert nt.object_content_type == ContentType.objects.get_for_model(Node)

0 commit comments

Comments
 (0)