From ddb391c6734c12114a17ae6a72035088f7e51c75 Mon Sep 17 00:00:00 2001 From: Daniel Allaire Date: Mon, 1 Jun 2026 09:16:37 -0400 Subject: [PATCH] Renommer l'application en app --- ansible/backup-now.yml | 2 +- ansible/group_vars/all.yml | 8 ++-- ansible/inventory/hosts.yml | 2 +- ansible/roles/app/handlers/main.yml | 2 +- ansible/roles/app/tasks/main.yml | 31 +++++++++++---- ...e-meditation.service.j2 => app.service.j2} | 3 +- ansible/roles/backup/tasks/main.yml | 9 ++++- ...upe-meditation-backup.j2 => app-backup.j2} | 5 ++- ansible/roles/nginx/tasks/main.yml | 18 ++++++--- ...{groupe-meditation.conf.j2 => app.conf.j2} | 0 ansible/site.yml | 2 +- ansible/verify.yml | 3 +- backend/app/core/config.py | 2 +- backend/app/main.py | 8 ++-- backend/app/routers/admin.py | 22 ++++++++++- backend/app/routers/depenses.py | 2 +- deploy/app.service | 17 +++++++++ deploy/backup.sh | 9 +++-- deploy/group_backup.py | 2 +- deploy/groupe-meditation.service | 17 --------- ...-groupe-meditation.conf => nginx-app.conf} | 8 ++-- deploy/seed.py | 2 +- docs/90_EXPLOITATION.md | 8 ++-- docs/91_DEPLOIEMENT_ANSIBLE.md | 4 +- docs/93_MULTI_GROUPE.md | 2 +- frontend/index.html | 2 +- frontend/package-lock.json | 4 +- frontend/package.json | 4 +- frontend/public/push-sw.js | 4 +- frontend/src/pages/GestionGroupes.jsx | 38 ++++++++++++++++++- frontend/src/pages/Login.jsx | 3 +- frontend/src/stores/api.js | 2 +- frontend/vite.config.js | 4 +- 33 files changed, 166 insertions(+), 83 deletions(-) rename ansible/roles/app/templates/{groupe-meditation.service.j2 => app.service.j2} (94%) rename ansible/roles/backup/templates/{groupe-meditation-backup.j2 => app-backup.j2} (89%) rename ansible/roles/nginx/templates/{groupe-meditation.conf.j2 => app.conf.j2} (100%) create mode 100644 deploy/app.service delete mode 100644 deploy/groupe-meditation.service rename deploy/{nginx-groupe-meditation.conf => nginx-app.conf} (86%) diff --git a/ansible/backup-now.yml b/ansible/backup-now.yml index 9662fb8..a39f658 100644 --- a/ansible/backup-now.yml +++ b/ansible/backup-now.yml @@ -6,7 +6,7 @@ tasks: - name: Lancer le script de sauvegarde - ansible.builtin.command: /etc/cron.daily/groupe-meditation-backup + ansible.builtin.command: /etc/cron.daily/app-backup changed_when: true - name: Lister les dernieres sauvegardes diff --git a/ansible/group_vars/all.yml b/ansible/group_vars/all.yml index 77191dd..ab3223d 100644 --- a/ansible/group_vars/all.yml +++ b/ansible/group_vars/all.yml @@ -3,16 +3,16 @@ groupe_meditation_domain: app.87-16.org # Chemins de déploiement. -groupe_meditation_app_dir: /opt/groupe-meditation +groupe_meditation_app_dir: /opt/app groupe_meditation_backend_dir: "{{ groupe_meditation_app_dir }}/backend" groupe_meditation_deploy_dir: "{{ groupe_meditation_app_dir }}/deploy" groupe_meditation_data_dir: "{{ groupe_meditation_app_dir }}/data" groupe_meditation_frontend_dir: "{{ groupe_meditation_app_dir }}/frontend" -groupe_meditation_web_root: /var/www/groupe-meditation +groupe_meditation_web_root: /var/www/app groupe_meditation_upload_dir: "{{ groupe_meditation_app_dir }}/uploads/preuves" # Service applicatif. -groupe_meditation_service_name: groupe-meditation +groupe_meditation_service_name: app groupe_meditation_service_user: www-data groupe_meditation_service_group: www-data groupe_meditation_api_host: 127.0.0.1 @@ -54,5 +54,5 @@ groupe_meditation_enable_tls: false groupe_meditation_certbot_email: admin@example.com # Sauvegardes. -groupe_meditation_backup_dir: /var/backups/groupe-meditation +groupe_meditation_backup_dir: /var/backups/app groupe_meditation_backup_retention_days: 30 diff --git a/ansible/inventory/hosts.yml b/ansible/inventory/hosts.yml index 2573e18..dad7ebc 100644 --- a/ansible/inventory/hosts.yml +++ b/ansible/inventory/hosts.yml @@ -3,7 +3,7 @@ all: children: groupe_meditation: hosts: - groupe-meditation-prod: + app-prod: ansible_host: 192.168.12.46 ansible_user: ansible ansible_ssh_private_key_file: ~/.ssh/id_ed25519_ansible_chezlepro diff --git a/ansible/roles/app/handlers/main.yml b/ansible/roles/app/handlers/main.yml index d745d70..344d63e 100644 --- a/ansible/roles/app/handlers/main.yml +++ b/ansible/roles/app/handlers/main.yml @@ -3,7 +3,7 @@ ansible.builtin.systemd: daemon_reload: true -- name: Redemarrer groupe-meditation +- name: Redemarrer app ansible.builtin.service: name: "{{ groupe_meditation_service_name }}" state: restarted diff --git a/ansible/roles/app/tasks/main.yml b/ansible/roles/app/tasks/main.yml index 90617ce..b4c4a30 100644 --- a/ansible/roles/app/tasks/main.yml +++ b/ansible/roles/app/tasks/main.yml @@ -39,21 +39,21 @@ - "--exclude=.env" - "--exclude=__pycache__/" - "--exclude=*.pyc" - notify: Redemarrer groupe-meditation + notify: Redemarrer app - name: Synchroniser les fichiers de deploiement ansible.posix.synchronize: src: "{{ playbook_dir }}/../deploy/" dest: "{{ groupe_meditation_deploy_dir }}/" delete: true - notify: Redemarrer groupe-meditation + notify: Redemarrer app - name: Synchroniser les donnees d'import ansible.posix.synchronize: src: "{{ playbook_dir }}/../data/" dest: "{{ groupe_meditation_data_dir }}/" delete: true - notify: Redemarrer groupe-meditation + notify: Redemarrer app - name: Synchroniser le frontend ansible.posix.synchronize: @@ -73,7 +73,7 @@ ansible.builtin.pip: requirements: "{{ groupe_meditation_backend_dir }}/requirements.txt" virtualenv: "{{ groupe_meditation_backend_dir }}/venv" - notify: Redemarrer groupe-meditation + notify: Redemarrer app - name: Deployer le fichier d'environnement backend ansible.builtin.template: @@ -83,7 +83,7 @@ group: "{{ groupe_meditation_service_group }}" mode: "0640" no_log: true - notify: Redemarrer groupe-meditation + notify: Redemarrer app - name: Installer les dependances frontend sur le poste de controle avec npm ci ansible.builtin.command: @@ -130,16 +130,31 @@ - "{{ groupe_meditation_app_dir }}" - "{{ groupe_meditation_web_root }}" +- name: Arreter l'ancien service applicatif si present + ansible.builtin.service: + name: groupe-meditation + state: stopped + enabled: false + failed_when: false + when: groupe_meditation_service_name != "groupe-meditation" + +- name: Retirer l'ancienne unite systemd + ansible.builtin.file: + path: /etc/systemd/system/groupe-meditation.service + state: absent + when: groupe_meditation_service_name != "groupe-meditation" + notify: Recharger systemd + - name: Installer l'unite systemd ansible.builtin.template: - src: groupe-meditation.service.j2 + src: app.service.j2 dest: "/etc/systemd/system/{{ groupe_meditation_service_name }}.service" owner: root group: root mode: "0644" notify: - Recharger systemd - - Redemarrer groupe-meditation + - Redemarrer app - name: Compter les groupes existants community.postgresql.postgresql_query: @@ -185,7 +200,7 @@ - groupe_meditation_run_seed | bool - groupes_table.query_result[0].count | int == 0 or (groupes_count.query_result[0].count | default(0) | int == 0) no_log: true - notify: Redemarrer groupe-meditation + notify: Redemarrer app - name: Appliquer les handlers apres le seed ansible.builtin.meta: flush_handlers diff --git a/ansible/roles/app/templates/groupe-meditation.service.j2 b/ansible/roles/app/templates/app.service.j2 similarity index 94% rename from ansible/roles/app/templates/groupe-meditation.service.j2 rename to ansible/roles/app/templates/app.service.j2 index 31828f7..26b153a 100644 --- a/ansible/roles/app/templates/groupe-meditation.service.j2 +++ b/ansible/roles/app/templates/app.service.j2 @@ -1,5 +1,5 @@ [Unit] -Description=Groupe Meditation API +Description=App API After=network.target postgresql.service Requires=postgresql.service @@ -15,4 +15,3 @@ RestartSec=5 [Install] WantedBy=multi-user.target - diff --git a/ansible/roles/backup/tasks/main.yml b/ansible/roles/backup/tasks/main.yml index 940237a..7e625c2 100644 --- a/ansible/roles/backup/tasks/main.yml +++ b/ansible/roles/backup/tasks/main.yml @@ -9,9 +9,14 @@ - name: Installer la sauvegarde quotidienne ansible.builtin.template: - src: groupe-meditation-backup.j2 - dest: /etc/cron.daily/groupe-meditation-backup + src: app-backup.j2 + dest: /etc/cron.daily/app-backup owner: root group: root mode: "0750" no_log: true + +- name: Retirer l'ancienne sauvegarde quotidienne + ansible.builtin.file: + path: /etc/cron.daily/groupe-meditation-backup + state: absent diff --git a/ansible/roles/backup/templates/groupe-meditation-backup.j2 b/ansible/roles/backup/templates/app-backup.j2 similarity index 89% rename from ansible/roles/backup/templates/groupe-meditation-backup.j2 rename to ansible/roles/backup/templates/app-backup.j2 index c7fbe81..c019448 100644 --- a/ansible/roles/backup/templates/groupe-meditation-backup.j2 +++ b/ansible/roles/backup/templates/app-backup.j2 @@ -16,12 +16,13 @@ cd "{{ groupe_meditation_backend_dir }}" "{{ groupe_meditation_backend_dir }}/venv/bin/python" "{{ groupe_meditation_deploy_dir }}/tenant_schemas.py" "{{ groupe_meditation_backend_dir }}/venv/bin/python" "{{ groupe_meditation_deploy_dir }}/group_backup.py" all -pg_dump -U "$DB_USER" -h "$DB_HOST" -Fc "$DB_NAME" > "$BACKUP_DIR/grpmed_${DATE}.dump" +pg_dump -U "$DB_USER" -h "$DB_HOST" -Fc "$DB_NAME" > "$BACKUP_DIR/app_${DATE}.dump" for schema in $(PGPASSWORD="$PGPASSWORD" psql -U "$DB_USER" -h "$DB_HOST" -d "$DB_NAME" -Atc "SELECT tenant_schema FROM groupes WHERE tenant_schema IS NOT NULL ORDER BY tenant_schema"); do pg_dump -U "$DB_USER" -h "$DB_HOST" -n "$schema" -Fc "$DB_NAME" > "$BACKUP_DIR/${schema}_${DATE}.dump" done find "$BACKUP_DIR" -name "grpmed_*.dump" -mtime +"$RETENTION_DAYS" -delete +find "$BACKUP_DIR" -name "app_*.dump" -mtime +"$RETENTION_DAYS" -delete find "$BACKUP_DIR" -name "group_*.json" -mtime +"$RETENTION_DAYS" -delete find "$BACKUP_DIR" -name "grp_*.dump" -mtime +"$RETENTION_DAYS" -delete -echo "[$(date)] Sauvegarde terminee: grpmed_${DATE}.dump" +echo "[$(date)] Sauvegarde terminee: app_${DATE}.dump" diff --git a/ansible/roles/nginx/tasks/main.yml b/ansible/roles/nginx/tasks/main.yml index a761b29..0baf22d 100644 --- a/ansible/roles/nginx/tasks/main.yml +++ b/ansible/roles/nginx/tasks/main.yml @@ -6,8 +6,8 @@ - name: Installer le site NGINX ansible.builtin.template: - src: groupe-meditation.conf.j2 - dest: /etc/nginx/sites-available/groupe-meditation + src: app.conf.j2 + dest: /etc/nginx/sites-available/app owner: root group: root mode: "0644" @@ -15,12 +15,21 @@ - name: Activer le site NGINX ansible.builtin.file: - src: /etc/nginx/sites-available/groupe-meditation - dest: /etc/nginx/sites-enabled/groupe-meditation + src: /etc/nginx/sites-available/app + dest: /etc/nginx/sites-enabled/app state: link force: true notify: Recharger nginx +- name: Desactiver l'ancien site NGINX + ansible.builtin.file: + path: "{{ item }}" + state: absent + loop: + - /etc/nginx/sites-enabled/groupe-meditation + - /etc/nginx/sites-available/groupe-meditation + notify: Recharger nginx + - name: Desactiver le site NGINX par defaut ansible.builtin.file: path: /etc/nginx/sites-enabled/default @@ -36,4 +45,3 @@ name: nginx state: started enabled: true - diff --git a/ansible/roles/nginx/templates/groupe-meditation.conf.j2 b/ansible/roles/nginx/templates/app.conf.j2 similarity index 100% rename from ansible/roles/nginx/templates/groupe-meditation.conf.j2 rename to ansible/roles/nginx/templates/app.conf.j2 diff --git a/ansible/site.yml b/ansible/site.yml index 5167571..8e2d757 100644 --- a/ansible/site.yml +++ b/ansible/site.yml @@ -1,5 +1,5 @@ --- -- name: Installer Groupe Meditation +- name: Installer App hosts: groupe_meditation become: true gather_facts: true diff --git a/ansible/verify.yml b/ansible/verify.yml index bae1d37..4882c78 100644 --- a/ansible/verify.yml +++ b/ansible/verify.yml @@ -1,5 +1,5 @@ --- -- name: Verifier Groupe Meditation +- name: Verifier App hosts: groupe_meditation become: true gather_facts: false @@ -39,4 +39,3 @@ that: - frontend_index.stat.exists fail_msg: "Le fichier {{ groupe_meditation_web_root }}/index.html est absent." - diff --git a/backend/app/core/config.py b/backend/app/core/config.py index 326c292..1f75718 100644 --- a/backend/app/core/config.py +++ b/backend/app/core/config.py @@ -20,7 +20,7 @@ class Settings(BaseSettings): VAPID_PUBLIC_KEY: str | None = None VAPID_PRIVATE_KEY_B64: str | None = None VAPID_SUBJECT: str = "mailto:admin@app.87-16.org" - GROUP_BACKUP_DIR: str = "/var/backups/groupe-meditation" + GROUP_BACKUP_DIR: str = "/var/backups/app" class Config: env_file = str(_ENV_FILE) diff --git a/backend/app/main.py b/backend/app/main.py index c3d2388..4893253 100644 --- a/backend/app/main.py +++ b/backend/app/main.py @@ -1,5 +1,5 @@ """ -Groupe Méditation — API Backend +App — API Backend District 87-16, Région 87 100% logiciel libre · Hébergé au Québec """ @@ -130,8 +130,8 @@ async def lifespan(app: FastAPI): app = FastAPI( - title="Groupe Méditation API", - description="API du Groupe Méditation — District 87-16, Région 87", + title="App API", + description="API du App — District 87-16, Région 87", version="0.1.0", lifespan=lifespan, ) @@ -178,4 +178,4 @@ app.include_router(journal.router, prefix="/api") @app.get("/api/health") async def root_health(): - return {"status": "ok", "app": "Groupe Méditation", "version": "0.1.0"} + return {"status": "ok", "app": "App", "version": "0.1.0"} diff --git a/backend/app/routers/admin.py b/backend/app/routers/admin.py index a665904..7d4918a 100644 --- a/backend/app/routers/admin.py +++ b/backend/app/routers/admin.py @@ -5,7 +5,7 @@ from sqlalchemy import func, select from pydantic import BaseModel from app.core.database import get_db -from app.core.security import create_token, get_current_membre, is_sysadmin, verify_pin +from app.core.security import create_token, get_current_membre, hash_pin, is_sysadmin, verify_pin from app.services.admin_database import ( assurer_sysadmin_instance, creer_groupe, @@ -48,6 +48,11 @@ class RestoreGroupeRequest(BaseModel): fichier: str +class ChangePinRequest(BaseModel): + pin_actuel: str + nouveau_pin: str + + async def require_sysadmin(membre=Depends(get_current_membre)): if not is_sysadmin(membre): raise HTTPException(status_code=403, detail="Réservé au sysadmin") @@ -75,6 +80,21 @@ async def sysadmin_login(req: SysadminLoginRequest, db: AsyncSession = Depends(g raise HTTPException(status_code=401, detail="PIN Sysadmin invalide") +@router.post("/sysadmin-pin") +async def changer_pin_sysadmin( + req: ChangePinRequest, + sysadmin=Depends(require_sysadmin), +): + if getattr(sysadmin, "groupe_id", None) is not None: + raise HTTPException(status_code=403, detail="Réservé au sysadmin d'instance") + if not req.nouveau_pin.isdigit() or len(req.nouveau_pin) != 4: + raise HTTPException(status_code=400, detail="Le nouveau PIN doit contenir 4 chiffres") + if not verify_pin(req.pin_actuel, sysadmin.pin_hash): + raise HTTPException(status_code=401, detail="PIN actuel invalide") + sysadmin.pin_hash = hash_pin(req.nouveau_pin) + return {"message": "PIN sysadmin mis à jour"} + + @router.post("/demo") async def demo_database( _sysadmin=Depends(require_sysadmin), diff --git a/backend/app/routers/depenses.py b/backend/app/routers/depenses.py index 1922a32..8c29193 100644 --- a/backend/app/routers/depenses.py +++ b/backend/app/routers/depenses.py @@ -17,7 +17,7 @@ from app.services.historique import enregistrer_historique, snapshot, verifier_v router = APIRouter(prefix="/depenses", tags=["S5 — Dépenses"]) METHODES_VALIDES = {"VIREMENT", "CHEQUE", "COLLECTE"} -UPLOAD_DIR = "/opt/groupe-meditation/uploads/preuves" +UPLOAD_DIR = "/opt/app/uploads/preuves" async def _to_out(d: Depense, db: AsyncSession) -> DepenseOut: diff --git a/deploy/app.service b/deploy/app.service new file mode 100644 index 0000000..427f290 --- /dev/null +++ b/deploy/app.service @@ -0,0 +1,17 @@ +[Unit] +Description=App API +After=network.target postgresql.service +Requires=postgresql.service + +[Service] +Type=simple +User=www-data +Group=www-data +WorkingDirectory=/opt/app/backend +Environment=PATH=/opt/app/backend/venv/bin +ExecStart=/opt/app/backend/venv/bin/uvicorn app.main:app --host 127.0.0.1 --port 8000 --workers 2 +Restart=always +RestartSec=5 + +[Install] +WantedBy=multi-user.target diff --git a/deploy/backup.sh b/deploy/backup.sh index f242d34..43a3279 100644 --- a/deploy/backup.sh +++ b/deploy/backup.sh @@ -1,8 +1,8 @@ #!/bin/bash -# Sauvegarde quotidienne PostgreSQL — Groupe Méditation +# Sauvegarde quotidienne PostgreSQL — App # À placer dans /etc/cron.daily/ ou via crontab -BACKUP_DIR="/var/backups/groupe-meditation" +BACKUP_DIR="/var/backups/app" RETENTION_DAYS=30 DB_NAME="groupe_meditation" DB_USER="grpmed" @@ -11,9 +11,10 @@ DATE=$(date +%Y-%m-%d_%H%M) mkdir -p "$BACKUP_DIR" # Dump -pg_dump -U "$DB_USER" -h 127.0.0.1 -Fc "$DB_NAME" > "$BACKUP_DIR/grpmed_${DATE}.dump" +pg_dump -U "$DB_USER" -h 127.0.0.1 -Fc "$DB_NAME" > "$BACKUP_DIR/app_${DATE}.dump" # Nettoyage des anciennes sauvegardes find "$BACKUP_DIR" -name "grpmed_*.dump" -mtime +$RETENTION_DAYS -delete +find "$BACKUP_DIR" -name "app_*.dump" -mtime +$RETENTION_DAYS -delete -echo "[$(date)] Sauvegarde terminée: grpmed_${DATE}.dump" +echo "[$(date)] Sauvegarde terminée: app_${DATE}.dump" diff --git a/deploy/group_backup.py b/deploy/group_backup.py index 452df92..9c5cc47 100644 --- a/deploy/group_backup.py +++ b/deploy/group_backup.py @@ -2,7 +2,7 @@ """Sauvegardes applicatives par groupe. Usage: - cd /opt/groupe-meditation/backend + cd /opt/app/backend venv/bin/python ../deploy/group_backup.py all """ import asyncio diff --git a/deploy/groupe-meditation.service b/deploy/groupe-meditation.service deleted file mode 100644 index 6edbc20..0000000 --- a/deploy/groupe-meditation.service +++ /dev/null @@ -1,17 +0,0 @@ -[Unit] -Description=Groupe Méditation API -After=network.target postgresql.service -Requires=postgresql.service - -[Service] -Type=simple -User=www-data -Group=www-data -WorkingDirectory=/opt/groupe-meditation/backend -Environment=PATH=/opt/groupe-meditation/backend/venv/bin -ExecStart=/opt/groupe-meditation/backend/venv/bin/uvicorn app.main:app --host 127.0.0.1 --port 8000 --workers 2 -Restart=always -RestartSec=5 - -[Install] -WantedBy=multi-user.target diff --git a/deploy/nginx-groupe-meditation.conf b/deploy/nginx-app.conf similarity index 86% rename from deploy/nginx-groupe-meditation.conf rename to deploy/nginx-app.conf index 210cf18..f9a9b6b 100644 --- a/deploy/nginx-groupe-meditation.conf +++ b/deploy/nginx-app.conf @@ -1,9 +1,9 @@ -# Groupe Méditation — NGINX (seul, sans Apache) +# App — NGINX (seul, sans Apache) # Sert les fichiers statiques + reverse proxy vers FastAPI # # Installation : -# sudo cp deploy/nginx-groupe-meditation.conf /etc/nginx/sites-available/groupe-meditation -# sudo ln -s /etc/nginx/sites-available/groupe-meditation /etc/nginx/sites-enabled/ +# sudo cp deploy/nginx-app.conf /etc/nginx/sites-available/app +# sudo ln -s /etc/nginx/sites-available/app /etc/nginx/sites-enabled/ # sudo nginx -t && sudo systemctl reload nginx # sudo certbot --nginx -d app.87-16.org @@ -32,7 +32,7 @@ server { } # ── Frontend — fichiers statiques (React build) ── - root /var/www/groupe-meditation; + root /var/www/app; index index.html; # Cache longue durée sur les assets (JS, CSS, images) diff --git a/deploy/seed.py b/deploy/seed.py index 36f92c4..f1ed4f5 100644 --- a/deploy/seed.py +++ b/deploy/seed.py @@ -1,7 +1,7 @@ """ Script d'initialisation. Crée le schéma et le groupe de démonstration initial. -Usage: cd /opt/groupe-meditation/backend && venv/bin/python ../deploy/seed.py +Usage: cd /opt/app/backend && venv/bin/python ../deploy/seed.py """ import asyncio import sys diff --git a/docs/90_EXPLOITATION.md b/docs/90_EXPLOITATION.md index 9ca257d..844d2ee 100644 --- a/docs/90_EXPLOITATION.md +++ b/docs/90_EXPLOITATION.md @@ -9,7 +9,7 @@ Dernière révision: 2026-06-01 Sur la VM: ```bash -systemctl status groupe-meditation +systemctl status app systemctl status nginx ``` @@ -28,20 +28,20 @@ curl http://127.0.0.1:8000/api/health Réponse attendue: ```json -{"status":"ok","app":"Groupe Méditation","version":"0.1.0"} +{"status":"ok","app":"App","version":"0.1.0"} ``` ## Redémarrer ```bash -sudo systemctl restart groupe-meditation +sudo systemctl restart app sudo systemctl reload nginx ``` ## Lire les journaux système ```bash -journalctl -u groupe-meditation -n 200 --no-pager +journalctl -u app -n 200 --no-pager journalctl -u nginx -n 100 --no-pager ``` diff --git a/docs/91_DEPLOIEMENT_ANSIBLE.md b/docs/91_DEPLOIEMENT_ANSIBLE.md index a69d903..998e1ae 100644 --- a/docs/91_DEPLOIEMENT_ANSIBLE.md +++ b/docs/91_DEPLOIEMENT_ANSIBLE.md @@ -105,13 +105,13 @@ ansible-playbook ansible/verify.yml --ask-vault-pass Vérification directe de l'API: ```bash -ansible groupe-meditation-prod -m uri -a 'url=http://127.0.0.1:8000/api/health return_content=true status_code=200' -o +ansible app-prod -m uri -a 'url=http://127.0.0.1:8000/api/health return_content=true status_code=200' -o ``` Vérification des groupes publics: ```bash -ansible groupe-meditation-prod -m uri -a 'url=http://127.0.0.1:8000/api/auth/groupes return_content=true status_code=200' -o +ansible app-prod -m uri -a 'url=http://127.0.0.1:8000/api/auth/groupes return_content=true status_code=200' -o ``` ## Initialisation de la base diff --git a/docs/93_MULTI_GROUPE.md b/docs/93_MULTI_GROUPE.md index 8564c3b..e6ce1b4 100644 --- a/docs/93_MULTI_GROUPE.md +++ b/docs/93_MULTI_GROUPE.md @@ -15,7 +15,7 @@ Le groupe courant est déterminé par le membre authentifié et le `groupe_id` d Chaque groupe reçoit aussi un schéma PostgreSQL dédié, nommé à partir de son identifiant (`grp_`). Les tables du groupe peuvent être rafraîchies dans ce schéma avec le script: ```bash -cd /opt/groupe-meditation/backend +cd /opt/app/backend venv/bin/python ../deploy/tenant_schemas.py ``` diff --git a/frontend/index.html b/frontend/index.html index d92966f..b93e8d9 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -8,7 +8,7 @@ - Groupe Méditation + App
diff --git a/frontend/package-lock.json b/frontend/package-lock.json index c29a817..7628329 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -1,11 +1,11 @@ { - "name": "groupe-meditation", + "name": "app", "version": "0.1.0", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "groupe-meditation", + "name": "app", "version": "0.1.0", "dependencies": { "react": "^18.3.1", diff --git a/frontend/package.json b/frontend/package.json index f9d8a0b..0020044 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,8 +1,8 @@ { - "name": "groupe-meditation", + "name": "app", "private": true, "version": "0.1.0", - "description": "Application du Groupe Méditation — District 87-16", + "description": "App — District 87-16", "type": "module", "scripts": { "dev": "vite", diff --git a/frontend/public/push-sw.js b/frontend/public/push-sw.js index 1304691..f95e75b 100644 --- a/frontend/public/push-sw.js +++ b/frontend/public/push-sw.js @@ -4,10 +4,10 @@ self.addEventListener('push', (event) => { try { data = event.data.json(); } catch { - data = { title: 'Groupe Méditation', body: event.data.text() }; + data = { title: 'App', body: event.data.text() }; } } - const title = data.title || 'Groupe Méditation'; + const title = data.title || 'App'; const options = { body: data.body || 'Nouvelle notification', icon: '/icon-192.png', diff --git a/frontend/src/pages/GestionGroupes.jsx b/frontend/src/pages/GestionGroupes.jsx index 30b9bad..fca9463 100644 --- a/frontend/src/pages/GestionGroupes.jsx +++ b/frontend/src/pages/GestionGroupes.jsx @@ -25,7 +25,6 @@ export default function GestionGroupes() { try { const data = await api.get('/admin/groupes'); setGroupes(data); - if (!ouvertId && data.length) setOuvertId(data[0].id); } catch (e) { setError(e.message); } finally { @@ -168,6 +167,36 @@ export default function GestionGroupes() { } }; + const changerPinSysadmin = async () => { + const pinActuel = window.prompt('PIN actuel'); + if (!pinActuel) return; + const nouveauPin = window.prompt('Nouveau PIN sysadmin (4 chiffres)'); + if (!nouveauPin) return; + if (!/^[0-9]{4}$/.test(nouveauPin)) { + setError('Le nouveau PIN doit contenir 4 chiffres'); + return; + } + const confirmation = window.prompt('Confirmer le nouveau PIN'); + if (confirmation !== nouveauPin) { + setError('La confirmation ne correspond pas'); + return; + } + setBusy(true); + setError(''); + setMsg(''); + try { + const res = await api.post('/admin/sysadmin-pin', { + pin_actuel: pinActuel, + nouveau_pin: nouveauPin, + }); + setMsg(res.message || 'PIN sysadmin mis à jour'); + } catch (e) { + setError(e.message); + } finally { + setBusy(false); + } + }; + return (
@@ -184,6 +213,13 @@ export default function GestionGroupes() { > Créer un groupe +
{form && ( diff --git a/frontend/src/pages/Login.jsx b/frontend/src/pages/Login.jsx index 80e31fd..dd2168d 100644 --- a/frontend/src/pages/Login.jsx +++ b/frontend/src/pages/Login.jsx @@ -12,7 +12,7 @@ export default function Login() { const [courriel, setCourriel] = useState(localStorage.getItem('gm_courriel') || ''); const [pin, setPin] = useState(''); const [groupeId, setGroupeId] = useState(localStorage.getItem('gm_groupe_id') || ''); - const [groupeOuvert, setGroupeOuvert] = useState(localStorage.getItem('gm_groupe_id') || ''); + const [groupeOuvert, setGroupeOuvert] = useState(''); const [seSouvenir, setSeSouvenir] = useState(!!localStorage.getItem('gm_courriel')); useEffect(() => { @@ -25,7 +25,6 @@ export default function Login() { if (groupeId && groupeExiste) return; const prochainGroupeId = groupes.length === 1 ? groupes[0].id : ''; setGroupeId(prochainGroupeId); - setGroupeOuvert(prochainGroupeId); if (prochainGroupeId) { localStorage.setItem('gm_groupe_id', prochainGroupeId); } else { diff --git a/frontend/src/stores/api.js b/frontend/src/stores/api.js index 6d5c912..b67d651 100644 --- a/frontend/src/stores/api.js +++ b/frontend/src/stores/api.js @@ -1,5 +1,5 @@ /** - * Client API — Groupe Méditation + * Client API — App */ const BASE = '/api'; diff --git a/frontend/vite.config.js b/frontend/vite.config.js index 5b199db..dda5d3d 100644 --- a/frontend/vite.config.js +++ b/frontend/vite.config.js @@ -9,9 +9,9 @@ export default defineConfig({ registerType: 'autoUpdate', includeAssets: ['favicon.svg'], manifest: { - name: 'Groupe Méditation', + name: 'App', short_name: 'Méditation', - description: 'Application du Groupe Méditation — District 87-16', + description: 'App — District 87-16', theme_color: '#1a5276', background_color: '#f8f9fa', display: 'standalone',