You've already forked snikket-web-portal
Compare commits
8 Commits
feature/si
...
feature/pr
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d9b73055a8 | ||
|
|
f37270594e | ||
|
|
fcfcdbeb23 | ||
|
|
fd566b7f30 | ||
|
|
2762304ae8 | ||
|
|
49bbc3ab09 | ||
|
|
8f1f80b7d7 | ||
|
|
13bc283a3e |
@@ -77,7 +77,7 @@ class EditUserForm(BaseForm):
|
|||||||
_l("Access Level"),
|
_l("Access Level"),
|
||||||
choices=[
|
choices=[
|
||||||
("prosody:restricted", _("Limited")),
|
("prosody:restricted", _("Limited")),
|
||||||
("prosody:normal", _l("Normal user")),
|
("prosody:user", _l("Normal user")),
|
||||||
("prosody:admin", _l("Administrator")),
|
("prosody:admin", _l("Administrator")),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
@@ -116,7 +116,7 @@ async def edit_user(localpart: str) -> typing.Union[werkzeug.Response, str]:
|
|||||||
await client.update_user(
|
await client.update_user(
|
||||||
localpart,
|
localpart,
|
||||||
display_name=form.display_name.data,
|
display_name=form.display_name.data,
|
||||||
roles=[form.role.data],
|
role=form.role.data,
|
||||||
)
|
)
|
||||||
|
|
||||||
await flash(
|
await flash(
|
||||||
@@ -131,7 +131,7 @@ async def edit_user(localpart: str) -> typing.Union[werkzeug.Response, str]:
|
|||||||
if target_user_info.roles:
|
if target_user_info.roles:
|
||||||
form.role.data = target_user_info.roles[0]
|
form.role.data = target_user_info.roles[0]
|
||||||
else:
|
else:
|
||||||
form.role.data = "prosody:normal"
|
form.role.data = "prosody:user"
|
||||||
|
|
||||||
return await render_template(
|
return await render_template(
|
||||||
"admin_edit_user.html",
|
"admin_edit_user.html",
|
||||||
@@ -452,10 +452,6 @@ class EditCircleForm(BaseForm):
|
|||||||
_l("Update circle")
|
_l("Update circle")
|
||||||
)
|
)
|
||||||
|
|
||||||
action_delete = wtforms.SubmitField(
|
|
||||||
_l("Delete circle permanently")
|
|
||||||
)
|
|
||||||
|
|
||||||
action_remove_user = wtforms.StringField()
|
action_remove_user = wtforms.StringField()
|
||||||
|
|
||||||
action_add_user = wtforms.SubmitField(
|
action_add_user = wtforms.SubmitField(
|
||||||
@@ -515,13 +511,6 @@ async def edit_circle(id_: str) -> typing.Union[str, werkzeug.Response]:
|
|||||||
_("Circle data updated"),
|
_("Circle data updated"),
|
||||||
"success",
|
"success",
|
||||||
)
|
)
|
||||||
elif form.action_delete.data:
|
|
||||||
await client.delete_group(id_)
|
|
||||||
await flash(
|
|
||||||
_("Circle deleted"),
|
|
||||||
"success",
|
|
||||||
)
|
|
||||||
return redirect(url_for(".circles"))
|
|
||||||
elif form.action_add_user.data:
|
elif form.action_add_user.data:
|
||||||
if form.user_to_add.data in valid_users:
|
if form.user_to_add.data in valid_users:
|
||||||
await client.add_group_member(
|
await client.add_group_member(
|
||||||
@@ -553,6 +542,47 @@ async def edit_circle(id_: str) -> typing.Union[str, werkzeug.Response]:
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class DeleteCircleForm(BaseForm):
|
||||||
|
action_delete = wtforms.SubmitField(
|
||||||
|
_l("Delete circle permanently")
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route("/circle/<id_>/delete", methods=["GET", "POST"])
|
||||||
|
@client.require_admin_session()
|
||||||
|
async def delete_circle(id_: str) -> typing.Union[str, werkzeug.Response]:
|
||||||
|
async with client.authenticated_session() as session:
|
||||||
|
try:
|
||||||
|
circle = await client.get_group_by_id(
|
||||||
|
id_,
|
||||||
|
session=session,
|
||||||
|
)
|
||||||
|
except aiohttp.ClientResponseError as exc:
|
||||||
|
if exc.status == 404:
|
||||||
|
await flash(
|
||||||
|
_("No such circle exists"),
|
||||||
|
"alert",
|
||||||
|
)
|
||||||
|
return redirect(url_for(".circles"))
|
||||||
|
raise
|
||||||
|
|
||||||
|
form = DeleteCircleForm()
|
||||||
|
if form.validate_on_submit():
|
||||||
|
if form.action_delete.data:
|
||||||
|
await client.delete_group(id_)
|
||||||
|
await flash(
|
||||||
|
_("Circle deleted"),
|
||||||
|
"success",
|
||||||
|
)
|
||||||
|
return redirect(url_for(".circles"))
|
||||||
|
|
||||||
|
return await render_template(
|
||||||
|
"admin_delete_circle.html",
|
||||||
|
target_circle=circle,
|
||||||
|
form=form,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
_CPU_EPOCH = time.process_time()
|
_CPU_EPOCH = time.process_time()
|
||||||
_MONOTONIC_EPOCH = time.monotonic()
|
_MONOTONIC_EPOCH = time.monotonic()
|
||||||
|
|
||||||
|
|||||||
@@ -27,8 +27,8 @@ from . import xmpputil
|
|||||||
from .xmpputil import split_jid
|
from .xmpputil import split_jid
|
||||||
|
|
||||||
|
|
||||||
SCOPE_DEFAULT = "prosody:scope:default"
|
SCOPE_DEFAULT = "prosody:user"
|
||||||
SCOPE_ADMIN = "prosody:scope:admin"
|
SCOPE_ADMIN = "prosody:admin"
|
||||||
|
|
||||||
|
|
||||||
T = typing.TypeVar("T")
|
T = typing.TypeVar("T")
|
||||||
@@ -61,12 +61,18 @@ class AdminUserInfo:
|
|||||||
cls,
|
cls,
|
||||||
data: typing.Mapping[str, typing.Any],
|
data: typing.Mapping[str, typing.Any],
|
||||||
) -> "AdminUserInfo":
|
) -> "AdminUserInfo":
|
||||||
|
try:
|
||||||
|
roles: typing.Optional[typing.List[str]] = [data["role"]]
|
||||||
|
assert roles is not None # make mypy happy
|
||||||
|
roles.extend(data.get("secondary_roles", []))
|
||||||
|
except KeyError:
|
||||||
|
roles = data.get("roles")
|
||||||
return cls(
|
return cls(
|
||||||
localpart=data["username"],
|
localpart=data["username"],
|
||||||
display_name=data.get("display_name") or None,
|
display_name=data.get("display_name") or None,
|
||||||
email=data.get("email") or None,
|
email=data.get("email") or None,
|
||||||
phone=data.get("phone") or None,
|
phone=data.get("phone") or None,
|
||||||
roles=data.get("roles"),
|
roles=roles,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -879,7 +885,7 @@ class ProsodyClient:
|
|||||||
localpart: str,
|
localpart: str,
|
||||||
*,
|
*,
|
||||||
display_name: typing.Optional[str],
|
display_name: typing.Optional[str],
|
||||||
roles: typing.Optional[typing.Collection[str]],
|
role: typing.Optional[str],
|
||||||
session: aiohttp.ClientSession,
|
session: aiohttp.ClientSession,
|
||||||
) -> None:
|
) -> None:
|
||||||
payload: typing.Dict[str, typing.Any] = {
|
payload: typing.Dict[str, typing.Any] = {
|
||||||
@@ -887,8 +893,8 @@ class ProsodyClient:
|
|||||||
}
|
}
|
||||||
if display_name is not None:
|
if display_name is not None:
|
||||||
payload["display_name"] = display_name
|
payload["display_name"] = display_name
|
||||||
if roles is not None:
|
if role is not None:
|
||||||
payload["roles"] = list(roles)
|
payload["role"] = role
|
||||||
|
|
||||||
async with session.put(
|
async with session.put(
|
||||||
self._admin_v1_endpoint("/users/{}".format(localpart)),
|
self._admin_v1_endpoint("/users/{}".format(localpart)),
|
||||||
|
|||||||
21
snikket_web/templates/admin_delete_circle.html
Normal file
21
snikket_web/templates/admin_delete_circle.html
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
{% extends "admin_app.html" %}
|
||||||
|
{% from "library.j2" import box, form_button, standard_button %}
|
||||||
|
{% block content %}
|
||||||
|
<h1>{% trans circle_name=target_circle.name %}Delete circle {{ circle_name }}{% endtrans %}</h1>
|
||||||
|
<div class="form layout-expanded"><form method="POST">
|
||||||
|
<h2 class="form-title">{% trans %}Delete circle{% endtrans %}</h2>
|
||||||
|
{{ form.csrf_token }}
|
||||||
|
<p class="form-descr">{% trans %}Are you sure you want to delete the following circle?{% endtrans %}</p>
|
||||||
|
<dl>
|
||||||
|
<dt>{% trans %}Name{% endtrans %}</dt>
|
||||||
|
<dd>{{ target_circle.name }}</dd>
|
||||||
|
</dl>
|
||||||
|
{% call box("alert", _("Danger")) %}
|
||||||
|
<p>{% trans %}The circle and the corresponding chat will be deleted, permanently and immediately upon pushing the below button. <strong>There is no way back!</strong>{% endtrans %}</p>
|
||||||
|
{% endcall %}
|
||||||
|
<div class="f-bbox">
|
||||||
|
{%- call standard_button("back", url_for(".edit_circle", id_=target_circle.id_), class="tertiary") %}{% trans %}Back{% endtrans %}{% endcall -%}
|
||||||
|
{%- call form_button("delete", form.action_delete, class="primary danger") %}{% endcall -%}
|
||||||
|
</div>
|
||||||
|
</form></div>
|
||||||
|
{% endblock %}
|
||||||
@@ -48,7 +48,7 @@
|
|||||||
<h3 class="form-title">{% trans %}Delete circle{% endtrans %}</h3>
|
<h3 class="form-title">{% trans %}Delete circle{% endtrans %}</h3>
|
||||||
<p class="form-desc">{% trans %}Deleting a circle does not delete any users in the circle.{% endtrans %}</p>
|
<p class="form-desc">{% trans %}Deleting a circle does not delete any users in the circle.{% endtrans %}</p>
|
||||||
<div class="f-bbox">
|
<div class="f-bbox">
|
||||||
{%- call form_button("delete", form.action_delete, class="secondary danger") %}{% endcall -%}
|
{%- call standard_button("delete", url_for(".delete_circle", id_=target_circle.id_), class="secondary danger") %}{% trans %}Delete circle{% endtrans %}{% endcall -%}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{%- endif -%}
|
{%- endif -%}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
{% macro access_level_description(role, caller=None) %}
|
{% macro access_level_description(role, caller=None) %}
|
||||||
{%- if role == "prosody:restricted" -%}
|
{%- if role == "prosody:restricted" -%}
|
||||||
{% trans %}Limited users can interact with users on the same Snikket service and be members of circles.{% endtrans %}
|
{% trans %}Limited users can interact with users on the same Snikket service and be members of circles.{% endtrans %}
|
||||||
{%- elif role == "prosody:normal" -%}
|
{%- elif role == "prosody:user" -%}
|
||||||
{% trans %}Like limited users and can also interact with users on other Snikket services.{% endtrans %}
|
{% trans %}Like limited users and can also interact with users on other Snikket services.{% endtrans %}
|
||||||
{%- elif role == "prosody:admin" -%}
|
{%- elif role == "prosody:admin" -%}
|
||||||
{% trans %}Like normal users and can access the admin panel in the web portal.{% endtrans %}
|
{% trans %}Like normal users and can access the admin panel in the web portal.{% endtrans %}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PROJECT VERSION\n"
|
"Project-Id-Version: PROJECT VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
||||||
"POT-Creation-Date: 2023-03-28 19:16+0200\n"
|
"POT-Creation-Date: 2023-04-01 10:07+0200\n"
|
||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
@@ -142,6 +142,7 @@ msgid "Invitation revoked"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: snikket_web/admin.py:394 snikket_web/admin.py:442
|
#: snikket_web/admin.py:394 snikket_web/admin.py:442
|
||||||
|
#: snikket_web/templates/admin_delete_circle.html:10
|
||||||
msgid "Name"
|
msgid "Name"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -161,51 +162,51 @@ msgstr ""
|
|||||||
msgid "Update circle"
|
msgid "Update circle"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: snikket_web/admin.py:456
|
#: snikket_web/admin.py:458
|
||||||
msgid "Delete circle permanently"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: snikket_web/admin.py:462
|
|
||||||
msgid "Add user"
|
msgid "Add user"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: snikket_web/admin.py:478
|
#: snikket_web/admin.py:474 snikket_web/admin.py:563
|
||||||
msgid "No such circle exists"
|
msgid "No such circle exists"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: snikket_web/admin.py:515
|
#: snikket_web/admin.py:511
|
||||||
msgid "Circle data updated"
|
msgid "Circle data updated"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: snikket_web/admin.py:521
|
#: snikket_web/admin.py:521
|
||||||
msgid "Circle deleted"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: snikket_web/admin.py:532
|
|
||||||
msgid "User added to circle"
|
msgid "User added to circle"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: snikket_web/admin.py:541
|
#: snikket_web/admin.py:530
|
||||||
msgid "User removed from circle"
|
msgid "User removed from circle"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: snikket_web/admin.py:610
|
#: snikket_web/admin.py:547
|
||||||
|
msgid "Delete circle permanently"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: snikket_web/admin.py:574
|
||||||
|
msgid "Circle deleted"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: snikket_web/admin.py:640
|
||||||
msgid "Message contents"
|
msgid "Message contents"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: snikket_web/admin.py:616
|
#: snikket_web/admin.py:646
|
||||||
msgid "Only send to online users"
|
msgid "Only send to online users"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: snikket_web/admin.py:620
|
#: snikket_web/admin.py:650
|
||||||
msgid "Post to all users"
|
msgid "Post to all users"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: snikket_web/admin.py:624
|
#: snikket_web/admin.py:654
|
||||||
msgid "Send preview to yourself"
|
msgid "Send preview to yourself"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: snikket_web/admin.py:646
|
#: snikket_web/admin.py:676
|
||||||
msgid "Announcement sent!"
|
msgid "Announcement sent!"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -552,6 +553,43 @@ msgstr ""
|
|||||||
msgid "Copy complete output"
|
msgid "Copy complete output"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: snikket_web/templates/admin_delete_circle.html:4
|
||||||
|
#, python-format
|
||||||
|
msgid "Delete circle %(circle_name)s"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: snikket_web/templates/admin_delete_circle.html:6
|
||||||
|
#: snikket_web/templates/admin_edit_circle.html:48
|
||||||
|
#: snikket_web/templates/admin_edit_circle.html:51
|
||||||
|
msgid "Delete circle"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: snikket_web/templates/admin_delete_circle.html:8
|
||||||
|
msgid "Are you sure you want to delete the following circle?"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: snikket_web/templates/admin_delete_circle.html:13
|
||||||
|
#: snikket_web/templates/admin_delete_user.html:15
|
||||||
|
msgid "Danger"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: snikket_web/templates/admin_delete_circle.html:14
|
||||||
|
msgid ""
|
||||||
|
"The circle and the corresponding chat will be deleted, permanently and "
|
||||||
|
"immediately upon pushing the below button. <strong>There is no way "
|
||||||
|
"back!</strong>"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: snikket_web/templates/admin_delete_circle.html:17
|
||||||
|
#: snikket_web/templates/admin_delete_user.html:19
|
||||||
|
#: snikket_web/templates/admin_reset_user_password.html:25
|
||||||
|
#: snikket_web/templates/user_logout.html:10
|
||||||
|
#: snikket_web/templates/user_manage_data.html:14
|
||||||
|
#: snikket_web/templates/user_passwd.html:27
|
||||||
|
#: snikket_web/templates/user_profile.html:32
|
||||||
|
msgid "Back"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: snikket_web/templates/admin_delete_user.html:4
|
#: snikket_web/templates/admin_delete_user.html:4
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Delete user %(user_name)s"
|
msgid "Delete user %(user_name)s"
|
||||||
@@ -566,10 +604,6 @@ msgstr ""
|
|||||||
msgid "Are you sure you want to delete the following user?"
|
msgid "Are you sure you want to delete the following user?"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: snikket_web/templates/admin_delete_user.html:15
|
|
||||||
msgid "Danger"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: snikket_web/templates/admin_delete_user.html:16
|
#: snikket_web/templates/admin_delete_user.html:16
|
||||||
msgid ""
|
msgid ""
|
||||||
"The user and their data will be deleted irrevocably, permanently and "
|
"The user and their data will be deleted irrevocably, permanently and "
|
||||||
@@ -577,15 +611,6 @@ msgid ""
|
|||||||
"back!</strong>"
|
"back!</strong>"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: snikket_web/templates/admin_delete_user.html:19
|
|
||||||
#: snikket_web/templates/admin_reset_user_password.html:25
|
|
||||||
#: snikket_web/templates/user_logout.html:10
|
|
||||||
#: snikket_web/templates/user_manage_data.html:14
|
|
||||||
#: snikket_web/templates/user_passwd.html:27
|
|
||||||
#: snikket_web/templates/user_profile.html:32
|
|
||||||
msgid "Back"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: snikket_web/templates/admin_edit_circle.html:14
|
#: snikket_web/templates/admin_edit_circle.html:14
|
||||||
msgid "This is your main circle"
|
msgid "This is your main circle"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -618,10 +643,6 @@ msgstr ""
|
|||||||
msgid "Return to circle list"
|
msgid "Return to circle list"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: snikket_web/templates/admin_edit_circle.html:48
|
|
||||||
msgid "Delete circle"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: snikket_web/templates/admin_edit_circle.html:49
|
#: snikket_web/templates/admin_edit_circle.html:49
|
||||||
msgid "Deleting a circle does not delete any users in the circle."
|
msgid "Deleting a circle does not delete any users in the circle."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|||||||
Reference in New Issue
Block a user