-
Notifications
You must be signed in to change notification settings - Fork 135
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
How to limit access to resources? #317
Comments
Hey @hamez0r, sorry about delay. Of course it is possible, there might just not be clear documentation or examples for this use case.
This may be straightforward to implement using a framework, but you're also discounting how much work the framework is actually doing. Generally speaking, a user will have an authentication token which the server must lookup which user it belongs to, then lookup whether a record is associated to that user, sometimes through multiple associations such as user => group => resource. Assuming that one already has figured out an authentication scheme, implementing authorization isn't too hard: // this is for reading a record, writing to a record would be almost identical.
function outputHook(context, record) {
return context.transaction.find('User', [record.user]).then(result => {
if (result.payload.records[0].id !== authenticatedUserId) {
throw new fortune.errors.UnauthorizedError(`Can't read this!`)
}
return record
})
} |
Hey, thanks for your reply! I do understand the framework does a lot of work, it's actually really nice and I'm trying to uncover all its functionalities. Your example works well with targeted records ( In the typical app with multiple users, each holding their own data, a request to By the time the output hook is called, all records have already been retrieved from the DB, and, AFAIK, returning Do you have any hints for this? Thanks in advance! |
So to implement this efficiently, you probably want to rewrite whatever request is coming in as matching a certain user, basically this query option: {
match: {
user: 'userId'
}
} Here's an oversimplified example: const originalRequest = store.request
store.request = function (contextRequest) {
if (contextRequest.type === 'Resource') {
contextRequest.options.match = { user: authenticatedUserId }
}
return originalRequest.call(this, contextRequest)
} However, it would be simpler query (and less work) to go in the reverse direction: just get the user and include its related records. store.find('User', [authenticatedUserId], null, [['resources']]) This way would also be easier to implement when you need to get nested related records. |
I faced a similar problem today. To me, it seems that fetching data from the DB is different from presenting data to the client. So anyway, I ended adding a custom hook in the serialization.
I was wondering what your thoughts would be, that's why I post it here. I am well aware this is not strictly speaking serialization, but I am missing the place right before the data gets passed to the serializer. |
Yes, this is by design. So you can do it that way by modifying the serializer. The reason why I didn't suggest doing that is because it's entirely dependent on the application protocol used. It's better to monkey-patch the |
How can one limit access to resources, based on application logic? I couldn't find anything in documentation about this, I'm not even sure it's possible.
For example User A should not be able to access resources belonging to User B. In the typical web app backed by an ORM, that's pretty straight forward.
I'm using fortune-json-api and MongoDB adapter. From what I understand, to interfere with what's going on during a request, my only option is using hooks.
The only other solution I can think of is using classic Express app, manually define routes, and use the store like I would use an ORM (but doesn't this defeat the purpose?). And since I want to stick to JSON:API, I probably need to find a serializer as well.
Cheers!
Edit
I found #270 in the meantime. I'll try to find out if something similar works for my case.
The text was updated successfully, but these errors were encountered: