From e6df5bbe71f5a8ee9b4dcc9f34c35b9db8585f26 Mon Sep 17 00:00:00 2001 From: Julian Rother <julian@cccv.de> Date: Sat, 4 Sep 2021 14:25:15 +0200 Subject: [PATCH] Refactor permission checking and differenciate login and selfservice access Fixes #104. Replaced "group" keyword argument for login_required with "permission_check". Most views already define a *_acl_check function that returns whether the current user has the required permissions for use with register_navbar. The same function can now be passed to login_required as the "permission_check" argument. Differenciated login and selfservice access permissions. Previously ACL_SELFSERVICE_GROUP was required to login. Now ACL_ACCESS_GROUP is required to login and ACL_SELFSERVICE_GROUP is required to access selfservice functions (and to use role-granting invite links). A user with just ACL_ACCESS_GROUP can now login, access the services overview page and authenticate with OAuth2 services he has access to, but not change his user attributes, password or roles/permissions. --- tests/test_mfa.py | 17 ++++ tests/test_selfservice.py | 5 +- tests/test_session.py | 4 +- tests/test_signup.py | 9 ++ uffd/__init__.py | 2 + uffd/default_config.cfg | 3 + uffd/invite/views.py | 29 ++---- uffd/mail/views.py | 12 +-- uffd/role/views.py | 13 ++- uffd/selfservice/views.py | 19 ++-- uffd/session/views.py | 8 +- uffd/translations/de/LC_MESSAGES/messages.mo | Bin 31578 -> 31578 bytes uffd/translations/de/LC_MESSAGES/messages.po | 100 +++++++++---------- uffd/user/views_group.py | 12 +-- uffd/user/views_user.py | 13 ++- 15 files changed, 138 insertions(+), 108 deletions(-) diff --git a/tests/test_mfa.py b/tests/test_mfa.py index 0157ad53..e12469b1 100644 --- a/tests/test_mfa.py +++ b/tests/test_mfa.py @@ -8,6 +8,7 @@ from flask import url_for, session, request from uffd import ldap, user from uffd.user.models import User +from uffd.role.models import Role, RoleGroup from uffd.mfa.models import MFAMethod, MFAType, RecoveryCodeMethod, TOTPMethod, WebauthnMethod, _hotp from uffd import create_app, db @@ -155,6 +156,10 @@ class TestMfaViews(UffdTestCase): self.assertEqual(r.status_code, 200) def test_disable(self): + baserole = Role(name='baserole', is_default=True) + db.session.add(baserole) + baserole.groups[self.get_access_group()] = RoleGroup() + db.session.commit() self.login_as('user') self.add_recovery_codes() self.add_totp() @@ -169,6 +174,10 @@ class TestMfaViews(UffdTestCase): self.assertEqual(len(MFAMethod.query.filter_by(dn=self.get_admin().dn).all()), admin_methods) def test_disable_recovery_only(self): + baserole = Role(name='baserole', is_default=True) + db.session.add(baserole) + baserole.groups[self.get_access_group()] = RoleGroup() + db.session.commit() self.login_as('user') self.add_recovery_codes() admin_methods = len(MFAMethod.query.filter_by(dn=self.get_admin().dn).all()) @@ -227,6 +236,10 @@ class TestMfaViews(UffdTestCase): self.assertEqual(r.status_code, 200) def test_setup_totp_finish(self): + baserole = Role(name='baserole', is_default=True) + db.session.add(baserole) + baserole.groups[self.get_access_group()] = RoleGroup() + db.session.commit() self.login_as('user') self.add_recovery_codes() self.assertEqual(len(TOTPMethod.query.filter_by(dn=request.user.dn).all()), 0) @@ -273,6 +286,10 @@ class TestMfaViews(UffdTestCase): self.assertEqual(len(TOTPMethod.query.filter_by(dn=request.user.dn).all()), 0) def test_delete_totp(self): + baserole = Role(name='baserole', is_default=True) + db.session.add(baserole) + baserole.groups[self.get_access_group()] = RoleGroup() + db.session.commit() self.login_as('user') self.add_recovery_codes() self.add_totp() diff --git a/tests/test_selfservice.py b/tests/test_selfservice.py index c7c4b14c..bb5075b2 100644 --- a/tests/test_selfservice.py +++ b/tests/test_selfservice.py @@ -8,7 +8,7 @@ from uffd import ldap, user from uffd.selfservice.models import MailToken, PasswordToken from uffd.user.models import User -from uffd.role.models import Role +from uffd.role.models import Role, RoleGroup from uffd import create_app, db from utils import dump, UffdTestCase @@ -130,6 +130,9 @@ class TestSelfservice(UffdTestCase): def test_leave_role(self): if self.use_userconnection: self.skipTest('Leaving roles is not possible in user mode') + baserole = Role(name='baserole', is_default=True) + db.session.add(baserole) + baserole.groups[self.get_access_group()] = RoleGroup() role1 = Role(name='testrole1') role2 = Role(name='testrole2') db.session.add(role1) diff --git a/tests/test_session.py b/tests/test_session.py index 312a66b4..c7707ea3 100644 --- a/tests/test_session.py +++ b/tests/test_session.py @@ -23,12 +23,12 @@ class TestSession(UffdTestCase): return 'SUCCESS', 200 @self.app.route('/test_group_required1') - @login_required(group='users') + @login_required(lambda: request.user.is_in_group('users')) def test_group_required1(): return 'SUCCESS', 200 @self.app.route('/test_group_required2') - @login_required(group='notagroup') + @login_required(lambda: request.user.is_in_group('notagroup')) def test_group_required2(): return 'SUCCESS', 200 diff --git a/tests/test_signup.py b/tests/test_signup.py index 3b940131..f6b65275 100644 --- a/tests/test_signup.py +++ b/tests/test_signup.py @@ -11,6 +11,7 @@ from uffd.ldap import ldap from uffd import create_app, db from uffd.signup.models import Signup from uffd.user.models import User +from uffd.role.models import Role, RoleGroup from uffd.session.views import login_get_user from utils import dump, UffdTestCase, db_flush @@ -323,6 +324,10 @@ class TestSignupViews(UffdTestCase): self.assertEqual(r.json['status'], 'ratelimited') def test_confirm(self): + baserole = Role(name='baserole', is_default=True) + db.session.add(baserole) + baserole.groups[self.get_access_group()] = RoleGroup() + db.session.commit() signup = Signup(loginname='newuser', displayname='New User', mail='test@example.com', password='notsecret') signup = refetch_signup(signup) self.assertFalse(signup.completed) @@ -349,6 +354,10 @@ class TestSignupViews(UffdTestCase): self.assertEqual(request.user.loginname, 'newuser') def test_confirm_loggedin(self): + baserole = Role(name='baserole', is_default=True) + db.session.add(baserole) + baserole.groups[self.get_access_group()] = RoleGroup() + db.session.commit() signup = Signup(loginname='newuser', displayname='New User', mail='test@example.com', password='notsecret') signup = refetch_signup(signup) self.login_as('user') diff --git a/uffd/__init__.py b/uffd/__init__.py index 90feeafd..fffb779d 100644 --- a/uffd/__init__.py +++ b/uffd/__init__.py @@ -59,6 +59,8 @@ def create_app(test_config=None): # pylint: disable=too-many-locals for cfg_name in ["config.cfg", "config.json", "config.yml", "config.yaml"]: if load_config_file(app, cfg_name, silent=True): break + # Prior to v1.1 login required ACL_SELFSERVICE_GROUP and ACL_ACCESS_GROUP did not exist + app.config.setdefault('ACL_ACCESS_GROUP', app.config['ACL_SELFSERVICE_GROUP']) register_template_helper(app) setup_navbar(app) diff --git a/uffd/default_config.cfg b/uffd/default_config.cfg index e7ee0d62..1db33f35 100644 --- a/uffd/default_config.cfg +++ b/uffd/default_config.cfg @@ -60,7 +60,10 @@ LANGUAGES={ } ACL_ADMIN_GROUP="uffd_admin" +# Group required to access selfservice functions (view selfservice, change profile/password/roles) ACL_SELFSERVICE_GROUP="uffd_access" +# Group required to login +#ACL_ACCESS_GROUP="uffd_access" # if unset, the value of ACL_SELFSERVICE_GROUP is used # Members can create invite links for signup ACL_SIGNUP_GROUP="uffd_signup" diff --git a/uffd/invite/views.py b/uffd/invite/views.py index 65f4c51c..2c0b7f27 100644 --- a/uffd/invite/views.py +++ b/uffd/invite/views.py @@ -1,7 +1,6 @@ import datetime -import functools -from flask import Blueprint, render_template, request, redirect, url_for, flash, current_app, jsonify, abort +from flask import Blueprint, render_template, request, redirect, url_for, flash, current_app, jsonify from flask_babel import gettext as _, lazy_gettext import sqlalchemy @@ -16,10 +15,11 @@ from uffd.sendmail import sendmail from uffd.navbar import register_navbar from uffd.ratelimit import host_ratelimit, format_delay from uffd.signup.views import signup_ratelimit +from uffd.selfservice.views import selfservice_acl_check bp = Blueprint('invite', __name__, template_folder='templates', url_prefix='/invite/') -def invite_acl(): +def invite_acl_check(): if not request.user: return False if request.user.is_in_group(current_app.config['ACL_ADMIN_GROUP']): @@ -30,15 +30,6 @@ def invite_acl(): return True return False -def invite_acl_required(func): - @functools.wraps(func) - @login_required() - def decorator(*args, **kwargs): - if not invite_acl(): - abort(403) - return func(*args, **kwargs) - return decorator - def view_acl_filter(user): if user.is_in_group(current_app.config['ACL_ADMIN_GROUP']): return sqlalchemy.true() @@ -52,14 +43,14 @@ def reset_acl_filter(user): return Invite.creator_dn == user.dn @bp.route('/') -@register_navbar(14, lazy_gettext('Invites'), icon='link', blueprint=bp, visible=invite_acl) -@invite_acl_required +@register_navbar(14, lazy_gettext('Invites'), icon='link', blueprint=bp, visible=invite_acl_check) +@login_required(invite_acl_check) def index(): invites = Invite.query.filter(view_acl_filter(request.user)).all() return render_template('invite/list.html', invites=invites) @bp.route('/new') -@invite_acl_required +@login_required(invite_acl_check) def new(): if request.user.is_in_group(current_app.config['ACL_ADMIN_GROUP']): allow_signup = True @@ -70,7 +61,7 @@ def new(): return render_template('invite/new.html', roles=roles, allow_signup=allow_signup) @bp.route('/new', methods=['POST']) -@invite_acl_required +@login_required(invite_acl_check) @csrf_protect(blueprint=bp) def new_submit(): invite = Invite(creator=request.user, @@ -94,7 +85,7 @@ def new_submit(): return redirect(url_for('invite.index')) @bp.route('/<int:invite_id>/disable', methods=['POST']) -@invite_acl_required +@login_required(invite_acl_check) @csrf_protect(blueprint=bp) def disable(invite_id): invite = Invite.query.filter(view_acl_filter(request.user)).filter_by(id=invite_id).first_or_404() @@ -103,7 +94,7 @@ def disable(invite_id): return redirect(url_for('.index')) @bp.route('/<int:invite_id>/reset', methods=['POST']) -@invite_acl_required +@login_required(invite_acl_check) @csrf_protect(blueprint=bp) def reset(invite_id): invite = Invite.query.filter(reset_acl_filter(request.user)).filter_by(id=invite_id).first_or_404() @@ -120,7 +111,7 @@ def use(token): return render_template('invite/use.html', invite=invite) @bp.route('/<token>/grant', methods=['POST']) -@login_required() +@login_required(selfservice_acl_check) @csrf_protect(blueprint=bp) def grant(token): invite = Invite.query.filter_by(token=token).first_or_404() diff --git a/uffd/mail/views.py b/uffd/mail/views.py index 2e11905b..9f5f2e1d 100644 --- a/uffd/mail/views.py +++ b/uffd/mail/views.py @@ -1,4 +1,4 @@ -from flask import Blueprint, render_template, request, url_for, redirect, flash, current_app, abort +from flask import Blueprint, render_template, request, url_for, redirect, flash, current_app from flask_babel import gettext as _, lazy_gettext from uffd.navbar import register_navbar @@ -9,15 +9,15 @@ from uffd.session import login_required from uffd.mail.models import Mail bp = Blueprint("mail", __name__, template_folder='templates', url_prefix='/mail/') -@bp.before_request -@login_required() -def mail_acl(): - if not mail_acl_check(): - abort(403) def mail_acl_check(): return request.user and request.user.is_in_group(current_app.config['ACL_ADMIN_GROUP']) +@bp.before_request +@login_required(mail_acl_check) +def mail_acl(): + pass + @bp.route("/") @register_navbar(29, lazy_gettext('Forwardings'), icon='envelope', blueprint=bp, visible=mail_acl_check) def index(): diff --git a/uffd/role/views.py b/uffd/role/views.py index 0b3e827f..7261c63f 100644 --- a/uffd/role/views.py +++ b/uffd/role/views.py @@ -1,6 +1,6 @@ import sys -from flask import Blueprint, render_template, request, url_for, redirect, flash, current_app, abort +from flask import Blueprint, render_template, request, url_for, redirect, flash, current_app from flask_babel import gettext as _, lazy_gettext import click @@ -37,15 +37,14 @@ def add_cli_commands(state): print('Error: LDAP groups are not consistent with roles in database') sys.exit(1) -@bp.before_request -@login_required() -def role_acl(): - if not role_acl_check(): - abort(403) - def role_acl_check(): return request.user and request.user.is_in_group(current_app.config['ACL_ADMIN_GROUP']) +@bp.before_request +@login_required(role_acl_check) +def role_acl(): + pass + @bp.route("/") @register_navbar(25, lazy_gettext('Roles'), icon='key', blueprint=bp, visible=role_acl_check) def index(): diff --git a/uffd/selfservice/views.py b/uffd/selfservice/views.py index 1ee8c668..66274b98 100644 --- a/uffd/selfservice/views.py +++ b/uffd/selfservice/views.py @@ -18,15 +18,18 @@ bp = Blueprint("selfservice", __name__, template_folder='templates', url_prefix= reset_ratelimit = Ratelimit('passwordreset', 1*60*60, 3) +def selfservice_acl_check(): + return request.user and request.user.is_in_group(current_app.config['ACL_SELFSERVICE_GROUP']) + @bp.route("/") -@register_navbar(0, lazy_gettext('Selfservice'), icon='portrait', blueprint=bp, visible=lambda: bool(request.user)) -@login_required() +@register_navbar(0, lazy_gettext('Selfservice'), icon='portrait', blueprint=bp, visible=selfservice_acl_check) +@login_required(selfservice_acl_check) def index(): return render_template('selfservice/self.html', user=request.user) @bp.route("/updateprofile", methods=(['POST'])) @csrf_protect(blueprint=bp) -@login_required() +@login_required(selfservice_acl_check) def update_profile(): user = request.user if request.values['displayname'] != user.displayname: @@ -42,7 +45,7 @@ def update_profile(): @bp.route("/changepassword", methods=(['POST'])) @csrf_protect(blueprint=bp) -@login_required() +@login_required(selfservice_acl_check) def change_password(): password_changed = False user = request.user @@ -79,7 +82,7 @@ def forgot_password(): host_ratelimit.log() flash(_("We sent a mail to this user's mail address if you entered the correct mail and login name combination")) user = User.query.filter_by(loginname=loginname).one_or_none() - if user and user.mail == mail: + if user and user.mail == mail and user.is_in_group(current_app.config['ACL_SELFSERVICE_GROUP']): send_passwordreset(user) return redirect(url_for('session.login')) @@ -101,6 +104,8 @@ def token_password(token): flash(_('Passwords do not match, please try again.')) return render_template('selfservice/set_password.html', token=token) user = User.query.filter_by(loginname=dbtoken.loginname).one() + if not user.is_in_group(current_app.config['ACL_SELFSERVICE_GROUP']): + abort(403) if not user.set_password(request.values['password1']): flash(_('Password ist not valid, please try again.')) return render_template('selfservice/set_password.html', token=token) @@ -111,7 +116,7 @@ def token_password(token): return redirect(url_for('session.login')) @bp.route("/token/mail_verification/<token>") -@login_required() +@login_required(selfservice_acl_check) def token_mail(token): dbtoken = MailToken.query.get(token) if not dbtoken or dbtoken.created < (datetime.datetime.now() - datetime.timedelta(days=2)): @@ -133,7 +138,7 @@ def token_mail(token): @bp.route("/leaverole/<int:roleid>", methods=(['POST'])) @csrf_protect(blueprint=bp) -@login_required() +@login_required(selfservice_acl_check) def leave_role(roleid): if not current_app.config['ENABLE_ROLESELFSERVICE']: flash(_('Leaving roles is disabled')) diff --git a/uffd/session/views.py b/uffd/session/views.py index 5e8433b0..76a5d660 100644 --- a/uffd/session/views.py +++ b/uffd/session/views.py @@ -28,6 +28,8 @@ def set_request_user(): if datetime.datetime.now().timestamp() > session['logintime'] + current_app.config['SESSION_LIFETIME_SECONDS']: return user = User.query.get(session['user_dn']) + if not user.is_in_group(current_app.config['ACL_ACCESS_GROUP']): + return request.user_pre_mfa = user if session.get('user_mfa'): request.user = user @@ -100,7 +102,7 @@ def login(): host_ratelimit.log() flash(_('Login name or password is wrong')) return render_template('session/login.html', ref=request.values.get('ref')) - if not user.is_in_group(current_app.config['ACL_SELFSERVICE_GROUP']): + if not user.is_in_group(current_app.config['ACL_ACCESS_GROUP']): flash(_('You do not have access to this service')) return render_template('session/login.html', ref=request.values.get('ref')) set_session(user, password=password) @@ -119,7 +121,7 @@ def login_required_pre_mfa(no_redirect=False): return decorator return wrapper -def login_required(group=None): +def login_required(permission_check=lambda: True): def wrapper(func): @functools.wraps(func) def decorator(*args, **kwargs): @@ -128,7 +130,7 @@ def login_required(group=None): return redirect(url_for('session.login', ref=request.full_path)) if not request.user: return redirect(url_for('mfa.auth', ref=request.full_path)) - if not request.user.is_in_group(group): + if not permission_check(): abort(403) return func(*args, **kwargs) return decorator diff --git a/uffd/translations/de/LC_MESSAGES/messages.mo b/uffd/translations/de/LC_MESSAGES/messages.mo index 73bf24fe50496a1513b4d3dd910f143915714e7a..9a19ad476f876ce75968e81163d0743da932f670 100644 GIT binary patch delta 19 acmcchjq%nu#tn8(EQVGFMw^|SBrE|~M+Ynb delta 19 acmcchjq%nu#tn8(ECyC4=9`_IBrE|~cn359 diff --git a/uffd/translations/de/LC_MESSAGES/messages.po b/uffd/translations/de/LC_MESSAGES/messages.po index da0a5199..a1673d29 100644 --- a/uffd/translations/de/LC_MESSAGES/messages.po +++ b/uffd/translations/de/LC_MESSAGES/messages.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2021-09-05 00:47+0200\n" +"POT-Creation-Date: 2021-09-05 01:02+0200\n" "PO-Revision-Date: 2021-05-25 21:18+0200\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language: de\n" @@ -44,54 +44,54 @@ msgstr "eine Stunde" msgid "%(hours)d hours" msgstr "%(hours)d Stunden\"" -#: uffd/invite/views.py:55 +#: uffd/invite/views.py:46 msgid "Invites" msgstr "Einladungslinks" -#: uffd/invite/views.py:84 +#: uffd/invite/views.py:75 msgid "The \"Expires After\" date is too far in the future" msgstr "Das Ablaufdatum liegt zu weit in der Zukunft" -#: uffd/invite/views.py:87 +#: uffd/invite/views.py:78 msgid "You are not allowed to create invite links with these permissions" msgstr "Dir fehlen Berechtigungen um diesen Einladungslink zu erstellen" -#: uffd/invite/views.py:90 +#: uffd/invite/views.py:81 msgid "Invite link must either allow signup or grant at least one role" msgstr "" "Einladungslink muss entweder Account-Registrierung erlauben oder Rollen " "vergeben" -#: uffd/invite/views.py:118 uffd/invite/views.py:147 +#: uffd/invite/views.py:109 uffd/invite/views.py:138 msgid "Invalid invite link" msgstr "Ungültiger Einladungslink" -#: uffd/invite/views.py:135 +#: uffd/invite/views.py:126 msgid "Roles successfully updated" msgstr "Rollen erfolgreich geändert" -#: uffd/invite/views.py:150 +#: uffd/invite/views.py:141 msgid "Invite link does not allow signup" msgstr "Einladungslink erlaubt keine Account-Registrierung" -#: uffd/invite/views.py:172 uffd/selfservice/views.py:50 +#: uffd/invite/views.py:163 uffd/selfservice/views.py:53 #: uffd/signup/views.py:49 msgid "Passwords do not match" msgstr "Die Passwörter stimmen nicht überein" -#: uffd/invite/views.py:177 uffd/signup/views.py:54 +#: uffd/invite/views.py:168 uffd/signup/views.py:54 #, python-format msgid "Too many signup requests with this mail address! Please wait %(delay)s." msgstr "" "Zu viele Account-Registrierungen mit dieser E-Mail-Adresse! Bitte warte " "%(delay)s." -#: uffd/invite/views.py:179 uffd/signup/views.py:56 uffd/signup/views.py:92 +#: uffd/invite/views.py:170 uffd/signup/views.py:56 uffd/signup/views.py:92 #, python-format msgid "Too many requests! Please wait %(delay)s." msgstr "Zu viele Anfragen! Bitte warte %(delay)s." -#: uffd/invite/views.py:192 uffd/signup/views.py:68 +#: uffd/invite/views.py:183 uffd/signup/views.py:68 msgid "Cound not send mail" msgstr "Mailversand fehlgeschlagen" @@ -704,8 +704,8 @@ msgstr "Verifiziere und beende das Setup" msgid "You need to login to access this service" msgstr "Du musst dich anmelden, um auf diesen Dienst zugreifen zu können" -#: uffd/oauth2/views.py:140 uffd/selfservice/views.py:76 -#: uffd/session/views.py:95 +#: uffd/oauth2/views.py:140 uffd/selfservice/views.py:79 +#: uffd/session/views.py:97 #, python-format msgid "" "We received too many requests from your ip address/network! Please wait " @@ -773,13 +773,13 @@ msgstr "" "Automatisches Abmelden bei einigen Diensten fehlgeschlagen. Nochmal " "versuchen?" -#: uffd/role/views.py:50 uffd/selfservice/templates/selfservice/self.html:86 +#: uffd/role/views.py:49 uffd/selfservice/templates/selfservice/self.html:86 #: uffd/user/templates/user/list.html:20 uffd/user/templates/user/show.html:21 #: uffd/user/templates/user/show.html:90 msgid "Roles" msgstr "Rollen" -#: uffd/role/views.py:100 +#: uffd/role/views.py:99 msgid "Locked roles cannot be deleted" msgstr "Gesperrte Rollen können nicht gelöscht werden" @@ -907,31 +907,31 @@ msgstr "Mitglieder:" msgid "Remove" msgstr "Entfernen" -#: uffd/selfservice/views.py:22 +#: uffd/selfservice/views.py:25 msgid "Selfservice" msgstr "Selfservice" -#: uffd/selfservice/views.py:34 +#: uffd/selfservice/views.py:37 msgid "Display name changed." msgstr "Anzeigename geändert." -#: uffd/selfservice/views.py:36 +#: uffd/selfservice/views.py:39 msgid "Display name is not valid." msgstr "Anzeigename ist nicht valide." -#: uffd/selfservice/views.py:39 +#: uffd/selfservice/views.py:42 msgid "We sent you an email, please verify your mail address." msgstr "Wir haben dir eine E-Mail gesendet, bitte prüfe deine E-Mail-Adresse." -#: uffd/selfservice/views.py:53 +#: uffd/selfservice/views.py:56 msgid "Password changed" msgstr "Passwort geändert" -#: uffd/selfservice/views.py:56 +#: uffd/selfservice/views.py:59 msgid "Invalid password" msgstr "Passwort ungültig" -#: uffd/selfservice/views.py:74 +#: uffd/selfservice/views.py:77 #, python-format msgid "" "We received too many password reset requests for this user! Please wait " @@ -940,7 +940,7 @@ msgstr "" "Wir haben zu viele fehlgeschlagene Anmeldeversuche für diesen Account! " "Bitte warte mindestens %(delay)s." -#: uffd/selfservice/views.py:80 +#: uffd/selfservice/views.py:83 msgid "" "We sent a mail to this user's mail address if you entered the correct " "mail and login name combination" @@ -948,27 +948,27 @@ msgstr "" "Falls E-Mail-Adresse und Anmeldename richtig waren, wurde eine E-Mail an " "die Adresse gesendet." -#: uffd/selfservice/views.py:90 uffd/selfservice/views.py:118 +#: uffd/selfservice/views.py:93 uffd/selfservice/views.py:123 msgid "Token expired, please try again." msgstr "Link abgelaufen, bitte versuche es erneut." -#: uffd/selfservice/views.py:98 +#: uffd/selfservice/views.py:101 msgid "You need to set a password, please try again." msgstr "Password fehlt, bitte versuche es erneut." -#: uffd/selfservice/views.py:101 +#: uffd/selfservice/views.py:104 msgid "Passwords do not match, please try again." msgstr "Die Passwörter stimmen nicht überein, bitte versuche es erneut" -#: uffd/selfservice/views.py:105 +#: uffd/selfservice/views.py:110 msgid "Password ist not valid, please try again." msgstr "Ungültiges Passwort, bitte versuche es erneut" -#: uffd/selfservice/views.py:108 +#: uffd/selfservice/views.py:113 msgid "New password set" msgstr "Passwort geändert" -#: uffd/selfservice/views.py:126 +#: uffd/selfservice/views.py:131 msgid "" "This link was generated for another user. Login as the correct user to " "continue." @@ -976,20 +976,20 @@ msgstr "" "Dieser Link wurde für einen anderen Account erstellt. Melde dich mit dem " "richtigen Account an um Fortzufahren." -#: uffd/selfservice/views.py:128 +#: uffd/selfservice/views.py:133 msgid "New mail set" msgstr "E-Mail-Adresse geändert" -#: uffd/selfservice/views.py:139 +#: uffd/selfservice/views.py:144 msgid "Leaving roles is disabled" msgstr "Verlassen von Rollen ist deaktiviert" -#: uffd/selfservice/views.py:146 +#: uffd/selfservice/views.py:151 #, python-format msgid "You left role %(role_name)s" msgstr "Rolle %(role_name)s verlassen" -#: uffd/selfservice/views.py:163 uffd/selfservice/views.py:183 +#: uffd/selfservice/views.py:168 uffd/selfservice/views.py:188 #, python-format msgid "Mail to \"%(mail_address)s\" could not be sent!" msgstr "E-Mail an \"%(mail_address)s\" konnte nicht gesendet werden!" @@ -1182,7 +1182,7 @@ msgstr "Kein Zugriff" msgid "Close" msgstr "Schließen" -#: uffd/session/views.py:93 +#: uffd/session/views.py:95 #, python-format msgid "" "We received too many invalid login attempts for this user! Please wait at" @@ -1191,27 +1191,27 @@ msgstr "" "Wir haben zu viele fehlgeschlagene Anmeldeversuche für diesen Account " "erhalten! Bitte warte mindestens %(delay)s." -#: uffd/session/views.py:101 +#: uffd/session/views.py:103 msgid "Login name or password is wrong" msgstr "Der Anmeldename oder das Passwort ist falsch" -#: uffd/session/views.py:104 +#: uffd/session/views.py:106 msgid "You do not have access to this service" msgstr "Du hast keinen Zugriff auf diesen Service" -#: uffd/session/views.py:116 uffd/session/views.py:127 +#: uffd/session/views.py:118 uffd/session/views.py:129 msgid "You need to login first" msgstr "Du musst dich erst anmelden" -#: uffd/session/views.py:148 uffd/session/views.py:158 +#: uffd/session/views.py:150 uffd/session/views.py:160 msgid "Initiation code is no longer valid" msgstr "Startcode ist nicht mehr gültig" -#: uffd/session/views.py:162 +#: uffd/session/views.py:164 msgid "Invalid confirmation code" msgstr "Ungültiger Bestätigungscode" -#: uffd/session/views.py:174 uffd/session/views.py:185 +#: uffd/session/views.py:176 uffd/session/views.py:187 msgid "Invalid initiation code" msgstr "Ungültiger Startcode" @@ -1445,41 +1445,41 @@ msgstr "" msgid "Groups" msgstr "Gruppen" -#: uffd/user/views_user.py:31 +#: uffd/user/views_user.py:30 msgid "Users" msgstr "Accounts" -#: uffd/user/views_user.py:51 +#: uffd/user/views_user.py:50 msgid "Login name does not meet requirements" msgstr "Anmeldename entspricht nicht den Anforderungen" -#: uffd/user/views_user.py:56 +#: uffd/user/views_user.py:55 msgid "Mail is invalid" msgstr "E-Mail-Adresse nicht valide" -#: uffd/user/views_user.py:60 +#: uffd/user/views_user.py:59 msgid "Display name does not meet requirements" msgstr "Anzeigename entspricht nicht den Anforderungen" -#: uffd/user/views_user.py:65 +#: uffd/user/views_user.py:64 msgid "Password is invalid" msgstr "Passwort ist ungültig" -#: uffd/user/views_user.py:79 +#: uffd/user/views_user.py:78 msgid "Service user created" msgstr "Service-Account erstellt" -#: uffd/user/views_user.py:82 +#: uffd/user/views_user.py:81 msgid "User created. We sent the user a password reset link by mail" msgstr "" "Account erstellt. E-Mail mit einem Link zum Setzen des Passworts wurde " "versendet." -#: uffd/user/views_user.py:84 +#: uffd/user/views_user.py:83 msgid "User updated" msgstr "Account aktualisiert" -#: uffd/user/views_user.py:95 +#: uffd/user/views_user.py:94 msgid "Deleted user" msgstr "Account gelöscht" diff --git a/uffd/user/views_group.py b/uffd/user/views_group.py index 1526d102..bfd71c2d 100644 --- a/uffd/user/views_group.py +++ b/uffd/user/views_group.py @@ -1,4 +1,4 @@ -from flask import Blueprint, render_template, current_app, request, abort +from flask import Blueprint, render_template, current_app, request from flask_babel import lazy_gettext from uffd.navbar import register_navbar @@ -7,15 +7,15 @@ from uffd.session import login_required from .models import Group bp = Blueprint("group", __name__, template_folder='templates', url_prefix='/group/') -@bp.before_request -@login_required() -def group_acl(): - if not group_acl_check(): - abort(403) def group_acl_check(): return request.user and request.user.is_in_group(current_app.config['ACL_ADMIN_GROUP']) +@bp.before_request +@login_required(group_acl_check) +def group_acl(): + pass + @bp.route("/") @register_navbar(23, lazy_gettext('Groups'), icon='layer-group', blueprint=bp, visible=group_acl_check) def index(): diff --git a/uffd/user/views_user.py b/uffd/user/views_user.py index 2b4497dd..c98ba361 100644 --- a/uffd/user/views_user.py +++ b/uffd/user/views_user.py @@ -1,7 +1,7 @@ import csv import io -from flask import Blueprint, render_template, request, url_for, redirect, flash, current_app, abort +from flask import Blueprint, render_template, request, url_for, redirect, flash, current_app from flask_babel import gettext as _, lazy_gettext from uffd.navbar import register_navbar @@ -18,15 +18,14 @@ bp = Blueprint("user", __name__, template_folder='templates', url_prefix='/user/ bp.add_app_template_global(User, 'User') -@bp.before_request -@login_required() -def user_acl(): - if not user_acl_check(): - abort(403) - def user_acl_check(): return request.user and request.user.is_in_group(current_app.config['ACL_ADMIN_GROUP']) +@bp.before_request +@login_required(user_acl_check) +def user_acl(): + pass + @bp.route("/") @register_navbar(21, lazy_gettext('Users'), icon='users', blueprint=bp, visible=user_acl_check) def index(): -- GitLab