paralect/node-mongo

Feature: Scopes

Closed this issue · 2 comments

Add a convenient option to append a scoping query.

For example, all entities in the DB (users, groups, templates, tasks) belong to one and only one space. In the schema, they all have spaceId field. To restrict users from space A to see the data from space B we need to add { spaceId: ctx.state.user.spaceId } to the most queries.

Obviously there should be a common mechanism for this to avoid data leaks and incorrect behavior.

Posssible solution:

const userService = db.createService('users', userSchema, { scope: 'spaceId' });
...
ctx.state.user = await userService.findUserByToken(accessToken);
userService.setScope({ spaceId: ctx.state.user.spaceId });
...
userService.findOne({ email: data.email });
[internally] => userService.findOne({ email: data.email, spaceId: ctx.state.user.spaceId });

I think we shouldn't add application specific logic to library.
Especially since you can define custom service methods and use them instead of usual methods:

// db.js

db.setServiceMethod('setScope', (service, scope) => {
  service.scope = scope;
});

db.setServiceMethod('findOneWithScope', (service, query) => {
  return service.atomic.findOne({ ...query, ...service.scope });
});

Usage:

// somewhere after authorization

ctx.state.user = await userService.findUserByToken(accessToken);
userService.setScope({ spaceId: ctx.state.user.spaceId });
// somewhere after authorization but deeper

userService.findOneWithScope({ email: data.email });

Agree, these methods should be out of node-mongo scope as it's more application specific and there's workaround as @hovoodd suggested