Merge branch 'Aufinal/permissions' into 'master'
Permissions par évènement See merge request cof-geek/GestionEvenementiel!15
This commit is contained in:
commit
3aab76613a
15 changed files with 302 additions and 94 deletions
|
@ -1,8 +1,7 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# Generated by Django 1.11.3 on 2017-07-21 14:20
|
# Generated by Django 1.11.3 on 2017-08-17 12:21
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.conf import settings
|
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
import django.db.models.deletion
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
@ -13,8 +12,6 @@ class Migration(migrations.Migration):
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
('contenttypes', '0002_remove_content_type_name'),
|
('contenttypes', '0002_remove_content_type_name'),
|
||||||
('auth', '0008_alter_user_username_max_length'),
|
|
||||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
|
||||||
]
|
]
|
||||||
|
|
||||||
operations = [
|
operations = [
|
||||||
|
@ -23,8 +20,6 @@ class Migration(migrations.Migration):
|
||||||
fields=[
|
fields=[
|
||||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
('object_id', models.PositiveIntegerField()),
|
('object_id', models.PositiveIntegerField()),
|
||||||
('content_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='contenttypes.ContentType')),
|
|
||||||
('group', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='auth.Group')),
|
|
||||||
],
|
],
|
||||||
options={
|
options={
|
||||||
'verbose_name': 'souscription en groupe',
|
'verbose_name': 'souscription en groupe',
|
||||||
|
@ -37,18 +32,9 @@ class Migration(migrations.Migration):
|
||||||
('object_id', models.PositiveIntegerField()),
|
('object_id', models.PositiveIntegerField()),
|
||||||
('is_unsub', models.BooleanField(default=False, verbose_name='désinscription')),
|
('is_unsub', models.BooleanField(default=False, verbose_name='désinscription')),
|
||||||
('content_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='contenttypes.ContentType')),
|
('content_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='contenttypes.ContentType')),
|
||||||
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
|
|
||||||
],
|
],
|
||||||
options={
|
options={
|
||||||
'verbose_name': 'souscription utilisateur',
|
'verbose_name': 'souscription utilisateur',
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
migrations.AlterUniqueTogether(
|
|
||||||
name='usersubscription',
|
|
||||||
unique_together=set([('user', 'content_type', 'object_id')]),
|
|
||||||
),
|
|
||||||
migrations.AlterUniqueTogether(
|
|
||||||
name='groupsubscription',
|
|
||||||
unique_together=set([('group', 'content_type', 'object_id')]),
|
|
||||||
),
|
|
||||||
]
|
]
|
||||||
|
|
45
communication/migrations/0002_auto_20170817_1221.py
Normal file
45
communication/migrations/0002_auto_20170817_1221.py
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.11.3 on 2017-08-17 12:21
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
initial = True
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('contenttypes', '0002_remove_content_type_name'),
|
||||||
|
('communication', '0001_initial'),
|
||||||
|
('auth', '0008_alter_user_username_max_length'),
|
||||||
|
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='usersubscription',
|
||||||
|
name='user',
|
||||||
|
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='groupsubscription',
|
||||||
|
name='content_type',
|
||||||
|
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='contenttypes.ContentType'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='groupsubscription',
|
||||||
|
name='group',
|
||||||
|
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='auth.Group'),
|
||||||
|
),
|
||||||
|
migrations.AlterUniqueTogether(
|
||||||
|
name='usersubscription',
|
||||||
|
unique_together=set([('user', 'content_type', 'object_id')]),
|
||||||
|
),
|
||||||
|
migrations.AlterUniqueTogether(
|
||||||
|
name='groupsubscription',
|
||||||
|
unique_together=set([('group', 'content_type', 'object_id')]),
|
||||||
|
),
|
||||||
|
]
|
|
@ -28,10 +28,8 @@ class SubscriptionTest(TestCase):
|
||||||
created_by=cls.root,
|
created_by=cls.root,
|
||||||
created_at=timezone.now(),
|
created_at=timezone.now(),
|
||||||
description="Ceci est un test",
|
description="Ceci est un test",
|
||||||
beginning_date=timezone.now()
|
beginning_date=timezone.now() + timedelta(days=30),
|
||||||
+ timedelta(days=30),
|
ending_date=timezone.now() + timedelta(days=31),
|
||||||
ending_date=timezone.now()
|
|
||||||
+ timedelta(days=31),
|
|
||||||
)
|
)
|
||||||
cls.groupsub = GroupSubscription.objects.create(
|
cls.groupsub = GroupSubscription.objects.create(
|
||||||
content_object=cls.event,
|
content_object=cls.event,
|
||||||
|
@ -55,4 +53,4 @@ class SubscriptionTest(TestCase):
|
||||||
|
|
||||||
def test_all_subs(self):
|
def test_all_subs(self):
|
||||||
self.assertSetEqual(set(self.event.get_all_subscribers()),
|
self.assertSetEqual(set(self.event.get_all_subscribers()),
|
||||||
{self.user_true, self.user_group_true})
|
{self.user_true, self.user_group_true})
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# Generated by Django 1.11.4 on 2017-08-12 12:47
|
# Generated by Django 1.11.3 on 2017-08-17 12:21
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
@ -11,7 +11,6 @@ class Migration(migrations.Migration):
|
||||||
initial = True
|
initial = True
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
('event', '0001_initial'),
|
|
||||||
]
|
]
|
||||||
|
|
||||||
operations = [
|
operations = [
|
||||||
|
@ -34,8 +33,6 @@ class Migration(migrations.Migration):
|
||||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
('amount', models.PositiveSmallIntegerField(verbose_name='quantité attribuée')),
|
('amount', models.PositiveSmallIntegerField(verbose_name='quantité attribuée')),
|
||||||
('remarks', models.TextField(verbose_name="remarques concernant l'attribution")),
|
('remarks', models.TextField(verbose_name="remarques concernant l'attribution")),
|
||||||
('activity', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='event.Activity')),
|
|
||||||
('equipment', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='equipment.Equipment')),
|
|
||||||
],
|
],
|
||||||
options={
|
options={
|
||||||
'verbose_name': 'attribution de matériel',
|
'verbose_name': 'attribution de matériel',
|
||||||
|
@ -57,14 +54,4 @@ class Migration(migrations.Migration):
|
||||||
'verbose_name_plural': 'remarques sur le matériel',
|
'verbose_name_plural': 'remarques sur le matériel',
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
migrations.AddField(
|
|
||||||
model_name='equipment',
|
|
||||||
name='activities',
|
|
||||||
field=models.ManyToManyField(related_name='equipment', through='equipment.EquipmentAttribution', to='event.Activity'),
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='equipment',
|
|
||||||
name='event',
|
|
||||||
field=models.ForeignKey(blank=True, help_text="Si spécifié, l'instance du modèle est spécifique à l'évènement en question.", null=True, on_delete=django.db.models.deletion.CASCADE, to='event.Event', verbose_name='évènement'),
|
|
||||||
),
|
|
||||||
]
|
]
|
||||||
|
|
39
equipment/migrations/0002_auto_20170817_1221.py
Normal file
39
equipment/migrations/0002_auto_20170817_1221.py
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.11.3 on 2017-08-17 12:21
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
initial = True
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('equipment', '0001_initial'),
|
||||||
|
('event', '0001_initial'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='equipmentattribution',
|
||||||
|
name='activity',
|
||||||
|
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='event.Activity'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='equipmentattribution',
|
||||||
|
name='equipment',
|
||||||
|
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='equipment.Equipment'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='equipment',
|
||||||
|
name='activities',
|
||||||
|
field=models.ManyToManyField(related_name='equipment', through='equipment.EquipmentAttribution', to='event.Activity'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='equipment',
|
||||||
|
name='event',
|
||||||
|
field=models.ForeignKey(blank=True, help_text="Si spécifié, l'instance du modèle est spécifique à l'évènement en question.", null=True, on_delete=django.db.models.deletion.CASCADE, to='event.Event', verbose_name='évènement'),
|
||||||
|
),
|
||||||
|
]
|
|
@ -55,6 +55,7 @@ INSTALLED_APPS = [
|
||||||
'rest_framework',
|
'rest_framework',
|
||||||
'bootstrapform',
|
'bootstrapform',
|
||||||
'widget_tweaks',
|
'widget_tweaks',
|
||||||
|
'guardian',
|
||||||
|
|
||||||
'api',
|
'api',
|
||||||
'communication',
|
'communication',
|
||||||
|
@ -136,6 +137,11 @@ CHANNEL_LAYERS = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AUTHENTICATION_BACKENDS = (
|
||||||
|
'django.contrib.auth.backends.ModelBackend',
|
||||||
|
'guardian.backends.ObjectPermissionBackend',
|
||||||
|
)
|
||||||
|
|
||||||
# Password validation
|
# Password validation
|
||||||
# https://docs.djangoproject.com/en/1.9/ref/settings/#auth-password-validators
|
# https://docs.djangoproject.com/en/1.9/ref/settings/#auth-password-validators
|
||||||
AUTH_PASSWORD_VALIDATORS = [
|
AUTH_PASSWORD_VALIDATORS = [
|
||||||
|
|
|
@ -5,3 +5,6 @@ from django.utils.translation import ugettext_lazy as _
|
||||||
class EventConfig(AppConfig):
|
class EventConfig(AppConfig):
|
||||||
name = 'event'
|
name = 'event'
|
||||||
verbose_name = _("Évènement")
|
verbose_name = _("Évènement")
|
||||||
|
|
||||||
|
def ready(self):
|
||||||
|
from . import signals
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# Generated by Django 1.11.4 on 2017-08-12 12:47
|
# Generated by Django 1.11.3 on 2017-08-17 12:21
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.conf import settings
|
|
||||||
import django.core.validators
|
import django.core.validators
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
import django.db.models.deletion
|
import django.db.models.deletion
|
||||||
|
@ -13,7 +12,7 @@ class Migration(migrations.Migration):
|
||||||
initial = True
|
initial = True
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
('auth', '0008_alter_user_username_max_length'),
|
||||||
]
|
]
|
||||||
|
|
||||||
operations = [
|
operations = [
|
||||||
|
@ -74,15 +73,25 @@ class Migration(migrations.Migration):
|
||||||
('slug', models.SlugField(help_text="Seulement des lettres, des chiffres ou les caractères '_' ou '-'.", unique=True, verbose_name='identificateur')),
|
('slug', models.SlugField(help_text="Seulement des lettres, des chiffres ou les caractères '_' ou '-'.", unique=True, verbose_name='identificateur')),
|
||||||
('created_at', models.DateTimeField(auto_now_add=True, verbose_name='date de création')),
|
('created_at', models.DateTimeField(auto_now_add=True, verbose_name='date de création')),
|
||||||
('description', models.TextField(verbose_name='description')),
|
('description', models.TextField(verbose_name='description')),
|
||||||
('beginning_date', models.DateTimeField(verbose_name='date de début')),
|
('beginning_date', models.DateTimeField(help_text="date publique de l'évènement", verbose_name='date de début')),
|
||||||
('ending_date', models.DateTimeField(verbose_name='date de fin')),
|
('ending_date', models.DateTimeField(help_text="date publique de l'évènement", verbose_name='date de fin')),
|
||||||
('created_by', models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='created_events', to=settings.AUTH_USER_MODEL, verbose_name='créé par')),
|
|
||||||
],
|
],
|
||||||
options={
|
options={
|
||||||
'verbose_name': 'évènement',
|
'verbose_name': 'évènement',
|
||||||
'verbose_name_plural': 'évènements',
|
'verbose_name_plural': 'évènements',
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='EventGroup',
|
||||||
|
fields=[
|
||||||
|
('group_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='auth.Group')),
|
||||||
|
('event', models.ForeignKey(blank=True, help_text="Si spécifié, l'instance du modèle est spécifique à l'évènement en question.", null=True, on_delete=django.db.models.deletion.CASCADE, to='event.Event', verbose_name='évènement')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'abstract': False,
|
||||||
|
},
|
||||||
|
bases=('auth.group', models.Model),
|
||||||
|
),
|
||||||
migrations.CreateModel(
|
migrations.CreateModel(
|
||||||
name='Place',
|
name='Place',
|
||||||
fields=[
|
fields=[
|
||||||
|
@ -96,49 +105,4 @@ class Migration(migrations.Migration):
|
||||||
'verbose_name_plural': 'lieux',
|
'verbose_name_plural': 'lieux',
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
migrations.AddField(
|
|
||||||
model_name='activitytemplate',
|
|
||||||
name='event',
|
|
||||||
field=models.ForeignKey(editable=False, on_delete=django.db.models.deletion.CASCADE, to='event.Event', verbose_name='évènement'),
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='activitytemplate',
|
|
||||||
name='places',
|
|
||||||
field=models.ManyToManyField(blank=True, to='event.Place', verbose_name='lieux'),
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='activitytemplate',
|
|
||||||
name='tags',
|
|
||||||
field=models.ManyToManyField(blank=True, to='event.ActivityTag', verbose_name='tags'),
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='activitytag',
|
|
||||||
name='event',
|
|
||||||
field=models.ForeignKey(blank=True, help_text="Si spécifié, l'instance du modèle est spécifique à l'évènement en question.", null=True, on_delete=django.db.models.deletion.CASCADE, to='event.Event', verbose_name='évènement'),
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='activity',
|
|
||||||
name='event',
|
|
||||||
field=models.ForeignKey(editable=False, on_delete=django.db.models.deletion.CASCADE, to='event.Event', verbose_name='évènement'),
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='activity',
|
|
||||||
name='parent',
|
|
||||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='children', to='event.ActivityTemplate', verbose_name='template'),
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='activity',
|
|
||||||
name='places',
|
|
||||||
field=models.ManyToManyField(blank=True, to='event.Place', verbose_name='lieux'),
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='activity',
|
|
||||||
name='staff',
|
|
||||||
field=models.ManyToManyField(blank=True, related_name='in_perm_activities', to=settings.AUTH_USER_MODEL, verbose_name='permanents'),
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='activity',
|
|
||||||
name='tags',
|
|
||||||
field=models.ManyToManyField(blank=True, to='event.ActivityTag', verbose_name='tags'),
|
|
||||||
),
|
|
||||||
]
|
]
|
||||||
|
|
70
event/migrations/0002_auto_20170817_1221.py
Normal file
70
event/migrations/0002_auto_20170817_1221.py
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.11.3 on 2017-08-17 12:21
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
initial = True
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('event', '0001_initial'),
|
||||||
|
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='event',
|
||||||
|
name='created_by',
|
||||||
|
field=models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='created_events', to=settings.AUTH_USER_MODEL, verbose_name='créé par'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='activitytemplate',
|
||||||
|
name='event',
|
||||||
|
field=models.ForeignKey(editable=False, on_delete=django.db.models.deletion.CASCADE, to='event.Event', verbose_name='évènement'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='activitytemplate',
|
||||||
|
name='places',
|
||||||
|
field=models.ManyToManyField(blank=True, to='event.Place', verbose_name='lieux'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='activitytemplate',
|
||||||
|
name='tags',
|
||||||
|
field=models.ManyToManyField(blank=True, to='event.ActivityTag', verbose_name='tags'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='activitytag',
|
||||||
|
name='event',
|
||||||
|
field=models.ForeignKey(blank=True, help_text="Si spécifié, l'instance du modèle est spécifique à l'évènement en question.", null=True, on_delete=django.db.models.deletion.CASCADE, to='event.Event', verbose_name='évènement'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='activity',
|
||||||
|
name='event',
|
||||||
|
field=models.ForeignKey(editable=False, on_delete=django.db.models.deletion.CASCADE, to='event.Event', verbose_name='évènement'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='activity',
|
||||||
|
name='parent',
|
||||||
|
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='children', to='event.ActivityTemplate', verbose_name='template'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='activity',
|
||||||
|
name='places',
|
||||||
|
field=models.ManyToManyField(blank=True, to='event.Place', verbose_name='lieux'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='activity',
|
||||||
|
name='staff',
|
||||||
|
field=models.ManyToManyField(blank=True, related_name='in_perm_activities', to=settings.AUTH_USER_MODEL, verbose_name='permanents'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='activity',
|
||||||
|
name='tags',
|
||||||
|
field=models.ManyToManyField(blank=True, to='event.ActivityTag', verbose_name='tags'),
|
||||||
|
),
|
||||||
|
]
|
|
@ -1,4 +1,5 @@
|
||||||
from django.contrib.auth import get_user_model
|
from django.contrib.auth import get_user_model
|
||||||
|
from django.contrib.auth.models import Group
|
||||||
from django.core.exceptions import FieldDoesNotExist, FieldError
|
from django.core.exceptions import FieldDoesNotExist, FieldError
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
@ -65,11 +66,16 @@ class EventSpecificMixin(models.Model):
|
||||||
on_delete=models.CASCADE,
|
on_delete=models.CASCADE,
|
||||||
blank=True, null=True,
|
blank=True, null=True,
|
||||||
)
|
)
|
||||||
|
needs_event_permissions = True
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
abstract = True
|
abstract = True
|
||||||
|
|
||||||
|
|
||||||
|
class EventGroup(EventSpecificMixin, Group):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class Place(EventSpecificMixin, models.Model):
|
class Place(EventSpecificMixin, models.Model):
|
||||||
name = models.CharField(
|
name = models.CharField(
|
||||||
_("nom du lieu"),
|
_("nom du lieu"),
|
||||||
|
@ -161,12 +167,14 @@ class AbstractActivityTemplate(SubscriptionMixin, models.Model):
|
||||||
verbose_name=_('lieux'),
|
verbose_name=_('lieux'),
|
||||||
blank=True,
|
blank=True,
|
||||||
)
|
)
|
||||||
|
needs_event_permissions = True
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
abstract = True
|
abstract = True
|
||||||
|
|
||||||
|
|
||||||
class ActivityTemplate(AbstractActivityTemplate):
|
class ActivityTemplate(AbstractActivityTemplate):
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = _("template activité")
|
verbose_name = _("template activité")
|
||||||
verbose_name_plural = _("templates activité")
|
verbose_name_plural = _("templates activité")
|
||||||
|
|
51
event/signals.py
Normal file
51
event/signals.py
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
from django.dispatch import receiver
|
||||||
|
from django.db.models.signals import post_save, post_migrate
|
||||||
|
from django.apps import apps
|
||||||
|
from django.contrib.contenttypes.models import ContentType
|
||||||
|
from django.contrib.auth.models import Permission
|
||||||
|
from event.models import Event, EventGroup
|
||||||
|
from guardian.shortcuts import assign_perm
|
||||||
|
|
||||||
|
|
||||||
|
@receiver(post_save, sender=Event)
|
||||||
|
def create_groups_for_event(sender, **kwargs):
|
||||||
|
event, created = kwargs["instance"], kwargs["created"]
|
||||||
|
if created:
|
||||||
|
orgas = EventGroup.objects.create(
|
||||||
|
name="{}_orgas".format(event.slug),
|
||||||
|
event=event
|
||||||
|
)
|
||||||
|
|
||||||
|
for perm in Permission.objects.filter(
|
||||||
|
content_type=ContentType.objects.get_for_model(Event),
|
||||||
|
codename__contains="event_"):
|
||||||
|
assign_perm(perm.codename, orgas, event)
|
||||||
|
|
||||||
|
EventGroup.objects.create(
|
||||||
|
name="{}_participants".format(event.slug),
|
||||||
|
event=event,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@receiver(post_migrate)
|
||||||
|
def create_event_permissions(sender, **kwargs):
|
||||||
|
|
||||||
|
def event_specific_permissions():
|
||||||
|
opes = ['Add', 'Change', 'Delete']
|
||||||
|
models = [model.__name__.lower() for model in apps.get_models()
|
||||||
|
if getattr(model, 'needs_event_permissions', False)]
|
||||||
|
|
||||||
|
return [
|
||||||
|
('event_{}_{}'.format(op.lower(), model),
|
||||||
|
'{} {} for event'.format(op, model))
|
||||||
|
for op in opes
|
||||||
|
for model in models
|
||||||
|
]
|
||||||
|
|
||||||
|
content_type = ContentType.objects.get_for_model(Event)
|
||||||
|
for (code, verbose) in event_specific_permissions():
|
||||||
|
Permission.objects.get_or_create(
|
||||||
|
name=verbose,
|
||||||
|
content_type=content_type,
|
||||||
|
codename=code
|
||||||
|
)
|
|
@ -1,10 +1,13 @@
|
||||||
from django.contrib.auth import get_user_model
|
from django.contrib.auth import get_user_model
|
||||||
|
from django.contrib.contenttypes.models import ContentType
|
||||||
|
from django.contrib.auth.models import Permission
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from .models import Event, ActivityTemplate, Activity, Place, \
|
from .models import Event, EventGroup, ActivityTemplate, Activity, Place, \
|
||||||
ActivityTag
|
ActivityTag
|
||||||
|
from guardian.shortcuts import assign_perm
|
||||||
|
|
||||||
User = get_user_model()
|
User = get_user_model()
|
||||||
|
|
||||||
|
@ -24,10 +27,8 @@ class ActivityInheritanceTest(TestCase):
|
||||||
created_by=cls.erkan,
|
created_by=cls.erkan,
|
||||||
created_at=timezone.now(),
|
created_at=timezone.now(),
|
||||||
description="La nuit c'est lol",
|
description="La nuit c'est lol",
|
||||||
beginning_date=timezone.now()
|
beginning_date=timezone.now() + timedelta(days=30),
|
||||||
+ timedelta(days=30),
|
ending_date=timezone.now() + timedelta(days=31),
|
||||||
ending_date=timezone.now()
|
|
||||||
+ timedelta(days=31),
|
|
||||||
)
|
)
|
||||||
cls.loge = Place.objects.create(name="Loge 45")
|
cls.loge = Place.objects.create(name="Loge 45")
|
||||||
cls.aqua = Place.objects.create(name="Aquarium")
|
cls.aqua = Place.objects.create(name="Aquarium")
|
||||||
|
@ -47,8 +48,7 @@ class ActivityInheritanceTest(TestCase):
|
||||||
self.real_act = Activity.objects.create(
|
self.real_act = Activity.objects.create(
|
||||||
parent=self.template_act,
|
parent=self.template_act,
|
||||||
event=self.event,
|
event=self.event,
|
||||||
beginning=timezone.now()
|
beginning=timezone.now() + timedelta(days=30),
|
||||||
+ timedelta(days=30),
|
|
||||||
end=timezone.now()
|
end=timezone.now()
|
||||||
+ timedelta(days=30)
|
+ timedelta(days=30)
|
||||||
+ timedelta(hours=2),
|
+ timedelta(hours=2),
|
||||||
|
@ -155,3 +155,50 @@ class ActivityTagColorTest(TestCase):
|
||||||
)
|
)
|
||||||
with self.assertRaises(ValidationError):
|
with self.assertRaises(ValidationError):
|
||||||
self.tag.full_clean()
|
self.tag.full_clean()
|
||||||
|
|
||||||
|
|
||||||
|
class EventPermissionTest(TestCase):
|
||||||
|
@classmethod
|
||||||
|
def setUpTestData(cls):
|
||||||
|
cls.user_perm = User.objects.create(username="userperm")
|
||||||
|
cls.user_noperm = User.objects.create(username="usernoperm")
|
||||||
|
cls.user_groupperm = User.objects.create(username="usergroupperm")
|
||||||
|
cls.user_groupnoperm = User.objects.create(username="usergroupnoperm")
|
||||||
|
cls.root = User.objects.create_superuser(
|
||||||
|
username="root",
|
||||||
|
email="toto@toto.io",
|
||||||
|
password="toto"
|
||||||
|
)
|
||||||
|
cls.event = Event.objects.create(
|
||||||
|
title="Hackathon",
|
||||||
|
slug="django",
|
||||||
|
created_by=cls.root,
|
||||||
|
description="Le code c'est cool",
|
||||||
|
beginning_date=timezone.now(),
|
||||||
|
ending_date=timezone.now() + timedelta(days=1),
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_event_groups(self):
|
||||||
|
groups = EventGroup.objects.filter(
|
||||||
|
event=self.event
|
||||||
|
)
|
||||||
|
self.assertEqual(groups.count(), 2)
|
||||||
|
|
||||||
|
def test_individual_perms(self):
|
||||||
|
assign_perm("event_add_place", self.user_perm, self.event)
|
||||||
|
self.assertTrue(self.user_perm.has_perm("event_add_place", self.event))
|
||||||
|
self.assertFalse(self.user_noperm.has_perm("event_add_place",
|
||||||
|
self.event))
|
||||||
|
|
||||||
|
def test_group_perms(self):
|
||||||
|
orgas = EventGroup.objects.get(
|
||||||
|
name="{}_orgas".format(self.event.slug),
|
||||||
|
)
|
||||||
|
self.user_groupperm.groups.add(orgas)
|
||||||
|
for perm in Permission.objects.filter(
|
||||||
|
content_type=ContentType.objects.get_for_model(Event),
|
||||||
|
codename__contains="event_"):
|
||||||
|
self.assertTrue(self.user_groupperm.has_perm(perm.codename,
|
||||||
|
self.event))
|
||||||
|
self.assertFalse(self.user_groupnoperm.has_perm(perm.codename,
|
||||||
|
self.event))
|
||||||
|
|
|
@ -9,6 +9,7 @@ djangorestframework==3.6.3
|
||||||
drf-nested-routers==0.90.0
|
drf-nested-routers==0.90.0
|
||||||
django-notifications
|
django-notifications
|
||||||
django-contrib-comments
|
django-contrib-comments
|
||||||
|
django-guardian
|
||||||
|
|
||||||
# Production specific
|
# Production specific
|
||||||
daphne
|
daphne
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# Generated by Django 1.11.3 on 2017-07-23 14:14
|
# Generated by Django 1.11.3 on 2017-08-17 12:21
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
import django.contrib.auth.models
|
import django.contrib.auth.models
|
||||||
|
|
|
@ -15,3 +15,6 @@ class User(AbstractUser):
|
||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = _("utilisateur")
|
verbose_name = _("utilisateur")
|
||||||
verbose_name_plural = _("utilisateurs")
|
verbose_name_plural = _("utilisateurs")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue