models/program: link to editor groups
This commit is contained in:
		
							
								
								
									
										25
									
								
								aircox/migrations/0015_program_editors.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								aircox/migrations/0015_program_editors.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,25 @@
 | 
				
			|||||||
 | 
					# Generated by Django 4.2.5 on 2023-10-18 13:50
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from django.db import migrations, models
 | 
				
			||||||
 | 
					import django.db.models.deletion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Migration(migrations.Migration):
 | 
				
			||||||
 | 
					    dependencies = [
 | 
				
			||||||
 | 
					        ("auth", "0012_alter_user_first_name_max_length"),
 | 
				
			||||||
 | 
					        ("aircox", "0014_alter_schedule_timezone"),
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    operations = [
 | 
				
			||||||
 | 
					        migrations.AddField(
 | 
				
			||||||
 | 
					            model_name="program",
 | 
				
			||||||
 | 
					            name="editors",
 | 
				
			||||||
 | 
					            field=models.ForeignKey(
 | 
				
			||||||
 | 
					                blank=True,
 | 
				
			||||||
 | 
					                null=True,
 | 
				
			||||||
 | 
					                on_delete=django.db.models.deletion.CASCADE,
 | 
				
			||||||
 | 
					                to="auth.group",
 | 
				
			||||||
 | 
					                verbose_name="editors",
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
@ -3,6 +3,8 @@ import os
 | 
				
			|||||||
import shutil
 | 
					import shutil
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from django.conf import settings as conf
 | 
					from django.conf import settings as conf
 | 
				
			||||||
 | 
					from django.contrib.auth.models import Group, Permission
 | 
				
			||||||
 | 
					from django.contrib.contenttypes.models import ContentType
 | 
				
			||||||
from django.db import models
 | 
					from django.db import models
 | 
				
			||||||
from django.db.models import F
 | 
					from django.db.models import F
 | 
				
			||||||
from django.db.models.functions import Concat, Substr
 | 
					from django.db.models.functions import Concat, Substr
 | 
				
			||||||
@ -58,6 +60,7 @@ class Program(Page):
 | 
				
			|||||||
        default=True,
 | 
					        default=True,
 | 
				
			||||||
        help_text=_("update later diffusions according to schedule changes"),
 | 
					        help_text=_("update later diffusions according to schedule changes"),
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					    editors = models.ForeignKey(Group, models.CASCADE, blank=True, null=True, verbose_name=_("editors"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    objects = ProgramQuerySet.as_manager()
 | 
					    objects = ProgramQuerySet.as_manager()
 | 
				
			||||||
    detail_url_name = "program-detail"
 | 
					    detail_url_name = "program-detail"
 | 
				
			||||||
@ -81,6 +84,14 @@ class Program(Page):
 | 
				
			|||||||
    def excerpts_path(self):
 | 
					    def excerpts_path(self):
 | 
				
			||||||
        return os.path.join(self.path, settings.SOUND_ARCHIVES_SUBDIR)
 | 
					        return os.path.join(self.path, settings.SOUND_ARCHIVES_SUBDIR)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @property
 | 
				
			||||||
 | 
					    def editors_group_name(self):
 | 
				
			||||||
 | 
					        return f"{self.title} editors"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @property
 | 
				
			||||||
 | 
					    def change_permission_codename(self):
 | 
				
			||||||
 | 
					        return f"change_program_{self.slug}"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __init__(self, *kargs, **kwargs):
 | 
					    def __init__(self, *kargs, **kwargs):
 | 
				
			||||||
        super().__init__(*kargs, **kwargs)
 | 
					        super().__init__(*kargs, **kwargs)
 | 
				
			||||||
        if self.slug:
 | 
					        if self.slug:
 | 
				
			||||||
@ -110,6 +121,19 @@ class Program(Page):
 | 
				
			|||||||
        os.makedirs(path, exist_ok=True)
 | 
					        os.makedirs(path, exist_ok=True)
 | 
				
			||||||
        return os.path.exists(path)
 | 
					        return os.path.exists(path)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def set_group_ownership(self):
 | 
				
			||||||
 | 
					        editors, created = Group.objects.get_or_create(name=self.editors_group_name)
 | 
				
			||||||
 | 
					        if created:
 | 
				
			||||||
 | 
					            self.editors = editors
 | 
				
			||||||
 | 
					            super().save()
 | 
				
			||||||
 | 
					        permission, _ = Permission.objects.get_or_create(
 | 
				
			||||||
 | 
					            name=f"change program {self.title}",
 | 
				
			||||||
 | 
					            codename=self.change_permission_codename,
 | 
				
			||||||
 | 
					            content_type=ContentType.objects.get_for_model(self),
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        if permission not in editors.permissions.all():
 | 
				
			||||||
 | 
					            editors.permissions.add(permission)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class Meta:
 | 
					    class Meta:
 | 
				
			||||||
        verbose_name = _("Program")
 | 
					        verbose_name = _("Program")
 | 
				
			||||||
        verbose_name_plural = _("Programs")
 | 
					        verbose_name_plural = _("Programs")
 | 
				
			||||||
@ -135,6 +159,8 @@ class Program(Page):
 | 
				
			|||||||
            shutil.move(abspath, self.abspath)
 | 
					            shutil.move(abspath, self.abspath)
 | 
				
			||||||
            Sound.objects.filter(path__startswith=path_).update(file=Concat("file", Substr(F("file"), len(path_))))
 | 
					            Sound.objects.filter(path__startswith=path_).update(file=Concat("file", Substr(F("file"), len(path_))))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.set_group_ownership()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ProgramChildQuerySet(PageQuerySet):
 | 
					class ProgramChildQuerySet(PageQuerySet):
 | 
				
			||||||
    def station(self, station=None, id=None):
 | 
					    def station(self, station=None, id=None):
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,5 @@
 | 
				
			|||||||
import pytest
 | 
					import pytest
 | 
				
			||||||
 | 
					from django.contrib.auth.models import User, Group
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.django_db()
 | 
					@pytest.mark.django_db()
 | 
				
			||||||
@ -12,3 +13,13 @@ def test_no_admin(user, client):
 | 
				
			|||||||
def test_user_cannot_change_program_or_episode(user, client, program):
 | 
					def test_user_cannot_change_program_or_episode(user, client, program):
 | 
				
			||||||
    assert not user.has_perm("aircox.change_program")
 | 
					    assert not user.has_perm("aircox.change_program")
 | 
				
			||||||
    assert not user.has_perm("aircox.change_episode")
 | 
					    assert not user.has_perm("aircox.change_episode")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@pytest.mark.django_db()
 | 
				
			||||||
 | 
					def test_group_can_change_program(user, client, program):
 | 
				
			||||||
 | 
					    assert program.editors in Group.objects.all()
 | 
				
			||||||
 | 
					    assert not user.has_perm("aircox.%s" % program.change_permission_codename)
 | 
				
			||||||
 | 
					    user.groups.add(program.editors)
 | 
				
			||||||
 | 
					    user = User.objects.get(pk=user.pk)  # reload user in order to have permissions set
 | 
				
			||||||
 | 
					    assert program.editors in user.groups.all()
 | 
				
			||||||
 | 
					    assert user.has_perm("aircox.%s" % program.change_permission_codename)
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user