426 lines
13 KiB
Markdown
426 lines
13 KiB
Markdown
# 📔 Carnet de Bord - Migration Inventory → Symfony
|
|
|
|
**Projet** : Migration backend NestJS/Prisma → Symfony/API Platform
|
|
**Début** : 2026-01-10
|
|
**Objectif** : Migrer vers Symfony + JWT + API Platform propre et maintenable
|
|
|
|
---
|
|
|
|
## 🔗 Convention de liaison des commits (INV)
|
|
|
|
- **Format** : `[INV-YYYYMMDD-XX]`
|
|
- **Usage** : même code dans les commits du backend **et** du frontend + ajout ici pour retrouver le duo rapidement.
|
|
|
|
## 🧾 Journal des liaisons INV
|
|
|
|
- INV-20260111-01 : ajout du lien submodule `Inventory_frontend` (commit backend : `987aa5c`, commit frontend : `936a73f`)
|
|
- INV-20260111-02 : alignement front API Platform + sessions (commit backend : `f7fc1bd`, commit frontend : `e99f053`)
|
|
|
|
## 🎯 Contexte
|
|
|
|
- **Situation initiale** :
|
|
- `Inventory_backend/` : NestJS + Prisma (fonctionnel, ~11k lignes)
|
|
- `Inventory_frontend/` : Nuxt 3 (fonctionnel, 105 fichiers)
|
|
- Base de données PostgreSQL avec données en production
|
|
|
|
- **Objectif** :
|
|
- Backend Symfony 8 + API Platform + JWT
|
|
- Garder les données existantes (migration Prisma → Doctrine)
|
|
- Frontend Nuxt connecté au nouveau backend
|
|
- Docker : 2 backends en parallèle pendant transition
|
|
|
|
---
|
|
|
|
## ✅ Phase 1 : Préparation (TERMINÉE - 10/01/2026)
|
|
|
|
### Ce qui a été fait
|
|
|
|
#### 1. Docker & Infrastructure ✅
|
|
- **pgAdmin ajouté** au docker-compose.yml
|
|
- Port : 5050
|
|
- Login : admin@admin.com / admin
|
|
- Container : `pgadmin-inventory`
|
|
- Volume persistant : `pgadmin_data`
|
|
- **Serveur PostgreSQL pré-configuré** :
|
|
- Fichier `docker/pgadmin/servers.json` monté automatiquement
|
|
- Fichier `docker/pgadmin/pgpass` pour authentification sans mot de passe
|
|
- Connexion automatique à `db:5432/inventory` au démarrage
|
|
- Nom du serveur : "Inventory PostgreSQL"
|
|
|
|
#### 2. Bundles Symfony installés ✅
|
|
```bash
|
|
# Versions installées
|
|
- lexik/jwt-authentication-bundle: v3.2.0
|
|
- vich/uploader-bundle: v2.9.1
|
|
- symfony/uid: 8.0.*
|
|
```
|
|
|
|
#### 3. JWT Configuration ✅
|
|
- **Clés RSA générées** : `config/jwt/private.pem` + `public.pem`
|
|
- **security.yaml configuré** :
|
|
- Firewall `login` : pattern `^/api/login_check` avec `json_login`
|
|
- Firewall `api` : pattern `^/api` avec `jwt` authenticator
|
|
- Provider : `app_user_provider` (entité Profile via email)
|
|
- Password hasher : bcrypt auto
|
|
|
|
#### 4. Entité Profile créée ✅
|
|
**Fichier** : `src/Entity/Profile.php`
|
|
|
|
**Caractéristiques** :
|
|
- Implémente `UserInterface` + `PasswordAuthenticatedUserInterface`
|
|
- Champs :
|
|
- `id` : string (30 chars, CUID-compatible pour Prisma)
|
|
- `email` : string unique (username pour JWT)
|
|
- `password` : string (hashed)
|
|
- `roles` : array JSON (ROLE_USER par défaut)
|
|
- `firstName`, `lastName` : string
|
|
- `isActive` : boolean
|
|
- `createdAt`, `updatedAt` : DateTimeImmutable
|
|
- Repository : `ProfileRepository` avec `PasswordUpgraderInterface`
|
|
- API Platform : endpoints CRUD auto-générés
|
|
|
|
#### 5. Base de Données ✅
|
|
- **Migration créée** : `Version20260110175413`
|
|
- **Table** : `profiles` créée avec succès
|
|
- **Utilisateur test créé** :
|
|
```
|
|
Email: admin@admin.com
|
|
Password: admin123
|
|
Roles: ['ROLE_USER', 'ROLE_ADMIN']
|
|
```
|
|
|
|
#### 6. API Platform ✅
|
|
- **Endpoint racine** : http://localhost:8081/api/
|
|
- **Réponse** :
|
|
```json
|
|
{
|
|
"@context": "/api/contexts/Entrypoint",
|
|
"@id": "/api/",
|
|
"@type": "Entrypoint",
|
|
"profile": "/api/profiles"
|
|
}
|
|
```
|
|
- **OpenAPI Docs** : Configurées (à tester)
|
|
|
|
#### 7. Configuration Apache ✅
|
|
- **VirtualHost** : `docker/php/config/vhost.conf`
|
|
- **DocumentRoot** : `/var/www/html/public`
|
|
- **AllowOverride** : All (pour `.htaccess`)
|
|
- **Port** : 8081 (Apache) → accessible depuis l'hôte
|
|
|
|
#### 8. Routing Symfony ✅
|
|
- **Routes définies** :
|
|
- `/api/login_check` : Login JWT
|
|
- `/api/test` : Test endpoint (TestController)
|
|
- `/api/*` : API Platform auto-routes
|
|
- **Vérification** :
|
|
```bash
|
|
php bin/console debug:router api_test
|
|
php bin/console router:match /api/test --method=GET
|
|
# ✅ Route found and matches
|
|
```
|
|
|
|
#### 9. .htaccess créé ✅
|
|
**Fichier** : `public/.htaccess`
|
|
|
|
**Contenu** : Symfony standard avec mod_rewrite
|
|
|
|
---
|
|
|
|
### ⚠️ Problèmes identifiés
|
|
|
|
#### 1. Routes inaccessibles via Apache (404)
|
|
|
|
**Symptôme** :
|
|
```bash
|
|
curl http://localhost:8081/api/test
|
|
# → 404 Not Found
|
|
```
|
|
|
|
**Tests effectués** :
|
|
- ✅ Route existe : `php bin/console debug:router api_test`
|
|
- ✅ Route match : `php bin/console router:match /api/test`
|
|
- ✅ Symfony fonctionne : `curl http://localhost:8081/api/` → JSON OK
|
|
- ✅ PHP built-in server OK :
|
|
```bash
|
|
php -S localhost:9000
|
|
curl http://localhost:9000/api/test
|
|
# → {"status":"ok","message":"Test endpoint works!"}
|
|
```
|
|
- ❌ Apache 404 : Depuis l'hôte via port 8081
|
|
|
|
**Diagnostic** :
|
|
- Le problème est **Apache-spécifique**
|
|
- Symfony/PHP fonctionnent correctement
|
|
- Le `.htaccess` n'est probablement **PAS lu par Apache**
|
|
- Hypothèses :
|
|
1. `AllowOverride All` non pris en compte
|
|
2. `mod_rewrite` mal configuré
|
|
3. Ordre des directives Apache incorrect
|
|
4. Problème de permissions sur `.htaccess`
|
|
|
|
**Actions à faire** :
|
|
- [ ] Vérifier permissions `.htaccess` dans container
|
|
- [ ] Tester `apache2ctl configtest`
|
|
- [ ] Activer logs de rewrite : `LogLevel alert rewrite:trace3`
|
|
- [ ] Tester FallbackResource dans vhost au lieu de `.htaccess`
|
|
|
|
#### 2. JWT Login non testé
|
|
|
|
**Raison** : Bloqué par problème #1 (routes inaccessibles)
|
|
|
|
**Actions à faire** :
|
|
- [ ] Résoudre problème Apache
|
|
- [ ] Tester `POST /api/login_check` avec credentials
|
|
- [ ] Vérifier génération du token JWT
|
|
- [ ] Tester route protégée avec token
|
|
|
|
---
|
|
|
|
## 📝 Configuration Actuelle
|
|
|
|
### Docker Compose
|
|
|
|
```yaml
|
|
services:
|
|
web:
|
|
ports:
|
|
- "8081:80" # Symfony API
|
|
- "3001:3000" # (prévu pour Nuxt)
|
|
|
|
db:
|
|
ports:
|
|
- "5433:5432" # PostgreSQL
|
|
|
|
pgadmin:
|
|
ports:
|
|
- "5050:80" # pgAdmin
|
|
```
|
|
|
|
### Variables d'Environnement
|
|
|
|
**Fichier** : `docker/.env.docker.local`
|
|
|
|
```env
|
|
# PostgreSQL
|
|
POSTGRES_DB=inventory
|
|
POSTGRES_USER=root
|
|
POSTGRES_PASSWORD=root
|
|
POSTGRES_PORT=5433
|
|
|
|
---
|
|
|
|
## ✅ Phase 2 : Migration DB + Frontend (TERMINÉE - 10/01/2026)
|
|
|
|
### Ce qui a été fait
|
|
|
|
#### 1. Entités Doctrine alignées Prisma ✅
|
|
- **Toutes les entités manquantes** créées (Machine, ModelType, Composant, Piece, Product, Links, Requirements, CustomField, Document, etc.)
|
|
- **IDs en string(36)** pour compatibilité CUID/UUID
|
|
- **Colonnes Prisma en camelCase** conservées via `name="..."` (ex: `machineId`, `createdAt`, `supplierPrice`)
|
|
- **Corrections** :
|
|
- `Document.path` passé en `TEXT`
|
|
- `CustomField.options` nullable
|
|
- `TypeMachineComponentRequirement.required` corrigé
|
|
|
|
#### 2. Migration DB inventory-data → inventory ✅
|
|
- **Dump data-only + normalisation** (conversion des identifiants quoted vers lowercase)
|
|
- **Mapping table Prisma** : `"ModelType"` → `model_types`
|
|
- **Exclusions** : `profiles`, `_prisma_migrations`
|
|
- **Import validé** : `Counts match for all tables.`
|
|
|
|
Scripts utiles :
|
|
```bash
|
|
scripts/normalize-dump.py
|
|
scripts/validate-migration.php
|
|
```
|
|
|
|
#### 3. Frontend basculé sur Inventory_frontend ✅
|
|
- `make dev-nuxt` pointe vers `Inventory_frontend/`
|
|
- `README.md` mis à jour
|
|
- **Base API** ajustée : `http://localhost:8081/api`
|
|
|
|
Fichiers modifiés :
|
|
```
|
|
makefile
|
|
README.md
|
|
Inventory_frontend/.env
|
|
Inventory_frontend/nuxt.config.ts
|
|
Inventory_frontend/app/services/modelTypes.ts
|
|
```
|
|
|
|
---
|
|
|
|
# pgAdmin
|
|
PGADMIN_EMAIL=admin@admin.com
|
|
PGADMIN_PASSWORD=admin
|
|
PGADMIN_PORT=5050
|
|
|
|
# Symfony
|
|
APP_ENV=dev
|
|
APP_SECRET=changeme_super_secret_key_123456789
|
|
JWT_SECRET_KEY=%kernel.project_dir%/config/jwt/private.pem
|
|
JWT_PUBLIC_KEY=%kernel.project_dir%/config/jwt/public.pem
|
|
JWT_PASSPHRASE=your_jwt_passphrase_change_me
|
|
|
|
# NestJS (pour futur parallèle)
|
|
NESTJS_PORT=3000
|
|
SESSION_SECRET=changeme_session_secret
|
|
CORS_ORIGIN=http://localhost:3001
|
|
```
|
|
|
|
---
|
|
|
|
## 🚧 Phase 2 : Debugging & Tests (EN COURS)
|
|
|
|
### Objectifs
|
|
- [x] Résoudre problème Apache `.htaccess`
|
|
- [ ] Tester authentification JWT complète
|
|
- [ ] Créer endpoint de test public fonctionnel
|
|
- [ ] Documenter la solution Apache
|
|
|
|
### Prochaines étapes
|
|
1. **Fix Apache** : Logs de debug + test FallbackResource
|
|
2. **Test JWT** : Login + génération token + route protégée
|
|
3. **Documentation** : Documenter la config Apache qui fonctionne
|
|
|
|
---
|
|
|
|
## 📊 Métriques
|
|
|
|
### Temps passé
|
|
- **Phase 1** : ~3h (exploration + setup + debugging)
|
|
- **Problème Apache** : ~1h30 (en cours)
|
|
|
|
### Fichiers créés/modifiés
|
|
|
|
**Nouveaux fichiers** :
|
|
- `src/Entity/Profile.php`
|
|
- `src/Repository/ProfileRepository.php`
|
|
- `src/Controller/TestController.php`
|
|
- `public/.htaccess`
|
|
- `config/routes/routing.controllers.yaml`
|
|
- `create_test_user.php` (script utilitaire)
|
|
- `migrations/Version20260110175413.php`
|
|
- `docker/pgadmin/servers.json` (config serveur PostgreSQL)
|
|
- `docker/pgadmin/pgpass` (credentials PostgreSQL)
|
|
- `CARNET_DE_BORD.md` (ce fichier)
|
|
|
|
**Fichiers modifiés** :
|
|
- `docker-compose.yml` (+ pgAdmin)
|
|
- `docker/.env.docker.local` (+ variables Symfony/JWT/pgAdmin)
|
|
- `docker/php/config/vhost.conf` (DocumentRoot → public/)
|
|
- `config/packages/security.yaml` (JWT firewalls)
|
|
- `config/routes.yaml` (+ api_login_check)
|
|
- `composer.json` (+ lexik JWT, vich uploader)
|
|
|
|
---
|
|
|
|
## 🎓 Leçons Apprises
|
|
|
|
### 1. Symfony 8 + API Platform
|
|
- **Attributs PHP 8** : `use Symfony\Component\Routing\Attribute\Route;` (pas `Annotation`)
|
|
- **Routes controllers** : Nécessite `config/routes/routing.controllers.yaml` avec `type: attribute`
|
|
- **API Platform** : Auto-génère les endpoints CRUD avec `#[ApiResource]`
|
|
|
|
### 2. JWT Authentication
|
|
- **3 composants** :
|
|
1. Firewall `login` : `json_login` intercepte `/api/login_check`
|
|
2. Firewall `api` : `jwt` vérifie le token sur `/api/*`
|
|
3. Access control : `PUBLIC_ACCESS` vs `IS_AUTHENTICATED_FULLY`
|
|
- **username_path** : Permet de mapper `email` au lieu de `username`
|
|
- **Provider** : Doit être défini dans le firewall `login`
|
|
|
|
### 3. Doctrine Migrations
|
|
- **ID Prisma CUID** : Garder en `string(30)` pour compatibilité
|
|
- **Lifecycle callbacks** : `#[ORM\PrePersist]` pour `createdAt`/`updatedAt`
|
|
- **UserInterface** : Nécessite `getUserIdentifier()`, `getRoles()`, `eraseCredentials()`
|
|
|
|
### 4. Docker & Apache
|
|
- **`.htaccess` vs VirtualHost** : Le vhost peut override le `.htaccess`
|
|
- **AllowOverride All** : Indispensable pour que `.htaccess` fonctionne
|
|
- **FallbackResource** : Alternative au mod_rewrite dans `.htaccess`
|
|
- **Debugging** : Tester avec PHP built-in server pour isoler le problème
|
|
|
|
---
|
|
|
|
## 📚 Ressources Utiles
|
|
|
|
### Accès aux Services
|
|
|
|
```
|
|
🌐 pgAdmin: http://localhost:5050
|
|
└─ Login: admin@admin.com / admin
|
|
└─ Serveur: "Inventory PostgreSQL" (pré-configuré)
|
|
└─ Database: inventory
|
|
└─ Note: Le serveur PostgreSQL est automatiquement connecté au démarrage
|
|
|
|
🌐 API Platform: http://localhost:8081/api/
|
|
└─ Docs: http://localhost:8081/api/docs (à venir)
|
|
|
|
🗄️ PostgreSQL: localhost:5433
|
|
└─ User: root / root
|
|
└─ Database: inventory
|
|
```
|
|
|
|
### Commandes fréquentes
|
|
|
|
```bash
|
|
# Symfony
|
|
make shell # Entrer dans le container
|
|
php bin/console cache:clear # Clear cache
|
|
make cache-clear-full # Clear cache + purge var/cache
|
|
php bin/console debug:router # Lister routes
|
|
php bin/console debug:firewall # Lister firewalls
|
|
php bin/console doctrine:migrations:migrate # Exécuter migrations
|
|
|
|
# Docker
|
|
make start # Démarrer containers
|
|
make stop # Arrêter containers
|
|
docker logs -f php-inventory-apache # Logs Apache
|
|
docker logs -f pgadmin-inventory # Logs pgAdmin
|
|
docker exec php-inventory-apache bash # Shell root
|
|
|
|
# Tests API
|
|
curl http://localhost:8081/api/ # Test API Platform
|
|
curl -X POST http://localhost:8081/api/login_check \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"email":"admin@admin.com","password":"admin123"}'
|
|
```
|
|
|
|
### Documentation
|
|
- [Lexik JWT Bundle](https://github.com/lexik/LexikJWTAuthenticationBundle/blob/2.x/Resources/doc/index.rst)
|
|
- [API Platform Security](https://api-platform.com/docs/core/security/)
|
|
- [Symfony Security](https://symfony.com/doc/current/security.html)
|
|
|
|
---
|
|
|
|
## 🔄 Historique des Changements
|
|
|
|
### 2026-01-15 - Session 3
|
|
- ✅ Filtre API Platform `category` sur `ModelType`
|
|
- ✅ Normalisation des structures `ModelType` (structure ↔ skeleton)
|
|
- ✅ Migration `custom_fields.options` en JSON
|
|
- ✅ Ajout commande `make cache-clear-full`
|
|
- ✅ Correctifs frontend: headers API Platform, pagination par catégorie, persistance tri
|
|
|
|
### 2026-01-10 - Session 2 (20h30)
|
|
- ✅ Problème Apache résolu (routes fonctionnelles)
|
|
- ✅ Phase 2 complète (JWT 100% opérationnel)
|
|
- ✅ Authentification testée avec succès
|
|
- ✅ Réorganisation projet (frontend/ + _archives/)
|
|
- ✅ État des lieux dans MIGRATION_PLAN.md
|
|
- ✅ 5 commits conventionnels créés
|
|
- 📊 Base inventory-data analysée (673 lignes)
|
|
|
|
### 2026-01-10 - Session 1 (19h00)
|
|
- ✅ Création projet migration
|
|
- ✅ Phase 1 complète (pgAdmin, JWT, Profile, migrations)
|
|
- ⚠️ Problème Apache identifié (routes 404)
|
|
- 📝 Carnet de bord créé
|
|
|
|
---
|
|
|
|
**Dernière mise à jour** : 2026-01-15 13:45
|
|
**Statut** : Phase 3 EN COURS ⚠️ - Migrations et intégration frontend
|