Add UI for exporting user account data

This commit is contained in:
Matthew Wild
2022-01-10 14:20:33 +00:00
committed by Jonas Schäfer
parent e18f727db0
commit 275b302531
3 changed files with 71 additions and 0 deletions

View File

@@ -30,6 +30,7 @@
<div>
<div>{% call standard_button("edit", url_for(".profile"), class="primary") %}{% trans %}Edit profile{% endtrans %}{% endcall %}</div>
<div>{% call standard_button("passwd", url_for(".change_pw"), class="secondary") %}{% trans %}Change password{% endtrans %}{% endcall %}</div>
<div>{% call standard_button("folder", url_for(".manage_data"), class="secondary") %}{% trans %}Manage your data{% endtrans %}{% endcall %}</div>
</div>
{#- -#}
</li>

View File

@@ -0,0 +1,23 @@
{% extends "app.html" %}
{% from "library.j2" import standard_button, form_button, render_errors, avatar with context %}
{% block content %}
<h1>{% trans %}Manage your data{% endtrans %}</h1>
<p>{% trans user_name=user_info.display_name %}Welcome home, {{ user_name }}.{% endtrans %}</p>
<nav class="welcome">
<ul>
<li>
<h2>{% trans %}Export account{% endtrans %}</h2>
<p>{% trans %}Download your account data as a file for backup purposes or to move your account to another service.{% endtrans %}</p>
{% call render_errors(form) %}{% endcall %}
<div class="f-bbox">
<form method="POST">
{{ form.csrf_token }}
{%- call form_button("download", form.action_export, class="primary") %}{% endcall -%}
</form>
</div>
</li>
</ul>
</nav>
{% endblock %}

View File

@@ -1,9 +1,12 @@
import aiohttp
import asyncio
import typing
import urllib
import quart.flask_patch
from quart import (
Blueprint,
Response,
render_template,
request,
redirect,
@@ -168,6 +171,50 @@ async def profile() -> typing.Union[str, quart.Response]:
avatar_too_big_warning=EAVATARTOOBIG)
class DataExportForm(BaseForm):
action_export = wtforms.SubmitField(
_l("Export")
)
@bp.route("/manage_data", methods=["GET", "POST"])
@client.require_session()
async def manage_data() -> typing.Union[str, quart.Response]:
form = DataExportForm()
if form.validate_on_submit():
user_info = await client.get_user_info()
# The UTF-8 version of the filename needs to be percent-encoded
encoded_address = urllib.parse.quote(
user_info["address"].encode(encoding='utf-8', errors='strict')
)
try:
account_data = await client.export_account_data()
except aiohttp.ClientResponseError as e:
if e.status == 404:
await flash(
_("You currently have no account data to export."),
"alert"
)
else:
raise e
else:
return Response(account_data,
mimetype="application/xml",
headers={
# We provide the UTF-8 filename, but the ASCII
# one will be used as a fallback for legacy
# browsers (RFC 5987)
"Content-Disposition": (
'attachment; filename="account-data.xml"; '
'filename*="UTF-8\'\'account-data-{}.xml"'
).format(encoded_address)
})
return await render_template("user_manage_data.html",
form=form,
)
@bp.route("/logout", methods=["GET", "POST"])
@client.require_session()
async def logout() -> typing.Union[quart.Response, str]: