forked from Github-Mirrors/canaille
Renamed user attributes to match SCIM naming convention
This commit is contained in:
parent
ff87975601
commit
db3a4a74ff
47 changed files with 835 additions and 750 deletions
|
@ -3,6 +3,12 @@ All notable changes to this project will be documented in this file.
|
|||
The format is based on `Keep a Changelog <https://keepachangelog.com/en/1.0.0/>`_,
|
||||
and this project adheres to `Semantic Versioning <https://semver.org/spec/v2.0.0.html>`_.
|
||||
|
||||
Changed
|
||||
*******
|
||||
|
||||
- Renamed user model attributes to match SCIM naming convention. :pr:`123`
|
||||
🚨Configuration files must be updated. See the changes in the PR.🚨
|
||||
|
||||
[0.0.24] - 2023-04-07
|
||||
=====================
|
||||
|
||||
|
|
|
@ -68,7 +68,7 @@ def index():
|
|||
|
||||
if user.can_edit_self or user.can_manage_users:
|
||||
return redirect(
|
||||
url_for("account.profile_edition", username=current_user().uid[0])
|
||||
url_for("account.profile_edition", username=current_user().user_name[0])
|
||||
)
|
||||
|
||||
if user.can_use_oidc:
|
||||
|
@ -90,7 +90,7 @@ def about():
|
|||
def login():
|
||||
if current_user():
|
||||
return redirect(
|
||||
url_for("account.profile_edition", username=current_user().uid[0])
|
||||
url_for("account.profile_edition", username=current_user().user_name[0])
|
||||
)
|
||||
|
||||
form = LoginForm(request.form or None)
|
||||
|
@ -99,7 +99,7 @@ def login():
|
|||
if request.form:
|
||||
user = User.get(form.login.data)
|
||||
if user and not user.has_password():
|
||||
return redirect(url_for("account.firstlogin", uid=user.uid[0]))
|
||||
return redirect(url_for("account.firstlogin", user_name=user.user_name[0]))
|
||||
|
||||
if not form.validate():
|
||||
User.logout()
|
||||
|
@ -122,7 +122,7 @@ def password():
|
|||
if request.form:
|
||||
user = User.get(session["attempt_login"])
|
||||
if user and not user.has_password():
|
||||
return redirect(url_for("account.firstlogin", uid=user.uid[0]))
|
||||
return redirect(url_for("account.firstlogin", user_name=user.user_name[0]))
|
||||
|
||||
if not form.validate() or not User.authenticate(
|
||||
session["attempt_login"], form.password.data, True
|
||||
|
@ -154,17 +154,18 @@ def logout():
|
|||
return redirect("/")
|
||||
|
||||
|
||||
@bp.route("/firstlogin/<uid>", methods=("GET", "POST"))
|
||||
def firstlogin(uid):
|
||||
user = User.get(uid)
|
||||
@bp.route("/firstlogin/<user_name>", methods=("GET", "POST"))
|
||||
def firstlogin(user_name):
|
||||
user = User.get(user_name)
|
||||
if not user or user.has_password():
|
||||
abort(404)
|
||||
|
||||
form = FirstLoginForm(request.form or None)
|
||||
if not request.form:
|
||||
return render_template("firstlogin.html", form=form, uid=uid)
|
||||
return render_template("firstlogin.html", form=form, user_name=user_name)
|
||||
|
||||
form.validate()
|
||||
|
||||
if send_password_initialization_mail(user):
|
||||
flash(
|
||||
_(
|
||||
|
@ -175,7 +176,7 @@ def firstlogin(uid):
|
|||
else:
|
||||
flash(_("Could not send the password initialization email"), "error")
|
||||
|
||||
return render_template("firstlogin.html", form=form, uid=uid)
|
||||
return render_template("firstlogin.html", form=form, user_name=user_name)
|
||||
|
||||
|
||||
@bp.route("/users", methods=["GET", "POST"])
|
||||
|
@ -195,9 +196,9 @@ def users(user):
|
|||
@dataclass
|
||||
class Invitation:
|
||||
creation_date_isoformat: str
|
||||
uid: str
|
||||
uid_editable: bool
|
||||
mail: str
|
||||
user_name: str
|
||||
user_name_editable: bool
|
||||
email: str
|
||||
groups: List[str]
|
||||
|
||||
@property
|
||||
|
@ -227,16 +228,16 @@ class Invitation:
|
|||
def user_invitation(user):
|
||||
form = InvitationForm(request.form or None)
|
||||
|
||||
mail_sent = None
|
||||
email_sent = None
|
||||
registration_url = None
|
||||
form_validated = False
|
||||
if request.form and form.validate():
|
||||
form_validated = True
|
||||
invitation = Invitation(
|
||||
datetime.datetime.now(datetime.timezone.utc).isoformat(),
|
||||
form.uid.data,
|
||||
form.uid_editable.data,
|
||||
form.mail.data,
|
||||
form.user_name.data,
|
||||
form.user_name_editable.data,
|
||||
form.email.data,
|
||||
form.groups.data,
|
||||
)
|
||||
registration_url = url_for(
|
||||
|
@ -247,14 +248,14 @@ def user_invitation(user):
|
|||
)
|
||||
|
||||
if request.form["action"] == "send":
|
||||
mail_sent = send_invitation_mail(form.mail.data, registration_url)
|
||||
email_sent = send_invitation_mail(form.email.data, registration_url)
|
||||
|
||||
return render_template(
|
||||
"invite.html",
|
||||
form=form,
|
||||
menuitems="users",
|
||||
form_validated=form_validated,
|
||||
mail_sent=mail_sent,
|
||||
email_sent=email_sent,
|
||||
registration_url=registration_url,
|
||||
)
|
||||
|
||||
|
@ -277,7 +278,7 @@ def registration(data, hash):
|
|||
)
|
||||
return redirect(url_for("account.index"))
|
||||
|
||||
if User.get(invitation.uid):
|
||||
if User.get(invitation.user_name):
|
||||
flash(
|
||||
_("Your account has already been created."),
|
||||
"error",
|
||||
|
@ -298,7 +299,11 @@ def registration(data, hash):
|
|||
)
|
||||
return redirect(url_for("account.index"))
|
||||
|
||||
data = {"uid": invitation.uid, "mail": invitation.mail, "groups": invitation.groups}
|
||||
data = {
|
||||
"user_name": invitation.user_name,
|
||||
"email": invitation.email,
|
||||
"groups": invitation.groups,
|
||||
}
|
||||
|
||||
readable_fields, writable_fields = default_fields()
|
||||
|
||||
|
@ -311,8 +316,8 @@ def registration(data, hash):
|
|||
)
|
||||
form.process(CombinedMultiDict((request.files, request.form)) or None, data=data)
|
||||
|
||||
if "readonly" in form["uid"].render_kw and invitation.uid_editable:
|
||||
del form["uid"].render_kw["readonly"]
|
||||
if "readonly" in form["user_name"].render_kw and invitation.user_name_editable:
|
||||
del form["user_name"].render_kw["readonly"]
|
||||
|
||||
form["password1"].validators = [
|
||||
wtforms.validators.DataRequired(),
|
||||
|
@ -333,7 +338,9 @@ def registration(data, hash):
|
|||
user = profile_create(current_app, form)
|
||||
user.login()
|
||||
flash(_("Your account has been created successfuly."), "success")
|
||||
return redirect(url_for("account.profile_edition", username=user.uid[0]))
|
||||
return redirect(
|
||||
url_for("account.profile_edition", username=user.user_name[0])
|
||||
)
|
||||
|
||||
return render_template(
|
||||
"profile_add.html",
|
||||
|
@ -360,7 +367,9 @@ def profile_creation(user):
|
|||
|
||||
else:
|
||||
user = profile_create(current_app, form)
|
||||
return redirect(url_for("account.profile_edition", username=user.uid[0]))
|
||||
return redirect(
|
||||
url_for("account.profile_edition", username=user.user_name[0])
|
||||
)
|
||||
|
||||
return render_template(
|
||||
"profile_add.html",
|
||||
|
@ -374,7 +383,7 @@ def profile_creation(user):
|
|||
def profile_create(current_app, form):
|
||||
user = User()
|
||||
for attribute in form:
|
||||
if attribute.name in user.may() + user.must():
|
||||
if attribute.name in user.attribute_table:
|
||||
if isinstance(attribute.data, FileStorage):
|
||||
data = attribute.data.stream.read()
|
||||
else:
|
||||
|
@ -382,10 +391,10 @@ def profile_create(current_app, form):
|
|||
|
||||
user[attribute.name] = data
|
||||
|
||||
if "jpegPhoto" in form and form["jpegPhoto_delete"].data:
|
||||
user["jpegPhoto"] = None
|
||||
if "photo" in form and form["photo_delete"].data:
|
||||
user["photo"] = None
|
||||
|
||||
user.cn = [f"{user.givenName[0]} {user.sn[0]}".strip()]
|
||||
user.formatted_name = [f"{user.given_name[0]} {user.family_name[0]}".strip()]
|
||||
user.save()
|
||||
|
||||
if "groups" in form:
|
||||
|
@ -408,13 +417,13 @@ def profile_create(current_app, form):
|
|||
def profile_edition(user, username):
|
||||
editor = user
|
||||
if not user.can_manage_users and not (
|
||||
user.can_edit_self and username == user.uid[0]
|
||||
user.can_edit_self and username == user.user_name[0]
|
||||
):
|
||||
abort(403)
|
||||
|
||||
menuitem = "profile" if username == editor.uid[0] else "users"
|
||||
menuitem = "profile" if username == editor.user_name[0] else "users"
|
||||
fields = editor.read | editor.write
|
||||
if username != editor.uid[0]:
|
||||
if username != editor.user_name[0]:
|
||||
user = User.get(username)
|
||||
else:
|
||||
user = editor
|
||||
|
@ -423,25 +432,25 @@ def profile_edition(user, username):
|
|||
abort(404)
|
||||
|
||||
available_fields = {
|
||||
"cn",
|
||||
"formatted_name",
|
||||
"title",
|
||||
"givenName",
|
||||
"sn",
|
||||
"displayName",
|
||||
"mail",
|
||||
"telephoneNumber",
|
||||
"postalAddress",
|
||||
"given_name",
|
||||
"family_name",
|
||||
"display_name",
|
||||
"email",
|
||||
"phone_number",
|
||||
"formatted_address",
|
||||
"street",
|
||||
"postalCode",
|
||||
"l",
|
||||
"st",
|
||||
"jpegPhoto",
|
||||
"jpegPhoto_delete",
|
||||
"employeeNumber",
|
||||
"departmentNumber",
|
||||
"labeledURI",
|
||||
"preferredLanguage",
|
||||
"o",
|
||||
"postal_code",
|
||||
"locality",
|
||||
"region",
|
||||
"photo",
|
||||
"photo_delete",
|
||||
"employee_number",
|
||||
"department",
|
||||
"profile_url",
|
||||
"preferred_language",
|
||||
"organization",
|
||||
}
|
||||
data = {
|
||||
k: getattr(user, k)[0]
|
||||
|
@ -463,7 +472,7 @@ def profile_edition(user, username):
|
|||
else:
|
||||
for attribute in form:
|
||||
if (
|
||||
attribute.name in user.may() + user.must()
|
||||
attribute.name in user.attribute_table
|
||||
and attribute.name in editor.write
|
||||
):
|
||||
if isinstance(attribute.data, FileStorage):
|
||||
|
@ -473,15 +482,15 @@ def profile_edition(user, username):
|
|||
|
||||
user[attribute.name] = data
|
||||
|
||||
if "jpegPhoto" in form and form["jpegPhoto_delete"].data:
|
||||
user["jpegPhoto"] = None
|
||||
if "photo" in form and form["photo_delete"].data:
|
||||
user["photo"] = None
|
||||
|
||||
if "preferredLanguage" in request.form:
|
||||
if "preferred_language" in request.form:
|
||||
# Refresh the babel cache in case the lang is updated
|
||||
refresh()
|
||||
|
||||
if form["preferredLanguage"].data == "auto":
|
||||
user.preferredLanguage = None
|
||||
if form["preferred_language"].data == "auto":
|
||||
user.preferred_language = None
|
||||
|
||||
user.save()
|
||||
flash(_("Profile updated successfuly."), "success")
|
||||
|
@ -499,7 +508,7 @@ def profile_edition(user, username):
|
|||
@user_needed()
|
||||
def profile_settings(user, username):
|
||||
if not user.can_manage_users and not (
|
||||
user.can_edit_self and username == user.uid[0]
|
||||
user.can_edit_self and username == user.user_name[0]
|
||||
):
|
||||
abort(403)
|
||||
|
||||
|
@ -550,7 +559,7 @@ def profile_settings_edit(editor, edited_user):
|
|||
menuitem = "profile" if editor.id == editor.id else "users"
|
||||
fields = editor.read | editor.write
|
||||
|
||||
available_fields = {"userPassword", "groups", "uid"}
|
||||
available_fields = {"password", "groups", "user_name"}
|
||||
data = {
|
||||
k: getattr(edited_user, k)[0]
|
||||
if getattr(edited_user, k) and isinstance(getattr(edited_user, k), list)
|
||||
|
@ -586,7 +595,7 @@ def profile_settings_edit(editor, edited_user):
|
|||
edited_user.save()
|
||||
flash(_("Profile updated successfuly."), "success")
|
||||
return redirect(
|
||||
url_for("account.profile_edition", username=edited_user.uid[0])
|
||||
url_for("account.profile_edition", username=edited_user.user_name[0])
|
||||
)
|
||||
|
||||
return render_template(
|
||||
|
@ -675,16 +684,18 @@ def forgotten():
|
|||
return render_template("forgotten-password.html", form=form)
|
||||
|
||||
|
||||
@bp.route("/reset/<uid>/<hash>", methods=["GET", "POST"])
|
||||
def reset(uid, hash):
|
||||
@bp.route("/reset/<user_name>/<hash>", methods=["GET", "POST"])
|
||||
def reset(user_name, hash):
|
||||
if not current_app.config.get("ENABLE_PASSWORD_RECOVERY", True):
|
||||
abort(404)
|
||||
|
||||
form = PasswordResetForm(request.form)
|
||||
user = User.get(uid)
|
||||
user = User.get(user_name)
|
||||
|
||||
if not user or hash != profile_hash(
|
||||
user.uid[0], user.mail[0], user.userPassword[0] if user.has_password() else ""
|
||||
user.user_name[0],
|
||||
user.email[0],
|
||||
user.password[0] if user.has_password() else "",
|
||||
):
|
||||
flash(
|
||||
_("The password reset link that brought you here was invalid."),
|
||||
|
@ -697,25 +708,27 @@ def reset(uid, hash):
|
|||
user.login()
|
||||
|
||||
flash(_("Your password has been updated successfuly"), "success")
|
||||
return redirect(url_for("account.profile_edition", username=uid))
|
||||
return redirect(url_for("account.profile_edition", username=user_name))
|
||||
|
||||
return render_template("reset-password.html", form=form, uid=uid, hash=hash)
|
||||
return render_template(
|
||||
"reset-password.html", form=form, user_name=user_name, hash=hash
|
||||
)
|
||||
|
||||
|
||||
@bp.route("/profile/<uid>/<field>")
|
||||
def photo(uid, field):
|
||||
if field.lower() != "jpegphoto":
|
||||
@bp.route("/profile/<user_name>/<field>")
|
||||
def photo(user_name, field):
|
||||
if field.lower() != "photo":
|
||||
abort(404)
|
||||
|
||||
user = User.get(uid)
|
||||
user = User.get(user_name)
|
||||
if not user:
|
||||
abort(404)
|
||||
|
||||
etag = None
|
||||
if request.if_modified_since and request.if_modified_since >= user.modifyTimestamp:
|
||||
if request.if_modified_since and request.if_modified_since >= user.last_modified:
|
||||
return "", 304
|
||||
|
||||
etag = profile_hash(uid, user.modifyTimestamp.isoformat())
|
||||
etag = profile_hash(user_name, user.last_modified.isoformat())
|
||||
if request.if_none_match and etag in request.if_none_match:
|
||||
return "", 304
|
||||
|
||||
|
@ -725,5 +738,5 @@ def photo(uid, field):
|
|||
|
||||
stream = io.BytesIO(photos[0])
|
||||
return send_file(
|
||||
stream, mimetype="image/jpeg", last_modified=user.modifyTimestamp, etag=etag
|
||||
stream, mimetype="image/jpeg", last_modified=user.last_modified, etag=etag
|
||||
)
|
||||
|
|
|
@ -19,7 +19,7 @@ bp = Blueprint("admin", __name__, url_prefix="/admin")
|
|||
|
||||
|
||||
class MailTestForm(HTMXForm):
|
||||
mail = StringField(
|
||||
email = StringField(
|
||||
_("Email"),
|
||||
validators=[
|
||||
DataRequired(),
|
||||
|
@ -38,7 +38,7 @@ class MailTestForm(HTMXForm):
|
|||
def mail_index(user):
|
||||
form = MailTestForm(request.form or None)
|
||||
if request.form and form.validate():
|
||||
if send_test_mail(form.mail.data):
|
||||
if send_test_mail(form.email.data):
|
||||
flash(_("The test invitation mail has been sent correctly"), "success")
|
||||
else:
|
||||
flash(_("The test invitation mail has not been sent correctly"), "error")
|
||||
|
@ -75,8 +75,8 @@ def password_init_html(user):
|
|||
base_url = url_for("account.index", _external=True)
|
||||
reset_url = url_for(
|
||||
"account.reset",
|
||||
uid=user.uid[0],
|
||||
hash=profile_hash(user.uid[0], user.mail[0], user.userPassword[0]),
|
||||
user_name=user.user_name[0],
|
||||
hash=profile_hash(user.user_name[0], user.email[0], user.password[0]),
|
||||
_external=True,
|
||||
)
|
||||
|
||||
|
@ -98,8 +98,8 @@ def password_init_txt(user):
|
|||
base_url = url_for("account.index", _external=True)
|
||||
reset_url = url_for(
|
||||
"account.reset",
|
||||
uid=user.uid[0],
|
||||
hash=profile_hash(user.uid[0], user.mail[0], user.userPassword[0]),
|
||||
user_name=user.user_name[0],
|
||||
hash=profile_hash(user.user_name[0], user.email[0], user.password[0]),
|
||||
_external=True,
|
||||
)
|
||||
|
||||
|
@ -117,8 +117,8 @@ def password_reset_html(user):
|
|||
base_url = url_for("account.index", _external=True)
|
||||
reset_url = url_for(
|
||||
"account.reset",
|
||||
uid=user.uid[0],
|
||||
hash=profile_hash(user.uid[0], user.mail[0], user.userPassword[0]),
|
||||
user_name=user.user_name[0],
|
||||
hash=profile_hash(user.user_name[0], user.email[0], user.password[0]),
|
||||
_external=True,
|
||||
)
|
||||
|
||||
|
@ -140,8 +140,8 @@ def password_reset_txt(user):
|
|||
base_url = url_for("account.index", _external=True)
|
||||
reset_url = url_for(
|
||||
"account.reset",
|
||||
uid=user.uid[0],
|
||||
hash=profile_hash(user.uid[0], user.mail[0], user.userPassword[0]),
|
||||
user_name=user.user_name[0],
|
||||
hash=profile_hash(user.user_name[0], user.email[0], user.password[0]),
|
||||
_external=True,
|
||||
)
|
||||
|
||||
|
@ -153,14 +153,14 @@ def password_reset_txt(user):
|
|||
)
|
||||
|
||||
|
||||
@bp.route("/mail/<uid>/<email>/invitation.html")
|
||||
@bp.route("/mail/<user_name>/<email>/invitation.html")
|
||||
@permissions_needed("manage_oidc")
|
||||
def invitation_html(user, uid, email):
|
||||
def invitation_html(user, user_name, email):
|
||||
base_url = url_for("account.index", _external=True)
|
||||
registration_url = url_for(
|
||||
"account.registration",
|
||||
data=obj_to_b64([uid, email]),
|
||||
hash=profile_hash(uid, email),
|
||||
data=obj_to_b64([user_name, email]),
|
||||
hash=profile_hash(user_name, email),
|
||||
_external=True,
|
||||
)
|
||||
|
||||
|
@ -176,14 +176,14 @@ def invitation_html(user, uid, email):
|
|||
)
|
||||
|
||||
|
||||
@bp.route("/mail/<uid>/<email>/invitation.txt")
|
||||
@bp.route("/mail/<user_name>/<email>/invitation.txt")
|
||||
@permissions_needed("manage_oidc")
|
||||
def invitation_txt(user, uid, email):
|
||||
def invitation_txt(user, user_name, email):
|
||||
base_url = url_for("account.index", _external=True)
|
||||
registration_url = url_for(
|
||||
"account.registration",
|
||||
data=obj_to_b64([uid, email]),
|
||||
hash=profile_hash(uid, email),
|
||||
data=obj_to_b64([user_name, email]),
|
||||
hash=profile_hash(user_name, email),
|
||||
_external=True,
|
||||
)
|
||||
|
||||
|
|
|
@ -130,26 +130,26 @@ GROUP_BASE = "ou=groups,dc=mydomain,dc=tld"
|
|||
# object that users will be able to read and/or write.
|
||||
[ACL.DEFAULT]
|
||||
PERMISSIONS = ["edit_self", "use_oidc"]
|
||||
READ = ["uid", "groups"]
|
||||
READ = ["user_name", "groups"]
|
||||
WRITE = [
|
||||
"jpegPhoto",
|
||||
"givenName",
|
||||
"sn",
|
||||
"displayName",
|
||||
"userPassword",
|
||||
"telephoneNumber",
|
||||
"mail",
|
||||
"labeledURI",
|
||||
"postalAddress",
|
||||
"photo",
|
||||
"given_name",
|
||||
"family_name",
|
||||
"display_name",
|
||||
"password",
|
||||
"phone_number",
|
||||
"email",
|
||||
"profile_url",
|
||||
"formatted_address",
|
||||
"street",
|
||||
"postalCode",
|
||||
"l",
|
||||
"st",
|
||||
"preferredLanguage",
|
||||
"employeeNumber",
|
||||
"departmentNumber",
|
||||
"postal_code",
|
||||
"locality",
|
||||
"region",
|
||||
"preferred_language",
|
||||
"employee_number",
|
||||
"department",
|
||||
"title",
|
||||
"o",
|
||||
"organization",
|
||||
]
|
||||
|
||||
[ACL.ADMIN]
|
||||
|
@ -185,17 +185,17 @@ PUBLIC_KEY = "canaille/conf/public.pem"
|
|||
# User objectClass.
|
||||
# {attribute} will be replaced by the user ldap attribute value.
|
||||
# Default values fits inetOrgPerson.
|
||||
SUB = "{{ user.uid[0] }}"
|
||||
NAME = "{{ user.cn[0] }}"
|
||||
PHONE_NUMBER = "{{ user.telephoneNumber[0] }}"
|
||||
SUB = "{{ user.user_name[0] }}"
|
||||
NAME = "{{ user.formatted_name[0] }}"
|
||||
PHONE_NUMBER = "{{ user.phone_number[0] }}"
|
||||
EMAIL = "{{ user.mail[0] }}"
|
||||
GIVEN_NAME = "{{ user.givenName[0] }}"
|
||||
FAMILY_NAME = "{{ user.sn[0] }}"
|
||||
PREFERRED_USERNAME = "{{ user.displayName }}"
|
||||
LOCALE = "{{ user.preferredLanguage }}"
|
||||
ADDRESS = "{{ user.postalAddress[0] }}"
|
||||
PICTURE = "{% if user.jpegPhoto %}{{ url_for('account.photo', uid=user.uid[0], field='jpegPhoto', _external=True) }}{% endif %}"
|
||||
WEBSITE = "{{ user.labeledURI[0] }}"
|
||||
GIVEN_NAME = "{{ user.given_name[0] }}"
|
||||
FAMILY_NAME = "{{ user.family_name[0] }}"
|
||||
PREFERRED_USERNAME = "{{ user.display_name }}"
|
||||
LOCALE = "{{ user.preferred_language }}"
|
||||
ADDRESS = "{{ user.formatted_address[0] }}"
|
||||
PICTURE = "{% if user.photo %}{{ url_for('account.photo', user_name=user.user_name[0], field='photo', _external=True) }}{% endif %}"
|
||||
WEBSITE = "{{ user.profile_url[0] }}"
|
||||
|
||||
# The SMTP server options. If not set, mail related features such as
|
||||
# user invitations, and password reset emails, will be disabled.
|
||||
|
|
|
@ -122,16 +122,16 @@ def available_language_choices():
|
|||
|
||||
|
||||
PROFILE_FORM_FIELDS = dict(
|
||||
uid=wtforms.StringField(
|
||||
user_name=wtforms.StringField(
|
||||
_("Username"),
|
||||
render_kw={"placeholder": _("jdoe")},
|
||||
validators=[wtforms.validators.DataRequired(), unique_login],
|
||||
),
|
||||
cn=wtforms.StringField(_("Name")),
|
||||
formatted_name=wtforms.StringField(_("Name")),
|
||||
title=wtforms.StringField(
|
||||
_("Title"), render_kw={"placeholder": _("Vice president")}
|
||||
),
|
||||
givenName=wtforms.StringField(
|
||||
given_name=wtforms.StringField(
|
||||
_("Given name"),
|
||||
render_kw={
|
||||
"placeholder": _("John"),
|
||||
|
@ -139,7 +139,7 @@ PROFILE_FORM_FIELDS = dict(
|
|||
"autocorrect": "off",
|
||||
},
|
||||
),
|
||||
sn=wtforms.StringField(
|
||||
family_name=wtforms.StringField(
|
||||
_("Family Name"),
|
||||
validators=[wtforms.validators.DataRequired()],
|
||||
render_kw={
|
||||
|
@ -148,7 +148,7 @@ PROFILE_FORM_FIELDS = dict(
|
|||
"autocorrect": "off",
|
||||
},
|
||||
),
|
||||
displayName=wtforms.StringField(
|
||||
display_name=wtforms.StringField(
|
||||
_("Display Name"),
|
||||
validators=[wtforms.validators.Optional()],
|
||||
render_kw={
|
||||
|
@ -157,7 +157,7 @@ PROFILE_FORM_FIELDS = dict(
|
|||
"autocorrect": "off",
|
||||
},
|
||||
),
|
||||
mail=wtforms.EmailField(
|
||||
email=wtforms.EmailField(
|
||||
_("Email address"),
|
||||
validators=[
|
||||
wtforms.validators.DataRequired(),
|
||||
|
@ -173,10 +173,10 @@ PROFILE_FORM_FIELDS = dict(
|
|||
"autocorrect": "off",
|
||||
},
|
||||
),
|
||||
telephoneNumber=wtforms.TelField(
|
||||
phone_number=wtforms.TelField(
|
||||
_("Phone number"), render_kw={"placeholder": _("555-000-555")}
|
||||
),
|
||||
postalAddress=wtforms.StringField(
|
||||
formatted_address=wtforms.StringField(
|
||||
_("Address"),
|
||||
render_kw={
|
||||
"placeholder": _("132, Foobar Street, Gotham City 12401, XX"),
|
||||
|
@ -188,30 +188,30 @@ PROFILE_FORM_FIELDS = dict(
|
|||
"placeholder": _("132, Foobar Street"),
|
||||
},
|
||||
),
|
||||
postalCode=wtforms.StringField(
|
||||
postal_code=wtforms.StringField(
|
||||
_("Postal Code"),
|
||||
render_kw={
|
||||
"placeholder": "12401",
|
||||
},
|
||||
),
|
||||
l=wtforms.StringField(
|
||||
locality=wtforms.StringField(
|
||||
_("Locality"),
|
||||
render_kw={
|
||||
"placeholder": _("Gotham City"),
|
||||
},
|
||||
),
|
||||
st=wtforms.StringField(
|
||||
region=wtforms.StringField(
|
||||
_("Region"),
|
||||
render_kw={
|
||||
"placeholder": _("North Pole"),
|
||||
},
|
||||
),
|
||||
jpegPhoto=FileField(
|
||||
photo=FileField(
|
||||
_("Photo"),
|
||||
validators=[FileAllowed(["jpg", "jpeg"])],
|
||||
render_kw={"accept": "image/jpg, image/jpeg"},
|
||||
),
|
||||
jpegPhoto_delete=wtforms.BooleanField(_("Delete the photo")),
|
||||
photo_delete=wtforms.BooleanField(_("Delete the photo")),
|
||||
password1=wtforms.PasswordField(
|
||||
_("Password"),
|
||||
validators=[wtforms.validators.Optional(), wtforms.validators.Length(min=8)],
|
||||
|
@ -230,32 +230,32 @@ PROFILE_FORM_FIELDS = dict(
|
|||
"autocomplete": "new-password",
|
||||
},
|
||||
),
|
||||
employeeNumber=wtforms.StringField(
|
||||
employee_number=wtforms.StringField(
|
||||
_("User number"),
|
||||
render_kw={
|
||||
"placeholder": _("1234"),
|
||||
},
|
||||
),
|
||||
departmentNumber=wtforms.StringField(
|
||||
_("Department number"),
|
||||
department=wtforms.StringField(
|
||||
_("Department"),
|
||||
render_kw={
|
||||
"placeholder": _("1234"),
|
||||
},
|
||||
),
|
||||
o=wtforms.StringField(
|
||||
organization=wtforms.StringField(
|
||||
_("Organization"),
|
||||
render_kw={
|
||||
"placeholder": _("Cogip LTD."),
|
||||
},
|
||||
),
|
||||
labeledURI=wtforms.URLField(
|
||||
profile_url=wtforms.URLField(
|
||||
_("Website"),
|
||||
render_kw={
|
||||
"placeholder": _("https://mywebsite.tld"),
|
||||
},
|
||||
validators=[wtforms.validators.Optional(), is_uri],
|
||||
),
|
||||
preferredLanguage=wtforms.SelectField(
|
||||
preferred_language=wtforms.SelectField(
|
||||
_("Preferred language"),
|
||||
choices=available_language_choices,
|
||||
),
|
||||
|
@ -268,11 +268,11 @@ PROFILE_FORM_FIELDS = dict(
|
|||
|
||||
|
||||
def profile_form(write_field_names, readonly_field_names, user=None):
|
||||
if "userPassword" in write_field_names:
|
||||
if "password" in write_field_names:
|
||||
write_field_names |= {"password1", "password2"}
|
||||
|
||||
if "jpegPhoto" in write_field_names:
|
||||
write_field_names |= {"jpegPhoto_delete"}
|
||||
if "photo" in write_field_names:
|
||||
write_field_names |= {"photo_delete"}
|
||||
|
||||
fields = {
|
||||
name: PROFILE_FORM_FIELDS.get(name)
|
||||
|
@ -321,13 +321,13 @@ class EditGroupForm(HTMXForm):
|
|||
|
||||
|
||||
class InvitationForm(HTMXForm):
|
||||
uid = wtforms.StringField(
|
||||
user_name = wtforms.StringField(
|
||||
_("Username"),
|
||||
render_kw={"placeholder": _("jdoe")},
|
||||
validators=[wtforms.validators.DataRequired(), unique_login],
|
||||
)
|
||||
uid_editable = wtforms.BooleanField(_("Username editable by the invitee"))
|
||||
mail = wtforms.EmailField(
|
||||
user_name_editable = wtforms.BooleanField(_("Username editable by the invitee"))
|
||||
email = wtforms.EmailField(
|
||||
_("Email address"),
|
||||
validators=[
|
||||
wtforms.validators.DataRequired(),
|
||||
|
|
|
@ -132,11 +132,11 @@ def validate_configuration(config):
|
|||
try:
|
||||
User.ldap_object_classes(conn)
|
||||
user = User(
|
||||
cn=f"canaille_{uuid.uuid4()}",
|
||||
sn=f"canaille_{uuid.uuid4()}",
|
||||
uid=f"canaille_{uuid.uuid4()}",
|
||||
mail=f"canaille_{uuid.uuid4()}@mydomain.tld",
|
||||
userPassword="{SSHA}fw9DYeF/gHTHuVMepsQzVYAkffGcU8Fz",
|
||||
formatted_name=f"canaille_{uuid.uuid4()}",
|
||||
family_name=f"canaille_{uuid.uuid4()}",
|
||||
user_name=f"canaille_{uuid.uuid4()}",
|
||||
email=f"canaille_{uuid.uuid4()}@mydomain.tld",
|
||||
password="{SSHA}fw9DYeF/gHTHuVMepsQzVYAkffGcU8Fz",
|
||||
)
|
||||
user.save(conn)
|
||||
user.delete(conn)
|
||||
|
@ -152,10 +152,10 @@ def validate_configuration(config):
|
|||
|
||||
user = User(
|
||||
cn=f"canaille_{uuid.uuid4()}",
|
||||
sn=f"canaille_{uuid.uuid4()}",
|
||||
uid=f"canaille_{uuid.uuid4()}",
|
||||
mail=f"canaille_{uuid.uuid4()}@mydomain.tld",
|
||||
userPassword="{SSHA}fw9DYeF/gHTHuVMepsQzVYAkffGcU8Fz",
|
||||
family_name=f"canaille_{uuid.uuid4()}",
|
||||
user_name=f"canaille_{uuid.uuid4()}",
|
||||
email=f"canaille_{uuid.uuid4()}@mydomain.tld",
|
||||
password="{SSHA}fw9DYeF/gHTHuVMepsQzVYAkffGcU8Fz",
|
||||
)
|
||||
user.save(conn)
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@ def ldap_to_python(value, syntax):
|
|||
if syntax == Syntax.INTEGER:
|
||||
return int(value.decode("utf-8"))
|
||||
|
||||
if syntax == Syntax.JPEG:
|
||||
if syntax in (Syntax.JPEG, Syntax.FAX_IMAGE):
|
||||
return value
|
||||
|
||||
if syntax == Syntax.BOOLEAN:
|
||||
|
@ -68,7 +68,7 @@ def python_to_ldap(value, syntax, encode=True):
|
|||
if syntax == Syntax.INTEGER and isinstance(value, int):
|
||||
value = str(value)
|
||||
|
||||
if syntax == Syntax.JPEG:
|
||||
if syntax in (Syntax.JPEG, Syntax.FAX_IMAGE):
|
||||
encodable = False
|
||||
|
||||
if syntax == Syntax.BOOLEAN and isinstance(value, bool):
|
||||
|
|
|
@ -134,11 +134,11 @@ def send_password_reset_mail(user):
|
|||
base_url = url_for("account.index", _external=True)
|
||||
reset_url = url_for(
|
||||
"account.reset",
|
||||
uid=user.uid[0],
|
||||
user_name=user.user_name[0],
|
||||
hash=profile_hash(
|
||||
user.uid[0],
|
||||
user.mail[0],
|
||||
user.userPassword[0] if user.has_password() else "",
|
||||
user.user_name[0],
|
||||
user.email[0],
|
||||
user.password[0] if user.has_password() else "",
|
||||
),
|
||||
_external=True,
|
||||
)
|
||||
|
@ -163,7 +163,7 @@ def send_password_reset_mail(user):
|
|||
|
||||
return send_email(
|
||||
subject=subject,
|
||||
recipient=user.mail[0],
|
||||
recipient=user.email[0],
|
||||
text=text_body,
|
||||
html=html_body,
|
||||
attachements=[(logo_cid, logo_filename, logo_raw)] if logo_filename else None,
|
||||
|
@ -174,11 +174,11 @@ def send_password_initialization_mail(user):
|
|||
base_url = url_for("account.index", _external=True)
|
||||
reset_url = url_for(
|
||||
"account.reset",
|
||||
uid=user.uid[0],
|
||||
user_name=user.user_name[0],
|
||||
hash=profile_hash(
|
||||
user.uid[0],
|
||||
user.mail[0],
|
||||
user.userPassword[0] if user.has_password() else "",
|
||||
user.user_name[0],
|
||||
user.email[0],
|
||||
user.password[0] if user.has_password() else "",
|
||||
),
|
||||
_external=True,
|
||||
)
|
||||
|
@ -203,7 +203,7 @@ def send_password_initialization_mail(user):
|
|||
|
||||
return send_email(
|
||||
subject=subject,
|
||||
recipient=user.mail[0],
|
||||
recipient=user.email[0],
|
||||
text=text_body,
|
||||
html=html_body,
|
||||
attachements=[(logo_cid, logo_filename, logo_raw)] if logo_filename else None,
|
||||
|
|
|
@ -12,6 +12,27 @@ class User(LDAPObject):
|
|||
|
||||
attribute_table = {
|
||||
"id": "dn",
|
||||
"user_name": "uid",
|
||||
"password": "userPassword",
|
||||
"preferred_language": "preferredLanguage",
|
||||
"family_name": "sn",
|
||||
"given_name": "givenName",
|
||||
"formatted_name": "cn",
|
||||
"display_name": "displayName",
|
||||
"email": "mail",
|
||||
"phone_number": "telephoneNumber",
|
||||
"formatted_address": "postalAddress",
|
||||
"street": "street",
|
||||
"postal_code": "postalCode",
|
||||
"locality": "l",
|
||||
"region": "st",
|
||||
"photo": "jpegPhoto",
|
||||
"profile_url": "labeledURI",
|
||||
"employee_number": "employeeNumber",
|
||||
"department": "departmentNumber",
|
||||
"title": "title",
|
||||
"organization": "o",
|
||||
"last_modified": "modifyTimestamp",
|
||||
}
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
|
@ -79,7 +100,7 @@ class User(LDAPObject):
|
|||
pass
|
||||
|
||||
def has_password(self):
|
||||
return bool(self.userPassword)
|
||||
return bool(self.password)
|
||||
|
||||
def check_password(self, password):
|
||||
conn = ldap.initialize(current_app.config["LDAP"]["URI"])
|
||||
|
@ -106,7 +127,7 @@ class User(LDAPObject):
|
|||
|
||||
@property
|
||||
def name(self):
|
||||
return self.cn[0]
|
||||
return self.formatted_name[0]
|
||||
|
||||
@property
|
||||
def groups(self):
|
||||
|
|
|
@ -276,7 +276,7 @@ def end_session():
|
|||
|
||||
if (
|
||||
not data.get("id_token_hint")
|
||||
or (data.get("logout_hint") and data["logout_hint"] != user.uid[0])
|
||||
or (data.get("logout_hint") and data["logout_hint"] != user.user_name[0])
|
||||
) and not session.get("end_session_confirmation"):
|
||||
session["end_session_data"] = data
|
||||
return render_template(
|
||||
|
@ -316,7 +316,7 @@ def end_session():
|
|||
if client:
|
||||
valid_uris.extend(client.post_logout_redirect_uris or [])
|
||||
|
||||
if user.uid[0] != id_token["sub"] and not session.get(
|
||||
if user.user_name[0] != id_token["sub"] and not session.get(
|
||||
"end_session_confirmation"
|
||||
):
|
||||
session["end_session_data"] = data
|
||||
|
|
|
@ -297,7 +297,7 @@ class IntrospectionEndpoint(_IntrospectionEndpoint):
|
|||
"token_type": token.type,
|
||||
"username": token.subject.name,
|
||||
"scope": token.get_scope(),
|
||||
"sub": token.subject.uid[0],
|
||||
"sub": token.subject.user_name[0],
|
||||
"aud": audience,
|
||||
"iss": get_issuer(),
|
||||
"exp": token.get_expires_at(),
|
||||
|
|
|
@ -21,23 +21,23 @@ def fake_users(nb=1):
|
|||
fake = random.choice(fakes)
|
||||
name = fake.unique.name()
|
||||
user = User(
|
||||
cn=name,
|
||||
givenName=name.split(" ")[0],
|
||||
sn=name.split(" ")[1],
|
||||
uid=fake.unique.user_name(),
|
||||
mail=fake.unique.email(),
|
||||
telephoneNumber=fake.unique.ssn(),
|
||||
labeledURI=fake.unique.uri(),
|
||||
postalAddress=fake.unique.address(),
|
||||
formatted_name=name,
|
||||
given_name=name.split(" ")[0],
|
||||
family_name=name.split(" ")[1],
|
||||
user_name=fake.unique.user_name(),
|
||||
email=fake.unique.email(),
|
||||
phone_number=fake.unique.ssn(),
|
||||
profile_url=fake.unique.uri(),
|
||||
address=fake.unique.address(),
|
||||
street=fake.street_name(),
|
||||
postalCode=fake.postcode(),
|
||||
l=fake.city(),
|
||||
st=fake.state(),
|
||||
employeeNumber=str(fake.unique.random_number()),
|
||||
departmentNumber=fake.word(),
|
||||
postal_code=fake.postcode(),
|
||||
locality=fake.city(),
|
||||
region=fake.state(),
|
||||
employee_number=str(fake.unique.random_number()),
|
||||
department=fake.word(),
|
||||
title=fake.job(),
|
||||
userPassword=fake.password(),
|
||||
preferredLanguage=fake._locales[0],
|
||||
password=fake.password(),
|
||||
preferred_language=fake._locales[0],
|
||||
)
|
||||
user.save()
|
||||
users.append(user)
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
<div class="content">
|
||||
{% if request.form["action"] == "generate" %}
|
||||
{{ _("Invitation link") }}
|
||||
{% elif mail_sent %}
|
||||
{% elif email_sent %}
|
||||
{{ _("Invitation sent") }}
|
||||
{% else %}
|
||||
{{ _("Invitation not sent") }}
|
||||
|
@ -49,18 +49,18 @@
|
|||
{% trans %}Here is the invitation link you can provide to the user you want to invite:{% endtrans %}
|
||||
</div>
|
||||
|
||||
{% elif mail_sent %}
|
||||
{% elif email_sent %}
|
||||
|
||||
<div class="ui success message">
|
||||
{% set email = form.mail.data %}
|
||||
<div class="ui attached success message">
|
||||
{% set email = form.email.data %}
|
||||
{% trans %}This invitation link has been sent to {{ email }}{% endtrans %}
|
||||
{% trans %}If you need to provide this link by other ways than email, you can copy it there:{% endtrans %}
|
||||
</div>
|
||||
|
||||
{% else %}
|
||||
|
||||
<div class="ui error message">
|
||||
{% set email = form.mail.data %}
|
||||
<div class="ui attached error message">
|
||||
{% set email = form.email.data %}
|
||||
{% trans %}This invitation link could not be sent to {{ email }} due to technical issues.{% endtrans %}
|
||||
{% trans %}However you can copy the link there to provide it by other ways than email:{% endtrans %}
|
||||
</div>
|
||||
|
@ -82,7 +82,7 @@
|
|||
<a class="ui right floated button" href="{{ url_for("account.profile_creation") }}">
|
||||
{{ _("Create a user") }}
|
||||
</a>
|
||||
{% if request.form["action"] == "generate" or mail_sent %}
|
||||
{% if request.form["action"] == "generate" or email_sent %}
|
||||
<a href="{{ url_for('account.user_invitation') }}" class="ui right floated button" name="action" value="invite" id="invite">
|
||||
{{ _("Invite another user") }}
|
||||
</a>
|
||||
|
@ -108,16 +108,16 @@
|
|||
</div>
|
||||
|
||||
{% call fui.render_form(form) %}
|
||||
{% block uid_field scoped %}
|
||||
{{ fui.render_field(form.uid, icon="user") }}
|
||||
{% block user_name_field scoped %}
|
||||
{{ fui.render_field(form.user_name, icon="user") }}
|
||||
{% endblock %}
|
||||
|
||||
{% block uid_editable_field scoped %}
|
||||
{{ fui.render_checkbox(form.uid_editable) }}
|
||||
{% block user_name_editable_field scoped %}
|
||||
{{ fui.render_checkbox(form.user_name_editable) }}
|
||||
{% endblock %}
|
||||
|
||||
{% block mail_field scoped %}
|
||||
{{ fui.render_field(form.mail, icon="mail") }}
|
||||
{% block email_field scoped %}
|
||||
{{ fui.render_field(form.email, icon="email") }}
|
||||
{% endblock %}
|
||||
|
||||
{% block groups_field scoped %}
|
||||
|
|
|
@ -46,7 +46,7 @@
|
|||
</div>
|
||||
|
||||
{% call fui.render_form(form) %}
|
||||
{{ fui.render_field(form.mail) }}
|
||||
{{ fui.render_field(form.email) }}
|
||||
<div class="ui right aligned container">
|
||||
<div class="ui stackable buttons">
|
||||
<input type="submit" class="ui primary button" value="{{ _("Send") }}">
|
||||
|
@ -101,8 +101,8 @@
|
|||
<div class="item">
|
||||
<div class="right floated content">
|
||||
<div class="ui buttons">
|
||||
<a class="ui button primary" href="{{ url_for("admin.invitation_txt", uid=user.uid, email=user.mail[0]) }}">TXT</a>
|
||||
<a class="ui button primary" href="{{ url_for("admin.invitation_html", uid=user.uid, email=user.mail[0]) }}">HTML</a>
|
||||
<a class="ui button primary" href="{{ url_for("admin.invitation_txt", user_name=user.user_name, email=user.email[0]) }}">TXT</a>
|
||||
<a class="ui button primary" href="{{ url_for("admin.invitation_html", user_name=user.user_name, email=user.email[0]) }}">HTML</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="middle aligned content">
|
||||
|
|
|
@ -70,8 +70,8 @@
|
|||
<tr>
|
||||
<td>{{ _("Subject") }}</td>
|
||||
<td>
|
||||
<a href="{{ url_for("account.profile_edition", username=token.subject.uid[0]) }}">
|
||||
{{ token.subject.name }} - {{ token.subject.uid[0] }}
|
||||
<a href="{{ url_for("account.profile_edition", username=token.subject.user_name[0]) }}">
|
||||
{{ token.subject.name }} - {{ token.subject.user_name[0] }}
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
|
|
|
@ -22,8 +22,8 @@
|
|||
</a>
|
||||
</td>
|
||||
<td>
|
||||
<a href="{{ url_for("account.profile_edition", username=token.subject.uid[0]) }}">
|
||||
{{ token.subject.uid[0] }}
|
||||
<a href="{{ url_for("account.profile_edition", username=token.subject.user_name[0]) }}">
|
||||
{{ token.subject.user_name[0] }}
|
||||
</a>
|
||||
</td>
|
||||
<td>{{ token.issue_date }}</td>
|
||||
|
|
|
@ -2,16 +2,16 @@
|
|||
<table class="ui bottom attached table users">
|
||||
<thead>
|
||||
<tr>
|
||||
{% if user.can_read("jpegPhoto") %}
|
||||
{% if user.can_read("photo") %}
|
||||
<th></th>
|
||||
{% endif %}
|
||||
{% if user.can_read("uid") %}
|
||||
{% if user.can_read("user_name") %}
|
||||
<th>{% trans %}Login{% endtrans %}</th>
|
||||
{% endif %}
|
||||
{% if user.can_read("sn") or user.can_read("givenName") %}
|
||||
{% if user.can_read("family_name") or user.can_read("given_name") %}
|
||||
<th>{% trans %}Name{% endtrans %}</th>
|
||||
{% endif %}
|
||||
{% if user.can_read("mail") %}
|
||||
{% if user.can_read("email") %}
|
||||
<th>{% trans %}Email{% endtrans %}</th>
|
||||
{% endif %}
|
||||
{% if user.can_manage_groups %}
|
||||
|
@ -22,25 +22,25 @@
|
|||
<tbody>
|
||||
{% for watched_user in table_form.items_slice %}
|
||||
<tr>
|
||||
{% if user.can_read("jpegPhoto") %}
|
||||
{% if user.can_read("photo") %}
|
||||
<td>
|
||||
<a href="{{ url_for('account.profile_edition', username=watched_user.uid[0]) }}">
|
||||
{% if watched_user.jpegPhoto and watched_user.jpegPhoto[0] %}
|
||||
<img class="ui avatar image" src="{{ url_for("account.photo", uid=watched_user.uid[0], field="jpegPhoto") }}" alt="User photo">
|
||||
<a href="{{ url_for('account.profile_edition', username=watched_user.user_name[0]) }}">
|
||||
{% if watched_user.photo and watched_user.photo[0] %}
|
||||
<img class="ui avatar image" src="{{ url_for("account.photo", user_name=watched_user.user_name[0], field="photo") }}" alt="User photo">
|
||||
{% else %}
|
||||
<i class="user circle big black icon"></i>
|
||||
{% endif %}
|
||||
</a>
|
||||
</td>
|
||||
{% endif %}
|
||||
{% if user.can_read("uid") %}
|
||||
<td><a href="{{ url_for('account.profile_edition', username=watched_user.uid[0]) }}">{{ watched_user.uid[0] }}</a></td>
|
||||
{% if user.can_read("user_name") %}
|
||||
<td><a href="{{ url_for('account.profile_edition', username=watched_user.user_name[0]) }}">{{ watched_user.user_name[0] }}</a></td>
|
||||
{% endif %}
|
||||
{% if user.can_read("sn") or user.can_read("givenName") %}
|
||||
{% if user.can_read("family_name") or user.can_read("given_name") %}
|
||||
<td>{{ watched_user.name }}</td>
|
||||
{% endif %}
|
||||
{% if user.can_read("mail") %}
|
||||
<td><a href="mailto:{{ watched_user.mail[0] }}">{{ watched_user.mail[0] }}</a></td>
|
||||
{% if user.can_read("email") %}
|
||||
<td><a href="mailto:{{ watched_user.email[0] }}">{{ watched_user.email[0] }}</a></td>
|
||||
{% endif %}
|
||||
{% if user.can_manage_groups %}
|
||||
<td>
|
||||
|
|
|
@ -30,33 +30,79 @@
|
|||
{% endblock %}
|
||||
|
||||
{% macro render_field(field, noindicator=false) %}
|
||||
{{ fui.render_field(field, **kwargs) }}
|
||||
{% set lock_indicator = field.render_kw and ("readonly" in field.render_kw or "disabled" in field.render_kw) %}
|
||||
{% if not edited_user %}
|
||||
{{ fui.render_field(field, **kwargs) }}
|
||||
{% elif edited_user.user_name == user.user_name or lock_indicator or noindicator %}
|
||||
{{ fui.render_field(field, **kwargs) }}
|
||||
{% elif field.name in edited_user.write %}
|
||||
{{ fui.render_field(field, **kwargs) }}
|
||||
{% elif field.name in edited_user.read %}
|
||||
{{ fui.render_field(field, indicator_icon="eye", indicator_text=_("This user cannot edit this field"), **kwargs) }}
|
||||
{% else %}
|
||||
{{ fui.render_field(field, indicator_icon="eye slash", indicator_text=_("This user cannot see this field"), **kwargs) }}
|
||||
{% endif %}
|
||||
{% endmacro %}
|
||||
|
||||
{% block content %}
|
||||
{% if self_deletion or (user.can_manage_users and edited_user) %}
|
||||
<div id="modal-delete" class="ui basic modal">
|
||||
<div class="ui icon header">
|
||||
<i class="user minus icon"></i>
|
||||
{% trans %}Account deletion{% endtrans %}
|
||||
</div>
|
||||
<div class="content">
|
||||
<p>
|
||||
{% if user.user_name != edited_user.user_name %}
|
||||
{{ _("Are you sure you want to delete this user? This action is unrevokable and all the data about this user will be removed.") }}
|
||||
{% else %}
|
||||
{{ _("Are you sure you want to delete your account? This action is unrevokable and all your data will be removed forever.") }}
|
||||
{% endif %}
|
||||
</p>
|
||||
</div>
|
||||
<div class="actions">
|
||||
<div class="ui inverted cancel button">{% trans %}Cancel{% endtrans %}</div>
|
||||
<div class="ui inverted red approve button">{% trans %}Delete{% endtrans %}</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="ui clearing segment">
|
||||
<h2 class="ui center aligned header">
|
||||
<div class="content">
|
||||
{% trans %}User creation{% endtrans %}
|
||||
{% if not edited_user %}
|
||||
{% trans %}User creation{% endtrans %}
|
||||
{% elif user.user_name == edited_user.user_name %}
|
||||
{% trans %}My profile{% endtrans %}
|
||||
{% else %}
|
||||
{% trans %}User profile edition{% endtrans %}
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
<div class="sub header">
|
||||
{% trans %}Create a new user account{% endtrans %}
|
||||
{% if not edited_user %}
|
||||
{% trans %}Create a new user account{% endtrans %}
|
||||
{% elif user.user_name == edited_user.user_name %}
|
||||
{% trans %}Edit your personal information{% endtrans %}
|
||||
{% else %}
|
||||
{% trans %}Edit information about a user{% endtrans %}
|
||||
{% endif %}
|
||||
</div>
|
||||
</h2>
|
||||
|
||||
{% call fui.render_form(form, class_="profile-form info") %}
|
||||
<h4 class="ui dividing header">{% trans %}Personal information{% endtrans %}</h4>
|
||||
|
||||
{% if "jpegPhoto" in form %}
|
||||
{% if "photo" in form %}
|
||||
<div class="ui grid">
|
||||
<div class="three wide column">
|
||||
{% block photo_field scoped %}
|
||||
{{ render_field(form.jpegPhoto, display=false, class="photo-field") }}
|
||||
{{ render_field(form.jpegPhoto_delete, display=false, class="photo-delete-button") }}
|
||||
{{ render_field(form.photo, display=false, class="photo-field") }}
|
||||
{{ render_field(form.photo_delete, display=false, class="photo-delete-button") }}
|
||||
{% set photo = edited_user.photo and edited_user.photo[0] %}
|
||||
<label
|
||||
class="ui small bordered image photo-content"
|
||||
for="{{ form.jpegPhoto.id }}"
|
||||
for="{{ form.photo.id }}"
|
||||
title="{{ _("Click to upload a photo") }}"
|
||||
style="display: none;">
|
||||
|
||||
|
@ -67,7 +113,7 @@
|
|||
</label>
|
||||
<label
|
||||
class="ui centered photo-placeholder"
|
||||
for="{{ form.jpegPhoto.id }}"
|
||||
for="{{ form.photo.id }}"
|
||||
title="{{ _("Click to upload a photo") }}"
|
||||
{% if photo %}style="display: none;"{% endif %}>
|
||||
<i class="massive centered portrait icon"></i>
|
||||
|
@ -78,34 +124,34 @@
|
|||
<div class="thirteen wide column">
|
||||
{% endif %}
|
||||
|
||||
{% if "givenName" in form or "sn" in form %}
|
||||
{% if "given_name" in form or "family_name" in form %}
|
||||
<div class="equal width fields">
|
||||
{% if "givenName" in form %}
|
||||
{% block given_name_field scoped %}{{ render_field(form.givenName) }}{% endblock %}
|
||||
{% if "given_name" in form %}
|
||||
{% block given_name_field scoped %}{{ render_field(form.given_name) }}{% endblock %}
|
||||
{% endif %}
|
||||
|
||||
{% if "sn" in form %}
|
||||
{% block sn_field scoped %}{{ render_field(form.sn) }}{% endblock %}
|
||||
{% if "family_name" in form %}
|
||||
{% block family_name_field scoped %}{{ render_field(form.family_name) }}{% endblock %}
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if "displayName" in form %}
|
||||
{% block display_name_field scoped %}{{ render_field(form.displayName) }}{% endblock %}
|
||||
{% if "display_name" in form %}
|
||||
{% block display_name_field scoped %}{{ render_field(form.display_name) }}{% endblock %}
|
||||
{% endif %}
|
||||
|
||||
{% if "jpegPhoto" in form %}</div></div>{% endif %}
|
||||
{% if "photo" in form %}</div></div>{% endif %}
|
||||
|
||||
{% if "mail" in form %}
|
||||
{% block mail_field scoped %}{{ render_field(form.mail) }}{% endblock %}
|
||||
{% if "email" in form %}
|
||||
{% block email_field scoped %}{{ render_field(form.email) }}{% endblock %}
|
||||
{% endif %}
|
||||
|
||||
{% if "telephoneNumber" in form %}
|
||||
{% block telephone_number_field scoped %}{{ render_field(form.telephoneNumber) }}{% endblock %}
|
||||
{% if "phone_number" in form %}
|
||||
{% block phone_number_field scoped %}{{ render_field(form.phone_number) }}{% endblock %}
|
||||
{% endif %}
|
||||
|
||||
{% if "postalAddress" in form %}
|
||||
{% block postal_address_field scoped %}{{ render_field(form.postalAddress) }}{% endblock %}
|
||||
{% if "formatted_address" in form %}
|
||||
{% block formatted_address_field scoped %}{{ render_field(form.formatted_address) }}{% endblock %}
|
||||
{% endif %}
|
||||
|
||||
{% if "street" in form %}
|
||||
|
@ -113,29 +159,28 @@
|
|||
{% endif %}
|
||||
|
||||
<div class="equal width fields">
|
||||
{% if "postalCode" in form %}
|
||||
{% block postal_code_field scoped %}{{ render_field(form.postalCode) }}{% endblock %}
|
||||
{% if "postal_code" in form %}
|
||||
{% block postal_code_field scoped %}{{ render_field(form.postal_code) }}{% endblock %}
|
||||
{% endif %}
|
||||
|
||||
{% if "l" in form %}
|
||||
{% block locality_field scoped %}{{ render_field(form.l) }}{% endblock %}
|
||||
{% if "locality" in form %}
|
||||
{% block locality_field scoped %}{{ render_field(form.locality) }}{% endblock %}
|
||||
{% endif %}
|
||||
|
||||
{% if "st" in form %}
|
||||
{% block region_field scoped %}{{ render_field(form.st) }}{% endblock %}
|
||||
{% if "region" in form %}
|
||||
{% block region_field scoped %}{{ render_field(form.region) }}{% endblock %}
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="equal width fields">
|
||||
|
||||
{% if "departmentNumber" in form %}
|
||||
{% block department_number_field scoped %}{{ render_field(form.departmentNumber) }}{% endblock %}
|
||||
{% if "department" in form %}
|
||||
{% block department_field scoped %}{{ render_field(form.department) }}{% endblock %}
|
||||
{% endif %}
|
||||
|
||||
{% if "employeeNumber" in form %}
|
||||
{% block employee_number_field scoped %}{{ render_field(form.employeeNumber) }}{% endblock %}
|
||||
{% if "employee_number" in form %}
|
||||
{% block employee_number_field scoped %}{{ render_field(form.employee_number) }}{% endblock %}
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
|
||||
<div class="equal width fields">
|
||||
|
@ -144,24 +189,24 @@
|
|||
{% block title_field scoped %}{{ render_field(form.title) }}{% endblock %}
|
||||
{% endif %}
|
||||
|
||||
{% if "o" in form %}
|
||||
{% block organization_field scoped %}{{ render_field(form.o) }}{% endblock %}
|
||||
{% if "organization" in form %}
|
||||
{% block organization_field scoped %}{{ render_field(form.organization) }}{% endblock %}
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
|
||||
{% if "labeledURI" in form %}
|
||||
{% block labeled_uri_field scoped %}{{ render_field(form.labeledURI) }}{% endblock %}
|
||||
{% if "profile_url" in form %}
|
||||
{% block profile_uri_field scoped %}{{ render_field(form.profile_url) }}{% endblock %}
|
||||
{% endif %}
|
||||
|
||||
{% if "preferredLanguage" in form %}
|
||||
{% block preferred_language_field scoped %}{{ render_field(form.preferredLanguage) }}{% endblock %}
|
||||
{% if "preferred_language" in form %}
|
||||
{% block preferred_language_field scoped %}{{ render_field(form.preferred_language) }}{% endblock %}
|
||||
{% endif %}
|
||||
|
||||
<h4 class="ui dividing header">{% trans %}Account information{% endtrans %}</h4>
|
||||
|
||||
{% if "uid" in form %}
|
||||
{% block uid_field scoped %}{{ render_field(form.uid) }}{% endblock %}
|
||||
{% if "user_name" in form %}
|
||||
{% block user_name_field scoped %}{{ render_field(form.user_name) }}{% endblock %}
|
||||
{% endif %}
|
||||
|
||||
{% if "groups" in form %}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
{%- block title -%}
|
||||
{% if not edited_user %}
|
||||
{%- trans %}User creation{% endtrans -%}
|
||||
{% elif user.uid == edited_user.uid %}
|
||||
{% elif user.user_name == edited_user.user_name %}
|
||||
{%- trans %}My profile{% endtrans -%}
|
||||
{% else %}
|
||||
{%- trans %}User profile edition{% endtrans -%}
|
||||
|
@ -18,11 +18,11 @@
|
|||
|
||||
{% block submenu %}
|
||||
<nav class="ui bottom attached two item borderless menu">
|
||||
<a class="active item" href="{{ url_for('account.profile_edition', username=edited_user.uid[0]) }}">
|
||||
<a class="active item" href="{{ url_for('account.profile_edition', username=edited_user.user_name[0]) }}">
|
||||
<i class="id card icon"></i>
|
||||
{% trans %}Personal information{% endtrans %}
|
||||
</a>
|
||||
<a class="item" href="{{ url_for('account.profile_settings', username=edited_user.uid[0]) }}">
|
||||
<a class="item" href="{{ url_for('account.profile_settings', username=edited_user.user_name[0]) }}">
|
||||
<i class="tools icon"></i>
|
||||
{% trans %}Account information{% endtrans %}
|
||||
</a>
|
||||
|
@ -33,7 +33,7 @@
|
|||
{% set lock_indicator = field.render_kw and ("readonly" in field.render_kw or "disabled" in field.render_kw) %}
|
||||
{% if not edited_user %}
|
||||
{{ fui.render_field(field, **kwargs) }}
|
||||
{% elif edited_user.uid == user.uid or lock_indicator or noindicator %}
|
||||
{% elif edited_user.user_name == user.user_name or lock_indicator or noindicator %}
|
||||
{{ fui.render_field(field, **kwargs) }}
|
||||
{% elif field.name in edited_user.write %}
|
||||
{{ fui.render_field(field, **kwargs) }}
|
||||
|
@ -48,7 +48,7 @@
|
|||
<div class="ui clearing segment">
|
||||
<h2 class="ui center aligned header">
|
||||
<div class="content">
|
||||
{% if user.uid == edited_user.uid %}
|
||||
{% if user.user_name == edited_user.user_name %}
|
||||
{% trans %}My profile{% endtrans %}
|
||||
{% else %}
|
||||
{% trans %}User profile edition{% endtrans %}
|
||||
|
@ -56,7 +56,7 @@
|
|||
|
||||
</div>
|
||||
<div class="sub header">
|
||||
{% if user.uid == edited_user.uid %}
|
||||
{% if user.user_name == edited_user.user_name %}
|
||||
{% trans %}Edit your personal information{% endtrans %}
|
||||
{% else %}
|
||||
{% trans %}Edit information about a user{% endtrans %}
|
||||
|
@ -65,27 +65,27 @@
|
|||
</h2>
|
||||
|
||||
{% call fui.render_form(form) %}
|
||||
{% if "jpegPhoto" in form %}
|
||||
{% if "photo" in form %}
|
||||
<div class="ui grid">
|
||||
<div class="three wide column">
|
||||
{% block photo_field scoped %}
|
||||
{{ render_field(form.jpegPhoto, display=false, class="photo-field") }}
|
||||
{{ render_field(form.jpegPhoto_delete, display=false, class="photo-delete-button") }}
|
||||
{% set photo = edited_user.jpegPhoto and edited_user.jpegPhoto[0] %}
|
||||
{{ render_field(form.photo, display=false, class="photo-field") }}
|
||||
{{ render_field(form.photo_delete, display=false, class="photo-delete-button") }}
|
||||
{% set photo = edited_user.photo and edited_user.photo[0] %}
|
||||
<label
|
||||
class="ui small bordered image photo-content"
|
||||
for="{{ form.jpegPhoto.id }}"
|
||||
for="{{ form.photo.id }}"
|
||||
title="{{ _("Click to upload a photo") }}"
|
||||
{% if not photo %}style="display: none;"{% endif %}>
|
||||
|
||||
<a class="ui right corner label photo-delete-icon" title="{{ _("Delete the photo") }}">
|
||||
<i class="times icon"></i>
|
||||
</a>
|
||||
<img src="{% if photo %}{{ url_for("account.photo", uid=edited_user.uid[0], field="jpegPhoto") }}{% endif %}" alt="User photo">
|
||||
<img src="{% if photo %}{{ url_for("account.photo", user_name=edited_user.user_name[0], field="photo") }}{% endif %}" alt="User photo">
|
||||
</label>
|
||||
<label
|
||||
class="ui centered photo-placeholder"
|
||||
for="{{ form.jpegPhoto.id }}"
|
||||
for="{{ form.photo.id }}"
|
||||
title="{{ _("Click to upload a photo") }}"
|
||||
{% if photo %}style="display: none;"{% endif %}>
|
||||
<i class="massive centered portrait icon"></i>
|
||||
|
@ -96,34 +96,34 @@
|
|||
<div class="thirteen wide column">
|
||||
{% endif %}
|
||||
|
||||
{% if "givenName" in form or "sn" in form %}
|
||||
{% if "given_name" in form or "family_name" in form %}
|
||||
<div class="equal width fields">
|
||||
{% if "givenName" in form %}
|
||||
{% block given_name_field scoped %}{{ render_field(form.givenName) }}{% endblock %}
|
||||
{% if "given_name" in form %}
|
||||
{% block given_name_field scoped %}{{ render_field(form.given_name) }}{% endblock %}
|
||||
{% endif %}
|
||||
|
||||
{% if "sn" in form %}
|
||||
{% block sn_field scoped %}{{ render_field(form.sn) }}{% endblock %}
|
||||
{% if "family_name" in form %}
|
||||
{% block sn_field scoped %}{{ render_field(form.family_name) }}{% endblock %}
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if "displayName" in form %}
|
||||
{% block display_name_field scoped %}{{ render_field(form.displayName) }}{% endblock %}
|
||||
{% if "display_name" in form %}
|
||||
{% block display_name_field scoped %}{{ render_field(form.display_name) }}{% endblock %}
|
||||
{% endif %}
|
||||
|
||||
{% if "jpegPhoto" in form %}</div></div>{% endif %}
|
||||
{% if "photo" in form %}</div></div>{% endif %}
|
||||
|
||||
{% if "mail" in form %}
|
||||
{% block mail_field scoped %}{{ render_field(form.mail) }}{% endblock %}
|
||||
{% if "email" in form %}
|
||||
{% block email_field scoped %}{{ render_field(form.email) }}{% endblock %}
|
||||
{% endif %}
|
||||
|
||||
{% if "telephoneNumber" in form %}
|
||||
{% block telephone_number_field scoped %}{{ render_field(form.telephoneNumber) }}{% endblock %}
|
||||
{% if "phone_number" in form %}
|
||||
{% block phone_number_field scoped %}{{ render_field(form.phone_number) }}{% endblock %}
|
||||
{% endif %}
|
||||
|
||||
{% if "postalAddress" in form %}
|
||||
{% block postal_address_field scoped %}{{ render_field(form.postalAddress) }}{% endblock %}
|
||||
{% if "formatted_address" in form %}
|
||||
{% block formatted_address_field scoped %}{{ render_field(form.formatted_address) }}{% endblock %}
|
||||
{% endif %}
|
||||
|
||||
{% if "street" in form %}
|
||||
|
@ -131,27 +131,27 @@
|
|||
{% endif %}
|
||||
|
||||
<div class="equal width fields">
|
||||
{% if "postalCode" in form %}
|
||||
{% block postal_code_field scoped %}{{ render_field(form.postalCode) }}{% endblock %}
|
||||
{% if "postal_code" in form %}
|
||||
{% block postal_code_field scoped %}{{ render_field(form.postal_code) }}{% endblock %}
|
||||
{% endif %}
|
||||
|
||||
{% if "l" in form %}
|
||||
{% block locality_field scoped %}{{ render_field(form.l) }}{% endblock %}
|
||||
{% if "locality" in form %}
|
||||
{% block locality_field scoped %}{{ render_field(form.locality) }}{% endblock %}
|
||||
{% endif %}
|
||||
|
||||
{% if "st" in form %}
|
||||
{% block region_field scoped %}{{ render_field(form.st) }}{% endblock %}
|
||||
{% if "region" in form %}
|
||||
{% block region_field scoped %}{{ render_field(form.region) }}{% endblock %}
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="equal width fields">
|
||||
|
||||
{% if "departmentNumber" in form %}
|
||||
{% block department_number_field scoped %}{{ render_field(form.departmentNumber) }}{% endblock %}
|
||||
{% if "department" in form %}
|
||||
{% block department_number_field scoped %}{{ render_field(form.department) }}{% endblock %}
|
||||
{% endif %}
|
||||
|
||||
{% if "employeeNumber" in form %}
|
||||
{% block employee_number_field scoped %}{{ render_field(form.employeeNumber) }}{% endblock %}
|
||||
{% if "employee_number" in form %}
|
||||
{% block employee_number_field scoped %}{{ render_field(form.employee_number) }}{% endblock %}
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
|
@ -161,18 +161,18 @@
|
|||
{% block title_field scoped %}{{ render_field(form.title) }}{% endblock %}
|
||||
{% endif %}
|
||||
|
||||
{% if "o" in form %}
|
||||
{% block organization_field scoped %}{{ render_field(form.o) }}{% endblock %}
|
||||
{% if "organization" in form %}
|
||||
{% block organization_field scoped %}{{ render_field(form.organization) }}{% endblock %}
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
|
||||
{% if "labeledURI" in form %}
|
||||
{% block labeled_uri_field scoped %}{{ render_field(form.labeledURI) }}{% endblock %}
|
||||
{% if "profile_url" in form %}
|
||||
{% block profile_url_field scoped %}{{ render_field(form.profile_url) }}{% endblock %}
|
||||
{% endif %}
|
||||
|
||||
{% if "preferredLanguage" in form %}
|
||||
{% block preferred_language_field scoped %}{{ render_field(form.preferredLanguage) }}{% endblock %}
|
||||
{% if "preferred_language" in form %}
|
||||
{% block preferred_language_field scoped %}{{ render_field(form.preferred_language) }}{% endblock %}
|
||||
{% endif %}
|
||||
|
||||
<div class="ui right aligned container">
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
{% import 'macro/form.html' as fui %}
|
||||
|
||||
{%- block title -%}
|
||||
{% if user.uid == edited_user.uid %}
|
||||
{% if user.user_name == edited_user.user_name %}
|
||||
{%- trans %}My profile{% endtrans -%}
|
||||
{% else %}
|
||||
{%- trans %}User profile edition{% endtrans -%}
|
||||
|
@ -16,11 +16,11 @@
|
|||
|
||||
{% block submenu %}
|
||||
<nav class="ui bottom attached two item borderless menu">
|
||||
<a class="item" href="{{ url_for('account.profile_edition', username=edited_user.uid[0]) }}">
|
||||
<a class="item" href="{{ url_for('account.profile_edition', username=edited_user.user_name[0]) }}">
|
||||
<i class="id card icon"></i>
|
||||
{% trans %}Personal information{% endtrans %}
|
||||
</a>
|
||||
<a class="active item" href="{{ url_for('account.profile_settings', username=edited_user.uid[0]) }}">
|
||||
<a class="active item" href="{{ url_for('account.profile_settings', username=edited_user.user_name[0]) }}">
|
||||
<i class="tools icon"></i>
|
||||
{% trans %}Account information{% endtrans %}
|
||||
</a>
|
||||
|
@ -29,7 +29,7 @@
|
|||
|
||||
{% macro render_field(field, noindicator=false) %}
|
||||
{% set lock_indicator = field.render_kw and ("readonly" in field.render_kw or "disabled" in field.render_kw) %}
|
||||
{% if edited_user.uid == user.uid or lock_indicator or noindicator %}
|
||||
{% if edited_user.user_name == user.user_name or lock_indicator or noindicator %}
|
||||
{{ fui.render_field(field, **kwargs) }}
|
||||
{% elif field.name in edited_user.write %}
|
||||
{{ fui.render_field(field, **kwargs) }}
|
||||
|
@ -49,7 +49,7 @@
|
|||
</div>
|
||||
<div class="content">
|
||||
<p>
|
||||
{% if user.uid != edited_user.uid %}
|
||||
{% if user.user_name != edited_user.user_name %}
|
||||
{{ _("Are you sure you want to delete this user? This action is unrevokable and all the data about this user will be removed.") }}
|
||||
{% else %}
|
||||
{{ _("Are you sure you want to delete your account? This action is unrevokable and all your data will be removed forever.") }}
|
||||
|
@ -71,8 +71,8 @@
|
|||
</h2>
|
||||
|
||||
{% call fui.render_form(form, class_="profile-form info warning") %}
|
||||
{% if "uid" in form %}
|
||||
{% block uid_field scoped %}{{ render_field(form.uid) }}{% endblock %}
|
||||
{% if "user_name" in form %}
|
||||
{% block user_name_field scoped %}{{ render_field(form.user_name) }}{% endblock %}
|
||||
{% endif %}
|
||||
|
||||
{% if "groups" in form %}
|
||||
|
@ -113,7 +113,7 @@
|
|||
{% endif %}
|
||||
</div>
|
||||
|
||||
{% elif has_smtp and edited_user.uid != user.uid and edited_user.has_password() and edited_user.can_edit_self %}
|
||||
{% elif has_smtp and edited_user.user_name != user.user_name and edited_user.has_password() and edited_user.can_edit_self %}
|
||||
|
||||
<div class="ui message info">
|
||||
<button type="submit" name="action" value="password-reset-mail" class="ui right floated button">
|
||||
|
@ -133,7 +133,7 @@
|
|||
<div class="ui stackable buttons">
|
||||
{% if user.can_manage_users or self_deletion %}
|
||||
<button type="submit" class="ui right floated basic negative button confirm" name="action" value="delete" id="delete">
|
||||
{% if user.uid != edited_user.uid %}
|
||||
{% if user.user_name != edited_user.user_name %}
|
||||
{{ _("Delete the user") }}
|
||||
{% else %}
|
||||
{{ _("Delete my account") }}
|
||||
|
@ -141,8 +141,8 @@
|
|||
</button>
|
||||
{% endif %}
|
||||
|
||||
{% if user.can_impersonate_users and user.uid != edited_user.uid %}
|
||||
<a href="{{ url_for('account.impersonate', username=edited_user.uid[0]) }}" class="ui right floated basic button" name="action" value="impersonate" id="impersonate">
|
||||
{% if user.can_impersonate_users and user.user_name != edited_user.user_name %}
|
||||
<a href="{{ url_for('account.impersonate', username=edited_user.user_name[0]) }}" class="ui right floated basic button" name="action" value="impersonate" id="impersonate">
|
||||
{{ _("Impersonate") }}
|
||||
</a>
|
||||
{% endif %}
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
</h3>
|
||||
|
||||
<div class="ui attached clearing segment">
|
||||
{{ fui.render_form(form, _("Password reset"), action=url_for("account.reset", uid=uid, hash=hash)) }}
|
||||
{{ fui.render_form(form, _("Password reset"), action=url_for("account.reset", user_name=user_name, hash=hash)) }}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
|
|
@ -94,10 +94,10 @@
|
|||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if user.locale %}
|
||||
{% if user.preferred_language %}
|
||||
<div class="extra content">
|
||||
<i class="flag icon" title="locale"></i>
|
||||
{{ user.locale }}
|
||||
<i class="flag icon" title="preferred_language"></i>
|
||||
{{ user.preferred_language }}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
|
|
|
@ -131,26 +131,26 @@ GROUP_BASE = "ou=groups,dc=mydomain,dc=tld"
|
|||
# object that users will be able to read and/or write.
|
||||
[ACL.DEFAULT]
|
||||
PERMISSIONS = ["edit_self", "use_oidc"]
|
||||
READ = ["uid", "groups"]
|
||||
READ = ["user_name", "groups"]
|
||||
WRITE = [
|
||||
"jpegPhoto",
|
||||
"givenName",
|
||||
"sn",
|
||||
"displayName",
|
||||
"userPassword",
|
||||
"telephoneNumber",
|
||||
"mail",
|
||||
"labeledURI",
|
||||
"postalAddress",
|
||||
"photo",
|
||||
"given_name",
|
||||
"family_name",
|
||||
"display_name",
|
||||
"password",
|
||||
"phone_number",
|
||||
"email",
|
||||
"profile_url",
|
||||
"formatted_address",
|
||||
"street",
|
||||
"postalCode",
|
||||
"l",
|
||||
"st",
|
||||
"preferredLanguage",
|
||||
"employeeNumber",
|
||||
"departmentNumber",
|
||||
"postal_code",
|
||||
"locality",
|
||||
"region",
|
||||
"preferred_language",
|
||||
"employee_number",
|
||||
"department",
|
||||
"title",
|
||||
"o",
|
||||
"organization",
|
||||
]
|
||||
|
||||
[ACL.ADMIN]
|
||||
|
@ -191,17 +191,17 @@ PUBLIC_KEY = "conf/public.pem"
|
|||
# User objectClass.
|
||||
# {attribute} will be replaced by the user ldap attribute value.
|
||||
# Default values fits inetOrgPerson.
|
||||
SUB = "{{ user.uid[0] }}"
|
||||
NAME = "{{ user.cn[0] }}"
|
||||
PHONE_NUMBER = "{{ user.telephoneNumber[0] }}"
|
||||
EMAIL = "{{ user.mail[0] }}"
|
||||
GIVEN_NAME = "{{ user.givenName[0] }}"
|
||||
FAMILY_NAME = "{{ user.sn[0] }}"
|
||||
PREFERRED_USERNAME = "{{ user.displayName }}"
|
||||
LOCALE = "{{ user.preferredLanguage }}"
|
||||
ADDRESS = "{{ user.postalAddress[0] }}"
|
||||
PICTURE = "{% if user.jpegPhoto %}{{ url_for('account.photo', uid=user.uid[0], field='jpegPhoto', _external=True) }}{% endif %}"
|
||||
WEBSITE = "{{ user.labeledURI[0] }}"
|
||||
SUB = "{{ user.user_name[0] }}"
|
||||
NAME = "{{ user.formatted_name[0] }}"
|
||||
PHONE_NUMBER = "{{ user.phone_number[0] }}"
|
||||
EMAIL = "{{ user.email[0] }}"
|
||||
GIVEN_NAME = "{{ user.given_name[0] }}"
|
||||
FAMILY_NAME = "{{ user.family_name[0] }}"
|
||||
PREFERRED_USERNAME = "{{ user.display_name }}"
|
||||
LOCALE = "{{ user.preferred_language }}"
|
||||
ADDRESS = "{{ user.formatted_address[0] }}"
|
||||
PICTURE = "{% if user.photo %}{{ url_for('account.photo', user_name=user.user_name[0], field='photo', _external=True) }}{% endif %}"
|
||||
WEBSITE = "{{ user.profile_url[0] }}"
|
||||
|
||||
# The SMTP server options. If not set, mail related features such as
|
||||
# user invitations, and password reset emails, will be disabled.
|
||||
|
|
|
@ -131,26 +131,26 @@ GROUP_BASE = "ou=groups,dc=mydomain,dc=tld"
|
|||
# object that users will be able to read and/or write.
|
||||
[ACL.DEFAULT]
|
||||
PERMISSIONS = ["edit_self", "use_oidc"]
|
||||
READ = ["uid", "groups"]
|
||||
READ = ["user_name", "groups"]
|
||||
WRITE = [
|
||||
"jpegPhoto",
|
||||
"givenName",
|
||||
"sn",
|
||||
"displayName",
|
||||
"userPassword",
|
||||
"telephoneNumber",
|
||||
"mail",
|
||||
"labeledURI",
|
||||
"postalAddress",
|
||||
"photo",
|
||||
"given_name",
|
||||
"family_name",
|
||||
"display_name",
|
||||
"password",
|
||||
"phone_number",
|
||||
"email",
|
||||
"profile_url",
|
||||
"formatted_address",
|
||||
"street",
|
||||
"postalCode",
|
||||
"l",
|
||||
"st",
|
||||
"preferredLanguage",
|
||||
"employeeNumber",
|
||||
"departmentNumber",
|
||||
"postal_code",
|
||||
"locality",
|
||||
"region",
|
||||
"preferred_language",
|
||||
"employee_number",
|
||||
"department",
|
||||
"title",
|
||||
"o",
|
||||
"organization",
|
||||
]
|
||||
|
||||
[ACL.ADMIN]
|
||||
|
@ -191,17 +191,17 @@ PUBLIC_KEY = "conf/public.pem"
|
|||
# User objectClass.
|
||||
# {attribute} will be replaced by the user ldap attribute value.
|
||||
# Default values fits inetOrgPerson.
|
||||
SUB = "{{ user.uid[0] }}"
|
||||
NAME = "{{ user.cn[0] }}"
|
||||
PHONE_NUMBER = "{{ user.telephoneNumber[0] }}"
|
||||
EMAIL = "{{ user.mail[0] }}"
|
||||
GIVEN_NAME = "{{ user.givenName[0] }}"
|
||||
FAMILY_NAME = "{{ user.sn[0] }}"
|
||||
PREFERRED_USERNAME = "{{ user.displayName }}"
|
||||
LOCALE = "{{ user.preferredLanguage }}"
|
||||
ADDRESS = "{{ user.postalAddress[0] }}"
|
||||
PICTURE = "{% if user.jpegPhoto %}{{ url_for('account.photo', uid=user.uid[0], field='jpegPhoto', _external=True) }}{% endif %}"
|
||||
WEBSITE = "{{ user.labeledURI[0] }}"
|
||||
SUB = "{{ user.user_name[0] }}"
|
||||
NAME = "{{ user.formatted_name[0] }}"
|
||||
PHONE_NUMBER = "{{ user.phone_number[0] }}"
|
||||
EMAIL = "{{ user.email[0] }}"
|
||||
GIVEN_NAME = "{{ user.given_name[0] }}"
|
||||
FAMILY_NAME = "{{ user.family_name[0] }}"
|
||||
PREFERRED_USERNAME = "{{ user.display_name }}"
|
||||
LOCALE = "{{ user.preferred_language }}"
|
||||
ADDRESS = "{{ user.formatted_address[0] }}"
|
||||
PICTURE = "{% if user.photo %}{{ url_for('account.photo', user_name=user.user_name[0], field='photo', _external=True) }}{% endif %}"
|
||||
WEBSITE = "{{ user.profile_url[0] }}"
|
||||
|
||||
# The SMTP server options. If not set, mail related features such as
|
||||
# user invitations, and password reset emails, will be disabled.
|
||||
|
|
|
@ -196,37 +196,37 @@ A mapping where keys are JWT claims, and values are LDAP user object attributes.
|
|||
Attributes are rendered using jinja2, and can use a ``user`` variable.
|
||||
|
||||
:SUB:
|
||||
*Optional.* Defaults to ``{{ user.uid[0] }}``
|
||||
*Optional.* Defaults to ``{{ user.user_name[0] }}``
|
||||
|
||||
:NAME:
|
||||
*Optional.* Defaults to ``{{ user.cn[0] }}``
|
||||
|
||||
:PHONE_NUMBER:
|
||||
*Optional.* Defaults to ``{{ user.telephoneNumber[0] }}``
|
||||
*Optional.* Defaults to ``{{ user.phone_number[0] }}``
|
||||
|
||||
:EMAIL:
|
||||
*Optional.* Defaults to ``{{ user.mail[0] }}``
|
||||
|
||||
:GIVEN_NAME:
|
||||
*Optional.* Defaults to ``{{ user.givenName[0] }}``
|
||||
*Optional.* Defaults to ``{{ user.given_name[0] }}``
|
||||
|
||||
:FAMILY_NAME:
|
||||
*Optional.* Defaults to ``{{ user.sn[0] }}``
|
||||
*Optional.* Defaults to ``{{ user.family_name[0] }}``
|
||||
|
||||
:PREFERRED_USERNAME:
|
||||
*Optional.* Defaults to ``{{ user.displayName[0] }}``
|
||||
*Optional.* Defaults to ``{{ user.display_name[0] }}``
|
||||
|
||||
:LOCALE:
|
||||
*Optional.* Defaults to ``{{ user.preferredLanguage }}``
|
||||
*Optional.* Defaults to ``{{ user.locale }}``
|
||||
|
||||
:ADDRESS:
|
||||
*Optional.* Defaults to ``{{ user.postalAddress[0] }}``
|
||||
*Optional.* Defaults to ``{{ user.address[0] }}``
|
||||
|
||||
:PICTURE:
|
||||
*Optional.* Defaults to ``{% if user.jpegPhoto %}{{ url_for('account.photo', uid=user.uid[0], field='jpegPhoto', _external=True) }}{% endif %}``
|
||||
*Optional.* Defaults to ``{% if user.photo %}{{ url_for('account.photo', user_name=user.user_name[0], field='photo', _external=True) }}{% endif %}``
|
||||
|
||||
:WEBSITE:
|
||||
*Optional.* Defaults to ``{{ user.labeledURI[0] }}``
|
||||
*Optional.* Defaults to ``{{ user.profile_url[0] }}``
|
||||
|
||||
|
||||
SMTP
|
||||
|
|
|
@ -91,26 +91,26 @@ def configuration(slapd_server, smtpd):
|
|||
},
|
||||
"ACL": {
|
||||
"DEFAULT": {
|
||||
"READ": ["uid", "groups"],
|
||||
"READ": ["user_name", "groups"],
|
||||
"PERMISSIONS": ["edit_self", "use_oidc"],
|
||||
"WRITE": [
|
||||
"mail",
|
||||
"givenName",
|
||||
"jpegPhoto",
|
||||
"sn",
|
||||
"displayName",
|
||||
"userPassword",
|
||||
"telephoneNumber",
|
||||
"postalAddress",
|
||||
"email",
|
||||
"given_name",
|
||||
"photo",
|
||||
"family_name",
|
||||
"display_name",
|
||||
"password",
|
||||
"phone_number",
|
||||
"formatted_address",
|
||||
"street",
|
||||
"postalCode",
|
||||
"l",
|
||||
"st",
|
||||
"employeeNumber",
|
||||
"preferredLanguage",
|
||||
"departmentNumber",
|
||||
"postal_code",
|
||||
"locality",
|
||||
"region",
|
||||
"employee_number",
|
||||
"department",
|
||||
"preferred_language",
|
||||
"title",
|
||||
"o",
|
||||
"organization",
|
||||
],
|
||||
},
|
||||
"ADMIN": {
|
||||
|
@ -164,17 +164,17 @@ def testclient(app):
|
|||
@pytest.fixture
|
||||
def user(app, slapd_connection):
|
||||
u = User(
|
||||
cn="John (johnny) Doe",
|
||||
givenName="John",
|
||||
sn="Doe",
|
||||
uid="user",
|
||||
mail="john@doe.com",
|
||||
userPassword="{SSHA}fw9DYeF/gHTHuVMepsQzVYAkffGcU8Fz",
|
||||
displayName="Johnny",
|
||||
preferredLanguage="en",
|
||||
telephoneNumber="555-000-000",
|
||||
labeledURI="https://john.example",
|
||||
postalAddress="1235, somewhere",
|
||||
formatted_name="John (johnny) Doe",
|
||||
given_name="John",
|
||||
family_name="Doe",
|
||||
user_name="user",
|
||||
email="john@doe.com",
|
||||
password="{SSHA}fw9DYeF/gHTHuVMepsQzVYAkffGcU8Fz",
|
||||
display_name="Johnny",
|
||||
preferred_language="en",
|
||||
phone_number="555-000-000",
|
||||
profile_url="https://john.example",
|
||||
formatted_address="1235, somewhere",
|
||||
)
|
||||
u.save()
|
||||
yield u
|
||||
|
@ -184,11 +184,11 @@ def user(app, slapd_connection):
|
|||
@pytest.fixture
|
||||
def admin(app, slapd_connection):
|
||||
u = User(
|
||||
cn="Jane Doe",
|
||||
sn="Doe",
|
||||
uid="admin",
|
||||
mail="jane@doe.com",
|
||||
userPassword="{SSHA}Vmgh2jkD0idX3eZHf8RzGos31oerjGiU",
|
||||
formatted_name="Jane Doe",
|
||||
family_name="Doe",
|
||||
user_name="admin",
|
||||
email="jane@doe.com",
|
||||
password="{SSHA}Vmgh2jkD0idX3eZHf8RzGos31oerjGiU",
|
||||
)
|
||||
u.save()
|
||||
yield u
|
||||
|
@ -198,11 +198,11 @@ def admin(app, slapd_connection):
|
|||
@pytest.fixture
|
||||
def moderator(app, slapd_connection):
|
||||
u = User(
|
||||
cn="Jack Doe",
|
||||
sn="Doe",
|
||||
uid="moderator",
|
||||
mail="jack@doe.com",
|
||||
userPassword="{SSHA}+eHyxWqajMHsOWnhONC2vbtfNZzKTkag",
|
||||
formatted_name="Jack Doe",
|
||||
family_name="Doe",
|
||||
user_name="moderator",
|
||||
email="jack@doe.com",
|
||||
password="{SSHA}+eHyxWqajMHsOWnhONC2vbtfNZzKTkag",
|
||||
)
|
||||
u.save()
|
||||
yield u
|
||||
|
|
2
tests/fixtures/themes/test/base.html
vendored
2
tests/fixtures/themes/test/base.html
vendored
|
@ -34,7 +34,7 @@
|
|||
</div>
|
||||
{% endif %}
|
||||
<a class="item {% if menuitem == "profile" %}active{% endif %}"
|
||||
href="{{ url_for('account.profile_edition', username=user.uid[0]) }}">
|
||||
href="{{ url_for('account.profile_edition', username=user.user_name[0]) }}">
|
||||
<i class="id card icon"></i>
|
||||
{% trans %}My profile{% endtrans %}
|
||||
</a>
|
||||
|
|
|
@ -14,10 +14,10 @@ from canaille.models import User
|
|||
def test_object_creation(slapd_connection):
|
||||
User.initialize(slapd_connection)
|
||||
user = User(
|
||||
cn="Doe", # leading space
|
||||
sn="Doe",
|
||||
uid="user",
|
||||
mail="john@doe.com",
|
||||
formatted_name="Doe", # leading space
|
||||
family_name="Doe",
|
||||
user_name="user",
|
||||
email="john@doe.com",
|
||||
)
|
||||
assert not user.exists
|
||||
user.save()
|
||||
|
@ -31,7 +31,7 @@ def test_object_creation(slapd_connection):
|
|||
|
||||
def test_repr(slapd_connection, foo_group, user):
|
||||
assert repr(foo_group) == "<Group display_name=foo>"
|
||||
assert repr(user) == "<User cn=John (johnny) Doe>"
|
||||
assert repr(user) == "<User formatted_name=John (johnny) Doe>"
|
||||
|
||||
|
||||
def test_equality(slapd_connection, foo_group, bar_group):
|
||||
|
@ -43,10 +43,10 @@ def test_equality(slapd_connection, foo_group, bar_group):
|
|||
def test_dn_when_leading_space_in_id_attribute(slapd_connection):
|
||||
User.initialize(slapd_connection)
|
||||
user = User(
|
||||
cn=" Doe", # leading space
|
||||
sn="Doe",
|
||||
uid="user",
|
||||
mail="john@doe.com",
|
||||
formatted_name=" Doe", # leading space
|
||||
family_name="Doe",
|
||||
user_name="user",
|
||||
email="john@doe.com",
|
||||
)
|
||||
user.save()
|
||||
|
||||
|
@ -60,10 +60,10 @@ def test_dn_when_leading_space_in_id_attribute(slapd_connection):
|
|||
def test_dn_when_ldap_special_char_in_id_attribute(slapd_connection):
|
||||
User.initialize(slapd_connection)
|
||||
user = User(
|
||||
cn="#Doe", # special char
|
||||
sn="Doe",
|
||||
uid="user",
|
||||
mail="john@doe.com",
|
||||
formatted_name="#Doe", # special char
|
||||
family_name="Doe",
|
||||
user_name="user",
|
||||
email="john@doe.com",
|
||||
)
|
||||
user.save()
|
||||
|
||||
|
|
|
@ -63,17 +63,17 @@ def configuration(configuration, keypair_path):
|
|||
"PRIVATE_KEY": private_key_path,
|
||||
"ISS": "https://auth.mydomain.tld",
|
||||
"MAPPING": {
|
||||
"SUB": "{{ user.uid[0] }}",
|
||||
"SUB": "{{ user.user_name[0] }}",
|
||||
"NAME": "{{ user.cn[0] }}",
|
||||
"PHONE_NUMBER": "{{ user.telephoneNumber[0] }}",
|
||||
"EMAIL": "{{ user.mail[0] }}",
|
||||
"GIVEN_NAME": "{{ user.givenName[0] }}",
|
||||
"FAMILY_NAME": "{{ user.sn[0] }}",
|
||||
"PREFERRED_USERNAME": "{{ user.displayName }}",
|
||||
"LOCALE": "{{ user.preferredLanguage }}",
|
||||
"PICTURE": "{% if user.jpegPhoto %}{{ url_for('account.photo', uid=user.uid[0], field='jpegPhoto', _external=True) }}{% endif %}",
|
||||
"ADDRESS": "{{ user.postalAddress[0] }}",
|
||||
"WEBSITE": "{{ user.labeledURI[0] }}",
|
||||
"PHONE_NUMBER": "{{ user.phone_number[0] }}",
|
||||
"EMAIL": "{{ user.email[0] }}",
|
||||
"GIVEN_NAME": "{{ user.given_name[0] }}",
|
||||
"FAMILY_NAME": "{{ user.family_name[0] }}",
|
||||
"PREFERRED_USERNAME": "{{ user.display_name }}",
|
||||
"LOCALE": "{{ user.preferred_language }}",
|
||||
"PICTURE": "{% if user.photo %}{{ url_for('account.photo', user_name=user.user_name[0], field='photo', _external=True) }}{% endif %}",
|
||||
"ADDRESS": "{{ user.formatted_address[0] }}",
|
||||
"WEBSITE": "{{ user.profile_url[0] }}",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
|
@ -82,14 +82,14 @@ def test_authorization_code_flow(
|
|||
"phone",
|
||||
}
|
||||
claims = jwt.decode(access_token, keypair[1])
|
||||
assert claims["sub"] == logged_user.uid[0]
|
||||
assert claims["name"] == logged_user.cn[0]
|
||||
assert claims["sub"] == logged_user.user_name[0]
|
||||
assert claims["name"] == logged_user.formatted_name[0]
|
||||
assert claims["aud"] == [client.client_id, other_client.client_id]
|
||||
|
||||
id_token = res.json["id_token"]
|
||||
claims = jwt.decode(id_token, keypair[1])
|
||||
assert claims["sub"] == logged_user.uid[0]
|
||||
assert claims["name"] == logged_user.cn[0]
|
||||
assert claims["sub"] == logged_user.user_name[0]
|
||||
assert claims["name"] == logged_user.formatted_name[0]
|
||||
assert claims["aud"] == [client.client_id, other_client.client_id]
|
||||
|
||||
res = testclient.get(
|
||||
|
@ -210,8 +210,8 @@ def test_authorization_code_flow_preconsented(
|
|||
|
||||
id_token = res.json["id_token"]
|
||||
claims = jwt.decode(id_token, keypair[1])
|
||||
assert logged_user.uid[0] == claims["sub"]
|
||||
assert logged_user.cn[0] == claims["name"]
|
||||
assert logged_user.user_name[0] == claims["sub"]
|
||||
assert logged_user.formatted_name[0] == claims["name"]
|
||||
assert [client.client_id, other_client.client_id] == claims["aud"]
|
||||
|
||||
res = testclient.get(
|
||||
|
@ -761,8 +761,8 @@ def test_authorization_code_request_scope_too_large(
|
|||
|
||||
id_token = res.json["id_token"]
|
||||
claims = jwt.decode(id_token, keypair[1])
|
||||
assert logged_user.uid[0] == claims["sub"]
|
||||
assert logged_user.cn[0] == claims["name"]
|
||||
assert logged_user.user_name[0] == claims["sub"]
|
||||
assert logged_user.formatted_name[0] == claims["name"]
|
||||
|
||||
res = testclient.get(
|
||||
"/oauth/userinfo",
|
||||
|
@ -814,11 +814,11 @@ def test_authorization_code_expired(testclient, user, client):
|
|||
|
||||
def test_code_with_invalid_user(testclient, admin, client):
|
||||
user = User(
|
||||
cn="John Doe",
|
||||
sn="Doe",
|
||||
uid="temp",
|
||||
mail="temp@temp.com",
|
||||
userPassword="{SSHA}fw9DYeF/gHTHuVMepsQzVYAkffGcU8Fz",
|
||||
formatted_name="John Doe",
|
||||
family_name="Doe",
|
||||
user_name="temp",
|
||||
email="temp@temp.com",
|
||||
password="{SSHA}fw9DYeF/gHTHuVMepsQzVYAkffGcU8Fz",
|
||||
)
|
||||
user.save()
|
||||
|
||||
|
@ -862,11 +862,11 @@ def test_code_with_invalid_user(testclient, admin, client):
|
|||
|
||||
def test_refresh_token_with_invalid_user(testclient, client):
|
||||
user = User(
|
||||
cn="John Doe",
|
||||
sn="Doe",
|
||||
uid="temp",
|
||||
mail="temp@temp.com",
|
||||
userPassword="{SSHA}fw9DYeF/gHTHuVMepsQzVYAkffGcU8Fz",
|
||||
formatted_name="John Doe",
|
||||
family_name="Doe",
|
||||
user_name="temp",
|
||||
email="temp@temp.com",
|
||||
password="{SSHA}fw9DYeF/gHTHuVMepsQzVYAkffGcU8Fz",
|
||||
)
|
||||
user.save()
|
||||
|
||||
|
|
|
@ -4,14 +4,14 @@ from canaille.oidc.oauth import get_jwt_config
|
|||
|
||||
|
||||
def test_end_session(testclient, slapd_connection, logged_user, client, id_token):
|
||||
testclient.get(f"/profile/{logged_user.uid[0]}", status=200)
|
||||
testclient.get(f"/profile/{logged_user.user_name[0]}", status=200)
|
||||
|
||||
post_logout_redirect_url = "https://mydomain.tld/disconnected"
|
||||
res = testclient.get(
|
||||
"/oauth/end_session",
|
||||
params={
|
||||
"id_token_hint": id_token,
|
||||
"logout_hint": logged_user.uid[0],
|
||||
"logout_hint": logged_user.user_name[0],
|
||||
"client_id": client.client_id,
|
||||
"post_logout_redirect_uri": post_logout_redirect_url,
|
||||
"state": "foobar",
|
||||
|
@ -24,20 +24,20 @@ def test_end_session(testclient, slapd_connection, logged_user, client, id_token
|
|||
with testclient.session_transaction() as sess:
|
||||
assert not sess.get("user_id")
|
||||
|
||||
testclient.get(f"/profile/{logged_user.uid[0]}", status=403)
|
||||
testclient.get(f"/profile/{logged_user.user_name[0]}", status=403)
|
||||
|
||||
|
||||
def test_end_session_no_client_id(
|
||||
testclient, slapd_connection, logged_user, client, id_token
|
||||
):
|
||||
testclient.get(f"/profile/{logged_user.uid[0]}", status=200)
|
||||
testclient.get(f"/profile/{logged_user.user_name[0]}", status=200)
|
||||
|
||||
post_logout_redirect_url = "https://mydomain.tld/disconnected"
|
||||
res = testclient.get(
|
||||
"/oauth/end_session",
|
||||
params={
|
||||
"id_token_hint": id_token,
|
||||
"logout_hint": logged_user.uid[0],
|
||||
"logout_hint": logged_user.user_name[0],
|
||||
"post_logout_redirect_uri": post_logout_redirect_url,
|
||||
"state": "foobar",
|
||||
},
|
||||
|
@ -49,19 +49,19 @@ def test_end_session_no_client_id(
|
|||
with testclient.session_transaction() as sess:
|
||||
assert not sess.get("user_id")
|
||||
|
||||
testclient.get(f"/profile/{logged_user.uid[0]}", status=403)
|
||||
testclient.get(f"/profile/{logged_user.user_name[0]}", status=403)
|
||||
|
||||
|
||||
def test_no_redirect_uri_no_redirect(
|
||||
testclient, slapd_connection, logged_user, client, id_token
|
||||
):
|
||||
testclient.get(f"/profile/{logged_user.uid[0]}", status=200)
|
||||
testclient.get(f"/profile/{logged_user.user_name[0]}", status=200)
|
||||
|
||||
res = testclient.get(
|
||||
"/oauth/end_session",
|
||||
params={
|
||||
"id_token_hint": id_token,
|
||||
"logout_hint": logged_user.uid[0],
|
||||
"logout_hint": logged_user.user_name[0],
|
||||
"client_id": client.client_id,
|
||||
"state": "foobar",
|
||||
},
|
||||
|
@ -73,20 +73,20 @@ def test_no_redirect_uri_no_redirect(
|
|||
with testclient.session_transaction() as sess:
|
||||
assert not sess.get("user_id")
|
||||
|
||||
testclient.get(f"/profile/{logged_user.uid[0]}", status=403)
|
||||
testclient.get(f"/profile/{logged_user.user_name[0]}", status=403)
|
||||
|
||||
|
||||
def test_bad_redirect_uri_no_redirect(
|
||||
testclient, slapd_connection, logged_user, client, id_token
|
||||
):
|
||||
testclient.get(f"/profile/{logged_user.uid[0]}", status=200)
|
||||
testclient.get(f"/profile/{logged_user.user_name[0]}", status=200)
|
||||
|
||||
post_logout_redirect_url = "https://mydomain.tld/invalid-uri"
|
||||
res = testclient.get(
|
||||
"/oauth/end_session",
|
||||
params={
|
||||
"id_token_hint": id_token,
|
||||
"logout_hint": logged_user.uid[0],
|
||||
"logout_hint": logged_user.user_name[0],
|
||||
"client_id": client.client_id,
|
||||
"post_logout_redirect_uri": post_logout_redirect_url,
|
||||
"state": "foobar",
|
||||
|
@ -99,19 +99,19 @@ def test_bad_redirect_uri_no_redirect(
|
|||
with testclient.session_transaction() as sess:
|
||||
assert not sess.get("user_id")
|
||||
|
||||
testclient.get(f"/profile/{logged_user.uid[0]}", status=403)
|
||||
testclient.get(f"/profile/{logged_user.user_name[0]}", status=403)
|
||||
|
||||
|
||||
def test_no_client_hint_no_redirect(
|
||||
testclient, slapd_connection, logged_user, client, id_token
|
||||
):
|
||||
testclient.get(f"/profile/{logged_user.uid[0]}", status=200)
|
||||
testclient.get(f"/profile/{logged_user.user_name[0]}", status=200)
|
||||
|
||||
post_logout_redirect_url = "https://mydomain.tld/disconnected"
|
||||
res = testclient.get(
|
||||
"/oauth/end_session",
|
||||
params={
|
||||
"logout_hint": logged_user.uid[0],
|
||||
"logout_hint": logged_user.user_name[0],
|
||||
"post_logout_redirect_uri": post_logout_redirect_url,
|
||||
"state": "foobar",
|
||||
},
|
||||
|
@ -125,19 +125,19 @@ def test_no_client_hint_no_redirect(
|
|||
with testclient.session_transaction() as sess:
|
||||
assert not sess.get("user_id")
|
||||
|
||||
testclient.get(f"/profile/{logged_user.uid[0]}", status=403)
|
||||
testclient.get(f"/profile/{logged_user.user_name[0]}", status=403)
|
||||
|
||||
|
||||
def test_end_session_invalid_client_id(
|
||||
testclient, slapd_connection, logged_user, client
|
||||
):
|
||||
testclient.get(f"/profile/{logged_user.uid[0]}", status=200)
|
||||
testclient.get(f"/profile/{logged_user.user_name[0]}", status=200)
|
||||
|
||||
post_logout_redirect_url = "https://mydomain.tld/disconnected"
|
||||
res = testclient.get(
|
||||
"/oauth/end_session",
|
||||
params={
|
||||
"logout_hint": logged_user.uid[0],
|
||||
"logout_hint": logged_user.user_name[0],
|
||||
"post_logout_redirect_uri": post_logout_redirect_url,
|
||||
"client_id": "invalid_client_id",
|
||||
"state": "foobar",
|
||||
|
@ -153,7 +153,7 @@ def test_end_session_invalid_client_id(
|
|||
with testclient.session_transaction() as sess:
|
||||
assert not sess.get("user_id")
|
||||
|
||||
testclient.get(f"/profile/{logged_user.uid[0]}", status=403)
|
||||
testclient.get(f"/profile/{logged_user.user_name[0]}", status=403)
|
||||
|
||||
|
||||
def test_client_hint_invalid(testclient, slapd_connection, logged_user, client):
|
||||
|
@ -164,14 +164,14 @@ def test_client_hint_invalid(testclient, slapd_connection, logged_user, client):
|
|||
**get_jwt_config(None),
|
||||
)
|
||||
|
||||
testclient.get(f"/profile/{logged_user.uid[0]}", status=200)
|
||||
testclient.get(f"/profile/{logged_user.user_name[0]}", status=200)
|
||||
|
||||
post_logout_redirect_url = "https://mydomain.tld/disconnected"
|
||||
res = testclient.get(
|
||||
"/oauth/end_session",
|
||||
params={
|
||||
"id_token_hint": id_token,
|
||||
"logout_hint": logged_user.uid[0],
|
||||
"logout_hint": logged_user.user_name[0],
|
||||
"post_logout_redirect_uri": post_logout_redirect_url,
|
||||
"state": "foobar",
|
||||
},
|
||||
|
@ -183,17 +183,17 @@ def test_client_hint_invalid(testclient, slapd_connection, logged_user, client):
|
|||
with testclient.session_transaction() as sess:
|
||||
assert not sess.get("user_id")
|
||||
|
||||
testclient.get(f"/profile/{logged_user.uid[0]}", status=403)
|
||||
testclient.get(f"/profile/{logged_user.user_name[0]}", status=403)
|
||||
|
||||
|
||||
def test_no_jwt_logout(testclient, slapd_connection, logged_user, client):
|
||||
testclient.get(f"/profile/{logged_user.uid[0]}", status=200)
|
||||
testclient.get(f"/profile/{logged_user.user_name[0]}", status=200)
|
||||
|
||||
post_logout_redirect_url = "https://mydomain.tld/disconnected"
|
||||
res = testclient.get(
|
||||
"/oauth/end_session",
|
||||
params={
|
||||
"logout_hint": logged_user.uid[0],
|
||||
"logout_hint": logged_user.user_name[0],
|
||||
"client_id": client.client_id,
|
||||
"post_logout_redirect_uri": post_logout_redirect_url,
|
||||
"state": "foobar",
|
||||
|
@ -209,17 +209,17 @@ def test_no_jwt_logout(testclient, slapd_connection, logged_user, client):
|
|||
|
||||
assert res.location == f"{post_logout_redirect_url}?state=foobar"
|
||||
|
||||
testclient.get(f"/profile/{logged_user.uid[0]}", status=403)
|
||||
testclient.get(f"/profile/{logged_user.user_name[0]}", status=403)
|
||||
|
||||
|
||||
def test_no_jwt_no_logout(testclient, slapd_connection, logged_user, client):
|
||||
testclient.get(f"/profile/{logged_user.uid[0]}", status=200)
|
||||
testclient.get(f"/profile/{logged_user.user_name[0]}", status=200)
|
||||
|
||||
post_logout_redirect_url = "https://mydomain.tld/disconnected"
|
||||
res = testclient.get(
|
||||
"/oauth/end_session",
|
||||
params={
|
||||
"logout_hint": logged_user.uid[0],
|
||||
"logout_hint": logged_user.user_name[0],
|
||||
"client_id": client.client_id,
|
||||
"post_logout_redirect_uri": post_logout_redirect_url,
|
||||
"state": "foobar",
|
||||
|
@ -234,7 +234,7 @@ def test_no_jwt_no_logout(testclient, slapd_connection, logged_user, client):
|
|||
|
||||
assert res.location == "/"
|
||||
|
||||
testclient.get(f"/profile/{logged_user.uid[0]}", status=200)
|
||||
testclient.get(f"/profile/{logged_user.user_name[0]}", status=200)
|
||||
|
||||
|
||||
def test_jwt_not_issued_here(
|
||||
|
@ -242,14 +242,14 @@ def test_jwt_not_issued_here(
|
|||
):
|
||||
testclient.app.config["JWT"]["ISS"] = "https://foo.bar"
|
||||
|
||||
testclient.get(f"/profile/{logged_user.uid[0]}", status=200)
|
||||
testclient.get(f"/profile/{logged_user.user_name[0]}", status=200)
|
||||
|
||||
post_logout_redirect_url = "https://mydomain.tld/disconnected"
|
||||
res = testclient.get(
|
||||
"/oauth/end_session",
|
||||
params={
|
||||
"id_token_hint": id_token,
|
||||
"logout_hint": logged_user.uid[0],
|
||||
"logout_hint": logged_user.user_name[0],
|
||||
"client_id": client.client_id,
|
||||
"post_logout_redirect_uri": post_logout_redirect_url,
|
||||
"state": "foobar",
|
||||
|
@ -271,14 +271,14 @@ def test_client_hint_mismatch(testclient, slapd_connection, logged_user, client)
|
|||
**get_jwt_config(None),
|
||||
)
|
||||
|
||||
testclient.get(f"/profile/{logged_user.uid[0]}", status=200)
|
||||
testclient.get(f"/profile/{logged_user.user_name[0]}", status=200)
|
||||
|
||||
post_logout_redirect_url = "https://mydomain.tld/disconnected"
|
||||
res = testclient.get(
|
||||
"/oauth/end_session",
|
||||
params={
|
||||
"id_token_hint": id_token,
|
||||
"logout_hint": logged_user.uid[0],
|
||||
"logout_hint": logged_user.user_name[0],
|
||||
"client_id": client.client_id,
|
||||
"post_logout_redirect_uri": post_logout_redirect_url,
|
||||
"state": "foobar",
|
||||
|
@ -295,7 +295,7 @@ def test_client_hint_mismatch(testclient, slapd_connection, logged_user, client)
|
|||
def test_bad_user_id_token_mismatch(
|
||||
testclient, slapd_connection, logged_user, client, admin
|
||||
):
|
||||
testclient.get(f"/profile/{logged_user.uid[0]}", status=200)
|
||||
testclient.get(f"/profile/{logged_user.user_name[0]}", status=200)
|
||||
|
||||
id_token = generate_id_token(
|
||||
{},
|
||||
|
@ -309,7 +309,7 @@ def test_bad_user_id_token_mismatch(
|
|||
"/oauth/end_session",
|
||||
params={
|
||||
"id_token_hint": id_token,
|
||||
"logout_hint": logged_user.uid[0],
|
||||
"logout_hint": logged_user.user_name[0],
|
||||
"client_id": client.client_id,
|
||||
"post_logout_redirect_uri": post_logout_redirect_url,
|
||||
"state": "foobar",
|
||||
|
@ -325,20 +325,20 @@ def test_bad_user_id_token_mismatch(
|
|||
|
||||
assert res.location == f"{post_logout_redirect_url}?state=foobar"
|
||||
|
||||
testclient.get(f"/profile/{logged_user.uid[0]}", status=403)
|
||||
testclient.get(f"/profile/{logged_user.user_name[0]}", status=403)
|
||||
|
||||
|
||||
def test_bad_user_hint(
|
||||
testclient, slapd_connection, logged_user, client, id_token, admin
|
||||
):
|
||||
testclient.get(f"/profile/{logged_user.uid[0]}", status=200)
|
||||
testclient.get(f"/profile/{logged_user.user_name[0]}", status=200)
|
||||
|
||||
post_logout_redirect_url = "https://mydomain.tld/disconnected"
|
||||
res = testclient.get(
|
||||
"/oauth/end_session",
|
||||
params={
|
||||
"id_token_hint": id_token,
|
||||
"logout_hint": admin.uid[0],
|
||||
"logout_hint": admin.user_name[0],
|
||||
"client_id": client.client_id,
|
||||
"post_logout_redirect_uri": post_logout_redirect_url,
|
||||
"state": "foobar",
|
||||
|
@ -354,17 +354,17 @@ def test_bad_user_hint(
|
|||
|
||||
assert res.location == f"{post_logout_redirect_url}?state=foobar"
|
||||
|
||||
testclient.get(f"/profile/{logged_user.uid[0]}", status=403)
|
||||
testclient.get(f"/profile/{logged_user.user_name[0]}", status=403)
|
||||
|
||||
|
||||
def test_no_jwt_bad_csrf(testclient, slapd_connection, logged_user, client):
|
||||
testclient.get(f"/profile/{logged_user.uid[0]}", status=200)
|
||||
testclient.get(f"/profile/{logged_user.user_name[0]}", status=200)
|
||||
|
||||
post_logout_redirect_url = "https://mydomain.tld/disconnected"
|
||||
res = testclient.get(
|
||||
"/oauth/end_session",
|
||||
params={
|
||||
"logout_hint": logged_user.uid[0],
|
||||
"logout_hint": logged_user.user_name[0],
|
||||
"client_id": client.client_id,
|
||||
"post_logout_redirect_uri": post_logout_redirect_url,
|
||||
"state": "foobar",
|
||||
|
@ -385,7 +385,7 @@ def test_end_session_already_disconnected(
|
|||
"/oauth/end_session",
|
||||
params={
|
||||
"id_token_hint": id_token,
|
||||
"logout_hint": user.uid[0],
|
||||
"logout_hint": user.user_name[0],
|
||||
"client_id": client.client_id,
|
||||
"post_logout_redirect_uri": post_logout_redirect_url,
|
||||
"state": "foobar",
|
||||
|
@ -399,14 +399,14 @@ def test_end_session_already_disconnected(
|
|||
def test_end_session_no_state(
|
||||
testclient, slapd_connection, logged_user, client, id_token
|
||||
):
|
||||
testclient.get(f"/profile/{logged_user.uid[0]}", status=200)
|
||||
testclient.get(f"/profile/{logged_user.user_name[0]}", status=200)
|
||||
|
||||
post_logout_redirect_url = "https://mydomain.tld/disconnected"
|
||||
res = testclient.get(
|
||||
"/oauth/end_session",
|
||||
params={
|
||||
"id_token_hint": id_token,
|
||||
"logout_hint": logged_user.uid[0],
|
||||
"logout_hint": logged_user.user_name[0],
|
||||
"client_id": client.client_id,
|
||||
"post_logout_redirect_uri": post_logout_redirect_url,
|
||||
},
|
||||
|
@ -418,4 +418,4 @@ def test_end_session_no_state(
|
|||
with testclient.session_transaction() as sess:
|
||||
assert not sess.get("user_id")
|
||||
|
||||
testclient.get(f"/profile/{logged_user.uid[0]}", status=403)
|
||||
testclient.get(f"/profile/{logged_user.user_name[0]}", status=403)
|
||||
|
|
|
@ -77,8 +77,8 @@ def test_oidc_hybrid(
|
|||
|
||||
id_token = params["id_token"][0]
|
||||
claims = jwt.decode(id_token, keypair[1])
|
||||
assert logged_user.uid[0] == claims["sub"]
|
||||
assert logged_user.cn[0] == claims["name"]
|
||||
assert logged_user.user_name[0] == claims["sub"]
|
||||
assert logged_user.formatted_name[0] == claims["name"]
|
||||
assert [client.client_id, other_client.client_id] == claims["aud"]
|
||||
|
||||
res = testclient.get(
|
||||
|
|
|
@ -84,8 +84,8 @@ def test_oidc_implicit(testclient, keypair, user, client, other_client):
|
|||
|
||||
id_token = params["id_token"][0]
|
||||
claims = jwt.decode(id_token, keypair[1])
|
||||
assert user.uid[0] == claims["sub"]
|
||||
assert user.cn[0] == claims["name"]
|
||||
assert user.user_name[0] == claims["sub"]
|
||||
assert user.formatted_name[0] == claims["name"]
|
||||
assert [client.client_id, other_client.client_id] == claims["aud"]
|
||||
|
||||
res = testclient.get(
|
||||
|
@ -138,8 +138,8 @@ def test_oidc_implicit_with_group(
|
|||
|
||||
id_token = params["id_token"][0]
|
||||
claims = jwt.decode(id_token, keypair[1])
|
||||
assert user.uid[0] == claims["sub"]
|
||||
assert user.cn[0] == claims["name"]
|
||||
assert user.user_name[0] == claims["sub"]
|
||||
assert user.formatted_name[0] == claims["name"]
|
||||
assert [client.client_id, other_client.client_id] == claims["aud"]
|
||||
assert ["foo"] == claims["groups"]
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ def test_access_token_introspection(testclient, user, client, token):
|
|||
"token_type": token.type,
|
||||
"username": user.name,
|
||||
"scope": token.get_scope(),
|
||||
"sub": user.uid[0],
|
||||
"sub": user.user_name[0],
|
||||
"aud": [client.client_id],
|
||||
"iss": "https://auth.mydomain.tld",
|
||||
"exp": token.get_expires_at(),
|
||||
|
@ -41,7 +41,7 @@ def test_refresh_token_introspection(testclient, user, client, token):
|
|||
"token_type": token.type,
|
||||
"username": user.name,
|
||||
"scope": token.get_scope(),
|
||||
"sub": user.uid[0],
|
||||
"sub": user.user_name[0],
|
||||
"aud": [client.client_id],
|
||||
"iss": "https://auth.mydomain.tld",
|
||||
"exp": token.get_expires_at(),
|
||||
|
@ -111,7 +111,7 @@ def test_full_flow(testclient, logged_user, client, user, other_client):
|
|||
"token_type": token.type,
|
||||
"username": user.name,
|
||||
"scope": token.get_scope(),
|
||||
"sub": user.uid[0],
|
||||
"sub": user.user_name[0],
|
||||
"iss": "https://auth.mydomain.tld",
|
||||
"exp": token.get_expires_at(),
|
||||
"iat": token.get_issued_at(),
|
||||
|
|
|
@ -264,21 +264,21 @@ STANDARD_CLAIMS = [
|
|||
"updated_at",
|
||||
]
|
||||
DEFAULT_JWT_MAPPING_CONFIG = {
|
||||
"SUB": "{{ user.uid[0] }}",
|
||||
"NAME": "{{ user.cn[0] }}",
|
||||
"PHONE_NUMBER": "{{ user.telephoneNumber[0] }}",
|
||||
"EMAIL": "{{ user.mail[0] }}",
|
||||
"GIVEN_NAME": "{{ user.givenName[0] }}",
|
||||
"FAMILY_NAME": "{{ user.sn[0] }}",
|
||||
"PREFERRED_USERNAME": "{{ user.displayName }}",
|
||||
"LOCALE": "{{ user.preferredLanguage }}",
|
||||
"SUB": "{{ user.user_name[0] }}",
|
||||
"NAME": "{{ user.formatted_name[0] }}",
|
||||
"PHONE_NUMBER": "{{ user.phone_number[0] }}",
|
||||
"EMAIL": "{{ user.email[0] }}",
|
||||
"GIVEN_NAME": "{{ user.given_name[0] }}",
|
||||
"FAMILY_NAME": "{{ user.family_name[0] }}",
|
||||
"PREFERRED_USERNAME": "{{ user.display_name }}",
|
||||
"LOCALE": "{{ user.preferred_language }}",
|
||||
}
|
||||
|
||||
|
||||
def test_generate_user_standard_claims_with_default_config(
|
||||
testclient, slapd_connection, user
|
||||
):
|
||||
user.preferredLanguage = ["fr"]
|
||||
user.preferred_language = ["fr"]
|
||||
|
||||
data = generate_user_claims(user, STANDARD_CLAIMS, DEFAULT_JWT_MAPPING_CONFIG)
|
||||
|
||||
|
@ -297,7 +297,7 @@ def test_custom_config_format_claim_is_well_formated(
|
|||
testclient, slapd_connection, user
|
||||
):
|
||||
jwt_mapping_config = DEFAULT_JWT_MAPPING_CONFIG.copy()
|
||||
jwt_mapping_config["EMAIL"] = "{{ user.uid[0] }}@mydomain.tld"
|
||||
jwt_mapping_config["EMAIL"] = "{{ user.user_name[0] }}@mydomain.tld"
|
||||
|
||||
data = generate_user_claims(user, STANDARD_CLAIMS, jwt_mapping_config)
|
||||
|
||||
|
@ -307,7 +307,7 @@ def test_custom_config_format_claim_is_well_formated(
|
|||
def test_claim_is_omitted_if_empty(testclient, slapd_connection, user):
|
||||
# According to https://openid.net/specs/openid-connect-core-1_0.html#UserInfoResponse
|
||||
# it's better to not insert a null or empty string value
|
||||
user.mail = ""
|
||||
user.email = ""
|
||||
user.save()
|
||||
|
||||
data = generate_user_claims(user, STANDARD_CLAIMS, DEFAULT_JWT_MAPPING_CONFIG)
|
||||
|
|
|
@ -109,10 +109,10 @@ def test_password_page_without_signin_in_redirects_to_login_page(testclient, use
|
|||
def test_user_without_password_first_login(testclient, slapd_connection, smtpd):
|
||||
assert len(smtpd.messages) == 0
|
||||
u = User(
|
||||
cn="Temp User",
|
||||
sn="Temp",
|
||||
uid="temp",
|
||||
mail="john@doe.com",
|
||||
formatted_name="Temp User",
|
||||
family_name="Temp",
|
||||
user_name="temp",
|
||||
email="john@doe.com",
|
||||
)
|
||||
u.save()
|
||||
|
||||
|
@ -143,10 +143,10 @@ def test_first_login_account_initialization_mail_sending_failed(
|
|||
assert len(smtpd.messages) == 0
|
||||
|
||||
u = User(
|
||||
cn="Temp User",
|
||||
sn="Temp",
|
||||
uid="temp",
|
||||
mail="john@doe.com",
|
||||
formatted_name="Temp User",
|
||||
family_name="Temp",
|
||||
user_name="temp",
|
||||
email="john@doe.com",
|
||||
)
|
||||
u.save()
|
||||
|
||||
|
@ -165,10 +165,10 @@ def test_first_login_account_initialization_mail_sending_failed(
|
|||
def test_first_login_form_error(testclient, slapd_connection, smtpd):
|
||||
assert len(smtpd.messages) == 0
|
||||
u = User(
|
||||
cn="Temp User",
|
||||
sn="Temp",
|
||||
uid="temp",
|
||||
mail="john@doe.com",
|
||||
formatted_name="Temp User",
|
||||
family_name="Temp",
|
||||
user_name="temp",
|
||||
email="john@doe.com",
|
||||
)
|
||||
u.save()
|
||||
|
||||
|
@ -187,11 +187,11 @@ def test_first_login_page_unavailable_for_users_with_password(
|
|||
|
||||
def test_user_password_deleted_during_login(testclient, slapd_connection):
|
||||
u = User(
|
||||
cn="Temp User",
|
||||
sn="Temp",
|
||||
uid="temp",
|
||||
mail="john@doe.com",
|
||||
userPassword="{SSHA}Yr1ZxSljRsKyaTB30suY2iZ1KRTStF1X",
|
||||
formatted_name="Temp User",
|
||||
family_name="Temp",
|
||||
user_name="temp",
|
||||
email="john@doe.com",
|
||||
password="{SSHA}Yr1ZxSljRsKyaTB30suY2iZ1KRTStF1X",
|
||||
)
|
||||
u.save()
|
||||
|
||||
|
@ -200,7 +200,7 @@ def test_user_password_deleted_during_login(testclient, slapd_connection):
|
|||
res = res.form.submit().follow()
|
||||
res.form["password"] = "correct horse battery staple"
|
||||
|
||||
u.userPassword = None
|
||||
u.password = None
|
||||
u.save()
|
||||
|
||||
res = res.form.submit(status=302)
|
||||
|
@ -211,11 +211,11 @@ def test_user_password_deleted_during_login(testclient, slapd_connection):
|
|||
|
||||
def test_user_deleted_in_session(testclient, slapd_connection):
|
||||
u = User(
|
||||
cn="Jake Doe",
|
||||
sn="Jake",
|
||||
uid="jake",
|
||||
mail="jake@doe.com",
|
||||
userPassword="{SSHA}fw9DYeF/gHTHuVMepsQzVYAkffGcU8Fz",
|
||||
formatted_name="Jake Doe",
|
||||
family_name="Jake",
|
||||
user_name="jake",
|
||||
email="jake@doe.com",
|
||||
password="{SSHA}fw9DYeF/gHTHuVMepsQzVYAkffGcU8Fz",
|
||||
)
|
||||
u.save()
|
||||
testclient.get("/profile/jake", status=403)
|
||||
|
@ -235,7 +235,7 @@ def test_impersonate(testclient, logged_admin, user):
|
|||
res = (
|
||||
testclient.get("/", status=302).follow(status=200).click("Account information")
|
||||
)
|
||||
assert "admin" == res.form["uid"].value
|
||||
assert "admin" == res.form["user_name"].value
|
||||
|
||||
res = (
|
||||
testclient.get("/impersonate/user", status=302)
|
||||
|
@ -243,14 +243,14 @@ def test_impersonate(testclient, logged_admin, user):
|
|||
.follow(status=200)
|
||||
.click("Account information")
|
||||
)
|
||||
assert "user" == res.form["uid"].value
|
||||
assert "user" == res.form["user_name"].value
|
||||
|
||||
testclient.get("/logout", status=302).follow(status=302).follow(status=200)
|
||||
|
||||
res = (
|
||||
testclient.get("/", status=302).follow(status=200).click("Account information")
|
||||
)
|
||||
assert "admin" == res.form["uid"].value
|
||||
assert "admin" == res.form["user_name"].value
|
||||
|
||||
|
||||
def test_wrong_login(testclient, user):
|
||||
|
@ -275,11 +275,11 @@ def test_wrong_login(testclient, user):
|
|||
|
||||
def test_admin_self_deletion(testclient, slapd_connection):
|
||||
admin = User(
|
||||
cn="Temp admin",
|
||||
sn="admin",
|
||||
uid="temp",
|
||||
mail="temp@temp.com",
|
||||
userPassword="{SSHA}Vmgh2jkD0idX3eZHf8RzGos31oerjGiU",
|
||||
formatted_name="Temp admin",
|
||||
family_name="admin",
|
||||
user_name="temp",
|
||||
email="temp@temp.com",
|
||||
password="{SSHA}Vmgh2jkD0idX3eZHf8RzGos31oerjGiU",
|
||||
)
|
||||
admin.save()
|
||||
with testclient.session_transaction() as sess:
|
||||
|
@ -300,11 +300,11 @@ def test_admin_self_deletion(testclient, slapd_connection):
|
|||
|
||||
def test_user_self_deletion(testclient, slapd_connection):
|
||||
user = User(
|
||||
cn="Temp user",
|
||||
sn="user",
|
||||
uid="temp",
|
||||
mail="temp@temp.com",
|
||||
userPassword="{SSHA}Vmgh2jkD0idX3eZHf8RzGos31oerjGiU",
|
||||
formatted_name="Temp user",
|
||||
family_name="user",
|
||||
user_name="temp",
|
||||
email="temp@temp.com",
|
||||
password="{SSHA}Vmgh2jkD0idX3eZHf8RzGos31oerjGiU",
|
||||
)
|
||||
user.save()
|
||||
with testclient.session_transaction() as sess:
|
||||
|
@ -347,6 +347,6 @@ def test_login_placeholder(testclient):
|
|||
placeholder = testclient.get("/login").form["login"].attrs["placeholder"]
|
||||
assert placeholder == "john@doe.com"
|
||||
|
||||
testclient.app.config["LDAP"]["USER_FILTER"] = "(|(uid={login})(email={login}))"
|
||||
testclient.app.config["LDAP"]["USER_FILTER"] = "(|(uid={login})(mail={login}))"
|
||||
placeholder = testclient.get("/login").form["login"].attrs["placeholder"]
|
||||
assert placeholder == "jdoe or john@doe.com"
|
||||
|
|
|
@ -66,7 +66,7 @@ def test_logging_to_file(configuration, tmp_path, smtpd, admin, slapd_server):
|
|||
sess["user_id"] = [admin.id]
|
||||
|
||||
res = testclient.get("/admin/mail")
|
||||
res.form["mail"] = "test@test.com"
|
||||
res.form["email"] = "test@test.com"
|
||||
res = res.form.submit()
|
||||
|
||||
g.ldap_connection.unbind_s()
|
||||
|
|
|
@ -5,7 +5,7 @@ def test_password_forgotten_disabled(smtpd, testclient, user):
|
|||
testclient.app.config["ENABLE_PASSWORD_RECOVERY"] = False
|
||||
|
||||
testclient.get("/reset", status=404)
|
||||
testclient.get("/reset/uid/hash", status=404)
|
||||
testclient.get("/reset/user_name/hash", status=404)
|
||||
|
||||
res = testclient.get("/login")
|
||||
res.mustcontain(no="Forgotten password")
|
||||
|
|
|
@ -85,10 +85,10 @@ def test_set_groups(app, user, foo_group, bar_group):
|
|||
|
||||
def test_set_groups_with_leading_space_in_user_id_attribute(app, foo_group):
|
||||
user = User(
|
||||
cn=" Doe", # leading space in id attribute
|
||||
sn="Doe",
|
||||
uid="user2",
|
||||
mail="john@doe.com",
|
||||
formatted_name=" Doe", # leading space in id attribute
|
||||
family_name="Doe",
|
||||
user_name="user2",
|
||||
email="john@doe.com",
|
||||
)
|
||||
user.save()
|
||||
|
||||
|
@ -181,7 +181,7 @@ def test_get_members_filters_non_existent_user(
|
|||
testclient, logged_moderator, foo_group, user
|
||||
):
|
||||
# an LDAP group can be inconsistent by containing members which doesn't exist
|
||||
non_existent_user = User(cn="foo", sn="bar")
|
||||
non_existent_user = User(formatted_name="foo", family_name="bar")
|
||||
foo_group.member = foo_group.member + [non_existent_user]
|
||||
foo_group.save()
|
||||
|
||||
|
|
|
@ -3,44 +3,44 @@ from flask_babel import refresh
|
|||
|
||||
|
||||
def test_preferred_language(slapd_server, testclient, logged_user):
|
||||
logged_user.preferredLanguage = None
|
||||
logged_user.preferred_language = None
|
||||
logged_user.save()
|
||||
|
||||
res = testclient.get("/profile/user", status=200)
|
||||
assert res.form["preferredLanguage"].value == "auto"
|
||||
assert res.form["preferred_language"].value == "auto"
|
||||
assert res.pyquery("html")[0].attrib["lang"] == "en"
|
||||
res.mustcontain("My profile")
|
||||
res.mustcontain(no="Mon profil")
|
||||
|
||||
res.form["preferredLanguage"] = "fr"
|
||||
res.form["preferred_language"] = "fr"
|
||||
res = res.form.submit(name="action", value="edit")
|
||||
assert res.flashes == [("success", "Le profil a été mis à jour avec succès.")]
|
||||
res = res.follow()
|
||||
logged_user = User.get(id=logged_user.id)
|
||||
assert logged_user.preferredLanguage == "fr"
|
||||
assert res.form["preferredLanguage"].value == "fr"
|
||||
assert logged_user.preferred_language == "fr"
|
||||
assert res.form["preferred_language"].value == "fr"
|
||||
assert res.pyquery("html")[0].attrib["lang"] == "fr"
|
||||
res.mustcontain(no="My profile")
|
||||
res.mustcontain("Mon profil")
|
||||
|
||||
res.form["preferredLanguage"] = "en"
|
||||
res.form["preferred_language"] = "en"
|
||||
res = res.form.submit(name="action", value="edit")
|
||||
assert res.flashes == [("success", "Profile updated successfuly.")]
|
||||
res = res.follow()
|
||||
logged_user = User.get(id=logged_user.id)
|
||||
assert logged_user.preferredLanguage == "en"
|
||||
assert res.form["preferredLanguage"].value == "en"
|
||||
assert logged_user.preferred_language == "en"
|
||||
assert res.form["preferred_language"].value == "en"
|
||||
assert res.pyquery("html")[0].attrib["lang"] == "en"
|
||||
res.mustcontain("My profile")
|
||||
res.mustcontain(no="Mon profil")
|
||||
|
||||
res.form["preferredLanguage"] = "auto"
|
||||
res.form["preferred_language"] = "auto"
|
||||
res = res.form.submit(name="action", value="edit")
|
||||
assert res.flashes == [("success", "Profile updated successfuly.")]
|
||||
res = res.follow()
|
||||
logged_user = User.get(id=logged_user.id)
|
||||
assert logged_user.preferredLanguage is None
|
||||
assert res.form["preferredLanguage"].value == "auto"
|
||||
assert logged_user.preferred_language is None
|
||||
assert res.form["preferred_language"].value == "auto"
|
||||
assert res.pyquery("html")[0].attrib["lang"] == "en"
|
||||
res.mustcontain("My profile")
|
||||
res.mustcontain(no="Mon profil")
|
||||
|
@ -51,7 +51,7 @@ def test_form_translations(slapd_server, testclient, logged_user):
|
|||
logged_user.save()
|
||||
|
||||
res = testclient.get("/profile/user", status=200)
|
||||
res.form["mail"] = "invalid"
|
||||
res.form["email"] = "invalid"
|
||||
res = res.form.submit(name="action", value="edit")
|
||||
|
||||
res.mustcontain(no="Invalid email address.")
|
||||
|
@ -59,7 +59,7 @@ def test_form_translations(slapd_server, testclient, logged_user):
|
|||
|
||||
|
||||
def test_language_config(testclient, logged_user):
|
||||
logged_user.preferredLanguage = None
|
||||
logged_user.preferred_language = None
|
||||
logged_user.save()
|
||||
|
||||
res = testclient.get("/profile/user", status=200)
|
||||
|
|
|
@ -9,9 +9,9 @@ def test_invitation(testclient, logged_admin, foo_group, smtpd):
|
|||
|
||||
res = testclient.get("/invite", status=200)
|
||||
|
||||
res.form["uid"] = "someone"
|
||||
res.form["uid_editable"] = False
|
||||
res.form["mail"] = "someone@domain.tld"
|
||||
res.form["user_name"] = "someone"
|
||||
res.form["user_name_editable"] = False
|
||||
res.form["email"] = "someone@domain.tld"
|
||||
res.form["groups"] = [foo_group.id]
|
||||
res = res.form.submit(name="action", value="send", status=200)
|
||||
assert len(smtpd.messages) == 1
|
||||
|
@ -24,15 +24,15 @@ def test_invitation(testclient, logged_admin, foo_group, smtpd):
|
|||
|
||||
res = testclient.get(url, status=200)
|
||||
|
||||
assert res.form["uid"].value == "someone"
|
||||
assert res.form["uid"].attrs["readonly"]
|
||||
assert res.form["mail"].value == "someone@domain.tld"
|
||||
assert res.form["user_name"].value == "someone"
|
||||
assert res.form["user_name"].attrs["readonly"]
|
||||
assert res.form["email"].value == "someone@domain.tld"
|
||||
assert res.form["groups"].value == [foo_group.id]
|
||||
|
||||
res.form["password1"] = "whatever"
|
||||
res.form["password2"] = "whatever"
|
||||
res.form["givenName"] = "George"
|
||||
res.form["sn"] = "Abitbol"
|
||||
res.form["given_name"] = "George"
|
||||
res.form["family_name"] = "Abitbol"
|
||||
|
||||
res = res.form.submit(status=302)
|
||||
|
||||
|
@ -53,15 +53,15 @@ def test_invitation(testclient, logged_admin, foo_group, smtpd):
|
|||
user.delete()
|
||||
|
||||
|
||||
def test_invitation_editable_uid(testclient, logged_admin, foo_group, smtpd):
|
||||
def test_invitation_editable_user_name(testclient, logged_admin, foo_group, smtpd):
|
||||
assert User.get("jackyjack") is None
|
||||
assert User.get("djorje") is None
|
||||
|
||||
res = testclient.get("/invite", status=200)
|
||||
|
||||
res.form["uid"] = "jackyjack"
|
||||
res.form["uid_editable"] = True
|
||||
res.form["mail"] = "jackyjack@domain.tld"
|
||||
res.form["user_name"] = "jackyjack"
|
||||
res.form["user_name_editable"] = True
|
||||
res.form["email"] = "jackyjack@domain.tld"
|
||||
res.form["groups"] = [foo_group.id]
|
||||
res = res.form.submit(name="action", value="send", status=200)
|
||||
assert len(smtpd.messages) == 1
|
||||
|
@ -74,16 +74,16 @@ def test_invitation_editable_uid(testclient, logged_admin, foo_group, smtpd):
|
|||
|
||||
res = testclient.get(url, status=200)
|
||||
|
||||
assert res.form["uid"].value == "jackyjack"
|
||||
assert "readonly" not in res.form["uid"].attrs
|
||||
assert res.form["mail"].value == "jackyjack@domain.tld"
|
||||
assert res.form["user_name"].value == "jackyjack"
|
||||
assert "readonly" not in res.form["user_name"].attrs
|
||||
assert res.form["email"].value == "jackyjack@domain.tld"
|
||||
assert res.form["groups"].value == [foo_group.id]
|
||||
|
||||
res.form["uid"] = "djorje"
|
||||
res.form["user_name"] = "djorje"
|
||||
res.form["password1"] = "whatever"
|
||||
res.form["password2"] = "whatever"
|
||||
res.form["givenName"] = "George"
|
||||
res.form["sn"] = "Abitbol"
|
||||
res.form["given_name"] = "George"
|
||||
res.form["family_name"] = "Abitbol"
|
||||
|
||||
res = res.form.submit(status=302)
|
||||
|
||||
|
@ -107,8 +107,8 @@ def test_generate_link(testclient, logged_admin, foo_group, smtpd):
|
|||
|
||||
res = testclient.get("/invite", status=200)
|
||||
|
||||
res.form["uid"] = "sometwo"
|
||||
res.form["mail"] = "sometwo@domain.tld"
|
||||
res.form["user_name"] = "sometwo"
|
||||
res.form["email"] = "sometwo@domain.tld"
|
||||
res.form["groups"] = [foo_group.id]
|
||||
res = res.form.submit(name="action", value="generate", status=200)
|
||||
assert len(smtpd.messages) == 0
|
||||
|
@ -121,14 +121,14 @@ def test_generate_link(testclient, logged_admin, foo_group, smtpd):
|
|||
|
||||
res = testclient.get(url, status=200)
|
||||
|
||||
assert res.form["uid"].value == "sometwo"
|
||||
assert res.form["mail"].value == "sometwo@domain.tld"
|
||||
assert res.form["user_name"].value == "sometwo"
|
||||
assert res.form["email"].value == "sometwo@domain.tld"
|
||||
assert res.form["groups"].value == [foo_group.id]
|
||||
|
||||
res.form["password1"] = "whatever"
|
||||
res.form["password2"] = "whatever"
|
||||
res.form["givenName"] = "George"
|
||||
res.form["sn"] = "Abitbol"
|
||||
res.form["given_name"] = "George"
|
||||
res.form["family_name"] = "Abitbol"
|
||||
|
||||
res = res.form.submit(status=302)
|
||||
res = res.follow(status=200)
|
||||
|
@ -150,8 +150,8 @@ def test_generate_link(testclient, logged_admin, foo_group, smtpd):
|
|||
def test_invitation_login_already_taken(testclient, logged_admin):
|
||||
res = testclient.get("/invite", status=200)
|
||||
|
||||
res.form["uid"] = logged_admin.uid
|
||||
res.form["mail"] = logged_admin.mail[0]
|
||||
res.form["user_name"] = logged_admin.user_name
|
||||
res.form["email"] = logged_admin.email[0]
|
||||
res = res.form.submit(name="action", value="send", status=200)
|
||||
|
||||
res.mustcontain("The login 'admin' already exists")
|
||||
|
@ -272,7 +272,7 @@ def test_groups_are_saved_even_when_user_does_not_have_read_permission(
|
|||
testclient, foo_group
|
||||
):
|
||||
testclient.app.config["ACL"]["DEFAULT"]["READ"] = [
|
||||
"uid"
|
||||
"user_name"
|
||||
] # remove groups from default read permissions
|
||||
|
||||
invitation = Invitation(
|
||||
|
@ -292,8 +292,8 @@ def test_groups_are_saved_even_when_user_does_not_have_read_permission(
|
|||
|
||||
res.form["password1"] = "whatever"
|
||||
res.form["password2"] = "whatever"
|
||||
res.form["givenName"] = "George"
|
||||
res.form["sn"] = "Abitbol"
|
||||
res.form["given_name"] = "George"
|
||||
res.form["family_name"] = "Abitbol"
|
||||
|
||||
res = res.form.submit(status=302)
|
||||
res = res.follow(status=200)
|
||||
|
|
|
@ -11,7 +11,7 @@ def test_send_test_email(testclient, logged_admin, smtpd):
|
|||
assert len(smtpd.messages) == 0
|
||||
|
||||
res = testclient.get("/admin/mail")
|
||||
res.form["mail"] = "test@test.com"
|
||||
res.form["email"] = "test@test.com"
|
||||
res = res.form.submit()
|
||||
assert (
|
||||
"success",
|
||||
|
@ -33,7 +33,7 @@ def test_send_test_email_ssl(testclient, logged_admin, smtpd):
|
|||
assert len(smtpd.messages) == 0
|
||||
|
||||
res = testclient.get("/admin/mail")
|
||||
res.form["mail"] = "test@test.com"
|
||||
res.form["email"] = "test@test.com"
|
||||
res = res.form.submit()
|
||||
assert (
|
||||
"success",
|
||||
|
@ -50,7 +50,7 @@ def test_send_test_email_without_credentials(testclient, logged_admin, smtpd):
|
|||
assert len(smtpd.messages) == 0
|
||||
|
||||
res = testclient.get("/admin/mail")
|
||||
res.form["mail"] = "test@test.com"
|
||||
res.form["email"] = "test@test.com"
|
||||
res = res.form.submit()
|
||||
assert (
|
||||
"success",
|
||||
|
@ -68,7 +68,7 @@ def test_send_test_email_recipient_refused(SMTP, testclient, logged_admin, smtpd
|
|||
assert len(smtpd.messages) == 0
|
||||
|
||||
res = testclient.get("/admin/mail")
|
||||
res.form["mail"] = "test@test.com"
|
||||
res.form["email"] = "test@test.com"
|
||||
res = res.form.submit()
|
||||
assert (
|
||||
"success",
|
||||
|
@ -81,7 +81,7 @@ def test_send_test_email_recipient_refused(SMTP, testclient, logged_admin, smtpd
|
|||
def test_send_test_email_failed(testclient, logged_admin):
|
||||
testclient.app.config["SMTP"]["TLS"] = False
|
||||
res = testclient.get("/admin/mail")
|
||||
res.form["mail"] = "test@test.com"
|
||||
res.form["email"] = "test@test.com"
|
||||
with warnings.catch_warnings(record=True):
|
||||
res = res.form.submit(expect_errors=True)
|
||||
assert (
|
||||
|
@ -95,7 +95,7 @@ def test_mail_with_default_no_logo(testclient, logged_admin, smtpd):
|
|||
assert len(smtpd.messages) == 0
|
||||
|
||||
res = testclient.get(f"/admin/mail")
|
||||
res.form["mail"] = "test@test.com"
|
||||
res.form["email"] = "test@test.com"
|
||||
res = res.form.submit()
|
||||
assert (
|
||||
"success",
|
||||
|
@ -118,7 +118,7 @@ def test_mail_with_default_logo(testclient, logged_admin, smtpd, httpserver):
|
|||
assert len(smtpd.messages) == 0
|
||||
|
||||
res = testclient.get(f"http://{httpserver.host}:{httpserver.port}/admin/mail")
|
||||
res.form["mail"] = "test@test.com"
|
||||
res.form["email"] = "test@test.com"
|
||||
res = res.form.submit()
|
||||
assert (
|
||||
"success",
|
||||
|
@ -146,7 +146,7 @@ def test_mail_with_logo_in_http(testclient, logged_admin, smtpd, httpserver):
|
|||
assert len(smtpd.messages) == 0
|
||||
|
||||
res = testclient.get("/admin/mail")
|
||||
res.form["mail"] = "test@test.com"
|
||||
res.form["email"] = "test@test.com"
|
||||
res = res.form.submit()
|
||||
assert (
|
||||
"success",
|
||||
|
|
|
@ -2,7 +2,7 @@ from canaille.account import profile_hash
|
|||
|
||||
|
||||
def test_password_reset(testclient, user):
|
||||
hash = profile_hash("user", user.mail[0], user.userPassword[0])
|
||||
hash = profile_hash("user", user.email[0], user.password[0])
|
||||
|
||||
res = testclient.get("/reset/user/" + hash, status=200)
|
||||
|
||||
|
@ -30,7 +30,7 @@ def test_password_reset_bad_link(testclient, user):
|
|||
|
||||
|
||||
def test_password_reset_bad_password(testclient, user):
|
||||
hash = profile_hash("user", user.mail[0], user.userPassword[0])
|
||||
hash = profile_hash("user", user.email[0], user.password[0])
|
||||
|
||||
res = testclient.get("/reset/user/" + hash, status=200)
|
||||
|
||||
|
|
|
@ -11,11 +11,11 @@ def test_user_creation_edition_and_deletion(
|
|||
|
||||
# Fill the profile for a new user.
|
||||
res = testclient.get("/profile", status=200)
|
||||
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["user_name"] = "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["groups"] = [foo_group.id]
|
||||
res.form["password1"] = "totoyolo"
|
||||
res.form["password2"] = "totoyolo"
|
||||
|
@ -27,7 +27,7 @@ def test_user_creation_edition_and_deletion(
|
|||
george = User.get("george")
|
||||
george.load_groups()
|
||||
foo_group.reload()
|
||||
assert "George" == george.givenName[0]
|
||||
assert "George" == george.given_name[0]
|
||||
assert george.groups == [foo_group]
|
||||
assert george.check_password("totoyolo")
|
||||
|
||||
|
@ -39,7 +39,7 @@ def test_user_creation_edition_and_deletion(
|
|||
|
||||
# User have been edited
|
||||
res = testclient.get("/profile/george", status=200)
|
||||
res.form["givenName"] = "Georgio"
|
||||
res.form["given_name"] = "Georgio"
|
||||
res = res.form.submit(name="action", value="edit").follow()
|
||||
|
||||
res = testclient.get("/profile/george/settings", status=200)
|
||||
|
@ -48,7 +48,7 @@ def test_user_creation_edition_and_deletion(
|
|||
|
||||
george = User.get("george")
|
||||
george.load_groups()
|
||||
assert "Georgio" == george.givenName[0]
|
||||
assert "Georgio" == george.given_name[0]
|
||||
assert george.check_password("totoyolo")
|
||||
|
||||
foo_group.reload()
|
||||
|
@ -72,11 +72,11 @@ def test_profile_creation_dynamic_validation(testclient, logged_admin, user):
|
|||
f"/profile",
|
||||
{
|
||||
"csrf_token": res.form["csrf_token"].value,
|
||||
"mail": "john@doe.com",
|
||||
"email": "john@doe.com",
|
||||
},
|
||||
headers={
|
||||
"HX-Request": "true",
|
||||
"HX-Trigger-Name": "mail",
|
||||
"HX-Trigger-Name": "email",
|
||||
},
|
||||
)
|
||||
res.mustcontain("The email 'john@doe.com' is already used")
|
||||
|
@ -84,15 +84,15 @@ def test_profile_creation_dynamic_validation(testclient, logged_admin, user):
|
|||
|
||||
def test_user_creation_without_password(testclient, logged_moderator):
|
||||
res = testclient.get("/profile", status=200)
|
||||
res.form["uid"] = "george"
|
||||
res.form["sn"] = "Abitbol"
|
||||
res.form["mail"] = "george@abitbol.com"
|
||||
res.form["user_name"] = "george"
|
||||
res.form["family_name"] = "Abitbol"
|
||||
res.form["email"] = "george@abitbol.com"
|
||||
|
||||
res = res.form.submit(name="action", value="edit", status=302)
|
||||
assert ("success", "User account creation succeed.") in res.flashes
|
||||
res = res.follow(status=200)
|
||||
george = User.get("george")
|
||||
assert george.uid[0] == "george"
|
||||
assert george.user_name[0] == "george"
|
||||
assert not george.userPassword
|
||||
|
||||
george.delete()
|
||||
|
@ -115,9 +115,9 @@ def test_username_already_taken(
|
|||
testclient, logged_moderator, user, foo_group, bar_group
|
||||
):
|
||||
res = testclient.get("/profile", status=200)
|
||||
res.form["uid"] = "user"
|
||||
res.form["sn"] = "foo"
|
||||
res.form["mail"] = "any@thing.com"
|
||||
res.form["user_name"] = "user"
|
||||
res.form["family_name"] = "foo"
|
||||
res.form["email"] = "any@thing.com"
|
||||
res = res.form.submit(name="action", value="edit")
|
||||
assert ("error", "User account creation failed.") in res.flashes
|
||||
res.mustcontain("The login 'user' already exists")
|
||||
|
@ -125,9 +125,9 @@ def test_username_already_taken(
|
|||
|
||||
def test_email_already_taken(testclient, logged_moderator, user, foo_group, bar_group):
|
||||
res = testclient.get("/profile", status=200)
|
||||
res.form["uid"] = "user2"
|
||||
res.form["sn"] = "foo"
|
||||
res.form["mail"] = "john@doe.com"
|
||||
res.form["user_name"] = "user2"
|
||||
res.form["family_name"] = "foo"
|
||||
res.form["email"] = "john@doe.com"
|
||||
res = res.form.submit(name="action", value="edit")
|
||||
assert ("error", "User account creation failed.") in res.flashes
|
||||
res.mustcontain("The email 'john@doe.com' is already used")
|
||||
|
@ -135,10 +135,10 @@ def test_email_already_taken(testclient, logged_moderator, user, foo_group, bar_
|
|||
|
||||
def test_cn_setting_with_given_name_and_surname(testclient, logged_moderator):
|
||||
res = testclient.get("/profile", status=200)
|
||||
res.form["uid"] = "george"
|
||||
res.form["givenName"] = "George"
|
||||
res.form["sn"] = "Abitbol"
|
||||
res.form["mail"] = "george@abitbol.com"
|
||||
res.form["user_name"] = "george"
|
||||
res.form["given_name"] = "George"
|
||||
res.form["family_name"] = "Abitbol"
|
||||
res.form["email"] = "george@abitbol.com"
|
||||
|
||||
res = res.form.submit(name="action", value="edit", status=302).follow(status=200)
|
||||
|
||||
|
@ -149,9 +149,9 @@ def test_cn_setting_with_given_name_and_surname(testclient, logged_moderator):
|
|||
|
||||
def test_cn_setting_with_surname_only(testclient, logged_moderator):
|
||||
res = testclient.get("/profile", status=200)
|
||||
res.form["uid"] = "george"
|
||||
res.form["sn"] = "Abitbol"
|
||||
res.form["mail"] = "george@abitbol.com"
|
||||
res.form["user_name"] = "george"
|
||||
res.form["family_name"] = "Abitbol"
|
||||
res.form["email"] = "george@abitbol.com"
|
||||
|
||||
res = res.form.submit(name="action", value="edit", status=302).follow(status=200)
|
||||
|
||||
|
|
|
@ -72,7 +72,7 @@ def test_user_list_search_only_allowed_fields(
|
|||
res.mustcontain(user.name)
|
||||
res.mustcontain(no=moderator.name)
|
||||
|
||||
testclient.app.config["ACL"]["DEFAULT"]["READ"].remove("uid")
|
||||
testclient.app.config["ACL"]["DEFAULT"]["READ"].remove("user_name")
|
||||
|
||||
form = res.forms["search"]
|
||||
form["query"] = "user"
|
||||
|
@ -104,22 +104,22 @@ def test_edition(
|
|||
jpeg_photo,
|
||||
):
|
||||
res = testclient.get("/profile/user", status=200)
|
||||
res.form["givenName"] = "given_name"
|
||||
res.form["sn"] = "family_name"
|
||||
res.form["displayName"] = "display_name"
|
||||
res.form["mail"] = "email@mydomain.tld"
|
||||
res.form["telephoneNumber"] = "555-666-777"
|
||||
res.form["postalAddress"] = "postal_address"
|
||||
res.form["given_name"] = "given_name"
|
||||
res.form["family_name"] = "family_name"
|
||||
res.form["display_name"] = "display_name"
|
||||
res.form["email"] = "email@mydomain.tld"
|
||||
res.form["phone_number"] = "555-666-777"
|
||||
res.form["formatted_address"] = "formatted_address"
|
||||
res.form["street"] = "street"
|
||||
res.form["postalCode"] = "postal_code"
|
||||
res.form["l"] = "locality"
|
||||
res.form["st"] = "region"
|
||||
res.form["employeeNumber"] = 666
|
||||
res.form["departmentNumber"] = 1337
|
||||
res.form["postal_code"] = "postal_code"
|
||||
res.form["locality"] = "locality"
|
||||
res.form["region"] = "region"
|
||||
res.form["employee_number"] = 666
|
||||
res.form["department"] = 1337
|
||||
res.form["title"] = "title"
|
||||
res.form["o"] = "organization"
|
||||
res.form["preferredLanguage"] = "fr"
|
||||
res.form["jpegPhoto"] = Upload("logo.jpg", jpeg_photo)
|
||||
res.form["organization"] = "organization"
|
||||
res.form["preferred_language"] = "fr"
|
||||
res.form["photo"] = Upload("logo.jpg", jpeg_photo)
|
||||
|
||||
res = res.form.submit(name="action", value="edit")
|
||||
assert res.flashes == [
|
||||
|
@ -129,28 +129,28 @@ def test_edition(
|
|||
|
||||
logged_user = User.get(id=logged_user.id)
|
||||
|
||||
assert logged_user.givenName == ["given_name"]
|
||||
assert logged_user.sn == ["family_name"]
|
||||
assert logged_user.displayName == "display_name"
|
||||
assert logged_user.given_name == ["given_name"]
|
||||
assert logged_user.family_name == ["family_name"]
|
||||
assert logged_user.display_name == "display_name"
|
||||
assert logged_user.mail == ["email@mydomain.tld"]
|
||||
assert logged_user.telephoneNumber == ["555-666-777"]
|
||||
assert logged_user.postalAddress == ["postal_address"]
|
||||
assert logged_user.phone_number == ["555-666-777"]
|
||||
assert logged_user.formatted_address == ["formatted_address"]
|
||||
assert logged_user.street == ["street"]
|
||||
assert logged_user.postalCode == ["postal_code"]
|
||||
assert logged_user.l == ["locality"]
|
||||
assert logged_user.st == ["region"]
|
||||
assert logged_user.preferredLanguage == "fr"
|
||||
assert logged_user.employeeNumber == "666"
|
||||
assert logged_user.departmentNumber == ["1337"]
|
||||
assert logged_user.postal_code == ["postal_code"]
|
||||
assert logged_user.locality == ["locality"]
|
||||
assert logged_user.region == ["region"]
|
||||
assert logged_user.preferred_language == "fr"
|
||||
assert logged_user.employee_number == "666"
|
||||
assert logged_user.department == ["1337"]
|
||||
assert logged_user.title == ["title"]
|
||||
assert logged_user.o == ["organization"]
|
||||
assert logged_user.organization == ["organization"]
|
||||
assert logged_user.jpegPhoto == [jpeg_photo]
|
||||
|
||||
logged_user.cn = ["John (johnny) Doe"]
|
||||
logged_user.sn = ["Doe"]
|
||||
logged_user.family_name = ["Doe"]
|
||||
logged_user.mail = ["john@doe.com"]
|
||||
logged_user.givenName = None
|
||||
logged_user.jpegPhoto = None
|
||||
logged_user.given_name = None
|
||||
logged_user.photo = None
|
||||
logged_user.save()
|
||||
|
||||
|
||||
|
@ -160,11 +160,11 @@ def test_profile_edition_dynamic_validation(testclient, logged_admin, user):
|
|||
f"/profile/admin",
|
||||
{
|
||||
"csrf_token": res.form["csrf_token"].value,
|
||||
"mail": "john@doe.com",
|
||||
"email": "john@doe.com",
|
||||
},
|
||||
headers={
|
||||
"HX-Request": "true",
|
||||
"HX-Trigger-Name": "mail",
|
||||
"HX-Trigger-Name": "email",
|
||||
},
|
||||
)
|
||||
res.mustcontain("The email 'john@doe.com' is already used")
|
||||
|
@ -172,78 +172,78 @@ def test_profile_edition_dynamic_validation(testclient, logged_admin, user):
|
|||
|
||||
def test_field_permissions_none(testclient, slapd_server, logged_user):
|
||||
testclient.get("/profile/user", status=200)
|
||||
logged_user.telephoneNumber = ["555-666-777"]
|
||||
logged_user.phone_number = ["555-666-777"]
|
||||
logged_user.save()
|
||||
|
||||
testclient.app.config["ACL"]["DEFAULT"] = {
|
||||
"READ": ["uid"],
|
||||
"READ": ["user_name"],
|
||||
"WRITE": [],
|
||||
"PERMISSIONS": ["edit_self"],
|
||||
}
|
||||
|
||||
res = testclient.get("/profile/user", status=200)
|
||||
assert "telephoneNumber" not in res.form.fields
|
||||
assert "phone_number" not in res.form.fields
|
||||
|
||||
testclient.post(
|
||||
"/profile/user",
|
||||
{
|
||||
"action": "edit",
|
||||
"telephoneNumber": "000-000-000",
|
||||
"phone_number": "000-000-000",
|
||||
"csrf_token": res.form["csrf_token"].value,
|
||||
},
|
||||
)
|
||||
user = User.get(id=logged_user.id)
|
||||
assert user.telephoneNumber == ["555-666-777"]
|
||||
assert user.phone_number == ["555-666-777"]
|
||||
|
||||
|
||||
def test_field_permissions_read(testclient, slapd_server, logged_user):
|
||||
testclient.get("/profile/user", status=200)
|
||||
logged_user.telephoneNumber = ["555-666-777"]
|
||||
logged_user.phone_number = ["555-666-777"]
|
||||
logged_user.save()
|
||||
|
||||
testclient.app.config["ACL"]["DEFAULT"] = {
|
||||
"READ": ["uid", "telephoneNumber"],
|
||||
"READ": ["user_name", "phone_number"],
|
||||
"WRITE": [],
|
||||
"PERMISSIONS": ["edit_self"],
|
||||
}
|
||||
res = testclient.get("/profile/user", status=200)
|
||||
assert "telephoneNumber" in res.form.fields
|
||||
assert "phone_number" in res.form.fields
|
||||
|
||||
testclient.post(
|
||||
"/profile/user",
|
||||
{
|
||||
"action": "edit",
|
||||
"telephoneNumber": "000-000-000",
|
||||
"phone_number": "000-000-000",
|
||||
"csrf_token": res.form["csrf_token"].value,
|
||||
},
|
||||
)
|
||||
user = User.get(id=logged_user.id)
|
||||
assert user.telephoneNumber == ["555-666-777"]
|
||||
assert user.phone_number == ["555-666-777"]
|
||||
|
||||
|
||||
def test_field_permissions_write(testclient, slapd_server, logged_user):
|
||||
testclient.get("/profile/user", status=200)
|
||||
logged_user.telephoneNumber = ["555-666-777"]
|
||||
logged_user.phone_number = ["555-666-777"]
|
||||
logged_user.save()
|
||||
|
||||
testclient.app.config["ACL"]["DEFAULT"] = {
|
||||
"READ": ["uid"],
|
||||
"WRITE": ["telephoneNumber"],
|
||||
"READ": ["user_name"],
|
||||
"WRITE": ["phone_number"],
|
||||
"PERMISSIONS": ["edit_self"],
|
||||
}
|
||||
res = testclient.get("/profile/user", status=200)
|
||||
assert "telephoneNumber" in res.form.fields
|
||||
assert "phone_number" in res.form.fields
|
||||
|
||||
testclient.post(
|
||||
"/profile/user",
|
||||
{
|
||||
"action": "edit",
|
||||
"telephoneNumber": "000-000-000",
|
||||
"phone_number": "000-000-000",
|
||||
"csrf_token": res.form["csrf_token"].value,
|
||||
},
|
||||
)
|
||||
user = User.get(id=logged_user.id)
|
||||
assert user.telephoneNumber == ["000-000-000"]
|
||||
assert user.phone_number == ["000-000-000"]
|
||||
|
||||
|
||||
def test_simple_user_cannot_edit_other(testclient, logged_user):
|
||||
|
@ -269,7 +269,7 @@ def test_admin_bad_request(testclient, logged_moderator):
|
|||
def test_bad_email(testclient, logged_user):
|
||||
res = testclient.get("/profile/user", status=200)
|
||||
|
||||
res.form["mail"] = "john@doe.com"
|
||||
res.form["email"] = "john@doe.com"
|
||||
|
||||
res = res.form.submit(name="action", value="edit").follow()
|
||||
|
||||
|
@ -277,7 +277,7 @@ def test_bad_email(testclient, logged_user):
|
|||
|
||||
res = testclient.get("/profile/user", status=200)
|
||||
|
||||
res.form["mail"] = "yolo"
|
||||
res.form["email"] = "yolo"
|
||||
|
||||
res = res.form.submit(name="action", value="edit", status=200)
|
||||
|
||||
|
@ -288,12 +288,12 @@ def test_bad_email(testclient, logged_user):
|
|||
|
||||
def test_surname_is_mandatory(testclient, logged_user):
|
||||
res = testclient.get("/profile/user", status=200)
|
||||
logged_user.sn = ["Doe"]
|
||||
logged_user.family_name = ["Doe"]
|
||||
|
||||
res.form["sn"] = ""
|
||||
res.form["family_name"] = ""
|
||||
|
||||
res = res.form.submit(name="action", value="edit", status=200)
|
||||
|
||||
logged_user.reload()
|
||||
|
||||
assert ["Doe"] == logged_user.sn
|
||||
assert ["Doe"] == logged_user.family_name
|
||||
|
|
|
@ -5,18 +5,18 @@ from webtest import Upload
|
|||
|
||||
|
||||
def test_photo(testclient, user, jpeg_photo):
|
||||
user.jpegPhoto = [jpeg_photo]
|
||||
user.photo = [jpeg_photo]
|
||||
user.save()
|
||||
user = User.get(id=user.id)
|
||||
|
||||
res = testclient.get("/profile/user/jpegPhoto")
|
||||
res = testclient.get("/profile/user/photo")
|
||||
assert res.body == jpeg_photo
|
||||
assert res.last_modified == user.modifyTimestamp
|
||||
assert res.last_modified == user.last_modified
|
||||
etag = res.etag
|
||||
assert etag
|
||||
|
||||
res = testclient.get(
|
||||
"/profile/user/jpegPhoto",
|
||||
"/profile/user/photo",
|
||||
headers={
|
||||
"If-Modified-Since": (
|
||||
res.last_modified + datetime.timedelta(days=1)
|
||||
|
@ -27,7 +27,7 @@ def test_photo(testclient, user, jpeg_photo):
|
|||
assert not res.body
|
||||
|
||||
res = testclient.get(
|
||||
"/profile/user/jpegPhoto",
|
||||
"/profile/user/photo",
|
||||
headers={"If-None-Match": etag},
|
||||
status=304,
|
||||
)
|
||||
|
@ -35,12 +35,12 @@ def test_photo(testclient, user, jpeg_photo):
|
|||
|
||||
|
||||
def test_photo_invalid_user(testclient, user):
|
||||
res = testclient.get("/profile/invalid/jpegPhoto", status=404)
|
||||
res = testclient.get("/profile/invalid/photo", status=404)
|
||||
|
||||
|
||||
def test_photo_absent(testclient, user):
|
||||
assert not user.jpegPhoto
|
||||
res = testclient.get("/profile/user/jpegPhoto", status=404)
|
||||
assert not user.photo
|
||||
res = testclient.get("/profile/user/photo", status=404)
|
||||
|
||||
|
||||
def test_photo_invalid_path(testclient, user):
|
||||
|
@ -55,49 +55,49 @@ def test_photo_on_profile_edition(
|
|||
):
|
||||
# Add a photo
|
||||
res = testclient.get("/profile/user", status=200)
|
||||
res.form["jpegPhoto"] = Upload("logo.jpg", jpeg_photo)
|
||||
res.form["jpegPhoto_delete"] = False
|
||||
res.form["photo"] = Upload("logo.jpg", jpeg_photo)
|
||||
res.form["photo_delete"] = False
|
||||
res = res.form.submit(name="action", value="edit")
|
||||
assert ("success", "Profile updated successfuly.") in res.flashes
|
||||
res = res.follow()
|
||||
|
||||
logged_user = User.get(id=logged_user.id)
|
||||
|
||||
assert [jpeg_photo] == logged_user.jpegPhoto
|
||||
assert [jpeg_photo] == logged_user.photo
|
||||
|
||||
# No change
|
||||
res = testclient.get("/profile/user", status=200)
|
||||
res.form["jpegPhoto_delete"] = False
|
||||
res.form["photo_delete"] = False
|
||||
res = res.form.submit(name="action", value="edit")
|
||||
assert ("success", "Profile updated successfuly.") in res.flashes
|
||||
res = res.follow()
|
||||
|
||||
logged_user = User.get(id=logged_user.id)
|
||||
|
||||
assert [jpeg_photo] == logged_user.jpegPhoto
|
||||
assert [jpeg_photo] == logged_user.photo
|
||||
|
||||
# Photo deletion
|
||||
res = testclient.get("/profile/user", status=200)
|
||||
res.form["jpegPhoto_delete"] = True
|
||||
res.form["photo_delete"] = True
|
||||
res = res.form.submit(name="action", value="edit")
|
||||
assert ("success", "Profile updated successfuly.") in res.flashes
|
||||
res = res.follow()
|
||||
|
||||
logged_user = User.get(id=logged_user.id)
|
||||
|
||||
assert [] == logged_user.jpegPhoto
|
||||
assert [] == logged_user.photo
|
||||
|
||||
# Photo deletion AND upload, this should never happen
|
||||
res = testclient.get("/profile/user", status=200)
|
||||
res.form["jpegPhoto"] = Upload("logo.jpg", jpeg_photo)
|
||||
res.form["jpegPhoto_delete"] = True
|
||||
res.form["photo"] = Upload("logo.jpg", jpeg_photo)
|
||||
res.form["photo_delete"] = True
|
||||
res = res.form.submit(name="action", value="edit")
|
||||
assert ("success", "Profile updated successfuly.") in res.flashes
|
||||
res = res.follow()
|
||||
|
||||
logged_user = User.get(id=logged_user.id)
|
||||
|
||||
assert [] == logged_user.jpegPhoto
|
||||
assert [] == logged_user.photo
|
||||
|
||||
|
||||
def test_photo_on_profile_creation(testclient, slapd_server, jpeg_photo, logged_admin):
|
||||
|
@ -106,14 +106,14 @@ def test_photo_on_profile_creation(testclient, slapd_server, jpeg_photo, logged_
|
|||
res.mustcontain(no="foobar")
|
||||
|
||||
res = testclient.get("/profile", status=200)
|
||||
res.form["jpegPhoto"] = Upload("logo.jpg", jpeg_photo)
|
||||
res.form["uid"] = "foobar"
|
||||
res.form["sn"] = "Abitbol"
|
||||
res.form["mail"] = "george@abitbol.com"
|
||||
res.form["photo"] = Upload("logo.jpg", jpeg_photo)
|
||||
res.form["user_name"] = "foobar"
|
||||
res.form["family_name"] = "Abitbol"
|
||||
res.form["email"] = "george@abitbol.com"
|
||||
res = res.form.submit(name="action", value="edit", status=302).follow(status=200)
|
||||
|
||||
user = User.get("foobar")
|
||||
assert user.jpegPhoto == [jpeg_photo]
|
||||
assert user.photo == [jpeg_photo]
|
||||
user.delete()
|
||||
|
||||
|
||||
|
@ -125,13 +125,13 @@ def test_photo_deleted_on_profile_creation(
|
|||
res.mustcontain(no="foobar")
|
||||
|
||||
res = testclient.get("/profile", status=200)
|
||||
res.form["jpegPhoto"] = Upload("logo.jpg", jpeg_photo)
|
||||
res.form["jpegPhoto_delete"] = True
|
||||
res.form["uid"] = "foobar"
|
||||
res.form["sn"] = "Abitbol"
|
||||
res.form["mail"] = "george@abitbol.com"
|
||||
res.form["photo"] = Upload("logo.jpg", jpeg_photo)
|
||||
res.form["photo_delete"] = True
|
||||
res.form["user_name"] = "foobar"
|
||||
res.form["family_name"] = "Abitbol"
|
||||
res.form["email"] = "george@abitbol.com"
|
||||
res = res.form.submit(name="action", value="edit", status=302).follow(status=200)
|
||||
|
||||
user = User.get("foobar")
|
||||
assert user.jpegPhoto == []
|
||||
assert user.photo == []
|
||||
user.delete()
|
||||
|
|
|
@ -20,9 +20,9 @@ def test_edition(
|
|||
assert foo_group.members == [logged_user]
|
||||
assert bar_group.members == [admin]
|
||||
assert res.form["groups"].attrs["readonly"]
|
||||
assert res.form["uid"].attrs["readonly"]
|
||||
assert res.form["user_name"].attrs["readonly"]
|
||||
|
||||
res.form["uid"] = "toto"
|
||||
res.form["user_name"] = "toto"
|
||||
res = res.form.submit(name="action", value="edit")
|
||||
assert res.flashes == [("success", "Profile updated successfuly.")]
|
||||
res = res.follow()
|
||||
|
@ -30,7 +30,7 @@ def test_edition(
|
|||
logged_user = User.get(id=logged_user.id)
|
||||
logged_user.load_groups()
|
||||
|
||||
assert logged_user.uid == ["user"]
|
||||
assert logged_user.user_name == ["user"]
|
||||
|
||||
foo_group.reload()
|
||||
bar_group.reload()
|
||||
|
@ -40,7 +40,7 @@ def test_edition(
|
|||
|
||||
assert logged_user.check_password("correct horse battery staple")
|
||||
|
||||
logged_user.uid = ["user"]
|
||||
logged_user.user_name = ["user"]
|
||||
logged_user.save()
|
||||
|
||||
|
||||
|
@ -75,10 +75,10 @@ def test_edition_without_groups(
|
|||
|
||||
logged_user = User.get(id=logged_user.id)
|
||||
|
||||
assert logged_user.uid == ["user"]
|
||||
assert logged_user.user_name == ["user"]
|
||||
assert logged_user.check_password("correct horse battery staple")
|
||||
|
||||
logged_user.uid = ["user"]
|
||||
logged_user.user_name = ["user"]
|
||||
logged_user.save()
|
||||
|
||||
|
||||
|
@ -128,10 +128,10 @@ def test_password_initialization_mail(
|
|||
smtpd, testclient, slapd_connection, logged_admin
|
||||
):
|
||||
u = User(
|
||||
cn="Temp User",
|
||||
sn="Temp",
|
||||
uid="temp",
|
||||
mail="john@doe.com",
|
||||
formatted_name="Temp User",
|
||||
family_name="Temp",
|
||||
user_name="temp",
|
||||
email="john@doe.com",
|
||||
)
|
||||
u.save()
|
||||
|
||||
|
@ -148,7 +148,7 @@ def test_password_initialization_mail(
|
|||
assert len(smtpd.messages) == 1
|
||||
|
||||
u.reload()
|
||||
u.userPassword = ["{SSHA}fw9DYeF/gHTHuVMepsQzVYAkffGcU8Fz"]
|
||||
u.password = ["{SSHA}fw9DYeF/gHTHuVMepsQzVYAkffGcU8Fz"]
|
||||
u.save()
|
||||
|
||||
res = testclient.get("/profile/temp/settings", status=200)
|
||||
|
@ -163,10 +163,10 @@ def test_password_initialization_mail_send_fail(
|
|||
):
|
||||
SMTP.side_effect = mock.Mock(side_effect=OSError("unit test mail error"))
|
||||
u = User(
|
||||
cn="Temp User",
|
||||
sn="Temp",
|
||||
uid="temp",
|
||||
mail="john@doe.com",
|
||||
formatted_name="Temp User",
|
||||
family_name="Temp",
|
||||
user_name="temp",
|
||||
email="john@doe.com",
|
||||
)
|
||||
u.save()
|
||||
|
||||
|
@ -235,11 +235,11 @@ def test_invalid_form_request(testclient, logged_admin):
|
|||
|
||||
def test_password_reset_email(smtpd, testclient, slapd_connection, logged_admin):
|
||||
u = User(
|
||||
cn="Temp User",
|
||||
sn="Temp",
|
||||
uid="temp",
|
||||
mail="john@doe.com",
|
||||
userPassword=["{SSHA}fw9DYeF/gHTHuVMepsQzVYAkffGcU8Fz"],
|
||||
formatted_name="Temp User",
|
||||
family_name="Temp",
|
||||
user_name="temp",
|
||||
email="john@doe.com",
|
||||
password="{SSHA}fw9DYeF/gHTHuVMepsQzVYAkffGcU8Fz",
|
||||
)
|
||||
u.save()
|
||||
|
||||
|
@ -264,11 +264,11 @@ def test_password_reset_email_failed(
|
|||
):
|
||||
SMTP.side_effect = mock.Mock(side_effect=OSError("unit test mail error"))
|
||||
u = User(
|
||||
cn="Temp User",
|
||||
sn="Temp",
|
||||
uid="temp",
|
||||
mail="john@doe.com",
|
||||
userPassword=["{SSHA}fw9DYeF/gHTHuVMepsQzVYAkffGcU8Fz"],
|
||||
formatted_name="Temp User",
|
||||
family_name="Temp",
|
||||
user_name="temp",
|
||||
email="john@doe.com",
|
||||
password=["{SSHA}fw9DYeF/gHTHuVMepsQzVYAkffGcU8Fz"],
|
||||
)
|
||||
u.save()
|
||||
|
||||
|
|
Loading…
Reference in a new issue