Skip to content

Commit bfec2a3

Browse files
fix: fix UserBuilder to always set isAnonymous, refactor DevCycleUser params (#236)
* fix: fix UserBuilder to always set isAnonymous, refactor DevCycleUser params * fix: set isAnonymous=false if user_id is set
1 parent a5fa580 commit bfec2a3

File tree

7 files changed

+242
-164
lines changed

7 files changed

+242
-164
lines changed

DevCycle/DevCycleClient.swift

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ public class DevCycleClient {
166166
if let config = config,
167167
self.checkIfEdgeDBEnabled(config: config, enableEdgeDB: self.enableEdgeDB)
168168
{
169-
if !(user.isAnonymous ?? false) {
169+
if !user.isAnonymous {
170170
self.service?.saveEntity(
171171
user: user,
172172
completion: { data, response, error in
@@ -264,10 +264,13 @@ public class DevCycleClient {
264264
return
265265
}
266266
do {
267-
guard let messageDictionary =
268-
try JSONSerialization.jsonObject(
269-
with: messageData, options: .fragmentsAllowed) as? [String: Any] else {
270-
throw SSEMessage.SSEMessageError.messageError("Error serializing sse message to JSON")
267+
guard
268+
let messageDictionary =
269+
try JSONSerialization.jsonObject(
270+
with: messageData, options: .fragmentsAllowed) as? [String: Any]
271+
else {
272+
throw SSEMessage.SSEMessageError.messageError(
273+
"Error serializing sse message to JSON")
271274
}
272275
let sseMessage = try SSEMessage(from: messageDictionary)
273276
if sseMessage.data.type == nil || sseMessage.data.type == "refetchConfig" {
@@ -396,14 +399,14 @@ public class DevCycleClient {
396399
}
397400

398401
public func identifyUser(user: DevCycleUser, callback: IdentifyCompletedHandler? = nil) throws {
399-
guard let currentUser = self.user, let userId = currentUser.userId,
400-
let incomingUserId = user.userId
402+
guard let currentUser = self.user, !currentUser.userId.isEmpty,
403+
!user.userId.isEmpty
401404
else {
402405
throw ClientError.InvalidUser
403406
}
404407
self.flushEvents()
405408
var updateUser: DevCycleUser = currentUser
406-
if userId == incomingUserId {
409+
if currentUser.userId == user.userId {
407410
updateUser.update(with: user)
408411
} else {
409412
updateUser = user
@@ -416,7 +419,9 @@ public class DevCycleClient {
416419
completion: { [weak self] config, error in
417420
guard let self = self else { return }
418421
if let error = error {
419-
Log.error("Error getting config: \(error) for user_id \(String(describing: updateUser.userId))", tags: ["identify"])
422+
Log.error(
423+
"Error getting config: \(error) for user_id \(String(describing: updateUser.userId))",
424+
tags: ["identify"])
420425
self.cache = self.cacheService.load(user: updateUser)
421426
self.useCachedConfigForUser(user: updateUser)
422427
} else {
@@ -443,7 +448,9 @@ public class DevCycleClient {
443448
}
444449
}
445450
} catch {
446-
Log.error("Error calling identifyUser for user_id \(String(describing: user.userId))", tags: ["identify"])
451+
Log.error(
452+
"Error calling identifyUser for user_id \(String(describing: user.userId))",
453+
tags: ["identify"])
447454
continuation.resume(throwing: error)
448455
}
449456
}

DevCycle/DevCycleUser.swift

Lines changed: 76 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -20,90 +20,115 @@ enum UserError: Error {
2020
public class UserBuilder {
2121
private let cacheService: CacheServiceProtocol = CacheService()
2222

23-
var user: DevCycleUser
23+
var userId: String?
24+
var isAnonymous: Bool?
25+
var email: String?
26+
var name: String?
27+
var language: String?
28+
var country: String?
2429
var customData: [String: Any]?
2530
var privateCustomData: [String: Any]?
2631

2732
init() {
28-
self.user = DevCycleUser()
2933
}
3034

3135
public func userId(_ userId: String) -> UserBuilder {
32-
self.user.userId = userId
36+
self.userId = userId
3337
return self
3438
}
3539

3640
public func isAnonymous(_ isAnonymous: Bool) -> UserBuilder {
37-
self.user.isAnonymous = isAnonymous
41+
self.isAnonymous = isAnonymous
3842
return self
3943
}
4044

41-
public func email(_ email: String) -> UserBuilder {
42-
self.user.email = email
45+
public func email(_ email: String?) -> UserBuilder {
46+
self.email = email
4347
return self
4448
}
4549

46-
public func name(_ name: String) -> UserBuilder {
47-
self.user.name = name
50+
public func name(_ name: String?) -> UserBuilder {
51+
self.name = name
4852
return self
4953
}
5054

51-
public func language(_ language: String) -> UserBuilder {
52-
self.user.language = language
55+
public func language(_ language: String?) -> UserBuilder {
56+
self.language = language
5357
return self
5458
}
5559

56-
public func country(_ country: String) -> UserBuilder {
57-
self.user.country = country
60+
public func country(_ country: String?) -> UserBuilder {
61+
self.country = country
5862
return self
5963
}
6064

61-
public func customData(_ customData: [String: Any]) -> UserBuilder {
65+
public func customData(_ customData: [String: Any]?) -> UserBuilder {
6266
self.customData = customData
6367
return self
6468
}
6569

66-
public func privateCustomData(_ privateCustomData: [String: Any]) -> UserBuilder {
70+
public func privateCustomData(_ privateCustomData: [String: Any]?) -> UserBuilder {
6771
self.privateCustomData = privateCustomData
6872
return self
6973
}
7074

75+
private func cleanup() {
76+
self.userId = nil
77+
self.isAnonymous = nil
78+
self.email = nil
79+
self.name = nil
80+
self.language = nil
81+
self.country = nil
82+
self.customData = nil
83+
self.privateCustomData = nil
84+
}
85+
7186
public func build() throws -> DevCycleUser {
72-
// Validate the userId
73-
let hasValidUserId = self.user.userId != nil && !self.user.userId!.isEmpty
87+
let hasValidUserId = self.userId != nil && !self.userId!.isEmpty
7488

75-
// Handle the different cases based on isAnonymous and userId
76-
if self.user.isAnonymous == false && !hasValidUserId {
89+
if self.isAnonymous == false && !hasValidUserId {
7790
throw UserError.MissingUserIdAndIsAnonymousFalse
7891
}
7992

80-
if self.user.isAnonymous == true && !hasValidUserId {
81-
self.user.userId = self.cacheService.getOrCreateAnonUserId()
82-
} else if !hasValidUserId {
83-
// Default case: no userId and isAnonymous not explicitly set to false, make anonymous
84-
self.user.userId = self.cacheService.getOrCreateAnonUserId()
85-
self.user.isAnonymous = true
86-
}
87-
88-
if let customData = self.customData {
89-
self.user.customData = try CustomData.customDataFromDic(customData)
93+
let finalUserId: String
94+
let finalIsAnonymous: Bool
95+
96+
if !hasValidUserId {
97+
// Default case: no userId provided, make anonymous
98+
finalUserId = self.cacheService.getOrCreateAnonUserId()
99+
finalIsAnonymous = true
100+
} else if let userId = self.userId {
101+
// Valid userId provided, use it
102+
finalUserId = userId
103+
finalIsAnonymous = false
104+
} else {
105+
throw UserError.InvalidUser
90106
}
91107

92-
if let privateCustomData = self.privateCustomData {
93-
self.user.privateCustomData = try CustomData.customDataFromDic(privateCustomData)
108+
let customDataConverted = try self.customData.map { try CustomData.customDataFromDic($0) }
109+
let privateCustomDataConverted = try self.privateCustomData.map {
110+
try CustomData.customDataFromDic($0)
94111
}
95112

96-
let result = self.user
97-
self.user = DevCycleUser()
98-
self.customData = nil
99-
self.privateCustomData = nil
100-
return result
113+
let user = DevCycleUser(
114+
userId: finalUserId,
115+
isAnonymous: finalIsAnonymous,
116+
email: self.email,
117+
name: self.name,
118+
language: self.language,
119+
country: self.country,
120+
customData: customDataConverted,
121+
privateCustomData: privateCustomDataConverted
122+
)
123+
124+
self.cleanup()
125+
return user
101126
}
102127
}
103128

104129
public class DevCycleUser: Codable {
105-
public var userId: String?
106-
public var isAnonymous: Bool?
130+
public var userId: String
131+
public var isAnonymous: Bool
107132
public var email: String?
108133
public var name: String?
109134
public var language: String?
@@ -121,7 +146,20 @@ public class DevCycleUser: Codable {
121146
internal var appVersion: String?
122147
internal var appBuild: Int?
123148

124-
init() {
149+
init(
150+
userId: String, isAnonymous: Bool, email: String? = nil, name: String? = nil,
151+
language: String? = nil, country: String? = nil, customData: CustomData? = nil,
152+
privateCustomData: CustomData? = nil
153+
) {
154+
self.userId = userId
155+
self.isAnonymous = isAnonymous
156+
self.email = email
157+
self.name = name
158+
self.language = language
159+
self.country = country
160+
self.customData = customData
161+
self.privateCustomData = privateCustomData
162+
125163
let platform = PlatformDetails()
126164
self.lastSeenDate = Date()
127165
self.createdDate = Date()

DevCycle/Models/Cache.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -127,11 +127,11 @@ class CacheService: CacheServiceProtocol {
127127

128128
private func getConfigKeyPrefix(user: DevCycleUser) -> String {
129129
let baseKey =
130-
(user.isAnonymous ?? false)
130+
user.isAnonymous
131131
? CacheKeys.anonymousConfigKey : CacheKeys.identifiedConfigKey
132132

133-
if let userId = user.userId {
134-
return "\(baseKey)_\(userId)"
133+
if !user.userId.isEmpty {
134+
return "\(baseKey)_\(user.userId)"
135135
}
136136

137137
return baseKey

0 commit comments

Comments
 (0)