You've already forked snikket-web-portal
Compare commits
34 Commits
feature/ap
...
feature/ac
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
958b3365f7 | ||
|
|
05caf38d37 | ||
|
|
390ecded42 | ||
|
|
f6395d4d9c | ||
|
|
32179c72cd | ||
|
|
3cb8185b1a | ||
|
|
481379d03f | ||
|
|
275b302531 | ||
|
|
e18f727db0 | ||
|
|
f7429413cd | ||
|
|
aed9ad1cde | ||
|
|
b545c137b1 | ||
|
|
47642dc384 | ||
|
|
5d7183a0b8 | ||
|
|
c1cf6ab1e5 | ||
|
|
aee53a2e1a | ||
|
|
3a81a0140b | ||
|
|
5b4d4ddd36 | ||
|
|
28ff19c19c | ||
|
|
8e3837f704 | ||
|
|
98e7de3166 | ||
|
|
61c71b2145 | ||
|
|
6b35e9a259 | ||
|
|
58c2112fec | ||
|
|
c856afee82 | ||
|
|
c8356a8e9e | ||
|
|
0eb464f428 | ||
|
|
2a6ef3c8f1 | ||
|
|
b5d148458a | ||
|
|
ff99c9488a | ||
|
|
fe78631039 | ||
|
|
12ddd288bf | ||
|
|
633fb0d084 | ||
|
|
f9690063bc |
55
Dockerfile
55
Dockerfile
@@ -1,7 +1,13 @@
|
||||
FROM debian:buster-slim
|
||||
FROM debian:bullseye-slim AS build
|
||||
|
||||
ARG BUILD_SERIES=dev
|
||||
ARG BUILD_ID=0
|
||||
RUN set -eu; \
|
||||
export DEBIAN_FRONTEND=noninteractive ; \
|
||||
apt-get update ; \
|
||||
apt-get install -y --no-install-recommends \
|
||||
python3 python3-pip python3-setuptools python3-wheel \
|
||||
libpython3-dev \
|
||||
make build-essential \
|
||||
netcat;
|
||||
|
||||
COPY requirements.txt /opt/snikket-web-portal/requirements.txt
|
||||
COPY build-requirements.txt /opt/snikket-web-portal/build-requirements.txt
|
||||
@@ -11,32 +17,41 @@ COPY babel.cfg /opt/snikket-web-portal/babel.cfg
|
||||
|
||||
WORKDIR /opt/snikket-web-portal
|
||||
|
||||
RUN set -eu; \
|
||||
export DEBIAN_FRONTEND=noninteractive ; \
|
||||
apt-get update ; \
|
||||
apt-get install -y --no-install-recommends \
|
||||
python3 python3-pip python3-setuptools python3-wheel \
|
||||
libpython3-dev \
|
||||
make build-essential \
|
||||
netcat \
|
||||
; \
|
||||
pip3 install -r requirements.txt; \
|
||||
RUN pip3 install -r requirements.txt; \
|
||||
pip3 install -r build-requirements.txt; \
|
||||
make; \
|
||||
pip3 uninstall -yr build-requirements.txt; \
|
||||
apt-get remove -y build-essential make libpython3-dev; \
|
||||
apt-get autoremove -y; \
|
||||
pip3 install hypercorn; \
|
||||
rm -rf /root/.cache; \
|
||||
apt-get clean ; rm -rf /var/lib/apt/lists
|
||||
make;
|
||||
|
||||
|
||||
FROM debian:bullseye-slim
|
||||
|
||||
ARG BUILD_SERIES=dev
|
||||
ARG BUILD_ID=0
|
||||
|
||||
COPY docker/env.py /etc/snikket-web-portal/env.py
|
||||
|
||||
ENV SNIKKET_WEB_PYENV=/etc/snikket-web-portal/env.py
|
||||
|
||||
ENV SNIKKET_WEB_PROSODY_ENDPOINT=http://127.0.0.1:5280/
|
||||
|
||||
HEALTHCHECK CMD nc -zv ${SNIKKET_TWEAK_PORTAL_INTERNAL_HTTP_INTERFACE:-127.0.0.1} ${SNIKKET_TWEAK_PORTAL_INTERNAL_HTTP_PORT:-5765}
|
||||
|
||||
RUN set -eu; \
|
||||
export DEBIAN_FRONTEND=noninteractive ; \
|
||||
apt-get update ; \
|
||||
apt-get install -y --no-install-recommends \
|
||||
python3 python3-pip python3-setuptools python3-wheel; \
|
||||
apt-get clean ; rm -rf /var/lib/apt/lists; \
|
||||
pip3 install hypercorn; \
|
||||
rm -rf /root/.cache;
|
||||
|
||||
WORKDIR /opt/snikket-web-portal
|
||||
|
||||
COPY requirements.txt /opt/snikket-web-portal/requirements.txt
|
||||
RUN pip3 install -r requirements.txt; rm -rf /root/.cache;
|
||||
|
||||
COPY --from=build /opt/snikket-web-portal/snikket_web/ /opt/snikket-web-portal/snikket_web
|
||||
COPY babel.cfg /opt/snikket-web-portal/babel.cfg
|
||||
|
||||
RUN echo "$BUILD_SERIES $BUILD_ID" > /opt/snikket-web-portal/.app_version
|
||||
|
||||
ADD docker/entrypoint.sh /entrypoint.sh
|
||||
|
||||
@@ -5,4 +5,5 @@ hsluv~=0.0.2
|
||||
flask-babel~=1.0
|
||||
email-validator~=1.1
|
||||
environ-config~=20.0
|
||||
wtforms~=2.3
|
||||
typing-extensions
|
||||
|
||||
@@ -63,9 +63,6 @@ async def users() -> str:
|
||||
)
|
||||
|
||||
|
||||
_LIMITED_ROLE_NAME = _("Limited")
|
||||
|
||||
|
||||
class EditUserForm(BaseForm):
|
||||
localpart = wtforms.StringField(
|
||||
_l("Login name"),
|
||||
@@ -78,9 +75,7 @@ class EditUserForm(BaseForm):
|
||||
role = wtforms.RadioField(
|
||||
_l("Access Level"),
|
||||
choices=[
|
||||
# NOTE: enable this only after something has been done which
|
||||
# actually enforces the described restrictions :).
|
||||
# ("prosody:restricted", _LIMITED_ROLE_NAME),
|
||||
("prosody:restricted", _("Limited")),
|
||||
("prosody:normal", _l("Normal user")),
|
||||
("prosody:admin", _l("Administrator")),
|
||||
],
|
||||
|
||||
@@ -10,13 +10,14 @@ from quart import (
|
||||
current_app,
|
||||
render_template,
|
||||
redirect,
|
||||
request,
|
||||
url_for,
|
||||
session as http_session,
|
||||
)
|
||||
|
||||
import wtforms
|
||||
|
||||
from flask_babel import lazy_gettext as _l
|
||||
from flask_babel import lazy_gettext as _l, gettext
|
||||
|
||||
from .infra import client, selected_locale, BaseForm
|
||||
|
||||
@@ -26,6 +27,11 @@ bp = Blueprint("invite", __name__)
|
||||
|
||||
INVITE_SESSION_JID = "invite-session-jid"
|
||||
|
||||
MAX_IMPORT_DATA_SIZE = 5*1024*1024 # 5MB
|
||||
SUPPORTED_IMPORT_TYPES = ["application/xml", "text/xml"]
|
||||
|
||||
EIMPORTTOOBIG = _l("The account data you tried to import is too large to"
|
||||
"upload. Please contact your Snikket operator.")
|
||||
|
||||
# https://play.google.com/store/apps/details?id=org.snikket.android&referrer={uri|urlescape}&pcampaignid=pcampaignidMKT-Other-global-all-co-prtnr-py-PartBadge-Mar2515-1
|
||||
|
||||
@@ -163,6 +169,7 @@ async def register(id_: str) -> typing.Union[str, quart.Response]:
|
||||
raise
|
||||
else:
|
||||
http_session[INVITE_SESSION_JID] = jid
|
||||
await client.login(jid, form.password.data)
|
||||
return redirect(url_for(".success"))
|
||||
|
||||
return await render_template(
|
||||
@@ -232,11 +239,55 @@ async def reset(id_: str) -> typing.Union[str, quart.Response]:
|
||||
)
|
||||
|
||||
|
||||
class DataImportForm(BaseForm):
|
||||
account_data_file = wtforms.FileField(
|
||||
_l("Account data file")
|
||||
)
|
||||
|
||||
action_import = wtforms.SubmitField(
|
||||
_l("Import data")
|
||||
)
|
||||
|
||||
|
||||
@bp.route("/success", methods=["GET", "POST"])
|
||||
@client.require_session()
|
||||
async def success() -> str:
|
||||
form = DataImportForm()
|
||||
if form.validate_on_submit():
|
||||
ok = True
|
||||
file_info = (await request.files).get(form.account_data_file.name)
|
||||
if file_info is not None:
|
||||
mimetype = file_info.mimetype
|
||||
data = file_info.stream.read()
|
||||
if len(data) > MAX_IMPORT_DATA_SIZE:
|
||||
form.account_data_file.errors.append(EIMPORTTOOBIG)
|
||||
ok = False
|
||||
elif mimetype not in SUPPORTED_IMPORT_TYPES:
|
||||
form.account_data_file.errors.append(
|
||||
# not breaking the line here to avoid extract
|
||||
# translations failing (defensive)
|
||||
gettext("The account data you tried to import is in an unknown format. Please upload an XML file in XEP-0227 format (provided format: %(mimetype)s).", mimetype=mimetype), # noqa:E501
|
||||
)
|
||||
ok = False
|
||||
elif len(data) > 0:
|
||||
await client.import_account_data(data)
|
||||
|
||||
if ok:
|
||||
# Re-render success page, this time with no import option
|
||||
return await render_template(
|
||||
"invite_success.html",
|
||||
jid=http_session.get(INVITE_SESSION_JID, ""),
|
||||
migration_success=True,
|
||||
)
|
||||
|
||||
return await render_template(
|
||||
"invite_success.html",
|
||||
jid=http_session.get(INVITE_SESSION_JID, ""),
|
||||
migration_success=False,
|
||||
form=form,
|
||||
max_import_size=MAX_IMPORT_DATA_SIZE,
|
||||
import_too_big_warning_header=_l("Error"),
|
||||
import_too_big_warning=EIMPORTTOOBIG,
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -296,6 +296,9 @@ class ProsodyClient:
|
||||
def _public_v1_endpoint(self, subpath: str) -> str:
|
||||
return "{}/register_api{}".format(self._endpoint_base, subpath)
|
||||
|
||||
def _xep227_endpoint(self, subpath: str) -> str:
|
||||
return "{}/xep227{}".format(self._endpoint_base, subpath)
|
||||
|
||||
async def _oauth2_bearer_token(self,
|
||||
session: aiohttp.ClientSession,
|
||||
jid: str,
|
||||
@@ -1121,6 +1124,34 @@ class ProsodyClient:
|
||||
) as resp:
|
||||
self._raise_error_from_response(resp)
|
||||
|
||||
@autosession
|
||||
async def export_account_data(
|
||||
self,
|
||||
*,
|
||||
session: aiohttp.ClientSession,
|
||||
) -> typing.Optional[str]:
|
||||
async with session.get(
|
||||
self._xep227_endpoint("/export?stores=roster,vcard,pep,pep_data"), # noqa:E501
|
||||
) as resp:
|
||||
self._raise_error_from_response(resp)
|
||||
if resp.status == 204:
|
||||
return None
|
||||
return await resp.text()
|
||||
|
||||
@autosession
|
||||
async def import_account_data(
|
||||
self,
|
||||
user_xml: str,
|
||||
*,
|
||||
session: aiohttp.ClientSession,
|
||||
) -> bool:
|
||||
async with session.put(
|
||||
self._xep227_endpoint("/import?stores=roster,vcard,pep,pep_data"), # noqa:E501
|
||||
data=user_xml,
|
||||
) as resp:
|
||||
self._raise_error_from_response(resp)
|
||||
return True
|
||||
|
||||
@autosession
|
||||
async def revoke_token(
|
||||
self,
|
||||
|
||||
@@ -42,6 +42,11 @@ licensed under the terms of the Apache 2.0 License -->
|
||||
<g fill="none"><path d="M0 0h24v24H0V0z" /><path d="M0 0h24v24H0V0z" opacity=".87" /></g>
|
||||
<path d="M18 8h-1V6c0-2.76-2.24-5-5-5S7 3.24 7 6v2H6c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V10c0-1.1-.9-2-2-2zm-6 9c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2zM9 8V6c0-1.66 1.34-3 3-3s3 1.34 3 3v2H9z" />
|
||||
</symbol>
|
||||
<!-- from: communication/import_export/materialiconsround/24px.svg -->
|
||||
<symbol id="icon-import_export" viewBox="0 0 24 24">
|
||||
<path d="M0 0h24v24H0V0z" fill="none" />
|
||||
<path d="M8.65 3.35L5.86 6.14c-.32.31-.1.85.35.85H8V13c0 .55.45 1 1 1s1-.45 1-1V6.99h1.79c.45 0 .67-.54.35-.85L9.35 3.35c-.19-.19-.51-.19-.7 0zM16 17.01V11c0-.55-.45-1-1-1s-1 .45-1 1v6.01h-1.79c-.45 0-.67.54-.35.85l2.79 2.78c.2.19.51.19.71 0l2.79-2.78c.32-.31.09-.85-.35-.85H16z" />
|
||||
</symbol>
|
||||
<!-- from: communication/qr_code/materialiconsround/24px.svg -->
|
||||
<symbol id="icon-qrcode" viewBox="0 0 24 24">
|
||||
<g><rect fill="none" height="24" width="24" /><rect fill="none" height="24" width="24" /></g>
|
||||
@@ -88,6 +93,21 @@ licensed under the terms of the Apache 2.0 License -->
|
||||
<path d="M0 0h24v24H0V0z" fill="none" />
|
||||
<path d="M3.4 20.4l17.45-7.48c.81-.35.81-1.49 0-1.84L3.4 3.6c-.66-.29-1.39.2-1.39.91L2 9.12c0 .5.37.93.87.99L17 12 2.87 13.88c-.5.07-.87.5-.87 1l.01 4.61c0 .71.73 1.2 1.39.91z" />
|
||||
</symbol>
|
||||
<!-- from: file/file_download/materialicons/24px.svg -->
|
||||
<symbol id="icon-download" viewBox="0 0 24 24">
|
||||
<path d="M0 0h24v24H0z" fill="none" />
|
||||
<path d="M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z" />
|
||||
</symbol>
|
||||
<!-- from: file/file_upload/materialicons/24px.svg -->
|
||||
<symbol id="icon-upload" viewBox="0 0 24 24">
|
||||
<path d="M0 0h24v24H0z" fill="none" />
|
||||
<path d="M9 16h6v-6h4l-7-7-7 7h4zm-4 2h14v2H5z" />
|
||||
</symbol>
|
||||
<!-- from: file/folder/materialiconsround/24px.svg -->
|
||||
<symbol id="icon-folder" viewBox="0 0 24 24">
|
||||
<path d="M0 0h24v24H0V0z" fill="none" />
|
||||
<path d="M10.59 4.59C10.21 4.21 9.7 4 9.17 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2h-8l-1.41-1.41z" />
|
||||
</symbol>
|
||||
<!-- from: navigation/arrow_back/materialiconsround/24px.svg -->
|
||||
<symbol id="icon-back" viewBox="0 0 24 24">
|
||||
<path d="M0 0h24v24H0V0z" fill="none" />
|
||||
|
||||
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 18 KiB |
@@ -1,6 +1,6 @@
|
||||
{% extends "invite.html" %}
|
||||
{% set body_id = "invite" %}
|
||||
{% from "library.j2" import form_button, clipboard_button %}
|
||||
{% from "library.j2" import form_button, clipboard_button, render_errors %}
|
||||
{% block head_lead %}
|
||||
<title>{% trans site_name=config["SITE_NAME"] %}Successfully registered on {{ site_name }} | Snikket{% endtrans %}</title>
|
||||
{%- include "copy-snippet.html" -%}
|
||||
@@ -15,6 +15,47 @@
|
||||
{% trans %}Copy address{% endtrans %}
|
||||
{%- endcall -%}
|
||||
<p>{% trans %}You can now set up your legacy XMPP client with the above address and the password you chose during registration.{% endtrans %}</p>
|
||||
<p>{% trans %}You can now safely close this page.{% endtrans %}</p>
|
||||
<p>{% trans login_url=url_for('main.login') %}You can now safely close this page, or log in to the web portal to <a href="{{ login_url }}">manage your account</a>.{% endtrans %}</p>
|
||||
|
||||
{% if migration_success %}
|
||||
<h2>{% trans %}Import successful{% endtrans %}</h2>
|
||||
<p>{% trans %}Congratulations! Your account data has been successfully imported.{% endtrans %}</p>
|
||||
{% endif %}
|
||||
|
||||
{% if form %}
|
||||
<h2>{% trans %}Moving to Snikket?{% endtrans %}</h2>
|
||||
<p>{% trans %}If you are moving from a different Snikket instance or another XMPP-compatible service, you may optionally import the data (contacts, profile information, etc.) from your previous account. When you have exported the data from your previous account, upload it using the form below.{% endtrans %}</p>
|
||||
|
||||
<div class="form layout-expanded"><form method="POST" enctype="multipart/form-data">
|
||||
<h3 class="form-title">{% trans %}Upload account data{% endtrans %}</h3>
|
||||
{{ form.csrf_token }}
|
||||
{% call render_errors(form) %}{% endcall %}
|
||||
<div class="f-ebox">
|
||||
{{ form.account_data_file.label }}
|
||||
{{ form.account_data_file(accept="application/xml",
|
||||
data_maxsize=max_import_size,
|
||||
data_warning_header=import_too_big_warning_header,
|
||||
data_maxsize_warning=import_too_big_warning) }}
|
||||
</div>
|
||||
<div class="f-bbox">
|
||||
{%- call form_button("upload", form.action_import, class="secondary") %}{% endcall -%}
|
||||
</div>
|
||||
<script type="text/javascript">
|
||||
document.getElementById("{{ form.account_data_file.id }}").onchange = function() {
|
||||
var maxsize_s = this.dataset.maxsize;
|
||||
var maxsize = parseInt(maxsize_s);
|
||||
if (this.files[0].size > maxsize) {
|
||||
var warning_header = this.dataset.warningHeader;
|
||||
var warning_text = this.dataset.maxsizeWarning;
|
||||
this.setCustomValidity(warning_text);
|
||||
this.reportValidity();
|
||||
this.value = null;
|
||||
} else {
|
||||
this.setCustomValidity("");
|
||||
}
|
||||
};
|
||||
</script>
|
||||
</form></div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
@@ -68,7 +68,7 @@
|
||||
{#- -#}
|
||||
<div id="qr-info-url" class="tab-pane active">
|
||||
<p>{% trans %}Use a <em>QR code</em> scanner on your mobile device to scan the code below:{% endtrans %}</p>
|
||||
<div id="qr-invite-page" data-qrdata="{{ url_for(".view", id_=invite_id, _external=True) }}" class="qr"></div>
|
||||
<div id="qr-invite-page" data-qrdata="{{ url_for(".view", id_=invite_id, _external=True, _scheme="https") }}" class="qr"></div>
|
||||
</div>
|
||||
{#- -#}
|
||||
<div id="qr-info-uri" class="tab-pane">
|
||||
|
||||
@@ -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>
|
||||
|
||||
22
snikket_web/templates/user_manage_data.html
Normal file
22
snikket_web/templates/user_manage_data.html
Normal file
@@ -0,0 +1,22 @@
|
||||
{% 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>
|
||||
<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 %}
|
||||
Binary file not shown.
@@ -6,18 +6,18 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PROJECT VERSION\n"
|
||||
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
||||
"Report-Msgid-Bugs-To: translations@snikket.org\n"
|
||||
"POT-Creation-Date: 2021-06-18 16:05+0200\n"
|
||||
"PO-Revision-Date: 2021-05-19 15:12+0000\n"
|
||||
"PO-Revision-Date: 2021-12-12 07:00+0000\n"
|
||||
"Last-Translator: uira <inboxriau@andriana.id>\n"
|
||||
"Language-Team: Indonesian <https://i18n.sotecware.net/projects/snikket/web-"
|
||||
"portal/id/>\n"
|
||||
"Language-Team: Indonesian <http://i18n.sotecware.net/projects/snikket/"
|
||||
"web-portal/id/>\n"
|
||||
"Language: id\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||
"X-Generator: Weblate 4.5.1\n"
|
||||
"X-Generator: Weblate 4.8.1\n"
|
||||
"Generated-By: Babel 2.9.0\n"
|
||||
|
||||
#: snikket_web/admin.py:66
|
||||
@@ -194,23 +194,23 @@ msgstr "Pengguna dihapus dari kelompok"
|
||||
|
||||
#: snikket_web/admin.py:616
|
||||
msgid "Message contents"
|
||||
msgstr ""
|
||||
msgstr "Isi pesan"
|
||||
|
||||
#: snikket_web/admin.py:622
|
||||
msgid "Only send to online users"
|
||||
msgstr ""
|
||||
msgstr "Hanya kirim ke pengguna online"
|
||||
|
||||
#: snikket_web/admin.py:626
|
||||
msgid "Post to all users"
|
||||
msgstr ""
|
||||
msgstr "Kirim ke semua pengguna"
|
||||
|
||||
#: snikket_web/admin.py:630
|
||||
msgid "Send preview to yourself"
|
||||
msgstr ""
|
||||
msgstr "Kirim pratinjau ke diri sendiri"
|
||||
|
||||
#: snikket_web/admin.py:652
|
||||
msgid "Announcement sent!"
|
||||
msgstr ""
|
||||
msgstr "Pengumuman terkirim!"
|
||||
|
||||
#: snikket_web/infra.py:51
|
||||
msgid "Main"
|
||||
@@ -630,7 +630,7 @@ msgstr "Anggota kelompok"
|
||||
|
||||
#: snikket_web/templates/admin_edit_circle.html:71
|
||||
msgid "The user has been deleted from the server."
|
||||
msgstr ""
|
||||
msgstr "Pengguna telah dihapus dari server"
|
||||
|
||||
#: snikket_web/templates/admin_edit_circle.html:71
|
||||
#: snikket_web/templates/library.j2:108
|
||||
@@ -843,22 +843,20 @@ msgstr "Kelola undangan"
|
||||
|
||||
#: snikket_web/templates/admin_home.html:35
|
||||
msgid "System health"
|
||||
msgstr ""
|
||||
msgstr "Kesehatan sistem"
|
||||
|
||||
#: snikket_web/templates/admin_home.html:38
|
||||
msgid "View the server status or send a broadcast message to all users."
|
||||
msgstr ""
|
||||
msgstr "Lihat status server atau kirim pesan siaran ke semua pengguna."
|
||||
|
||||
#: snikket_web/templates/admin_home.html:40
|
||||
msgid "Send a broadcast message to all users."
|
||||
msgstr ""
|
||||
msgstr "Kirim pesan siaran ke semua pengguna."
|
||||
|
||||
#: snikket_web/templates/admin_home.html:43
|
||||
#: snikket_web/templates/admin_system.html:4
|
||||
#, fuzzy
|
||||
#| msgid "Manage users"
|
||||
msgid "Manage system"
|
||||
msgstr "Kelola pengguna"
|
||||
msgstr "Kelola sistem"
|
||||
|
||||
#: snikket_web/templates/admin_home.html:48
|
||||
msgid "Go back to your user's web portal page."
|
||||
@@ -919,11 +917,11 @@ msgstr "Hancurkan tautan"
|
||||
|
||||
#: snikket_web/templates/admin_system.html:6
|
||||
msgid "Overall system status"
|
||||
msgstr ""
|
||||
msgstr "Kesehatan sistem keseluruhan"
|
||||
|
||||
#: snikket_web/templates/admin_system.html:9
|
||||
msgid "System load (5 minute average)"
|
||||
msgstr ""
|
||||
msgstr "Beban sistem (rata-rata 5 menit)"
|
||||
|
||||
#: snikket_web/templates/admin_system.html:14
|
||||
#: snikket_web/templates/admin_system.html:22
|
||||
@@ -933,11 +931,11 @@ msgstr ""
|
||||
#: snikket_web/templates/admin_system.html:68
|
||||
#: snikket_web/templates/admin_system.html:76
|
||||
msgid "unknown"
|
||||
msgstr ""
|
||||
msgstr "Tidak diketahui"
|
||||
|
||||
#: snikket_web/templates/admin_system.html:17
|
||||
msgid "Memory use"
|
||||
msgstr ""
|
||||
msgstr "Penggunaan memori"
|
||||
|
||||
#: snikket_web/templates/admin_system.html:20
|
||||
#, python-format
|
||||
@@ -945,50 +943,52 @@ msgid ""
|
||||
"%(percentage_global)s of %(mem_available)s. Of that, Snikket uses "
|
||||
"%(percentage_snikket)s."
|
||||
msgstr ""
|
||||
"%(percentage_global)s of %(mem_available)s. Dari jumlah itu, Snikket "
|
||||
"menggunakan %(percentage_snikket)s."
|
||||
|
||||
#: snikket_web/templates/admin_system.html:27
|
||||
msgid "Web portal status"
|
||||
msgstr ""
|
||||
msgstr "Status portal web"
|
||||
|
||||
#: snikket_web/templates/admin_system.html:30
|
||||
#: snikket_web/templates/admin_system.html:53
|
||||
msgid "Version"
|
||||
msgstr ""
|
||||
msgstr "Versi"
|
||||
|
||||
#: snikket_web/templates/admin_system.html:31
|
||||
#: snikket_web/templates/admin_system.html:54
|
||||
msgid "View all versions"
|
||||
msgstr ""
|
||||
msgstr "Lihat versi semua"
|
||||
|
||||
#: snikket_web/templates/admin_system.html:32
|
||||
#: snikket_web/templates/admin_system.html:55
|
||||
msgid "Average CPU use"
|
||||
msgstr ""
|
||||
msgstr "Penggunaan CPU rata-rata"
|
||||
|
||||
#: snikket_web/templates/admin_system.html:40
|
||||
#: snikket_web/templates/admin_system.html:63
|
||||
msgid "Current memory use"
|
||||
msgstr ""
|
||||
msgstr "Penggunaan CPU rata-rata"
|
||||
|
||||
#: snikket_web/templates/admin_system.html:50
|
||||
#, fuzzy
|
||||
#| msgid "Snikket Web Portal"
|
||||
msgid "Snikket server status"
|
||||
msgstr "Portal Web Snikket"
|
||||
msgstr "Status server Snikket"
|
||||
|
||||
#: snikket_web/templates/admin_system.html:71
|
||||
msgid "Connected devices"
|
||||
msgstr ""
|
||||
msgstr "Perangkat terhubung"
|
||||
|
||||
#: snikket_web/templates/admin_system.html:82
|
||||
msgid "Broadcast message"
|
||||
msgstr ""
|
||||
msgstr "Sebarkan pesan"
|
||||
|
||||
#: snikket_web/templates/admin_system.html:84
|
||||
msgid ""
|
||||
"This form allows you to send a message to all users currently online on your "
|
||||
"Snikket server. Use it wisely."
|
||||
msgstr ""
|
||||
"Form ini memungkinkan mengirim pesan ke semua pengguna yang saat ini online "
|
||||
"di server Snikket Anda. Gunakan dengan bijak."
|
||||
|
||||
#: snikket_web/templates/admin_users.html:19
|
||||
msgid "The user is an administrator."
|
||||
|
||||
Binary file not shown.
@@ -8,17 +8,17 @@ msgstr ""
|
||||
"Project-Id-Version: PROJECT VERSION\n"
|
||||
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
||||
"POT-Creation-Date: 2021-06-18 16:05+0200\n"
|
||||
"PO-Revision-Date: 2021-05-19 15:12+0000\n"
|
||||
"PO-Revision-Date: 2021-09-03 15:00+0000\n"
|
||||
"Last-Translator: misiek <migelazur@mailbox.org>\n"
|
||||
"Language-Team: Polish <https://i18n.sotecware.net/projects/snikket/web-"
|
||||
"portal/pl/>\n"
|
||||
"Language-Team: Polish <http://i18n.sotecware.net/projects/snikket/web-portal/"
|
||||
"pl/>\n"
|
||||
"Language: pl\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 "
|
||||
"|| n%100>=20) ? 1 : 2;\n"
|
||||
"X-Generator: Weblate 4.5.1\n"
|
||||
"X-Generator: Weblate 4.7.2\n"
|
||||
"Generated-By: Babel 2.9.0\n"
|
||||
|
||||
#: snikket_web/admin.py:66
|
||||
@@ -195,23 +195,23 @@ msgstr "Usunięto użytkownika z kręgu"
|
||||
|
||||
#: snikket_web/admin.py:616
|
||||
msgid "Message contents"
|
||||
msgstr ""
|
||||
msgstr "Treść wiadomości"
|
||||
|
||||
#: snikket_web/admin.py:622
|
||||
msgid "Only send to online users"
|
||||
msgstr ""
|
||||
msgstr "Wyślij jedynie do użytkowników online"
|
||||
|
||||
#: snikket_web/admin.py:626
|
||||
msgid "Post to all users"
|
||||
msgstr ""
|
||||
msgstr "Wyślij do wszystkich użytkowników"
|
||||
|
||||
#: snikket_web/admin.py:630
|
||||
msgid "Send preview to yourself"
|
||||
msgstr ""
|
||||
msgstr "Prześlij do siebie podgląd wiadomości"
|
||||
|
||||
#: snikket_web/admin.py:652
|
||||
msgid "Announcement sent!"
|
||||
msgstr ""
|
||||
msgstr "Komunikat wysłany!"
|
||||
|
||||
#: snikket_web/infra.py:51
|
||||
msgid "Main"
|
||||
@@ -629,7 +629,7 @@ msgstr "Członkowie kręgu"
|
||||
|
||||
#: snikket_web/templates/admin_edit_circle.html:71
|
||||
msgid "The user has been deleted from the server."
|
||||
msgstr ""
|
||||
msgstr "Użytkownik został usunięty z serwera."
|
||||
|
||||
#: snikket_web/templates/admin_edit_circle.html:71
|
||||
#: snikket_web/templates/library.j2:108
|
||||
@@ -844,22 +844,21 @@ msgstr "Zarządzaj zaproszeniami"
|
||||
|
||||
#: snikket_web/templates/admin_home.html:35
|
||||
msgid "System health"
|
||||
msgstr ""
|
||||
msgstr "Stan systemu"
|
||||
|
||||
#: snikket_web/templates/admin_home.html:38
|
||||
msgid "View the server status or send a broadcast message to all users."
|
||||
msgstr ""
|
||||
"Podejrzyj status serwera lub prześlij komunikat do wszystkich użytkowników."
|
||||
|
||||
#: snikket_web/templates/admin_home.html:40
|
||||
msgid "Send a broadcast message to all users."
|
||||
msgstr ""
|
||||
msgstr "Prześlij komunikat do wszystkich użytkowników."
|
||||
|
||||
#: snikket_web/templates/admin_home.html:43
|
||||
#: snikket_web/templates/admin_system.html:4
|
||||
#, fuzzy
|
||||
#| msgid "Manage users"
|
||||
msgid "Manage system"
|
||||
msgstr "Zarządzaj użytkownikami"
|
||||
msgstr "Zarządzaj systemem"
|
||||
|
||||
#: snikket_web/templates/admin_home.html:48
|
||||
msgid "Go back to your user's web portal page."
|
||||
@@ -920,11 +919,11 @@ msgstr "Zniszcz link"
|
||||
|
||||
#: snikket_web/templates/admin_system.html:6
|
||||
msgid "Overall system status"
|
||||
msgstr ""
|
||||
msgstr "Ogólny status systemu"
|
||||
|
||||
#: snikket_web/templates/admin_system.html:9
|
||||
msgid "System load (5 minute average)"
|
||||
msgstr ""
|
||||
msgstr "Obciążenie systemu (dla ostatnich 5 minut)"
|
||||
|
||||
#: snikket_web/templates/admin_system.html:14
|
||||
#: snikket_web/templates/admin_system.html:22
|
||||
@@ -934,11 +933,11 @@ msgstr ""
|
||||
#: snikket_web/templates/admin_system.html:68
|
||||
#: snikket_web/templates/admin_system.html:76
|
||||
msgid "unknown"
|
||||
msgstr ""
|
||||
msgstr "nieznane"
|
||||
|
||||
#: snikket_web/templates/admin_system.html:17
|
||||
msgid "Memory use"
|
||||
msgstr ""
|
||||
msgstr "Wykorzystanie pamięci"
|
||||
|
||||
#: snikket_web/templates/admin_system.html:20
|
||||
#, python-format
|
||||
@@ -946,50 +945,52 @@ msgid ""
|
||||
"%(percentage_global)s of %(mem_available)s. Of that, Snikket uses "
|
||||
"%(percentage_snikket)s."
|
||||
msgstr ""
|
||||
"%(percentage_global)s z %(mem_available)s. Z tego Snikket używa "
|
||||
"%(percentage_snikket)s."
|
||||
|
||||
#: snikket_web/templates/admin_system.html:27
|
||||
msgid "Web portal status"
|
||||
msgstr ""
|
||||
msgstr "Status portalu internetowego"
|
||||
|
||||
#: snikket_web/templates/admin_system.html:30
|
||||
#: snikket_web/templates/admin_system.html:53
|
||||
msgid "Version"
|
||||
msgstr ""
|
||||
msgstr "Wersja"
|
||||
|
||||
#: snikket_web/templates/admin_system.html:31
|
||||
#: snikket_web/templates/admin_system.html:54
|
||||
msgid "View all versions"
|
||||
msgstr ""
|
||||
msgstr "Pokaż wszystkie wersje"
|
||||
|
||||
#: snikket_web/templates/admin_system.html:32
|
||||
#: snikket_web/templates/admin_system.html:55
|
||||
msgid "Average CPU use"
|
||||
msgstr ""
|
||||
msgstr "Średnie użycie CPU"
|
||||
|
||||
#: snikket_web/templates/admin_system.html:40
|
||||
#: snikket_web/templates/admin_system.html:63
|
||||
msgid "Current memory use"
|
||||
msgstr ""
|
||||
msgstr "Bieżące użycie pamięci"
|
||||
|
||||
#: snikket_web/templates/admin_system.html:50
|
||||
#, fuzzy
|
||||
#| msgid "Snikket Web Portal"
|
||||
msgid "Snikket server status"
|
||||
msgstr "Portal użytkownika Snikket"
|
||||
msgstr "Status serwera Snikket"
|
||||
|
||||
#: snikket_web/templates/admin_system.html:71
|
||||
msgid "Connected devices"
|
||||
msgstr ""
|
||||
msgstr "Podłączone urządzenia"
|
||||
|
||||
#: snikket_web/templates/admin_system.html:82
|
||||
msgid "Broadcast message"
|
||||
msgstr ""
|
||||
msgstr "Wiadomość globalna"
|
||||
|
||||
#: snikket_web/templates/admin_system.html:84
|
||||
msgid ""
|
||||
"This form allows you to send a message to all users currently online on your "
|
||||
"Snikket server. Use it wisely."
|
||||
msgstr ""
|
||||
"Ten formularz pozwala na wysłanie wiadomości do wszystkich użytkowników, "
|
||||
"którzy obecnie są online na twoim serwerze Snikket. Używaj go z rozwagą."
|
||||
|
||||
#: snikket_web/templates/admin_users.html:19
|
||||
msgid "The user is an administrator."
|
||||
|
||||
Binary file not shown.
@@ -8,16 +8,16 @@ msgstr ""
|
||||
"Project-Id-Version: PROJECT VERSION\n"
|
||||
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
||||
"POT-Creation-Date: 2021-06-18 16:05+0200\n"
|
||||
"PO-Revision-Date: 2021-05-28 21:00+0000\n"
|
||||
"PO-Revision-Date: 2021-08-01 14:00+0000\n"
|
||||
"Last-Translator: Kim Alvefur <zash@zash.se>\n"
|
||||
"Language-Team: Swedish <https://i18n.sotecware.net/projects/snikket/web-"
|
||||
"portal/sv/>\n"
|
||||
"Language-Team: Swedish <http://i18n.sotecware.net/projects/snikket/"
|
||||
"web-portal/sv/>\n"
|
||||
"Language: sv\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||
"X-Generator: Weblate 4.5.1\n"
|
||||
"X-Generator: Weblate 4.7.2\n"
|
||||
"Generated-By: Babel 2.9.0\n"
|
||||
|
||||
#: snikket_web/admin.py:66
|
||||
@@ -624,7 +624,7 @@ msgstr "Medlemmar i krets"
|
||||
|
||||
#: snikket_web/templates/admin_edit_circle.html:71
|
||||
msgid "The user has been deleted from the server."
|
||||
msgstr ""
|
||||
msgstr "Användaren har raderats från servern."
|
||||
|
||||
#: snikket_web/templates/admin_edit_circle.html:71
|
||||
#: snikket_web/templates/library.j2:108
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import asyncio
|
||||
import typing
|
||||
import urllib
|
||||
|
||||
import quart.flask_patch
|
||||
from quart import (
|
||||
Blueprint,
|
||||
Response,
|
||||
render_template,
|
||||
request,
|
||||
redirect,
|
||||
@@ -75,6 +77,16 @@ class ProfileForm(BaseForm):
|
||||
)
|
||||
|
||||
|
||||
class ImportAccountDataForm(BaseForm):
|
||||
account_data_file = wtforms.FileField(
|
||||
_l("Account data")
|
||||
)
|
||||
|
||||
action_upload = wtforms.SubmitField(
|
||||
_l("Upload"),
|
||||
)
|
||||
|
||||
|
||||
@bp.route("/")
|
||||
@client.require_session()
|
||||
async def index() -> str:
|
||||
@@ -168,6 +180,46 @@ 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')
|
||||
)
|
||||
account_data = await client.export_account_data()
|
||||
if account_data is None:
|
||||
await flash(
|
||||
_("You currently have no account data to export."),
|
||||
"alert"
|
||||
)
|
||||
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]:
|
||||
|
||||
@@ -207,7 +207,7 @@ def make_avatar_metadata_set_request(
|
||||
item,
|
||||
"metadata", xmlns=NS_USER_AVATAR_METADATA)
|
||||
|
||||
attr: typing.MutableMapping[str, str] = {
|
||||
attr: typing.Dict[str, str] = {
|
||||
"id": id_,
|
||||
"bytes": str(size),
|
||||
"type": mimetype,
|
||||
@@ -217,7 +217,12 @@ def make_avatar_metadata_set_request(
|
||||
if height is not None:
|
||||
attr["height"] = str(height)
|
||||
|
||||
ET.SubElement(metadata_wrap, "info", xmlns=NS_USER_AVATAR_METADATA, **attr)
|
||||
ET.SubElement(
|
||||
metadata_wrap,
|
||||
"info",
|
||||
xmlns=NS_USER_AVATAR_METADATA,
|
||||
**attr, # type: ignore
|
||||
)
|
||||
return req
|
||||
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ action/logout:logout
|
||||
action/login:login
|
||||
action/exit_to_app:exit_to_app
|
||||
action/lock:lock
|
||||
communication/import_export:import_export
|
||||
communication/qr_code:qrcode
|
||||
communication/vpn_key:passwd
|
||||
communication/rss_feed:broadcast
|
||||
@@ -15,6 +16,9 @@ content/remove_circle_outline:remove
|
||||
content/content_copy:copy
|
||||
content/link_off:remove_link
|
||||
content/send:send
|
||||
file/file_download:download
|
||||
file/file_upload:upload
|
||||
file/folder:folder
|
||||
navigation/arrow_back:back
|
||||
navigation/arrow_forward:forward
|
||||
navigation/cancel:cancel
|
||||
|
||||
Reference in New Issue
Block a user