From 7bda0bb31f6d61e7dd198380bccd180c0b585d08 Mon Sep 17 00:00:00 2001 From: Yohann D'ANELLO Date: Sat, 30 May 2020 15:45:44 +0200 Subject: [PATCH 1/5] Fix JS --- static/js/base.js | 60 ++++++++++++++++++++++++----------------------- 1 file changed, 31 insertions(+), 29 deletions(-) diff --git a/static/js/base.js b/static/js/base.js index b04f71cb..c9a4caff 100644 --- a/static/js/base.js +++ b/static/js/base.js @@ -335,37 +335,39 @@ function autoCompleteNote(field_id, note_list_id, notes, notes_display, alias_pr }) }); - $("#validate_" + id).html(""); + $("#validate_" + id).html(""); - // Perform a PATCH request to the API in order to update the transaction - // If the user has insufficient rights, an error message will appear - $.ajax({ - "url": "/api/note/transaction/transaction/" + id + "/", - type: "PATCH", - dataType: "json", - headers: { - "X-CSRFTOKEN": CSRF_TOKEN - }, - data: { - "resourcetype": "RecurrentTransaction", - "valid": !validated, - "invalidity_reason": invalidity_reason, - }, - success: function () { - // Refresh jQuery objects - $(".validate").click(de_validate); + // Perform a PATCH request to the API in order to update the transaction + // If the user has insufficient rights, an error message will appear + $.ajax({ + "url": "/api/note/transaction/transaction/" + id + "/", + type: "PATCH", + dataType: "json", + headers: { + "X-CSRFTOKEN": CSRF_TOKEN + }, + data: { + "resourcetype": "RecurrentTransaction", + "valid": !validated, + "invalidity_reason": invalidity_reason, + }, + success: function () { + // Refresh jQuery objects + $(".validate").click(de_validate); - refreshBalance(); - // error if this method doesn't exist. Please define it. - refreshHistory(); - }, - error: function (err) { - addMsg("Une erreur est survenue lors de la validation/dévalidation " + - "de cette transaction : " + err.responseText, "danger"); + refreshBalance(); + // error if this method doesn't exist. Please define it. + refreshHistory(); + }, + error: function (err) { + addMsg("Une erreur est survenue lors de la validation/dévalidation " + + "de cette transaction : " + err.responseText, "danger"); - refreshBalance(); - // error if this method doesn't exist. Please define it. - refreshHistory(); - } + refreshBalance(); + // error if this method doesn't exist. Please define it. + refreshHistory(); + } + }); + }); }); } From 302f9e752c03c1a1ded458cfd19b2123cc8e15b2 Mon Sep 17 00:00:00 2001 From: Yohann D'ANELLO Date: Sat, 30 May 2020 15:46:09 +0200 Subject: [PATCH 2/5] Create a test to check that permission queries are well formed --- apps/permission/backends.py | 11 ++-- apps/permission/fixtures/initial.json | 30 +++++----- apps/permission/test.py | 86 +++++++++++++++++++++++++++ 3 files changed, 106 insertions(+), 21 deletions(-) create mode 100644 apps/permission/test.py diff --git a/apps/permission/backends.py b/apps/permission/backends.py index 94816bfe..2446f211 100644 --- a/apps/permission/backends.py +++ b/apps/permission/backends.py @@ -1,13 +1,12 @@ # Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # SPDX-License-Identifier: GPL-3.0-or-later -import datetime - from django.conf import settings from django.contrib.auth.backends import ModelBackend from django.contrib.auth.models import User, AnonymousUser from django.contrib.contenttypes.models import ContentType from django.db.models import Q, F +from django.utils import timezone from note.models import Note, NoteUser, NoteClub, NoteSpecial from note_kfet.middlewares import get_current_session from member.models import Membership, Club @@ -43,8 +42,8 @@ class PermissionBackend(ModelBackend): ).filter( ( Q( - rolepermissions__role__membership__date_start__lte=datetime.date.today(), - rolepermissions__role__membership__date_end__gte=datetime.date.today(), + rolepermissions__role__membership__date_start__lte=timezone.now().today(), + rolepermissions__role__membership__date_end__gte=timezone.now().today(), ) | Q(permanent=True) ) @@ -98,8 +97,8 @@ class PermissionBackend(ModelBackend): NoteSpecial=NoteSpecial, F=F, Q=Q, - now=datetime.datetime.now(), - today=datetime.date.today(), + now=timezone.now(), + today=timezone.now().date(), ) yield permission diff --git a/apps/permission/fixtures/initial.json b/apps/permission/fixtures/initial.json index 089cb2a1..095bcfc1 100644 --- a/apps/permission/fixtures/initial.json +++ b/apps/permission/fixtures/initial.json @@ -272,7 +272,7 @@ "note", "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__memberships__club__name\": \"Kfet\"}], [\"all\"]]}, {\"note__in\": [\"NoteClub\", \"objects\", [\"all\"]]}]", "type": "view", "mask": 1, "field": "", @@ -480,7 +480,7 @@ "note", "note" ], - "query": "[\"OR\", {\"pk\": [\"club\", \"note\", \"pk\"]}, {\"pk__in\": [\"NoteUser\", \"objects\", [\"filter\", {\"user__membership__club\": [\"club\"]}], [\"all\"]]}]", + "query": "[\"OR\", {\"pk\": [\"club\", \"note\", \"pk\"]}, {\"pk__in\": [\"NoteUser\", \"objects\", [\"filter\", {\"user__memberships__club\": [\"club\"]}], [\"all\"]]}]", "type": "view", "mask": 2, "field": "", @@ -1872,7 +1872,7 @@ "wei", "busteam" ], - "query": "{\"wei\": [\"club\"], \"wei__membership_end__gte\": [\"today\"]}", + "query": "{\"bus__wei\": [\"club\"], \"bus__wei__membership_end__gte\": [\"today\"]}", "type": "add", "mask": 3, "field": "", @@ -1888,7 +1888,7 @@ "wei", "busteam" ], - "query": "{\"wei\": [\"club\"], \"wei__membership_end__gte\": [\"today\"]}", + "query": "{\"bus__wei\": [\"club\"], \"bus__wei__membership_end__gte\": [\"today\"]}", "type": "change", "mask": 3, "field": "", @@ -1920,7 +1920,7 @@ "wei", "busteam" ], - "query": "[\"AND\", {\"wei\": [\"club\"]}, [\"OR\", [\"NOT\", [\"membership\", \"registration\", \"first_year\"]], {\"wei__date_end__lte\": [\"today\"]}]]", + "query": "[\"AND\", {\"bus__wei\": [\"club\"]}, [\"OR\", [\"NOT\", [\"membership\", \"registration\", \"first_year\"]], {\"bus__wei__date_end__lte\": [\"today\"]}]]", "type": "view", "mask": 1, "field": "", @@ -1936,7 +1936,7 @@ "wei", "weimembership" ], - "query": "[\"AND\", {\"club\": [\"club\"], \"club__weiclub__membership_end__gte\": [\"today\"]}, [\"OR\", {\"registration__soge_credit\": true}, {\"user__note__balance__gte\": [\"F\", \"fee\"]}]]", + "query": "[\"AND\", {\"club\": [\"club\"], \"club__weiclub__membership_end__gte\": [\"today\"]}, [\"OR\", {\"registration__soge_credit\": true}, {\"user__note__balance__gte\": {\"F\": [\"F\", \"fee\"]}}]]", "type": "add", "mask": 3, "field": "", @@ -2048,7 +2048,7 @@ "wei", "bus" ], - "query": "{\"pk\": [\"membership\", \"bus\", \"pk\"], \"wei__date_end__gte\": [\"today\"]}", + "query": "{\"pk\": [\"membership\", \"weimembership\", \"bus\", \"pk\"], \"wei__date_end__gte\": [\"today\"]}", "type": "change", "mask": 1, "field": "name", @@ -2064,7 +2064,7 @@ "wei", "bus" ], - "query": "{\"pk\": [\"membership\", \"bus\", \"pk\"], \"wei__date_end__gte\": [\"today\"]}", + "query": "{\"pk\": [\"membership\", \"weimembership\", \"bus\", \"pk\"], \"wei__date_end__gte\": [\"today\"]}", "type": "change", "mask": 1, "field": "description", @@ -2080,7 +2080,7 @@ "wei", "busteam" ], - "query": "{\"bus\": [\"membership\", \"bus\"], \"wei__date_end__gte\": [\"today\"]}", + "query": "{\"bus\": [\"membership\", \"weimembership\", \"bus\"], \"bus__wei__date_end__gte\": [\"today\"]}", "type": "add", "mask": 1, "field": "", @@ -2096,7 +2096,7 @@ "wei", "busteam" ], - "query": "{\"bus\": [\"membership\", \"bus\"], \"wei__date_end__gte\": [\"today\"]}", + "query": "{\"bus\": [\"membership\", \"weimembership\", \"bus\"], \"bus__wei__date_end__gte\": [\"today\"]}", "type": "change", "mask": 1, "field": "name", @@ -2112,7 +2112,7 @@ "wei", "busteam" ], - "query": "{\"bus\": [\"membership\", \"bus\"], \"wei__date_end__gte\": [\"today\"]}", + "query": "{\"bus\": [\"membership\", \"weimembership\", \"bus\"], \"bus__wei__date_end__gte\": [\"today\"]}", "type": "change", "mask": 1, "field": "color", @@ -2128,7 +2128,7 @@ "wei", "busteam" ], - "query": "{\"bus\": [\"membership\", \"bus\"], \"wei__date_end__gte\": [\"today\"]}", + "query": "{\"bus\": [\"membership\", \"weimembership\", \"bus\"], \"bus__wei__date_end__gte\": [\"today\"]}", "type": "change", "mask": 1, "field": "description", @@ -2144,7 +2144,7 @@ "wei", "busteam" ], - "query": "{\"pk\": [\"membership\", \"team\", \"pk\"], \"wei__date_end__gte\": [\"today\"]}", + "query": "{\"pk\": [\"membership\", \"weimembership\", \"team\", \"pk\"], \"bus__wei__date_end__gte\": [\"today\"]}", "type": "change", "mask": 1, "field": "name", @@ -2160,7 +2160,7 @@ "wei", "busteam" ], - "query": "{\"pk\": [\"membership\", \"team\", \"pk\"], \"wei__date_end__gte\": [\"today\"]}", + "query": "{\"pk\": [\"membership\", \"weimembership\", \"team\", \"pk\"], \"bus__wei__date_end__gte\": [\"today\"]}", "type": "change", "mask": 1, "field": "color", @@ -2176,7 +2176,7 @@ "wei", "busteam" ], - "query": "{\"pk\": [\"membership\", \"team\", \"pk\"], \"wei__date_end__gte\": [\"today\"]}", + "query": "{\"pk\": [\"membership\", \"weimembership\", \"team\", \"pk\"], \"bus__wei__date_end__gte\": [\"today\"]}", "type": "change", "mask": 1, "field": "description", diff --git a/apps/permission/test.py b/apps/permission/test.py new file mode 100644 index 00000000..de46d5aa --- /dev/null +++ b/apps/permission/test.py @@ -0,0 +1,86 @@ +# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay +# SPDX-License-Identifier: GPL-3.0-or-later + +from django.contrib.auth.models import User +from django.core.exceptions import FieldError +from django.db.models import F, Q +from django.test import TestCase +from django.utils import timezone +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 + + +class PermissionQueryTestCase(TestCase): + fixtures = ('initial', ) + + @classmethod + def setUpTestData(cls): + user = User.objects.create(username="user") + NoteUser.objects.create(user=user) + wei = WEIClub.objects.create( + name="wei", + date_start=timezone.now().date(), + date_end=timezone.now().date(), + ) + NoteClub.objects.create(club=wei) + weiregistration = WEIRegistration.objects.create( + user=user, + wei=wei, + birth_date=timezone.now().date(), + ) + bus = Bus.objects.create( + name="bus", + wei=wei, + ) + team = BusTeam.objects.create( + name="team", + bus=bus, + color=0xFFFFFF, + ) + WEIMembership.objects.create( + user=user, + club=wei, + registration=weiregistration, + bus=bus, + team=team, + ) + + def test_permission_queries(self): + """ + Check for all permissions that the query is compilable and that the database can parse the query. + We use a random user with a random WEIClub (to use permissions for the WEI) in a random team in a random bus. + """ + for perm in Permission.objects.all(): + instanced = perm.about( + user=User.objects.get(), + club=WEIClub.objects.get(), + membership=Membership.objects.get(), + User=User, + Club=Club, + Membership=Membership, + Note=Note, + NoteUser=NoteUser, + NoteClub=NoteClub, + NoteSpecial=NoteSpecial, + F=F, + Q=Q, + now=timezone.now(), + today=timezone.now().date(), + ) + try: + instanced.update_query() + query = instanced.query + model = perm.model.model_class() + model.objects.filter(query).all() + # print("Good query for permission", perm) + except (FieldError, AttributeError, ValueError): + print("Query error for permission", perm) + print("Query:", perm.query) + if instanced.query: + print("Compiled query:", instanced.query) + raise + + print("All permission queries are well formed") From 8751b3936e52b8dd20d06d82ac4c8114ac6264d9 Mon Sep 17 00:00:00 2001 From: Yohann D'ANELLO Date: Sat, 30 May 2020 15:48:43 +0200 Subject: [PATCH 3/5] One button should not be displayed --- templates/activity/activity_detail.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/activity/activity_detail.html b/templates/activity/activity_detail.html index 7ee9f7c0..3a3de8d0 100644 --- a/templates/activity/activity_detail.html +++ b/templates/activity/activity_detail.html @@ -63,7 +63,7 @@ {% if not activity.open and ".change__valid"|has_perm:activity %} {% if activity.valid %}{% trans "invalidate"|capfirst %}{% else %}{% trans "validate"|capfirst %}{% endif %} {% endif %} - {% if ".view_"|has_perm:activity %} + {% if ".change_"|has_perm:activity %} {% trans "edit"|capfirst %} {% endif %} {% if activity.activity_type.can_invite and not activity_started %} From c8fe3435de025822655ef88dc5d105f140156237 Mon Sep 17 00:00:00 2001 From: Yohann D'ANELLO Date: Sat, 30 May 2020 16:14:37 +0200 Subject: [PATCH 4/5] Some lines of the base.js file mysteriously disappeared... --- static/js/base.js | 68 ++++++++++++++++++++++++++--------------------- 1 file changed, 37 insertions(+), 31 deletions(-) diff --git a/static/js/base.js b/static/js/base.js index c9a4caff..87a79af2 100644 --- a/static/js/base.js +++ b/static/js/base.js @@ -335,39 +335,45 @@ function autoCompleteNote(field_id, note_list_id, notes, notes_display, alias_pr }) }); - $("#validate_" + id).html(""); + });// end getJSON alias + }); +}// end function autocomplete - // Perform a PATCH request to the API in order to update the transaction - // If the user has insufficient rights, an error message will appear - $.ajax({ - "url": "/api/note/transaction/transaction/" + id + "/", - type: "PATCH", - dataType: "json", - headers: { - "X-CSRFTOKEN": CSRF_TOKEN - }, - data: { - "resourcetype": "RecurrentTransaction", - "valid": !validated, - "invalidity_reason": invalidity_reason, - }, - success: function () { - // Refresh jQuery objects - $(".validate").click(de_validate); - refreshBalance(); - // error if this method doesn't exist. Please define it. - refreshHistory(); - }, - error: function (err) { - addMsg("Une erreur est survenue lors de la validation/dévalidation " + - "de cette transaction : " + err.responseText, "danger"); +// When a validate button is clicked, we switch the validation status +function de_validate(id, validated) { + let invalidity_reason = $("#invalidity_reason_" + id).val(); + $("#validate_" + id).html("⟳ ..."); - refreshBalance(); - // error if this method doesn't exist. Please define it. - refreshHistory(); - } - }); - }); + // Perform a PATCH request to the API in order to update the transaction + // If the user has insufficient rights, an error message will appear + $.ajax({ + "url": "/api/note/transaction/transaction/" + id + "/", + type: "PATCH", + dataType: "json", + headers: { + "X-CSRFTOKEN": CSRF_TOKEN + }, + data: { + "resourcetype": "RecurrentTransaction", + "valid": !validated, + "invalidity_reason": invalidity_reason, + }, + success: function () { + // Refresh jQuery objects + $(".validate").click(de_validate); + + refreshBalance(); + // error if this method doesn't exist. Please define it. + refreshHistory(); + }, + error: function (err) { + addMsg("Une erreur est survenue lors de la validation/dévalidation " + + "de cette transaction : " + err.responseText, "danger"); + + refreshBalance(); + // error if this method doesn't exist. Please define it. + refreshHistory(); + } }); } From 518de596bb0999f1cac7c2c748ae5ae9a12e2d5c Mon Sep 17 00:00:00 2001 From: Yohann D'ANELLO Date: Sat, 30 May 2020 16:16:31 +0200 Subject: [PATCH 5/5] Update one translation --- locale/fr/LC_MESSAGES/django.po | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/locale/fr/LC_MESSAGES/django.po b/locale/fr/LC_MESSAGES/django.po index 967e00bc..4af9cfd5 100644 --- a/locale/fr/LC_MESSAGES/django.po +++ b/locale/fr/LC_MESSAGES/django.po @@ -1739,7 +1739,7 @@ msgstr "Consommer" #: templates/note/conso_form.html:39 templates/note/transaction_form.html:61 #: templates/note/transaction_form.html:76 msgid "Name or alias..." -msgstr "" +msgstr "Pseudo ou alias ..." #: templates/note/conso_form.html:48 msgid "Select consumptions"