Skip to content
Snippets Groups Projects
Verified Commit 8be0b378 authored by nd's avatar nd
Browse files

add basic password reset, missing mail sending

parent 6957cded
No related branches found
No related tags found
No related merge requests found
import datetime
import secrets
from sqlalchemy import Column, Integer, String, Text, LargeBinary, DateTime, Boolean, ForeignKey
from uffd.database import db
def random_token():
return secrets.token_hex(128)
class Token():
token = Column(String(128), primary_key=True, default=random_token)
created = Column(DateTime, default=datetime.datetime.now)
class PasswordToken(Token, db.Model):
__tablename__ = 'passwortToken'
loginname = Column(String(32))
class MailToken(Token, db.Model):
__tablename__ = 'mailToken'
loginname = Column(String(32))
newmail = Column(String(255))
{% extends 'base.html' %}
{% block body %}
<form action="{{ url_for(".self_token_password", token=token) }}" method="POST" onInput="password2.setCustomValidity(password1.value != password2.value ? 'Passwords do not match.' : '') ">
<div class="row mt-2 justify-content-center">
<div class="col-lg-6 col-md-10" style="background: #f7f7f7; box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3); padding: 30px;">
<div class="text-center">
<img src="{{ url_for("static", filename="chaosknoten.png") }}" class="col-lg-8 col-md-12" >
</div>
<div class="col-12">
<h2 class="text-center">Reset password</h2>
</div>
<div class="form-group col-12">
<label for="user-loginname">login name</label>
<input type="text" class="form-control" id="user-loginname" name="loginname" required="required" tabindex = "1">
</div>
<div class="form-group col-12">
<label for="user-password1">new password</label>
<input type="password" class="form-control" id="user-password1" name="password1" required="required" tabindex = "2">
</div>
<div class="form-group col-12">
<label for="user-password2">new password again</label>
<input type="password" class="form-control" id="user-password2" name="password2" required="required" tabindex = "2">
</div>
<div class="form-group col-12">
<button type="submit" class="btn btn-primary btn-block" tabindex = "3">Set password</button>
</div>
</div>
</div>
</form>
{% endblock %}
import datetime
from flask import Blueprint, render_template, request, url_for, redirect, flash, current_app from flask import Blueprint, render_template, request, url_for, redirect, flash, current_app
from uffd.navbar import register_navbar from uffd.navbar import register_navbar
from uffd.csrf import csrf_protect from uffd.csrf import csrf_protect
from uffd.user.models import User, Group from uffd.user.models import User, Group
from uffd.session import get_current_user, login_required, is_valid_session from uffd.session import get_current_user, login_required, is_valid_session
from uffd.ldap import get_conn, escape_filter_chars from uffd.ldap import get_conn, escape_filter_chars, loginname_to_dn
from uffd.selfservice.models import PasswordToken
from uffd.database import db
bp = Blueprint("selfservice", __name__, template_folder='templates', url_prefix='/self/') bp = Blueprint("selfservice", __name__, template_folder='templates', url_prefix='/self/')
@bp.before_request
@login_required()
def self_acl():
pass
#if not self_acl_check():
# flash('Access denied')
# return redirect(url_for('index'))
def self_acl_check():
return is_valid_session() and get_current_user().is_in_group(current_app.config['ACL_SELFSERVICE_GROUP'])
@bp.route("/") @bp.route("/")
@register_navbar('Selfservice', icon='portrait', blueprint=bp, visible=is_valid_session) @register_navbar('Selfservice', icon='portrait', blueprint=bp, visible=is_valid_session)
@login_required()
def self_index(): def self_index():
return render_template('self.html', user=get_current_user()) return render_template('self.html', user=get_current_user())
@bp.route("/update", methods=(['POST'])) @bp.route("/update", methods=(['POST']))
@csrf_protect(blueprint=bp) @csrf_protect(blueprint=bp)
@login_required()
def self_update(): def self_update():
pass # TODO: actualy update the user...
send_passwordreset('uffdtest')
return 'OK', 200
@bp.route("/token/password/<token>", methods=(['POST', 'GET']))
def self_token_password(token):
session = db.session
dbtoken = PasswordToken.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('session.login'))
if not 'loginname' in request.values:
flash('Please set a new password.')
return render_template('reset_password.html', token=token)
else:
if not request.values['loginname'] == dbtoken.loginname:
flash('That is not the correct login name. Please start the password reset process again')
session.delete(dbtoken)
session.commit()
return redirect(url_for('session.login'))
if not request.values['password1']:
flash('Please specify a new password.')
return render_template('reset_password.html', token=token)
user = User.from_ldap_dn(loginname_to_dn(dbtoken.loginname))
user.set_password(request.values['password1'])
user.to_ldap()
flash('New password set')
session.delete(dbtoken)
session.commit()
return redirect(url_for('session.login'))
def send_passwordreset(loginname):
session = db.session
expired_tokens = PasswordToken.query.filter(PasswordToken.created < (datetime.datetime.now() - datetime.timedelta(days=2))).all()
for i in expired_tokens:
session.delete(i)
token = PasswordToken()
token.loginname = loginname
session.add(token)
# TODO: send mail
session.commit()
...@@ -41,7 +41,7 @@ class User(): ...@@ -41,7 +41,7 @@ class User():
return None return None
return User.from_ldap(conn.entries[0]) return User.from_ldap(conn.entries[0])
def to_ldap(self, new): def to_ldap(self, new=False):
conn = ldap.get_conn() conn = ldap.get_conn()
if new: if new:
attributes= { attributes= {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment