---
title: Modèle de Données
description: Structure et organisation des données
---

## 📊 Modèle de Données

### Conceptuel (MCD)

Le Modèle Conceptuel de Données décrit les grandes entités du système et leurs relations métier, incluant la gestion des accès et la modération.

```mermaid
erDiagram
    USER ||--o{ CONTENT : "publie"
    USER ||--o{ REPORT : "signale"
    USER ||--o{ USER_ROLE : "possede"
    USER ||--o{ SESSION : "detient"
    USER ||--o{ API_KEY : "genere"
    USER ||--o{ AUDIT_LOG : "genere"
    
    CONTENT ||--o{ CONTENT_TAG : "possede"
    TAG ||--o{ CONTENT_TAG : "est_lie_a"
    CONTENT ||--o{ REPORT : "est_signale"
    TAG ||--o{ REPORT : "est_signale"

    ROLE ||--o{ USER_ROLE : "attribue_a"
    ROLE ||--o{ ROLE_PERMISSION : "possede"
    PERMISSION ||--o{ ROLE_PERMISSION : "est_lie_a"

    USER {
        string username
        string email
        string display_name
        string status
    }
    CONTENT {
        string title
        string type
        string storage_key
    }
    TAG {
        string name
        string slug
    }
    ROLE {
        string name
        string slug
    }
    REPORT {
        string reason
        string status
    }
    SESSION {
        string refresh_token
        boolean is_valid
    }
    API_KEY {
        string name
        string prefix
        boolean is_active
    }
    AUDIT_LOG {
        string action
        string entity_type
        jsonb details
    }
```

### Logique (MLD)

Le Modèle Logique de Données précise les tables, les colonnes et les clés étrangères (FK).

```mermaid
erDiagram
    users {
        uuid uuid PK
        varchar username
        bytea email
        varchar email_hash
        varchar display_name
        varchar password_hash
        user_status status
        bytea two_factor_secret
        boolean is_two_factor_enabled
        varchar terms_version
        varchar privacy_version
        timestamp gdpr_accepted_at
        timestamp last_login_at
        timestamp created_at
        timestamp updated_at
        timestamp deleted_at
    }
    contents {
        uuid id PK
        uuid user_id FK
        content_type type
        varchar title
        varchar storage_key
        varchar mime_type
        integer file_size
        timestamp created_at
        timestamp updated_at
        timestamp deleted_at
    }
    tags {
        uuid id PK
        varchar name
        varchar slug
        timestamp created_at
        timestamp updated_at
    }
    contents_to_tags {
        uuid content_id PK, FK
        uuid tag_id PK, FK
    }
    roles {
        uuid id PK
        varchar name
        varchar slug
        varchar description
        timestamp created_at
    }
    permissions {
        uuid id PK
        varchar name
        varchar slug
        varchar description
        timestamp created_at
    }
    roles_to_permissions {
        uuid role_id PK, FK
        uuid permission_id PK, FK
    }
    users_to_roles {
        uuid user_id PK, FK
        uuid role_id PK, FK
    }
    reports {
        uuid id PK
        uuid reporter_id FK
        uuid content_id FK
        uuid tag_id FK
        report_reason reason
        text description
        report_status status
        timestamp expires_at
        timestamp created_at
        timestamp updated_at
    }
    sessions {
        uuid id PK
        uuid user_id FK
        varchar refresh_token
        varchar user_agent
        varchar ip_hash
        boolean is_valid
        timestamp expires_at
        timestamp created_at
        timestamp updated_at
    }
    api_keys {
        uuid id PK
        uuid user_id FK
        varchar key_hash
        varchar name
        varchar prefix
        boolean is_active
        timestamp last_used_at
        timestamp expires_at
        timestamp created_at
        timestamp updated_at
    }
    audit_logs {
        uuid id PK
        uuid user_id FK
        varchar action
        varchar entity_type
        uuid entity_id
        jsonb details
        varchar ip_hash
        varchar user_agent
        timestamp created_at
    }

    users ||--o{ contents : "user_id"
    users ||--o{ users_to_roles : "user_id"
    roles ||--o{ users_to_roles : "role_id"
    roles ||--o{ roles_to_permissions : "role_id"
    permissions ||--o{ roles_to_permissions : "permission_id"
    contents ||--o{ contents_to_tags : "content_id"
    tags ||--o{ contents_to_tags : "tag_id"
    users ||--o{ reports : "reporter_id"
    contents ||--o{ reports : "content_id"
    tags ||--o{ reports : "tag_id"
    users ||--o{ sessions : "user_id"
    users ||--o{ api_keys : "user_id"
    users ||--o{ audit_logs : "user_id"
```

### Physique (MPD)

Le Modèle Physique de Données détaille l'implémentation spécifique pour **PostgreSQL**.

```mermaid
erDiagram
    users {
        uuid uuid "DEFAULT gen_random_uuid()"
        bytea email "ENCRYPTED, NOT NULL"
        varchar email_hash "UNIQUE, INDEXED"
        varchar username "UNIQUE, NOT NULL"
        varchar password_hash "NOT NULL"
        bytea two_factor_secret "ENCRYPTED"
        boolean is_two_factor_enabled "DEFAULT false"
        timestamp gdpr_accepted_at "NULLABLE"
        timestamp deleted_at "SOFT DELETE"
    }
    contents {
        uuid id "DEFAULT gen_random_uuid()"
        uuid user_id "REFERENCES users(uuid)"
        varchar storage_key "UNIQUE, NOT NULL"
        integer file_size "NOT NULL"
        timestamp deleted_at "SOFT DELETE"
    }
    reports {
        uuid id "DEFAULT gen_random_uuid()"
        uuid reporter_id "REFERENCES users(uuid)"
        timestamp expires_at "RGPD PURGE"
    }
    api_keys {
        uuid id "DEFAULT gen_random_uuid()"
        varchar key_hash "UNIQUE, INDEXED, SHA-256"
        varchar prefix "NOT NULL"
    }
    audit_logs {
        uuid id "DEFAULT gen_random_uuid()"
        jsonb details "STORED AS JSONB"
        varchar ip_hash "RGPD COMPLIANT"
    }
    sessions {
        uuid id "DEFAULT gen_random_uuid()"
        varchar refresh_token "UNIQUE, NOT NULL"
        varchar ip_hash "RGPD COMPLIANT"
    }
```

#### Sécurité et Chiffrement
- **Chiffrement PGP (Native)** : Les colonnes `email` et `two_factor_secret` sont stockées au format `bytea` et chiffrées/déchiffrées via les fonctions `pgp_sym_encrypt` et `pgp_sym_decrypt` de PostgreSQL (via l'extension `pgcrypto`).
- **Hachage aveugle (Blind Indexing)** : La colonne `email_hash` stocke un hash (SHA-256) de l'email pour permettre les recherches d'unicité et les recherches rapides sans déchiffrer la donnée.

#### Index et Optimisations
- **Index B-Tree** systématiques sur toutes les clés étrangères (`user_id`, `role_id`, etc.).
- **Index sur `deleted_at`** : Pour optimiser les requêtes excluant les données supprimées logiciellement.
- **Index unique sur `email_hash`** et `username`.

#### Conformité RGPD
- **Soft Delete** : Implémenté via `deleted_at` pour permettre le "droit à l'oubli" tout en conservant l'intégrité référentielle temporaire.
- **Purge Automatique** : La colonne `expires_at` dans la table `reports` permet de programmer la suppression automatique des données de signalement après traitement.
