diff --git a/lumi2/templates/usermanager/user_detail.html b/lumi2/templates/usermanager/user_update.html
similarity index 94%
rename from lumi2/templates/usermanager/user_detail.html
rename to lumi2/templates/usermanager/user_update.html
index 8b5d013..01f65f2 100644
--- a/lumi2/templates/usermanager/user_detail.html
+++ b/lumi2/templates/usermanager/user_update.html
@@ -27,6 +27,6 @@
{{ form.picture.label }}
{{ form.picture }}
-
+ {{ form.submit }}
{% endblock content %}
diff --git a/lumi2/usermanager.py b/lumi2/usermanager.py
index 646a502..57cfa39 100644
--- a/lumi2/usermanager.py
+++ b/lumi2/usermanager.py
@@ -9,11 +9,12 @@ from flask import (
from PIL import Image, UnidentifiedImageError
from flask_wtf import FlaskForm
from flask_wtf.file import FileField, FileAllowed
-from wtforms import ValidationError, StringField, PasswordField
+from wtforms import ValidationError, StringField, PasswordField, SubmitField
from wtforms.validators import InputRequired, Email, EqualTo
import lumi2.ldap as ldap
from lumi2.usermodel import User, Group
+from lumi2.exceptions import InvalidStringFormatException, InvalidImageException
bp = Blueprint('usermanager', __name__)
@@ -26,11 +27,31 @@ def index():
return render_template('usermanager/index.html')
-class UserEditForm(FlaskForm):
+class UserUpdateForm(FlaskForm):
@staticmethod
def validate_name(form, field) -> None:
- if not User.is_valid_person_name(field.data):
- raise ValidationError("Invalid name.")
+ try:
+ User.assert_is_valid_name(field.data)
+ except InvalidStringFormatException as e:
+ raise ValidationError from e
+
+ @staticmethod
+ def validate_password(form, field) -> None:
+ try:
+ User.assert_is_valid_password(field.data)
+ except InvalidStringFormatException as e:
+ raise ValidationError from e
+
+ @staticmethod
+ def validate_picture(form, field) -> None:
+ if field.data:
+ try:
+ with TemporaryDirectory() as temp_dir:
+ temp_file = Path(temp_dir) / "upload.jpg"
+ field.data.save(temp_file)
+ Image.open(temp_file, formats=['JPEG'])
+ except UnidentifiedImageError as e:
+ raise ValidationError from e
email = StringField(
'Email',
@@ -50,7 +71,10 @@ class UserEditForm(FlaskForm):
)
password = PasswordField(
'Password',
- [EqualTo('password_confirmation', message='Passwords must match')],
+ [
+ EqualTo('password_confirmation', message='Passwords must match'),
+ validate_password,
+ ],
)
password_confirmation = PasswordField(
'Password (repeat)',
@@ -59,11 +83,14 @@ class UserEditForm(FlaskForm):
'Picture',
[FileAllowed(['jpg', 'jpeg'], 'JPEG images only.')]
)
+ submit = SubmitField(
+ 'Update',
+ )
-@bp.route("/user/", methods=("GET", "POST"))
-def user_detail(username: str):
- """Detail view for a specific User."""
+@bp.route("/user/update/", methods=("GET", "POST"))
+def user_update(username: str):
+ """Update view for a specific User."""
try:
conn = ldap.get_connection()
@@ -78,19 +105,41 @@ def user_detail(username: str):
user._generate_static_images()
- # data = {
- # "email": user.email,
- # "first_name": user.first_name,
- # "last_name": user.last_name,
- # "display_name": user.display_name,
- # }
+ if request.method == 'GET':
+ form = UserUpdateForm(obj=user)
+ else:
+ form = UserUpdateForm(request.form)
+ if form.validate():
+ if form.email.data:
+ user.email = form.email.data
+ print("Email updated.")
+ if form.first_name.data:
+ user.first_name = form.first_name.data
+ print("First Name updated.")
+ if form.last_name.data:
+ user.last_name = form.last_name.data
+ print("Last Name updated.")
+ if form.display_name.data:
+ user.display_name = form.display_name.data
+ print("Display Name updated.")
+ if form.password.data:
+ user.password_hash = User.generate_password_hash(form.password.data)
+ print("Password updated.")
+ picture_updated = False
+ if form.picture.data:
+ with TemporaryDirectory() as temp_dir:
+ temp_file = Path(temp_dir) / "upload.jpg"
+ form.picture.data.save(temp_file)
+ user.picture = Image.open(temp_file, formats=['JPEG'])
+ picture_updated = True
+ print("Picture updated.")
- form = UserEditForm(obj=user)
- if form.validate_on_submit():
- conn.unbind()
-
- # TODO update user
- return redirect(request.url)
+ ldap.update_user(conn, user)
+ if picture_updated:
+ user._generate_static_images(force=True)
+ conn.unbind()
+ # TODO redirect to user detail view
+ return redirect(request.url)
conn.unbind()
- return render_template('usermanager/user_detail.html', form=form, user=user)
+ return render_template('usermanager/user_update.html', form=form, user=user)
diff --git a/lumi2/usermodel.py b/lumi2/usermodel.py
index 1ff2599..1a14cf2 100644
--- a/lumi2/usermodel.py
+++ b/lumi2/usermodel.py
@@ -6,7 +6,8 @@ import hashlib
from binascii import Error as Base64DecodeError
from pathlib import Path
-from PIL.Image import JpegImageFile, Image
+from PIL.Image import Image
+from PIL.JpegImagePlugin import JpegImageFile
from flask import current_app
from lumi2.exceptions import InvalidStringFormatException, InvalidImageException
@@ -297,7 +298,7 @@ class User:
@staticmethod
- def _get_default_picture() -> Image.Image:
+ def _get_default_picture() -> Image:
"""Returns the default user picture as a PIL Image object.
Returns