Refactor breadcrumbs to respect permissions, refs #1831

pull/1842/head
Simon Willison 2022-10-13 14:42:52 -07:00
rodzic b7fec7f902
commit 1a5e5f2aa9
13 zmienionych plików z 65 dodań i 59 usunięć

Wyświetl plik

@ -631,6 +631,44 @@ class Datasette:
else:
return []
async def _crumb_items(self, request, table=None, database=None):
crumbs = []
# Top-level link
if await self.permission_allowed(
actor=request.actor, action="view-instance", default=True
):
crumbs.append({"href": self.urls.instance(), "label": "home"})
# Database link
if database:
if await self.permission_allowed(
actor=request.actor,
action="view-database",
resource=database,
default=True,
):
crumbs.append(
{
"href": self.urls.database(database),
"label": database,
}
)
# Table link
if table:
assert database, "table= requires database="
if await self.permission_allowed(
actor=request.actor,
action="view-table",
resource=(database, table),
default=True,
):
crumbs.append(
{
"href": self.urls.table(database, table),
"label": table,
}
)
return crumbs
async def permission_allowed(self, actor, action, resource=None, default=False):
"""Check permissions using the permissions_allowed plugin hook"""
result = None
@ -1009,6 +1047,8 @@ class Datasette:
template_context = {
**context,
**{
"request": request,
"crumb_items": self._crumb_items,
"urls": self.urls,
"actor": request.actor if request else None,
"menu_links": menu_links,

Wyświetl plik

@ -0,0 +1,15 @@
{% macro nav(request, database=None, table=None) -%}
{% if crumb_items is defined %}
{% set items=crumb_items(request=request, database=database, table=table) %}
{% if items %}
<p class="crumbs">
{% for item in items %}
<a href="{{ item.href }}">{{ item.label }}</a>
{% if not loop.last %}
/
{% endif %}
{% endfor %}
</p>
{% endif %}
{% endif %}
{%- endmacro %}

Wyświetl plik

@ -1,4 +1,4 @@
<!DOCTYPE html>
{% import "_crumbs.html" as crumbs with context %}<!DOCTYPE html>
<html>
<head>
<title>{% block title %}{% endblock %}</title>
@ -17,7 +17,7 @@
</head>
<body class="{% block body_class %}{% endblock %}">
<div class="not-footer">
<header><nav>{% block nav %}
<header><nav>{% block nav %}{% block crumbs %}{{ crumbs.nav(request=request) }}{% endblock %}
{% set links = menu_links() %}{% if links or show_logout %}
<details class="nav-menu">
<summary><svg aria-labelledby="nav-menu-svg-title" role="img"

Wyświetl plik

@ -9,16 +9,7 @@
{% block body_class %}db db-{{ database|to_css_class }}{% endblock %}
{% block nav %}
<p class="crumbs">
<a href="{{ urls.instance() }}">home</a>
</p>
{{ super() }}
{% endblock %}
{% block content %}
<div class="page-header" style="border-color: #{{ database_color(database) }}">
<h1>{{ metadata.title or database }}{% if private %} 🔒{% endif %}</h1>
{% set links = database_actions() %}{% if links %}

Wyświetl plik

@ -2,13 +2,6 @@
{% block title %}{% if title %}{{ title }}{% else %}Error {{ status }}{% endif %}{% endblock %}
{% block nav %}
<p class="crumbs">
<a href="{{ urls.instance() }}">home</a>
</p>
{{ super() }}
{% endblock %}
{% block content %}
<h1>{% if title %}{{ title }}{% else %}Error {{ status }}{% endif %}</h1>

Wyświetl plik

@ -2,13 +2,6 @@
{% block title %}Log out{% endblock %}
{% block nav %}
<p class="crumbs">
<a href="{{ base_url }}">home</a>
</p>
{{ super() }}
{% endblock %}
{% block content %}
<h1>Log out</h1>

Wyświetl plik

@ -22,13 +22,6 @@
</style>
{% endblock %}
{% block nav %}
<p class="crumbs">
<a href="{{ base_url }}">home</a>
</p>
{{ super() }}
{% endblock %}
{% block content %}
<h1>Recent permissions checks</h1>

Wyświetl plik

@ -18,12 +18,8 @@
{% block body_class %}query db-{{ database|to_css_class }}{% if canned_query %} query-{{ canned_query|to_css_class }}{% endif %}{% endblock %}
{% block nav %}
<p class="crumbs">
<a href="{{ urls.instance() }}">home</a> /
<a href="{{ urls.database(database) }}">{{ database }}</a>
</p>
{{ super() }}
{% block crumbs %}
{{ crumbs.nav(request=request, database=database) }}
{% endblock %}
{% block content %}

Wyświetl plik

@ -15,13 +15,8 @@
{% block body_class %}row db-{{ database|to_css_class }} table-{{ table|to_css_class }}{% endblock %}
{% block nav %}
<p class="crumbs">
<a href="{{ urls.instance() }}">home</a> /
<a href="{{ urls.database(database) }}">{{ database }}</a> /
<a href="{{ urls.table(database, table) }}">{{ table }}</a>
</p>
{{ super() }}
{% block crumbs %}
{{ crumbs.nav(request=request, database=database, table=table) }}
{% endblock %}
{% block content %}

Wyświetl plik

@ -4,13 +4,6 @@
{% block body_class %}show-json{% endblock %}
{% block nav %}
<p class="crumbs">
<a href="{{ urls.instance() }}">home</a>
</p>
{{ super() }}
{% endblock %}
{% block content %}
<h1>{{ filename }}</h1>

Wyświetl plik

@ -16,12 +16,8 @@
{% block body_class %}table db-{{ database|to_css_class }} table-{{ table|to_css_class }}{% endblock %}
{% block nav %}
<p class="crumbs">
<a href="{{ urls.instance() }}">home</a> /
<a href="{{ urls.database(database) }}">{{ database }}</a>
</p>
{{ super() }}
{% block crumbs %}
{{ crumbs.nav(request=request, database=database) }}
{% endblock %}
{% block content %}

Wyświetl plik

@ -333,6 +333,7 @@ def test_permissions_debug(app_client):
{"action": "permissions-debug", "result": True, "used_default": False},
{"action": "view-instance", "result": None, "used_default": True},
{"action": "debug-menu", "result": False, "used_default": True},
{"action": "view-instance", "result": True, "used_default": True},
{"action": "permissions-debug", "result": False, "used_default": True},
{"action": "view-instance", "result": None, "used_default": True},
]

Wyświetl plik

@ -845,7 +845,7 @@ def test_hook_menu_links(app_client):
def get_menu_links(html):
soup = Soup(html, "html.parser")
return [
{"label": a.text, "href": a["href"]} for a in soup.find("nav").select("a")
{"label": a.text, "href": a["href"]} for a in soup.select(".nav-menu a")
]
response = app_client.get("/")