613 lines
13 KiB
Markdown
613 lines
13 KiB
Markdown
# API D6MON - Documentation
|
|
|
|
## Introduction
|
|
|
|
L'API D6MON est une interface RESTful permettant d'interagir avec l'application D6MON. Cette API gère l'authentification des utilisateurs, la gestion des profils utilisateurs et la gestion des entités.
|
|
|
|
## Configuration
|
|
|
|
### Base URL
|
|
|
|
```
|
|
https://app.d6mon.com/api/mon
|
|
```
|
|
|
|
### En-têtes requis
|
|
|
|
Pour toutes les requêtes à l'API, les en-têtes suivants sont requis :
|
|
|
|
```
|
|
Content-Type: application/json
|
|
X-App-Identifier: app.d6mon.com
|
|
X-Client-Type: mobile
|
|
```
|
|
|
|
Pour les endpoints protégés (nécessitant une authentification), ajoutez également :
|
|
|
|
```
|
|
Authorization: Bearer {token}
|
|
```
|
|
|
|
Où `{token}` est le jeton d'authentification obtenu lors de la connexion.
|
|
|
|
## Authentification
|
|
|
|
### Connexion
|
|
|
|
**Endpoint :** `POST /login`
|
|
|
|
**Corps de la requête :**
|
|
|
|
```json
|
|
{
|
|
"email": "utilisateur@exemple.com",
|
|
"password": "motdepasse"
|
|
}
|
|
```
|
|
|
|
**Réponse réussie :**
|
|
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"token": "session_token_here",
|
|
"user": {
|
|
"id": 123,
|
|
"email": "utilisateur@exemple.com",
|
|
"last_name": "Nom",
|
|
"first_name": "Prénom",
|
|
"display_name": "Nom d'affichage",
|
|
"entity_id": 456
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
### Inscription
|
|
|
|
**Endpoint :** `POST /register`
|
|
|
|
**Corps de la requête :**
|
|
|
|
```json
|
|
{
|
|
"display_name": "Nom d'affichage",
|
|
"email": "utilisateur@exemple.com",
|
|
"first_name": "Prénom",
|
|
"last_name": "Nom",
|
|
"entity_id": 456
|
|
}
|
|
```
|
|
|
|
**Réponse réussie :**
|
|
|
|
```json
|
|
{
|
|
"success": true,
|
|
"message": "Inscription réussie. Un email contenant vos identifiants vous a été envoyé.",
|
|
"data": {
|
|
"user": {
|
|
"id": 123,
|
|
"email": "utilisateur@exemple.com",
|
|
"display_name": "Nom d'affichage"
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
### Mot de passe oublié
|
|
|
|
**Endpoint :** `POST /lost-password`
|
|
|
|
**Corps de la requête :**
|
|
|
|
```json
|
|
{
|
|
"email": "utilisateur@exemple.com"
|
|
}
|
|
```
|
|
|
|
**Réponse réussie :**
|
|
|
|
```json
|
|
{
|
|
"success": true,
|
|
"message": "Un nouveau mot de passe a été envoyé à votre adresse email."
|
|
}
|
|
```
|
|
|
|
### Déconnexion
|
|
|
|
**Endpoint :** `POST /logout`
|
|
|
|
**Réponse réussie :**
|
|
|
|
```json
|
|
{
|
|
"success": true,
|
|
"message": "Déconnecté avec succès"
|
|
}
|
|
```
|
|
|
|
## Gestion des utilisateurs
|
|
|
|
### Récupérer le profil de l'utilisateur connecté
|
|
|
|
**Endpoint :** `GET /user/profile`
|
|
|
|
**Réponse réussie :**
|
|
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"id": 123,
|
|
"entity_id": 456,
|
|
"display_name": "Nom d'affichage",
|
|
"first_name": "Prénom",
|
|
"last_name": "Nom",
|
|
"avatar": "url_avatar",
|
|
"email": "utilisateur@exemple.com",
|
|
"phone": "+33612345678",
|
|
"address1": "Adresse ligne 1",
|
|
"address2": "Adresse ligne 2",
|
|
"code_postal": "75000",
|
|
"city": "Paris",
|
|
"country": "France",
|
|
"seat_name": "Siège",
|
|
"created_at": "2023-01-01T00:00:00Z",
|
|
"updated_at": "2023-01-01T00:00:00Z",
|
|
"connected_at": "2023-01-01T00:00:00Z",
|
|
"is_active": true,
|
|
"entity": {
|
|
"id": 456,
|
|
"name": "Nom de l'entité",
|
|
"email": "entite@exemple.com",
|
|
"phone": "+33123456789",
|
|
"address1": "Adresse ligne 1",
|
|
"address2": "Adresse ligne 2",
|
|
"code_postal": "75000",
|
|
"city": "Paris",
|
|
"country": "France",
|
|
"created_at": "2023-01-01T00:00:00Z",
|
|
"updated_at": "2023-01-01T00:00:00Z",
|
|
"is_active": true
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
### Mettre à jour le profil de l'utilisateur connecté
|
|
|
|
**Endpoint :** `PUT /user/profile`
|
|
|
|
**Corps de la requête :**
|
|
|
|
```json
|
|
{
|
|
"display_name": "Nouveau nom d'affichage",
|
|
"first_name": "Nouveau prénom",
|
|
"last_name": "Nouveau nom",
|
|
"phone": "+33612345678",
|
|
"address1": "Nouvelle adresse ligne 1",
|
|
"address2": "Nouvelle adresse ligne 2",
|
|
"code_postal": "75001",
|
|
"city": "Paris",
|
|
"country": "France",
|
|
"seat_name": "Nouveau siège"
|
|
}
|
|
```
|
|
|
|
**Réponse réussie :**
|
|
Même format que `GET /user/profile` avec les données mises à jour.
|
|
|
|
### Changer le mot de passe
|
|
|
|
**Endpoint :** `POST /user/change-password`
|
|
|
|
**Corps de la requête :**
|
|
|
|
```json
|
|
{
|
|
"current_password": "ancien_mot_de_passe",
|
|
"new_password": "nouveau_mot_de_passe"
|
|
}
|
|
```
|
|
|
|
**Réponse réussie :**
|
|
|
|
```json
|
|
{
|
|
"success": true,
|
|
"message": "Mot de passe changé avec succès"
|
|
}
|
|
```
|
|
|
|
### Récupérer un utilisateur par ID
|
|
|
|
**Endpoint :** `GET /user/{id}`
|
|
|
|
**Réponse réussie :**
|
|
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"id": 123,
|
|
"entity_id": 456,
|
|
"display_name": "Nom d'affichage",
|
|
"first_name": "Prénom",
|
|
"last_name": "Nom",
|
|
"avatar": "url_avatar",
|
|
"email": "utilisateur@exemple.com",
|
|
"phone": "+33612345678",
|
|
"address1": "Adresse ligne 1",
|
|
"address2": "Adresse ligne 2",
|
|
"code_postal": "75000",
|
|
"city": "Paris",
|
|
"country": "France",
|
|
"seat_name": "Siège",
|
|
"created_at": "2023-01-01T00:00:00Z",
|
|
"updated_at": "2023-01-01T00:00:00Z",
|
|
"connected_at": "2023-01-01T00:00:00Z",
|
|
"is_active": true
|
|
}
|
|
}
|
|
```
|
|
|
|
### Récupérer la liste des utilisateurs
|
|
|
|
**Endpoint :** `GET /users`
|
|
|
|
**Paramètres de requête :**
|
|
|
|
- `page` (optionnel) : Numéro de page (défaut : 1)
|
|
- `limit` (optionnel) : Nombre d'éléments par page (défaut : 20)
|
|
- `entity_id` (optionnel) : Filtrer par ID d'entité
|
|
|
|
**Réponse réussie :**
|
|
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"users": [
|
|
{
|
|
"id": 123,
|
|
"entity_id": 456,
|
|
"display_name": "Nom d'affichage",
|
|
"first_name": "Prénom",
|
|
"last_name": "Nom",
|
|
"avatar": "url_avatar",
|
|
"email": "utilisateur@exemple.com",
|
|
"address1": "Adresse ligne 1",
|
|
"city": "Paris",
|
|
"country": "France",
|
|
"created_at": "2023-01-01T00:00:00Z",
|
|
"updated_at": "2023-01-01T00:00:00Z",
|
|
"connected_at": "2023-01-01T00:00:00Z",
|
|
"is_active": true
|
|
}
|
|
],
|
|
"pagination": {
|
|
"total": 100,
|
|
"page": 1,
|
|
"limit": 20,
|
|
"pages": 5
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
### Créer un nouvel utilisateur
|
|
|
|
**Endpoint :** `POST /user`
|
|
|
|
**Corps de la requête :**
|
|
|
|
```json
|
|
{
|
|
"display_name": "Nom d'affichage",
|
|
"email": "utilisateur@exemple.com",
|
|
"first_name": "Prénom",
|
|
"last_name": "Nom",
|
|
"entity_id": 456,
|
|
"phone": "+33612345678",
|
|
"address1": "Adresse ligne 1",
|
|
"address2": "Adresse ligne 2",
|
|
"code_postal": "75000",
|
|
"city": "Paris",
|
|
"country": "France",
|
|
"seat_name": "Siège"
|
|
}
|
|
```
|
|
|
|
**Réponse réussie :**
|
|
|
|
```json
|
|
{
|
|
"success": true,
|
|
"message": "Utilisateur créé avec succès. Un email avec les identifiants a été envoyé.",
|
|
"data": {
|
|
"id": 123,
|
|
"display_name": "Nom d'affichage",
|
|
"email": "utilisateur@exemple.com"
|
|
}
|
|
}
|
|
```
|
|
|
|
### Désactiver un utilisateur
|
|
|
|
**Endpoint :** `DELETE /user/{id}`
|
|
|
|
**Réponse réussie :**
|
|
|
|
```json
|
|
{
|
|
"success": true,
|
|
"message": "Utilisateur désactivé avec succès"
|
|
}
|
|
```
|
|
|
|
## Gestion des entités
|
|
|
|
### Récupérer toutes les entités
|
|
|
|
**Endpoint :** `GET /entities`
|
|
|
|
**Paramètres de requête :**
|
|
|
|
- `page` (optionnel) : Numéro de page (défaut : 1)
|
|
- `limit` (optionnel) : Nombre d'éléments par page (défaut : 20)
|
|
- `search` (optionnel) : Terme de recherche
|
|
|
|
**Réponse réussie :**
|
|
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"entities": [
|
|
{
|
|
"id": 456,
|
|
"name": "Nom de l'entité",
|
|
"email": "entite@exemple.com",
|
|
"phone": "+33123456789",
|
|
"address1": "Adresse ligne 1",
|
|
"address2": "Adresse ligne 2",
|
|
"code_postal": "75000",
|
|
"city": "Paris",
|
|
"country": "France",
|
|
"created_at": "2023-01-01T00:00:00Z",
|
|
"updated_at": "2023-01-01T00:00:00Z",
|
|
"is_active": true
|
|
}
|
|
],
|
|
"pagination": {
|
|
"total": 50,
|
|
"page": 1,
|
|
"limit": 20,
|
|
"pages": 3
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
### Récupérer une entité par ID
|
|
|
|
**Endpoint :** `GET /entity/{id}`
|
|
|
|
**Réponse réussie :**
|
|
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"id": 456,
|
|
"name": "Nom de l'entité",
|
|
"email": "entite@exemple.com",
|
|
"phone": "+33123456789",
|
|
"address1": "Adresse ligne 1",
|
|
"address2": "Adresse ligne 2",
|
|
"code_postal": "75000",
|
|
"city": "Paris",
|
|
"country": "France",
|
|
"created_at": "2023-01-01T00:00:00Z",
|
|
"updated_at": "2023-01-01T00:00:00Z",
|
|
"is_active": true,
|
|
"users": [
|
|
{
|
|
"id": 123,
|
|
"display_name": "Nom d'affichage",
|
|
"first_name": "Prénom",
|
|
"last_name": "Nom",
|
|
"avatar": "url_avatar",
|
|
"email": "utilisateur@exemple.com",
|
|
"created_at": "2023-01-01T00:00:00Z",
|
|
"is_active": true
|
|
}
|
|
]
|
|
}
|
|
}
|
|
```
|
|
|
|
### Créer une nouvelle entité
|
|
|
|
**Endpoint :** `POST /entity`
|
|
|
|
**Corps de la requête :**
|
|
|
|
```json
|
|
{
|
|
"name": "Nom de l'entité",
|
|
"email": "entite@exemple.com",
|
|
"phone": "+33123456789",
|
|
"address1": "Adresse ligne 1",
|
|
"address2": "Adresse ligne 2",
|
|
"code_postal": "75000",
|
|
"city": "Paris",
|
|
"country": "France"
|
|
}
|
|
```
|
|
|
|
**Réponse réussie :**
|
|
|
|
```json
|
|
{
|
|
"success": true,
|
|
"message": "Entité créée avec succès",
|
|
"data": {
|
|
"id": 456,
|
|
"name": "Nom de l'entité"
|
|
}
|
|
}
|
|
```
|
|
|
|
### Mettre à jour une entité
|
|
|
|
**Endpoint :** `PUT /entity/{id}`
|
|
|
|
**Corps de la requête :**
|
|
|
|
```json
|
|
{
|
|
"name": "Nouveau nom de l'entité",
|
|
"email": "nouvelle-entite@exemple.com",
|
|
"phone": "+33987654321",
|
|
"address1": "Nouvelle adresse ligne 1",
|
|
"address2": "Nouvelle adresse ligne 2",
|
|
"code_postal": "75001",
|
|
"city": "Paris",
|
|
"country": "France"
|
|
}
|
|
```
|
|
|
|
**Réponse réussie :**
|
|
Même format que `GET /entity/{id}` avec les données mises à jour.
|
|
|
|
### Désactiver une entité
|
|
|
|
**Endpoint :** `DELETE /entity/{id}`
|
|
|
|
**Réponse réussie :**
|
|
|
|
```json
|
|
{
|
|
"success": true,
|
|
"message": "Entité désactivée avec succès"
|
|
}
|
|
```
|
|
|
|
### Récupérer les utilisateurs d'une entité
|
|
|
|
**Endpoint :** `GET /entity/{id}/users`
|
|
|
|
**Paramètres de requête :**
|
|
|
|
- `page` (optionnel) : Numéro de page (défaut : 1)
|
|
- `limit` (optionnel) : Nombre d'éléments par page (défaut : 20)
|
|
|
|
**Réponse réussie :**
|
|
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"users": [
|
|
{
|
|
"id": 123,
|
|
"display_name": "Nom d'affichage",
|
|
"first_name": "Prénom",
|
|
"last_name": "Nom",
|
|
"avatar": "url_avatar",
|
|
"email": "utilisateur@exemple.com",
|
|
"phone": "+33612345678",
|
|
"created_at": "2023-01-01T00:00:00Z",
|
|
"updated_at": "2023-01-01T00:00:00Z",
|
|
"connected_at": "2023-01-01T00:00:00Z",
|
|
"is_active": true
|
|
}
|
|
],
|
|
"pagination": {
|
|
"total": 25,
|
|
"page": 1,
|
|
"limit": 20,
|
|
"pages": 2
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
## Structure des données
|
|
|
|
### Table `users`
|
|
|
|
```sql
|
|
CREATE TABLE users (
|
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
|
entity_id INT,
|
|
display_name VARCHAR(100) NOT NULL,
|
|
first_name VARCHAR(100),
|
|
encrypted_last_name VARCHAR(512),
|
|
avatar VARCHAR(255),
|
|
encrypted_email VARCHAR(512),
|
|
encrypted_phone VARCHAR(255),
|
|
address1 VARCHAR(255),
|
|
address2 VARCHAR(255),
|
|
code_postal VARCHAR(20),
|
|
city VARCHAR(100),
|
|
country VARCHAR(100),
|
|
seat_name VARCHAR(20),
|
|
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
|
connected_at DATETIME,
|
|
is_active BOOLEAN DEFAULT TRUE,
|
|
FOREIGN KEY (entity_id) REFERENCES entities(id)
|
|
);
|
|
```
|
|
|
|
### Table `entities`
|
|
|
|
```sql
|
|
CREATE TABLE entities (
|
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
|
encrypted_name VARCHAR(512) NOT NULL,
|
|
encrypted_email VARCHAR(512),
|
|
encrypted_phone VARCHAR(255),
|
|
address1 VARCHAR(255),
|
|
address2 VARCHAR(255),
|
|
code_postal VARCHAR(20),
|
|
city VARCHAR(100),
|
|
country VARCHAR(100),
|
|
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
|
is_active BOOLEAN DEFAULT TRUE
|
|
);
|
|
```
|
|
|
|
## Sécurité
|
|
|
|
L'API utilise plusieurs mécanismes pour assurer la sécurité des données :
|
|
|
|
1. **Authentification par jeton** : Un jeton d'authentification est requis pour accéder aux endpoints protégés.
|
|
2. **Chiffrement des données sensibles** : Les données sensibles comme les noms, emails et numéros de téléphone sont chiffrées en base de données.
|
|
3. **Validation des entrées** : Toutes les entrées utilisateur sont validées avant traitement.
|
|
4. **Gestion des erreurs** : Les erreurs sont gérées de manière sécurisée sans divulguer d'informations sensibles.
|
|
|
|
## Codes d'erreur
|
|
|
|
- `400 Bad Request` : Requête invalide ou données manquantes
|
|
- `401 Unauthorized` : Authentification requise ou échouée
|
|
- `403 Forbidden` : Accès non autorisé à la ressource
|
|
- `404 Not Found` : Ressource non trouvée
|
|
- `409 Conflict` : Conflit avec l'état actuel de la ressource
|
|
- `500 Internal Server Error` : Erreur serveur
|
|
|
|
## Notes d'implémentation
|
|
|
|
- Les mots de passe sont hachés avec l'algorithme bcrypt.
|
|
- Les données sensibles sont chiffrées avec AES-256-CBC.
|
|
- Les emails sont envoyés pour les opérations importantes (inscription, réinitialisation de mot de passe).
|
|
- Les sessions sont gérées côté serveur avec un délai d'expiration.
|