diff --git a/apps/family/templates/family/challenge_list.html b/apps/family/templates/family/challenge_list.html index 2a1502d0..e7b554a2 100644 --- a/apps/family/templates/family/challenge_list.html +++ b/apps/family/templates/family/challenge_list.html @@ -16,9 +16,11 @@ SPDX-License-Identifier: GPL-3.0-or-later {% trans "Challenges" %} + {% if can_manage %} {% trans "Manage" %} + {% endif %} diff --git a/apps/family/templates/family/family_detail.html b/apps/family/templates/family/family_detail.html index dc38edda..b81fa955 100644 --- a/apps/family/templates/family/family_detail.html +++ b/apps/family/templates/family/family_detail.html @@ -7,6 +7,7 @@ SPDX-License-Identifier: GPL-3.0-or-later {% load i18n perms %} {% block profile_content %} +{% if member_list.data %}
{% trans "Family members" %} @@ -15,11 +16,14 @@ SPDX-License-Identifier: GPL-3.0-or-later
+{% endif %} +{% if achievement_list.data %}
{% trans "Completed challenges" %}
{% render_table achievement_list %}
+{% endif %} {% endblock %} \ No newline at end of file diff --git a/apps/family/templates/family/family_list.html b/apps/family/templates/family/family_list.html index 55feed5e..f06eba6e 100644 --- a/apps/family/templates/family/family_list.html +++ b/apps/family/templates/family/family_list.html @@ -16,9 +16,11 @@ SPDX-License-Identifier: GPL-3.0-or-later {% trans "Challenges" %} + {% if can_manage %} {% trans "Manage" %} + {% endif %}
diff --git a/apps/family/templates/family/manage.html b/apps/family/templates/family/manage.html index cd835c3d..06df632b 100644 --- a/apps/family/templates/family/manage.html +++ b/apps/family/templates/family/manage.html @@ -26,6 +26,7 @@ SPDX-License-Identifier: GPL-3.0-or-later
+ {% if can_add_achievement %}
{# Family details column #}
@@ -81,8 +82,10 @@ SPDX-License-Identifier: GPL-3.0-or-later
+ {% endif %} {# Create family/challenge buttons #} + {% if can_add_family or can_add_challenge %}

{% trans "Create a family or challenge" %} @@ -100,10 +103,12 @@ SPDX-License-Identifier: GPL-3.0-or-later {% endif %}

+ {% endif %} {# Buttons column #}
+ {% if can_add_achievement %}
{# Tabs for list and search #}
@@ -149,10 +154,12 @@ SPDX-License-Identifier: GPL-3.0-or-later
+ {% endif %}
{# achievement history #} +{% if table.data %}
- +{% endif %} {% endblock %} diff --git a/apps/family/views.py b/apps/family/views.py index fee0c5ad..07ecc23c 100644 --- a/apps/family/views.py +++ b/apps/family/views.py @@ -6,6 +6,7 @@ from datetime import date from django.conf import settings from django.shortcuts import redirect from django.contrib.auth.mixins import LoginRequiredMixin +from django.core.exceptions import PermissionDenied from django.db import transaction from django.views.generic import DetailView, UpdateView, ListView from django.views.generic.edit import DeleteView, FormMixin @@ -51,6 +52,24 @@ class FamilyListView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTableView): table_class = FamilyTable extra_context = {"title": _('Families list')} + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + + fake_family = Family(name="", description="") + fake_challenge = Challenge(name="", description="", points=0) + can_add_family = PermissionBackend.check_perm(self.request, "family.add_family", fake_family) + can_add_challenge = PermissionBackend.check_perm(self.request, "family.add_challenge", fake_challenge) + + if Family.objects.exists() and Challenge.objects.exists(): + fake_achievement = Achievement(family=Family.objects.first(), challenge=Challenge.objects.first(), valid=False) + can_add_achievement = PermissionBackend.check_perm(self.request, "family.add_achievement", fake_achievement) + else: + can_add_achievement = False + + context["can_manage"] = can_add_family or can_add_challenge or can_add_achievement + + return context + class FamilyDetailView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView): """ @@ -231,6 +250,24 @@ class ChallengeListView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTableVie table_class = ChallengeTable extra_context = {"title": _('Challenges list')} + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + + fake_family = Family(name="", description="") + fake_challenge = Challenge(name="", description="", points=0) + can_add_family = PermissionBackend.check_perm(self.request, "family.add_family", fake_family) + can_add_challenge = PermissionBackend.check_perm(self.request, "family.add_challenge", fake_challenge) + + if Family.objects.exists() and Challenge.objects.exists(): + fake_achievement = Achievement(family=Family.objects.first(), challenge=Challenge.objects.first(), valid=False) + can_add_achievement = PermissionBackend.check_perm(self.request, "family.add_achievement", fake_achievement) + else: + can_add_achievement = False + + context["can_manage"] = can_add_family or can_add_challenge or can_add_achievement + + return context + class ChallengeDetailView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView): """ @@ -283,6 +320,11 @@ class FamilyManageView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTableView if not request.user.is_authenticated: return self.handle_no_permission() + perm = PermissionBackend.has_model_perm(self.request, Achievement(), "add") + perm = perm or PermissionBackend.has_model_perm(self.request, Challenge(), "add") + perm = perm or PermissionBackend.has_model_perm(self.request, Family(), "add") + if not perm: + raise PermissionDenied(_("You are not able to manage families and challenges.")) return super().dispatch(request, *args, **kwargs) def get_queryset(self, **kwargs): @@ -298,8 +340,9 @@ class FamilyManageView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTableView PermissionBackend.filter_queryset(self.request, Challenge, "view") ).order_by('name') - context["can_add_family"] = PermissionBackend.check_perm(self.request, "family.family_create") - context["can_add_challenge"] = PermissionBackend.check_perm(self.request, "family.challenge_create") + context["can_add_family"] = PermissionBackend.has_model_perm(self.request, Family(), "add") + context["can_add_challenge"] = PermissionBackend.has_model_perm(self.request, Challenge(), "add") + context["can_add_achievement"] = PermissionBackend.has_model_perm(self.request, Achievement(), "add") # Get the user's family if they have one try: @@ -316,6 +359,13 @@ class FamilyManageView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTableView table.orderable = False return table + def get_table_data(self, **kwargs): + qs = super().get_queryset(**kwargs) + + qs = qs.filter(PermissionBackend.filter_queryset(self.request, Achievement, "view")) + + return qs + class AchievementListView(ProtectQuerysetMixin, LoginRequiredMixin, MultiTableMixin, ListView): """ @@ -325,6 +375,14 @@ class AchievementListView(ProtectQuerysetMixin, LoginRequiredMixin, MultiTableMi tables = [AchievementTable, AchievementTable, ] extra_context = {'title': _('Achievement list')} + def dispatch(self, request, *args, **kwargs): + if not request.user.is_authenticated: + return self.handle_no_permission() + + if not PermissionBackend.has_model_perm(self.request, Achievement(), "change"): + raise PermissionDenied(_("You are not able to see the achievement validation interface.")) + return super().dispatch(request, *args, **kwargs) + def get_tables(self, **kwargs): tables = super().get_tables(**kwargs) @@ -355,6 +413,19 @@ class AchievementValidateView(ProtectQuerysetMixin, LoginRequiredMixin, Template """ template_name = 'family/achievement_confirm_validate.html' + def dispatch(self, request, *args, **kwargs): + if not request.user.is_authenticated: + return self.handle_no_permission() + + fake_achievement = Achievement( + family=Family.objects.first(), + challenge=Challenge.objects.first(), + valid=False, + ) + if not PermissionBackend.check_perm(self.request, "family.change_achievement_valid", fake_achievement): + raise PermissionDenied() + return super().dispatch(request, *args, **kwargs) + def post(self, request, pk): achievement = Achievement.objects.get(pk=pk) @@ -370,5 +441,18 @@ class AchievementDeleteView(ProtectQuerysetMixin, LoginRequiredMixin, DeleteView """ model = Achievement + def dispatch(self, request, *args, **kwargs): + if not request.user.is_authenticated: + return self.handle_no_permission() + + fake_achievement = Achievement( + family=Family.objects.first(), + challenge=Challenge.objects.first(), + valid=False, + ) + if not PermissionBackend.check_perm(self.request, "family.change_achievement_valid", fake_achievement): + raise PermissionDenied() + return super().dispatch(request, *args, **kwargs) + def get_success_url(self): return reverse_lazy('family:achievement_list') diff --git a/apps/member/signals.py b/apps/member/signals.py index b1b8cd82..f07c8896 100644 --- a/apps/member/signals.py +++ b/apps/member/signals.py @@ -17,7 +17,6 @@ def save_user_profile(instance, created, raw, **_kwargs): def update_wei_registration_fee_on_membership_creation(sender, instance, created, **kwargs): if not hasattr(instance, "_no_signal") and created: - print('update_wei_registration_fee_on_membership_creation') from wei.models import WEIRegistration if instance.club.id == 1 or instance.club.id == 2: registrations = WEIRegistration.objects.filter( diff --git a/apps/permission/fixtures/initial.json b/apps/permission/fixtures/initial.json index 248574e1..e642c4e6 100644 --- a/apps/permission/fixtures/initial.json +++ b/apps/permission/fixtures/initial.json @@ -4430,6 +4430,262 @@ "description": "Modifier le type de caution de mon inscription WEI tant qu'elle n'est pas validée" } }, + { + "model": "permission.permission", + "pk": 311, + "fields": { + "model": [ + "family", + "family" + ], + "query": "{}", + "type": "view", + "mask": 1, + "field": "", + "permanent": false, + "description": "Voir toutes les familles" + } + }, + { + "model": "permission.permission", + "pk": 312, + "fields": { + "model": [ + "family", + "family" + ], + "query": "{}", + "type": "add", + "mask": 2, + "field": "", + "permanent": false, + "description": "Créer une famille" + } + }, + { + "model": "permission.permission", + "pk": 313, + "fields": { + "model": [ + "family", + "family" + ], + "query": "{}", + "type": "change", + "mask": 2, + "field": "", + "permanent": false, + "description": "Modifier n'importe quelle famille" + } + }, + { + "model": "permission.permission", + "pk": 314, + "fields": { + "model": [ + "family", + "family" + ], + "query": "{\"pk\": [\"user\", \"family_memberships\", \"family\", \"pk\"]}", + "type": "change", + "mask": 2, + "field": "", + "permanent": false, + "description": "Modifier ma famille" + } + }, + { + "model": "permission.permission", + "pk": 315, + "fields": { + "model": [ + "family", + "familymembership" + ], + "query": "{}", + "type": "view", + "mask": 2, + "field": "", + "permanent": false, + "description": "Voir les membres de n'importe quelle famille" + } + }, + { + "model": "permission.permission", + "pk": 316, + "fields": { + "model": [ + "family", + "familymembership" + ], + "query": "{\"family\": [\"user\", \"family_memberships\", \"family\"]}", + "type": "view", + "mask": 1, + "field": "", + "permanent": false, + "description": "Voir les membres de ma famille" + } + }, + { + "model": "permission.permission", + "pk": 317, + "fields": { + "model": [ + "family", + "familymembership" + ], + "query": "{}", + "type": "add", + "mask": 2, + "field": "", + "permanent": false, + "description": "Ajouter un membre à n'importe quelle famille" + } + }, + { + "model": "permission.permission", + "pk": 318, + "fields": { + "model": [ + "family", + "familymembership" + ], + "query": "{\"family\": [\"user\", \"family_memberships\", \"family\"]}", + "type": "add", + "mask": 2, + "field": "", + "permanent": false, + "description": "Ajouter un membre à ma famille" + } + }, + { + "model": "permission.permission", + "pk": 319, + "fields": { + "model": [ + "family", + "challenge" + ], + "query": "{}", + "type": "view", + "mask": 1, + "field": "", + "permanent": false, + "description": "Voir tous les défis" + } + }, + { + "model": "permission.permission", + "pk": 320, + "fields": { + "model": [ + "family", + "challenge" + ], + "query": "{}", + "type": "add", + "mask": 2, + "field": "", + "permanent": false, + "description": "Créer un défi" + } + }, + { + "model": "permission.permission", + "pk": 321, + "fields": { + "model": [ + "family", + "challenge" + ], + "query": "{}", + "type": "change", + "mask": 2, + "field": "", + "permanent": false, + "description": "Modifier un défi" + } + }, + { + "model": "permission.permission", + "pk": 322, + "fields": { + "model": [ + "family", + "challenge" + ], + "query": "{}", + "type": "delete", + "mask": 2, + "field": "{}", + "permanent": false, + "description": "Supprimer un défi" + } + }, + { + "model": "permission.permission", + "pk": 323, + "fields": { + "model": [ + "family", + "achievement" + ], + "query": "{}", + "type": "view", + "mask": 1, + "field": "", + "permanent": false, + "description": "Voir tous les succès" + } + }, + { + "model": "permission.permission", + "pk": 324, + "fields": { + "model": [ + "family", + "achievement" + ], + "query": "{}", + "type": "add", + "mask": 2, + "field": "", + "permanent": false, + "description": "Créer un succès" + } + }, + { + "model": "permission.permission", + "pk": 325, + "fields": { + "model": [ + "family", + "achievement" + ], + "query": "{}", + "type": "change", + "mask": 1, + "field": "valid", + "permanent": false, + "description": "Valider un succès" + } + }, + { + "model": "permission.permission", + "pk": 326, + "fields": { + "model": [ + "family", + "achievement" + ], + "query": "{}", + "type": "delete", + "mask": 1, + "field": "", + "permanent": false, + "description": "Supprimer un succès" + } + }, { "model": "permission.role", "pk": 1, @@ -4482,9 +4738,13 @@ 206, 248, 249, - 255, - 256, - 257 + 255, + 256, + 257, + 311, + 316, + 319, + 323 ] } }, @@ -5008,7 +5268,7 @@ 216 ] } - }, + }, { "model": "permission.role", "pk": 23, @@ -5021,7 +5281,7 @@ 32 ] } - }, + }, { "model": "permission.role", "pk": 24, @@ -5030,7 +5290,7 @@ "name": "Staffeur⋅euse (S&L,Respo Tech,...)", "permissions": [] } - }, + }, { "model": "permission.role", "pk": 25, @@ -5056,7 +5316,7 @@ 293 ] } - }, + }, { "model": "permission.role", "pk": 28, @@ -5086,7 +5346,7 @@ 269 ] } - }, + }, { "model": "permission.role", "pk": 30, @@ -5094,15 +5354,15 @@ "for_club": 10, "name": "Respo sorties", "permissions": [ - 49, - 62, - 141, - 241, - 242, + 49, + 62, + 141, + 241, + 242, 243 ] } - }, + }, { "model": "permission.role", "pk": 31, @@ -5114,7 +5374,7 @@ 244 ] } - }, + }, { "model": "permission.role", "pk": 32, @@ -5126,7 +5386,7 @@ 245 ] } - }, + }, { "model": "permission.role", "pk": 33, @@ -5134,15 +5394,48 @@ "for_club": 10, "name": "Respo Jam", "permissions": [ - 247, - 250, - 251, - 252, - 253, + 247, + 250, + 251, + 252, + 253, 254 ] } - }, + }, + { + "model": "permission.role", + "pk": 34, + "fields": { + "for_club": 1, + "name": "Chef·fe de famille", + "permissions": [ + 314, + 318, + 324 + ] + } + }, + { + "model": "permission.role", + "pk": 35, + "fields": { + "for_club": 1, + "name": "Respo familles", + "permissions": [ + 312, + 313, + 315, + 317, + 320, + 321, + 322, + 324, + 325, + 326 + ] + } + }, { "model": "wei.weirole", "pk": 12,