You've already forked snikket-web-portal
Compare commits
103 Commits
feature/ad
...
cookie-sam
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6407eb90db | ||
|
|
a8c6b1a70c | ||
|
|
67c94bb045 | ||
|
|
f4c1173a34 | ||
|
|
e39b0082b1 | ||
|
|
9eb187a951 | ||
|
|
b928e74a74 | ||
|
|
75c0f504d0 | ||
|
|
7c0310a141 | ||
|
|
5e2e645787 | ||
|
|
9b31894e85 | ||
|
|
a4472e1a44 | ||
|
|
b99cae84de | ||
|
|
1cac19e4c9 | ||
|
|
d4883765b2 | ||
|
|
041f26274b | ||
|
|
82db30ffd9 | ||
|
|
b8684329b4 | ||
|
|
7e26b5f994 | ||
|
|
4bdcb46a8a | ||
|
|
ed6f413c18 | ||
|
|
f63549ee87 | ||
|
|
bd71ab1449 | ||
|
|
220bf9994b | ||
|
|
33d28e5890 | ||
|
|
f0f0fa15c9 | ||
|
|
30a9a6816f | ||
|
|
970b8fa7f1 | ||
|
|
629d725ff5 | ||
|
|
6998e66b22 | ||
|
|
c668c4c56a | ||
|
|
a13fbd87a6 | ||
|
|
7ffcd76cea | ||
|
|
bda0f52320 | ||
|
|
5efc2a671e | ||
|
|
1578654816 | ||
|
|
e8ab33e12f | ||
|
|
712b0dc502 | ||
|
|
e56c0f9029 | ||
|
|
794b48a50b | ||
|
|
393b30cf5c | ||
|
|
97198a1da4 | ||
|
|
3ba1195fbe | ||
|
|
121f3eddb5 | ||
|
|
38ad81b0e2 | ||
|
|
ec94c64dbc | ||
|
|
28a9a33aa1 | ||
|
|
97eeb85032 | ||
|
|
ceef9f024c | ||
|
|
40c8b9cc36 | ||
|
|
95a8ac1387 | ||
|
|
4c6e26e66b | ||
|
|
ad2b351a99 | ||
|
|
3bda1f9863 | ||
|
|
f46d95db66 | ||
|
|
ddfdd2fd55 | ||
|
|
17d586e384 | ||
|
|
dbec07d149 | ||
|
|
ebf142b505 | ||
|
|
0539d0ab88 | ||
|
|
2736bff76b | ||
|
|
192601f387 | ||
|
|
bc9cfeabab | ||
|
|
b770086071 | ||
|
|
b2c1fdd23b | ||
|
|
906978556e | ||
|
|
274c8e4658 | ||
|
|
257a44dac2 | ||
|
|
f393a3980b | ||
|
|
badff7eed8 | ||
|
|
384e07c2a9 | ||
|
|
89724a9712 | ||
|
|
94f4325f40 | ||
|
|
af1285b650 | ||
|
|
52eba53d8e | ||
|
|
94f240687a | ||
|
|
1b2bdfa881 | ||
|
|
271f450c86 | ||
|
|
6186e8b635 | ||
|
|
dfc6c392c3 | ||
|
|
0ec9a2ae02 | ||
|
|
09fcf64818 | ||
|
|
c25db5c3ae | ||
|
|
c85fff7581 | ||
|
|
039f4b8210 | ||
|
|
7be7ee67c2 | ||
|
|
6f5fc14dbc | ||
|
|
65edd3a52b | ||
|
|
ab7149403a | ||
|
|
5b2f3db867 | ||
|
|
e12941eab0 | ||
|
|
eda3f4826c | ||
|
|
61161eb472 | ||
|
|
325826c19b | ||
|
|
587839f852 | ||
|
|
7411f4a9e1 | ||
|
|
d63ae4768a | ||
|
|
92a8da724f | ||
|
|
ea3a081b6c | ||
|
|
0647ba2601 | ||
|
|
2769036f94 | ||
|
|
c76befad1c | ||
|
|
74ecfb8653 |
4
.github/workflows/main.yaml
vendored
4
.github/workflows/main.yaml
vendored
@@ -66,10 +66,10 @@ jobs:
|
||||
pip install flask-babel
|
||||
- name: Linting
|
||||
run: |
|
||||
sed -ri '/^"POT-Creation-Date: /d' snikket_web/translations/messages.pot
|
||||
sed -ri '/^"POT-Creation-Date: /d;/^"Generated-By: /d' snikket_web/translations/messages.pot
|
||||
git add snikket_web/translations/messages.pot
|
||||
make extract_translations
|
||||
sed -ri '/^"POT-Creation-Date: /d' snikket_web/translations/messages.pot
|
||||
sed -ri '/^"POT-Creation-Date: /d;/^"Generated-By: /d' snikket_web/translations/messages.pot
|
||||
git diff --exit-code --color -- snikket_web/translations/messages.pot
|
||||
|
||||
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
aiohttp~=3.6
|
||||
quart~=0.17,<0.18
|
||||
flask-wtf~=1.0
|
||||
aiohttp~=3.8,<3.9
|
||||
quart~=0.18,<0.19
|
||||
flask-wtf~=1.1,<1.2
|
||||
hsluv~=5.0
|
||||
flask-babel~=1.0
|
||||
email-validator~=1.1
|
||||
flask-babel~=2.0,<3
|
||||
email-validator~=1.3
|
||||
environ-config~=20.0
|
||||
wtforms~=3.0
|
||||
wtforms~=3.0,<4
|
||||
typing-extensions
|
||||
werkzeug~=2.2,<3
|
||||
|
||||
@@ -158,7 +158,9 @@ class AppConfig:
|
||||
"id",
|
||||
"it",
|
||||
"pl",
|
||||
"ru",
|
||||
"sv",
|
||||
"uk",
|
||||
"zh_Hans_CN",
|
||||
], converter=autosplit)
|
||||
apple_store_url = environ.var(
|
||||
@@ -210,6 +212,8 @@ def create_app() -> quart.Quart:
|
||||
app.config["PRIVACY_URI"] = config.privacy_uri
|
||||
app.config["ABUSE_EMAIL"] = config.abuse_email
|
||||
app.config["SECURITY_EMAIL"] = config.security_email
|
||||
app.config["SESSION_COOKIE_SECURE"] = True
|
||||
app.config["SESSION_COOKIE_SAMESITE"] = "Lax"
|
||||
|
||||
app.context_processor(proc)
|
||||
app.register_error_handler(
|
||||
|
||||
@@ -76,10 +76,11 @@ class EditUserForm(BaseForm):
|
||||
role = wtforms.RadioField(
|
||||
_l("Access Level"),
|
||||
choices=[
|
||||
("prosody:restricted", _("Limited")),
|
||||
("prosody:restricted", _l("Limited")),
|
||||
("prosody:registered", _l("Normal user")),
|
||||
("prosody:admin", _l("Administrator")),
|
||||
],
|
||||
default="prosody:registered",
|
||||
)
|
||||
|
||||
action_save = wtforms.SubmitField(
|
||||
@@ -290,6 +291,16 @@ class InvitePost(BaseForm):
|
||||
default="account",
|
||||
)
|
||||
|
||||
role = wtforms.RadioField(
|
||||
_l("Access Level"),
|
||||
choices=[
|
||||
("prosody:restricted", _l("Limited")),
|
||||
("prosody:registered", _l("Normal user")),
|
||||
("prosody:admin", _l("Administrator")),
|
||||
],
|
||||
default="prosody:registered",
|
||||
)
|
||||
|
||||
action_create_invite = wtforms.SubmitField(
|
||||
_l("New invitation link")
|
||||
)
|
||||
@@ -369,11 +380,13 @@ async def create_invite() -> typing.Union[str, werkzeug.Response]:
|
||||
if form.type_.data == "group":
|
||||
invite = await client.create_group_invite(
|
||||
group_ids=form.circles.data,
|
||||
role_names=[form.role.data],
|
||||
ttl=form.lifetime.data,
|
||||
)
|
||||
else:
|
||||
invite = await client.create_account_invite(
|
||||
group_ids=form.circles.data,
|
||||
role_names=[form.role.data],
|
||||
ttl=form.lifetime.data,
|
||||
)
|
||||
await flash(
|
||||
@@ -733,21 +746,21 @@ def get_system_stats() -> typing.MutableMapping[
|
||||
|
||||
class AnnouncementForm(BaseForm):
|
||||
text = wtforms.StringField(
|
||||
_("Message contents"),
|
||||
_l("Message contents"),
|
||||
widget=wtforms.widgets.TextArea(),
|
||||
validators=[wtforms.validators.DataRequired()],
|
||||
)
|
||||
|
||||
online_only = wtforms.BooleanField(
|
||||
_("Only send to online users"),
|
||||
_l("Only send to online users"),
|
||||
)
|
||||
|
||||
action_post_all = wtforms.SubmitField(
|
||||
_("Post to all users"),
|
||||
_l("Post to all users"),
|
||||
)
|
||||
|
||||
action_send_preview = wtforms.SubmitField(
|
||||
_("Send preview to yourself"),
|
||||
_l("Send preview to yourself"),
|
||||
)
|
||||
|
||||
|
||||
@@ -812,6 +825,11 @@ async def system() -> typing.Union[str, werkzeug.Response]:
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
try:
|
||||
metrics["users"] = prosody_metrics["users"]
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
for k in list(metrics.keys()):
|
||||
if metrics[k] is None:
|
||||
# so that defaulting in jinja works
|
||||
|
||||
@@ -53,7 +53,7 @@ def flatten(a: typing.Iterable, levels: int = 1) -> typing.Iterable:
|
||||
|
||||
def circle_name(c: typing.Any) -> str:
|
||||
if c.id_ == "default" and c.name == "default":
|
||||
return _("Main")
|
||||
return _l("Main")
|
||||
return c.name
|
||||
|
||||
|
||||
|
||||
@@ -116,6 +116,10 @@ class RegisterForm(BaseForm):
|
||||
|
||||
password = wtforms.PasswordField(
|
||||
_l("Password"),
|
||||
validators=[
|
||||
wtforms.validators.InputRequired(),
|
||||
wtforms.validators.Length(min=10),
|
||||
],
|
||||
)
|
||||
|
||||
password_confirm = wtforms.PasswordField(
|
||||
@@ -184,6 +188,10 @@ async def register(id_: str) -> typing.Union[str, werkzeug.Response]:
|
||||
class ResetForm(BaseForm):
|
||||
password = wtforms.PasswordField(
|
||||
_l("Password"),
|
||||
validators=[
|
||||
wtforms.validators.InputRequired(),
|
||||
wtforms.validators.Length(min=10),
|
||||
],
|
||||
)
|
||||
|
||||
password_confirm = wtforms.PasswordField(
|
||||
|
||||
@@ -29,6 +29,7 @@ from . import xmpputil
|
||||
from .xmpputil import split_jid
|
||||
|
||||
|
||||
SCOPE_RESTRICTED = "prosody:restricted"
|
||||
SCOPE_DEFAULT = "prosody:registered"
|
||||
SCOPE_ADMIN = "prosody:admin"
|
||||
|
||||
@@ -119,6 +120,14 @@ class AdminUserInfo:
|
||||
roles.extend(data.get("secondary_roles", []))
|
||||
except KeyError:
|
||||
roles = data.get("roles")
|
||||
avatar_info: typing.List[AvatarMetadata] = []
|
||||
for avatar in data.get("avatar_info", []):
|
||||
# Ignore somehow broken avatars.
|
||||
try:
|
||||
avatar_metadata = AvatarMetadata.from_api_response(avatar)
|
||||
avatar_info.append(avatar_metadata)
|
||||
except KeyError:
|
||||
pass
|
||||
return cls(
|
||||
localpart=data["username"],
|
||||
display_name=data.get("display_name") or None,
|
||||
@@ -130,10 +139,7 @@ class AdminUserInfo:
|
||||
deletion_request=UserDeletionRequestInfo.from_api_response(
|
||||
data.get("deletion_request")
|
||||
),
|
||||
avatar_info=[
|
||||
AvatarMetadata.from_api_response(avatar_info)
|
||||
for avatar_info in data.get("avatar_info", [])
|
||||
],
|
||||
avatar_info=avatar_info,
|
||||
)
|
||||
|
||||
|
||||
@@ -154,6 +160,7 @@ class AdminInviteInfo:
|
||||
expires: datetime
|
||||
reusable: bool
|
||||
group_ids: typing.Collection[str]
|
||||
role_names: typing.Collection[str]
|
||||
is_reset: bool
|
||||
|
||||
@classmethod
|
||||
@@ -171,6 +178,7 @@ class AdminInviteInfo:
|
||||
xmpp_uri=data.get("xmpp_uri"),
|
||||
landing_page=data.get("landing_page"),
|
||||
group_ids=data.get("groups", []),
|
||||
role_names=data.get("roles", []),
|
||||
reusable=data["reusable"],
|
||||
is_reset=data.get("reset", False),
|
||||
)
|
||||
@@ -190,7 +198,7 @@ class AdminGroupChatInfo:
|
||||
return cls(
|
||||
id_=data["id"],
|
||||
jid=data["jid"],
|
||||
name=data["name"],
|
||||
name=data.get("name", ""),
|
||||
)
|
||||
|
||||
|
||||
@@ -399,7 +407,7 @@ class ProsodyClient:
|
||||
request.add_field("password", password)
|
||||
request.add_field(
|
||||
"scope",
|
||||
" ".join([SCOPE_DEFAULT, SCOPE_ADMIN])
|
||||
" ".join([SCOPE_RESTRICTED, SCOPE_DEFAULT, SCOPE_ADMIN])
|
||||
)
|
||||
|
||||
self.logger.debug("sending OAuth2 request (payload omitted)")
|
||||
@@ -908,7 +916,7 @@ class ProsodyClient:
|
||||
self.session_address,
|
||||
current_password,
|
||||
)
|
||||
await self._xml_iq_call(
|
||||
password_changed = await self._xml_iq_call(
|
||||
session,
|
||||
xmpputil.make_password_change_request(
|
||||
self.session_address,
|
||||
@@ -919,7 +927,7 @@ class ProsodyClient:
|
||||
},
|
||||
sensitive=True,
|
||||
)
|
||||
# TODO: error handling
|
||||
xmpputil.extract_iq_reply(password_changed)
|
||||
# TODO: obtain a new token using the new password to allow the
|
||||
# server to expire/revoke all tokens on password change.
|
||||
self._store_token_in_session(token_info)
|
||||
@@ -1080,12 +1088,14 @@ class ProsodyClient:
|
||||
self,
|
||||
*,
|
||||
group_ids: typing.Collection[str] = [],
|
||||
role_names: typing.Collection[str] = [],
|
||||
restrict_username: typing.Optional[str] = None,
|
||||
ttl: typing.Optional[int] = None,
|
||||
session: aiohttp.ClientSession,
|
||||
) -> AdminInviteInfo:
|
||||
payload: typing.Dict[str, typing.Any] = {}
|
||||
payload["groups"] = list(group_ids)
|
||||
payload["roles"] = list(role_names)
|
||||
if restrict_username is not None:
|
||||
payload["username"] = restrict_username
|
||||
if ttl is not None:
|
||||
@@ -1102,11 +1112,13 @@ class ProsodyClient:
|
||||
self,
|
||||
*,
|
||||
group_ids: typing.Collection[str] = [],
|
||||
role_names: typing.Collection[str] = [],
|
||||
ttl: typing.Optional[int] = None,
|
||||
session: aiohttp.ClientSession,
|
||||
) -> AdminInviteInfo:
|
||||
payload: typing.Dict[str, typing.Any] = {
|
||||
"groups": list(group_ids),
|
||||
"roles": list(role_names),
|
||||
}
|
||||
if ttl is not None:
|
||||
payload["ttl"] = ttl
|
||||
|
||||
@@ -259,6 +259,13 @@ div.form.layout-expanded {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
fieldset.descriptive-radio-selection {
|
||||
p {
|
||||
margin-top: 0;
|
||||
margin-bottom: $w-s2;
|
||||
}
|
||||
}
|
||||
|
||||
input[type="radio"] + label, input[type="checkbox"] + label {
|
||||
font-weight: inherit;
|
||||
color: inherit;
|
||||
@@ -363,6 +370,10 @@ div.form.layout-expanded {
|
||||
margin-left: 0.25em;
|
||||
}
|
||||
|
||||
.radio-button-ext {
|
||||
margin-left: 0.5rem;
|
||||
}
|
||||
|
||||
div.select-wrap {
|
||||
display: block;
|
||||
border-bottom: $w-s4 solid $primary-500;
|
||||
@@ -1304,4 +1315,11 @@ pre.guru-meditation {
|
||||
margin-left: 0.5em;
|
||||
}
|
||||
|
||||
.user-display-name {
|
||||
font-size: 110%;
|
||||
}
|
||||
|
||||
.user-jid {
|
||||
font-size: 90%;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -148,6 +148,11 @@ licensed under the terms of the Apache 2.0 License -->
|
||||
<path d="M0 0h24v24H0V0z" fill="none" />
|
||||
<path d="M16 11c1.66 0 2.99-1.34 2.99-3S17.66 5 16 5s-3 1.34-3 3 1.34 3 3 3zm-8 0c1.66 0 2.99-1.34 2.99-3S9.66 5 8 5 5 6.34 5 8s1.34 3 3 3zm0 2c-2.33 0-7 1.17-7 3.5V18c0 .55.45 1 1 1h12c.55 0 1-.45 1-1v-1.5c0-2.33-4.67-3.5-7-3.5zm8 0c-.29 0-.62.02-.97.05.02.01.03.03.04.04 1.14.83 1.93 1.94 1.93 3.41V18c0 .35-.07.69-.18 1H22c.55 0 1-.45 1-1v-1.5c0-2.33-4.67-3.5-7-3.5z" />
|
||||
</symbol>
|
||||
<!-- from: social/person/materialiconsround/24px.svg -->
|
||||
<symbol id="icon-person" viewBox="0 0 24 24">
|
||||
<path d="M0 0h24v24H0V0z" fill="none" />
|
||||
<path d="M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v1c0 .55.45 1 1 1h14c.55 0 1-.45 1-1v-1c0-2.66-5.33-4-8-4z" />
|
||||
</symbol>
|
||||
<!-- from: social/group_add/materialiconsround/24px.svg -->
|
||||
<symbol id="icon-create_group" viewBox="0 0 24 24">
|
||||
<path d="M0 0h24v24H0V0z" fill="none" />
|
||||
|
||||
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
@@ -1,19 +1,57 @@
|
||||
{% from "library.j2" import form_button, render_errors %}
|
||||
{% from "library.j2" import form_button,
|
||||
render_errors,
|
||||
access_level_description, access_level_icon,
|
||||
invite_type_description, invite_type_icon
|
||||
%}
|
||||
<form method="POST" action="{{ url_for(".create_invite") }}">
|
||||
{{- invite_form.csrf_token -}}
|
||||
<div class="form layout-expanded">
|
||||
<h2 class="form-title">{% trans %}Create new invitation{% endtrans %}</h2>
|
||||
<p class="form-descr weak">{% trans %}Create a new invitation link to invite more users to your Snikket service by clicking the button below.{% endtrans %}</p>
|
||||
|
||||
<!-- Invitation type -->
|
||||
<div class="f-ebox">
|
||||
<fieldset>{#- -#}
|
||||
<fieldset class="descriptive-radio-selection">{#- -#}
|
||||
<legend>{{ invite_form.type_.label.text }}</legend>
|
||||
{{- invite_form.type_ -}}
|
||||
<p>{% trans %}Choose whether this invitation link will allow more than one person to join.{% endtrans %}</p>
|
||||
|
||||
{%- for invite_type in invite_form.type_ -%}
|
||||
<div class="radio-button-ext">
|
||||
{{ invite_type }}<label for="{{ invite_type.id }}">
|
||||
{%- trans title=invite_type.label.text, icon=invite_type_icon(invite_type.data), description=invite_type_description(invite_type.data) -%}
|
||||
<span class="invite-type">{{ title }}{{ icon }}</span><p>{{ description }}</p>
|
||||
{%- endtrans -%}
|
||||
</label>
|
||||
</div>
|
||||
{%- endfor -%}
|
||||
</fieldset>
|
||||
</div>
|
||||
|
||||
<!-- Access level -->
|
||||
<div class="f-ebox">
|
||||
<fieldset class="descriptive-radio-selection">{#- -#}
|
||||
<legend>{{ invite_form.role.label.text }}</legend>
|
||||
<p>{% trans %}The access level of a user determines what interactions are allowed for them on your Snikket service.{% endtrans %}</p>
|
||||
{%- for level in invite_form.role -%}
|
||||
<div class="radio-button-ext">
|
||||
{{ level }}<label for="{{ level.id }}">
|
||||
{%- trans title=level.label.text, icon=access_level_icon(level.data), description=access_level_description(level.data) -%}
|
||||
<span class="access-level">{{ title }}{{ icon }}</span><p>{{ description }}</p>
|
||||
{%- endtrans -%}
|
||||
</label>
|
||||
</div>
|
||||
{%- endfor -%}
|
||||
</fieldset>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- Valid for -->
|
||||
<div class="f-ebox">
|
||||
{{ invite_form.lifetime.label }}
|
||||
<div class="select-wrap">{{ invite_form.lifetime }}</div>
|
||||
</div>
|
||||
|
||||
<!-- Invite to circle -->
|
||||
<div class="f-ebox">
|
||||
{#
|
||||
NOTE: This is for when/if we ever support multi-group invites.
|
||||
@@ -27,6 +65,7 @@
|
||||
<div class="select-wrap">{{ invite_form.circles }}</div>
|
||||
{%- call render_errors(invite_form.circles) -%}{%- endcall -%}
|
||||
</div>
|
||||
|
||||
<div class="f-bbox">
|
||||
{%- call form_button("create_link", invite_form.action_create_invite, class="primary") %}{% endcall -%}
|
||||
</div>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{% extends "admin_app.html" %}
|
||||
{% from "library.j2" import form_button, standard_button, value_or_hint, custom_form_button, clipboard_button, icon %}
|
||||
{% from "library.j2" import form_button, standard_button, value_or_hint, custom_form_button, clipboard_button, icon, render_user with context %}
|
||||
{% block head_lead %}
|
||||
{{ super() }}
|
||||
{% include "copy-snippet.html" %}
|
||||
@@ -47,7 +47,7 @@
|
||||
<tbody>
|
||||
{%- for chat in circle_chats -%}
|
||||
<tr>
|
||||
<td class="collapsible">{% call value_or_hint(chat.name) %}{% endcall %}</td>
|
||||
<td>{% call value_or_hint(chat.name) %}{% endcall %}</td>
|
||||
<td class="nowrap">
|
||||
{%- call custom_form_button("delete", form.action_remove_group_chat.name, chat.id_, class="primary danger", slim=True) -%}
|
||||
{% trans name=chat.name %}Delete group chat '{{ name }}'{% endtrans %}
|
||||
@@ -71,7 +71,6 @@
|
||||
<div class="el-2 elevated"><table>
|
||||
<thead>
|
||||
<th>{% trans %}Login name{% endtrans %}</th>
|
||||
<th class="collapsible">{% trans %}Display name{% endtrans %}</th>
|
||||
<th>{% trans %}Actions{% endtrans %}</th>
|
||||
</thead>
|
||||
<tbody>
|
||||
@@ -79,13 +78,12 @@
|
||||
<tr>
|
||||
<td>
|
||||
{%- if member -%}
|
||||
{{ localpart }}
|
||||
{%- call render_user(member) -%}{%- endcall -%}
|
||||
{%- else -%}
|
||||
{{ localpart }}
|
||||
<span class="with-tooltip above" data-tooltip="{% trans %}The user has been deleted from the server.{% endtrans %}"><em> ({% trans %}deleted{% endtrans %})</em></span>
|
||||
{%- endif -%}
|
||||
</td>
|
||||
<td class="collapsible">{% call value_or_hint(member.display_name) %}{% endcall %}</td>
|
||||
<td class="nowrap">
|
||||
{%- call custom_form_button("remove_user", form.action_remove_user.name, member.localpart, class="primary danger", slim=True) -%}
|
||||
{% trans username=member.localpart %}Remove user {{ username }} from circle{% endtrans %}
|
||||
|
||||
@@ -1,21 +1,5 @@
|
||||
{% extends "admin_app.html" %}
|
||||
{% from "library.j2" import box, form_button, standard_button, icon %}
|
||||
{% macro access_level_description(role, caller=None) %}
|
||||
{%- if role == "prosody:restricted" -%}
|
||||
{% trans %}Limited users can interact with users on the same Snikket service and be members of circles.{% endtrans %}
|
||||
{%- elif role == "prosody:registered" -%}
|
||||
{% trans %}Like limited users and can also interact with users on other Snikket services.{% endtrans %}
|
||||
{%- elif role == "prosody:admin" -%}
|
||||
{% trans %}Like normal users and can access the admin panel in the web portal.{% endtrans %}
|
||||
{%- endif -%}
|
||||
{% endmacro %}
|
||||
{% macro access_level_icon(role, caller=None) %}
|
||||
{%- if role == "prosody:restricted" -%}
|
||||
{% call icon("lock") %}{% endcall %}
|
||||
{%- elif role == "prosody:admin" -%}
|
||||
{% call icon("admin") %}{% endcall %}
|
||||
{%- endif -%}
|
||||
{% endmacro %}
|
||||
{% from "library.j2" import box, form_button, standard_button, icon, access_level_description, access_level_icon %}
|
||||
{% block content %}
|
||||
<h1>{% trans user_name=target_user.localpart %}Edit user {{ user_name }}{% endtrans %}</h1>
|
||||
<form method="POST">{{ form.csrf_token }}<div class="form layout-expanded">
|
||||
|
||||
@@ -76,13 +76,20 @@
|
||||
<em>{% trans %}unknown{% endtrans %}</em>
|
||||
{%- endif -%}
|
||||
</dd>
|
||||
<dt>{% trans %}Connected devices{% endtrans %}</dt>
|
||||
<dt>{% trans %}Active users{% endtrans %}</dt>
|
||||
<dd>
|
||||
<ul>
|
||||
{%- if metrics.prosody_devices | default(None) is not none -%}
|
||||
{{ metrics.prosody_devices }}
|
||||
<li>{% trans %}Connected now:{% endtrans %} {{ metrics.prosody_devices }}</li>
|
||||
{%- else -%}
|
||||
<em>{% trans %}unknown{% endtrans %}</em>
|
||||
<li><em>{% trans %}unknown{% endtrans %}</em></li>
|
||||
{%- endif -%}
|
||||
{%- if metrics.users | default(None) is not none -%}
|
||||
<li>{% trans %}Past 24 hours:{% endtrans %} {{ metrics.users.active_1d }}</li>
|
||||
<li>{% trans %}Past 7 days:{% endtrans %} {{ metrics.users.active_7d }}</li>
|
||||
<li>{% trans %}Past 30 days:{% endtrans %} {{ metrics.users.active_30d }}</li>
|
||||
{%- endif -%}
|
||||
</ul>
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
|
||||
@@ -27,7 +27,6 @@
|
||||
{%- call action_button("edit", url_for(".edit_user", localpart=user.localpart), class="primary") -%}
|
||||
{% trans user_name=user.localpart %}Edit user {{ user_name }}{% endtrans %}
|
||||
{%- endcall -%}
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
{% block head_lead %}
|
||||
{{ super() }}
|
||||
<title>{% trans %}Reset your password | Snikket{% endtrans %}</title>
|
||||
<script async type="text/javascript" src="{{ url_for("static", filename="js/qrcode.min.js") }}"></script>
|
||||
{% endblock %}
|
||||
{% block content %}
|
||||
<form method="POST"><div class="form layout-expanded">
|
||||
@@ -27,9 +26,4 @@
|
||||
{%- call form_button("passwd", form.action_reset, class="primary") -%}{%- endcall -%}
|
||||
</div>
|
||||
</div></form>
|
||||
<script type="text/javascript">
|
||||
var onload = function() {
|
||||
apply_qr_code(document.getElementById("qr-uri"));
|
||||
};
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
@@ -134,7 +134,6 @@
|
||||
|
||||
var onload = function() {
|
||||
apply_qr_code(document.getElementById("qr-invite-page"));
|
||||
apply_qr_code(document.getElementById("qr-uri"));
|
||||
var popover_as = document.getElementsByClassName("popover");
|
||||
for (var i = 0; i < popover_as.length; ++i) {
|
||||
var a = popover_as[i];
|
||||
|
||||
@@ -25,10 +25,10 @@
|
||||
{%- endif -%}
|
||||
</div>
|
||||
<div class="user-info-container">
|
||||
<div class="user-localpart">{{- user.localpart -}}</div>
|
||||
{%- if user.display_name %}
|
||||
<div class="user-display-name">{{- user.display_name -}}</div>
|
||||
{%- endif %}
|
||||
<div class="user-jid"><span class="user-jid-localpart">{{- user.localpart -}}</span><span class="user-jid-at">@</span><span class="user-jid-domain">{{- config["SNIKKET_DOMAIN"] -}}</span></div>
|
||||
</div>
|
||||
</div>
|
||||
{%- endmacro -%}
|
||||
@@ -147,3 +147,37 @@
|
||||
{% trans %}Can be used once to create an account on this Snikket service.{% endtrans %}
|
||||
{%- endif -%}
|
||||
{%- endmacro -%}
|
||||
|
||||
{% macro access_level_description(role, caller=None) %}
|
||||
{%- if role == "prosody:restricted" -%}
|
||||
{% trans %}Limited users can interact with users on the same Snikket service and be members of circles.{% endtrans %}
|
||||
{%- elif role == "prosody:registered" -%}
|
||||
{% trans %}Like limited users and can also interact with users on other Snikket services.{% endtrans %}
|
||||
{%- elif role == "prosody:admin" -%}
|
||||
{% trans %}Like normal users and can access the admin panel in the web portal.{% endtrans %}
|
||||
{%- endif -%}
|
||||
{% endmacro %}
|
||||
|
||||
{% macro access_level_icon(role, caller=None) %}
|
||||
{%- if role == "prosody:restricted" -%}
|
||||
{% call icon("lock") %}{% endcall %}
|
||||
{%- elif role == "prosody:admin" -%}
|
||||
{% call icon("admin") %}{% endcall %}
|
||||
{%- endif -%}
|
||||
{% endmacro %}
|
||||
|
||||
{% macro invite_type_description(invite_type, caller=None) %}
|
||||
{%- if invite_type == "account" -%}
|
||||
{% trans %}Invite a single person (invitation link can only be used once).{% endtrans %}
|
||||
{%- elif invite_type == "group" -%}
|
||||
{% trans %}Invite a group of people (invitation link can be used multiple times).{% endtrans %}
|
||||
{%- endif -%}
|
||||
{% endmacro %}
|
||||
|
||||
{% macro invite_type_icon(invite_type, caller=None) %}
|
||||
{%- if invite_type == "account" -%}
|
||||
{% call icon("person") %}{% endcall %}
|
||||
{%- elif invite_type == "group" -%}
|
||||
{% call icon("people") %}{% endcall %}
|
||||
{%- endif -%}
|
||||
{% endmacro %}
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
<div class="f-bbox">
|
||||
{%- call form_button("login", form.action_signin, class="primary") -%}{% endcall -%}
|
||||
</div>
|
||||
</from>
|
||||
</form>
|
||||
<script type="text/javascript">
|
||||
var domainCheck = function() {
|
||||
var form = document.getElementById("login-form");
|
||||
|
||||
@@ -6,8 +6,13 @@
|
||||
{% include "copy-snippet.html" %}
|
||||
{% endblock %}
|
||||
{% block content %}
|
||||
<h1>{% trans %}Welcome!{% endtrans %}</h1>
|
||||
<p>{% trans user_name=user_info.display_name %}Welcome home, {{ user_name }}.{% endtrans %}</p>
|
||||
{% if user_info.is_admin and metrics.users and metrics.users.active_1d <= 1 %}
|
||||
<aside class="box hint">
|
||||
<header>{% trans %}Welcome to Snikket!{% endtrans %}</header>
|
||||
<p>{% trans %}Now your Snikket instance is up and running, the next step is to invite people to join it. Family, friends, colleagues... you choose!{% endtrans %}</p>
|
||||
<a href="/admin/invitations">{% trans %}Create new invitation{% endtrans %}</a>
|
||||
</aside>
|
||||
{% endif %}
|
||||
<nav class="welcome">
|
||||
<ul>
|
||||
<li class="wide">
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
BIN
snikket_web/translations/es/LC_MESSAGES/messages.mo
Normal file
BIN
snikket_web/translations/es/LC_MESSAGES/messages.mo
Normal file
Binary file not shown.
1817
snikket_web/translations/es/LC_MESSAGES/messages.po
Normal file
1817
snikket_web/translations/es/LC_MESSAGES/messages.po
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,21 +1,21 @@
|
||||
# Translations template for PROJECT.
|
||||
# Copyright (C) 2023 ORGANIZATION
|
||||
# Copyright (C) 2024 ORGANIZATION
|
||||
# This file is distributed under the same license as the PROJECT project.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2023.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2024.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PROJECT VERSION\n"
|
||||
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
||||
"POT-Creation-Date: 2023-12-08 12:08+0000\n"
|
||||
"POT-Creation-Date: 2024-04-27 14:22+0200\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: Babel 2.13.1\n"
|
||||
"Generated-By: Babel 2.10.3\n"
|
||||
|
||||
#: snikket_web/admin.py:69 snikket_web/templates/admin_delete_user.html:10
|
||||
#: snikket_web/templates/admin_edit_circle.html:73
|
||||
@@ -23,229 +23,230 @@ msgid "Login name"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:73 snikket_web/templates/admin_delete_user.html:12
|
||||
#: snikket_web/templates/admin_edit_circle.html:74 snikket_web/user.py:63
|
||||
#: snikket_web/user.py:69
|
||||
msgid "Display name"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:77 snikket_web/templates/admin_edit_user.html:53
|
||||
#: snikket_web/admin.py:77 snikket_web/admin.py:295
|
||||
#: snikket_web/templates/admin_edit_user.html:37
|
||||
msgid "Access Level"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:79
|
||||
#: snikket_web/admin.py:79 snikket_web/admin.py:297
|
||||
msgid "Limited"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:80
|
||||
#: snikket_web/admin.py:80 snikket_web/admin.py:298
|
||||
msgid "Normal user"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:81
|
||||
#: snikket_web/admin.py:81 snikket_web/admin.py:299
|
||||
msgid "Administrator"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:86
|
||||
#: snikket_web/admin.py:87
|
||||
msgid "Update user"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:90
|
||||
#: snikket_web/admin.py:91
|
||||
msgid "Restore account"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:94
|
||||
#: snikket_web/admin.py:95
|
||||
msgid "Unlock account"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:98
|
||||
#: snikket_web/admin.py:99
|
||||
msgid "Create password reset link"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:116
|
||||
#: snikket_web/admin.py:117
|
||||
msgid "Password reset link created"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:128
|
||||
#: snikket_web/admin.py:129
|
||||
msgid "User account restored"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:133
|
||||
#: snikket_web/admin.py:134
|
||||
msgid "User account unlocked"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:140
|
||||
#: snikket_web/admin.py:141
|
||||
msgid "Could not restore user account"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:145
|
||||
#: snikket_web/admin.py:146
|
||||
msgid "Could not unlock user account"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:157
|
||||
#: snikket_web/admin.py:158
|
||||
msgid "User information updated."
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:179
|
||||
#: snikket_web/admin.py:180
|
||||
msgid "Delete user permanently"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:192
|
||||
#: snikket_web/admin.py:193
|
||||
msgid "User deleted"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:230
|
||||
#: snikket_web/admin.py:231
|
||||
msgid "Password reset link not found"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:242
|
||||
#: snikket_web/admin.py:243
|
||||
msgid "Password reset link deleted"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:262
|
||||
#: snikket_web/admin.py:263
|
||||
msgid "Invite to circle"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:268
|
||||
#: snikket_web/admin.py:269
|
||||
msgid "At least one circle must be selected"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:273
|
||||
#: snikket_web/admin.py:274
|
||||
msgid "Valid for"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:275
|
||||
#: snikket_web/admin.py:276
|
||||
msgid "One hour"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:276
|
||||
#: snikket_web/admin.py:277
|
||||
msgid "Twelve hours"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:277
|
||||
#: snikket_web/admin.py:278
|
||||
msgid "One day"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:278
|
||||
#: snikket_web/admin.py:279
|
||||
msgid "One week"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:279
|
||||
#: snikket_web/admin.py:280
|
||||
msgid "Four weeks"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:285 snikket_web/templates/admin_edit_invite.html:17
|
||||
#: snikket_web/admin.py:286 snikket_web/templates/admin_edit_invite.html:17
|
||||
msgid "Invitation type"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:287 snikket_web/templates/library.j2:139
|
||||
#: snikket_web/admin.py:288 snikket_web/templates/library.j2:139
|
||||
msgid "Individual"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:288 snikket_web/templates/library.j2:137
|
||||
#: snikket_web/admin.py:289 snikket_web/templates/library.j2:137
|
||||
msgid "Group"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:294
|
||||
#: snikket_web/admin.py:305
|
||||
msgid "New invitation link"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:356
|
||||
#: snikket_web/admin.py:367
|
||||
msgid "Revoke"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:380
|
||||
#: snikket_web/admin.py:393
|
||||
msgid "Invitation created"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:396
|
||||
#: snikket_web/admin.py:409
|
||||
msgid "No such invitation exists"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:411
|
||||
#: snikket_web/admin.py:424
|
||||
msgid "Invitation revoked"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:428 snikket_web/admin.py:476
|
||||
#: snikket_web/admin.py:441 snikket_web/admin.py:489
|
||||
#: snikket_web/templates/admin_delete_circle.html:10
|
||||
#: snikket_web/templates/admin_edit_circle.html:44
|
||||
msgid "Name"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:433 snikket_web/templates/admin_circles.html:47
|
||||
#: snikket_web/admin.py:446 snikket_web/templates/admin_circles.html:47
|
||||
msgid "Create circle"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:463
|
||||
#: snikket_web/admin.py:476
|
||||
msgid "Circle created"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:481
|
||||
#: snikket_web/admin.py:494
|
||||
msgid "Select user"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:486
|
||||
#: snikket_web/admin.py:499
|
||||
msgid "Update circle"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:492
|
||||
#: snikket_web/admin.py:505
|
||||
msgid "Add user"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:510 snikket_web/admin.py:609 snikket_web/admin.py:657
|
||||
#: snikket_web/admin.py:523 snikket_web/admin.py:622 snikket_web/admin.py:670
|
||||
msgid "No such circle exists"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:547
|
||||
#: snikket_web/admin.py:560
|
||||
msgid "Circle data updated"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:557
|
||||
#: snikket_web/admin.py:570
|
||||
msgid "User added to circle"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:566
|
||||
#: snikket_web/admin.py:579
|
||||
msgid "User removed from circle"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:575
|
||||
#: snikket_web/admin.py:588
|
||||
msgid "Chat removed from circle"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:593
|
||||
#: snikket_web/admin.py:606
|
||||
msgid "Delete circle permanently"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:620
|
||||
#: snikket_web/admin.py:633
|
||||
msgid "Circle deleted"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:634
|
||||
#: snikket_web/admin.py:647
|
||||
msgid "Group chat name"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:639
|
||||
#: snikket_web/admin.py:652
|
||||
msgid "Create group chat"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:669
|
||||
#: snikket_web/admin.py:682
|
||||
msgid "New group chat added to circle"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:736
|
||||
#: snikket_web/admin.py:749
|
||||
msgid "Message contents"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:742
|
||||
#: snikket_web/admin.py:755
|
||||
msgid "Only send to online users"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:746
|
||||
#: snikket_web/admin.py:759
|
||||
msgid "Post to all users"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:750
|
||||
#: snikket_web/admin.py:763
|
||||
msgid "Send preview to yourself"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/admin.py:772
|
||||
#: snikket_web/admin.py:785
|
||||
msgid "Announcement sent!"
|
||||
msgstr ""
|
||||
|
||||
@@ -280,56 +281,56 @@ msgstr ""
|
||||
msgid "Username"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/invite.py:118 snikket_web/invite.py:186 snikket_web/main.py:43
|
||||
#: snikket_web/invite.py:118 snikket_web/invite.py:190 snikket_web/main.py:43
|
||||
msgid "Password"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/invite.py:122 snikket_web/invite.py:190
|
||||
#: snikket_web/invite.py:126 snikket_web/invite.py:198
|
||||
msgid "Confirm password"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/invite.py:126 snikket_web/invite.py:194
|
||||
#: snikket_web/invite.py:130 snikket_web/invite.py:202
|
||||
msgid "The passwords must match."
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/invite.py:131
|
||||
#: snikket_web/invite.py:135
|
||||
msgid "Create account"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/invite.py:158
|
||||
#: snikket_web/invite.py:162
|
||||
msgid "That username is already taken."
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/invite.py:162 snikket_web/invite.py:227
|
||||
#: snikket_web/invite.py:166 snikket_web/invite.py:235
|
||||
msgid "Registration was declined for unknown reasons."
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/invite.py:166
|
||||
#: snikket_web/invite.py:170
|
||||
msgid "The username is not valid."
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/invite.py:199 snikket_web/templates/user_home.html:32
|
||||
#: snikket_web/invite.py:207 snikket_web/templates/user_home.html:37
|
||||
#: snikket_web/templates/user_passwd.html:29
|
||||
msgid "Change password"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/invite.py:246
|
||||
#: snikket_web/invite.py:254
|
||||
msgid "Account data file"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/invite.py:250
|
||||
#: snikket_web/invite.py:258
|
||||
msgid "Import data"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/invite.py:271
|
||||
#: snikket_web/invite.py:279
|
||||
#, python-format
|
||||
msgid ""
|
||||
"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)."
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/invite.py:291 snikket_web/templates/unauth.html:18
|
||||
#: snikket_web/user.py:178
|
||||
#: snikket_web/invite.py:299 snikket_web/templates/unauth.html:18
|
||||
#: snikket_web/user.py:189
|
||||
msgid "Error"
|
||||
msgstr ""
|
||||
|
||||
@@ -357,73 +358,73 @@ msgstr ""
|
||||
msgid "New password"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/user.py:39
|
||||
#: snikket_web/user.py:42
|
||||
msgid "Confirm new password"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/user.py:43
|
||||
#: snikket_web/user.py:47
|
||||
msgid "The new passwords must match."
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/user.py:50
|
||||
#: snikket_web/user.py:56
|
||||
msgid "Sign out"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/user.py:55
|
||||
#: snikket_web/user.py:61
|
||||
msgid "Nobody"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/user.py:56
|
||||
#: snikket_web/user.py:62
|
||||
msgid "Friends only"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/user.py:57
|
||||
#: snikket_web/user.py:63
|
||||
msgid "Everyone"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/user.py:67
|
||||
#: snikket_web/user.py:73
|
||||
msgid "Avatar"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/user.py:71
|
||||
#: snikket_web/user.py:77
|
||||
msgid "Profile visibility"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/user.py:76
|
||||
#: snikket_web/user.py:82
|
||||
msgid "Update profile"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/user.py:82
|
||||
#: snikket_web/user.py:88
|
||||
msgid "Account data"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/user.py:86
|
||||
#: snikket_web/user.py:92
|
||||
msgid "Upload"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/user.py:111
|
||||
#: snikket_web/user.py:122
|
||||
msgid "Incorrect password."
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/user.py:115
|
||||
#: snikket_web/user.py:126
|
||||
msgid "Password changed"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/user.py:123
|
||||
#: snikket_web/user.py:134
|
||||
msgid ""
|
||||
"The chosen avatar is too big. To be able to upload larger avatars, please"
|
||||
" use the app."
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/user.py:170
|
||||
#: snikket_web/user.py:181
|
||||
msgid "Profile updated"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/user.py:184
|
||||
#: snikket_web/user.py:195
|
||||
msgid "Export"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/user.py:202
|
||||
#: snikket_web/user.py:213
|
||||
msgid "You currently have no account data to export."
|
||||
msgstr ""
|
||||
|
||||
@@ -544,7 +545,7 @@ msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_circles.html:15
|
||||
#: snikket_web/templates/admin_edit_circle.html:45
|
||||
#: snikket_web/templates/admin_edit_circle.html:75
|
||||
#: snikket_web/templates/admin_edit_circle.html:74
|
||||
#: snikket_web/templates/admin_invites.html:24
|
||||
#: snikket_web/templates/admin_users.html:10
|
||||
msgid "Actions"
|
||||
@@ -603,16 +604,42 @@ msgstr ""
|
||||
msgid "Create invitation"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_create_invite_form.html:5
|
||||
#: snikket_web/templates/admin_create_invite_form.html:9
|
||||
#: snikket_web/templates/user_home.html:13
|
||||
msgid "Create new invitation"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_create_invite_form.html:6
|
||||
#: snikket_web/templates/admin_create_invite_form.html:10
|
||||
msgid ""
|
||||
"Create a new invitation link to invite more users to your Snikket service"
|
||||
" by clicking the button below."
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_create_invite_form.html:16
|
||||
msgid ""
|
||||
"Choose whether this invitation link will allow more than one person to "
|
||||
"join."
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_create_invite_form.html:21
|
||||
#, python-format
|
||||
msgid "<span class=\"invite-type\">%(title)s%(icon)s</span><p>%(description)s</p>"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_create_invite_form.html:34
|
||||
#: snikket_web/templates/admin_edit_user.html:38
|
||||
msgid ""
|
||||
"The access level of a user determines what interactions are allowed for "
|
||||
"them on your Snikket service."
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_create_invite_form.html:38
|
||||
#, python-format
|
||||
msgid ""
|
||||
"<span class=\"access-"
|
||||
"level\">%(title)s%(icon)s</span><p>%(description)s</p>"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_debug_user.html:8
|
||||
#, python-format
|
||||
msgid "Debug information for %(user_name)s"
|
||||
@@ -678,7 +705,7 @@ msgid "Delete user %(user_name)s"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_delete_user.html:6
|
||||
#: snikket_web/templates/admin_edit_user.html:74
|
||||
#: snikket_web/templates/admin_edit_user.html:58
|
||||
msgid "Delete user"
|
||||
msgstr ""
|
||||
|
||||
@@ -742,37 +769,37 @@ msgstr ""
|
||||
msgid "All members of the circle will see each other in their contact list."
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_edit_circle.html:85
|
||||
#: snikket_web/templates/admin_edit_circle.html:84
|
||||
msgid "The user has been deleted from the server."
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_edit_circle.html:85
|
||||
#: snikket_web/templates/admin_edit_circle.html:84
|
||||
#: snikket_web/templates/library.j2:131
|
||||
msgid "deleted"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_edit_circle.html:91
|
||||
#: snikket_web/templates/admin_edit_circle.html:89
|
||||
#, python-format
|
||||
msgid "Remove user %(username)s from circle"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_edit_circle.html:99
|
||||
#: snikket_web/templates/admin_edit_circle.html:97
|
||||
msgid "This circle currently has no members."
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_edit_circle.html:101
|
||||
#: snikket_web/templates/admin_edit_circle.html:99
|
||||
msgid "Invite more members"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_edit_circle.html:104
|
||||
#: snikket_web/templates/admin_edit_circle.html:102
|
||||
msgid "Add existing user"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_edit_circle.html:115
|
||||
#: snikket_web/templates/admin_edit_circle.html:113
|
||||
msgid "All users added"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_edit_circle.html:116
|
||||
#: snikket_web/templates/admin_edit_circle.html:114
|
||||
msgid "All users on this service are already in this circle."
|
||||
msgstr ""
|
||||
|
||||
@@ -825,112 +852,90 @@ msgstr ""
|
||||
msgid "Return to invitation list"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_edit_user.html:5
|
||||
msgid ""
|
||||
"Limited users can interact with users on the same Snikket service and be "
|
||||
"members of circles."
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_edit_user.html:7
|
||||
msgid ""
|
||||
"Like limited users and can also interact with users on other Snikket "
|
||||
"services."
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_edit_user.html:9
|
||||
msgid "Like normal users and can access the admin panel in the web portal."
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_edit_user.html:20
|
||||
#: snikket_web/templates/admin_edit_user.html:4
|
||||
#: snikket_web/templates/admin_users.html:28
|
||||
#, python-format
|
||||
msgid "Edit user %(user_name)s"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_edit_user.html:24
|
||||
#: snikket_web/templates/admin_edit_user.html:8
|
||||
msgid "This user account is pending deletion"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_edit_user.html:25
|
||||
#: snikket_web/templates/admin_edit_user.html:9
|
||||
#, python-format
|
||||
msgid ""
|
||||
"The owner of the account sent a deletion request on %(date)s using their "
|
||||
"app."
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_edit_user.html:26
|
||||
#: snikket_web/templates/admin_edit_user.html:10
|
||||
#, python-format
|
||||
msgid ""
|
||||
"The account has been locked, and will be automatically deleted "
|
||||
"permanently in %(time)s."
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_edit_user.html:28
|
||||
#: snikket_web/templates/admin_edit_user.html:12
|
||||
msgid ""
|
||||
"If this was a mistake, you can cancel the deletion and restore the "
|
||||
"account."
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_edit_user.html:34
|
||||
#: snikket_web/templates/admin_edit_user.html:18
|
||||
msgid "This user account is locked"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_edit_user.html:35
|
||||
#: snikket_web/templates/admin_edit_user.html:19
|
||||
msgid ""
|
||||
"The user will not be able to log in to their account until it is unlocked"
|
||||
" again."
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_edit_user.html:41
|
||||
#: snikket_web/templates/admin_edit_user.html:25
|
||||
msgid "Edit user"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_edit_user.html:46
|
||||
#: snikket_web/templates/admin_edit_user.html:30
|
||||
msgid "The login name cannot be changed."
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_edit_user.html:54
|
||||
msgid ""
|
||||
"The access level of a user determines what interactions are allowed for "
|
||||
"them on your Snikket service."
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_edit_user.html:61
|
||||
#: snikket_web/templates/admin_edit_user.html:45
|
||||
#, python-format
|
||||
msgid "<strong>%(title)s%(icon)s</strong><p>%(description)s</p>"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_edit_user.html:71
|
||||
#: snikket_web/templates/admin_edit_user.html:55
|
||||
msgid "Return to user list"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_edit_user.html:79
|
||||
#: snikket_web/templates/admin_edit_user.html:63
|
||||
msgid "Further actions"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_edit_user.html:81
|
||||
#: snikket_web/templates/admin_edit_user.html:65
|
||||
msgid "Reset password"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_edit_user.html:84
|
||||
#: snikket_web/templates/admin_edit_user.html:68
|
||||
msgid ""
|
||||
"If the user has lost their password, you can use the button below to "
|
||||
"create a special link which allows to change the password of the account,"
|
||||
" once."
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_edit_user.html:89
|
||||
#: snikket_web/templates/admin_edit_user.html:73
|
||||
msgid "Debug information"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_edit_user.html:91
|
||||
#: snikket_web/templates/admin_edit_user.html:75
|
||||
msgid ""
|
||||
"In some cases, extended information about the user account and the "
|
||||
"connected devices is necessary to troubleshoot issues. The button below "
|
||||
"reveals this (sensitive) information."
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_edit_user.html:95
|
||||
#: snikket_web/templates/admin_edit_user.html:79
|
||||
msgid "Show debug information"
|
||||
msgstr ""
|
||||
|
||||
@@ -1060,7 +1065,7 @@ msgstr ""
|
||||
#: snikket_web/templates/admin_system.html:60
|
||||
#: snikket_web/templates/admin_system.html:68
|
||||
#: snikket_web/templates/admin_system.html:76
|
||||
#: snikket_web/templates/admin_system.html:84
|
||||
#: snikket_web/templates/admin_system.html:85
|
||||
msgid "unknown"
|
||||
msgstr ""
|
||||
|
||||
@@ -1108,14 +1113,30 @@ msgid "Storage used by shared files"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_system.html:79
|
||||
msgid "Connected devices"
|
||||
msgid "Active users"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_system.html:83
|
||||
msgid "Connected now:"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_system.html:88
|
||||
msgid "Past 24 hours:"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_system.html:89
|
||||
msgid "Past 7 days:"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_system.html:90
|
||||
msgid "Past 30 days:"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_system.html:97
|
||||
msgid "Broadcast message"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/admin_system.html:92
|
||||
#: snikket_web/templates/admin_system.html:99
|
||||
msgid ""
|
||||
"This form allows you to send a message to all users currently online on "
|
||||
"your Snikket server. Use it wisely."
|
||||
@@ -1260,11 +1281,11 @@ msgstr ""
|
||||
msgid "Reset your password | Snikket"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/invite_reset.html:15
|
||||
#: snikket_web/templates/invite_reset.html:14
|
||||
msgid "Reset your password online"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/invite_reset.html:16
|
||||
#: snikket_web/templates/invite_reset.html:15
|
||||
msgid ""
|
||||
"To reset your password online, fill out the fields below and confirm "
|
||||
"using the button."
|
||||
@@ -1358,7 +1379,7 @@ msgid "Your address"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/invite_success.html:15
|
||||
#: snikket_web/templates/user_home.html:21
|
||||
#: snikket_web/templates/user_home.html:26
|
||||
msgid "Copy address"
|
||||
msgstr ""
|
||||
|
||||
@@ -1560,6 +1581,30 @@ msgstr ""
|
||||
msgid "Can be used once to create an account on this Snikket service."
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/library.j2:153
|
||||
msgid ""
|
||||
"Limited users can interact with users on the same Snikket service and be "
|
||||
"members of circles."
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/library.j2:155
|
||||
msgid ""
|
||||
"Like limited users and can also interact with users on other Snikket "
|
||||
"services."
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/library.j2:157
|
||||
msgid "Like normal users and can access the admin panel in the web portal."
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/library.j2:171
|
||||
msgid "Invite a single person (invitation link can only be used once)."
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/library.j2:173
|
||||
msgid "Invite a group of people (invitation link can be used multiple times)."
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/login.html:5
|
||||
msgid "Snikket Login"
|
||||
msgstr ""
|
||||
@@ -1620,41 +1665,42 @@ msgstr ""
|
||||
msgid "Operation successful"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/user_home.html:9
|
||||
msgid "Welcome!"
|
||||
#: snikket_web/templates/user_home.html:11
|
||||
msgid "Welcome to Snikket!"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/user_home.html:10
|
||||
#, python-format
|
||||
msgid "Welcome home, %(user_name)s."
|
||||
#: snikket_web/templates/user_home.html:12
|
||||
msgid ""
|
||||
"Now your Snikket instance is up and running, the next step is to invite "
|
||||
"people to join it. Family, friends, colleagues... you choose!"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/user_home.html:14
|
||||
#: snikket_web/templates/user_home.html:19
|
||||
msgid "Your account"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/user_home.html:20
|
||||
#: snikket_web/templates/user_home.html:25
|
||||
msgid "Your XMPP address"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/user_home.html:31
|
||||
#: snikket_web/templates/user_home.html:36
|
||||
msgid "Edit profile"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/user_home.html:33
|
||||
#: snikket_web/templates/user_home.html:38
|
||||
#: snikket_web/templates/user_manage_data.html:4
|
||||
msgid "Manage your data"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/user_home.html:39
|
||||
#: snikket_web/templates/user_home.html:44
|
||||
msgid "Your Snikket"
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/user_home.html:41
|
||||
#: snikket_web/templates/user_home.html:46
|
||||
msgid "Manage users, invitations and circles of your Snikket service."
|
||||
msgstr ""
|
||||
|
||||
#: snikket_web/templates/user_home.html:43
|
||||
#: snikket_web/templates/user_home.html:48
|
||||
msgid "Admin panel"
|
||||
msgstr ""
|
||||
|
||||
|
||||
Binary file not shown.
File diff suppressed because it is too large
Load Diff
BIN
snikket_web/translations/ru/LC_MESSAGES/messages.mo
Normal file
BIN
snikket_web/translations/ru/LC_MESSAGES/messages.mo
Normal file
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
BIN
snikket_web/translations/uk/LC_MESSAGES/messages.mo
Normal file
BIN
snikket_web/translations/uk/LC_MESSAGES/messages.mo
Normal file
Binary file not shown.
1938
snikket_web/translations/uk/LC_MESSAGES/messages.po
Normal file
1938
snikket_web/translations/uk/LC_MESSAGES/messages.po
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -32,16 +32,22 @@ class ChangePasswordForm(BaseForm):
|
||||
|
||||
new_password = wtforms.PasswordField(
|
||||
_l("New password"),
|
||||
validators=[wtforms.validators.InputRequired()]
|
||||
validators=[
|
||||
wtforms.validators.InputRequired(),
|
||||
wtforms.validators.Length(min=10),
|
||||
]
|
||||
)
|
||||
|
||||
new_password_confirm = wtforms.PasswordField(
|
||||
_l("Confirm new password"),
|
||||
validators=[wtforms.validators.InputRequired(),
|
||||
wtforms.validators.EqualTo(
|
||||
"new_password",
|
||||
_l("The new passwords must match.")
|
||||
)]
|
||||
validators=[
|
||||
wtforms.validators.InputRequired(),
|
||||
wtforms.validators.EqualTo(
|
||||
"new_password",
|
||||
_l("The new passwords must match.")
|
||||
),
|
||||
wtforms.validators.Length(min=10),
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
@@ -91,7 +97,12 @@ class ImportAccountDataForm(BaseForm):
|
||||
@client.require_session()
|
||||
async def index() -> str:
|
||||
user_info = await client.get_user_info()
|
||||
return await render_template("user_home.html", user_info=user_info)
|
||||
metrics = await client.get_system_metrics()
|
||||
return await render_template(
|
||||
"user_home.html",
|
||||
user_info=user_info,
|
||||
metrics=metrics,
|
||||
)
|
||||
|
||||
|
||||
@bp.route('/passwd', methods=["GET", "POST"])
|
||||
|
||||
@@ -27,6 +27,7 @@ navigation/cancel:cancel
|
||||
navigation/more_vert:more
|
||||
social/groups:groups
|
||||
social/people:people
|
||||
social/person:person
|
||||
social/group_add:create_group
|
||||
social/person_add:add_user
|
||||
social/person_remove:remove_user
|
||||
|
||||
Reference in New Issue
Block a user