Commit Graph

111 Commits

Author SHA1 Message Date
Matthieu
6101bd85ce build(frontend) : ERP-26 - bump @malio/layer-ui to ^1.3.0 (DataTable)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 09:21:50 +02:00
Matthieu
6e0c875bd7 feat(frontend) : ERP-26 - admin roles page with table, drawer, delete modal
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 09:20:10 +02:00
Matthieu
2cb5a7a0b0 feat(frontend) : ERP-26 - RoleDrawer component (create/edit with permissions)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 09:18:07 +02:00
Matthieu
84f91428bc feat(frontend) : ERP-26 - RoleDeleteModal component
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 09:16:08 +02:00
Matthieu
44c73b6551 feat(frontend) : ERP-26 - PermissionGroup component 2026-04-16 09:10:58 +02:00
Matthieu
9117bc0a6c feat(frontend) : ERP-26 - sidebar entry + i18n keys for admin roles 2026-04-16 09:08:51 +02:00
Matthieu
c1a620f593 build(core) : RBAC #345 - nuxt-test and test-all makefile targets 2026-04-15 17:19:35 +02:00
Matthieu
6cc576f000 test(frontend) : RBAC #345 - vitest setup + usePermissions unit tests 2026-04-15 17:15:27 +02:00
Matthieu
91b2ae0c65 build(core) : RBAC #345 - sync permissions in db-reset 2026-04-15 16:39:44 +02:00
Matthieu
45f40ed1b3 feat(frontend) : RBAC #345 - usePermissions composable
Ajout de isAdmin et effectivePermissions dans UserData, creation du
composable usePermissions() (can/canAny/canAll) avec bypass admin.
2026-04-15 16:38:15 +02:00
Matthieu
6df4316950 test(core) : RBAC #345 - functional coverage voter + last admin guard 2026-04-15 16:38:15 +02:00
Matthieu
d1e4402368 feat(core) : RBAC #345 - expose effectivePermissions via /api/me
- Ajoute #[Groups(['me:read'])] sur getEffectivePermissions() dans User.php
- Fixe la serialisation de isAdmin : le prefixe "is" etait strip par Symfony,
  expose desormais via le getter avec #[SerializedName('isAdmin')] + groups lecture,
  la propriete conserve uniquement le groupe d'ecriture user:rbac:write
- Cree MeApiTest avec 4 tests fonctionnels (isAdmin admin, permissions vides user,
  401 sans auth, effectivePermissions avec role portant une permission)
2026-04-15 16:10:11 +02:00
Matthieu
b05c10097f refactor(core) : RBAC #345 - replace ROLE_ADMIN placeholders with RBAC codes 2026-04-15 16:02:57 +02:00
Matthieu
80b63cd7d7 feat(core) : RBAC #345 - UserRbacProcessor last admin guard 2026-04-15 16:00:34 +02:00
Matthieu
ba5eb804f2 feat(core) : RBAC #345 - UserProcessor DELETE guard
Introduit AdminHeadcountGuardInterface pour permettre le mock en tests
unitaires, puis cree UserProcessor qui protege DELETE /api/users/{id}
contre la suppression du dernier administrateur via la garde domaine.
2026-04-15 15:57:19 +02:00
Matthieu
ab2f11d40d feat(core) : RBAC #345 - PermissionVoter symfony 2026-04-15 15:51:23 +02:00
Matthieu
4325b1d8a0 feat(core) : RBAC #345 - AdminHeadcountGuard domain service 2026-04-15 15:45:55 +02:00
Matthieu
b7aa445cef feat(core) : RBAC #345 - add core.roles.view permission 2026-04-15 15:42:42 +02:00
Matthieu
fd4ed25c63 docs(core) : RBAC #345 - spec voter + usePermissions 2026-04-15 15:28:51 +02:00
Matthieu
0ccbc70f27 fix(core) : RBAC #344 - ferme leak user list + test cascade delete role 2026-04-15 14:53:49 +02:00
Matthieu
534bdbccdd refactor(core) : RBAC #344 - polish review - narrow rbac read group + fail-fast processors 2026-04-15 14:28:02 +02:00
Matthieu
3c7dc88fe7 feat(core) : RBAC #344 - UserRbacProcessor + endpoint /users/{id}/rbac
Ajoute une operation Patch dediee `PATCH /api/users/{id}/rbac` (nom
`user_rbac_patch`) qui accepte exclusivement les champs RBAC isAdmin,
roles et directPermissions via le groupe user:rbac:write. L'endpoint est
separe volontairement du Patch profil existant pour isoler la modification
des droits de celle des donnees profil (decision 0fc4e16).

UserRbacProcessor delegue au PersistProcessor Doctrine decore et applique
une garde auto-suicide : un admin ne peut pas retirer ses propres droits
administrateur (compare l'etat entrant a l'etat UnitOfWork). La garde
'dernier admin' globale est reportee au ticket #345.

La propriete Doctrine $roles est renommee $rbacRoles pour eviter la
collision avec UserInterface::getRoles() (qui renvoie list<string>) lors
de la normalization API Platform. La cle JSON reste `roles` grace a
SerializedName, le contrat API est inchange.

Tests : 6 unitaires (UserRbacProcessorTest) + 8 fonctionnels
(UserRbacApiTest) couvrant promotion admin, remplacement des collections
roles/directPermissions, 401/403, filtrage du groupe denormalization
(`username` ignore), preservation de isAdmin sur le Patch profil, et
garde auto-suicide.
2026-04-15 14:17:18 +02:00
Matthieu
168a47f2b8 refactor(test) : RBAC #344 - AbstractApiTestCase pour mutualiser auth JWT
Extrait l'helper authenticatedClient(), $alwaysBootKernel et getEm() dans
une classe de base commune aux tests fonctionnels API Platform du module
Core. Supprime la duplication entre PermissionApiTest et RoleApiTest
(flaggee en code review de la Task 2). Prepare le terrain pour le nouveau
UserRbacApiTest introduit avec la Task 4.
2026-04-15 12:14:20 +02:00
Matthieu
87aa1d0b04 test(core) : RBAC #344 - renforce docblock setCode + assertion message exception 2026-04-15 12:05:26 +02:00
Matthieu
d527fbe2d1 feat(core) : RBAC #344 - RoleProcessor + gardes systeme et code immuable 2026-04-15 11:58:37 +02:00
Matthieu
efc12c8bdb fix(test) : RBAC #344 - role test cleanup + SystemRoles constant + assertion seuil 2026-04-15 11:53:01 +02:00
Matthieu
7be0260b29 feat(core) : RBAC #344 - API Platform Role CRUD nominal + validators 2026-04-15 11:41:21 +02:00
Matthieu
f79f061131 fix(test) : RBAC #344 - corrige EM stale et ajoute cas orphan=true 2026-04-15 11:15:41 +02:00
Matthieu
fdb7aded82 feat(core) : RBAC #344 - API Platform Permission en lecture seule
- Expose l'entite Permission via ApiResource (GetCollection + Get uniquement)
- Serialisation limitee au groupe permission:read (id, code, label, module, orphan)
- Securite temporaire is_granted('ROLE_ADMIN'), a remplacer par
  is_granted('core.permissions.view') au ticket #345
- Filtres : SearchFilter exact sur module, BooleanFilter sur orphan
- Configure api_platform.mapping.paths pour que le compile pass AP decouvre
  les ApiResource/ApiFilter declares dans src/Module/Core/Domain/Entity
- Ajoute symfony/browser-kit et symfony/http-client en dev pour les tests
  fonctionnels API Platform, plus KERNEL_CLASS dans phpunit.dist.xml
- Tests fonctionnels PermissionApiTest : collection, get item, filtres
  module et orphan, 405 sur POST, 401 non authentifie, 403 non-admin
2026-04-15 11:03:22 +02:00
Matthieu
1cf550721b docs(rbac) : spec ticket #344 - API CRUD roles & permissions 2026-04-15 10:31:10 +02:00
Matthieu
46fa7d17ae chore(core) : merge RBAC ticket #343 + fix user:write sensibles (PR #2)
Some checks failed
Auto Tag Develop / tag (push) Has been cancelled
2026-04-15 10:30:59 +02:00
Matthieu
0fc4e1651b fix(core) : retire user:write des champs RBAC sensibles du User
isAdmin, roles et directPermissions ne doivent pas etre modifiables via
PATCH /api/users/{id}. L exposition en ecriture sera traitee par un
processor dedie dans le ticket #344 (spec section 2 OUT).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 08:15:43 +02:00
Matthieu
d8bda517f9 docs : ajoute note delegation Codex pour taches mecaniques 2026-04-15 08:12:17 +02:00
Matthieu
7ccc913862 docs : exception CLAUDE.md pour les migrations multi-namespace
Documente le bug Doctrine Migrations 3.x (tri par FQCN au lieu de
version timestamp avec plusieurs migrations_paths) et la regle
provisoire : migrations d'init au namespace racine, namespace
modulaire reserve aux migrations applicatives.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 17:25:26 +02:00
Matthieu
eb0b49a7ef fix(core) : RBAC migration deplacee vers le namespace DoctrineMigrations racine
Bug decouvert a l'execution de 'make db-reset' sur base vide : Doctrine
Migrations 3.x avec plusieurs 'migrations_paths' execute les migrations
dans l'ordre (namespace, version) et non (version, namespace). Le
Version20260414150034 sous 'App\Module\Core\...' passait donc avant
Version20260407095546 sous 'DoctrineMigrations', provoquant un
"relation user does not exist".

Deplacement du fichier vers 'migrations/' (namespace DoctrineMigrations).
Le chemin modulaire reste configure pour les futurs modules, mais
la migration RBAC d'initialisation vit a la racine pour que
'make db-reset' fonctionne en one-shot.

Smoke test end-to-end valide :
- db-reset + fixtures : admin (is_admin=t, role admin), alice/bob
  (is_admin=f, role user)
- app:sync-permissions : 4 permissions Core ajoutees, idempotent au 2e run
- User::getRoles() : ['ROLE_USER', 'ROLE_ADMIN'] pour admin, ['ROLE_USER']
  pour alice/bob
- User::getEffectivePermissions() : union triee des permissions via roles

Ticket #343 - 7/7 : smoke test end-to-end OK.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 17:21:43 +02:00
Matthieu
0a496f34e0 fix(core) : RBAC Task 6 polish - descriptions des roles systeme coherentes
ensureSystemRole() recopie desormais la description depuis la migration
RBAC pour que les chemins prod (migration) et dev (fixtures) produisent
un etat identique.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 17:15:23 +02:00
Matthieu
aafe08b6ad feat(core) : RBAC Task 6 - fixtures et CreateUserCommand branches sur les roles systeme
- AppFixtures : rattachement des users aux entites Role via
  RoleRepositoryInterface. Re-seed idempotent des roles systeme dans
  ensureSystemRole() pour compenser le purger Doctrine qui vide la table
  role avant load(), afin que "make db-reset && make fixtures" reste un
  workflow one-shot.
- CreateUserCommand : flag --admin attache au role systeme admin + is_admin,
  sinon au role user. Gestion d'erreur explicite si les roles systeme sont
  absents (FAILURE + message pointant vers la migration).
- CreateUserCommand devient final, descriptions traduites en francais.

Ticket #343 - 6/7 : fixtures et command alignes sur le RBAC relationnel.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 17:12:09 +02:00
Matthieu
d68aa0456a feat(core) : RBAC Task 5 - migration Doctrine RBAC + data-migration JSON roles
- Nouvelles tables permission, role, role_permission, user_role, user_permission
- Ajout user.is_admin (BOOLEAN, default false)
- Seed des roles systeme admin et user via SQL brut (autonome, pas besoin
  de fixtures pour cette etape)
- Migration des donnees : is_admin reflete ROLE_ADMIN du JSON roles, puis
  rattachement user_role selon admin/user
- Drop user.roles en dernier (apres la migration de donnees)
- down() recree la colonne roles et la rehydrate depuis is_admin

Ticket #343 - 5/7 : persistance + migration donnees safe.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 17:02:26 +02:00
Matthieu
3b1f18b0e0 feat(core) : RBAC Task 4 - CoreModule::permissions() + SyncPermissionsCommand
- CoreModule declare 4 permissions initiales (users.view/manage, roles.manage,
  permissions.view)
- Nouvelle commande app:sync-permissions :
  * scan des *Module::permissions() via config/modules.php
  * validation stricte : cles [code, label], prefixe module, non-vides
  * upsert transactionnel non-destructif
  * revival des permissions orphelines qui reapparaissent
  * marquage orphan pour les permissions disparues du code
  * un seul flush() final (evite le flush-par-save de la repo save())

Ticket #343 - 4/7 : scanner et synchroniseur de permissions RBAC.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 16:56:50 +02:00
Matthieu
7aa32b1972 feat(core) : RBAC Task 3 - mutation User (isAdmin + roles RBAC + permissions directes)
- Suppression de la colonne JSON roles (persiste jusqu'a la migration Task 5)
- Ajout is_admin bool (seul levier de bypass RBAC via getRoles())
- Ajout ManyToMany User-Role (EAGER, table user_role)
- Ajout ManyToMany User-Permission directes (EAGER, table user_permission)
- getEffectivePermissions() : union dedupliquee triee, utilisee par le
  futur PermissionVoter (#345)
- getRbacRoles() pour ne pas shadow getRoles() de UserInterface Symfony
- Tests unitaires couvrant derivation getRoles, union, deduplication, tri

Ticket #343 - 3/7 : migration du User vers le modele RBAC relationnel.
Fetch EAGER documente : evite le lazy-load au refresh JWT.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 16:48:49 +02:00
Matthieu
3b34d00872 feat(core) : RBAC Task 2 - repositories Permission et Role
- PermissionRepositoryInterface avec findByCode et findAllCodes (pour le sync
  command et le futur PermissionVoter)
- RoleRepositoryInterface avec findByCode
- Implementations Doctrine alignees sur DoctrineUserRepository
- Alias DI dans config/services.yaml
- Rebranchement de repositoryClass sur les entites Permission et Role

Ticket #343 - 2/7 : couche persistence RBAC.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 16:40:44 +02:00
Matthieu
0fc0b57e37 refactor(core) : RBAC Task 1 - polish apres revue qualite
- Permission : guards constructeur (code/label/module non vides, code avec point)
- Permission::revive() reutilise updateMetadata() pour eviter la duplication
- Suppression de SystemRolesTest (tautologique, ne capture aucun comportement)
- Role::permissions : commentaire explicite sur la raison du fetch EAGER
- Alignement des types de retour sur static (style User.php)
- Nouveau test Role::addPermission avec permissions distinctes

Ticket #343 - Task 1 polish (revue qualite).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 16:37:53 +02:00
Matthieu
f0ea9201f5 feat(core) : RBAC Task 1 - entites Permission et Role + domaine securite
- Entite Permission avec methodes markOrphan/revive/updateMetadata
- Entite Role avec addPermission/removePermission/ensureDeletable
- Constantes SystemRoles (codes admin/user partages)
- Exception SystemRoleDeletionException pour la garde de suppression
- Tests unitaires couvrant le comportement domaine (pas de BDD)

Ticket #343 - 1/7 : fondations RBAC (domaine pur, sans persistence).
Les entites ne portent pas encore repositoryClass (ajoute en Task 2).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 16:30:15 +02:00
Matthieu
e3025bf2c9 docs(rbac) : plan et spec ticket #343 + conventions permissions
- Spec detaillee des fondations RBAC backend (entites Role/Permission, sync
  command, migration, fixtures, tests) dans docs/rbac/ticket-343-spec.md
- Ajout CLAUDE.md des regles projet : commentaires francais (PHP + TS/Vue)
  et convention de nommage des permissions module.resource[.sub].action

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 16:26:49 +02:00
gitea-actions
b59d0f8a44 chore: bump version to v0.1.29
Some checks failed
Build & Push Docker Image / build (push) Failing after 16s
Auto Tag Develop / tag (push) Successful in 5s
v0.1.29
2026-04-14 13:12:49 +00:00
Matthieu
5cb8cff4ce Merge branch 'feature/ERP-7-mise-en-place-du-modular-monolith' into develop
Some checks failed
Auto Tag Develop / tag (push) Has been cancelled
# Conflicts:
#	docker-compose.yml
2026-04-14 15:11:59 +02:00
gitea-actions
c62f054da1 chore: bump version to v0.1.28
All checks were successful
Auto Tag Develop / tag (push) Successful in 5s
Build & Push Docker Image / build (push) Successful in 53s
v0.1.28
2026-04-14 13:07:45 +00:00
Matthieu
168dad4657 feat(infra) : add logs volume to prod docker-compose
Persist var/log/ via named volume coltura_logs so logs survive
container restarts.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 14:28:09 +02:00
Matthieu
68bdb6ff72 docs : add code review report for PR #1
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 14:16:33 +02:00
Matthieu
7045debc66 feat : add ESLint linter to frontend with pre-commit hook
Add ESLint with @nuxt/eslint-config enforcing 4-space indentation.
Add make nuxt-lint and nuxt-lint-fix targets.
Add ESLint check to pre-commit hook (lint only, no auto-fix).
Fix auth.vue indentation from 2 to 4 spaces.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 14:16:25 +02:00