From b019c546cd91e95ccdb6a1ffede3d8d8b1397a19 Mon Sep 17 00:00:00 2001 From: Maxime Bombar Date: Sat, 7 Mar 2020 15:56:00 +0100 Subject: [PATCH 01/98] Use example.org in nginx_note.conf_example --- nginx_note.conf_example | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nginx_note.conf_example b/nginx_note.conf_example index 1f7ce4ca..204784d0 100644 --- a/nginx_note.conf_example +++ b/nginx_note.conf_example @@ -9,7 +9,7 @@ server { # the port your site will be served on listen 80; # the domain name it will serve for - server_name note.comby.xyz; # substitute your machine's IP address or FQDN + server_name note.example.org; # substitute your machine's IP address or FQDN charset utf-8; # max upload size From 09137dd9d72017db42c4166ca64a243f035fa8b1 Mon Sep 17 00:00:00 2001 From: Yohann D'ANELLO Date: Sat, 7 Mar 2020 16:45:45 +0100 Subject: [PATCH 02/98] Fix anonymous users issue --- apps/logs/signals.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/apps/logs/signals.py b/apps/logs/signals.py index 55e0f041..13194e5b 100644 --- a/apps/logs/signals.py +++ b/apps/logs/signals.py @@ -78,6 +78,10 @@ def save_object(sender, instance, **kwargs): user, ip = get_user_and_ip(sender) + from django.contrib.auth.models import AnonymousUser + if isinstance(user, AnonymousUser): + user = None + if user is not None and instance._meta.label_lower == "auth.user" and previous: # Don't save last login modifications if instance.last_login != previous.last_login: From 55a775427756794e6896d44e905776a1282dcc31 Mon Sep 17 00:00:00 2001 From: Pierre-antoine Comby Date: Sat, 7 Mar 2020 17:27:28 +0100 Subject: [PATCH 03/98] use localhost in dev --- note_kfet/settings/development.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/note_kfet/settings/development.py b/note_kfet/settings/development.py index ad2cd2f1..e68e9d68 100644 --- a/note_kfet/settings/development.py +++ b/note_kfet/settings/development.py @@ -51,4 +51,4 @@ SESSION_COOKIE_AGE = 60 * 60 * 3 # CAS Client settings # Can be modified in secrets.py -CAS_SERVER_URL = "https://note.comby.xyz/cas/" +CAS_SERVER_URL = "http://localhost:8000/cas/" From 762585134ccc0e2fc9a56fd5645568c97fedf902 Mon Sep 17 00:00:00 2001 From: Pierre-antoine Comby Date: Sat, 7 Mar 2020 17:47:34 +0100 Subject: [PATCH 04/98] fix static files config for development enviromnent --- note_kfet/settings/development.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/note_kfet/settings/development.py b/note_kfet/settings/development.py index e68e9d68..83436339 100644 --- a/note_kfet/settings/development.py +++ b/note_kfet/settings/development.py @@ -52,3 +52,9 @@ SESSION_COOKIE_AGE = 60 * 60 * 3 # CAS Client settings # Can be modified in secrets.py CAS_SERVER_URL = "http://localhost:8000/cas/" + + +STATIC_ROOT = '' # not needed in development settings +STATICFILES_DIRS = [ + os.path.join(BASE_DIR, 'static')] + From 663ee072d499cf89071ec7e1873b4c63a36cd8a4 Mon Sep 17 00:00:00 2001 From: Pierre-antoine Comby Date: Sat, 7 Mar 2020 17:58:41 +0100 Subject: [PATCH 05/98] always save to png --- apps/member/views.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/apps/member/views.py b/apps/member/views.py index 870079cc..d4bbc592 100644 --- a/apps/member/views.py +++ b/apps/member/views.py @@ -238,17 +238,18 @@ class ProfilePictureUpdateView(LoginRequiredMixin, FormMixin, DetailView): h = form.cleaned_data['height'] # image crop and resize image_file = io.BytesIO(image_field.read()) - ext = image_field.name.split('.')[-1] + ext = image_field.name.split('.')[-1].lower() + #TODO: support GIF format image = Image.open(image_file) image = image.crop((x, y, x+w, y+h)) image_clean = image.resize((settings.PIC_WIDTH, settings.PIC_RATIO*settings.PIC_WIDTH), Image.ANTIALIAS) image_file = io.BytesIO() - image_clean.save(image_file,ext) + image_clean.save(image_file,"PNG") image_field.file = image_file # renaming - filename = "{}_pic.{}".format(self.object.note.pk, ext) + filename = "{}_pic.png".format(self.object.note.pk) image_field.name = filename self.object.note.display_image = image_field self.object.note.save() From 8f1caddbe0f83ee83e6321e19ec67ad53b3df031 Mon Sep 17 00:00:00 2001 From: Yohann D'ANELLO Date: Sat, 7 Mar 2020 18:18:35 +0100 Subject: [PATCH 06/98] Add signup link, customize templates --- locale/de/LC_MESSAGES/django.po | 191 +++++++++++----- locale/fr/LC_MESSAGES/django.po | 207 +++++++++++++----- note_kfet/settings/base.py | 18 ++ note_kfet/settings/development.py | 5 + templates/cas_server/base.html | 99 +++++++++ templates/cas_server/form.html | 26 +++ templates/cas_server/logged.html | 21 ++ templates/cas_server/login.html | 33 +++ templates/cas_server/logout.html | 7 + templates/cas_server/proxy.xml | 5 + templates/cas_server/samlValidate.xml | 59 +++++ templates/cas_server/samlValidateError.xml | 14 ++ templates/cas_server/serviceValidate.xml | 19 ++ templates/cas_server/serviceValidateError.xml | 3 + templates/cas_server/warn.html | 11 + 15 files changed, 607 insertions(+), 111 deletions(-) create mode 100644 templates/cas_server/base.html create mode 100644 templates/cas_server/form.html create mode 100644 templates/cas_server/logged.html create mode 100644 templates/cas_server/login.html create mode 100644 templates/cas_server/logout.html create mode 100644 templates/cas_server/proxy.xml create mode 100644 templates/cas_server/samlValidate.xml create mode 100644 templates/cas_server/samlValidateError.xml create mode 100644 templates/cas_server/serviceValidate.xml create mode 100644 templates/cas_server/serviceValidateError.xml create mode 100644 templates/cas_server/warn.html diff --git a/locale/de/LC_MESSAGES/django.po b/locale/de/LC_MESSAGES/django.po index 386db34c..ce17f5de 100644 --- a/locale/de/LC_MESSAGES/django.po +++ b/locale/de/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2020-02-27 17:39+0100\n" +"POT-Creation-Date: 2020-03-07 18:01+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -24,8 +24,8 @@ msgstr "" #: apps/activity/models.py:19 apps/activity/models.py:44 #: apps/member/models.py:60 apps/member/models.py:111 -#: apps/note/models/notes.py:184 apps/note/models/transactions.py:24 -#: apps/note/models/transactions.py:44 templates/member/profile_detail.html:11 +#: apps/note/models/notes.py:187 apps/note/models/transactions.py:24 +#: apps/note/models/transactions.py:44 templates/member/profile_detail.html:15 msgid "name" msgstr "" @@ -49,7 +49,7 @@ msgstr "" msgid "description" msgstr "" -#: apps/activity/models.py:54 apps/note/models/notes.py:160 +#: apps/activity/models.py:54 apps/note/models/notes.py:163 #: apps/note/models/transactions.py:62 msgid "type" msgstr "" @@ -90,39 +90,43 @@ msgstr "" msgid "Logs" msgstr "" -#: apps/logs/models.py:20 apps/note/models/notes.py:105 +#: apps/logs/models.py:21 apps/note/models/notes.py:116 msgid "user" msgstr "" #: apps/logs/models.py:27 +msgid "IP Address" +msgstr "" + +#: apps/logs/models.py:35 msgid "model" msgstr "" -#: apps/logs/models.py:34 +#: apps/logs/models.py:42 msgid "identifier" msgstr "" -#: apps/logs/models.py:39 +#: apps/logs/models.py:47 msgid "previous data" msgstr "" -#: apps/logs/models.py:44 +#: apps/logs/models.py:52 msgid "new data" msgstr "" -#: apps/logs/models.py:51 +#: apps/logs/models.py:59 msgid "action" msgstr "" -#: apps/logs/models.py:59 +#: apps/logs/models.py:67 msgid "timestamp" msgstr "" -#: apps/logs/models.py:63 +#: apps/logs/models.py:71 msgid "Logs cannot be destroyed." msgstr "" -#: apps/member/apps.py:10 +#: apps/member/apps.py:14 msgid "member" msgstr "" @@ -130,7 +134,7 @@ msgstr "" msgid "phone number" msgstr "" -#: apps/member/models.py:29 templates/member/profile_detail.html:24 +#: apps/member/models.py:29 templates/member/profile_detail.html:28 msgid "section" msgstr "" @@ -138,7 +142,7 @@ msgstr "" msgid "e.g. \"1A0\", \"9A♥\", \"SAPHIRE\"" msgstr "" -#: apps/member/models.py:36 templates/member/profile_detail.html:27 +#: apps/member/models.py:36 templates/member/profile_detail.html:31 msgid "address" msgstr "" @@ -184,7 +188,7 @@ msgid "" "members can renew their membership." msgstr "" -#: apps/member/models.py:93 apps/note/models/notes.py:135 +#: apps/member/models.py:93 apps/note/models/notes.py:138 msgid "club" msgstr "" @@ -220,19 +224,23 @@ msgstr "" msgid "memberships" msgstr "" -#: apps/member/views.py:63 templates/member/profile_detail.html:42 +#: apps/member/views.py:69 templates/member/profile_detail.html:46 msgid "Update Profile" msgstr "" -#: apps/member/views.py:79 +#: apps/member/views.py:82 msgid "An alias with a similar name already exists." msgstr "" -#: apps/member/views.py:130 +#: apps/member/views.py:132 #, python-format msgid "Account #%(id)s: %(username)s" msgstr "" +#: apps/member/views.py:200 +msgid "Alias successfully deleted" +msgstr "" + #: apps/note/admin.py:120 apps/note/models/transactions.py:93 msgid "source" msgstr "" @@ -242,11 +250,23 @@ msgstr "" msgid "destination" msgstr "" -#: apps/note/apps.py:14 apps/note/models/notes.py:54 +#: apps/note/apps.py:14 apps/note/models/notes.py:57 msgid "note" msgstr "" -#: apps/note/forms.py:49 +#: apps/note/forms.py:26 +msgid "New Alias" +msgstr "" + +#: apps/note/forms.py:31 +msgid "select an image" +msgstr "" + +#: apps/note/forms.py:32 +msgid "Maximal size: 2MB" +msgstr "" + +#: apps/note/forms.py:77 msgid "Source and destination must be different." msgstr "" @@ -280,81 +300,77 @@ msgstr "" msgid "display image" msgstr "" -#: apps/note/models/notes.py:49 apps/note/models/transactions.py:102 +#: apps/note/models/notes.py:52 apps/note/models/transactions.py:102 msgid "created at" msgstr "" -#: apps/note/models/notes.py:55 +#: apps/note/models/notes.py:58 msgid "notes" msgstr "" -#: apps/note/models/notes.py:63 +#: apps/note/models/notes.py:66 msgid "Note" msgstr "" -#: apps/note/models/notes.py:73 apps/note/models/notes.py:97 +#: apps/note/models/notes.py:76 apps/note/models/notes.py:100 msgid "This alias is already taken." msgstr "" -#: apps/note/models/notes.py:113 -msgid "user" -msgstr "" - -#: apps/note/models/notes.py:117 +#: apps/note/models/notes.py:120 msgid "one's note" msgstr "" -#: apps/note/models/notes.py:118 +#: apps/note/models/notes.py:121 msgid "users note" msgstr "" -#: apps/note/models/notes.py:124 +#: apps/note/models/notes.py:127 #, python-format msgid "%(user)s's note" msgstr "" -#: apps/note/models/notes.py:139 +#: apps/note/models/notes.py:142 msgid "club note" msgstr "" -#: apps/note/models/notes.py:140 +#: apps/note/models/notes.py:143 msgid "clubs notes" msgstr "" -#: apps/note/models/notes.py:146 +#: apps/note/models/notes.py:149 #, python-format msgid "Note of %(club)s club" msgstr "" -#: apps/note/models/notes.py:166 +#: apps/note/models/notes.py:169 msgid "special note" msgstr "" -#: apps/note/models/notes.py:167 +#: apps/note/models/notes.py:170 msgid "special notes" msgstr "" -#: apps/note/models/notes.py:190 +#: apps/note/models/notes.py:193 msgid "Invalid alias" msgstr "" -#: apps/note/models/notes.py:206 +#: apps/note/models/notes.py:209 msgid "alias" msgstr "" -#: apps/note/models/notes.py:207 templates/member/profile_detail.html:33 +#: apps/note/models/notes.py:210 templates/member/profile_detail.html:37 msgid "aliases" msgstr "" -#: apps/note/models/notes.py:233 +#: apps/note/models/notes.py:228 msgid "Alias is too long." msgstr "" -#: apps/note/models/notes.py:238 -msgid "An alias with a similar name already exists:" +#: apps/note/models/notes.py:233 +msgid "An alias with a similar name already exists: {} " msgstr "" -#: apps/note/models/notes.py:246 +#: apps/note/models/notes.py:242 msgid "You can't delete your main alias." msgstr "" @@ -422,22 +438,79 @@ msgstr "" msgid "Consommations" msgstr "" -#: note_kfet/settings/base.py:155 +#: note_kfet/settings/base.py:162 msgid "German" msgstr "" -#: note_kfet/settings/base.py:156 +#: note_kfet/settings/base.py:163 msgid "English" msgstr "" -#: note_kfet/settings/base.py:157 +#: note_kfet/settings/base.py:164 msgid "French" msgstr "" +#: note_kfet/settings/base.py:215 +msgid "" +"The Central Authentication Service grants you access to most of our websites " +"by authenticating only once, so you don't need to type your credentials " +"again unless your session expires or you logout." +msgstr "" + #: templates/base.html:13 msgid "The ENS Paris-Saclay BDE note." msgstr "" +#: templates/cas_server/base.html:7 templates/cas_server/base.html:26 +msgid "Central Authentication Service" +msgstr "" + +#: templates/cas_server/base.html:43 +#, python-format +msgid "" +"A new version of the application is available. This instance runs " +"%(VERSION)s and the last version is %(LAST_VERSION)s. Please consider " +"upgrading." +msgstr "" + +#: templates/cas_server/logged.html:4 +msgid "" +"

Log In Successful

You have successfully logged into the Central " +"Authentication Service.
For security reasons, please Log Out and Exit " +"your web browser when you are done accessing services that require " +"authentication!" +msgstr "" + +#: templates/cas_server/logged.html:8 +msgid "Log me out from all my sessions" +msgstr "" + +#: templates/cas_server/logged.html:14 +msgid "Forget the identity provider" +msgstr "" + +#: templates/cas_server/logged.html:18 +msgid "Logout" +msgstr "" + +#: templates/cas_server/login.html:6 +msgid "Please log in" +msgstr "" + +#: templates/cas_server/login.html:11 +msgid "" +"If you don't have any Note Kfet account, please follow this link to sign up." +msgstr "" + +#: templates/cas_server/login.html:17 +msgid "Login" +msgstr "" + +#: templates/cas_server/warn.html:9 +msgid "Connect to the service" +msgstr "" + #: templates/member/club_detail.html:10 msgid "Membership starts on" msgstr "" @@ -450,10 +523,14 @@ msgstr "" msgid "Membership duration" msgstr "" -#: templates/member/club_detail.html:18 templates/member/profile_detail.html:30 +#: templates/member/club_detail.html:18 templates/member/profile_detail.html:34 msgid "balance" msgstr "" +#: templates/member/club_detail.html:51 templates/member/profile_detail.html:75 +msgid "Transaction history" +msgstr "" + #: templates/member/manage_auth_tokens.html:16 msgid "Token" msgstr "" @@ -466,27 +543,35 @@ msgstr "" msgid "Regenerate token" msgstr "" -#: templates/member/profile_detail.html:11 +#: templates/member/profile_alias.html:10 +msgid "Add alias" +msgstr "" + +#: templates/member/profile_detail.html:15 msgid "first name" msgstr "" -#: templates/member/profile_detail.html:14 +#: templates/member/profile_detail.html:18 msgid "username" msgstr "" -#: templates/member/profile_detail.html:17 +#: templates/member/profile_detail.html:21 msgid "password" msgstr "" -#: templates/member/profile_detail.html:20 +#: templates/member/profile_detail.html:24 msgid "Change password" msgstr "" -#: templates/member/profile_detail.html:38 +#: templates/member/profile_detail.html:42 msgid "Manage auth token" msgstr "" -#: templates/member/profile_detail.html:54 +#: templates/member/profile_detail.html:49 +msgid "View Profile" +msgstr "" + +#: templates/member/profile_detail.html:62 msgid "View my memberships" msgstr "" diff --git a/locale/fr/LC_MESSAGES/django.po b/locale/fr/LC_MESSAGES/django.po index e7341740..3a8cfb79 100644 --- a/locale/fr/LC_MESSAGES/django.po +++ b/locale/fr/LC_MESSAGES/django.po @@ -3,7 +3,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2020-02-27 17:39+0100\n" +"POT-Creation-Date: 2020-03-07 18:01+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -19,8 +19,8 @@ msgstr "activité" #: apps/activity/models.py:19 apps/activity/models.py:44 #: apps/member/models.py:60 apps/member/models.py:111 -#: apps/note/models/notes.py:184 apps/note/models/transactions.py:24 -#: apps/note/models/transactions.py:44 templates/member/profile_detail.html:11 +#: apps/note/models/notes.py:187 apps/note/models/transactions.py:24 +#: apps/note/models/transactions.py:44 templates/member/profile_detail.html:15 msgid "name" msgstr "nom" @@ -44,7 +44,7 @@ msgstr "types d'activité" msgid "description" msgstr "description" -#: apps/activity/models.py:54 apps/note/models/notes.py:160 +#: apps/activity/models.py:54 apps/note/models/notes.py:163 #: apps/note/models/transactions.py:62 msgid "type" msgstr "type" @@ -85,43 +85,49 @@ msgstr "" msgid "Logs" msgstr "" -#: apps/logs/models.py:20 apps/note/models/notes.py:105 +#: apps/logs/models.py:21 apps/note/models/notes.py:116 msgid "user" msgstr "utilisateur" #: apps/logs/models.py:27 +#, fuzzy +#| msgid "address" +msgid "IP Address" +msgstr "adresse" + +#: apps/logs/models.py:35 msgid "model" msgstr "Modèle" -#: apps/logs/models.py:34 +#: apps/logs/models.py:42 msgid "identifier" msgstr "Identifiant" -#: apps/logs/models.py:39 +#: apps/logs/models.py:47 msgid "previous data" msgstr "Données précédentes" -#: apps/logs/models.py:44 +#: apps/logs/models.py:52 #, fuzzy #| msgid "end date" msgid "new data" msgstr "Nouvelles données" -#: apps/logs/models.py:51 +#: apps/logs/models.py:59 #, fuzzy #| msgid "section" msgid "action" msgstr "Action" -#: apps/logs/models.py:59 +#: apps/logs/models.py:67 msgid "timestamp" msgstr "Date" -#: apps/logs/models.py:63 +#: apps/logs/models.py:71 msgid "Logs cannot be destroyed." msgstr "Les logs ne peuvent pas être détruits." -#: apps/member/apps.py:10 +#: apps/member/apps.py:14 msgid "member" msgstr "adhérent" @@ -129,7 +135,7 @@ msgstr "adhérent" msgid "phone number" msgstr "numéro de téléphone" -#: apps/member/models.py:29 templates/member/profile_detail.html:24 +#: apps/member/models.py:29 templates/member/profile_detail.html:28 msgid "section" msgstr "section" @@ -137,7 +143,7 @@ msgstr "section" msgid "e.g. \"1A0\", \"9A♥\", \"SAPHIRE\"" msgstr "e.g. \"1A0\", \"9A♥\", \"SAPHIRE\"" -#: apps/member/models.py:36 templates/member/profile_detail.html:27 +#: apps/member/models.py:36 templates/member/profile_detail.html:31 msgid "address" msgstr "adresse" @@ -187,7 +193,7 @@ msgstr "" "Combien de temps l'adhésion peut durer après le 1er Janvier de l'année " "suivante avant que les adhérents peuvent renouveler leur adhésion." -#: apps/member/models.py:93 apps/note/models/notes.py:135 +#: apps/member/models.py:93 apps/note/models/notes.py:138 msgid "club" msgstr "club" @@ -223,19 +229,23 @@ msgstr "adhésion" msgid "memberships" msgstr "adhésions" -#: apps/member/views.py:63 templates/member/profile_detail.html:42 +#: apps/member/views.py:69 templates/member/profile_detail.html:46 msgid "Update Profile" msgstr "Modifier le profil" -#: apps/member/views.py:79 +#: apps/member/views.py:82 msgid "An alias with a similar name already exists." msgstr "Un alias avec un nom similaire existe déjà." -#: apps/member/views.py:130 +#: apps/member/views.py:132 #, python-format msgid "Account #%(id)s: %(username)s" msgstr "Compte n°%(id)s : %(username)s" +#: apps/member/views.py:200 +msgid "Alias successfully deleted" +msgstr "" + #: apps/note/admin.py:120 apps/note/models/transactions.py:93 msgid "source" msgstr "source" @@ -245,11 +255,25 @@ msgstr "source" msgid "destination" msgstr "destination" -#: apps/note/apps.py:14 apps/note/models/notes.py:54 +#: apps/note/apps.py:14 apps/note/models/notes.py:57 msgid "note" msgstr "note" -#: apps/note/forms.py:49 +#: apps/note/forms.py:26 +msgid "New Alias" +msgstr "" + +#: apps/note/forms.py:31 +#, fuzzy +#| msgid "display image" +msgid "select an image" +msgstr "image affichée" + +#: apps/note/forms.py:32 +msgid "Maximal size: 2MB" +msgstr "" + +#: apps/note/forms.py:77 msgid "Source and destination must be different." msgstr "La source et la destination doivent être différentes." @@ -284,81 +308,79 @@ msgstr "" msgid "display image" msgstr "image affichée" -#: apps/note/models/notes.py:49 apps/note/models/transactions.py:102 +#: apps/note/models/notes.py:52 apps/note/models/transactions.py:102 msgid "created at" msgstr "créée le" -#: apps/note/models/notes.py:55 +#: apps/note/models/notes.py:58 msgid "notes" msgstr "notes" -#: apps/note/models/notes.py:63 +#: apps/note/models/notes.py:66 msgid "Note" msgstr "Note" -#: apps/note/models/notes.py:73 apps/note/models/notes.py:97 +#: apps/note/models/notes.py:76 apps/note/models/notes.py:100 msgid "This alias is already taken." msgstr "Cet alias est déjà pris." -#: apps/note/models/notes.py:113 -msgid "user" -msgstr "utilisateur" - -#: apps/note/models/notes.py:117 +#: apps/note/models/notes.py:120 msgid "one's note" msgstr "note d'un utilisateur" -#: apps/note/models/notes.py:118 +#: apps/note/models/notes.py:121 msgid "users note" msgstr "notes des utilisateurs" -#: apps/note/models/notes.py:124 +#: apps/note/models/notes.py:127 #, python-format msgid "%(user)s's note" msgstr "Note de %(user)s" -#: apps/note/models/notes.py:139 +#: apps/note/models/notes.py:142 msgid "club note" msgstr "note d'un club" -#: apps/note/models/notes.py:140 +#: apps/note/models/notes.py:143 msgid "clubs notes" msgstr "notes des clubs" -#: apps/note/models/notes.py:146 +#: apps/note/models/notes.py:149 #, python-format msgid "Note of %(club)s club" msgstr "Note du club %(club)s" -#: apps/note/models/notes.py:166 +#: apps/note/models/notes.py:169 msgid "special note" msgstr "note spéciale" -#: apps/note/models/notes.py:167 +#: apps/note/models/notes.py:170 msgid "special notes" msgstr "notes spéciales" -#: apps/note/models/notes.py:190 +#: apps/note/models/notes.py:193 msgid "Invalid alias" msgstr "Alias invalide" -#: apps/note/models/notes.py:206 +#: apps/note/models/notes.py:209 msgid "alias" msgstr "alias" -#: apps/note/models/notes.py:207 templates/member/profile_detail.html:33 +#: apps/note/models/notes.py:210 templates/member/profile_detail.html:37 msgid "aliases" msgstr "alias" -#: apps/note/models/notes.py:233 +#: apps/note/models/notes.py:228 msgid "Alias is too long." msgstr "L'alias est trop long." -#: apps/note/models/notes.py:238 -msgid "An alias with a similar name already exists:" +#: apps/note/models/notes.py:233 +#, fuzzy +#| msgid "An alias with a similar name already exists:" +msgid "An alias with a similar name already exists: {} " msgstr "Un alias avec un nom similaire existe déjà." -#: apps/note/models/notes.py:246 +#: apps/note/models/notes.py:242 msgid "You can't delete your main alias." msgstr "Vous ne pouvez pas supprimer votre alias principal." @@ -427,22 +449,81 @@ msgstr "Transfert d'argent de ton compte vers un ou plusieurs autres" msgid "Consommations" msgstr "transactions" -#: note_kfet/settings/base.py:155 +#: note_kfet/settings/base.py:162 msgid "German" msgstr "" -#: note_kfet/settings/base.py:156 +#: note_kfet/settings/base.py:163 msgid "English" msgstr "" -#: note_kfet/settings/base.py:157 +#: note_kfet/settings/base.py:164 msgid "French" msgstr "" +#: note_kfet/settings/base.py:215 +msgid "" +"The Central Authentication Service grants you access to most of our websites " +"by authenticating only once, so you don't need to type your credentials " +"again unless your session expires or you logout." +msgstr "" + #: templates/base.html:13 msgid "The ENS Paris-Saclay BDE note." msgstr "La note du BDE de l'ENS Paris-Saclay." +#: templates/cas_server/base.html:7 templates/cas_server/base.html:26 +msgid "Central Authentication Service" +msgstr "" + +#: templates/cas_server/base.html:43 +#, python-format +msgid "" +"A new version of the application is available. This instance runs " +"%(VERSION)s and the last version is %(LAST_VERSION)s. Please consider " +"upgrading." +msgstr "" + +#: templates/cas_server/logged.html:4 +msgid "" +"

Log In Successful

You have successfully logged into the Central " +"Authentication Service.
For security reasons, please Log Out and Exit " +"your web browser when you are done accessing services that require " +"authentication!" +msgstr "" + +#: templates/cas_server/logged.html:8 +msgid "Log me out from all my sessions" +msgstr "" + +#: templates/cas_server/logged.html:14 +msgid "Forget the identity provider" +msgstr "" + +#: templates/cas_server/logged.html:18 +msgid "Logout" +msgstr "" + +#: templates/cas_server/login.html:6 +msgid "Please log in" +msgstr "" + +#: templates/cas_server/login.html:11 +msgid "" +"If you don't have any Note Kfet account, please follow this link to sign up." +msgstr "" +"Si vous n'avez pas de compte Note Kfet, veuillez suivre ce lien pour vous inscrire." + +#: templates/cas_server/login.html:17 +msgid "Login" +msgstr "" + +#: templates/cas_server/warn.html:9 +msgid "Connect to the service" +msgstr "" + #: templates/member/club_detail.html:10 msgid "Membership starts on" msgstr "L'adhésion commence le" @@ -455,10 +536,14 @@ msgstr "L'adhésion finie le" msgid "Membership duration" msgstr "Durée de l'adhésion" -#: templates/member/club_detail.html:18 templates/member/profile_detail.html:30 +#: templates/member/club_detail.html:18 templates/member/profile_detail.html:34 msgid "balance" msgstr "solde du compte" +#: templates/member/club_detail.html:51 templates/member/profile_detail.html:75 +msgid "Transaction history" +msgstr "Historique des transactions" + #: templates/member/manage_auth_tokens.html:16 msgid "Token" msgstr "Jeton" @@ -471,33 +556,39 @@ msgstr "Créé le" msgid "Regenerate token" msgstr "Regénérer le jeton" -#: templates/member/profile_detail.html:11 +#: templates/member/profile_alias.html:10 +#, fuzzy +#| msgid "alias" +msgid "Add alias" +msgstr "alias" + +#: templates/member/profile_detail.html:15 msgid "first name" msgstr "" -#: templates/member/profile_detail.html:14 +#: templates/member/profile_detail.html:18 msgid "username" msgstr "" -#: templates/member/profile_detail.html:17 -#, fuzzy -#| msgid "Change password" +#: templates/member/profile_detail.html:21 msgid "password" msgstr "" -#: templates/member/profile_detail.html:20 +#: templates/member/profile_detail.html:24 msgid "Change password" msgstr "Changer le mot de passe" -#: templates/member/profile_detail.html:38 +#: templates/member/profile_detail.html:42 msgid "Manage auth token" msgstr "Gérer les jetons d'authentification" -#: templates/member/profile_detail.html:51 -msgid "Transaction history" -msgstr "Historique des transactions" +#: templates/member/profile_detail.html:49 +#, fuzzy +#| msgid "Update Profile" +msgid "View Profile" +msgstr "Modifier le profil" -#: templates/member/profile_detail.html:54 +#: templates/member/profile_detail.html:62 msgid "View my memberships" msgstr "Voir mes adhésions" diff --git a/note_kfet/settings/base.py b/note_kfet/settings/base.py index 1810989d..7ab59272 100644 --- a/note_kfet/settings/base.py +++ b/note_kfet/settings/base.py @@ -206,4 +206,22 @@ PIC_RATIO = 1 CAS_AUTO_CREATE_USER = False CAS_LOGO_URL = "/static/img/Saperlistpopette.png" CAS_FAVICON_URL = "/static/favicon/favicon-32x32.png" +CAS_SHOW_SERVICE_MESSAGES = True +CAS_SHOW_POWERED = False +CAS_REDIRECT_TO_LOGIN_AFTER_LOGOUT = False +CAS_INFO_MESSAGES = { + "cas_explained": { + "message":_( + u"The Central Authentication Service grants you access to most of our websites by " + u"authenticating only once, so you don't need to type your credentials again unless " + u"your session expires or you logout." + ), + "discardable": True, + "type": "info", # one of info, success, info, warning, danger + }, +} + +CAS_INFO_MESSAGES_ORDER = [ + 'cas_explained', +] diff --git a/note_kfet/settings/development.py b/note_kfet/settings/development.py index ad2cd2f1..e16b6cf2 100644 --- a/note_kfet/settings/development.py +++ b/note_kfet/settings/development.py @@ -52,3 +52,8 @@ SESSION_COOKIE_AGE = 60 * 60 * 3 # CAS Client settings # Can be modified in secrets.py CAS_SERVER_URL = "https://note.comby.xyz/cas/" + + +STATIC_ROOT = '' # not needed in development settings +STATICFILES_DIRS = [ + os.path.join(BASE_DIR, 'static')] diff --git a/templates/cas_server/base.html b/templates/cas_server/base.html new file mode 100644 index 00000000..4e93cee0 --- /dev/null +++ b/templates/cas_server/base.html @@ -0,0 +1,99 @@ +{% load i18n %}{% load static %}{% get_current_language as LANGUAGE_CODE %} + + + + + + {% block title %}{% trans "Central Authentication Service" %}{% endblock %} + + + + + {% if settings.CAS_FAVICON_URL %}{% endif %} + + + +
+
+ {% if auto_submit %}{% endif %} +
+
+
+ {% if auto_submit %}{% endif %} + {% block content %}{% endblock %} +
+
+
+
+
+
+ {% if settings.CAS_SHOW_POWERED %} + + {% endif %} + + + + + {% block javascript %}{% endblock %} + + + diff --git a/templates/cas_server/form.html b/templates/cas_server/form.html new file mode 100644 index 00000000..405dedd1 --- /dev/null +++ b/templates/cas_server/form.html @@ -0,0 +1,26 @@ +{% load cas_server %} +{% for error in form.non_field_errors %} +
+ + {{error}} +
+{% endfor %} +{% for field in form %}{% if not field|is_hidden %} +
{% spaceless %} + {% if field|is_checkbox %} +
+ {% else %} + + {{field}} + {% endif %} + {% for error in field.errors %} + {{error}} + {% endfor %} +{% endspaceless %}
+{% else %}{{field}}{% endif %}{% endfor %} diff --git a/templates/cas_server/logged.html b/templates/cas_server/logged.html new file mode 100644 index 00000000..46e1c9a8 --- /dev/null +++ b/templates/cas_server/logged.html @@ -0,0 +1,21 @@ +{% extends "cas_server/base.html" %} +{% load i18n %} +{% block content %} + + +{% endblock %} + diff --git a/templates/cas_server/login.html b/templates/cas_server/login.html new file mode 100644 index 00000000..ddc2eb32 --- /dev/null +++ b/templates/cas_server/login.html @@ -0,0 +1,33 @@ +{% extends "cas_server/base.html" %} +{% load i18n %} + +{% block ante_messages %} +{% if auto_submit %}{% endif %} +{% endblock %} +{% block content %} +
+ {% trans "If you don't have any Note Kfet account, please follow this link to sign up." %} +
+ +{% endblock %} +{% block javascript_inline %} +jQuery(function( $ ){ + $("#id_warn").click(function(e){ + if($("#id_warn").is(':checked')){ + createCookie("warn", "on", 10 * 365); + } else { + eraseCookie("warn"); + } + }); +});{% if auto_submit %} +document.getElementById('login_form').submit(); // SUBMIT FORM{% endif %} +{% endblock %} + diff --git a/templates/cas_server/logout.html b/templates/cas_server/logout.html new file mode 100644 index 00000000..80693376 --- /dev/null +++ b/templates/cas_server/logout.html @@ -0,0 +1,7 @@ +{% extends "cas_server/base.html" %} +{% load static %} +{% load i18n %} +{% block content %} + +{% endblock %} + diff --git a/templates/cas_server/proxy.xml b/templates/cas_server/proxy.xml new file mode 100644 index 00000000..ab51d89a --- /dev/null +++ b/templates/cas_server/proxy.xml @@ -0,0 +1,5 @@ + + + {{ticket}} + + diff --git a/templates/cas_server/samlValidate.xml b/templates/cas_server/samlValidate.xml new file mode 100644 index 00000000..d61bed11 --- /dev/null +++ b/templates/cas_server/samlValidate.xml @@ -0,0 +1,59 @@ + + + + + + + + + + + + + {{Recipient}} + + + + + + {{username}} + + + urn:oasis:names:tc:SAML:1.0:cm:artifact + + + + + {{auth_date}} + + + false{# we do not support long-term (Remember-Me) auth #} + + + {{is_new_login}} + +{% for name, value in attributes %} + {{value}} + +{% endfor %} + + + {{username}} + + + urn:oasis:names:tc:SAML:1.0:cm:artifact + + + + + + + + diff --git a/templates/cas_server/samlValidateError.xml b/templates/cas_server/samlValidateError.xml new file mode 100644 index 00000000..b1b4226f --- /dev/null +++ b/templates/cas_server/samlValidateError.xml @@ -0,0 +1,14 @@ + + + + + + {{msg}} + + + + diff --git a/templates/cas_server/serviceValidate.xml b/templates/cas_server/serviceValidate.xml new file mode 100644 index 00000000..f583dbea --- /dev/null +++ b/templates/cas_server/serviceValidate.xml @@ -0,0 +1,19 @@ + + + {{username}} + + {{auth_date}} + false{# we do not support long-term (Remember-Me) auth #} + {{is_new_login}} +{% for key, value in attributes %} {{value}} +{% endfor %} + + + +{% for key, value in attributes %} +{% endfor %}{% if proxyGrantingTicket %} {{proxyGrantingTicket}} +{% endif %}{% if proxies %} +{% for proxy in proxies %} {{proxy}} +{% endfor %} +{% endif %} + diff --git a/templates/cas_server/serviceValidateError.xml b/templates/cas_server/serviceValidateError.xml new file mode 100644 index 00000000..cab8d9bd --- /dev/null +++ b/templates/cas_server/serviceValidateError.xml @@ -0,0 +1,3 @@ + + {{msg}} + diff --git a/templates/cas_server/warn.html b/templates/cas_server/warn.html new file mode 100644 index 00000000..4f80b15a --- /dev/null +++ b/templates/cas_server/warn.html @@ -0,0 +1,11 @@ +{% extends "cas_server/base.html" %} +{% load static %} +{% load i18n %} + +{% block content %} + +{% endblock %} From 21fd121ba7155a7ea4abbe3076402c5e8318e706 Mon Sep 17 00:00:00 2001 From: Yohann D'ANELLO Date: Sat, 7 Mar 2020 18:55:18 +0100 Subject: [PATCH 07/98] Add signup link, customize templates --- apps/note/fixtures/initial.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/apps/note/fixtures/initial.json b/apps/note/fixtures/initial.json index c0e92bda..f80332c0 100644 --- a/apps/note/fixtures/initial.json +++ b/apps/note/fixtures/initial.json @@ -3,7 +3,7 @@ "model": "note.note", "pk": 1, "fields": { - "polymorphic_ctype": 22, + "polymorphic_ctype": 39, "balance": 0, "is_active": true, "display_image": "", @@ -14,7 +14,7 @@ "model": "note.note", "pk": 2, "fields": { - "polymorphic_ctype": 22, + "polymorphic_ctype": 39, "balance": 0, "is_active": true, "display_image": "", @@ -25,7 +25,7 @@ "model": "note.note", "pk": 3, "fields": { - "polymorphic_ctype": 22, + "polymorphic_ctype": 39, "balance": 0, "is_active": true, "display_image": "", @@ -36,7 +36,7 @@ "model": "note.note", "pk": 4, "fields": { - "polymorphic_ctype": 22, + "polymorphic_ctype": 39, "balance": 0, "is_active": true, "display_image": "", @@ -47,7 +47,7 @@ "model": "note.note", "pk": 5, "fields": { - "polymorphic_ctype": 21, + "polymorphic_ctype": 38, "balance": 0, "is_active": true, "display_image": "", @@ -58,7 +58,7 @@ "model": "note.note", "pk": 6, "fields": { - "polymorphic_ctype": 21, + "polymorphic_ctype": 38, "balance": 0, "is_active": true, "display_image": "", From d0667ad7cb716877d045175c927acb99d59eee84 Mon Sep 17 00:00:00 2001 From: Maxime Bombar Date: Sat, 7 Mar 2020 21:29:45 +0100 Subject: [PATCH 08/98] Typo in README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5ae8a396..8e749cac 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,7 @@ On supposera pour la suite que vous utiliser debian/ubuntu sur un serveur tout n ***Modifier le fichier pour être en accord avec le reste de votre config*** - On utilise uwsgi et Nginx pour gérer le coté serveu : + On utilise uwsgi et Nginx pour gérer le coté serveur : $ sudo ln -sf /var/www/note_kfet/nginx_note.conf /etc/nginx/sites-enabled/ From 9f41f7c9a522650ed268c08ca57e5dc7d4b06a8e Mon Sep 17 00:00:00 2001 From: Maxime Bombar Date: Sat, 7 Mar 2020 22:20:42 +0100 Subject: [PATCH 09/98] New typo in README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8e749cac..5c38384c 100644 --- a/README.md +++ b/README.md @@ -102,7 +102,7 @@ On supposera pour la suite que vous utiliser debian/ubuntu sur un serveur tout n DJANGO_APP_STAGE='prod' DJANGO_DB_PASSWORD='le_mot_de_passe_de_la_bdd' DJANGO_SECRET_KEY='une_secret_key_longue_et_compliquee' - ALLOWED_HOSTS='le_ndd_de_votre_instance' + ALLOWED_HOSTS='le_ndd_de_votre_instance' 6. Variable d'environnement et Migrations From d0206fb79051fd647313741f8eae1d61c5b415fc Mon Sep 17 00:00:00 2001 From: Yohann D'ANELLO Date: Sat, 7 Mar 2020 22:28:59 +0100 Subject: [PATCH 10/98] Make erdnaxe be happy --- apps/activity/admin.py | 2 +- apps/activity/api/serializers.py | 3 + apps/activity/api/views.py | 2 +- apps/api/urls.py | 1 + apps/logs/models.py | 4 +- apps/logs/signals.py | 29 +++---- apps/member/admin.py | 4 +- apps/member/api/serializers.py | 4 + apps/member/api/views.py | 2 +- apps/member/filters.py | 6 +- apps/member/forms.py | 32 ++++---- apps/member/models.py | 7 +- apps/member/signals.py | 1 + apps/member/views.py | 93 ++++++++++++---------- apps/note/admin.py | 18 ++--- apps/note/api/serializers.py | 8 ++ apps/note/api/views.py | 4 +- apps/note/forms.py | 84 +++++++++---------- apps/note/models/notes.py | 11 +-- apps/note/models/transactions.py | 9 ++- apps/note/tables.py | 19 +++-- apps/note/views.py | 6 +- note_kfet/middlewares.py | 5 -- note_kfet/settings/__init__.py | 13 ++- note_kfet/settings/base.py | 11 ++- note_kfet/settings/development.py | 9 +-- note_kfet/settings/production.py | 2 +- note_kfet/urls.py | 11 ++- templates/cas_server/samlValidate.xml | 10 +-- templates/cas_server/samlValidateError.xml | 10 +-- 30 files changed, 215 insertions(+), 205 deletions(-) diff --git a/apps/activity/admin.py b/apps/activity/admin.py index 5ceb4e81..0529d306 100644 --- a/apps/activity/admin.py +++ b/apps/activity/admin.py @@ -11,7 +11,7 @@ class ActivityAdmin(admin.ModelAdmin): Admin customisation for Activity """ list_display = ('name', 'activity_type', 'organizer') - list_filter = ('activity_type', ) + list_filter = ('activity_type',) search_fields = ['name', 'organizer__name'] # Organize activities by start date diff --git a/apps/activity/api/serializers.py b/apps/activity/api/serializers.py index 0b9302f1..514515ef 100644 --- a/apps/activity/api/serializers.py +++ b/apps/activity/api/serializers.py @@ -11,6 +11,7 @@ class ActivityTypeSerializer(serializers.ModelSerializer): REST API Serializer for Activity types. The djangorestframework plugin will analyse the model `ActivityType` and parse all fields in the API. """ + class Meta: model = ActivityType fields = '__all__' @@ -21,6 +22,7 @@ class ActivitySerializer(serializers.ModelSerializer): REST API Serializer for Activities. The djangorestframework plugin will analyse the model `Activity` and parse all fields in the API. """ + class Meta: model = Activity fields = '__all__' @@ -31,6 +33,7 @@ class GuestSerializer(serializers.ModelSerializer): REST API Serializer for Guests. The djangorestframework plugin will analyse the model `Guest` and parse all fields in the API. """ + class Meta: model = Guest fields = '__all__' diff --git a/apps/activity/api/views.py b/apps/activity/api/views.py index 5683d458..6a6c024e 100644 --- a/apps/activity/api/views.py +++ b/apps/activity/api/views.py @@ -3,8 +3,8 @@ from rest_framework import viewsets -from ..models import ActivityType, Activity, Guest from .serializers import ActivityTypeSerializer, ActivitySerializer, GuestSerializer +from ..models import ActivityType, Activity, Guest class ActivityTypeViewSet(viewsets.ModelViewSet): diff --git a/apps/api/urls.py b/apps/api/urls.py index 7e59a8c0..c1b6bf48 100644 --- a/apps/api/urls.py +++ b/apps/api/urls.py @@ -14,6 +14,7 @@ class UserSerializer(serializers.ModelSerializer): REST API Serializer for Users. The djangorestframework plugin will analyse the model `User` and parse all fields in the API. """ + class Meta: model = User exclude = ( diff --git a/apps/logs/models.py b/apps/logs/models.py index 337315bb..1018ce72 100644 --- a/apps/logs/models.py +++ b/apps/logs/models.py @@ -1,11 +1,11 @@ # Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # SPDX-License-Identifier: GPL-3.0-or-later -from django.contrib.contenttypes.models import ContentType -from django.utils.translation import gettext_lazy as _ from django.conf import settings +from django.contrib.contenttypes.models import ContentType from django.core.exceptions import ValidationError from django.db import models +from django.utils.translation import gettext_lazy as _ class Changelog(models.Model): diff --git a/apps/logs/signals.py b/apps/logs/signals.py index 13194e5b..415e7c1c 100644 --- a/apps/logs/signals.py +++ b/apps/logs/signals.py @@ -7,6 +7,7 @@ from django.contrib.contenttypes.models import ContentType from django.core import serializers from django.db.models.signals import pre_save, post_save, post_delete from django.dispatch import receiver + from .models import Changelog @@ -43,20 +44,20 @@ def get_user_and_ip(sender): EXCLUDED = [ - 'admin.logentry', - 'authtoken.token', - 'cas_server.user', - 'cas_server.userattributes', - 'contenttypes.contenttype', - 'logs.changelog', - 'migrations.migration', - 'note.noteuser', - 'note.noteclub', - 'note.notespecial', - 'sessions.session', - 'reversion.revision', - 'reversion.version', - ] + 'admin.logentry', + 'authtoken.token', + 'cas_server.user', + 'cas_server.userattributes', + 'contenttypes.contenttype', + 'logs.changelog', + 'migrations.migration', + 'note.noteuser', + 'note.noteclub', + 'note.notespecial', + 'sessions.session', + 'reversion.revision', + 'reversion.version', +] @receiver(pre_save) diff --git a/apps/member/admin.py b/apps/member/admin.py index fb107377..c7c3ead3 100644 --- a/apps/member/admin.py +++ b/apps/member/admin.py @@ -18,9 +18,9 @@ class ProfileInline(admin.StackedInline): class CustomUserAdmin(UserAdmin): - inlines = (ProfileInline, ) + inlines = (ProfileInline,) list_display = ('username', 'email', 'first_name', 'last_name', 'is_staff') - list_select_related = ('profile', ) + list_select_related = ('profile',) form = ProfileForm def get_inline_instances(self, request, obj=None): diff --git a/apps/member/api/serializers.py b/apps/member/api/serializers.py index f4df6799..962841ae 100644 --- a/apps/member/api/serializers.py +++ b/apps/member/api/serializers.py @@ -11,6 +11,7 @@ class ProfileSerializer(serializers.ModelSerializer): REST API Serializer for Profiles. The djangorestframework plugin will analyse the model `Profile` and parse all fields in the API. """ + class Meta: model = Profile fields = '__all__' @@ -21,6 +22,7 @@ class ClubSerializer(serializers.ModelSerializer): REST API Serializer for Clubs. The djangorestframework plugin will analyse the model `Club` and parse all fields in the API. """ + class Meta: model = Club fields = '__all__' @@ -31,6 +33,7 @@ class RoleSerializer(serializers.ModelSerializer): REST API Serializer for Roles. The djangorestframework plugin will analyse the model `Role` and parse all fields in the API. """ + class Meta: model = Role fields = '__all__' @@ -41,6 +44,7 @@ class MembershipSerializer(serializers.ModelSerializer): REST API Serializer for Memberships. The djangorestframework plugin will analyse the model `Memberships` and parse all fields in the API. """ + class Meta: model = Membership fields = '__all__' diff --git a/apps/member/api/views.py b/apps/member/api/views.py index 79ba4c12..7e7dcd1d 100644 --- a/apps/member/api/views.py +++ b/apps/member/api/views.py @@ -3,8 +3,8 @@ from rest_framework import viewsets -from ..models import Profile, Club, Role, Membership from .serializers import ProfileSerializer, ClubSerializer, RoleSerializer, MembershipSerializer +from ..models import Profile, Club, Role, Membership class ProfileViewSet(viewsets.ModelViewSet): diff --git a/apps/member/filters.py b/apps/member/filters.py index 418e52fc..951723e8 100644 --- a/apps/member/filters.py +++ b/apps/member/filters.py @@ -1,11 +1,11 @@ # Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # SPDX-License-Identifier: GPL-3.0-or-later -from django_filters import FilterSet, CharFilter -from django.contrib.auth.models import User -from django.db.models import CharField from crispy_forms.helper import FormHelper from crispy_forms.layout import Layout, Submit +from django.contrib.auth.models import User +from django.db.models import CharField +from django_filters import FilterSet, CharFilter class UserFilter(FilterSet): diff --git a/apps/member/forms.py b/apps/member/forms.py index abb35cd9..d2134cdd 100644 --- a/apps/member/forms.py +++ b/apps/member/forms.py @@ -1,23 +1,22 @@ # Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # SPDX-License-Identifier: GPL-3.0-or-later +from crispy_forms.bootstrap import Div +from crispy_forms.helper import FormHelper +from crispy_forms.layout import Layout from dal import autocomplete +from django import forms from django.contrib.auth.forms import UserCreationForm from django.contrib.auth.models import User -from django import forms from .models import Profile, Club, Membership -from crispy_forms.helper import FormHelper -from crispy_forms.bootstrap import Div -from crispy_forms.layout import Layout - class SignUpForm(UserCreationForm): - def __init__(self,*args,**kwargs): - super().__init__(*args,**kwargs) + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) self.fields['username'].widget.attrs.pop("autofocus", None) - self.fields['first_name'].widget.attrs.update({"autofocus":"autofocus"}) + self.fields['first_name'].widget.attrs.update({"autofocus": "autofocus"}) class Meta: model = User @@ -28,6 +27,7 @@ class ProfileForm(forms.ModelForm): """ A form for the extras field provided by the :model:`member.Profile` model. """ + class Meta: model = Profile fields = '__all__' @@ -42,7 +42,7 @@ class ClubForm(forms.ModelForm): class AddMembersForm(forms.Form): class Meta: - fields = ('', ) + fields = ('',) class MembershipForm(forms.ModelForm): @@ -54,13 +54,13 @@ class MembershipForm(forms.ModelForm): # et récupère les noms d'utilisateur valides widgets = { 'user': - autocomplete.ModelSelect2( - url='member:user_autocomplete', - attrs={ - 'data-placeholder': 'Nom ...', - 'data-minimum-input-length': 1, - }, - ), + autocomplete.ModelSelect2( + url='member:user_autocomplete', + attrs={ + 'data-placeholder': 'Nom ...', + 'data-minimum-input-length': 1, + }, + ), } diff --git a/apps/member/models.py b/apps/member/models.py index cd754bd8..50b0bea1 100644 --- a/apps/member/models.py +++ b/apps/member/models.py @@ -3,8 +3,8 @@ from django.conf import settings from django.db import models -from django.utils.translation import gettext_lazy as _ from django.urls import reverse, reverse_lazy +from django.utils.translation import gettext_lazy as _ class Profile(models.Model): @@ -48,7 +48,7 @@ class Profile(models.Model): verbose_name_plural = _('user profile') def get_absolute_url(self): - return reverse('user_detail', args=(self.pk, )) + return reverse('user_detail', args=(self.pk,)) class Club(models.Model): @@ -97,7 +97,7 @@ class Club(models.Model): return self.name def get_absolute_url(self): - return reverse_lazy('member:club_detail', args=(self.pk, )) + return reverse_lazy('member:club_detail', args=(self.pk,)) class Role(models.Model): @@ -153,7 +153,6 @@ class Membership(models.Model): verbose_name = _('membership') verbose_name_plural = _('memberships') - # @receiver(post_save, sender=settings.AUTH_USER_MODEL) # def save_user_profile(instance, created, **_kwargs): # """ diff --git a/apps/member/signals.py b/apps/member/signals.py index b17b3ae8..2b03e3ce 100644 --- a/apps/member/signals.py +++ b/apps/member/signals.py @@ -1,6 +1,7 @@ # Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # SPDX-License-Identifier: GPL-3.0-or-later + def save_user_profile(instance, created, raw, **_kwargs): """ Hook to create and save a profile when an user is updated if it is not registered with the signup form diff --git a/apps/member/views.py b/apps/member/views.py index d4bbc592..88bd2678 100644 --- a/apps/member/views.py +++ b/apps/member/views.py @@ -1,33 +1,33 @@ # Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # SPDX-License-Identifier: GPL-3.0-or-later -from django.contrib.auth.mixins import LoginRequiredMixin -from django.shortcuts import redirect -from django.utils.translation import gettext_lazy as _ -from django.views.generic import CreateView, DetailView, UpdateView, TemplateView,DeleteView -from django.views.generic.edit import FormMixin -from django.contrib.auth.models import User -from django.contrib import messages -from django.urls import reverse_lazy -from django.http import HttpResponseRedirect -from django.db.models import Q -from django.core.exceptions import ValidationError -from django.conf import settings -from django_tables2.views import SingleTableView -from rest_framework.authtoken.models import Token -from dal import autocomplete -from PIL import Image import io +from PIL import Image +from dal import autocomplete +from django.conf import settings +from django.contrib import messages +from django.contrib.auth.mixins import LoginRequiredMixin +from django.contrib.auth.models import User +from django.core.exceptions import ValidationError +from django.db.models import Q +from django.http import HttpResponseRedirect +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, DetailView, UpdateView, TemplateView, DeleteView +from django.views.generic.edit import FormMixin +from django_tables2.views import SingleTableView +from rest_framework.authtoken.models import Token +from note.forms import AliasForm, ImageForm from note.models import Alias, NoteUser from note.models.transactions import Transaction from note.tables import HistoryTable, AliasTable -from note.forms import AliasForm, ImageForm -from .models import Profile, Club, Membership -from .forms import SignUpForm, ProfileForm, ClubForm, MembershipForm, MemberFormSet, FormSetHelper -from .tables import ClubTable, UserTable from .filters import UserFilter, UserFilterFormHelper +from .forms import SignUpForm, ProfileForm, ClubForm, MembershipForm, MemberFormSet, FormSetHelper +from .models import Club, Membership +from .tables import ClubTable, UserTable class UserCreateView(CreateView): @@ -109,7 +109,7 @@ class UserUpdateView(LoginRequiredMixin, UpdateView): return reverse_lazy('member:user_detail', kwargs={'pk': kwargs['id']}) else: - return reverse_lazy('member:user_detail', args=(self.object.id, )) + return reverse_lazy('member:user_detail', args=(self.object.id,)) class UserDetailView(LoginRequiredMixin, DetailView): @@ -157,13 +157,14 @@ class UserListView(LoginRequiredMixin, SingleTableView): context["filter"] = self.filter return context -class AliasView(LoginRequiredMixin,FormMixin,DetailView): + +class AliasView(LoginRequiredMixin, FormMixin, DetailView): model = User template_name = 'member/profile_alias.html' context_object_name = 'user_object' form_class = AliasForm - def get_context_data(self,**kwargs): + def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) note = context['user_object'].note context["aliases"] = AliasTable(note.alias_set.all()) @@ -172,7 +173,7 @@ class AliasView(LoginRequiredMixin,FormMixin,DetailView): def get_success_url(self): return reverse_lazy('member:user_alias', kwargs={'pk': self.object.id}) - def post(self,request,*args,**kwargs): + def post(self, request, *args, **kwargs): self.object = self.get_object() form = self.get_form() if form.is_valid(): @@ -186,42 +187,45 @@ class AliasView(LoginRequiredMixin,FormMixin,DetailView): alias.save() return super().form_valid(form) + class DeleteAliasView(LoginRequiredMixin, DeleteView): model = Alias - def delete(self,request,*args,**kwargs): + def delete(self, request, *args, **kwargs): try: self.object = self.get_object() self.object.delete() except ValidationError as e: # TODO: pass message to redirected view. - messages.error(self.request,str(e)) + messages.error(self.request, str(e)) else: - messages.success(self.request,_("Alias successfully deleted")) + messages.success(self.request, _("Alias successfully deleted")) return HttpResponseRedirect(self.get_success_url()) - + def get_success_url(self): print(self.request) - return reverse_lazy('member:user_alias',kwargs={'pk':self.object.note.user.pk}) + return reverse_lazy('member:user_alias', kwargs={'pk': self.object.note.user.pk}) def get(self, request, *args, **kwargs): return self.post(request, *args, **kwargs) + class ProfilePictureUpdateView(LoginRequiredMixin, FormMixin, DetailView): model = User template_name = 'member/profile_picture_update.html' context_object_name = 'user_object' form_class = ImageForm - def get_context_data(self,*args,**kwargs): - context = super().get_context_data(*args,**kwargs) - context['form'] = self.form_class(self.request.POST,self.request.FILES) + + def get_context_data(self, *args, **kwargs): + context = super().get_context_data(*args, **kwargs) + context['form'] = self.form_class(self.request.POST, self.request.FILES) return context - + def get_success_url(self): return reverse_lazy('member:user_detail', kwargs={'pk': self.object.id}) - def post(self,request,*args,**kwargs): - form = self.get_form() + def post(self, request, *args, **kwargs): + form = self.get_form() self.object = self.get_object() if form.is_valid(): return self.form_valid(form) @@ -230,7 +234,7 @@ class ProfilePictureUpdateView(LoginRequiredMixin, FormMixin, DetailView): print(form) return self.form_invalid(form) - def form_valid(self,form): + def form_valid(self, form): image_field = form.cleaned_data['image'] x = form.cleaned_data['x'] y = form.cleaned_data['y'] @@ -238,15 +242,15 @@ class ProfilePictureUpdateView(LoginRequiredMixin, FormMixin, DetailView): h = form.cleaned_data['height'] # image crop and resize image_file = io.BytesIO(image_field.read()) - ext = image_field.name.split('.')[-1].lower() - #TODO: support GIF format + # ext = image_field.name.split('.')[-1].lower() + # TODO: support GIF format image = Image.open(image_file) - image = image.crop((x, y, x+w, y+h)) + image = image.crop((x, y, x + w, y + h)) image_clean = image.resize((settings.PIC_WIDTH, - settings.PIC_RATIO*settings.PIC_WIDTH), - Image.ANTIALIAS) + settings.PIC_RATIO * settings.PIC_WIDTH), + Image.ANTIALIAS) image_file = io.BytesIO() - image_clean.save(image_file,"PNG") + image_clean.save(image_file, "PNG") image_field.file = image_file # renaming filename = "{}_pic.png".format(self.object.note.pk) @@ -255,7 +259,7 @@ class ProfilePictureUpdateView(LoginRequiredMixin, FormMixin, DetailView): self.object.note.save() return super().form_valid(form) - + class ManageAuthTokens(LoginRequiredMixin, TemplateView): """ Affiche le jeton d'authentification, et permet de le regénérer @@ -283,6 +287,7 @@ class UserAutocomplete(autocomplete.Select2QuerySetView): """ Auto complete users by usernames """ + def get_queryset(self): """ Quand une personne cherche un utilisateur par pseudo, une requête est envoyée sur l'API dédiée à l'auto-complétion. @@ -331,7 +336,7 @@ class ClubDetailView(LoginRequiredMixin, DetailView): def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) club = context["club"] - club_transactions = \ + club_transactions = \ Transaction.objects.all().filter(Q(source=club.note) | Q(destination=club.note)) context['history_list'] = HistoryTable(club_transactions) club_member = \ diff --git a/apps/note/admin.py b/apps/note/admin.py index 52c1cc17..a0928641 100644 --- a/apps/note/admin.py +++ b/apps/note/admin.py @@ -47,11 +47,11 @@ class NoteClubAdmin(PolymorphicChildModelAdmin): """ Child for a club note, see NoteAdmin """ - inlines = (AliasInlines, ) + inlines = (AliasInlines,) # We can't change club after creation or the balance readonly_fields = ('club', 'balance') - search_fields = ('club', ) + search_fields = ('club',) def has_add_permission(self, request): """ @@ -71,7 +71,7 @@ class NoteSpecialAdmin(PolymorphicChildModelAdmin): """ Child for a special note, see NoteAdmin """ - readonly_fields = ('balance', ) + readonly_fields = ('balance',) @admin.register(NoteUser) @@ -79,7 +79,7 @@ class NoteUserAdmin(PolymorphicChildModelAdmin): """ Child for an user note, see NoteAdmin """ - inlines = (AliasInlines, ) + inlines = (AliasInlines,) # We can't change user after creation or the balance readonly_fields = ('user', 'balance') @@ -133,7 +133,7 @@ class TransactionAdmin(PolymorphicParentModelAdmin): Else the amount of money would not be transferred """ if obj: # user is editing an existing object - return 'created_at', 'source', 'destination', 'quantity',\ + return 'created_at', 'source', 'destination', 'quantity', \ 'amount' return [] @@ -143,9 +143,9 @@ class TransactionTemplateAdmin(admin.ModelAdmin): """ Admin customisation for TransactionTemplate """ - list_display = ('name', 'poly_destination', 'amount', 'category', 'display', ) + list_display = ('name', 'poly_destination', 'amount', 'category', 'display',) list_filter = ('category', 'display') - autocomplete_fields = ('destination', ) + autocomplete_fields = ('destination',) def poly_destination(self, obj): """ @@ -161,5 +161,5 @@ class TemplateCategoryAdmin(admin.ModelAdmin): """ Admin customisation for TransactionTemplate """ - list_display = ('name', ) - list_filter = ('name', ) + list_display = ('name',) + list_filter = ('name',) diff --git a/apps/note/api/serializers.py b/apps/note/api/serializers.py index db0e3531..1696bfee 100644 --- a/apps/note/api/serializers.py +++ b/apps/note/api/serializers.py @@ -13,6 +13,7 @@ class NoteSerializer(serializers.ModelSerializer): REST API Serializer for Notes. The djangorestframework plugin will analyse the model `Note` and parse all fields in the API. """ + class Meta: model = Note fields = '__all__' @@ -29,6 +30,7 @@ class NoteClubSerializer(serializers.ModelSerializer): REST API Serializer for Club's notes. The djangorestframework plugin will analyse the model `NoteClub` and parse all fields in the API. """ + class Meta: model = NoteClub fields = '__all__' @@ -39,6 +41,7 @@ class NoteSpecialSerializer(serializers.ModelSerializer): REST API Serializer for special notes. The djangorestframework plugin will analyse the model `NoteSpecial` and parse all fields in the API. """ + class Meta: model = NoteSpecial fields = '__all__' @@ -49,6 +52,7 @@ class NoteUserSerializer(serializers.ModelSerializer): REST API Serializer for User's notes. The djangorestframework plugin will analyse the model `NoteUser` and parse all fields in the API. """ + class Meta: model = NoteUser fields = '__all__' @@ -59,6 +63,7 @@ class AliasSerializer(serializers.ModelSerializer): REST API Serializer for Aliases. The djangorestframework plugin will analyse the model `Alias` and parse all fields in the API. """ + class Meta: model = Alias fields = '__all__' @@ -78,6 +83,7 @@ class TransactionTemplateSerializer(serializers.ModelSerializer): REST API Serializer for Transaction templates. The djangorestframework plugin will analyse the model `TransactionTemplate` and parse all fields in the API. """ + class Meta: model = TransactionTemplate fields = '__all__' @@ -88,6 +94,7 @@ class TransactionSerializer(serializers.ModelSerializer): REST API Serializer for Transactions. The djangorestframework plugin will analyse the model `Transaction` and parse all fields in the API. """ + class Meta: model = Transaction fields = '__all__' @@ -98,6 +105,7 @@ class MembershipTransactionSerializer(serializers.ModelSerializer): REST API Serializer for Membership transactions. The djangorestframework plugin will analyse the model `MembershipTransaction` and parse all fields in the API. """ + class Meta: model = MembershipTransaction fields = '__all__' diff --git a/apps/note/api/views.py b/apps/note/api/views.py index 94b4a47a..cf0136f2 100644 --- a/apps/note/api/views.py +++ b/apps/note/api/views.py @@ -4,11 +4,11 @@ from django.db.models import Q from rest_framework import viewsets -from ..models.notes import Note, NoteClub, NoteSpecial, NoteUser, Alias -from ..models.transactions import TransactionTemplate, Transaction, MembershipTransaction from .serializers import NoteSerializer, NotePolymorphicSerializer, NoteClubSerializer, NoteSpecialSerializer, \ NoteUserSerializer, AliasSerializer, \ TransactionTemplateSerializer, TransactionSerializer, MembershipTransactionSerializer +from ..models.notes import Note, NoteClub, NoteSpecial, NoteUser, Alias +from ..models.transactions import TransactionTemplate, Transaction, MembershipTransaction class NoteViewSet(viewsets.ModelViewSet): diff --git a/apps/note/forms.py b/apps/note/forms.py index 819ed97a..07e44206 100644 --- a/apps/note/forms.py +++ b/apps/note/forms.py @@ -3,31 +3,25 @@ from dal import autocomplete from django import forms -from django.conf import settings from django.utils.translation import gettext_lazy as _ -import os - -from crispy_forms.helper import FormHelper -from crispy_forms.bootstrap import Div -from crispy_forms.layout import Layout, HTML - +from .models import Alias from .models import Transaction, TransactionTemplate, TemplateTransaction -from .models import Note, Alias + class AliasForm(forms.ModelForm): class Meta: model = Alias fields = ("name",) - def __init__(self,*args,**kwargs): - super().__init__(*args,**kwargs) + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) self.fields["name"].label = False - self.fields["name"].widget.attrs={"placeholder":_('New Alias')} - + self.fields["name"].widget.attrs = {"placeholder": _('New Alias')} + class ImageForm(forms.Form): - image = forms.ImageField(required = False, + image = forms.ImageField(required=False, label=_('select an image'), help_text=_('Maximal size: 2MB')) x = forms.FloatField(widget=forms.HiddenInput()) @@ -35,7 +29,7 @@ class ImageForm(forms.Form): width = forms.FloatField(widget=forms.HiddenInput()) height = forms.FloatField(widget=forms.HiddenInput()) - + class TransactionTemplateForm(forms.ModelForm): class Meta: model = TransactionTemplate @@ -48,13 +42,13 @@ class TransactionTemplateForm(forms.ModelForm): # forward=(forward.Const('TYPE', 'note_type') où TYPE est dans {user, club, special} widgets = { 'destination': - autocomplete.ModelSelect2( - url='note:note_autocomplete', - attrs={ - 'data-placeholder': 'Note ...', - 'data-minimum-input-length': 1, - }, - ), + autocomplete.ModelSelect2( + url='note:note_autocomplete', + attrs={ + 'data-placeholder': 'Note ...', + 'data-minimum-input-length': 1, + }, + ), } @@ -62,7 +56,6 @@ class TransactionForm(forms.ModelForm): def save(self, commit=True): super().save(commit) - def clean(self): """ If the user has no right to transfer funds, then it will be the source of the transfer by default. @@ -70,7 +63,7 @@ class TransactionForm(forms.ModelForm): """ cleaned_data = super().clean() - if not "source" in cleaned_data: # TODO Replace it with "if %user has no right to transfer funds" + if "source" not in cleaned_data: # TODO Replace it with "if %user has no right to transfer funds" cleaned_data["source"] = self.user.note if cleaned_data["source"].pk == cleaned_data["destination"].pk: @@ -78,7 +71,6 @@ class TransactionForm(forms.ModelForm): return cleaned_data - class Meta: model = Transaction fields = ( @@ -91,21 +83,21 @@ class TransactionForm(forms.ModelForm): # Voir ci-dessus widgets = { 'source': - autocomplete.ModelSelect2( - url='note:note_autocomplete', - attrs={ - 'data-placeholder': 'Note ...', - 'data-minimum-input-length': 1, - }, - ), + autocomplete.ModelSelect2( + url='note:note_autocomplete', + attrs={ + 'data-placeholder': 'Note ...', + 'data-minimum-input-length': 1, + }, + ), 'destination': - autocomplete.ModelSelect2( - url='note:note_autocomplete', - attrs={ - 'data-placeholder': 'Note ...', - 'data-minimum-input-length': 1, - }, - ), + autocomplete.ModelSelect2( + url='note:note_autocomplete', + attrs={ + 'data-placeholder': 'Note ...', + 'data-minimum-input-length': 1, + }, + ), } @@ -122,18 +114,18 @@ class ConsoForm(forms.ModelForm): class Meta: model = TemplateTransaction - fields = ('source', ) + fields = ('source',) # Le champ d'utilisateur est remplacé par un champ d'auto-complétion. # Quand des lettres sont tapées, une requête est envoyée sur l'API d'auto-complétion # et récupère les aliases de note valides widgets = { 'source': - autocomplete.ModelSelect2( - url='note:note_autocomplete', - attrs={ - 'data-placeholder': 'Note ...', - 'data-minimum-input-length': 1, - }, - ), + autocomplete.ModelSelect2( + url='note:note_autocomplete', + attrs={ + 'data-placeholder': 'Note ...', + 'data-minimum-input-length': 1, + }, + ), } diff --git a/apps/note/models/notes.py b/apps/note/models/notes.py index 4b06c93a..74cda3ea 100644 --- a/apps/note/models/notes.py +++ b/apps/note/models/notes.py @@ -9,6 +9,7 @@ from django.core.validators import RegexValidator from django.db import models from django.utils.translation import gettext_lazy as _ from polymorphic.models import PolymorphicModel + """ Defines each note types """ @@ -27,7 +28,7 @@ class Note(PolymorphicModel): help_text=_('in centimes, money credited for this instance'), default=0, ) - last_negative= models.DateTimeField( + last_negative = models.DateTimeField( verbose_name=_('last negative date'), help_text=_('last time the balance was negative'), null=True, @@ -98,7 +99,7 @@ class Note(PolymorphicModel): # Alias exists, so check if it is linked to this note if aliases.first().note != self: raise ValidationError(_('This alias is already taken.'), - code="same_alias",) + code="same_alias", ) else: # Alias does not exist yet, so check if it can exist a = Alias(name=str(self)) @@ -231,12 +232,12 @@ class Alias(models.Model): sim_alias = Alias.objects.get(normalized_name=normalized_name) if self != sim_alias: raise ValidationError(_('An alias with a similar name already exists: {} '.format(sim_alias)), - code="same_alias" - ) + code="same_alias" + ) except Alias.DoesNotExist: pass self.normalized_name = normalized_name - + def delete(self, using=None, keep_parents=False): if self.name == str(self.note): raise ValidationError(_("You can't delete your main alias."), diff --git a/apps/note/models/transactions.py b/apps/note/models/transactions.py index 598c119b..3bb7ca76 100644 --- a/apps/note/models/transactions.py +++ b/apps/note/models/transactions.py @@ -2,9 +2,9 @@ # SPDX-License-Identifier: GPL-3.0-or-later from django.db import models +from django.urls import reverse from django.utils import timezone from django.utils.translation import gettext_lazy as _ -from django.urls import reverse from polymorphic.models import PolymorphicModel from .notes import Note, NoteClub @@ -44,7 +44,7 @@ class TransactionTemplate(models.Model): verbose_name=_('name'), max_length=255, unique=True, - error_messages={'unique':_("A template with this name already exist")}, + error_messages={'unique': _("A template with this name already exist")}, ) destination = models.ForeignKey( NoteClub, @@ -63,7 +63,7 @@ class TransactionTemplate(models.Model): max_length=31, ) display = models.BooleanField( - default = True, + default=True, ) description = models.CharField( verbose_name=_('description'), @@ -75,7 +75,7 @@ class TransactionTemplate(models.Model): verbose_name_plural = _("transaction templates") def get_absolute_url(self): - return reverse('note:template_update', args=(self.pk, )) + return reverse('note:template_update', args=(self.pk,)) class Transaction(PolymorphicModel): @@ -168,6 +168,7 @@ class TemplateTransaction(Transaction): on_delete=models.PROTECT, ) + class MembershipTransaction(Transaction): """ Special type of :model:`note.Transaction` associated to a :model:`member.Membership`. diff --git a/apps/note/tables.py b/apps/note/tables.py index 20476cb6..9a2dce45 100644 --- a/apps/note/tables.py +++ b/apps/note/tables.py @@ -4,14 +4,16 @@ import django_tables2 as tables from django.db.models import F from django_tables2.utils import A -from .models.transactions import Transaction + from .models.notes import Alias +from .models.transactions import Transaction + class HistoryTable(tables.Table): class Meta: attrs = { 'class': - 'table table-condensed table-striped table-hover' + 'table table-condensed table-striped table-hover' } model = Transaction template_name = 'django_tables2/bootstrap4.html' @@ -25,21 +27,22 @@ class HistoryTable(tables.Table): .order_by(('-' if is_descending else '') + 'total') return (queryset, True) + class AliasTable(tables.Table): class Meta: attrs = { 'class': - 'table table condensed table-striped table-hover' + 'table table condensed table-striped table-hover' } model = Alias - fields =('name',) + fields = ('name',) template_name = 'django_tables2/bootstrap4.html' show_header = False - name = tables.Column(attrs={'td':{'class':'text-center'}}) + name = tables.Column(attrs={'td': {'class': 'text-center'}}) delete = tables.LinkColumn('member:user_alias_delete', args=[A('pk')], attrs={ - 'td': {'class':'col-sm-2'}, - 'a': {'class': 'btn btn-danger'} }, - text='delete',accessor='pk') + 'td': {'class': 'col-sm-2'}, + 'a': {'class': 'btn btn-danger'}}, + text='delete', accessor='pk') diff --git a/apps/note/views.py b/apps/note/views.py index 5038df16..09846057 100644 --- a/apps/note/views.py +++ b/apps/note/views.py @@ -8,8 +8,8 @@ from django.urls import reverse from django.utils.translation import gettext_lazy as _ from django.views.generic import CreateView, ListView, UpdateView -from .models import Transaction, TransactionTemplate, Alias, TemplateTransaction from .forms import TransactionForm, TransactionTemplateForm, ConsoForm +from .models import Transaction, TransactionTemplate, Alias, TemplateTransaction class TransactionCreate(LoginRequiredMixin, CreateView): @@ -53,6 +53,7 @@ class NoteAutocomplete(autocomplete.Select2QuerySetView): """ Auto complete note by aliases """ + def get_queryset(self): """ Quand une personne cherche un alias, une requête est envoyée sur l'API dédiée à l'auto-complétion. @@ -66,7 +67,7 @@ class NoteAutocomplete(autocomplete.Select2QuerySetView): # self.q est le paramètre de la recherche if self.q: - qs = qs.filter(Q(name__regex=self.q) | Q(normalized_name__regex=Alias.normalize(self.q)))\ + qs = qs.filter(Q(name__regex=self.q) | Q(normalized_name__regex=Alias.normalize(self.q))) \ .order_by('normalized_name').distinct() # Filtrage par type de note (user, club, special) @@ -147,4 +148,3 @@ class ConsoView(LoginRequiredMixin, CreateView): When clicking a button, reload the same page """ return reverse('note:consos') - diff --git a/note_kfet/middlewares.py b/note_kfet/middlewares.py index 73b87e36..b034e2be 100644 --- a/note_kfet/middlewares.py +++ b/note_kfet/middlewares.py @@ -1,10 +1,6 @@ # Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # SPDX-License-Identifier: GPL-3.0-or-later -from django.http import HttpResponseRedirect - -from urllib.parse import urlencode, parse_qs, urlsplit, urlunsplit - class TurbolinksMiddleware(object): """ @@ -35,4 +31,3 @@ class TurbolinksMiddleware(object): location = request.session.pop('_turbolinks_redirect_to') response['Turbolinks-Location'] = location return response - diff --git a/note_kfet/settings/__init__.py b/note_kfet/settings/__init__.py index 68a40b88..02abcd6e 100644 --- a/note_kfet/settings/__init__.py +++ b/note_kfet/settings/__init__.py @@ -1,8 +1,6 @@ -import os -import re - from .base import * + def read_env(): """Pulled from Honcho code with minor updates, reads local default environment variables from a .env file located in the project root @@ -25,14 +23,16 @@ def read_env(): val = re.sub(r'\\(.)', r'\1', m3.group(1)) os.environ.setdefault(key, val) + read_env() app_stage = os.environ.get('DJANGO_APP_STAGE', 'dev') if app_stage == 'prod': from .production import * - DATABASES["default"]["PASSWORD"] = os.environ.get('DJANGO_DB_PASSWORD','CHANGE_ME_IN_ENV_SETTINGS') - SECRET_KEY = os.environ.get('DJANGO_SECRET_KEY','CHANGE_ME_IN_ENV_SETTINGS') - ALLOWED_HOSTS.append(os.environ.get('ALLOWED_HOSTS','localhost')) + + DATABASES["default"]["PASSWORD"] = os.environ.get('DJANGO_DB_PASSWORD', 'CHANGE_ME_IN_ENV_SETTINGS') + SECRET_KEY = os.environ.get('DJANGO_SECRET_KEY', 'CHANGE_ME_IN_ENV_SETTINGS') + ALLOWED_HOSTS.append(os.environ.get('ALLOWED_HOSTS', 'localhost')) else: from .development import * @@ -43,4 +43,3 @@ except ImportError: # env variables set at the of in /env/bin/activate # don't forget to unset in deactivate ! - diff --git a/note_kfet/settings/base.py b/note_kfet/settings/base.py index 7ab59272..103e368d 100644 --- a/note_kfet/settings/base.py +++ b/note_kfet/settings/base.py @@ -97,7 +97,7 @@ TEMPLATES = [ 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', 'django.template.context_processors.request', - # 'django.template.context_processors.media', + # 'django.template.context_processors.media', ], }, }, @@ -183,7 +183,7 @@ FIXTURE_DIRS = [os.path.join(BASE_DIR, "note_kfet/fixtures")] # Don't put anything in this directory yourself; store your static files # in apps' "static/" subdirectories and in STATICFILES_DIRS. # Example: "/var/www/example.com/static/" -STATIC_ROOT = os.path.join(BASE_DIR,"static/") +STATIC_ROOT = os.path.join(BASE_DIR, "static/") # STATICFILES_DIRS = [ # os.path.join(BASE_DIR, 'static')] STATICFILES_DIRS = [] @@ -195,8 +195,8 @@ STATIC_URL = '/static/' ALIAS_VALIDATOR_REGEX = r'' -MEDIA_ROOT=os.path.join(BASE_DIR,"media") -MEDIA_URL='/media/' +MEDIA_ROOT = os.path.join(BASE_DIR, "media") +MEDIA_URL = '/media/' # Profile Picture Settings PIC_WIDTH = 200 @@ -211,7 +211,7 @@ CAS_SHOW_POWERED = False CAS_REDIRECT_TO_LOGIN_AFTER_LOGOUT = False CAS_INFO_MESSAGES = { "cas_explained": { - "message":_( + "message": _( u"The Central Authentication Service grants you access to most of our websites by " u"authenticating only once, so you don't need to type your credentials again unless " u"your session expires or you logout." @@ -224,4 +224,3 @@ CAS_INFO_MESSAGES = { CAS_INFO_MESSAGES_ORDER = [ 'cas_explained', ] - diff --git a/note_kfet/settings/development.py b/note_kfet/settings/development.py index 83436339..cf738f33 100644 --- a/note_kfet/settings/development.py +++ b/note_kfet/settings/development.py @@ -11,10 +11,11 @@ # - and more ... +import os + # Database # https://docs.djangoproject.com/en/2.2/ref/settings/#databases from . import * -import os DATABASES = { 'default': { @@ -53,8 +54,6 @@ SESSION_COOKIE_AGE = 60 * 60 * 3 # Can be modified in secrets.py CAS_SERVER_URL = "http://localhost:8000/cas/" - -STATIC_ROOT = '' # not needed in development settings +STATIC_ROOT = '' # not needed in development settings STATICFILES_DIRS = [ - os.path.join(BASE_DIR, 'static')] - + os.path.join(BASE_DIR, 'static')] diff --git a/note_kfet/settings/production.py b/note_kfet/settings/production.py index 353d7b8a..c595ee1f 100644 --- a/note_kfet/settings/production.py +++ b/note_kfet/settings/production.py @@ -26,7 +26,7 @@ DATABASES = { DEBUG = True # Mandatory ! -ALLOWED_HOSTS = ['127.0.0.1','note.comby.xyz'] +ALLOWED_HOSTS = ['127.0.0.1', 'note.comby.xyz'] # Emails EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' diff --git a/note_kfet/urls.py b/note_kfet/urls.py index a261a9eb..56251955 100644 --- a/note_kfet/urls.py +++ b/note_kfet/urls.py @@ -1,13 +1,12 @@ # Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # SPDX-License-Identifier: GPL-3.0-or-later +from cas import views as cas_views +from django.conf import settings +from django.conf.urls.static import static from django.contrib import admin from django.urls import path, include from django.views.generic import RedirectView -from django.conf.urls.static import static -from django.conf import settings - -from cas import views as cas_views urlpatterns = [ # Dev so redirect to something random @@ -36,5 +35,5 @@ urlpatterns = [ path('logs/', include('logs.urls')), ] -urlpatterns += static(settings.MEDIA_URL,document_root=settings.MEDIA_ROOT) -urlpatterns += static(settings.STATIC_URL,document_root=settings.STATIC_ROOT) +urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) +urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) diff --git a/templates/cas_server/samlValidate.xml b/templates/cas_server/samlValidate.xml index d61bed11..3b130fd2 100644 --- a/templates/cas_server/samlValidate.xml +++ b/templates/cas_server/samlValidate.xml @@ -1,11 +1,11 @@ - + diff --git a/templates/cas_server/samlValidateError.xml b/templates/cas_server/samlValidateError.xml index b1b4226f..c72daba1 100644 --- a/templates/cas_server/samlValidateError.xml +++ b/templates/cas_server/samlValidateError.xml @@ -1,11 +1,11 @@ - + {{msg}} From 931e41804d37fb85fa516c29a4d2b14527314751 Mon Sep 17 00:00:00 2001 From: Benjamin Graillot Date: Sat, 7 Mar 2020 23:39:22 +0100 Subject: [PATCH 11/98] Remove psycopg2 from requirements --- requirements.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 244690bc..69e69230 100644 --- a/requirements.txt +++ b/requirements.txt @@ -16,7 +16,6 @@ django-rest-polymorphic==0.1.8 django-reversion==3.0.3 django-tables2==2.1.0 docutils==0.14 -psycopg2==2.8.4 idna==2.8 oauthlib==3.1.0 Pillow==6.1.0 From f17104770bce0497d336f68ab4e2937382064d05 Mon Sep 17 00:00:00 2001 From: Maxime Bombar Date: Sat, 7 Mar 2020 23:55:35 +0100 Subject: [PATCH 12/98] Delete comby.xyz from ALLOWED_HOSTS --- note_kfet/settings/production.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/note_kfet/settings/production.py b/note_kfet/settings/production.py index c595ee1f..4512dc85 100644 --- a/note_kfet/settings/production.py +++ b/note_kfet/settings/production.py @@ -26,7 +26,7 @@ DATABASES = { DEBUG = True # Mandatory ! -ALLOWED_HOSTS = ['127.0.0.1', 'note.comby.xyz'] +ALLOWED_HOSTS = [] # Emails EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' From aaa958d14639bd9d8681100ecc712613bd7fd184 Mon Sep 17 00:00:00 2001 From: Maxime Bombar Date: Sat, 7 Mar 2020 18:24:33 -0500 Subject: [PATCH 13/98] Import used modules ... --- note_kfet/settings/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/note_kfet/settings/__init__.py b/note_kfet/settings/__init__.py index 02abcd6e..a2e28372 100644 --- a/note_kfet/settings/__init__.py +++ b/note_kfet/settings/__init__.py @@ -1,3 +1,4 @@ +import re from .base import * From c7ba0e470efc412246bb764d0a0d35c354232d75 Mon Sep 17 00:00:00 2001 From: Benjamin Graillot Date: Sun, 8 Mar 2020 22:42:22 +0100 Subject: [PATCH 14/98] Split requirements into files --- Dockerfile | 5 ++++- README.md | 2 +- note_kfet/settings/base.py | 1 - requirements/api.txt | 3 +++ requirements.txt => requirements/base.txt | 6 ------ requirements/cas.txt | 2 ++ requirements/production.txt | 1 + tox.ini | 10 ++++++++-- 8 files changed, 19 insertions(+), 11 deletions(-) create mode 100644 requirements/api.txt rename requirements.txt => requirements/base.txt (72%) create mode 100644 requirements/cas.txt create mode 100644 requirements/production.txt diff --git a/Dockerfile b/Dockerfile index 2c840829..a2f45b00 100644 --- a/Dockerfile +++ b/Dockerfile @@ -10,7 +10,10 @@ RUN apt update && \ rm -rf /var/lib/apt/lists/* COPY requirements.txt /code/ -RUN pip install -r requirements.txt +RUN pip install -r requirements/base.txt +RUN pip install -r requirements/api.txt +RUN pip install -r requirements/cas.txt +RUN pip install -r requirements/production.txt COPY . /code/ diff --git a/README.md b/README.md index 5ae8a396..123f09b8 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ On supposera pour la suite que vous utiliser debian/ubuntu sur un serveur tout n $ python3 -m venv env $ source env/bin/activate - (env)$ pip3 install -r requirements.txt + (env)$ pip3 install -r requirements/base.txt (env)$ deactivate 4. uwsgi et Nginx diff --git a/note_kfet/settings/base.py b/note_kfet/settings/base.py index 103e368d..fead0e44 100644 --- a/note_kfet/settings/base.py +++ b/note_kfet/settings/base.py @@ -37,7 +37,6 @@ INSTALLED_APPS = [ # External apps 'polymorphic', - 'reversion', 'crispy_forms', 'django_tables2', # Django contrib diff --git a/requirements/api.txt b/requirements/api.txt new file mode 100644 index 00000000..8dd9f5f2 --- /dev/null +++ b/requirements/api.txt @@ -0,0 +1,3 @@ +djangorestframework==3.9.0 +django-rest-polymorphic==0.1.8 + diff --git a/requirements.txt b/requirements/base.txt similarity index 72% rename from requirements.txt rename to requirements/base.txt index 69e69230..e9dc7635 100644 --- a/requirements.txt +++ b/requirements/base.txt @@ -4,16 +4,10 @@ defusedxml==0.6.0 Django~=2.2 django-allauth==0.39.1 django-autocomplete-light==3.5.1 -django-cas-client==1.5.3 -django-cas-server==1.1.0 django-crispy-forms==1.7.2 django-extensions==2.1.9 django-filter==2.2.0 -django-guardian==2.1.0 django-polymorphic==2.0.3 -djangorestframework==3.9.0 -django-rest-polymorphic==0.1.8 -django-reversion==3.0.3 django-tables2==2.1.0 docutils==0.14 idna==2.8 diff --git a/requirements/cas.txt b/requirements/cas.txt new file mode 100644 index 00000000..d468d2d5 --- /dev/null +++ b/requirements/cas.txt @@ -0,0 +1,2 @@ +django-cas-client==1.5.3 +django-cas-server==1.1.0 diff --git a/requirements/production.txt b/requirements/production.txt new file mode 100644 index 00000000..f0b52228 --- /dev/null +++ b/requirements/production.txt @@ -0,0 +1 @@ +psycopg2==2.8.4 diff --git a/tox.ini b/tox.ini index c4e88c78..7c432d55 100644 --- a/tox.ini +++ b/tox.ini @@ -9,7 +9,10 @@ skipsdist = True setenv = PYTHONWARNINGS = all deps = - -r{toxinidir}/requirements.txt + -r{toxinidir}/requirements/base.txt + -r{toxinidir}/requirements/api.txt + -r{toxinidir}/requirements/cas.txt + -r{toxinidir}/requirements/production.txt coverage commands = ./manage.py makemigrations @@ -18,7 +21,10 @@ commands = [testenv:linters] deps = - -r{toxinidir}/requirements.txt + -r{toxinidir}/requirements/base.txt + -r{toxinidir}/requirements/api.txt + -r{toxinidir}/requirements/cas.txt + -r{toxinidir}/requirements/production.txt flake8 flake8-colors flake8-import-order From 30fb311b2ead289fb27f7880c9d228bfa400c7b4 Mon Sep 17 00:00:00 2001 From: Pierre-antoine Comby Date: Sun, 8 Mar 2020 23:03:35 +0100 Subject: [PATCH 15/98] modular settings start --- note_kfet/settings/__init__.py | 34 +++++++++++++++++++++--- note_kfet/settings/base.py | 28 -------------------- note_kfet/settings/secrets_example.py | 9 +++++++ note_kfet/urls.py | 38 ++++++++++++++++++--------- 4 files changed, 66 insertions(+), 43 deletions(-) create mode 100644 note_kfet/settings/secrets_example.py diff --git a/note_kfet/settings/__init__.py b/note_kfet/settings/__init__.py index a2e28372..6d871599 100644 --- a/note_kfet/settings/__init__.py +++ b/note_kfet/settings/__init__.py @@ -33,14 +33,42 @@ if app_stage == 'prod': DATABASES["default"]["PASSWORD"] = os.environ.get('DJANGO_DB_PASSWORD', 'CHANGE_ME_IN_ENV_SETTINGS') SECRET_KEY = os.environ.get('DJANGO_SECRET_KEY', 'CHANGE_ME_IN_ENV_SETTINGS') - ALLOWED_HOSTS.append(os.environ.get('ALLOWED_HOSTS', 'localhost')) + ALLOWED_HOSTS = [os.environ.get('ALLOWED_HOSTS', 'localhost')] else: from .development import * try: + #in secrets.py defines everything you want from .secrets import * except ImportError: pass -# env variables set at the of in /env/bin/activate -# don't forget to unset in deactivate ! +if "cas" in INSTALLED_APPS: + MIDDLEWARE += ['cas.middleware.CASMiddleware'] + # CAS Settings + CAS_AUTO_CREATE_USER = False + CAS_LOGO_URL = "/static/img/Saperlistpopette.png" + CAS_FAVICON_URL = "/static/favicon/favicon-32x32.png" + CAS_SHOW_SERVICE_MESSAGES = True + CAS_SHOW_POWERED = False + CAS_REDIRECT_TO_LOGIN_AFTER_LOGOUT = False + CAS_INFO_MESSAGES = { + "cas_explained": { + "message": _( + u"The Central Authentication Service grants you access to most of our websites by " + u"authenticating only once, so you don't need to type your credentials again unless " + u"your session expires or you logout." + ), + "discardable": True, + "type": "info", # one of info, success, info, warning, danger + }, + } + + CAS_INFO_MESSAGES_ORDER = [ + 'cas_explained', + ] + AUTHENTICATION_BACKENDS += ('cas.backends.CASBackend',) + +if "debug_toolbar" in INSTALLED_APPS: + MIDDLEWARE.insert(1,"debug_toolbar.middleware.DebugToolbarMiddleware") + INTERNAL_IPS = [ '127.0.0.1'] diff --git a/note_kfet/settings/base.py b/note_kfet/settings/base.py index 103e368d..f339699c 100644 --- a/note_kfet/settings/base.py +++ b/note_kfet/settings/base.py @@ -55,9 +55,6 @@ INSTALLED_APPS = [ # Autocomplete 'dal', 'dal_select2', - # CAS - 'cas_server', - 'cas', # Note apps 'activity', @@ -80,7 +77,6 @@ MIDDLEWARE = [ 'django.middleware.locale.LocaleMiddleware', 'django.contrib.sites.middleware.CurrentSiteMiddleware', 'note_kfet.middlewares.TurbolinksMiddleware', - 'cas.middleware.CASMiddleware', ] ROOT_URLCONF = 'note_kfet.urls' @@ -134,7 +130,6 @@ PASSWORD_HASHERS = [ AUTHENTICATION_BACKENDS = ( 'django.contrib.auth.backends.ModelBackend', # this is default 'guardian.backends.ObjectPermissionBackend', - 'cas.backends.CASBackend', ) REST_FRAMEWORK = { @@ -201,26 +196,3 @@ MEDIA_URL = '/media/' # Profile Picture Settings PIC_WIDTH = 200 PIC_RATIO = 1 - -# CAS Settings -CAS_AUTO_CREATE_USER = False -CAS_LOGO_URL = "/static/img/Saperlistpopette.png" -CAS_FAVICON_URL = "/static/favicon/favicon-32x32.png" -CAS_SHOW_SERVICE_MESSAGES = True -CAS_SHOW_POWERED = False -CAS_REDIRECT_TO_LOGIN_AFTER_LOGOUT = False -CAS_INFO_MESSAGES = { - "cas_explained": { - "message": _( - u"The Central Authentication Service grants you access to most of our websites by " - u"authenticating only once, so you don't need to type your credentials again unless " - u"your session expires or you logout." - ), - "discardable": True, - "type": "info", # one of info, success, info, warning, danger - }, -} - -CAS_INFO_MESSAGES_ORDER = [ - 'cas_explained', -] diff --git a/note_kfet/settings/secrets_example.py b/note_kfet/settings/secrets_example.py new file mode 100644 index 00000000..70d17ad4 --- /dev/null +++ b/note_kfet/settings/secrets_example.py @@ -0,0 +1,9 @@ +# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay +# SPDX-License-Identifier: GPL-3.0-or-later + +# CAS +OPTIONAL_APPS = [ +# 'cas_server', +# 'cas', +# 'debug_toolbar' +] diff --git a/note_kfet/urls.py b/note_kfet/urls.py index 56251955..b4f4ed5c 100644 --- a/note_kfet/urls.py +++ b/note_kfet/urls.py @@ -1,7 +1,6 @@ # Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # SPDX-License-Identifier: GPL-3.0-or-later -from cas import views as cas_views from django.conf import settings from django.conf.urls.static import static from django.contrib import admin @@ -15,25 +14,40 @@ urlpatterns = [ # Include project routers path('note/', include('note.urls')), - # Include CAS Client routers - path('accounts/login/', cas_views.login, name='login'), - path('accounts/logout/', cas_views.logout, name='logout'), - # Include Django Contrib and Core routers path('i18n/', include('django.conf.urls.i18n')), path('accounts/', include('member.urls')), path('accounts/', include('django.contrib.auth.urls')), path('admin/doc/', include('django.contrib.admindocs.urls')), path('admin/', admin.site.urls), - - # Include CAS Server routers - path('cas/', include('cas_server.urls', namespace="cas_server")), - - # Include Django REST API - path('api/', include('api.urls')), - path('logs/', include('logs.urls')), ] urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) + + +if "cas_server" in settings.INSTALLED_APPS: + urlpatterns += [ + # Include CAS Server routers + path('cas/', include('cas_server.urls', namespace="cas_server")), + ] +if "cas" in settings.INSTALLED_APPS: + from cas import views as cas_views + urlpatterns += [ + # Include CAS Client routers + path('accounts/login/', cas_views.login, name='login'), + path('accounts/logout/', cas_views.logout, name='logout'), + + ] +if "debug_toolbar" in settings.INSTALLED_APPS: + import debug_toolbar + urlpatterns = [ + path('__debug__/', include(debug_toolbar.urls)), + ] + urlpatterns + +if "api" in settings.INSTALLED_APPS: + # Include Django REST API + urlpatterns += [ + path('api/', include('api.urls')), + ] From b7fc598837301710fee4aed9fc71379aabfb5c8e Mon Sep 17 00:00:00 2001 From: Maxime Bombar Date: Sun, 8 Mar 2020 23:17:55 +0100 Subject: [PATCH 16/98] OTL --- apps/logs/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/logs/models.py b/apps/logs/models.py index 1018ce72..9ab3cf6a 100644 --- a/apps/logs/models.py +++ b/apps/logs/models.py @@ -10,7 +10,7 @@ from django.utils.translation import gettext_lazy as _ class Changelog(models.Model): """ - Store each modification on the database (except sessions and logging), + Store each modification in the database (except sessions and logging), including creating, editing and deleting models. """ From 7d616eb1c93146c04966e382623f3cb3a810004e Mon Sep 17 00:00:00 2001 From: Pierre-antoine Comby Date: Mon, 9 Mar 2020 11:48:39 +0100 Subject: [PATCH 17/98] api should stay mandatory --- note_kfet/urls.py | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/note_kfet/urls.py b/note_kfet/urls.py index b4f4ed5c..896c0655 100644 --- a/note_kfet/urls.py +++ b/note_kfet/urls.py @@ -21,6 +21,7 @@ urlpatterns = [ path('admin/doc/', include('django.contrib.admindocs.urls')), path('admin/', admin.site.urls), path('logs/', include('logs.urls')), + path('api/', include('api.urls')), ] urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) @@ -45,9 +46,3 @@ if "debug_toolbar" in settings.INSTALLED_APPS: urlpatterns = [ path('__debug__/', include(debug_toolbar.urls)), ] + urlpatterns - -if "api" in settings.INSTALLED_APPS: - # Include Django REST API - urlpatterns += [ - path('api/', include('api.urls')), - ] From 79b9131049b24e40706c6cbee0fe10d064021803 Mon Sep 17 00:00:00 2001 From: Benjamin Graillot Date: Mon, 9 Mar 2020 11:51:20 +0100 Subject: [PATCH 18/98] [note] Fix template for TemplateTransaction in Conso form --- apps/note/forms.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/note/forms.py b/apps/note/forms.py index 07e44206..20804412 100644 --- a/apps/note/forms.py +++ b/apps/note/forms.py @@ -108,7 +108,7 @@ class ConsoForm(forms.ModelForm): self.instance.destination = button.destination self.instance.amount = button.amount self.instance.reason = '{} ({})'.format(button.name, button.category) - self.instance.name = button.name + self.instance.template = button self.instance.category = button.category super().save(commit) From 3990009400527f68601e76a7e0e59715cce58dfa Mon Sep 17 00:00:00 2001 From: Pierre-antoine Comby Date: Mon, 9 Mar 2020 18:06:51 +0100 Subject: [PATCH 19/98] remove django guardian settings --- note_kfet/settings/base.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/note_kfet/settings/base.py b/note_kfet/settings/base.py index a1dbb929..4fe12fbf 100644 --- a/note_kfet/settings/base.py +++ b/note_kfet/settings/base.py @@ -128,7 +128,6 @@ PASSWORD_HASHERS = [ AUTHENTICATION_BACKENDS = ( 'django.contrib.auth.backends.ModelBackend', # this is default - 'guardian.backends.ObjectPermissionBackend', ) REST_FRAMEWORK = { @@ -143,10 +142,6 @@ REST_FRAMEWORK = { ] } -ANONYMOUS_USER_NAME = None # Disable guardian anonymous user - -GUARDIAN_GET_CONTENT_TYPE = 'polymorphic.contrib.guardian.get_polymorphic_base_content_type' - # Internationalization # https://docs.djangoproject.com/en/2.2/topics/i18n/ From 0de2c18bec385e350fb68bc4d38b515f96c78e3b Mon Sep 17 00:00:00 2001 From: Pierre-antoine Comby Date: Mon, 9 Mar 2020 18:08:37 +0100 Subject: [PATCH 20/98] profile is first created via signal. --- apps/member/views.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/member/views.py b/apps/member/views.py index 88bd2678..21c8de5f 100644 --- a/apps/member/views.py +++ b/apps/member/views.py @@ -49,10 +49,10 @@ class UserCreateView(CreateView): def form_valid(self, form): profile_form = ProfileForm(self.request.POST) if form.is_valid() and profile_form.is_valid(): - user = form.save() - profile = profile_form.save(commit=False) - profile.user = user - profile.save() + user = form.save(commit=False) + user.profile = profile_form.save(commit=False) + user.save() + user.profile.save() return super().form_valid(form) From 08d692c0daf637642d4ae2d6a396ca97433ba21f Mon Sep 17 00:00:00 2001 From: Pierre-antoine Comby Date: Mon, 9 Mar 2020 18:10:24 +0100 Subject: [PATCH 21/98] fix #39 --- apps/note/tables.py | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/note/tables.py b/apps/note/tables.py index 9a2dce45..53fca321 100644 --- a/apps/note/tables.py +++ b/apps/note/tables.py @@ -16,6 +16,7 @@ class HistoryTable(tables.Table): 'table table-condensed table-striped table-hover' } model = Transaction + exclude = ("polymorphic_ctype",) template_name = 'django_tables2/bootstrap4.html' sequence = ('...', 'total', 'valid') From dad1889c8d95f3c86d2eed9b105fc9874ce4754d Mon Sep 17 00:00:00 2001 From: Pierre-antoine Comby Date: Mon, 9 Mar 2020 18:24:31 +0100 Subject: [PATCH 22/98] move cas fixture to own file --- note_kfet/fixtures/cas.json | 11 +++++++++++ note_kfet/fixtures/initial.json | 11 +---------- 2 files changed, 12 insertions(+), 10 deletions(-) create mode 100644 note_kfet/fixtures/cas.json diff --git a/note_kfet/fixtures/cas.json b/note_kfet/fixtures/cas.json new file mode 100644 index 00000000..c3109d19 --- /dev/null +++ b/note_kfet/fixtures/cas.json @@ -0,0 +1,11 @@ +[ + { + "model": "cas_server.servicepattern", + "pk": 1, + "fields": { + "pos": 1, + "pattern": ".*", + "name": "REPLACEME" + } + } +] diff --git a/note_kfet/fixtures/initial.json b/note_kfet/fixtures/initial.json index 1b779980..72e47234 100644 --- a/note_kfet/fixtures/initial.json +++ b/note_kfet/fixtures/initial.json @@ -6,14 +6,5 @@ "domain": "localhost", "name": "La Note Kfet \ud83c\udf7b" } - }, - { - "model": "cas_server.servicepattern", - "pk": 1, - "fields": { - "pos": 1, - "pattern": ".*", - "name": "REPLACEME" - } } -] \ No newline at end of file +] From e1063fcaa2c89c0a1ab5833c1155c4975d0be8a4 Mon Sep 17 00:00:00 2001 From: Pierre-antoine Comby Date: Mon, 9 Mar 2020 18:35:11 +0100 Subject: [PATCH 23/98] translation in navbar and transfer tab --- templates/base.html | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/templates/base.html b/templates/base.html index 6814bedf..887bc970 100644 --- a/templates/base.html +++ b/templates/base.html @@ -67,16 +67,19 @@ SPDX-License-Identifier: GPL-3.0-or-later