pyronear / pyro-api

Alert Management API for wildfire prevention, detection & monitoring. Built with FastAPI & PostgreSQL
Apache License 2.0
21 stars 9 forks source link

[users] Implementing user_group #125

Closed frgfm closed 3 years ago

frgfm commented 3 years ago

Following up on #45, I think it is sound to have a discussion about the multiple access levels in the API. With the current design of scopes, we cannot efficiently separate accesses of large user groups.

Requirements

Design suggestion

Simply put, I believe two fields are required:

frgfm commented 3 years ago

Hi @florianriche :wave:

I had the occasion to think about this over the weekend and here is my suggestion !

Feature constraints

Design suggestion

I think we would benefit from splitting the work into the following PRs:

Any thoughts @pyronear/back-end ?

florianriche commented 3 years ago

Seems like a good design to me. However I think there is an issue for the last point. In the "Security" schema, you don't have have access to the requested id. E.g for this route below:

@router.get("/{user_id}/", response_model=UserRead, summary="Get information about a specific user")
async def get_user(user_id: int = Path(..., gt=0), _=Security(get_current_user, scopes=["admin"])):

We can't pass user_id to get_current_user (or any other function for that matters). I guess that could be solved through a refactor (e.g: using a decorator somehow but my point) but my point is that it won't be as trivial as expected.

frgfm commented 3 years ago

@florianriche sorry I didn't get your point. Since get_current_user can be changed with get_current_access we will have access to the scopes and group_id for instance ?

Apart from that, let's turn your #137 into the standalone group PR if that's alright with you :)

florianriche commented 3 years ago

What I mean is that you can't pass arguments to get_current_user/get_current_access. So you can't make sure that the resources that is being requested belong to the current user group. You will have to handle that loic directly into the route code. That is doable, just not as clean as altering get_current_user. But maybe I am overlooking somehing.

Agree to alter #137, will do that.

florianriche commented 3 years ago

@pyronear/back-end / @frgfm I am ready to iterate further on that topic but do we agree that we can't use exactly the same mechanism as the "Security" one (see previous message) ? I just want to make sure I understand all the mechanisms you have in mind.

frgfm commented 3 years ago

Yes I agree!

frgfm commented 3 years ago

@pyronear/back-end a few relevant questions:

  1. for tables that do not have an access, should we add group_id field ? (installation, alert, media, event)
  2. How do process group information?

On the second part, here is a suggestion

Route type scope group processing
GET admin None
GET other denied unless the requested object & the access share the same group_id**
POST admin can specify group_id upon creation
POST other group_id automatically set to the same as the access
UPDATE admin can update group_id
UPDATE other denied unless the requested object & the access share the same group_id
DELETE admin None
DELETE other denied unless the requested object & the access share the same group_id and that the route doesn't require admin rights

** For general fetching (not a specific id), it would filter the results

This is just a general suggestion but each route might deserve its own decision.

What do you think?

florianriche commented 3 years ago

Overall I agree with your suggestion. Although I above all agree with the fact we will need to think about it on a route by route basis.

A few comments/questions:

NB: In this implementation, all groups are identical, there is no hierarchy notion. In the future we will need to have another system to manage complex relationships

frgfm commented 3 years ago

Regarding your questions:

Regarding the horizontally of groups: yes, I kept this for another issue but I would suggest having in access: type (user, admin, device), group_id (SDIS 07 vs SDIS 40), level (group manager vs. member)