diff --git a/ephios/core/forms/events.py b/ephios/core/forms/events.py index 14974f4ed..ce199e170 100644 --- a/ephios/core/forms/events.py +++ b/ephios/core/forms/events.py @@ -119,7 +119,7 @@ def save(self, commit=True): # delete existing permissions # (better implement https://github.com/django-guardian/django-guardian/issues/654) for group in get_groups_with_perms( - event, only_with_perms_in=["view_event", "change_event"] + event, only_with_perms_in=["view_event", "change_event"], must_have_all_perms=False ): remove_perm("view_event", group, event) remove_perm("change_event", group, event) diff --git a/ephios/core/forms/users.py b/ephios/core/forms/users.py index 54c14727e..668c5fde3 100644 --- a/ephios/core/forms/users.py +++ b/ephios/core/forms/users.py @@ -25,7 +25,7 @@ from ephios.core.signals import register_group_permission_fields from ephios.core.widgets import MultiUserProfileWidget from ephios.extra.crispy import AbortLink -from ephios.extra.permissions import PermissionField, PermissionFormMixin +from ephios.extra.permissions import PermissionField, PermissionFormMixin, get_groups_with_perms from ephios.extra.widgets import CustomDateInput from ephios.modellogging.log import add_log_recorder from ephios.modellogging.recorders import DerivedFieldsLogRecorder @@ -176,6 +176,24 @@ def __init__(self, **kwargs): ), ) + def clean_is_management_group(self): + is_management_group = self.cleaned_data["is_management_group"] + if self.fields["is_management_group"].initial and not is_management_group: + other_management_groups = get_groups_with_perms( + only_with_perms_in=CORE_MANAGEMENT_PERMISSIONS, + must_have_all_perms=True, + ).exclude(pk=self.instance.pk) + if not other_management_groups.exists(): + raise ValidationError( + _( + "At least one group with management permissions must exist. " + "Please promote another group before demoting this one." + ) + ) + if is_management_group: + self.cleaned_data["is_hr_group"] = True + return is_management_group + def save(self, commit=True): add_log_recorder(self.instance, DerivedFieldsLogRecorder(get_group_permission_log_fields)) group = super().save(commit) @@ -200,7 +218,7 @@ def save(self, commit=True): return group -class UserProfileForm(ModelForm): +class UserProfileForm(PermissionFormMixin, ModelForm): groups = ModelMultipleChoiceField( label=_("Groups"), queryset=Group.objects.all(), @@ -208,6 +226,14 @@ class UserProfileForm(ModelForm): required=False, disabled=True, # explicitly enable for users with `change_group` permission ) + is_staff = PermissionField( + label=_("Administrator"), + help_text=_( + "If checked, this user can change technical ephios settings as well as edit all user profiles, " + "groups, qualifications, events and event types." + ), + permissions=CORE_MANAGEMENT_PERMISSIONS, + ) def __init__(self, *args, **kwargs): request = kwargs.pop("request") @@ -230,6 +256,10 @@ def __init__(self, *args, **kwargs): "Only other technical administrators can change this." ) + @property + def permission_target(self): + return self.instance + field_order = [ "email", "first_name", @@ -280,6 +310,44 @@ def save(self, commit=True): return userprofile +class DeleteUserProfileForm(Form): + def __init__(self, *args, **kwargs): + self.instance = kwargs.pop("instance") + super().__init__(*args, **kwargs) + + def clean(self): + other_staff = UserProfile.objects.filter(is_staff=True).exclude(pk=self.instance.pk) + if self.instance.is_staff and not other_staff.exists(): + raise ValidationError( + _( + "At least one user must be technical administrator. " + "Please promote another user before deleting this one." + ) + ) + + +class DeleteGroupForm(Form): + def __init__(self, *args, **kwargs): + self.instance = kwargs.pop("instance") + super().__init__(*args, **kwargs) + + def clean(self): + management_groups = get_groups_with_perms( + only_with_perms_in=CORE_MANAGEMENT_PERMISSIONS, must_have_all_perms=True + ) + + if ( + self.instance in management_groups + and not management_groups.exclude(pk=self.instance.pk).exists() + ): + raise ValidationError( + _( + "At least one group with management permissions must exist. " + "Please promote another group before deleting this one." + ) + ) + + class QualificationGrantForm(ModelForm): model = QualificationGrant diff --git a/ephios/core/models/users.py b/ephios/core/models/users.py index 92136f83b..e7481a38b 100644 --- a/ephios/core/models/users.py +++ b/ephios/core/models/users.py @@ -104,8 +104,7 @@ class UserProfile(guardian.mixins.GuardianUserMixin, PermissionsMixin, AbstractB is_visible = BooleanField(default=True, verbose_name=_("Visible")) is_staff = BooleanField( default=False, - verbose_name=_("Technical Administrator"), - help_text=_("If checked, this user can change technical ephios settings."), + verbose_name=_("Administrator"), ) first_name = CharField(_("first name"), max_length=254) last_name = CharField(_("last name"), max_length=254) diff --git a/ephios/core/templates/core/group_confirm_delete.html b/ephios/core/templates/core/group_confirm_delete.html index 0d84343b8..369de67f6 100644 --- a/ephios/core/templates/core/group_confirm_delete.html +++ b/ephios/core/templates/core/group_confirm_delete.html @@ -1,4 +1,5 @@ {% extends "base.html" %} +{% load crispy_forms_filters %} {% load i18n %} {% load static %} @@ -12,6 +13,7 @@