检查用户是否在FIrestore上

时间:2019-11-06 16:54:13

标签: firebase flutter dart google-cloud-firestore

我具有使用SignInWithGogle来登录/注册用户的功能

 void _signInWithGoogle() async {
    final GoogleSignInAccount googleUser = await _googleSignIn.signIn();
    final GoogleSignInAuthentication googleAuth =
        await googleUser.authentication;
    final AuthCredential credential = GoogleAuthProvider.getCredential(
      accessToken: googleAuth.accessToken,
      idToken: googleAuth.idToken,
    );
    final FirebaseUser user = (await _auth.signInWithCredential(credential)).user;
    assert(user.email != null);
    assert(user.displayName != null);
    assert(!user.isAnonymous);
    assert(await user.getIdToken() != null);

    final FirebaseUser currentUser = await _auth.currentUser();
    assert(user.uid == currentUser.uid);
    print('user email here $user.email');
    setState(() {
      if (user != null) {
        _success = true;
        _userID = user.uid;
        final userToSubmit = User(
            email: user.email,
            id: user.uid,
            name: user.displayName,
            owner: false,
            favorites: null);
        print('USER ID USER ID USER ID ${user.uid}');
        DocumentReference dbRef =
            Firestore.instance.collection('users').document(user.uid);
        dbRef.get().then((value) {
          print('VALUE EXISTS? ${value.exists} y VALUE $value');
          value.exists ?
            _goToHomeScreen(user)
          :
          dbRef
              .collection('prf')
              .document('profile')
              .setData(userToSubmit.toJson())
              .then(_goToHomeScreen(user));
        });
      } else {
        _success = false;
      }
    });
  }

问题是,当用户注销并再次登录时,它会设置新数据,并且用户丢失了自己喜欢的所有内容,依此类推……我认为检查文档是否存在应该可以解决问题,尽管文档是否存在返回false。 这是我正在谈论的代码片段

DocumentReference dbRef =
                Firestore.instance.collection('users').document(user.uid);
            dbRef.get().then((value) {
              print('VALUE EXISTS? ${value.exists} y VALUE $value');
              value.exists ?
                _goToHomeScreen(user)
              :
              dbRef
                  .collection('prf')
                  .document('profile')
                  .setData(userToSubmit.toJson())
                  .then(_goToHomeScreen(user));
            });
          }

为什么即使user.uid和文档存在也返回false?我在做什么错了?

2 个答案:

答案 0 :(得分:0)

我实现的最终解决方案是:

 FirebaseUser firebaseUser;
    try {
      firebaseUser = (await FirebaseAuth.instance.signInWithCredential(credential)).user;
    } catch(e) {
      print(e.toString());
    } finally {
      final userToSubmit = User(
          email: firebaseUser.email,
          id: firebaseUser.uid,
          name: firebaseUser.displayName,
          owner: false,
          restauranteAdded: false);
      DocumentReference dbRef =
      Firestore.instance.collection('users').document(firebaseUser.uid).collection('nameOfTheCollection').document('documentName');

      dbRef.get().then((data) {
        data.exists ? _goToHomeScreen(user) :  
          _createUser();
      });

通过这种方式,我检查用户文档是否存在于Firestore数据库中,如果不存在,它将创建该文档。

答案 1 :(得分:-1)

发生了很多事情。通常,您不会使用state方法更新任何setState()对象。 setState用于告诉窗口小部件某些state已更改-并且与更改一起被称为 ,但是在这里,您只是在检查文档是否存在,没有任何变化,这是不需要的。

而且看来您根本没有真正返回user对象,因此在我阅读本文时,此代码将始终返回false

  1. 您应该在此处完全删除setState(执行此操作不需要)
  2. 运行登录方法,该方法返回您要执行操作的用户对象。
  3. 一旦您知道已登录的用户(即带有已登录用户的uid),便可以访问数据库

这里是尝试的选项:

//Create a User class so that you don't have to call FireBase in your methods.
class User {
  User({
    @required this.uid,
    this.email,
    this.displayName,
  });
  final String uid;
  final String email;//these are whatever you want
  final String displayName;
}

//put sign in methods into an abstract class. Don't have to, but keeps code flexible if you don't stay with firebase
abstract class AuthBase {
 //add in other signin methods as needed
  Future<User> signInWithGoogle();

}

//Implement AuthBase in class Auth
class Auth implements AuthBase {
  final FirebaseAuth _firebaseAuth = FirebaseAuth.instance;

//Get a User from Firebase User
  User _userFromFirebase(FirebaseUser user) {
    if (user == null) {
      return null;
    }
    return User(
      uid: user.uid,
      displayName: user.displayName,
      email: user.email,
    );
  }

//your signinWithGoogle method
Future<User> signInWithGoogle() async {
  //where User is the class you've created
  GoogleSignIn googleSignIn = GoogleSignIn();
  GoogleSignInAccount googleUser = await googleSignIn.signIn();

  if (googleUser != null) {
    GoogleSignInAuthentication googleAuth = await googleUser.authentication;
    if (googleAuth.idToken != null && googleAuth.accessToken != null) {
      final authResult = await _firebaseAuth.signInWithCredential( //await your instance of FirebaseAuth
        GoogleAuthProvider.getCredential(
          idToken: googleAuth.idToken,
          accessToken: googleAuth.accessToken,
        ),
      );

      return _userFromFirebase(authResult.user); //your signed in firebase user that you can do stuff with uid, email, displayname, etc.
    } else {
      throw PlatformException(
        code: 'ERROR_MISSING_GOOGLE_AUTH_TOKEN',
        message: '',
      );
    }
  } else {
    throw PlatformException(
      code: 'ERROR_ABORTED_BY_USER',
      message: '',
    );
  }
}