Skip to content

Commit f4e0153

Browse files
authored
fix: [SDK-5314] JWT - drop the Identity Verification beta queues and limit cached queue (#1758)
1 parent 630b355 commit f4e0153

14 files changed

Lines changed: 491 additions & 20 deletions

‎iOS_SDK/OneSignalSDK/OneSignal.xcodeproj/project.pbxproj‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -371,6 +371,7 @@
371371
7EB69F3B404D0AEF46EC1536 /* UserJwtLifecycleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BFE2F960129386AFA6D5F41 /* UserJwtLifecycleTests.swift */; };
372372
E42087CB1AB15481E55D34FE /* UserStateReportingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDA6355B75EDC9A3100B98F5 /* UserStateReportingTests.swift */; };
373373
9345FA2E8878EA1B0216A49A /* UserJwtAskTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3567F486AA4335CCA79D659B /* UserJwtAskTests.swift */; };
374+
59611FB5A88143468425CCB3 /* CachedUserWithoutAnIdTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5249D3FD71F02D4BCAF0995B /* CachedUserWithoutAnIdTests.swift */; };
374375
8D2F4893453206700BB60F85 /* OSOperationRepoTestSupport.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5221EEDBA5A74BD565490D52 /* OSOperationRepoTestSupport.swift */; };
375376
8E949FF4C7A7A2C7182E53EA /* OSUserJwtConfigTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9376A4957E9090C748BCB18 /* OSUserJwtConfigTests.swift */; };
376377
911E2CBD1E398AB3003112A4 /* UnitTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 911E2CBC1E398AB3003112A4 /* UnitTests.m */; };
@@ -1613,6 +1614,7 @@
16131614
5BFE2F960129386AFA6D5F41 /* UserJwtLifecycleTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = UserJwtLifecycleTests.swift; sourceTree = "<group>"; };
16141615
FDA6355B75EDC9A3100B98F5 /* UserStateReportingTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = UserStateReportingTests.swift; sourceTree = "<group>"; };
16151616
3567F486AA4335CCA79D659B /* UserJwtAskTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = UserJwtAskTests.swift; sourceTree = "<group>"; };
1617+
5249D3FD71F02D4BCAF0995B /* CachedUserWithoutAnIdTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = CachedUserWithoutAnIdTests.swift; sourceTree = "<group>"; };
16161618
6552F2A6DF7776B0582CFAEF /* OSUserJwtConfig.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = OSUserJwtConfig.swift; sourceTree = "<group>"; };
16171619
67ECA2928D863073B785F93F /* IamFetchIdentityVerificationTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = IamFetchIdentityVerificationTests.swift; sourceTree = "<group>"; };
16181620
6A8BBA843AFC81A4940CF7CC /* OSUserJwtRepo.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = OSUserJwtRepo.swift; sourceTree = "<group>"; };
@@ -2558,6 +2560,7 @@
25582560
5BFE2F960129386AFA6D5F41 /* UserJwtLifecycleTests.swift */,
25592561
FDA6355B75EDC9A3100B98F5 /* UserStateReportingTests.swift */,
25602562
3567F486AA4335CCA79D659B /* UserJwtAskTests.swift */,
2563+
5249D3FD71F02D4BCAF0995B /* CachedUserWithoutAnIdTests.swift */,
25612564
);
25622565
path = OneSignalUserTests;
25632566
sourceTree = "<group>";
@@ -4760,6 +4763,7 @@
47604763
7EB69F3B404D0AEF46EC1536 /* UserJwtLifecycleTests.swift in Sources */,
47614764
E42087CB1AB15481E55D34FE /* UserStateReportingTests.swift in Sources */,
47624765
9345FA2E8878EA1B0216A49A /* UserJwtAskTests.swift in Sources */,
4766+
59611FB5A88143468425CCB3 /* CachedUserWithoutAnIdTests.swift in Sources */,
47634767
);
47644768
runOnlyForDeploymentPostprocessing = 0;
47654769
};

‎iOS_SDK/OneSignalSDK/OneSignalCore/Source/OneSignalCommonDefines.h‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,17 @@ typedef enum {GET, POST, HEAD, PUT, DELETE, OPTIONS, CONNECT, TRACE, PATCH} HTTP
378378
#define OS_CUSTOM_EVENTS_EXECUTOR_DELTA_QUEUE_KEY @"OS_CUSTOM_EVENTS_EXECUTOR_DELTA_QUEUE_KEY"
379379
#define OS_CUSTOM_EVENTS_EXECUTOR_REQUEST_QUEUE_KEY @"OS_CUSTOM_EVENTS_EXECUTOR_REQUEST_QUEUE_KEY"
380380

381+
// A codeable value larger than this is not written, and a cached queue blob larger than it is dropped without
382+
// decoding it. Real queues are a few KB. CFPreferences rejects a value of 4 MB or more on iOS.
383+
#define OS_USER_DEFAULTS_MAX_VALUE_BYTES 1048576
384+
385+
// Written only by the 5.3.0-beta Identity Verification builds. Nothing reads them anymore.
386+
#define OS_IV_BETA_USER_EXECUTOR_PENDING_QUEUE_KEY @"OS_USER_EXECUTOR_PENDING_QUEUE_KEY"
387+
#define OS_IV_BETA_IDENTITY_EXECUTOR_PENDING_QUEUE_KEY @"OS_IDENTITY_EXECUTOR_PENDING_QUEUE_KEY"
388+
#define OS_IV_BETA_PROPERTIES_EXECUTOR_PENDING_QUEUE_KEY @"OS_PROPERTIES_EXECUTOR_PENDING_QUEUE_KEY"
389+
#define OS_IV_BETA_SUBSCRIPTION_EXECUTOR_PENDING_QUEUE_KEY @"OS_SUBSCRIPTION_EXECUTOR_PENDING_QUEUE_KEY"
390+
#define OS_IV_BETA_CUSTOM_EVENTS_EXECUTOR_PENDING_QUEUE_KEY @"OS_CUSTOM_EVENTS_EXECUTOR_PENDING_QUEUE_KEY"
391+
381392
// Live Activies Executor
382393
#define OS_LIVE_ACTIVITIES_EXECUTOR_UPDATE_TOKENS_KEY @"OS_LIVE_ACTIVITIES_EXECUTOR_UPDATE_TOKENS_KEY"
383394
#define OS_LIVE_ACTIVITIES_EXECUTOR_START_TOKENS_KEY @"OS_LIVE_ACTIVITIES_EXECUTOR_START_TOKENS_KEY"

‎iOS_SDK/OneSignalSDK/OneSignalCore/Source/OneSignalUserDefaults.h‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,11 @@
6969
- (void)saveObjectForKey:(NSString * _Nonnull)key withValue:(id _Nullable)value;
7070

7171
// NSUserDefaults for storing and getting saved codeable data (custom objects)
72+
/// A blob that is not archived data or cannot be decoded is logged, left in place and `value` returned.
7273
- (id _Nullable)getSavedCodeableDataForKey:(NSString * _Nonnull)key defaultValue:(id _Nullable)value;
74+
/// Same, except that a blob larger than `maxBytes`, not archived data or undecodable is removed. 0 means no limit, and nothing is removed.
75+
- (id _Nullable)getSavedCodeableDataForKey:(NSString * _Nonnull)key defaultValue:(id _Nullable)value maxBytes:(NSUInteger)maxBytes;
76+
/// A value whose archive is larger than `OS_USER_DEFAULTS_MAX_VALUE_BYTES` is not written and the key is removed.
7377
- (void)saveCodeableDataForKey:(NSString * _Nonnull)key withValue:(id _Nullable)value;
7478

7579
@end

‎iOS_SDK/OneSignalSDK/OneSignalCore/Source/OneSignalUserDefaults.m‎

Lines changed: 57 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#import <Foundation/Foundation.h>
2929
#import "OneSignalUserDefaults.h"
3030
#import "OneSignalCommonDefines.h"
31+
#import "OneSignalLog.h"
3132

3233
@implementation OneSignalUserDefaults : NSObject
3334

@@ -152,15 +153,65 @@ - (void)saveObjectForKey:(NSString * _Nonnull)key withValue:(id _Nullable)object
152153
}
153154

154155
- (id _Nullable)getSavedCodeableDataForKey:(NSString * _Nonnull)key defaultValue:(id _Nullable)value {
155-
if ([self keyExists:key])
156-
return [NSKeyedUnarchiver unarchiveObjectWithData:[self.userDefaults objectForKey:key]];
157-
158-
return value;
156+
return [self getSavedCodeableDataForKey:key defaultValue:value maxBytes:0];
157+
}
158+
159+
- (id _Nullable)getSavedCodeableDataForKey:(NSString * _Nonnull)key defaultValue:(id _Nullable)value maxBytes:(NSUInteger)maxBytes {
160+
if (![self keyExists:key])
161+
return value;
162+
163+
id stored = [self.userDefaults objectForKey:key];
164+
if (![stored isKindOfClass:[NSData class]]) {
165+
[OneSignalLog onesignalLog:ONE_S_LL_ERROR message:[NSString stringWithFormat:@"OneSignalUserDefaults cannot decode %@: not archived data", key]];
166+
[self removeUndecodableValueForKey:key maxBytes:maxBytes];
167+
return value;
168+
}
169+
NSData *data = stored;
170+
if (maxBytes > 0 && data.length > maxBytes) {
171+
[OneSignalLog onesignalLog:ONE_S_LL_ERROR message:[NSString stringWithFormat:@"OneSignalUserDefaults dropping %@: %lu bytes, limit %lu", key, (unsigned long)data.length, (unsigned long)maxBytes]];
172+
[self removeValueForKey:key];
173+
return value;
174+
}
175+
@try {
176+
// A blob that decodes to nil is treated like a missing key.
177+
return [NSKeyedUnarchiver unarchiveObjectWithData:data] ?: value;
178+
} @catch (NSException *exception) {
179+
[OneSignalLog onesignalLog:ONE_S_LL_ERROR message:[NSString stringWithFormat:@"OneSignalUserDefaults cannot decode %@: %@", key, exception.reason]];
180+
[self removeUndecodableValueForKey:key maxBytes:maxBytes];
181+
return value;
182+
}
183+
}
184+
185+
/// Only a capped read, a queue of this SDK's own Requests, heals by deletion. An uncapped read leaves the blob to
186+
/// whichever module wrote it; a model store, for one, is overwritten by the user the SDK creates in its place.
187+
- (void)removeUndecodableValueForKey:(NSString *)key maxBytes:(NSUInteger)maxBytes {
188+
if (maxBytes > 0) {
189+
[self removeValueForKey:key];
190+
}
159191
}
160192

161193
- (void)saveCodeableDataForKey:(NSString * _Nonnull)key withValue:(id _Nullable)value {
162-
[self.userDefaults setObject:[NSKeyedArchiver archivedDataWithRootObject:value] forKey:key];
163-
[self.userDefaults synchronize];
194+
NSData *data;
195+
@try {
196+
data = [NSKeyedArchiver archivedDataWithRootObject:value];
197+
} @catch (NSException *exception) {
198+
[OneSignalLog onesignalLog:ONE_S_LL_ERROR message:[NSString stringWithFormat:@"OneSignalUserDefaults could not archive %@: %@", key, exception.reason]];
199+
return;
200+
}
201+
// Nothing the SDK caches is legitimately this large: a queue that reached it is the bloat the read cap drops,
202+
// so the previous blob goes too rather than resend the Requests it held. CFPreferences refuses a value of 4 MB
203+
// or more and can stop persisting the suite afterwards.
204+
if (data.length > OS_USER_DEFAULTS_MAX_VALUE_BYTES) {
205+
[OneSignalLog onesignalLog:ONE_S_LL_ERROR message:[NSString stringWithFormat:@"OneSignalUserDefaults not caching %@: %lu bytes", key, (unsigned long)data.length]];
206+
[self removeValueForKey:key];
207+
return;
208+
}
209+
@try {
210+
[self.userDefaults setObject:data forKey:key];
211+
[self.userDefaults synchronize];
212+
} @catch (NSException *exception) {
213+
[OneSignalLog onesignalLog:ONE_S_LL_ERROR message:[NSString stringWithFormat:@"OneSignalUserDefaults could not cache %@: %@", key, exception.reason]];
214+
}
164215
}
165216

166217
//gets the NSBundle of the primary application - NOT the app extension

‎iOS_SDK/OneSignalSDK/OneSignalCoreTests/OneSignalCoreTests.swift‎

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,4 +73,99 @@ final class OneSignalCoreTests: XCTestCase {
7373
XCTAssertEqual(templateId, "templateId123")
7474
XCTAssertEqual(templateName, "Template name")
7575
}
76+
77+
// MARK: - Codeable data guards
78+
79+
private let guardKey = "OS_CORE_TESTS_CODEABLE_GUARD"
80+
81+
func testOversizedCodeableDataIsDroppedNotDecoded() {
82+
let defaults = OneSignalUserDefaults.initShared()
83+
// A real archive over the cap; without the cap it would decode.
84+
defaults.saveCodeableData(forKey: guardKey, withValue: [String(repeating: "x", count: 2048)])
85+
86+
let restored = defaults.getSavedCodeableData(forKey: guardKey, defaultValue: ["default"], maxBytes: 1024) as? [String]
87+
88+
XCTAssertEqual(restored, ["default"])
89+
XCTAssertFalse(defaults.keyExists(guardKey))
90+
}
91+
92+
func testCodeableDataWithinTheLimitIsDecoded() {
93+
let defaults = OneSignalUserDefaults.initShared()
94+
defaults.saveCodeableData(forKey: guardKey, withValue: ["cached"])
95+
96+
let restored = defaults.getSavedCodeableData(forKey: guardKey, defaultValue: [], maxBytes: 1024) as? [String]
97+
98+
XCTAssertEqual(restored, ["cached"])
99+
defaults.removeValue(forKey: guardKey)
100+
}
101+
102+
func testUnreadableCodeableDataReturnsTheDefaultWithoutThrowing() {
103+
let defaults = OneSignalUserDefaults.initShared()
104+
defaults.saveObject(forKey: guardKey, withValue: Data("not an archive".utf8))
105+
106+
let restored = defaults.getSavedCodeableData(forKey: guardKey, defaultValue: ["default"]) as? [String]
107+
108+
XCTAssertEqual(restored, ["default"])
109+
defaults.removeValue(forKey: guardKey)
110+
}
111+
112+
func testUnarchivableValueLeavesTheCachedValueInPlace() {
113+
let defaults = OneSignalUserDefaults.initShared()
114+
defaults.saveCodeableData(forKey: guardKey, withValue: ["cached"])
115+
116+
// NSObject does not adopt NSCoding, so archiving it raises.
117+
defaults.saveCodeableData(forKey: guardKey, withValue: NSObject())
118+
119+
XCTAssertEqual(defaults.getSavedCodeableData(forKey: guardKey, defaultValue: nil) as? [String], ["cached"])
120+
defaults.removeValue(forKey: guardKey)
121+
}
122+
123+
func testValueOverTheLimitIsNotCachedAndThePreviousBlobGoesWithIt() {
124+
let defaults = OneSignalUserDefaults.initShared()
125+
defaults.saveCodeableData(forKey: guardKey, withValue: ["cached"])
126+
127+
defaults.saveCodeableData(forKey: guardKey, withValue: Data(count: Int(OS_USER_DEFAULTS_MAX_VALUE_BYTES)))
128+
129+
XCTAssertFalse(defaults.keyExists(guardKey))
130+
}
131+
132+
func testBlobThatIsNotArchivedDataIsRemovedOnlyByACappedRead() {
133+
let defaults = OneSignalUserDefaults.initShared()
134+
defaults.saveObject(forKey: guardKey, withValue: "not data")
135+
136+
XCTAssertEqual(defaults.getSavedCodeableData(forKey: guardKey, defaultValue: ["default"]) as? [String], ["default"])
137+
XCTAssertTrue(defaults.keyExists(guardKey))
138+
139+
XCTAssertEqual(defaults.getSavedCodeableData(forKey: guardKey, defaultValue: ["default"], maxBytes: 1024) as? [String], ["default"])
140+
XCTAssertFalse(defaults.keyExists(guardKey))
141+
}
142+
143+
func testUndecodableBlobIsRemovedOnlyByACappedRead() throws {
144+
let defaults = OneSignalUserDefaults.initShared()
145+
defaults.saveObject(forKey: guardKey, withValue: try archiveNamingAnUnknownClass())
146+
147+
XCTAssertEqual(defaults.getSavedCodeableData(forKey: guardKey, defaultValue: ["default"]) as? [String], ["default"])
148+
XCTAssertTrue(defaults.keyExists(guardKey))
149+
150+
XCTAssertEqual(defaults.getSavedCodeableData(forKey: guardKey, defaultValue: ["default"], maxBytes: 1024) as? [String], ["default"])
151+
XCTAssertFalse(defaults.keyExists(guardKey))
152+
}
153+
154+
/// A keyed archive whose root is of a class this process does not have. Decoding it raises, as a queue written
155+
/// by a newer build does.
156+
private func archiveNamingAnUnknownClass() throws -> Data {
157+
let archive = try NSKeyedArchiver.archivedData(withRootObject: ["cached"], requiringSecureCoding: false)
158+
var plist = try XCTUnwrap(try PropertyListSerialization.propertyList(from: archive, format: nil) as? [String: Any])
159+
var objects = try XCTUnwrap(plist["$objects"] as? [Any])
160+
for (index, object) in objects.enumerated() {
161+
guard var descriptor = object as? [String: Any], descriptor["$classname"] != nil else {
162+
continue
163+
}
164+
descriptor["$classname"] = "OSNoSuchClass"
165+
descriptor["$classes"] = ["OSNoSuchClass"]
166+
objects[index] = descriptor
167+
}
168+
plist["$objects"] = objects
169+
return try PropertyListSerialization.data(fromPropertyList: plist, format: .binary, options: 0)
170+
}
76171
}

‎iOS_SDK/OneSignalSDK/OneSignalOSCore/Source/OSOperationRepo.swift‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ public class OSOperationRepo: NSObject {
7878
}
7979

8080
private func uncacheDeltaQueue() {
81-
guard let cached = OneSignalUserDefaults.initShared().getSavedCodeableData(forKey: OS_OPERATION_REPO_DELTA_QUEUE_KEY, defaultValue: []) as? [OSDelta] else {
81+
guard let cached = OneSignalUserDefaults.initShared().getSavedCodeableData(forKey: OS_OPERATION_REPO_DELTA_QUEUE_KEY, defaultValue: [], maxBytes: UInt(OS_USER_DEFAULTS_MAX_VALUE_BYTES)) as? [OSDelta] else {
8282
OneSignalLog.onesignalLog(.LL_ERROR, message: "OSOperationRepo is unable to uncache the OSDelta queue.")
8383
return
8484
}

‎iOS_SDK/OneSignalSDK/OneSignalUser/Source/Executors/OSCustomEventsExecutor.swift‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ class OSCustomEventsExecutor: OSOperationExecutor {
6363
}
6464

6565
private func uncacheDeltas() {
66-
if var deltaQueue = OneSignalUserDefaults.initShared().getSavedCodeableData(forKey: OS_CUSTOM_EVENTS_EXECUTOR_DELTA_QUEUE_KEY, defaultValue: []) as? [OSDelta] {
66+
if var deltaQueue = OneSignalUserDefaults.initShared().getSavedCodeableData(forKey: OS_CUSTOM_EVENTS_EXECUTOR_DELTA_QUEUE_KEY, defaultValue: [], maxBytes: UInt(OS_USER_DEFAULTS_MAX_VALUE_BYTES)) as? [OSDelta] {
6767
for (index, delta) in deltaQueue.enumerated().reversed() {
6868
if OneSignalUserManagerImpl.sharedInstance.getIdentityModel(delta.identityModelId) == nil {
6969
// The identity model does not exist, drop this Delta
@@ -81,7 +81,7 @@ class OSCustomEventsExecutor: OSOperationExecutor {
8181
}
8282

8383
private func uncacheRequests() {
84-
if var requestQueue = OneSignalUserDefaults.initShared().getSavedCodeableData(forKey: OS_CUSTOM_EVENTS_EXECUTOR_REQUEST_QUEUE_KEY, defaultValue: []) as? [OSRequestCustomEvents] {
84+
if var requestQueue = OneSignalUserDefaults.initShared().getSavedCodeableData(forKey: OS_CUSTOM_EVENTS_EXECUTOR_REQUEST_QUEUE_KEY, defaultValue: [], maxBytes: UInt(OS_USER_DEFAULTS_MAX_VALUE_BYTES)) as? [OSRequestCustomEvents] {
8585
// Hook each uncached Request to the model in the store
8686
for (index, request) in requestQueue.enumerated().reversed() {
8787
if let identityModel = OneSignalUserManagerImpl.sharedInstance.getIdentityModel(request.identityModel.modelId) {

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ class OSIdentityOperationExecutor: OSOperationExecutor {
5050
}
5151

5252
private func uncacheDeltas() {
53-
if var deltaQueue = OneSignalUserDefaults.initShared().getSavedCodeableData(forKey: OS_IDENTITY_EXECUTOR_DELTA_QUEUE_KEY, defaultValue: []) as? [OSDelta] {
53+
if var deltaQueue = OneSignalUserDefaults.initShared().getSavedCodeableData(forKey: OS_IDENTITY_EXECUTOR_DELTA_QUEUE_KEY, defaultValue: [], maxBytes: UInt(OS_USER_DEFAULTS_MAX_VALUE_BYTES)) as? [OSDelta] {
5454
// Hook each uncached Delta to the model in the store
5555
for (index, delta) in deltaQueue.enumerated().reversed() {
5656
if let modelInStore = OneSignalUserManagerImpl.sharedInstance.getIdentityModel(delta.model.modelId) {
@@ -70,7 +70,7 @@ class OSIdentityOperationExecutor: OSOperationExecutor {
7070
}
7171

7272
private func uncacheAddAliasRequests() {
73-
if var addRequestQueue = OneSignalUserDefaults.initShared().getSavedCodeableData(forKey: OS_IDENTITY_EXECUTOR_ADD_REQUEST_QUEUE_KEY, defaultValue: []) as? [OSRequestAddAliases] {
73+
if var addRequestQueue = OneSignalUserDefaults.initShared().getSavedCodeableData(forKey: OS_IDENTITY_EXECUTOR_ADD_REQUEST_QUEUE_KEY, defaultValue: [], maxBytes: UInt(OS_USER_DEFAULTS_MAX_VALUE_BYTES)) as? [OSRequestAddAliases] {
7474
// Hook each uncached Request to the model in the store
7575
for (index, request) in addRequestQueue.enumerated().reversed() {
7676
if let identityModel = OneSignalUserManagerImpl.sharedInstance.getIdentityModel(request.identityModel.modelId) {
@@ -93,7 +93,7 @@ class OSIdentityOperationExecutor: OSOperationExecutor {
9393
}
9494

9595
private func uncacheRemoveAliasRequests() {
96-
if var removeRequestQueue = OneSignalUserDefaults.initShared().getSavedCodeableData(forKey: OS_IDENTITY_EXECUTOR_REMOVE_REQUEST_QUEUE_KEY, defaultValue: []) as? [OSRequestRemoveAlias] {
96+
if var removeRequestQueue = OneSignalUserDefaults.initShared().getSavedCodeableData(forKey: OS_IDENTITY_EXECUTOR_REMOVE_REQUEST_QUEUE_KEY, defaultValue: [], maxBytes: UInt(OS_USER_DEFAULTS_MAX_VALUE_BYTES)) as? [OSRequestRemoveAlias] {
9797
// Hook each uncached Request to the model in the store
9898
for (index, request) in removeRequestQueue.enumerated().reversed() {
9999
if let identityModel = OneSignalUserManagerImpl.sharedInstance.getIdentityModel(request.identityModel.modelId) {

0 commit comments

Comments
 (0)