kopia lustrzana https://github.com/simonw/datasette
Refactor breadcrumbs to respect permissions, refs #1831
rodzic
b7fec7f902
commit
1a5e5f2aa9
|
@ -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,
|
||||
|
|
|
@ -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 %}
|
|
@ -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"
|
||||
|
|
|
@ -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 %}
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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 %}
|
||||
|
|
|
@ -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 %}
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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 %}
|
||||
|
|
|
@ -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},
|
||||
]
|
||||
|
|
|
@ -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("/")
|
||||
|
|
Ładowanie…
Reference in New Issue