diff --git a/packages/firebase_auth/CHANGELOG.md b/packages/firebase_auth/CHANGELOG.md index 1728a08e358f..567fe3fe4d8c 100644 --- a/packages/firebase_auth/CHANGELOG.md +++ b/packages/firebase_auth/CHANGELOG.md @@ -1,3 +1,9 @@ +## 0.12.0 + +* Added new `AuthResult` and `AdditionalUserInfo` classes. +* **Breaking Change**. Sign-in methods now return `AuthResult` instead of `FirebaseUser`. + Retrieve the `FirebaseUser` using the `user` property of `AuthResult`. + ## 0.11.1+12 * Update google-services Android gradle plugin to 4.3.0 in documentation and examples. diff --git a/packages/firebase_auth/android/src/main/java/io/flutter/plugins/firebaseauth/FirebaseAuthPlugin.java b/packages/firebase_auth/android/src/main/java/io/flutter/plugins/firebaseauth/FirebaseAuthPlugin.java index 8b0ac80f3a53..b3b782d8ac04 100755 --- a/packages/firebase_auth/android/src/main/java/io/flutter/plugins/firebaseauth/FirebaseAuthPlugin.java +++ b/packages/firebase_auth/android/src/main/java/io/flutter/plugins/firebaseauth/FirebaseAuthPlugin.java @@ -16,6 +16,7 @@ import com.google.firebase.FirebaseNetworkException; import com.google.firebase.FirebaseTooManyRequestsException; import com.google.firebase.auth.ActionCodeSettings; +import com.google.firebase.auth.AdditionalUserInfo; import com.google.firebase.auth.AuthCredential; import com.google.firebase.auth.AuthResult; import com.google.firebase.auth.EmailAuthProvider; @@ -669,9 +670,15 @@ public void onComplete(@NonNull Task task) { if (!task.isSuccessful() || task.getResult() == null) { reportException(result, task.getException()); } else { - FirebaseUser user = task.getResult().getUser(); - Map userMap = Collections.unmodifiableMap(mapFromUser(user)); - result.success(userMap); + AuthResult authResult = task.getResult(); + FirebaseUser user = authResult.getUser(); + AdditionalUserInfo additionalUserInfo = authResult.getAdditionalUserInfo(); + Map userMap = (mapFromUser(user)); + Map additionalUserInfoMap = mapFromAdditionalUserInfo(additionalUserInfo); + Map map = new HashMap<>(); + map.put("user", userMap); + map.put("additionalUserInfo", additionalUserInfoMap); + result.success(Collections.unmodifiableMap(map)); } } } @@ -752,6 +759,19 @@ private Map mapFromUser(FirebaseUser user) { } } + private Map mapFromAdditionalUserInfo(AdditionalUserInfo info) { + if (info != null) { + Map additionalUserInfoMap = new HashMap<>(); + additionalUserInfoMap.put("profile", info.getProfile()); + additionalUserInfoMap.put("providerId", info.getProviderId()); + additionalUserInfoMap.put("username", info.getUsername()); + additionalUserInfoMap.put("isNewUser", info.isNewUser()); + return Collections.unmodifiableMap(additionalUserInfoMap); + } else { + return null; + } + } + private void markUserRequired(Result result) { result.error("USER_REQUIRED", "Please authenticate with Firebase first", null); } diff --git a/packages/firebase_auth/example/lib/register_page.dart b/packages/firebase_auth/example/lib/register_page.dart index fd4c74430ff5..acc055aa17b5 100644 --- a/packages/firebase_auth/example/lib/register_page.dart +++ b/packages/firebase_auth/example/lib/register_page.dart @@ -82,10 +82,11 @@ class RegisterPageState extends State { // Example code for registration. void _register() async { - final FirebaseUser user = await _auth.createUserWithEmailAndPassword( + final FirebaseUser user = (await _auth.createUserWithEmailAndPassword( email: _emailController.text, password: _passwordController.text, - ); + )) + .user; if (user != null) { setState(() { _success = true; diff --git a/packages/firebase_auth/example/lib/signin_page.dart b/packages/firebase_auth/example/lib/signin_page.dart index 52faf6f50d02..ac1638f5f2d8 100644 --- a/packages/firebase_auth/example/lib/signin_page.dart +++ b/packages/firebase_auth/example/lib/signin_page.dart @@ -145,10 +145,11 @@ class _EmailPasswordFormState extends State<_EmailPasswordForm> { // Example code of how to sign in with email and password. void _signInWithEmailAndPassword() async { - final FirebaseUser user = await _auth.signInWithEmailAndPassword( + final FirebaseUser user = (await _auth.signInWithEmailAndPassword( email: _emailController.text, password: _passwordController.text, - ); + )) + .user; if (user != null) { setState(() { _success = true; @@ -193,10 +194,11 @@ class _EmailLinkSignInSectionState extends State<_EmailLinkSignInSection> final Uri link = await _retrieveDynamicLink(); if (link != null) { - final FirebaseUser user = await _auth.signInWithEmailAndLink( + final FirebaseUser user = (await _auth.signInWithEmailAndLink( email: _userEmail, link: link.toString(), - ); + )) + .user; if (user != null) { _userID = user.uid; @@ -330,7 +332,7 @@ class _AnonymouslySignInSectionState extends State<_AnonymouslySignInSection> { // Example code of how to sign in anonymously. void _signInAnonymously() async { - final FirebaseUser user = await _auth.signInAnonymously(); + final FirebaseUser user = (await _auth.signInAnonymously()).user; assert(user != null); assert(user.isAnonymous); assert(!user.isEmailVerified); @@ -413,7 +415,8 @@ class _GoogleSignInSectionState extends State<_GoogleSignInSection> { accessToken: googleAuth.accessToken, idToken: googleAuth.idToken, ); - final FirebaseUser user = await _auth.signInWithCredential(credential); + final FirebaseUser user = + (await _auth.signInWithCredential(credential)).user; assert(user.email != null); assert(user.displayName != null); assert(!user.isAnonymous); @@ -554,7 +557,8 @@ class _PhoneSignInSectionState extends State<_PhoneSignInSection> { verificationId: _verificationId, smsCode: _smsController.text, ); - final FirebaseUser user = await _auth.signInWithCredential(credential); + final FirebaseUser user = + (await _auth.signInWithCredential(credential)).user; final FirebaseUser currentUser = await _auth.currentUser(); assert(user.uid == currentUser.uid); setState(() { @@ -698,7 +702,8 @@ class _OtherProvidersSignInSectionState final AuthCredential credential = GithubAuthProvider.getCredential( token: _tokenController.text, ); - final FirebaseUser user = await _auth.signInWithCredential(credential); + final FirebaseUser user = + (await _auth.signInWithCredential(credential)).user; assert(user.email != null); assert(user.displayName != null); assert(!user.isAnonymous); @@ -720,7 +725,8 @@ class _OtherProvidersSignInSectionState final AuthCredential credential = FacebookAuthProvider.getCredential( accessToken: _tokenController.text, ); - final FirebaseUser user = await _auth.signInWithCredential(credential); + final FirebaseUser user = + (await _auth.signInWithCredential(credential)).user; assert(user.email != null); assert(user.displayName != null); assert(!user.isAnonymous); @@ -742,7 +748,8 @@ class _OtherProvidersSignInSectionState final AuthCredential credential = TwitterAuthProvider.getCredential( authToken: _tokenController.text, authTokenSecret: _tokenSecretController.text); - final FirebaseUser user = await _auth.signInWithCredential(credential); + final FirebaseUser user = + (await _auth.signInWithCredential(credential)).user; assert(user.email != null); assert(user.displayName != null); assert(!user.isAnonymous); diff --git a/packages/firebase_auth/example/pubspec.yaml b/packages/firebase_auth/example/pubspec.yaml index 5356bd5c52a2..a72835476bcb 100755 --- a/packages/firebase_auth/example/pubspec.yaml +++ b/packages/firebase_auth/example/pubspec.yaml @@ -8,7 +8,7 @@ dependencies: firebase_auth: path: ../ google_sign_in: ^4.0.0 - firebase_core: ^0.4.0 + firebase_core: ^0.4.0+8 firebase_dynamic_links: ^0.3.0 dev_dependencies: diff --git a/packages/firebase_auth/example/test/firebase_auth.dart b/packages/firebase_auth/example/test/firebase_auth.dart index 2c4f4c8ede32..5a76e4c05998 100644 --- a/packages/firebase_auth/example/test/firebase_auth.dart +++ b/packages/firebase_auth/example/test/firebase_auth.dart @@ -16,9 +16,15 @@ void main() { final FirebaseAuth auth = FirebaseAuth.instance; test('signInAnonymously', () async { - final FirebaseUser user = await auth.signInAnonymously(); + final AuthResult result = await auth.signInAnonymously(); + final FirebaseUser user = result.user; expect(user.uid, isNotNull); expect(user.isAnonymous, isTrue); + final AdditionalUserInfo additionalUserInfo = result.additionalUserInfo; + expect(additionalUserInfo.username, isNull); + expect(additionalUserInfo.isNewUser, isNotNull); + expect(additionalUserInfo.profile, isNull); + expect(additionalUserInfo.providerId, isNull); }); test('isSignInWithEmailLink', () async { diff --git a/packages/firebase_auth/ios/Classes/FirebaseAuthPlugin.m b/packages/firebase_auth/ios/Classes/FirebaseAuthPlugin.m index bbe6f8c4f283..83c18c8dd5fb 100644 --- a/packages/firebase_auth/ios/Classes/FirebaseAuthPlugin.m +++ b/packages/firebase_auth/ios/Classes/FirebaseAuthPlugin.m @@ -107,13 +107,15 @@ - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result } else if ([@"signInAnonymously" isEqualToString:call.method]) { [[self getAuth:call.arguments] signInAnonymouslyWithCompletion:^(FIRAuthDataResult *authResult, NSError *error) { - [self sendResult:result forUser:authResult.user error:error]; + [self sendResult:result forAuthDataResult:authResult error:error]; }]; } else if ([@"signInWithCredential" isEqualToString:call.method]) { [[self getAuth:call.arguments] signInAndRetrieveDataWithCredential:[self getCredential:call.arguments] completion:^(FIRAuthDataResult *authResult, NSError *error) { - [self sendResult:result forUser:authResult.user error:error]; + [self sendResult:result + forAuthDataResult:authResult + error:error]; }]; } else if ([@"createUserWithEmailAndPassword" isEqualToString:call.method]) { NSString *email = call.arguments[@"email"]; @@ -122,7 +124,7 @@ - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result createUserWithEmail:email password:password completion:^(FIRAuthDataResult *authResult, NSError *error) { - [self sendResult:result forUser:authResult.user error:error]; + [self sendResult:result forAuthDataResult:authResult error:error]; }]; } else if ([@"fetchSignInMethodsForEmail" isEqualToString:call.method]) { NSString *email = call.arguments[@"email"]; @@ -177,7 +179,7 @@ - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result signInWithEmail:email link:link completion:^(FIRAuthDataResult *_Nullable authResult, NSError *_Nullable error) { - [self sendResult:result forUser:authResult.user error:error]; + [self sendResult:result forAuthDataResult:authResult error:error]; }]; } else if ([@"signInWithEmailAndPassword" isEqualToString:call.method]) { NSString *email = call.arguments[@"email"]; @@ -186,7 +188,7 @@ - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result signInWithEmail:email password:password completion:^(FIRAuthDataResult *authResult, NSError *error) { - [self sendResult:result forUser:authResult.user error:error]; + [self sendResult:result forAuthDataResult:authResult error:error]; }]; } else if ([@"signOut" isEqualToString:call.method]) { NSError *signOutError; @@ -215,8 +217,8 @@ - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result } else if ([@"linkWithCredential" isEqualToString:call.method]) { [[self getAuth:call.arguments].currentUser linkAndRetrieveDataWithCredential:[self getCredential:call.arguments] - completion:^(FIRAuthDataResult *r, NSError *error) { - [self sendResult:result forUser:r.user error:error]; + completion:^(FIRAuthDataResult *authResult, NSError *error) { + [self sendResult:result forAuthDataResult:authResult error:error]; }]; } else if ([@"unlinkFromProvider" isEqualToString:call.method]) { NSString *provider = call.arguments[@"provider"]; @@ -266,7 +268,7 @@ - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result [[self getAuth:call.arguments] signInWithCustomToken:token completion:^(FIRAuthDataResult *authResult, NSError *error) { - [self sendResult:result forUser:authResult.user error:error]; + [self sendResult:result forAuthDataResult:authResult error:error]; }]; } else if ([@"startListeningAuthState" isEqualToString:call.method]) { @@ -329,8 +331,11 @@ - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result verificationCode:smsCode]; [[self getAuth:call.arguments] signInAndRetrieveDataWithCredential:credential - completion:^(FIRAuthDataResult *r, NSError *_Nullable error) { - [self sendResult:result forUser:r.user error:error]; + completion:^(FIRAuthDataResult *authResult, + NSError *_Nullable error) { + [self sendResult:result + forAuthDataResult:authResult + error:error]; }]; } else if ([@"setLanguageCode" isEqualToString:call.method]) { NSString *language = call.arguments[@"language"]; @@ -353,7 +358,7 @@ - (NSMutableDictionary *)dictionaryFromUser:(FIRUser *)user { NSMutableDictionary *userData = [toDictionary(user) mutableCopy]; userData[@"creationTimestamp"] = [NSNumber numberWithLong:creationDate]; - userData[@"lastSignInTimestamp"] = [NSNumber numberWithInt:lastSignInDate]; + userData[@"lastSignInTimestamp"] = [NSNumber numberWithLong:lastSignInDate]; userData[@"isAnonymous"] = [NSNumber numberWithBool:user.isAnonymous]; userData[@"isEmailVerified"] = [NSNumber numberWithBool:user.isEmailVerified]; userData[@"providerData"] = providerData; @@ -361,6 +366,24 @@ - (NSMutableDictionary *)dictionaryFromUser:(FIRUser *)user { } #pragma clang diagnostic pop +- (void)sendResult:(FlutterResult)result + forAuthDataResult:(FIRAuthDataResult *)authResult + error:(NSError *)error { + FIRUser *user = authResult.user; + FIRAdditionalUserInfo *additionalUserInfo = authResult.additionalUserInfo; + [self sendResult:result + forObject:@{ + @"user" : (user != nil ? [self dictionaryFromUser:user] : nil), + @"additionalUserInfo" : @{ + @"isNewUser" : [NSNumber numberWithBool:additionalUserInfo.isNewUser], + @"username" : additionalUserInfo.username, + @"providerId" : additionalUserInfo.providerID, + @"profile" : additionalUserInfo.profile, + } + } + error:error]; +} + - (void)sendResult:(FlutterResult)result forUser:(FIRUser *)user error:(NSError *)error { [self sendResult:result forObject:(user != nil ? [self dictionaryFromUser:user] : nil) diff --git a/packages/firebase_auth/lib/firebase_auth.dart b/packages/firebase_auth/lib/firebase_auth.dart index 1f31ead02dc0..0e7ba33d706c 100755 --- a/packages/firebase_auth/lib/firebase_auth.dart +++ b/packages/firebase_auth/lib/firebase_auth.dart @@ -16,8 +16,10 @@ part 'src/auth_provider/github_auth_provider.dart'; part 'src/auth_provider/google_auth_provider.dart'; part 'src/auth_provider/phone_auth_provider.dart'; part 'src/auth_provider/twitter_auth_provider.dart'; +part 'src/additional_user_info.dart'; part 'src/auth_credential.dart'; part 'src/auth_exception.dart'; +part 'src/auth_result.dart'; part 'src/firebase_auth.dart'; part 'src/firebase_user.dart'; part 'src/user_info.dart'; diff --git a/packages/firebase_auth/lib/src/additional_user_info.dart b/packages/firebase_auth/lib/src/additional_user_info.dart new file mode 100644 index 000000000000..2fb0f7707fc4 --- /dev/null +++ b/packages/firebase_auth/lib/src/additional_user_info.dart @@ -0,0 +1,26 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +part of firebase_auth; + +/// Interface representing a user's additional information +class AdditionalUserInfo { + AdditionalUserInfo._(this._data); + + final Map _data; + + /// Returns whether the user is new or existing + bool get isNewUser => _data['isNewUser']; + + /// Returns the username if the provider is GitHub or Twitter + String get username => _data['username']; + + /// Returns the provider ID for specifying which provider the + /// information in [profile] is for. + String get providerId => _data['providerId']; + + /// Returns a Map containing IDP-specific user data if the provider + /// is one of Facebook, GitHub, Google, Twitter, Microsoft, or Yahoo. + Map get profile => _data['profile']?.cast(); +} diff --git a/packages/firebase_auth/lib/src/auth_result.dart b/packages/firebase_auth/lib/src/auth_result.dart new file mode 100644 index 000000000000..dd003dac0791 --- /dev/null +++ b/packages/firebase_auth/lib/src/auth_result.dart @@ -0,0 +1,31 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +part of firebase_auth; + +/// Result object obtained from operations that can affect the authentication +/// state. Contains a method that returns the currently signed-in user after +/// the operation has completed. +class AuthResult { + AuthResult._(this._data, FirebaseApp app) + : user = FirebaseUser._(_data['user'].cast(), app); + + final Map _data; + + /// Returns the currently signed-in [FirebaseUser], or `null` if there isn't + /// any (i.e. the user is signed out). + final FirebaseUser user; + + /// Returns IDP-specific information for the user if the provider is one of + /// Facebook, Github, Google, or Twitter. + AdditionalUserInfo get additionalUserInfo => + _data['additionalUserInfo'] == null + ? null + : AdditionalUserInfo._(_data['additionalUserInfo']); + + @override + String toString() { + return '$runtimeType($_data)'; + } +} diff --git a/packages/firebase_auth/lib/src/firebase_auth.dart b/packages/firebase_auth/lib/src/firebase_auth.dart index f3c79ffd5cfa..8f0c30a13544 100644 --- a/packages/firebase_auth/lib/src/firebase_auth.dart +++ b/packages/firebase_auth/lib/src/firebase_auth.dart @@ -71,12 +71,12 @@ class FirebaseAuth { /// /// Errors: /// • `ERROR_OPERATION_NOT_ALLOWED` - Indicates that Anonymous accounts are not enabled. - Future signInAnonymously() async { + Future signInAnonymously() async { final Map data = await channel .invokeMapMethod( 'signInAnonymously', {"app": app.name}); - final FirebaseUser currentUser = FirebaseUser._(data, app); - return currentUser; + final AuthResult authResult = AuthResult._(data, app); + return authResult; } /// Tries to create a new user account with the given email address and password. @@ -88,7 +88,7 @@ class FirebaseAuth { /// • `ERROR_WEAK_PASSWORD` - If the password is not strong enough. /// • `ERROR_INVALID_EMAIL` - If the email address is malformed. /// • `ERROR_EMAIL_ALREADY_IN_USE` - If the email is already in use by a different account. - Future createUserWithEmailAndPassword({ + Future createUserWithEmailAndPassword({ @required String email, @required String password, }) async { @@ -99,8 +99,8 @@ class FirebaseAuth { 'createUserWithEmailAndPassword', {'email': email, 'password': password, 'app': app.name}, ); - final FirebaseUser currentUser = FirebaseUser._(data, app); - return currentUser; + final AuthResult authResult = AuthResult._(data, app); + return authResult; } /// Returns a list of sign-in methods that can be used to sign in a given @@ -187,8 +187,7 @@ class FirebaseAuth { /// Firebase console. /// • `ERROR_DISABLED` - Indicates the user's account is disabled. /// • `ERROR_INVALID` - Indicates the email address is invalid. - Future signInWithEmailAndLink( - {String email, String link}) async { + Future signInWithEmailAndLink({String email, String link}) async { final Map data = await channel.invokeMapMethod( 'signInWithEmailAndLink', @@ -198,8 +197,8 @@ class FirebaseAuth { 'link': link, }, ); - final FirebaseUser currentUser = FirebaseUser._(data, app); - return currentUser; + final AuthResult authResult = AuthResult._(data, app); + return authResult; } /// Tries to sign in a user with the given email address and password. @@ -217,7 +216,7 @@ class FirebaseAuth { /// • `ERROR_USER_DISABLED` - If the user has been disabled (for example, in the Firebase console) /// • `ERROR_TOO_MANY_REQUESTS` - If there was too many attempts to sign in as this user. /// • `ERROR_OPERATION_NOT_ALLOWED` - Indicates that Email & Password accounts are not enabled. - Future signInWithEmailAndPassword({ + Future signInWithEmailAndPassword({ @required String email, @required String password, }) { @@ -251,7 +250,7 @@ class FirebaseAuth { /// • `ERROR_OPERATION_NOT_ALLOWED` - Indicates that Google accounts are not enabled. /// • `ERROR_INVALID_ACTION_CODE` - If the action code in the link is malformed, expired, or has already been used. /// This can only occur when using [EmailAuthProvider.getCredentialWithLink] to obtain the credential. - Future signInWithCredential(AuthCredential credential) async { + Future signInWithCredential(AuthCredential credential) async { assert(credential != null); final Map data = await channel.invokeMapMethod( @@ -262,8 +261,8 @@ class FirebaseAuth { 'data': credential._data, }, ); - final FirebaseUser currentUser = FirebaseUser._(data, app); - return currentUser; + final AuthResult authResult = AuthResult._(data, app); + return authResult; } /// Starts the phone number verification process for the given phone number. @@ -356,15 +355,15 @@ class FirebaseAuth { /// Please check the documentation. /// • `ERROR_CUSTOM_TOKEN_MISMATCH` - Invalid configuration. /// Ensure your app's SHA1 is correct in the Firebase console. - Future signInWithCustomToken({@required String token}) async { + Future signInWithCustomToken({@required String token}) async { assert(token != null); final Map data = await channel.invokeMapMethod( 'signInWithCustomToken', {'token': token, 'app': app.name}, ); - final FirebaseUser currentUser = FirebaseUser._(data, app); - return currentUser; + final AuthResult authResult = AuthResult._(data, app); + return authResult; } /// Signs out the current user and clears it from the disk cache. diff --git a/packages/firebase_auth/lib/src/firebase_user.dart b/packages/firebase_auth/lib/src/firebase_user.dart index 60e341648d44..e9093ce2f1ad 100644 --- a/packages/firebase_auth/lib/src/firebase_user.dart +++ b/packages/firebase_auth/lib/src/firebase_user.dart @@ -58,7 +58,7 @@ class FirebaseUser extends UserInfo { /// • `ERROR_OPERATION_NOT_ALLOWED` - Indicates that this type of account is not enabled. /// • `ERROR_INVALID_ACTION_CODE` - If the action code in the link is malformed, expired, or has already been used. /// This can only occur when using [EmailAuthProvider.getCredentialWithLink] to obtain the credential. - Future linkWithCredential(AuthCredential credential) async { + Future linkWithCredential(AuthCredential credential) async { assert(credential != null); final Map data = await FirebaseAuth.channel.invokeMapMethod( @@ -69,8 +69,8 @@ class FirebaseUser extends UserInfo { 'data': credential._data, }, ); - final FirebaseUser currentUser = FirebaseUser._(data, _app); - return currentUser; + final AuthResult result = AuthResult._(data, _app); + return result; } /// Initiates email verification for the user. @@ -190,10 +190,11 @@ class FirebaseUser extends UserInfo { /// • `ERROR_USER_DISABLED` - If the user has been disabled (for example, in the Firebase console) /// • `ERROR_USER_NOT_FOUND` - If the user has been deleted (for example, in the Firebase console) /// • `ERROR_OPERATION_NOT_ALLOWED` - Indicates that Email & Password accounts are not enabled. - Future reauthenticateWithCredential( + Future reauthenticateWithCredential( AuthCredential credential) async { assert(credential != null); - await FirebaseAuth.channel.invokeMethod( + final Map data = + await FirebaseAuth.channel.invokeMapMethod( 'reauthenticateWithCredential', { 'app': _app.name, @@ -201,7 +202,7 @@ class FirebaseUser extends UserInfo { 'data': credential._data, }, ); - return this; + return AuthResult._(data, _app); } /// Detaches the [provider] account from the current user. diff --git a/packages/firebase_auth/pubspec.yaml b/packages/firebase_auth/pubspec.yaml index 238c1d38128d..fa57e4707dbc 100755 --- a/packages/firebase_auth/pubspec.yaml +++ b/packages/firebase_auth/pubspec.yaml @@ -4,7 +4,7 @@ description: Flutter plugin for Firebase Auth, enabling Android and iOS like Google, Facebook and Twitter. author: Flutter Team homepage: https://github.com/flutter/plugins/tree/master/packages/firebase_auth -version: "0.11.1+12" +version: "0.12.0" flutter: plugin: diff --git a/packages/firebase_auth/test/firebase_auth_test.dart b/packages/firebase_auth/test/firebase_auth_test.dart index 928cb9916854..a05cdec4adec 100755 --- a/packages/firebase_auth/test/firebase_auth_test.dart +++ b/packages/firebase_auth/test/firebase_auth_test.dart @@ -25,6 +25,25 @@ const String kMockPhoneNumber = '5555555555'; const String kMockVerificationId = '12345'; const String kMockSmsCode = '123456'; const String kMockLanguage = 'en'; +const Map kMockAdditionalUserInfo = { + 'isNewUser': false, + 'username': 'flutterUser', + 'providerId': 'testProvider', + 'profile': {'foo': 'bar'}, +}; +const Map kMockUser = { + 'isAnonymous': true, + 'isEmailVerified': false, + 'providerData': >[ + { + 'providerId': kMockProviderId, + 'uid': kMockUid, + 'displayName': kMockDisplayName, + 'photoUrl': kMockPhotoUrl, + 'email': kMockEmail, + }, + ], +}; void main() { group('$FirebaseAuth', () { @@ -48,6 +67,8 @@ void main() { case "startListeningAuthState": return mockHandleId++; break; + case "currentUser": + return kMockUser; case "sendLinkToEmail": case "sendPasswordResetEmail": case "updateEmail": @@ -63,7 +84,10 @@ void main() { return null; break; default: - return mockFirebaseUser(); + return { + 'user': kMockUser, + 'additionalUserInfo': kMockAdditionalUserInfo, + }; break; } }); @@ -81,27 +105,25 @@ void main() { expect(userInfo.email, kMockEmail); } - test('currentUser', () async { - final FirebaseUser user = await auth.currentUser(); - verifyUser(user); + void verifyAuthResult(AuthResult result) { + verifyUser(result.user); + final AdditionalUserInfo additionalUserInfo = result.additionalUserInfo; expect( - log, - [ - isMethodCall('currentUser', - arguments: {'app': auth.app.name}), - ], - ); - }); + additionalUserInfo.isNewUser, kMockAdditionalUserInfo['isNewUser']); + expect(additionalUserInfo.username, kMockAdditionalUserInfo['username']); + expect( + additionalUserInfo.providerId, kMockAdditionalUserInfo['providerId']); + expect(additionalUserInfo.profile, kMockAdditionalUserInfo['profile']); + } - test('signInAnonymously', () async { - final FirebaseUser user = await auth.signInAnonymously(); - verifyUser(user); + test('getIdToken', () async { + final FirebaseUser user = await auth.currentUser(); expect(await user.getIdToken(), equals(kMockIdToken)); expect(await user.getIdToken(refresh: true), equals(kMockIdToken)); expect( log, [ - isMethodCall('signInAnonymously', + isMethodCall('currentUser', arguments: {'app': auth.app.name}), isMethodCall( 'getIdToken', @@ -118,6 +140,18 @@ void main() { ); }); + test('signInAnonymously', () async { + final AuthResult result = await auth.signInAnonymously(); + verifyAuthResult(result); + expect( + log, + [ + isMethodCall('signInAnonymously', + arguments: {'app': auth.app.name}), + ], + ); + }); + test('sendSignInWithEmailLink', () async { await auth.sendSignInWithEmailLink( email: 'test@example.com', @@ -158,10 +192,11 @@ void main() { }); test('signInWithEmailAndLink', () async { - await auth.signInWithEmailAndLink( + final AuthResult result = await auth.signInWithEmailAndLink( email: 'test@example.com', link: '', ); + verifyAuthResult(result); expect( log, [ @@ -175,11 +210,11 @@ void main() { }); test('createUserWithEmailAndPassword', () async { - final FirebaseUser user = await auth.createUserWithEmailAndPassword( + final AuthResult result = await auth.createUserWithEmailAndPassword( email: kMockEmail, password: kMockPassword, ); - verifyUser(user); + verifyAuthResult(result); expect( log, [ @@ -219,9 +254,9 @@ void main() { email: 'test@example.com', link: '', ); - FirebaseUser user = await auth.currentUser(); - user = await user.linkWithCredential(credential); - verifyUser(user); + final FirebaseUser user = await auth.currentUser(); + final AuthResult result = await user.linkWithCredential(credential); + verifyAuthResult(result); expect( log, [ @@ -251,8 +286,8 @@ void main() { email: 'test@example.com', link: '', ); - final FirebaseUser user = await auth.signInWithCredential(credential); - verifyUser(user); + final AuthResult result = await auth.signInWithCredential(credential); + verifyAuthResult(result); expect( log, [ @@ -302,9 +337,9 @@ void main() { authToken: kMockIdToken, authTokenSecret: kMockAccessToken, ); - FirebaseUser user = await auth.currentUser(); - user = await user.linkWithCredential(credential); - verifyUser(user); + final FirebaseUser user = await auth.currentUser(); + final AuthResult result = await user.linkWithCredential(credential); + verifyAuthResult(result); expect( log, [ @@ -334,8 +369,8 @@ void main() { authToken: kMockIdToken, authTokenSecret: kMockAccessToken, ); - final FirebaseUser user = await auth.signInWithCredential(credential); - verifyUser(user); + final AuthResult result = await auth.signInWithCredential(credential); + verifyAuthResult(result); expect( log, [ @@ -358,9 +393,9 @@ void main() { final AuthCredential credential = GithubAuthProvider.getCredential( token: kMockGithubToken, ); - FirebaseUser user = await auth.currentUser(); - user = await user.linkWithCredential(credential); - verifyUser(user); + final FirebaseUser user = await auth.currentUser(); + final AuthResult result = await user.linkWithCredential(credential); + verifyAuthResult(result); expect( log, [ @@ -388,8 +423,8 @@ void main() { final AuthCredential credential = GithubAuthProvider.getCredential( token: kMockGithubToken, ); - final FirebaseUser user = await auth.signInWithCredential(credential); - verifyUser(user); + final AuthResult result = await auth.signInWithCredential(credential); + verifyAuthResult(result); expect( log, [ @@ -412,9 +447,9 @@ void main() { email: kMockEmail, password: kMockPassword, ); - FirebaseUser user = await auth.currentUser(); - user = await user.linkWithCredential(credential); - verifyUser(user); + final FirebaseUser user = await auth.currentUser(); + final AuthResult result = await user.linkWithCredential(credential); + verifyAuthResult(result); expect( log, [ @@ -444,8 +479,8 @@ void main() { idToken: kMockIdToken, accessToken: kMockAccessToken, ); - final FirebaseUser user = await auth.signInWithCredential(credential); - verifyUser(user); + final AuthResult result = await auth.signInWithCredential(credential); + verifyAuthResult(result); expect( log, [ @@ -469,7 +504,8 @@ void main() { verificationId: kMockVerificationId, smsCode: kMockSmsCode, ); - await auth.signInWithCredential(credential); + final AuthResult result = await auth.signInWithCredential(credential); + verifyAuthResult(result); expect(log, [ isMethodCall('signInWithCredential', arguments: { 'app': auth.app.name, @@ -508,7 +544,9 @@ void main() { email: kMockEmail, password: kMockPassword, ); - await user.reauthenticateWithCredential(credential); + final AuthResult result = + await user.reauthenticateWithCredential(credential); + verifyAuthResult(result); expect( log, [ @@ -533,7 +571,9 @@ void main() { idToken: kMockIdToken, accessToken: kMockAccessToken, ); - await user.reauthenticateWithCredential(credential); + final AuthResult result = + await user.reauthenticateWithCredential(credential); + verifyAuthResult(result); expect( log, [ @@ -558,7 +598,9 @@ void main() { final AuthCredential credential = FacebookAuthProvider.getCredential( accessToken: kMockAccessToken, ); - await user.reauthenticateWithCredential(credential); + final AuthResult result = + await user.reauthenticateWithCredential(credential); + verifyAuthResult(result); expect( log, [ @@ -583,7 +625,9 @@ void main() { authToken: kMockAuthToken, authTokenSecret: kMockAuthTokenSecret, ); - await user.reauthenticateWithCredential(credential); + final AuthResult result = + await user.reauthenticateWithCredential(credential); + verifyAuthResult(result); expect( log, [ @@ -608,7 +652,9 @@ void main() { final AuthCredential credential = GithubAuthProvider.getCredential( token: kMockGithubToken, ); - await user.reauthenticateWithCredential(credential); + final AuthResult result = + await user.reauthenticateWithCredential(credential); + verifyAuthResult(result); expect( log, [ @@ -631,9 +677,9 @@ void main() { idToken: kMockIdToken, accessToken: kMockAccessToken, ); - FirebaseUser user = await auth.currentUser(); - user = await user.linkWithCredential(credential); - verifyUser(user); + final FirebaseUser user = await auth.currentUser(); + final AuthResult result = await user.linkWithCredential(credential); + verifyAuthResult(result); expect( log, [ @@ -662,9 +708,9 @@ void main() { final AuthCredential credential = FacebookAuthProvider.getCredential( accessToken: kMockAccessToken, ); - FirebaseUser user = await auth.currentUser(); - user = await user.linkWithCredential(credential); - verifyUser(user); + final FirebaseUser user = await auth.currentUser(); + final AuthResult result = await user.linkWithCredential(credential); + verifyAuthResult(result); expect( log, [ @@ -692,8 +738,8 @@ void main() { final AuthCredential credential = FacebookAuthProvider.getCredential( accessToken: kMockAccessToken, ); - final FirebaseUser user = await auth.signInWithCredential(credential); - verifyUser(user); + final AuthResult result = await auth.signInWithCredential(credential); + verifyAuthResult(result); expect( log, [ @@ -716,9 +762,9 @@ void main() { authToken: kMockAuthToken, authTokenSecret: kMockAuthTokenSecret, ); - FirebaseUser user = await auth.currentUser(); - user = await user.linkWithCredential(credential); - verifyUser(user); + final FirebaseUser user = await auth.currentUser(); + final AuthResult result = await user.linkWithCredential(credential); + verifyAuthResult(result); expect( log, [ @@ -748,8 +794,8 @@ void main() { authToken: kMockAuthToken, authTokenSecret: kMockAuthTokenSecret, ); - final FirebaseUser user = await auth.signInWithCredential(credential); - verifyUser(user); + final AuthResult result = await auth.signInWithCredential(credential); + verifyAuthResult(result); expect( log, [ @@ -772,9 +818,9 @@ void main() { final AuthCredential credential = GithubAuthProvider.getCredential( token: kMockGithubToken, ); - FirebaseUser user = await auth.currentUser(); - user = await user.linkWithCredential(credential); - verifyUser(user); + final FirebaseUser user = await auth.currentUser(); + final AuthResult result = await user.linkWithCredential(credential); + verifyAuthResult(result); expect( log, [ @@ -802,8 +848,8 @@ void main() { final AuthCredential credential = GithubAuthProvider.getCredential( token: kMockGithubToken, ); - final FirebaseUser user = await auth.signInWithCredential(credential); - verifyUser(user); + final AuthResult result = await auth.signInWithCredential(credential); + verifyAuthResult(result); expect( log, [ @@ -826,9 +872,9 @@ void main() { email: kMockEmail, password: kMockPassword, ); - FirebaseUser user = await auth.currentUser(); - user = await user.linkWithCredential(credential); - verifyUser(user); + final FirebaseUser user = await auth.currentUser(); + final AuthResult result = await user.linkWithCredential(credential); + verifyAuthResult(result); expect( log, [ @@ -1122,9 +1168,9 @@ void main() { }); test('signInWithCustomToken', () async { - final FirebaseUser user = + final AuthResult result = await auth.signInWithCustomToken(token: kMockCustomToken); - verifyUser(user); + verifyAuthResult(result); expect( log, [ @@ -1163,7 +1209,7 @@ void main() { await Future.delayed(const Duration(seconds: 0)); await simulateEvent(null); - await simulateEvent(mockFirebaseUser()); + await simulateEvent(kMockUser); final FirebaseUser user1 = await events.remove(); expect(user1, isNull); @@ -1211,26 +1257,6 @@ void main() { }); } -Map mockFirebaseUser( - {String providerId = kMockProviderId, - String uid = kMockUid, - String displayName = kMockDisplayName, - String photoUrl = kMockPhotoUrl, - String email = kMockEmail}) => - { - 'isAnonymous': true, - 'isEmailVerified': false, - 'providerData': >[ - { - 'providerId': providerId, - 'uid': uid, - 'displayName': displayName, - 'photoUrl': photoUrl, - 'email': email, - }, - ], - }; - /// Queue whose remove operation is asynchronous, awaiting a corresponding add. class AsyncQueue { Map> _completers = >{};