From 5e79ddf78aa6134bb5f3d7b608e70246ee8c64e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexis=20M=C3=A9taireau?= Date: Sun, 17 Dec 2023 03:28:56 +0100 Subject: [PATCH 1/9] chore: run ruff to format the code --- la_chariotte/order/migrations/0001_initial.py | 47 +++++++++++++----- .../migrations/0002_grouped_order_name.py | 7 ++- la_chariotte/order/migrations/0003_item.py | 25 +++++++--- .../order/migrations/0004_item_ordered_nb.py | 7 ++- ...d_nb_alter_order_grouped_order_and_more.py | 49 ++++++++++++++----- .../order/migrations/0006_item_ordered_nb.py | 7 ++- ...rdereditem_item_alter_ordereditem_order.py | 23 ++++++--- .../migrations/0008_grouped_order_deadline.py | 14 ++++-- ...rename_date_grouped_order_delivery_date.py | 9 ++-- .../migrations/0025_groupedorder_code.py | 18 ++++--- 10 files changed, 140 insertions(+), 66 deletions(-) diff --git a/la_chariotte/order/migrations/0001_initial.py b/la_chariotte/order/migrations/0001_initial.py index d72f72e..22987db 100644 --- a/la_chariotte/order/migrations/0001_initial.py +++ b/la_chariotte/order/migrations/0001_initial.py @@ -5,27 +5,52 @@ import django.db.models.deletion class Migration(migrations.Migration): - initial = True - dependencies = [ - ] + dependencies = [] operations = [ migrations.CreateModel( - name='Grouped_order', + name="Grouped_order", fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('orga', models.CharField(max_length=100)), - ('date', models.DateField(verbose_name='Date de livraison')), + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("orga", models.CharField(max_length=100)), + ("date", models.DateField(verbose_name="Date de livraison")), ], ), migrations.CreateModel( - name='Order', + name="Order", fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('author', models.CharField(max_length=100, verbose_name='Personne qui passe la commande')), - ('grouped_order', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='order.grouped_order')), + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "author", + models.CharField( + max_length=100, verbose_name="Personne qui passe la commande" + ), + ), + ( + "grouped_order", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + to="order.grouped_order", + ), + ), ], ), ] diff --git a/la_chariotte/order/migrations/0002_grouped_order_name.py b/la_chariotte/order/migrations/0002_grouped_order_name.py index 87ff618..88752fa 100644 --- a/la_chariotte/order/migrations/0002_grouped_order_name.py +++ b/la_chariotte/order/migrations/0002_grouped_order_name.py @@ -4,15 +4,14 @@ from django.db import migrations, models class Migration(migrations.Migration): - dependencies = [ - ('order', '0001_initial'), + ("order", "0001_initial"), ] operations = [ migrations.AddField( - model_name='grouped_order', - name='name', + model_name="grouped_order", + name="name", field=models.CharField(max_length=100, null=True), ), ] diff --git a/la_chariotte/order/migrations/0003_item.py b/la_chariotte/order/migrations/0003_item.py index 3de7cad..1b1eaea 100644 --- a/la_chariotte/order/migrations/0003_item.py +++ b/la_chariotte/order/migrations/0003_item.py @@ -5,18 +5,31 @@ import django.db.models.deletion class Migration(migrations.Migration): - dependencies = [ - ('order', '0002_grouped_order_name'), + ("order", "0002_grouped_order_name"), ] operations = [ migrations.CreateModel( - name='Item', + name="Item", fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=100)), - ('grouped_order', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='order.grouped_order')), + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("name", models.CharField(max_length=100)), + ( + "grouped_order", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + to="order.grouped_order", + ), + ), ], ), ] diff --git a/la_chariotte/order/migrations/0004_item_ordered_nb.py b/la_chariotte/order/migrations/0004_item_ordered_nb.py index 382f464..36d7f8c 100644 --- a/la_chariotte/order/migrations/0004_item_ordered_nb.py +++ b/la_chariotte/order/migrations/0004_item_ordered_nb.py @@ -4,15 +4,14 @@ from django.db import migrations, models class Migration(migrations.Migration): - dependencies = [ - ('order', '0003_item'), + ("order", "0003_item"), ] operations = [ migrations.AddField( - model_name='item', - name='ordered_nb', + model_name="item", + name="ordered_nb", field=models.IntegerField(default=0), ), ] diff --git a/la_chariotte/order/migrations/0005_remove_item_ordered_nb_alter_order_grouped_order_and_more.py b/la_chariotte/order/migrations/0005_remove_item_ordered_nb_alter_order_grouped_order_and_more.py index 70d001d..6ee6d0d 100644 --- a/la_chariotte/order/migrations/0005_remove_item_ordered_nb_alter_order_grouped_order_and_more.py +++ b/la_chariotte/order/migrations/0005_remove_item_ordered_nb_alter_order_grouped_order_and_more.py @@ -5,28 +5,53 @@ import django.db.models.deletion class Migration(migrations.Migration): - dependencies = [ - ('order', '0004_item_ordered_nb'), + ("order", "0004_item_ordered_nb"), ] operations = [ migrations.RemoveField( - model_name='item', - name='ordered_nb', + model_name="item", + name="ordered_nb", ), migrations.AlterField( - model_name='order', - name='grouped_order', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='order_set', to='order.grouped_order'), + model_name="order", + name="grouped_order", + field=models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="order_set", + to="order.grouped_order", + ), ), migrations.CreateModel( - name='OrderedItem', + name="OrderedItem", fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('nb', models.PositiveSmallIntegerField(default=0)), - ('item', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='ordered_items', to='order.item')), - ('order', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='orders', to='order.order')), + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("nb", models.PositiveSmallIntegerField(default=0)), + ( + "item", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="ordered_items", + to="order.item", + ), + ), + ( + "order", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="orders", + to="order.order", + ), + ), ], ), ] diff --git a/la_chariotte/order/migrations/0006_item_ordered_nb.py b/la_chariotte/order/migrations/0006_item_ordered_nb.py index 6989454..50122a4 100644 --- a/la_chariotte/order/migrations/0006_item_ordered_nb.py +++ b/la_chariotte/order/migrations/0006_item_ordered_nb.py @@ -4,15 +4,14 @@ from django.db import migrations, models class Migration(migrations.Migration): - dependencies = [ - ('order', '0005_remove_item_ordered_nb_alter_order_grouped_order_and_more'), + ("order", "0005_remove_item_ordered_nb_alter_order_grouped_order_and_more"), ] operations = [ migrations.AddField( - model_name='item', - name='ordered_nb', + model_name="item", + name="ordered_nb", field=models.IntegerField(default=0), ), ] diff --git a/la_chariotte/order/migrations/0007_alter_ordereditem_item_alter_ordereditem_order.py b/la_chariotte/order/migrations/0007_alter_ordereditem_item_alter_ordereditem_order.py index 4af4531..179c8e5 100644 --- a/la_chariotte/order/migrations/0007_alter_ordereditem_item_alter_ordereditem_order.py +++ b/la_chariotte/order/migrations/0007_alter_ordereditem_item_alter_ordereditem_order.py @@ -5,20 +5,27 @@ import django.db.models.deletion class Migration(migrations.Migration): - dependencies = [ - ('order', '0006_item_ordered_nb'), + ("order", "0006_item_ordered_nb"), ] operations = [ migrations.AlterField( - model_name='ordereditem', - name='item', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='orders', to='order.item'), + model_name="ordereditem", + name="item", + field=models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="orders", + to="order.item", + ), ), migrations.AlterField( - model_name='ordereditem', - name='order', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='ordered_items', to='order.order'), + model_name="ordereditem", + name="order", + field=models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="ordered_items", + to="order.order", + ), ), ] diff --git a/la_chariotte/order/migrations/0008_grouped_order_deadline.py b/la_chariotte/order/migrations/0008_grouped_order_deadline.py index ae453d0..6c12a3d 100644 --- a/la_chariotte/order/migrations/0008_grouped_order_deadline.py +++ b/la_chariotte/order/migrations/0008_grouped_order_deadline.py @@ -5,16 +5,20 @@ from django.db import migrations, models class Migration(migrations.Migration): - dependencies = [ - ('order', '0007_alter_ordereditem_item_alter_ordereditem_order'), + ("order", "0007_alter_ordereditem_item_alter_ordereditem_order"), ] operations = [ migrations.AddField( - model_name='grouped_order', - name='deadline', - field=models.DateTimeField(default=datetime.datetime(2023, 3, 23, 14, 38, 17, 365192, tzinfo=datetime.timezone.utc), verbose_name='Date limite de commande'), + model_name="grouped_order", + name="deadline", + field=models.DateTimeField( + default=datetime.datetime( + 2023, 3, 23, 14, 38, 17, 365192, tzinfo=datetime.timezone.utc + ), + verbose_name="Date limite de commande", + ), preserve_default=False, ), ] diff --git a/la_chariotte/order/migrations/0009_rename_date_grouped_order_delivery_date.py b/la_chariotte/order/migrations/0009_rename_date_grouped_order_delivery_date.py index 1998119..708ab53 100644 --- a/la_chariotte/order/migrations/0009_rename_date_grouped_order_delivery_date.py +++ b/la_chariotte/order/migrations/0009_rename_date_grouped_order_delivery_date.py @@ -4,15 +4,14 @@ from django.db import migrations class Migration(migrations.Migration): - dependencies = [ - ('order', '0008_grouped_order_deadline'), + ("order", "0008_grouped_order_deadline"), ] operations = [ migrations.RenameField( - model_name='grouped_order', - old_name='date', - new_name='delivery_date', + model_name="grouped_order", + old_name="date", + new_name="delivery_date", ), ] diff --git a/la_chariotte/order/migrations/0025_groupedorder_code.py b/la_chariotte/order/migrations/0025_groupedorder_code.py index f67a2c4..47cba02 100644 --- a/la_chariotte/order/migrations/0025_groupedorder_code.py +++ b/la_chariotte/order/migrations/0025_groupedorder_code.py @@ -7,30 +7,34 @@ import random def create_code_from_pk(pk): """When a grouped order is created, we compute a unique code that will be used in url path - How we generate this code : + How we generate this code : 1. The instance pk, written in base36 (max 5 digits for now - we assume that there will not be more than 60466175 grouped orders) 2. A random int written in base36 (5 digits long) 3. Only the 6 first digits of this string - The use of pk in the beginning of the string guarantees the uniqueness, and the random part makes that we cannot guess the url path. + The use of pk in the beginning of the string guarantees the uniqueness, and the random part makes that we cannot guess the url path. """ base_36_pk = base36.dumps(pk) - random_string = base36.dumps(random.randint(1727605,60466175)) # generates a 5 digits long string + random_string = base36.dumps( + random.randint(1727605, 60466175) + ) # generates a 5 digits long string return f"{base_36_pk}{random_string}" + def set_code_default(apps, schema_editor): """Provides a default code to existing grouped orders during migration""" - GroupedOrder = apps.get_model("order","GroupedOrder") + GroupedOrder = apps.get_model("order", "GroupedOrder") for grouped_order in GroupedOrder.objects.all().iterator(): grouped_order.code = create_code_from_pk(grouped_order.pk) grouped_order.save() + def reverse_set_code_default(apps, schema_editor): """Reverse the set_code default function""" - GroupedOrder = apps.get_model("order","GroupedOrder") + GroupedOrder = apps.get_model("order", "GroupedOrder") for grouped_order in GroupedOrder.objects.all().iterator(): - grouped_order.code = '' + grouped_order.code = "" grouped_order.save() - + class Migration(migrations.Migration): dependencies = [ From 7ff388331adbf088079dca4379997741a8dd4912 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexis=20M=C3=A9taireau?= Date: Sun, 17 Dec 2023 03:32:57 +0100 Subject: [PATCH 2/9] chore: cleanup imports --- la_chariotte/mail/test_mail.py | 1 - la_chariotte/mail/utils.py | 1 - la_chariotte/order/forms.py | 6 ------ .../order/tests/test_views/test_views_item.py | 3 --- .../order/tests/test_views/test_views_order.py | 3 --- la_chariotte/order/tests/utils.py | 2 -- la_chariotte/order/urls.py | 1 - la_chariotte/order/views/grouped_order.py | 5 ----- la_chariotte/urls.py | 1 - mails.sqlite | Bin 299008 -> 0 bytes 10 files changed, 23 deletions(-) delete mode 100644 mails.sqlite diff --git a/la_chariotte/mail/test_mail.py b/la_chariotte/mail/test_mail.py index aa7e039..99d4fc8 100644 --- a/la_chariotte/mail/test_mail.py +++ b/la_chariotte/mail/test_mail.py @@ -2,7 +2,6 @@ import pytest from django.urls import reverse from la_chariotte import settings -from la_chariotte.order.models import GroupedOrder pytestmark = pytest.mark.django_db diff --git a/la_chariotte/mail/utils.py b/la_chariotte/mail/utils.py index cb345df..8b91873 100644 --- a/la_chariotte/mail/utils.py +++ b/la_chariotte/mail/utils.py @@ -2,7 +2,6 @@ import html2text from django.conf import settings from django.core import mail from django.template.loader import render_to_string -from django.utils.html import strip_tags def send_order_confirmation_mail(order): diff --git a/la_chariotte/order/forms.py b/la_chariotte/order/forms.py index bd622d6..8e28d5a 100644 --- a/la_chariotte/order/forms.py +++ b/la_chariotte/order/forms.py @@ -1,16 +1,10 @@ import datetime -from typing import Any, Optional, Sequence, Type, Union -import pytz from django import forms from django.contrib.auth import get_user_model -from django.core.exceptions import NON_FIELD_ERRORS, ValidationError -from django.db import IntegrityError from django.forms.utils import to_current_timezone -from django.forms.widgets import Widget from django.utils import timezone -from la_chariotte import settings from la_chariotte.order.models import GroupedOrder, Item diff --git a/la_chariotte/order/tests/test_views/test_views_item.py b/la_chariotte/order/tests/test_views/test_views_item.py index 54cb904..b592fee 100644 --- a/la_chariotte/order/tests/test_views/test_views_item.py +++ b/la_chariotte/order/tests/test_views/test_views_item.py @@ -1,9 +1,6 @@ -import datetime - import pytest from django.contrib import auth from django.urls import reverse -from django.utils import timezone from la_chariotte.order import models from la_chariotte.order.tests.utils import create_grouped_order diff --git a/la_chariotte/order/tests/test_views/test_views_order.py b/la_chariotte/order/tests/test_views/test_views_order.py index 7e4151b..b152084 100644 --- a/la_chariotte/order/tests/test_views/test_views_order.py +++ b/la_chariotte/order/tests/test_views/test_views_order.py @@ -1,9 +1,6 @@ -import datetime - import pytest from django.contrib import auth from django.urls import reverse -from django.utils import timezone from la_chariotte.order import models from la_chariotte.order.tests.utils import ( diff --git a/la_chariotte/order/tests/utils.py b/la_chariotte/order/tests/utils.py index c990f6e..b7cc913 100644 --- a/la_chariotte/order/tests/utils.py +++ b/la_chariotte/order/tests/utils.py @@ -1,8 +1,6 @@ import datetime import pytest -from django.contrib import auth -from django.urls import reverse from django.utils import timezone from la_chariotte.order import models diff --git a/la_chariotte/order/urls.py b/la_chariotte/order/urls.py index 9ca4541..c6226e6 100644 --- a/la_chariotte/order/urls.py +++ b/la_chariotte/order/urls.py @@ -1,5 +1,4 @@ from django.urls import path -from django.views.generic.base import TemplateView from . import views diff --git a/la_chariotte/order/views/grouped_order.py b/la_chariotte/order/views/grouped_order.py index 9200fc4..54ea4fe 100644 --- a/la_chariotte/order/views/grouped_order.py +++ b/la_chariotte/order/views/grouped_order.py @@ -1,20 +1,15 @@ import csv import json -from datetime import timedelta -from io import BytesIO from django import http from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin from django.core.serializers.json import DjangoJSONEncoder from django.shortcuts import get_object_or_404, redirect -from django.template.loader import get_template from django.urls import reverse, reverse_lazy from django.utils import timezone from django.views import generic from django_weasyprint import WeasyTemplateResponseMixin -from django_weasyprint.views import WeasyTemplateResponse, WeasyTemplateView from icalendar import Calendar, Event, vCalAddress, vText -from xhtml2pdf import pisa from ..forms import GroupedOrderForm, Item, JoinGroupedOrderForm from ..models import GroupedOrder, OrderAuthor diff --git a/la_chariotte/urls.py b/la_chariotte/urls.py index cf1a53f..611bcc4 100644 --- a/la_chariotte/urls.py +++ b/la_chariotte/urls.py @@ -19,7 +19,6 @@ from django.contrib.auth.views import ( PasswordResetCompleteView, PasswordResetConfirmView, PasswordResetDoneView, - PasswordResetView, ) from django.urls import include, path from django.views.generic.base import TemplateView diff --git a/mails.sqlite b/mails.sqlite deleted file mode 100644 index a079d5d19778fab9c675e3af8d92f7110b29d3a2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 299008 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%0DEmeDrtR()C2wVsvD2n2P# zzO&AEj*IQc-hLG#=ZHKsPmg7Io7k@3+-c~oO5ae9fW|z{`FV0RxL3@hgqzBcl>0#f zBK8!Ar^i^wAFD04?njIOd5C_3B0raH5Ew;ON`$RmbYUxu+~4{G@$)qLed#A?^gCT_ z^s8&{_M!KO*Nb1wb)j^#lBsP{1kEGTL2@6x5c*R=Z_+PHu>*`L6sL`XRImgwD+u6-%?+kMR$C+J%iIdKvlm#F`J6zYFu>EQX$bDEhK@aL{Y z0aWFC!yo6E{ome0$`z8VvZ_&&Qko%Q(ALvRN>ggNlm>=Cc<^e@$huUliP~Sn3m7Cl zJ(rk$>Kq?J($>qB1b~dP1pgnQon00mcyRv&|BwA!(dvu#CxI4_X4P;8&r5{=|F^Eq z{8FA)j5BW-B#8nH$1y2UfF%w9bQJl`;61A$f}A|VXfw1kG+SI4)s{pkoDR?<4DZ80 zN8{=*C36G}&=9~PK=HSxDjG6bHKT+BAzgty2N1ku>NrsvX3q&vJ*YOFk#0QhRQFwq z85Td`nF>Vu=t;5>0|>)A@&F6}UD;n-b4H|#u{Ek9RpHUv;TUV*m>wX4Gjy&;`{&a3 z-Nf1#QqWJz&N0t z@a)Wi8^ix&=5@J*XH5W@hW{6yRk9`JTB2q%CtI=v0RD8jZ$(d+gpBAvObOepHOYC*YS_?0kO(5`Zpy2OvC>pb85Z>fI0C0vA!$e z|KGj=|IfgK*Vg~4!s7q0{F7U+e-$su&kJjTUwZOWJna7KPY? zJ)cb#0H#gJX)TvY*CZpCc3GD`GSWP`Yc)kh#H%0D)ivY1-fa(BX3A(g?e4NzQ|Z4b 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 !7jm*7L`6C6pgr+=i+)L;+w;f3>`W>bmm2}? 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 Date: Sun, 17 Dec 2023 03:18:20 +0100 Subject: [PATCH 3/9] fix: send reset emails At the moment, the email is stored in the `username` field. Django form-handling looks for the default email field [0] to find the user email. If it doesnet find anything, it fails silently (to avoid leaking information about the users present in the system, which is a good thing) The fix was to change the field used to check for the email. [0] https://github.com/django/django/blob/eea4f92f9aa57d1b25f1c28d11c3b5a6a5841e82/django/contrib/auth/forms.py#L326-L337 --- la_chariotte/accounts/models.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/la_chariotte/accounts/models.py b/la_chariotte/accounts/models.py index fee40a8..a953c3b 100644 --- a/la_chariotte/accounts/models.py +++ b/la_chariotte/accounts/models.py @@ -3,6 +3,8 @@ from django.db import models class CustomUser(AbstractUser): + EMAIL_FIELD = "username" + username = models.EmailField( "Email", unique=True, From 056e0840696c94d1f138899ffa51aa8b40e77aeb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexis=20M=C3=A9taireau?= Date: Thu, 21 Dec 2023 00:14:59 +0100 Subject: [PATCH 4/9] doc: merging rules --- docs/contributing/contributing.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/contributing/contributing.md b/docs/contributing/contributing.md index 6454e09..9108b5c 100644 --- a/docs/contributing/contributing.md +++ b/docs/contributing/contributing.md @@ -60,3 +60,7 @@ build it locally, just run: ```bash mkdocs serve ``` + +## Merging rules + +In order to be merged, your code needs to be reviewed by two maintainers. Don't hesitate to ping us if needed. From 08a9f6e3f61e98b84809a2937aba9c6705257741 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexis=20M=C3=A9taireau?= Date: Thu, 21 Dec 2023 22:25:30 +0100 Subject: [PATCH 5/9] doc: document sentry in deployment docs --- README.md | 2 +- docs/deploy.md | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 9a70a1f..e76a396 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,6 @@ La Chariotte is a web application to handle grouped orders. - [Public server](https://chariotte.fr) - [Online documentation](https://docs.chariotte.fr) -This project has been initially developped and published by [Hashbang](https:// +This project has been initially developed and published by [Hashbang](https:// hashbang.fr/) under an [Affero GPLv3](LICENSE) license, and is now maintained and developed by a team of volunteers. diff --git a/docs/deploy.md b/docs/deploy.md index 7f1723a..3864bde 100644 --- a/docs/deploy.md +++ b/docs/deploy.md @@ -50,6 +50,61 @@ en/latest/), managed by AlwaysData. The production settings are stored in `~/ la_chariotte/prod_settings.py`, and the secrets are defined in the admin console. +Here are the settings, with some comments that might be useful. + +```python title="prod_settings.py" +SECRET_KEY = "YOUR SECRET KEY HERE, used to hash the passwords. CHANGE IT." + +# We're connecting to a psql server, AD manages the access and the backups. +DATABASES = { + "default": { + "ENGINE": "django.db.backends.postgresql", + "NAME": "chariotte_prod", + "USER": "chariotte_prod", + "PASSWORD": "", + "HOST": "host", + } +} + +ALLOWED_HOSTS = ["chariotte.fr",] +DEBUG = False + +# We're sending mails using AD infrastructure +EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' +EMAIL_FROM = 'notification@chariotte.fr' +EMAIL_HOST = 'smtp-chariotte.alwaysdata.net' +EMAIL_PORT = 587 +EMAIL_HOST_USER = 'notification@chariotte.fr' +EMAIL_HOST_PASSWORD = "XXX" +EMAIL_USE_TLS = True + +DEFAULT_FROM_EMAIL = os.getenv( + "DJANGO_DEFAULT_FROM_EMAIL", "La Chariotte " +) + +CONTACT_MAIL = "contact@chariotte.fr" + +# We're collecting the static files on this specific folder. +STATIC_ROOT = "/home/chariotte/static/" +``` + +We're using sentry (sentry.io) to be alerted when an error happens on the server + +```python title="prod_settings.py" +import sentry_sdk + +sentry_sdk.init( + dsn="PUT YOUR DSN HERE", + # Set traces_sample_rate to 1.0 to capture 100% + # of transactions for performance monitoring. + traces_sample_rate=1.0, + # Set profiles_sample_rate to 1.0 to profile 100% + # of sampled transactions. + # We recommend adjusting this value in production. + profiles_sample_rate=1.0, +) +``` + ### The different sites In the AD console, here are the defined sites: From 12e8cd8baa60c6e1494b39131760ea4ff6631d5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexis=20M=C3=A9taireau?= Date: Thu, 21 Dec 2023 23:00:23 +0100 Subject: [PATCH 6/9] doc: fix broken readme link --- README.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index e76a396..185777c 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,5 @@ La Chariotte is a web application to handle grouped orders. - [Public server](https://chariotte.fr) - [Online documentation](https://docs.chariotte.fr) -This project has been initially developed and published by [Hashbang](https:// -hashbang.fr/) under an [Affero GPLv3](LICENSE) license, and is now maintained -and developed by a team of volunteers. +This project has been initially developed and published by [Hashbang](https://hashbang.fr/) +under an [Affero GPLv3](LICENSE) license, and is now maintained and developed by a team of volunteers. From dd1b28cc118cacaf214047e33d7e4bfb622222e3 Mon Sep 17 00:00:00 2001 From: pauline Date: Tue, 2 Jan 2024 20:33:15 +0100 Subject: [PATCH 7/9] merge branch feature/160 --- .../order/templates/order/grouped_order_sheet.html | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/la_chariotte/order/templates/order/grouped_order_sheet.html b/la_chariotte/order/templates/order/grouped_order_sheet.html index 4608f4d..f472f10 100644 --- a/la_chariotte/order/templates/order/grouped_order_sheet.html +++ b/la_chariotte/order/templates/order/grouped_order_sheet.html @@ -83,7 +83,8 @@ {% if items %} - + + {% for item in items %} {% endfor %} - + {% for item in items %} {% endfor %} - + {% for item in items %} {% endfor %} - {% for order, ordered_items in orders_dict.items %} + @@ -130,7 +131,6 @@ - {% endfor %} From 8f50039667227a059c4d694d4cc7776e8582da1c Mon Sep 17 00:00:00 2001 From: pauline Date: Thu, 21 Dec 2023 21:56:34 +0100 Subject: [PATCH 8/9] add links doc and gitlab in footer --- la_chariotte/templates/base.html | 3 +++ 1 file changed, 3 insertions(+) diff --git a/la_chariotte/templates/base.html b/la_chariotte/templates/base.html index f2bca14..f30b58a 100644 --- a/la_chariotte/templates/base.html +++ b/la_chariotte/templates/base.html @@ -126,6 +126,9 @@

Mentions légales

+

+ Code source et documentation +

From 0576d93a6be3dd89020d2a99506fe2136b27d347 Mon Sep 17 00:00:00 2001 From: pauline Date: Thu, 21 Dec 2023 22:04:35 +0100 Subject: [PATCH 9/9] correct mistake of link --- la_chariotte/templates/base.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/la_chariotte/templates/base.html b/la_chariotte/templates/base.html index f30b58a..7dde997 100644 --- a/la_chariotte/templates/base.html +++ b/la_chariotte/templates/base.html @@ -127,7 +127,7 @@ Mentions légales

- Code source et documentation + Code source et documentation

OK Nom @@ -91,11 +92,11 @@ PrixOK
Prix unitaire @@ -103,9 +104,9 @@
TOTAL @@ -113,10 +114,10 @@ {{ grouped_order.total_price }} €
{{ order.author.last_name|upper }} {{ order.author.first_name }} {{ order.price }} €