(text "{% extends \"root.html\" %} {% block head %}") (title (text "{{ app.title }} - {{ config.name }}")) (text "{% endblock %} {% block body %} {{ macros::nav() }}") (main ("class" "flex flex-col gap-2") (div ("class" "w-full flex flex-col gap-2") (div ("class" "card-nest") (div ("class" "card flex flex-col gap-2") (h4 (text "Would you like to allow \"{{ app.title }}\" to access your account?")) (p (text "This app is requesting the following permissions on your account:")) (div ("class" "card") (ul (text "{% for scope in app.scopes -%}") (li (a ("href" "https://tetratto.com/reference/tetratto/model/oauth/enum.AppScope.html#variant.{{ scope }}") ("target" "_blank") (text "{{ scope }}"))) (text "{%- endfor %}"))) (p (text "You can revoke this app's permissions at any time through your connection settings."))) (div ("class" "card flex gap-2") (button ("onclick" "authorize()") (str (text "developer:action.authorize"))) (a ("class" "button secondary") ("href" "javascript:window.close()") (str (text "dialog:action.cancel"))))))) (script (text "setTimeout(() => { globalThis.authorize = async (event) => { if ( !(await trigger(\"atto::confirm\", [ \"Are you sure you would like to do this?\", ])) ) { return; } const verifier = await trigger(\"connections::pkce_verifier\", [ 128, ]); const challenge = await trigger(\"connections::pkce_challenge\", [ verifier, ]); fetch(\"/api/v1/apps/{{ app.id }}/grant\", { method: \"POST\", headers: { \"Content-Type\": \"application/json\", }, body: JSON.stringify({ challenge }) }) .then((res) => res.json()) .then((res) => { trigger(\"atto::toast\", [ res.ok ? \"success\" : \"error\", res.message, ]); if (res.ok) { const search = new URLSearchParams(window.location.search); search.append(\"verifier\", verifier); search.append(\"token\", res.payload); window.location.href = `{{ app.redirect|remove_script_tags|safe }}?${search.toString()}`; } }); }; }, 250);")) (text "{% endblock %}")