@@ -35,82 +35,116 @@ class OSIdentityOperationExecutor: OSOperationExecutor {
3535 var addRequestQueue : [ OSRequestAddAliases ] = [ ]
3636 var removeRequestQueue : [ OSRequestRemoveAlias ] = [ ]
3737 let newRecordsState : OSNewRecordsState
38+ let jwtConfig : OSUserJwtConfig
3839
3940 // The Identity executor dispatch queue, serial. This synchronizes access to the delta and request queues.
4041 private let dispatchQueue = DispatchQueue ( label: " OneSignal.OSIdentityOperationExecutor " , target: . global( ) )
4142
42- init ( newRecordsState: OSNewRecordsState ) {
43+ init ( newRecordsState: OSNewRecordsState , jwtConfig : OSUserJwtConfig ) {
4344 self . newRecordsState = newRecordsState
45+ self . jwtConfig = jwtConfig
46+ self . jwtConfig. subscribe ( self , key: OS_IDENTITY_EXECUTOR)
47+ print ( " ❌ OSIdentityOperationExecutor init( \( jwtConfig. isRequired) ) " )
4448 // Read unfinished deltas and requests from cache, if any...
4549 uncacheDeltas ( )
4650 uncacheAddAliasRequests ( )
4751 uncacheRemoveAliasRequests ( )
4852 }
4953
5054 private func uncacheDeltas( ) {
51- if var deltaQueue = OneSignalUserDefaults . initShared ( ) . getSavedCodeableData ( forKey: OS_IDENTITY_EXECUTOR_DELTA_QUEUE_KEY, defaultValue: [ ] ) as? [ OSDelta ] {
52- // Hook each uncached Delta to the model in the store
53- for (index, delta) in deltaQueue. enumerated ( ) . reversed ( ) {
54- if let modelInStore = OneSignalUserManagerImpl . sharedInstance. getIdentityModel ( delta. model. modelId) {
55- // The model exists in the repo, set it to be the Delta's model
56- delta. model = modelInStore
57- } else {
58- // The model does not exist, drop this Delta
59- OneSignalLog . onesignalLog ( . LL_ERROR, message: " OSIdentityOperationExecutor.init dropped \( delta) " )
60- deltaQueue. remove ( at: index)
61- }
62- }
63- self . deltaQueue = deltaQueue
64- OneSignalUserDefaults . initShared ( ) . saveCodeableData ( forKey: OS_IDENTITY_EXECUTOR_DELTA_QUEUE_KEY, withValue: self . deltaQueue)
65- } else {
55+ guard var deltaQueue = OneSignalUserDefaults . initShared ( ) . getSavedCodeableData ( forKey: OS_IDENTITY_EXECUTOR_DELTA_QUEUE_KEY, defaultValue: [ ] ) as? [ OSDelta ] else {
6656 OneSignalLog . onesignalLog ( . LL_ERROR, message: " OSIdentityOperationExecutor error encountered reading from cache for \( OS_IDENTITY_EXECUTOR_DELTA_QUEUE_KEY) " )
57+ return
58+ }
59+
60+ // Hook each uncached Delta to the model in the store
61+ for (index, delta) in deltaQueue. enumerated ( ) . reversed ( ) {
62+ if jwtConfig. isRequired == true ,
63+ ( delta. model as? OSIdentityModel ) ? . externalId == nil
64+ {
65+ // remove if jwt is on but the model does not have external ID
66+ deltaQueue. remove ( at: index)
67+ continue
68+ }
69+
70+ if let modelInStore = OneSignalUserManagerImpl . sharedInstance. getIdentityModel ( delta. model. modelId) {
71+ // The model exists in the repo, set it to be the Delta's model
72+ delta. model = modelInStore
73+ } else {
74+ // The model does not exist, drop this Delta
75+ OneSignalLog . onesignalLog ( . LL_ERROR, message: " OSIdentityOperationExecutor.init dropped \( delta) " )
76+ deltaQueue. remove ( at: index)
77+ }
6778 }
79+
80+ self . deltaQueue = deltaQueue
81+ OneSignalUserDefaults . initShared ( ) . saveCodeableData ( forKey: OS_IDENTITY_EXECUTOR_DELTA_QUEUE_KEY, withValue: self . deltaQueue)
6882 }
6983
7084 private func uncacheAddAliasRequests( ) {
71- if var addRequestQueue = OneSignalUserDefaults . initShared ( ) . getSavedCodeableData ( forKey: OS_IDENTITY_EXECUTOR_ADD_REQUEST_QUEUE_KEY, defaultValue: [ ] ) as? [ OSRequestAddAliases ] {
72- // Hook each uncached Request to the model in the store
73- for (index, request) in addRequestQueue. enumerated ( ) . reversed ( ) {
74- if let identityModel = OneSignalUserManagerImpl . sharedInstance. getIdentityModel ( request. identityModel. modelId) {
75- // 1. The model exists in the repo, so set it to be the Request's models
76- request. identityModel = identityModel
77- } else if request. prepareForExecution ( newRecordsState: newRecordsState) {
78- // 2. The request can be sent, add the model to the repo
79- OneSignalUserManagerImpl . sharedInstance. addIdentityModelToRepo ( request. identityModel)
80- } else {
81- // 3. The model do not exist AND this request cannot be sent, drop this Request
82- OneSignalLog . onesignalLog ( . LL_ERROR, message: " OSIdentityOperationExecutor.init dropped \( request) " )
83- addRequestQueue. remove ( at: index)
84- }
85- }
86- self . addRequestQueue = addRequestQueue
87- OneSignalUserDefaults . initShared ( ) . saveCodeableData ( forKey: OS_IDENTITY_EXECUTOR_ADD_REQUEST_QUEUE_KEY, withValue: self . addRequestQueue)
88- } else {
85+ guard var addRequestQueue = OneSignalUserDefaults . initShared ( ) . getSavedCodeableData ( forKey: OS_IDENTITY_EXECUTOR_ADD_REQUEST_QUEUE_KEY, defaultValue: [ ] ) as? [ OSRequestAddAliases ] else {
8986 OneSignalLog . onesignalLog ( . LL_ERROR, message: " OSIdentityOperationExecutor error encountered reading from cache for \( OS_IDENTITY_EXECUTOR_ADD_REQUEST_QUEUE_KEY) " )
87+ return
88+ }
89+
90+ // Hook each uncached Request to the model in the store
91+ for (index, request) in addRequestQueue. enumerated ( ) . reversed ( ) {
92+ if jwtConfig. isRequired == true ,
93+ request. identityModel. externalId == nil
94+ {
95+ // remove if jwt is on but the model does not have external ID
96+ addRequestQueue. remove ( at: index)
97+ continue
98+ }
99+
100+ if let identityModel = OneSignalUserManagerImpl . sharedInstance. getIdentityModel ( request. identityModel. modelId) {
101+ // 1. The model exists in the repo, so set it to be the Request's models
102+ request. identityModel = identityModel
103+ } else if request. prepareForExecution ( newRecordsState: newRecordsState) {
104+ // 2. The request can be sent, add the model to the repo
105+ OneSignalUserManagerImpl . sharedInstance. addIdentityModelToRepo ( request. identityModel)
106+ } else {
107+ // 3. The model do not exist AND this request cannot be sent, drop this Request
108+ OneSignalLog . onesignalLog ( . LL_ERROR, message: " OSIdentityOperationExecutor.init dropped \( request) " )
109+ addRequestQueue. remove ( at: index)
110+ }
90111 }
112+
113+ self . addRequestQueue = addRequestQueue
114+ OneSignalUserDefaults . initShared ( ) . saveCodeableData ( forKey: OS_IDENTITY_EXECUTOR_ADD_REQUEST_QUEUE_KEY, withValue: self . addRequestQueue)
91115 }
92116
93117 private func uncacheRemoveAliasRequests( ) {
94- if var removeRequestQueue = OneSignalUserDefaults . initShared ( ) . getSavedCodeableData ( forKey: OS_IDENTITY_EXECUTOR_REMOVE_REQUEST_QUEUE_KEY, defaultValue: [ ] ) as? [ OSRequestRemoveAlias ] {
95- // Hook each uncached Request to the model in the store
96- for (index, request) in removeRequestQueue. enumerated ( ) . reversed ( ) {
97- if let identityModel = OneSignalUserManagerImpl . sharedInstance. getIdentityModel ( request. identityModel. modelId) {
98- // 1. The model exists in the repo, so set it to be the Request's model
99- request. identityModel = identityModel
100- } else if request. prepareForExecution ( newRecordsState: newRecordsState) {
101- // 2. The request can be sent, add the model to the repo
102- OneSignalUserManagerImpl . sharedInstance. addIdentityModelToRepo ( request. identityModel)
103- } else {
104- // 3. The model does not exist AND this request cannot be sent, drop this Request
105- OneSignalLog . onesignalLog ( . LL_ERROR, message: " OSIdentityOperationExecutor.init dropped \( request) " )
106- removeRequestQueue. remove ( at: index)
107- }
108- }
109- self . removeRequestQueue = removeRequestQueue
110- OneSignalUserDefaults . initShared ( ) . saveCodeableData ( forKey: OS_IDENTITY_EXECUTOR_REMOVE_REQUEST_QUEUE_KEY, withValue: self . removeRequestQueue)
111- } else {
118+ guard var removeRequestQueue = OneSignalUserDefaults . initShared ( ) . getSavedCodeableData ( forKey: OS_IDENTITY_EXECUTOR_REMOVE_REQUEST_QUEUE_KEY, defaultValue: [ ] ) as? [ OSRequestRemoveAlias ] else {
112119 OneSignalLog . onesignalLog ( . LL_ERROR, message: " OSIdentityOperationExecutor error encountered reading from cache for \( OS_IDENTITY_EXECUTOR_REMOVE_REQUEST_QUEUE_KEY) " )
120+ return
121+ }
122+
123+ // Hook each uncached Request to the model in the store
124+ for (index, request) in removeRequestQueue. enumerated ( ) . reversed ( ) {
125+ if jwtConfig. isRequired == true ,
126+ request. identityModel. externalId == nil
127+ {
128+ // remove if jwt is on but the model does not have external ID
129+ removeRequestQueue. remove ( at: index)
130+ continue
131+ }
132+
133+ if let identityModel = OneSignalUserManagerImpl . sharedInstance. getIdentityModel ( request. identityModel. modelId) {
134+ // 1. The model exists in the repo, so set it to be the Request's models
135+ request. identityModel = identityModel
136+ } else if request. prepareForExecution ( newRecordsState: newRecordsState) {
137+ // 2. The request can be sent, add the model to the repo
138+ OneSignalUserManagerImpl . sharedInstance. addIdentityModelToRepo ( request. identityModel)
139+ } else {
140+ // 3. The model do not exist AND this request cannot be sent, drop this Request
141+ OneSignalLog . onesignalLog ( . LL_ERROR, message: " OSIdentityOperationExecutor.init dropped \( request) " )
142+ removeRequestQueue. remove ( at: index)
143+ }
113144 }
145+
146+ self . removeRequestQueue = removeRequestQueue
147+ OneSignalUserDefaults . initShared ( ) . saveCodeableData ( forKey: OS_IDENTITY_EXECUTOR_REMOVE_REQUEST_QUEUE_KEY, withValue: self . removeRequestQueue)
114148 }
115149
116150 func enqueueDelta( _ delta: OSDelta ) {
@@ -139,6 +173,11 @@ class OSIdentityOperationExecutor: OSOperationExecutor {
139173 continue
140174 }
141175
176+ // If JWT is on but the external ID does not exist, drop this Delta
177+ if self . jwtConfig. isRequired == true , model. externalId == nil {
178+ print ( " ❌ \( delta) is Invalid with JWT, being dropped " )
179+ }
180+
142181 switch delta. name {
143182 case OS_ADD_ALIAS_DELTA:
144183 let request = OSRequestAddAliases ( aliases: aliases, identityModel: model)
@@ -294,6 +333,49 @@ class OSIdentityOperationExecutor: OSOperationExecutor {
294333 }
295334}
296335
336+ extension OSIdentityOperationExecutor : OSUserJwtConfigListener {
337+ func onRequiresUserAuthChanged( from: Bool ? , to: Bool ? ) {
338+ print ( " ❌ OSIdentityOperationExecutor onUserAuthChanged from \( String ( describing: from) ) to \( String ( describing: to) ) " )
339+ // If auth changed from false or unknown to true, process requests
340+ if to == true {
341+ removeInvalidDeltasAndRequests ( )
342+ }
343+ }
344+
345+ func onJwtUpdated( externalId: String , to: String ? ) {
346+ print ( " ❌ OSIdentityOperationExecutor onJwtUpdated for \( externalId) to \( String ( describing: to) ) " )
347+ }
348+
349+ private func removeInvalidDeltasAndRequests( ) {
350+ self . dispatchQueue. async {
351+ print ( " ❌ OSIdentityOperationExecutor.removeInvalidDeltasAndRequests called " )
352+ for (index, delta) in self . deltaQueue. enumerated ( ) . reversed ( ) {
353+ if ( delta. model as? OSIdentityModel ) ? . externalId == nil {
354+ print ( " \( delta) is Invalid, being removed " )
355+ self . deltaQueue. remove ( at: index)
356+ }
357+ }
358+ OneSignalUserDefaults . initShared ( ) . saveCodeableData ( forKey: OS_IDENTITY_EXECUTOR_DELTA_QUEUE_KEY, withValue: self . deltaQueue)
359+
360+ for (index, request) in self . addRequestQueue. enumerated ( ) . reversed ( ) {
361+ if request. identityModel. externalId == nil {
362+ print ( " \( request) is Invalid, being removed " )
363+ self . addRequestQueue. remove ( at: index)
364+ }
365+ }
366+ OneSignalUserDefaults . initShared ( ) . saveCodeableData ( forKey: OS_IDENTITY_EXECUTOR_ADD_REQUEST_QUEUE_KEY, withValue: self . addRequestQueue)
367+
368+ for (index, request) in self . removeRequestQueue. enumerated ( ) . reversed ( ) {
369+ if request. identityModel. externalId == nil {
370+ print ( " \( request) is Invalid, being removed " )
371+ self . removeRequestQueue. remove ( at: index)
372+ }
373+ }
374+ OneSignalUserDefaults . initShared ( ) . saveCodeableData ( forKey: OS_IDENTITY_EXECUTOR_REMOVE_REQUEST_QUEUE_KEY, withValue: self . removeRequestQueue)
375+ }
376+ }
377+ }
378+
297379extension OSIdentityOperationExecutor : OSLoggable {
298380 func logSelf( ) {
299381 print (
0 commit comments