diff --git a/mellon/exceptions.py b/mellon/exceptions.py new file mode 100644 index 0000000..0d4fec2 --- /dev/null +++ b/mellon/exceptions.py @@ -0,0 +1,4 @@ +class RolesNotInSession(Exception): + + def __init__(self, roles): + self.roles = roles diff --git a/mellon/middleware.py b/mellon/middleware.py index a0b814a..ed35eb1 100644 --- a/mellon/middleware.py +++ b/mellon/middleware.py @@ -3,6 +3,7 @@ from django.http import HttpResponseRedirect from django.core.urlresolvers import reverse from . import app_settings, utils +from .exceptions import RolesNotInSession PASSIVE_TRIED_COOKIE = 'MELLON_PASSIVE_TRIED' @@ -50,3 +51,10 @@ class PassiveAuthenticationMiddleware(object): # prevent loops response.set_cookie(PASSIVE_TRIED_COOKIE, value='1', max_age=None) 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)) diff --git a/mellon/utils.py b/mellon/utils.py index ee8b8a5..018246f 100644 --- a/mellon/utils.py +++ b/mellon/utils.py @@ -6,7 +6,9 @@ import isodate from xml.parsers import expat from django.contrib import auth +from django.contrib.auth.models import Group from django.core.urlresolvers import reverse +from django.http import QueryDict, HttpResponseRedirect 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.conf import settings @@ -14,6 +16,7 @@ from django.utils.six.moves.urllib.parse import urlparse import lasso from . import app_settings +from .exceptions import RolesNotInSession def create_metadata(request): @@ -289,3 +292,31 @@ def has_superuser_flag(idp, saml_attributes): if attribute_values & values: return True 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='/')))