paralect / node-mongo

Node Mongo — is reactive 🚀 extension to MongoDB API
https://github.com/paralect/node-mongo
23 stars 7 forks source link

Feature: Scopes #24

Closed alldayalone closed 4 years ago

alldayalone commented 4 years ago

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 });
jqueryisamonad commented 4 years ago

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 });
IharKrasnik commented 4 years ago

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