Skip to content

Commit cffaee2

Browse files
authored
Implement migration identity keys (#556)
1 parent 5eae19c commit cffaee2

File tree

11 files changed

+274
-48
lines changed

11 files changed

+274
-48
lines changed

LeanplumSDK/LeanplumSDK/ClassesSwift/Migration/MigrationManager+API.swift

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
// LeanplumSDK
44
//
55
// Created by Nikola Zagorchev on 6.10.22.
6-
// Copyright © 2022 Leanplum. All rights reserved.
6+
// Copyright © 2023 Leanplum. All rights reserved.
77

88
@objc public extension MigrationManager {
99
var state: MigrationState {
@@ -26,6 +26,10 @@
2626
return attributeMappings
2727
}
2828

29+
var cleverTapIdentityKeys: [String] {
30+
return identityKeys
31+
}
32+
2933
var hasLaunched: Bool {
3034
guard let wrapper = wrapper else { return false }
3135

LeanplumSDK/LeanplumSDK/ClassesSwift/Migration/MigrationManager+Constants.swift

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
// LeanplumSDK
44
//
55
// Created by Nikola Zagorchev on 2.10.22.
6-
// Copyright © 2022 Leanplum. All rights reserved.
6+
// Copyright © 2023 Leanplum. All rights reserved.
77

88
import Foundation
99

@@ -15,15 +15,9 @@ import Foundation
1515
static let MigrationStateKey = "__leanplum_migration_state"
1616
static let RegionCodeKey = "__leanplum_region_code"
1717
static let AttributeMappingsKey = "__leanplum_attribute_mappings"
18+
static let IdentityKeysKey = "__leanplum_identity_keys"
1819

19-
static let MigrateStateResponseParam = "migrateState"
20-
static let SdkResponseParam = "sdk"
21-
static let CTResponseParam = "ct"
22-
static let AccountIdResponseParam = "accountId"
23-
static let AccountTokenResponseParam = "token"
24-
static let RegionCodeResponseParam = "regionCode"
25-
static let AttributeMappingsResponseParam = "attributeMappings"
26-
static let HashResponseParam = "sha256";
20+
static let DefaultIdentityKeys = [IdentityManager.Constants.Identity]
2721

2822
static let CleverTapRequestArg = "ct"
2923
}

LeanplumSDK/LeanplumSDK/ClassesSwift/Migration/MigrationManager+ResponseHandler.swift

Lines changed: 89 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -3,74 +3,130 @@
33
// LeanplumSDK
44
//
55
// Created by Nikola Zagorchev on 3.10.22.
6-
// Copyright © 2022 Leanplum. All rights reserved.
6+
// Copyright © 2023 Leanplum. All rights reserved.
77

88
import Foundation
99

1010
@objc public extension MigrationManager {
11-
// migrateState = {
11+
12+
// MARK: - ResponseParams
13+
enum ResponseParams {
14+
static let MigrateState = "migrateState"
15+
static let Hash = "sha256";
16+
}
17+
18+
// MARK: - MigrationData
19+
struct MigrationData: Codable, Equatable {
20+
let ct: CTConfig?
21+
let migrationState: String?
22+
let hash: String?
23+
24+
enum CodingKeys: String, CodingKey {
25+
case hash = "sha256"
26+
case migrationState = "sdk"
27+
case ct
28+
}
29+
}
30+
31+
// MARK: - CTConfig
32+
struct CTConfig: Codable, Equatable {
33+
let accountID: String?
34+
let token: String?
35+
let regionCode: String?
36+
let attributeMappings: [String: String]?
37+
let identityKeys: [String]?
38+
39+
enum CodingKeys: String, CodingKey {
40+
case accountID = "accountId"
41+
case token, regionCode, attributeMappings, identityKeys
42+
}
43+
}
44+
45+
// MARK: - Handle Responses
46+
// migrateState = {
1247
// sha256 = 31484a565dcd3e1672922c7c4166bfeee0f500b6d6473fc412091304cc162ca8;
1348
// };
1449
@objc
1550
func handleMigrateState(multiApiResponse: Any) {
1651
guard let migrateState = getValue(dict: multiApiResponse,
17-
key: Constants.MigrateStateResponseParam)
52+
key: ResponseParams.MigrateState)
1853
else { return }
1954

20-
if let hash = getValue(dict: migrateState, key: Constants.HashResponseParam) as? String,
55+
if let hash = getValue(dict: migrateState, key: ResponseParams.Hash) as? String,
2156
hash != self.migrationHash {
2257
Log.debug("[Wrapper] CleverTap Hash changed")
2358
fetchMigrationStateAsync {}
2459
}
2560
}
2661

27-
// response = (
28-
// {
29-
// api = {
30-
// events = "lp+ct";
31-
// profile = "lp+ct";
32-
// };
33-
// ct = {
34-
// accountId = "accId";
35-
// attributeMappings = {
36-
// name1 = "ct-name1";
37-
// };
38-
// regionCode = eu1;
39-
// token = "token";
40-
// };
41-
// eventsUploadStartedTs = "2022-10-02T17:46:01.356Z";
42-
// profileUploadStartedTs = "2022-10-02T17:46:01.356Z";
43-
// reqId = "A285641F-9903-4182-8A10-EB42782CAE69";
44-
// sdk = "lp+ct";
45-
// sha256 = 31484a565dcd3e1672922c7c4166bfeee0f500b6d6473fc412091304cc162ca8;
46-
// state = "EVENTS_UPLOAD_STARTED";
47-
// success = 1;
62+
// "response": [
63+
// {
64+
// "api": {
65+
// "events": "lp+ct",
66+
// "profile": "lp+ct",
67+
// },
68+
// "ct": {
69+
// "accountId": "accId",
70+
// "attributeMappings": {
71+
// "name1": "ct-name1",
72+
// },
73+
// "identityKeys": ["Identity", "Email"],
74+
// "regionCode": "eu1",
75+
// "token": "token",
76+
// },
77+
// "eventsUploadStartedTs": "2022-10-02T17:46:01.356Z",
78+
// "profileUploadStartedTs": "2022-10-02T17:46:01.356Z",
79+
// "reqId": "A285641F-9903-4182-8A10-EB42782CAE69",
80+
// "sdk": "lp+ct",
81+
// "sha256": "31484a565dcd3e1672922c7c4166bfeee0f500b6d6473fc412091304cc162ca8",
82+
// "state": "EVENTS_UPLOAD_STARTED",
83+
// "success": 1,
4884
// }
49-
// );
85+
// ]
5086
func handleGetMigrateState(apiResponse: Any) {
51-
if let ct = getValue(dict: apiResponse, key: Constants.CTResponseParam) {
52-
if let id = getValue(dict: ct, key: Constants.AccountIdResponseParam) as? String {
87+
guard let migrationData = parseResponse(apiResponse: apiResponse) else {
88+
return
89+
}
90+
91+
if let ct = migrationData.ct {
92+
if let id = ct.accountID {
5393
accountId = id
5494
}
55-
if let token = getValue(dict: ct, key: Constants.AccountTokenResponseParam) as? String {
95+
if let token = ct.token {
5696
accountToken = token
5797
}
58-
if let region = getValue(dict: ct, key: Constants.RegionCodeResponseParam) as? String {
98+
if let region = ct.regionCode {
5999
regionCode = region
60100
}
61-
if let mappings = getValue(dict: ct, key: Constants.AttributeMappingsResponseParam) as? [String: String] {
101+
if let mappings = ct.attributeMappings {
62102
attributeMappings = mappings
63103
}
104+
if let keys = ct.identityKeys, keys.count > 0 {
105+
identityKeys = keys
106+
}
64107
}
65108

66-
if let sdk = getValue(dict: apiResponse, key: Constants.SdkResponseParam) as? String {
109+
if let sdk = migrationData.migrationState {
67110
migrationState = MigrationState(stringValue: sdk)
68111
}
69-
if let hash = getValue(dict: apiResponse, key: Constants.HashResponseParam) as? String {
112+
if let hash = migrationData.hash {
70113
migrationHash = hash
71114
}
72115
}
73116

117+
// MARK: - Utils
118+
@nonobjc internal func parseResponse(apiResponse: Any) -> MigrationData? {
119+
if let dict = apiResponse as? [String: Any] {
120+
do {
121+
let jsonData = try JSONSerialization.data(withJSONObject: dict, options: .prettyPrinted)
122+
return try JSONDecoder().decode(MigrationData.self, from: jsonData)
123+
} catch {
124+
Log.error("[Wrapper] Error parsing getMigrateState response: \(error.localizedDescription), error: \(String(describing: error))")
125+
}
126+
}
127+
return nil
128+
}
129+
74130
private func getValue(dict: Any, key: String) -> Any? {
75131
guard let dict = dict as? [String: Any] else {
76132
return nil

LeanplumSDK/LeanplumSDK/ClassesSwift/Migration/MigrationManager.swift

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
// LeanplumSDK
44
//
55
// Created by Nikola Zagorchev on 13.07.22.
6-
// Copyright © 2022 Leanplum. All rights reserved.
6+
// Copyright © 2023 Leanplum. All rights reserved.
77

88
import Foundation
99

@@ -33,6 +33,9 @@ import Foundation
3333
@PropUserDefaults(key: Constants.AttributeMappingsKey, defaultValue: [:])
3434
var attributeMappings: [String: String]
3535

36+
@PropUserDefaults(key: Constants.IdentityKeysKey, defaultValue: Constants.DefaultIdentityKeys)
37+
var identityKeys: [String]
38+
3639
@MigrationStateUserDefaults(key: Constants.MigrationStateKey, defaultValue: .undefined)
3740
var migrationState: MigrationState {
3841
didSet {

LeanplumSDK/LeanplumSDK/ClassesSwift/Migration/Wrapper/CTWrapper.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
// LeanplumSDK
44
//
55
// Created by Nikola Zagorchev on 9.07.22.
6-
// Copyright © 2022 Leanplum. All rights reserved.
6+
// Copyright © 2023 Leanplum. All rights reserved.
77

88
import Foundation
99
// Use @_implementationOnly to *not* expose CleverTapSDK to the Leanplum-Swift header
@@ -53,6 +53,7 @@ class CTWrapper: Wrapper {
5353

5454
func launch() {
5555
let config = CleverTapInstanceConfig.init(accountId: accountId, accountToken: accountToken, accountRegion: accountRegion)
56+
config.identityKeys = MigrationManager.shared.identityKeys
5657
config.useCustomCleverTapId = true
5758
config.logLevel = CleverTapLogLevel(LPLogManager.logLevel())
5859
cleverTapInstance = CleverTap.instance(with: config, andCleverTapID: identityManager.cleverTapID)

LeanplumSDKApp/LeanplumSDKApp.xcodeproj/project.pbxproj

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,13 @@
139139
6A9D0A9A273430A700466133 /* NotificationTestHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A9D0A99273430A700466133 /* NotificationTestHelper.swift */; };
140140
6A9DECA527B6ABFB00052807 /* change_host_response.json in Resources */ = {isa = PBXBuildFile; fileRef = 6A9DECA427B69D8800052807 /* change_host_response.json */; };
141141
6A9DECA627B6ABFB00052807 /* change_host_response.json in Resources */ = {isa = PBXBuildFile; fileRef = 6A9DECA427B69D8800052807 /* change_host_response.json */; };
142+
6AA3505B29953CFF008677C1 /* get_migrate_state_response.json in Resources */ = {isa = PBXBuildFile; fileRef = 6AA3505529953CEF008677C1 /* get_migrate_state_response.json */; };
143+
6AA3505C29953D00008677C1 /* get_migrate_state_response.json in Resources */ = {isa = PBXBuildFile; fileRef = 6AA3505529953CEF008677C1 /* get_migrate_state_response.json */; };
144+
6AA3505E29955FD4008677C1 /* get_migrate_state_response_error.json in Resources */ = {isa = PBXBuildFile; fileRef = 6AA3505D29955FD4008677C1 /* get_migrate_state_response_error.json */; };
145+
6AA3505F29955FD4008677C1 /* get_migrate_state_response_error.json in Resources */ = {isa = PBXBuildFile; fileRef = 6AA3505D29955FD4008677C1 /* get_migrate_state_response_error.json */; };
146+
6AA3506129956040008677C1 /* get_migrate_state_response_missing.json in Resources */ = {isa = PBXBuildFile; fileRef = 6AA3506029956040008677C1 /* get_migrate_state_response_missing.json */; };
147+
6AA3506229956040008677C1 /* get_migrate_state_response_missing.json in Resources */ = {isa = PBXBuildFile; fileRef = 6AA3506029956040008677C1 /* get_migrate_state_response_missing.json */; };
148+
6AA3506429956AEC008677C1 /* MigrationResponsesTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6AA3506329956AEC008677C1 /* MigrationResponsesTest.swift */; };
142149
6AF543A228E883AD0025F2A9 /* LeanplumLocationAndBeacons.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6AF5439728E882CA0025F2A9 /* LeanplumLocationAndBeacons.framework */; };
143150
6AF6426D298198160021A997 /* Leanplum.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6AA13C7B2900546400EDCA69 /* Leanplum.framework */; };
144151
6AF6426E298198160021A997 /* Leanplum.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 6AA13C7B2900546400EDCA69 /* Leanplum.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
@@ -355,6 +362,10 @@
355362
6A9D0A99273430A700466133 /* NotificationTestHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationTestHelper.swift; sourceTree = "<group>"; };
356363
6A9DECA427B69D8800052807 /* change_host_response.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = change_host_response.json; sourceTree = "<group>"; };
357364
6AA13C742900546400EDCA69 /* LeanplumSDK.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = LeanplumSDK.xcodeproj; path = ../LeanplumSDK/LeanplumSDK.xcodeproj; sourceTree = "<group>"; };
365+
6AA3505529953CEF008677C1 /* get_migrate_state_response.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = get_migrate_state_response.json; sourceTree = "<group>"; };
366+
6AA3505D29955FD4008677C1 /* get_migrate_state_response_error.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = get_migrate_state_response_error.json; sourceTree = "<group>"; };
367+
6AA3506029956040008677C1 /* get_migrate_state_response_missing.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = get_migrate_state_response_missing.json; sourceTree = "<group>"; };
368+
6AA3506329956AEC008677C1 /* MigrationResponsesTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MigrationResponsesTest.swift; sourceTree = "<group>"; };
358369
6AEAEE592795B68700680F84 /* Leanplum.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = Leanplum.framework; sourceTree = BUILT_PRODUCTS_DIR; };
359370
6AEAEE612795B72A00680F84 /* LeanplumLocationAndBeacons.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = LeanplumLocationAndBeacons.framework; sourceTree = BUILT_PRODUCTS_DIR; };
360371
6AF5438D28E882CA0025F2A9 /* LeanplumSDKLocation.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = LeanplumSDKLocation.xcodeproj; path = ../LeanplumSDKLocation/LeanplumSDKLocation.xcodeproj; sourceTree = "<group>"; };
@@ -589,6 +600,9 @@
589600
075AB1342684AB9D007CA1BD /* variants_response.json */,
590601
075AB13A2684AB9D007CA1BD /* Malformed */,
591602
6A9DECA427B69D8800052807 /* change_host_response.json */,
603+
6AA3505529953CEF008677C1 /* get_migrate_state_response.json */,
604+
6AA3505D29955FD4008677C1 /* get_migrate_state_response_error.json */,
605+
6AA3506029956040008677C1 /* get_migrate_state_response_missing.json */,
592606
);
593607
path = Responses;
594608
sourceTree = "<group>";
@@ -658,6 +672,7 @@
658672
6A37A8A928F0078500F4339F /* Migration+Extensions.swift */,
659673
6A37A8AB28F00B5800F4339F /* IdentityManagerTest.swift */,
660674
6A37A8AD28F0164700F4339F /* IdentityManagerMocks.swift */,
675+
6AA3506329956AEC008677C1 /* MigrationResponsesTest.swift */,
661676
);
662677
path = Migration;
663678
sourceTree = "<group>";
@@ -856,13 +871,16 @@
856871
07828DB2268B4A630029A339 /* local_caps_week_response.json in Resources */,
857872
07828DB5268B4A630029A339 /* local_caps_session_response.json in Resources */,
858873
075AACF726847BF4007CA1BD /* LaunchScreen.storyboard in Resources */,
874+
6AA3505E29955FD4008677C1 /* get_migrate_state_response_error.json in Resources */,
859875
075AB1842684AB9D007CA1BD /* TiedPriorities2.json in Resources */,
860876
07828DB4268B4A630029A339 /* local_caps_day_response.json in Resources */,
861877
07828DB3268B4A630029A339 /* local_caps_response.json in Resources */,
862878
075AB1862684AB9D007CA1BD /* TiedPrioritiesDifferentDelay.json in Resources */,
863879
075AB15E2684AB9D007CA1BD /* action_response.json in Resources */,
864880
075AB16C2684AB9D007CA1BD /* state_response.json in Resources */,
881+
6AA3506129956040008677C1 /* get_migrate_state_response_missing.json in Resources */,
865882
075AB0962684A1A4007CA1BD /* Leanplum-Info.plist in Resources */,
883+
6AA3505B29953CFF008677C1 /* get_migrate_state_response.json in Resources */,
866884
075AB1622684AB9D007CA1BD /* start_variables_response.json in Resources */,
867885
075AB1702684AB9D007CA1BD /* batch_response.json in Resources */,
868886
075AB1602684AB9D007CA1BD /* track_event_response.json in Resources */,
@@ -924,15 +942,18 @@
924942
075AB1672684AB9D007CA1BD /* secured_vars_no_sign_response.json in Resources */,
925943
075AB17F2684AB9D007CA1BD /* DifferentPriorities2.json in Resources */,
926944
075AB1772684AB9D007CA1BD /* variables_response.json in Resources */,
945+
6AA3506229956040008677C1 /* get_migrate_state_response_missing.json in Resources */,
927946
075AB1572684AB9D007CA1BD /* test.pdf in Resources */,
928947
075AB1792684AB9D007CA1BD /* secured_vars_response.json in Resources */,
929948
075AB1892684AB9D007CA1BD /* TiedPriorities1.json in Resources */,
930949
07828DAE268B4A5E0029A339 /* local_caps_day_response.json in Resources */,
931950
075AB18B2684AB9D007CA1BD /* DifferentPrioritiesWithMissingValues.json in Resources */,
932951
075AB1712684AB9D007CA1BD /* batch_response.json in Resources */,
952+
6AA3505F29955FD4008677C1 /* get_migrate_state_response_error.json in Resources */,
933953
075AB1692684AB9D007CA1BD /* malformed_track_event_response.json in Resources */,
934954
075AB1592684AB9D007CA1BD /* test.file in Resources */,
935955
075AB1872684AB9D007CA1BD /* TiedPrioritiesDifferentDelay.json in Resources */,
956+
6AA3505C29953D00008677C1 /* get_migrate_state_response.json in Resources */,
936957
075AB1652684AB9D007CA1BD /* start_with_variant_debug_info_response.json in Resources */,
937958
075AB16F2684AB9D007CA1BD /* simple_start_response.json in Resources */,
938959
);
@@ -1080,6 +1101,7 @@
10801101
075AB1172684AAD9007CA1BD /* LPRequestTest.m in Sources */,
10811102
6A9D0A9827342EE300466133 /* NotificationsManagerMock.swift in Sources */,
10821103
075AB1282684AAD9007CA1BD /* LPRequestFactory+Extension.m in Sources */,
1104+
6AA3506429956AEC008677C1 /* MigrationResponsesTest.swift in Sources */,
10831105
39C081A8278D95ED00C1DBD6 /* ActionManagerTest.swift in Sources */,
10841106
6A07FDA52811AF3800995BE3 /* ContentMergerTest.swift in Sources */,
10851107
075AB12A2684AAD9007CA1BD /* LPRequestSenderTimerTest.m in Sources */,

LeanplumSDKApp/LeanplumSDKTests/Classes/Migration/CTWrapperTest.swift

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
//
2-
// WrapperTest.swift
2+
// CTWrapperTest.swift
33
// LeanplumSDKTests
44
//
55
// Created by Nikola Zagorchev on 5.10.22.
6-
//
6+
// Copyright © 2023 Leanplum. All rights reserved.
77

88
import Foundation
99
import XCTest
1010
@testable import Leanplum
1111

12-
class WrapperTest: XCTestCase {
12+
class CTWrapperTest: XCTestCase {
1313

1414
static let attributeMappings = ["lpName": "ctName", "lpName2": "ctName2"]
1515
let wrapper = CTWrapper(accountId: "", accountToken: "", accountRegion: "", userId: "", deviceId: "", callbacks: [])
@@ -118,4 +118,8 @@ class WrapperTest: XCTestCase {
118118
XCTAssertTrue(actual.isEqual(expected))
119119
XCTAssertTrue(actualWithNil.isEqual(expected))
120120
}
121+
122+
func testIdentityDefaultValue() {
123+
XCTAssertEqual(MigrationManager.shared.identityKeys, ["Identity"])
124+
}
121125
}

0 commit comments

Comments
 (0)