Compare commits
10 Commits
e78423dd16
...
develop
| Author | SHA1 | Date | |
|---|---|---|---|
| 6cdf4a345e | |||
| 2d0b1db015 | |||
| 951d9f0435 | |||
| f54f959fdc | |||
| 82b927fdd1 | |||
| da2e763428 | |||
| 770176092d | |||
|
|
2dd20ee068 | ||
|
|
13d3097b3e | ||
|
|
fc451f025e |
@@ -26,7 +26,7 @@ DB_PASSWORD=skyfile
|
|||||||
# === Production Lions (via Kubernetes Secrets) ===
|
# === Production Lions (via Kubernetes Secrets) ===
|
||||||
# DB_HOST=postgresql-service.postgresql.svc.cluster.local
|
# DB_HOST=postgresql-service.postgresql.svc.cluster.local
|
||||||
# DB_PORT=5432
|
# DB_PORT=5432
|
||||||
# DB_NAME=mic-after-work-server-impl-quarkus-main
|
# DB_NAME=afterwork-server-impl-quarkus
|
||||||
# DB_USERNAME=lionsuser
|
# DB_USERNAME=lionsuser
|
||||||
# DB_PASSWORD=<voir-kubernetes-secrets>
|
# DB_PASSWORD=<voir-kubernetes-secrets>
|
||||||
|
|
||||||
@@ -37,7 +37,8 @@ DB_PASSWORD=skyfile
|
|||||||
# Générez avec: openssl rand -base64 32
|
# Générez avec: openssl rand -base64 32
|
||||||
JWT_SECRET=afterwork-jwt-secret-min-32-bytes-for-hs256!
|
JWT_SECRET=afterwork-jwt-secret-min-32-bytes-for-hs256!
|
||||||
JWT_LIFESPAN=86400
|
JWT_LIFESPAN=86400
|
||||||
JWT_ISSUER=afterwork-api
|
# IMPORTANT: L'issuer doit être "afterwork" (correspondant à JwtService.ISSUER)
|
||||||
|
JWT_ISSUER=afterwork
|
||||||
|
|
||||||
# ============================================
|
# ============================================
|
||||||
# SUPER ADMIN
|
# SUPER ADMIN
|
||||||
@@ -114,7 +115,7 @@ QUARKUS_SMALLRYE_HEALTH_UI_ENABLE=true
|
|||||||
# ============================================
|
# ============================================
|
||||||
# Pour déployer avec lionsctl:
|
# Pour déployer avec lionsctl:
|
||||||
# lionsctl pipeline \
|
# lionsctl pipeline \
|
||||||
# -u https://git.lions.dev/lionsdev/mic-after-work-server-impl-quarkus-main \
|
# -u https://git.lions.dev/lionsdev/afterwork-server-impl-quarkus \
|
||||||
# -b develop \
|
# -b develop \
|
||||||
# -j 17 \
|
# -j 17 \
|
||||||
# -e production \
|
# -e production \
|
||||||
|
|||||||
58
.gitea/workflows/ci.yml
Normal file
58
.gitea/workflows/ci.yml
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
name: CI/CD Lions Pipeline
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [main, develop]
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
environment:
|
||||||
|
description: 'Environnement cible'
|
||||||
|
required: true
|
||||||
|
default: 'production'
|
||||||
|
type: choice
|
||||||
|
options:
|
||||||
|
- dev
|
||||||
|
- staging
|
||||||
|
- production
|
||||||
|
|
||||||
|
env:
|
||||||
|
LIONS_CLUSTER: k1
|
||||||
|
LIONS_JAVA_VERSION: '17' # override si app en Java 21
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
pipeline:
|
||||||
|
name: Build + Push + Deploy
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
timeout-minutes: 30
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Setup lionsctl
|
||||||
|
run: |
|
||||||
|
# Suppose lionsctl installé sur le runner (via image custom)
|
||||||
|
# Alternative : curl -L https://git.lions.dev/lionsdev/lionsctl/releases/download/latest/lionsctl -o /usr/local/bin/lionsctl
|
||||||
|
lionsctl --version
|
||||||
|
|
||||||
|
- name: Pipeline deploy
|
||||||
|
env:
|
||||||
|
LIONS_REGISTRY_USERNAME: ${{ secrets.LIONS_REGISTRY_USERNAME }}
|
||||||
|
LIONS_REGISTRY_PASSWORD: ${{ secrets.LIONS_REGISTRY_PASSWORD }}
|
||||||
|
LIONS_GIT_USERNAME: lionsctl-bot
|
||||||
|
LIONS_GIT_PASSWORD: ${{ secrets.LIONS_GIT_PASSWORD }}
|
||||||
|
LIONS_GIT_ACCESS_TOKEN: ${{ secrets.LIONS_GIT_ACCESS_TOKEN }}
|
||||||
|
SMTP_HOST: ${{ secrets.SMTP_HOST }}
|
||||||
|
SMTP_USERNAME: ${{ secrets.SMTP_USERNAME }}
|
||||||
|
SMTP_PASSWORD: ${{ secrets.SMTP_PASSWORD }}
|
||||||
|
SMTP_FROM: ${{ secrets.SMTP_FROM }}
|
||||||
|
run: |
|
||||||
|
ENV="${{ github.event.inputs.environment || 'production' }}"
|
||||||
|
lionsctl pipeline \
|
||||||
|
-u ${{ gitea.server_url }}/${{ gitea.repository }} \
|
||||||
|
-b ${{ gitea.ref_name }} \
|
||||||
|
-j ${{ env.LIONS_JAVA_VERSION }} \
|
||||||
|
-e "$ENV" \
|
||||||
|
-c ${{ env.LIONS_CLUSTER }} \
|
||||||
|
-p prod \
|
||||||
|
-m admin@lions.dev
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
# Audit intégral – Frontend (Flutter) & Backend (Quarkus)
|
# Audit intégral – Frontend (Flutter) & Backend (Quarkus)
|
||||||
|
|
||||||
**Date** : 4 février 2026
|
**Date** : 4 février 2026
|
||||||
**Périmètre** : `afterwork` (Flutter), `mic-after-work-server-impl-quarkus-main` (Quarkus)
|
**Périmètre** : `afterwork` (Flutter), `afterwork-server-impl-quarkus` (Quarkus)
|
||||||
**Références** : bonnes pratiques Quarkus REST, Flutter clean architecture, REST/JWT, WebSocket, Kafka (recherches web et documentation officielle).
|
**Références** : bonnes pratiques Quarkus REST, Flutter clean architecture, REST/JWT, WebSocket, Kafka (recherches web et documentation officielle).
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ Remplacez `<org>` par votre organisation Git (ex. `lionsdev`, `developer`) et `<
|
|||||||
```bash
|
```bash
|
||||||
# Déploiement en dev (clone + build + image + déploiement K8s)
|
# Déploiement en dev (clone + build + image + déploiement K8s)
|
||||||
lionsctl pipeline \
|
lionsctl pipeline \
|
||||||
-u https://git.lions.dev/<org>/mic-after-work-server-impl-quarkus-main \
|
-u https://git.lions.dev/<org>/afterwork-server-impl-quarkus \
|
||||||
-b develop \
|
-b develop \
|
||||||
-j 17 \
|
-j 17 \
|
||||||
-e dev \
|
-e dev \
|
||||||
@@ -106,7 +106,7 @@ lionsctl pipeline \
|
|||||||
|
|
||||||
# Déploiement en production sur le cluster k2
|
# Déploiement en production sur le cluster k2
|
||||||
lionsctl pipeline \
|
lionsctl pipeline \
|
||||||
-u https://git.lions.dev/<org>/mic-after-work-server-impl-quarkus-main \
|
-u https://git.lions.dev/<org>/afterwork-server-impl-quarkus \
|
||||||
-b main \
|
-b main \
|
||||||
-j 17 \
|
-j 17 \
|
||||||
-e production \
|
-e production \
|
||||||
@@ -116,7 +116,7 @@ lionsctl pipeline \
|
|||||||
|
|
||||||
# Avec déploiement Helm (charts générés automatiquement)
|
# Avec déploiement Helm (charts générés automatiquement)
|
||||||
lionsctl pipeline \
|
lionsctl pipeline \
|
||||||
-u https://git.lions.dev/<org>/mic-after-work-server-impl-quarkus-main \
|
-u https://git.lions.dev/<org>/afterwork-server-impl-quarkus \
|
||||||
-b develop \
|
-b develop \
|
||||||
-j 17 \
|
-j 17 \
|
||||||
-e dev \
|
-e dev \
|
||||||
@@ -129,7 +129,7 @@ lionsctl pipeline \
|
|||||||
|
|
||||||
| Option | Description | Exemple |
|
| Option | Description | Exemple |
|
||||||
|--------|-------------|---------|
|
|--------|-------------|---------|
|
||||||
| `-u`, `--url` | URL du repo Git (obligatoire) | `https://git.lions.dev/.../mic-after-work-server-impl-quarkus-main` |
|
| `-u`, `--url` | URL du repo Git (obligatoire) | `https://git.lions.dev/.../afterwork-server-impl-quarkus` |
|
||||||
| `-b`, `--branch` | Branche à déployer | `develop`, `main` |
|
| `-b`, `--branch` | Branche à déployer | `develop`, `main` |
|
||||||
| `-j`, `--java-version` | Version Java (8–21) | `17` |
|
| `-j`, `--java-version` | Version Java (8–21) | `17` |
|
||||||
| `-e`, `--environment` | Environnement (dev / staging / production) | `dev`, `production` |
|
| `-e`, `--environment` | Environnement (dev / staging / production) | `dev`, `production` |
|
||||||
@@ -141,11 +141,11 @@ lionsctl pipeline \
|
|||||||
### Vérification du déploiement
|
### Vérification du déploiement
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Pods et statut (nom d'app dérivé du repo, ex. mic-after-work-server-impl-quarkus-main)
|
# Pods et statut (nom d'app dérivé du repo, ex. afterwork-server-impl-quarkus)
|
||||||
kubectl get pods -n applications -l app=mic-after-work-server-impl-quarkus-main
|
kubectl get pods -n applications -l app=afterwork-server-impl-quarkus
|
||||||
|
|
||||||
# Logs en temps réel
|
# Logs en temps réel
|
||||||
kubectl logs -n applications -l app=mic-after-work-server-impl-quarkus-main -f
|
kubectl logs -n applications -l app=afterwork-server-impl-quarkus -f
|
||||||
|
|
||||||
# Health check
|
# Health check
|
||||||
curl https://api.lions.dev/afterwork/q/health/ready
|
curl https://api.lions.dev/afterwork/q/health/ready
|
||||||
@@ -307,7 +307,7 @@ spec:
|
|||||||
### Étape 1 : Préparation
|
### Étape 1 : Préparation
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cd C:\Users\dadyo\PersonalProjects\mic-after-work-server-impl-quarkus-main
|
cd C:\Users\dadyo\PersonalProjects/lions-workspace/afterwork/afterwork-server-impl-quarkus
|
||||||
|
|
||||||
# Build Maven
|
# Build Maven
|
||||||
mvn clean package -DskipTests
|
mvn clean package -DskipTests
|
||||||
@@ -361,7 +361,7 @@ kubectl apply -f kubernetes/afterwork-service.yaml
|
|||||||
kubectl apply -f kubernetes/afterwork-ingress.yaml
|
kubectl apply -f kubernetes/afterwork-ingress.yaml
|
||||||
|
|
||||||
# Ou via lionsctl pipeline (clone + build + déploiement)
|
# Ou via lionsctl pipeline (clone + build + déploiement)
|
||||||
lionsctl pipeline -u https://git.lions.dev/<org>/mic-after-work-server-impl-quarkus-main -b develop -j 17 -e dev -c k1 -m <email>
|
lionsctl pipeline -u https://git.lions.dev/<org>/afterwork-server-impl-quarkus -b develop -j 17 -e dev -c k1 -m <email>
|
||||||
```
|
```
|
||||||
|
|
||||||
### Étape 5 : Vérification
|
### Étape 5 : Vérification
|
||||||
|
|||||||
21
Dockerfile
Normal file
21
Dockerfile
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
# Dockerfile for afterwork-server-impl-quarkus
|
||||||
|
# Used by lionsctl pipeline. Expects `mvn clean package -Pprod` to have produced target/quarkus-app/ (fast-jar).
|
||||||
|
FROM registry.access.redhat.com/ubi8/openjdk-21:1.21
|
||||||
|
|
||||||
|
ENV LANGUAGE='en_US:en'
|
||||||
|
|
||||||
|
COPY --chown=1001:1001 target/quarkus-app/lib/ /deployments/lib/
|
||||||
|
COPY --chown=1001:1001 target/quarkus-app/*.jar /deployments/
|
||||||
|
COPY --chown=1001:1001 target/quarkus-app/app/ /deployments/app/
|
||||||
|
COPY --chown=1001:1001 target/quarkus-app/quarkus/ /deployments/quarkus/
|
||||||
|
|
||||||
|
USER 1001
|
||||||
|
|
||||||
|
EXPOSE 8080
|
||||||
|
|
||||||
|
ENV JAVA_OPTS="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager"
|
||||||
|
|
||||||
|
HEALTHCHECK --interval=30s --timeout=3s --start-period=30s --retries=3 \
|
||||||
|
CMD curl -f http://localhost:8080/q/health/live || exit 1
|
||||||
|
|
||||||
|
ENTRYPOINT [ "java", "-jar", "/deployments/quarkus-run.jar" ]
|
||||||
@@ -5,7 +5,7 @@
|
|||||||
### Option 1 : Déploiement Automatique via Script PowerShell
|
### Option 1 : Déploiement Automatique via Script PowerShell
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
cd C:\Users\dadyo\PersonalProjects\mic-after-work-server-impl-quarkus-main
|
cd C:\Users\dadyo\PersonalProjects/lions-workspace/afterwork/afterwork-server-impl-quarkus
|
||||||
|
|
||||||
# Déploiement complet (build + push + deploy)
|
# Déploiement complet (build + push + deploy)
|
||||||
.\scripts\deploy.ps1 -Action all -Version 1.0.0
|
.\scripts\deploy.ps1 -Action all -Version 1.0.0
|
||||||
@@ -22,7 +22,7 @@ cd C:\Users\dadyo\PersonalProjects\mic-after-work-server-impl-quarkus-main
|
|||||||
### Option 2 : Déploiement Manuel
|
### Option 2 : Déploiement Manuel
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
cd C:\Users\dadyo\PersonalProjects\mic-after-work-server-impl-quarkus-main
|
cd C:\Users\dadyo\PersonalProjects/lions-workspace/afterwork/afterwork-server-impl-quarkus
|
||||||
|
|
||||||
# 1. Build Maven (tests non-bloquants)
|
# 1. Build Maven (tests non-bloquants)
|
||||||
mvn clean package -DskipTests
|
mvn clean package -DskipTests
|
||||||
@@ -51,12 +51,12 @@ kubectl logs -n applications -l app=afterwork-api -f
|
|||||||
### Option 3 : Déploiement via lionsctl pipeline
|
### Option 3 : Déploiement via lionsctl pipeline
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cd C:\Users\dadyo\PersonalProjects\mic-after-work-server-impl-quarkus-main
|
cd C:\Users\dadyo\PersonalProjects/lions-workspace/afterwork/afterwork-server-impl-quarkus
|
||||||
|
|
||||||
# Le pipeline clone le repo, build Maven, construit l’image Docker et déploie sur K8s. Remplacer <org> et <email>.
|
# Le pipeline clone le repo, build Maven, construit l’image Docker et déploie sur K8s. Remplacer <org> et <email>.
|
||||||
|
|
||||||
# Déploiement
|
# Déploiement
|
||||||
lionsctl pipeline -u https://git.lions.dev/<org>/mic-after-work-server-impl-quarkus-main -b develop -j 17 -e dev -c k1 -m <email>
|
lionsctl pipeline -u https://git.lions.dev/<org>/afterwork-server-impl-quarkus -b develop -j 17 -e dev -c k1 -m <email>
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
262
README.md
262
README.md
@@ -1,113 +1,185 @@
|
|||||||
# mic-after-work-server-impl-quarkus-main
|
# afterwork-server-impl-quarkus
|
||||||
|
|
||||||
This project uses Quarkus, the Supersonic Subatomic Java Framework.
|
> Backend REST — application sociale AfterWork (événements, chat temps réel, social feed, stories)
|
||||||
|
|
||||||
If you want to learn more about Quarkus, please visit its website: <https://quarkus.io/>.
|
## Dépôt Git
|
||||||
|
|
||||||
## Running the application in dev mode
|
`https://git.lions.dev/lionsdev/afterwork-server-impl-quarkus`
|
||||||
|
|
||||||
You can run your application in dev mode that enables live coding using:
|
|
||||||
|
|
||||||
```shell script
|
|
||||||
./mvnw compile quarkus:dev
|
|
||||||
```
|
|
||||||
|
|
||||||
> **_NOTE:_** Quarkus now ships with a Dev UI, which is available in dev mode only at <http://localhost:8080/q/dev/>.
|
|
||||||
|
|
||||||
## Packaging and running the application
|
|
||||||
|
|
||||||
The application can be packaged using:
|
|
||||||
|
|
||||||
```shell script
|
|
||||||
./mvnw package
|
|
||||||
```
|
|
||||||
|
|
||||||
It produces the `quarkus-run.jar` file in the `target/quarkus-app/` directory.
|
|
||||||
Be aware that it’s not an _über-jar_ as the dependencies are copied into the `target/quarkus-app/lib/` directory.
|
|
||||||
|
|
||||||
The application is now runnable using `java -jar target/quarkus-app/quarkus-run.jar`.
|
|
||||||
|
|
||||||
If you want to build an _über-jar_, execute the following command:
|
|
||||||
|
|
||||||
```shell script
|
|
||||||
./mvnw package -Dquarkus.package.jar.type=uber-jar
|
|
||||||
```
|
|
||||||
|
|
||||||
The application, packaged as an _über-jar_, is now runnable using `java -jar target/*-runner.jar`.
|
|
||||||
|
|
||||||
## Creating a native executable
|
|
||||||
|
|
||||||
You can create a native executable using:
|
|
||||||
|
|
||||||
```shell script
|
|
||||||
./mvnw package -Dnative
|
|
||||||
```
|
|
||||||
|
|
||||||
Or, if you don't have GraalVM installed, you can run the native executable build in a container using:
|
|
||||||
|
|
||||||
```shell script
|
|
||||||
./mvnw package -Dnative -Dquarkus.native.container-build=true
|
|
||||||
```
|
|
||||||
|
|
||||||
You can then execute your native executable with: `./target/mic-after-work-server-impl-quarkus-main-1.0.0-SNAPSHOT-runner`
|
|
||||||
|
|
||||||
If you want to learn more about building native executables, please consult <https://quarkus.io/guides/maven-tooling>.
|
|
||||||
|
|
||||||
## Fonctionnalités métier (AfterWork)
|
|
||||||
|
|
||||||
### Notifications
|
|
||||||
|
|
||||||
- **Service** : `NotificationService` — création, lecture, pagination, marquage lu/suppression des notifications en base.
|
|
||||||
- **Déclencheurs** : Notifications créées automatiquement pour les demandes d’amitié (destinataire), les likes/commentaires sur les posts (auteur du post), les nouvelles notes d’établissement (manager).
|
|
||||||
- **API** : `GET/POST /notifications/user/{userId}`, pagination, marquer lu, supprimer. Voir [SECURITY.md](SECURITY.md) pour l’usage en production (userId issu de l’auth).
|
|
||||||
|
|
||||||
### Jobs planifiés (Quarkus Scheduler)
|
|
||||||
|
|
||||||
- **Stories** : Désactivation des stories expirées (cron : toutes les heures).
|
|
||||||
- **Tokens** : Suppression des tokens de réinitialisation de mot de passe expirés (tous les jours à 3h).
|
|
||||||
- **Abonnements** : Expiration des abonnements établissements et désactivation des établissements non payés (toutes les heures).
|
|
||||||
- **Rappels événements** : Notifications en base pour les participants (J-1 et H-1), exécution toutes les 15 minutes.
|
|
||||||
- **Avertissement abonnement** : Envoi d’emails J-3 avant expiration aux managers (tous les jours à 9h).
|
|
||||||
|
|
||||||
Configuration : `quarkus.scheduler.enabled=true` (désactivé en test via `%test.quarkus.scheduler.enabled=false`).
|
|
||||||
|
|
||||||
### Emails transactionnels
|
|
||||||
|
|
||||||
- **EmailService** : Réinitialisation mot de passe, bienvenue, confirmation de paiement Wave, rappel événement, avertissement expiration abonnement, confirmation de réservation, échec de paiement Wave.
|
|
||||||
- Configuration SMTP via variables d’environnement (`MAILER_HOST`, `MAILER_USERNAME`, `MAILER_PASSWORD`, etc.) ; en test le mailer peut être en mode mock.
|
|
||||||
|
|
||||||
### Paiement Wave (établissements)
|
|
||||||
|
|
||||||
- Initiation de paiement (abonnement mensuel/annuel), webhook `POST /webhooks/wave` pour `payment.completed`, `payment.refunded`, `payment.failed`, etc.
|
|
||||||
- Vérification optionnelle de la signature du webhook (header `X-Wave-Signature`, HMAC-SHA256) si `wave.webhook.secret` est configuré. Voir [SECURITY.md](SECURITY.md).
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Related Guides
|
## Responsabilités
|
||||||
|
|
||||||
- Hibernate ORM ([guide](https://quarkus.io/guides/hibernate-orm)): Define your persistent model with Hibernate ORM and Jakarta Persistence
|
- API REST sécurisée (JWT HS256 + OIDC Keycloak)
|
||||||
- SmallRye OpenAPI ([guide](https://quarkus.io/guides/openapi-swaggerui)): Document your REST APIs with OpenAPI - comes with Swagger UI
|
- Gestion des utilisateurs, amis, événements, cotisations
|
||||||
- RESTEasy Classic ([guide](https://quarkus.io/guides/resteasy)): REST endpoint framework implementing Jakarta REST and more
|
- Chat temps réel (WebSocket)
|
||||||
- Logging JSON ([guide](https://quarkus.io/guides/logging#json-logging)): Add JSON formatter for console logging
|
- Notifications push temps réel
|
||||||
- JDBC Driver - PostgreSQL ([guide](https://quarkus.io/guides/datasource)): Connect to the PostgreSQL database via JDBC
|
- Social feed (posts, likes, commentaires, stories)
|
||||||
|
- Upload médias (images/vidéos)
|
||||||
|
- Emailing transactionnel (via Brevo SMTP)
|
||||||
|
|
||||||
## Sécurité et déploiement
|
---
|
||||||
|
|
||||||
- **Sécurité** : Voir [SECURITY.md](SECURITY.md) (auth, webhook Wave, secrets, validation).
|
## API principales
|
||||||
- **Docker** : Voir [docker/README.md](docker/README.md) pour lancer l’app et les dépendances (PostgreSQL, etc.).
|
|
||||||
|
|
||||||
## Provided Code
|
| Domaine | Path |
|
||||||
|
|---------|------|
|
||||||
|
| Auth | `/api/auth/*` |
|
||||||
|
| Utilisateurs | `/api/users/*` |
|
||||||
|
| Amis | `/api/friends/*` |
|
||||||
|
| Événements | `/api/events/*` |
|
||||||
|
| Posts / Stories | `/api/posts/*`, `/api/stories/*` |
|
||||||
|
| Chat | `/api/chat/*` + WebSocket `/ws/chat/{userId}` |
|
||||||
|
| Notifications | WebSocket `/ws/notifications/{userId}` |
|
||||||
|
| Health | `/q/health` |
|
||||||
|
| Swagger | `/q/swagger-ui` |
|
||||||
|
|
||||||
### Hibernate ORM
|
---
|
||||||
|
|
||||||
Create your first JPA entity
|
## Stack
|
||||||
|
|
||||||
[Related guide section...](https://quarkus.io/guides/hibernate-orm)
|
| Composant | Technologie |
|
||||||
|
|-----------|-------------|
|
||||||
|
| Framework | Quarkus 3.27.3 LTS |
|
||||||
|
| API | Quarkus REST (RESTEasy Reactive) + Jackson |
|
||||||
|
| Auth | JWT HS256 + `quarkus-oidc` (Keycloak) |
|
||||||
|
| ORM | Hibernate ORM Panache |
|
||||||
|
| Base de données | PostgreSQL 15 |
|
||||||
|
| Migrations | Flyway |
|
||||||
|
| Messaging | Kafka (event streaming) |
|
||||||
|
| Emailing | Brevo SMTP (via `quarkus-mailer`) |
|
||||||
|
| Temps réel | WebSockets-Next |
|
||||||
|
| Templates | Qute |
|
||||||
|
| Docs | SmallRye OpenAPI (Swagger UI) |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Développement local
|
||||||
|
|
||||||
### RESTEasy JAX-RS
|
### Prérequis
|
||||||
|
|
||||||
Easily start your RESTful Web Services
|
- Java 21 LTS
|
||||||
|
- Maven 3.9+
|
||||||
|
- PostgreSQL sur `localhost:5432` (DB : `afterwork`)
|
||||||
|
- Keycloak sur `localhost:8180` (realm à configurer)
|
||||||
|
|
||||||
[Related guide section...](https://quarkus.io/guides/getting-started#the-jax-rs-resources)
|
### Démarrage
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mvn quarkus:dev
|
||||||
|
```
|
||||||
|
|
||||||
|
Swagger UI : `http://localhost:8080/q/swagger-ui`
|
||||||
|
|
||||||
|
### Configuration dev
|
||||||
|
|
||||||
|
Variables d'environnement recommandées (voir `.env.example`) :
|
||||||
|
|
||||||
|
```bash
|
||||||
|
DB_NAME=afterwork
|
||||||
|
DB_USERNAME=lionsuser
|
||||||
|
DB_PASSWORD=...
|
||||||
|
JWT_SECRET=dev-jwt-secret-min-32-chars
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Configuration production
|
||||||
|
|
||||||
|
Fichier : `src/main/resources/application-prod.properties`
|
||||||
|
|
||||||
|
Toutes les valeurs sensibles via variables d'env ou secrets K8s. Principales :
|
||||||
|
|
||||||
|
| Variable | Description |
|
||||||
|
|----------|-------------|
|
||||||
|
| `DB_HOST` / `DB_PORT` / `DB_NAME` | PostgreSQL (défaut DB `afterwork`) |
|
||||||
|
| `QUARKUS_DATASOURCE_USERNAME` / `QUARKUS_DATASOURCE_PASSWORD` | Injectés via secret `afterwork-db-eso` (ESO Vault) |
|
||||||
|
| `QUARKUS_OIDC_*` | Config Keycloak (via `afterwork-oidc-eso`) |
|
||||||
|
| `JWT_SECRET` | Clé HS256 ≥32 caractères |
|
||||||
|
| `STORAGE_PATH` | Chemin stockage uploads (défaut `/app/storage` en prod) |
|
||||||
|
| Brevo SMTP | `QUARKUS_MAILER_*` via `brevo-smtp-eso` |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Build
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Build standard (dev)
|
||||||
|
mvn clean package -DskipTests
|
||||||
|
|
||||||
|
# Build production (fast-jar)
|
||||||
|
mvn clean package -Pprod -DskipTests
|
||||||
|
```
|
||||||
|
|
||||||
|
Produit `target/quarkus-app/` (fast-jar, runnable via `java -jar target/quarkus-app/quarkus-run.jar`).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Déploiement (lionsctl)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
lionsctl pipeline \
|
||||||
|
-u https://git.lions.dev/lionsdev/afterwork-server-impl-quarkus \
|
||||||
|
-b develop -j 21 -e production -c k1 -p prod
|
||||||
|
```
|
||||||
|
|
||||||
|
> ℹ️ La branche prod est `develop` (pas `main`).
|
||||||
|
|
||||||
|
**Pipeline** : clone → `mvn package -P prod` → `docker build -f Dockerfile` (racine, fast-jar, `ubi8/openjdk-21:1.21`, UID 1001) → push `registry.lions.dev` → `kubectl apply` → health check
|
||||||
|
|
||||||
|
**URL prod** : `https://api.lions.dev/afterwork`
|
||||||
|
**Health prod** : `https://api.lions.dev/afterwork/q/health`
|
||||||
|
|
||||||
|
**Pré-requis infrastructure** (migration Helm → lionsctl pipeline, fait 2026-04-24) :
|
||||||
|
- Secret K8s `afterwork-server-impl-quarkus-db-secret` (clés `QUARKUS_DATASOURCE_USERNAME/PASSWORD`)
|
||||||
|
- ExternalSecrets `afterwork-db-eso` + `afterwork-oidc-eso` (ESO Vault, path `applications/afterwork-server/*`)
|
||||||
|
- DB PostgreSQL `afterwork` (renommée depuis `mic-after-work-server-impl-quarkus-main`)
|
||||||
|
- Override `QUARKUS_DATASOURCE_JDBC_URL=jdbc:postgresql://postgresql-service.postgresql.svc.cluster.local:5432/afterwork` sur le deployment
|
||||||
|
- Deployment Helm existant supprimé au préalable (selector immutable)
|
||||||
|
- `envFrom: [afterwork-db-eso, afterwork-oidc-eso]` patché post-deploy
|
||||||
|
|
||||||
|
### Helm (alternative GitOps)
|
||||||
|
|
||||||
|
Repo values dédié : [`afterwork-server-impl-quarkus-k1`](https://git.lions.dev/lionsdev/afterwork-server-impl-quarkus-k1) (Chart `lions-app 1.0.3`).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Tests
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mvn test # unitaires
|
||||||
|
mvn verify # avec intégration
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
src/main/
|
||||||
|
├── java/com/lions/dev/
|
||||||
|
│ ├── entity/ # Entités JPA (User, Event, Post, Story, Message, ...)
|
||||||
|
│ ├── repository/ # Repositories Panache
|
||||||
|
│ ├── service/ # Services métier
|
||||||
|
│ ├── resource/ # Resources JAX-RS
|
||||||
|
│ ├── websocket/ # Endpoints WebSocket (chat, notifications)
|
||||||
|
│ ├── security/ # JWT + OIDC filters
|
||||||
|
│ └── mapper/ # MapStruct mappers
|
||||||
|
└── resources/
|
||||||
|
├── db/migration/ # Scripts Flyway
|
||||||
|
├── application.properties
|
||||||
|
└── application-prod.properties
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Historique récent
|
||||||
|
|
||||||
|
- **2026-04-24** — Refactor `mic-after-work-server-impl-quarkus-main` → `afterwork-server-impl-quarkus` (Gitea repo, artifactId, DB `afterwork`, ingress path `/afterwork`, ExternalSecrets ESO). Déployé en prod via lionsctl pipeline.
|
||||||
|
- **2026-04-24** — Upgrade Quarkus **3.16.3 → 3.27.3 LTS** + Java **17 → 21** (cohérence avec les autres backends de l'écosystème).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Licence
|
||||||
|
|
||||||
|
Propriétaire — Lions Dev © 2026
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ docker run -d --name kafka-dev -p 9092:9092 \
|
|||||||
## 2. Démarrer le backend Quarkus (profil dev)
|
## 2. Démarrer le backend Quarkus (profil dev)
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cd mic-after-work-server-impl-quarkus-main
|
cd afterwork-server-impl-quarkus
|
||||||
mvn quarkus:dev
|
mvn quarkus:dev
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
8880
backend_log.txt
8880
backend_log.txt
File diff suppressed because it is too large
Load Diff
@@ -44,7 +44,7 @@ L’application se connecte à PostgreSQL sur l’hôte (`host.docker.internal:5
|
|||||||
CREATE USER afterwork WITH PASSWORD 'changeme';
|
CREATE USER afterwork WITH PASSWORD 'changeme';
|
||||||
CREATE DATABASE afterwork_db OWNER afterwork;
|
CREATE DATABASE afterwork_db OWNER afterwork;
|
||||||
```
|
```
|
||||||
- Ou utiliser **vos** identifiants via un fichier **`.env` à la racine du projet** (mic-after-work-server-impl-quarkus-main) — Docker Compose le charge quand vous lancez depuis cette racine :
|
- Ou utiliser **vos** identifiants via un fichier **`.env` à la racine du projet** (afterwork-server-impl-quarkus) — Docker Compose le charge quand vous lancez depuis cette racine :
|
||||||
```bash
|
```bash
|
||||||
# Contenu de .env à la racine du projet
|
# Contenu de .env à la racine du projet
|
||||||
DB_USERNAME=monuser
|
DB_USERNAME=monuser
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
apiVersion: apps/v1
|
apiVersion: apps/v1
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
name: mic-after-work-server-impl-quarkus-main
|
name: afterwork-server-impl-quarkus
|
||||||
namespace: applications
|
namespace: applications
|
||||||
labels:
|
labels:
|
||||||
app: mic-after-work-server-impl-quarkus-main
|
app: afterwork-server-impl-quarkus
|
||||||
version: "1.0.0"
|
version: "1.0.0"
|
||||||
environment: production
|
environment: production
|
||||||
component: application
|
component: application
|
||||||
@@ -22,11 +22,11 @@ spec:
|
|||||||
maxUnavailable: 0
|
maxUnavailable: 0
|
||||||
selector:
|
selector:
|
||||||
matchLabels:
|
matchLabels:
|
||||||
app: mic-after-work-server-impl-quarkus-main
|
app: afterwork-server-impl-quarkus
|
||||||
template:
|
template:
|
||||||
metadata:
|
metadata:
|
||||||
labels:
|
labels:
|
||||||
app: mic-after-work-server-impl-quarkus-main
|
app: afterwork-server-impl-quarkus
|
||||||
version: "1.0.0"
|
version: "1.0.0"
|
||||||
component: application
|
component: application
|
||||||
project: lions-infrastructure-2025
|
project: lions-infrastructure-2025
|
||||||
@@ -45,8 +45,8 @@ spec:
|
|||||||
type: RuntimeDefault
|
type: RuntimeDefault
|
||||||
terminationGracePeriodSeconds: 30
|
terminationGracePeriodSeconds: 30
|
||||||
containers:
|
containers:
|
||||||
- name: mic-after-work-server-impl-quarkus-main
|
- name: afterwork-server-impl-quarkus
|
||||||
image: registry.lions.dev/lionsdev/mic-after-work-server-impl-quarkus-main:latest
|
image: registry.lions.dev/lionsdev/afterwork-server-impl-quarkus:latest
|
||||||
imagePullPolicy: Always
|
imagePullPolicy: Always
|
||||||
ports:
|
ports:
|
||||||
- containerPort: 8080
|
- containerPort: 8080
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
apiVersion: networking.k8s.io/v1
|
apiVersion: networking.k8s.io/v1
|
||||||
kind: Ingress
|
kind: Ingress
|
||||||
metadata:
|
metadata:
|
||||||
name: mic-after-work-server-impl-quarkus-main-ingress
|
name: afterwork-server-impl-quarkus-ingress
|
||||||
namespace: applications
|
namespace: applications
|
||||||
labels:
|
labels:
|
||||||
app: mic-after-work-server-impl-quarkus-main
|
app: afterwork-server-impl-quarkus
|
||||||
annotations:
|
annotations:
|
||||||
# SSL/TLS
|
# SSL/TLS
|
||||||
cert-manager.io/cluster-issuer: "letsencrypt-prod"
|
cert-manager.io/cluster-issuer: "letsencrypt-prod"
|
||||||
@@ -27,7 +27,7 @@ metadata:
|
|||||||
|
|
||||||
# WebSocket support
|
# WebSocket support
|
||||||
nginx.ingress.kubernetes.io/proxy-http-version: "1.1"
|
nginx.ingress.kubernetes.io/proxy-http-version: "1.1"
|
||||||
nginx.ingress.kubernetes.io/websocket-services: "mic-after-work-server-impl-quarkus-main-service"
|
nginx.ingress.kubernetes.io/websocket-services: "afterwork-server-impl-quarkus-service"
|
||||||
|
|
||||||
# Security headers and CORS
|
# Security headers and CORS
|
||||||
nginx.ingress.kubernetes.io/enable-cors: "true"
|
nginx.ingress.kubernetes.io/enable-cors: "true"
|
||||||
@@ -63,6 +63,6 @@ spec:
|
|||||||
pathType: Prefix
|
pathType: Prefix
|
||||||
backend:
|
backend:
|
||||||
service:
|
service:
|
||||||
name: mic-after-work-server-impl-quarkus-main-service
|
name: afterwork-server-impl-quarkus-service
|
||||||
port:
|
port:
|
||||||
number: 80
|
number: 80
|
||||||
|
|||||||
@@ -18,13 +18,13 @@ metadata:
|
|||||||
name: afterwork-api-monitor
|
name: afterwork-api-monitor
|
||||||
namespace: monitoring
|
namespace: monitoring
|
||||||
labels:
|
labels:
|
||||||
app: mic-after-work-server-impl-quarkus-main
|
app: afterwork-server-impl-quarkus
|
||||||
release: prometheus
|
release: prometheus
|
||||||
project: lions-infrastructure-2025
|
project: lions-infrastructure-2025
|
||||||
spec:
|
spec:
|
||||||
selector:
|
selector:
|
||||||
matchLabels:
|
matchLabels:
|
||||||
app: mic-after-work-server-impl-quarkus-main
|
app: afterwork-server-impl-quarkus
|
||||||
namespaceSelector:
|
namespaceSelector:
|
||||||
matchNames:
|
matchNames:
|
||||||
- applications
|
- applications
|
||||||
@@ -45,7 +45,7 @@ metadata:
|
|||||||
name: afterwork-api-alerts
|
name: afterwork-api-alerts
|
||||||
namespace: monitoring
|
namespace: monitoring
|
||||||
labels:
|
labels:
|
||||||
app: mic-after-work-server-impl-quarkus-main
|
app: afterwork-server-impl-quarkus
|
||||||
release: prometheus
|
release: prometheus
|
||||||
project: lions-infrastructure-2025
|
project: lions-infrastructure-2025
|
||||||
spec:
|
spec:
|
||||||
@@ -68,12 +68,12 @@ spec:
|
|||||||
expr: |
|
expr: |
|
||||||
sum(rate(http_server_requests_seconds_count{
|
sum(rate(http_server_requests_seconds_count{
|
||||||
kubernetes_namespace="applications",
|
kubernetes_namespace="applications",
|
||||||
app="mic-after-work-server-impl-quarkus-main",
|
app="afterwork-server-impl-quarkus",
|
||||||
status=~"5.."
|
status=~"5.."
|
||||||
}[5m])) /
|
}[5m])) /
|
||||||
sum(rate(http_server_requests_seconds_count{
|
sum(rate(http_server_requests_seconds_count{
|
||||||
kubernetes_namespace="applications",
|
kubernetes_namespace="applications",
|
||||||
app="mic-after-work-server-impl-quarkus-main"
|
app="afterwork-server-impl-quarkus"
|
||||||
}[5m])) > 0.05
|
}[5m])) > 0.05
|
||||||
for: 5m
|
for: 5m
|
||||||
labels:
|
labels:
|
||||||
@@ -88,7 +88,7 @@ spec:
|
|||||||
expr: |
|
expr: |
|
||||||
histogram_quantile(0.95, sum(rate(http_server_requests_seconds_bucket{
|
histogram_quantile(0.95, sum(rate(http_server_requests_seconds_bucket{
|
||||||
kubernetes_namespace="applications",
|
kubernetes_namespace="applications",
|
||||||
app="mic-after-work-server-impl-quarkus-main"
|
app="afterwork-server-impl-quarkus"
|
||||||
}[5m])) by (le)) > 2
|
}[5m])) by (le)) > 2
|
||||||
for: 5m
|
for: 5m
|
||||||
labels:
|
labels:
|
||||||
@@ -103,11 +103,11 @@ spec:
|
|||||||
expr: |
|
expr: |
|
||||||
sum(container_memory_working_set_bytes{
|
sum(container_memory_working_set_bytes{
|
||||||
namespace="applications",
|
namespace="applications",
|
||||||
pod=~"mic-after-work-server-impl-quarkus-main.*"
|
pod=~"afterwork-server-impl-quarkus.*"
|
||||||
}) /
|
}) /
|
||||||
sum(container_spec_memory_limit_bytes{
|
sum(container_spec_memory_limit_bytes{
|
||||||
namespace="applications",
|
namespace="applications",
|
||||||
pod=~"mic-after-work-server-impl-quarkus-main.*"
|
pod=~"afterwork-server-impl-quarkus.*"
|
||||||
}) > 0.85
|
}) > 0.85
|
||||||
for: 5m
|
for: 5m
|
||||||
labels:
|
labels:
|
||||||
@@ -122,7 +122,7 @@ spec:
|
|||||||
expr: |
|
expr: |
|
||||||
increase(kube_pod_container_status_restarts_total{
|
increase(kube_pod_container_status_restarts_total{
|
||||||
namespace="applications",
|
namespace="applications",
|
||||||
pod=~"mic-after-work-server-impl-quarkus-main.*"
|
pod=~"afterwork-server-impl-quarkus.*"
|
||||||
}[1h]) > 3
|
}[1h]) > 3
|
||||||
for: 5m
|
for: 5m
|
||||||
labels:
|
labels:
|
||||||
@@ -143,7 +143,7 @@ metadata:
|
|||||||
namespace: monitoring
|
namespace: monitoring
|
||||||
labels:
|
labels:
|
||||||
grafana_dashboard: "1"
|
grafana_dashboard: "1"
|
||||||
app: mic-after-work-server-impl-quarkus-main
|
app: afterwork-server-impl-quarkus
|
||||||
project: lions-infrastructure-2025
|
project: lions-infrastructure-2025
|
||||||
data:
|
data:
|
||||||
afterwork-api-dashboard.json: |
|
afterwork-api-dashboard.json: |
|
||||||
@@ -184,7 +184,7 @@ data:
|
|||||||
"options": {},
|
"options": {},
|
||||||
"targets": [
|
"targets": [
|
||||||
{
|
{
|
||||||
"expr": "sum(rate(http_server_requests_seconds_count{kubernetes_namespace=\"applications\",app=\"mic-after-work-server-impl-quarkus-main\"}[5m]))",
|
"expr": "sum(rate(http_server_requests_seconds_count{kubernetes_namespace=\"applications\",app=\"afterwork-server-impl-quarkus\"}[5m]))",
|
||||||
"legendFormat": "Requests/s",
|
"legendFormat": "Requests/s",
|
||||||
"refId": "A"
|
"refId": "A"
|
||||||
}
|
}
|
||||||
@@ -210,12 +210,12 @@ data:
|
|||||||
"options": {},
|
"options": {},
|
||||||
"targets": [
|
"targets": [
|
||||||
{
|
{
|
||||||
"expr": "histogram_quantile(0.95, sum(rate(http_server_requests_seconds_bucket{kubernetes_namespace=\"applications\",app=\"mic-after-work-server-impl-quarkus-main\"}[5m])) by (le)) * 1000",
|
"expr": "histogram_quantile(0.95, sum(rate(http_server_requests_seconds_bucket{kubernetes_namespace=\"applications\",app=\"afterwork-server-impl-quarkus\"}[5m])) by (le)) * 1000",
|
||||||
"legendFormat": "p95 Latency",
|
"legendFormat": "p95 Latency",
|
||||||
"refId": "A"
|
"refId": "A"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"expr": "histogram_quantile(0.50, sum(rate(http_server_requests_seconds_bucket{kubernetes_namespace=\"applications\",app=\"mic-after-work-server-impl-quarkus-main\"}[5m])) by (le)) * 1000",
|
"expr": "histogram_quantile(0.50, sum(rate(http_server_requests_seconds_bucket{kubernetes_namespace=\"applications\",app=\"afterwork-server-impl-quarkus\"}[5m])) by (le)) * 1000",
|
||||||
"legendFormat": "p50 Latency",
|
"legendFormat": "p50 Latency",
|
||||||
"refId": "B"
|
"refId": "B"
|
||||||
}
|
}
|
||||||
@@ -241,7 +241,7 @@ data:
|
|||||||
"options": {},
|
"options": {},
|
||||||
"targets": [
|
"targets": [
|
||||||
{
|
{
|
||||||
"expr": "sum(rate(http_server_requests_seconds_count{kubernetes_namespace=\"applications\",app=\"mic-after-work-server-impl-quarkus-main\",status=~\"5..\"}[5m])) / sum(rate(http_server_requests_seconds_count{kubernetes_namespace=\"applications\",app=\"mic-after-work-server-impl-quarkus-main\"}[5m])) * 100",
|
"expr": "sum(rate(http_server_requests_seconds_count{kubernetes_namespace=\"applications\",app=\"afterwork-server-impl-quarkus\",status=~\"5..\"}[5m])) / sum(rate(http_server_requests_seconds_count{kubernetes_namespace=\"applications\",app=\"afterwork-server-impl-quarkus\"}[5m])) * 100",
|
||||||
"legendFormat": "Error Rate %",
|
"legendFormat": "Error Rate %",
|
||||||
"refId": "A"
|
"refId": "A"
|
||||||
}
|
}
|
||||||
@@ -267,12 +267,12 @@ data:
|
|||||||
"options": {},
|
"options": {},
|
||||||
"targets": [
|
"targets": [
|
||||||
{
|
{
|
||||||
"expr": "sum(container_memory_working_set_bytes{namespace=\"applications\",pod=~\"mic-after-work-server-impl-quarkus-main.*\"})",
|
"expr": "sum(container_memory_working_set_bytes{namespace=\"applications\",pod=~\"afterwork-server-impl-quarkus.*\"})",
|
||||||
"legendFormat": "Memory Used",
|
"legendFormat": "Memory Used",
|
||||||
"refId": "A"
|
"refId": "A"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"expr": "sum(container_spec_memory_limit_bytes{namespace=\"applications\",pod=~\"mic-after-work-server-impl-quarkus-main.*\"})",
|
"expr": "sum(container_spec_memory_limit_bytes{namespace=\"applications\",pod=~\"afterwork-server-impl-quarkus.*\"})",
|
||||||
"legendFormat": "Memory Limit",
|
"legendFormat": "Memory Limit",
|
||||||
"refId": "B"
|
"refId": "B"
|
||||||
}
|
}
|
||||||
@@ -298,7 +298,7 @@ data:
|
|||||||
"options": {},
|
"options": {},
|
||||||
"targets": [
|
"targets": [
|
||||||
{
|
{
|
||||||
"expr": "sum(rate(container_cpu_usage_seconds_total{namespace=\"applications\",pod=~\"mic-after-work-server-impl-quarkus-main.*\"}[5m])) * 1000",
|
"expr": "sum(rate(container_cpu_usage_seconds_total{namespace=\"applications\",pod=~\"afterwork-server-impl-quarkus.*\"}[5m])) * 1000",
|
||||||
"legendFormat": "CPU Usage (millicores)",
|
"legendFormat": "CPU Usage (millicores)",
|
||||||
"refId": "A"
|
"refId": "A"
|
||||||
}
|
}
|
||||||
@@ -379,7 +379,7 @@ data:
|
|||||||
},
|
},
|
||||||
"targets": [
|
"targets": [
|
||||||
{
|
{
|
||||||
"expr": "increase(kube_pod_container_status_restarts_total{namespace=\"applications\",pod=~\"mic-after-work-server-impl-quarkus-main.*\"}[1h])",
|
"expr": "increase(kube_pod_container_status_restarts_total{namespace=\"applications\",pod=~\"afterwork-server-impl-quarkus.*\"}[1h])",
|
||||||
"legendFormat": "Restarts (1h)",
|
"legendFormat": "Restarts (1h)",
|
||||||
"refId": "A"
|
"refId": "A"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ data:
|
|||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
DB_HOST: "postgresql-service.postgresql.svc.cluster.local"
|
DB_HOST: "postgresql-service.postgresql.svc.cluster.local"
|
||||||
DB_PORT: "5432"
|
DB_PORT: "5432"
|
||||||
DB_NAME: "mic-after-work-server-impl-quarkus-main"
|
DB_NAME: "afterwork-server-impl-quarkus"
|
||||||
DB_USERNAME: "lionsuser"
|
DB_USERNAME: "lionsuser"
|
||||||
|
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Service
|
kind: Service
|
||||||
metadata:
|
metadata:
|
||||||
name: mic-after-work-server-impl-quarkus-main-service
|
name: afterwork-server-impl-quarkus-service
|
||||||
namespace: applications
|
namespace: applications
|
||||||
labels:
|
labels:
|
||||||
app: mic-after-work-server-impl-quarkus-main
|
app: afterwork-server-impl-quarkus
|
||||||
component: application
|
component: application
|
||||||
project: lions-infrastructure-2025
|
project: lions-infrastructure-2025
|
||||||
annotations:
|
annotations:
|
||||||
@@ -27,4 +27,4 @@ spec:
|
|||||||
protocol: TCP
|
protocol: TCP
|
||||||
name: http-direct
|
name: http-direct
|
||||||
selector:
|
selector:
|
||||||
app: mic-after-work-server-impl-quarkus-main
|
app: afterwork-server-impl-quarkus
|
||||||
|
|||||||
6
pom.xml
6
pom.xml
@@ -2,17 +2,17 @@
|
|||||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<groupId>dev.lions</groupId>
|
<groupId>dev.lions</groupId>
|
||||||
<artifactId>mic-after-work-server-impl-quarkus-main</artifactId>
|
<artifactId>afterwork-server-impl-quarkus</artifactId>
|
||||||
<version>1.0.0-SNAPSHOT</version>
|
<version>1.0.0-SNAPSHOT</version>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<compiler-plugin.version>3.13.0</compiler-plugin.version>
|
<compiler-plugin.version>3.13.0</compiler-plugin.version>
|
||||||
<maven.compiler.release>17</maven.compiler.release>
|
<maven.compiler.release>21</maven.compiler.release>
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||||
<quarkus.platform.artifact-id>quarkus-bom</quarkus.platform.artifact-id>
|
<quarkus.platform.artifact-id>quarkus-bom</quarkus.platform.artifact-id>
|
||||||
<quarkus.platform.group-id>io.quarkus.platform</quarkus.platform.group-id>
|
<quarkus.platform.group-id>io.quarkus.platform</quarkus.platform.group-id>
|
||||||
<quarkus.platform.version>3.16.3</quarkus.platform.version>
|
<quarkus.platform.version>3.27.3</quarkus.platform.version>
|
||||||
<quarkus.package.type>fast-jar</quarkus.package.type>
|
<quarkus.package.type>fast-jar</quarkus.package.type>
|
||||||
<skipITs>true</skipITs>
|
<skipITs>true</skipITs>
|
||||||
<surefire-plugin.version>3.5.0</surefire-plugin.version>
|
<surefire-plugin.version>3.5.0</surefire-plugin.version>
|
||||||
|
|||||||
@@ -7,11 +7,11 @@
|
|||||||
#
|
#
|
||||||
# Then, build the image with:
|
# Then, build the image with:
|
||||||
#
|
#
|
||||||
# docker build -f src/main/docker/Dockerfile.jvm -t quarkus/mic-after-work-server-impl-quarkus-main-jvm .
|
# docker build -f src/main/docker/Dockerfile.jvm -t quarkus/afterwork-jvm .
|
||||||
#
|
#
|
||||||
# Then run the container using:
|
# Then run the container using:
|
||||||
#
|
#
|
||||||
# docker run -i --rm -p 8080:8080 quarkus/mic-after-work-server-impl-quarkus-main-jvm
|
# docker run -i --rm -p 8080:8080 quarkus/afterwork-jvm
|
||||||
#
|
#
|
||||||
# If you want to include the debug port into your docker image
|
# If you want to include the debug port into your docker image
|
||||||
# you will have to expose the debug port (default 5005 being the default) like this : EXPOSE 8080 5005.
|
# you will have to expose the debug port (default 5005 being the default) like this : EXPOSE 8080 5005.
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
#
|
#
|
||||||
# Then run the container using :
|
# Then run the container using :
|
||||||
#
|
#
|
||||||
# docker run -i --rm -p 8080:8080 quarkus/mic-after-work-server-impl-quarkus-main-jvm
|
# docker run -i --rm -p 8080:8080 quarkus/afterwork-jvm
|
||||||
#
|
#
|
||||||
# This image uses the `run-java.sh` script to run the application.
|
# This image uses the `run-java.sh` script to run the application.
|
||||||
# This scripts computes the command line to execute your Java application, and
|
# This scripts computes the command line to execute your Java application, and
|
||||||
|
|||||||
@@ -7,11 +7,11 @@
|
|||||||
#
|
#
|
||||||
# Then, build the image with:
|
# Then, build the image with:
|
||||||
#
|
#
|
||||||
# docker build -f src/main/docker/Dockerfile.legacy-jar -t quarkus/mic-after-work-server-impl-quarkus-main-legacy-jar .
|
# docker build -f src/main/docker/Dockerfile.legacy-jar -t quarkus/afterwork-legacy-jar .
|
||||||
#
|
#
|
||||||
# Then run the container using:
|
# Then run the container using:
|
||||||
#
|
#
|
||||||
# docker run -i --rm -p 8080:8080 quarkus/mic-after-work-server-impl-quarkus-main-legacy-jar
|
# docker run -i --rm -p 8080:8080 quarkus/afterwork-legacy-jar
|
||||||
#
|
#
|
||||||
# If you want to include the debug port into your docker image
|
# If you want to include the debug port into your docker image
|
||||||
# you will have to expose the debug port (default 5005 being the default) like this : EXPOSE 8080 5005.
|
# you will have to expose the debug port (default 5005 being the default) like this : EXPOSE 8080 5005.
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
#
|
#
|
||||||
# Then run the container using :
|
# Then run the container using :
|
||||||
#
|
#
|
||||||
# docker run -i --rm -p 8080:8080 quarkus/mic-after-work-server-impl-quarkus-main-legacy-jar
|
# docker run -i --rm -p 8080:8080 quarkus/afterwork-legacy-jar
|
||||||
#
|
#
|
||||||
# This image uses the `run-java.sh` script to run the application.
|
# This image uses the `run-java.sh` script to run the application.
|
||||||
# This scripts computes the command line to execute your Java application, and
|
# This scripts computes the command line to execute your Java application, and
|
||||||
|
|||||||
@@ -7,11 +7,11 @@
|
|||||||
#
|
#
|
||||||
# Then, build the image with:
|
# Then, build the image with:
|
||||||
#
|
#
|
||||||
# docker build -f src/main/docker/Dockerfile.native -t quarkus/mic-after-work-server-impl-quarkus-main .
|
# docker build -f src/main/docker/Dockerfile.native -t quarkus/afterwork .
|
||||||
#
|
#
|
||||||
# Then run the container using:
|
# Then run the container using:
|
||||||
#
|
#
|
||||||
# docker run -i --rm -p 8080:8080 quarkus/mic-after-work-server-impl-quarkus-main
|
# docker run -i --rm -p 8080:8080 quarkus/afterwork
|
||||||
#
|
#
|
||||||
###
|
###
|
||||||
FROM registry.access.redhat.com/ubi8/ubi-minimal:8.10
|
FROM registry.access.redhat.com/ubi8/ubi-minimal:8.10
|
||||||
|
|||||||
@@ -10,11 +10,11 @@
|
|||||||
#
|
#
|
||||||
# Then, build the image with:
|
# Then, build the image with:
|
||||||
#
|
#
|
||||||
# docker build -f src/main/docker/Dockerfile.native-micro -t quarkus/mic-after-work-server-impl-quarkus-main .
|
# docker build -f src/main/docker/Dockerfile.native-micro -t quarkus/afterwork .
|
||||||
#
|
#
|
||||||
# Then run the container using:
|
# Then run the container using:
|
||||||
#
|
#
|
||||||
# docker run -i --rm -p 8080:8080 quarkus/mic-after-work-server-impl-quarkus-main
|
# docker run -i --rm -p 8080:8080 quarkus/afterwork
|
||||||
#
|
#
|
||||||
###
|
###
|
||||||
FROM quay.io/quarkus/quarkus-micro-image:2.0
|
FROM quay.io/quarkus/quarkus-micro-image:2.0
|
||||||
|
|||||||
@@ -88,8 +88,8 @@ public class RolePermissionConfig {
|
|||||||
PROFILE_READ, PROFILE_UPDATE, PROFILE_DELETE,
|
PROFILE_READ, PROFILE_UPDATE, PROFILE_DELETE,
|
||||||
// Social / Recherche
|
// Social / Recherche
|
||||||
SOCIAL_SEARCH, SOCIAL_FOLLOW, SOCIAL_BLOCK,
|
SOCIAL_SEARCH, SOCIAL_FOLLOW, SOCIAL_BLOCK,
|
||||||
// Événements
|
// Événements - lecture, participation et création
|
||||||
EVENTS_READ, EVENTS_PARTICIPATE,
|
EVENTS_READ, EVENTS_PARTICIPATE, EVENTS_CREATE, EVENTS_UPDATE_OWN, EVENTS_DELETE_OWN,
|
||||||
// Établissements
|
// Établissements
|
||||||
ESTABLISHMENTS_READ,
|
ESTABLISHMENTS_READ,
|
||||||
// Réservations
|
// Réservations
|
||||||
@@ -137,8 +137,8 @@ public class RolePermissionConfig {
|
|||||||
|
|
||||||
// ===== ESTABLISHMENT_MANAGER (Gérant / Manager) =====
|
// ===== ESTABLISHMENT_MANAGER (Gérant / Manager) =====
|
||||||
rolePermissions.put(ESTABLISHMENT_MANAGER, EnumSet.of(
|
rolePermissions.put(ESTABLISHMENT_MANAGER, EnumSet.of(
|
||||||
// Établissement - gestion partielle
|
// Établissement - gestion partielle + création
|
||||||
ESTABLISHMENTS_UPDATE_OWN,
|
ESTABLISHMENTS_CREATE, ESTABLISHMENTS_UPDATE_OWN,
|
||||||
// Événements - gestion pour l'établissement
|
// Événements - gestion pour l'établissement
|
||||||
EVENTS_CREATE, EVENTS_UPDATE_OWN, EVENTS_DELETE_OWN,
|
EVENTS_CREATE, EVENTS_UPDATE_OWN, EVENTS_DELETE_OWN,
|
||||||
// Réservations - gestion
|
// Réservations - gestion
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||||||
*
|
*
|
||||||
* URL: ws://localhost:8080/chat/{userId}
|
* URL: ws://localhost:8080/chat/{userId}
|
||||||
*/
|
*/
|
||||||
@WebSocket(path = "/chat/{userId}")
|
@WebSocket(path = "/afterwork/chat/{userId}")
|
||||||
@ApplicationScoped
|
@ApplicationScoped
|
||||||
public class ChatWebSocketNext {
|
public class ChatWebSocketNext {
|
||||||
|
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||||||
*
|
*
|
||||||
* URL: ws://localhost:8080/notifications/{userId}
|
* URL: ws://localhost:8080/notifications/{userId}
|
||||||
*/
|
*/
|
||||||
@WebSocket(path = "/notifications/{userId}")
|
@WebSocket(path = "/afterwork/notifications/{userId}")
|
||||||
@ApplicationScoped
|
@ApplicationScoped
|
||||||
public class NotificationWebSocketNext {
|
public class NotificationWebSocketNext {
|
||||||
|
|
||||||
|
|||||||
6
src/main/resources/META-INF/resources/jwt-secret.jwk
Normal file
6
src/main/resources/META-INF/resources/jwt-secret.jwk
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"kty": "oct",
|
||||||
|
"k": "YWZ0ZXJ3b3JrLWp3dC1zZWNyZXQtbWluLTMyLWJ5dGVzLWZvci1oczI1NiE",
|
||||||
|
"alg": "HS256",
|
||||||
|
"use": "sig"
|
||||||
|
}
|
||||||
@@ -40,7 +40,9 @@ quarkus.flyway.clean-at-start=false
|
|||||||
# ====================================================================
|
# ====================================================================
|
||||||
# drop-and-create: recrée le schéma à chaque démarrage (pratique en dev).
|
# drop-and-create: recrée le schéma à chaque démarrage (pratique en dev).
|
||||||
# ATTENTION: Ne JAMAIS utiliser ce mode en production !
|
# ATTENTION: Ne JAMAIS utiliser ce mode en production !
|
||||||
quarkus.hibernate-orm.database.generation=drop-and-create
|
# Utiliser 'update' pour conserver les données entre les redémarrages
|
||||||
|
# Changer en 'drop-and-create' uniquement si vous voulez réinitialiser la base
|
||||||
|
quarkus.hibernate-orm.database.generation=update
|
||||||
quarkus.hibernate-orm.log.sql=true
|
quarkus.hibernate-orm.log.sql=true
|
||||||
quarkus.hibernate-orm.log.format-sql=true
|
quarkus.hibernate-orm.log.format-sql=true
|
||||||
quarkus.hibernate-orm.packages=com.lions.dev.entity
|
quarkus.hibernate-orm.packages=com.lions.dev.entity
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ quarkus.smallrye-openapi.servers=https://api.lions.dev
|
|||||||
# IMPORTANT: Les credentials doivent ?tre fournis via variables d'environnement
|
# IMPORTANT: Les credentials doivent ?tre fournis via variables d'environnement
|
||||||
# en production (Kubernetes Secrets ou Vault).
|
# en production (Kubernetes Secrets ou Vault).
|
||||||
quarkus.datasource.db-kind=postgresql
|
quarkus.datasource.db-kind=postgresql
|
||||||
quarkus.datasource.jdbc.url=jdbc:postgresql://${DB_HOST:postgresql-service.postgresql.svc.cluster.local}:${DB_PORT:5432}/${DB_NAME:mic-after-work-server-impl-quarkus-main}
|
quarkus.datasource.jdbc.url=jdbc:postgresql://${DB_HOST:postgresql-service.postgresql.svc.cluster.local}:${DB_PORT:5432}/${DB_NAME:afterwork-server-impl-quarkus}
|
||||||
quarkus.datasource.username=${DB_USERNAME:lionsuser}
|
quarkus.datasource.username=${DB_USERNAME:lionsuser}
|
||||||
quarkus.datasource.password=${DB_PASSWORD}
|
quarkus.datasource.password=${DB_PASSWORD}
|
||||||
quarkus.datasource.jdbc.driver=org.postgresql.Driver
|
quarkus.datasource.jdbc.driver=org.postgresql.Driver
|
||||||
|
|||||||
@@ -35,30 +35,29 @@ smallrye.jwt.new-token.lifespan=${JWT_LIFESPAN:86400}
|
|||||||
smallrye.jwt.new-token.issuer=afterwork
|
smallrye.jwt.new-token.issuer=afterwork
|
||||||
|
|
||||||
# ====================================================================
|
# ====================================================================
|
||||||
# JWT Configuration (SmallRye JWT)
|
# JWT Configuration (SmallRye JWT avec HS256)
|
||||||
# ====================================================================
|
# ====================================================================
|
||||||
# Algorithme de signature/vérification (symétrique HS256)
|
# Algorithme de signature/vérification : HMAC-SHA256 (symétrique)
|
||||||
smallrye.jwt.verify.algorithm=HS256
|
smallrye.jwt.verify.algorithm=HS256
|
||||||
mp.jwt.verify.issuer=afterwork
|
mp.jwt.verify.issuer=afterwork
|
||||||
|
|
||||||
# Clé secrète pour vérifier les tokens HS256 (même valeur que afterwork.jwt.secret)
|
# Clé secrète HS256 au format JWK (JSON Web Key)
|
||||||
# SmallRye JWT supporte les clés symétriques via cette propriété
|
# IMPORTANT: La valeur "k" est la clé afterwork.jwt.secret encodée en Base64URL
|
||||||
smallrye.jwt.verify.key.location=META-INF/jwt-secret.key
|
smallrye.jwt.verify.key.location=jwt-secret.jwk
|
||||||
|
|
||||||
# Activer la propagation du token pour @RolesAllowed
|
# Désactiver l'authentification proactive (laisser les endpoints publics accessibles)
|
||||||
quarkus.smallrye-jwt.blocking-authentication=true
|
quarkus.http.auth.proactive=false
|
||||||
|
|
||||||
# ====================================================================
|
# ====================================================================
|
||||||
# Sécurité HTTP - Permissions par chemin
|
# Sécurité HTTP - Permissions par chemin
|
||||||
# ====================================================================
|
# ====================================================================
|
||||||
# Endpoints publics (sans authentification requise)
|
# Endpoints publics (sans authentification requise)
|
||||||
quarkus.http.auth.permission.public.paths=/afterwork/users/register,/afterwork/users/authenticate,/afterwork/users/forgot-password,/afterwork/users/reset-password,/afterwork/q/*,/afterwork/openapi,/afterwork/webhooks/*
|
quarkus.http.auth.permission.public.paths=/afterwork/users/register,/afterwork/users/authenticate,/afterwork/users/forgot-password,/afterwork/users/reset-password,/afterwork/q/*,/afterwork/openapi,/afterwork/webhooks/*,/afterwork/media/files/*,/q/*
|
||||||
quarkus.http.auth.permission.public.policy=permit
|
quarkus.http.auth.permission.public.policy=permit
|
||||||
|
|
||||||
# Endpoints admin (SUPER_ADMIN ou ADMIN requis)
|
# Endpoints admin (SUPER_ADMIN ou ADMIN requis)
|
||||||
quarkus.http.auth.permission.admin.paths=/afterwork/admin/*
|
quarkus.http.auth.permission.admin.paths=/afterwork/admin/*
|
||||||
quarkus.http.auth.permission.admin.policy=authenticated
|
quarkus.http.auth.permission.admin.policy=authenticated
|
||||||
quarkus.http.auth.permission.admin.roles=SUPER_ADMIN,ADMIN
|
|
||||||
|
|
||||||
# Tous les autres endpoints requièrent une authentification
|
# Tous les autres endpoints requièrent une authentification
|
||||||
quarkus.http.auth.permission.authenticated.paths=/afterwork/*
|
quarkus.http.auth.permission.authenticated.paths=/afterwork/*
|
||||||
@@ -105,7 +104,7 @@ quarkus.http.root-path=/afterwork
|
|||||||
# ne pourra pas utiliser PostgreSQL en prod. Donc on met la config prod par défaut ;
|
# ne pourra pas utiliser PostgreSQL en prod. Donc on met la config prod par défaut ;
|
||||||
# le profil dev surcharge avec PostgreSQL local (application-dev.properties).
|
# le profil dev surcharge avec PostgreSQL local (application-dev.properties).
|
||||||
quarkus.datasource.db-kind=postgresql
|
quarkus.datasource.db-kind=postgresql
|
||||||
quarkus.datasource.jdbc.url=jdbc:postgresql://${DB_HOST:postgresql-service.postgresql.svc.cluster.local}:${DB_PORT:5432}/${DB_NAME:mic-after-work-server-impl-quarkus-main}
|
quarkus.datasource.jdbc.url=jdbc:postgresql://${DB_HOST:postgresql-service.postgresql.svc.cluster.local}:${DB_PORT:5432}/${DB_NAME:afterwork-server-impl-quarkus}
|
||||||
quarkus.datasource.username=${DB_USERNAME:lionsuser}
|
quarkus.datasource.username=${DB_USERNAME:lionsuser}
|
||||||
quarkus.datasource.password=${DB_PASSWORD}
|
quarkus.datasource.password=${DB_PASSWORD}
|
||||||
quarkus.datasource.jdbc.driver=org.postgresql.Driver
|
quarkus.datasource.jdbc.driver=org.postgresql.Driver
|
||||||
@@ -116,6 +115,8 @@ quarkus.datasource.devservices.enabled=false
|
|||||||
# Hibernate ORM (prod : Flyway gère le schéma ; dev/test surchargent)
|
# Hibernate ORM (prod : Flyway gère le schéma ; dev/test surchargent)
|
||||||
quarkus.hibernate-orm.database.generation=none
|
quarkus.hibernate-orm.database.generation=none
|
||||||
quarkus.hibernate-orm.log.sql=false
|
quarkus.hibernate-orm.log.sql=false
|
||||||
|
# Quarkus 3.27 : opt-in au nouveau comportement par défaut (séparation REST JSON vs colonnes JSON en BDD)
|
||||||
|
quarkus.hibernate-orm.mapping.format.global=ignore
|
||||||
|
|
||||||
# ====================================================================
|
# ====================================================================
|
||||||
# Upload de fichiers (commun à tous les environnements)
|
# Upload de fichiers (commun à tous les environnements)
|
||||||
|
|||||||
5
src/main/resources/jwt-secret.jwk
Normal file
5
src/main/resources/jwt-secret.jwk
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"kty": "oct",
|
||||||
|
"k": "YWZ0ZXJ3b3JrLWp3dC1zZWNyZXQtbWluLTMyLWJ5dGVzLWZvci1oczI1NiE",
|
||||||
|
"alg": "HS256"
|
||||||
|
}
|
||||||
@@ -26,6 +26,9 @@ class SecurityServiceTest {
|
|||||||
@Inject
|
@Inject
|
||||||
SecurityService securityService;
|
SecurityService securityService;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
RolePermissionConfig rolePermissionConfig;
|
||||||
|
|
||||||
// =========================================================================
|
// =========================================================================
|
||||||
// Tests des permissions par rôle
|
// Tests des permissions par rôle
|
||||||
// =========================================================================
|
// =========================================================================
|
||||||
@@ -33,7 +36,7 @@ class SecurityServiceTest {
|
|||||||
@Test
|
@Test
|
||||||
@DisplayName("Role USER devrait avoir les permissions de base")
|
@DisplayName("Role USER devrait avoir les permissions de base")
|
||||||
void testUserRoleHasBasicPermissions() {
|
void testUserRoleHasBasicPermissions() {
|
||||||
Set<Permission> userPermissions = RolePermissionConfig.getPermissions(Role.USER);
|
Set<Permission> userPermissions = rolePermissionConfig.getPermissions(Role.USER);
|
||||||
|
|
||||||
// Vérifier les permissions de profil
|
// Vérifier les permissions de profil
|
||||||
assertTrue(userPermissions.contains(Permission.PROFILE_READ), "USER devrait pouvoir lire son profil");
|
assertTrue(userPermissions.contains(Permission.PROFILE_READ), "USER devrait pouvoir lire son profil");
|
||||||
@@ -53,27 +56,27 @@ class SecurityServiceTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@DisplayName("Role OWNER devrait avoir les permissions d'établissement")
|
@DisplayName("Role ESTABLISHMENT_OWNER devrait avoir les permissions d'établissement")
|
||||||
void testOwnerRoleHasEstablishmentPermissions() {
|
void testOwnerRoleHasEstablishmentPermissions() {
|
||||||
Set<Permission> ownerPermissions = RolePermissionConfig.getPermissions(Role.OWNER);
|
Set<Permission> ownerPermissions = rolePermissionConfig.getPermissions(Role.ESTABLISHMENT_OWNER);
|
||||||
|
|
||||||
// Permissions de gestion d'établissement
|
// Permissions de gestion d'établissement
|
||||||
assertTrue(ownerPermissions.contains(Permission.ESTABLISHMENTS_CREATE), "OWNER devrait pouvoir créer un établissement");
|
assertTrue(ownerPermissions.contains(Permission.ESTABLISHMENTS_CREATE), "ESTABLISHMENT_OWNER devrait pouvoir créer un établissement");
|
||||||
assertTrue(ownerPermissions.contains(Permission.ESTABLISHMENTS_UPDATE_OWN), "OWNER devrait pouvoir modifier son établissement");
|
assertTrue(ownerPermissions.contains(Permission.ESTABLISHMENTS_UPDATE_OWN), "ESTABLISHMENT_OWNER devrait pouvoir modifier son établissement");
|
||||||
assertTrue(ownerPermissions.contains(Permission.ESTABLISHMENTS_DELETE_OWN), "OWNER devrait pouvoir supprimer son établissement");
|
assertTrue(ownerPermissions.contains(Permission.ESTABLISHMENTS_DELETE_OWN), "ESTABLISHMENT_OWNER devrait pouvoir supprimer son établissement");
|
||||||
assertTrue(ownerPermissions.contains(Permission.ESTABLISHMENTS_MANAGE_STAFF), "OWNER devrait pouvoir gérer le personnel");
|
assertTrue(ownerPermissions.contains(Permission.ESTABLISHMENTS_MANAGE_STAFF), "ESTABLISHMENT_OWNER devrait pouvoir gérer le personnel");
|
||||||
assertTrue(ownerPermissions.contains(Permission.ESTABLISHMENTS_VIEW_ANALYTICS), "OWNER devrait voir les analytics");
|
assertTrue(ownerPermissions.contains(Permission.ESTABLISHMENTS_VIEW_ANALYTICS), "ESTABLISHMENT_OWNER devrait voir les analytics");
|
||||||
|
|
||||||
// Permissions de promotions
|
// Permissions de promotions
|
||||||
assertTrue(ownerPermissions.contains(Permission.PROMOTIONS_CREATE), "OWNER devrait pouvoir créer des promotions");
|
assertTrue(ownerPermissions.contains(Permission.PROMOTIONS_CREATE), "ESTABLISHMENT_OWNER devrait pouvoir créer des promotions");
|
||||||
assertTrue(ownerPermissions.contains(Permission.PROMOTIONS_UPDATE_OWN), "OWNER devrait pouvoir modifier ses promotions");
|
assertTrue(ownerPermissions.contains(Permission.PROMOTIONS_UPDATE_OWN), "ESTABLISHMENT_OWNER devrait pouvoir modifier ses promotions");
|
||||||
assertTrue(ownerPermissions.contains(Permission.PROMOTIONS_DELETE_OWN), "OWNER devrait pouvoir supprimer ses promotions");
|
assertTrue(ownerPermissions.contains(Permission.PROMOTIONS_DELETE_OWN), "ESTABLISHMENT_OWNER devrait pouvoir supprimer ses promotions");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@DisplayName("Role SUPER_ADMIN devrait avoir toutes les permissions")
|
@DisplayName("Role SUPER_ADMIN devrait avoir toutes les permissions")
|
||||||
void testSuperAdminHasAllPermissions() {
|
void testSuperAdminHasAllPermissions() {
|
||||||
Set<Permission> superAdminPermissions = RolePermissionConfig.getPermissions(Role.SUPER_ADMIN);
|
Set<Permission> superAdminPermissions = rolePermissionConfig.getPermissions(Role.SUPER_ADMIN);
|
||||||
|
|
||||||
// SUPER_ADMIN devrait avoir accès à tout
|
// SUPER_ADMIN devrait avoir accès à tout
|
||||||
assertTrue(superAdminPermissions.contains(Permission.SUPER_ADMIN_ACCESS), "SUPER_ADMIN devrait avoir accès super admin");
|
assertTrue(superAdminPermissions.contains(Permission.SUPER_ADMIN_ACCESS), "SUPER_ADMIN devrait avoir accès super admin");
|
||||||
@@ -86,7 +89,7 @@ class SecurityServiceTest {
|
|||||||
@Test
|
@Test
|
||||||
@DisplayName("Role MODERATOR devrait avoir les permissions de modération")
|
@DisplayName("Role MODERATOR devrait avoir les permissions de modération")
|
||||||
void testModeratorRoleHasModerationPermissions() {
|
void testModeratorRoleHasModerationPermissions() {
|
||||||
Set<Permission> modPermissions = RolePermissionConfig.getPermissions(Role.MODERATOR);
|
Set<Permission> modPermissions = rolePermissionConfig.getPermissions(Role.MODERATOR);
|
||||||
|
|
||||||
assertTrue(modPermissions.contains(Permission.MODERATION_VIEW_REPORTS), "MODERATOR devrait voir les signalements");
|
assertTrue(modPermissions.contains(Permission.MODERATION_VIEW_REPORTS), "MODERATOR devrait voir les signalements");
|
||||||
assertTrue(modPermissions.contains(Permission.MODERATION_HANDLE_REPORTS), "MODERATOR devrait traiter les signalements");
|
assertTrue(modPermissions.contains(Permission.MODERATION_HANDLE_REPORTS), "MODERATOR devrait traiter les signalements");
|
||||||
@@ -128,23 +131,28 @@ class SecurityServiceTest {
|
|||||||
// =========================================================================
|
// =========================================================================
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@DisplayName("Test conversion String vers Role")
|
@DisplayName("Test conversion String vers Role avec fromString")
|
||||||
void testRoleFromString() {
|
void testRoleFromString() {
|
||||||
assertEquals(Role.USER, Role.valueOf("USER"));
|
// Nouveaux noms de rôles
|
||||||
assertEquals(Role.OWNER, Role.valueOf("OWNER"));
|
assertEquals(Role.USER, Role.fromString("USER"));
|
||||||
assertEquals(Role.MANAGER, Role.valueOf("MANAGER"));
|
assertEquals(Role.ESTABLISHMENT_OWNER, Role.fromString("ESTABLISHMENT_OWNER"));
|
||||||
assertEquals(Role.ADMIN, Role.valueOf("ADMIN"));
|
assertEquals(Role.ESTABLISHMENT_MANAGER, Role.fromString("ESTABLISHMENT_MANAGER"));
|
||||||
assertEquals(Role.SUPER_ADMIN, Role.valueOf("SUPER_ADMIN"));
|
assertEquals(Role.ADMIN, Role.fromString("ADMIN"));
|
||||||
assertEquals(Role.MODERATOR, Role.valueOf("MODERATOR"));
|
assertEquals(Role.SUPER_ADMIN, Role.fromString("SUPER_ADMIN"));
|
||||||
assertEquals(Role.SUPPORT, Role.valueOf("SUPPORT"));
|
assertEquals(Role.MODERATOR, Role.fromString("MODERATOR"));
|
||||||
assertEquals(Role.FINANCE, Role.valueOf("FINANCE"));
|
assertEquals(Role.SUPPORT, Role.fromString("SUPPORT"));
|
||||||
|
assertEquals(Role.FINANCE_MANAGER, Role.fromString("FINANCE_MANAGER"));
|
||||||
|
|
||||||
|
// Rétrocompatibilité avec anciens noms
|
||||||
|
assertEquals(Role.ESTABLISHMENT_OWNER, Role.fromString("OWNER"));
|
||||||
|
assertEquals(Role.ESTABLISHMENT_MANAGER, Role.fromString("MANAGER"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@DisplayName("Test que chaque rôle a au moins une permission")
|
@DisplayName("Test que chaque rôle a au moins une permission")
|
||||||
void testAllRolesHavePermissions() {
|
void testAllRolesHavePermissions() {
|
||||||
for (Role role : Role.values()) {
|
for (Role role : Role.values()) {
|
||||||
Set<Permission> permissions = RolePermissionConfig.getPermissions(role);
|
Set<Permission> permissions = rolePermissionConfig.getPermissions(role);
|
||||||
assertFalse(permissions.isEmpty(), "Le rôle " + role + " devrait avoir au moins une permission");
|
assertFalse(permissions.isEmpty(), "Le rôle " + role + " devrait avoir au moins une permission");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -161,4 +169,12 @@ class SecurityServiceTest {
|
|||||||
assertFalse(permission.getDescription().isBlank(), "La description de " + permission + " ne devrait pas être vide");
|
assertFalse(permission.getDescription().isBlank(), "La description de " + permission + " ne devrait pas être vide");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("Role ESTABLISHMENT_MANAGER devrait pouvoir créer des établissements")
|
||||||
|
void testManagerCanCreateEstablishments() {
|
||||||
|
Set<Permission> managerPermissions = rolePermissionConfig.getPermissions(Role.ESTABLISHMENT_MANAGER);
|
||||||
|
assertTrue(managerPermissions.contains(Permission.ESTABLISHMENTS_CREATE),
|
||||||
|
"ESTABLISHMENT_MANAGER devrait pouvoir créer un établissement");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user