# Guide administrateur

Ce guide couvre l'administration generale de l'application (moteur
principal). La documentation d'administration des modules est dans
leurs repertoires respectifs :

- **Module Oracle** : [modules/oracle/docs/guide-administrateur.md](../mon-appli/modules/oracle/docs/guide-administrateur.md)
- **Module CNP** : [modules/CNP/docs/guide-administrateur.md](../mon-appli/modules/CNP/docs/guide-administrateur.md)

Pour l'utilisation quotidienne, voir
[guide-utilisateur.md](guide-utilisateur.md).
Pour l'installation initiale, voir
[installation-deploiement.md](installation-deploiement.md).

---

## Table des matieres

1. [Tableau de bord admin](#1-tableau-de-bord-admin)
2. [Gestion des utilisateurs](#2-gestion-des-utilisateurs)
3. [Systeme de roles](#3-systeme-de-roles)
4. [Methodes d'authentification](#4-methodes-dauthentification)
5. [Parametres de l'application](#5-parametres-de-lapplication)
6. [Systeme de modules](#6-systeme-de-modules)
7. [Sauvegarde et restauration](#7-sauvegarde-et-restauration)
8. [Journalisation et debug](#8-journalisation-et-debug)
9. [Securite](#9-securite)

---

# Moteur principal

## 1. Tableau de bord admin

Accessible via le menu utilisateur > **Administration** (visible
uniquement avec le role `app_admin`).

![admin](./imgs/01-ADM-IndexDash.png)

Le panneau d'administration est organise en sections dans la barre
laterale gauche :

```mermaid
graph TD
    A[Administration] --> B[Tableau de bord]
    A --> C[Utilisateurs]
    A --> D[Parametres]
    A --> E[Maintenance]
    A --> F[Modules]
    C --> C1[Liste des utilisateurs]
    C --> C2[Creer un utilisateur]
    D --> D1[Apparence]
    D --> D2[Debug / Trace]
    D --> D3[Methodes d'authentification]
    D --> D4[SMTP]
    E --> E1[Sauvegarde et restauration]
    E --> E2[Mise a jour]
    F --> F1[Gestion des modules]
```

---

## 2. Gestion des utilisateurs

**Acces** : `app_admin` uniquement.

### Liste des utilisateurs

![users](./imgs/02-ADM-users.png)

Tableau de tous les comptes avec :

- Identifiant, e-mail
- Methode d'authentification (local / LDAP / OAuth)
- Roles attribues
- Statut (actif / inactif)
- Derniere connexion
- Actions : modifier, supprimer

### Creation d'un utilisateur

![creUser](./imgs/03-ADM-UserADD.png)

| Champ | Obligatoire | Notes |
|-------|:-----------:|-------|
| Identifiant | Oui | Unique, non modifiable apres creation |
| E-mail | Non | |
| Mot de passe | Oui (creation) | Min. 8 caracteres, hache en bcrypt |
| Methode d'auth | Oui | local, ldap ou oauth |
| Roles | Non | Checkboxes groupees par module |
| Langue | Non | Herite du defaut si vide |
| Theme | Non | Herite du defaut si vide |
| Actif | Oui | Un compte inactif ne peut pas se connecter |

### Modification d'un utilisateur

Meme formulaire que la creation, avec les regles suivantes :

- L'identifiant est en lecture seule
- Le mot de passe est optionnel (vide = conserver l'existant)
- **Protection** : vous ne pouvez pas retirer votre propre role
  `app_admin` ni supprimer votre propre compte

### Comptes crees automatiquement (LDAP/OAuth)

Lors d'une premiere connexion LDAP ou OAuth, un compte est cree
automatiquement **sans aucun role**. L'administrateur doit attribuer les
roles manuellement.

---

## 3. Systeme de roles

### Architecture multi-roles

Chaque utilisateur peut avoir 0 a N roles. Les roles sont de deux types :

```mermaid
graph LR
    subgraph "Roles systeme"
        A[app_admin<br>Super-administrateur]
    end
    subgraph "Roles de module"
        B[oracle_admin]
        C[oracle_user]
        D[module_admin]
        E[module_user]
    end
    A -.->|"acces implicite<br>a tout"| B
    A -.-> C
    A -.-> D
    A -.-> E
```

**`app_admin`** est un **super-role implicite** : tous les controles de
role (`hasRole`, `hasAnyRole`, `canAccess`, `canAccessAsAdmin`)
renvoient vrai si l'utilisateur le possede.

### Roles declares par les modules

Chaque module declare ses propres roles dans son descripteur. Convention :

- `<module>_admin` : acces complet au module (configuration + consultation)
- `<module>_user` : consultation uniquement

Les roles sont automatiquement synchronises dans la table `roles` au
demarrage de l'application (idempotent).

### Verification des roles dans le code

| Methode | Usage |
|---------|-------|
| `$auth->hasRole('oracle_admin')` | Verifie un role specifique |
| `$auth->hasAnyRole('oracle_admin', 'oracle_user')` | Verifie au moins un role |
| `$auth->requireRole('oracle_admin')` | Bloque avec HTTP 403 si le role manque |

---

## 4. Methodes d'authentification

### Vue d'ensemble

La configuration des methodes se fait dans **Parametres > Methodes
d'authentification**.

![authMethods](./imgs/04-ADM-AuthMethod.png)

Chaque methode peut etre activee/desactivee independamment. Plusieurs
methodes peuvent coexister.

### Authentification locale

Aucune configuration requise. Les comptes et mots de passe sont stockes
dans la base SQLite de l'application. Les mots de passe sont haches en
bcrypt.

### Authentification LDAP

| Parametre | Description |
|-----------|-------------|
| Hote | Adresse du serveur LDAP (ex. `ldap.exemple.com`) |
| Port | Port (389 pour LDAP, 636 pour LDAPS) |
| Base DN | Racine de recherche (ex. `dc=exemple,dc=com`) |
| Bind DN | DN du compte de service (ex. `cn=admin,dc=...`) |
| Bind Password | Mot de passe du compte de service (chiffre au repos) |
| User DN Pattern | Pattern de recherche (ex. `uid={user},{base_dn}`) |
| TLS insecure | Accepter les certificats auto-signes |

**Variables disponibles dans User DN Pattern** :

| Variable | Remplacee par |
|----------|---------------|
| `{user}` | Identifiant saisi |
| `{base_dn}` | Valeur du champ Base DN |
| `{domain}` | Domaine extrait des DC= du Base DN |

Un bouton **Tester la connexion** permet de valider la configuration.

![settings](./imgs/05-ADM-ADConf.png)

Pour plus de details, voir
[authentification-ldap.md](authentification-ldap.md).

### Authentification OAuth / OIDC

| Parametre | Description |
|-----------|-------------|
| Client ID | Identifiant de l'application aupres du fournisseur |
| Client Secret | Secret client (chiffre au repos) |
| Redirect URI | URL de callback (ex. `https://app.exemple.com/login.php`) |
| Auth URL | URL d'autorisation du fournisseur |
| Token URL | URL d'echange de token |

Compatible avec tout fournisseur OpenID Connect (Keycloak, Azure AD,
Google, etc.).

---

## 5. Parametres de l'application

### Apparence

| Parametre | Description |
|-----------|-------------|
| Theme par defaut | Theme applique aux nouveaux utilisateurs et aux visiteurs |
| Langue par defaut | Langue appliquee si l'utilisateur n'a pas de preference |

![apparence](./imgs/06-ADM-AppParams.png)

### SMTP (envoi d'e-mails)

| Parametre | Description |
|-----------|-------------|
| Serveur SMTP | Nom d'hote |
| Port | 25, 465 (SSL) ou 587 (STARTTLS) |
| Chiffrement | Aucun, TLS (STARTTLS) ou SSL. Les certificats auto-signes sont acceptes (relais internes). |
| Authentification SMTP | Checkbox. Decocher pour un relais interne anonyme (pas d'identifiants requis). |
| Identifiant | Actif uniquement si la checkbox est cochee |
| Mot de passe | Chiffre au repos. Actif uniquement si la checkbox est cochee |
| Adresse expediteur | Adresse From: |
| Nom expediteur | Nom affiche |

Le bouton **Envoyer un test** envoie un vrai e-mail HTML (avec le logo
de l'application) a l'adresse saisie. Le log complet de la conversation
SMTP (commandes et reponses) s'affiche pour faciliter le diagnostic.

![SMTP](./imgs/07-ADM-SMTP_Conf.png)

---

## 6. Systeme de modules

### Principe

Chaque module est un dossier dans `mon-appli/modules/<nom>/` contenant
un descripteur `module.php`. La decouverte est automatique au demarrage.

```mermaid
sequenceDiagram
    participant B as Bootstrap
    participant M as Module Registry
    participant DB as Base SQLite
    B->>M: glob(modules/*/module.php)
    loop Chaque module
        M->>DB: INSERT OR IGNORE module
        M->>DB: INSERT OR IGNORE roles du module
    end
    Note over M: Modules decouverts mais pas forcement actifs
```

### Activation / Desactivation

![modules](./imgs/08-ADM-Modules.png)

Sur la page **Gestion des modules**, chaque module est represente par une
carte avec :

- Nom, version, description, icone
- Badge vert (actif) ou rouge (inactif)
- Roles declares
- Dependances
- Bouton Activer/Desactiver

**Regles de dependance** :

- Un module ne peut etre active que si tous les modules dont il depend
  (`depends_on`) sont deja actifs
- Un module ne peut etre desactive que si aucun module actif ne depend de
  lui

**Hook d'activation** : certains modules executent un script de
verification avant activation (ex. verifier qu'une configuration
prealable est en place). En cas d'echec, l'activation est refusee avec
un message d'erreur et une redirection vers la page de configuration du
module.

**Activation groupee (PostgreSQL)** : si le module `postgresql` est
inactif, un bouton « Activer PostgreSQL et ses dependances » apparait
dans l'en-tete de la page. Il active le module postgresql ainsi que
tous les modules dont il depend (`depends_on`, suivi transitivement),
dans l'ordre impose par les dependances. Les hooks d'activation et le
provisioning de chaque module sont executes normalement ; en cas
d'echec d'un module, les autres activations se poursuivent et un
message recapitule les modules actives et les echecs (avec leur
raison). Contrairement a l'activation unitaire, il n'y a pas de
redirection vers la page de configuration du module en echec.

### Ajout et mise a jour d'un module

En bas de la page **Gestion des modules**, le formulaire « Ajouter ou
mettre a jour un module » accepte une archive ZIP contenant un **unique
dossier de module**, avec son `module.php` a la racine de ce dossier
(format produit par *Developer -> Export d'un module*). Le nom du dossier
et la cle `name` du descripteur doivent coincider, sinon l'archive est
refusee.

Le traitement depend de l'existence du module :

| Cas | Comportement |
| --- | --- |
| Module absent | Ajoute **desactive**. Activez-le ensuite. |
| Module deja installe | **Mis a jour en place**, sans desactivation prealable. |

Lors d'une mise a jour, seuls les **fichiers** du module sont remplaces.
Sont conserves : son etat actif/inactif, ses roles et leurs affectations
aux utilisateurs, sa configuration et ses tables de donnees. C'est la
difference essentielle avec la suppression, qui elle efface roles,
affectations et configuration.

Deroule d'une mise a jour :

1. l'application passe en mode maintenance (les `app_admin` gardent
   l'acces) ;
2. la version installee est sauvegardee dans
   `securite/backups/module_<nom>_<horodatage>.zip` — les 3 sauvegardes
   les plus recentes sont conservees ;
3. les fichiers sont remplaces ; en cas d'echec, la version precedente
   est restauree automatiquement ;
4. si le module est actif et declare un hook d'activation, celui-ci est
   rejoue (point d'accroche des migrations de schema d'une nouvelle
   version) ; son echec est signale sans desactiver le module ;
5. le mode maintenance est leve.

> La sauvegarde produite est elle-meme une archive de module valide :
> pour revenir a la version precedente, il suffit de la reteleverser par
> ce meme formulaire.

Si le remplacement echoue **et** que la restauration echoue aussi, le
mode maintenance reste actif volontairement : restaurez la sauvegarde
indiquee dans le message d'erreur, puis levez la maintenance depuis
*Administration -> Mise a jour*.

### Suppression d'un module

Reservee aux modules **desactives**. Elle retire le dossier du module
puis nettoie la base : ligne `modules`, roles du module (et donc leurs
affectations aux utilisateurs, en cascade) et fichier de configuration.
Les tables de donnees du module ne sont pas supprimees. Pour livrer une
nouvelle version d'un module, utilisez la mise a jour et non le couple
suppression + reinstallation.

### Configuration de module

Chaque module peut stocker sa configuration dans un fichier JSON
`securite/modules/<nom>.json` (anciennement le champ `modules.config`,
migre automatiquement au demarrage). L'acces se fait via :

```
$moduleRegistry->getConfig('oracle')    // lecture
$moduleRegistry->updateConfig('oracle', [...])  // ecriture
```

---

## 7. Sauvegarde et restauration

**Acces** : `app_admin` uniquement.

![backups](./imgs/09-ADM-BackupRestore.png)

### Perimetre

La sauvegarde couvre l'integralite du repertoire `securite/` :

| Contenu | Fichier |
|---------|---------|
| Base de donnees applicative | `database.sqlite` |
| Cle de chiffrement | `master.key` |
| Wallets Oracle | `wallets/` |
| Snapshots CPU schedule | `cpu_schedule_snapshots/` |
| Autres fichiers secrets | Tout fichier dans `securite/` |

> **Important** : la cle `master.key` et la base `database.sqlite`
> doivent etre sauvegardees **ensemble**. Perdre la cle rend les mots de
> passe chiffres irrecuperables.

### Creer une sauvegarde

Deux options :

| Action | Resultat |
|--------|----------|
| **Sauvegarder localement** | Cree `metadata_YYYYMMDD_HHMMSS.zip` dans `securite/backups/` |
| **Telecharger** | Genere le ZIP et le propose en telechargement |

### Restaurer une sauvegarde

1. **Depuis un fichier** : uploadez un fichier ZIP via le formulaire
2. **Depuis une sauvegarde locale** : selectionnez dans la liste

La restauration :

- Cree automatiquement une **sauvegarde pre-restauration**
  (`pre_restore_YYYYMMDD_HHMMSS.zip`) avant d'ecraser les fichiers
- Extrait fichier par fichier avec rapport de succes/echec
- Restaure les permissions de `master.key` (mode 0600)

> **Attention** : la restauration remplace la base de donnees. Apres
> restauration, les comptes, roles et configurations reviennent a l'etat
> de la sauvegarde.

### Gestion des sauvegardes locales

Le tableau liste les ZIP dans `securite/backups/` avec :
- Nom du fichier, taille, date
- Boutons : Restaurer, Supprimer

---

## 8. Journalisation et debug

### Fichiers de log

| Fichier | Contenu | Actif par defaut |
|---------|---------|:----------------:|
| `log/app.log` | Evenements applicatifs (connexions, erreurs) | Oui |
| `log/debug.log` | Messages de debug detailles | Non |
| `log/trace.log` | Trace complete de chaque requete HTTP | Non |

### Activation

Dans **Parametres > Debug / Trace** :

| Parametre | Description |
|-----------|-------------|
| Mode debug | Active `debug.log` — messages detailles |
| Mode trace | Active `trace.log` — chaque requete HTTP avec URL, parametres, headers |

![debug](./imgs/10-ADM-Debug.png)

> **Performance** : le mode trace genere un volume important de logs.
> Ne l'activer que temporairement pour diagnostiquer un probleme.

---

## 9. Securite

### Chiffrement au repos

Les secrets (mots de passe LDAP, OAuth, Oracle, wallet CMDB) sont
chiffres avec **libsodium** (XSalsa20-Poly1305 AEAD).

```mermaid
graph LR
    A[Mot de passe\nen clair] -->|Crypto::encrypt| B["enc_v1:base64(nonce||ciphertext)"]
    B -->|Crypto::decrypt| C[Mot de passe\nen clair]
    D[securite/master.key\n32 octets] --> A
    D --> B
```

- **Cle maitre** : `securite/master.key` (32 octets, auto-generee,
  mode 0600)
- **Format** : prefixe `enc_v1:` suivi du nonce et du ciphertext en
  base64
- **Idempotence** : `Crypto::encrypt()` ne re-chiffre pas une valeur
  deja chiffree ; une chaine vide reste vide

### Protection CSRF

Chaque formulaire POST inclut un jeton CSRF (`csrf_token`) verifie
cote serveur via `hash_equals()`.

### Protection de session

| Mesure | Detail |
|--------|--------|
| Cookie HttpOnly | JavaScript ne peut pas lire le cookie de session |
| Cookie SameSite=Lax | Protection contre les attaques CSRF cross-site |
| Cookie Secure | Transmis uniquement en HTTPS (si applicable) |
| Regeneration | L'ID de session est regenere toutes les 5 minutes |
| Duree de vie | 1 heure (configurable via `SESSION_LIFETIME`) |

### Requetes preparees

Toutes les requetes SQL passent par des parametres lies (bind). Aucune
concatenation de donnees utilisateur dans les requetes.

---

## Annexes

### Arborescence des fichiers importants

```
securite/
  database.sqlite          Base applicative (SQLite)
  master.key               Cle de chiffrement (mode 0600)
  backups/                 Sauvegardes ZIP
  wallets/<id>/            Wallets Oracle Cloud
  cpu_schedule_snapshots/  Snapshots du planning CPU
  remediation_oracle.json  Taches de remediation planifiees
  cmdb.sqlite              Cache CMDB local

log/
  app.log                  Journal applicatif
  debug.log                Debug (si active)
  trace.log                Trace HTTP (si activee)

mon-appli/
  bootstrap.php            Point d'entree commun
  login.php                Authentification
  index.php                Tableau de bord
  admin/                   Pages d'administration
  modules/oracle/          Module Oracle
  i18n/                    Fichiers de traduction
  assets/                  CSS, JS, images
  includes/                En-tete, pied de page, navigation
```

### Schema de la base de donnees (tables principales)

```mermaid
erDiagram
    users ||--o{ user_roles : "possede"
    roles ||--o{ user_roles : "attribue a"
    users {
        int id PK
        text username UK
        text email
        text password_hash
        text auth_method
        text language
        text theme
        int active
        datetime last_login
    }
    roles {
        int id PK
        text name UK
        text label
        text module
        int is_system
    }
    user_roles {
        int user_id FK
        int role_id FK
        datetime granted_at
    }
    auth_config {
        text method PK
        int enabled
        text config
    }
    settings {
        text key PK
        text value
    }
    modules {
        text name PK
        text label
        int active
        text config
    }
```

