From c364ff7d9905f3fef928eaadb4891fa996d52a11 Mon Sep 17 00:00:00 2001
From: Valentin Deniaud <vdeniaud@entrouvert.com>
Date: Tue, 7 May 2019 11:24:55 +0200
Subject: [PATCH] manager: handle special cases of access control (#33515)

Making use of the new could_{action} attribute previously introduced.
---
 src/authentic2/manager/ou_views.py   |  2 +-
 src/authentic2/manager/role_views.py | 11 +++++++++--
 src/authentic2/manager/utils.py      |  6 ++++++
 src/authentic2/manager/views.py      |  5 ++---
 4 files changed, 18 insertions(+), 6 deletions(-)

diff --git a/src/authentic2/manager/ou_views.py b/src/authentic2/manager/ou_views.py
index a9904a70..2c0b7f89 100644
--- a/src/authentic2/manager/ou_views.py
+++ b/src/authentic2/manager/ou_views.py
@@ -63,7 +63,7 @@ class OrganizationalUnitDetailView(views.BaseDetailView):
 
     def authorize(self, request, *args, **kwargs):
         super(OrganizationalUnitDetailView, self).authorize(request, *args, **kwargs)
-        self.can_delete = self.can_delete and not self.object.default
+        self.could_delete = self.could_delete and not self.object.default
 
 detail = OrganizationalUnitDetailView.as_view()
 
diff --git a/src/authentic2/manager/role_views.py b/src/authentic2/manager/role_views.py
index 7df448a0..125ba345 100644
--- a/src/authentic2/manager/role_views.py
+++ b/src/authentic2/manager/role_views.py
@@ -27,12 +27,13 @@ from django.db.models import Count
 from django.core.urlresolvers import reverse
 from django.contrib.auth import get_user_model
 
+from django_rbac.exceptions import InsufficientAuthLevel
 from django_rbac.utils import get_role_model, get_permission_model, get_ou_model
 
 from authentic2.utils import redirect
 from authentic2 import hooks, data_transfer
 
-from . import tables, views, resources, forms, app_settings
+from . import tables, views, resources, forms, app_settings, utils
 
 
 class RolesMixin(object):
@@ -79,7 +80,7 @@ class RolesView(views.HideOUColumnMixin, RolesMixin, views.BaseTableView):
 
     def authorize(self, request, *args, **kwargs):
         super(RolesView, self).authorize(request, *args, **kwargs)
-        self.can_add = bool(request.user.ous_with_perm('a2_rbac.add_role'))
+        self.could_add = bool(request.user.ous_with_perm('a2_rbac.add_role'))
 
 
 listing = RolesView.as_view()
@@ -176,6 +177,8 @@ class RoleMembersView(views.HideOUColumnMixin, RoleViewMixin, views.BaseSubTable
                     hooks.call_hooks('event', name='manager-remove-role-member',
                                      user=self.request.user, role=self.object, member=user)
         else:
+            if self.could_change:
+                return utils.increase_auth_level(self.request)
             messages.warning(self.request, _('You are not authorized'))
         return super(RoleMembersView, self).form_valid(form)
 
@@ -205,6 +208,8 @@ class RoleDeleteView(RoleViewMixin, views.BaseDeleteView):
 
     def post(self, request, *args, **kwargs):
         if not self.can_delete:
+            if self.could_delete:
+                return utils.increase_auth_level(self.request)
             raise PermissionDenied
         return super(RoleDeleteView, self).post(request, *args, **kwargs)
 
@@ -259,6 +264,8 @@ class RolePermissionsView(RoleViewMixin, views.BaseSubTableView):
                         hooks.call_hooks('event', name='manager-remove-permission',
                                          user=self.request.user, role=self.object, permission=perm)
         else:
+            if self.could_change:
+                return utils.increase_auth_level(self.request)
             messages.warning(self.request, _('You are not authorized'))
         return super(RolePermissionsView, self).form_valid(form)
 
diff --git a/src/authentic2/manager/utils.py b/src/authentic2/manager/utils.py
index bf3d00a0..10d217ca 100644
--- a/src/authentic2/manager/utils.py
+++ b/src/authentic2/manager/utils.py
@@ -17,6 +17,7 @@
 from django_rbac.utils import get_ou_model
 
 from authentic2.decorators import GlobalCache
+from authentic2.utils import login_require
 
 
 def label_from_user(user):
@@ -40,3 +41,8 @@ def label_from_user(user):
 @GlobalCache(timeout=10)
 def get_ou_count():
     return get_ou_model().objects.count()
+
+
+def increase_auth_level(request):
+    current_auth_level = request.session.get('auth_level', 1)
+    return login_require(request, params={'auth_level': current_auth_level + 1})
diff --git a/src/authentic2/manager/views.py b/src/authentic2/manager/views.py
index 62bf1676..a549c0af 100644
--- a/src/authentic2/manager/views.py
+++ b/src/authentic2/manager/views.py
@@ -43,7 +43,7 @@ from django_rbac.utils import get_ou_model
 
 from authentic2.data_transfer import export_site, import_site, DataImportError, ImportContext
 from authentic2.forms.profile import modelform_factory
-from authentic2.utils import redirect, batch_queryset, login_require
+from authentic2.utils import redirect, batch_queryset
 from authentic2.decorators import json as json_view
 from authentic2 import hooks
 
@@ -150,8 +150,7 @@ class PermissionMixin(object):
         try:
             response = self.authorize(request, *args, **kwargs)
         except InsufficientAuthLevel:
-            current_auth_level = request.session.get('auth_level', 1)
-            return login_require(request, params={'auth_level': current_auth_level + 1})
+            return utils.increase_auth_level(request)
         if response is not None:
             return response
         return super(PermissionMixin, self).dispatch(request, *args, **kwargs)
-- 
2.20.1

