forked from Github-Mirrors/canaille
fix: display an error message when trying to remove the last user from a group
This commit is contained in:
parent
fe2665ae32
commit
5aaccca4cf
5 changed files with 135 additions and 84 deletions
|
@ -2,6 +2,7 @@
|
|||
Fixed
|
||||
^^^^^
|
||||
- LDAP user group removal.
|
||||
- Display an error message when trying to remove the last user from a group.
|
||||
|
||||
[0.0.48] - 2024-04-08
|
||||
---------------------
|
||||
|
|
|
@ -256,7 +256,7 @@ class IDToModel:
|
|||
|
||||
def __call__(self, data):
|
||||
model = getattr(models, self.model_name)
|
||||
instance = data if isinstance(data, model) else model.get(id=data)
|
||||
instance = data if isinstance(data, model) else model.get(data)
|
||||
if not instance:
|
||||
raise wtforms.ValidationError()
|
||||
return instance
|
||||
|
|
|
@ -56,6 +56,24 @@ def existing_login(form, field):
|
|||
)
|
||||
|
||||
|
||||
def non_empty_groups(form, field):
|
||||
"""LDAP groups cannot be empty because groupOfNames.member is a MUST
|
||||
attribute.
|
||||
|
||||
https://www.rfc-editor.org/rfc/rfc2256.html#section-7.10
|
||||
"""
|
||||
if not form.user:
|
||||
return
|
||||
|
||||
for group in form.user.groups:
|
||||
if len(group.members) == 1 and group not in field.data:
|
||||
raise wtforms.ValidationError(
|
||||
_(
|
||||
"The group '{group}' cannot be removed, because it must have at least one user left."
|
||||
).format(group=group.display_name)
|
||||
)
|
||||
|
||||
|
||||
class LoginForm(Form):
|
||||
login = wtforms.StringField(
|
||||
_("Login"),
|
||||
|
@ -279,6 +297,7 @@ PROFILE_FORM_FIELDS = dict(
|
|||
choices=lambda: [(group, group.display_name) for group in models.Group.query()],
|
||||
render_kw={"placeholder": _("users, admins …")},
|
||||
coerce=IDToModel("Group"),
|
||||
validators=[non_empty_groups],
|
||||
),
|
||||
)
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: PROJECT VERSION\n"
|
||||
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
||||
"POT-Creation-Date: 2024-04-07 19:49+0200\n"
|
||||
"POT-Creation-Date: 2024-04-08 14:43+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"
|
||||
|
@ -41,36 +41,36 @@ msgstr ""
|
|||
msgid "Not a valid datetime value."
|
||||
msgstr ""
|
||||
|
||||
#: canaille/backends/ldap/backend.py:94
|
||||
#: canaille/backends/ldap/backend.py:97
|
||||
msgid "Could not connect to the LDAP server '{uri}'"
|
||||
msgstr ""
|
||||
|
||||
#: canaille/backends/ldap/backend.py:101
|
||||
#: canaille/backends/ldap/backend.py:104
|
||||
msgid "LDAP authentication failed with user '{user}'"
|
||||
msgstr ""
|
||||
|
||||
#: canaille/backends/ldap/backend.py:170
|
||||
#: canaille/backends/ldap/backend.py:173
|
||||
msgid "John Doe"
|
||||
msgstr ""
|
||||
|
||||
#: canaille/backends/ldap/backend.py:173 canaille/core/endpoints/forms.py:127
|
||||
#: canaille/core/endpoints/forms.py:375
|
||||
#: canaille/backends/ldap/backend.py:176 canaille/core/endpoints/forms.py:146
|
||||
#: canaille/core/endpoints/forms.py:395
|
||||
msgid "jdoe"
|
||||
msgstr ""
|
||||
|
||||
#: canaille/backends/ldap/backend.py:176
|
||||
#: canaille/backends/ldap/backend.py:179
|
||||
msgid "john@doe.com"
|
||||
msgstr ""
|
||||
|
||||
#: canaille/backends/ldap/backend.py:178
|
||||
#: canaille/backends/ldap/backend.py:181
|
||||
msgid " or "
|
||||
msgstr ""
|
||||
|
||||
#: canaille/backends/ldap/models.py:98
|
||||
#: canaille/backends/ldap/backend.py:236
|
||||
msgid "Your account has been locked."
|
||||
msgstr ""
|
||||
|
||||
#: canaille/backends/ldap/models.py:103
|
||||
#: canaille/backends/ldap/backend.py:241
|
||||
msgid "You should change your password."
|
||||
msgstr ""
|
||||
|
||||
|
@ -128,8 +128,8 @@ msgstr ""
|
|||
msgid "You are already logged in, you cannot create an account."
|
||||
msgstr ""
|
||||
|
||||
#: canaille/core/endpoints/account.py:297 canaille/core/endpoints/forms.py:276
|
||||
#: canaille/core/endpoints/forms.py:393 canaille/core/templates/groups.html:5
|
||||
#: canaille/core/endpoints/account.py:297 canaille/core/endpoints/forms.py:295
|
||||
#: canaille/core/endpoints/forms.py:413 canaille/core/templates/groups.html:5
|
||||
#: canaille/core/templates/groups.html:23
|
||||
#: canaille/core/templates/partial/users.html:18
|
||||
#: canaille/templates/base.html:57
|
||||
|
@ -175,12 +175,12 @@ msgid "User account creation succeed."
|
|||
msgstr ""
|
||||
|
||||
#: canaille/core/endpoints/account.py:609
|
||||
#: canaille/core/endpoints/account.py:771
|
||||
#: canaille/core/endpoints/account.py:770
|
||||
msgid "Profile edition failed."
|
||||
msgstr ""
|
||||
|
||||
#: canaille/core/endpoints/account.py:613
|
||||
#: canaille/core/endpoints/account.py:786
|
||||
#: canaille/core/endpoints/account.py:785
|
||||
msgid "Profile updated successfully."
|
||||
msgstr ""
|
||||
|
||||
|
@ -212,7 +212,7 @@ msgid ""
|
|||
"It should be received within a few minutes."
|
||||
msgstr ""
|
||||
|
||||
#: canaille/core/endpoints/account.py:689 canaille/core/endpoints/auth.py:137
|
||||
#: canaille/core/endpoints/account.py:689 canaille/core/endpoints/auth.py:136
|
||||
msgid "Could not send the password initialization email"
|
||||
msgstr ""
|
||||
|
||||
|
@ -234,12 +234,12 @@ msgstr ""
|
|||
msgid "The account has been unlocked"
|
||||
msgstr ""
|
||||
|
||||
#: canaille/core/endpoints/account.py:806
|
||||
#: canaille/core/endpoints/account.py:805
|
||||
#, python-format
|
||||
msgid "The user %(user)s has been sucessfuly deleted"
|
||||
msgstr ""
|
||||
|
||||
#: canaille/core/endpoints/account.py:824 canaille/core/endpoints/auth.py:93
|
||||
#: canaille/core/endpoints/account.py:823 canaille/core/endpoints/auth.py:92
|
||||
#, python-format
|
||||
msgid "Connection successful. Welcome %(user)s"
|
||||
msgstr ""
|
||||
|
@ -249,10 +249,10 @@ msgstr ""
|
|||
msgid "Email"
|
||||
msgstr ""
|
||||
|
||||
#: canaille/core/endpoints/admin.py:29 canaille/core/endpoints/forms.py:63
|
||||
#: canaille/core/endpoints/forms.py:83 canaille/core/endpoints/forms.py:172
|
||||
#: canaille/core/endpoints/forms.py:361 canaille/core/endpoints/forms.py:387
|
||||
#: canaille/core/endpoints/forms.py:408 canaille/core/endpoints/forms.py:424
|
||||
#: canaille/core/endpoints/admin.py:29 canaille/core/endpoints/forms.py:82
|
||||
#: canaille/core/endpoints/forms.py:102 canaille/core/endpoints/forms.py:191
|
||||
#: canaille/core/endpoints/forms.py:381 canaille/core/endpoints/forms.py:407
|
||||
#: canaille/core/endpoints/forms.py:428 canaille/core/endpoints/forms.py:444
|
||||
msgid "jane@doe.com"
|
||||
msgstr ""
|
||||
|
||||
|
@ -272,96 +272,102 @@ msgstr ""
|
|||
msgid "Email confirmation on {website_name}"
|
||||
msgstr ""
|
||||
|
||||
#: canaille/core/endpoints/auth.py:51 canaille/core/endpoints/auth.py:77
|
||||
#: canaille/core/endpoints/auth.py:85
|
||||
#: canaille/core/endpoints/auth.py:50 canaille/core/endpoints/auth.py:76
|
||||
#: canaille/core/endpoints/auth.py:84
|
||||
msgid "Login failed, please check your information"
|
||||
msgstr ""
|
||||
|
||||
#: canaille/core/endpoints/auth.py:105
|
||||
#: canaille/core/endpoints/auth.py:104
|
||||
#, python-format
|
||||
msgid "You have been disconnected. See you next time %(user)s"
|
||||
msgstr ""
|
||||
|
||||
#: canaille/core/endpoints/auth.py:130
|
||||
#: canaille/core/endpoints/auth.py:129
|
||||
msgid ""
|
||||
"A password initialization link has been sent at your email address. You "
|
||||
"should receive it within a few minutes."
|
||||
msgstr ""
|
||||
|
||||
#: canaille/core/endpoints/auth.py:153
|
||||
#: canaille/core/endpoints/auth.py:152
|
||||
msgid "Could not send the password reset link."
|
||||
msgstr ""
|
||||
|
||||
#: canaille/core/endpoints/auth.py:157
|
||||
#: canaille/core/endpoints/auth.py:156
|
||||
msgid ""
|
||||
"A password reset link has been sent at your email address. You should "
|
||||
"receive it within a few minutes."
|
||||
msgstr ""
|
||||
|
||||
#: canaille/core/endpoints/auth.py:169
|
||||
#: canaille/core/endpoints/auth.py:168
|
||||
#, python-format
|
||||
msgid ""
|
||||
"The user '%(user)s' does not have permissions to update their password. "
|
||||
"We cannot send a password reset email."
|
||||
msgstr ""
|
||||
|
||||
#: canaille/core/endpoints/auth.py:185
|
||||
#: canaille/core/endpoints/auth.py:184
|
||||
msgid "We encountered an issue while we sent the password recovery email."
|
||||
msgstr ""
|
||||
|
||||
#: canaille/core/endpoints/auth.py:208
|
||||
#: canaille/core/endpoints/auth.py:207
|
||||
msgid "The password reset link that brought you here was invalid."
|
||||
msgstr ""
|
||||
|
||||
#: canaille/core/endpoints/auth.py:217
|
||||
#: canaille/core/endpoints/auth.py:216
|
||||
msgid "Your password has been updated successfully"
|
||||
msgstr ""
|
||||
|
||||
#: canaille/core/endpoints/forms.py:29
|
||||
#: canaille/core/endpoints/forms.py:30
|
||||
msgid "The user name '{user_name}' already exists"
|
||||
msgstr ""
|
||||
|
||||
#: canaille/core/endpoints/forms.py:38
|
||||
#: canaille/core/endpoints/forms.py:39
|
||||
msgid "The email '{email}' is already used"
|
||||
msgstr ""
|
||||
|
||||
#: canaille/core/endpoints/forms.py:45
|
||||
#: canaille/core/endpoints/forms.py:46
|
||||
msgid "The group '{group}' already exists"
|
||||
msgstr ""
|
||||
|
||||
#: canaille/core/endpoints/forms.py:54
|
||||
#: canaille/core/endpoints/forms.py:55
|
||||
msgid "The login '{login}' does not exist"
|
||||
msgstr ""
|
||||
|
||||
#: canaille/core/endpoints/forms.py:60 canaille/core/endpoints/forms.py:80
|
||||
#: canaille/core/endpoints/forms.py:71
|
||||
msgid ""
|
||||
"The group '{group}' cannot be removed, because it must have at least one "
|
||||
"user left."
|
||||
msgstr ""
|
||||
|
||||
#: canaille/core/endpoints/forms.py:79 canaille/core/endpoints/forms.py:99
|
||||
#: canaille/core/templates/partial/users.html:9
|
||||
msgid "Login"
|
||||
msgstr ""
|
||||
|
||||
#: canaille/core/endpoints/forms.py:73 canaille/core/endpoints/forms.py:92
|
||||
#: canaille/core/endpoints/forms.py:226
|
||||
#: canaille/core/endpoints/forms.py:92 canaille/core/endpoints/forms.py:111
|
||||
#: canaille/core/endpoints/forms.py:245
|
||||
#: canaille/core/templates/profile_settings.html:63
|
||||
msgid "Password"
|
||||
msgstr ""
|
||||
|
||||
#: canaille/core/endpoints/forms.py:99 canaille/core/endpoints/forms.py:236
|
||||
#: canaille/core/endpoints/forms.py:118 canaille/core/endpoints/forms.py:255
|
||||
msgid "Password confirmation"
|
||||
msgstr ""
|
||||
|
||||
#: canaille/core/endpoints/forms.py:102 canaille/core/endpoints/forms.py:239
|
||||
#: canaille/core/endpoints/forms.py:121 canaille/core/endpoints/forms.py:258
|
||||
msgid "Password and confirmation do not match."
|
||||
msgstr ""
|
||||
|
||||
#: canaille/core/endpoints/forms.py:121
|
||||
#: canaille/core/endpoints/forms.py:140
|
||||
msgid "Automatic"
|
||||
msgstr ""
|
||||
|
||||
#: canaille/core/endpoints/forms.py:126
|
||||
#: canaille/core/endpoints/forms.py:145
|
||||
msgid "Username"
|
||||
msgstr ""
|
||||
|
||||
#: canaille/core/endpoints/forms.py:130 canaille/core/endpoints/forms.py:324
|
||||
#: canaille/core/endpoints/forms.py:338
|
||||
#: canaille/core/endpoints/forms.py:149 canaille/core/endpoints/forms.py:344
|
||||
#: canaille/core/endpoints/forms.py:358
|
||||
#: canaille/core/templates/partial/groups.html:6
|
||||
#: canaille/core/templates/partial/users.html:12
|
||||
#: canaille/oidc/endpoints/forms.py:26
|
||||
|
@ -369,165 +375,165 @@ msgstr ""
|
|||
msgid "Name"
|
||||
msgstr ""
|
||||
|
||||
#: canaille/core/endpoints/forms.py:132
|
||||
#: canaille/core/endpoints/forms.py:151
|
||||
msgid "Title"
|
||||
msgstr ""
|
||||
|
||||
#: canaille/core/endpoints/forms.py:132
|
||||
#: canaille/core/endpoints/forms.py:151
|
||||
msgid "Vice president"
|
||||
msgstr ""
|
||||
|
||||
#: canaille/core/endpoints/forms.py:135
|
||||
#: canaille/core/endpoints/forms.py:154
|
||||
msgid "Given name"
|
||||
msgstr ""
|
||||
|
||||
#: canaille/core/endpoints/forms.py:137
|
||||
#: canaille/core/endpoints/forms.py:156
|
||||
msgid "John"
|
||||
msgstr ""
|
||||
|
||||
#: canaille/core/endpoints/forms.py:143
|
||||
#: canaille/core/endpoints/forms.py:162
|
||||
msgid "Family Name"
|
||||
msgstr ""
|
||||
|
||||
#: canaille/core/endpoints/forms.py:146
|
||||
#: canaille/core/endpoints/forms.py:165
|
||||
msgid "Doe"
|
||||
msgstr ""
|
||||
|
||||
#: canaille/core/endpoints/forms.py:152
|
||||
#: canaille/core/endpoints/forms.py:171
|
||||
msgid "Display Name"
|
||||
msgstr ""
|
||||
|
||||
#: canaille/core/endpoints/forms.py:155
|
||||
#: canaille/core/endpoints/forms.py:174
|
||||
msgid "Johnny"
|
||||
msgstr ""
|
||||
|
||||
#: canaille/core/endpoints/forms.py:162 canaille/core/endpoints/forms.py:414
|
||||
#: canaille/core/endpoints/forms.py:181 canaille/core/endpoints/forms.py:434
|
||||
#: canaille/core/templates/profile_edit.html:176
|
||||
msgid "Email addresses"
|
||||
msgstr ""
|
||||
|
||||
#: canaille/core/endpoints/forms.py:168 canaille/core/endpoints/forms.py:404
|
||||
#: canaille/core/endpoints/forms.py:187 canaille/core/endpoints/forms.py:424
|
||||
msgid ""
|
||||
"This email will be used as a recovery address to reset the password if "
|
||||
"needed"
|
||||
msgstr ""
|
||||
|
||||
#: canaille/core/endpoints/forms.py:182
|
||||
#: canaille/core/endpoints/forms.py:201
|
||||
msgid "Phone numbers"
|
||||
msgstr ""
|
||||
|
||||
#: canaille/core/endpoints/forms.py:183
|
||||
#: canaille/core/endpoints/forms.py:202
|
||||
msgid "555-000-555"
|
||||
msgstr ""
|
||||
|
||||
#: canaille/core/endpoints/forms.py:190
|
||||
#: canaille/core/endpoints/forms.py:209
|
||||
msgid "Address"
|
||||
msgstr ""
|
||||
|
||||
#: canaille/core/endpoints/forms.py:192
|
||||
#: canaille/core/endpoints/forms.py:211
|
||||
msgid "132, Foobar Street, Gotham City 12401, XX"
|
||||
msgstr ""
|
||||
|
||||
#: canaille/core/endpoints/forms.py:196
|
||||
#: canaille/core/endpoints/forms.py:215
|
||||
msgid "Street"
|
||||
msgstr ""
|
||||
|
||||
#: canaille/core/endpoints/forms.py:198
|
||||
#: canaille/core/endpoints/forms.py:217
|
||||
msgid "132, Foobar Street"
|
||||
msgstr ""
|
||||
|
||||
#: canaille/core/endpoints/forms.py:202
|
||||
#: canaille/core/endpoints/forms.py:221
|
||||
msgid "Postal Code"
|
||||
msgstr ""
|
||||
|
||||
#: canaille/core/endpoints/forms.py:208
|
||||
#: canaille/core/endpoints/forms.py:227
|
||||
msgid "Locality"
|
||||
msgstr ""
|
||||
|
||||
#: canaille/core/endpoints/forms.py:210
|
||||
#: canaille/core/endpoints/forms.py:229
|
||||
msgid "Gotham City"
|
||||
msgstr ""
|
||||
|
||||
#: canaille/core/endpoints/forms.py:214
|
||||
#: canaille/core/endpoints/forms.py:233
|
||||
msgid "Region"
|
||||
msgstr ""
|
||||
|
||||
#: canaille/core/endpoints/forms.py:216
|
||||
#: canaille/core/endpoints/forms.py:235
|
||||
msgid "North Pole"
|
||||
msgstr ""
|
||||
|
||||
#: canaille/core/endpoints/forms.py:220
|
||||
#: canaille/core/endpoints/forms.py:239
|
||||
msgid "Photo"
|
||||
msgstr ""
|
||||
|
||||
#: canaille/core/endpoints/forms.py:224
|
||||
#: canaille/core/endpoints/forms.py:243
|
||||
#: canaille/core/templates/profile_add.html:56
|
||||
#: canaille/core/templates/profile_edit.html:64
|
||||
msgid "Delete the photo"
|
||||
msgstr ""
|
||||
|
||||
#: canaille/core/endpoints/forms.py:247
|
||||
#: canaille/core/endpoints/forms.py:266
|
||||
msgid "User number"
|
||||
msgstr ""
|
||||
|
||||
#: canaille/core/endpoints/forms.py:249 canaille/core/endpoints/forms.py:255
|
||||
#: canaille/core/endpoints/forms.py:268 canaille/core/endpoints/forms.py:274
|
||||
msgid "1234"
|
||||
msgstr ""
|
||||
|
||||
#: canaille/core/endpoints/forms.py:253
|
||||
#: canaille/core/endpoints/forms.py:272
|
||||
msgid "Department"
|
||||
msgstr ""
|
||||
|
||||
#: canaille/core/endpoints/forms.py:259
|
||||
#: canaille/core/endpoints/forms.py:278
|
||||
msgid "Organization"
|
||||
msgstr ""
|
||||
|
||||
#: canaille/core/endpoints/forms.py:261
|
||||
#: canaille/core/endpoints/forms.py:280
|
||||
msgid "Cogip LTD."
|
||||
msgstr ""
|
||||
|
||||
#: canaille/core/endpoints/forms.py:265
|
||||
#: canaille/core/endpoints/forms.py:284
|
||||
msgid "Website"
|
||||
msgstr ""
|
||||
|
||||
#: canaille/core/endpoints/forms.py:267
|
||||
#: canaille/core/endpoints/forms.py:286
|
||||
msgid "https://mywebsite.tld"
|
||||
msgstr ""
|
||||
|
||||
#: canaille/core/endpoints/forms.py:272
|
||||
#: canaille/core/endpoints/forms.py:291
|
||||
msgid "Preferred language"
|
||||
msgstr ""
|
||||
|
||||
#: canaille/core/endpoints/forms.py:279
|
||||
#: canaille/core/endpoints/forms.py:298
|
||||
msgid "users, admins …"
|
||||
msgstr ""
|
||||
|
||||
#: canaille/core/endpoints/forms.py:303
|
||||
#: canaille/core/endpoints/forms.py:323
|
||||
msgid "Account expiration"
|
||||
msgstr ""
|
||||
|
||||
#: canaille/core/endpoints/forms.py:327
|
||||
#: canaille/core/endpoints/forms.py:347
|
||||
msgid "group"
|
||||
msgstr ""
|
||||
|
||||
#: canaille/core/endpoints/forms.py:331 canaille/core/endpoints/forms.py:348
|
||||
#: canaille/core/endpoints/forms.py:351 canaille/core/endpoints/forms.py:368
|
||||
#: canaille/core/templates/partial/groups.html:7
|
||||
msgid "Description"
|
||||
msgstr ""
|
||||
|
||||
#: canaille/core/endpoints/forms.py:355 canaille/core/endpoints/forms.py:380
|
||||
#: canaille/core/endpoints/forms.py:375 canaille/core/endpoints/forms.py:400
|
||||
msgid "Email address"
|
||||
msgstr ""
|
||||
|
||||
#: canaille/core/endpoints/forms.py:374
|
||||
#: canaille/core/endpoints/forms.py:394
|
||||
msgid "User name"
|
||||
msgstr ""
|
||||
|
||||
#: canaille/core/endpoints/forms.py:378
|
||||
#: canaille/core/endpoints/forms.py:398
|
||||
msgid "Username editable by the invitee"
|
||||
msgstr ""
|
||||
|
||||
#: canaille/core/endpoints/forms.py:417
|
||||
#: canaille/core/endpoints/forms.py:437
|
||||
msgid "New email address"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -38,6 +38,7 @@ def test_edition(testclient, logged_user, admin, foo_group, bar_group, backend):
|
|||
|
||||
|
||||
def test_group_removal(testclient, logged_admin, user, foo_group, backend):
|
||||
"""Tests that one can remove a group from a user."""
|
||||
foo_group.members = [user, logged_admin]
|
||||
foo_group.save()
|
||||
user.reload()
|
||||
|
@ -52,9 +53,33 @@ def test_group_removal(testclient, logged_admin, user, foo_group, backend):
|
|||
assert foo_group not in user.groups
|
||||
|
||||
foo_group.reload()
|
||||
logged_admin.reload()
|
||||
assert foo_group.members == [logged_admin]
|
||||
|
||||
|
||||
def test_empty_group_removal(testclient, logged_admin, user, foo_group, backend):
|
||||
"""Tests that one cannot remove a group from a user, when was the last
|
||||
person in the group.
|
||||
|
||||
This is because LDAP groups cannot be empty because
|
||||
groupOfNames.member is a MUST attribute.
|
||||
https://www.rfc-editor.org/rfc/rfc2256.html#section-7.10
|
||||
"""
|
||||
assert foo_group in user.groups
|
||||
|
||||
res = testclient.get("/profile/user/settings", status=200)
|
||||
res.form["groups"] = []
|
||||
res = res.form.submit(name="action", value="edit-settings")
|
||||
assert res.flashes == [("error", "Profile edition failed.")]
|
||||
|
||||
res.mustcontain(
|
||||
"The group 'foo' cannot be removed, because it must have at least one user left."
|
||||
)
|
||||
|
||||
user.reload()
|
||||
assert foo_group in user.groups
|
||||
|
||||
|
||||
def test_profile_settings_edition_dynamic_validation(testclient, logged_admin):
|
||||
res = testclient.get("/profile/admin/settings")
|
||||
res = testclient.post(
|
||||
|
|
Loading…
Reference in a new issue