From 7176e0e23ebccb94c74cc6e392faf17685979cf8 Mon Sep 17 00:00:00 2001 From: Valentin Deniaud Date: Tue, 21 May 2019 12:41:12 +0200 Subject: [PATCH 1/4] delegate permission checking to mellon if possible We pass request instead of user in permission method because mellon wants to look inside the session. --- chrono/agendas/models.py | 35 ++++++++++++++++++++++++----------- chrono/exceptions.py | 5 +++++ chrono/manager/views.py | 33 +++++++++++++++++++++------------ 3 files changed, 50 insertions(+), 23 deletions(-) create mode 100644 chrono/exceptions.py diff --git a/chrono/agendas/models.py b/chrono/agendas/models.py index 50409e8..461ed5e 100644 --- a/chrono/agendas/models.py +++ b/chrono/agendas/models.py @@ -35,7 +35,17 @@ from django.utils.translation import ugettext_lazy as _ from jsonfield import JSONField -from ..interval import Intervals +from chrono.exceptions import RolesNotInSession +from chrono.interval import Intervals + + +try: + from mellon.utils import user_has_role +except ImportError: + def user_has_role(request, role_id): + if request.user.is_staff: + return True + return request.user.groups.filter(id=role_id).exists() AGENDA_KINDS = ( @@ -93,17 +103,20 @@ class Agenda(models.Model): def get_absolute_url(self): return reverse('chrono-manager-agenda-view', kwargs={'pk': self.id}) - def can_be_managed(self, user): - if user.is_staff: - return True - group_ids = [x.id for x in user.groups.all()] - return bool(self.edit_role_id in group_ids) + def can_be_managed(self, request): + return user_has_role(request, self.edit_role_id) - def can_be_viewed(self, user): - if self.can_be_managed(user): - return True - group_ids = [x.id for x in user.groups.all()] - return bool(self.view_role_id in group_ids) + def can_be_viewed(self, request): + could_be_managed = False + try: + if self.can_be_managed(request): + return True + except RolesNotInSession as e: + could_be_managed = e + has_role = user_has_role(request, self.view_role_id) + if not has_role and could_be_managed: + raise could_be_managed + return has_role def get_base_meeting_duration(self): durations = [x.duration for x in MeetingType.objects.filter(agenda=self)] diff --git a/chrono/exceptions.py b/chrono/exceptions.py new file mode 100644 index 0000000..becfb64 --- /dev/null +++ b/chrono/exceptions.py @@ -0,0 +1,5 @@ +try: + from mellon.exceptions import RolesNotInSession +except ImportError: + class RolesNotInSession(Exception): + pass diff --git a/chrono/manager/views.py b/chrono/manager/views.py index 80a59e4..e0cc257 100644 --- a/chrono/manager/views.py +++ b/chrono/manager/views.py @@ -35,6 +35,7 @@ from django.views.generic import (DetailView, CreateView, UpdateView, from chrono.agendas.models import (Agenda, Event, MeetingType, TimePeriod, Booking, Desk, TimePeriodException, ICSError, AgendaImportError) +from chrono.exceptions import RolesNotInSession from .forms import (AgendaAddForm, AgendaEditForm, EventForm, NewMeetingTypeForm, MeetingTypeForm, TimePeriodForm, ImportEventsForm, NewDeskForm, DeskForm, TimePeriodExceptionForm, @@ -130,7 +131,7 @@ class AgendaEditView(UpdateView): def get_object(self, queryset=None): obj = super(AgendaEditView, self).get_object(queryset=queryset) - if not obj.can_be_managed(self.request.user): + if not obj.can_be_managed(self.request): raise PermissionDenied() return obj @@ -176,7 +177,7 @@ class AgendaView(DetailView): agenda = Agenda.objects.get(id=kwargs.get('pk')) except Agenda.DoesNotExist: raise Http404() - if not agenda.can_be_viewed(self.request.user): + if not agenda.can_be_viewed(self.request): raise PermissionDenied() if agenda.kind == 'meetings': @@ -206,7 +207,7 @@ class AgendaDateView(object): self.agenda = get_object_or_404(Agenda, id=kwargs.get('pk')) if self.agenda.kind != 'meetings': raise Http404() - if not self.agenda.can_be_viewed(request.user): + if not self.agenda.can_be_viewed(request): raise PermissionDenied() # specify 6am time to get the expected timezone on daylight saving time @@ -443,7 +444,7 @@ class ManagedAgendaMixin(object): self.agenda = Agenda.objects.get(id=kwargs.get('pk')) except Agenda.DoesNotExist: raise Http404() - if not self.agenda.can_be_managed(request.user): + if not self.agenda.can_be_managed(request): raise PermissionDenied() return super(ManagedAgendaMixin, self).dispatch(request, *args, **kwargs) @@ -466,7 +467,7 @@ class ManagedAgendaSubobjectMixin(object): def dispatch(self, request, *args, **kwargs): self.agenda = self.get_object().agenda - if not self.agenda.can_be_managed(request.user): + if not self.agenda.can_be_managed(request): raise PermissionDenied() return super(ManagedAgendaSubobjectMixin, self).dispatch(request, *args, **kwargs) @@ -487,7 +488,7 @@ class ManagedDeskMixin(object): self.desk = Desk.objects.get(id=kwargs.get('pk')) except Desk.DoesNotExist: raise Http404() - if not self.desk.agenda.can_be_managed(request.user): + if not self.desk.agenda.can_be_managed(request): raise PermissionDenied() return super(ManagedDeskMixin, self).dispatch(request, *args, **kwargs) @@ -511,7 +512,7 @@ class ManagedDeskSubobjectMixin(object): def dispatch(self, request, *args, **kwargs): self.desk = self.get_object().desk - if not self.desk.agenda.can_be_managed(request.user): + if not self.desk.agenda.can_be_managed(request): raise PermissionDenied() return super(ManagedDeskSubobjectMixin, self).dispatch(request, *args, **kwargs) @@ -534,11 +535,19 @@ class AgendaSettings(ManagedAgendaMixin, DetailView): self.agenda = Agenda.objects.get(id=kwargs.get('pk')) except Agenda.DoesNotExist: raise Http404() - if not self.agenda.can_be_managed(request.user): - # "events" agendas settings page can be access by user with the - # view permission as there are no other "view" page for this type - # of agenda. - if self.agenda.kind != 'events' or not self.agenda.can_be_viewed(request.user): + # Do something different here as "events" agendas settings page can be + # access by user with the view permission as there are no other "view" + # page for this type of agenda. + raised_exception = None + try: + can_be_managed = self.agenda.can_be_managed(request) + except RolesNotInSession as e: + can_be_managed = False + raised_exception = e + if not can_be_managed: + if self.agenda.kind != 'events' or not self.agenda.can_be_viewed(request): + if raised_exception: + raise raised_exception raise PermissionDenied() return super(DetailView, self).dispatch(request, *args, **kwargs) -- 2.20.1