Flutter Realm: User.Customdata is always null

Currently i am trying to get the customdata of my loggedin user

class RealmService with ChangeNotifier {
  final String appId = "xxxx";
  late final appConfig = AppConfiguration(appId);
  late final _app = App(appConfig);

  late final user = _app.currentUser;
  final updatedTimestamp = DateTime.now().millisecondsSinceEpoch;
  var logger = Logger();
  late String _token = '';
  final storage = FlutterSecureStorage();

  late userModel.User user2;

  static final RealmService _singleton = RealmService._internal();


  factory RealmService() {
    return _singleton;
  }

  RealmService._internal();

  User? get currentUser {
    return _app.currentUser;
  }

The login works fine. But when i try to fetch the customData it for somereason shows null. Meanwhile the profile of the current user shows just fine.

  @override
  Widget build(BuildContext context) {
    final realmService = Provider.of<RealmService>(context, listen: false);
   customUserData = realmService.currentUser!.customData;
    logger.d(realmService.currentUser!.profile); //<-works
    logger.d(realmService.currentUser!.customData); // <-shows null

Any idea why this is the case. I already had the “Enable Custom User Data” enabled in Atlas.

Hi @Salman_lartey!
The customData are embedded in user access token. You have to be sure that your table has data populated for the user before logging with this user to the app. It is important that the field set to “user ID field” has the user id inserted as data.
I’m sending one of our samples, which is based on customData security roles. You can find custom data configuration file here.
Here is an example how the roles, which are set as custom data, are populated for the purpose of this sample.
Feel free to write back in case you still receive null.
By the way, we provide a method user.refreshCustomData() that could also be used in case your custom data items have been added after user login.

1 Like

Hi,

I still get that it shows null. My login method looks like:

class RealmService with ChangeNotifier {
  final String appId = "xxx";
  late final appConfig = AppConfiguration(appId);
  late final _app = App(appConfig);

  late final user = _app.currentUser;
  final updatedTimestamp = DateTime.now().millisecondsSinceEpoch;
  var logger = Logger();
  late String _token = '';
  final storage = FlutterSecureStorage();

  late userModel.User user2;

  static final RealmService _singleton = RealmService._internal();

factory RealmService() {
    return _singleton;
  }

  RealmService._internal();

  User? get currentUser {
    return _app.currentUser;
  }

  Future<userModel.User> logInWithEmail(String email) async {

    await _app.emailPasswordAuthProvider
        .registerUser(email, 'myStr0ngPassw0rd');
    print('User registration successful!');

    final user =
        await _app.logIn(Credentials.emailPassword(email, 'myStr0ngPassw0rd'));
    print('User login successful!');

    logger.d(user.customData);
    final AuthLink authLink = AuthLink(getToken: () async {
      final currentUser = _app.currentUser;
      final accessToken = await currentUser?.accessToken;
      return 'Bearer $accessToken'; // Assuming your server expects the token in the "Bearer" format
    });

    // user.customData;
    logger.i(currentUser!.customData);

but even in the method i get that customData = Null.

Could you please check whether the id of the user is the same as the “user ID field” in the collection that is set for custom data? In this example custom data collection is Role and “user ID field” is owner_id .


Users is my cusom data collection.

The _id should be equal to user.id.

I have changed it to the following:


and:

but the issue still persists strange enough

I would advice you to add additional field for user_id that is from type String.

Even when adding “user_id” to the field and adding it to the database it doesnt work. Do you have a screenshot on how it looks like in the Atlas when you add the userfield?

and

Now it looks correct to me. Could you please also check if “user_id” is set as queryable field? See the last image.


Also make sure that the users have permissions to read these data.

You can use either filter by user or permissions for all.

{
  "roles": [
    {
      "name": "readOwnWriteOwn",
      "apply_when": {},
      "document_filters": {
        "write": {
          "user_id": "%%user.id"
        },
        "read": {
          "user_id": "%%user.id"
        }
      },
      "read": true,
      "write": true,
      "insert": true,
      "delete": true,
      "search": true
    }
  ]
}

or for all users:

{
  "roles": [
    {
      "name": "readOwnWriteOwn",
      "apply_when": {},
      "document_filters": {
        "write": true,
        "read": true
      },
      "read": true,
      "write": true,
      "insert": true,
      "delete": true,
      "search": true
    }
  ]
}

It is not. I have:


and:

The database name in Device Sync tab looks wrong. It is “todo”.
And what is the permission Rule, can you switch to View mode, so that we can check the json content?

Okay i have changed the Device Sync to:

And the json looks like:

You can remove owner_id queryable field. It was from my example. For you it is user_id. By the way you need this queryable field in case you have set permissions rules based on this field. If your rule is write:false and read:true the queryable field shouldn’t be required.
Is it working now?

No, it isn’t working. Is there a reference where i can see an implementation of the custom User data?

Yes, here is that sample that I sent earlier users_permissions.
Here is the place where the custom data is used in isAdmin extension property .

Oke so I manage to find something. When i login with google for the first time, it is null. When i then try to logout and login with the same Google account i get it.

 @override
  void initState() {
    super.initState();

    final realmService = Provider.of<RealmService>(context, listen: false);
    final user = realmService.currentUser;
    socketClient.emit('setUser', user!.profile.email);

    try {
      setState(() {
        final customUserData = realmService.currentUser?.customData;
        logger.d(customUserData);
      });
    } catch (e) {}

but how and why is that possible? Isn’t it the case that you get the customData once you login?

1 Like

We will try to reproduce this.
You mentioned google, but I saw in the code above you are using Credentials.emailPassword, right?

That is correct. First i started with the email/password. But as i was troubleshooting, i thought let me try google. and voilla. I notice that the first login attempt is null. But after the 2nd login, it will give me the customData. With email/password i havent tried it .