Skip to content

Commit fb427ab

Browse files
feat: Handle Hashed Email for Rokt (#22)
* feat: Handle Hashed Email for Rokt * fix crash when passing user tags into Rokt
1 parent 0c2ead6 commit fb427ab

2 files changed

Lines changed: 110 additions & 2 deletions

File tree

mParticle-Rokt/MPKitRokt.m

Lines changed: 62 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ - (RoktFrameworkType)mapMPWrapperSdkToRoktFrameworkType:(MPWrapperSdk)wrapperSdk
181181
if (filteredUser == nil && roktKit != nil) {
182182
filteredUser = [[[MPKitAPI alloc] init] getCurrentUserWithKit:roktKit];
183183
}
184-
NSDictionary<NSString *, NSString *> *mpAttributes = [filteredUser.userAttributes transformValuesToString];
184+
NSDictionary<NSString *, NSString *> *mpAttributes = [self transformValuesToString:filteredUser.userAttributes];
185185
if (performMapping) {
186186
mpAttributes = [self mapAttributes:attributes filteredUser:filteredUser];
187187
}
@@ -197,6 +197,9 @@ - (RoktFrameworkType)mapMPWrapperSdkToRoktFrameworkType:(MPWrapperSdk)wrapperSdk
197197
// Add all known user identities to the attributes being passed to the Rokt SDK
198198
[self addIdentityAttributes:finalAtt filteredUser:filteredUser];
199199

200+
// Handle hashed email use case
201+
[self handleHashedEmail:finalAtt];
202+
200203
// The core SDK does not set sandbox on the user, but we must pass it to Rokt if provided
201204
NSString *sandboxKey = @"sandbox";
202205
if (attributes[sandboxKey] != nil) {
@@ -206,6 +209,42 @@ - (RoktFrameworkType)mapMPWrapperSdkToRoktFrameworkType:(MPWrapperSdk)wrapperSdk
206209
return [self confirmSandboxAttribute:finalAtt];
207210
}
208211

212+
+ (NSDictionary<NSString *, NSString *> *)transformValuesToString:(NSDictionary<NSString *, id> * _Nullable)originalDictionary {
213+
__block NSMutableDictionary<NSString *, NSString *> *transformedDictionary = [[NSMutableDictionary alloc] initWithCapacity:originalDictionary.count];
214+
Class NSStringClass = [NSString class];
215+
Class NSNumberClass = [NSNumber class];
216+
217+
[originalDictionary enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
218+
if ([obj isKindOfClass:NSStringClass]) {
219+
transformedDictionary[key] = obj;
220+
} else if ([obj isKindOfClass:NSNumberClass]) {
221+
NSNumber *numberAttribute = (NSNumber *)obj;
222+
223+
if (numberAttribute == (void *)kCFBooleanFalse || numberAttribute == (void *)kCFBooleanTrue) {
224+
transformedDictionary[key] = [numberAttribute boolValue] ? @"true" : @"false";
225+
} else {
226+
transformedDictionary[key] = [numberAttribute stringValue];
227+
}
228+
} else if ([obj isKindOfClass:[NSDate class]]) {
229+
transformedDictionary[key] = [MPDateFormatter stringFromDateRFC3339:obj];
230+
} else if ([obj isKindOfClass:[NSData class]] && [(NSData *)obj length] > 0) {
231+
transformedDictionary[key] = [[NSString alloc] initWithData:obj encoding:NSUTF8StringEncoding];
232+
} else if ([obj isKindOfClass:[NSDictionary class]]) {
233+
transformedDictionary[key] = [obj description];
234+
} else if ([obj isKindOfClass:[NSMutableDictionary class]]) {
235+
transformedDictionary[key] = [obj description];
236+
} else if ([obj isKindOfClass:[NSArray class]]) {
237+
transformedDictionary[key] = [obj description];
238+
} else if ([obj isKindOfClass:[NSMutableArray class]]) {
239+
transformedDictionary[key] = [obj description];
240+
} else if ([obj isKindOfClass:[NSNull class]]) {
241+
transformedDictionary[key] = @"null";
242+
}
243+
}];
244+
245+
return transformedDictionary;
246+
}
247+
209248
+ (NSDictionary<NSString *, NSString *> *)mapAttributes:(NSDictionary<NSString *, NSString *> * _Nullable)attributes filteredUser:(FilteredMParticleUser * _Nonnull)filteredUser {
210249
NSArray<NSDictionary<NSString *, NSString *> *> *attributeMap = nil;
211250

@@ -273,7 +312,7 @@ - (RoktFrameworkType)mapMPWrapperSdkToRoktFrameworkType:(MPWrapperSdk)wrapperSdk
273312
}
274313
}
275314

276-
return [mappedAttributes transformValuesToString];
315+
return [self transformValuesToString:mappedAttributes];
277316
} else {
278317
return attributes;
279318
}
@@ -293,6 +332,27 @@ + (void)addIdentityAttributes:(NSMutableDictionary<NSString *, NSString *> * _Nu
293332
}
294333
}
295334

335+
+ (void)handleHashedEmail:(NSMutableDictionary<NSString *, NSString *> * _Nullable)attributes {
336+
NSString *emailKey = [MPKitRokt stringForIdentityType:MPIdentityEmail];
337+
NSString *otherKey = [MPKitRokt stringForIdentityType:MPIdentityOther];
338+
NSString *hashedEmailValue = attributes[@"emailsha256"];
339+
340+
// Remove email and other is hashed vlaue already set
341+
if (hashedEmailValue != nil) {
342+
[attributes removeObjectForKey:emailKey];
343+
[attributes removeObjectForKey:otherKey];
344+
}
345+
346+
NSString *otherValue = attributes[otherKey];
347+
348+
// Remove email and replace key on other if it's set
349+
if (otherValue != nil) {
350+
[attributes removeObjectForKey:emailKey];
351+
attributes[@"emailsha256"] = otherValue;
352+
[attributes removeObjectForKey:otherKey];
353+
}
354+
}
355+
296356
+ (RoktConfig *)convertMPRoktConfig:(MPRoktConfig *)mpRoktConfig {
297357
if (mpRoktConfig != nil) {
298358
Builder *builder = [[Builder alloc] init];

mParticle_RoktTests/mParticle_RoktTests.m

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,12 @@ - (MPKitExecStatus *)purchaseFinalized:(NSString *)placementId
2323

2424
+ (void)addIdentityAttributes:(NSMutableDictionary<NSString *, NSString *> * _Nullable)attributes filteredUser:(FilteredMParticleUser * _Nonnull)filteredUser;
2525

26+
+ (void)handleHashedEmail:(NSMutableDictionary<NSString *, NSString *> * _Nullable)attributes;
27+
2628
+ (RoktConfig *)convertMPRoktConfig:(MPRoktConfig *)mpRoktConfig;
2729

30+
+ (NSDictionary<NSString *, NSString *> *)transformValuesToString:(NSDictionary<NSString *, id> * _Nullable)originalDictionary;
31+
2832
@end
2933

3034
@interface mParticle_RoktTests : XCTestCase
@@ -493,4 +497,48 @@ - (void)testEvents_NilIdentifier {
493497
[mockRoktSDK stopMocking];
494498
}
495499

500+
- (void)testHandleHashedEmailOtherOverride {
501+
NSMutableDictionary<NSString *, NSString *> *passedAttributes = [[NSMutableDictionary alloc] init];
502+
[passedAttributes setObject:@"foo@gmail.com" forKey:@"email"];
503+
[passedAttributes setObject:@"test@gmail.com" forKey:@"other"];
504+
505+
[MPKitRokt handleHashedEmail:passedAttributes];
506+
507+
XCTAssertNil(passedAttributes[@"email"]);
508+
XCTAssertNil(passedAttributes[@"other"]);
509+
XCTAssertEqualObjects(passedAttributes[@"emailsha256"], @"test@gmail.com");
510+
XCTAssertTrue(passedAttributes.allKeys.count == 1);
511+
}
512+
513+
- (void)testHandleHashedEmailHashedOverride {
514+
NSMutableDictionary<NSString *, NSString *> *passedAttributes = [[NSMutableDictionary alloc] init];
515+
[passedAttributes setObject:@"foo@gmail.com" forKey:@"email"];
516+
[passedAttributes setObject:@"test@gmail.com" forKey:@"other"];
517+
[passedAttributes setObject:@"test2@gmail.com" forKey:@"emailsha256"];
518+
519+
[MPKitRokt handleHashedEmail:passedAttributes];
520+
521+
XCTAssertNil(passedAttributes[@"email"]);
522+
XCTAssertNil(passedAttributes[@"other"]);
523+
XCTAssertEqualObjects(passedAttributes[@"emailsha256"], @"test2@gmail.com");
524+
XCTAssertTrue(passedAttributes.allKeys.count == 1);
525+
}
526+
527+
- (void)testTransformValuesToString {
528+
NSMutableDictionary<NSString *, id> *passedAttributes = [[NSMutableDictionary alloc] init];
529+
[passedAttributes setObject:@"foo@gmail.com" forKey:@"email"];
530+
[passedAttributes setObject:@"test@gmail.com" forKey:@"other"];
531+
[passedAttributes setObject:@"test2@gmail.com" forKey:@"emailsha256"];
532+
[passedAttributes setObject:[NSNull null] forKey:@"testCrash"];
533+
534+
535+
NSDictionary<NSString *, NSString *> *finalAtt = [MPKitRokt transformValuesToString:passedAttributes];
536+
537+
XCTAssertEqualObjects(finalAtt[@"testCrash"], @"null");
538+
XCTAssertEqualObjects(finalAtt[@"email"], @"foo@gmail.com");
539+
XCTAssertEqualObjects(finalAtt[@"other"], @"test@gmail.com");
540+
XCTAssertEqualObjects(finalAtt[@"emailsha256"], @"test2@gmail.com");
541+
XCTAssertTrue(finalAtt.allKeys.count == 4);
542+
}
543+
496544
@end

0 commit comments

Comments
 (0)