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

Flutter - Get Firebase custom claims while writing Firebase user to own user instance

我正在尝试将 中给出的示例应用到我现有的代码中。

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

问题出在_userFromFirebaseUser

它说“等待表达式只能在异步函数中使用。 尝试用 'async' 或 'async*'."

标记函数体

但是当我这样做时,错误跳转到我的流,然后它说“参数类型 'Future Function(User)' 不能分配给参数类型 'User Function(User)'。”

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

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

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;
  }
}

我走错方向了吗?有什么明显的,我根本不考虑吗?

感谢您的帮助!

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

您必须将 .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;
  }
}

在此处找到:In flutter, how can I "merge" Firebase onAuthStateChanged with user.getTokenId() to return a Stream?