From 41bff53853e524fc37e0f395d460da3c61391ef1 Mon Sep 17 00:00:00 2001 From: imperosol Date: Tue, 24 Dec 2024 15:40:58 +0100 Subject: [PATCH 1/3] use `.env` for project configuration --- .env.example | 83 ++++++++++++++++ .github/workflows/ci.yml | 4 + .gitignore | 1 + docs/howto/prod.md | 4 +- docs/tutorial/install-advanced.md | 57 +++-------- docs/tutorial/install.md | 66 ++++++++++--- docs/tutorial/structure.md | 42 ++++---- pyproject.toml | 3 +- sith/settings.py | 153 +++++++++++++++++------------- sith/urls.py | 2 +- uv.lock | 82 +++++++++++++++- 11 files changed, 341 insertions(+), 156 deletions(-) create mode 100644 .env.example diff --git a/.env.example b/.env.example new file mode 100644 index 00000000..266af2a1 --- /dev/null +++ b/.env.example @@ -0,0 +1,83 @@ +HTTPS=off +DEBUG=true + +# This is not the real key used in prod +SECRET_KEY=(4sjxvhz@m5$0a$j0_pqicnc$s!vbve)z+&++m%g%bjhlz4+g2 + +DATABASE_URL=sqlite:///db.sqlite3 +# uncomment the next line if you want to use a postgres database +#DATABASE_URL=postgres://user:password@127.0.0.1:5432/sith +CACHE_URL=redis://127.0.0.1:6379/0 + +MEDIA_ROOT=data +STATIC_ROOT=static + +DEFAULT_FROM_EMAIL=bibou@git.an +SITH_COM_EMAIL=bibou_com@git.an + +HONEYPOT_VALUE=content +HONEYPOT_FIELD_NAME=body2 +HONEYPOT_FIELD_NAME_FORUM=message2 + +EMAIL_BACKEND=django.core.mail.backends.console.EmailBackend +EMAIL_HOST=localhost +EMAIL_PORT=25 + +SITH_URL=127.0.0.1:8000 +SITH_NAME="AE UTBM" + +SITH_MAIN_CLUB_ID=1 + +SITH_GROUP_ROOT_ID=1 +SITH_GROUP_PUBLIC_ID=2 +SITH_GROUP_SUBSCRIBERS_ID=3 +SITH_GROUP_OLD_SUBSCRIBERS_ID=4 +SITH_GROUP_ACCOUNTING_ADMIN_ID=5 +SITH_GROUP_COM_ADMIN_ID=6 +SITH_GROUP_COUNTER_ADMIN_ID=7 +SITH_GROUP_SAS_ADMIN_ID=8 +SITH_GROUP_FORUM_ADMIN_ID=9 +SITH_GROUP_PEDAGOGY_ADMIN_ID=10 + +SITH_GROUP_BANNED_ALCOHOL_ID=11 +SITH_GROUP_BANNED_COUNTER_ID=12 +SITH_GROUP_BANNED_SUBSCRIPTION_ID=13 + +SITH_CLUB_REFOUND_ID=89 +SITH_COUNTER_REFOUND_ID=38 +SITH_PRODUCT_REFOUND_ID=5 + +# Counter + +SITH_COUNTER_ACCOUNT_DUMP_ID=39 + +# Defines which product type is the refilling type, and thus increases the account amount +SITH_COUNTER_PRODUCTTYPE_REFILLING=3 + +SITH_ECOCUP_CONS=1152 +SITH_ECOCUP_DECO=1151 + +# Defines which product is the one year subscription and which one is the six month subscription +SITH_PRODUCT_SUBSCRIPTION_ONE_SEMESTER=1 +SITH_PRODUCT_SUBSCRIPTION_TWO_SEMESTERS=2 +SITH_PRODUCTTYPE_SUBSCRIPTION=2 + +# Defines which clubs let its members the ability to see users subscription history +SITH_CAN_CREATE_SUBSCRIPTION_HISTORY=1 +SITH_CAN_READ_SUBSCRIPTION_HISTORY=1 + +# SAS variables +SITH_SAS_ROOT_DIR_ID=4 + +# ET variables +SITH_EBOUTIC_CB_ENABLED=true +SITH_EBOUTIC_ET_URL="https://preprod-tpeweb.e-transactions.fr/cgi/MYchoix_pagepaiement.cgi" +SITH_EBOUTIC_PBX_SITE=1999888 +SITH_EBOUTIC_PBX_RANG=32 +SITH_EBOUTIC_PBX_IDENTIFIANT=2 +SITH_EBOUTIC_HMAC_KEY=0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF +SITH_EBOUTIC_PUB_KEY_PATH=sith/et_keys/pubkey.pem + +SITH_MAILING_FETCH_KEY=IloveMails +SENTRY_DSN= +SENTRY_ENV=production \ No newline at end of file diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 57f36d6f..aa17e14c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,6 +7,10 @@ on: branches: [master, taiste] workflow_dispatch: +env: + SECRET_KEY: notTheRealOne + DATABASE_URL: sqlite:///db.sqlite3 + jobs: pre-commit: name: Launch pre-commits checks (ruff) diff --git a/.gitignore b/.gitignore index cf8d7f67..19b65265 100644 --- a/.gitignore +++ b/.gitignore @@ -21,3 +21,4 @@ node_modules/ # compiled documentation site/ +.env diff --git a/docs/howto/prod.md b/docs/howto/prod.md index 769f681f..472f8c3e 100644 --- a/docs/howto/prod.md +++ b/docs/howto/prod.md @@ -2,13 +2,13 @@ Pour connecter l'application à une instance de sentry (ex: https://sentry.io), il est nécessaire de configurer la variable `SENTRY_DSN` -dans le fichier `settings_custom.py`. +dans le fichier `.env`. Cette variable est composée d'un lien complet vers votre projet sentry. ## Récupérer les statiques Nous utilisons du SCSS dans le projet. -En environnement de développement (`DEBUG=True`), +En environnement de développement (`DEBUG=true`), le SCSS est compilé à chaque fois que le fichier est demandé. Pour la production, le projet considère que chacun des fichiers est déjà compilé. diff --git a/docs/tutorial/install-advanced.md b/docs/tutorial/install-advanced.md index 318166ab..357d013c 100644 --- a/docs/tutorial/install-advanced.md +++ b/docs/tutorial/install-advanced.md @@ -47,19 +47,19 @@ Commencez par installer les dépendances système : === "Debian/Ubuntu" ```bash - sudo apt install postgresql redis libq-dev nginx + sudo apt install postgresql libq-dev nginx ``` === "Arch Linux" ```bash - sudo pacman -S postgresql redis nginx + sudo pacman -S postgresql nginx ``` === "macOS" ```bash - brew install postgresql redis lipbq nginx + brew install postgresql lipbq nginx export PATH="/usr/local/opt/libpq/bin:$PATH" source ~/.zshrc ``` @@ -77,34 +77,6 @@ uv sync --group prod C'est parce que ces dépendances compilent certains modules à l'installation. -## Configurer Redis - -Redis est utilisé comme cache. -Assurez-vous qu'il tourne : - -```bash -sudo systemctl redis status -``` - -Et s'il ne tourne pas, démarrez-le : - -```bash -sudo systemctl start redis -sudo systemctl enable redis # si vous voulez que redis démarre automatiquement au boot -``` - -Puis ajoutez le code suivant à la fin de votre fichier -`settings_custom.py` : - -```python -CACHES = { - "default": { - "BACKEND": "django.core.cache.backends.redis.RedisCache", - "LOCATION": "redis://127.0.0.1:6379", - } -} -``` - ## Configurer PostgreSQL PostgreSQL est utilisé comme base de données. @@ -139,26 +111,19 @@ en étant connecté en tant que postgres : psql -d sith -c "GRANT ALL PRIVILEGES ON SCHEMA public to sith"; ``` -Puis ajoutez le code suivant à la fin de votre -`settings_custom.py` : +Puis modifiez votre `.env`. +Dedans, décommentez l'url de la base de données +de postgres et commentez l'url de sqlite : -```python -DATABASES = { - "default": { - "ENGINE": "django.db.backends.postgresql", - "NAME": "sith", - "USER": "sith", - "PASSWORD": "password", - "HOST": "localhost", - "PORT": "", # laissez ce champ vide pour que le choix du port soit automatique - } -} +```dotenv +#DATABASE_URL=sqlite:///db.sqlite3 +DATABASE_URL=postgres://sith:password@localhost:5432/sith ``` Enfin, créez vos données : ```bash -uv run ./manage.py populate +uv run ./manage.py setup ``` !!! note @@ -247,7 +212,7 @@ Puis lancez ou relancez nginx : sudo systemctl restart nginx ``` -Dans votre `settings_custom.py`, remplacez `DEBUG=True` par `DEBUG=False`. +Dans votre `.env`, remplacez `DEBUG=true` par `DEBUG=false`. Enfin, démarrez le serveur Django : diff --git a/docs/tutorial/install.md b/docs/tutorial/install.md index bdd2cfc5..0a621587 100644 --- a/docs/tutorial/install.md +++ b/docs/tutorial/install.md @@ -7,6 +7,7 @@ Certaines dépendances sont nécessaires niveau système : - libjpeg - zlib1g-dev - gettext +- redis ### Installer WSL @@ -65,8 +66,8 @@ cd /mnt//vos/fichiers/comme/dhab ```bash sudo apt install curl build-essential libssl-dev \ - libjpeg-dev zlib1g-dev npm libffi-dev pkg-config \ - gettext git + libjpeg-dev zlib1g-dev npm libffi-dev pkg-config \ + gettext git redis curl -LsSf https://astral.sh/uv/install.sh | sh ``` @@ -75,7 +76,7 @@ cd /mnt//vos/fichiers/comme/dhab ```bash sudo pacman -Syu # on s'assure que les dépôts et le système sont à jour - sudo pacman -S uv gcc git gettext pkgconf npm + sudo pacman -S uv gcc git gettext pkgconf npm redis ``` === "macOS" @@ -84,7 +85,7 @@ cd /mnt//vos/fichiers/comme/dhab Il est également nécessaire d'avoir installé xcode ```bash - brew install git uv npm + brew install git uv npm redis # Pour bien configurer gettext brew link gettext # (suivez bien les instructions supplémentaires affichées) @@ -99,6 +100,15 @@ cd /mnt//vos/fichiers/comme/dhab Python ne fait pas parti des dépendances puisqu'il est automatiquement installé par uv. +Parmi les dépendances installées se trouve redis (que nous utilisons comme cache). +Redis est un service qui doit être activé pour être utilisé. +Pour cela, effectuez les commandes : + +```bash +sudo systemctl start redis +sudo systemctl enable redis # si vous voulez que redis démarre automatiquement au boot +``` + ## Finaliser l'installation Clonez le projet (depuis votre console WSL, si vous utilisez WSL) @@ -120,20 +130,24 @@ uv run ./manage.py install_xapian de texte à l'écran. C'est normal, il ne faut pas avoir peur. -Maintenant que les dépendances sont installées, nous -allons créer la base de données, la remplir avec des données de test, -et compiler les traductions. -Cependant, avant de faire cela, il est nécessaire de modifier -la configuration pour signifier que nous sommes en mode développement. -Pour cela, nous allons créer un fichier `sith/settings_custom.py` -et l'utiliser pour surcharger les settings de base. +Une fois les dépendances installées, il faut encore +mettre en place quelques éléments de configuration, +qui peuvent varier d'un environnement à l'autre. +Ces variables sont stockées dans un fichier `.env`. +Pour le créer, vous pouvez copier le fichier `.env.example` : ```bash -echo "DEBUG=True" > sith/settings_custom.py -echo 'SITH_URL = "localhost:8000"' >> sith/settings_custom.py +cp .env.example .env ``` -Enfin, nous pouvons lancer les commandes suivantes : +Les variables par défaut contenues dans le fichier `.env` +devraient convenir pour le développement, sans modification. + +Maintenant que les dépendances sont installées +et la configuration remplie, nous allons pouvoir générer +des données utiles pendant le développement. + +Pour cela, lancez les commandes suivantes : ```bash # Prépare la base de données @@ -171,6 +185,30 @@ uv run ./manage.py runserver [http://localhost:8000/api/docs](http://localhost:8000/api/docs), une interface swagger, avec toutes les routes de l'API. +!!! question "Pourquoi l'installation est aussi complexe ?" + + Cette question nous a été posée de nombreuses fois par des personnes + essayant d'installer le projet. + Il y a en effet un certain nombre d'étapes à suivre, + de paquets à installer et de commandes à exécuter. + + Le processus d'installation peut donc sembler complexe. + + En réalité, il est difficile de faire plus simple. + En effet, un site web a besoin de beaucoup de composants + pour être développé : il lui faut au minimum + une base de données, un cache, un bundler Javascript + et un interpréteur pour le code du serveur. + Pour nos besoin particuliers, nous utilisons également + un moteur de recherche full-text. + + Nous avons tenté au maximum de limiter le nombre de dépendances + et de sélecionner les plus simples à installer. + Cependant, il est impossible de retirer l'intégralité + de la complexité du processus. + Si vous rencontrez des difficulté lors de l'installation, + n'hésitez pas à demander de l'aide. + ## Générer la documentation La documentation est automatiquement mise en ligne à chaque envoi de code sur GitHub. diff --git a/docs/tutorial/structure.md b/docs/tutorial/structure.md index bc3fed36..aff331d2 100644 --- a/docs/tutorial/structure.md +++ b/docs/tutorial/structure.md @@ -72,12 +72,14 @@ sith/ ├── .gitattributes ├── .gitignore ├── .mailmap -├── manage.py (26) -├── mkdocs.yml (27) +├── .env (26) +├── .env.example (27) +├── manage.py (28) +├── mkdocs.yml (29) ├── uv.lock -├── pyproject.toml (28) -├── .venv/ (29) -├── .python-version (30) +├── pyproject.toml (30) +├── .venv/ (31) +├── .python-version (32) └── README.md ``` @@ -121,15 +123,19 @@ sith/ de manière transparente pour l'utilisateur. 24. Fichier de configuration de coverage. 25. Fichier de configuration de direnv. -26. Fichier généré automatiquement par Django. C'est lui +26. Contient les variables d'environnement, qui sont susceptibles + de varier d'une machine à l'autre. +27. Contient des valeurs par défaut pour le `.env` + pouvant convenir à un environnment de développement local +28. Fichier généré automatiquement par Django. C'est lui qui permet d'appeler des commandes de gestion du projet avec la syntaxe `python ./manage.py ` -27. Le fichier de configuration de la documentation, +29. Le fichier de configuration de la documentation, avec ses plugins et sa table des matières. -28. Le fichier où sont déclarés les dépendances et la configuration +30. Le fichier où sont déclarés les dépendances et la configuration de certaines d'entre elles. -29. Dossier d'environnement virtuel généré par uv -30. Fichier qui contrôle quel version de python utiliser pour le projet +31. Dossier d'environnement virtuel généré par uv +32. Fichier qui contrôle quelle version de python utiliser pour le projet ## L'application principale @@ -144,10 +150,9 @@ Il est organisé comme suit : ``` sith/ ├── settings.py (1) -├── settings_custom.py (2) -├── toolbar_debug.py (3) -├── urls.py (4) -└── wsgi.py (5) +├── toolbar_debug.py (2) +├── urls.py (3) +└── wsgi.py (4) ``` @@ -155,13 +160,10 @@ sith/ Ce fichier contient les paramètres de configuration du projet. Par exemple, il contient la liste des applications installées dans le projet. -2. Configuration maison pour votre environnement. - Toute variable que vous définissez dans ce fichier sera prioritaire - sur la configuration donnée dans `settings.py`. -3. Configuration de la barre de debug. +2. Configuration de la barre de debug. C'est inutilisé en prod, mais c'est très pratique en développement. -4. Fichier de configuration des urls du projet. -5. Fichier de configuration pour le serveur WSGI. +3. Fichier de configuration des urls du projet. +4. Fichier de configuration pour le serveur WSGI. WSGI est un protocole de communication entre le serveur et les applications. Ce fichier ne vous servira sans doute pas sur un environnement diff --git a/pyproject.toml b/pyproject.toml index b3db97cb..a4d16abc 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -44,6 +44,8 @@ dependencies = [ "django-honeypot<2.0.0,>=1.2.1", "pydantic-extra-types<3.0.0,>=2.10.1", "ical<9.0.0,>=8.3.0", + "redis[hiredis]<6.0.0,>=5.2.0", + "environs[django]<15.0.0,>=14.1.0", "requests>=2.32.3", ] @@ -54,7 +56,6 @@ documentation = "https://sith-ae.readthedocs.io/" [dependency-groups] prod = [ "psycopg[c]<4.0.0,>=3.2.3", - "redis[hiredis]<6.0.0,>=5.2.0", ] dev = [ "django-debug-toolbar<5.0.0,>=4.4.6", diff --git a/sith/settings.py b/sith/settings.py index b7d7e71c..a9cab286 100644 --- a/sith/settings.py +++ b/sith/settings.py @@ -34,7 +34,6 @@ https://docs.djangoproject.com/en/1.8/ref/settings/ """ import binascii -import logging import os import sys from datetime import timedelta @@ -43,25 +42,32 @@ from pathlib import Path import sentry_sdk from dateutil.relativedelta import relativedelta from django.utils.translation import gettext_lazy as _ +from environs import Env from sentry_sdk.integrations.django import DjangoIntegration from .honeypot import custom_honeypot_error -BASE_DIR = Path(__file__).parent.parent.resolve() +env = Env() +env.read_env() -os.environ["HTTPS"] = "off" +BASE_DIR = Path(__file__).parent.parent.resolve() # Quick-start development settings - unsuitable for production # See https://docs.djangoproject.com/en/1.8/howto/deployment/checklist/ # SECURITY WARNING: keep the secret key used in production secret! -SECRET_KEY = "(4sjxvhz@m5$0a$j0_pqicnc$s!vbve)z+&++m%g%bjhlz4+g2" +SECRET_KEY = env.str("SECRET_KEY") # SECURITY WARNING: don't run with debug turned on in production! -DEBUG = False +DEBUG = env.bool("DEBUG", default=False) TESTING = "pytest" in sys.modules INTERNAL_IPS = ["127.0.0.1"] +# force csrf tokens and cookies to be secure when in https +CSRF_COOKIE_SECURE = env.bool("HTTPS", default=True) +SESSION_COOKIE_SECURE = env.bool("HTTPS", default=True) +X_FRAME_OPTIONS = "SAMEORIGIN" + ALLOWED_HOSTS = ["*"] # Application definition @@ -208,12 +214,12 @@ WSGI_APPLICATION = "sith.wsgi.application" # Database DATABASES = { - "default": { - "ENGINE": "django.db.backends.sqlite3", - "NAME": BASE_DIR / "db.sqlite3", - }, + "default": env.dj_db_url("DATABASE_URL", conn_max_age=None, conn_health_checks=True) } +if "CACHE_URL" in os.environ: + CACHES = {"default": env.dj_cache_url("CACHE_URL")} + SESSION_ENGINE = "django.contrib.sessions.backends.cached_db" # Logging @@ -265,13 +271,13 @@ PHONENUMBER_DEFAULT_REGION = "FR" # Medias MEDIA_URL = "/data/" -MEDIA_ROOT = BASE_DIR / "data" +MEDIA_ROOT = env.path("MEDIA_ROOT", default=BASE_DIR / "data") # Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/1.8/howto/static-files/ STATIC_URL = "/static/" -STATIC_ROOT = BASE_DIR / "static" +STATIC_ROOT = env.path("STATIC_ROOT", default=BASE_DIR / "static") # Static files finders which allow to see static folder in all apps STATICFILES_FINDERS = [ @@ -295,24 +301,28 @@ AUTHENTICATION_BACKENDS = ["core.auth.backends.SithModelBackend"] LOGIN_URL = "/login/" LOGOUT_URL = "/logout/" LOGIN_REDIRECT_URL = "/" -DEFAULT_FROM_EMAIL = "bibou@git.an" -SITH_COM_EMAIL = "bibou_com@git.an" +DEFAULT_FROM_EMAIL = env.str("DEFAULT_FROM_EMAIL", default="bibou@git.an") +SITH_COM_EMAIL = env.str("SITH_COM_EMAIL", default="bibou_com@git.an") # Those values are to be changed in production to be more effective -HONEYPOT_FIELD_NAME = "body2" -HONEYPOT_VALUE = "content" +HONEYPOT_FIELD_NAME = env.str("HONEYPOT_FIELD_NAME", default="body2") +HONEYPOT_VALUE = env.str("HONEYPOT_VALUE", default="content") HONEYPOT_RESPONDER = custom_honeypot_error # Make honeypot errors less suspicious -HONEYPOT_FIELD_NAME_FORUM = "message2" # Only used on forum +HONEYPOT_FIELD_NAME_FORUM = env.str( + "HONEYPOT_FIELD_NAME_FORUM", default="message2" +) # Only used on forum # Email -EMAIL_BACKEND = "django.core.mail.backends.console.EmailBackend" -EMAIL_HOST = "localhost" -EMAIL_PORT = 25 +EMAIL_BACKEND = env.str( + "EMAIL_BACKEND", default="django.core.mail.backends.dummy.EmailBackend" +) +EMAIL_HOST = env.str("EMAIL_HOST", default="localhost") +EMAIL_PORT = env.int("EMAIL_PORT", default=25) # Below this line, only Sith-specific variables are defined -SITH_URL = "my.url.git.an" -SITH_NAME = "Sith website" +SITH_URL = env.str("SITH_URL", default="127.0.0.1:8000") +SITH_NAME = env.str("SITH_NAME", default="AE UTBM") SITH_TWITTER = "@ae_utbm" # Enable experimental features @@ -321,7 +331,7 @@ SITH_ENABLE_GALAXY = False # AE configuration # TODO: keep only that first setting, with the ID, and do the same for the other clubs -SITH_MAIN_CLUB_ID = 1 +SITH_MAIN_CLUB_ID = env.int("SITH_MAIN_CLUB_ID", default=1) SITH_MAIN_CLUB = { "name": "AE", "unix_name": "ae", @@ -356,26 +366,28 @@ SITH_SCHOOL_START_YEAR = 1999 # id of the Root account SITH_ROOT_USER_ID = 0 -SITH_GROUP_ROOT_ID = 1 -SITH_GROUP_PUBLIC_ID = 2 -SITH_GROUP_SUBSCRIBERS_ID = 3 -SITH_GROUP_OLD_SUBSCRIBERS_ID = 4 -SITH_GROUP_ACCOUNTING_ADMIN_ID = 5 -SITH_GROUP_COM_ADMIN_ID = 6 -SITH_GROUP_COUNTER_ADMIN_ID = 7 -SITH_GROUP_SAS_ADMIN_ID = 8 -SITH_GROUP_FORUM_ADMIN_ID = 9 -SITH_GROUP_PEDAGOGY_ADMIN_ID = 10 +SITH_GROUP_ROOT_ID = env.int("SITH_GROUP_ROOT_ID", default=1) +SITH_GROUP_PUBLIC_ID = env.int("SITH_GROUP_PUBLIC_ID", default=2) +SITH_GROUP_SUBSCRIBERS_ID = env.int("SITH_GROUP_SUBSCRIBERS_ID", default=3) +SITH_GROUP_OLD_SUBSCRIBERS_ID = env.int("SITH_GROUP_OLD_SUBSCRIBERS_ID", default=4) +SITH_GROUP_ACCOUNTING_ADMIN_ID = env.int("SITH_GROUP_ACCOUNTING_ADMIN_ID", default=5) +SITH_GROUP_COM_ADMIN_ID = env.int("SITH_GROUP_COM_ADMIN_ID", default=6) +SITH_GROUP_COUNTER_ADMIN_ID = env.int("SITH_GROUP_COUNTER_ADMIN_ID", default=7) +SITH_GROUP_SAS_ADMIN_ID = env.int("SITH_GROUP_SAS_ADMIN_ID", default=8) +SITH_GROUP_FORUM_ADMIN_ID = env.int("SITH_GROUP_FORUM_ADMIN_ID", default=9) +SITH_GROUP_PEDAGOGY_ADMIN_ID = env.int("SITH_GROUP_PEDAGOGY_ADMIN_ID", default=10) -SITH_GROUP_BANNED_ALCOHOL_ID = 11 -SITH_GROUP_BANNED_COUNTER_ID = 12 -SITH_GROUP_BANNED_SUBSCRIPTION_ID = 13 +SITH_GROUP_BANNED_ALCOHOL_ID = env.int("SITH_GROUP_BANNED_ALCOHOL_ID", default=11) +SITH_GROUP_BANNED_COUNTER_ID = env.int("SITH_GROUP_BANNED_COUNTER_ID", default=12) +SITH_GROUP_BANNED_SUBSCRIPTION_ID = env.int( + "SITH_GROUP_BANNED_SUBSCRIPTION_ID", default=13 +) -SITH_CLUB_REFOUND_ID = 89 -SITH_COUNTER_REFOUND_ID = 38 -SITH_PRODUCT_REFOUND_ID = 5 +SITH_CLUB_REFOUND_ID = env.int("SITH_CLUB_REFOUND_ID", default=89) +SITH_COUNTER_REFOUND_ID = env.int("SITH_COUNTER_REFOUND_ID", default=38) +SITH_PRODUCT_REFOUND_ID = env.int("SITH_PRODUCT_REFOUND_ID", default=5) -SITH_COUNTER_ACCOUNT_DUMP_ID = 39 +SITH_COUNTER_ACCOUNT_DUMP_ID = env.int("SITH_COUNTER_ACCOUNT_DUMP_ID", default=39) # Pages SITH_CORE_PAGE_SYNTAX = "Aide_sur_la_syntaxe" @@ -385,7 +397,7 @@ SITH_CORE_PAGE_SYNTAX = "Aide_sur_la_syntaxe" SITH_FORUM_PAGE_LENGTH = 30 # SAS variables -SITH_SAS_ROOT_DIR_ID = 4 +SITH_SAS_ROOT_DIR_ID = env.int("SITH_SAS_ROOT_DIR_ID", default=4) SITH_SAS_IMAGES_PER_PAGE = 60 SITH_BOARD_SUFFIX = "-bureau" @@ -492,9 +504,9 @@ SITH_LOG_OPERATION_TYPE = [ SITH_PEDAGOGY_UTBM_API = "https://extranet1.utbm.fr/gpedago/api/guide" -SITH_ECOCUP_CONS = 1152 +SITH_ECOCUP_CONS = env.int("SITH_ECOCUP_CONS", default=1151) -SITH_ECOCUP_DECO = 1151 +SITH_ECOCUP_DECO = env.int("SITH_ECOCUP_DECO", default=1152) # The limit is the maximum difference between cons and deco possible for a customer SITH_ECOCUP_LIMIT = 3 @@ -509,13 +521,19 @@ SITH_ACCOUNT_DUMP_DELTA = timedelta(days=30) # Defines which product type is the refilling type, # and thus increases the account amount -SITH_COUNTER_PRODUCTTYPE_REFILLING = 3 +SITH_COUNTER_PRODUCTTYPE_REFILLING = env.int( + "SITH_COUNTER_PRODUCTTYPE_REFILLING", default=3 +) # Defines which product is the one year subscription # and which one is the six month subscription -SITH_PRODUCT_SUBSCRIPTION_ONE_SEMESTER = 1 -SITH_PRODUCT_SUBSCRIPTION_TWO_SEMESTERS = 2 -SITH_PRODUCTTYPE_SUBSCRIPTION = 2 +SITH_PRODUCT_SUBSCRIPTION_ONE_SEMESTER = env.int( + "SITH_PRODUCT_SUBSCRIPTION_ONE_SEMESTER", default=1 +) +SITH_PRODUCT_SUBSCRIPTION_TWO_SEMESTERS = env.int( + "SITH_PRODUCT_SUBSCRIPTION_TWO_SEMESTERS", default=2 +) +SITH_PRODUCTTYPE_SUBSCRIPTION = env.int("SITH_PRODUCTTYPE_SUBSCRIPTION", default=2) # Number of weeks before the end of a subscription when the subscriber can resubscribe SITH_SUBSCRIPTION_END = 10 @@ -624,21 +642,29 @@ SITH_BARMAN_TIMEOUT = 30 SITH_LAST_OPERATIONS_LIMIT = 10 # ET variables -SITH_EBOUTIC_CB_ENABLED = True -SITH_EBOUTIC_ET_URL = ( - "https://preprod-tpeweb.e-transactions.fr/cgi/MYchoix_pagepaiement.cgi" +SITH_EBOUTIC_CB_ENABLED = env.bool("SITH_EBOUTIC_CB_ENABLED", default=True) +SITH_EBOUTIC_ET_URL = env.str( + "SITH_EBOUTIC_ET_URL", + default="https://preprod-tpeweb.e-transactions.fr/cgi/MYchoix_pagepaiement.cgi", ) -SITH_EBOUTIC_PBX_SITE = "1999888" -SITH_EBOUTIC_PBX_RANG = "32" -SITH_EBOUTIC_PBX_IDENTIFIANT = "2" +SITH_EBOUTIC_PBX_SITE = env.str("SITH_EBOUTIC_PBX_SITE", default="1999888") +SITH_EBOUTIC_PBX_RANG = env.str("SITH_EBOUTIC_PBX_RANG", default="32") +SITH_EBOUTIC_PBX_IDENTIFIANT = env.str("SITH_EBOUTIC_PBX_IDENTIFIANT", default="2") SITH_EBOUTIC_HMAC_KEY = binascii.unhexlify( - "0123456789ABCDEF0123456789ABCDEF" - "0123456789ABCDEF0123456789ABCDEF" - "0123456789ABCDEF0123456789ABCDEF" - "0123456789ABCDEF0123456789ABCDEF" + env.str( + "SITH_EBOUTIC_HMAC_KEY", + default=( + "0123456789ABCDEF0123456789ABCDEF" + "0123456789ABCDEF0123456789ABCDEF" + "0123456789ABCDEF0123456789ABCDEF" + "0123456789ABCDEF0123456789ABCDEF" + ), + ) ) SITH_EBOUTIC_PUB_KEY = "" -with open(os.path.join(os.path.dirname(__file__), "et_keys/pubkey.pem")) as f: +with open( + env.path("SITH_EBOUTIC_PUB_KEY_PATH", default=BASE_DIR / "sith/et_keys/pubkey.pem") +) as f: SITH_EBOUTIC_PUB_KEY = f.read() # Launderette variables @@ -680,24 +706,17 @@ SITH_QUICK_NOTIF = { # Mailing related settings SITH_MAILING_DOMAIN = "utbm.fr" -SITH_MAILING_FETCH_KEY = "IloveMails" +SITH_MAILING_FETCH_KEY = env.str("SITH_MAILING_FETCH_KEY", default="ILoveMails") SITH_GIFT_LIST = [("AE Tee-shirt", _("AE tee-shirt"))] -SENTRY_DSN = "" -SENTRY_ENV = "production" +SENTRY_DSN = env.str("SENRY_DSN", default=None) +SENTRY_ENV = env.str("SENTRY_ENV", default="production") TOXIC_DOMAINS_PROVIDERS = [ "https://www.stopforumspam.com/downloads/toxic_domains_whole.txt", ] -try: - from .settings_custom import * # noqa F403 (this star-import is actually useful) - - logging.getLogger("django").info("Custom settings imported") -except ImportError: - logging.getLogger("django").warning("Custom settings failed") - if DEBUG: INSTALLED_APPS += ("debug_toolbar",) MIDDLEWARE = ("debug_toolbar.middleware.DebugToolbarMiddleware", *MIDDLEWARE) diff --git a/sith/urls.py b/sith/urls.py index 95f22662..f6f7c8bb 100644 --- a/sith/urls.py +++ b/sith/urls.py @@ -81,7 +81,7 @@ def sentry_debug(request): The error will be displayed on Sentry inside the "development" environment - NOTE : you need to specify the SENTRY_DSN setting in settings_custom.py + NOTE : you need to specify the SENTRY_DSN setting in .env """ if settings.SENTRY_ENV != "development" or not settings.SENTRY_DSN: raise Http404 diff --git a/uv.lock b/uv.lock index abf0fb98..c76028d9 100644 --- a/uv.lock +++ b/uv.lock @@ -276,6 +276,28 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/91/a1/cf2472db20f7ce4a6be1253a81cfdf85ad9c7885ffbed7047fb72c24cf87/distlib-0.3.9-py2.py3-none-any.whl", hash = "sha256:47f8c22fd27c27e25a65601af709b38e4f0a45ea4fc2e710f65755fa8caaaf87", size = 468973 }, ] +[[package]] +name = "dj-database-url" +version = "2.3.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "django" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/98/9f/fc9905758256af4f68a55da94ab78a13e7775074edfdcaddd757d4921686/dj_database_url-2.3.0.tar.gz", hash = "sha256:ae52e8e634186b57e5a45e445da5dc407a819c2ceed8a53d1fac004cc5288787", size = 10980 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e5/91/641a4e5c8903ed59f6cbcce571003bba9c5d2f731759c31db0ba83bb0bdb/dj_database_url-2.3.0-py3-none-any.whl", hash = "sha256:bb0d414ba0ac5cd62773ec7f86f8cc378a9dbb00a80884c2fc08cc570452521e", size = 7793 }, +] + +[[package]] +name = "dj-email-url" +version = "1.0.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/14/ef/8eb478accd9b0369d46a98d1b43027ee0c254096149265c78e6b2e2fa3b0/dj-email-url-1.0.6.tar.gz", hash = "sha256:55ffe3329e48f54f8a75aa36ece08f365e09d61f8a209773ef09a1d4760e699a", size = 15590 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8a/f9/fcb9745099d821f9a26092d3d6f4df8f10049885045c3a93ff726d2e40a6/dj_email_url-1.0.6-py2.py3-none-any.whl", hash = "sha256:cbd08327fbb08b104eac160fb4703f375532e4c0243eb230f5b960daee7a96db", size = 6296 }, +] + [[package]] name = "django" version = "4.2.17" @@ -290,6 +312,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/5e/85/457360cb3de496382e35db4c2af054066df5c40e26df31400d0109a0500c/Django-4.2.17-py3-none-any.whl", hash = "sha256:3a93350214ba25f178d4045c0786c61573e7dbfa3c509b3551374f1e11ba8de0", size = 7993390 }, ] +[[package]] +name = "django-cache-url" +version = "3.4.5" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/20/28/d420aaa89028d2ec0cf17c1510d06ff6a8ed0bf1abfb7f33c999e1c5befa/django-cache-url-3.4.5.tar.gz", hash = "sha256:eb9fb194717524348c95cad9905b70b647452741c1d9e481fac6d2125f0ad917", size = 7230 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/48/90/01755e4a42558b763f7021e9369aa6aa94c2ede7313deed56cb7483834ab/django_cache_url-3.4.5-py2.py3-none-any.whl", hash = "sha256:5f350759978483ab85dc0e3e17b3d53eed3394a28148f6bf0f53d11d0feb5b3c", size = 4760 }, +] + [[package]] name = "django-countries" version = "7.6.1" @@ -439,6 +470,26 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/93/69/e391bd51bc08ed9141ecd899a0ddb61ab6465309f1eb470905c0c8868081/docutils-0.19-py3-none-any.whl", hash = "sha256:5e1de4d849fee02c63b040a4a3fd567f4ab104defd8a5511fbbc24a8a017efbc", size = 570472 }, ] +[[package]] +name = "environs" +version = "14.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "marshmallow" }, + { name = "python-dotenv" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/3c/8f/952bd034eac79c8b68b6c770cb78c2bdcb3140d31ff224847f3520077d75/environs-14.1.0.tar.gz", hash = "sha256:a5f2afe9d5a21b468e74a3cceacf5d2371fd67dbb9a7e54fe62290c75a09cdfa", size = 30985 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d5/ad/57cfa3e8a006df88e723524127dbab2971a4877c97e7bad070257e15cb6c/environs-14.1.0-py3-none-any.whl", hash = "sha256:a7edda1668ddf1fbfcb7662bdc242dac25648eff2c7fdbaa5d959693afed7a3e", size = 15332 }, +] + +[package.optional-dependencies] +django = [ + { name = "dj-database-url" }, + { name = "dj-email-url" }, + { name = "django-cache-url" }, +] + [[package]] name = "executing" version = "2.1.0" @@ -708,6 +759,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/4f/65/6079a46068dfceaeabb5dcad6d674f5f5c61a6fa5673746f42a9f4c233b3/MarkupSafe-3.0.2-cp313-cp313t-win_amd64.whl", hash = "sha256:e444a31f8db13eb18ada366ab3cf45fd4b31e4db1236a4448f68778c1d1a5a2f", size = 15739 }, ] +[[package]] +name = "marshmallow" +version = "3.25.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "packaging" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/bd/5c/cbfa41491d6c83b36471f2a2f75602349d20a8f88afd94f83c1e68bbc298/marshmallow-3.25.0.tar.gz", hash = "sha256:5ba94a4eb68894ad6761a505eb225daf7e5cb7b4c32af62d4a45e9d42665bc31", size = 176751 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/76/26/b347619b719d4c048e038929769f8f6b28c6d930149b40d950bbdde31d48/marshmallow-3.25.0-py3-none-any.whl", hash = "sha256:50894cd57c6b097a6c6ed2bf216af47d10146990a54db52d03e32edb0448c905", size = 49480 }, +] + [[package]] name = "matplotlib-inline" version = "0.1.7" @@ -1229,6 +1292,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427", size = 229892 }, ] +[[package]] +name = "python-dotenv" +version = "1.0.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/bc/57/e84d88dfe0aec03b7a2d4327012c1627ab5f03652216c63d49846d7a6c58/python-dotenv-1.0.1.tar.gz", hash = "sha256:e324ee90a023d808f1959c46bcbc04446a10ced277783dc6ee09987c37ec10ca", size = 39115 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6a/3e/b68c118422ec867fa7ab88444e1274aa40681c606d59ac27de5a5588f082/python_dotenv-1.0.1-py3-none-any.whl", hash = "sha256:f7b63ef50f1b690dddf550d03497b66d609393b40b564ed0d674909a68ebf16a", size = 19863 }, +] + [[package]] name = "pyyaml" version = "6.0.2" @@ -1428,6 +1500,7 @@ dependencies = [ { name = "django-ordered-model" }, { name = "django-phonenumber-field" }, { name = "django-simple-captcha" }, + { name = "environs", extra = ["django"] }, { name = "ical" }, { name = "jinja2" }, { name = "libsass" }, @@ -1436,6 +1509,7 @@ dependencies = [ { name = "pillow" }, { name = "pydantic-extra-types" }, { name = "python-dateutil" }, + { name = "redis", extra = ["hiredis"] }, { name = "reportlab" }, { name = "requests" }, { name = "sentry-sdk" }, @@ -1463,7 +1537,6 @@ docs = [ ] prod = [ { name = "psycopg", extra = ["c"] }, - { name = "redis", extra = ["hiredis"] }, ] tests = [ { name = "freezegun" }, @@ -1487,6 +1560,7 @@ requires-dist = [ { name = "django-ordered-model", specifier = ">=3.7.4,<4.0.0" }, { name = "django-phonenumber-field", specifier = ">=8.0.0,<9.0.0" }, { name = "django-simple-captcha", specifier = ">=0.6.0,<1.0.0" }, + { name = "environs", extras = ["django"], specifier = ">=14.1.0,<15.0.0" }, { name = "ical", specifier = ">=8.3.0,<9.0.0" }, { name = "jinja2", specifier = ">=3.1.4,<4.0.0" }, { name = "libsass", specifier = ">=0.23.0,<1.0.0" }, @@ -1495,6 +1569,7 @@ requires-dist = [ { name = "pillow", specifier = ">=11.0.0,<12.0.0" }, { name = "pydantic-extra-types", specifier = ">=2.10.1,<3.0.0" }, { name = "python-dateutil", specifier = ">=2.9.0.post0,<3.0.0.0" }, + { name = "redis", extras = ["hiredis"], specifier = ">=5.2.0,<6.0.0" }, { name = "reportlab", specifier = ">=4.2.5,<5.0.0" }, { name = "requests", specifier = ">=2.32.3" }, { name = "sentry-sdk", specifier = ">=2.19.2,<3.0.0" }, @@ -1520,10 +1595,7 @@ docs = [ { name = "mkdocstrings", specifier = ">=0.27.0,<1.0.0" }, { name = "mkdocstrings-python", specifier = ">=1.12.2,<2.0.0" }, ] -prod = [ - { name = "psycopg", extras = ["c"], specifier = ">=3.2.3,<4.0.0" }, - { name = "redis", extras = ["hiredis"], specifier = ">=5.2.0,<6.0.0" }, -] +prod = [{ name = "psycopg", extras = ["c"], specifier = ">=3.2.3,<4.0.0" }] tests = [ { name = "freezegun", specifier = ">=1.5.1,<2.0.0" }, { name = "model-bakery", specifier = ">=1.20.0,<2.0.0" }, From 59e90ec7540dbae12437eff01b5f4a8205017dbb Mon Sep 17 00:00:00 2001 From: imperosol Date: Sat, 25 Jan 2025 23:26:24 +0100 Subject: [PATCH 2/3] add CSRF_TRUSTED_ORIGINS to settings --- .env.example | 3 +++ sith/settings.py | 1 + 2 files changed, 4 insertions(+) diff --git a/.env.example b/.env.example index 266af2a1..0f716d8a 100644 --- a/.env.example +++ b/.env.example @@ -4,6 +4,9 @@ DEBUG=true # This is not the real key used in prod SECRET_KEY=(4sjxvhz@m5$0a$j0_pqicnc$s!vbve)z+&++m%g%bjhlz4+g2 +# comma-separated values +CSRF_TRUSTED_ORIGINS= + DATABASE_URL=sqlite:///db.sqlite3 # uncomment the next line if you want to use a postgres database #DATABASE_URL=postgres://user:password@127.0.0.1:5432/sith diff --git a/sith/settings.py b/sith/settings.py index a9cab286..09d155ee 100644 --- a/sith/settings.py +++ b/sith/settings.py @@ -65,6 +65,7 @@ INTERNAL_IPS = ["127.0.0.1"] # force csrf tokens and cookies to be secure when in https CSRF_COOKIE_SECURE = env.bool("HTTPS", default=True) +CSRF_TRUSTED_ORIGINS = env.list("CSRF_TRUSTED_ORIGINS", default=[]) SESSION_COOKIE_SECURE = env.bool("HTTPS", default=True) X_FRAME_OPTIONS = "SAMEORIGIN" From 9945993f0ba77a2ec7ccb31e06661c554f0f34a0 Mon Sep 17 00:00:00 2001 From: imperosol Date: Sun, 16 Feb 2025 16:54:32 +0100 Subject: [PATCH 3/3] simplify `.env.example` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit La plupart des variables du `.env.example` n'ont pas besoin d'être modifiées régulièrement et ont déjà des valeurs par défaut dans le `settings.py` qui sont adaptées à un environnement local. En gardant uniquement les variables qui seront régulièrement modifiées, on rend le fichier plus compréhensible et plus simple à maintenir. --- .env.example | 81 ++----------------------------- docs/howto/prod.md | 2 +- docs/tutorial/install-advanced.md | 65 ++++++++++++++++++++++++- mkdocs.yml | 1 + sith/settings.py | 4 +- 5 files changed, 70 insertions(+), 83 deletions(-) diff --git a/.env.example b/.env.example index 0f716d8a..5c4c0d97 100644 --- a/.env.example +++ b/.env.example @@ -1,86 +1,11 @@ HTTPS=off -DEBUG=true +SITH_DEBUG=true # This is not the real key used in prod SECRET_KEY=(4sjxvhz@m5$0a$j0_pqicnc$s!vbve)z+&++m%g%bjhlz4+g2 -# comma-separated values -CSRF_TRUSTED_ORIGINS= - +# comment the sqlite line and uncomment the postgres one to switch the dbms DATABASE_URL=sqlite:///db.sqlite3 -# uncomment the next line if you want to use a postgres database #DATABASE_URL=postgres://user:password@127.0.0.1:5432/sith + CACHE_URL=redis://127.0.0.1:6379/0 - -MEDIA_ROOT=data -STATIC_ROOT=static - -DEFAULT_FROM_EMAIL=bibou@git.an -SITH_COM_EMAIL=bibou_com@git.an - -HONEYPOT_VALUE=content -HONEYPOT_FIELD_NAME=body2 -HONEYPOT_FIELD_NAME_FORUM=message2 - -EMAIL_BACKEND=django.core.mail.backends.console.EmailBackend -EMAIL_HOST=localhost -EMAIL_PORT=25 - -SITH_URL=127.0.0.1:8000 -SITH_NAME="AE UTBM" - -SITH_MAIN_CLUB_ID=1 - -SITH_GROUP_ROOT_ID=1 -SITH_GROUP_PUBLIC_ID=2 -SITH_GROUP_SUBSCRIBERS_ID=3 -SITH_GROUP_OLD_SUBSCRIBERS_ID=4 -SITH_GROUP_ACCOUNTING_ADMIN_ID=5 -SITH_GROUP_COM_ADMIN_ID=6 -SITH_GROUP_COUNTER_ADMIN_ID=7 -SITH_GROUP_SAS_ADMIN_ID=8 -SITH_GROUP_FORUM_ADMIN_ID=9 -SITH_GROUP_PEDAGOGY_ADMIN_ID=10 - -SITH_GROUP_BANNED_ALCOHOL_ID=11 -SITH_GROUP_BANNED_COUNTER_ID=12 -SITH_GROUP_BANNED_SUBSCRIPTION_ID=13 - -SITH_CLUB_REFOUND_ID=89 -SITH_COUNTER_REFOUND_ID=38 -SITH_PRODUCT_REFOUND_ID=5 - -# Counter - -SITH_COUNTER_ACCOUNT_DUMP_ID=39 - -# Defines which product type is the refilling type, and thus increases the account amount -SITH_COUNTER_PRODUCTTYPE_REFILLING=3 - -SITH_ECOCUP_CONS=1152 -SITH_ECOCUP_DECO=1151 - -# Defines which product is the one year subscription and which one is the six month subscription -SITH_PRODUCT_SUBSCRIPTION_ONE_SEMESTER=1 -SITH_PRODUCT_SUBSCRIPTION_TWO_SEMESTERS=2 -SITH_PRODUCTTYPE_SUBSCRIPTION=2 - -# Defines which clubs let its members the ability to see users subscription history -SITH_CAN_CREATE_SUBSCRIPTION_HISTORY=1 -SITH_CAN_READ_SUBSCRIPTION_HISTORY=1 - -# SAS variables -SITH_SAS_ROOT_DIR_ID=4 - -# ET variables -SITH_EBOUTIC_CB_ENABLED=true -SITH_EBOUTIC_ET_URL="https://preprod-tpeweb.e-transactions.fr/cgi/MYchoix_pagepaiement.cgi" -SITH_EBOUTIC_PBX_SITE=1999888 -SITH_EBOUTIC_PBX_RANG=32 -SITH_EBOUTIC_PBX_IDENTIFIANT=2 -SITH_EBOUTIC_HMAC_KEY=0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF -SITH_EBOUTIC_PUB_KEY_PATH=sith/et_keys/pubkey.pem - -SITH_MAILING_FETCH_KEY=IloveMails -SENTRY_DSN= -SENTRY_ENV=production \ No newline at end of file diff --git a/docs/howto/prod.md b/docs/howto/prod.md index 472f8c3e..df7c7644 100644 --- a/docs/howto/prod.md +++ b/docs/howto/prod.md @@ -8,7 +8,7 @@ Cette variable est composée d'un lien complet vers votre projet sentry. ## Récupérer les statiques Nous utilisons du SCSS dans le projet. -En environnement de développement (`DEBUG=true`), +En environnement de développement (`SITH_DEBUG=true`), le SCSS est compilé à chaque fois que le fichier est demandé. Pour la production, le projet considère que chacun des fichiers est déjà compilé. diff --git a/docs/tutorial/install-advanced.md b/docs/tutorial/install-advanced.md index 357d013c..7b4fe493 100644 --- a/docs/tutorial/install-advanced.md +++ b/docs/tutorial/install-advanced.md @@ -212,7 +212,7 @@ Puis lancez ou relancez nginx : sudo systemctl restart nginx ``` -Dans votre `.env`, remplacez `DEBUG=true` par `DEBUG=false`. +Dans votre `.env`, remplacez `SITH_DEBUG=true` par `SITH_DEBUG=false`. Enfin, démarrez le serveur Django : @@ -224,7 +224,7 @@ uv run ./manage.py runserver 8001 Et c'est bon, votre reverse-proxy est prêt à tourner devant votre serveur. Nginx écoutera sur le port 8000. Toutes les requêtes vers des fichiers statiques et les medias publiques -seront seront servies directement par nginx. +seront servies directement par nginx. Toutes les autres requêtes seront transmises au serveur django. @@ -238,3 +238,64 @@ un cron pour la mettre à jour au moins une fois par jour. ```bash python manage.py update_spam_database ``` + +## Personnaliser l'environnement + +Le site utilise beaucoup de variables configurables via l'environnement. +Cependant, pour des raisons de maintenabilité et de simplicité +pour les nouveaux développeurs, nous n'avons mis dans le fichier +`.env.example` que celles qui peuvent nécessiter d'être fréquemment modifiées +(par exemple, l'url de connexion à la db, ou l'activation du mode debug). + +Cependant, il en existe beaucoup d'autres, que vous pouvez trouver +dans le `settings.py` en recherchant `env.` +(avec `grep` ou avec un ++ctrl+f++ dans votre éditeur). + +Si le besoin de les modifier se présente, c'est chose possible. +Il suffit de rajouter la paire clef-valeur correspondante dans le `.env`. + +!!!tip + + Si vous utilisez nushell, + vous pouvez automatiser le processus avec + avec le script suivant, qui va parser le `settings.py` + pour récupérer toutes les variables d'environnement qui ne sont pas + définies dans le .env puis va les rajouter : + + ```nu + # si le fichier .env n'existe pas, on le crée + if not (".env" | path exists) { + cp .env.example .env + } + + # puis on récupère les variables d'environnement déjà existantes + let existing = open .env + + # on récupère toutes les variables d'environnement utilisées + # dans le settings.py qui ne sont pas encore définies dans le .env, + # on les convertit dans un format .env, + # puis on les ajoute à la fin du .env + let regex = '(env\.)(?\w+)\(\s*"(?\w+)"(\s*(, default=)(?.+))?\s*\)'; + let content = open sith/settings.py; + let vars = $content + | parse --regex $regex + | filter { |i| $i.env_name not-in $existing } + | each { |i| + let parsed_value = match [$i.method, $i.value] { + ["str", "None"] => "" + ["bool", $val] => ($val | str downcase) + ["list", $val] => ($val | str trim -c '[' | str trim -c ']') + ["path", $val] => ($val | str replace 'BASE_DIR / "' $'"(pwd)/') + [_, $val] => $val + } + $"($i.env_name)=($parsed_value)" + } + + if ($vars | is-not-empty) { + # on ajoute les nouvelles valeurs, + # en mettant une ligne vide de séparation avec les anciennes + ["", ...$vars] | save --append .env + } + + print $"($vars | length) values added to .env" + ``` \ No newline at end of file diff --git a/mkdocs.yml b/mkdocs.yml index f307cb8a..9a7c3114 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -157,6 +157,7 @@ markdown_extensions: - md_in_html - pymdownx.details - pymdownx.inlinehilite + - pymdownx.keys - pymdownx.superfences: custom_fences: - name: mermaid diff --git a/sith/settings.py b/sith/settings.py index 09d155ee..9cd3ca89 100644 --- a/sith/settings.py +++ b/sith/settings.py @@ -59,7 +59,7 @@ BASE_DIR = Path(__file__).parent.parent.resolve() SECRET_KEY = env.str("SECRET_KEY") # SECURITY WARNING: don't run with debug turned on in production! -DEBUG = env.bool("DEBUG", default=False) +DEBUG = env.bool("SITH_DEBUG", default=False) TESTING = "pytest" in sys.modules INTERNAL_IPS = ["127.0.0.1"] @@ -711,7 +711,7 @@ SITH_MAILING_FETCH_KEY = env.str("SITH_MAILING_FETCH_KEY", default="ILoveMails") SITH_GIFT_LIST = [("AE Tee-shirt", _("AE tee-shirt"))] -SENTRY_DSN = env.str("SENRY_DSN", default=None) +SENTRY_DSN = env.str("SENTRY_DSN", default=None) SENTRY_ENV = env.str("SENTRY_ENV", default="production") TOXIC_DOMAINS_PROVIDERS = [