Reputation: 519
Currently testing a bunch of frameworks in order to determine a good candidate for future uses in my company, LoopBack caught my attention by being almost perfect for my needs.
However, I get the feeling that their ACL model is quite limited in some cases. Let's take the following use case: on a collaborative travels management website, a user can create and/or join public travels. Let's assume the following API:
/Travels
lists all travels the user has/Travels/public
lists all public travels/Travels/{id}/join
join the Travel with the given IDWould building such an API require to re-invent the wheel? Or is it some middlewares to implement?
The same goes for per-field ACL. Suppose you have a few checklist items, some manually added and some others automatically generated. Can you block the WRITE operations only on automatic ones, except for changing the "done" field?
Upvotes: 1
Views: 1932
Reputation: 21
As @amenadiel suggested, you can use a hooks to set a default filter by the logged in user:
MyModel.observe('access', function limitToTenant(ctx, next) {
ctx.query.where.tenantId = loopback.getCurrentContext().tenantId;
next();
});
Got this from the docs.
Upvotes: 2
Reputation: 17501
By default, a request to
GET /Travels
would list every element of the Travel model. If you set proper relations (probably a many to many relationship between users and travels) the proper way to query for a given user travels is
GET /Users/{id}/Travels
But you can customize the default behavior of Travels.find()
using hooks, scopes and even overloading the method prototype.
Regarding /Travels/public
that's trivial, you just need to create a remote method. Use the path
property to customize the endpoint.
Finally, joining a travel with a request to /Travels/{id}/join
would be managed with remote methods too, but this should be a POST request.
Loopback is able to manage many to many relations without specifying a relation table, but in your case I'd rather define it. For example
{
"name": "UserTravel",
"options": { ... },
"properties": {
"id":{"type":"Number", "id":1},
"userId":{"type":"Number"},
"travelId":{"type":"Number"}
},
"relations": {
"Travel": {
"type": "belongsTo",
"model": "Travel",
"foreignKey": "travelId"
},
"User": {
"type": "belongsTo",
"model": "User",
"foreignKey": "userId"
}
}
}
having this model at hand would allow you to insert a specific user/travel tuple when calling the join
endpoint. You get the travelId from the request params, and the userId from the request accessToken, provider the user is authenticated in your app.
Upvotes: 6