From 24489e8510b66de6c83a9f95abc57b6378451a9e Mon Sep 17 00:00:00 2001
From: nd <git@notandy.de>
Date: Thu, 16 Jul 2020 19:37:27 +0200
Subject: [PATCH] small fixes

---
 uffd/selfservice/__init__.py                  |  2 +-
 .../templates/mailverification.mail.txt       |  2 +-
 .../templates/passwordreset.mail.txt          |  2 +-
 uffd/selfservice/templates/self.html          | 37 +------------------
 uffd/selfservice/views.py                     |  1 -
 uffd/user/templates/user.html                 |  5 ++-
 uffd/user/views.py                            | 26 ++++++++-----
 7 files changed, 25 insertions(+), 50 deletions(-)

diff --git a/uffd/selfservice/__init__.py b/uffd/selfservice/__init__.py
index 67157866..69a1df97 100644
--- a/uffd/selfservice/__init__.py
+++ b/uffd/selfservice/__init__.py
@@ -1,3 +1,3 @@
-from .views import bp as bp_ui
+from .views import bp as bp_ui, send_passwordreset
 
 bp = [bp_ui]
diff --git a/uffd/selfservice/templates/mailverification.mail.txt b/uffd/selfservice/templates/mailverification.mail.txt
index e9ff7e31..24a5b5d8 100644
--- a/uffd/selfservice/templates/mailverification.mail.txt
+++ b/uffd/selfservice/templates/mailverification.mail.txt
@@ -1,7 +1,7 @@
 Hi {{ user.displayname }},
 
 you have requested to change your mail address.
-To do so, visit this url: {{ url_for('.self_token_mail', token=token, _external=True) }} 
+To do so, visit this url: {{ url_for('selfservice.self_token_mail', token=token, _external=True) }} 
 **Please note this link is only valid for 48h**
 
 If you did not request a mail address change, you should change your password asap because somebody else logged in and requested this.
diff --git a/uffd/selfservice/templates/passwordreset.mail.txt b/uffd/selfservice/templates/passwordreset.mail.txt
index 9560ff86..2cc66e91 100644
--- a/uffd/selfservice/templates/passwordreset.mail.txt
+++ b/uffd/selfservice/templates/passwordreset.mail.txt
@@ -1,7 +1,7 @@
 Hi {{ user.displayname }},
 
 you have requested a password reset.
-To reset your password, visit this url: {{ url_for('.self_token_password', token=token, _external=True) }} 
+To reset your password, visit this url: {{ url_for('selfservice.self_token_password', token=token, _external=True) }} 
 **Please note this link is only valid for 48h**
 
 If you did not request a password reset, you do not need to do anything.
diff --git a/uffd/selfservice/templates/self.html b/uffd/selfservice/templates/self.html
index 4f9756d0..aadc2e96 100644
--- a/uffd/selfservice/templates/self.html
+++ b/uffd/selfservice/templates/self.html
@@ -1,7 +1,8 @@
 {% extends 'base.html' %}
 
 {% block body %}
-<form action="{{ url_for(".self_update") }}" method="POST" onInput="password2.setCustomValidity(password1.value != password2.value ? 'Passwords do not match.' : '')">
+<form action="{{ url_for(".self_update") }}" method="POST"
+	onInput="password2.setCustomValidity(password1.value != password2.value ? 'Passwords do not match.' : ''); password1.setCustomValidity(password1.value.length < 8 ? 'Password is too short' : '')">
 <div class="align-self-center row">
 	<div class="form-group col-md-6">
 		<label for="user-uid">uid</label>
@@ -35,40 +36,6 @@
 	<div class="form-group col-md-12">
 		<button type="submit" class="btn btn-primary float-right"><i class="fa fa-save" aria-hidden="true"></i> Save</button>
 	</div>
-	<div class="form-group col-md-12" "id="accordion">
-		<div class="card">
-			<div class="card-header" id="user-group">
-				<h5 class="mb-0">
-					<a class="btn btn-link collapsed" data-toggle="collapse" data-target="#user-group-body" aria-expanded="false" aria-controls="user-group">
-						groups
-					</a>
-				</h5>
-			</div>
-			<div id="user-group-body" class="collapse" aria-labelledby="user-group" data-parent="#accordion">
-				<div class="card-body">
-					<ul class="list-group">
-					{% for group in user.get_groups() %}
-					<li class="list-group-item"><a href="{{ url_for("group.group_show", gid=group.gid) }}">{{ group.name }}</a></li>
-					{% endfor %}
-					</ul>
-				</div>
-			</div>
-		</div>
-		<div class="card">
-			<div class="card-header" id="user-role">
-				<h5 class="mb-0">
-					<a class="btn btn-link" data-toggle="collapse" data-target="#user-role-body" aria-expanded="true" aria-controls="user-role">
-						roles
-					</a>
-				</h5>
-			</div>
-			<div id="user-role-body" class="collapse show" aria-labelledby="user-role" data-parent="#accordion">
-				<div class="card-body">
-					roles.
-				</div>
-			</div>
-		</div>
-	</div>
 </div>
 </form>
 {% endblock %}
diff --git a/uffd/selfservice/views.py b/uffd/selfservice/views.py
index 0ef6f8a0..6ace04dd 100644
--- a/uffd/selfservice/views.py
+++ b/uffd/selfservice/views.py
@@ -46,7 +46,6 @@ def self_update():
 	return redirect(url_for('.self_index'))
 
 @bp.route("/passwordreset", methods=(['GET', 'POST']))
-@csrf_protect(blueprint=bp)
 def self_forgot_password():
 	if request.method == 'GET':
 		return render_template('forgot_password.html')
diff --git a/uffd/user/templates/user.html b/uffd/user/templates/user.html
index 0fa6163c..c1f8855d 100644
--- a/uffd/user/templates/user.html
+++ b/uffd/user/templates/user.html
@@ -22,13 +22,14 @@
 		<label for="user-loginname">display name</label>
 		<input type="text" class="form-control" id="user-displayname" name="displayname" value="{{ user.displayname }}">
 		<small class="form-text text-muted">
-			At most 128, at least 2 characters. No character restrictions.
+			If you leave this empty it will be set to the login name. At most 128, at least 2 characters. No character restrictions.
 		</small>
 	</div>
 	<div class="form-group col">
 		<label for="user-mail">mail</label>
 		<input type="email" class="form-control" id="user-mail" name="mail" value="{{ user.mail }}">
 		<small class="form-text text-muted">
+			Do a sanity check here. A user can take over another account if both have the same mail address set.
 		</small>
 	</div>
 	<div class="form-group col">
@@ -42,6 +43,7 @@
 			At least 8 characters, no other special requirements. But please don't be stupid and use a password manager.
 		</small>
 	</div>
+	{% if user.uid %}
 	<div class="form-group col "id="accordion">
 		<div class="card">
 			<div class="card-header" id="user-ldif">
@@ -90,6 +92,7 @@
 			</div>
 		</div>
 	</div>
+	{% endif %}
 	<div class="form-group col">
 		<button type="submit" class="btn btn-primary"><i class="fa fa-save" aria-hidden="true"></i> Save</button>
 		<a href="{{ url_for(".user_list") }}" class="btn btn-secondary">Cancle</a>
diff --git a/uffd/user/views.py b/uffd/user/views.py
index 4906cdbb..067807ca 100644
--- a/uffd/user/views.py
+++ b/uffd/user/views.py
@@ -2,6 +2,7 @@ from flask import Blueprint, render_template, request, url_for, redirect, flash,
 
 from uffd.navbar import register_navbar
 from uffd.csrf import csrf_protect
+from uffd.selfservice import send_passwordreset
 from uffd.ldap import get_conn, escape_filter_chars
 from uffd.session import login_required, is_valid_session, get_current_user
 
@@ -47,25 +48,30 @@ def user_show(uid=None):
 @csrf_protect(blueprint=bp_user)
 def user_update(uid=False):
 	conn = get_conn()
-	if uid:
-		conn.search(current_app.config["LDAP_BASE_USER"], '(&(objectclass=person)(uidNumber={}))'.format((escape_filter_chars(uid))))
-		assert len(conn.entries) == 1
-		user = User.from_ldap(conn.entries[0])
-	else:
-		# new user
+	is_newuser = bool(not uid)
+	if is_newuser:
 		user = User()
 		if not user.set_loginname(request.form['loginname']):
 			flash('Login name does not meet requirements')
 			return url_for('.user_show')
+	else:
+		conn.search(current_app.config["LDAP_BASE_USER"], '(&(objectclass=person)(uidNumber={}))'.format((escape_filter_chars(uid))))
+		assert len(conn.entries) == 1
+		user = User.from_ldap(conn.entries[0])
 	user.mail = request.form['mail']
-	if not user.set_displayname(request.form['displayname']):
+	new_displayname = request.form['displayname'] if request.form['displayname'] else request.form['loginname']
+	if not user.set_displayname(new_displayname):
 		flash('Display name does not meet requirements')
 		return url_for('.user_show')
 	new_password = request.form.get('password')
-	if new_password:
+	if new_password and not is_newuser:
 		user.set_password(new_password)
-	if user.to_ldap(new=(not uid)):
-		flash('User updated')
+	if user.to_ldap(new=is_newuser):
+		if is_newuser:
+			send_passwordreset(user.loginname)
+			flash('User created. We sent the user a password reset link by mail')
+		else:
+			flash('User updated')
 	else:
 		flash('Error updating user: {}'.format(conn.result['message']))
 	return redirect(url_for('.user_list'))
-- 
GitLab