Reputation: 677
How would correctly should look API that returns only objects belonging to the user who asks for them?
api/version/items/<items_id>
or
api/version/user/<user_id>/items/<items_id>
In the first case, the server queried the database with a user id, which it obtains from its authentication.
I don't know how to create both cases in Flask-restless. I think a preprocessor will be useful, where I could get user_id from authorization (JWT token), but I can't find a way to use it as search parameters for DB.
from flask_jwt import JWT, jwt_required, current_user
...
manager.create_api(Item,
methods=['GET'],
collection_name='items',
url_prefix='/api',
preprocessors=dict(GET_SINGLE=[api_auth],GET_MANY=[api_auth]))
@jwt_required()
def api_auth(*args, **kwargs):
user_id = current_user.id
# some code with user id addition.
pass
Upvotes: 1
Views: 424
Reputation: 163
You should use an endpoint that refers directly to the resources that you are trying to query. For example:
api/version/items
You should define a get_single
and get_many
preprocessor separately. The instance_id
for the single (integer) and the result
argument (dictionary) for the multiple pre-processor should be used to define what is returned to the user.
From the Flask-restless docs:
Those preprocessors and postprocessors that accept dictionaries as parameters can (and should) modify their arguments in-place. That means the changes made to, for example, the result dictionary will be seen by the Flask-Restless view functions and ultimately returned to the client.
Therefore in your pre-processors, you could do something like the following to retrieve the items (defined in a relationship to the user) in your database:
@jwt_required()
def api_auth_get_many(instance_id=None, *args, **kwargs):
user_id = current_user.id
if instance_id in User.query.get(user_id).items:
pass
else:
instance_id = None # Do not return the value if not permitted
@jwt_required()
def api_auth_get_many(result=None, *args, **kwargs):
user_id = current_user.id
result = User.query.get(user_id).items # Return all items allowed for user
Upvotes: 0
Reputation: 942
Preprocessor would be the place where you build a query object. I think the endpoint for items should look simply like:
api/version/items
but whithin the preprocessor you would build a query object that would be passed with the request:
GET api/version/items?q={"filters":[{"name":"userid","op":"eq","val":10}]}
Upvotes: 0