utils: add method to check if a user has a role
gitea/django-mellon/pipeline/head Build started... Details

Along with a middleware to allow catching the exception it raises when
the user is missing roles, redirecting them appropriately.

A distinction is made between roles which are obtained at the SSO,
stored in session, and roles which the user could have, statically
stored in database.

todo: ce commit dépend totalement du provisionning tel qu'implémenté par
hobo, il faudrait améliorer ça
This commit is contained in:
Valentin Deniaud 2019-05-21 11:58:58 +02:00
parent 12a5327367
commit 1c3f3d887c
3 changed files with 43 additions and 0 deletions

4
mellon/exceptions.py Normal file
View File

@ -0,0 +1,4 @@
class RolesNotInSession(Exception):
def __init__(self, roles):
self.roles = roles

View File

@ -3,6 +3,7 @@ from django.http import HttpResponseRedirect
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from . import app_settings, utils from . import app_settings, utils
from .exceptions import RolesNotInSession
PASSIVE_TRIED_COOKIE = 'MELLON_PASSIVE_TRIED' PASSIVE_TRIED_COOKIE = 'MELLON_PASSIVE_TRIED'
@ -50,3 +51,10 @@ class PassiveAuthenticationMiddleware(object):
# prevent loops # prevent loops
response.set_cookie(PASSIVE_TRIED_COOKIE, value='1', max_age=None) response.set_cookie(PASSIVE_TRIED_COOKIE, value='1', max_age=None)
return response return response
class RolesRequestMiddleware(object):
def process_exception(self, request, exception):
if isinstance(exception, RolesNotInSession):
return HttpResponseRedirect(
utils.get_role_request_url(request, exception.roles))

View File

@ -6,7 +6,9 @@ import isodate
from xml.parsers import expat from xml.parsers import expat
from django.contrib import auth from django.contrib import auth
from django.contrib.auth.models import Group
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.http import QueryDict, HttpResponseRedirect
from django.template.loader import render_to_string from django.template.loader import render_to_string
from django.utils.timezone import make_aware, now, make_naive, is_aware, get_default_timezone from django.utils.timezone import make_aware, now, make_naive, is_aware, get_default_timezone
from django.conf import settings from django.conf import settings
@ -14,6 +16,7 @@ from django.utils.six.moves.urllib.parse import urlparse
import lasso import lasso
from . import app_settings from . import app_settings
from .exceptions import RolesNotInSession
def create_metadata(request): def create_metadata(request):
@ -289,3 +292,31 @@ def has_superuser_flag(idp, saml_attributes):
if attribute_values & values: if attribute_values & values:
return True return True
return False return False
def user_has_roles(request, roles):
if request.user.is_staff and request.session.get('is_staff'):
return True
groups = set(roles).intersection(request.user.groups.all())
if not groups:
if request.user.is_staff:
raise RolesNotInSession(('staff',))
return False
role_uuids = {getattr(group, 'role').uuid for group in groups}
if not role_uuids:
return True
if set(request.session['mellon_session']['role-slug']) & role_uuids:
return True
raise RolesNotInSession(role_uuids)
def user_has_role(request, role):
return user_has_roles(request, {role})
def get_role_request_url(request, roles):
login_url = reverse(app_settings.LOGIN_URL)
q = QueryDict(mutable=True)
q.setlist('roles', roles)
q['next'] = request.get_full_path()
return '?'.join((login_url, q.urlencode(safe='/')))