-
-
Notifications
You must be signed in to change notification settings - Fork 813
Description
Spotted this in the code for datasette.permission_allowed():
Lines 906 to 914 in 232a304
| for check in pm.hook.permission_allowed( | |
| datasette=self, | |
| actor=actor, | |
| action=action, | |
| resource=resource, | |
| ): | |
| check = await await_me_maybe(check) | |
| if check is not None: | |
| result = check |
This is effectively saying that the permission hook which "wins" is the last one checked in the sequence.
This is actually new behaviour, introduced in dfdbdf3#diff-83d29b1fb42ebaa92e01122d8142807188ab7b6689697c9defdcdca60ce13bc5L435 - prior to that commit the logic looked like this instead:
Lines 426 to 436 in 57cf513
| action=action, | |
| resource_type=resource_type, | |
| resource_identifier=resource_identifier, | |
| ): | |
| if callable(check): | |
| check = check() | |
| if asyncio.iscoroutine(check): | |
| check = await check | |
| if check is not None: | |
| return check | |
| return default |
So the original logic was first-non-Null-wins, and then I changed it to last-non-Null-wins in dfdbdf3 - but the commit message and issue for that change don't mention it, which makes me think this was a mistake:
I don't think first wins OR last wins are the right solution here, especially given that Pluggy plugin order is a little bit non-deterministic (aside from when plugins use tryfirst= and trylast=).
Instead, I think a better solution would be to run ALL of the hooks and then have these rules:
- If any of them returned
Falsethen the answer isFalse(a veto rule) - Otherwise, if any returned
Truethen the answer isTrue - If all returned
None(no opinion) then the answer is whatever the default is for that permission