Авторизация по ролевой базе во Flutter Web с использованием Firestore и GetX State Management (шаблон MVC)

Я просто собираюсь разработать решение Flutter Web корпоративного уровня. Поэтому я решил использовать правильный пакет управления состоянием вместо SetState. Это мое первое веб-приложение Flutter, и я впервые попробовал использовать GetX.

Я собираюсь реализовать авторизацию Rolebase с помощью Firestore. После того, как пользователь вошел в систему, он будет перенаправлен на страницу администратора, если он является администратором, в противном случае перенаправлен на страницу пользователя. Функция входа в систему работает нормально. Но я не могу получить роль от Firestore. Я объяснил все это, потому что хочу знать решение следующей ошибки и знать, правильно ли я делаю это управление состоянием.

Ошибка явно говорит о том, что "Плохое состояние: невозможно получить поле на DocumentSnapshotPlatform, которое не существует". Но как я могу определить точную причину? Кто-нибудь может помочь мне понять, где я сделал ошибку.

Ошибка:

       [GETX] "AuthController" has been initialized
[GETX] "UserController" has been initialized
[GETX] "GetMaterialController" has been initialized
[GETX] GOING TO ROUTE /login-page
LoginSuccess
Error: Bad state: cannot get a field on a DocumentSnapshotPlatform which does not exist
    at Object.throw_ [as throw] (http://localhost:5000/dart_sdk.js:4328:11)
    at platform_interface_document_snapshot.DocumentSnapshotPlatform.new.get (http://localhost:5000/packages/cloud_firestore_platform_interface/src/platform_interface/platform_interface_write_batch.dart.lib.js:652:19)
    at cloud_firestore.DocumentSnapshot.__.get (http://localhost:5000/packages/cloud_firestore/cloud_firestore.dart.lib.js:697:73)
    at cloud_firestore.DocumentSnapshot.__._get (http://localhost:5000/packages/cloud_firestore/cloud_firestore.dart.lib.js:700:19)
    at new user_model.UserModel.fromDocumentSnapshot (http://localhost:5000/packages/equipment_management_system/models/user_model.dart.lib.js:47:32)
    at database.Database.new.getUser (http://localhost:5000/packages/equipment_management_system/views/pages/login_page.dart.lib.js:3180:16)
    at getUser.next (<anonymous>)
    at http://localhost:5000/dart_sdk.js:37593:33
    at _RootZone.runUnary (http://localhost:5000/dart_sdk.js:37447:58)
    at _FutureListener.thenAwait.handleValue (http://localhost:5000/dart_sdk.js:32424:29)
    at handleValueCallback (http://localhost:5000/dart_sdk.js:32971:49)
    at Function._propagateToListeners (http://localhost:5000/dart_sdk.js:33009:17)
    at _Future.new.[_completeWithValue] (http://localhost:5000/dart_sdk.js:32852:23)
    at async._AsyncCallbackEntry.new.callback (http://localhost:5000/dart_sdk.js:32874:35)
    at Object._microtaskLoop (http://localhost:5000/dart_sdk.js:37708:13)
    at _startMicrotaskLoop (http://localhost:5000/dart_sdk.js:37714:13)
    at http://localhost:5000/dart_sdk.js:33226:9

Контроллер аутентификации:

         handleAuthChanged(isLoggedIn) async {
    final UserController userController = Get.put<UserController>(UserController());
    if (isLoggedIn == false) {
      Get.offAllNamed(LoginPageRoute);
    } else {
      print("LoginSuccess");
      userController.user = await Database().getUser(user.value.uid).then((value){
        print(userController.user.id);
        if(userController.user.role == "Admin"){
          Get.offAllNamed(AdminHomePageRoute);
        }else{
          Get.offAllNamed(UserHomePageRoute);
        }
        return;
      });
    }
  }

Модель пользователя

       class UserModel{
  String id;
  String name;
  String role;

  UserModel({id, name, email, role});

  UserModel.fromDocumentSnapshot(DocumentSnapshot doc){
    id = doc["id"];
    name = doc["name"];
    name = doc["role"];
  }

}

Пользовательский контроллер

       class UserController extends GetxController{
  Rx<UserModel> _userModel = UserModel().obs;
  UserModel get user => _userModel.value;
  set user(UserModel value) => this._userModel.value = value;
  void clear(){
    _userModel.value = UserModel();
  }
}

Служба базы данных

       class Database{
  final FirebaseFirestore _firebaseFirestore = FirebaseFirestore.instance;

  Future<bool> createNewUser(UserModel user) async {
    await _firebaseFirestore.collection("users").doc(user.id).set({
      "name" : user.name,
      "role" : user.role,
    }).catchError((onError){
      Get.snackbar(
        "", "",
        titleText: Text("An error occurred while connecting to the database", style: TextStyle(fontFamily: "Poppins", fontWeight: FontWeight.bold, fontSize: 16)),
        messageText: Text(onError.message, style: TextStyle(fontFamily: "Poppins")),
        colorText: primaryColor,
        backgroundColor: Colors.white.withOpacity(0.5),
        margin: EdgeInsets.only(top: 20, left: 20, right: 20),
        barBlur: 10,
      );
      return false;
    });
    return true;
  }

  Future<UserModel> getUser(String uid) async{
    DocumentSnapshot doc = await _firebaseFirestore.collection("users").doc(uid).get().catchError((onError){
      Get.snackbar(
        "", "",
        titleText: Text("An error occurred while retrieving data", style: TextStyle(fontFamily: "Poppins", fontWeight: FontWeight.bold, fontSize: 16)),
        messageText: Text(onError.message, style: TextStyle(fontFamily: "Poppins")),
        colorText: primaryColor,
        backgroundColor: Colors.white.withOpacity(0.5),
        margin: EdgeInsets.only(top: 20, left: 20, right: 20),
        barBlur: 10,
      );
    });
      return UserModel.fromDocumentSnapshot(doc);
  }
}

Коллекция Firestore

2 ответа

      class UserModel {
  String id;
  String name;
  String role;

  UserModel({id, name, email, role});

  UserModel.fromDocumentSnapshot(DocumentSnapshot doc) {
    id = doc.data().containsKey("id") ? doc.data()["id"] : '';
    name = doc.data().containsKey("name") ? doc.data()["name"] : '';
    role = doc.data().containsKey("role") ? doc.data()["role"] : '';
  }
}

Недавно у меня была такая же ошибка. Недавно я обновил несколько пакетов Firebase (cloud_firestore: ^0.14.1+3, firebase_auth: ^0.18.1+2, firebase_dynamic_links: ^0.6.0+2, firebase_storage: ^4.0.1). После очистки всех устаревших методов и т. Д. Я начал получать то же самое "не могу получить поле на DocumentSnapshotPlatform, которое не существует".

В конце концов я понял, что если я изменил все ссылки с doc["fooBar"] на doc.data()["fooBar"], это решило бы проблему. Попробуйте изменить свой код на следующий:

class UserModel{
    String id;
    String name;
    String role;

    UserModel({id, name, email, role});

    UserModel.fromDocumentSnapshot(DocumentSnapshot doc){
        id = doc.data()["id"] // previously doc["id"];
        name = doc.data()["name"] // previously doc["name"];
        name = doc.data()["role"] // previously doc["role"];
    }
}

После дальнейшего чтения (https://pub.dev/packages/cloud_firestore/changelog) я обнаружил следующее примечание относительно DocumentSnapshots из версии 0.14.0^

"Снимок документа:

ПРЕРЫВАНИЕ: теперь получателем данных является метод data ().... "