diff --git a/uffd/selfservice/templates/mailverification.mail.txt b/uffd/selfservice/templates/mailverification.mail.txt new file mode 100644 index 0000000000000000000000000000000000000000..e9ff7e3134e0a3484098bf8c72bea4f4d6190fcc --- /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 6e89f8de01347f3d2c928520df69f877c49795b8..4f9756d0d724f636e90413e2589bd967fde2d809 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 ff823e40f4a764529d15a27136f27b73e2a593a3..04908696e9dfd9a298a61275a538fc635fe7b5fd 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 bc28ec2fd012260918fcca83c37cd50d6cd42518..7b553a8c40eada32c6e6a28dd17cab35a8c74d25 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 899183358c2e52eaae2aef69c340c219a11fb5dd..f00dffaa393cea0b7b21afb8e78b78cb9bb60b92 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 e25d37baccf2bc8c1cc494a277b9254e3102abdd..0fa6163c122f05658609168c1773d6f456ea939a 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">