@@ -47,7 +47,7 @@ class OSSubscriptionOperationExecutor: OSOperationExecutor {
4747 init ( newRecordsState: OSNewRecordsState , jwtConfig: OSUserJwtConfig ) {
4848 self . newRecordsState = newRecordsState
4949 self . jwtConfig = jwtConfig
50- // Read unfinished deltas and requests from cache, if any...
50+ self . jwtConfig . subscribe ( self , key : OS_SUBSCRIPTION_EXECUTOR )
5151 uncacheDeltas ( )
5252 uncacheRequests ( )
5353 }
@@ -141,17 +141,30 @@ class OSSubscriptionOperationExecutor: OSOperationExecutor {
141141 private func linkDeleteSubscriptionRequests( requests: inout [ OSRequestDeleteSubscription ] ) {
142142 // Hook each uncached Request to the model in the store
143143 for (index, request) in requests. enumerated ( ) . reversed ( ) {
144+ // 1. Hook up the subscription model
144145 if let subscriptionModel = getSubscriptionModelFromStores ( modelId: request. subscriptionModel. modelId) {
145- // 1 . The model exists in the store, set it to be the Request's model
146+ // a . The model exists in the store, set it to be the Request's model
146147 request. subscriptionModel = subscriptionModel
147148 } else if let subscriptionModel = subscriptionModels [ request. subscriptionModel. modelId] {
148- // 2 . The model exists in the dict of seen subscription models
149+ // b . The model exists in the dict of seen subscription models
149150 request. subscriptionModel = subscriptionModel
150151 } else if !request. prepareForExecution ( newRecordsState: newRecordsState) {
151- // 3 . The model does not exist AND this request cannot be sent, drop this Request
152+ // c . The model does not exist AND this request cannot be sent, drop this Request
152153 OneSignalLog . onesignalLog ( . LL_ERROR, message: " OSSubscriptionOperationExecutor.init dropped \( request) " )
153154 requests. remove ( at: index)
154155 }
156+ // 2. Hook up the identity model
157+ if let identityModel = OneSignalUserManagerImpl . sharedInstance. getIdentityModel ( request. identityModel. modelId) {
158+ // a. The model exist in the repo
159+ request. identityModel = identityModel
160+ } else if request. prepareForExecution ( newRecordsState: newRecordsState) {
161+ // b. The request can be sent, add the model to the repo
162+ OneSignalUserManagerImpl . sharedInstance. addIdentityModelToRepo ( request. identityModel)
163+ } else {
164+ // c. The model do not exist AND this request cannot be sent, drop this Request
165+ OneSignalLog . onesignalLog ( . LL_WARN, message: " OSSubscriptionOperationExecutor.init dropped: \( request) " )
166+ requests. remove ( at: index)
167+ }
155168 }
156169 self . removeRequestQueue = requests
157170 OneSignalUserDefaults . initShared ( ) . saveCodeableData ( forKey: OS_SUBSCRIPTION_EXECUTOR_REMOVE_REQUEST_QUEUE_KEY, withValue: self . removeRequestQueue)
@@ -254,8 +267,20 @@ class OSSubscriptionOperationExecutor: OSOperationExecutor {
254267 self . addRequestQueue. append ( request)
255268
256269 case OS_REMOVE_SUBSCRIPTION_DELTA:
270+ // Only create the request if the identity model exists
271+ guard let identityModel = OneSignalUserManagerImpl . sharedInstance. getIdentityModel ( delta. identityModelId) else {
272+ OneSignalLog . onesignalLog ( . LL_ERROR, message: " OSSubscriptionOperationExecutor.processDeltaQueue dropped \( delta) " )
273+ continue
274+ }
275+
276+ // If JWT is on but the external ID does not exist, drop this Delta
277+ if self . jwtConfig. isRequired == true , identityModel. externalId == nil {
278+ print ( " ❌ \( delta) is Invalid with JWT, being dropped " )
279+ }
280+
257281 let request = OSRequestDeleteSubscription (
258- subscriptionModel: subModel
282+ subscriptionModel: subModel,
283+ identityModel: identityModel
259284 )
260285 self . removeRequestQueue. append ( request)
261286
@@ -317,31 +342,11 @@ class OSSubscriptionOperationExecutor: OSOperationExecutor {
317342 }
318343 }
319344 }
345+ }
320346
321- func handleUnauthorizedError( externalId: String , error: NSError , request: OSUserRequest ) {
322- if jwtConfig. isRequired ?? false {
323- self . pendRequestUntilAuthUpdated ( request, externalId: externalId)
324- OneSignalUserManagerImpl . sharedInstance. invalidateJwtForExternalId ( externalId: externalId, error: error)
325- }
326- }
327-
328- func pendRequestUntilAuthUpdated( _ request: OSUserRequest , externalId: String ? ) {
329- self . dispatchQueue. async {
330- self . removeFromRequestQueueAndPersist ( request)
331- guard let externalId = externalId else {
332- return
333- }
334- var requests = self . pendingAuthRequests [ externalId] ?? [ ]
335- let inQueue = requests. contains ( where: { $0 == request} )
336- guard !inQueue else {
337- return
338- }
339- requests. append ( request)
340- self . pendingAuthRequests [ externalId] = requests
341- OneSignalUserDefaults . initShared ( ) . saveCodeableData ( forKey: OS_SUBSCRIPTION_EXECUTOR_PENDING_QUEUE_KEY, withValue: self . pendingAuthRequests)
342- }
343- }
347+ // MARK: - Execution
344348
349+ extension OSSubscriptionOperationExecutor {
345350 func executeCreateSubscriptionRequest( _ request: OSRequestCreateSubscription , inBackground: Bool ) {
346351 guard !request. sentToClient else {
347352 return
@@ -416,7 +421,7 @@ class OSSubscriptionOperationExecutor: OSOperationExecutor {
416421 guard !request. sentToClient else {
417422 return
418423 }
419- // ECM TODO
424+ // ECM TODO - Delete Subscription, not supported on JWT yet (9-23-2024)
420425// guard request.addJWTHeaderIsValid(identityModel: request.identityModel) else {
421426// pendRequestUntilAuthUpdated(request, externalId:request.identityModel.externalId)
422427// return
@@ -448,8 +453,7 @@ class OSSubscriptionOperationExecutor: OSOperationExecutor {
448453 if let nsError = error as? NSError {
449454 let responseType = OSNetworkingUtils . getResponseStatusType ( nsError. code)
450455 if responseType == . unauthorized && ( self . jwtConfig. isRequired ?? false ) {
451- // ECM The delete subscription request doesn't have an identity model?
452- if let externalId = OneSignalUserManagerImpl . sharedInstance. user. identityModel. externalId {
456+ if let externalId = request. identityModel. externalId {
453457 self . handleUnauthorizedError ( externalId: externalId, error: nsError, request: request)
454458 }
455459 request. sentToClient = false
@@ -470,11 +474,6 @@ class OSSubscriptionOperationExecutor: OSOperationExecutor {
470474 guard !request. sentToClient else {
471475 return
472476 }
473- // ECM TODO
474- // guard request.addJWTHeaderIsValid(identityModel: request.identityModel) else {
475- // pendRequestUntilAuthUpdated(request, externalId:request.identityModel.externalId)
476- // return
477- // }
478477 guard request. prepareForExecution ( newRecordsState: newRecordsState) else {
479478 return
480479 }
@@ -499,11 +498,7 @@ class OSSubscriptionOperationExecutor: OSOperationExecutor {
499498 if let nsError = error as? NSError {
500499 let responseType = OSNetworkingUtils . getResponseStatusType ( nsError. code)
501500 if responseType == . unauthorized && ( self . jwtConfig. isRequired ?? false ) {
502- // ECM The update subscription request doesn't have an identity model?
503- if let externalId = OneSignalUserManagerImpl . sharedInstance. user. identityModel. externalId {
504- self . handleUnauthorizedError ( externalId: externalId, error: nsError, request: request)
505- }
506- request. sentToClient = false
501+ // TODO: Jwt, do we need to handle this case, as this request does not use user JWT
507502 } else if responseType != . retryable {
508503 // Fail, no retry, remove from cache and queue
509504 self . removeFromRequestQueueAndPersist ( request)
@@ -520,14 +515,40 @@ class OSSubscriptionOperationExecutor: OSOperationExecutor {
520515extension OSSubscriptionOperationExecutor : OSUserJwtConfigListener {
521516 func onRequiresUserAuthChanged( from: OneSignalOSCore . OSRequiresUserAuth , to: OneSignalOSCore . OSRequiresUserAuth ) {
522517 print ( " ❌ OSSubscriptionOperationExecutor onUserAuthChanged from \( String ( describing: from) ) to \( String ( describing: to) ) " )
523- // ECM TODO If auth changed from false or unknown to true, process requests
518+ if to == . on {
519+ removeInvalidDeltasAndRequests ( )
520+ }
524521 }
525522
526523 func onJwtUpdated( externalId: String , token: String ? ) {
527524 print ( " ❌ OSSubscriptionOperationExecutor onJwtUpdated for \( externalId) to \( String ( describing: token) ) " )
528525 reQueuePendingRequestsForExternalId ( externalId: externalId)
529526 }
530527
528+ func handleUnauthorizedError( externalId: String , error: NSError , request: OSUserRequest ) {
529+ if jwtConfig. isRequired ?? false {
530+ self . pendRequestUntilAuthUpdated ( request, externalId: externalId)
531+ OneSignalUserManagerImpl . sharedInstance. invalidateJwtForExternalId ( externalId: externalId, error: error)
532+ }
533+ }
534+
535+ func pendRequestUntilAuthUpdated( _ request: OSUserRequest , externalId: String ? ) {
536+ self . dispatchQueue. async {
537+ self . removeFromRequestQueueAndPersist ( request)
538+ guard let externalId = externalId else {
539+ return
540+ }
541+ var requests = self . pendingAuthRequests [ externalId] ?? [ ]
542+ let inQueue = requests. contains ( where: { $0 == request} )
543+ guard !inQueue else {
544+ return
545+ }
546+ requests. append ( request)
547+ self . pendingAuthRequests [ externalId] = requests
548+ OneSignalUserDefaults . initShared ( ) . saveCodeableData ( forKey: OS_SUBSCRIPTION_EXECUTOR_PENDING_QUEUE_KEY, withValue: self . pendingAuthRequests)
549+ }
550+ }
551+
531552 private func reQueuePendingRequestsForExternalId( externalId: String ) {
532553 self . dispatchQueue. async {
533554 guard let requests = self . pendingAuthRequests [ externalId] else {
@@ -538,18 +559,52 @@ extension OSSubscriptionOperationExecutor: OSUserJwtConfigListener {
538559 self . addRequestQueue. append ( addRequest)
539560 } else if let removeRequest = request as? OSRequestDeleteSubscription {
540561 self . removeRequestQueue. append ( removeRequest)
541- } else if let updateRequest = request as? OSRequestUpdateSubscription {
542- self . updateRequestQueue. append ( updateRequest)
543562 }
544563 }
545564 OneSignalUserDefaults . initShared ( ) . saveCodeableData ( forKey: OS_SUBSCRIPTION_EXECUTOR_ADD_REQUEST_QUEUE_KEY, withValue: self . addRequestQueue)
546565 OneSignalUserDefaults . initShared ( ) . saveCodeableData ( forKey: OS_SUBSCRIPTION_EXECUTOR_REMOVE_REQUEST_QUEUE_KEY, withValue: self . removeRequestQueue)
547- OneSignalUserDefaults . initShared ( ) . saveCodeableData ( forKey: OS_SUBSCRIPTION_EXECUTOR_UPDATE_REQUEST_QUEUE_KEY, withValue: self . updateRequestQueue)
548566 self . pendingAuthRequests [ externalId] = nil
549567 OneSignalUserDefaults . initShared ( ) . saveCodeableData ( forKey: OS_SUBSCRIPTION_EXECUTOR_PENDING_QUEUE_KEY, withValue: self . pendingAuthRequests)
550568 self . processRequestQueue ( inBackground: false )
551569 }
552570 }
571+
572+ /**
573+ Drops deltas and requests that add and remove subscriptions on unidentified users.
574+ Subscription updates are used only for push subscriptions, which are kept as they do not use User JWT.
575+ */
576+ private func removeInvalidDeltasAndRequests( ) {
577+ self . dispatchQueue. async {
578+ print ( " ❌ OSSubscriptionOperationExecutor.removeInvalidDeltasAndRequests called " )
579+
580+ for (index, delta) in self . deltaQueue. enumerated ( ) . reversed ( ) {
581+ if delta. name != OS_UPDATE_SUBSCRIPTION_DELTA,
582+ let identityModel = OneSignalUserManagerImpl . sharedInstance. getIdentityModel ( delta. identityModelId) ,
583+ identityModel. externalId == nil
584+ {
585+ print ( " \( delta) is Invalid, being removed " )
586+ self . deltaQueue. remove ( at: index)
587+ }
588+ }
589+ OneSignalUserDefaults . initShared ( ) . saveCodeableData ( forKey: OS_SUBSCRIPTION_EXECUTOR_DELTA_QUEUE_KEY, withValue: self . deltaQueue)
590+
591+ for (index, request) in self . addRequestQueue. enumerated ( ) . reversed ( ) {
592+ if request. identityModel. externalId == nil {
593+ print ( " \( request) is Invalid, being removed " )
594+ self . addRequestQueue. remove ( at: index)
595+ }
596+ }
597+ OneSignalUserDefaults . initShared ( ) . saveCodeableData ( forKey: OS_SUBSCRIPTION_EXECUTOR_ADD_REQUEST_QUEUE_KEY, withValue: self . updateRequestQueue)
598+
599+ for (index, request) in self . removeRequestQueue. enumerated ( ) . reversed ( ) {
600+ if request. identityModel. externalId == nil {
601+ print ( " \( request) is Invalid, being removed " )
602+ self . removeRequestQueue. remove ( at: index)
603+ }
604+ }
605+ OneSignalUserDefaults . initShared ( ) . saveCodeableData ( forKey: OS_SUBSCRIPTION_EXECUTOR_REMOVE_REQUEST_QUEUE_KEY, withValue: self . updateRequestQueue)
606+ }
607+ }
553608}
554609
555610extension OSSubscriptionOperationExecutor : OSLoggable {
0 commit comments