docs: une seule source d architecture, et un README qui dit vrai
DOC-002. docs/architecture.html (746 l.) et docs/architecture-v3.html (798 l.) coexistaient, en HTML versionne, sans rien qui indique laquelle faisait foi ni ou etait passee la v2. docs/architecture.md reprend la v3 -- la plus complete : 24 classes au lieu de 19, plus la structure des paquets -- en Markdown avec les diagrammes en Mermaid. Lisible en revue, comparable en diff, rendu directement par Gitea comme par GitHub. Ajoute au document ce que les diagrammes ne montrent pas et qu il faut savoir avant de les lire : la double modelisation coach/equipe, l absence de migrations, et le bot dans le meme processus que le web. README Il annoncait « Authorization Checks: Proper ownership validation on all sensitive operations » a une epoque ou trois IDOR etaient ouverts, et « Rate Limiting » sans mentionner que trusted_proxy='*' la rend contournable. Il ne disait pas non plus comment installer, lancer ni tester le projet. Reecrit en francais, avec deux sections distinctes : ce qui est en place et verifie par des tests, et **ce qui ne l est pas** -- migrations absentes, secrets non revoques, proxy de confiance, identite Discord non prouvee. Une liste de securite qui ne mentionne que les bonnes nouvelles est pire qu absente : on s y fie. Instructions d installation, de lancement et de verification ajoutees, avec les deux seuls points d entree (ARCH-007). Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
@@ -1,90 +1,133 @@
|
||||
# Plateforme centralisée de tryouts
|
||||
|
||||
## Security Configuration
|
||||
Application interne du club e-sport de l'UdeS : inscriptions aux sélections,
|
||||
évaluations, gestion des équipes, disponibilités, contrats, et notifications
|
||||
Discord.
|
||||
|
||||
### Required Environment Variables
|
||||
Le site est servi **en français**, l'anglais reste accessible par le sélecteur
|
||||
de la barre latérale (voir `docs/translations.md`).
|
||||
|
||||
Before deploying, create a `.env` file which integrates everything in the .env.exemple.
|
||||
Ensure you follow the comments of the exemple if you are to use this tool in production.
|
||||
---
|
||||
|
||||
## Démarrer
|
||||
|
||||
### Security Features Implemented
|
||||
```bash
|
||||
python -m venv .venv
|
||||
.venv/Scripts/pip install -r requirements.txt -r requirements-dev.txt
|
||||
cp app/.env.exemple .env # puis remplir les valeurs
|
||||
.venv/Scripts/python run.py # développement, http://127.0.0.1:5000
|
||||
```
|
||||
|
||||
- **Rate Limiting**: Login endpoint limited to 10 requests per minute to prevent brute-force attacks
|
||||
- **Secure Session Cookies**: HTTPSOnly, SameSite=Lax, and Secure flags enabled
|
||||
- **CSRF Protection**: Enabled by default on all forms
|
||||
- **HTTPS Enforcement**: Automatic redirect to HTTPS in production
|
||||
- **Security Headers**: X-Frame-Options, X-Content-Type-Options, Content-Security-Policy, HSTS
|
||||
- **Open Redirect Prevention**: URL validation on login redirect
|
||||
- **Authorization Checks**: Proper ownership validation on all sensitive operations
|
||||
- **nginx**: reverse-proxy and load balancer
|
||||
- **Waitress WSGI**: Production ready WSGI
|
||||
`SECRET_KEY` et `DATABASE_URL` sont **obligatoires** : `create_app()` refuse
|
||||
de démarrer sans eux. `DATABASE_URL` doit pointer sur PostgreSQL ; le pilote
|
||||
psycopg 3 est nommé automatiquement si l'URL n'en nomme pas.
|
||||
|
||||
### When true in .env:
|
||||
- **Forces HTTPS only**
|
||||
- **Forcer secure cookies**
|
||||
Production : `python wsgi.py` (Waitress derrière nginx). Voir
|
||||
`docs/deployment.md`.
|
||||
|
||||
## App details
|
||||
Ce sont les **deux seuls** points d'entrée.
|
||||
|
||||
### Code
|
||||
## Vérifier
|
||||
|
||||
- Full python backend using flask
|
||||
- statics are pure HTML and CSS
|
||||
- Some js to add logic to styling and showing certain pages/cards
|
||||
```bash
|
||||
.venv/Scripts/python -m pytest # suite complète
|
||||
.venv/Scripts/python -m ruff check . # lint
|
||||
.venv/Scripts/python -m ruff format --check .
|
||||
```
|
||||
|
||||
### Functionalities
|
||||
Les trois tournent en CI et y sont bloquants.
|
||||
|
||||
- **User base with sign-ins**: Forces users to create an account and register pertinent information for tryouts and teams. The admin can attribute them a role.
|
||||
- **User-Role-Based Permissions**: admin - full acces, coach/manager - access to team management, player - views what he is registered in (no management), scout - view only
|
||||
- **Tryout Management**: manage internal tryout teams, organise internal tryouts matches (3 formats, team vs team, PvP, scrim). Coaches can Evaluate players based on 10 criteria
|
||||
- **Team Management**: manage teams for the season, create matches and practices. When planning a practice there will be a calendar showing player availabitlities slots to help chose a time
|
||||
- **Coach and Player Availabilities**: Allow better planning for the coaches, and for players to book One on Ones with their coach.
|
||||
- **Player Notes**: Coaches can give notes to their players. The players will see them and there is a history which keeps the most recent notes.
|
||||
- **Team Notes**: Coaches can give notes to their teams, where all players from that team can see the note.
|
||||
- **One on One**: Players can request a One on One meeting with their coach. This sends a discord dm to the coach to accept or refuse. The player is then notified of the response.
|
||||
- **Availabilities**: Allow players and coach to enter the moments they are available. Allows for easier practice setup and One on One planning.
|
||||
---
|
||||
|
||||
## Ce que fait l'application
|
||||
|
||||
## Discord Integration
|
||||
- **Comptes et rôles** — cinq rôles : président (`admin`), gérant
|
||||
(`manager`), coach, joueur (`player`), recruteur (`scout`). Le président
|
||||
attribue les rôles.
|
||||
- **Sélections** — organisation des tryouts, trois formats de match
|
||||
(équipe contre équipe, joueur contre joueur, scrim), évaluation des
|
||||
joueurs sur dix critères.
|
||||
- **Équipes** — effectifs de la saison, matchs et entraînements. Le
|
||||
formulaire d'entraînement affiche les disponibilités des joueurs.
|
||||
- **Disponibilités** — créneaux hebdomadaires des joueurs, créneaux
|
||||
réservables des coachs.
|
||||
- **Notes** — un coach écrit des notes d'équipe (visibles par l'équipe) et
|
||||
des notes nominatives (visibles par le joueur concerné).
|
||||
- **Un-à-un** — un joueur demande une séance à son coach ; le coach répond
|
||||
depuis le site ou par une réaction sur le message privé Discord.
|
||||
- **Contrats** — dépôt d'un contrat par le staff, signature par le joueur.
|
||||
|
||||
The application supports sending Discord direct messages to coaches when players request One on One sessions,
|
||||
when matches/tryouts/practices are created and a player is in it, and the players get match reminders 24h before a match.
|
||||
## Comment c'est construit
|
||||
|
||||
When sending a **One on One** request, the coach can accept via the platform or react to the discord message to answer the booking request.
|
||||
Same thing with **matches** and **practices**, the players can react or answer on the platform.
|
||||
Backend Python 3.12 / Flask, rendu serveur en Jinja2, CSS et JavaScript
|
||||
maison, sans framework front. Base PostgreSQL via SQLAlchemy. Bot Discord
|
||||
(`discord.py`) dans un fil du même processus que le serveur web.
|
||||
|
||||
### Setup Instructions
|
||||
`docs/architecture.md` contient les diagrammes (classes, paquets, flux
|
||||
d'une requête).
|
||||
|
||||
#### 1. Create a Discord Bot (Not needed for UdeS user, the bot already exists)
|
||||
---
|
||||
|
||||
1. Go to the [Discord Developer Portal](https://discord.com/developers/applications)
|
||||
2. Create a new application
|
||||
3. Go to the "Bot" tab and create a bot user
|
||||
4. Copy the bot token - this will be your `DISCORD_BOT_TOKEN`
|
||||
5. Enable the "Message Content Intent" under Privileged Gateway Intents (required for sending messages)
|
||||
## Sécurité
|
||||
|
||||
#### 2. Add Bot to your server
|
||||
En place et vérifié par des tests :
|
||||
|
||||
For the bot to send DMs:
|
||||
1. Each user must have the bot added to their Discord server OR be friends with the bot
|
||||
2. Users need to add their Discord User ID to their profile:
|
||||
- Enable Developer Mode in Discord (User Settings → Advanced → Developer Mode)
|
||||
- Right-click on their profile → Copy ID
|
||||
- Enter this numeric ID in the "Discord User ID" field in their profile settings
|
||||
- **Limitation de débit** sur la connexion (10 requêtes/minute par IP).
|
||||
- **Cookies de session** `HttpOnly`, `SameSite=Lax`, `Secure`, avec
|
||||
expiration effective.
|
||||
- **CSRF** sur tous les formulaires, y compris la déconnexion (en POST).
|
||||
- **HTTPS** forcé en production, **HSTS**.
|
||||
- **CSP sans `unsafe-inline`** sur `script-src` : aucun gestionnaire
|
||||
d'événement en ligne, chaque bloc `<script>` porte un nonce par requête.
|
||||
- **Redirections** validées (rien ne sort du site).
|
||||
- **Validation** par schémas marshmallow sur les formulaires de compte, avec
|
||||
politique de mot de passe.
|
||||
- **Autorisation** centralisée dans `app/permissions.py`.
|
||||
- **Journal d'authentification** (`logs/auth.log`) : connexions, échecs,
|
||||
changements de rôle, suppressions de compte.
|
||||
- **Téléversements** vérifiés par extension *et* par signature de fichier.
|
||||
|
||||
Ce qui **n'est pas** fait, pour que personne ne s'y fie :
|
||||
|
||||
### How It Works
|
||||
- **Aucune migration de schéma.** `db.create_all()` crée les tables
|
||||
manquantes et ne modifie jamais une table existante : une colonne ajoutée
|
||||
à un modèle est absente de la production.
|
||||
- **Les secrets de l'historique git ne sont pas révoqués** — jeton du bot,
|
||||
mot de passe PostgreSQL, `SECRET_KEY`.
|
||||
- **`trusted_proxy='*'`** dans `wsgi.py` : l'en-tête `X-Forwarded-For` est
|
||||
accepté de n'importe quelle source, donc la limitation par IP est
|
||||
contournable. À régler avec la topologie réelle du déploiement.
|
||||
- **L'identité Discord** transite encore par un champ caché du formulaire
|
||||
d'inscription : elle n'est pas prouvée par le passage OAuth2.
|
||||
|
||||
When a player submits a One on One request:
|
||||
1. The system checks if the coach has a Discord User ID configured
|
||||
2. If configured, a direct message is sent to the coach via the Discord bot
|
||||
`docs/security-checklist.md` détaille la liste avant mise en production.
|
||||
|
||||
### Message Format
|
||||
---
|
||||
|
||||
The Discord DM includes:
|
||||
- Player name
|
||||
- Team name
|
||||
- Requested date and time slot
|
||||
- Discussion points (if provided)
|
||||
- Link to the application for approval/rejection
|
||||
- Two provided reactions to accept or refuse via discord
|
||||
## Intégration Discord
|
||||
|
||||
Messages privés au coach lors d'une demande d'un-à-un, aux joueurs à la
|
||||
création d'un match ou d'un entraînement les concernant, et rappel 24 h
|
||||
avant un match. Les réponses se font par réaction sur le message ou depuis
|
||||
le site.
|
||||
|
||||
L'état des messages en attente de réponse est dans `discord_pending.json`,
|
||||
**non versionné** : c'est de l'état d'exécution, propre à chaque serveur.
|
||||
|
||||
### Mise en place
|
||||
|
||||
Le bot du club existe déjà ; ce qui suit ne concerne qu'une nouvelle
|
||||
installation.
|
||||
|
||||
1. Créer une application sur le [portail développeur
|
||||
Discord](https://discord.com/developers/applications), puis un bot.
|
||||
2. Copier le jeton dans `DISCORD_BOT_TOKEN`.
|
||||
3. Activer **Message Content Intent** dans les *Privileged Gateway Intents*.
|
||||
C'est le seul intent privilégié demandé : il sert à lire le motif d'un
|
||||
refus écrit en réponse au message.
|
||||
4. Chaque personne doit partager un serveur avec le bot (ou l'avoir en ami)
|
||||
pour recevoir un message privé, et renseigner son identifiant Discord
|
||||
dans son profil (Discord → Paramètres → Avancés → Mode développeur, puis
|
||||
clic droit sur son profil → Copier l'identifiant).
|
||||
|
||||
`/health` indique si le bot tourne et s'il est connecté.
|
||||
|
||||
Reference in New Issue
Block a user