diff --git a/deps/ldapalchemy b/deps/ldapalchemy index db135ec7a4940a384e82a4500cfb0e73ecd2f557..d2c133381a8e536ee433e5ab305fc24146c0feb9 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 237271e7e004d7103f3b4966a5b4a46f98b5d297..67e627c9eb99787dd856997afe20ae8498d3ba2c 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 d7b68782650127a14c4c9033df88fe08db0c1462..2aaebf559f44465c17ac6bde67796047b48d86e9 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 898798897e9fd50cffabc4ff450b97e2864854d0..e525a3782551efca3a51d14a71d4cc31f8c2d5f8 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 3ce9a9f0f5dcb739e7732ad1db4b586415910503..f7a3e239c6394471543baf940dbbaa9c01de45f4 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 4ba815143e6aec26d1732db69d2b9c2310ee3ea8..40dc49e010832ed5c5d1d1add343842ad6f2eb61 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 d4e777417eb0891bee30972eee303f587ac59f11..22fdd9e9d9def67a36fb5c18e2351878e61ebc0f 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 18b380b021521813abcc049682a7abc3705456ca..78ad85c26074927d79dda1fbb123f0f972125690 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()