Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 62 additions & 2 deletions mParticle-Rokt/MPKitRokt.m
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ - (RoktFrameworkType)mapMPWrapperSdkToRoktFrameworkType:(MPWrapperSdk)wrapperSdk
if (filteredUser == nil && roktKit != nil) {
filteredUser = [[[MPKitAPI alloc] init] getCurrentUserWithKit:roktKit];
}
NSDictionary<NSString *, NSString *> *mpAttributes = [filteredUser.userAttributes transformValuesToString];
NSDictionary<NSString *, NSString *> *mpAttributes = [self transformValuesToString:filteredUser.userAttributes];
if (performMapping) {
mpAttributes = [self mapAttributes:attributes filteredUser:filteredUser];
}
Expand All @@ -197,6 +197,9 @@ - (RoktFrameworkType)mapMPWrapperSdkToRoktFrameworkType:(MPWrapperSdk)wrapperSdk
// Add all known user identities to the attributes being passed to the Rokt SDK
[self addIdentityAttributes:finalAtt filteredUser:filteredUser];

// Handle hashed email use case
[self handleHashedEmail:finalAtt];
Comment thread
BrandonStalnaker marked this conversation as resolved.

// The core SDK does not set sandbox on the user, but we must pass it to Rokt if provided
NSString *sandboxKey = @"sandbox";
if (attributes[sandboxKey] != nil) {
Expand All @@ -206,6 +209,42 @@ - (RoktFrameworkType)mapMPWrapperSdkToRoktFrameworkType:(MPWrapperSdk)wrapperSdk
return [self confirmSandboxAttribute:finalAtt];
}

+ (NSDictionary<NSString *, NSString *> *)transformValuesToString:(NSDictionary<NSString *, id> * _Nullable)originalDictionary {
__block NSMutableDictionary<NSString *, NSString *> *transformedDictionary = [[NSMutableDictionary alloc] initWithCapacity:originalDictionary.count];
Class NSStringClass = [NSString class];
Class NSNumberClass = [NSNumber class];

[originalDictionary enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
if ([obj isKindOfClass:NSStringClass]) {
transformedDictionary[key] = obj;
} else if ([obj isKindOfClass:NSNumberClass]) {
NSNumber *numberAttribute = (NSNumber *)obj;

if (numberAttribute == (void *)kCFBooleanFalse || numberAttribute == (void *)kCFBooleanTrue) {
transformedDictionary[key] = [numberAttribute boolValue] ? @"true" : @"false";
} else {
transformedDictionary[key] = [numberAttribute stringValue];
}
} else if ([obj isKindOfClass:[NSDate class]]) {
transformedDictionary[key] = [MPDateFormatter stringFromDateRFC3339:obj];
} else if ([obj isKindOfClass:[NSData class]] && [(NSData *)obj length] > 0) {
transformedDictionary[key] = [[NSString alloc] initWithData:obj encoding:NSUTF8StringEncoding];
} else if ([obj isKindOfClass:[NSDictionary class]]) {
transformedDictionary[key] = [obj description];
} else if ([obj isKindOfClass:[NSMutableDictionary class]]) {
transformedDictionary[key] = [obj description];
} else if ([obj isKindOfClass:[NSArray class]]) {
transformedDictionary[key] = [obj description];
} else if ([obj isKindOfClass:[NSMutableArray class]]) {
transformedDictionary[key] = [obj description];
} else if ([obj isKindOfClass:[NSNull class]]) {
transformedDictionary[key] = @"null";
}
}];

return transformedDictionary;
}

+ (NSDictionary<NSString *, NSString *> *)mapAttributes:(NSDictionary<NSString *, NSString *> * _Nullable)attributes filteredUser:(FilteredMParticleUser * _Nonnull)filteredUser {
NSArray<NSDictionary<NSString *, NSString *> *> *attributeMap = nil;

Expand Down Expand Up @@ -273,7 +312,7 @@ - (RoktFrameworkType)mapMPWrapperSdkToRoktFrameworkType:(MPWrapperSdk)wrapperSdk
}
}

return [mappedAttributes transformValuesToString];
return [self transformValuesToString:mappedAttributes];
} else {
return attributes;
}
Expand All @@ -293,6 +332,27 @@ + (void)addIdentityAttributes:(NSMutableDictionary<NSString *, NSString *> * _Nu
}
}

+ (void)handleHashedEmail:(NSMutableDictionary<NSString *, NSString *> * _Nullable)attributes {
NSString *emailKey = [MPKitRokt stringForIdentityType:MPIdentityEmail];
NSString *otherKey = [MPKitRokt stringForIdentityType:MPIdentityOther];
NSString *hashedEmailValue = attributes[@"emailsha256"];

// Remove email and other is hashed vlaue already set
if (hashedEmailValue != nil) {
[attributes removeObjectForKey:emailKey];
[attributes removeObjectForKey:otherKey];
}

NSString *otherValue = attributes[otherKey];

// Remove email and replace key on other if it's set
if (otherValue != nil) {
[attributes removeObjectForKey:emailKey];
attributes[@"emailsha256"] = otherValue;
[attributes removeObjectForKey:otherKey];
}
}

+ (RoktConfig *)convertMPRoktConfig:(MPRoktConfig *)mpRoktConfig {
if (mpRoktConfig != nil) {
Builder *builder = [[Builder alloc] init];
Expand Down
48 changes: 48 additions & 0 deletions mParticle_RoktTests/mParticle_RoktTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,12 @@ - (MPKitExecStatus *)purchaseFinalized:(NSString *)placementId

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

+ (void)handleHashedEmail:(NSMutableDictionary<NSString *, NSString *> * _Nullable)attributes;

+ (RoktConfig *)convertMPRoktConfig:(MPRoktConfig *)mpRoktConfig;

+ (NSDictionary<NSString *, NSString *> *)transformValuesToString:(NSDictionary<NSString *, id> * _Nullable)originalDictionary;

@end

@interface mParticle_RoktTests : XCTestCase
Expand Down Expand Up @@ -493,4 +497,48 @@ - (void)testEvents_NilIdentifier {
[mockRoktSDK stopMocking];
}

- (void)testHandleHashedEmailOtherOverride {
NSMutableDictionary<NSString *, NSString *> *passedAttributes = [[NSMutableDictionary alloc] init];
[passedAttributes setObject:@"foo@gmail.com" forKey:@"email"];
[passedAttributes setObject:@"test@gmail.com" forKey:@"other"];

[MPKitRokt handleHashedEmail:passedAttributes];

XCTAssertNil(passedAttributes[@"email"]);
XCTAssertNil(passedAttributes[@"other"]);
XCTAssertEqualObjects(passedAttributes[@"emailsha256"], @"test@gmail.com");
XCTAssertTrue(passedAttributes.allKeys.count == 1);
}

- (void)testHandleHashedEmailHashedOverride {
NSMutableDictionary<NSString *, NSString *> *passedAttributes = [[NSMutableDictionary alloc] init];
[passedAttributes setObject:@"foo@gmail.com" forKey:@"email"];
[passedAttributes setObject:@"test@gmail.com" forKey:@"other"];
[passedAttributes setObject:@"test2@gmail.com" forKey:@"emailsha256"];

[MPKitRokt handleHashedEmail:passedAttributes];

XCTAssertNil(passedAttributes[@"email"]);
XCTAssertNil(passedAttributes[@"other"]);
XCTAssertEqualObjects(passedAttributes[@"emailsha256"], @"test2@gmail.com");
XCTAssertTrue(passedAttributes.allKeys.count == 1);
}

- (void)testTransformValuesToString {
NSMutableDictionary<NSString *, id> *passedAttributes = [[NSMutableDictionary alloc] init];
[passedAttributes setObject:@"foo@gmail.com" forKey:@"email"];
[passedAttributes setObject:@"test@gmail.com" forKey:@"other"];
[passedAttributes setObject:@"test2@gmail.com" forKey:@"emailsha256"];
[passedAttributes setObject:[NSNull null] forKey:@"testCrash"];


NSDictionary<NSString *, NSString *> *finalAtt = [MPKitRokt transformValuesToString:passedAttributes];

XCTAssertEqualObjects(finalAtt[@"testCrash"], @"null");
XCTAssertEqualObjects(finalAtt[@"email"], @"foo@gmail.com");
XCTAssertEqualObjects(finalAtt[@"other"], @"test@gmail.com");
XCTAssertEqualObjects(finalAtt[@"emailsha256"], @"test2@gmail.com");
XCTAssertTrue(finalAtt.allKeys.count == 4);
}

@end
Loading