diff --git a/snikket_web/admin.py b/snikket_web/admin.py index e6ab070..b21a851 100644 --- a/snikket_web/admin.py +++ b/snikket_web/admin.py @@ -1,4 +1,5 @@ import asyncio +import json import typing from datetime import datetime @@ -69,6 +70,22 @@ async def delete_user(localpart: str) -> typing.Union[str, quart.Response]: ) +@bp.route("/user//debug") +@client.require_admin_session() +async def debug_user(localpart: str) -> typing.Union[str, quart.Response]: + target_user_info = await client.get_user_by_localpart(localpart) + debug_info = json.dumps( + await client.get_user_debug_info(localpart), + indent=2, + sort_keys=True, + ) + return await render_template( + "admin_debug_user.html", + target_user=target_user_info, + debug_dump=debug_info, + ) + + class InvitesListForm(flask_wtf.FlaskForm): # type:ignore action_revoke = wtforms.StringField() diff --git a/snikket_web/prosodyclient.py b/snikket_web/prosodyclient.py index 753c53d..bd27f0d 100644 --- a/snikket_web/prosodyclient.py +++ b/snikket_web/prosodyclient.py @@ -791,6 +791,19 @@ class ProsodyClient: self._raise_error_from_response(resp) return AdminUserInfo.from_api_response(await resp.json()) + @autosession + async def get_user_debug_info( + self, + localpart: str, + *, + session: aiohttp.ClientSession, + ) -> AdminUserInfo: + async with session.get( + self._admin_v1_endpoint("/users/{}/debug".format(localpart)), + ) as resp: + self._raise_error_from_response(resp) + return await resp.json() + @autosession async def delete_user_by_localpart( self, diff --git a/snikket_web/scss/_baseline.scss b/snikket_web/scss/_baseline.scss index 618cd0b..9192a41 100644 --- a/snikket_web/scss/_baseline.scss +++ b/snikket_web/scss/_baseline.scss @@ -14,6 +14,11 @@ p, blockquote, ul, ol, table, dl { color: inherit; } +pre { + line-height: 1.5; + margin: 1.5em 0; +} + blockquote { margin-left: $w-l2; margin-right: $w-l2; diff --git a/snikket_web/scss/app.scss b/snikket_web/scss/app.scss index 51110f1..d1cd3fe 100644 --- a/snikket_web/scss/app.scss +++ b/snikket_web/scss/app.scss @@ -813,11 +813,9 @@ div.elevated { div.elevated > *:first-child { margin-top: 0; - margin-bottom: 0; } div.elevated > *:last-child { - margin-top: 0; margin-bottom: 0; } @@ -870,7 +868,7 @@ ul.inline { margin-right: 0; } - div.elevated { + div.elevated, main > div.box { margin-left: 0; margin-right: 0; } diff --git a/snikket_web/static/img/icons.svg b/snikket_web/static/img/icons.svg index 4419117..b1de9c5 100644 --- a/snikket_web/static/img/icons.svg +++ b/snikket_web/static/img/icons.svg @@ -7,6 +7,11 @@ licensed under the terms of the Apache 2.0 License --> + + + + + diff --git a/snikket_web/templates/admin_debug_user.html b/snikket_web/templates/admin_debug_user.html new file mode 100644 index 0000000..a3745a1 --- /dev/null +++ b/snikket_web/templates/admin_debug_user.html @@ -0,0 +1,23 @@ +{% extends "app.html" %} +{% from "library.j2" import clipboard_button %} +{% block head_lead %} +{{ super() }} +{% include "copy-snippet.html" %} +{% endblock %} +{% block content %} +

{% trans user_name=target_user.localpart %}Debug information for {{ user_name }}{% endtrans %}

+

+
+
{% trans %}Warning{% endtrans %}
+

{% trans %}The below dump may contain sensitive information.{% endtrans %}

+
+
+
{% trans %}Raw debug dump{% endtrans %}
+

{% call clipboard_button(debug_dump, show_label=True, class="primary") -%} + {% trans %}Copy complete output{% endtrans %} + {%- endcall %}

+
+{{ debug_dump }}
+
+{% endblock %} diff --git a/snikket_web/templates/admin_users.html b/snikket_web/templates/admin_users.html index 31aebe4..d0663b7 100644 --- a/snikket_web/templates/admin_users.html +++ b/snikket_web/templates/admin_users.html @@ -23,6 +23,9 @@ {%- call action_button("remove", url_for(".delete_user", localpart=user.localpart), class="secondary") -%} {% trans user_name=user.localpart %}Delete user {{ user_name }}{% endtrans %} {%- endcall -%} + {%- call action_button("bug_report", url_for(".debug_user", localpart=user.localpart), class="secondary") -%} + {% trans user_name=user.localpart %}Show debug information for {{ user_name }}{% endtrans %} + {%- endcall -%} {% endfor %} diff --git a/snikket_web/translations/de/LC_MESSAGES/messages.po b/snikket_web/translations/de/LC_MESSAGES/messages.po index 6a771f0..3c6c4aa 100644 --- a/snikket_web/translations/de/LC_MESSAGES/messages.po +++ b/snikket_web/translations/de/LC_MESSAGES/messages.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: SnikketWeb 0.1.0\n" "Report-Msgid-Bugs-To: jonas@zombofant.net\n" -"POT-Creation-Date: 2021-01-21 16:55+0100\n" +"POT-Creation-Date: 2021-01-21 16:56+0100\n" "PO-Revision-Date: 2020-03-07 16:32+0100\n" "Last-Translator: Jonas Schäfer \n" "Language: de\n" @@ -18,71 +18,71 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 2.9.0\n" -#: snikket_web/admin.py:51 +#: snikket_web/admin.py:52 msgid "Delete user permanently" msgstr "Benutzer endgültig löschen" -#: snikket_web/admin.py:78 +#: snikket_web/admin.py:95 msgid "Invite to circle" msgstr "In Gemeinschaft einladen" -#: snikket_web/admin.py:84 +#: snikket_web/admin.py:101 msgid "At least one circle must be selected" msgstr "Mindestens eine Gemeinschaft muss ausgewählt sein" -#: snikket_web/admin.py:89 +#: snikket_web/admin.py:106 msgid "Valid for" msgstr "Gültig für" -#: snikket_web/admin.py:91 +#: snikket_web/admin.py:108 msgid "One hour" msgstr "Eine Stunde" -#: snikket_web/admin.py:92 +#: snikket_web/admin.py:109 msgid "Twelve hours" msgstr "Zwölf Stunden" -#: snikket_web/admin.py:93 +#: snikket_web/admin.py:110 msgid "One day" msgstr "Ein Tag" -#: snikket_web/admin.py:94 +#: snikket_web/admin.py:111 msgid "One week" msgstr "Eine Woche" -#: snikket_web/admin.py:95 +#: snikket_web/admin.py:112 msgid "Four weeks" msgstr "Vier Wochen" -#: snikket_web/admin.py:101 +#: snikket_web/admin.py:118 msgid "Allow multiple uses" msgstr "Mehrfach verwendbar" -#: snikket_web/admin.py:105 +#: snikket_web/admin.py:122 msgid "New invitation link" msgstr "Neuer Einladungslink" -#: snikket_web/admin.py:163 +#: snikket_web/admin.py:180 msgid "Revoke" msgstr "Löschen" -#: snikket_web/admin.py:214 snikket_web/admin.py:257 +#: snikket_web/admin.py:231 snikket_web/admin.py:274 msgid "Name" msgstr "Name" -#: snikket_web/admin.py:218 snikket_web/templates/admin_circles.html:42 +#: snikket_web/admin.py:235 snikket_web/templates/admin_circles.html:42 msgid "Create circle" msgstr "Gemeinschaft gründen" -#: snikket_web/admin.py:261 snikket_web/user.py:68 +#: snikket_web/admin.py:278 snikket_web/user.py:68 msgid "Apply" msgstr "Übernehmen" -#: snikket_web/admin.py:265 +#: snikket_web/admin.py:282 msgid "Delete circle permanently" msgstr "Gemeinschaft endgültig löschen" -#: snikket_web/infra.py:41 +#: snikket_web/infra.py:40 msgid "Main" msgstr "Kern" @@ -213,6 +213,28 @@ msgstr "" "Erzeuge eine neue Einladung um mehr Benutzer auf deine Snikket-Instanz " "einzuladen indem du den folgenden Button klickst." +#: snikket_web/templates/admin_debug_user.html:8 +#, python-format +msgid "Debug information for %(user_name)s" +msgstr "Debugging-Informationen für %(user_name)s" + +#: snikket_web/templates/admin_debug_user.html:11 +#: snikket_web/templates/user_passwd.html:36 +msgid "Warning" +msgstr "Warnung" + +#: snikket_web/templates/admin_debug_user.html:12 +msgid "The below dump may contain sensitive information." +msgstr "Die untenstehende Ausgabe könnte persönliche Informationen enthalten." + +#: snikket_web/templates/admin_debug_user.html:15 +msgid "Raw debug dump" +msgstr "Rohe Debug-Ausgabe" + +#: snikket_web/templates/admin_debug_user.html:17 +msgid "Copy complete output" +msgstr "Komplette Ausgabe kopieren" + #: snikket_web/templates/admin_delete_user.html:4 #: snikket_web/templates/admin_users.html:24 #, python-format @@ -434,6 +456,11 @@ msgstr "Derzeit gibt es keine ausstehenden Einladungen." msgid "Phone number" msgstr "Telefonnummer" +#: snikket_web/templates/admin_users.html:27 +#, python-format +msgid "Show debug information for %(user_name)s" +msgstr "Debugging-Informationen für %(user_name)s anzeigen" + #: snikket_web/templates/app.html:4 msgid "Snikket Web Portal" msgstr "Snikket Webportal" @@ -570,10 +597,6 @@ msgstr "" msgid "Password change failed" msgstr "Passwortänderung fehlgeschlagen" -#: snikket_web/templates/user_passwd.html:36 -msgid "Warning" -msgstr "Warnung" - #: snikket_web/templates/user_passwd.html:37 msgid "" "After changing your password, you will have to enter the new password on " diff --git a/snikket_web/translations/en/LC_MESSAGES/messages.po b/snikket_web/translations/en/LC_MESSAGES/messages.po index ca18fdf..fb4bfdb 100644 --- a/snikket_web/translations/en/LC_MESSAGES/messages.po +++ b/snikket_web/translations/en/LC_MESSAGES/messages.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2021-01-21 16:55+0100\n" +"POT-Creation-Date: 2021-01-21 16:56+0100\n" "PO-Revision-Date: 2020-03-07 16:50+0100\n" "Last-Translator: FULL NAME \n" "Language: en\n" @@ -18,71 +18,71 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 2.9.0\n" -#: snikket_web/admin.py:51 +#: snikket_web/admin.py:52 msgid "Delete user permanently" msgstr "" -#: snikket_web/admin.py:78 +#: snikket_web/admin.py:95 msgid "Invite to circle" msgstr "" -#: snikket_web/admin.py:84 +#: snikket_web/admin.py:101 msgid "At least one circle must be selected" msgstr "" -#: snikket_web/admin.py:89 +#: snikket_web/admin.py:106 msgid "Valid for" msgstr "" -#: snikket_web/admin.py:91 +#: snikket_web/admin.py:108 msgid "One hour" msgstr "" -#: snikket_web/admin.py:92 +#: snikket_web/admin.py:109 msgid "Twelve hours" msgstr "" -#: snikket_web/admin.py:93 +#: snikket_web/admin.py:110 msgid "One day" msgstr "" -#: snikket_web/admin.py:94 +#: snikket_web/admin.py:111 msgid "One week" msgstr "" -#: snikket_web/admin.py:95 +#: snikket_web/admin.py:112 msgid "Four weeks" msgstr "" -#: snikket_web/admin.py:101 +#: snikket_web/admin.py:118 msgid "Allow multiple uses" msgstr "" -#: snikket_web/admin.py:105 +#: snikket_web/admin.py:122 msgid "New invitation link" msgstr "" -#: snikket_web/admin.py:163 +#: snikket_web/admin.py:180 msgid "Revoke" msgstr "" -#: snikket_web/admin.py:214 snikket_web/admin.py:257 +#: snikket_web/admin.py:231 snikket_web/admin.py:274 msgid "Name" msgstr "" -#: snikket_web/admin.py:218 snikket_web/templates/admin_circles.html:42 +#: snikket_web/admin.py:235 snikket_web/templates/admin_circles.html:42 msgid "Create circle" msgstr "" -#: snikket_web/admin.py:261 snikket_web/user.py:68 +#: snikket_web/admin.py:278 snikket_web/user.py:68 msgid "Apply" msgstr "" -#: snikket_web/admin.py:265 +#: snikket_web/admin.py:282 msgid "Delete circle permanently" msgstr "" -#: snikket_web/infra.py:41 +#: snikket_web/infra.py:40 msgid "Main" msgstr "" @@ -211,6 +211,28 @@ msgid "" "instance by clicking the button below." msgstr "" +#: snikket_web/templates/admin_debug_user.html:8 +#, fuzzy, python-format +msgid "Debug information for %(user_name)s" +msgstr "Welcome home, %(user_name)s." + +#: snikket_web/templates/admin_debug_user.html:11 +#: snikket_web/templates/user_passwd.html:36 +msgid "Warning" +msgstr "Warning" + +#: snikket_web/templates/admin_debug_user.html:12 +msgid "The below dump may contain sensitive information." +msgstr "" + +#: snikket_web/templates/admin_debug_user.html:15 +msgid "Raw debug dump" +msgstr "" + +#: snikket_web/templates/admin_debug_user.html:17 +msgid "Copy complete output" +msgstr "" + #: snikket_web/templates/admin_delete_user.html:4 #: snikket_web/templates/admin_users.html:24 #, python-format @@ -421,6 +443,11 @@ msgstr "" msgid "Phone number" msgstr "" +#: snikket_web/templates/admin_users.html:27 +#, fuzzy, python-format +msgid "Show debug information for %(user_name)s" +msgstr "Welcome home, %(user_name)s." + #: snikket_web/templates/app.html:4 msgid "Snikket Web Portal" msgstr "" @@ -546,10 +573,6 @@ msgstr "" msgid "Password change failed" msgstr "" -#: snikket_web/templates/user_passwd.html:36 -msgid "Warning" -msgstr "" - #: snikket_web/templates/user_passwd.html:37 msgid "" "After changing your password, you will have to enter the new password on " diff --git a/tools/icons.list b/tools/icons.list index 644730a..3843c6e 100644 --- a/tools/icons.list +++ b/tools/icons.list @@ -1,4 +1,5 @@ action/account_circle:profile +action/bug_report:bug_report action/done:done action/logout:logout action/login:login