mirror of https://gitlab.crans.org/bde/nk20
Improved permissions, 404 and 403 errors will be more frequent (when we type an invalid URL)
This commit is contained in:
parent
c384ee02eb
commit
1aae18e6a6
|
@ -1,5 +1,6 @@
|
||||||
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay
|
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
from datetime import datetime, timezone
|
from datetime import datetime, timezone
|
||||||
|
|
||||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||||
|
@ -11,13 +12,14 @@ from django.utils.translation import gettext_lazy as _
|
||||||
from django_tables2.views import SingleTableView
|
from django_tables2.views import SingleTableView
|
||||||
from note.models import NoteUser, Alias, NoteSpecial
|
from note.models import NoteUser, Alias, NoteSpecial
|
||||||
from permission.backends import PermissionBackend
|
from permission.backends import PermissionBackend
|
||||||
|
from permission.views import ProtectQuerysetMixin
|
||||||
|
|
||||||
from .forms import ActivityForm, GuestForm
|
from .forms import ActivityForm, GuestForm
|
||||||
from .models import Activity, Guest, Entry
|
from .models import Activity, Guest, Entry
|
||||||
from .tables import ActivityTable, GuestTable, EntryTable
|
from .tables import ActivityTable, GuestTable, EntryTable
|
||||||
|
|
||||||
|
|
||||||
class ActivityCreateView(LoginRequiredMixin, CreateView):
|
class ActivityCreateView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView):
|
||||||
model = Activity
|
model = Activity
|
||||||
form_class = ActivityForm
|
form_class = ActivityForm
|
||||||
|
|
||||||
|
@ -30,13 +32,12 @@ class ActivityCreateView(LoginRequiredMixin, CreateView):
|
||||||
return reverse_lazy('activity:activity_detail', kwargs={"pk": self.object.pk})
|
return reverse_lazy('activity:activity_detail', kwargs={"pk": self.object.pk})
|
||||||
|
|
||||||
|
|
||||||
class ActivityListView(LoginRequiredMixin, SingleTableView):
|
class ActivityListView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTableView):
|
||||||
model = Activity
|
model = Activity
|
||||||
table_class = ActivityTable
|
table_class = ActivityTable
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
return super().get_queryset()\
|
return super().get_queryset().reverse()
|
||||||
.filter(PermissionBackend.filter_queryset(self.request.user, Activity, "view")).reverse()
|
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
ctx = super().get_context_data(**kwargs)
|
ctx = super().get_context_data(**kwargs)
|
||||||
|
@ -50,7 +51,7 @@ class ActivityListView(LoginRequiredMixin, SingleTableView):
|
||||||
return ctx
|
return ctx
|
||||||
|
|
||||||
|
|
||||||
class ActivityDetailView(LoginRequiredMixin, DetailView):
|
class ActivityDetailView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView):
|
||||||
model = Activity
|
model = Activity
|
||||||
context_object_name = "activity"
|
context_object_name = "activity"
|
||||||
|
|
||||||
|
@ -66,7 +67,7 @@ class ActivityDetailView(LoginRequiredMixin, DetailView):
|
||||||
return ctx
|
return ctx
|
||||||
|
|
||||||
|
|
||||||
class ActivityUpdateView(LoginRequiredMixin, UpdateView):
|
class ActivityUpdateView(ProtectQuerysetMixin, LoginRequiredMixin, UpdateView):
|
||||||
model = Activity
|
model = Activity
|
||||||
form_class = ActivityForm
|
form_class = ActivityForm
|
||||||
|
|
||||||
|
@ -74,18 +75,20 @@ class ActivityUpdateView(LoginRequiredMixin, UpdateView):
|
||||||
return reverse_lazy('activity:activity_detail', kwargs={"pk": self.kwargs["pk"]})
|
return reverse_lazy('activity:activity_detail', kwargs={"pk": self.kwargs["pk"]})
|
||||||
|
|
||||||
|
|
||||||
class ActivityInviteView(LoginRequiredMixin, CreateView):
|
class ActivityInviteView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView):
|
||||||
model = Guest
|
model = Guest
|
||||||
form_class = GuestForm
|
form_class = GuestForm
|
||||||
template_name = "activity/activity_invite.html"
|
template_name = "activity/activity_invite.html"
|
||||||
|
|
||||||
def get_form(self, form_class=None):
|
def get_form(self, form_class=None):
|
||||||
form = super().get_form(form_class)
|
form = super().get_form(form_class)
|
||||||
form.activity = Activity.objects.get(pk=self.kwargs["pk"])
|
form.activity = Activity.objects.filter(PermissionBackend.filter_queryset(self.request.user, Activity, "view"))\
|
||||||
|
.get(pk=self.kwargs["pk"])
|
||||||
return form
|
return form
|
||||||
|
|
||||||
def form_valid(self, form):
|
def form_valid(self, form):
|
||||||
form.instance.activity = Activity.objects.get(pk=self.kwargs["pk"])
|
form.instance.activity = Activity.objects\
|
||||||
|
.filter(PermissionBackend.filter_queryset(self.request.user, Activity, "view")).get(pk=self.kwargs["pk"])
|
||||||
return super().form_valid(form)
|
return super().form_valid(form)
|
||||||
|
|
||||||
def get_success_url(self, **kwargs):
|
def get_success_url(self, **kwargs):
|
||||||
|
@ -98,7 +101,8 @@ class ActivityEntryView(LoginRequiredMixin, TemplateView):
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
ctx = super().get_context_data(**kwargs)
|
ctx = super().get_context_data(**kwargs)
|
||||||
|
|
||||||
activity = Activity.objects.get(pk=self.kwargs["pk"])
|
activity = Activity.objects.filter(PermissionBackend.filter_queryset(self.request.user, Activity, "view"))\
|
||||||
|
.get(pk=self.kwargs["pk"])
|
||||||
ctx["activity"] = activity
|
ctx["activity"] = activity
|
||||||
|
|
||||||
matched = []
|
matched = []
|
||||||
|
|
|
@ -49,7 +49,13 @@ class ClubForm(forms.ModelForm):
|
||||||
model = Club
|
model = Club
|
||||||
fields = '__all__'
|
fields = '__all__'
|
||||||
widgets = {
|
widgets = {
|
||||||
"membership_fee": AmountInput()
|
"membership_fee": AmountInput(),
|
||||||
|
"parent_club": Autocomplete(
|
||||||
|
Club,
|
||||||
|
attrs={
|
||||||
|
'api_url': '/api/members/club/',
|
||||||
|
}
|
||||||
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,7 @@ from note.models.notes import NoteActivity
|
||||||
from note.models.transactions import Transaction
|
from note.models.transactions import Transaction
|
||||||
from note.tables import HistoryTable, AliasTable, NoteActivityTable
|
from note.tables import HistoryTable, AliasTable, NoteActivityTable
|
||||||
from permission.backends import PermissionBackend
|
from permission.backends import PermissionBackend
|
||||||
|
from permission.views import ProtectQuerysetMixin
|
||||||
|
|
||||||
from .filters import UserFilter, UserFilterFormHelper
|
from .filters import UserFilter, UserFilterFormHelper
|
||||||
from .forms import SignUpForm, ProfileForm, ClubForm, MembershipForm, MemberFormSet, FormSetHelper, \
|
from .forms import SignUpForm, ProfileForm, ClubForm, MembershipForm, MemberFormSet, FormSetHelper, \
|
||||||
|
@ -64,7 +65,7 @@ class UserCreateView(CreateView):
|
||||||
return super().form_valid(form)
|
return super().form_valid(form)
|
||||||
|
|
||||||
|
|
||||||
class UserUpdateView(LoginRequiredMixin, UpdateView):
|
class UserUpdateView(ProtectQuerysetMixin, LoginRequiredMixin, UpdateView):
|
||||||
model = User
|
model = User
|
||||||
fields = ['first_name', 'last_name', 'username', 'email']
|
fields = ['first_name', 'last_name', 'username', 'email']
|
||||||
template_name = 'member/profile_update.html'
|
template_name = 'member/profile_update.html'
|
||||||
|
@ -98,7 +99,8 @@ class UserUpdateView(LoginRequiredMixin, UpdateView):
|
||||||
if form.is_valid() and profile_form.is_valid():
|
if form.is_valid() and profile_form.is_valid():
|
||||||
new_username = form.data['username']
|
new_username = form.data['username']
|
||||||
alias = Alias.objects.filter(name=new_username)
|
alias = Alias.objects.filter(name=new_username)
|
||||||
# Si le nouveau pseudo n'est pas un de nos alias, on supprime éventuellement un alias similaire pour le remplacer
|
# Si le nouveau pseudo n'est pas un de nos alias,
|
||||||
|
# on supprime éventuellement un alias similaire pour le remplacer
|
||||||
if not alias.exists():
|
if not alias.exists():
|
||||||
similar = Alias.objects.filter(
|
similar = Alias.objects.filter(
|
||||||
normalized_name=Alias.normalize(new_username))
|
normalized_name=Alias.normalize(new_username))
|
||||||
|
@ -120,7 +122,7 @@ class UserUpdateView(LoginRequiredMixin, UpdateView):
|
||||||
return reverse_lazy('member:user_detail', args=(self.object.id,))
|
return reverse_lazy('member:user_detail', args=(self.object.id,))
|
||||||
|
|
||||||
|
|
||||||
class UserDetailView(LoginRequiredMixin, DetailView):
|
class UserDetailView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView):
|
||||||
"""
|
"""
|
||||||
Affiche les informations sur un utilisateur, sa note, ses clubs...
|
Affiche les informations sur un utilisateur, sa note, ses clubs...
|
||||||
"""
|
"""
|
||||||
|
@ -128,9 +130,6 @@ class UserDetailView(LoginRequiredMixin, DetailView):
|
||||||
context_object_name = "user_object"
|
context_object_name = "user_object"
|
||||||
template_name = "member/profile_detail.html"
|
template_name = "member/profile_detail.html"
|
||||||
|
|
||||||
def get_queryset(self, **kwargs):
|
|
||||||
return super().get_queryset().filter(PermissionBackend.filter_queryset(self.request.user, User, "view"))
|
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
context = super().get_context_data(**kwargs)
|
context = super().get_context_data(**kwargs)
|
||||||
user = context['user_object']
|
user = context['user_object']
|
||||||
|
@ -138,13 +137,13 @@ class UserDetailView(LoginRequiredMixin, DetailView):
|
||||||
Transaction.objects.all().filter(Q(source=user.note) | Q(destination=user.note)).order_by("-id")\
|
Transaction.objects.all().filter(Q(source=user.note) | Q(destination=user.note)).order_by("-id")\
|
||||||
.filter(PermissionBackend.filter_queryset(self.request.user, Transaction, "view"))
|
.filter(PermissionBackend.filter_queryset(self.request.user, Transaction, "view"))
|
||||||
context['history_list'] = HistoryTable(history_list)
|
context['history_list'] = HistoryTable(history_list)
|
||||||
club_list = \
|
club_list = Membership.objects.all().filter(user=user)\
|
||||||
Membership.objects.all().filter(user=user).only("club")
|
.filter(PermissionBackend.filter_queryset(self.request.user, Membership, "view")).only("club")
|
||||||
context['club_list'] = ClubTable(club_list)
|
context['club_list'] = ClubTable(club_list)
|
||||||
return context
|
return context
|
||||||
|
|
||||||
|
|
||||||
class UserListView(LoginRequiredMixin, SingleTableView):
|
class UserListView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTableView):
|
||||||
"""
|
"""
|
||||||
Affiche la liste des utilisateurs, avec une fonction de recherche statique
|
Affiche la liste des utilisateurs, avec une fonction de recherche statique
|
||||||
"""
|
"""
|
||||||
|
@ -155,7 +154,7 @@ class UserListView(LoginRequiredMixin, SingleTableView):
|
||||||
formhelper_class = UserFilterFormHelper
|
formhelper_class = UserFilterFormHelper
|
||||||
|
|
||||||
def get_queryset(self, **kwargs):
|
def get_queryset(self, **kwargs):
|
||||||
qs = super().get_queryset().filter(PermissionBackend.filter_queryset(self.request.user, User, "view"))
|
qs = super().get_queryset()
|
||||||
self.filter = self.filter_class(self.request.GET, queryset=qs)
|
self.filter = self.filter_class(self.request.GET, queryset=qs)
|
||||||
self.filter.form.helper = self.formhelper_class()
|
self.filter.form.helper = self.formhelper_class()
|
||||||
return self.filter.qs
|
return self.filter.qs
|
||||||
|
@ -166,7 +165,7 @@ class UserListView(LoginRequiredMixin, SingleTableView):
|
||||||
return context
|
return context
|
||||||
|
|
||||||
|
|
||||||
class ProfileAliasView(LoginRequiredMixin, DetailView):
|
class ProfileAliasView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView):
|
||||||
model = User
|
model = User
|
||||||
template_name = 'member/profile_alias.html'
|
template_name = 'member/profile_alias.html'
|
||||||
context_object_name = 'user_object'
|
context_object_name = 'user_object'
|
||||||
|
@ -178,7 +177,7 @@ class ProfileAliasView(LoginRequiredMixin, DetailView):
|
||||||
return context
|
return context
|
||||||
|
|
||||||
|
|
||||||
class PictureUpdateView(LoginRequiredMixin, FormMixin, DetailView):
|
class PictureUpdateView(ProtectQuerysetMixin, LoginRequiredMixin, FormMixin, DetailView):
|
||||||
form_class = ImageForm
|
form_class = ImageForm
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
|
@ -239,8 +238,7 @@ class ManageAuthTokens(LoginRequiredMixin, TemplateView):
|
||||||
template_name = "member/manage_auth_tokens.html"
|
template_name = "member/manage_auth_tokens.html"
|
||||||
|
|
||||||
def get(self, request, *args, **kwargs):
|
def get(self, request, *args, **kwargs):
|
||||||
if 'regenerate' in request.GET and Token.objects.filter(
|
if 'regenerate' in request.GET and Token.objects.filter(user=request.user).exists():
|
||||||
user=request.user).exists():
|
|
||||||
Token.objects.get(user=self.request.user).delete()
|
Token.objects.get(user=self.request.user).delete()
|
||||||
return redirect(reverse_lazy('member:auth_token') + "?show",
|
return redirect(reverse_lazy('member:auth_token') + "?show",
|
||||||
permanent=True)
|
permanent=True)
|
||||||
|
@ -249,8 +247,7 @@ class ManageAuthTokens(LoginRequiredMixin, TemplateView):
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
context = super().get_context_data(**kwargs)
|
context = super().get_context_data(**kwargs)
|
||||||
context['token'] = Token.objects.get_or_create(
|
context['token'] = Token.objects.get_or_create(user=self.request.user)[0]
|
||||||
user=self.request.user)[0]
|
|
||||||
return context
|
return context
|
||||||
|
|
||||||
|
|
||||||
|
@ -259,7 +256,7 @@ class ManageAuthTokens(LoginRequiredMixin, TemplateView):
|
||||||
# ******************************* #
|
# ******************************* #
|
||||||
|
|
||||||
|
|
||||||
class ClubCreateView(LoginRequiredMixin, CreateView):
|
class ClubCreateView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView):
|
||||||
"""
|
"""
|
||||||
Create Club
|
Create Club
|
||||||
"""
|
"""
|
||||||
|
@ -271,38 +268,32 @@ class ClubCreateView(LoginRequiredMixin, CreateView):
|
||||||
return super().form_valid(form)
|
return super().form_valid(form)
|
||||||
|
|
||||||
|
|
||||||
class ClubListView(LoginRequiredMixin, SingleTableView):
|
class ClubListView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTableView):
|
||||||
"""
|
"""
|
||||||
List existing Clubs
|
List existing Clubs
|
||||||
"""
|
"""
|
||||||
model = Club
|
model = Club
|
||||||
table_class = ClubTable
|
table_class = ClubTable
|
||||||
|
|
||||||
def get_queryset(self, **kwargs):
|
|
||||||
return super().get_queryset().filter(PermissionBackend.filter_queryset(self.request.user, Club, "view"))
|
|
||||||
|
|
||||||
|
class ClubDetailView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView):
|
||||||
class ClubDetailView(LoginRequiredMixin, DetailView):
|
|
||||||
model = Club
|
model = Club
|
||||||
context_object_name = "club"
|
context_object_name = "club"
|
||||||
|
|
||||||
def get_queryset(self, **kwargs):
|
|
||||||
return super().get_queryset().filter(PermissionBackend.filter_queryset(self.request.user, Club, "view"))
|
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
context = super().get_context_data(**kwargs)
|
context = super().get_context_data(**kwargs)
|
||||||
club = context["club"]
|
club = context["club"]
|
||||||
club_transactions = Transaction.objects.all().filter(Q(source=club.note) | Q(destination=club.note))\
|
club_transactions = Transaction.objects.all().filter(Q(source=club.note) | Q(destination=club.note))\
|
||||||
.filter(PermissionBackend.filter_queryset(self.request.user, Transaction, "view")).order_by('-id')
|
.filter(PermissionBackend.filter_queryset(self.request.user, Transaction, "view")).order_by('-id')
|
||||||
context['history_list'] = HistoryTable(club_transactions)
|
context['history_list'] = HistoryTable(club_transactions)
|
||||||
club_member = \
|
club_member = Membership.objects.filter(club=club)\
|
||||||
Membership.objects.all().filter(club=club)
|
.filter(PermissionBackend.filter_queryset(self.request.user, Membership, "view")).all()
|
||||||
# TODO: consider only valid Membership
|
# TODO: consider only valid Membership
|
||||||
context['member_list'] = club_member
|
context['member_list'] = club_member
|
||||||
return context
|
return context
|
||||||
|
|
||||||
|
|
||||||
class ClubAliasView(LoginRequiredMixin, DetailView):
|
class ClubAliasView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView):
|
||||||
model = Club
|
model = Club
|
||||||
template_name = 'member/club_alias.html'
|
template_name = 'member/club_alias.html'
|
||||||
context_object_name = 'club'
|
context_object_name = 'club'
|
||||||
|
@ -314,7 +305,7 @@ class ClubAliasView(LoginRequiredMixin, DetailView):
|
||||||
return context
|
return context
|
||||||
|
|
||||||
|
|
||||||
class ClubUpdateView(LoginRequiredMixin, UpdateView):
|
class ClubUpdateView(ProtectQuerysetMixin, LoginRequiredMixin, UpdateView):
|
||||||
model = Club
|
model = Club
|
||||||
context_object_name = "club"
|
context_object_name = "club"
|
||||||
form_class = ClubForm
|
form_class = ClubForm
|
||||||
|
@ -333,7 +324,7 @@ class ClubPictureUpdateView(PictureUpdateView):
|
||||||
return reverse_lazy('member:club_detail', kwargs={'pk': self.object.id})
|
return reverse_lazy('member:club_detail', kwargs={'pk': self.object.id})
|
||||||
|
|
||||||
|
|
||||||
class ClubAddMemberView(LoginRequiredMixin, CreateView):
|
class ClubAddMemberView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView):
|
||||||
model = Membership
|
model = Membership
|
||||||
form_class = MembershipForm
|
form_class = MembershipForm
|
||||||
template_name = 'member/add_members.html'
|
template_name = 'member/add_members.html'
|
||||||
|
@ -344,7 +335,8 @@ class ClubAddMemberView(LoginRequiredMixin, CreateView):
|
||||||
"change"))
|
"change"))
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
club = Club.objects.get(pk=self.kwargs["pk"])
|
club = Club.objects.filter(PermissionBackend.filter_queryset(self.request.user, Club, "view"))\
|
||||||
|
.get(pk=self.kwargs["pk"])
|
||||||
context = super().get_context_data(**kwargs)
|
context = super().get_context_data(**kwargs)
|
||||||
context['formset'] = MemberFormSet()
|
context['formset'] = MemberFormSet()
|
||||||
context['helper'] = FormSetHelper()
|
context['helper'] = FormSetHelper()
|
||||||
|
@ -367,36 +359,40 @@ class ClubAddMemberView(LoginRequiredMixin, CreateView):
|
||||||
return super().form_valid(formset)
|
return super().form_valid(formset)
|
||||||
|
|
||||||
|
|
||||||
class ClubLinkedNotesView(LoginRequiredMixin, SingleTableView):
|
class ClubLinkedNotesView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTableView):
|
||||||
model = NoteActivity
|
model = NoteActivity
|
||||||
table_class = NoteActivityTable
|
table_class = NoteActivityTable
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
return super().get_queryset().filter(club=self.get_object())\
|
return super().get_queryset().filter(club=self.get_object())
|
||||||
.filter(PermissionBackend.filter_queryset(self.request.user, NoteActivity, "view"))
|
|
||||||
|
|
||||||
def get_object(self):
|
def get_object(self):
|
||||||
if hasattr(self, 'object'):
|
if hasattr(self, 'object'):
|
||||||
return self.object
|
return self.object
|
||||||
self.object = Club.objects.get(pk=int(self.kwargs["pk"]))
|
self.object = Club.objects.filter(PermissionBackend.filter_queryset(self.request.user, Club, "view"))\
|
||||||
|
.get(pk=int(self.kwargs["pk"]))
|
||||||
return self.object
|
return self.object
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
ctx = super().get_context_data(**kwargs)
|
ctx = super().get_context_data(**kwargs)
|
||||||
|
|
||||||
ctx["object"] = ctx["club"] = self.get_object()
|
club = ctx["object"] = ctx["club"] = self.get_object()
|
||||||
|
|
||||||
|
empty_note = NoteActivity(note_name="", club=club, controller=self.request.user)
|
||||||
|
ctx["can_create"] = PermissionBackend().has_perm(self.request.user, "note.add_noteactivity", empty_note)
|
||||||
|
|
||||||
return ctx
|
return ctx
|
||||||
|
|
||||||
|
|
||||||
class ClubLinkedNoteCreateView(LoginRequiredMixin, CreateView):
|
class ClubLinkedNoteCreateView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView):
|
||||||
model = NoteActivity
|
model = NoteActivity
|
||||||
form_class = NoteActivityForm
|
form_class = NoteActivityForm
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
ctx = super().get_context_data(**kwargs)
|
ctx = super().get_context_data(**kwargs)
|
||||||
|
|
||||||
club = Club.objects.get(pk=self.kwargs["club_pk"])
|
club = Club.objects.filter(PermissionBackend.filter_queryset(self.request.user, Club, "view"))\
|
||||||
|
.get(pk=self.kwargs["club_pk"])
|
||||||
ctx["object"] = ctx["club"] = club
|
ctx["object"] = ctx["club"] = club
|
||||||
ctx["form"].fields["club"].initial = club
|
ctx["form"].fields["club"].initial = club
|
||||||
|
|
||||||
|
@ -408,14 +404,15 @@ class ClubLinkedNoteCreateView(LoginRequiredMixin, CreateView):
|
||||||
kwargs={"club_pk": self.object.club.pk, "pk": self.object.pk})
|
kwargs={"club_pk": self.object.club.pk, "pk": self.object.pk})
|
||||||
|
|
||||||
|
|
||||||
class ClubLinkedNoteUpdateView(LoginRequiredMixin, UpdateView):
|
class ClubLinkedNoteUpdateView(ProtectQuerysetMixin, LoginRequiredMixin, UpdateView):
|
||||||
model = NoteActivity
|
model = NoteActivity
|
||||||
form_class = NoteActivityForm
|
form_class = NoteActivityForm
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
ctx = super().get_context_data(**kwargs)
|
ctx = super().get_context_data(**kwargs)
|
||||||
|
|
||||||
ctx["club"] = Club.objects.get(pk=self.kwargs["club_pk"])
|
ctx["club"] = Club.objects.filter(PermissionBackend.filter_queryset(self.request.user, Club, "view"))\
|
||||||
|
.get(pk=self.kwargs["club_pk"])
|
||||||
|
|
||||||
return ctx
|
return ctx
|
||||||
|
|
||||||
|
@ -424,15 +421,15 @@ class ClubLinkedNoteUpdateView(LoginRequiredMixin, UpdateView):
|
||||||
kwargs={"club_pk": self.object.club.pk, "pk": self.object.pk})
|
kwargs={"club_pk": self.object.club.pk, "pk": self.object.pk})
|
||||||
|
|
||||||
|
|
||||||
class ClubLinkedNoteDetailView(LoginRequiredMixin, DetailView):
|
class ClubLinkedNoteDetailView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView):
|
||||||
model = NoteActivity
|
model = NoteActivity
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
ctx = super().get_context_data(**kwargs)
|
ctx = super().get_context_data(**kwargs)
|
||||||
|
|
||||||
note = NoteActivity.objects.get(pk=self.kwargs["pk"])
|
note = self.get_queryset().filter(pk=self.kwargs["pk"]).get()
|
||||||
|
|
||||||
transactions = Transaction.objects.all().filter(Q(source=note) | Q(destination=note))\
|
transactions = Transaction.objects.filter(Q(source=note) | Q(destination=note))\
|
||||||
.filter(PermissionBackend.filter_queryset(self.request.user, Transaction, "view")).order_by("-id")
|
.filter(PermissionBackend.filter_queryset(self.request.user, Transaction, "view")).order_by("-id")
|
||||||
ctx['history_list'] = HistoryTable(transactions)
|
ctx['history_list'] = HistoryTable(transactions)
|
||||||
ctx["note"] = note
|
ctx["note"] = note
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay
|
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
from .notes import Alias, Note, NoteClub, NoteSpecial, NoteUser
|
from .notes import Alias, Note, NoteClub, NoteSpecial, NoteUser, NoteActivity
|
||||||
from .transactions import MembershipTransaction, Transaction, \
|
from .transactions import MembershipTransaction, Transaction, \
|
||||||
TemplateCategory, TransactionTemplate, RecurrentTransaction, SpecialTransaction
|
TemplateCategory, TransactionTemplate, RecurrentTransaction, SpecialTransaction
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
# Notes
|
# Notes
|
||||||
'Alias', 'Note', 'NoteClub', 'NoteSpecial', 'NoteUser',
|
'Alias', 'Note', 'NoteClub', 'NoteSpecial', 'NoteUser', 'NoteActivity',
|
||||||
# Transactions
|
# Transactions
|
||||||
'MembershipTransaction', 'Transaction', 'TemplateCategory', 'TransactionTemplate',
|
'MembershipTransaction', 'Transaction', 'TemplateCategory', 'TransactionTemplate',
|
||||||
'RecurrentTransaction', 'SpecialTransaction',
|
'RecurrentTransaction', 'SpecialTransaction',
|
||||||
|
|
|
@ -9,6 +9,7 @@ from django_tables2 import SingleTableView
|
||||||
from django.urls import reverse_lazy
|
from django.urls import reverse_lazy
|
||||||
from note_kfet.inputs import AmountInput
|
from note_kfet.inputs import AmountInput
|
||||||
from permission.backends import PermissionBackend
|
from permission.backends import PermissionBackend
|
||||||
|
from permission.views import ProtectQuerysetMixin
|
||||||
|
|
||||||
from .forms import TransactionTemplateForm
|
from .forms import TransactionTemplateForm
|
||||||
from .models import Transaction, TransactionTemplate, RecurrentTransaction, NoteSpecial
|
from .models import Transaction, TransactionTemplate, RecurrentTransaction, NoteSpecial
|
||||||
|
@ -16,7 +17,7 @@ from .models.transactions import SpecialTransaction
|
||||||
from .tables import HistoryTable, ButtonTable
|
from .tables import HistoryTable, ButtonTable
|
||||||
|
|
||||||
|
|
||||||
class TransactionCreateView(LoginRequiredMixin, SingleTableView):
|
class TransactionCreateView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTableView):
|
||||||
"""
|
"""
|
||||||
View for the creation of Transaction between two note which are not :models:`transactions.RecurrentTransaction`.
|
View for the creation of Transaction between two note which are not :models:`transactions.RecurrentTransaction`.
|
||||||
e.g. for donation/transfer between people and clubs or for credit/debit with :models:`note.NoteSpecial`
|
e.g. for donation/transfer between people and clubs or for credit/debit with :models:`note.NoteSpecial`
|
||||||
|
@ -26,12 +27,9 @@ class TransactionCreateView(LoginRequiredMixin, SingleTableView):
|
||||||
model = Transaction
|
model = Transaction
|
||||||
# Transaction history table
|
# Transaction history table
|
||||||
table_class = HistoryTable
|
table_class = HistoryTable
|
||||||
table_pagination = {"per_page": 50}
|
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self, **kwargs):
|
||||||
return Transaction.objects.filter(PermissionBackend.filter_queryset(
|
return super().get_queryset(**kwargs).order_by("-id").all()[:50]
|
||||||
self.request.user, Transaction, "view")
|
|
||||||
).order_by("-id").all()[:50]
|
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
"""
|
"""
|
||||||
|
@ -42,12 +40,14 @@ class TransactionCreateView(LoginRequiredMixin, SingleTableView):
|
||||||
context['amount_widget'] = AmountInput(attrs={"id": "amount"})
|
context['amount_widget'] = AmountInput(attrs={"id": "amount"})
|
||||||
context['polymorphic_ctype'] = ContentType.objects.get_for_model(Transaction).pk
|
context['polymorphic_ctype'] = ContentType.objects.get_for_model(Transaction).pk
|
||||||
context['special_polymorphic_ctype'] = ContentType.objects.get_for_model(SpecialTransaction).pk
|
context['special_polymorphic_ctype'] = ContentType.objects.get_for_model(SpecialTransaction).pk
|
||||||
context['special_types'] = NoteSpecial.objects.order_by("special_type").all()
|
context['special_types'] = NoteSpecial.objects\
|
||||||
|
.filter(PermissionBackend.filter_queryset(self.request.user, NoteSpecial, "view"))\
|
||||||
|
.order_by("special_type").all()
|
||||||
|
|
||||||
return context
|
return context
|
||||||
|
|
||||||
|
|
||||||
class TransactionTemplateCreateView(LoginRequiredMixin, CreateView):
|
class TransactionTemplateCreateView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView):
|
||||||
"""
|
"""
|
||||||
Create TransactionTemplate
|
Create TransactionTemplate
|
||||||
"""
|
"""
|
||||||
|
@ -56,7 +56,7 @@ class TransactionTemplateCreateView(LoginRequiredMixin, CreateView):
|
||||||
success_url = reverse_lazy('note:template_list')
|
success_url = reverse_lazy('note:template_list')
|
||||||
|
|
||||||
|
|
||||||
class TransactionTemplateListView(LoginRequiredMixin, SingleTableView):
|
class TransactionTemplateListView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTableView):
|
||||||
"""
|
"""
|
||||||
List TransactionsTemplates
|
List TransactionsTemplates
|
||||||
"""
|
"""
|
||||||
|
@ -64,7 +64,7 @@ class TransactionTemplateListView(LoginRequiredMixin, SingleTableView):
|
||||||
table_class = ButtonTable
|
table_class = ButtonTable
|
||||||
|
|
||||||
|
|
||||||
class TransactionTemplateUpdateView(LoginRequiredMixin, UpdateView):
|
class TransactionTemplateUpdateView(ProtectQuerysetMixin, LoginRequiredMixin, UpdateView):
|
||||||
"""
|
"""
|
||||||
"""
|
"""
|
||||||
model = TransactionTemplate
|
model = TransactionTemplate
|
||||||
|
@ -72,21 +72,19 @@ class TransactionTemplateUpdateView(LoginRequiredMixin, UpdateView):
|
||||||
success_url = reverse_lazy('note:template_list')
|
success_url = reverse_lazy('note:template_list')
|
||||||
|
|
||||||
|
|
||||||
class ConsoView(LoginRequiredMixin, SingleTableView):
|
class ConsoView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTableView):
|
||||||
"""
|
"""
|
||||||
The Magic View that make people pay their beer and burgers.
|
The Magic View that make people pay their beer and burgers.
|
||||||
(Most of the magic happens in the dark world of Javascript see consos.js)
|
(Most of the magic happens in the dark world of Javascript see consos.js)
|
||||||
"""
|
"""
|
||||||
|
model = Transaction
|
||||||
template_name = "note/conso_form.html"
|
template_name = "note/conso_form.html"
|
||||||
|
|
||||||
# Transaction history table
|
# Transaction history table
|
||||||
table_class = HistoryTable
|
table_class = HistoryTable
|
||||||
table_pagination = {"per_page": 50}
|
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self, **kwargs):
|
||||||
return Transaction.objects.filter(
|
return super().get_queryset(**kwargs).order_by("-id").all()[:50]
|
||||||
PermissionBackend.filter_queryset(self.request.user, Transaction, "view")
|
|
||||||
).order_by("-id").all()[:50]
|
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -5,7 +5,7 @@ from django.contrib.auth.backends import ModelBackend
|
||||||
from django.contrib.auth.models import User, AnonymousUser
|
from django.contrib.auth.models import User, AnonymousUser
|
||||||
from django.contrib.contenttypes.models import ContentType
|
from django.contrib.contenttypes.models import ContentType
|
||||||
from django.db.models import Q, F
|
from django.db.models import Q, F
|
||||||
from note.models import Note, NoteUser, NoteClub, NoteSpecial
|
from note.models import Note, NoteUser, NoteClub, NoteSpecial, NoteActivity
|
||||||
from note_kfet.middlewares import get_current_session
|
from note_kfet.middlewares import get_current_session
|
||||||
from member.models import Membership, Club
|
from member.models import Membership, Club
|
||||||
|
|
||||||
|
@ -35,7 +35,7 @@ class PermissionBackend(ModelBackend):
|
||||||
model__app_label=model.app_label, # For polymorphic models, we don't filter on model type
|
model__app_label=model.app_label, # For polymorphic models, we don't filter on model type
|
||||||
type=type,
|
type=type,
|
||||||
).all():
|
).all():
|
||||||
if not isinstance(model, permission.model.__class__):
|
if not isinstance(model, permission.model.__class__) or not permission.club:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
club = Club.objects.get(pk=permission.club)
|
club = Club.objects.get(pk=permission.club)
|
||||||
|
@ -49,6 +49,7 @@ class PermissionBackend(ModelBackend):
|
||||||
NoteUser=NoteUser,
|
NoteUser=NoteUser,
|
||||||
NoteClub=NoteClub,
|
NoteClub=NoteClub,
|
||||||
NoteSpecial=NoteSpecial,
|
NoteSpecial=NoteSpecial,
|
||||||
|
NoteActivity=NoteActivity,
|
||||||
F=F,
|
F=F,
|
||||||
Q=Q
|
Q=Q
|
||||||
)
|
)
|
||||||
|
|
|
@ -176,7 +176,7 @@
|
||||||
"note",
|
"note",
|
||||||
"alias"
|
"alias"
|
||||||
],
|
],
|
||||||
"query": "[\"OR\", {\"note__in\": [\"NoteUser\", \"objects\", [\"filter\", {\"user__membership__club__name\": \"Kfet\"}], [\"all\"]]}, {\"note__in\": [\"NoteClub\", \"objects\", [\"all\"]]}]",
|
"query": "[\"OR\", {\"note__in\": [\"NoteUser\", \"objects\", [\"filter\", {\"user__membership__club__name\": \"Kfet\"}], [\"all\"]]}, {\"note__in\": [\"NoteClub\", \"objects\", [\"all\"]]}, {\"note__in\": [\"NoteActivity\", \"objects\", [\"all\"]]}]",
|
||||||
"type": "view",
|
"type": "view",
|
||||||
"mask": 1,
|
"mask": 1,
|
||||||
"field": "",
|
"field": "",
|
||||||
|
@ -386,7 +386,7 @@
|
||||||
"note",
|
"note",
|
||||||
"transaction"
|
"transaction"
|
||||||
],
|
],
|
||||||
"query": "[\"AND\", [\"OR\", {\"source\": [\"club\", \"note\"]}, {\"destination\": [\"club\", \"note\"]}], {\"amount__lte\": {\"F\": [\"ADD\", [\"F\", \"source__balance\"], 5000]}}]",
|
"query": "[\"AND\", [\"OR\", {\"source\": [\"club\", \"note\"]}, {\"destination\": [\"club\", \"note\"]}], [\"OR\", {\"amount__lte\": {\"F\": [\"ADD\", [\"F\", \"source__balance\"], 5000]}}, {\"valid\": false}]]",
|
||||||
"type": "add",
|
"type": "add",
|
||||||
"mask": 2,
|
"mask": 2,
|
||||||
"field": "",
|
"field": "",
|
||||||
|
@ -783,6 +783,111 @@
|
||||||
"description": "Validate invitation transactions"
|
"description": "Validate invitation transactions"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"model": "permission.permission",
|
||||||
|
"pk": 47,
|
||||||
|
"fields": {
|
||||||
|
"model": [
|
||||||
|
"member",
|
||||||
|
"club"
|
||||||
|
],
|
||||||
|
"query": "{\"pk\": [\"club\", \"pk\"]}",
|
||||||
|
"type": "change",
|
||||||
|
"mask": 1,
|
||||||
|
"field": "",
|
||||||
|
"description": "Update club"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"model": "permission.permission",
|
||||||
|
"pk": 48,
|
||||||
|
"fields": {
|
||||||
|
"model": [
|
||||||
|
"note",
|
||||||
|
"noteactivity"
|
||||||
|
],
|
||||||
|
"query": "{\"club\": [\"club\"]}",
|
||||||
|
"type": "change",
|
||||||
|
"mask": 1,
|
||||||
|
"field": "",
|
||||||
|
"description": "Manage notes that are linked to a club"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"model": "permission.permission",
|
||||||
|
"pk": 49,
|
||||||
|
"fields": {
|
||||||
|
"model": [
|
||||||
|
"note",
|
||||||
|
"noteactivity"
|
||||||
|
],
|
||||||
|
"query": "{\"club\": [\"club\"]}",
|
||||||
|
"type": "view",
|
||||||
|
"mask": 1,
|
||||||
|
"field": "",
|
||||||
|
"description": "View notes that are linked to a club"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"model": "permission.permission",
|
||||||
|
"pk": 50,
|
||||||
|
"fields": {
|
||||||
|
"model": [
|
||||||
|
"note",
|
||||||
|
"transaction"
|
||||||
|
],
|
||||||
|
"query": "[\"AND\", [\"OR\", {\"source__noteactivity__controller\": [\"user\"]}, {\"destination__noteactivity__controller\": [\"user\"]}], [\"OR\", {\"amount__lte\": {\"F\": [\"ADD\", [\"F\", \"source__balance\"], 5000]}}, {\"valid\": false}]]",
|
||||||
|
"type": "add",
|
||||||
|
"mask": 2,
|
||||||
|
"field": "",
|
||||||
|
"description": "Add transactions linked to a noteactivity"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"model": "permission.permission",
|
||||||
|
"pk": 51,
|
||||||
|
"fields": {
|
||||||
|
"model": [
|
||||||
|
"note",
|
||||||
|
"transaction"
|
||||||
|
],
|
||||||
|
"query": "[\"AND\", [\"OR\", {\"source__noteactivity__controller\": [\"user\"]}, {\"destination__noteactivity__controller\": [\"user\"]}]]",
|
||||||
|
"type": "view",
|
||||||
|
"mask": 1,
|
||||||
|
"field": "",
|
||||||
|
"description": "View transactions linked to a noteactivity"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"model": "permission.permission",
|
||||||
|
"pk": 52,
|
||||||
|
"fields": {
|
||||||
|
"model": [
|
||||||
|
"note",
|
||||||
|
"note"
|
||||||
|
],
|
||||||
|
"query": "{\"noteactivity__controller\": [\"user\"]}",
|
||||||
|
"type": "view",
|
||||||
|
"mask": 1,
|
||||||
|
"field": "",
|
||||||
|
"description": "View note activity"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"model": "permission.permission",
|
||||||
|
"pk": 53,
|
||||||
|
"fields": {
|
||||||
|
"model": [
|
||||||
|
"note",
|
||||||
|
"noteactivity"
|
||||||
|
],
|
||||||
|
"query": "{\"controller\": [\"user\"]}",
|
||||||
|
"type": "view",
|
||||||
|
"mask": 1,
|
||||||
|
"field": "",
|
||||||
|
"description": "View note activity"
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"model": "permission.rolepermissions",
|
"model": "permission.rolepermissions",
|
||||||
"pk": 1,
|
"pk": 1,
|
||||||
|
@ -810,7 +915,6 @@
|
||||||
3,
|
3,
|
||||||
4,
|
4,
|
||||||
5,
|
5,
|
||||||
6,
|
|
||||||
7,
|
7,
|
||||||
8,
|
8,
|
||||||
9,
|
9,
|
||||||
|
@ -827,7 +931,12 @@
|
||||||
35,
|
35,
|
||||||
36,
|
36,
|
||||||
39,
|
39,
|
||||||
40
|
40,
|
||||||
|
6,
|
||||||
|
52,
|
||||||
|
53,
|
||||||
|
51,
|
||||||
|
50
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -838,9 +947,9 @@
|
||||||
"role": 8,
|
"role": 8,
|
||||||
"permissions": [
|
"permissions": [
|
||||||
19,
|
19,
|
||||||
20,
|
|
||||||
21,
|
21,
|
||||||
22
|
22,
|
||||||
|
20
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -880,5 +989,18 @@
|
||||||
46
|
46
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"model": "permission.rolepermissions",
|
||||||
|
"pk": 6,
|
||||||
|
"fields": {
|
||||||
|
"role": 7,
|
||||||
|
"permissions": [
|
||||||
|
22,
|
||||||
|
47,
|
||||||
|
48,
|
||||||
|
49
|
||||||
|
]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -38,20 +38,29 @@ class InstancedPermission:
|
||||||
if permission_type == self.type:
|
if permission_type == self.type:
|
||||||
self.update_query()
|
self.update_query()
|
||||||
|
|
||||||
# Don't increase indexes
|
# Don't increase indexes, if the primary key is an AutoField
|
||||||
|
if not hasattr(obj, "pk") or not obj.pk:
|
||||||
obj.pk = 0
|
obj.pk = 0
|
||||||
|
oldpk = None
|
||||||
|
else:
|
||||||
|
oldpk = obj.pk
|
||||||
|
# Ensure previous models are deleted
|
||||||
|
self.model.model_class().objects.filter(pk=obj.pk).delete()
|
||||||
# Force insertion, no data verification, no trigger
|
# Force insertion, no data verification, no trigger
|
||||||
Model.save(obj, force_insert=True)
|
Model.save(obj, force_insert=True)
|
||||||
ret = obj in self.model.model_class().objects.filter(self.query).all()
|
ret = self.model.model_class().objects.filter(self.query & Q(pk=obj.pk)).exists()
|
||||||
# Delete testing object
|
# Delete testing object
|
||||||
Model.delete(obj)
|
Model.delete(obj)
|
||||||
|
|
||||||
|
# If the primary key was specified, we restore it
|
||||||
|
obj.pk = oldpk
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
if permission_type == self.type:
|
if permission_type == self.type:
|
||||||
if self.field and field_name != self.field:
|
if self.field and field_name != self.field:
|
||||||
return False
|
return False
|
||||||
self.update_query()
|
self.update_query()
|
||||||
return obj in self.model.model_class().objects.filter(self.query).all()
|
return self.model.model_class().objects.filter(self.query & Q(pk=obj.pk)).exists()
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay
|
||||||
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
from permission.backends import PermissionBackend
|
||||||
|
|
||||||
|
|
||||||
|
class ProtectQuerysetMixin:
|
||||||
|
def get_queryset(self, **kwargs):
|
||||||
|
qs = super().get_queryset(**kwargs)
|
||||||
|
|
||||||
|
return qs.filter(PermissionBackend.filter_queryset(self.request.user, qs.model, "view"))
|
|
@ -8,6 +8,7 @@ from crispy_forms.layout import Submit
|
||||||
from django import forms
|
from django import forms
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
from note_kfet.inputs import DatePickerInput, AmountInput
|
from note_kfet.inputs import DatePickerInput, AmountInput
|
||||||
|
from permission.backends import PermissionBackend
|
||||||
|
|
||||||
from .models import Invoice, Product, Remittance, SpecialTransactionProxy
|
from .models import Invoice, Product, Remittance, SpecialTransactionProxy
|
||||||
|
|
||||||
|
@ -131,7 +132,8 @@ class LinkTransactionToRemittanceForm(forms.ModelForm):
|
||||||
# Add submit button
|
# Add submit button
|
||||||
self.helper.add_input(Submit('submit', _("Submit"), attr={'class': 'btn btn-block btn-primary'}))
|
self.helper.add_input(Submit('submit', _("Submit"), attr={'class': 'btn btn-block btn-primary'}))
|
||||||
|
|
||||||
self.fields["remittance"].queryset = Remittance.objects.filter(closed=False)
|
self.fields["remittance"].queryset = Remittance.objects.filter(closed=False)\
|
||||||
|
.filter(PermissionBackend.filter_queryset(self.request.user, Remittance, "view"))
|
||||||
|
|
||||||
def clean_last_name(self):
|
def clean_last_name(self):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -19,13 +19,15 @@ from django.views.generic.base import View, TemplateView
|
||||||
from django_tables2 import SingleTableView
|
from django_tables2 import SingleTableView
|
||||||
from note.models import SpecialTransaction, NoteSpecial
|
from note.models import SpecialTransaction, NoteSpecial
|
||||||
from note_kfet.settings.base import BASE_DIR
|
from note_kfet.settings.base import BASE_DIR
|
||||||
|
from permission.backends import PermissionBackend
|
||||||
|
from permission.views import ProtectQuerysetMixin
|
||||||
|
|
||||||
from .forms import InvoiceForm, ProductFormSet, ProductFormSetHelper, RemittanceForm, LinkTransactionToRemittanceForm
|
from .forms import InvoiceForm, ProductFormSet, ProductFormSetHelper, RemittanceForm, LinkTransactionToRemittanceForm
|
||||||
from .models import Invoice, Product, Remittance, SpecialTransactionProxy
|
from .models import Invoice, Product, Remittance, SpecialTransactionProxy
|
||||||
from .tables import InvoiceTable, RemittanceTable, SpecialTransactionTable
|
from .tables import InvoiceTable, RemittanceTable, SpecialTransactionTable
|
||||||
|
|
||||||
|
|
||||||
class InvoiceCreateView(LoginRequiredMixin, CreateView):
|
class InvoiceCreateView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView):
|
||||||
"""
|
"""
|
||||||
Create Invoice
|
Create Invoice
|
||||||
"""
|
"""
|
||||||
|
@ -67,7 +69,7 @@ class InvoiceCreateView(LoginRequiredMixin, CreateView):
|
||||||
return reverse_lazy('treasury:invoice_list')
|
return reverse_lazy('treasury:invoice_list')
|
||||||
|
|
||||||
|
|
||||||
class InvoiceListView(LoginRequiredMixin, SingleTableView):
|
class InvoiceListView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTableView):
|
||||||
"""
|
"""
|
||||||
List existing Invoices
|
List existing Invoices
|
||||||
"""
|
"""
|
||||||
|
@ -75,7 +77,7 @@ class InvoiceListView(LoginRequiredMixin, SingleTableView):
|
||||||
table_class = InvoiceTable
|
table_class = InvoiceTable
|
||||||
|
|
||||||
|
|
||||||
class InvoiceUpdateView(LoginRequiredMixin, UpdateView):
|
class InvoiceUpdateView(ProtectQuerysetMixin, LoginRequiredMixin, UpdateView):
|
||||||
"""
|
"""
|
||||||
Create Invoice
|
Create Invoice
|
||||||
"""
|
"""
|
||||||
|
@ -130,7 +132,7 @@ class InvoiceRenderView(LoginRequiredMixin, View):
|
||||||
|
|
||||||
def get(self, request, **kwargs):
|
def get(self, request, **kwargs):
|
||||||
pk = kwargs["pk"]
|
pk = kwargs["pk"]
|
||||||
invoice = Invoice.objects.get(pk=pk)
|
invoice = Invoice.objects.filter(PermissionBackend.filter_queryset(request.user, Invoice, "view")).get(pk=pk)
|
||||||
products = Product.objects.filter(invoice=invoice).all()
|
products = Product.objects.filter(invoice=invoice).all()
|
||||||
|
|
||||||
# Informations of the BDE. Should be updated when the school will move.
|
# Informations of the BDE. Should be updated when the school will move.
|
||||||
|
@ -188,7 +190,7 @@ class InvoiceRenderView(LoginRequiredMixin, View):
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
|
||||||
class RemittanceCreateView(LoginRequiredMixin, CreateView):
|
class RemittanceCreateView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView):
|
||||||
"""
|
"""
|
||||||
Create Remittance
|
Create Remittance
|
||||||
"""
|
"""
|
||||||
|
@ -201,7 +203,9 @@ class RemittanceCreateView(LoginRequiredMixin, CreateView):
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
ctx = super().get_context_data(**kwargs)
|
ctx = super().get_context_data(**kwargs)
|
||||||
|
|
||||||
ctx["table"] = RemittanceTable(data=Remittance.objects.all())
|
ctx["table"] = RemittanceTable(data=Remittance.objects
|
||||||
|
.filter(PermissionBackend.filter_queryset(self.request.user, Remittance, "view"))
|
||||||
|
.all())
|
||||||
ctx["special_transactions"] = SpecialTransactionTable(data=SpecialTransaction.objects.none())
|
ctx["special_transactions"] = SpecialTransactionTable(data=SpecialTransaction.objects.none())
|
||||||
|
|
||||||
return ctx
|
return ctx
|
||||||
|
@ -216,22 +220,28 @@ class RemittanceListView(LoginRequiredMixin, TemplateView):
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
ctx = super().get_context_data(**kwargs)
|
ctx = super().get_context_data(**kwargs)
|
||||||
|
|
||||||
ctx["opened_remittances"] = RemittanceTable(data=Remittance.objects.filter(closed=False).all())
|
ctx["opened_remittances"] = RemittanceTable(
|
||||||
ctx["closed_remittances"] = RemittanceTable(data=Remittance.objects.filter(closed=True).reverse().all())
|
data=Remittance.objects.filter(closed=False).filter(
|
||||||
|
PermissionBackend.filter_queryset(self.request.user, Remittance, "view")).all())
|
||||||
|
ctx["closed_remittances"] = RemittanceTable(
|
||||||
|
data=Remittance.objects.filter(closed=True).filter(
|
||||||
|
PermissionBackend.filter_queryset(self.request.user, Remittance, "view")).reverse().all())
|
||||||
|
|
||||||
ctx["special_transactions_no_remittance"] = SpecialTransactionTable(
|
ctx["special_transactions_no_remittance"] = SpecialTransactionTable(
|
||||||
data=SpecialTransaction.objects.filter(source__in=NoteSpecial.objects.filter(~Q(remittancetype=None)),
|
data=SpecialTransaction.objects.filter(source__in=NoteSpecial.objects.filter(~Q(remittancetype=None)),
|
||||||
specialtransactionproxy__remittance=None).all(),
|
specialtransactionproxy__remittance=None).filter(
|
||||||
|
PermissionBackend.filter_queryset(self.request.user, Remittance, "view")).all(),
|
||||||
exclude=('remittance_remove', ))
|
exclude=('remittance_remove', ))
|
||||||
ctx["special_transactions_with_remittance"] = SpecialTransactionTable(
|
ctx["special_transactions_with_remittance"] = SpecialTransactionTable(
|
||||||
data=SpecialTransaction.objects.filter(source__in=NoteSpecial.objects.filter(~Q(remittancetype=None)),
|
data=SpecialTransaction.objects.filter(source__in=NoteSpecial.objects.filter(~Q(remittancetype=None)),
|
||||||
specialtransactionproxy__remittance__closed=False).all(),
|
specialtransactionproxy__remittance__closed=False).filter(
|
||||||
|
PermissionBackend.filter_queryset(self.request.user, Remittance, "view")).all(),
|
||||||
exclude=('remittance_add', ))
|
exclude=('remittance_add', ))
|
||||||
|
|
||||||
return ctx
|
return ctx
|
||||||
|
|
||||||
|
|
||||||
class RemittanceUpdateView(LoginRequiredMixin, UpdateView):
|
class RemittanceUpdateView(ProtectQuerysetMixin, LoginRequiredMixin, UpdateView):
|
||||||
"""
|
"""
|
||||||
Update Remittance
|
Update Remittance
|
||||||
"""
|
"""
|
||||||
|
@ -244,8 +254,10 @@ class RemittanceUpdateView(LoginRequiredMixin, UpdateView):
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
ctx = super().get_context_data(**kwargs)
|
ctx = super().get_context_data(**kwargs)
|
||||||
|
|
||||||
ctx["table"] = RemittanceTable(data=Remittance.objects.all())
|
ctx["table"] = RemittanceTable(data=Remittance.objects.filter(
|
||||||
data = SpecialTransaction.objects.filter(specialtransactionproxy__remittance=self.object).all()
|
PermissionBackend.filter_queryset(self.request.user, Remittance, "view")).all())
|
||||||
|
data = SpecialTransaction.objects.filter(specialtransactionproxy__remittance=self.object).filter(
|
||||||
|
PermissionBackend.filter_queryset(self.request.user, Remittance, "view")).all()
|
||||||
ctx["special_transactions"] = SpecialTransactionTable(
|
ctx["special_transactions"] = SpecialTransactionTable(
|
||||||
data=data,
|
data=data,
|
||||||
exclude=('remittance_add', 'remittance_remove', ) if self.object.closed else ('remittance_add', ))
|
exclude=('remittance_add', 'remittance_remove', ) if self.object.closed else ('remittance_add', ))
|
||||||
|
@ -253,7 +265,7 @@ class RemittanceUpdateView(LoginRequiredMixin, UpdateView):
|
||||||
return ctx
|
return ctx
|
||||||
|
|
||||||
|
|
||||||
class LinkTransactionToRemittanceView(LoginRequiredMixin, UpdateView):
|
class LinkTransactionToRemittanceView(ProtectQuerysetMixin, LoginRequiredMixin, UpdateView):
|
||||||
"""
|
"""
|
||||||
Attach a special transaction to a remittance
|
Attach a special transaction to a remittance
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
{% load render_table from django_tables2 %}
|
{% load render_table from django_tables2 %}
|
||||||
{% load pretty_money %}
|
{% load pretty_money %}
|
||||||
|
{% load perms %}
|
||||||
|
|
||||||
{% block profile_info %}
|
{% block profile_info %}
|
||||||
{% include "member/club_info.html" %}
|
{% include "member/club_info.html" %}
|
||||||
|
@ -25,9 +26,11 @@
|
||||||
<dd class="col-xl-6">{{ note.balance|pretty_money }}</dd>
|
<dd class="col-xl-6">{{ note.balance|pretty_money }}</dd>
|
||||||
</dl>
|
</dl>
|
||||||
|
|
||||||
|
{% if "change_"|has_perm:note %}
|
||||||
<div class="card-footer text-center">
|
<div class="card-footer text-center">
|
||||||
<a class="btn btn-primary btn-sm my-1" href="{% url 'member:club_linked_note_update' club_pk=club.pk pk=note.pk %}"> {% trans "Edit" %}</a>
|
<a class="btn btn-primary btn-sm my-1" href="{% url 'member:club_linked_note_update' club_pk=club.pk pk=note.pk %}"> {% trans "Edit" %}</a>
|
||||||
</div>
|
</div>
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -19,9 +19,11 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{% if can_create %}
|
||||||
<a href="{% url 'member:club_linked_note_create' club_pk=club.pk %}">
|
<a href="{% url 'member:club_linked_note_create' club_pk=club.pk %}">
|
||||||
<button class="btn btn-primary btn-block">{% trans "Add new note" %}</button>
|
<button class="btn btn-primary btn-block">{% trans "Add new note" %}</button>
|
||||||
</a>
|
</a>
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
Loading…
Reference in New Issue