@@ -35,82 +35,116 @@ class OSIdentityOperationExecutor: OSOperationExecutor {
35
35
var addRequestQueue : [ OSRequestAddAliases ] = [ ]
36
36
var removeRequestQueue : [ OSRequestRemoveAlias ] = [ ]
37
37
let newRecordsState : OSNewRecordsState
38
+ let jwtConfig : OSUserJwtConfig
38
39
39
40
// The Identity executor dispatch queue, serial. This synchronizes access to the delta and request queues.
40
41
private let dispatchQueue = DispatchQueue ( label: " OneSignal.OSIdentityOperationExecutor " , target: . global( ) )
41
42
42
- init ( newRecordsState: OSNewRecordsState ) {
43
+ init ( newRecordsState: OSNewRecordsState , jwtConfig : OSUserJwtConfig ) {
43
44
self . newRecordsState = newRecordsState
45
+ self . jwtConfig = jwtConfig
46
+ self . jwtConfig. subscribe ( self , key: OS_IDENTITY_EXECUTOR)
47
+ print ( " ❌ OSIdentityOperationExecutor init( \( jwtConfig. isRequired) ) " )
44
48
// Read unfinished deltas and requests from cache, if any...
45
49
uncacheDeltas ( )
46
50
uncacheAddAliasRequests ( )
47
51
uncacheRemoveAliasRequests ( )
48
52
}
49
53
50
54
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 {
66
56
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
+ }
67
78
}
79
+
80
+ self . deltaQueue = deltaQueue
81
+ OneSignalUserDefaults . initShared ( ) . saveCodeableData ( forKey: OS_IDENTITY_EXECUTOR_DELTA_QUEUE_KEY, withValue: self . deltaQueue)
68
82
}
69
83
70
84
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 {
89
86
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
+ }
90
111
}
112
+
113
+ self . addRequestQueue = addRequestQueue
114
+ OneSignalUserDefaults . initShared ( ) . saveCodeableData ( forKey: OS_IDENTITY_EXECUTOR_ADD_REQUEST_QUEUE_KEY, withValue: self . addRequestQueue)
91
115
}
92
116
93
117
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 {
112
119
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
+ }
113
144
}
145
+
146
+ self . removeRequestQueue = removeRequestQueue
147
+ OneSignalUserDefaults . initShared ( ) . saveCodeableData ( forKey: OS_IDENTITY_EXECUTOR_REMOVE_REQUEST_QUEUE_KEY, withValue: self . removeRequestQueue)
114
148
}
115
149
116
150
func enqueueDelta( _ delta: OSDelta ) {
@@ -139,6 +173,11 @@ class OSIdentityOperationExecutor: OSOperationExecutor {
139
173
continue
140
174
}
141
175
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
+
142
181
switch delta. name {
143
182
case OS_ADD_ALIAS_DELTA:
144
183
let request = OSRequestAddAliases ( aliases: aliases, identityModel: model)
@@ -294,6 +333,49 @@ class OSIdentityOperationExecutor: OSOperationExecutor {
294
333
}
295
334
}
296
335
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
+
297
379
extension OSIdentityOperationExecutor : OSLoggable {
298
380
func logSelf( ) {
299
381
print (
0 commit comments