Skip to content

Commit f3e6256

Browse files
committed
Update Executors to consider JWT
Updates to: * OSPropertyOperationExecutor * OSIdentityOperationExecutor * OSUserExecutor Updates to OSSubscriptionOperationExecutor is still to be done.
1 parent 722dd0e commit f3e6256

File tree

6 files changed

+396
-94
lines changed

6 files changed

+396
-94
lines changed

iOS_SDK/OneSignalSDK/OneSignalCore/Source/OneSignalCommonDefines.h

+3
Original file line numberDiff line numberDiff line change
@@ -343,15 +343,18 @@ typedef enum {GET, POST, HEAD, PUT, DELETE, OPTIONS, CONNECT, TRACE, PATCH} HTTP
343343
#define OS_OPERATION_REPO_DELTA_QUEUE_KEY @"OS_OPERATION_REPO_DELTA_QUEUE_KEY"
344344

345345
// User Executor
346+
#define OS_USER_EXECUTOR @"OS_USER_EXECUTOR"
346347
#define OS_USER_EXECUTOR_USER_REQUEST_QUEUE_KEY @"OS_USER_EXECUTOR_USER_REQUEST_QUEUE_KEY"
347348
#define OS_USER_EXECUTOR_TRANSFER_SUBSCRIPTION_REQUEST_QUEUE_KEY @"OS_USER_EXECUTOR_TRANSFER_SUBSCRIPTION_REQUEST_QUEUE_KEY"
348349

349350
// Identity Executor
351+
#define OS_IDENTITY_EXECUTOR @"OS_IDENTITY_EXECUTOR"
350352
#define OS_IDENTITY_EXECUTOR_DELTA_QUEUE_KEY @"OS_IDENTITY_EXECUTOR_DELTA_QUEUE_KEY"
351353
#define OS_IDENTITY_EXECUTOR_ADD_REQUEST_QUEUE_KEY @"OS_IDENTITY_EXECUTOR_ADD_REQUEST_QUEUE_KEY"
352354
#define OS_IDENTITY_EXECUTOR_REMOVE_REQUEST_QUEUE_KEY @"OS_IDENTITY_EXECUTOR_REMOVE_REQUEST_QUEUE_KEY"
353355

354356
// Property Executor
357+
#define OS_PROPERTIES_EXECUTOR @"OS_PROPERTIES_EXECUTOR"
355358
#define OS_PROPERTIES_EXECUTOR_DELTA_QUEUE_KEY @"OS_PROPERTIES_EXECUTOR_DELTA_QUEUE_KEY"
356359
#define OS_PROPERTIES_EXECUTOR_UPDATE_REQUEST_QUEUE_KEY @"OS_PROPERTIES_EXECUTOR_UPDATE_REQUEST_QUEUE_KEY"
357360

iOS_SDK/OneSignalSDK/OneSignalUser/Source/Executors/OSIdentityOperationExecutor.swift

+134-52
Original file line numberDiff line numberDiff line change
@@ -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+
297379
extension OSIdentityOperationExecutor: OSLoggable {
298380
func logSelf() {
299381
print(

0 commit comments

Comments
 (0)