forked from Github-Mirrors/canaille
Profile editable fields are configurable
This commit is contained in:
parent
0d981b5a84
commit
c63d53f0ed
11 changed files with 245 additions and 153 deletions
|
@ -15,9 +15,9 @@ from flask_babel import gettext as _
|
|||
|
||||
from .forms import (
|
||||
LoginForm,
|
||||
ProfileForm,
|
||||
PasswordResetForm,
|
||||
ForgottenPasswordForm,
|
||||
profile_form,
|
||||
)
|
||||
from .apputils import base64logo, send_email
|
||||
from .flaskutils import current_user, user_needed, moderator_needed
|
||||
|
@ -151,10 +151,11 @@ def users(user):
|
|||
@bp.route("/profile", methods=("GET", "POST"))
|
||||
@moderator_needed()
|
||||
def profile_creation(user):
|
||||
claims = current_app.config["JWT"]["MAPPING"]
|
||||
form = ProfileForm(request.form or None)
|
||||
form = profile_form(current_app.config["LDAP"]["FIELDS"])
|
||||
form.process(request.form or None)
|
||||
try:
|
||||
del form.sub.render_kw["readonly"]
|
||||
if "uid" in form:
|
||||
del form["uid"].render_kw["readonly"]
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
|
@ -165,14 +166,14 @@ def profile_creation(user):
|
|||
else:
|
||||
user = User(objectClass=current_app.config["LDAP"]["USER_CLASS"])
|
||||
for attribute in form:
|
||||
model_attribute_name = claims.get(attribute.name.upper())
|
||||
if (
|
||||
not model_attribute_name
|
||||
or model_attribute_name not in user.must + user.may
|
||||
):
|
||||
continue
|
||||
if attribute.name in user.may + user.must:
|
||||
if user.attr_type_by_name()[attribute.name].single_value:
|
||||
user[attribute.name] = attribute.data
|
||||
else:
|
||||
user[attribute.name] = [attribute.data]
|
||||
|
||||
user[model_attribute_name] = [attribute.data]
|
||||
if not form["password1"].data or user.set_password(form["password1"].data):
|
||||
flash(_("Profile updated successfuly."), "success")
|
||||
|
||||
user.cn = [f"{user.givenName[0]} {user.sn[0]}"]
|
||||
user.save()
|
||||
|
@ -204,18 +205,20 @@ def profile_edition(user, username):
|
|||
|
||||
def profile_edit(user, username):
|
||||
menuitem = "profile" if username == user.uid[0] else "users"
|
||||
claims = current_app.config["JWT"]["MAPPING"]
|
||||
fields = current_app.config["LDAP"]["FIELDS"]
|
||||
if username != user.uid[0]:
|
||||
user = User.get(username) or abort(404)
|
||||
|
||||
data = {
|
||||
k.lower(): getattr(user, v)[0]
|
||||
if getattr(user, v) and isinstance(getattr(user, v), list)
|
||||
else getattr(user, v) or ""
|
||||
for k, v in claims.items()
|
||||
k: getattr(user, k)[0]
|
||||
if getattr(user, k) and isinstance(getattr(user, k), list)
|
||||
else getattr(user, k) or ""
|
||||
for k in fields
|
||||
if hasattr(user, k)
|
||||
}
|
||||
form = ProfileForm(request.form or None, data=data)
|
||||
form.sub.render_kw["readonly"] = "true"
|
||||
form = profile_form(fields)
|
||||
form.process(request.form or None, data=data)
|
||||
form["uid"].render_kw["readonly"] = "true"
|
||||
|
||||
if request.form:
|
||||
if not form.validate():
|
||||
|
@ -223,16 +226,13 @@ def profile_edit(user, username):
|
|||
|
||||
else:
|
||||
for attribute in form:
|
||||
model_attribute_name = claims.get(attribute.name.upper())
|
||||
if (
|
||||
not model_attribute_name
|
||||
or model_attribute_name not in user.must + user.may
|
||||
):
|
||||
continue
|
||||
if attribute.name in user.may + user.must:
|
||||
if user.attr_type_by_name()[attribute.name].single_value:
|
||||
user[attribute.name] = attribute.data
|
||||
else:
|
||||
user[attribute.name] = [attribute.data]
|
||||
|
||||
user[model_attribute_name] = [attribute.data]
|
||||
|
||||
if not form.password1.data or user.set_password(form.password1.data):
|
||||
if not form["password1"].data or user.set_password(form["password1"].data):
|
||||
flash(_("Profile updated successfuly."), "success")
|
||||
|
||||
user.save()
|
||||
|
|
|
@ -54,6 +54,19 @@ ADMIN_FILTER = "memberof=cn=admins,ou=groups,dc=mydomain,dc=tld"
|
|||
# USER_ADMIN_FILTER = "uid=moderator"
|
||||
USER_ADMIN_FILTER = "memberof=cn=moderators,ou=groups,dc=mydomain,dc=tld"
|
||||
|
||||
# The list of ldap fields you want to be editable by the
|
||||
# users.
|
||||
FIELDS = [
|
||||
"uid",
|
||||
"mail",
|
||||
"givenName",
|
||||
"sn",
|
||||
"userPassword",
|
||||
"telephoneNumber",
|
||||
"employeeNumber",
|
||||
# "photo",
|
||||
]
|
||||
|
||||
# The jwt configuration. You can generate a RSA keypair with:
|
||||
# ssh-keygen -t rsa -b 4096 -m PEM -f private.pem
|
||||
# openssl rsa -in private.pem -pubout -outform PEM -out public.pem
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import wtforms
|
||||
import wtforms.form
|
||||
from flask_babel import lazy_gettext as _
|
||||
from flask_wtf import FlaskForm
|
||||
|
||||
|
@ -46,35 +47,30 @@ class PasswordResetForm(FlaskForm):
|
|||
)
|
||||
|
||||
|
||||
class ProfileForm(FlaskForm):
|
||||
sub = wtforms.StringField(
|
||||
PROFILE_FORM_FIELDS = dict(
|
||||
uid=wtforms.StringField(
|
||||
_("Username"),
|
||||
render_kw={"placeholder": _("jdoe")},
|
||||
validators=[wtforms.validators.DataRequired()],
|
||||
)
|
||||
# name = wtforms.StringField(_("Name"))
|
||||
given_name = wtforms.StringField(
|
||||
),
|
||||
cn=wtforms.StringField(_("Name")),
|
||||
givenName=wtforms.StringField(
|
||||
_("Given name"),
|
||||
render_kw={
|
||||
"placeholder": _("John"),
|
||||
"spellcheck": "false",
|
||||
"autocorrect": "off",
|
||||
},
|
||||
)
|
||||
family_name = wtforms.StringField(
|
||||
),
|
||||
sn=wtforms.StringField(
|
||||
_("Family Name"),
|
||||
render_kw={
|
||||
"placeholder": _("Doe"),
|
||||
"spellcheck": "false",
|
||||
"autocorrect": "off",
|
||||
},
|
||||
)
|
||||
# preferred_username = wtforms.StringField(_("Preferred username"))
|
||||
# gender = wtforms.StringField(_("Gender"))
|
||||
# birthdate = wtforms.DateField(_("Birth date"))
|
||||
# zoneinfo = wtforms.StringField(_("Zoneinfo"))
|
||||
# locale = wtforms.StringField(_("Language"))
|
||||
email = wtforms.EmailField(
|
||||
),
|
||||
mail=wtforms.EmailField(
|
||||
_("Email address"),
|
||||
validators=[wtforms.validators.DataRequired(), wtforms.validators.Email()],
|
||||
render_kw={
|
||||
|
@ -82,22 +78,38 @@ class ProfileForm(FlaskForm):
|
|||
"spellcheck": "false",
|
||||
"autocorrect": "off",
|
||||
},
|
||||
)
|
||||
# address = wtforms.StringField(_("Address"))
|
||||
phone_number = wtforms.TelField(
|
||||
),
|
||||
telephoneNumber=wtforms.TelField(
|
||||
_("Phone number"), render_kw={"placeholder": _("555-000-555")}
|
||||
)
|
||||
# picture = wtforms.StringField(_("Photo"))
|
||||
# website = wtforms.URLField(_("Website"))
|
||||
password1 = wtforms.PasswordField(
|
||||
),
|
||||
photo=wtforms.StringField(_("Photo")),
|
||||
password1=wtforms.PasswordField(
|
||||
_("Password"),
|
||||
validators=[wtforms.validators.Optional(), wtforms.validators.Length(min=8)],
|
||||
)
|
||||
password2 = wtforms.PasswordField(
|
||||
),
|
||||
password2=wtforms.PasswordField(
|
||||
_("Password confirmation"),
|
||||
validators=[
|
||||
wtforms.validators.EqualTo(
|
||||
"password1", message=_("Password and confirmation do not match.")
|
||||
)
|
||||
],
|
||||
)
|
||||
),
|
||||
employeeNumber=wtforms.StringField(
|
||||
_("Number"),
|
||||
render_kw={
|
||||
"placeholder": _("1234"),
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
def profile_form(field_names):
|
||||
if "userPassword" in field_names:
|
||||
field_names += ["password1", "password2"]
|
||||
fields = {
|
||||
name: PROFILE_FORM_FIELDS.get(name)
|
||||
for name in field_names
|
||||
if PROFILE_FORM_FIELDS.get(name)
|
||||
}
|
||||
return wtforms.form.BaseForm(fields)
|
||||
|
|
|
@ -56,21 +56,36 @@
|
|||
class="ui form"
|
||||
>
|
||||
|
||||
{{ sui.render_field(form.csrf_token) }}
|
||||
{#{ sui.render_field(form.csrf_token) }#}
|
||||
|
||||
<h4 class="ui dividing header">{% trans %}Personal information{% endtrans %}</h4>
|
||||
<div class="two fields">
|
||||
{{ sui.render_field(form.given_name) }}
|
||||
{{ sui.render_field(form.family_name) }}
|
||||
{% if "givenName" in form %}
|
||||
{{ sui.render_field(form.givenName) }}
|
||||
{% endif %}
|
||||
{% if "sn" in form %}
|
||||
{{ sui.render_field(form.sn) }}
|
||||
{% endif %}
|
||||
</div>
|
||||
{{ sui.render_field(form.email) }}
|
||||
{{ sui.render_field(form.phone_number) }}
|
||||
{% if "mail" in form %}
|
||||
{{ sui.render_field(form.mail) }}
|
||||
{% endif %}
|
||||
{% if "telephoneNumber" in form %}
|
||||
{{ sui.render_field(form.telephoneNumber) }}
|
||||
{% endif %}
|
||||
{% if "employeeNumber" in form %}
|
||||
{{ sui.render_field(form.employeeNumber) }}
|
||||
{% endif %}
|
||||
|
||||
<h4 class="ui dividing header">{% trans %}Account information{% endtrans %}</h4>
|
||||
{{ sui.render_field(form.sub) }}
|
||||
{% if "uid" in form %}
|
||||
{{ sui.render_field(form.uid) }}
|
||||
{% endif %}
|
||||
<div class="two fields">
|
||||
{{ sui.render_field(form.password1) }}
|
||||
{{ sui.render_field(form.password2) }}
|
||||
{% if "password1" in form %}
|
||||
{{ sui.render_field(form.password1) }}
|
||||
{{ sui.render_field(form.password2) }}
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<button type="submit" class="ui right floated primary button" name="action" value="edit" id="edit">
|
||||
|
|
Binary file not shown.
|
@ -8,8 +8,8 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: PROJECT VERSION\n"
|
||||
"Report-Msgid-Bugs-To: contact@yaal.fr\n"
|
||||
"POT-Creation-Date: 2020-11-25 15:25+0100\n"
|
||||
"PO-Revision-Date: 2020-11-25 15:27+0100\n"
|
||||
"POT-Creation-Date: 2020-11-26 11:41+0100\n"
|
||||
"PO-Revision-Date: 2020-11-26 11:41+0100\n"
|
||||
"Last-Translator: Éloi Rivard <eloi@yaal.fr>\n"
|
||||
"Language: fr_FR\n"
|
||||
"Language-Team: French - France <equipe@yaal.fr>\n"
|
||||
|
@ -20,29 +20,29 @@ msgstr ""
|
|||
"Generated-By: Babel 2.8.1\n"
|
||||
"X-Generator: Gtranslator 3.38.0\n"
|
||||
|
||||
#: canaille/account.py:61 canaille/oauth.py:58
|
||||
#: canaille/account.py:60 canaille/oauth.py:58
|
||||
msgid "Login failed, please check your information"
|
||||
msgstr "La connexion a échoué, veuillez vérifier vos informations."
|
||||
|
||||
#: canaille/account.py:64
|
||||
#: canaille/account.py:63
|
||||
#, python-format
|
||||
msgid "Connection successful. Welcome %(user)s"
|
||||
msgstr "Connexion réussie. Bienvenue %(user)s"
|
||||
|
||||
#: canaille/account.py:75
|
||||
#: canaille/account.py:74
|
||||
#, python-format
|
||||
msgid "You have been disconnected. See you next time %(user)s"
|
||||
msgstr "Vous avez été déconnectés. À bientôt %(user)s"
|
||||
|
||||
#: canaille/account.py:92
|
||||
#: canaille/account.py:91
|
||||
msgid "Could not send the password initialization link."
|
||||
msgstr "Impossible d'envoyer le courriel d'initialisation de mot de passe."
|
||||
|
||||
#: canaille/account.py:106
|
||||
#: canaille/account.py:105
|
||||
msgid "Password initialization on {website_name}"
|
||||
msgstr "Initialisation de votre mot de passe sur {website_name}"
|
||||
|
||||
#: canaille/account.py:134
|
||||
#: canaille/account.py:133
|
||||
msgid ""
|
||||
"A password initialization link has been sent at your email address. You "
|
||||
"should receive it within 10 minutes."
|
||||
|
@ -50,7 +50,7 @@ msgstr ""
|
|||
"Un lien d'initialisation de votre mot de passe vous a été envoyé par mail. "
|
||||
"Vous devriez le recevoir d'ici une dizaine de minutes."
|
||||
|
||||
#: canaille/account.py:140
|
||||
#: canaille/account.py:139
|
||||
msgid "Could not send the password initialization email"
|
||||
msgstr "Impossible d'envoyer le courriel d'initialisation de mot de passe."
|
||||
|
||||
|
@ -62,24 +62,24 @@ msgstr "La création de l'utilisateur a échoué."
|
|||
msgid "User creation succeed."
|
||||
msgstr "La création de l'utilisateur a réussi."
|
||||
|
||||
#: canaille/account.py:223
|
||||
#: canaille/account.py:224
|
||||
msgid "Profile edition failed."
|
||||
msgstr "L'édition du profil a échoué."
|
||||
|
||||
#: canaille/account.py:237
|
||||
#: canaille/account.py:238
|
||||
msgid "Profile updated successfuly."
|
||||
msgstr "Le profil a été mis à jour avec succès."
|
||||
|
||||
#: canaille/account.py:253
|
||||
#: canaille/account.py:254
|
||||
#, python-format
|
||||
msgid "The user %(user)s has been sucessfuly deleted"
|
||||
msgstr "L'utilisateur %(user)s a bien été supprimé"
|
||||
|
||||
#: canaille/account.py:276
|
||||
#: canaille/account.py:277
|
||||
msgid "Could not send the password reset link."
|
||||
msgstr "Impossible d'envoyer le lien de réinitialisation."
|
||||
|
||||
#: canaille/account.py:283 canaille/account.py:329
|
||||
#: canaille/account.py:284 canaille/account.py:330
|
||||
msgid ""
|
||||
"A password reset link has been sent at your email address. You should "
|
||||
"receive it within 10 minutes."
|
||||
|
@ -87,19 +87,19 @@ msgstr ""
|
|||
"Un lien de ré-initialisation de votre mot de passe vous a été envoyé par "
|
||||
"mail. Vous devriez le recevoir d'ici une dizaine de minutes."
|
||||
|
||||
#: canaille/account.py:301
|
||||
#: canaille/account.py:302
|
||||
msgid "Password reset on {website_name}"
|
||||
msgstr "Réinitialisation du mot de passe sur {website_name}"
|
||||
|
||||
#: canaille/account.py:335
|
||||
#: canaille/account.py:336
|
||||
msgid "Could not reset your password"
|
||||
msgstr "Impossible de réinitialiser votre mot de passe"
|
||||
|
||||
#: canaille/account.py:349
|
||||
#: canaille/account.py:350
|
||||
msgid "The password reset link that brought you here was invalid."
|
||||
msgstr "Le lien de réinitialisation qui vous a amené ici est invalide."
|
||||
|
||||
#: canaille/account.py:358
|
||||
#: canaille/account.py:359
|
||||
msgid "Your password has been updated successfuly"
|
||||
msgstr "Votre mot de passe a correctement été mis à jour."
|
||||
|
||||
|
@ -111,63 +111,80 @@ msgstr "Impossible de supprimer cet accès."
|
|||
msgid "The access has been revoked"
|
||||
msgstr "L'accès a été révoqué."
|
||||
|
||||
#: canaille/forms.py:8 canaille/forms.py:25
|
||||
#: canaille/forms.py:9 canaille/forms.py:26
|
||||
msgid "Login"
|
||||
msgstr "Identifiant"
|
||||
|
||||
#: canaille/forms.py:11 canaille/forms.py:28 canaille/forms.py:81
|
||||
#: canaille/forms.py:12 canaille/forms.py:29 canaille/forms.py:77
|
||||
msgid "jane@doe.com"
|
||||
msgstr "martin@dupont.fr"
|
||||
|
||||
#: canaille/forms.py:18 canaille/forms.py:37 canaille/forms.py:100
|
||||
#: canaille/forms.py:110
|
||||
#: canaille/forms.py:19 canaille/forms.py:38 canaille/forms.py:87
|
||||
msgid "Password"
|
||||
msgstr "Mot de passe"
|
||||
|
||||
#: canaille/forms.py:40 canaille/forms.py:104 canaille/forms.py:117
|
||||
#: canaille/forms.py:41 canaille/forms.py:91
|
||||
msgid "Password confirmation"
|
||||
msgstr "Confirmation du mot de passe"
|
||||
|
||||
#: canaille/forms.py:43 canaille/forms.py:95
|
||||
#: canaille/forms.py:44 canaille/forms.py:94
|
||||
msgid "Password and confirmation do not match."
|
||||
msgstr "Le mot de passe et sa confirmation ne correspondent pas."
|
||||
|
||||
#: canaille/forms.py:51
|
||||
#: canaille/forms.py:52
|
||||
msgid "Username"
|
||||
msgstr "Identifiant"
|
||||
|
||||
#: canaille/forms.py:52
|
||||
#: canaille/forms.py:53
|
||||
msgid "jdoe"
|
||||
msgstr "mdupont"
|
||||
|
||||
#: canaille/forms.py:57
|
||||
#: canaille/admin/clients.py:23 canaille/forms.py:56
|
||||
#: canaille/templates/admin/client_list.html:25
|
||||
#: canaille/templates/users.html:22
|
||||
msgid "Name"
|
||||
msgstr "Nom"
|
||||
|
||||
#: canaille/forms.py:58
|
||||
msgid "Given name"
|
||||
msgstr "Prénom"
|
||||
|
||||
#: canaille/forms.py:59
|
||||
#: canaille/forms.py:60
|
||||
msgid "John"
|
||||
msgstr "Martin"
|
||||
|
||||
#: canaille/forms.py:65
|
||||
#: canaille/forms.py:66
|
||||
msgid "Family Name"
|
||||
msgstr "Nom de famille"
|
||||
|
||||
#: canaille/forms.py:67
|
||||
#: canaille/forms.py:68
|
||||
msgid "Doe"
|
||||
msgstr "Dupont"
|
||||
|
||||
#: canaille/forms.py:78
|
||||
#: canaille/forms.py:74
|
||||
msgid "Email address"
|
||||
msgstr "Courriel"
|
||||
|
||||
#: canaille/forms.py:88 canaille/templates/users.html:24
|
||||
#: canaille/forms.py:83 canaille/templates/users.html:24
|
||||
msgid "Phone number"
|
||||
msgstr "Numéro de téléphone"
|
||||
|
||||
#: canaille/forms.py:88
|
||||
#: canaille/forms.py:83
|
||||
msgid "555-000-555"
|
||||
msgstr "06 01 02 03 04"
|
||||
|
||||
#: canaille/forms.py:85
|
||||
msgid "Photo"
|
||||
msgstr "Photo"
|
||||
|
||||
#: canaille/forms.py:99
|
||||
msgid "Number"
|
||||
msgstr "Numéro"
|
||||
|
||||
#: canaille/forms.py:101
|
||||
msgid "1234"
|
||||
msgstr "1234"
|
||||
|
||||
#: canaille/oauth.py:25
|
||||
msgid "Personnal information about yourself, such as your name or your gender."
|
||||
msgstr "Vos informations personnelles, comme votre nom ou votre genre."
|
||||
|
@ -188,11 +205,6 @@ msgstr "Votre numéro de téléphone."
|
|||
msgid "You have been successfully logged out."
|
||||
msgstr "Vous avez été déconnectés."
|
||||
|
||||
#: canaille/admin/clients.py:23 canaille/templates/admin/client_list.html:25
|
||||
#: canaille/templates/users.html:22
|
||||
msgid "Name"
|
||||
msgstr "Nom"
|
||||
|
||||
#: canaille/admin/clients.py:28
|
||||
msgid "Contact"
|
||||
msgstr "Contact"
|
||||
|
@ -451,7 +463,7 @@ msgstr ""
|
|||
" "
|
||||
|
||||
#: canaille/templates/forgotten-password.html:36
|
||||
#: canaille/templates/profile.html:77
|
||||
#: canaille/templates/profile.html:89
|
||||
msgid "Send"
|
||||
msgstr "Envoyer"
|
||||
|
||||
|
@ -514,11 +526,11 @@ msgstr "Éditez les informations d'un utilisateur"
|
|||
msgid "Personal information"
|
||||
msgstr "Informations personnelles"
|
||||
|
||||
#: canaille/templates/profile.html:69
|
||||
#: canaille/templates/profile.html:77
|
||||
msgid "Account information"
|
||||
msgstr "Informations sur le compte"
|
||||
|
||||
#: canaille/templates/profile.html:81
|
||||
#: canaille/templates/profile.html:93
|
||||
msgid "Delete the user"
|
||||
msgstr "Supprimer l'utilisateur"
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: PROJECT VERSION\n"
|
||||
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
||||
"POT-Creation-Date: 2020-11-25 15:25+0100\n"
|
||||
"POT-Creation-Date: 2020-11-26 11:41+0100\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"
|
||||
|
@ -17,35 +17,35 @@ msgstr ""
|
|||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: Babel 2.8.1\n"
|
||||
|
||||
#: canaille/account.py:61 canaille/oauth.py:58
|
||||
#: canaille/account.py:60 canaille/oauth.py:58
|
||||
msgid "Login failed, please check your information"
|
||||
msgstr ""
|
||||
|
||||
#: canaille/account.py:64
|
||||
#: canaille/account.py:63
|
||||
#, python-format
|
||||
msgid "Connection successful. Welcome %(user)s"
|
||||
msgstr ""
|
||||
|
||||
#: canaille/account.py:75
|
||||
#: canaille/account.py:74
|
||||
#, python-format
|
||||
msgid "You have been disconnected. See you next time %(user)s"
|
||||
msgstr ""
|
||||
|
||||
#: canaille/account.py:92
|
||||
#: canaille/account.py:91
|
||||
msgid "Could not send the password initialization link."
|
||||
msgstr ""
|
||||
|
||||
#: canaille/account.py:106
|
||||
#: canaille/account.py:105
|
||||
msgid "Password initialization on {website_name}"
|
||||
msgstr ""
|
||||
|
||||
#: canaille/account.py:134
|
||||
#: canaille/account.py:133
|
||||
msgid ""
|
||||
"A password initialization link has been sent at your email address. You "
|
||||
"should receive it within 10 minutes."
|
||||
msgstr ""
|
||||
|
||||
#: canaille/account.py:140
|
||||
#: canaille/account.py:139
|
||||
msgid "Could not send the password initialization email"
|
||||
msgstr ""
|
||||
|
||||
|
@ -57,42 +57,42 @@ msgstr ""
|
|||
msgid "User creation succeed."
|
||||
msgstr ""
|
||||
|
||||
#: canaille/account.py:223
|
||||
#: canaille/account.py:224
|
||||
msgid "Profile edition failed."
|
||||
msgstr ""
|
||||
|
||||
#: canaille/account.py:237
|
||||
#: canaille/account.py:238
|
||||
msgid "Profile updated successfuly."
|
||||
msgstr ""
|
||||
|
||||
#: canaille/account.py:253
|
||||
#: canaille/account.py:254
|
||||
#, python-format
|
||||
msgid "The user %(user)s has been sucessfuly deleted"
|
||||
msgstr ""
|
||||
|
||||
#: canaille/account.py:276
|
||||
#: canaille/account.py:277
|
||||
msgid "Could not send the password reset link."
|
||||
msgstr ""
|
||||
|
||||
#: canaille/account.py:283 canaille/account.py:329
|
||||
#: canaille/account.py:284 canaille/account.py:330
|
||||
msgid ""
|
||||
"A password reset link has been sent at your email address. You should "
|
||||
"receive it within 10 minutes."
|
||||
msgstr ""
|
||||
|
||||
#: canaille/account.py:301
|
||||
#: canaille/account.py:302
|
||||
msgid "Password reset on {website_name}"
|
||||
msgstr ""
|
||||
|
||||
#: canaille/account.py:335
|
||||
#: canaille/account.py:336
|
||||
msgid "Could not reset your password"
|
||||
msgstr ""
|
||||
|
||||
#: canaille/account.py:349
|
||||
#: canaille/account.py:350
|
||||
msgid "The password reset link that brought you here was invalid."
|
||||
msgstr ""
|
||||
|
||||
#: canaille/account.py:358
|
||||
#: canaille/account.py:359
|
||||
msgid "Your password has been updated successfuly"
|
||||
msgstr ""
|
||||
|
||||
|
@ -104,63 +104,80 @@ msgstr ""
|
|||
msgid "The access has been revoked"
|
||||
msgstr ""
|
||||
|
||||
#: canaille/forms.py:8 canaille/forms.py:25
|
||||
#: canaille/forms.py:9 canaille/forms.py:26
|
||||
msgid "Login"
|
||||
msgstr ""
|
||||
|
||||
#: canaille/forms.py:11 canaille/forms.py:28 canaille/forms.py:81
|
||||
#: canaille/forms.py:12 canaille/forms.py:29 canaille/forms.py:77
|
||||
msgid "jane@doe.com"
|
||||
msgstr ""
|
||||
|
||||
#: canaille/forms.py:18 canaille/forms.py:37 canaille/forms.py:100
|
||||
#: canaille/forms.py:110
|
||||
#: canaille/forms.py:19 canaille/forms.py:38 canaille/forms.py:87
|
||||
msgid "Password"
|
||||
msgstr ""
|
||||
|
||||
#: canaille/forms.py:40 canaille/forms.py:104 canaille/forms.py:117
|
||||
#: canaille/forms.py:41 canaille/forms.py:91
|
||||
msgid "Password confirmation"
|
||||
msgstr ""
|
||||
|
||||
#: canaille/forms.py:43 canaille/forms.py:95
|
||||
#: canaille/forms.py:44 canaille/forms.py:94
|
||||
msgid "Password and confirmation do not match."
|
||||
msgstr ""
|
||||
|
||||
#: canaille/forms.py:51
|
||||
#: canaille/forms.py:52
|
||||
msgid "Username"
|
||||
msgstr ""
|
||||
|
||||
#: canaille/forms.py:52
|
||||
#: canaille/forms.py:53
|
||||
msgid "jdoe"
|
||||
msgstr ""
|
||||
|
||||
#: canaille/forms.py:57
|
||||
#: canaille/admin/clients.py:23 canaille/forms.py:56
|
||||
#: canaille/templates/admin/client_list.html:25
|
||||
#: canaille/templates/users.html:22
|
||||
msgid "Name"
|
||||
msgstr ""
|
||||
|
||||
#: canaille/forms.py:58
|
||||
msgid "Given name"
|
||||
msgstr ""
|
||||
|
||||
#: canaille/forms.py:59
|
||||
#: canaille/forms.py:60
|
||||
msgid "John"
|
||||
msgstr ""
|
||||
|
||||
#: canaille/forms.py:65
|
||||
#: canaille/forms.py:66
|
||||
msgid "Family Name"
|
||||
msgstr ""
|
||||
|
||||
#: canaille/forms.py:67
|
||||
#: canaille/forms.py:68
|
||||
msgid "Doe"
|
||||
msgstr ""
|
||||
|
||||
#: canaille/forms.py:78
|
||||
#: canaille/forms.py:74
|
||||
msgid "Email address"
|
||||
msgstr ""
|
||||
|
||||
#: canaille/forms.py:88 canaille/templates/users.html:24
|
||||
#: canaille/forms.py:83 canaille/templates/users.html:24
|
||||
msgid "Phone number"
|
||||
msgstr ""
|
||||
|
||||
#: canaille/forms.py:88
|
||||
#: canaille/forms.py:83
|
||||
msgid "555-000-555"
|
||||
msgstr ""
|
||||
|
||||
#: canaille/forms.py:85
|
||||
msgid "Photo"
|
||||
msgstr ""
|
||||
|
||||
#: canaille/forms.py:99
|
||||
msgid "Number"
|
||||
msgstr ""
|
||||
|
||||
#: canaille/forms.py:101
|
||||
msgid "1234"
|
||||
msgstr ""
|
||||
|
||||
#: canaille/oauth.py:25
|
||||
msgid "Personnal information about yourself, such as your name or your gender."
|
||||
msgstr ""
|
||||
|
@ -181,11 +198,6 @@ msgstr ""
|
|||
msgid "You have been successfully logged out."
|
||||
msgstr ""
|
||||
|
||||
#: canaille/admin/clients.py:23 canaille/templates/admin/client_list.html:25
|
||||
#: canaille/templates/users.html:22
|
||||
msgid "Name"
|
||||
msgstr ""
|
||||
|
||||
#: canaille/admin/clients.py:28
|
||||
msgid "Contact"
|
||||
msgstr ""
|
||||
|
@ -428,7 +440,7 @@ msgid ""
|
|||
msgstr ""
|
||||
|
||||
#: canaille/templates/forgotten-password.html:36
|
||||
#: canaille/templates/profile.html:77
|
||||
#: canaille/templates/profile.html:89
|
||||
msgid "Send"
|
||||
msgstr ""
|
||||
|
||||
|
@ -489,11 +501,11 @@ msgstr ""
|
|||
msgid "Personal information"
|
||||
msgstr ""
|
||||
|
||||
#: canaille/templates/profile.html:69
|
||||
#: canaille/templates/profile.html:77
|
||||
msgid "Account information"
|
||||
msgstr ""
|
||||
|
||||
#: canaille/templates/profile.html:81
|
||||
#: canaille/templates/profile.html:93
|
||||
msgid "Delete the user"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -54,6 +54,19 @@ ADMIN_FILTER = "memberof=cn=admins,ou=groups,dc=mydomain,dc=tld"
|
|||
# USER_ADMIN_FILTER = "uid=moderator"
|
||||
USER_ADMIN_FILTER = "memberof=cn=moderators,ou=groups,dc=mydomain,dc=tld"
|
||||
|
||||
# The list of ldap fields you want to be editable by the
|
||||
# users.
|
||||
FIELDS = [
|
||||
"uid",
|
||||
"mail",
|
||||
"givenName",
|
||||
"sn",
|
||||
"userPassword",
|
||||
"telephoneNumber",
|
||||
"employeeNumber",
|
||||
# "photo",
|
||||
]
|
||||
|
||||
# The jwt configuration. You can generate a RSA keypair with:
|
||||
# ssh-keygen -t rsa -b 4096 -m PEM -f private.pem
|
||||
# openssl rsa -in private.pem -pubout -outform PEM -out public.pem
|
||||
|
|
|
@ -31,6 +31,7 @@ sn: Doe
|
|||
uid: admin
|
||||
mail: admin@mydomain.tld
|
||||
telephoneNumber: 555-000-000
|
||||
employeeNumber: 1000
|
||||
userPassword: {SSHA}7zQVLckaEc6cJEsS0ylVipvb2PAR/4tS
|
||||
memberof: cn=admins,ou=groups,dc=mydomain,dc=tld
|
||||
memberof: cn=users,ou=groups,dc=mydomain,dc=tld
|
||||
|
@ -44,6 +45,7 @@ sn: Doe
|
|||
uid: moderator
|
||||
mail: moderator@mydomain.tld
|
||||
telephoneNumber: 555-000-002
|
||||
employeeNumber: 1002
|
||||
userPassword: {SSHA}+eHyxWqajMHsOWnhONC2vbtfNZzKTkag
|
||||
memberof: cn=moderators,ou=groups,dc=mydomain,dc=tld
|
||||
|
||||
|
@ -56,6 +58,7 @@ sn: Doe
|
|||
uid: user
|
||||
mail: user@mydomain.tld
|
||||
telephoneNumber: 555-000-001
|
||||
employeeNumber: 1001
|
||||
userPassword: {SSHA}Yr1ZxSljRsKyaTB30suY2iZ1KRTStF1X
|
||||
memberof: cn=users,ou=groups,dc=mydomain,dc=tld
|
||||
|
||||
|
|
|
@ -132,6 +132,15 @@ def app(slapd_server, keypair_path):
|
|||
"USER_CLASS": "inetOrgPerson",
|
||||
"ADMIN_FILTER": "(|(uid=admin)(sn=admin))",
|
||||
"USER_ADMIN_FILTER": "(|(uid=moderator)(sn=moderator))",
|
||||
"FIELDS": [
|
||||
"uid",
|
||||
"mail",
|
||||
"givenName",
|
||||
"sn",
|
||||
"userPassword",
|
||||
"telephoneNumber",
|
||||
"employeeNumber",
|
||||
],
|
||||
},
|
||||
"JWT": {
|
||||
"PUBLIC_KEY": public_key_path,
|
||||
|
|
|
@ -4,13 +4,15 @@ from canaille.models import User
|
|||
def test_profile(testclient, slapd_connection, logged_user):
|
||||
res = testclient.get("/profile/user", status=200)
|
||||
|
||||
res.form["sub"] = "user"
|
||||
res.form["given_name"] = "given_name"
|
||||
res.form["family_name"] = "family_name"
|
||||
res.form["email"] = "email@mydomain.tld"
|
||||
res.form["phone_number"] = "555-666-777"
|
||||
res.form["uid"] = "user"
|
||||
res.form["givenName"] = "given_name"
|
||||
res.form["sn"] = "family_name"
|
||||
res.form["mail"] = "email@mydomain.tld"
|
||||
res.form["telephoneNumber"] = "555-666-777"
|
||||
res.form["employeeNumber"] = 666
|
||||
|
||||
res = res.form.submit(name="action", value="edit", status=200)
|
||||
assert "Profile updated successfuly." in res, str(res)
|
||||
|
||||
logged_user.reload(slapd_connection)
|
||||
|
||||
|
@ -19,6 +21,7 @@ def test_profile(testclient, slapd_connection, logged_user):
|
|||
assert ["family_name"] == logged_user.sn
|
||||
assert ["email@mydomain.tld"] == logged_user.mail
|
||||
assert ["555-666-777"] == logged_user.telephoneNumber
|
||||
assert "666" == logged_user.employeeNumber
|
||||
|
||||
with testclient.app.app_context():
|
||||
assert logged_user.check_password("correct horse battery staple")
|
||||
|
@ -27,7 +30,7 @@ def test_profile(testclient, slapd_connection, logged_user):
|
|||
def test_bad_email(testclient, slapd_connection, logged_user):
|
||||
res = testclient.get("/profile/user", status=200)
|
||||
|
||||
res.form["email"] = "john@doe.com"
|
||||
res.form["mail"] = "john@doe.com"
|
||||
|
||||
res = res.form.submit(name="action", value="edit", status=200)
|
||||
|
||||
|
@ -35,7 +38,7 @@ def test_bad_email(testclient, slapd_connection, logged_user):
|
|||
|
||||
res = testclient.get("/profile/user", status=200)
|
||||
|
||||
res.form["email"] = "yolo"
|
||||
res.form["mail"] = "yolo"
|
||||
|
||||
res = res.form.submit(name="action", value="edit", status=200)
|
||||
|
||||
|
@ -113,11 +116,11 @@ def test_user_creation_edition_and_deletion(
|
|||
|
||||
# Fill the profile for a new user.
|
||||
res = testclient.get("/profile", status=200)
|
||||
res.form["sub"] = "george"
|
||||
res.form["given_name"] = "George"
|
||||
res.form["family_name"] = "Abitbol"
|
||||
res.form["email"] = "george@abitbol.com"
|
||||
res.form["phone_number"] = "555-666-888"
|
||||
res.form["uid"] = "george"
|
||||
res.form["givenName"] = "George"
|
||||
res.form["sn"] = "Abitbol"
|
||||
res.form["mail"] = "george@abitbol.com"
|
||||
res.form["telephoneNumber"] = "555-666-888"
|
||||
res.form["password1"] = "totoyolo"
|
||||
res.form["password2"] = "totoyolo"
|
||||
|
||||
|
@ -126,7 +129,7 @@ def test_user_creation_edition_and_deletion(
|
|||
with testclient.app.app_context():
|
||||
assert "George" == User.get("george", conn=slapd_connection).givenName[0]
|
||||
assert "george" in testclient.get("/users", status=200).text
|
||||
res.form["given_name"] = "Georgio"
|
||||
res.form["givenName"] = "Georgio"
|
||||
|
||||
# User have been edited
|
||||
res = res.form.submit(name="action", value="edit", status=200)
|
||||
|
|
Loading…
Reference in a new issue