-
{% endblock content %}
diff --git a/lumi2/usermanager.py b/lumi2/usermanager.py
index ff128bd..cfc39e9 100644
--- a/lumi2/usermanager.py
+++ b/lumi2/usermanager.py
@@ -4,7 +4,7 @@ from pathlib import Path
from tempfile import TemporaryFile
from flask import (
- Blueprint, render_template, abort, request, flash, redirect, url_for
+ Blueprint, render_template, abort, request, flash, redirect, url_for, current_app
)
from PIL import Image, UnidentifiedImageError
from flask_wtf import FlaskForm
@@ -68,20 +68,14 @@ def user_list():
users=users,
)
-
-@bp.route("/users/test")
-def user_test():
- return render_template(
- 'usermanager/user_test.html',
- )
-
class UserUpdateForm(FlaskForm):
@staticmethod
def validate_name(form, field) -> None:
- try:
- User.assert_is_valid_name(field.data)
- except InvalidStringFormatException as e:
- raise ValidationError(str(e))
+ if field.data:
+ try:
+ User.assert_is_valid_name(field.data)
+ except InvalidStringFormatException as e:
+ raise ValidationError(str(e))
@staticmethod
def validate_password(form, field) -> None:
@@ -115,11 +109,11 @@ class UserUpdateForm(FlaskForm):
[InputRequired(), validate_name]
)
display_name = StringField(
- 'Nick Name',
+ 'Nickname',
[InputRequired(), validate_name]
)
password = PasswordField(
- 'Password (leave empty to keep the same)',
+ 'Password',
[
EqualTo('password_confirmation', message='Passwords must match'),
validate_password,
@@ -137,6 +131,82 @@ class UserUpdateForm(FlaskForm):
)
+class UserCreationForm(UserUpdateForm):
+ @staticmethod
+ def validate_username(form, field) -> None:
+ try:
+ User.assert_is_valid_username(field.data)
+ except InvalidStringFormatException as e:
+ raise ValidationError(str(e))
+ new_user_dn = f"uid={field.data}," + current_app.config['LDAP_USERS_OU']
+ conn = ldap.get_connection()
+ if ldap.user_exists(conn, new_user_dn):
+ raise ValidationError("Username is taken.")
+ conn.unbind()
+
+ username = StringField(
+ 'Username',
+ [
+ InputRequired('Please enter a username.'),
+ validate_username
+ ]
+ )
+ display_name = StringField(
+ 'Nickname',
+ [UserUpdateForm.validate_name]
+ )
+ password = PasswordField(
+ 'Password',
+ [
+ EqualTo('password_confirmation', message='Passwords must match'),
+ InputRequired('Please enter a password.'),
+ UserUpdateForm.validate_password,
+ ],
+ )
+ submit = SubmitField(
+ 'Create',
+ )
+
+
+
+@bp.route("/users/create", methods=("GET", "POST"))
+def user_create():
+ """Creation view for a new User.
+
+ Provides a form which can be used to enter the new user's details.
+ """
+ try:
+ conn = ldap.get_connection()
+ except Exception:
+ abort(500)
+
+ form = UserCreationForm()
+ if form.validate_on_submit():
+ user = User(
+ form.username.data,
+ User.generate_password_hash(form.password.data),
+ form.email.data,
+ form.first_name.data,
+ form.last_name.data,
+ form.display_name.data if form.display_name.data else None,
+ Image.open(form.picture.data, formats=['JPEG']) if form.picture.data and form.picture.data.filename else None,
+ )
+
+ ldap.create_user(conn, user)
+ user._generate_static_images(force=True)
+ conn.unbind()
+ flash(f"User '{user.username}' was created.")
+ return redirect(url_for('usermanager.user_view', username=user.username))
+
+ conn.unbind()
+ return render_template(
+ 'usermanager/user_edit.html',
+ form=form,
+ heading=f"Create a new user",
+ is_update=False,
+ )
+
+
@bp.route("/users/update/
", methods=("GET", "POST"))
def user_update(username: str):
"""Update view for a specific User.
@@ -183,7 +253,9 @@ def user_update(username: str):
conn.unbind()
return render_template(
- 'usermanager/user_update.html',
+ 'usermanager/user_edit.html',
form=form,
- username=user.username
+ username=user.username,
+ heading=f"Edit user: {user.username}",
+ is_update=True,
)