diff --git a/conventions/permissions.py b/conventions/permissions.py index 09bc919c7..335f01469 100644 --- a/conventions/permissions.py +++ b/conventions/permissions.py @@ -49,9 +49,10 @@ def wrapper(request, convention_uuid, **kwargs): def _check_currentrole_permission(request, convention, permission): + session_role = request.session.get("role") role_id = ( - request.session["role"]["id"] - if "role" in request.session and "id" in request.session["role"] + session_role["id"] + if isinstance(session_role, dict) and "id" in session_role else None ) request.user.check_perm(permission, obj=convention, role_id=role_id) diff --git a/conventions/tests/views/test_upload_signed_view.py b/conventions/tests/views/test_upload_signed_view.py index d146470e5..b8602a0ad 100644 --- a/conventions/tests/views/test_upload_signed_view.py +++ b/conventions/tests/views/test_upload_signed_view.py @@ -24,7 +24,7 @@ def test_get(self): request = RequestFactory().get(url) user = UserFactory(is_superuser=True) request.user = user - request.session = "session" + request.session = {} response = ConventionPreviewUploadSignedView.as_view()( request, convention_uuid=convention.uuid @@ -44,7 +44,7 @@ def test_get(self): request = RequestFactory().get(url) user = UserFactory(is_superuser=True) request.user = user - request.session = "session" + request.session = {} messages = FallbackStorage(request) request._messages = messages @@ -65,7 +65,7 @@ def test_post(self): ) user = UserFactory(is_superuser=True) request.user = user - request.session = "session" + request.session = {} messages = FallbackStorage(request) request._messages = messages diff --git a/users/models.py b/users/models.py index 0b8fd1f5a..50d772436 100644 --- a/users/models.py +++ b/users/models.py @@ -32,6 +32,7 @@ class GroupProfile(models.TextChoices): SIAP_ASS_HLM = "ASS_HLM", "Association HLM" SIAP_MO_PERS_MORALE = "MO_PERS_MORALE", "Maitre d'ouvrage - personne morale" SIAP_MO_PERS_PHYS = "MO_PERS_PHYS", "Maitre d'ouvrage - personne physique" + SIAP_PARTENAIRES = "PARTENAIRES", "Partenaires" @classmethod def instructeur_profiles(cls): @@ -198,6 +199,7 @@ class GroupProfileRole(models.TextChoices): "SERV_INSTR_DELGEG2_SIGNATAIRE", "appartient au groupe SER_GEST, périmètre LOC", ) + PARTENAIRES = "PARTENAIRES", "appartient au groupe PARTENAIRES, périmètre NAT" @classmethod def readonly_group_profile_roles(cls): @@ -216,6 +218,7 @@ def readonly_group_profile_roles(cls): cls.MO_MORAL_REG_LECTEUR, cls.DIR_REG_INSTRUCTEUR_CHORUS, cls.SERV_DEP_INSTRUCTEUR_CHORUS, + cls.PARTENAIRES, ] @@ -375,6 +378,14 @@ def is_instructeur(self): ] return self._is_role(TypeRole.INSTRUCTEUR) or self.is_superuser + def is_partenaire(self): + if self.is_cerbere_user(): + return ( + "currently" in self.siap_habilitation + and self.siap_habilitation["currently"] == GroupProfile.SIAP_PARTENAIRES + ) + return False + def is_instructeur_departemental(self): if self.is_cerbere_user(): return "currently" in self.siap_habilitation and self.siap_habilitation[ @@ -416,6 +427,9 @@ def programmes(self) -> QuerySet[Programme]: else: return Programme.objects.none() + if self.is_partenaire(): + return Programme.objects.all() + if self.is_bailleur(): programmes_result = Programme.objects.filter( bailleur_id__in=self._bailleur_ids() @@ -464,6 +478,9 @@ def administration_filter(self, full_scope=False): return {} return {"id__in": []} + if self.is_partenaire(): + return {} + raise ExceptionPermissionConfig( "L'utilisateur courant n'a pas de role associé permettant le " + "filtre sur les administrations" @@ -511,6 +528,9 @@ def bailleur_filter(self, full_scope=False): if self.is_bailleur(): return {"id__in": self._bailleur_ids()} + if self.is_partenaire(): + return {} + raise ExceptionPermissionConfig( "L'utilisateur courant n'a pas de role associé permettant le filtre sur les bailleurs" ) @@ -551,7 +571,11 @@ def bailleurs(self, order_by="nom", full_scope=False): ).order_by(order_by) def _apply_geo_filters(self, conventions): - if self.is_cerbere_user() and "role" in self.siap_habilitation: + if ( + self.is_cerbere_user() + and "role" in self.siap_habilitation + and self.siap_habilitation["role"] is not None + ): if self.siap_habilitation["role"]["perimetre_departement"]: return conventions.filter( programme__code_insee_departement=self.siap_habilitation["role"][ @@ -591,6 +615,7 @@ def conventions(self): if ( self.is_cerbere_user() and "role" in self.siap_habilitation + and self.siap_habilitation["role"] is not None and self.siap_habilitation["role"]["typologie"] == TypeRole.ADMINISTRATEUR ): return self._apply_geo_filters(convs) @@ -600,6 +625,9 @@ def conventions(self): convs = self._apply_administration_ids_filters(convs) return convs + if self.is_partenaire(): + return convs.all() + if self.is_bailleur(): convs = self._apply_geo_filters(convs) diff --git a/users/tests/test_models.py b/users/tests/test_models.py index 37d467eb0..c8fb07eb5 100644 --- a/users/tests/test_models.py +++ b/users/tests/test_models.py @@ -11,7 +11,7 @@ from conventions.services.avenants import create_avenant from core.tests.factories import ConventionFactory from programmes.models import Programme -from users.models import ExceptionPermissionConfig, Role, User +from users.models import ExceptionPermissionConfig, GroupProfile, Role, User from users.tests.factories import GroupFactory, UserFactory from users.type_models import TypeRole @@ -339,6 +339,25 @@ def test_user_list(self): user_bailleur = User.objects.get(username="raph") self.assertEqual(user_bailleur.user_list().count(), 2) + def test_partenaire_has_national_readonly_scope(self): + user = User.objects.create( + username="partenaire", + cerbere_login="partenaire", + ) + user.siap_habilitation = {"currently": GroupProfile.SIAP_PARTENAIRES} + + self.assertTrue(user.is_partenaire()) + self.assertEqual( + set(user.programmes().values_list("uuid", flat=True)), + set(Programme.objects.all().values_list("uuid", flat=True)), + ) + self.assertEqual(user.administration_filter(), {}) + self.assertEqual(user.bailleur_filter(), {}) + self.assertEqual( + set(user.conventions().values_list("uuid", flat=True)), + set(Convention.objects.all().values_list("uuid", flat=True)), + ) + # Test model Role def test_object_role_str(self): role = User.objects.get(username="sabine").roles.all()[0]