fix logout issue

This commit is contained in:
tzw
2024-02-23 17:05:51 +06:30
parent 421bcf0a11
commit 5496bae681
23 changed files with 144 additions and 84 deletions

View File

@@ -12,6 +12,8 @@ import 'package:fcs/helpers/firebase_helper.dart';
import 'package:firebase_auth/firebase_auth.dart' as fb;
import 'package:logging/logging.dart';
import '../services/services.dart';
class AuthFb {
final log = Logger('AuthFb');
@@ -21,6 +23,10 @@ class AuthFb {
late StreamController<User?> controller;
static final fb.FirebaseAuth _fb = fb.FirebaseAuth.instance;
static String _verificationId = '';
static bool _logIn = false;
StreamSubscription<DocumentSnapshot>? userListener;
StreamSubscription<DocumentSnapshot>? userAuthListener;
Future<fcs.AuthResult> sendSmsCodeToPhoneNumber(String phoneNumber) {
Completer<fcs.AuthResult> completer = Completer();
@@ -99,9 +105,13 @@ class AuthFb {
return Future.value(fcs.AuthResult(authStatus: AuthStatus.AUTH_VERIFIED));
}
Future<void> signout() async {
if (userListener != null) await userListener!.cancel();
return _fb.signOut();
Future<void> signoutStart() async {
await userListener?.cancel();
await userAuthListener?.cancel();
}
Future<void> signoutEnd() async {
await _fb.signOut();
}
Future<void> _addUserToStream({bool refreshIdToken = false}) async {
@@ -111,7 +121,6 @@ class AuthFb {
await getClaims(refreshIdToken: refreshIdToken);
log.info("Claims:$claims");
if (claims == null) return;
String? cid = claims["cid"];
User? user;
@@ -123,6 +132,11 @@ class AuthFb {
return;
}
loadUserClaim(claims, user);
controller.add(user);
}
loadUserClaim(Map claims, User user) {
// add privileges
String? privileges = claims["pr"];
if (privileges != null && privileges != "") {
@@ -130,7 +144,6 @@ class AuthFb {
} else {
user.privileges = [];
}
controller.add(user);
}
Future<User?> _getUserFromFirestore(String userID) async {
@@ -205,13 +218,12 @@ class AuthFb {
fb.User? firebaseUser = _fb.currentUser;
if (firebaseUser == null) return null;
Map? claims = await getClaims();
if (claims == null) return null;
String cid = claims["cid"];
return cid;
}
Future<void> _startUserListener() async {
if (userListener != null) userListener!.cancel();
_startAuthListener();
String? _userID = await _getCurrentUserID();
if (_userID == null) {
return;
@@ -221,6 +233,7 @@ class AuthFb {
.collection(user_collection)
.doc(_userID)
.snapshots();
userListener?.cancel();
userListener = snapshot.listen((snap) async {
User user = User.fromMap(snap.data() as Map<String, dynamic>, snap.id);
@@ -229,14 +242,12 @@ class AuthFb {
userListener?.cancel();
return;
}
if (!_logIn) return;
try {
// get privilege from claim
fb.IdTokenResult idToken = await firebaseUser.getIdTokenResult(true);
String? privileges = idToken.claims?["pr"] ?? '';
if (privileges != null && privileges != "") {
user.privileges = privileges.split(":").toList();
}
Map<dynamic, dynamic> claims = await getClaims(refreshIdToken: true);
loadUserClaim(claims, user);
controller.add(user);
} catch (e) {
controller.add(null);
@@ -244,14 +255,47 @@ class AuthFb {
});
}
StreamSubscription<DocumentSnapshot>? userListener;
Future<void> _startAuthListener() async {
String? authId = _fb.currentUser?.uid;
if (authId == null) return;
Stream<DocumentSnapshot> snapshot = FirebaseFirestore.instance
.collection(authCollection)
.doc(authId)
.snapshots();
userAuthListener?.cancel();
userAuthListener = snapshot.listen((snap) async {
if (snap.exists) {
Map<String, dynamic> map = snap.data() as Map<String, dynamic>;
String userID = map['user_id'] ?? "";
User? user = await Services.instance.userService.getUser(userID);
if (user == null) return;
if (_fb.currentUser == null) {
userAuthListener?.cancel();
return;
}
Map<dynamic, dynamic> claims = await getClaims(refreshIdToken: true);
loadUserClaim(claims, user);
log.info("_startAuthListener: $user");
if (_logIn) {
controller.add(user);
}
}
});
}
Stream<User?> user() {
// ignore: close_sinks
StreamSubscription<fb.User?>? authListener;
Future<void> _start() async {
await authListener?.cancel();
authListener = _fb.authStateChanges().listen((firebaseUser) {
authListener = _fb.authStateChanges().listen((firebaseUser) async {
_logIn = firebaseUser != null;
if (firebaseUser == null) {
controller.add(null);
} else {

View File

@@ -85,4 +85,29 @@ class UserDataProvider {
return await requestAPI("/enable_user", "PUT",
payload: {"id": userID, "enabled": enabled}, token: await getToken());
}
Future<User?> getUser(String userID) async {
if (userID == "") return null;
String path = "/$user_collection";
try {
var snap = await FirebaseFirestore.instance
.collection(path)
.doc(userID)
.get(const GetOptions(source: Source.server));
if (snap.data() == null) return null;
Map<String, dynamic>? data = snap.data() as Map<String, dynamic>;
if (data['delete_time'] == 0) {
User user = User.fromMap(data, snap.id);
return user;
} else {
return null;
}
} catch (e) {
log.warning("Error!! $e");
}
return null;
}
}

View File

@@ -25,11 +25,6 @@ class AuthServiceImp implements AuthService {
return authFb.signInWithPhoneNumber(smsCode);
}
@override
Future<void> signout() {
return authFb.signout();
}
@override
Stream<User?> getUserStream() {
return authFb.user();
@@ -64,4 +59,14 @@ class AuthServiceImp implements AuthService {
Future<void> updatePreferredCurrency(String currency) {
return authFb.updatePreferredCurrency(currency);
}
@override
Future<void> signoutEnd() {
return authFb.signoutEnd();
}
@override
Future<void> signoutStart() {
return authFb.signoutStart();
}
}

View File

@@ -5,7 +5,8 @@ import 'package:fcs/domain/entities/user.dart';
abstract class AuthService {
Future<AuthResult> sendSmsCodeToPhoneNumber(String phoneNumber);
Future<AuthResult> signInWithSmsCode(String smsCode);
Future<void> signout();
Future<void> signoutStart();
Future<void> signoutEnd();
Future<void> signup(String userName);
Future<void> joinInvite(String userName);
Future<void> updateProfileName(String newUserName);

View File

@@ -52,4 +52,9 @@ class UserServiceImp implements UserService {
Future<void> enableUser(String userID, bool enabled) {
return userDataProvider.enableUser(userID, enabled);
}
@override
Future<User?> getUser(String userID) {
return userDataProvider.getUser(userID);
}
}

View File

@@ -9,4 +9,5 @@ abstract class UserService {
Future<void> uploadMsgToken(String token);
Future<void> removeMsgToken(String token);
Future<void> enableUser(String userID, bool enabled);
Future<User?> getUser(String userID);
}