Cascade for restricted token view-table/view-database/view-instance operations#2154
Cascade for restricted token view-table/view-database/view-instance operations#2154
Conversation
Also includes a prototype implementation of --actor option from #2153 which I'm using for testing this.
|
Can be tested with: pip install https://github.com/simonw/datasette/archive/6d57a8c23043e99b27f7a2afbe58f4d58815fd51.zip |
Codecov ReportPatch coverage:
Additional details and impacted files@@ Coverage Diff @@
## main #2154 +/- ##
==========================================
+ Coverage 92.82% 92.85% +0.03%
==========================================
Files 40 40
Lines 5948 6008 +60
==========================================
+ Hits 5521 5579 +58
- Misses 427 429 +2
☔ View full report in Codecov by Sentry. |
|
Notes on manual testing so far - it looks like this might be working! |
datasette/default_permissions.py
Outdated
| # Special case for view-instance: it's allowed if there are any view-database | ||
| # or view-table permissions defined | ||
| if action == "view-instance": | ||
| all_rules = _r.get("a") or [] | ||
| if ( | ||
| "view-database" in all_rules | ||
| or "vd" in all_rules | ||
| or "view-table" in all_rules | ||
| or "vt" in all_rules | ||
| ): | ||
| return None | ||
| database_rules = _r.get("d") or {} | ||
| for rules in database_rules.values(): | ||
| if ( | ||
| "vd" in rules | ||
| or "view-database" in rules | ||
| or "vt" in rules | ||
| or "view-table" in rules | ||
| ): | ||
| return None | ||
| # Now check resources | ||
| resource_rules = _r.get("r") or {} | ||
| for _database, resources in resource_rules.items(): | ||
| for rules in resources.values(): | ||
| if "vt" in rules or "view-table" in rules: | ||
| return None | ||
|
|
||
| # Special case for view-database: it's allowed if there are any view-table permissions | ||
| # defined within that database | ||
| if action == "view-database": | ||
| database_name = resource | ||
| all_rules = _r.get("a") or [] | ||
| if ( | ||
| "view-database" in all_rules | ||
| or "vd" in all_rules | ||
| or "view-table" in all_rules | ||
| or "vt" in all_rules | ||
| ): | ||
| return None | ||
| database_rules = (_r.get("d") or {}).get(database_name) or {} | ||
| if "vt" in database_rules or "view-table" in database_rules: | ||
| return None | ||
| resource_rules = _r.get("r") or {} | ||
| resources_in_database = resource_rules.get(database_name) or {} | ||
| for rules in resources_in_database.values(): | ||
| if "vt" in rules or "view-table" in rules: | ||
| return None | ||
|
|
||
| if action == "view-table": | ||
| # Can view table if they have view-table in database or instance too | ||
| database_name = resource[0] | ||
| all_rules = _r.get("a") or [] | ||
| if "view-table" in all_rules or "vt" in all_rules: | ||
| return None | ||
| database_rules = (_r.get("d") or {}).get(database_name) or {} | ||
| if "vt" in database_rules or "view-table" in database_rules: | ||
| return None | ||
|
|
There was a problem hiding this comment.
This code is pretty complicated. Maybe it would be simple and better if the fact that a permission cascades like this was modeled on the permission classes here instead:
datasette/datasette/default_permissions.py
Lines 7 to 38 in 2e28258
There was a problem hiding this comment.
Permissions is currently a namedtuple:
datasette/datasette/permissions.py
Lines 3 to 6 in 2e28258
It's used by a few plugins too (post-1.0 alpha) via this plugin hook: https://docs.datasette.io/en/1.0a4/plugin_hooks.html#register-permissions-datasette
There was a problem hiding this comment.
I could add a implies_can_view=False property to that - if it's true, then it means that having this permission implies that you can view the database (if the permission takes_database) and the instance.
There was a problem hiding this comment.
Or... I could have a special subclass of Permission called PermissionImpliesView which is reserved for use by core, and isn't something that's documented for plugins to register their own.
There was a problem hiding this comment.
I'm going to upgrade Permission from a named tuple to a dataclass.
|
Should this have datasette/datasette/default_permissions.py Lines 20 to 22 in d64a989 |
|
Reminder that I also need to confirm that |
|
Code for this might be cleaner with a |
|
The code to refactor is this: datasette/datasette/default_permissions.py Lines 181 to 280 in d64a989 I'm going to turn that into a more general |
|
In that last commit I also upgraded Last step is to refactor the code to use that new property. |
Refs:
Also includes a prototype implementation of
--actor optionwhich I'm using for testing this, from:📚 Documentation preview 📚: https://datasette--2154.org.readthedocs.build/en/2154/