diff --git a/bds/apps.py b/bds/apps.py index 525776ec..86d97b09 100644 --- a/bds/apps.py +++ b/bds/apps.py @@ -1,36 +1,22 @@ from django.apps import AppConfig from django.db.models.signals import post_migrate - -def setup_groups(sender, apps, **kwargs): - """ - Add the appropriate permissions to the "member" and "buro" groups after the - `post_migrate` signal since the permissions will only be inserted in the - database at the very end of the migrations. - """ - Group = apps.get_model("auth", "Group") - Permission = apps.get_model("auth", "Permission") - - # Buro members have perms bds.* and gestion.* - buro, _ = Group.objects.get_or_create(name="bds_buro") - app_perms = Permission.objects.filter( - content_type__app_label__in=["cof", "gestion"] - ) - buro.permissions.add(*app_perms) - - # Members have perm bds.member - members, _ = Group.objects.get_or_create(name="bds_members") - perm = Permission.objects.get( - codename="member", - content_type__app_label="bds" - ) - members.permissions.add(perm) +from gestion.apps import setup_assoc_perms class BDSConfig(AppConfig): name = "bds" verbose_name = "Application de gestion du BDS" - def ready(self): - # https://docs.djangoproject.com/en/1.11/ref/signals/#post-migrate - post_migrate.connect(setup_groups, sender=self) + +def setup_bds_perms(sender, apps, **kwargs): + from bds.models import get_bds_assoc + setup_assoc_perms( + apps, get_bds_assoc, + buro_of_apps=['gestion', 'bds'], + perms=["custommail.add_custommail", "custommail.change_custommail"] + ) + +# Setup permissions of defaults groups of BDS association after Permission +# instances have been created, i.e. after applying migrations. +post_migrate.connect(setup_bds_perms) diff --git a/bds/models.py b/bds/models.py index da80dd77..30053ea8 100644 --- a/bds/models.py +++ b/bds/models.py @@ -3,7 +3,11 @@ import os.path from django.utils import timezone from django.db import models -from gestion.models import Profile +from gestion.models import Association, Profile + + +def get_bds_assoc(): + return Association.objects.get(name='BDS') class BdsProfile(models.Model): diff --git a/cof/apps.py b/cof/apps.py index c40e8896..98cffdd9 100644 --- a/cof/apps.py +++ b/cof/apps.py @@ -1,36 +1,22 @@ from django.apps import AppConfig from django.db.models.signals import post_migrate - -def setup_groups(sender, apps, **kwargs): - """ - Add the appropriate permissions to the "member" and "buro" groups after the - `post_migrate` signal since the permissions will only be inserted in the - database at the very end of the migrations. - """ - Group = apps.get_model("auth", "Group") - Permission = apps.get_model("auth", "Permission") - - # Buro members have perms cof.* and gestion.* - buro, _ = Group.objects.get_or_create(name="cof_buro") - app_perms = Permission.objects.filter( - content_type__app_label__in=["cof", "gestion"] - ) - buro.permissions.add(*app_perms) - - # Members have perm cof.member - members, _ = Group.objects.get_or_create(name="cof_members") - perm = Permission.objects.get( - codename="member", - content_type__app_label="cof" - ) - members.permissions.add(perm) +from gestion.apps import setup_assoc_perms class COFConfig(AppConfig): name = "cof" verbose_name = "Application de gestion du COF" - def ready(self): - # https://docs.djangoproject.com/en/1.11/ref/signals/#post-migrate - post_migrate.connect(setup_groups, sender=self) + +def setup_cof_perms(sender, apps, **kwargs): + from cof.models import get_cof_assoc + setup_assoc_perms( + apps, get_cof_assoc, + buro_of_apps=['gestion', 'cof'], + perms=["custommail.add_custommail", "custommail.change_custommail"] + ) + +# Setup permissions of defaults groups of BDS association after Permission +# instances have been created, i.e. after applying migrations. +post_migrate.connect(setup_cof_perms) diff --git a/cof/models.py b/cof/models.py index bdbd0e1b..4aba0ad3 100644 --- a/cof/models.py +++ b/cof/models.py @@ -6,11 +6,16 @@ from django.utils.translation import ugettext_lazy as _ from django.utils.encoding import python_2_unicode_compatible import django.utils.six as six -from gestion.models import Profile +from gestion.models import Association, Profile from bda.models import Spectacle from .petits_cours_models import choices_length + +def get_cof_assoc(): + return Association.objects.get(name='COF') + + TYPE_COTIZ_CHOICES = ( ('etudiant', _("Normalien étudiant")), ('normalien', _("Normalien élève")), diff --git a/cof/settings/secret.py b/cof/settings/secret.py new file mode 120000 index 00000000..f1c3d3f7 --- /dev/null +++ b/cof/settings/secret.py @@ -0,0 +1 @@ +secret_example.py \ No newline at end of file diff --git a/gestion/apps.py b/gestion/apps.py index efb14b29..c27b7265 100644 --- a/gestion/apps.py +++ b/gestion/apps.py @@ -4,3 +4,14 @@ from django.apps import AppConfig class GestionConfig(AppConfig): name = "gestion" verbose_name = "Gestion des outils communs COF/BDS" + + +def setup_assoc_perms(apps, assoc_getter, buro_of_apps=[], perms=[]): + try: + # Association and Permission models are required to be ready to setup + # perms. + apps.get_app_config('gestion') + apps.get_app_config('auth') + except LookupError: + return + assoc_getter().setup_perms(buro_of_apps=buro_of_apps, perms=perms) diff --git a/gestion/models.py b/gestion/models.py index d00cbec8..dc6101ba 100644 --- a/gestion/models.py +++ b/gestion/models.py @@ -1,7 +1,7 @@ -from django.contrib.auth.models import User, Group +from django.contrib.auth.models import Group, Permission, User from django.db import models +from django.db.models.signals import post_delete, post_save from django.dispatch import receiver -from django.db.models.signals import post_save, post_delete from django.urls import reverse from django.utils.translation import ugettext_lazy as _ @@ -105,6 +105,55 @@ class Association(models.Model): def __str__(self): return self.name + def setup_perms(self, buro_of_apps=[], perms=[]): + """ + Setup permissions of the staff and members groups. + + Permission '.member' is added to the 'members_group' of + the association. + + Permission '.buro' is added to the 'staff_group' of the + association. All permissions of applications from 'buro_of_apps' are + also added to this group. + + Arguments + buro_of_apps (list of 'app_label', optional) + perms (list of permission codes, optional) + + Should be used in receiver of 'post_migrate' signal, after permissions + creation. + + """ + def try_add_perm(group, app_label, codename): + try: + perm = Permission.objects.get( + content_type__app_label=app_label, + codename=codename, + ) + except Permission.DoesNotExist: + pass + else: + group.permissions.add(perm) + + assoc_app_label = self.name.lower() + + # Buro group has perm '.buro'. + try_add_perm(self.staff_group, assoc_app_label, 'buro') + + # Add all permissions of applications given 'buro_of_apps'. + apps_perms = Permission.objects.filter( + content_type__app_label__in=buro_of_apps, + ) + self.staff_group.permissions.add(*apps_perms) + + # Add extra permissions from 'perms' + for perm in perms: + app_label, codename = perm.split('.', maxsplit=1) + try_add_perm(self.staff_group, app_label, codename) + + # Members have perm '.member'. + try_add_perm(self.members_group, assoc_app_label, 'member') + # --- # Clubs diff --git a/gestion/tests.py b/gestion/tests.py index 21e532ed..8cba796e 100644 --- a/gestion/tests.py +++ b/gestion/tests.py @@ -1,16 +1,18 @@ # -*- coding: utf-8 -*- -""" -This file demonstrates writing tests using the unittest module. These will pass -when you run "manage.py test". - -Replace this with more appropriate tests for your application. -""" from unittest.mock import patch +from django.contrib.auth import get_user_model +from django.contrib.auth.models import Permission from django.db.utils import IntegrityError from django.test import Client, TestCase -from gestion.models import Profile, User +from bds.models import get_bds_assoc +from cof.models import get_cof_assoc + +from .models import Profile + + +User = get_user_model() def create_profile(username): @@ -120,3 +122,70 @@ class AuthTest(TestCase): resp.url.split('?')[0], "https://cas.eleves.ens.fr/login" ) + + +class AssociationTests(TestCase): + + def setUp(self): + self.custommail_p = Permission.objects.filter( + content_type__app_label="custommail", + codename__in=["add_custommail", "change_custommail"] + ) + + def assertAllAppPerms(self, group, app_label): + group_p = group.permissions.all() + app_p = Permission.objects.filter( + content_type__app_label=app_label, + ) + for perm in app_p: + self.assertIn(perm, group_p) + + def test_cof_assoc(self): + cof_assoc = get_cof_assoc() + + # Check cof buro group has 'cof.buro' permission. + buro_perm = Permission.objects.get( + content_type__app_label='cof', + codename='buro', + ) + self.assertIn(buro_perm, cof_assoc.staff_group.permissions.all()) + + # Check cof buro group has all permissions of 'gestion' and 'cof' apps. + self.assertAllAppPerms(cof_assoc.staff_group, 'cof') + self.assertAllAppPerms(cof_assoc.staff_group, 'gestion') + + # + some permissions in custommail + for p in self.custommail_p: + self.assertIn(p, cof_assoc.staff_group.permissions.all()) + + # Check cof members group has 'cof.member' permission. + member_perm = Permission.objects.get( + content_type__app_label='cof', + codename='member', + ) + self.assertIn(member_perm, cof_assoc.members_group.permissions.all()) + + def test_bds_assoc(self): + bds_assoc = get_bds_assoc() + + # Check cof buro group has 'bds.buro' permission. + buro_perm = Permission.objects.get( + content_type__app_label='bds', + codename='buro', + ) + self.assertIn(buro_perm, bds_assoc.staff_group.permissions.all()) + + # Check bds buro group has all permissions of 'gestion' and 'bds' apps. + self.assertAllAppPerms(bds_assoc.staff_group, 'bds') + self.assertAllAppPerms(bds_assoc.staff_group, 'gestion') + + # + some permissions in custommail + for p in self.custommail_p: + self.assertIn(p, bds_assoc.staff_group.permissions.all()) + + # Check cof members group has 'bds.member' permission. + member_perm = Permission.objects.get( + content_type__app_label='bds', + codename='member', + ) + self.assertIn(member_perm, bds_assoc.members_group.permissions.all())