From bdf6ac7ac77c24b3f980bea41f6ac36ed17ce6cd Mon Sep 17 00:00:00 2001 From: nd <git@notandy.de> Date: Thu, 16 Jul 2020 19:00:07 +0200 Subject: [PATCH] fully working self service --- .../templates/mailverification.mail.txt | 10 +++ uffd/selfservice/templates/self.html | 2 +- uffd/selfservice/views.py | 63 +++++++++++++++++-- uffd/templates/base.html | 2 +- uffd/user/models.py | 9 +++ uffd/user/templates/user.html | 2 +- 6 files changed, 81 insertions(+), 7 deletions(-) create mode 100644 uffd/selfservice/templates/mailverification.mail.txt diff --git a/uffd/selfservice/templates/mailverification.mail.txt b/uffd/selfservice/templates/mailverification.mail.txt new file mode 100644 index 00000000..e9ff7e31 --- /dev/null +++ b/uffd/selfservice/templates/mailverification.mail.txt @@ -0,0 +1,10 @@ +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) }} +**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. + +Kind regards, +uffd diff --git a/uffd/selfservice/templates/self.html b/uffd/selfservice/templates/self.html index 6e89f8de..4f9756d0 100644 --- a/uffd/selfservice/templates/self.html +++ b/uffd/selfservice/templates/self.html @@ -25,7 +25,7 @@ <label for="user-password1">password</label> <input type="password" class="form-control" id="user-password1" name="password1" placeholder="do not change"> <small class="form-text text-muted"> - No special requirements but please don't be stupid and use a password manager. + At least 8 characters, no other special requirements. But please don't be stupid and use a password manager. </small> </div> <div class="form-group col-md-6"> diff --git a/uffd/selfservice/views.py b/uffd/selfservice/views.py index ff823e40..04908696 100644 --- a/uffd/selfservice/views.py +++ b/uffd/selfservice/views.py @@ -10,7 +10,7 @@ from uffd.csrf import csrf_protect from uffd.user.models import User, Group from uffd.session import get_current_user, login_required, is_valid_session from uffd.ldap import get_conn, escape_filter_chars, loginname_to_dn -from uffd.selfservice.models import PasswordToken +from uffd.selfservice.models import PasswordToken, MailToken from uffd.database import db bp = Blueprint("selfservice", __name__, template_folder='templates', url_prefix='/self/') @@ -25,8 +25,25 @@ def self_index(): @csrf_protect(blueprint=bp) @login_required() def self_update(): - # TODO: actualy update the user... - return 'OK', 200 + user = get_current_user() + if request.values['displayname'] != user.displayname: + if user.set_displayname(request.values['displayname']): + flash('Display name changed.') + else: + flash('Display name is not valid.') + if request.values['password1']: + if not request.values['password1'] == request.values['password2']: + flash('Passwords do not match') + else: + if user.set_password(request.values['password1']): + flash('Password changed.') + else: + flash('Password could not be set.') + if request.values['mail'] != user.mail: + send_mail_verification(user.loginname, request.values['mail']) + flash('We sent you an email, please verify your mail address.') + user.to_ldap() + return redirect(url_for('.self_index')) @bp.route("/passwordreset", methods=(['GET', 'POST'])) @csrf_protect(blueprint=bp) @@ -38,7 +55,7 @@ def self_forgot_password(): mail = request.values['mail'] flash("We sent a mail to this users mail address if you entered the correct mail and login name combination") user = User.from_ldap_dn(loginname_to_dn(loginname)) - if user.mail == mail: + if user and user.mail == mail: send_passwordreset(loginname) return redirect(url_for('session.login')) @@ -72,6 +89,44 @@ def self_token_password(token): session.commit() return redirect(url_for('session.login')) +@bp.route("/token/mail_verification/<token>") +@login_required() +def self_token_mail(token): + session = db.session + dbtoken = MailToken.query.get(token) + if not dbtoken or dbtoken.created < (datetime.datetime.now() - datetime.timedelta(days=2)): + flash('Token expired, please try again.') + if dbtoken: + session.delete(dbtoken) + session.commit() + return redirect(url_for('.self_index')) + + user = User.from_ldap_dn(loginname_to_dn(dbtoken.loginname)) + user.set_mail(dbtoken.newmail) + user.to_ldap() + flash('New mail set') + session.delete(dbtoken) + session.commit() + return redirect(url_for('.self_index')) + +def send_mail_verification(loginname, newmail): + session = db.session + expired_tokens = MailToken.query.filter(MailToken.created < (datetime.datetime.now() - datetime.timedelta(days=2))).all() + for i in expired_tokens: + session.delete(i) + token = MailToken() + token.loginname = loginname + token.newmail = newmail + session.add(token) + session.commit() + + user = User.from_ldap_dn(loginname_to_dn(loginname)) + + msg = EmailMessage() + msg.set_content(render_template('mailverification.mail.txt', user=user, token=token.token)) + msg['Subject'] = 'Mail verification' + send_mail(newmail, msg) + def send_passwordreset(loginname): session = db.session expired_tokens = PasswordToken.query.filter(PasswordToken.created < (datetime.datetime.now() - datetime.timedelta(days=2))).all() diff --git a/uffd/templates/base.html b/uffd/templates/base.html index bc28ec2f..7b553a8c 100644 --- a/uffd/templates/base.html +++ b/uffd/templates/base.html @@ -85,7 +85,7 @@ <div class="container mt-2"> <div class="row"> {% for message in get_flashed_messages() %} - <div class="alert alert-primary col" role="alert">{{ message }}</div> + <div class="alert alert-primary col-12" role="alert">{{ message }}</div> {% endfor %} </div> </div> diff --git a/uffd/user/models.py b/uffd/user/models.py index 89918335..f00dffaa 100644 --- a/uffd/user/models.py +++ b/uffd/user/models.py @@ -106,7 +106,16 @@ class User(): return True def set_password(self, value): + if len(value) < 8: + return False self.newpassword = value + return True + + def set_mail(self, value): + if len(value) < 3 or '@' not in value: + return False + self.mail = value + return True class Group(): gid = None diff --git a/uffd/user/templates/user.html b/uffd/user/templates/user.html index e25d37ba..0fa6163c 100644 --- a/uffd/user/templates/user.html +++ b/uffd/user/templates/user.html @@ -39,7 +39,7 @@ <input type="password" class="form-control" id="user-password" name="password" placeholder="mail to set it will be sent" readonly> {% endif %} <small class="form-text text-muted"> - No special requirements but please don't be stupid and use a password manager. + At least 8 characters, no other special requirements. But please don't be stupid and use a password manager. </small> </div> <div class="form-group col "id="accordion"> -- GitLab