Pārlūkot izejas kodu

Resolved comments

pinlu 3 gadi atpakaļ
vecāks
revīzija
8c4d95453e

+ 22 - 10
GoogleSignIn/Sources/GIDGoogleUser.m

@@ -17,6 +17,7 @@
 #import "GoogleSignIn/Sources/GIDGoogleUser_Private.h"
 
 #import "GoogleSignIn/Sources/Public/GoogleSignIn/GIDConfiguration.h"
+#import "GoogleSignIn/Sources/Public/GoogleSignIn/GIDSignIn.h"
 
 #import "GoogleSignIn/Sources/GIDAppAuthFetcherAuthorizationWithEMMSupport.h"
 #import "GoogleSignIn/Sources/GIDAuthentication.h"
@@ -183,28 +184,39 @@ static NSTimeInterval const kMinimalTimeToExpire = 60.0;
 }
 
 #if TARGET_OS_IOS && !TARGET_OS_MACCATALYST
-
 - (void)addScopes:(NSArray<NSString *> *)scopes
     presentingViewController:(UIViewController *)presentingViewController
                   completion:(nullable void (^)(GIDUserAuth *_Nullable userAuth,
                                                 NSError *_Nullable error))completion {
+#elif TARGET_OS_OSX || TARGET_OS_MACCATALYST
+- (void)addScopes:(NSArray<NSString *> *)scopes
+    presentingWindow:(NSWindow *)presentingWindow
+          completion:(nullable void (^)(GIDUserAuth *_Nullable userAuth,
+                                        NSError *_Nullable error))completion {
+#endif // TARGET_OS_IOS && !TARGET_OS_MACCATALYST
+
+  if (self != GIDSignIn.sharedInstance.currentUser) {
+    NSError *error = [NSError errorWithDomain:kGIDSignInErrorDomain
+                                         code:kGIDSignInErrorCodePreviousUser
+                                     userInfo:nil];
+    if (completion) {
+      dispatch_async(dispatch_get_main_queue(), ^{
+        completion(nil, error);
+      });
+    }
+    return;
+  }
+  
+#if TARGET_OS_IOS && !TARGET_OS_MACCATALYST
   [GIDSignIn.sharedInstance addScopes:scopes
              presentingViewController:presentingViewController
                            completion:completion];
-}
-
 #elif TARGET_OS_OSX || TARGET_OS_MACCATALYST
-
-- (void)addScopes:(NSArray<NSString *> *)scopes
- presentingWindow:(NSWindow *)presentingWindow
-       completion:(nullable void (^)(GIDUserAuth *_Nullable userAuth,
-                                     NSError *_Nullable error))completion {
   [GIDSignIn.sharedInstance addScopes:scopes
                      presentingWindow:presentingWindow
                            completion:completion];
-}
-
 #endif // TARGET_OS_IOS && !TARGET_OS_MACCATALYST
+}
 
 #pragma mark - Private Methods
 

+ 5 - 5
GoogleSignIn/Sources/GIDSignIn_Private.h

@@ -55,9 +55,9 @@ typedef void (^GIDUserAuthCompletion)(GIDUserAuth *_Nullable userAuth, NSError *
 
 #if TARGET_OS_IOS || TARGET_OS_MACCATALYST
 
-/// Starts an interactive consent flow on iOS to add scopes to the current user's grants.
+/// Starts an interactive consent flow on iOS to add scopes to the user's grants.
 ///
-/// The completion will be called at the end of this process.  If successful, a new `GIDGoogleUser`
+/// The completion will be called at the end of this process.  If successful, a `GIDUserAuth`
 /// instance will be returned reflecting the new scopes and saved sign-in state will be updated.
 ///
 /// @param scopes The scopes to ask the user to consent to.
@@ -74,9 +74,9 @@ typedef void (^GIDUserAuthCompletion)(GIDUserAuth *_Nullable userAuth, NSError *
 
 #elif TARGET_OS_OSX
 
-/// Starts an interactive consent flow on macOS to add scopes to the current user's grants
+/// Starts an interactive consent flow on macOS to add scopes to the user's grants
 ///
-/// The completion will be called at the end of this process.  If successful, a new `GIDGoogleUser`
+/// The completion will be called at the end of this process.  If successful, a `GIDUserAuth`
 /// instance will be returned reflecting the new scopes and saved sign-in state will be updated.
 ///
 /// @param scopes An array of scopes to ask the user to consent to.
@@ -87,7 +87,7 @@ typedef void (^GIDUserAuthCompletion)(GIDUserAuth *_Nullable userAuth, NSError *
 - (void)addScopes:(NSArray<NSString *> *)scopes
     presentingWindow:(NSWindow *)presentingWindow
           completion:(nullable void (^)(GIDUserAuth *_Nullable userAuth,
-                                     NSError *_Nullable error))completion;
+                                        NSError *_Nullable error))completion;
 
 #endif
 

+ 7 - 7
GoogleSignIn/Sources/Public/GoogleSignIn/GIDGoogleUser.h

@@ -81,9 +81,9 @@ NS_ASSUME_NONNULL_BEGIN
 
 #if TARGET_OS_IOS || TARGET_OS_MACCATALYST
 
-/// Starts an interactive consent flow on iOS to add scopes to the current user's grants.
+/// Starts an interactive consent flow on iOS to add scopes to the user's grants.
 ///
-/// The completion will be called at the end of this process.  If successful, a new `GIDGoogleUser`
+/// The completion will be called at the end of this process.  If successful, a `GIDUserAuth`
 /// instance will be returned reflecting the new scopes and saved sign-in state will be updated.
 ///
 /// @param scopes The scopes to ask the user to consent to.
@@ -100,9 +100,9 @@ NS_ASSUME_NONNULL_BEGIN
 
 #elif TARGET_OS_OSX
 
-/// Starts an interactive consent flow on macOS to add scopes to the current user's grants.
+/// Starts an interactive consent flow on macOS to add scopes to the user's grants.
 ///
-/// The completion will be called at the end of this process.  If successful, a new `GIDGoogleUser`
+/// The completion will be called at the end of this process.  If successful, a `GIDUserAuth`
 /// instance will be returned reflecting the new scopes and saved sign-in state will be updated.
 ///
 /// @param scopes An array of scopes to ask the user to consent to.
@@ -110,9 +110,9 @@ NS_ASSUME_NONNULL_BEGIN
 /// @param completion The block that is called on completion.  This block will be called asynchronously
 ///     on the main queue.
 - (void)addScopes:(NSArray<NSString *> *)scopes
- presentingWindow:(NSWindow *)presentingWindow
-       completion:(nullable void (^)(GIDUserAuth *_Nullable userAuth,
-                                     NSError *_Nullable error))completion;
+    presentingWindow:(NSWindow *)presentingWindow
+          completion:(nullable void (^)(GIDUserAuth *_Nullable userAuth,
+                                        NSError *_Nullable error))completion;
 
 #endif
 

+ 3 - 1
GoogleSignIn/Sources/Public/GoogleSignIn/GIDSignIn.h

@@ -47,8 +47,10 @@ typedef NS_ERROR_ENUM(kGIDSignInErrorDomain, GIDSignInErrorCode) {
   kGIDSignInErrorCodeEMM = -6,
   /// Indicates there is no `currentUser`.
   kGIDSignInErrorCodeNoCurrentUser = -7,
+  /// Indicates there is an operation on a previous user.
+  kGIDSignInErrorCodePreviousUser = -8,
   /// Indicates the requested scopes have already been granted to the `currentUser`.
-  kGIDSignInErrorCodeScopesAlreadyGranted = -8,
+  kGIDSignInErrorCodeScopesAlreadyGranted = -9,
 };
 
 /// Represents a completion block that takes an error if the operation was unsuccessful.

+ 75 - 0
GoogleSignIn/Tests/Unit/GIDGoogleUserTest.m

@@ -15,9 +15,11 @@
 #import "GoogleSignIn/Sources/Public/GoogleSignIn/GIDGoogleUser.h"
 
 #import <XCTest/XCTest.h>
+#import <TargetConditionals.h>
 
 #import "GoogleSignIn/Sources/Public/GoogleSignIn/GIDConfiguration.h"
 #import "GoogleSignIn/Sources/Public/GoogleSignIn/GIDProfileData.h"
+#import "GoogleSignIn/Sources/Public/GoogleSignIn/GIDSignIn.h"
 #import "GoogleSignIn/Sources/Public/GoogleSignIn/GIDToken.h"
 
 #import "GoogleSignIn/Sources/GIDGoogleUser_Private.h"
@@ -33,6 +35,7 @@
 @import GoogleUtilities_MethodSwizzler;
 @import GoogleUtilities_SwizzlerTestHelpers;
 @import GTMAppAuth;
+@import OCMock;
 #else
 #import <AppAuth/OIDAuthState.h>
 #import <AppAuth/OIDAuthorizationRequest.h>
@@ -45,6 +48,7 @@
 #import <GoogleUtilities/GULSwizzler.h>
 #import <GoogleUtilities/GULSwizzler+Unswizzle.h>
 #import <GTMAppAuth/GTMAppAuthFetcherAuthorization.h>
+#import <OCMock/OCMock.h>
 #endif
 
 static NSString *const kNewAccessToken = @"new_access_token";
@@ -54,6 +58,8 @@ static NSTimeInterval const kTimeAccuracy = 10;
 static NSTimeInterval const kIDTokenExpiresIn = 100;
 static NSTimeInterval const kNewIDTokenExpiresIn = 200;
 
+static NSString *const kNewScope = @"newScope";
+
 @interface GIDGoogleUserTest : XCTestCase
 @end
 
@@ -437,6 +443,75 @@ static NSTimeInterval const kNewIDTokenExpiresIn = 200;
   [self waitForExpectationsWithTimeout:1 handler:nil];
 }
 
+- (void)testAddScopes_success {
+  id signIn = OCMClassMock([GIDSignIn class]);
+  OCMStub([signIn sharedInstance]).andReturn(signIn);
+  [[signIn expect] addScopes:OCMOCK_ANY
+#if TARGET_OS_IOS || TARGET_OS_MACCATALYST
+    presentingViewController:OCMOCK_ANY
+#elif TARGET_OS_OSX
+            presentingWindow:OCMOCK_ANY
+#endif // TARGET_OS_IOS || TARGET_OS_MACCATALYST
+                  completion:OCMOCK_ANY];
+  
+  GIDGoogleUser *currentUser = [self googleUserWithAccessTokenExpiresIn:kAccessTokenExpiresIn
+                                                       idTokenExpiresIn:kIDTokenExpiresIn];
+  
+  OCMStub([signIn currentUser]).andReturn(currentUser);
+  
+#if TARGET_OS_IOS || TARGET_OS_MACCATALYST
+  UIViewController *presentingViewController = [[UIViewController alloc] init];
+  [currentUser addScopes:@[kNewScope]
+    presentingViewController:presentingViewController
+                  completion:nil];
+#elif TARGET_OS_OSX
+  NSWindow *presentingWindow = [[NSWindow alloc] init];
+  [currentUser addScopes:@[kNewScope]
+    presentingWindow:presentingWindow
+          completion:nil];
+#endif // TARGET_OS_IOS || TARGET_OS_MACCATALYST
+  
+  [signIn verify];
+}
+
+- (void)testAddScopes_failure_addScopesToPreviousAccount {
+  id signIn = OCMClassMock([GIDSignIn class]);
+  OCMStub([signIn sharedInstance]).andReturn(signIn);
+
+  GIDGoogleUser *currentUser = [self googleUserWithAccessTokenExpiresIn:kAccessTokenExpiresIn
+                                                       idTokenExpiresIn:kIDTokenExpiresIn];
+  
+  OCMStub([signIn currentUser]).andReturn(currentUser);
+  
+  GIDGoogleUser *previousUser = [self googleUserWithAccessTokenExpiresIn:kAccessTokenExpiresIn
+                                                        idTokenExpiresIn:kNewIDTokenExpiresIn];
+  
+  XCTestExpectation *expectation =
+      [self expectationWithDescription:@"Completion is called."];
+  
+#if TARGET_OS_IOS || TARGET_OS_MACCATALYST
+  UIViewController *presentingViewController = [[UIViewController alloc] init];
+  [previousUser addScopes:@[kNewScope]
+    presentingViewController:presentingViewController
+                  completion:^(GIDUserAuth *userAuth, NSError *error) {
+    [expectation fulfill];
+    XCTAssertNil(userAuth);
+    XCTAssertEqual(error.code, kGIDSignInErrorCodePreviousUser);
+  }];
+#elif TARGET_OS_OSX
+  NSWindow *presentingWindow = [[NSWindow alloc] init];
+  [previousUser addScopes:@[kNewScope]
+         presentingWindow:presentingWindow
+                  completion:^(GIDUserAuth *userAuth, NSError *error) {
+    [expectation fulfill];
+    XCTAssertNil(userAuth);
+    XCTAssertEqual(error.code, kGIDSignInErrorCodePreviousUser);
+  }];
+#endif // TARGET_OS_IOS || TARGET_OS_MACCATALYST
+  
+  [self waitForExpectationsWithTimeout:1 handler:nil];
+}
+
 #pragma mark - Helpers
 
 // Returns a GIDGoogleUser with different tokens expiresIn time. The token strings are constants.

+ 6 - 4
Samples/Swift/DaysUntilBirthday/Shared/Services/GoogleSignInAuthenticator.swift

@@ -83,14 +83,16 @@ final class GoogleSignInAuthenticator: ObservableObject {
   /// - note: Successful requests will update the `authViewModel.state` with a new current user that
   /// has the granted scope.
   func addBirthdayReadScope(completion: @escaping () -> Void) {
-    let currentUser = GIDSignIn.sharedInstance.currentUser
+    guard let currentUser = GIDSignIn.sharedInstance.currentUser else {
+      fatalError("No user signed in!")
+    }
     
     #if os(iOS)
     guard let rootViewController = UIApplication.shared.windows.first?.rootViewController else {
       fatalError("No root view controller!")
     }
 
-    currentUser?.addScopes([BirthdayLoader.birthdayReadScope],
+    currentUser.addScopes([BirthdayLoader.birthdayReadScope],
                           presenting: rootViewController) { userAuth, error in
       if let error = error {
         print("Found error while adding birthday read scope: \(error).")
@@ -107,8 +109,8 @@ final class GoogleSignInAuthenticator: ObservableObject {
       fatalError("No presenting window!")
     }
 
-    currentUser?.addScopes([BirthdayLoader.birthdayReadScope],
-                           presenting: presentingWindow) { userAuth, error in
+    currentUser.addScopes([BirthdayLoader.birthdayReadScope],
+                          presenting: presentingWindow) { userAuth, error in
       if let error = error {
         print("Found error while adding birthday read scope: \(error).")
         return