From 4bdcb46a8a938ffea0e2347836c39f192f85ef5a Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Tue, 16 Apr 2024 21:16:06 +0100 Subject: [PATCH 1/2] Allow selecting a role when creating an invitation Includes some reorganization and prettification of the creation form. --- snikket_web/admin.py | 15 +++++- snikket_web/prosodyclient.py | 6 +++ snikket_web/scss/app.scss | 11 +++++ snikket_web/static/img/icons.svg | 5 ++ .../templates/admin_create_invite_form.html | 46 +++++++++++++++++-- snikket_web/templates/admin_edit_user.html | 18 +------- snikket_web/templates/library.j2 | 34 ++++++++++++++ tools/icons.list | 1 + 8 files changed, 113 insertions(+), 23 deletions(-) diff --git a/snikket_web/admin.py b/snikket_web/admin.py index 083cdb1..0f22054 100644 --- a/snikket_web/admin.py +++ b/snikket_web/admin.py @@ -284,12 +284,21 @@ class InvitePost(BaseForm): type_ = wtforms.RadioField( _l("Invitation type"), choices=[ - ("account", _l("Individual (for one person)")), - ("group", _l("Group (for multiple people)")), + ("account", _l("Individual")), + ("group", _l("Group")), ], default="account", ) + role = wtforms.RadioField( + _l("Access Level"), + choices=[ + ("prosody:restricted", _l("Limited")), + ("prosody:registered", _l("Normal user")), + ("prosody:admin", _l("Administrator")), + ], + ) + action_create_invite = wtforms.SubmitField( _l("New invitation link") ) @@ -369,11 +378,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( diff --git a/snikket_web/prosodyclient.py b/snikket_web/prosodyclient.py index 5c55c0e..2f9b6d1 100644 --- a/snikket_web/prosodyclient.py +++ b/snikket_web/prosodyclient.py @@ -160,6 +160,7 @@ class AdminInviteInfo: expires: datetime reusable: bool group_ids: typing.Collection[str] + role_names: typing.Collection[str] is_reset: bool @classmethod @@ -177,6 +178,7 @@ def from_api_response( 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), ) @@ -1086,12 +1088,14 @@ async def create_account_invite( 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: @@ -1108,11 +1112,13 @@ async def create_group_invite( 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 diff --git a/snikket_web/scss/app.scss b/snikket_web/scss/app.scss index 016b434..22c89b2 100644 --- a/snikket_web/scss/app.scss +++ b/snikket_web/scss/app.scss @@ -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; diff --git a/snikket_web/static/img/icons.svg b/snikket_web/static/img/icons.svg index 7b5fbf8..f2a0c88 100644 --- a/snikket_web/static/img/icons.svg +++ b/snikket_web/static/img/icons.svg @@ -148,6 +148,11 @@ licensed under the terms of the Apache 2.0 License --> + + + + + diff --git a/snikket_web/templates/admin_create_invite_form.html b/snikket_web/templates/admin_create_invite_form.html index acda7ec..f4c4144 100644 --- a/snikket_web/templates/admin_create_invite_form.html +++ b/snikket_web/templates/admin_create_invite_form.html @@ -1,20 +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 +%}
{{- invite_form.csrf_token -}}

{% trans %}Create new invitation{% endtrans %}

{% trans %}Create a new invitation link to invite more users to your Snikket service by clicking the button below.{% endtrans %}

+ +
-
{#- -#} +
{#- -#} {{ invite_form.type_.label.text }} - {% trans %}Choose whether this invitation link will allow more than one person to join.{% endtrans %} - {{- invite_form.type_ -}} +

{% trans %}Choose whether this invitation link will allow more than one person to join.{% endtrans %}

+ + {%- for invite_type in invite_form.type_ -%} +
+ {{ invite_type }} +
+ {%- endfor -%}
+ + +
+
{#- -#} + {{ invite_form.role.label.text }} +

{% trans %}The access level of a user determines what interactions are allowed for them on your Snikket service.{% endtrans %}

+ {%- for level in invite_form.role -%} +
+ {{ level }} +
+ {%- endfor -%} +
+
+ + +
{{ invite_form.lifetime.label }}
{{ invite_form.lifetime }}
+ +
{# NOTE: This is for when/if we ever support multi-group invites. @@ -28,6 +65,7 @@

{% trans %}Create new invitation{% endtrans %}

{{ invite_form.circles }}
{%- call render_errors(invite_form.circles) -%}{%- endcall -%}
+
{%- call form_button("create_link", invite_form.action_create_invite, class="primary") %}{% endcall -%}
diff --git a/snikket_web/templates/admin_edit_user.html b/snikket_web/templates/admin_edit_user.html index a5ac5e3..387cdba 100644 --- a/snikket_web/templates/admin_edit_user.html +++ b/snikket_web/templates/admin_edit_user.html @@ -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 %}

{% trans user_name=target_user.localpart %}Edit user {{ user_name }}{% endtrans %}

{{ form.csrf_token }}
diff --git a/snikket_web/templates/library.j2 b/snikket_web/templates/library.j2 index 9e5c660..76bcda7 100644 --- a/snikket_web/templates/library.j2 +++ b/snikket_web/templates/library.j2 @@ -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 %} diff --git a/tools/icons.list b/tools/icons.list index 803448e..a17999e 100644 --- a/tools/icons.list +++ b/tools/icons.list @@ -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 From 7e26b5f994028f76d4a236ebc4cf3175fe916880 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Tue, 16 Apr 2024 21:22:07 +0100 Subject: [PATCH 2/2] Update translations --- snikket_web/translations/messages.pot | 224 ++++++++++++-------------- 1 file changed, 105 insertions(+), 119 deletions(-) diff --git a/snikket_web/translations/messages.pot b/snikket_web/translations/messages.pot index f06d7ba..33ffbfb 100644 --- a/snikket_web/translations/messages.pot +++ b/snikket_web/translations/messages.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2024-04-16 15:50+0100\n" +"POT-Creation-Date: 2024-04-16 21:21+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -27,19 +27,20 @@ msgstr "" 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:294 +#: 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:296 msgid "Limited" msgstr "" -#: snikket_web/admin.py:80 +#: snikket_web/admin.py:80 snikket_web/admin.py:297 msgid "Normal user" msgstr "" -#: snikket_web/admin.py:81 +#: snikket_web/admin.py:81 snikket_web/admin.py:298 msgid "Administrator" msgstr "" @@ -135,117 +136,117 @@ msgstr "" msgid "Invitation type" msgstr "" -#: snikket_web/admin.py:287 -msgid "Individual (for one person)" +#: snikket_web/admin.py:287 snikket_web/templates/library.j2:139 +msgid "Individual" msgstr "" -#: snikket_web/admin.py:288 -msgid "Group (for multiple people)" +#: snikket_web/admin.py:288 snikket_web/templates/library.j2:137 +msgid "Group" msgstr "" -#: snikket_web/admin.py:294 +#: snikket_web/admin.py:303 msgid "New invitation link" msgstr "" -#: snikket_web/admin.py:356 +#: snikket_web/admin.py:365 msgid "Revoke" msgstr "" -#: snikket_web/admin.py:380 +#: snikket_web/admin.py:391 msgid "Invitation created" msgstr "" -#: snikket_web/admin.py:396 +#: snikket_web/admin.py:407 msgid "No such invitation exists" msgstr "" -#: snikket_web/admin.py:411 +#: snikket_web/admin.py:422 msgid "Invitation revoked" msgstr "" -#: snikket_web/admin.py:428 snikket_web/admin.py:476 +#: snikket_web/admin.py:439 snikket_web/admin.py:487 #: 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:444 snikket_web/templates/admin_circles.html:47 msgid "Create circle" msgstr "" -#: snikket_web/admin.py:463 +#: snikket_web/admin.py:474 msgid "Circle created" msgstr "" -#: snikket_web/admin.py:481 +#: snikket_web/admin.py:492 msgid "Select user" msgstr "" -#: snikket_web/admin.py:486 +#: snikket_web/admin.py:497 msgid "Update circle" msgstr "" -#: snikket_web/admin.py:492 +#: snikket_web/admin.py:503 msgid "Add user" msgstr "" -#: snikket_web/admin.py:510 snikket_web/admin.py:609 snikket_web/admin.py:657 +#: snikket_web/admin.py:521 snikket_web/admin.py:620 snikket_web/admin.py:668 msgid "No such circle exists" msgstr "" -#: snikket_web/admin.py:547 +#: snikket_web/admin.py:558 msgid "Circle data updated" msgstr "" -#: snikket_web/admin.py:557 +#: snikket_web/admin.py:568 msgid "User added to circle" msgstr "" -#: snikket_web/admin.py:566 +#: snikket_web/admin.py:577 msgid "User removed from circle" msgstr "" -#: snikket_web/admin.py:575 +#: snikket_web/admin.py:586 msgid "Chat removed from circle" msgstr "" -#: snikket_web/admin.py:593 +#: snikket_web/admin.py:604 msgid "Delete circle permanently" msgstr "" -#: snikket_web/admin.py:620 +#: snikket_web/admin.py:631 msgid "Circle deleted" msgstr "" -#: snikket_web/admin.py:634 +#: snikket_web/admin.py:645 msgid "Group chat name" msgstr "" -#: snikket_web/admin.py:639 +#: snikket_web/admin.py:650 msgid "Create group chat" msgstr "" -#: snikket_web/admin.py:669 +#: snikket_web/admin.py:680 msgid "New group chat added to circle" msgstr "" -#: snikket_web/admin.py:736 +#: snikket_web/admin.py:747 msgid "Message contents" msgstr "" -#: snikket_web/admin.py:742 +#: snikket_web/admin.py:753 msgid "Only send to online users" msgstr "" -#: snikket_web/admin.py:746 +#: snikket_web/admin.py:757 msgid "Post to all users" msgstr "" -#: snikket_web/admin.py:750 +#: snikket_web/admin.py:761 msgid "Send preview to yourself" msgstr "" -#: snikket_web/admin.py:772 +#: snikket_web/admin.py:783 msgid "Announcement sent!" msgstr "" @@ -308,8 +309,7 @@ msgstr "" msgid "The username is not valid." msgstr "" -#: snikket_web/invite.py:207 snikket_web/templates/user_home.html:37 -#: snikket_web/templates/user_passwd.html:29 +#: snikket_web/invite.py:207 snikket_web/templates/user_passwd.html:29 msgid "Change password" msgstr "" @@ -603,23 +603,41 @@ msgstr "" msgid "Create invitation" msgstr "" -#: snikket_web/templates/admin_create_invite_form.html:5 -#: snikket_web/templates/user_home.html:13 +#: snikket_web/templates/admin_create_invite_form.html:9 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:10 +#: 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 "%(title)s%(icon)s

%(description)s

" +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 "" +"%(title)s%(icon)s

%(description)s

" +msgstr "" + #: snikket_web/templates/admin_debug_user.html:8 #, python-format msgid "Debug information for %(user_name)s" @@ -685,7 +703,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 "" @@ -832,112 +850,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 "%(title)s%(icon)s

%(description)s

" 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 "" @@ -1381,7 +1377,6 @@ msgid "Your address" msgstr "" #: snikket_web/templates/invite_success.html:15 -#: snikket_web/templates/user_home.html:26 msgid "Copy address" msgstr "" @@ -1575,14 +1570,6 @@ msgstr "" msgid "Invalid input" msgstr "" -#: snikket_web/templates/library.j2:137 -msgid "Group" -msgstr "" - -#: snikket_web/templates/library.j2:139 -msgid "Individual" -msgstr "" - #: snikket_web/templates/library.j2:145 msgid "Can be used multiple times to create accounts on this Snikket service." msgstr "" @@ -1591,6 +1578,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 "" @@ -1651,35 +1662,6 @@ msgstr "" msgid "Operation successful" msgstr "" -#: snikket_web/templates/user_home.html:19 -msgid "Your account" -msgstr "" - -#: snikket_web/templates/user_home.html:25 -msgid "Your XMPP address" -msgstr "" - -#: snikket_web/templates/user_home.html:36 -msgid "Edit profile" -msgstr "" - -#: 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:44 -msgid "Your Snikket" -msgstr "" - -#: snikket_web/templates/user_home.html:46 -msgid "Manage users, invitations and circles of your Snikket service." -msgstr "" - -#: snikket_web/templates/user_home.html:48 -msgid "Admin panel" -msgstr "" - #: snikket_web/templates/user_logout.html:5 msgid "Sign out of the Snikket Web Portal" msgstr "" @@ -1690,6 +1672,10 @@ msgid "" "any other connected devices." msgstr "" +#: snikket_web/templates/user_manage_data.html:4 +msgid "Manage your data" +msgstr "" + #: snikket_web/templates/user_manage_data.html:8 msgid "Export account" msgstr ""