From e6afc4f1fa719acc8d46d18eee18da2cfbc5a316 Mon Sep 17 00:00:00 2001 From: Anthony Coyaud Date: Sat, 15 Aug 2026 13:28:23 +0200 Subject: [PATCH] =?UTF-8?q?chore(sql):=20compte=20de=20visite=20=C2=AB=20J?= =?UTF-8?q?ur=C3=A9=20=C2=BB=20+=20dump=20d'authentification=20versionn?= =?UTF-8?q?=C3=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ajoute sql/create_admin_jure.sql, script idempotent créant/réinitialisant le compte de démonstration destiné aux personnes qui consultent le site (rôle Admin). Aucune instruction USE : la base cible vient du paramètre -d de la connexion, avec un garde-fou qui arrête le script si les tables attendues sont absentes. Copie aussi sql/data_sentinel_auth.sql (déjà présent dans le dump livré sous RENDU/02_Dump_SQL/) : le README de ce dépôt le référençait déjà, mais le dossier sql/ n'existait pas encore ici. Documente le compte dans le tableau des comptes de démo du README. --- README.md | 25 ++++++--- sql/create_admin_jure.sql | 88 +++++++++++++++++++++++++++++++ sql/data_sentinel_auth.sql | 105 +++++++++++++++++++++++++++++++++++++ 3 files changed, 212 insertions(+), 6 deletions(-) create mode 100644 sql/create_admin_jure.sql create mode 100644 sql/data_sentinel_auth.sql diff --git a/README.md b/README.md index 673392b..3f2710b 100644 --- a/README.md +++ b/README.md @@ -44,11 +44,23 @@ Sans variables d'environnement, l'API se connecte en authentification Windows ### Comptes de démo -| Identifiant | Mot de passe | Rôle | -|-------------|--------------|------| -| `admin` | `Admin2026!` | Admin | -| `superviseur` | `Super2026!` | Superviseur | -| `consultant` | `Conseil2026!` | Consultant | +| Identifiant | Mot de passe | Rôle | Usage | +|-------------|--------------|------|-------| +| `Juré` (`JURE@NEXA.com`) | `123456` | Admin | **Compte de visite / évaluation** — à communiquer aux personnes qui consultent le site | +| `admin` | `Admin2026!` | Admin | Compte d'administration technique | +| `superviseur` | `Super2026!` | Superviseur | Illustration du RBAC (pas d'accès `/admin/*`) | +| `consultant` | `Conseil2026!` | Consultant | Illustration du RBAC (lecture seule) | + +Ces comptes sont créés par `sql/data_sentinel_auth.sql`. Pour (re)créer le seul +compte `Juré` sur une base déjà déployée, sans rejouer tout le script d'auth : + +```bash +sqlcmd -S -d DataSentinel -U -P -i sql/create_admin_jure.sql +``` + +Les mots de passe ci-dessus sont des identifiants de démonstration : ils sont +stockés hachés (bcrypt, coût 12) et doivent être régénérés avant toute mise en +production réelle (`POST /admin/users/{id}/reset-password`). ## Endpoints (résumé) @@ -65,7 +77,8 @@ Spécification complète : `GET /openapi.json` (export dans `docs/openapi.json`) - En-têtes : `X-Content-Type-Options`, `X-Frame-Options`, `Referrer-Policy`, `Strict-Transport-Security`. - CORS restreint aux origines `CORS_ORIGINS`, tous verbes + credentials. - Requêtes SQL **paramétrées** (noms de tables/colonnes whitelistés) ; le compte applicatif - n'est pas `sa`. Tables d'auth : `[USER]` + `JOURNAL_AUDIT` (`sql/data_sentinel_auth.sql`). + n'est pas `sa`. Tables d'auth : `[USER]` + `JOURNAL_AUDIT` (`sql/data_sentinel_auth.sql`, + identique au dump livré dans `RENDU/02_Dump_SQL/`). - Journal d'audit alimenté à chaque login + action admin. ## Tests diff --git a/sql/create_admin_jure.sql b/sql/create_admin_jure.sql new file mode 100644 index 0000000..2722a18 --- /dev/null +++ b/sql/create_admin_jure.sql @@ -0,0 +1,88 @@ +-- ============================================================ +-- DATA SENTINEL — Création / réinitialisation du compte « Juré » +-- Auteur : COYAUD Anthony +-- Version : 1.1 — Août 2026 +-- +-- Compte Admin destiné aux personnes qui consultent l'application +-- (évaluateurs, jury, démonstration). +-- +-- identifiant : Juré +-- mail : JURE@NEXA.com +-- mot de passe : 123456 +-- rôle : Admin +-- +-- Script idempotent : il peut être rejoué sur une base déjà déployée +-- sans dupliquer le compte ni toucher aux autres utilisateurs. +-- Prérequis : data_sentinel_auth.sql déjà exécuté ([USER] + JOURNAL_AUDIT). +-- +-- Pas d'instruction USE : la base cible vient du paramètre -d de la +-- connexion, et le garde-fou ci-dessous interrompt le script si ce +-- n'est pas la bonne. Tout tient dans un seul lot (aucun GO), sans +-- quoi le RETURN du garde-fou n'empêcherait pas la suite de tourner. +-- +-- Exécution : +-- sqlcmd -S -d -U -P -C -b -f 65001 \ +-- -i sql/create_admin_jure.sql +-- ============================================================ + +SET NOCOUNT ON; +SET XACT_ABORT ON; + +DECLARE @base NVARCHAR(128) = DB_NAME(); + +IF OBJECT_ID('[USER]', 'U') IS NULL OR OBJECT_ID('JOURNAL_AUDIT', 'U') IS NULL +BEGIN + RAISERROR( + 'ARRET : base incorrecte (%s). [USER] ou JOURNAL_AUDIT est introuvable. Reconnectez-vous sur la base Data Sentinel (option -d).', + 16, 1, @base); + RETURN; +END + +-- Hachage bcrypt (coût 12) du mot de passe de démonstration. +-- Généré avec passlib.CryptContext(schemes=["bcrypt"]) — même librairie que auth.py. +DECLARE @username NVARCHAR(100) = N'Juré'; +DECLARE @email NVARCHAR(200) = N'JURE@NEXA.com'; +DECLARE @password_hash NVARCHAR(255) = N'$2b$12$nnWMOCjSiUq4rAyPGbC3W.HGdsvWKu9kEfLst6zBIEIcsgP97W94m'; + +BEGIN TRY + BEGIN TRANSACTION; + + IF EXISTS (SELECT 1 FROM [USER] WHERE username = @username) + BEGIN + UPDATE [USER] + SET email = @email, + password_hash = @password_hash, + role = N'Admin', + actif = 1 + WHERE username = @username; + + INSERT INTO JOURNAL_AUDIT (id_user, username, action, detail) + SELECT id_user, username, 'RESET_PASSWORD', 'Compte de visite reinitialise (script SQL)' + FROM [USER] WHERE username = @username; + + PRINT 'Compte "Jure" deja present -> mis a jour.'; + END + ELSE + BEGIN + INSERT INTO [USER] (username, email, password_hash, role, actif) + VALUES (@username, @email, @password_hash, N'Admin', 1); + + INSERT INTO JOURNAL_AUDIT (id_user, username, action, detail) + SELECT id_user, username, 'CREATE_USER', 'Compte de visite cree (script SQL)' + FROM [USER] WHERE username = @username; + + PRINT 'Compte "Jure" cree.'; + END + + COMMIT TRANSACTION; +END TRY +BEGIN CATCH + IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION; + PRINT 'ECHEC : ' + ERROR_MESSAGE(); + THROW; +END CATCH + +-- Vérification +SELECT id_user, username, email, role, actif, created_at, last_login + FROM [USER] + WHERE username = N'Juré'; diff --git a/sql/data_sentinel_auth.sql b/sql/data_sentinel_auth.sql new file mode 100644 index 0000000..25ecb7c --- /dev/null +++ b/sql/data_sentinel_auth.sql @@ -0,0 +1,105 @@ +-- ============================================================ +-- DATA SENTINEL — Script d'authentification SQL Server +-- Tables [USER] + JOURNAL_AUDIT + comptes de démonstration +-- Auteur : COYAUD Anthony +-- Version : 1.1 — Juin 2026 +-- À exécuter APRÈS data_sentinel_init.sql (même base DataSentinel) +-- ============================================================ +-- +-- Ce script crée la couche de sécurité référencée par l'API +-- (main.py / auth.py) : +-- - [USER] : comptes applicatifs (RBAC : Admin / Superviseur / Consultant) +-- - JOURNAL_AUDIT : journal d'audit (connexions + actions d'administration) +-- +-- Les mots de passe sont stockés hachés en bcrypt (passlib[bcrypt]). +-- Les hachages ci-dessous correspondent aux comptes de démonstration +-- documentés dans le README (à régénérer en production). +-- ============================================================ + +USE DataSentinel; +GO + +-- ============================================================ +-- SUPPRESSION (ordre inverse des dépendances) +-- ============================================================ +IF OBJECT_ID('JOURNAL_AUDIT', 'U') IS NOT NULL DROP TABLE JOURNAL_AUDIT; +IF OBJECT_ID('[USER]', 'U') IS NOT NULL DROP TABLE [USER]; +GO + +-- ============================================================ +-- 1. TABLE [USER] — comptes applicatifs +-- ([USER] entre crochets car USER est un mot réservé SQL Server) +-- ============================================================ +CREATE TABLE [USER] ( + id_user INT NOT NULL IDENTITY(1,1), + username NVARCHAR(100) NOT NULL, + email NVARCHAR(200) NULL, + password_hash NVARCHAR(255) NOT NULL, -- bcrypt + role NVARCHAR(20) NOT NULL, -- Admin | Superviseur | Consultant + actif BIT NOT NULL DEFAULT 1, + created_at DATETIME2 NOT NULL DEFAULT SYSDATETIME(), + last_login DATETIME2 NULL, + CONSTRAINT PK_USER PRIMARY KEY (id_user), + CONSTRAINT UQ_USER_NAME UNIQUE (username), + CONSTRAINT CK_USER_ROLE CHECK (role IN ('Admin', 'Superviseur', 'Consultant')) +); +GO + +CREATE INDEX IX_USER_USERNAME ON [USER] (username); +GO + +-- ============================================================ +-- 2. TABLE JOURNAL_AUDIT — journal d'audit applicatif +-- Alimenté à chaque login + action d'administration. +-- username/id_user nullables (anonymisation RGPD : droit à l'oubli). +-- ============================================================ +CREATE TABLE JOURNAL_AUDIT ( + id_audit INT NOT NULL IDENTITY(1,1), + id_user INT NULL, + username NVARCHAR(100) NULL, + action NVARCHAR(50) NOT NULL, -- LOGIN | CREATE_USER | UPDATE_USER | DELETE_USER | RESET_PASSWORD + detail NVARCHAR(500) NULL, + ip NVARCHAR(50) NULL, + date_action DATETIME2 NOT NULL DEFAULT SYSDATETIME(), + CONSTRAINT PK_JOURNAL_AUDIT PRIMARY KEY (id_audit) +); +GO + +CREATE INDEX IX_AUDIT_DATE ON JOURNAL_AUDIT (date_action DESC); +GO + +-- ============================================================ +-- 3. COMPTES DE DÉMONSTRATION +-- ⚠️ Mots de passe en clair (à usage de recette / soutenance) : +-- Juré / 123456 → rôle Admin (compte de visite / évaluation) +-- admin / Admin2026! → rôle Admin +-- superviseur / Super2026! → rôle Superviseur +-- consultant / Conseil2026! → rôle Consultant +-- Les hachages bcrypt ci-dessous sont fonctionnels tels quels. +-- ============================================================ +INSERT INTO [USER] (username, email, password_hash, role, actif) VALUES + (N'Juré', 'JURE@NEXA.com', + '$2b$12$nnWMOCjSiUq4rAyPGbC3W.HGdsvWKu9kEfLst6zBIEIcsgP97W94m', 'Admin', 1), + ('admin', 'admin@xefi-fictif.fr', + '$2b$12$XJobnqM0cHwekv7UYWXUfuxVjMKLZI6VLzpDvRzDdLJgnYHLRNRCy', 'Admin', 1), + ('superviseur', 'superviseur@xefi-fictif.fr', + '$2b$12$gMVg2j6wngZZ2KXH2jF6HuvlcAkGIJsbZ05JEQdDYNnIu7fDxOXri', 'Superviseur', 1), + ('consultant', 'consultant@xefi-fictif.fr', + '$2b$12$s4Gl3UDq56HOw/GdjeHCrOFjXN/QrV1OEj3wmHhf3T8mFVfijJkty', 'Consultant', 1); +GO + +-- Entrée d'audit initiale (création du jeu de comptes) +INSERT INTO JOURNAL_AUDIT (id_user, username, action, detail) +SELECT id_user, username, 'CREATE_USER', 'Compte de démonstration (seed)' +FROM [USER]; +GO + +-- ============================================================ +-- 4. VÉRIFICATIONS +-- ============================================================ +SELECT 'USER' AS [Table], COUNT(*) AS [Lignes] FROM [USER] +UNION ALL SELECT 'JOURNAL_AUDIT', COUNT(*) FROM JOURNAL_AUDIT; +GO + +SELECT id_user, username, email, role, actif, created_at FROM [USER] ORDER BY id_user; +GO