diff --git a/.circleci/config.yml b/.circleci/config.yml index 7e634ae5d..effab375f 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -72,9 +72,7 @@ workflows: jobs: - ios - macos - - carthage: - requires: - - ios + - carthage nightly: jobs: - carthage diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4be36104f..085f863b4 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -35,6 +35,24 @@ Check the Rakefile and the circleci config for more information. #### 5. Make sure your code follows the [style guide](#style-guide) +### Preparing for a new release + +#### Update the version number + +You can use the rake task in order to bump the version number, it's safe, and will properly update all version numbers + +``` +$ bundle exec rake package:set_version[X.X.X] +``` + +Note that zsh users (such as those using macOS >= 10.15) need to escape the brackets as follows: + +``` +$ bundle exec rake package:set_version\[X.X.X\] +``` + +Replace X.X.X by the version number and push to the repository. + ## Bugs Although we try to keep developing with the Parse Platform easy, you still may run into some issues. General questions should be asked on our [community forum](community-forum), technical questions should be asked on [Stack Overflow][stack-overflow], and for everything else we use GitHub issues. diff --git a/ParseUI/Classes/LogInViewController/PFLogInViewController.h b/ParseUI/Classes/LogInViewController/PFLogInViewController.h index f88cfed8d..be6cfe126 100644 --- a/ParseUI/Classes/LogInViewController/PFLogInViewController.h +++ b/ParseUI/Classes/LogInViewController/PFLogInViewController.h @@ -179,6 +179,15 @@ shouldBeginLogInWithUsername:(NSString *)username */ - (void)logInViewControllerDidCancelLogIn:(PFLogInViewController *)logInController; +/** + Sent to the delegate when user data is received following successful login using Sign In With Apple. + + @param logInController The login view controller that received the credentials + @param credential The ASAuthorizationAppleIDCredential object received + */ + +-(void)logInViewController:(PFLogInViewController *)logInController didReceiveAppleCredential:(ASAuthorizationAppleIDCredential *)credential forUser:(PFUser *)user API_AVAILABLE(ios(13.0)); + @end NS_ASSUME_NONNULL_END diff --git a/ParseUI/Classes/LogInViewController/PFLogInViewController.m b/ParseUI/Classes/LogInViewController/PFLogInViewController.m index ccd126537..da388b9b3 100644 --- a/ParseUI/Classes/LogInViewController/PFLogInViewController.m +++ b/ParseUI/Classes/LogInViewController/PFLogInViewController.m @@ -30,6 +30,7 @@ #import "PFSignUpViewController.h" #import "PFTextField.h" #import "PFLogInView_Private.h" +#import "PFAppleUtils.h" NSString *const PFLogInSuccessNotification = @"com.parse.ui.login.success"; NSString *const PFLogInFailureNotification = @"com.parse.ui.login.failure"; @@ -332,7 +333,7 @@ - (void)_requestPasswordResetWithEmail:(NSString *)email { #pragma mark Sign in with Apple -(void)_loginWithApple API_AVAILABLE(ios(13.0)){ - + if (self.loading) { return; } @@ -344,28 +345,26 @@ -(void)_loginWithApple API_AVAILABLE(ios(13.0)){ __weak typeof(self) wself = self; - Class appleUtils = NSClassFromString(@"PFAppleUtils"); - SEL selector = NSSelectorFromString(@"logInInBackground"); - if ([appleUtils respondsToSelector:selector]) { - [[appleUtils logInInBackground] continueWithBlock:^id _Nullable(BFTask * _Nonnull t) { - __strong typeof(wself) sself = wself; - dispatch_async(dispatch_get_main_queue(), ^{ - sself.loading = NO; - if ([sself.logInView.appleButton isKindOfClass:[PFActionButton class]]) { - [(PFActionButton *)sself.logInView.appleButton setLoading:NO]; - } - if (t.error) { - [sself _loginDidFailWithError:t.error]; - } - else - { - PFUser *user = t.result[@"user"]; - [sself _loginDidSucceedWithUser:user]; - } - }); - return nil; - }]; - } + [[PFAppleUtils logInInBackground] continueWithBlock:^id _Nullable(BFTask * _Nonnull t) { + __strong typeof(wself) sself = wself; + dispatch_async(dispatch_get_main_queue(), ^{ + sself.loading = NO; + if ([sself.logInView.appleButton isKindOfClass:[PFActionButton class]]) { + [(PFActionButton *)sself.logInView.appleButton setLoading:NO]; + } + if (t.error) { + [sself _loginDidFailWithError:t.error]; + } + else + { + PFUser *user = t.result[PFAppleAuthUserKey]; + ASAuthorizationAppleIDCredential *cred = t.result[PFAppleAuthCredentialKey]; + [sself _loginDidSucceedWithUser:user]; + [sself.delegate logInViewController:sself didReceiveAppleCredential:cred forUser:user]; + } + }); + return nil; + }]; } #pragma mark Log In With Facebook diff --git a/ParseUI/ParseUI.xcodeproj/project.pbxproj b/ParseUI/ParseUI.xcodeproj/project.pbxproj index 8fdc75630..d14d34fde 100644 --- a/ParseUI/ParseUI.xcodeproj/project.pbxproj +++ b/ParseUI/ParseUI.xcodeproj/project.pbxproj @@ -184,14 +184,20 @@ B9DDA283243C322D0003061D /* ParseTwitterUtils.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4A51E4272027CC2D0066DE1A /* ParseTwitterUtils.framework */; }; B9DDA284243C32E50003061D /* ParseFacebookUtilsV4.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4A51E4362027CC330066DE1A /* ParseFacebookUtilsV4.framework */; }; BC0632E023ABCC8F0089096D /* AuthenticationServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BC0632DC23ABCB1D0089096D /* AuthenticationServices.framework */; }; - BC0632E423AD005E0089096D /* PFAppleUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = BC0632E323AD005E0089096D /* PFAppleUtils.m */; }; - BC0632E823AD03B30089096D /* PFAppleAuthenticationProvider.m in Sources */ = {isa = PBXBuildFile; fileRef = BC0632E723AD03B30089096D /* PFAppleAuthenticationProvider.m */; }; BC0632EA23AD3F050089096D /* Bolts.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4A13523820282059000F5FD5 /* Bolts.framework */; }; BC488EA0246B196800947E3C /* ParseUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BC488E9F246B196800947E3C /* ParseUI.framework */; }; BC488EA1246B196800947E3C /* ParseUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BC488E9F246B196800947E3C /* ParseUI.framework */; }; BC488EA2246B196800947E3C /* ParseUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BC488E9F246B196800947E3C /* ParseUI.framework */; }; BC8C2923246B1873000AEE3F /* ParseUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4A9A9497200D0329005D8F4B /* ParseUI.framework */; }; BCA5CC8523BFCFB8003BC0A0 /* SignInWithAppleTests.m in Sources */ = {isa = PBXBuildFile; fileRef = BCCBE8CB23BFB89D0044A79C /* SignInWithAppleTests.m */; }; + BCB2A82E251D337E0030D987 /* PFAppleUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = BC0632E223AD005E0089096D /* PFAppleUtils.h */; }; + BCB2A82F251D337E0030D987 /* PFAppleUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = BC0632E323AD005E0089096D /* PFAppleUtils.m */; }; + BCB2A830251D337E0030D987 /* PFAppleAuthenticationProvider.h in Headers */ = {isa = PBXBuildFile; fileRef = BC0632E623AD03B20089096D /* PFAppleAuthenticationProvider.h */; }; + BCB2A831251D337E0030D987 /* PFAppleAuthenticationProvider.m in Sources */ = {isa = PBXBuildFile; fileRef = BC0632E723AD03B30089096D /* PFAppleAuthenticationProvider.m */; }; + BCB2A840251D337F0030D987 /* PFAppleUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = BC0632E223AD005E0089096D /* PFAppleUtils.h */; }; + BCB2A841251D337F0030D987 /* PFAppleUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = BC0632E323AD005E0089096D /* PFAppleUtils.m */; }; + BCB2A842251D337F0030D987 /* PFAppleAuthenticationProvider.h in Headers */ = {isa = PBXBuildFile; fileRef = BC0632E623AD03B20089096D /* PFAppleAuthenticationProvider.h */; }; + BCB2A843251D337F0030D987 /* PFAppleAuthenticationProvider.m in Sources */ = {isa = PBXBuildFile; fileRef = BC0632E723AD03B30089096D /* PFAppleAuthenticationProvider.m */; }; BCCBE8CE23BFB89D0044A79C /* ParseUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4A9A9497200D0329005D8F4B /* ParseUI.framework */; }; BCCBE8E023BFC8BF0044A79C /* OCMock.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BCCBE8DF23BFC8BF0044A79C /* OCMock.framework */; }; F57F3D231B0C03D40087F60B /* DeletionCollectionViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = F57F3D201B0C03C90087F60B /* DeletionCollectionViewController.m */; }; @@ -1332,6 +1338,7 @@ buildActionMask = 2147483647; files = ( 4A0ECC03200D8C0200BA84A3 /* PFLoadingView.h in Headers */, + BCB2A840251D337F0030D987 /* PFAppleUtils.h in Headers */, 4A0ECC04200D8C0200BA84A3 /* PFQueryCollectionViewController.h in Headers */, 4A0ECC05200D8C0200BA84A3 /* PFUIAlertView.h in Headers */, 4A0ECC06200D8C0200BA84A3 /* PFSignUpViewController.h in Headers */, @@ -1344,6 +1351,7 @@ 4A0ECC0D200D8C0200BA84A3 /* PFCollectionViewCell.h in Headers */, 4A0ECC0E200D8C0200BA84A3 /* PFDismissButton.h in Headers */, 4A0ECC0F200D8C0200BA84A3 /* PFActivityIndicatorCollectionReusableView.h in Headers */, + BCB2A842251D337F0030D987 /* PFAppleAuthenticationProvider.h in Headers */, 4A0ECC10200D8C0200BA84A3 /* PFQueryTableViewController.h in Headers */, 4A0ECC11200D8C0200BA84A3 /* PFLogInViewController.h in Headers */, 4A0ECC12200D8C0200BA84A3 /* PFPurchaseTableViewCell.h in Headers */, @@ -1368,6 +1376,7 @@ buildActionMask = 2147483647; files = ( 4A9A94C6200D03BA005D8F4B /* PFLoadingView.h in Headers */, + BCB2A82E251D337E0030D987 /* PFAppleUtils.h in Headers */, 4A9A94C9200D03BE005D8F4B /* PFQueryCollectionViewController.h in Headers */, 4A9A94B6200D03B6005D8F4B /* PFUIAlertView.h in Headers */, 4A9A94AD200D03B6005D8F4B /* PFSignUpViewController.h in Headers */, @@ -1380,6 +1389,7 @@ 4A9A94A8200D03B6005D8F4B /* PFCollectionViewCell.h in Headers */, 4A9A94BE200D03BA005D8F4B /* PFDismissButton.h in Headers */, 4A9A94AF200D03B6005D8F4B /* PFActivityIndicatorCollectionReusableView.h in Headers */, + BCB2A830251D337E0030D987 /* PFAppleAuthenticationProvider.h in Headers */, 4A9A94CA200D03C8005D8F4B /* PFQueryTableViewController.h in Headers */, 4A9A94D3200D03C8005D8F4B /* PFLogInViewController.h in Headers */, 4A9A94A4200D03B6005D8F4B /* PFPurchaseTableViewCell.h in Headers */, @@ -1826,7 +1836,9 @@ 4A0ECBFC200D8C0200BA84A3 /* PFTableViewCell.m in Sources */, 4A0ECBFD200D8C0200BA84A3 /* PFLogInViewController.m in Sources */, 4A0ECBFE200D8C0200BA84A3 /* PFSignUpView.m in Sources */, + BCB2A843251D337F0030D987 /* PFAppleAuthenticationProvider.m in Sources */, 4A0ECBFF200D8C0200BA84A3 /* PFTextField.m in Sources */, + BCB2A841251D337F0030D987 /* PFAppleUtils.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1859,7 +1871,9 @@ 4A9A94A9200D03B6005D8F4B /* PFTableViewCell.m in Sources */, 4A9A94D0200D03C8005D8F4B /* PFLogInViewController.m in Sources */, 4A9A94AC200D03B6005D8F4B /* PFSignUpView.m in Sources */, + BCB2A831251D337E0030D987 /* PFAppleAuthenticationProvider.m in Sources */, 4A9A94CE200D03C8005D8F4B /* PFTextField.m in Sources */, + BCB2A82F251D337E0030D987 /* PFAppleUtils.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1894,13 +1908,11 @@ 81C5993F1A64346000F574E8 /* SimpleCollectionViewController.m in Sources */, 81472FBB1A1AB37500FD6EED /* main.m in Sources */, 81C599421A6454C900F574E8 /* PaginatedCollectionViewController.m in Sources */, - BC0632E423AD005E0089096D /* PFAppleUtils.m in Sources */, 81472FB31A1AB37500FD6EED /* CustomSignUpViewController.m in Sources */, 81472FB41A1AB37500FD6EED /* CustomLogInViewController.m in Sources */, 81472FB91A1AB37500FD6EED /* CustomProductTableViewController.m in Sources */, 819A4B3A1A6808EA00D01241 /* SubtitleImageCollectionViewController.m in Sources */, F57F3D241B0C03DB0087F60B /* DeletionTableViewController.m in Sources */, - BC0632E823AD03B30089096D /* PFAppleAuthenticationProvider.m in Sources */, 812E5C041A7A8EFB000FBDE1 /* StoryboardCollectionViewController.m in Sources */, 81472FB51A1AB37500FD6EED /* SimpleTableViewController.m in Sources */, F57F3D231B0C03D40087F60B /* DeletionCollectionViewController.m in Sources */, diff --git a/ParseUI/Sign In With Apple/PFAppleUtils.h b/ParseUI/Sign In With Apple/PFAppleUtils.h index b32a27d65..46020f290 100644 --- a/ParseUI/Sign In With Apple/PFAppleUtils.h +++ b/ParseUI/Sign In With Apple/PFAppleUtils.h @@ -15,6 +15,8 @@ NS_ASSUME_NONNULL_BEGIN extern NSString *const PFAppleUserAuthenticationType; +extern NSString *const PFAppleAuthUserKey; +extern NSString *const PFAppleAuthCredentialKey; API_AVAILABLE(ios(13.0)) @interface PFAppleLoginManager : NSObject diff --git a/ParseUI/Sign In With Apple/PFAppleUtils.m b/ParseUI/Sign In With Apple/PFAppleUtils.m index 984333620..d26bf418d 100644 --- a/ParseUI/Sign In With Apple/PFAppleUtils.m +++ b/ParseUI/Sign In With Apple/PFAppleUtils.m @@ -8,10 +8,12 @@ #import "PFAppleUtils.h" #import "PFAppleAuthenticationProvider.h" -@import AuthenticationServices; +#import #import NSString *const PFAppleUserAuthenticationType = @"apple"; +NSString *const PFAppleAuthUserKey = @"user"; +NSString *const PFAppleAuthCredentialKey = @"credential"; API_AVAILABLE(ios(13.0)) @interface PFAppleLoginManager () @@ -46,17 +48,16 @@ - (nonnull ASPresentationAnchor)presentationAnchorForAuthorizationController:(no - (void)authorizationController:(ASAuthorizationController *)controller didCompleteWithAuthorization:(ASAuthorization *)authorization { ASAuthorizationAppleIDCredential *cred = authorization.credential; NSString *userId = cred.user; - NSPersonNameComponents *fullName = cred.fullName; NSData *token = cred.identityToken; NSString *tokenString = [[NSString alloc] initWithData:token encoding:NSUTF8StringEncoding]; __weak typeof(self) wself = self; - [[[PFUser logInWithAuthTypeInBackground:@"apple" + [[[PFUser logInWithAuthTypeInBackground:PFAppleUserAuthenticationType authData:@{@"token" : tokenString, @"id" : userId}] continueWithSuccessBlock:^id _Nullable(BFTask<__kindof PFUser *> * _Nonnull t) { __strong typeof(wself) sself = wself; - [sself.completionSource setResult:@{@"user" : t.result, - @"name" : fullName}]; + [sself.completionSource setResult:@{PFAppleAuthUserKey : t.result, + PFAppleAuthCredentialKey : cred}]; sself.strongSelf = nil; return t; }] continueWithBlock:^id _Nullable(BFTask * _Nonnull t) { diff --git a/ParseUI/SignInWithAppleTests/SignInWithAppleTests.m b/ParseUI/SignInWithAppleTests/SignInWithAppleTests.m index 7b63650d8..dca75dff0 100644 --- a/ParseUI/SignInWithAppleTests/SignInWithAppleTests.m +++ b/ParseUI/SignInWithAppleTests/SignInWithAppleTests.m @@ -8,6 +8,9 @@ #import #import "PFAppleUtils.h" +#import "Parse/PFUser.h" +#import "PFLoginViewController.h" + @import OCMock; @interface SignInWithAppleTests : XCTestCase @@ -59,7 +62,7 @@ - (void)tearDown { // Put teardown code here. This method is called after the invocation of each test method in the class. } -- (void)testLoginSuccess { +- (void)testAppleUtilsLoginSuccess { // Create test ASAuthorization and ASAuthorizationAppleIDCredential FakeAuth *fakeAuth = [FakeAuth new]; @@ -78,29 +81,33 @@ - (void)testLoginSuccess { id mockUser = OCMClassMock([PFUser class]); NSDictionary *authData = @{@"token" : aString, @"id" : aString }; - NSDictionary *result = @{ @"user" : aString, - @"name" : name }; - OCMStub(ClassMethod([mockUser logInWithAuthTypeInBackground:@"apple" authData:authData])).andReturn([BFTask taskWithResult:result]); + PFUser *loggedInUser = [PFUser new]; + OCMStub(ClassMethod([mockUser logInWithAuthTypeInBackground:@"apple" authData:authData])).andReturn([BFTask taskWithResult:loggedInUser]); // Create the login task PFAppleLoginManager *manager = [PFAppleLoginManager new]; BFTask *logInTask = [PFAppleUtils logInInBackgroundWithManager:manager]; - XCTestExpectation *expect = [self expectationWithDescription:@"Task should complete."]; + XCTestExpectation *expectLoginSuccess = [self expectationWithDescription:@"Login should complete."]; [logInTask continueWithSuccessBlock:^id _Nullable(BFTask * _Nonnull t) { - [expect fulfill]; + XCTAssert(t.result[@"user"] == loggedInUser); + ASAuthorizationAppleIDCredential *credential = t.result[@"credential"]; + XCTAssert([credential.fullName isEqual:cred.fullName]); + XCTAssert([credential.identityToken isEqual:cred.identityToken]); + XCTAssert([credential.user isEqual:cred.user]); + [expectLoginSuccess fulfill]; return nil; }]; // Call the success callback as Apple would [manager authorizationController:manager.controller didCompleteWithAuthorization:(ASAuthorization *)fakeAuth]; - [self waitForExpectations:@[expect] timeout:2]; + [self waitForExpectations:@[expectLoginSuccess] timeout:2]; [mockUser stopMocking]; } -- (void)testPFUserLoginFails { +- (void)testAppleUtilsLoginFailure { // Create test ASAuthorization and ASAuthorizationAppleIDCredential FakeAuth *fakeAuth = [FakeAuth new]; FakeCredential *cred = [FakeCredential new]; @@ -140,25 +147,4 @@ - (void)testPFUserLoginFails { [mockUser stopMocking]; } -- (void)testAppleAuthCompletesWithError { - - // Create the login task - PFAppleLoginManager *manager = [PFAppleLoginManager new]; - BFTask *logInTask = [PFAppleUtils logInInBackgroundWithManager:manager]; - - XCTestExpectation *expect = [self expectationWithDescription:@"Task should fail."]; - [logInTask continueWithBlock:^id _Nullable(BFTask * _Nonnull t) { - if (t.error) { - [expect fulfill]; - } - return nil; - }]; - - // Call the failure callback as Apple would - NSError *err = [[NSError alloc] initWithDomain:@"org.parseplatform.error" code:1337 userInfo:nil]; - [manager authorizationController:manager.controller didCompleteWithError:err]; - [self waitForExpectations:@[expect] timeout:2]; - -} - @end diff --git a/README.md b/README.md index 735fd3138..086429ff0 100644 --- a/README.md +++ b/README.md @@ -16,13 +16,12 @@ License Podspec Backers on Open Collective - Sponsors on Open Collective + Sponsors on Open Collective

Carthage compatible Dependencies - References Build status Build status Coverage status @@ -109,7 +108,6 @@ Compiled frameworks will be in multiple archives inside the `build/release` fold - `ParseTwitterUtils-iOS.zip` - `ParseUI.zip` - #### Using Parse as a sub-project You can also include parse as a subproject inside of your application if you'd prefer, although we do not recommend this, as it will increase your indexing time significantly. To do so, just drag and drop the Parse.xcodeproj file into your workspace. Note that unit tests will be unavailable if you use Parse like this, as OCMock will be unable to be found. @@ -118,24 +116,6 @@ You can also include parse as a subproject inside of your application if you'd p We want to make contributing to this project as easy and transparent as possible. Please refer to the [Contribution Guidelines][contributing]. -## Preparing for a new release - -### Update the version number - -You can use the rake task in order to bump the version number, it's safe, and will properly update all version numbers - -``` -$ bundle exec rake package:set_version[X.X.X] -``` - -Note that zsh users (such as those using macOS >= 10.15) need to escape the brackets as follows: - -``` -$ bundle exec rake package:set_version\[X.X.X\] -``` - -Replace X.X.X by the version number and push to the repository. - ## Dependencies We use the following libraries as dependencies inside of Parse: @@ -143,19 +123,6 @@ We use the following libraries as dependencies inside of Parse: - [Bolts][bolts-framework], for task management. - [OCMock][ocmock-framework], for unit testing. -## License - -``` -Copyright (c) 2015-present, Parse, LLC. -All rights reserved. - -This source code is licensed under the BSD-style license found in the -LICENSE file in the root directory of this source tree. An additional grant -of patent rights can be found in the PATENTS file in the same directory. -``` - -As of April 5, 2017, Parse, LLC has transferred this code to the parse-community organization, and will no longer be contributing to or distributing this code. - [docs]: http://docs.parseplatform.org/ios/guide/ [api]: http://parseplatform.org/Parse-SDK-iOS-OSX/api/