CustomEntity.GetEntityPage() Improvement

The Challenge

Last week we became aware of a potential issue when using GetEntityPage() with owned entities.

The issue is related to how brainCloud handles ACL permissions. As you may or may not know, all entities in brainCloud support ACL permissions – and you can set the global accessibility of an object by setting the acl.other permission to one of the following:

  • 0 = no access
  • 1 = read-only access
  • 2 = read + write access

In loose terms, any object with acl.other != 0 is shared with (or accessible by) all users of the app.

This has large implications when dealing with Owned Custom Entities and the GetEntityPage() call – because by the previous default – the call would look for all entities that meet the search criteria that:

  • Are owned by the current user
  • Are accessible by the current user

Owned is simple – we simply add “ownerId”: <profileId> to the query provided by the developer.

Accessible is not so simple – the database must look at all of the objects that the player doesn’t own, and specifically examine each objects ACL to see if acl.other != 0 !!! This is incredibly slow, and exponentially so! Especially since 99.9% of the time, a developer is only looking for the entities owned by the current user!

Information

Note – this issue does not affect Unowned Custom Entities, Sys calls (which ignore permissions), or the Singleton API (which assumes objects must be owned by the current user). It only affects GetEntityPage() and GetEntityPageOffset().


The Solution

To address this issue, we are changing to the default behaviour of `GetEntityPage() so that it no longer considers shared entities (by default) for Owned Custom Entities.

Thus, a query with the following criteria will now only return objects that are owned by the current user:

{
  "pagination": {
    "rowsPerPage": 50,
    "pageNumber": 1
  },
  "searchCriteria": {
    "data.position": "defense"
  },
  "sortCriteria": {
  }
}

Going forward, if an app wants to modify this default behaviour to include accessible (i.e. shared) objects that are owned by other users – they can add the new ownedOnly: false option. For example:

{
  "pagination": {
    "rowsPerPage": 50,
    "pageNumber": 1
  },
  "searchCriteria": {
    "data.position": "defense"
  },
  "sortCriteria": {
  },
  {
  "options": {
    "ownedOnly": false
  }
}

Advice

Note also that your CustomEntity should include Custom Indexes that include the acl.other field for efficient queries where ownedOnly: false.


Compatibility Flag

Because this is a change to the previous brainCloud behaviour, we have introduced a new compatibility flag. When enabled, the following flag preserves the old functionality – where both objects owned and accessible by the user will be returned.

The new compatibility flag can be found in the Design | Core App Info | Advanced Settings page:

[ x ] Include shared objects in Owned Custom Entity GetEntityPage queries (warning: can be slow). Can be overwritten by specifying ‘ownedOnly’ in query context ‘options’.

When enabled, the default for ownedOnly is false – and when disabled, the default for ownedOnly is true.

Advice

Note that this compatibility flag, like all compatibility flags, is automatically enabled for existing apps (for backwards compatibility), and disabled for new apps.


We believe strongly that this new-and-improved GetEntityPage behaviour is the better + safer default – and thus highly recommend that all developers whose owned queries are only expecting objects owned by the current user go to this compatibility flag and immediately “uncheck” it to enable the new behaviour!

Remember – this option does not affect queries for Un-owned Custom Entities. It also does not affect Sys calls. So both of those scenarios will continue to return objects not owned by the current user – regardless of the compatibility setting.

If you have any questions – please reach out to the support team.

Cheers!