Skip to content
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

Merged
merged 62 commits into from Mar 17, 2021
Merged

identity v3 #438

merged 62 commits into from Mar 17, 2021

Conversation

aboedo
Copy link
Member

@aboedo aboedo commented Jan 7, 2021

Introduces a new take on identity.

Public changes overview

New methods

  • Introduces logIn, a new way of identifying users, which also returns whether a new user has been registered in the system.
    logIn uses a new backend endpoint.
  • Introduces logOut, a replacement for reset.

Deprecations / removals

  • removes createAlias
  • deprecates identify in favor of logIn
  • deprecates reset in favor of logOut
  • deprecates allowSharingAppStoreAccount in favor of dashboard-side configuration

Review notes

  • A new class was created, RCPurchaserInfoManager, which takes on the responsibility of sending information to the delegate, knowing what has last been sent, serializing purchaserInfo for caching, and everything else purchaser-info related.
  • the public changes aren't a part of this PR, they'll be a part of the follow-up. This is intended so that we can actually merge this into develop before the backend is ready.

@aboedo aboedo added this to the 4.0.0 milestone Jan 7, 2021
@aboedo aboedo self-assigned this Jan 7, 2021
@aboedo aboedo force-pushed the feature/identityV3 branch 5 times, most recently from 68d9a08 to 7f76486 Compare January 11, 2021 19:52
@aboedo aboedo force-pushed the feature/identityV3 branch 2 times, most recently from a96f970 to 3f1c121 Compare January 20, 2021 18:41

[self clearLatestNetworkAndAdvertisingIdsSentForAppUserID:oldAppUserID];
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤔 I did this because I figured if we're clearing caches, we should probably delete everything about the old user, but... this might be a problem because we call this method even if the user gets aliased, so if the user doesn't change, we might still be deleting this

#import <Foundation/Foundation.h>
#import "RCDeviceCache.h"

@class RCPurchaserInfo, RCPurchaserInfoManager, RCBackend;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this class is mostly just the same as before, it was moved into the Identity group

Comment on lines 31 to 36
- (void)logInAppUserID:(NSString *)newAppUserID
completionBlock:(void (^)(RCPurchaserInfo * _Nullable purchaserInfo,
BOOL created,
NSError *error))completion;

- (void)logOutWithCompletionBlock:(void (^)(NSError * _Nullable error))completion;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

new methods: logIn, logOut

Comment on lines +38 to +31
#pragma MARK - deprecated methods

Copy link
Member Author

Choose a reason for hiding this comment

The 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

@@ -51,10 +55,10 @@ - (void)configureWithAppUserID:(nullable NSString *)appUserID {
[self.deviceCache cleanupSubscriberAttributes];
}

- (void)identifyAppUserID:(NSString *)appUserID withCompletionBlock:(void (^)(NSError *_Nullable error))completion {
- (void)identifyAppUserID:(NSString *)appUserID completionBlock:(void (^)(NSError *_Nullable error))completion {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mild rename because you're only supposed to reference the first param in objc, after that you can just use the name

@@ -52,6 +52,7 @@ typedef NS_ERROR_ENUM(RCPurchasesErrorDomain, RCPurchasesErrorCode) {
RCInsufficientPermissionsError,
RCPaymentPendingError,
RCInvalidSubscriberAttributesError,
RCLogOutAnonymousUserError,
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will update this to add a number after the #452 stuff gets merged

@@ -1,37 +0,0 @@
//
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

again, this wasn't removed, it was moved to the Identity group / folder

@@ -0,0 +1,420 @@
//
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tests start here

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the ones in this class aren't fully new, the file was moved into the Identity group. I'll point out the new ones.

assertCorrectlyIdentified(expectedAppUserID: "cesar")
}

func testLogInFailsIfEmptyAppUserID() {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

new tests start here

- (void)cachePurchaserInfo:(RCPurchaserInfo *)info forAppUserID:(NSString *)appUserID {
if (info) {
NSDictionary *infoAsJSONDict = info.JSONObject;
if ([NSJSONSerialization isValidJSONObject:infoAsJSONDict]) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this check is new. previously, if there was an error parsing the JSON (for example if the json has a value like infinity), the app would crash.
the jsonError bit only helps for errors like incomplete stream and stuff like that, but it for some reason doesn't actually cover what would happen with an invalid json.

@aboedo aboedo marked this pull request as ready for review January 20, 2021 20:21
@aboedo aboedo requested a review from vegaro January 20, 2021 20:22
Copy link
Contributor

@vegaro vegaro left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Haven't finished yet but I have some comments

Purchases/Identity/RCIdentityManager.m Show resolved Hide resolved
NSString *currentAppUserID = self.currentAppUserID;
if (!currentAppUserID) {
RCWarnLog(@"%@", RCStrings.identity.logging_in_with_initial_appuserid_nil);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not that I don't like this, but this should technically not happen right? Just checking

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, this should never happen. In other cases like this, we would just crash. But this is the one instance where if it did happen, this method would actually make the SDK recover, so I figured I might as well continue execution if it does happen.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

come to think about this again, we had issues in the past with aliasing to nil #255, so I'll give this some more thought

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated so that it errors out now, like with identity v2

Purchases/Identity/RCIdentityManager.m Outdated Show resolved Hide resolved
Purchases/Identity/RCIdentityManager.m Outdated Show resolved Hide resolved

NSString *currentAppUserID = self.currentAppUserID;
if (!currentAppUserID) {
RCWarnLog(@"%@", RCStrings.identity.logging_in_with_initial_appuserid_nil);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this string should be creating_alias_failed_null_currentappuserid

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is just the identityV3 version of the same string

Purchases/Networking/RCBackend.h Show resolved Hide resolved
Purchases/Public/RCPurchases.m Outdated Show resolved Hide resolved
@aboedo
Copy link
Member Author

aboedo commented Feb 19, 2021

@vegaro bump

}

[self.systemInfo isApplicationBackgroundedWithCompletion:^(BOOL isAppBackgrounded) {
BOOL shouldCallCompletionAfterFetching = infoFromCache == nil && completion != nil;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had some trouble understanding this part. I didn't understand why you were not just passing completion to fetchAndCachePurchaserInfoIfStaleWithAppUserID even if it's nil. I now get that it's to avoid the completion being called again if it was called already in line 167, but it took me a bit.

I was thinking maybe the check for [self.systemInfo isApplicationBackgroundedWithCompletion could be done in fetchAndCachePurchaserInfoIfStaleWithAppUserID. Then calling fetchAndCachePurchaserInfoIfStaleWithAppUserID in line 169 passing a nil completion.

This is just a suggestion including my personal preference, it is not necessarily the way I think this method should be written. If you think your current implementation is clear, leave it as is :)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, this looks pretty confusing

I did some cleanup here: I added an explicit boolean to store whether we've already called completion, and added a comment. lmk if it feels better! Doing the isAppBackgrounded check in fetchAndCachePurchaserInfoIfStaleWithAppUserID is a slightly larger refactor, but I'm happy to do it if the new logic is still confusing

PurchasesTests/Identity/IdentityManagerTests.swift Outdated Show resolved Hide resolved
}

// prevent calling completion twice
RCReceivePurchaserInfoBlock _Nullable fetchPurchaserInfoCompletion = completionCalled ? nil : completion;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for changing this!

@aboedo
Copy link
Member Author

aboedo commented Mar 17, 2021

merging this since it's approved, but I'm going to follow up to update the location of the appUserID param for login calls

@aboedo aboedo merged commit 194ec49 into develop Mar 17, 2021
@aboedo aboedo deleted the feature/identityV3 branch March 17, 2021 18:56
@aboedo aboedo mentioned this pull request May 27, 2021
@aboedo aboedo mentioned this pull request Jun 9, 2021
@aboedo aboedo mentioned this pull request Jul 13, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants