99from rest_framework .response import Response
1010
1111from framework .auth .oauth_scopes import CoreScopes
12+ from framework import sentry
1213
1314from api .base .views import JSONAPIBaseView
1415from api .base .filters import ListFilterMixin
3132 Guid ,
3233 OSFUser ,
3334)
34- from osf .models .notification_type import NotificationTypeEnum
35+ from osf .models .notification_type import NotificationTypeEnum , NotificationType
3536from osf .models .notification_subscription import NotificationSubscription
3637
3738
@@ -174,12 +175,47 @@ def get_queryset(self):
174175
175176class AbstractProviderSubscriptionList (SubscriptionList ):
176177 def get_queryset (self ):
177- provider = AbstractProvider .objects .get (_id = self .kwargs ['provider_id' ])
178+ # Get specific provider by _id and type to avoid potential conflicts with multiple provider with the same _id.
179+ try :
180+ provider = AbstractProvider .objects .get (
181+ _id = self .kwargs ['provider_id' ],
182+ type = self .provider_class ._typedmodels_type ,
183+ )
184+ except AbstractProvider .MultipleObjectsReturned :
185+ provider = AbstractProvider .objects .filter (
186+ _id = self .kwargs ['provider_id' ],
187+ type = self .provider_class ._typedmodels_type ,
188+ ).first ()
189+ sentry .log_message (f'''
190+ Multiple providers found with the same _id: [_id={ self .kwargs ["provider_id" ]} , type={ self .provider_class ._typedmodels_type } ].
191+ Using the first one with id={ provider .id } .''' )
192+
193+ # Create missing default subscriptions for the provider if they don't exist.
194+ notification_names = [
195+ NotificationTypeEnum .PROVIDER_NEW_PENDING_SUBMISSIONS .value ,
196+ NotificationTypeEnum .PROVIDER_NEW_PENDING_WITHDRAW_REQUESTS .value ,
197+ ]
198+ content_type = ContentType .objects .get_for_model (provider .__class__ )
199+
200+ notification_types = NotificationType .objects .filter (name__in = notification_names )
201+ for nt in notification_types :
202+ NotificationSubscription .objects .get_or_create (
203+ object_id = provider .id ,
204+ content_type = content_type ,
205+ user = self .request .user ,
206+ notification_type = nt ,
207+ defaults = {
208+ '_is_digest' : nt .is_digest_type ,
209+ 'message_frequency' : 'instantly' ,
210+ },
211+ )
212+
178213 return NotificationSubscription .objects .filter (
179- object_id = provider ,
180- content_type = ContentType . objects . get_for_model ( provider . __class__ ) ,
214+ object_id = provider . id ,
215+ content_type = content_type ,
181216 user = self .request .user ,
182- )
217+ notification_type__name__in = notification_names ,
218+ ).annotate (legacy_id = F ('notification_type__name' ), event_name = F ('notification_type__name' ))
183219
184220class SubscriptionDetail (JSONAPIBaseView , generics .RetrieveUpdateAPIView ):
185221 view_name = 'notification-subscription-detail'
@@ -222,7 +258,7 @@ def get_object(self):
222258 content_type = user_ct ,
223259 then = Value (f'{ user_guid } _global_reviews' ),
224260 ),
225- default = Value ( f' { user_guid } _global ' ),
261+ default = F ( 'notification_type__name ' ),
226262 output_field = CharField (),
227263 ),
228264 )
@@ -248,7 +284,7 @@ def update(self, request, *args, **kwargs):
248284 """
249285 Update a notification subscription
250286 """
251- self .get_object ()
287+ instance = self .get_object ()
252288
253289 if '_global_file_updated' in self .kwargs ['subscription_id' ]:
254290 # Copy _global_file_updated subscription changes to all file subscriptions
@@ -324,7 +360,14 @@ def update(self, request, *args, **kwargs):
324360 return Response (serializer .data )
325361
326362 else :
327- return super ().update (request , * args , ** kwargs )
363+ instance .event_name = instance .notification_type .name # Set event_name for serializer to use
364+
365+ partial = kwargs .pop ('partial' , False )
366+ serializer = self .get_serializer (instance , data = request .data , partial = partial )
367+ serializer .is_valid (raise_exception = True )
368+ self .perform_update (serializer )
369+
370+ return Response (serializer .data )
328371
329372
330373class AbstractProviderSubscriptionDetail (SubscriptionDetail ):
0 commit comments