Node.js Agent – Filter result depending on the current signed-in user

Hello all :wave:

I’m currently adding a backend to a project of mine, using the Node.js agent. The project uses different user accounts, and I would like to add some “filtering” depending on the current sign-in user in ForestAdmin.

Typically, depending on the current user (context.caller.email for ex.) what I would like to do is to add “where clauses” to my query so (s)he can see a pert the list of entries, but not every row in the database.

Does anybody known if it is possible and how to do this ?

Note that the clauses I would like to inject are not limited to a single where clause: there are a few joins involved. But nothing too fancy neither.

Kind regards,
Aurélien

Context

  • Agent (forest package) name & version: @forestadmin/agent v1.36.13 and @forestadmin/datasource-sql v1.7.44
  • Database type: Postgres

Hello @Aurel ! :wave:

We have a great feature called Scopes that would hopefully allow you to do exactly that without having to write code.

I hope this helps.

Best regards,

Thank you for your answer @dogan.ay !

My issue with the scopes in the Gui is that I cannot leverage JOINs to do a more complex query.
My understanding is that I could use the addSegment method in my code and add a custom SQL statement, but I could not figure out how to make it work…

You can use your native driver to query your database as shown by this example.
As you have stated above you can also fetch the the caller via the context given to the function definition.

However if I understood what was your intent properly:

  • limit the access of certain records to users and not simply offer a pre-filtered view

The solution with segments won’t prohibit users to access to the full collection of records.

I think it would be great feedback for us, to improve our Scope feature, if you could share with us the type of joins/conditions you wish to make but cannot at the moment.

The reason you can’t do scope from the agent-nodejs API is that at the time the nodejs agent was made, scopes were a paying feature. Not sure this is still the case.

It would certainly be easier if there was a collection.addScope method on the agent

With the current API the only solution is to create a dummy field, and use it in a scope from the GUI.

agent.customizeCollection('whatever', c => {
  // create a dummy field
  c.addField('canBeSeenByCurrentUser', {
    columnType: 'Boolean',
    dependencies: ['id'],
    // the value does not matter
    getValues: records => records.map(r => true);
  });

  // implement filtering
  c.replaceFieldOperator('canBeSeenByCurrentUser', 'Equal', (value, context) => {
    // value will always be true, if it's false, match zero records
    if (!value) return { aggregator: 'Or', conditions: [] };

    // build a condition tree which match records that the current user can see
    // here I'm using a SQL query, but that's not very efficient.
    // The efficient way to do that is to use a forstadmin condition tree
    // @see https://docs.forestadmin.com/developer-guide-agents-nodejs/data-sources/getting-started/queries/filters#condition-trees
    const rows = context.collection.nativeDriver.rawQuery(
      'select id from whatever inner join x inner joint y where y.email = :email',
      { email: context.caller.email }
    });

    return { field: 'id', operator: 'In', value: rows.map(r => r.id) }
  });

  // Needed for the frontend to let you use scopes on that field
  c.emulateFieldFiltering('canBeSeenByCurrentUser')
});

Then go to the GUI, and add a scope to the collection (from the collection settings).
And set it to:

field: canBeSeenByCurrentUser
operator: Equal
value: true
4 Likes