From 6876fcc8ef83339456c748baa96cdf9a2f204874 Mon Sep 17 00:00:00 2001 From: Razvan Cristian Lung Date: Sat, 27 Jul 2019 10:29:22 +0300 Subject: [PATCH 01/10] [firebase_auth] fix inconsistency between iOS and Android on `FirebaseUserMetadata` --- packages/firebase_auth/CHANGELOG.md | 4 ++++ .../firebase_auth/example/test/firebase_auth.dart | 11 +++++++++++ .../firebase_auth/ios/Classes/FirebaseAuthPlugin.m | 6 +++--- packages/firebase_auth/pubspec.yaml | 2 +- 4 files changed, 19 insertions(+), 4 deletions(-) diff --git a/packages/firebase_auth/CHANGELOG.md b/packages/firebase_auth/CHANGELOG.md index 1728a08e358f..8ec9949c8a7e 100644 --- a/packages/firebase_auth/CHANGELOG.md +++ b/packages/firebase_auth/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.11.1+13 + +* Fix inconsistency between iOS and Android `FirebaseUserMetadata`. On iOS `creationTimestamp` and `lastSignInTimestamp` were return in seconds and on Android in milliseconds. Now both platforms return those values in milliseconds. + ## 0.11.1+12 * Update google-services Android gradle plugin to 4.3.0 in documentation and examples. diff --git a/packages/firebase_auth/example/test/firebase_auth.dart b/packages/firebase_auth/example/test/firebase_auth.dart index 2c4f4c8ede32..b07bd16c15f1 100644 --- a/packages/firebase_auth/example/test/firebase_auth.dart +++ b/packages/firebase_auth/example/test/firebase_auth.dart @@ -12,13 +12,24 @@ void main() { enableFlutterDriverExtension(handler: (_) => completer.future); tearDownAll(() => completer.complete(null)); + setUp(() async { + final FirebaseAuth auth = FirebaseAuth.instance; + final FirebaseUser currentUser = await auth.currentUser(); + if (currentUser != null) { + await auth.signOut(); + } + }); + group('$FirebaseAuth', () { final FirebaseAuth auth = FirebaseAuth.instance; test('signInAnonymously', () async { + final int start = DateTime.now().millisecondsSinceEpoch; final FirebaseUser user = await auth.signInAnonymously(); expect(user.uid, isNotNull); expect(user.isAnonymous, isTrue); + expect(user.metadata.lastSignInTimestamp, greaterThan(start)); + expect(user.metadata.creationTimestamp, greaterThan(start)); }); test('isSignInWithEmailLink', () async { diff --git a/packages/firebase_auth/ios/Classes/FirebaseAuthPlugin.m b/packages/firebase_auth/ios/Classes/FirebaseAuthPlugin.m index bbe6f8c4f283..c305f78de078 100644 --- a/packages/firebase_auth/ios/Classes/FirebaseAuthPlugin.m +++ b/packages/firebase_auth/ios/Classes/FirebaseAuthPlugin.m @@ -348,12 +348,12 @@ - (NSMutableDictionary *)dictionaryFromUser:(FIRUser *)user { [providerData addObject:toDictionary(userInfo)]; } - long creationDate = [user.metadata.creationDate timeIntervalSince1970]; - long lastSignInDate = [user.metadata.lastSignInDate timeIntervalSince1970]; + long creationDate = [user.metadata.creationDate timeIntervalSince1970] * 1000; + long lastSignInDate = [user.metadata.lastSignInDate timeIntervalSince1970] * 1000; 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; diff --git a/packages/firebase_auth/pubspec.yaml b/packages/firebase_auth/pubspec.yaml index 238c1d38128d..e41e3969518e 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.11.1+13" flutter: plugin: From 802715a9c137d30ca517c8b57771df7eda9ae84c Mon Sep 17 00:00:00 2001 From: Razvan Cristian Lung Date: Sat, 27 Jul 2019 11:38:57 +0300 Subject: [PATCH 02/10] test: modify testing logic --- .../example/test/firebase_auth.dart | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/packages/firebase_auth/example/test/firebase_auth.dart b/packages/firebase_auth/example/test/firebase_auth.dart index b07bd16c15f1..500b80f82175 100644 --- a/packages/firebase_auth/example/test/firebase_auth.dart +++ b/packages/firebase_auth/example/test/firebase_auth.dart @@ -3,33 +3,25 @@ // BSD-style license that can be found in the LICENSE file. import 'dart:async'; + +import 'package:firebase_auth/firebase_auth.dart'; import 'package:flutter_driver/driver_extension.dart'; import 'package:flutter_test/flutter_test.dart'; -import 'package:firebase_auth/firebase_auth.dart'; void main() { final Completer completer = Completer(); enableFlutterDriverExtension(handler: (_) => completer.future); tearDownAll(() => completer.complete(null)); - setUp(() async { - final FirebaseAuth auth = FirebaseAuth.instance; - final FirebaseUser currentUser = await auth.currentUser(); - if (currentUser != null) { - await auth.signOut(); - } - }); - group('$FirebaseAuth', () { final FirebaseAuth auth = FirebaseAuth.instance; test('signInAnonymously', () async { - final int start = DateTime.now().millisecondsSinceEpoch; final FirebaseUser user = await auth.signInAnonymously(); expect(user.uid, isNotNull); expect(user.isAnonymous, isTrue); - expect(user.metadata.lastSignInTimestamp, greaterThan(start)); - expect(user.metadata.creationTimestamp, greaterThan(start)); + expect('${user.metadata.lastSignInTimestamp}'.length, greaterThan(12)); + expect('${user.metadata.creationTimestamp}'.length, greaterThan(12)); }); test('isSignInWithEmailLink', () async { From 5172d2919e2ae4237543820a9909b6fcc54d705a Mon Sep 17 00:00:00 2001 From: Collin Jackson Date: Sat, 27 Jul 2019 11:52:55 -0700 Subject: [PATCH 03/10] Update to `creationTime` and `lastSignInTime` --- packages/firebase_auth/CHANGELOG.md | 8 ++++++-- .../firebase_auth/example/test/firebase_auth.dart | 12 ++++++++++-- packages/firebase_auth/lib/src/user_metadata.dart | 10 ++++++++-- packages/firebase_auth/pubspec.yaml | 2 +- packages/firebase_auth/test/firebase_auth_test.dart | 6 ++++++ 5 files changed, 31 insertions(+), 7 deletions(-) diff --git a/packages/firebase_auth/CHANGELOG.md b/packages/firebase_auth/CHANGELOG.md index 8ec9949c8a7e..2cc333868cb2 100644 --- a/packages/firebase_auth/CHANGELOG.md +++ b/packages/firebase_auth/CHANGELOG.md @@ -1,6 +1,10 @@ -## 0.11.1+13 +## 0.12.0 -* Fix inconsistency between iOS and Android `FirebaseUserMetadata`. On iOS `creationTimestamp` and `lastSignInTimestamp` were return in seconds and on Android in milliseconds. Now both platforms return those values in milliseconds. +* **Breaking change**: Replace `FirebaseUserMetadata.creationTimestamp` and + `FirebaseUserMetadata.lastSignInTimestamp` with `creationTime` and `lastSignInTime`. + Previously on iOS `creationTimestamp` and `lastSignInTimestamp` returned in + seconds and on Android in milliseconds. Now, both platforms provide values as a + `DateTime`. ## 0.11.1+12 diff --git a/packages/firebase_auth/example/test/firebase_auth.dart b/packages/firebase_auth/example/test/firebase_auth.dart index 500b80f82175..9c18e6bf64db 100644 --- a/packages/firebase_auth/example/test/firebase_auth.dart +++ b/packages/firebase_auth/example/test/firebase_auth.dart @@ -20,8 +20,16 @@ void main() { final FirebaseUser user = await auth.signInAnonymously(); expect(user.uid, isNotNull); expect(user.isAnonymous, isTrue); - expect('${user.metadata.lastSignInTimestamp}'.length, greaterThan(12)); - expect('${user.metadata.creationTimestamp}'.length, greaterThan(12)); + expect(user.metadata.creationTime.isAfter(DateTime(2018, 1, 1)), isTrue); + expect(user.metadata.creationTime.isBefore(DateTime.now()), isTrue); + await auth.signOut(); + final FirebaseUser user2 = await auth.signInAnonymously(); + expect(user2.uid, isNot(equals(user.uid))); + expect(user2.metadata.creationTime.isBefore(user.metadata.creationTime), isFalse); + expect(user2.metadata.lastSignInTime.isAfter(DateTime(2018, 1, 1)), isTrue); + expect(user2.metadata.lastSignInTime + .isBefore(DateTime.now().add(Duration(days: 1))), + isTrue); }); test('isSignInWithEmailLink', () async { diff --git a/packages/firebase_auth/lib/src/user_metadata.dart b/packages/firebase_auth/lib/src/user_metadata.dart index 66c1fedf4911..79910709a584 100644 --- a/packages/firebase_auth/lib/src/user_metadata.dart +++ b/packages/firebase_auth/lib/src/user_metadata.dart @@ -10,7 +10,13 @@ class FirebaseUserMetadata { final Map _data; - int get creationTimestamp => _data['creationTimestamp']; + /// The timestamp at which this account was created as dictated by the server clock. + DateTime get creationTime => + DateTime.fromMillisecondsSinceEpoch(_data['creationTimestamp']); - int get lastSignInTimestamp => _data['lastSignInTimestamp']; + /// The last sign-in timestamp as dictated by the server clock. + /// + /// This is only accurate up to a granularity of 2 minutes for consecutive sign-in attempts. + DateTime get lastSignInTime => + DateTime.fromMillisecondsSinceEpoch(_data['lastSignInTimestamp']); } diff --git a/packages/firebase_auth/pubspec.yaml b/packages/firebase_auth/pubspec.yaml index e41e3969518e..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+13" +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..61fd8143d296 100755 --- a/packages/firebase_auth/test/firebase_auth_test.dart +++ b/packages/firebase_auth/test/firebase_auth_test.dart @@ -25,6 +25,8 @@ const String kMockPhoneNumber = '5555555555'; const String kMockVerificationId = '12345'; const String kMockSmsCode = '123456'; const String kMockLanguage = 'en'; +final DateTime kMockCreationTime = DateTime(2019, 1, 1); +final DateTime kMockLastSignInTime = DateTime.now().subtract(Duration(days: 1)); void main() { group('$FirebaseAuth', () { @@ -1229,6 +1231,10 @@ Map mockFirebaseUser( 'email': email, }, ], + 'metadata': { + 'creationTimestamp': kMockCreationTime.millisecondsSinceEpoch, + 'lastSignInTimestamp': kMockLastSignInTime.millisecondsSinceEpoch, + }, }; /// Queue whose remove operation is asynchronous, awaiting a corresponding add. From 495c12ad0fa09f1f630a4e87f14f05e348bf70b7 Mon Sep 17 00:00:00 2001 From: Collin Jackson Date: Sat, 27 Jul 2019 11:59:01 -0700 Subject: [PATCH 04/10] Simplify driver test --- packages/firebase_auth/example/test/firebase_auth.dart | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/packages/firebase_auth/example/test/firebase_auth.dart b/packages/firebase_auth/example/test/firebase_auth.dart index 9c18e6bf64db..4187a2fd9741 100644 --- a/packages/firebase_auth/example/test/firebase_auth.dart +++ b/packages/firebase_auth/example/test/firebase_auth.dart @@ -26,10 +26,7 @@ void main() { final FirebaseUser user2 = await auth.signInAnonymously(); expect(user2.uid, isNot(equals(user.uid))); expect(user2.metadata.creationTime.isBefore(user.metadata.creationTime), isFalse); - expect(user2.metadata.lastSignInTime.isAfter(DateTime(2018, 1, 1)), isTrue); - expect(user2.metadata.lastSignInTime - .isBefore(DateTime.now().add(Duration(days: 1))), - isTrue); + expect(user2.metadata.lastSignInTime, equals(user2.metadata.creationTime)); }); test('isSignInWithEmailLink', () async { From f60d45891b38745c502dd6c6b6a27ecd4e10d016 Mon Sep 17 00:00:00 2001 From: Collin Jackson Date: Sat, 27 Jul 2019 12:04:39 -0700 Subject: [PATCH 05/10] Fix lints --- packages/firebase_auth/example/test/firebase_auth.dart | 6 ++++-- packages/firebase_auth/test/firebase_auth_test.dart | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/packages/firebase_auth/example/test/firebase_auth.dart b/packages/firebase_auth/example/test/firebase_auth.dart index 4187a2fd9741..72d56a7f6bd0 100644 --- a/packages/firebase_auth/example/test/firebase_auth.dart +++ b/packages/firebase_auth/example/test/firebase_auth.dart @@ -25,8 +25,10 @@ void main() { await auth.signOut(); final FirebaseUser user2 = await auth.signInAnonymously(); expect(user2.uid, isNot(equals(user.uid))); - expect(user2.metadata.creationTime.isBefore(user.metadata.creationTime), isFalse); - expect(user2.metadata.lastSignInTime, equals(user2.metadata.creationTime)); + expect(user2.metadata.creationTime.isBefore(user.metadata.creationTime), + isFalse); + expect( + user2.metadata.lastSignInTime, equals(user2.metadata.creationTime)); }); test('isSignInWithEmailLink', () async { diff --git a/packages/firebase_auth/test/firebase_auth_test.dart b/packages/firebase_auth/test/firebase_auth_test.dart index 61fd8143d296..c69026a20ab8 100755 --- a/packages/firebase_auth/test/firebase_auth_test.dart +++ b/packages/firebase_auth/test/firebase_auth_test.dart @@ -26,7 +26,7 @@ const String kMockVerificationId = '12345'; const String kMockSmsCode = '123456'; const String kMockLanguage = 'en'; final DateTime kMockCreationTime = DateTime(2019, 1, 1); -final DateTime kMockLastSignInTime = DateTime.now().subtract(Duration(days: 1)); +final DateTime kMockLastSignInTime = DateTime.now().subtract(const Duration(days: 1)); void main() { group('$FirebaseAuth', () { @@ -1231,7 +1231,7 @@ Map mockFirebaseUser( 'email': email, }, ], - 'metadata': { + 'metadata': { 'creationTimestamp': kMockCreationTime.millisecondsSinceEpoch, 'lastSignInTimestamp': kMockLastSignInTime.millisecondsSinceEpoch, }, From d7243dcc42b4f0ebf21c6218155ce6008f2e0f28 Mon Sep 17 00:00:00 2001 From: Collin Jackson Date: Sat, 27 Jul 2019 12:20:07 -0700 Subject: [PATCH 06/10] fix format --- packages/firebase_auth/test/firebase_auth_test.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/firebase_auth/test/firebase_auth_test.dart b/packages/firebase_auth/test/firebase_auth_test.dart index c69026a20ab8..c5a755f39a02 100755 --- a/packages/firebase_auth/test/firebase_auth_test.dart +++ b/packages/firebase_auth/test/firebase_auth_test.dart @@ -26,7 +26,8 @@ const String kMockVerificationId = '12345'; const String kMockSmsCode = '123456'; const String kMockLanguage = 'en'; final DateTime kMockCreationTime = DateTime(2019, 1, 1); -final DateTime kMockLastSignInTime = DateTime.now().subtract(const Duration(days: 1)); +final DateTime kMockLastSignInTime = + DateTime.now().subtract(const Duration(days: 1)); void main() { group('$FirebaseAuth', () { From 6be1216bd982704c1a959b713e789c43b07120eb Mon Sep 17 00:00:00 2001 From: Collin Jackson Date: Sat, 27 Jul 2019 14:55:04 -0700 Subject: [PATCH 07/10] Update doc comment --- packages/firebase_auth/lib/src/user_metadata.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/firebase_auth/lib/src/user_metadata.dart b/packages/firebase_auth/lib/src/user_metadata.dart index 79910709a584..293d294b6ecb 100644 --- a/packages/firebase_auth/lib/src/user_metadata.dart +++ b/packages/firebase_auth/lib/src/user_metadata.dart @@ -10,11 +10,11 @@ class FirebaseUserMetadata { final Map _data; - /// The timestamp at which this account was created as dictated by the server clock. + /// When this account was created as dictated by the server clock. DateTime get creationTime => DateTime.fromMillisecondsSinceEpoch(_data['creationTimestamp']); - /// The last sign-in timestamp as dictated by the server clock. + /// When the user last signed in as dictated by the server clock. /// /// This is only accurate up to a granularity of 2 minutes for consecutive sign-in attempts. DateTime get lastSignInTime => From ff497b0dbc2f0b90cc9fd0075fe751b6e0e968bb Mon Sep 17 00:00:00 2001 From: Collin Jackson Date: Sat, 27 Jul 2019 17:47:54 -0700 Subject: [PATCH 08/10] More unit testing --- packages/firebase_auth/test/firebase_auth_test.dart | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/firebase_auth/test/firebase_auth_test.dart b/packages/firebase_auth/test/firebase_auth_test.dart index c5a755f39a02..9418c1b6c870 100755 --- a/packages/firebase_auth/test/firebase_auth_test.dart +++ b/packages/firebase_auth/test/firebase_auth_test.dart @@ -82,6 +82,8 @@ void main() { expect(userInfo.displayName, kMockDisplayName); expect(userInfo.photoUrl, kMockPhotoUrl); expect(userInfo.email, kMockEmail); + expect(user.metadata.creationTime, equals(kMockCreationTime)); + expect(user.metadata.lastSignInTime, equals(kMockLastSignInTime)); } test('currentUser', () async { From 0a22e3ca2767f7ff8d95333fc9067a596674b5ec Mon Sep 17 00:00:00 2001 From: Collin Jackson Date: Sat, 27 Jul 2019 19:04:20 -0700 Subject: [PATCH 09/10] fix test --- .../firebase_auth/test/firebase_auth_test.dart | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/packages/firebase_auth/test/firebase_auth_test.dart b/packages/firebase_auth/test/firebase_auth_test.dart index 9418c1b6c870..ccb2f3e75c7f 100755 --- a/packages/firebase_auth/test/firebase_auth_test.dart +++ b/packages/firebase_auth/test/firebase_auth_test.dart @@ -25,9 +25,9 @@ const String kMockPhoneNumber = '5555555555'; const String kMockVerificationId = '12345'; const String kMockSmsCode = '123456'; const String kMockLanguage = 'en'; -final DateTime kMockCreationTime = DateTime(2019, 1, 1); -final DateTime kMockLastSignInTime = - DateTime.now().subtract(const Duration(days: 1)); +final int kMockCreationTimestamp = DateTime(2019, 1, 1).millisecondsSinceEpoch; +final int kMockLastSignInTimestamp = + DateTime.now().subtract(const Duration(days: 1)).millisecondsSinceEpoch; void main() { group('$FirebaseAuth', () { @@ -82,8 +82,10 @@ void main() { expect(userInfo.displayName, kMockDisplayName); expect(userInfo.photoUrl, kMockPhotoUrl); expect(userInfo.email, kMockEmail); - expect(user.metadata.creationTime, equals(kMockCreationTime)); - expect(user.metadata.lastSignInTime, equals(kMockLastSignInTime)); + expect(user.metadata.creationTime.millisecondsSinceEpoch, + kMockCreationTimestamp); + expect(user.metadata.lastSignInTime.millisecondsSinceEpoch, + kMockLastSignInTimestamp); } test('currentUser', () async { @@ -1234,10 +1236,8 @@ Map mockFirebaseUser( 'email': email, }, ], - 'metadata': { - 'creationTimestamp': kMockCreationTime.millisecondsSinceEpoch, - 'lastSignInTimestamp': kMockLastSignInTime.millisecondsSinceEpoch, - }, + 'creationTimestamp': kMockCreationTimestamp, + 'lastSignInTimestamp': kMockLastSignInTimestamp, }; /// Queue whose remove operation is asynchronous, awaiting a corresponding add. From 9bab4cb4b4f51ee57be34bcde3b3443dc18ff705 Mon Sep 17 00:00:00 2001 From: Collin Jackson Date: Sat, 27 Jul 2019 19:31:29 -0700 Subject: [PATCH 10/10] Fix analyzer warnings --- packages/firebase_auth/test/firebase_auth_test.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/firebase_auth/test/firebase_auth_test.dart b/packages/firebase_auth/test/firebase_auth_test.dart index 478f1a6347fa..9acff316492d 100755 --- a/packages/firebase_auth/test/firebase_auth_test.dart +++ b/packages/firebase_auth/test/firebase_auth_test.dart @@ -28,7 +28,7 @@ const String kMockLanguage = 'en'; final int kMockCreationTimestamp = DateTime(2019, 1, 1).millisecondsSinceEpoch; final int kMockLastSignInTimestamp = DateTime.now().subtract(const Duration(days: 1)).millisecondsSinceEpoch; -const Map kMockUser = { +final Map kMockUser = { 'isAnonymous': true, 'isEmailVerified': false, 'creationTimestamp': kMockCreationTimestamp,