Проверьте, существует ли пользователь в FIrestore - PullRequest
0 голосов
/ 06 ноября 2019

У меня есть эта функция, которая использует 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));
            });
          }

Почему он возвращает false, даже если user.uid и документ существуют? Что я делаю не так?

Ответы [ 2 ]

0 голосов
/ 06 ноября 2019

Окей, не уверен, что это лучшая практика, но теперь я получаю идентификатор документа

final id = await dbRef.documentID;

, затем проверим, пусто это или нет ... тогда делай вещи ...

0 голосов
/ 06 ноября 2019

Многое происходит. Как правило, вы не обновляете объект state методом setState(). setState используется, чтобы сообщить виджету, что некоторые state изменились - и он называется синхронно с изменением, но здесь вы просто проверяете, существует ли документ и ничего не меняется, это не нужно.

Также не похоже, что вы вообще возвращаете объект user, поэтому этот код, который я прочитал, всегда будет возвращать false.

  1. Вы должны полностью удалить setState здесь (не нужно для того, что вы делаете)
  2. Запустить метод входа, который возвращает объект пользователя, с которым вы хотите что-то делать.
  3. Получите доступ к вашей БД, как только узнаете, что у вас есть вошедший в систему пользователь (т.е. без идентификатора вошедшего в систему пользователя)

Вот вариант, который можно попробовать:

//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: '',
    );
  }
}

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...