Flutter - 在将 Firebase 用户写入自己的用户实例时获取 Firebase 自定义声明

Ocr*_*ops 4 future stream async-await firebase firebase-authentication

我正在尝试实现如何访问自定义声明?到我现有的代码。

我有一个 Stream,它监听身份验证更改并使用响应的 Firebase 用户更新我自己的用户对象。当我存储用户对象时,我也想获取该用户的自定义声明。

问题出在_userFromFirebaseUser中。

它说“await 表达式只能在异步函数中使用。尝试用‘async’或‘async*’标记函数体。”

但是,当我这样做时,错误会跳转到我的流,然后显示“参数类型‘Future Function(User)’无法分配给参数类型‘User Function(User)’。” 对于“_userFromFirebaseUser”

// auth change user stream
  Stream<local.User> get user {
    return _auth.authStateChanges().map(_userFromFirebaseUser);
  }
Run Code Online (Sandbox Code Playgroud)

这是我完整的身份验证类:

import 'package:<my-pckg>/models/user.dart' as local;
import 'package:firebase_auth/firebase_auth.dart' as auth;
import 'package:<my-pckg>/services/database.dart';
//import 'package:shared_preferences/shared_preferences.dart';

class AuthService {
  final auth.FirebaseAuth _auth = auth.FirebaseAuth.instance;

  // create user obj based on firebase user
  local.User _userFromFirebaseUser(auth.User user) {
    
    final isAdmin = (await _currentUserClaims)['admin'] == true;
    
    return user != null
        ? local.User(
            uid: user.uid,
            email: user.email,
            displayName: user.displayName,
            isAdmin: isAdmin)
        : null;
  }

  // auth change user stream
  Stream<local.User> get user {
    return _auth.authStateChanges().map(_userFromFirebaseUser);
  }

  // sign in anon
  Future signInAnon() async {
    try {
      auth.UserCredential result = await _auth.signInAnonymously();
      auth.User user = result.user;
      return _userFromFirebaseUser(user);
    } catch (e) {
      print(e.toString());
      return null;
    }
  }

  // sign in with email and password
  Future signInWithEmailAndPassword(String email, String password) async {
    try {
      auth.UserCredential result = await _auth.signInWithEmailAndPassword(
          email: email, password: password);
      auth.User user = result.user;
      print('Successfully logged in, User UID: ${user.uid}');
      return user;
    } catch (error) {
      print(error.toString());
      return null;
    }
  }

  // register with email and password
  Future registerWithEmailAndPassword(String email, String password) async {
    try {
      auth.UserCredential result = await _auth.createUserWithEmailAndPassword(
          email: email, password: password);
      auth.User user = result.user;
      // create a new document for the user with the uid
      await DatabaseService(uid: user.uid).updateUserData(null);
      print('Successfully registered, User UID: ${user.uid}');
      return _userFromFirebaseUser(user);
    } catch (error) {
      print(error.toString());
      return null;
    }
  }

  // sign out
  Future signOut() async {
    try {
      print('User signed out');
      return await _auth.signOut();
    } catch (error) {
      print(error.toString());
      return null;
    }
  }

  Future<Map<dynamic, dynamic>> get _currentUserClaims async {
    final user = _auth.currentUser;

    // If refresh is set to true, a refresh of the id token is forced.
    final idTokenResult = await user.getIdTokenResult(true);

    return idTokenResult.claims;
  }
}
Run Code Online (Sandbox Code Playgroud)

我是否走错了方向?有什么明显的事情是我根本没有考虑到的吗?

感谢您的帮助!

Ocr*_*ops 5

对于那些遇到同样问题的人,我经过进一步研究找到了解决方案:

您必须将其更改.map.asyncMap.

这是对我有用的代码:

import 'package:<my-pckg>/models/user.dart' as local;
import 'package:firebase_auth/firebase_auth.dart' as auth;
import 'package:<my-pckg>/services/database.dart';
//import 'package:shared_preferences/shared_preferences.dart';

class AuthService {
  final auth.FirebaseAuth _auth = auth.FirebaseAuth.instance;

  // create user obj based on firebase user
  Future<local.User> _userFromFirebaseUser(auth.User user) async {
    final isAdmin = (await _userClaims)['admin'] == true;

    return user != null
        ? local.User(
            uid: user.uid,
            email: user.email,
            displayName: user.displayName,
            isAdmin: isAdmin)
        : null;
  }

  // auth change user stream
  Stream<local.User> get user {
    return _auth.authStateChanges().asyncMap(_userFromFirebaseUser);
  }

  // sign in anon
  Future signInAnon() async {
    try {
      auth.UserCredential result = await _auth.signInAnonymously();
      auth.User user = result.user;
      return _userFromFirebaseUser(user);
    } catch (e) {
      print(e.toString());
      return null;
    }
  }

  // sign in with email and password
  Future signInWithEmailAndPassword(String email, String password) async {
    try {
      auth.UserCredential result = await _auth.signInWithEmailAndPassword(
          email: email, password: password);
      auth.User user = result.user;
      print('Successfully logged in, User UID: ${user.uid}');
      return user;
    } catch (error) {
      print(error.toString());
      return null;
    }
  }

  // register with email and password
  Future registerWithEmailAndPassword(String email, String password) async {
    try {
      auth.UserCredential result = await _auth.createUserWithEmailAndPassword(
          email: email, password: password);
      auth.User user = result.user;
      // create a new document for the user with the uid
      await DatabaseService(uid: user.uid).updateUserData(null);
      print('Successfully registered, User UID: ${user.uid}');
      return _userFromFirebaseUser(user);
    } catch (error) {
      print(error.toString());
      return null;
    }
  }

  // sign out
  Future signOut() async {
    try {
      print('User signed out');
      return await _auth.signOut();
    } catch (error) {
      print(error.toString());
      return null;
    }
  }

  Future<Map<dynamic, dynamic>> get _userClaims async {
    final user = _auth.currentUser;

    // If refresh is set to true, a refresh of the id token is forced.
    final idTokenResult = await user.getIdTokenResult(true);

    return idTokenResult.claims;
  }
}
Run Code Online (Sandbox Code Playgroud)

在这里找到:In flutter, how can I“merge”Firebase onAuthStateChanged with user.getTokenId() to return a Stream?