Instance locale sans config : mail et lien email optionnels

L'app tourne désormais pour soi sans rien configurer. Sans relais
SMTP, le lien de création de compte s'affiche directement à l'écran,
construit depuis l'URL en cours — aucune config d'URL nécessaire,
même en naviguant par IP sur le LAN (le contrôle anti-open-redirect
du Host ne concerne que le chemin par email). allowed_email_domain
vide accepte tous les emails : l'adresse ne sert que d'identifiant.

Le fichier d'exemple de config était périmé : il datait d'avant les
plages, force_secure_cookies et login_rate_limit_per_min, et
laissait croire le SMTP obligatoire. Il reflète maintenant les clés
réelles, toutes optionnelles et vides par défaut.

💘 Generated with Crush

Assisted-by: Crush:glm-5.2
This commit is contained in:
Jacquin Antoine
2026-09-11 16:05:32 +02:00
parent 1b4bf0d488
commit 8e0f2c453f
6 changed files with 199 additions and 65 deletions

View File

@ -122,12 +122,20 @@ performance — une seule fois par semaine et par onglet, promis.
Chaque personne a son propre compte, ses propres pointages, congés, réglages et jetons de
présence — tout est stocké séparément dans `data/users/<identifiant>/`.
Connexion par email + mot de passe, restreinte au domaine `allowed_email_domain` (voir
[Configuration](#configuration)). Pour un compte qui n'a pas encore de mot de passe, se
connecter avec son adresse envoie un lien (valable 24h) pour en définir un — c'est aussi
le seul moyen d'en obtenir un : il n'y a pas de "mot de passe oublié" en libre-service une
fois un mot de passe défini. La session est un cookie signé (HMAC), sans base de données
de sessions côté serveur.
**Utilisation locale sans aucune config** : `data/config.json` est optionnel (créé
avec les valeurs par défaut au premier lancement) et la config mail aussi — sans
relais SMTP, le lien de création de compte s'affiche directement à l'écran au lieu
d'être envoyé par email. Lance, ouvre [http://localhost:8000](http://localhost:8000), tape ton
email, clique sur le lien affiché, définis ton mot de passe : c'est tout.
Connexion par email + mot de passe. Si `allowed_email_domain` est renseigné, seules
les adresses de ce domaine peuvent se connecter (vide = tous les domaines acceptés).
Pour un compte qui n'a pas encore de mot de passe, se connecter avec son adresse
génère un lien (valable 24h) pour en définir un — envoyé par email si un serveur
SMTP est configuré, affiché à l'écran sinon. C'est aussi le seul moyen d'en obtenir
un : il n'y a pas de "mot de passe oublié" en libre-service une fois un mot de
passe défini. La session est un cookie signé (HMAC), sans base de données de
sessions côté serveur.
---
@ -146,37 +154,44 @@ Seul `data/config.example.json` est versionné.
## Configuration
`data/config.json` (voir `data/config.example.json`) :
`data/config.json` (voir `data/config.example.json`) — toutes les clés sont
optionnelles (le fichier lui-même est créé avec les défauts au premier lancement) :
```json
{
"heures_semaine": 39.0,
"jours_par_semaine": 5,
"log_level": "DEBUG",
"allowed_email_domain": "exemple.fr",
"base_url": "https://pointeuse.exemple.fr",
"mail_from": "no-reply@exemple.fr",
"log_level": "INFO",
"allowed_email_domain": "",
"base_url": "",
"mail_from": "",
"smtp": {
"host": "smtp.exemple.fr",
"host": "",
"port": 587,
"user": "no-reply@exemple.fr",
"password": "change-moi",
"user": "",
"password": "",
"use_tls": true
}
},
"plages": { "matin_debut": "09:00", "matin_fin": "12:00", "aprem_debut": "14:00", "aprem_fin": "17:00", "pause_dejeuner_fin": "13:30" },
"astreinte_facteurs": []
}
```
- `heures_semaine` — heures hebdomadaires visées (ex: `39.0`).
- `jours_par_semaine` — nombre de jours travaillés dans la semaine (ex: `5`). Le quota quotidien est calculé : `heures_semaine ÷ jours_par_semaine` (39h / 5 = 7h48/jour).
- `log_level` — `DEBUG`, `INFO`, `WARNING` ou `ERROR`. Contrôle la verbosité des logs (`docker logs`).
- `allowed_email_domain` — seules les adresses de ce domaine peuvent se connecter.
- `base_url` — schéma + domaine (ex: `https://pointeuse.exemple.fr`, sans `/` final) utilisés
pour construire les liens envoyés par email (magic link) et les URLs Tasker/Automation
affichées dans Réglages. Si vide, ces URLs sont dérivées de la requête entrante (Host header)
quand celui-ci correspond à `localhost` ou à `allowed_email_domain` ; sinon l'envoi d'email est
refusé par sécurité (anti open-redirect). **Toujours renseigner `base_url` en production.**
- `mail_from` — adresse expéditrice des emails de connexion.
- `smtp` — serveur relais utilisé pour l'envoi (host, port, identifiants, TLS).
- `allowed_email_domain` — **optionnel** : seules les adresses de ce domaine peuvent se
connecter ; vide = tous les domaines acceptés (l'email ne sert que d'identifiant).
- `base_url` — **optionnel** : schéma + domaine (ex: `https://pointeuse.exemple.fr`, sans `/` final)
utilisés pour construire les liens envoyés par email. Si vide, ces URLs sont dérivées de
la requête entrante (Host header) quand celui-ci correspond à `localhost` ou à
`allowed_email_domain` ; sinon l'envoi d'email est refusé par sécurité (anti
open-redirect). **À renseigner en production si le mail est activé.**
- `mail_from` — **optionnel** : adresse expéditrice des emails de connexion (défaut local
`no-reply@pointeuse.local`).
- `smtp` — **optionnel** : serveur relais utilisé pour l'envoi (host, port, identifiants,
TLS). Sans `smtp.host`, aucun email n'est envoyé : le lien de création de compte
s'affiche directement à l'écran — parfait pour une instance locale perso.
- `force_secure_cookies` (optionnel, `false` par défaut) — force le flag `Secure` sur le
cookie de session même si la requête entrante n'est pas vue comme HTTPS par l'app
(utile derrière un reverse proxy qui termine le TLS).