from django import forms from django.contrib.auth.models import Group from django.template.loader import render_to_string from django.utils.functional import cached_property from django.utils.translation import ugettext_lazy as _ from wagtail.wagtailusers.forms import GroupPagePermissionFormSet from utils.forms import KeepUnselectableModelFormMixin from kfet.auth.fields import BasePermissionsField from kfet.auth.models import Permission class CmsGroupForm(KeepUnselectableModelFormMixin, forms.ModelForm): """ Allow to change permissions related to the cms of a `Group` object. """ access_admin = forms.BooleanField( label=_("Accès à l'administration"), required=False, help_text=_( "Attention : Aucun paramétrage effectué dans cette section " "n'aura d'effet si cette case est décochée." ), ) class Meta: model = Group fields = () def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) group = self.instance if group.pk is not None: self.fields['access_admin'].initial = ( group.permissions.filter(pk=self.access_admin_perm.pk).exists() ) def save(self): group = super().save() if self.cleaned_data['access_admin']: group.permissions.add(self.access_admin_perm) else: group.permissions.remove(self.access_admin_perm) return group @cached_property def access_admin_perm(self): return Permission.objects.get( content_type__app_label='wagtailadmin', codename='access_admin', ) class SnippetsCmsGroupForm(KeepUnselectableModelFormMixin, forms.ModelForm): permissions = BasePermissionsField( label='', required=False, queryset=Permission.kfetcms.all(), ) keep_unselectable_fields = ['permissions'] class Meta: model = Group fields = ('permissions',) def prepare_page_permissions_formset(pages): """ Create a new formset from base `GroupPagePermissionFormSet` Wagtail formset. - The choices of `pages` field of forms are limited to `pages`. - If there is no initial data, add an initial with the first collection selected. - Make 'as_admin_panel' use a custom template. Arguments pages (iterable of `Page`) Returns A formset to select group permissions of pages. """ class RestrictedFormSet(GroupPagePermissionFormSet): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # Remove forms cache, as theirs options are changed. del self.forms # 'initial' must be setup before accessing 'forms'. self.initial = list( filter(lambda i: i['page'] in pages, self.initial)) # This is just little kindness. if not self.initial and pages: self.initial = [{'page': pages[0]}] for form in self.forms: self.customize_form(form) @property def empty_form(self): form = super().empty_form self.customize_form(form) return form def customize_form(self, form): # Widget must be setup before queryset. form.fields['page'].widget = forms.Select() form.fields['page'].queryset = pages # Force use of `CheckboxInput` for `DELETE` field, as `HiddenInput` # is not compatible with `django-formset-js`. form.fields['DELETE'].widget = forms.CheckboxInput() def as_admin_panel(self): # http://docs.wagtail.io/en/latest/reference/hooks.html#register-group-permission-panel template = 'kfet/permissions/page_permissions_formset.html' return render_to_string(template, {'formset': self}) return RestrictedFormSet def prepare_collection_member_permissions_formset(formset_cls, collections): """ Create a new formset from base `formset_cls`. - The choices of `collections` field of forms produced by `formset_cls` are limited to `collections`. - If there is no initial data, add an initial with the first collection selected. - Make 'as_admin_panel' use a custom template. Arguments formset_cls (subclass of `wagtail.wagtailcore.forms` `.BaseGroupCollectionMemberPermissionFormSet` ): Formset to select group permissions of a collection member model. It should be rerieved from the `group_permission_panel` Wagtail hook. This includes the `Document` and `Image` models of Wagtail. collections (iterable of `wagtail.wagtailcore.models.Collection`) Returns A formset to select group permissions of collection-related models. """ class RestrictedFormSet(formset_cls): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # Remove forms cache, as theirs options are changed. del self.forms # 'initial' must be setup before accessing 'forms'. self.initial = list( filter(lambda i: i['collection'] in collections, self.initial)) # This is just little kindness. if not self.initial and collections: self.initial = [{'collection': collections[0]}] for form in self.forms: self.customize_form(form) @property def empty_form(self): form = super().empty_form self.customize_form(form) return form def customize_form(self, form): form.fields['collection'].queryset = collections # Force use of `CheckboxInput` for `DELETE` field, as `HiddenInput` # is not compatible with `django-formset-js`. form.fields['DELETE'].widget = forms.CheckboxInput() def as_admin_panel(self): template = ( 'kfet/permissions/collection_member_permissions_formset.html') model = self.permission_queryset[0].content_type.model_class() return render_to_string(template, { 'formset': self, 'model_name': model._meta.verbose_name_plural, }) return RestrictedFormSet