Better management of roles in ClubMemberForm

This commit is contained in:
imperosol
2025-09-13 18:37:53 +02:00
parent 63125edeaa
commit c76ff92c30
5 changed files with 64 additions and 27 deletions

View File

@@ -26,6 +26,7 @@ from django import forms
from django.conf import settings
from django.db.models import Exists, OuterRef, Q
from django.db.models.functions import Lower
from django.utils.functional import cached_property
from django.utils.translation import gettext_lazy as _
from club.models import Club, Mailing, MailingSubscription, Membership
@@ -217,20 +218,36 @@ class ClubMemberForm(forms.ModelForm):
fields = ["user", "role", "description"]
widgets = {"user": AutoCompleteSelectUser}
def __init__(
self,
*args,
club: Club,
request_user: User,
**kwargs,
):
def __init__(self, *args, club: Club, request_user: User, **kwargs):
self.club = club
self.request_user = request_user
self.request_user_membership = self.club.get_membership_for(self.request_user)
super().__init__(*args, **kwargs)
self.fields["role"].required = True
self.fields["role"].choices = [
(value, name)
for value, name in settings.SITH_CLUB_ROLES.items()
if value <= self.max_available_role
]
self.instance.club = club
@cached_property
def max_available_role(self):
"""The greatest role that will be obtainable with this form.
Admins and the club president can attribute any role.
Board members can attribute roles lower than their own.
Other users can attribute curious and member roles.
"""
if self.request_user.has_perm("club.add_subscription"):
return settings.SITH_CLUB_ROLES_ID["President"]
membership = self.request_user_membership
if membership is not None and membership.role > settings.SITH_MAXIMUM_FREE_ROLE:
if membership.role == settings.SITH_CLUB_ROLES_ID["President"]:
return membership.role
return membership.role - 1
return settings.SITH_MAXIMUM_FREE_ROLE
def clean_user(self):
"""Check that the user is not trying to add a user already in the club.
@@ -248,16 +265,21 @@ class ClubMemberForm(forms.ModelForm):
return user
def clean(self):
"""Check user rights for adding an user."""
"""Check user rights for adding a user."""
cleaned_data = super().clean()
if "role" not in cleaned_data:
return cleaned_data
request_user = self.request_user
membership = self.request_user_membership
if not (
cleaned_data["role"] <= settings.SITH_MAXIMUM_FREE_ROLE
or (membership is not None and membership.role >= cleaned_data["role"])
or request_user.has_perm("club.add_subscription")
):
if (
self.request_user_membership is None
or self.request_user_membership.role <= settings.SITH_MAXIMUM_FREE_ROLE
) and not self.request_user.has_perm("club.add_membership"):
raise forms.ValidationError(
_(
"You cannot add other users to a club "
"if you are not in the club board."
),
code="invalid",
)
if cleaned_data["role"] > self.max_available_role:
raise forms.ValidationError(_("You do not have the permission to do that"))
return cleaned_data

View File

@@ -12,11 +12,13 @@
{% block content %}
<h2>{% trans %}Club members{% endtrans %}</h2>
<br />
<h4>{% trans %}Add a new member{% endtrans %}</h4>
{{ add_member_fragment }}
<br />
{% if add_member_fragment %}
<br />
<h4>{% trans %}Add a new member{% endtrans %}</h4>
{{ add_member_fragment }}
<br />
{% endif %}
{% if members %}
<form action="{{ url('club:club_members', club_id=club.id) }}" id="members_old" method="post">
{% csrf_token %}

View File

@@ -353,7 +353,7 @@ class TestMembership(TestClub):
assert not form.is_valid()
assert form.errors == {
"__all__": ["Vous n'avez pas la permission de faire cela"]
"role": ["Sélectionnez un choix valide. 10 n\u2019en fait pas partie."]
}
self.club.refresh_from_db()
assert nb_memberships == self.club.members.count()

View File

@@ -69,7 +69,7 @@ from com.views import (
from core.auth.mixins import CanCreateMixin, CanEditMixin
from core.models import PageRev
from core.views import DetailFormView, PageEditViewBase, UseFragmentsMixin
from core.views.mixins import FragmentMixin, TabedViewMixin
from core.views.mixins import FragmentMixin, FragmentRenderer, TabedViewMixin
from counter.models import Selling
@@ -301,9 +301,14 @@ class ClubMembersView(
form_class = ClubOldMemberForm
template_name = "club/club_members.jinja"
current_tab = "members"
fragments = {"add_member_fragment": ClubAddMembersFragment}
permission_required = "club.view_club"
def get_fragments(self) -> dict[str, type[FragmentMixin] | FragmentRenderer]:
membership = self.object.get_membership_for(self.request.user)
if membership and membership.role <= settings.SITH_MAXIMUM_FREE_ROLE:
return {}
return {"add_member_fragment": ClubAddMembersFragment}
def get_fragment_data(self) -> dict[str, Any]:
return {"add_member_fragment": {"club": self.object}}