Closed frgfm closed 3 years ago
Hi @florianriche :wave:
I had the occasion to think about this over the weekend and here is my suggestion !
I think we would benefit from splitting the work into the following PRs:
id
, name
(make a first PR with this + unittests, I suggest adapting #137 for this)id
, login
, hashed_password
, type
(formerly "scopes"), group_id
(so that we could dynamically link a user/device to a group) #144group_id
field (#147)Security
, if we want to protect a GET route to the group, we would require to have either the admin
access type (fetching everything) or by checking the group_id, we limit results to the one accessible to this group Any thoughts @pyronear/back-end ?
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.
@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 :)
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.
@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.
Yes I agree!
@pyronear/back-end a few relevant questions:
group_id
field ? (installation, alert, media, event)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?
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
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)
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:
groups
table withgroup_id
, andgroup_name
)