From 72092da6e1efb8f707d01605a62bbb360537ab39 Mon Sep 17 00:00:00 2001 From: Julian Rother <julianr@fsmpi.rwth-aachen.de> Date: Tue, 23 Feb 2021 21:54:15 +0100 Subject: [PATCH] Implemented flask-sqlalchemy-style query functions and refactored code with them --- deps/ldapalchemy | 2 +- uffd/ldap.py | 20 +++++++++++++++++++- uffd/mail/views.py | 6 +++--- uffd/mfa/models.py | 3 +++ uffd/mfa/views.py | 2 +- uffd/selfservice/views.py | 8 ++++---- uffd/user/views_group.py | 2 +- uffd/user/views_user.py | 6 +++--- 8 files changed, 35 insertions(+), 14 deletions(-) diff --git a/deps/ldapalchemy b/deps/ldapalchemy index db135ec7..d2c13338 160000 --- a/deps/ldapalchemy +++ b/deps/ldapalchemy @@ -1 +1 @@ -Subproject commit db135ec7a4940a384e82a4500cfb0e73ecd2f557 +Subproject commit d2c133381a8e536ee433e5ab305fc24146c0feb9 diff --git a/uffd/ldap.py b/uffd/ldap.py index 237271e7..67e627c9 100644 --- a/uffd/ldap.py +++ b/uffd/ldap.py @@ -1,12 +1,30 @@ -from flask import current_app, request +from flask import current_app, request, abort import ldap3 from ldapalchemy import LDAPMapper, LDAPCommitError # pylint: disable=unused-import +from ldapalchemy.model import Query + +class FlaskQuery(Query): + def get_or_404(self, dn): + res = self.get(dn) + if res is None: + abort(404) + return res + + def first_or_404(self): + res = self.first() + if res is None: + abort(404) + return res class FlaskLDAPMapper(LDAPMapper): def __init__(self): super().__init__() + class Model(self.Model): + query_class = FlaskQuery + + self.Model = Model # pylint: disable=invalid-name @property def session(self): diff --git a/uffd/mail/views.py b/uffd/mail/views.py index d7b68782..2aaebf55 100644 --- a/uffd/mail/views.py +++ b/uffd/mail/views.py @@ -28,7 +28,7 @@ def index(): def show(uid=None): mail = Mail() if uid is not None: - mail = Mail.query.filter_by(uid=uid)[0] + mail = Mail.query.filter_by(uid=uid).first_or_404() return render_template('mail.html', mail=mail) @bp.route("/<uid>/update", methods=['POST']) @@ -36,7 +36,7 @@ def show(uid=None): @csrf_protect(blueprint=bp) def update(uid=None): if uid is not None: - mail = Mail.query.filter_by(uid=uid)[0] + mail = Mail.query.filter_by(uid=uid).first_or_404() else: mail = Mail(uid=request.form.get('mail-uid')) mail.receivers = request.form.get('mail-receivers', '').splitlines() @@ -49,7 +49,7 @@ def update(uid=None): @bp.route("/<uid>/del") @csrf_protect(blueprint=bp) def delete(uid): - mail = Mail.query.filter_by(uid=uid)[0] + mail = Mail.query.filter_by(uid=uid).first_or_404() ldap.session.delete(mail) ldap.session.commit() flash('Deleted mail mapping.') diff --git a/uffd/mfa/models.py b/uffd/mfa/models.py index 89879889..e525a378 100644 --- a/uffd/mfa/models.py +++ b/uffd/mfa/models.py @@ -44,6 +44,7 @@ class MFAMethod(db.Model): class RecoveryCodeMethod(MFAMethod): code_salt = Column('recovery_salt', String(64)) code_hash = Column('recovery_hash', String(256)) + user = DBRelationship('dn', User, backref='mfa_recovery_codes') __mapper_args__ = { 'polymorphic_identity': MFAType.RECOVERY_CODE @@ -76,6 +77,7 @@ def _hotp(counter, key, digits=6): class TOTPMethod(MFAMethod): key = Column('totp_key', String(64)) + user = DBRelationship('dn', User, backref='mfa_totp_methods') __mapper_args__ = { 'polymorphic_identity': MFAType.TOTP @@ -124,6 +126,7 @@ class TOTPMethod(MFAMethod): class WebauthnMethod(MFAMethod): _cred = Column('webauthn_cred', Text()) + user = DBRelationship('dn', User, backref='mfa_webauthn_methods') __mapper_args__ = { 'polymorphic_identity': MFAType.WEBAUTHN diff --git a/uffd/mfa/views.py b/uffd/mfa/views.py index 3ce9a9f0..f7a3e239 100644 --- a/uffd/mfa/views.py +++ b/uffd/mfa/views.py @@ -46,7 +46,7 @@ def admin_disable(uid): if not get_current_user().is_in_group(current_app.config['ACL_ADMIN_GROUP']): flash('Access denied') return redirect(url_for('index')) - user = User.query.filter_by(uid=uid)[0] + user = User.query.filter_by(uid=uid).one() MFAMethod.query.filter_by(dn=user.dn).delete() db.session.commit() flash('Two-factor authentication was reset') diff --git a/uffd/selfservice/views.py b/uffd/selfservice/views.py index 4ba81514..40dc49e0 100644 --- a/uffd/selfservice/views.py +++ b/uffd/selfservice/views.py @@ -67,7 +67,7 @@ def forgot_password(): reset_ratelimit.log(loginname+'/'+mail) host_ratelimit.log() flash("We sent a mail to this users mail address if you entered the correct mail and login name combination") - user = (User.query.filter_by(loginname=loginname) or [None])[0] + user = User.query.filter_by(loginname=loginname).one_or_none() if user and user.mail == mail: send_passwordreset(user) return redirect(url_for('session.login')) @@ -89,7 +89,7 @@ def token_password(token): if not request.values['password1'] == request.values['password2']: flash('Passwords do not match, please try again.') return render_template('set_password.html', token=token) - user = User.query.filter_by(loginname=dbtoken.loginname)[0] + user = User.query.filter_by(loginname=dbtoken.loginname).one() if not user.set_password(request.values['password1']): flash('Password ist not valid, please try again.') return render_template('set_password.html', token=token) @@ -110,7 +110,7 @@ def token_mail(token): db.session.commit() return redirect(url_for('selfservice.index')) - user = User.query.filter_by(loginname=dbtoken.loginname)[0] + user = User.query.filter_by(loginname=dbtoken.loginname).one() user.set_mail(dbtoken.newmail) flash('New mail set') db.session.delete(dbtoken) @@ -129,7 +129,7 @@ def send_mail_verification(loginname, newmail): db.session.add(token) db.session.commit() - user = User.query.filter_by(loginname=loginname)[0] + user = User.query.filter_by(loginname=loginname).one() msg = EmailMessage() msg.set_content(render_template('mailverification.mail.txt', user=user, token=token.token)) diff --git a/uffd/user/views_group.py b/uffd/user/views_group.py index d4e77741..22fdd9e9 100644 --- a/uffd/user/views_group.py +++ b/uffd/user/views_group.py @@ -23,4 +23,4 @@ def index(): @bp.route("/<int:gid>") def show(gid): - return render_template('group.html', group=Group.query.filter_by(gid=gid)[0]) + return render_template('group.html', group=Group.query.filter_by(gid=gid).first_or_404()) diff --git a/uffd/user/views_user.py b/uffd/user/views_user.py index 18b380b0..78ad85c2 100644 --- a/uffd/user/views_user.py +++ b/uffd/user/views_user.py @@ -32,7 +32,7 @@ def index(): @bp.route("/<int:uid>") @bp.route("/new") def show(uid=None): - user = User() if uid is None else User.query.filter_by(uid=uid)[0] + user = User() if uid is None else User.query.filter_by(uid=uid).first_or_404() return render_template('user.html', user=user, roles=Role.query.all()) @bp.route("/<int:uid>/update", methods=['POST']) @@ -45,7 +45,7 @@ def update(uid=None): flash('Login name does not meet requirements') return redirect(url_for('user.show')) else: - user = User.query.filter_by(uid=uid)[0] + user = User.query.filter_by(uid=uid).first_or_404() if not user.set_mail(request.form['mail']): flash('Mail is invalid') return redirect(url_for('user.show', uid=uid)) @@ -74,7 +74,7 @@ def update(uid=None): @bp.route("/<int:uid>/del") @csrf_protect(blueprint=bp) def delete(uid): - user = User.query.filter_by(uid=uid)[0] + user = User.query.filter_by(uid=uid).first_or_404() user.roles.clear() ldap.session.delete(user) ldap.session.commit() -- GitLab