/-/allow-debug tool, closes #908

This commit is contained in:
Simon Willison 2020-07-24 15:54:41 -07:00
commit 12c0bc09cc
5 changed files with 125 additions and 0 deletions

View file

@ -35,6 +35,7 @@ from .views.special import (
PatternPortfolioView,
AuthTokenView,
LogoutView,
AllowDebugView,
PermissionsDebugView,
MessagesDebugView,
)
@ -869,6 +870,9 @@ class Datasette:
add_route(
MessagesDebugView.as_view(self), r"/-/messages$",
)
add_route(
AllowDebugView.as_view(self), r"/-/allow-debug$",
)
add_route(
PatternPortfolioView.as_view(self), r"/-/patterns$",
)

View file

@ -0,0 +1,58 @@
{% extends "base.html" %}
{% block title %}Debug allow rules{% endblock %}
{% block extra_head %}
<style>
textarea {
height: 8em;
width: 95%;
box-sizing: border-box;
padding: 0.5em;
border: 2px dotted black;
}
.two-col {
display: inline-block;
width: 48%;
}
.two-col label {
width: 48%;
}
p.message-warning {
white-space: pre-wrap;
}
@media only screen and (max-width: 576px) {
.two-col {
width: 100%;
}
}
</style>
{% endblock %}
{% block content %}
<h1>Debug allow rules</h1>
<p>Use this tool to try out different actor and allow combinations. See <a href="https://datasette.readthedocs.io/en/stable/authentication.html#defining-permissions-with-allow-blocks">Defining permissions with "allow" blocks</a> for documentation.</p>
<form action="/-/allow-debug" method="get">
<div class="two-col">
<p><label>Actor</label></p>
<textarea name="actor">{{ actor_input }}</textarea>
</div>
<div class="two-col">
<p><label>Allow block</label></p>
<textarea name="allow">{{ allow_input }}</textarea>
</div>
<div style="margin-top: 1em;">
<input type="submit" value="Apply allow block to actor">
</div>
</form>
{% if error %}<p class="message-warning">{{ error }}</p>{% endif %}
{% if result == "True" %}<p class="message-info">Result: allow</p>{% endif %}
{% if result == "False" %}<p class="message-error">Result: deny</p>{% endif %}
{% endblock %}

View file

@ -1,5 +1,6 @@
import json
from datasette.utils.asgi import Response, Forbidden
from datasette.utils import actor_matches_allow
from .base import BaseView
import secrets
@ -107,6 +108,43 @@ class PermissionsDebugView(BaseView):
)
class AllowDebugView(BaseView):
name = "allow_debug"
def __init__(self, datasette):
self.ds = datasette
async def get(self, request):
errors = []
actor_input = request.args.get("actor") or '{"id": "root"}'
try:
actor = json.loads(actor_input)
actor_input = json.dumps(actor, indent=4)
except json.decoder.JSONDecodeError as ex:
errors.append("Actor JSON error: {}".format(ex))
allow_input = request.args.get("allow") or '{"id": "*"}'
try:
allow = json.loads(allow_input)
allow_input = json.dumps(allow, indent=4)
except json.decoder.JSONDecodeError as ex:
errors.append("Allow JSON error: {}".format(ex))
result = None
if not errors:
result = str(actor_matches_allow(actor, allow))
return await self.render(
["allow_debug.html"],
request,
{
"result": result,
"error": "\n\n".join(errors) if errors else "",
"actor_input": actor_input,
"allow_input": allow_input,
},
)
class MessagesDebugView(BaseView):
name = "messages_debug"