-
Notifications
You must be signed in to change notification settings - Fork 292
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
identity v3 #438
identity v3 #438
Changes from all commits
59bd4be
a157840
618e5f8
fc51be7
60b9c61
7e43f62
72d1890
60c2dd9
6ba2302
9b0a253
32b87ae
0e8cb81
6c19a42
65d9f41
8a08116
eb3e9a6
dd635cd
c9c6f69
5aad648
d770c0c
bec7b20
85de042
087d9b3
122d3aa
ee20400
139254a
4491b2f
b8ff63c
77a8ee7
bcaf112
3c57c7a
b5a31f6
2087a4d
c4455d6
f34070b
ca79deb
1b05eea
7503a82
132dc75
321384d
22b9470
1c038e6
5e2d1b1
75a0786
49c2e65
8678073
eef8b03
b6e99f5
9b91e9c
6143ad5
a008105
6a3a0ec
87972a0
01f2a04
f749508
43845ba
cd25017
6a5a162
4464903
0bbbb22
6024f3c
404edf4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
// | ||
// Created by RevenueCat. | ||
// Copyright (c) 2019 Purchases. All rights reserved. | ||
// | ||
|
||
#import <Foundation/Foundation.h> | ||
|
||
@class RCPurchaserInfo, RCPurchaserInfoManager, RCBackend, RCDeviceCache; | ||
|
||
NS_ASSUME_NONNULL_BEGIN | ||
|
||
@interface RCIdentityManager : NSObject | ||
|
||
@property (nonatomic, readonly) NSString *currentAppUserID; | ||
@property (nonatomic, readonly) BOOL currentUserIsAnonymous; | ||
|
||
- (instancetype)initWith:(RCDeviceCache *)deviceCache | ||
backend:(RCBackend *)backend | ||
purchaserInfoManager:(RCPurchaserInfoManager *)purchaserInfoManager; | ||
|
||
- (void)configureWithAppUserID:(nullable NSString *)appUserID; | ||
|
||
- (void)logInWithAppUserID:(NSString *)newAppUserID | ||
completion:(void (^)(RCPurchaserInfo * _Nullable purchaserInfo, | ||
BOOL created, | ||
NSError * _Nullable error))completion; | ||
|
||
- (void)logOutWithCompletion:(void (^)(NSError * _Nullable error))completion; | ||
|
||
#pragma MARK - deprecated methods | ||
|
||
Comment on lines
+30
to
+31
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. added the deprecated pragma, but since these are the internal methods, I didn't actually mark them deprecated otherwise we'd get a compiler warning ourselves |
||
- (void)identifyAppUserID:(NSString *)appUserID completion:(void (^)(NSError * _Nullable error))completion; | ||
|
||
- (void)createAliasForAppUserID:(NSString *)alias completion:(void (^)(NSError * _Nullable error))completion; | ||
|
||
- (void)resetAppUserID; | ||
|
||
@end | ||
|
||
NS_ASSUME_NONNULL_END |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,157 @@ | ||
// | ||
// Created by RevenueCat. | ||
// Copyright (c) 2019 Purchases. All rights reserved. | ||
// | ||
|
||
#import "RCIdentityManager.h" | ||
#import "RCLogUtils.h" | ||
#import "RCBackend.h" | ||
#import "RCDeviceCache.h" | ||
#import "RCPurchasesErrorUtils.h" | ||
#import "RCPurchaserInfoManager.h" | ||
@import PurchasesCoreSwift; | ||
|
||
|
||
@interface RCIdentityManager () | ||
|
||
@property (nonatomic) RCDeviceCache *deviceCache; | ||
@property (nonatomic) RCBackend *backend; | ||
@property (nonatomic) RCPurchaserInfoManager *purchaserInfoManager; | ||
|
||
@end | ||
|
||
@implementation RCIdentityManager | ||
|
||
- (instancetype)initWith:(RCDeviceCache *)deviceCache | ||
backend:(RCBackend *)backend | ||
purchaserInfoManager:(RCPurchaserInfoManager *)purchaserInfoManager { | ||
self = [super init]; | ||
if (self) { | ||
self.deviceCache = deviceCache; | ||
self.backend = backend; | ||
self.purchaserInfoManager = purchaserInfoManager; | ||
} | ||
|
||
return self; | ||
} | ||
|
||
- (NSString *)generateRandomID { | ||
NSString *uuid = [NSUUID.new.UUIDString stringByReplacingOccurrencesOfString:@"-" withString:@""]; | ||
return [NSString stringWithFormat:@"$RCAnonymousID:%@", uuid.lowercaseString]; | ||
} | ||
|
||
- (void)configureWithAppUserID:(nullable NSString *)appUserID { | ||
if (appUserID == nil) { | ||
appUserID = [self.deviceCache cachedAppUserID]; | ||
if (appUserID == nil) { | ||
appUserID = [self.deviceCache cachedLegacyAppUserID]; | ||
if (appUserID == nil) { | ||
appUserID = [self generateRandomID]; | ||
RCUserLog(RCStrings.identity.identifying_app_user_id, appUserID); | ||
} | ||
} | ||
} | ||
|
||
[self saveAppUserID:appUserID]; | ||
[self.deviceCache cleanupSubscriberAttributes]; | ||
} | ||
|
||
- (void)identifyAppUserID:(NSString *)appUserID completion:(void (^)(NSError *_Nullable error))completion { | ||
if (self.currentUserIsAnonymous) { | ||
RCUserLog(RCStrings.identity.identifying_anon_id, self.currentAppUserID); | ||
[self createAliasForAppUserID:appUserID completion:completion]; | ||
} else { | ||
RCUserLog(RCStrings.identity.changing_app_user_id, self.currentAppUserID, appUserID); | ||
[self.deviceCache clearCachesForAppUserID:self.currentAppUserID andSaveNewUserID:appUserID]; | ||
completion(nil); | ||
} | ||
} | ||
|
||
- (void)saveAppUserID:(NSString *)appUserID { | ||
[self.deviceCache cacheAppUserID:appUserID]; | ||
} | ||
|
||
- (void)createAliasForAppUserID:(NSString *)alias completion:(void (^)(NSError *_Nullable error))completion { | ||
NSString *currentAppUserID = self.currentAppUserID; | ||
if (!currentAppUserID) { | ||
RCWarnLog(@"%@", RCStrings.identity.creating_alias_failed_null_currentappuserid); | ||
completion(RCPurchasesErrorUtils.missingAppUserIDError); | ||
return; | ||
} | ||
RCUserLog(RCStrings.identity.creating_alias, currentAppUserID, alias); | ||
[self.backend createAliasForAppUserID:currentAppUserID withNewAppUserID:alias completion:^(NSError *_Nullable error) { | ||
if (error == nil) { | ||
RCUserLog(@"%@", RCStrings.identity.creating_alias_success); | ||
[self.deviceCache clearCachesForAppUserID:currentAppUserID andSaveNewUserID:alias]; | ||
} | ||
completion(error); | ||
}]; | ||
} | ||
|
||
- (void)resetAppUserID { | ||
NSString *randomId = [self generateRandomID]; | ||
NSString *oldAppUserID = self.currentAppUserID; | ||
[self.deviceCache clearCachesForAppUserID:oldAppUserID andSaveNewUserID:randomId]; | ||
[self.deviceCache clearLatestNetworkAndAdvertisingIdsSentForAppUserID:oldAppUserID]; | ||
} | ||
|
||
- (NSString *)currentAppUserID { | ||
return [self.deviceCache cachedAppUserID]; | ||
} | ||
|
||
- (BOOL)currentUserIsAnonymous { | ||
BOOL currentAppUserIDLooksAnonymous = [[self.deviceCache cachedAppUserID] rangeOfString:@"\\$RCAnonymousID:([a-z0-9]{32})$" options:NSRegularExpressionSearch].length > 0; | ||
BOOL isLegacyAnonymousAppUserID = [self.deviceCache.cachedAppUserID isEqualToString:self.deviceCache.cachedLegacyAppUserID]; | ||
return currentAppUserIDLooksAnonymous || isLegacyAnonymousAppUserID; | ||
} | ||
|
||
- (void)logInWithAppUserID:(NSString *)newAppUserID | ||
completion:(void (^)(RCPurchaserInfo * _Nullable purchaserInfo, | ||
BOOL created, | ||
NSError * _Nullable error))completion { | ||
NSString *currentAppUserID = self.currentAppUserID; | ||
|
||
if (!currentAppUserID || !newAppUserID || [newAppUserID isEqualToString:@""]) { | ||
NSString *errorMessage = currentAppUserID == nil ? RCStrings.identity.logging_in_with_initial_appuserid_nil | ||
: RCStrings.identity.logging_in_with_nil_appuserid; | ||
RCErrorLog(@"%@", errorMessage); | ||
completion(nil, NO, RCPurchasesErrorUtils.missingAppUserIDError); | ||
return; | ||
} | ||
|
||
if ([newAppUserID isEqualToString:currentAppUserID]) { | ||
RCWarnLog(@"%@", RCStrings.identity.logging_in_with_same_appuserid); | ||
[self.purchaserInfoManager purchaserInfoWithAppUserID:currentAppUserID | ||
completionBlock:^(RCPurchaserInfo *purchaserInfo, NSError *error) { | ||
completion(purchaserInfo, NO, error); | ||
}]; | ||
return; | ||
} | ||
|
||
[self.backend logInWithCurrentAppUserID:currentAppUserID | ||
newAppUserID:newAppUserID | ||
completion:^(RCPurchaserInfo *purchaserInfo, BOOL created, NSError * _Nullable error) { | ||
if (error == nil) { | ||
RCUserLog(@"%@", RCStrings.identity.login_success); | ||
|
||
[self.deviceCache clearCachesForAppUserID:currentAppUserID | ||
andSaveNewUserID:newAppUserID]; | ||
[self.purchaserInfoManager cachePurchaserInfo:purchaserInfo | ||
forAppUserID:newAppUserID]; | ||
Comment on lines
+137
to
+140
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
} | ||
completion(purchaserInfo, created, error); | ||
}]; | ||
} | ||
|
||
- (void)logOutWithCompletion:(void (^)(NSError * _Nullable error))completion { | ||
aboedo marked this conversation as resolved.
Show resolved
Hide resolved
|
||
RCLog(RCStrings.identity.logging_out_user, self.currentAppUserID); | ||
if (self.currentUserIsAnonymous) { | ||
completion(RCPurchasesErrorUtils.logOutAnonymousUserError); | ||
return; | ||
} | ||
[self resetAppUserID]; | ||
RCLog(@"%@", RCStrings.identity.log_out_success); | ||
completion(nil); | ||
} | ||
|
||
@end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
// | ||
// Created by Andrés Boedo on 1/4/21. | ||
// Copyright (c) 2021 Purchases. All rights reserved. | ||
// | ||
|
||
|
||
#import <Foundation/Foundation.h> | ||
|
||
NS_ASSUME_NONNULL_BEGIN | ||
@class RCPurchaserInfo, RCDeviceCache, RCBackend, RCOperationDispatcher, RCSystemInfo; | ||
typedef void (^RCReceivePurchaserInfoBlock)(RCPurchaserInfo * _Nullable, NSError * _Nullable) NS_SWIFT_NAME(Purchases.ReceivePurchaserInfoBlock); | ||
|
||
NS_SWIFT_NAME(PurchaserInfoManagerDelegate) | ||
@protocol RCPurchaserInfoManagerDelegate <NSObject> | ||
- (void)purchaserInfoManagerDidReceiveUpdatedPurchaserInfo:(RCPurchaserInfo *)purchaserInfo; | ||
@end | ||
|
||
NS_SWIFT_NAME(PurchaserInfoManager) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this class is mostly stuff extracted from |
||
@interface RCPurchaserInfoManager : NSObject | ||
|
||
@property (nonatomic, weak, nullable) id<RCPurchaserInfoManagerDelegate> delegate; | ||
|
||
- (instancetype)initWithOperationDispatcher:(RCOperationDispatcher *)operationDispatcher | ||
deviceCache:(RCDeviceCache *)deviceCache | ||
backend:(RCBackend *)backend | ||
systemInfo:(RCSystemInfo *)systemInfo; | ||
|
||
- (void)fetchAndCachePurchaserInfoWithAppUserID:(NSString *)appUserID | ||
isAppBackgrounded:(BOOL)isAppBackgrounded | ||
completion:(nullable RCReceivePurchaserInfoBlock)completion; | ||
|
||
- (void)fetchAndCachePurchaserInfoIfStaleWithAppUserID:(NSString *)appUserID | ||
isAppBackgrounded:(BOOL)isAppBackgrounded | ||
completion:(nullable RCReceivePurchaserInfoBlock)completion; | ||
- (void)sendCachedPurchaserInfoIfAvailableForAppUserID:(NSString *)appUserID; | ||
|
||
- (void)purchaserInfoWithAppUserID:(NSString *)appUserID | ||
completionBlock:(nullable RCReceivePurchaserInfoBlock)completion; | ||
|
||
- (nullable RCPurchaserInfo *)cachedPurchaserInfoForAppUserID:(NSString *)appUserID; | ||
- (void)cachePurchaserInfo:(RCPurchaserInfo *)info forAppUserID:(NSString *)appUserID; | ||
- (void)clearPurchaserInfoCacheForAppUserID:(NSString *)appUserID; | ||
|
||
@end | ||
|
||
|
||
NS_ASSUME_NONNULL_END |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is mostly the same class as it used to be.
I moved it to
/Identity/
so it shows up as a new class.Changes summary: