Compare commits
14 Commits
release-1.
...
9cf88d9f5a
| Author | SHA1 | Date | |
|---|---|---|---|
| 9cf88d9f5a | |||
| 4d7ca7945b | |||
| c22c72e99c | |||
| efe5073aaa | |||
| 39b7b7f8a4 | |||
| f8c02b3cfc | |||
| 35bffc8a0b | |||
| 2d54a7384f | |||
| ab8ea038c0 | |||
| 87ad8988fa | |||
| 23c548992d | |||
| 7513bf45d6 | |||
| 6096da5bb8 | |||
| ad147eb930 |
103
Jenkinsfile
vendored
103
Jenkinsfile
vendored
@@ -180,16 +180,35 @@ pipeline {
|
||||
allowEmptyResults: true
|
||||
)
|
||||
|
||||
recordCoverage(
|
||||
tools: [[
|
||||
parser: 'LCOV',
|
||||
pattern: 'backend/coverage/lcov.info'
|
||||
]],
|
||||
sourceCodeRetention: 'EVERY_BUILD',
|
||||
id: 'backend-coverage',
|
||||
name: 'Backend Coverage'
|
||||
)
|
||||
|
||||
publishHTML([
|
||||
allowMissing: true,
|
||||
alwaysLinkToLastBuild: true,
|
||||
keepAll: true,
|
||||
reportDir: 'backend/coverage',
|
||||
reportFiles: 'index.html',
|
||||
reportName: 'Backend Coverage HTML'
|
||||
])
|
||||
|
||||
archiveArtifacts(
|
||||
artifacts: 'backend/coverage/**',
|
||||
fingerprint: true,
|
||||
allowEmptyArchive: true
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stage('Frontend - Lint et Build') {
|
||||
stage('Frontend - Lint, Tests et Build') {
|
||||
steps {
|
||||
sh '''
|
||||
docker run --rm \
|
||||
@@ -213,12 +232,92 @@ pipeline {
|
||||
sh -c "
|
||||
npm ci --prefer-offline --no-audit --no-fund &&
|
||||
npm run lint &&
|
||||
npm run test:coverage &&
|
||||
npm run build
|
||||
"
|
||||
'''
|
||||
}
|
||||
post {
|
||||
always {
|
||||
junit(
|
||||
testResults: 'frontend/test-results/*.xml',
|
||||
allowEmptyResults: true
|
||||
)
|
||||
|
||||
recordCoverage(
|
||||
tools: [[
|
||||
parser: 'LCOV',
|
||||
pattern: 'frontend/coverage/lcov.info'
|
||||
]],
|
||||
sourceCodeRetention: 'EVERY_BUILD',
|
||||
id: 'frontend-coverage',
|
||||
name: 'Frontend Coverage'
|
||||
)
|
||||
|
||||
publishHTML([
|
||||
allowMissing: true,
|
||||
alwaysLinkToLastBuild: true,
|
||||
keepAll: true,
|
||||
reportDir: 'frontend/coverage',
|
||||
reportFiles: 'index.html',
|
||||
reportName: 'Frontend Coverage HTML'
|
||||
])
|
||||
|
||||
archiveArtifacts(
|
||||
artifacts: 'frontend/coverage/**',
|
||||
fingerprint: true,
|
||||
allowEmptyArchive: true
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stage('SonarQube Analysis') {
|
||||
when {
|
||||
branch 'develop'
|
||||
}
|
||||
|
||||
tools {
|
||||
nodejs 'node22'
|
||||
}
|
||||
|
||||
steps {
|
||||
script {
|
||||
def scannerHome = tool 'sonar-scanner'
|
||||
|
||||
withEnv(["SCANNER_HOME=${scannerHome}"]) {
|
||||
withSonarQubeEnv('sonarqube') {
|
||||
sh '''
|
||||
echo "Node utilisé par Sonar :"
|
||||
node -v
|
||||
|
||||
"${SCANNER_HOME}/bin/sonar-scanner" \
|
||||
-Dsonar.projectKey=THE-TIP-TOP \
|
||||
-Dsonar.projectName=THE-TIP-TOP \
|
||||
-Dsonar.sources=backend/src,frontend/src \
|
||||
-Dsonar.tests=backend/tests,frontend/src/test \
|
||||
-Dsonar.exclusions=frontend/src/test/**,backend/tests/**,**/node_modules/**,**/coverage/**,**/dist/** \
|
||||
-Dsonar.test.inclusions=backend/tests/**,frontend/src/test/** \
|
||||
-Dsonar.javascript.lcov.reportPaths=backend/coverage/lcov.info,frontend/coverage/lcov.info \
|
||||
-Dsonar.sourceEncoding=UTF-8
|
||||
'''
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stage('SonarQube Quality Gate') {
|
||||
when {
|
||||
branch 'develop'
|
||||
}
|
||||
|
||||
steps {
|
||||
timeout(time: 5, unit: 'MINUTES') {
|
||||
waitForQualityGate abortPipeline: false
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('Construction des images Docker') {
|
||||
when {
|
||||
expression {
|
||||
|
||||
781
README.md
Normal file
781
README.md
Normal file
@@ -0,0 +1,781 @@
|
||||
# Thé Tip Top – Plateforme du jeu-concours
|
||||
|
||||
## Présentation
|
||||
|
||||
**Thé Tip Top** est une application web complète développée dans le cadre d’un projet de certification **Expert en Stratégie et Transformation Digitale**.
|
||||
|
||||
Le projet simule le système d’information d’un jeu-concours organisé à l’occasion de l’ouverture de la 10ᵉ boutique Thé Tip Top à Nice.
|
||||
|
||||
La plateforme permet aux clients de participer avec un code unique présent sur leur ticket, de consulter leurs gains et de les récupérer en boutique. Elle fournit également des interfaces dédiées aux employés et aux administrateurs.
|
||||
|
||||
Au-delà de l’application, le projet met en œuvre une chaîne complète de **CI/CD**, plusieurs environnements isolés, un registre Docker privé, un reverse proxy HTTPS et une stack de supervision.
|
||||
|
||||
> **Projet étudiant — client fictif Thé Tip Top.**
|
||||
|
||||
---
|
||||
|
||||
## Fonctionnalités principales
|
||||
|
||||
### Espace client
|
||||
|
||||
- création de compte ;
|
||||
- vérification de l’adresse email ;
|
||||
- connexion email / mot de passe ;
|
||||
- connexion avec Google OAuth 2.0 ;
|
||||
- gestion du profil ;
|
||||
- saisie d’un code ticket unique ;
|
||||
- participation au jeu-concours ;
|
||||
- consultation des gains.
|
||||
|
||||
### Espace employé
|
||||
|
||||
- authentification avec rôle `EMPLOYEE` ;
|
||||
- recherche d’un gain ;
|
||||
- contrôle des informations associées au ticket ;
|
||||
- validation de la remise d’un lot.
|
||||
|
||||
### Espace administrateur
|
||||
|
||||
- authentification avec rôle `ADMIN` ;
|
||||
- tableau de bord et statistiques ;
|
||||
- consultation des participants ;
|
||||
- gestion des données nécessaires à l’administration ;
|
||||
- création de comptes employés ;
|
||||
- configuration du lancement du jeu-concours ;
|
||||
- tirage au sort final ;
|
||||
- consultation du grand gagnant.
|
||||
|
||||
### Jeu-concours
|
||||
|
||||
Le système gère plusieurs phases :
|
||||
|
||||
```text
|
||||
NOT_CONFIGURED
|
||||
↓
|
||||
SCHEDULED
|
||||
↓
|
||||
OPEN
|
||||
↓
|
||||
CLAIM_ONLY
|
||||
↓
|
||||
CLOSED
|
||||
```
|
||||
|
||||
Parmi les principales règles métier :
|
||||
|
||||
- un ticket ne peut être utilisé qu’une seule fois ;
|
||||
- les tickets du jeu sont gagnants ;
|
||||
- les gains sont associés aux tickets ;
|
||||
- seuls les clients participent au jeu ;
|
||||
- plusieurs participations d’un même client n’augmentent pas ses chances au tirage final ;
|
||||
- un seul grand gagnant peut être enregistré ;
|
||||
- le tirage final respecte les contraintes temporelles définies dans l’application.
|
||||
|
||||
---
|
||||
|
||||
# Architecture générale
|
||||
|
||||
```text
|
||||
UTILISATEURS
|
||||
│
|
||||
HTTPS
|
||||
│
|
||||
▼
|
||||
┌─────────┐
|
||||
│ Traefik │
|
||||
└────┬────┘
|
||||
│
|
||||
┌────────────┴────────────┐
|
||||
│ │
|
||||
▼ ▼
|
||||
Frontend React Backend API
|
||||
Vite + Nginx Node.js + Express
|
||||
│ │
|
||||
│ ▼
|
||||
│ PostgreSQL
|
||||
│ + Prisma
|
||||
│
|
||||
└────────── API REST ─────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# Stack technique
|
||||
|
||||
## Frontend
|
||||
|
||||
- React
|
||||
- Vite
|
||||
- React Router
|
||||
- Tailwind CSS
|
||||
- Vitest
|
||||
- Testing Library
|
||||
- ESLint
|
||||
- Nginx
|
||||
|
||||
## Backend
|
||||
|
||||
- Node.js 22
|
||||
- Express.js
|
||||
- Prisma ORM 6
|
||||
- PostgreSQL 16
|
||||
- JWT
|
||||
- Passport.js
|
||||
- Google OAuth 2.0
|
||||
- Bcrypt
|
||||
- Zod
|
||||
- Nodemailer
|
||||
- Helmet
|
||||
- express-rate-limit
|
||||
- Swagger / OpenAPI
|
||||
- Jest
|
||||
- Supertest
|
||||
|
||||
## DevOps
|
||||
|
||||
- Git
|
||||
- Gitea
|
||||
- Jenkins
|
||||
- Docker
|
||||
- Docker Compose
|
||||
- Docker Registry privé
|
||||
- Traefik
|
||||
- HTTPS
|
||||
- Let's Encrypt
|
||||
|
||||
## Monitoring
|
||||
|
||||
- Prometheus
|
||||
- Grafana
|
||||
- cAdvisor
|
||||
- Node Exporter
|
||||
|
||||
---
|
||||
|
||||
# Structure du dépôt
|
||||
|
||||
```text
|
||||
THE-TIP-TOP/
|
||||
│
|
||||
├── backend/
|
||||
│ ├── prisma/
|
||||
│ │ ├── migrations/
|
||||
│ │ ├── schema.prisma
|
||||
│ │ └── seed.js
|
||||
│ ├── src/
|
||||
│ ├── tests/
|
||||
│ ├── Dockerfile
|
||||
│ ├── package.json
|
||||
│ └── README.md
|
||||
│
|
||||
├── frontend/
|
||||
│ ├── src/
|
||||
│ │ ├── components/
|
||||
│ │ ├── context/
|
||||
│ │ ├── pages/
|
||||
│ │ ├── services/
|
||||
│ │ └── test/
|
||||
│ ├── Dockerfile
|
||||
│ ├── nginx.conf
|
||||
│ ├── package.json
|
||||
│ └── README.md
|
||||
│
|
||||
├── deploy/
|
||||
│ ├── dev/
|
||||
│ │ └── docker-compose.yml
|
||||
│ ├── preprod/
|
||||
│ │ └── docker-compose.yml
|
||||
│ └── prod/
|
||||
│ └── docker-compose.yml
|
||||
│
|
||||
├── Jenkinsfile
|
||||
└── README.md
|
||||
```
|
||||
|
||||
Pour les informations spécifiques à chaque application :
|
||||
|
||||
- [`backend/README.md`](backend/README.md)
|
||||
- [`frontend/README.md`](frontend/README.md)
|
||||
|
||||
---
|
||||
|
||||
# Environnements
|
||||
|
||||
Le projet utilise trois environnements distincts.
|
||||
|
||||
| Environnement | Branche | Frontend | API |
|
||||
|---|---|---|---|
|
||||
| DEV | `develop` | `https://dev.dsp5-archi-o24a-4-5-g4.fr` | `https://api-dev.dsp5-archi-o24a-4-5-g4.fr` |
|
||||
| PREPROD | `release-*` | `https://preprod.dsp5-archi-o24a-4-5-g4.fr` | `https://api-preprod.dsp5-archi-o24a-4-5-g4.fr` |
|
||||
| PROD | `main` | `https://dsp5-archi-o24a-4-5-g4.fr` | `https://api.dsp5-archi-o24a-4-5-g4.fr` |
|
||||
|
||||
Les bases PostgreSQL et conteneurs applicatifs sont séparés entre les environnements.
|
||||
|
||||
---
|
||||
|
||||
# Stratégie Git
|
||||
|
||||
Le workflow de branches est organisé autour de plusieurs niveaux de validation.
|
||||
|
||||
```text
|
||||
feature/*
|
||||
│
|
||||
│ Pull Request / Merge
|
||||
▼
|
||||
develop
|
||||
│
|
||||
│ CI + déploiement DEV
|
||||
▼
|
||||
release-*
|
||||
│
|
||||
│ CI + déploiement PREPROD
|
||||
▼
|
||||
main
|
||||
│
|
||||
│ validation manuelle Jenkins
|
||||
▼
|
||||
PRODUCTION
|
||||
```
|
||||
|
||||
### `feature/*`
|
||||
|
||||
Branches utilisées pour le développement des fonctionnalités.
|
||||
|
||||
### `develop`
|
||||
|
||||
Branche d’intégration. Un changement validé sur cette branche est déployé automatiquement en DEV.
|
||||
|
||||
### `release-*`
|
||||
|
||||
Branches de préparation d’une version. Elles sont déployées en PREPROD pour validation avant production.
|
||||
|
||||
### `main`
|
||||
|
||||
Branche stable de production. Le déploiement PROD nécessite une validation manuelle dans Jenkins.
|
||||
|
||||
---
|
||||
|
||||
# Pipeline CI/CD
|
||||
|
||||
Le fichier `Jenkinsfile` placé à la racine du dépôt définit la chaîne d’intégration et de déploiement.
|
||||
|
||||
```text
|
||||
Push Gitea
|
||||
│
|
||||
▼
|
||||
Jenkins
|
||||
│
|
||||
├── Checkout
|
||||
│
|
||||
├── Vérification workspace
|
||||
│
|
||||
├── PostgreSQL CI temporaire
|
||||
│
|
||||
├── Prisma migrations
|
||||
│
|
||||
├── Prisma seed
|
||||
│
|
||||
├── Tests backend Jest
|
||||
│
|
||||
├── Publication JUnit
|
||||
│
|
||||
├── Frontend ESLint
|
||||
│
|
||||
├── Frontend Vite build
|
||||
│
|
||||
├── Docker build
|
||||
│
|
||||
├── Push Registry privé
|
||||
│
|
||||
└── Docker Compose deploy
|
||||
│
|
||||
▼
|
||||
DEV / PREPROD / PROD
|
||||
```
|
||||
|
||||
## Comportement selon la branche
|
||||
|
||||
### Feature
|
||||
|
||||
```text
|
||||
Push
|
||||
↓
|
||||
Tests
|
||||
↓
|
||||
Lint
|
||||
↓
|
||||
Build
|
||||
```
|
||||
|
||||
Pas de déploiement automatique.
|
||||
|
||||
### Develop
|
||||
|
||||
```text
|
||||
Push develop
|
||||
↓
|
||||
CI
|
||||
↓
|
||||
Images Docker
|
||||
↓
|
||||
Registry
|
||||
↓
|
||||
Déploiement DEV
|
||||
```
|
||||
|
||||
### Release
|
||||
|
||||
```text
|
||||
Push release-*
|
||||
↓
|
||||
CI
|
||||
↓
|
||||
Images Docker
|
||||
↓
|
||||
Registry
|
||||
↓
|
||||
Déploiement PREPROD
|
||||
```
|
||||
|
||||
### Main
|
||||
|
||||
```text
|
||||
Push main
|
||||
↓
|
||||
CI
|
||||
↓
|
||||
Images Docker
|
||||
↓
|
||||
Registry
|
||||
↓
|
||||
Validation Jenkins
|
||||
↓
|
||||
Déploiement PROD
|
||||
```
|
||||
|
||||
Cette validation constitue une barrière supplémentaire avant la mise en production.
|
||||
|
||||
---
|
||||
|
||||
# Tests automatisés
|
||||
|
||||
## Backend
|
||||
|
||||
Les tests utilisent **Jest** et **Supertest**.
|
||||
|
||||
Ils couvrent notamment :
|
||||
|
||||
- inscription ;
|
||||
- connexion ;
|
||||
- parcours E2E ;
|
||||
- autorisations ;
|
||||
- participation ;
|
||||
- phases du jeu ;
|
||||
- tirage au sort ;
|
||||
- notifications liées aux gains ;
|
||||
- notification du grand gagnant ;
|
||||
- authentification Google ;
|
||||
- gestion du mot de passe ;
|
||||
- comportements liés aux emails.
|
||||
|
||||
Commande :
|
||||
|
||||
```bash
|
||||
cd backend
|
||||
npm test
|
||||
```
|
||||
|
||||
Dans Jenkins, PostgreSQL est lancé temporairement pour les tests. Les migrations et données initiales sont appliquées avant l’exécution des suites.
|
||||
|
||||
## Frontend
|
||||
|
||||
Les tests utilisent **Vitest** et **Testing Library**.
|
||||
|
||||
Ils couvrent notamment :
|
||||
|
||||
- connexion ;
|
||||
- inscription ;
|
||||
- formulaire d’inscription ;
|
||||
- saisie du code unique ;
|
||||
- routes protégées ;
|
||||
- contexte d’authentification ;
|
||||
- gestion des erreurs d’authentification ;
|
||||
- services ;
|
||||
- bannière de cookies.
|
||||
|
||||
Commandes :
|
||||
|
||||
```bash
|
||||
cd frontend
|
||||
npm run lint
|
||||
npm test -- --run
|
||||
npm run build
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# Authentification et sécurité
|
||||
|
||||
Le projet met en œuvre plusieurs mécanismes de sécurité.
|
||||
|
||||
## Authentification
|
||||
|
||||
- JWT ;
|
||||
- email / mot de passe ;
|
||||
- Google OAuth 2.0 ;
|
||||
- vérification email.
|
||||
|
||||
## Protection des mots de passe
|
||||
|
||||
Les mots de passe sont hachés avec **Bcrypt** avant stockage.
|
||||
|
||||
## Validation
|
||||
|
||||
Les données reçues par l’API sont validées avec **Zod**.
|
||||
|
||||
## Contrôle d’accès
|
||||
|
||||
Des middlewares backend contrôlent :
|
||||
|
||||
- l’authentification ;
|
||||
- le rôle ;
|
||||
- l’accès aux routes protégées.
|
||||
|
||||
## Sécurité HTTP
|
||||
|
||||
Le backend utilise notamment :
|
||||
|
||||
- Helmet ;
|
||||
- rate limiting ;
|
||||
- validation des entrées.
|
||||
|
||||
## HTTPS
|
||||
|
||||
Traefik assure le routage HTTP/HTTPS vers les différents services.
|
||||
|
||||
---
|
||||
|
||||
# Gestion des secrets
|
||||
|
||||
Les secrets ne doivent jamais être stockés directement dans le dépôt Git.
|
||||
|
||||
Sont notamment concernés :
|
||||
|
||||
```text
|
||||
JWT_SECRET
|
||||
DATABASE_URL / mots de passe PostgreSQL
|
||||
MAIL_USER
|
||||
MAIL_PASS
|
||||
GOOGLE_CLIENT_ID
|
||||
GOOGLE_CLIENT_SECRET
|
||||
FACEBOOK_APP_ID
|
||||
FACEBOOK_APP_SECRET
|
||||
identifiants du Docker Registry
|
||||
```
|
||||
|
||||
Les valeurs sensibles de déploiement sont externalisées sur le serveur ou injectées par Jenkins.
|
||||
|
||||
> Les fichiers contenant des secrets réels ne doivent jamais être ajoutés au dépôt.
|
||||
|
||||
---
|
||||
|
||||
# Docker
|
||||
|
||||
Le frontend et le backend disposent chacun de leur propre image Docker.
|
||||
|
||||
## Backend
|
||||
|
||||
```text
|
||||
Node.js 22
|
||||
↓
|
||||
npm ci
|
||||
↓
|
||||
Prisma generate
|
||||
↓
|
||||
Application Express
|
||||
```
|
||||
|
||||
## Frontend
|
||||
|
||||
Build multi-stage :
|
||||
|
||||
```text
|
||||
Node.js 22
|
||||
↓
|
||||
npm ci
|
||||
↓
|
||||
Vite build
|
||||
↓
|
||||
Nginx
|
||||
```
|
||||
|
||||
Les images sont versionnées et publiées dans le Registry privé par Jenkins.
|
||||
|
||||
---
|
||||
|
||||
# Docker Compose
|
||||
|
||||
Chaque environnement possède son propre fichier Compose :
|
||||
|
||||
```text
|
||||
deploy/dev/docker-compose.yml
|
||||
deploy/preprod/docker-compose.yml
|
||||
deploy/prod/docker-compose.yml
|
||||
```
|
||||
|
||||
Chaque stack contient notamment :
|
||||
|
||||
```text
|
||||
Frontend
|
||||
Backend
|
||||
PostgreSQL
|
||||
```
|
||||
|
||||
Les stacks sont isolées avec leurs propres conteneurs, réseaux, données et paramètres d’environnement.
|
||||
|
||||
---
|
||||
|
||||
# Reverse proxy et HTTPS
|
||||
|
||||
**Traefik** constitue le point d’entrée HTTP/HTTPS de l’infrastructure.
|
||||
|
||||
Il permet notamment :
|
||||
|
||||
- le routage par nom de domaine ;
|
||||
- l’exposition des frontends ;
|
||||
- l’exposition des APIs ;
|
||||
- la terminaison TLS ;
|
||||
- la gestion des certificats HTTPS.
|
||||
|
||||
Seuls les ports nécessaires sont exposés publiquement.
|
||||
|
||||
---
|
||||
|
||||
# Monitoring
|
||||
|
||||
La plateforme dispose d’une stack de supervision.
|
||||
|
||||
```text
|
||||
Node Exporter ──┐
|
||||
│
|
||||
cAdvisor ───────┼──► Prometheus ───► Grafana
|
||||
│
|
||||
Services ───────┘
|
||||
```
|
||||
|
||||
### Prometheus
|
||||
|
||||
Collecte les métriques.
|
||||
|
||||
### Grafana
|
||||
|
||||
Permet de construire et consulter les tableaux de bord.
|
||||
|
||||
### cAdvisor
|
||||
|
||||
Expose les métriques relatives aux conteneurs Docker.
|
||||
|
||||
### Node Exporter
|
||||
|
||||
Expose les métriques système du serveur.
|
||||
|
||||
---
|
||||
|
||||
# Documentation API
|
||||
|
||||
Le backend expose une documentation Swagger / OpenAPI.
|
||||
|
||||
En environnement local :
|
||||
|
||||
```text
|
||||
http://localhost:5000/api-docs
|
||||
```
|
||||
|
||||
Elle permet de :
|
||||
|
||||
- consulter les routes ;
|
||||
- consulter les schémas ;
|
||||
- examiner les paramètres ;
|
||||
- tester les endpoints ;
|
||||
- utiliser l’authentification prévue par l’API.
|
||||
|
||||
---
|
||||
|
||||
# Installation locale
|
||||
|
||||
## 1. Cloner le dépôt
|
||||
|
||||
```bash
|
||||
git clone <URL_DU_DEPOT>
|
||||
cd THE-TIP-TOP
|
||||
```
|
||||
|
||||
## 2. Backend
|
||||
|
||||
```bash
|
||||
cd backend
|
||||
npm install
|
||||
```
|
||||
|
||||
Configurer les variables d’environnement locales puis :
|
||||
|
||||
```bash
|
||||
npx prisma generate
|
||||
npx prisma migrate dev
|
||||
npx prisma db seed
|
||||
npm run dev
|
||||
```
|
||||
|
||||
## 3. Frontend
|
||||
|
||||
Dans un second terminal :
|
||||
|
||||
```bash
|
||||
cd frontend
|
||||
npm install
|
||||
npm run dev
|
||||
```
|
||||
|
||||
Le frontend local est généralement accessible sur :
|
||||
|
||||
```text
|
||||
http://localhost:5173
|
||||
```
|
||||
|
||||
et l’API sur :
|
||||
|
||||
```text
|
||||
http://localhost:5000
|
||||
```
|
||||
|
||||
Consulter les README des sous-projets pour les détails de configuration.
|
||||
|
||||
---
|
||||
|
||||
# Base de données
|
||||
|
||||
Le projet utilise **PostgreSQL 16** avec **Prisma ORM 6**.
|
||||
|
||||
Commandes Prisma utiles :
|
||||
|
||||
```bash
|
||||
npx prisma generate
|
||||
npx prisma migrate dev
|
||||
npx prisma migrate deploy
|
||||
npx prisma db seed
|
||||
npx prisma studio
|
||||
```
|
||||
|
||||
En environnement déployé, les migrations sont appliquées avec `prisma migrate deploy`.
|
||||
|
||||
---
|
||||
|
||||
# Qualité logicielle
|
||||
|
||||
Le projet applique plusieurs niveaux de contrôle :
|
||||
|
||||
```text
|
||||
Code
|
||||
↓
|
||||
ESLint
|
||||
↓
|
||||
Tests unitaires / fonctionnels
|
||||
↓
|
||||
Tests backend / E2E
|
||||
↓
|
||||
Build
|
||||
↓
|
||||
Docker Build
|
||||
↓
|
||||
Déploiement
|
||||
```
|
||||
|
||||
Un échec dans une étape critique provoque l’échec du pipeline et empêche la promotion normale de la version.
|
||||
|
||||
---
|
||||
|
||||
# Infrastructure DevOps
|
||||
|
||||
Vue simplifiée :
|
||||
|
||||
```text
|
||||
┌───────────────┐
|
||||
│ Gitea │
|
||||
└───────┬───────┘
|
||||
│ Webhook
|
||||
▼
|
||||
┌───────────────┐
|
||||
│ Jenkins │
|
||||
└───────┬───────┘
|
||||
│
|
||||
Tests / Build / Docker
|
||||
│
|
||||
▼
|
||||
┌───────────────┐
|
||||
│Docker Registry│
|
||||
└───────┬───────┘
|
||||
│
|
||||
┌───────────────┼───────────────┐
|
||||
▼ ▼ ▼
|
||||
DEV PREPROD PROD
|
||||
│ │ │
|
||||
└───────────────┼───────────────┘
|
||||
▼
|
||||
Traefik
|
||||
│
|
||||
HTTPS
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# État du projet
|
||||
|
||||
Le projet dispose notamment de :
|
||||
|
||||
- frontend React opérationnel ;
|
||||
- backend Express opérationnel ;
|
||||
- PostgreSQL et Prisma ;
|
||||
- authentification JWT ;
|
||||
- Google OAuth 2.0 ;
|
||||
- vérification email ;
|
||||
- gestion CLIENT / EMPLOYEE / ADMIN ;
|
||||
- jeu-concours et gestion des gains ;
|
||||
- tirage final ;
|
||||
- tests automatisés ;
|
||||
- documentation Swagger ;
|
||||
- images Docker ;
|
||||
- Registry privé ;
|
||||
- pipeline Jenkins multibranch ;
|
||||
- environnements DEV / PREPROD / PROD ;
|
||||
- déploiements Docker Compose ;
|
||||
- reverse proxy Traefik ;
|
||||
- HTTPS ;
|
||||
- monitoring Prometheus / Grafana.
|
||||
|
||||
---
|
||||
|
||||
# Documentation complémentaire
|
||||
|
||||
Documentation backend :
|
||||
|
||||
```text
|
||||
backend/README.md
|
||||
```
|
||||
|
||||
Documentation frontend :
|
||||
|
||||
```text
|
||||
frontend/README.md
|
||||
```
|
||||
|
||||
Ces fichiers détaillent respectivement l’API et l’application React.
|
||||
|
||||
---
|
||||
|
||||
# Projet académique
|
||||
|
||||
Projet réalisé dans le cadre de la certification :
|
||||
|
||||
**Expert en Stratégie et Transformation Digitale**
|
||||
|
||||
Le cas **Thé Tip Top** est utilisé comme contexte métier fictif pour la conception, le développement, les tests, la sécurisation, l’industrialisation et le déploiement de l’application.
|
||||
@@ -2,367 +2,284 @@
|
||||
|
||||
## Présentation
|
||||
|
||||
Ce projet correspond au backend du jeu-concours organisé par **Thé Tip Top** à l'occasion de l'ouverture de sa 10ᵉ boutique à Nice.
|
||||
Backend REST du jeu-concours fictif **Thé Tip Top**, réalisé dans le cadre de la certification **Expert en Stratégie et Transformation Digitale**.
|
||||
|
||||
L'application permet aux clients de participer à un jeu-concours via un code présent sur leur ticket de caisse, de consulter leurs gains et de réclamer leurs lots en boutique.
|
||||
L’API fournit les services des espaces **CLIENT**, **EMPLOYEE** et **ADMIN** et prend notamment en charge :
|
||||
|
||||
Le backend expose une **API** **REST** sécurisée utilisée par :
|
||||
|
||||
- l'application client (participants)
|
||||
- l'espace employé en boutique
|
||||
- l'espace administrateur
|
||||
- les futurs services externes de l'écosystème Thé Tip Top
|
||||
- inscription, vérification email et connexion ;
|
||||
- authentification JWT et Google OAuth 2.0 ;
|
||||
- rôles et autorisations ;
|
||||
- tickets, participations et gains ;
|
||||
- remise des lots ;
|
||||
- configuration des phases du jeu ;
|
||||
- tirage au sort final ;
|
||||
- notifications email ;
|
||||
- administration et statistiques.
|
||||
|
||||
---
|
||||
|
||||
## Fonctionnalités
|
||||
## Stack technique
|
||||
|
||||
### Authentification
|
||||
| Technologie | Utilisation |
|
||||
|---|---|
|
||||
| Node.js 22 | Runtime |
|
||||
| Express.js | API REST |
|
||||
| PostgreSQL 16 | Base de données |
|
||||
| Prisma ORM 6 | ORM et migrations |
|
||||
| JWT | Authentification |
|
||||
| Passport.js | Authentification externe |
|
||||
| Google OAuth 2.0 | Connexion Google |
|
||||
| Bcrypt | Hachage des mots de passe |
|
||||
| Zod | Validation |
|
||||
| Nodemailer | Emails |
|
||||
| Helmet | Sécurité HTTP |
|
||||
| express-rate-limit | Rate limiting |
|
||||
| Swagger / OpenAPI | Documentation |
|
||||
| Jest / Supertest | Tests |
|
||||
| Docker | Conteneurisation |
|
||||
|
||||
- Inscription utilisateur
|
||||
- Connexion sécurisée
|
||||
- Authentification **JWT**
|
||||
- Gestion des rôles (**CLIENT**, **EMPLOYEE**, **ADMIN**)
|
||||
- Hachage des mots de passe avec Bcrypt
|
||||
- Validation des données avec **Zod**
|
||||
## Authentification
|
||||
|
||||
### Jeu-concours
|
||||
### Email / mot de passe
|
||||
|
||||
- Génération automatique des lots
|
||||
- Génération des tickets gagnants
|
||||
- Participation via code ticket unique
|
||||
- Attribution automatique des gains
|
||||
- Historique des participations
|
||||
- Historique des gains remportés
|
||||
Le parcours comprend l’inscription, le hachage Bcrypt, l’envoi d’un code de vérification par email, la validation du compte, la connexion et la génération d’un JWT.
|
||||
|
||||
### Espace Employé
|
||||
### Google OAuth 2.0
|
||||
|
||||
- Recherche d'un gain via un code ticket
|
||||
- Vérification du statut du gain
|
||||
- Validation de la remise d'un lot
|
||||
- Mise à jour automatique du statut du gain
|
||||
|
||||
### Espace Administrateur
|
||||
|
||||
- Tableau de bord statistique
|
||||
- Liste des participants
|
||||
- Liste des contacts ayant accepté les communications marketing
|
||||
- Création de comptes employés
|
||||
- Tirage au sort du grand gagnant
|
||||
- Consultation du gagnant du gros lot
|
||||
|
||||
### Documentation API
|
||||
|
||||
- Documentation interactive avec **Swagger UI**
|
||||
- Génération automatique de la documentation via **Swagger JSDoc**
|
||||
- Tests des endpoints directement depuis le navigateur
|
||||
|
||||
---
|
||||
|
||||
## Architecture Technique
|
||||
|
||||
### Backend
|
||||
|
||||
- Node.js
|
||||
- Express.js
|
||||
|
||||
### Base de données
|
||||
|
||||
- PostgreSQL
|
||||
- **Prisma **ORM** 6**
|
||||
- Prisma Client 6
|
||||
- Prisma Migrate
|
||||
- Prisma Studio
|
||||
|
||||
### Validation des données
|
||||
|
||||
- **Zod**
|
||||
- Middleware de validation personnalisé
|
||||
|
||||
### Sécurité
|
||||
|
||||
- **JWT** (**JSON** Web Token)
|
||||
- Bcrypt
|
||||
- Gestion des rôles et permissions
|
||||
- Validation des entrées utilisateur
|
||||
|
||||
### Documentation
|
||||
|
||||
- Swagger UI
|
||||
- Swagger JSDoc
|
||||
- OpenAPI 3.0
|
||||
|
||||
---
|
||||
|
||||
## Installation
|
||||
|
||||
### Cloner le projet
|
||||
|
||||
```bash
|
||||
git clone <url-du-repository>
|
||||
cd the-tip-top-backend
|
||||
```text
|
||||
Utilisateur
|
||||
↓
|
||||
Frontend
|
||||
↓
|
||||
API /api/auth/google
|
||||
↓
|
||||
Google OAuth 2.0
|
||||
↓
|
||||
Callback backend
|
||||
↓
|
||||
Création / récupération utilisateur
|
||||
↓
|
||||
JWT
|
||||
↓
|
||||
Redirection frontend
|
||||
```
|
||||
|
||||
### Installer les dépendances
|
||||
Les secrets OAuth restent hors du dépôt Git.
|
||||
|
||||
## Rôles
|
||||
|
||||
### CLIENT
|
||||
- participer au jeu ;
|
||||
- consulter ses gains ;
|
||||
- gérer son profil.
|
||||
|
||||
### EMPLOYEE
|
||||
- rechercher et vérifier un gain ;
|
||||
- valider la remise d’un lot.
|
||||
|
||||
### ADMIN
|
||||
- consulter les statistiques ;
|
||||
- créer des employés ;
|
||||
- configurer le jeu ;
|
||||
- effectuer le tirage final ;
|
||||
- consulter le grand gagnant.
|
||||
|
||||
## Jeu-concours
|
||||
|
||||
Phases applicatives :
|
||||
|
||||
- `NOT_CONFIGURED`
|
||||
- `SCHEDULED`
|
||||
- `OPEN`
|
||||
- `CLAIM_ONLY`
|
||||
- `CLOSED`
|
||||
|
||||
Principales règles métier :
|
||||
|
||||
- un ticket ne peut être utilisé qu’une fois ;
|
||||
- les tickets sont gagnants ;
|
||||
- les comptes EMPLOYEE et ADMIN ne participent pas comme clients ;
|
||||
- plusieurs participations d’un client n’augmentent pas ses chances au tirage final ;
|
||||
- un seul grand gagnant peut être enregistré ;
|
||||
- le tirage final respecte les contraintes temporelles du jeu.
|
||||
|
||||
## Notifications email
|
||||
|
||||
Nodemailer est utilisé notamment pour la vérification des comptes et les notifications liées aux gains et au tirage final. La configuration SMTP est fournie par variables d’environnement.
|
||||
|
||||
## Sécurité
|
||||
|
||||
- Bcrypt ;
|
||||
- JWT ;
|
||||
- Google OAuth 2.0 ;
|
||||
- Zod ;
|
||||
- contrôle d’accès par rôle ;
|
||||
- Helmet ;
|
||||
- rate limiting ;
|
||||
- secrets externalisés ;
|
||||
- HTTPS via Traefik ;
|
||||
- séparation DEV / PREPROD / PROD.
|
||||
|
||||
> Ne jamais versionner les mots de passe, tokens, secrets JWT, secrets OAuth ou identifiants SMTP.
|
||||
|
||||
## Modèle de données principal
|
||||
|
||||
- `User` : utilisateurs et rôles CLIENT / EMPLOYEE / ADMIN.
|
||||
- `Ticket` : code unique, lot associé et état d’utilisation.
|
||||
- `Lot` : lot, description, valeur et répartition.
|
||||
- `Participation` : participation d’un utilisateur avec un ticket.
|
||||
- `Claim` : gestion de la remise du gain.
|
||||
- `GameSettings` : configuration temporelle du concours.
|
||||
- `GrandPrizeWinner` : résultat du tirage final.
|
||||
|
||||
## Installation locale
|
||||
|
||||
Prérequis : Node.js 22, npm et PostgreSQL 16.
|
||||
|
||||
```bash
|
||||
npm install
|
||||
```
|
||||
|
||||
### Variables d'environnement
|
||||
Exemple de `.env` local :
|
||||
|
||||
Créer un fichier `.env` à la racine du projet :
|
||||
|
||||
|
||||
```env **PORT**=**5000**```
|
||||
|
||||
```DATABASE_URL="postgresql://postgres:password@localhost:**5432**/the_tip_top_db*```
|
||||
|
||||
```JWT_SECRET=*your_secret_key" ```
|
||||
|
||||
---
|
||||
|
||||
## Base de données
|
||||
|
||||
### Générer les migrations
|
||||
|
||||
```bash
|
||||
npx prisma migrate dev
|
||||
```env
|
||||
PORT=5000
|
||||
NODE_ENV=development
|
||||
DATABASE_URL="postgresql://postgres:password@localhost:5432/the_tip_top_db"
|
||||
JWT_SECRET="change_me"
|
||||
APP_URL="http://localhost:5000"
|
||||
FRONTEND_URL="http://localhost:5173"
|
||||
MAIL_HOST="smtp.example.com"
|
||||
MAIL_PORT=587
|
||||
MAIL_USER="user@example.com"
|
||||
MAIL_PASS="change_me"
|
||||
MAIL_FROM="Thé Tip Top <user@example.com>"
|
||||
GOOGLE_CLIENT_ID=""
|
||||
GOOGLE_CLIENT_SECRET=""
|
||||
```
|
||||
|
||||
### Générer Prisma Client
|
||||
Ces valeurs sont uniquement des exemples.
|
||||
|
||||
## Prisma
|
||||
|
||||
```bash
|
||||
npx prisma generate
|
||||
```
|
||||
|
||||
### Exécuter le seed de la base
|
||||
|
||||
```bash
|
||||
npx prisma migrate dev
|
||||
npx prisma migrate deploy
|
||||
npx prisma db seed
|
||||
```
|
||||
|
||||
### Générer les tickets du jeu-concours
|
||||
|
||||
```bash
|
||||
npm run generate:tickets
|
||||
```
|
||||
|
||||
### Ouvrir Prisma Studio
|
||||
|
||||
```bash
|
||||
npx prisma studio
|
||||
```
|
||||
|
||||
---
|
||||
## Lancement
|
||||
|
||||
## Technologies utilisées
|
||||
|
||||
| Technologie | Version |
|
||||
| ----------- | ---------------- |
|
||||
| Node.js | 20+ |
|
||||
| Express.js | 5 |
|
||||
| PostgreSQL | 16+ |
|
||||
| Prisma ORM | 6 |
|
||||
| JWT | Dernière version |
|
||||
| Bcrypt | Dernière version |
|
||||
| Zod | Dernière version |
|
||||
| Swagger UI | Dernière version |
|
||||
|
||||
---
|
||||
|
||||
## Lancement du projet
|
||||
|
||||
### Développement
|
||||
|
||||
Le projet utilise **Nodemon** afin de redémarrer automatiquement le serveur lors des modifications du code.
|
||||
Développement :
|
||||
|
||||
```bash
|
||||
npm run dev
|
||||
|
||||
```
|
||||
|
||||
Serveur :
|
||||
Démarrage standard :
|
||||
|
||||
```txt [http://localhost:**5000**](http://localhost:**5000**) ```
|
||||
```bash
|
||||
npm start
|
||||
```
|
||||
|
||||
---
|
||||
API locale généralement disponible sur `http://localhost:5000`.
|
||||
|
||||
## Tests
|
||||
|
||||
```bash
|
||||
npm test
|
||||
```
|
||||
|
||||
Les tests Jest/Supertest couvrent notamment l’inscription, la connexion, les autorisations, les participations, les phases du jeu, le tirage final, les notifications, l’authentification Google et des scénarios E2E.
|
||||
|
||||
Dans Jenkins, une base PostgreSQL temporaire est créée. Les migrations et le seed sont exécutés avant les tests, puis les résultats sont publiés au format JUnit.
|
||||
|
||||
## Documentation API
|
||||
|
||||
La documentation Swagger est accessible à l'adresse :
|
||||
Swagger UI est accessible localement sur :
|
||||
|
||||
```txt [http://localhost:**5000**/api-docs](http://localhost:**5000**/api-docs) ```
|
||||
|
||||
Fonctionnalités disponibles :
|
||||
|
||||
- Consultation de toutes les routes
|
||||
- Visualisation des schémas de données
|
||||
- Test des endpoints
|
||||
- Authentification via **JWT** avec le bouton **Authorize**
|
||||
|
||||
---
|
||||
|
||||
## Gestion des rôles
|
||||
|
||||
### CLIENT
|
||||
|
||||
Peut :
|
||||
|
||||
- Participer au jeu-concours
|
||||
- Consulter ses gains
|
||||
- Consulter son profil
|
||||
|
||||
### EMPLOYEE
|
||||
|
||||
Peut :
|
||||
|
||||
- Rechercher un gain
|
||||
- Vérifier les informations du gagnant
|
||||
- Valider la remise d'un lot
|
||||
|
||||
### ADMIN
|
||||
|
||||
Peut :
|
||||
|
||||
- Accéder aux statistiques
|
||||
- Créer des employés
|
||||
- Gérer les campagnes emailing
|
||||
- Effectuer le tirage au sort final
|
||||
- Consulter le gagnant du gros lot
|
||||
|
||||
---
|
||||
|
||||
## Routes API
|
||||
|
||||
### Auth
|
||||
|
||||
| Méthode | Route |
|
||||
| ------- | ------------------ |
|
||||
| POST | /api/auth/register |
|
||||
| POST | /api/auth/login |
|
||||
| GET | /api/auth/me |
|
||||
|
||||
### Game
|
||||
|
||||
| Méthode | Route |
|
||||
| ------- | --------------------- |
|
||||
| POST | /api/game/participate |
|
||||
| GET | /api/game/my-gains |
|
||||
|
||||
### Employee
|
||||
|
||||
| Méthode | Route |
|
||||
| ------- | ---------------------------- |
|
||||
| GET | /api/employee/ticket/ |
|
||||
| PATCH | /api/employee/claim//deliver |
|
||||
|
||||
### Admin
|
||||
|
||||
| Méthode | Route |
|
||||
| ------- | -------------------- |
|
||||
| GET | /api/admin/stats |
|
||||
| GET | /api/admin/users |
|
||||
| GET | /api/admin/emailing |
|
||||
| POST | /api/admin/employees |
|
||||
| POST | /api/admin/draw |
|
||||
| GET | /api/admin/draw |
|
||||
|
||||
---
|
||||
|
||||
## Validation avec Zod
|
||||
|
||||
Toutes les données reçues par l'**API** sont validées avant traitement grâce à **Zod**.
|
||||
|
||||
Exemples :
|
||||
|
||||
- Inscription utilisateur
|
||||
- Connexion
|
||||
- Création d'employés
|
||||
- Participation au jeu-concours
|
||||
- Validation des paramètres de requête
|
||||
|
||||
Cette approche garantit :
|
||||
|
||||
- Des données cohérentes
|
||||
- Une meilleure sécurité
|
||||
- Des messages d'erreur explicites
|
||||
- Une maintenance facilitée
|
||||
|
||||
---
|
||||
|
||||
## Modèle de données principal
|
||||
|
||||
### User
|
||||
|
||||
- **CLIENT**
|
||||
- **EMPLOYEE**
|
||||
- **ADMIN**
|
||||
|
||||
### Ticket
|
||||
|
||||
- Code unique
|
||||
- Gain associé
|
||||
- Utilisé / Non utilisé
|
||||
|
||||
### Lot
|
||||
|
||||
- Nom
|
||||
- Description
|
||||
- Valeur
|
||||
- Pourcentage de répartition
|
||||
|
||||
### Participation
|
||||
|
||||
- Utilisateur
|
||||
- Ticket
|
||||
- Lot gagné
|
||||
|
||||
### Claim
|
||||
|
||||
- **PENDING**
|
||||
- **DELIVERED**
|
||||
- **CANCELLED**
|
||||
|
||||
### GrandPrizeWinner
|
||||
|
||||
- Gagnant du gros lot
|
||||
- Date du tirage
|
||||
- Récompense
|
||||
|
||||
---
|
||||
|
||||
## Prisma ORM 6
|
||||
|
||||
Le projet utilise **Prisma **ORM** 6** pour :
|
||||
|
||||
- La modélisation des données
|
||||
- Les migrations de base de données
|
||||
- Les requêtes **SQL** typées
|
||||
- La génération automatique du client Prisma
|
||||
- L'administration de la base via Prisma Studio
|
||||
|
||||
Commandes utiles :
|
||||
|
||||
```bash
|
||||
npx prisma migrate dev npx prisma generate npx prisma db seed npx prisma studio
|
||||
```text
|
||||
http://localhost:5000/api-docs
|
||||
```
|
||||
|
||||
---
|
||||
## CI/CD
|
||||
|
||||
## Règles métier
|
||||
Le projet utilise Gitea, Jenkins, Docker et un Registry privé.
|
||||
|
||||
- Tous les tickets sont gagnants.
|
||||
- Un ticket ne peut être utilisé qu'une seule fois.
|
||||
- Les gains sont associés aux tickets dès leur génération.
|
||||
- Plusieurs participations n'augmentent pas les chances de remporter le gros lot.
|
||||
- Un seul gagnant du gros lot peut être enregistré.
|
||||
- Les gains non récupérés dans les délais peuvent être annulés.
|
||||
```text
|
||||
feature/* → CI uniquement
|
||||
develop → DEV automatique
|
||||
release-* → PREPROD automatique
|
||||
main → validation manuelle → PROD
|
||||
```
|
||||
|
||||
---
|
||||
Pipeline :
|
||||
|
||||
## Auteur
|
||||
```text
|
||||
Checkout
|
||||
↓
|
||||
Tests backend + PostgreSQL temporaire
|
||||
↓
|
||||
Lint + Build frontend
|
||||
↓
|
||||
Docker Build
|
||||
↓
|
||||
Registry
|
||||
↓
|
||||
Déploiement
|
||||
↓
|
||||
Contrôle des conteneurs
|
||||
```
|
||||
|
||||
Projet réalisé dans le cadre de la certification : **Expert en Stratégie et Transformation Digitale**
|
||||
## Environnements
|
||||
|
||||
| Environnement | Frontend | API |
|
||||
|---|---|---|
|
||||
| DEV | `https://dev.dsp5-archi-o24a-4-5-g4.fr` | `https://api-dev.dsp5-archi-o24a-4-5-g4.fr` |
|
||||
| PREPROD | `https://preprod.dsp5-archi-o24a-4-5-g4.fr` | `https://api-preprod.dsp5-archi-o24a-4-5-g4.fr` |
|
||||
| PROD | `https://dsp5-archi-o24a-4-5-g4.fr` | `https://api.dsp5-archi-o24a-4-5-g4.fr` |
|
||||
|
||||
## Infrastructure
|
||||
|
||||
- Docker / Docker Compose ;
|
||||
- Gitea ;
|
||||
- Jenkins ;
|
||||
- Docker Registry ;
|
||||
- Traefik ;
|
||||
- Let's Encrypt / HTTPS ;
|
||||
- PostgreSQL ;
|
||||
- Prometheus ;
|
||||
- Grafana ;
|
||||
- cAdvisor ;
|
||||
- Node Exporter.
|
||||
|
||||
## Arborescence simplifiée
|
||||
|
||||
```text
|
||||
backend/
|
||||
├── prisma/
|
||||
│ ├── migrations/
|
||||
│ ├── schema.prisma
|
||||
│ └── seed.js
|
||||
├── src/
|
||||
│ ├── config/
|
||||
│ ├── controllers/
|
||||
│ ├── docs/
|
||||
│ ├── middlewares/
|
||||
│ ├── routes/
|
||||
│ ├── utils/
|
||||
│ ├── validations/
|
||||
│ └── app.js
|
||||
├── tests/
|
||||
├── Dockerfile
|
||||
├── package.json
|
||||
└── README.md
|
||||
```
|
||||
|
||||
## Projet
|
||||
|
||||
Projet étudiant fictif réalisé dans le cadre de la certification **Expert en Stratégie et Transformation Digitale**.
|
||||
|
||||
Client fictif : **Thé Tip Top**.
|
||||
4
frontend/.gitignore
vendored
4
frontend/.gitignore
vendored
@@ -22,3 +22,7 @@ dist-ssr
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
|
||||
# Tests / coverage
|
||||
coverage/
|
||||
test-results/
|
||||
|
||||
@@ -1,16 +1,275 @@
|
||||
# React + Vite
|
||||
# Thé Tip Top – Frontend
|
||||
|
||||
This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
|
||||
## Présentation
|
||||
|
||||
Currently, two official plugins are available:
|
||||
Frontend React du jeu-concours fictif **Thé Tip Top**, réalisé dans le cadre de la certification **Expert en Stratégie et Transformation Digitale**.
|
||||
|
||||
- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Oxc](https://oxc.rs)
|
||||
- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/)
|
||||
L’interface communique avec l’API backend et propose des parcours adaptés aux visiteurs, clients, employés et administrateurs.
|
||||
|
||||
## React Compiler
|
||||
## Stack technique
|
||||
|
||||
The React Compiler is not enabled on this template because of its impact on dev & build performances. To add it, see [this documentation](https://react.dev/learn/react-compiler/installation).
|
||||
| Technologie | Utilisation |
|
||||
|---|---|
|
||||
| React | Interface utilisateur |
|
||||
| Vite | Développement et build |
|
||||
| React Router | Navigation |
|
||||
| Tailwind CSS | Interface responsive |
|
||||
| Vitest | Tests |
|
||||
| Testing Library | Tests fonctionnels |
|
||||
| ESLint | Analyse statique |
|
||||
| Nginx | Serveur web du conteneur |
|
||||
| Docker | Conteneurisation |
|
||||
|
||||
## Expanding the ESLint configuration
|
||||
## Fonctionnalités
|
||||
|
||||
If you are developing a production application, we recommend using TypeScript with type-aware lint rules enabled. Check out the [TS template](https://github.com/vitejs/vite/tree/main/packages/create-vite/template-react-ts) for information on how to integrate TypeScript and [`typescript-eslint`](https://typescript-eslint.io) in your project.
|
||||
### Visiteur
|
||||
- accueil ;
|
||||
- règles du jeu ;
|
||||
- inscription ;
|
||||
- connexion ;
|
||||
- connexion Google ;
|
||||
- pages légales et confidentialité ;
|
||||
- CGU et accessibilité ;
|
||||
- contact ;
|
||||
- plan du site.
|
||||
|
||||
### Client
|
||||
- profil ;
|
||||
- saisie d’un code unique ;
|
||||
- participation ;
|
||||
- consultation des gains ;
|
||||
- gestion de session.
|
||||
|
||||
### Employé
|
||||
- recherche d’un gain ;
|
||||
- vérification d’un ticket ;
|
||||
- validation de la remise d’un lot.
|
||||
|
||||
### Administrateur
|
||||
- statistiques ;
|
||||
- gestion administrative ;
|
||||
- création d’employés ;
|
||||
- configuration du jeu ;
|
||||
- tirage au sort ;
|
||||
- consultation du grand gagnant.
|
||||
|
||||
## Authentification
|
||||
|
||||
Le frontend prend en charge l’authentification email/mot de passe, la vérification email, le JWT, les routes protégées et Google OAuth 2.0.
|
||||
|
||||
Flux OAuth :
|
||||
|
||||
```text
|
||||
Frontend
|
||||
↓
|
||||
/api/auth/google
|
||||
↓
|
||||
Google
|
||||
↓
|
||||
Callback backend
|
||||
↓
|
||||
/auth/callback frontend
|
||||
↓
|
||||
JWT + utilisateur
|
||||
↓
|
||||
Redirection selon le rôle
|
||||
```
|
||||
|
||||
## Rôles
|
||||
|
||||
- `CLIENT`
|
||||
- `EMPLOYEE`
|
||||
- `ADMIN`
|
||||
|
||||
Les protections frontend améliorent l’expérience utilisateur ; les autorisations sensibles restent également contrôlées côté backend.
|
||||
|
||||
## Configuration API
|
||||
|
||||
Le frontend utilise :
|
||||
|
||||
```env
|
||||
VITE_API_URL=http://localhost:5000
|
||||
```
|
||||
|
||||
Les services utilisent cette URL pour les routes `/api/auth`, `/api/game`, `/api/employee` et `/api/admin`.
|
||||
|
||||
Dans Jenkins, `VITE_API_URL` est injectée au moment du build Docker selon l’environnement cible.
|
||||
|
||||
## Installation locale
|
||||
|
||||
Prérequis : Node.js 22 et npm.
|
||||
|
||||
```bash
|
||||
npm install
|
||||
```
|
||||
|
||||
Puis, si nécessaire :
|
||||
|
||||
```env
|
||||
VITE_API_URL=http://localhost:5000
|
||||
```
|
||||
|
||||
## Développement
|
||||
|
||||
```bash
|
||||
npm run dev
|
||||
```
|
||||
|
||||
L’application Vite est généralement disponible sur `http://localhost:5173`.
|
||||
|
||||
## Qualité et tests
|
||||
|
||||
Lint :
|
||||
|
||||
```bash
|
||||
npm run lint
|
||||
```
|
||||
|
||||
Tests :
|
||||
|
||||
```bash
|
||||
npm test -- --run
|
||||
```
|
||||
|
||||
Build :
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
```
|
||||
|
||||
Les tests couvrent notamment la connexion, l’inscription, la saisie de code, les routes protégées, le contexte d’authentification, les services et la bannière de cookies.
|
||||
|
||||
## Docker
|
||||
|
||||
Le frontend utilise un build multi-stage :
|
||||
|
||||
```text
|
||||
Node.js
|
||||
↓
|
||||
npm ci
|
||||
↓
|
||||
Vite build
|
||||
↓
|
||||
dist/
|
||||
↓
|
||||
Nginx
|
||||
```
|
||||
|
||||
## CI/CD
|
||||
|
||||
```text
|
||||
feature/* → CI uniquement
|
||||
develop → DEV automatique
|
||||
release-* → PREPROD automatique
|
||||
main → validation manuelle → PROD
|
||||
```
|
||||
|
||||
Pour le frontend, Jenkins exécute notamment :
|
||||
|
||||
1. `npm ci` ;
|
||||
2. `npm run lint` ;
|
||||
3. `npm run build` ;
|
||||
4. Docker build ;
|
||||
5. publication dans le Registry ;
|
||||
6. déploiement dans l’environnement cible.
|
||||
|
||||
## Environnements
|
||||
|
||||
| Environnement | Frontend | API |
|
||||
|---|---|---|
|
||||
| DEV | `https://dev.dsp5-archi-o24a-4-5-g4.fr` | `https://api-dev.dsp5-archi-o24a-4-5-g4.fr` |
|
||||
| PREPROD | `https://preprod.dsp5-archi-o24a-4-5-g4.fr` | `https://api-preprod.dsp5-archi-o24a-4-5-g4.fr` |
|
||||
| PROD | `https://dsp5-archi-o24a-4-5-g4.fr` | `https://api.dsp5-archi-o24a-4-5-g4.fr` |
|
||||
|
||||
## Architecture applicative
|
||||
|
||||
```text
|
||||
Navigateur
|
||||
↓ HTTPS
|
||||
Traefik
|
||||
↓
|
||||
Nginx / React
|
||||
↓
|
||||
API Express
|
||||
↓
|
||||
PostgreSQL
|
||||
```
|
||||
|
||||
Le frontend n’accède jamais directement à PostgreSQL.
|
||||
|
||||
## Pages principales
|
||||
|
||||
Le projet comprend notamment les pages suivantes :
|
||||
|
||||
- accueil ;
|
||||
- inscription ;
|
||||
- connexion ;
|
||||
- callback OAuth ;
|
||||
- définition du mot de passe ;
|
||||
- saisie du code unique ;
|
||||
- gains ;
|
||||
- profil ;
|
||||
- espace employé ;
|
||||
- espace administrateur ;
|
||||
- règles du jeu ;
|
||||
- contact ;
|
||||
- mentions légales ;
|
||||
- confidentialité ;
|
||||
- CGU ;
|
||||
- accessibilité ;
|
||||
- plan du site ;
|
||||
- page 404.
|
||||
|
||||
## Sécurité
|
||||
|
||||
- routes protégées ;
|
||||
- gestion centralisée de l’authentification ;
|
||||
- traitement des erreurs 401 ;
|
||||
- redirection selon le rôle ;
|
||||
- HTTPS sur les environnements déployés ;
|
||||
- aucun secret OAuth privé dans le frontend.
|
||||
|
||||
> Le `GOOGLE_CLIENT_SECRET`, le secret JWT, les identifiants SMTP et les mots de passe de base de données ne doivent jamais être exposés dans le frontend.
|
||||
|
||||
## Arborescence simplifiée
|
||||
|
||||
```text
|
||||
frontend/
|
||||
├── src/
|
||||
│ ├── components/
|
||||
│ ├── context/
|
||||
│ ├── pages/
|
||||
│ ├── services/
|
||||
│ ├── test/
|
||||
│ └── App.jsx
|
||||
├── Dockerfile
|
||||
├── nginx.conf
|
||||
├── package.json
|
||||
└── README.md
|
||||
```
|
||||
|
||||
## Infrastructure globale
|
||||
|
||||
```text
|
||||
Développeur
|
||||
↓
|
||||
Gitea
|
||||
↓
|
||||
Jenkins
|
||||
↓
|
||||
Tests + Lint + Build
|
||||
↓
|
||||
Docker Registry
|
||||
↓
|
||||
DEV / PREPROD / PROD
|
||||
↓
|
||||
Traefik + HTTPS
|
||||
```
|
||||
|
||||
Supervision : Prometheus, Grafana, cAdvisor et Node Exporter.
|
||||
|
||||
## Projet
|
||||
|
||||
Projet étudiant fictif réalisé dans le cadre de la certification **Expert en Stratégie et Transformation Digitale**.
|
||||
|
||||
Client fictif : **Thé Tip Top**.
|
||||
|
||||
259
frontend/package-lock.json
generated
259
frontend/package-lock.json
generated
@@ -21,6 +21,7 @@
|
||||
"@types/react": "^19.2.14",
|
||||
"@types/react-dom": "^19.2.3",
|
||||
"@vitejs/plugin-react": "^6.0.1",
|
||||
"@vitest/coverage-v8": "^4.1.11",
|
||||
"eslint": "^10.3.0",
|
||||
"eslint-plugin-react-hooks": "^7.1.1",
|
||||
"eslint-plugin-react-refresh": "^0.5.2",
|
||||
@@ -339,6 +340,16 @@
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@bcoe/v8-coverage": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-1.0.2.tgz",
|
||||
"integrity": "sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@bramus/specificity": {
|
||||
"version": "2.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@bramus/specificity/-/specificity-2.4.2.tgz",
|
||||
@@ -1657,17 +1668,48 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@vitest/coverage-v8": {
|
||||
"version": "4.1.11",
|
||||
"resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-4.1.11.tgz",
|
||||
"integrity": "sha512-8MVGEFnJIcdGjcbfKmeq8z0pZHH0JlVtoVZH9Q/qwUp6wyFnEJUBMrw9DCaj+ra3vShGmhavjalMIhPNxZAUcw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@bcoe/v8-coverage": "^1.0.2",
|
||||
"@vitest/utils": "4.1.11",
|
||||
"ast-v8-to-istanbul": "^1.0.0",
|
||||
"istanbul-lib-coverage": "^3.2.2",
|
||||
"istanbul-lib-report": "^3.0.1",
|
||||
"istanbul-reports": "^3.2.0",
|
||||
"magicast": "^0.5.2",
|
||||
"obug": "^2.1.1",
|
||||
"std-env": "^4.0.0-rc.1",
|
||||
"tinyrainbow": "^3.1.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/vitest"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@vitest/browser": "4.1.11",
|
||||
"vitest": "4.1.11"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@vitest/browser": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@vitest/expect": {
|
||||
"version": "4.1.10",
|
||||
"resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.1.10.tgz",
|
||||
"integrity": "sha512-YsCn+qAk1GWjQOWFEsEcL2gNQ0zmVmQu3T03qP6UyjhtmdtwtbuI+DASn/7iQB3HGTXkdBwGddzxPlmiql5vlA==",
|
||||
"version": "4.1.11",
|
||||
"resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.1.11.tgz",
|
||||
"integrity": "sha512-VX2x5vNJXET47KAFzwERI+KRMtTTCSWTfSMKsW7JsUsXV4psq++e3DvZpuTDOpHcxytiDs6p2nhVb2tVDiiUYw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@standard-schema/spec": "^1.1.0",
|
||||
"@types/chai": "^5.2.2",
|
||||
"@vitest/spy": "4.1.10",
|
||||
"@vitest/utils": "4.1.10",
|
||||
"@vitest/spy": "4.1.11",
|
||||
"@vitest/utils": "4.1.11",
|
||||
"chai": "^6.2.2",
|
||||
"tinyrainbow": "^3.1.0"
|
||||
},
|
||||
@@ -1676,13 +1718,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@vitest/mocker": {
|
||||
"version": "4.1.10",
|
||||
"resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.1.10.tgz",
|
||||
"integrity": "sha512-v0xaezt+DKEmKfaxg133ldzADrwLGd7Ze1MfQQTYfvs8OqZIwbxyxaYURivwV7sWy5fqn3rH5uOrSp07bp44Ow==",
|
||||
"version": "4.1.11",
|
||||
"resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.1.11.tgz",
|
||||
"integrity": "sha512-2XJVD55d1o5AZous5CCGKS74g/riOj9odEt2bQpCVZeblHyHdnMeFl4jl0XjU21stf4mbjUkew2eXQZt65g5CQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@vitest/spy": "4.1.10",
|
||||
"@vitest/spy": "4.1.11",
|
||||
"estree-walker": "^3.0.3",
|
||||
"magic-string": "^0.30.21"
|
||||
},
|
||||
@@ -1703,9 +1745,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@vitest/pretty-format": {
|
||||
"version": "4.1.10",
|
||||
"resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.1.10.tgz",
|
||||
"integrity": "sha512-W1HsjSH4MXQ9YfmmhLAoIYf1HRfekQCGngeIgcei6MP5QQGWUe0gkopdZQaVCFO+JDJMrAJGwa5pRpNpvy4P8Q==",
|
||||
"version": "4.1.11",
|
||||
"resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.1.11.tgz",
|
||||
"integrity": "sha512-yiZzPbGTS9Sr/JpFl8zHrcIkAofNbFV6k21vIgQN/cY/oxZeXhJv5sc/MBJ5jFKWmWs+oJHw0UXLZjmf931+Vw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -1716,13 +1758,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@vitest/runner": {
|
||||
"version": "4.1.10",
|
||||
"resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.1.10.tgz",
|
||||
"integrity": "sha512-IKI6kpIH+LmpROplyLwBBaCfMgOZOMsygVa6BARD6ahA04VRuJSa6OaVG7kRvSEMD870Vd91rSSw0eegtWyLGg==",
|
||||
"version": "4.1.11",
|
||||
"resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.1.11.tgz",
|
||||
"integrity": "sha512-LztvUgdwMNJMIkj3hQnnxiC2Xy1zNxq928W/xhjCLaNCzqTZOudjwbQf6v9IntZGPw132i2Lq2rgTRZHD3JHNw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@vitest/utils": "4.1.10",
|
||||
"@vitest/utils": "4.1.11",
|
||||
"pathe": "^2.0.3"
|
||||
},
|
||||
"funding": {
|
||||
@@ -1730,14 +1772,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@vitest/snapshot": {
|
||||
"version": "4.1.10",
|
||||
"resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.1.10.tgz",
|
||||
"integrity": "sha512-xRkfOT1qpTAi/Ti4Y1LtfRc3kEuqxGw59eN2jN9pRWMtS/XDevekhcFSqvQqjUNGksfjMJu3Y+oJ+4Ypn2OaJw==",
|
||||
"version": "4.1.11",
|
||||
"resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.1.11.tgz",
|
||||
"integrity": "sha512-pN7ikn1ON7h8ee4gIAp4AzyK+zBtJPzVbqOgu5LCEh4VaJVbPQcgYQYJIMGQPXVeJJq1fnfazis7a5pFNPahog==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@vitest/pretty-format": "4.1.10",
|
||||
"@vitest/utils": "4.1.10",
|
||||
"@vitest/pretty-format": "4.1.11",
|
||||
"@vitest/utils": "4.1.11",
|
||||
"magic-string": "^0.30.21",
|
||||
"pathe": "^2.0.3"
|
||||
},
|
||||
@@ -1746,9 +1788,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@vitest/spy": {
|
||||
"version": "4.1.10",
|
||||
"resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.1.10.tgz",
|
||||
"integrity": "sha512-PLf/Ugvoq5wO/b4rwYCR1h2PSIdXz7wnkQFMiUpLdtM7l6pqVFcQIBEHyT1+l+cj7mNwAfZHzqXqDyjvOuwbDw==",
|
||||
"version": "4.1.11",
|
||||
"resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.1.11.tgz",
|
||||
"integrity": "sha512-apNa/prQy2qCeywhnixOHPRCgGNhvg7T4Dapfl1GahLp/R+uhBm5cPyFoNVyqsNd2h1nJxL6BqqdIjiABL60YA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
@@ -1756,13 +1798,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@vitest/utils": {
|
||||
"version": "4.1.10",
|
||||
"resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.1.10.tgz",
|
||||
"integrity": "sha512-fy9am/HWxbaGt/Sawrp90vt6Y6jQwf1RX77cz3uwoJwJVMli/e1IEwRPnMNJ7vKfPTwo0diXifkpPvwH9v7nGA==",
|
||||
"version": "4.1.11",
|
||||
"resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.1.11.tgz",
|
||||
"integrity": "sha512-zTCVGpyFsGWBhllOyKlTw/vnr6D9qxsfSDyfbyZmTyjHw5N/VuvzHpHoQjm2ZJzn4RJgx5w4r7V0er69CmLgPQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@vitest/pretty-format": "4.1.10",
|
||||
"@vitest/pretty-format": "4.1.11",
|
||||
"convert-source-map": "^2.0.0",
|
||||
"tinyrainbow": "^3.1.0"
|
||||
},
|
||||
@@ -1855,6 +1897,25 @@
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/ast-v8-to-istanbul": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/ast-v8-to-istanbul/-/ast-v8-to-istanbul-1.0.5.tgz",
|
||||
"integrity": "sha512-UPAgKJFSEGMWSDr3LX4tqnAb4f7KGT8O40Tyx8wbYmmZ/yn58lNCm8h3svs3eXgiGd5AXxz8NDOvXWvicq+rJA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@jridgewell/trace-mapping": "^0.3.31",
|
||||
"estree-walker": "^3.0.3",
|
||||
"js-tokens": "^10.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/ast-v8-to-istanbul/node_modules/js-tokens": {
|
||||
"version": "10.0.0",
|
||||
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-10.0.0.tgz",
|
||||
"integrity": "sha512-lM/UBzQmfJRo9ABXbPWemivdCW8V2G8FHaHdypQaIy523snUjog0W71ayWXTjiR+ixeMyVHN2XcpnTd/liPg/Q==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/balanced-match": {
|
||||
"version": "4.0.4",
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz",
|
||||
@@ -2517,6 +2578,16 @@
|
||||
"dev": true,
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/has-flag": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
|
||||
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/hermes-estree": {
|
||||
"version": "0.25.1",
|
||||
"resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.25.1.tgz",
|
||||
@@ -2547,6 +2618,13 @@
|
||||
"node": "^20.19.0 || ^22.12.0 || >=24.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/html-escaper": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz",
|
||||
"integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/ignore": {
|
||||
"version": "5.3.2",
|
||||
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
|
||||
@@ -2614,6 +2692,45 @@
|
||||
"dev": true,
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/istanbul-lib-coverage": {
|
||||
"version": "3.2.2",
|
||||
"resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz",
|
||||
"integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==",
|
||||
"dev": true,
|
||||
"license": "BSD-3-Clause",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/istanbul-lib-report": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz",
|
||||
"integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==",
|
||||
"dev": true,
|
||||
"license": "BSD-3-Clause",
|
||||
"dependencies": {
|
||||
"istanbul-lib-coverage": "^3.0.0",
|
||||
"make-dir": "^4.0.0",
|
||||
"supports-color": "^7.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/istanbul-reports": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.2.0.tgz",
|
||||
"integrity": "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==",
|
||||
"dev": true,
|
||||
"license": "BSD-3-Clause",
|
||||
"dependencies": {
|
||||
"html-escaper": "^2.0.0",
|
||||
"istanbul-lib-report": "^3.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/jiti": {
|
||||
"version": "2.7.0",
|
||||
"resolved": "https://registry.npmjs.org/jiti/-/jiti-2.7.0.tgz",
|
||||
@@ -3061,6 +3178,47 @@
|
||||
"@jridgewell/sourcemap-codec": "^1.5.5"
|
||||
}
|
||||
},
|
||||
"node_modules/magicast": {
|
||||
"version": "0.5.4",
|
||||
"resolved": "https://registry.npmjs.org/magicast/-/magicast-0.5.4.tgz",
|
||||
"integrity": "sha512-llBEhWm1SacoRwgHUoQJYtwp4PBLF4faQi5TCpIGyGs9n4y5+juI0tDgyKIfpqxckRHaHzouUEph3THklWh03w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/parser": "^7.29.7",
|
||||
"@babel/types": "^7.29.7",
|
||||
"source-map-js": "^1.2.1"
|
||||
}
|
||||
},
|
||||
"node_modules/make-dir": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz",
|
||||
"integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"semver": "^7.5.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/make-dir/node_modules/semver": {
|
||||
"version": "7.8.5",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz",
|
||||
"integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"bin": {
|
||||
"semver": "bin/semver.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/mdn-data": {
|
||||
"version": "2.27.1",
|
||||
"resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.27.1.tgz",
|
||||
@@ -3553,6 +3711,19 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/supports-color": {
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
|
||||
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"has-flag": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/symbol-tree": {
|
||||
"version": "3.2.4",
|
||||
"resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz",
|
||||
@@ -3822,19 +3993,19 @@
|
||||
}
|
||||
},
|
||||
"node_modules/vitest": {
|
||||
"version": "4.1.10",
|
||||
"resolved": "https://registry.npmjs.org/vitest/-/vitest-4.1.10.tgz",
|
||||
"integrity": "sha512-R9jUTe5S4Qb0HCd4TNqpC7oGcrMssMRGXLW80ubjWsW9VH5GF8y1Y0SFLY9AbqSk6nt0PnOx4H4WNJYZ13GUPw==",
|
||||
"version": "4.1.11",
|
||||
"resolved": "https://registry.npmjs.org/vitest/-/vitest-4.1.11.tgz",
|
||||
"integrity": "sha512-fhACrNXUidIbGSBr5FlbuBkO7VWC1ZyLl0DO4CU2DrQoAPxX84Ysxs+HeGQpii5lZWV1Q4gBZTTu49mF+A6Edw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@vitest/expect": "4.1.10",
|
||||
"@vitest/mocker": "4.1.10",
|
||||
"@vitest/pretty-format": "4.1.10",
|
||||
"@vitest/runner": "4.1.10",
|
||||
"@vitest/snapshot": "4.1.10",
|
||||
"@vitest/spy": "4.1.10",
|
||||
"@vitest/utils": "4.1.10",
|
||||
"@vitest/expect": "4.1.11",
|
||||
"@vitest/mocker": "4.1.11",
|
||||
"@vitest/pretty-format": "4.1.11",
|
||||
"@vitest/runner": "4.1.11",
|
||||
"@vitest/snapshot": "4.1.11",
|
||||
"@vitest/spy": "4.1.11",
|
||||
"@vitest/utils": "4.1.11",
|
||||
"es-module-lexer": "^2.0.0",
|
||||
"expect-type": "^1.3.0",
|
||||
"magic-string": "^0.30.21",
|
||||
@@ -3862,12 +4033,12 @@
|
||||
"@edge-runtime/vm": "*",
|
||||
"@opentelemetry/api": "^1.9.0",
|
||||
"@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0",
|
||||
"@vitest/browser-playwright": "4.1.10",
|
||||
"@vitest/browser-preview": "4.1.10",
|
||||
"@vitest/browser-webdriverio": "4.1.10",
|
||||
"@vitest/coverage-istanbul": "4.1.10",
|
||||
"@vitest/coverage-v8": "4.1.10",
|
||||
"@vitest/ui": "4.1.10",
|
||||
"@vitest/browser-playwright": "4.1.11",
|
||||
"@vitest/browser-preview": "4.1.11",
|
||||
"@vitest/browser-webdriverio": "4.1.11",
|
||||
"@vitest/coverage-istanbul": "4.1.11",
|
||||
"@vitest/coverage-v8": "4.1.11",
|
||||
"@vitest/ui": "4.1.11",
|
||||
"happy-dom": "*",
|
||||
"jsdom": "*",
|
||||
"vite": "^6.0.0 || ^7.0.0 || ^8.0.0"
|
||||
|
||||
@@ -9,7 +9,8 @@
|
||||
"lint": "eslint .",
|
||||
"preview": "vite preview",
|
||||
"test": "vitest run",
|
||||
"test:watch": "vitest"
|
||||
"test:watch": "vitest",
|
||||
"test:coverage": "vitest run --coverage"
|
||||
},
|
||||
"dependencies": {
|
||||
"react": "^19.2.6",
|
||||
@@ -25,6 +26,7 @@
|
||||
"@types/react": "^19.2.14",
|
||||
"@types/react-dom": "^19.2.3",
|
||||
"@vitejs/plugin-react": "^6.0.1",
|
||||
"@vitest/coverage-v8": "^4.1.11",
|
||||
"eslint": "^10.3.0",
|
||||
"eslint-plugin-react-hooks": "^7.1.1",
|
||||
"eslint-plugin-react-refresh": "^0.5.2",
|
||||
|
||||
@@ -4,14 +4,29 @@ import tailwindcss from '@tailwindcss/vite'
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [react(), tailwindcss()],
|
||||
|
||||
server: {
|
||||
proxy: {
|
||||
'/api': 'http://localhost:5000',
|
||||
},
|
||||
},
|
||||
|
||||
test: {
|
||||
environment: 'jsdom',
|
||||
globals: true,
|
||||
setupFiles: './src/setupTests.js',
|
||||
|
||||
// Jenkins pourra lire directement ce fichier.
|
||||
reporters: ['default', 'junit'],
|
||||
outputFile: {
|
||||
junit: './test-results/junit.xml',
|
||||
},
|
||||
|
||||
// Rapports utilisés ensuite par Jenkins et SonarQube.
|
||||
coverage: {
|
||||
provider: 'v8',
|
||||
reporter: ['text', 'html', 'lcov'],
|
||||
reportsDirectory: './coverage',
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user