mirror of
https://gitlab.crans.org/bde/nk20
synced 2025-06-20 17:41:55 +02:00
Raise permission denied on CreateView if you don't have the permission to create a sample instance, see #53
This commit is contained in:
@ -124,7 +124,7 @@ class Activity(models.Model):
|
||||
Update the activity wiki page each time the activity is updated (validation, change description, ...)
|
||||
"""
|
||||
ret = super().save(*args, **kwargs)
|
||||
if self.pk and "scripts" in settings.INSTALLED_APPS:
|
||||
if settings.DEBUG and self.pk and "scripts" in settings.INSTALLED_APPS:
|
||||
def refresh_activities():
|
||||
from scripts.management.commands.refresh_activities import Command as RefreshActivitiesCommand
|
||||
RefreshActivitiesCommand.refresh_human_readable_wiki_page("Modification de l'activité " + self.name)
|
||||
|
@ -4,26 +4,39 @@
|
||||
from django.conf import settings
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.core.exceptions import PermissionDenied
|
||||
from django.db.models import F, Q
|
||||
from django.urls import reverse_lazy
|
||||
from django.utils import timezone
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.views.generic import CreateView, DetailView, TemplateView, UpdateView
|
||||
from django.views.generic import DetailView, TemplateView, UpdateView
|
||||
from django_tables2.views import SingleTableView
|
||||
from note.models import Alias, NoteSpecial, NoteUser
|
||||
from permission.backends import PermissionBackend
|
||||
from permission.views import ProtectQuerysetMixin
|
||||
from permission.views import ProtectQuerysetMixin, ProtectedCreateView
|
||||
|
||||
from .forms import ActivityForm, GuestForm
|
||||
from .models import Activity, Entry, Guest
|
||||
from .tables import ActivityTable, EntryTable, GuestTable
|
||||
|
||||
|
||||
class ActivityCreateView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView):
|
||||
class ActivityCreateView(LoginRequiredMixin, ProtectedCreateView):
|
||||
model = Activity
|
||||
form_class = ActivityForm
|
||||
extra_context = {"title": _("Create new activity")}
|
||||
|
||||
def get_sample_object(self):
|
||||
return Activity(
|
||||
name="",
|
||||
description="",
|
||||
creater=self.request.user,
|
||||
activity_type_id=1,
|
||||
organizer_id=1,
|
||||
attendees_club_id=1,
|
||||
date_start=timezone.now(),
|
||||
date_end=timezone.now(),
|
||||
)
|
||||
|
||||
def form_valid(self, form):
|
||||
form.instance.creater = self.request.user
|
||||
return super().form_valid(form)
|
||||
@ -85,11 +98,20 @@ class ActivityUpdateView(ProtectQuerysetMixin, LoginRequiredMixin, UpdateView):
|
||||
return reverse_lazy('activity:activity_detail', kwargs={"pk": self.kwargs["pk"]})
|
||||
|
||||
|
||||
class ActivityInviteView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView):
|
||||
class ActivityInviteView(ProtectQuerysetMixin, LoginRequiredMixin, ProtectedCreateView):
|
||||
model = Guest
|
||||
form_class = GuestForm
|
||||
template_name = "activity/activity_invite.html"
|
||||
|
||||
def get_sample_object(self):
|
||||
activity = Activity.objects.get(pk=self.kwargs["pk"])
|
||||
return Guest(
|
||||
activity=activity,
|
||||
first_name="",
|
||||
last_name="",
|
||||
inviter=self.request.user.note,
|
||||
)
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
activity = context["form"].activity
|
||||
@ -114,6 +136,24 @@ class ActivityInviteView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView):
|
||||
class ActivityEntryView(LoginRequiredMixin, TemplateView):
|
||||
template_name = "activity/activity_entry.html"
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
"""
|
||||
Don't display the entry interface if the user has no right to see it (no right to add an entry for itself),
|
||||
it is closed or doesn't manage entries.
|
||||
"""
|
||||
activity = Activity.objects.get(pk=self.kwargs["pk"])
|
||||
|
||||
sample_entry = Entry(activity=activity, note=self.request.user.note)
|
||||
if not PermissionBackend.check_perm(self.request.user, "activity.add_entry", sample_entry):
|
||||
raise PermissionDenied(_("You are not allowed to display the entry interface for this activity."))
|
||||
|
||||
if not activity.activity_type.manage_entries:
|
||||
raise PermissionDenied(_("This activity does not support activity entries."))
|
||||
|
||||
if not activity.open:
|
||||
raise PermissionDenied(_("This activity is closed."))
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
|
||||
|
@ -1,12 +1,15 @@
|
||||
{% extends "base.html" %}
|
||||
{% load render_table from django_tables2 %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row justify-content-center mb-4">
|
||||
<div class="col-md-10 text-center">
|
||||
<input class="form-control mx-auto w-25" type="text" id="search_field"/>
|
||||
<hr>
|
||||
<a class="btn btn-primary text-center my-4" href="{% url 'member:club_create' %}" data-turbolinks="false">{% trans "Create club" %}</a>
|
||||
{% if can_add_club %}
|
||||
<a class="btn btn-primary text-center my-4" href="{% url 'member:club_create' %}" data-turbolinks="false">{% trans "Create club" %}</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row justify-content-center">
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
from django.contrib.auth.models import User
|
||||
from django.test import TestCase
|
||||
from note.models import TransactionTemplate, TemplateCategory
|
||||
|
||||
"""
|
||||
Test that login page still works
|
||||
@ -16,6 +17,8 @@ class TemplateLoggedOutTests(TestCase):
|
||||
|
||||
|
||||
class TemplateLoggedInTests(TestCase):
|
||||
fixtures = ('initial', )
|
||||
|
||||
def setUp(self):
|
||||
self.user = User.objects.create_superuser(
|
||||
username="admin",
|
||||
@ -48,5 +51,12 @@ class TemplateLoggedInTests(TestCase):
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
def test_consos_page(self):
|
||||
# Create one button and ensure that it is visible
|
||||
cat = TemplateCategory.objects.create()
|
||||
TransactionTemplate.objects.create(
|
||||
destination_id=5,
|
||||
category=cat,
|
||||
amount=0,
|
||||
)
|
||||
response = self.client.get('/note/consos/')
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
@ -15,7 +15,7 @@ from django.shortcuts import redirect
|
||||
from django.urls import reverse_lazy
|
||||
from django.utils import timezone
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.views.generic import CreateView, DetailView, UpdateView, TemplateView
|
||||
from django.views.generic import DetailView, UpdateView, TemplateView
|
||||
from django.views.generic.edit import FormMixin
|
||||
from django_tables2.views import SingleTableView
|
||||
from rest_framework.authtoken.models import Token
|
||||
@ -26,7 +26,7 @@ from note.tables import HistoryTable, AliasTable
|
||||
from note_kfet.middlewares import _set_current_user_and_ip
|
||||
from permission.backends import PermissionBackend
|
||||
from permission.models import Role
|
||||
from permission.views import ProtectQuerysetMixin
|
||||
from permission.views import ProtectQuerysetMixin, ProtectedCreateView
|
||||
|
||||
from .forms import ProfileForm, ClubForm, MembershipForm, CustomAuthenticationForm, UserForm, MembershipRolesForm
|
||||
from .models import Club, Membership
|
||||
@ -295,7 +295,7 @@ class ManageAuthTokens(LoginRequiredMixin, TemplateView):
|
||||
# ******************************* #
|
||||
|
||||
|
||||
class ClubCreateView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView):
|
||||
class ClubCreateView(ProtectQuerysetMixin, LoginRequiredMixin, ProtectedCreateView):
|
||||
"""
|
||||
Create Club
|
||||
"""
|
||||
@ -304,6 +304,12 @@ class ClubCreateView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView):
|
||||
success_url = reverse_lazy('member:club_list')
|
||||
extra_context = {"title": _("Create new club")}
|
||||
|
||||
def get_sample_object(self):
|
||||
return Club(
|
||||
name="",
|
||||
email="",
|
||||
)
|
||||
|
||||
def form_valid(self, form):
|
||||
return super().form_valid(form)
|
||||
|
||||
@ -332,6 +338,14 @@ class ClubListView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTableView):
|
||||
|
||||
return qs
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context["can_add_club"] = PermissionBackend.check_perm(self.request.user, "member.add_club", Club(
|
||||
name="",
|
||||
email="club@example.com",
|
||||
))
|
||||
return context
|
||||
|
||||
|
||||
class ClubDetailView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView):
|
||||
"""
|
||||
@ -432,7 +446,7 @@ class ClubPictureUpdateView(PictureUpdateView):
|
||||
return reverse_lazy('member:club_detail', kwargs={'pk': self.object.id})
|
||||
|
||||
|
||||
class ClubAddMemberView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView):
|
||||
class ClubAddMemberView(ProtectQuerysetMixin, LoginRequiredMixin, ProtectedCreateView):
|
||||
"""
|
||||
Add a membership to a club.
|
||||
"""
|
||||
@ -441,6 +455,19 @@ class ClubAddMemberView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView):
|
||||
template_name = 'member/add_members.html'
|
||||
extra_context = {"title": _("Add new member to the club")}
|
||||
|
||||
def get_sample_object(self):
|
||||
if "club_pk" in self.kwargs:
|
||||
club = Club.objects.get(pk=self.kwargs["club_pk"])
|
||||
else:
|
||||
club = Membership.objects.get(pk=self.kwargs["pk"]).club
|
||||
return Membership(
|
||||
user=self.request.user,
|
||||
club=club,
|
||||
fee=0,
|
||||
date_start=timezone.now(),
|
||||
date_end=timezone.now() + timedelta(days=1),
|
||||
)
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
form = context['form']
|
||||
|
@ -1,10 +1,12 @@
|
||||
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
import json
|
||||
|
||||
from django.conf import settings
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.core.exceptions import PermissionDenied
|
||||
from django.db.models import Q, F
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.views.generic import CreateView, UpdateView, DetailView
|
||||
@ -145,6 +147,14 @@ class ConsoView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTableView):
|
||||
# Transaction history table
|
||||
table_class = HistoryTable
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
templates = TransactionTemplate.objects.filter(
|
||||
PermissionBackend().filter_queryset(self.request.user, TransactionTemplate, "view")
|
||||
)
|
||||
if not templates.exists():
|
||||
raise PermissionDenied(_("You can't see any button."))
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
|
||||
def get_queryset(self, **kwargs):
|
||||
return Transaction.objects.filter(
|
||||
PermissionBackend.filter_queryset(self.request.user, Transaction, "view")
|
||||
|
@ -70,7 +70,7 @@ def pre_save_object(sender, instance, **kwargs):
|
||||
|
||||
if not has_perm:
|
||||
raise PermissionDenied(
|
||||
_("You don't have the permission to add this instance of model {app_label}.{model_name}.")
|
||||
_("You don't have the permission to add an instance of model {app_label}.{model_name}.")
|
||||
.format(app_label=app_label, model_name=model_name, ))
|
||||
|
||||
|
||||
|
0
apps/permission/tests/__init__.py
Normal file
0
apps/permission/tests/__init__.py
Normal file
150
apps/permission/tests/test_permission_denied.py
Normal file
150
apps/permission/tests/test_permission_denied.py
Normal file
@ -0,0 +1,150 @@
|
||||
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
from datetime import timedelta
|
||||
|
||||
from django.contrib.auth.models import User
|
||||
from django.test import TestCase
|
||||
from django.urls import reverse
|
||||
from django.utils import timezone
|
||||
from activity.models import Activity
|
||||
from member.models import Club, Membership
|
||||
from note.models import NoteUser
|
||||
from wei.models import WEIClub, Bus, WEIRegistration
|
||||
|
||||
|
||||
class TestPermissionDenied(TestCase):
|
||||
"""
|
||||
Load some protected pages and check that we have 403 errors.
|
||||
"""
|
||||
fixtures = ('initial',)
|
||||
|
||||
def setUp(self) -> None:
|
||||
# Create sample user with no rights
|
||||
self.user = User.objects.create(
|
||||
username="toto",
|
||||
)
|
||||
NoteUser.objects.create(user=self.user)
|
||||
self.client.force_login(self.user)
|
||||
|
||||
def test_consos(self):
|
||||
response = self.client.get(reverse("note:consos"))
|
||||
self.assertEqual(response.status_code, 403)
|
||||
|
||||
def test_create_activity(self):
|
||||
response = self.client.get(reverse("activity:activity_create"))
|
||||
self.assertEqual(response.status_code, 403)
|
||||
|
||||
def test_activity_entries(self):
|
||||
activity = Activity.objects.create(
|
||||
name="",
|
||||
description="",
|
||||
creater=self.user,
|
||||
activity_type_id=1,
|
||||
organizer_id=1,
|
||||
attendees_club_id=1,
|
||||
date_start=timezone.now(),
|
||||
date_end=timezone.now(),
|
||||
)
|
||||
response = self.client.get(reverse("activity:activity_entry", kwargs=dict(pk=activity.pk)))
|
||||
self.assertEqual(response.status_code, 403)
|
||||
|
||||
def test_invite_activity(self):
|
||||
activity = Activity.objects.create(
|
||||
name="",
|
||||
description="",
|
||||
creater=self.user,
|
||||
activity_type_id=1,
|
||||
organizer_id=1,
|
||||
attendees_club_id=1,
|
||||
date_start=timezone.now(),
|
||||
date_end=timezone.now(),
|
||||
)
|
||||
response = self.client.get(reverse("activity:activity_invite", kwargs=dict(pk=activity.pk)))
|
||||
self.assertEqual(response.status_code, 403)
|
||||
|
||||
def test_create_club(self):
|
||||
response = self.client.get(reverse("member:club_create"))
|
||||
self.assertEqual(response.status_code, 403)
|
||||
|
||||
def test_add_member_club(self):
|
||||
club = Club.objects.create()
|
||||
response = self.client.get(reverse("member:club_add_member", kwargs=dict(club_pk=club.pk)))
|
||||
self.assertEqual(response.status_code, 403)
|
||||
|
||||
def test_renew_membership(self):
|
||||
club = Club.objects.create()
|
||||
membership = Membership.objects.create(user=self.user, club=club)
|
||||
response = self.client.get(reverse("member:club_renew_membership", kwargs=dict(pk=membership.pk)))
|
||||
self.assertEqual(response.status_code, 403)
|
||||
|
||||
def test_create_weiclub(self):
|
||||
response = self.client.get(reverse("wei:wei_create"))
|
||||
self.assertEqual(response.status_code, 403)
|
||||
|
||||
def test_create_wei_bus(self):
|
||||
wei = WEIClub.objects.create(
|
||||
membership_start=timezone.now().date(),
|
||||
date_start=timezone.now().date() + timedelta(days=1),
|
||||
date_end=timezone.now().date() + timedelta(days=1),
|
||||
)
|
||||
response = self.client.get(reverse("wei:add_bus", kwargs=dict(pk=wei.pk)))
|
||||
self.assertEqual(response.status_code, 403)
|
||||
|
||||
def test_create_wei_team(self):
|
||||
wei = WEIClub.objects.create(
|
||||
membership_start=timezone.now().date(),
|
||||
date_start=timezone.now().date() + timedelta(days=1),
|
||||
date_end=timezone.now().date() + timedelta(days=1),
|
||||
)
|
||||
bus = Bus.objects.create(wei=wei)
|
||||
response = self.client.get(reverse("wei:add_team", kwargs=dict(pk=bus.pk)))
|
||||
self.assertEqual(response.status_code, 403)
|
||||
|
||||
def test_create_1a_weiregistration(self):
|
||||
wei = WEIClub.objects.create(
|
||||
membership_start=timezone.now().date(),
|
||||
date_start=timezone.now().date() + timedelta(days=1),
|
||||
date_end=timezone.now().date() + timedelta(days=1),
|
||||
)
|
||||
response = self.client.get(reverse("wei:wei_register_1A", kwargs=dict(wei_pk=wei.pk)))
|
||||
self.assertEqual(response.status_code, 403)
|
||||
|
||||
def test_create_old_weiregistration(self):
|
||||
wei = WEIClub.objects.create(
|
||||
membership_start=timezone.now().date(),
|
||||
date_start=timezone.now().date() + timedelta(days=1),
|
||||
date_end=timezone.now().date() + timedelta(days=1),
|
||||
)
|
||||
response = self.client.get(reverse("wei:wei_register_2A", kwargs=dict(wei_pk=wei.pk)))
|
||||
self.assertEqual(response.status_code, 403)
|
||||
|
||||
def test_validate_weiregistration(self):
|
||||
wei = WEIClub.objects.create(
|
||||
membership_start=timezone.now().date(),
|
||||
date_start=timezone.now().date() + timedelta(days=1),
|
||||
date_end=timezone.now().date() + timedelta(days=1),
|
||||
)
|
||||
registration = WEIRegistration.objects.create(wei=wei, user=self.user, birth_date="2000-01-01")
|
||||
response = self.client.get(reverse("wei:validate_registration", kwargs=dict(pk=registration.pk)))
|
||||
self.assertEqual(response.status_code, 403)
|
||||
|
||||
def test_create_invoice(self):
|
||||
response = self.client.get(reverse("treasury:invoice_create"))
|
||||
self.assertEqual(response.status_code, 403)
|
||||
|
||||
def test_list_invoices(self):
|
||||
response = self.client.get(reverse("treasury:invoice_list"))
|
||||
self.assertEqual(response.status_code, 403)
|
||||
|
||||
def test_create_remittance(self):
|
||||
response = self.client.get(reverse("treasury:remittance_create"))
|
||||
self.assertEqual(response.status_code, 403)
|
||||
|
||||
def test_list_remittance(self):
|
||||
response = self.client.get(reverse("treasury:remittance_list"))
|
||||
self.assertEqual(response.status_code, 403)
|
||||
|
||||
def test_list_soge_credits(self):
|
||||
response = self.client.get(reverse("treasury:soge_credits"))
|
||||
self.assertEqual(response.status_code, 403)
|
@ -10,7 +10,7 @@ from member.models import Club, Membership
|
||||
from note.models import NoteUser, Note, NoteClub, NoteSpecial
|
||||
from wei.models import WEIMembership, WEIRegistration, WEIClub, Bus, BusTeam
|
||||
|
||||
from .models import Permission
|
||||
from ..models import Permission
|
||||
|
||||
|
||||
class PermissionQueryTestCase(TestCase):
|
@ -1,12 +1,14 @@
|
||||
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
from datetime import date
|
||||
|
||||
from django.core.exceptions import PermissionDenied
|
||||
from django.db.models import Q
|
||||
from django.forms import HiddenInput
|
||||
from django.utils import timezone
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.views.generic import UpdateView, TemplateView
|
||||
from django.views.generic import UpdateView, TemplateView, CreateView
|
||||
from member.models import Membership
|
||||
|
||||
from .backends import PermissionBackend
|
||||
@ -42,6 +44,30 @@ class ProtectQuerysetMixin:
|
||||
return form
|
||||
|
||||
|
||||
class ProtectedCreateView(CreateView):
|
||||
"""
|
||||
Extends a CreateView to check is the user has the right to create a sample instance of the given Model.
|
||||
If not, a 403 error is displayed.
|
||||
"""
|
||||
|
||||
def get_sample_object(self):
|
||||
"""
|
||||
return a sample instance of the Model.
|
||||
It should be valid (can be stored properly in database), but must not collide with existing data.
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
model_class = self.model
|
||||
# noinspection PyProtectedMember
|
||||
app_label, model_name = model_class._meta.app_label, model_class._meta.model_name.lower()
|
||||
perm = app_label + ".add_" + model_name
|
||||
if not PermissionBackend.check_perm(request.user, perm, self.get_sample_object()):
|
||||
raise PermissionDenied(_("You don't have the permission to add an instance of model "
|
||||
"{app_label}.{model_name}.").format(app_label=app_label, model_name=model_name))
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
|
||||
|
||||
class RightsView(TemplateView):
|
||||
template_name = "permission/all_rights.html"
|
||||
extra_context = {"title": _("Rights")}
|
||||
|
@ -8,28 +8,28 @@ from tempfile import mkdtemp
|
||||
|
||||
from crispy_forms.helper import FormHelper
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.core.exceptions import ValidationError, PermissionDenied
|
||||
from django.db.models import Q
|
||||
from django.forms import Form
|
||||
from django.http import HttpResponse
|
||||
from django.shortcuts import redirect
|
||||
from django.urls import reverse_lazy
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.views.generic import CreateView, UpdateView, DetailView
|
||||
from django.views.generic import UpdateView, DetailView
|
||||
from django.views.generic.base import View, TemplateView
|
||||
from django.views.generic.edit import BaseFormView, DeleteView
|
||||
from django_tables2 import SingleTableView
|
||||
from note.models import SpecialTransaction, NoteSpecial, Alias
|
||||
from note_kfet.settings.base import BASE_DIR
|
||||
from permission.backends import PermissionBackend
|
||||
from permission.views import ProtectQuerysetMixin
|
||||
from permission.views import ProtectQuerysetMixin, ProtectedCreateView
|
||||
|
||||
from .forms import InvoiceForm, ProductFormSet, ProductFormSetHelper, RemittanceForm, LinkTransactionToRemittanceForm
|
||||
from .models import Invoice, Product, Remittance, SpecialTransactionProxy, SogeCredit
|
||||
from .tables import InvoiceTable, RemittanceTable, SpecialTransactionTable, SogeCreditTable
|
||||
|
||||
|
||||
class InvoiceCreateView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView):
|
||||
class InvoiceCreateView(ProtectQuerysetMixin, LoginRequiredMixin, ProtectedCreateView):
|
||||
"""
|
||||
Create Invoice
|
||||
"""
|
||||
@ -37,6 +37,15 @@ class InvoiceCreateView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView):
|
||||
form_class = InvoiceForm
|
||||
extra_context = {"title": _("Create new invoice")}
|
||||
|
||||
def get_sample_object(self):
|
||||
return Invoice(
|
||||
id=0,
|
||||
object="",
|
||||
description="",
|
||||
name="",
|
||||
address="",
|
||||
)
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
|
||||
@ -72,7 +81,7 @@ class InvoiceCreateView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView):
|
||||
return reverse_lazy('treasury:invoice_list')
|
||||
|
||||
|
||||
class InvoiceListView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTableView):
|
||||
class InvoiceListView(LoginRequiredMixin, SingleTableView):
|
||||
"""
|
||||
List existing Invoices
|
||||
"""
|
||||
@ -80,6 +89,18 @@ class InvoiceListView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTableView)
|
||||
table_class = InvoiceTable
|
||||
extra_context = {"title": _("Invoices list")}
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
sample_invoice = Invoice(
|
||||
id=0,
|
||||
object="",
|
||||
description="",
|
||||
name="",
|
||||
address="",
|
||||
)
|
||||
if not PermissionBackend.check_perm(self.request.user, "treasury.add_invoice", sample_invoice):
|
||||
raise PermissionDenied(_("You are not able to see the treasury interface."))
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
|
||||
|
||||
class InvoiceUpdateView(ProtectQuerysetMixin, LoginRequiredMixin, UpdateView):
|
||||
"""
|
||||
@ -194,7 +215,7 @@ class InvoiceRenderView(LoginRequiredMixin, View):
|
||||
return response
|
||||
|
||||
|
||||
class RemittanceCreateView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView):
|
||||
class RemittanceCreateView(ProtectQuerysetMixin, LoginRequiredMixin, ProtectedCreateView):
|
||||
"""
|
||||
Create Remittance
|
||||
"""
|
||||
@ -202,6 +223,12 @@ class RemittanceCreateView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView)
|
||||
form_class = RemittanceForm
|
||||
extra_context = {"title": _("Create a new remittance")}
|
||||
|
||||
def get_sample_object(self):
|
||||
return Remittance(
|
||||
remittance_type_id=1,
|
||||
comment="",
|
||||
)
|
||||
|
||||
def get_success_url(self):
|
||||
return reverse_lazy('treasury:remittance_list')
|
||||
|
||||
@ -223,6 +250,15 @@ class RemittanceListView(LoginRequiredMixin, TemplateView):
|
||||
template_name = "treasury/remittance_list.html"
|
||||
extra_context = {"title": _("Remittances list")}
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
sample_remittance = Remittance(
|
||||
remittance_type_id=1,
|
||||
comment="",
|
||||
)
|
||||
if not PermissionBackend.check_perm(self.request.user, "treasury.add_remittance", sample_remittance):
|
||||
raise PermissionDenied(_("You are not able to see the treasury interface."))
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
|
||||
@ -340,6 +376,11 @@ class SogeCreditListView(LoginRequiredMixin, ProtectQuerysetMixin, SingleTableVi
|
||||
table_class = SogeCreditTable
|
||||
extra_context = {"title": _("List of credits from the Société générale")}
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
if not self.get_queryset().exists():
|
||||
raise PermissionDenied(_("You are not able to see the treasury interface."))
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
|
||||
def get_queryset(self, **kwargs):
|
||||
"""
|
||||
Filter the table with the given parameter.
|
||||
|
@ -4,7 +4,7 @@
|
||||
import os
|
||||
import shutil
|
||||
import subprocess
|
||||
from datetime import datetime, date
|
||||
from datetime import datetime, date, timedelta
|
||||
from tempfile import mkdtemp
|
||||
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
@ -19,7 +19,7 @@ from django.template.loader import render_to_string
|
||||
from django.urls import reverse_lazy
|
||||
from django.utils import timezone
|
||||
from django.views import View
|
||||
from django.views.generic import DetailView, UpdateView, CreateView, RedirectView, TemplateView
|
||||
from django.views.generic import DetailView, UpdateView, RedirectView, TemplateView
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.views.generic.edit import BaseFormView, DeleteView
|
||||
from django_tables2 import SingleTableView
|
||||
@ -28,7 +28,7 @@ from note.models import Transaction, NoteClub, Alias, SpecialTransaction, NoteSp
|
||||
from note.tables import HistoryTable
|
||||
from note_kfet.settings import BASE_DIR
|
||||
from permission.backends import PermissionBackend
|
||||
from permission.views import ProtectQuerysetMixin
|
||||
from permission.views import ProtectQuerysetMixin, ProtectedCreateView
|
||||
|
||||
from .forms.registration import WEIChooseBusForm
|
||||
from .models import WEIClub, WEIRegistration, WEIMembership, Bus, BusTeam, WEIRole
|
||||
@ -58,6 +58,8 @@ class WEIListView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTableView):
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context["can_create_wei"] = PermissionBackend.check_perm(self.request.user, "wei.add_weiclub", WEIClub(
|
||||
name="",
|
||||
email="weiclub@example.com",
|
||||
year=0,
|
||||
date_start=timezone.now().date(),
|
||||
date_end=timezone.now().date(),
|
||||
@ -65,14 +67,24 @@ class WEIListView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTableView):
|
||||
return context
|
||||
|
||||
|
||||
class WEICreateView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView):
|
||||
class WEICreateView(ProtectQuerysetMixin, LoginRequiredMixin, ProtectedCreateView):
|
||||
"""
|
||||
Create WEI
|
||||
"""
|
||||
|
||||
model = WEIClub
|
||||
form_class = WEIForm
|
||||
extra_context = {"title": _("Create WEI")}
|
||||
|
||||
def get_sample_object(self):
|
||||
return WEIClub(
|
||||
name="",
|
||||
email="weiclub@example.com",
|
||||
year=0,
|
||||
date_start=timezone.now().date(),
|
||||
date_end=timezone.now().date(),
|
||||
)
|
||||
|
||||
def form_valid(self, form):
|
||||
form.instance.requires_membership = True
|
||||
form.instance.parent_club = Club.objects.get(name="Kfet")
|
||||
@ -274,7 +286,7 @@ class WEIUpdateView(ProtectQuerysetMixin, LoginRequiredMixin, UpdateView):
|
||||
return reverse_lazy("wei:wei_detail", kwargs={"pk": self.object.pk})
|
||||
|
||||
|
||||
class BusCreateView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView):
|
||||
class BusCreateView(ProtectQuerysetMixin, LoginRequiredMixin, ProtectedCreateView):
|
||||
"""
|
||||
Create Bus
|
||||
"""
|
||||
@ -282,6 +294,13 @@ class BusCreateView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView):
|
||||
form_class = BusForm
|
||||
extra_context = {"title": _("Create new bus")}
|
||||
|
||||
def get_sample_object(self):
|
||||
wei = WEIClub.objects.get(pk=self.kwargs["pk"])
|
||||
return Bus(
|
||||
wei=wei,
|
||||
name="",
|
||||
)
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
wei = WEIClub.objects.get(pk=self.kwargs["pk"])
|
||||
today = date.today()
|
||||
@ -362,7 +381,7 @@ class BusManageView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView):
|
||||
return context
|
||||
|
||||
|
||||
class BusTeamCreateView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView):
|
||||
class BusTeamCreateView(ProtectQuerysetMixin, LoginRequiredMixin, ProtectedCreateView):
|
||||
"""
|
||||
Create BusTeam
|
||||
"""
|
||||
@ -370,6 +389,14 @@ class BusTeamCreateView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView):
|
||||
form_class = BusTeamForm
|
||||
extra_context = {"title": _("Create new team")}
|
||||
|
||||
def get_sample_object(self):
|
||||
bus = Bus.objects.get(pk=self.kwargs["pk"])
|
||||
return BusTeam(
|
||||
name="",
|
||||
bus=bus,
|
||||
color=0,
|
||||
)
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
wei = WEIClub.objects.get(buses__pk=self.kwargs["pk"])
|
||||
today = date.today()
|
||||
@ -447,7 +474,7 @@ class BusTeamManageView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView):
|
||||
return context
|
||||
|
||||
|
||||
class WEIRegister1AView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView):
|
||||
class WEIRegister1AView(ProtectQuerysetMixin, LoginRequiredMixin, ProtectedCreateView):
|
||||
"""
|
||||
Register a new user to the WEI
|
||||
"""
|
||||
@ -455,6 +482,18 @@ class WEIRegister1AView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView):
|
||||
form_class = WEIRegistrationForm
|
||||
extra_context = {"title": _("Register first year student to the WEI")}
|
||||
|
||||
def get_sample_object(self):
|
||||
wei = WEIClub.objects.get(pk=self.kwargs["wei_pk"])
|
||||
return WEIRegistration(
|
||||
wei=wei,
|
||||
user=self.request.user,
|
||||
first_year=True,
|
||||
birth_date="1970-01-01",
|
||||
gender="No",
|
||||
emergency_contact_name="No",
|
||||
emergency_contact_phone="No",
|
||||
)
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
wei = WEIClub.objects.get(pk=self.kwargs["wei_pk"])
|
||||
today = date.today()
|
||||
@ -502,7 +541,7 @@ class WEIRegister1AView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView):
|
||||
return reverse_lazy("wei:wei_survey", kwargs={"pk": self.object.pk})
|
||||
|
||||
|
||||
class WEIRegister2AView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView):
|
||||
class WEIRegister2AView(ProtectQuerysetMixin, LoginRequiredMixin, ProtectedCreateView):
|
||||
"""
|
||||
Register an old user to the WEI
|
||||
"""
|
||||
@ -510,6 +549,18 @@ class WEIRegister2AView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView):
|
||||
form_class = WEIRegistrationForm
|
||||
extra_context = {"title": _("Register old student to the WEI")}
|
||||
|
||||
def get_sample_object(self):
|
||||
wei = WEIClub.objects.get(pk=self.kwargs["wei_pk"])
|
||||
return WEIRegistration(
|
||||
wei=wei,
|
||||
user=self.request.user,
|
||||
first_year=True,
|
||||
birth_date="1970-01-01",
|
||||
gender="No",
|
||||
emergency_contact_name="No",
|
||||
emergency_contact_phone="No",
|
||||
)
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
wei = WEIClub.objects.get(pk=self.kwargs["wei_pk"])
|
||||
today = date.today()
|
||||
@ -713,7 +764,7 @@ class WEIDeleteRegistrationView(ProtectQuerysetMixin, LoginRequiredMixin, Delete
|
||||
return reverse_lazy('wei:wei_detail', args=(self.object.wei.pk,))
|
||||
|
||||
|
||||
class WEIValidateRegistrationView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView):
|
||||
class WEIValidateRegistrationView(ProtectQuerysetMixin, LoginRequiredMixin, ProtectedCreateView):
|
||||
"""
|
||||
Validate WEI Registration
|
||||
"""
|
||||
@ -721,6 +772,17 @@ class WEIValidateRegistrationView(ProtectQuerysetMixin, LoginRequiredMixin, Crea
|
||||
form_class = WEIMembershipForm
|
||||
extra_context = {"title": _("Validate WEI registration")}
|
||||
|
||||
def get_sample_object(self):
|
||||
registration = WEIRegistration.objects.get(pk=self.kwargs["pk"])
|
||||
return WEIMembership(
|
||||
club=registration.wei,
|
||||
user=registration.user,
|
||||
date_start=timezone.now().date(),
|
||||
date_end=timezone.now().date() + timedelta(days=1),
|
||||
fee=0,
|
||||
registration=registration,
|
||||
)
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
wei = WEIRegistration.objects.get(pk=self.kwargs["pk"]).wei
|
||||
today = date.today()
|
||||
|
Reference in New Issue
Block a user