Reputation: 1668
When building an API in Loopback, I want to have relatively flat, authentication protected routes like: /users
, /orders
, etc. So, if I'm a user and I have some orders, I should be able to simply call /orders
or /orders/:id
to get one or more of the orders for my account.
Using Loopback's model relationships, I could do something like: /users/:userId/orders
relatively easily, but there are definitely cases where I don't want to add in that complexity to the URL structure.
Is there a good, recommended way to do something like this? Seems like there should be a way to set this up such that the current user's access token tells Loopback which records it has access to and then can return only those.
Upvotes: 2
Views: 104
Reputation: 1668
The solution to this problem wasn't terribly obvious, but I came up with something that works well enough, though it's a bit "manual."
First, in my case, I always have access to the user via req.user
, which is a fairly common Node.js / Express pattern. I believe libs like Passport follow this as well.
Then, I created a generic helper method called that looks like this:
module.exports.sourceUser = function(ctx) {
var req = ctx.req;
if (!req.user) {
var err = new Error('You must pass valid credentials to call this API.');
err.statusCode = 401;
throw err;
}
return req.user;
};
This will ensure that APIs I attach this method to will require user authentication, rejecting any request that doesn't have a valid user cred.
Next, since I'm defining flat APIs, I'm just defining my own remote methods (not using built-in Loopback ones). Each remote method def looks like this:
Model.remoteMethod('getRecord', {
http: {
verb: 'get',
path: '/:id'
},
accepts: [
{ arg: 'id', type: 'string', required: true, http: { source: 'path' } },
{ arg: 'user', type: 'object', http: helpers.sourceUser }
],
returns: [
{ arg: 'model', type: 'model', root: true }
]
});
You'll need to adjust that code to match your model names, etc. Also, notice the usage of helpers.sourceUser
which is the thing that ensures we have a user and then provides that user as an argument to the API implementation.
Finally, I use a where
clause in my database queries, etc to ensure that a user only gets/sets their own records (e.g. where model.user == user.id
).
Hope this helps someone else...
Upvotes: 1
Reputation: 9396
/users/:userId/orders
is needed for admin area e.g
You should create a base route such /me
for your situation.
Upvotes: 1