54fe48993f
Les roles metier (bureau / compta / commerciale) prenaient un 403 sur GET /api/categories et GET /api/sites : la security des GetCollection/Get exigeait catalog.categories.view / sites.view, permissions reservees a l'administration du Catalogue et des Sites. Or ces referentiels sont transverses (selects de creation/filtre client) : creation de client cassee et filtres vides pour ces roles. Correctif back (Option C — permission de lecture-referentiel dediee) : - Nouvelles permissions catalog.categories.read_ref et sites.read_ref, distinctes de .view (pas d'item sidebar admin) et de .manage. Chaque permission appartient a son propre module -> aucun couplage inter-module (regle ABSOLUE n°1) et reutilisable tel quel par M2 Fournisseurs. - Security lecture (liste + item) elargie : view OR read_ref sur Category et Site. - Matrice RBAC § 2.7 (RbacSeeder) : read_ref attache a bureau / compta / commerciale. Usine reste sans acces. Durcissement front (resilience, requis dans tous les cas) : - useClientReferentials.loadCommon passe de Promise.all a Promise.allSettled avec affectation isolee par referentiel : l'echec d'un endpoint ne vide que SON select, plus la totalite du formulaire. Tests : - ClientRBACMatrixTest : les roles metier listent /categories et /sites (200), usine reste a 403. - SitesModuleTest : set de permissions porte a 4 codes. - useClientReferentials.spec : resilience d'un referentiel en echec. Miroirs E2E (personas.ts / SeedE2ECommand) non touches : read_ref n'ajoute aucun lien sidebar, le persona user-full lit deja via .view, et aucun persona ne modelise un role metier seul ; pas de nouveau test E2E (regle n°7).
55 lines
2.1 KiB
PHP
55 lines
2.1 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Tests\Module\Sites;
|
|
|
|
use App\Module\Sites\Infrastructure\ApiPlatform\State\Processor\SiteAwareInjectionProcessor;
|
|
use App\Module\Sites\SitesModule;
|
|
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
|
|
|
|
/**
|
|
* Tests structurels du module Sites : contrat `permissions()` et
|
|
* invariants d'enregistrement des services.
|
|
*
|
|
* @internal
|
|
*/
|
|
final class SitesModuleTest extends KernelTestCase
|
|
{
|
|
public function testPermissionsSetContainsExactlyFourCodes(): void
|
|
{
|
|
// Garde-fou : si quelqu'un ajoute une permission sans ajuster les
|
|
// tests ou la doc, ce test casse explicitement. Si au contraire une
|
|
// permission disparait (ex: bypass_scope retire par erreur), meme
|
|
// effet. Le set de permissions est fige par ce test.
|
|
// `sites.read_ref` ajoutee en ERP-102 (lecture-referentiel transverse).
|
|
$codes = array_column(SitesModule::permissions(), 'code');
|
|
sort($codes);
|
|
|
|
self::assertSame(
|
|
['sites.bypass_scope', 'sites.manage', 'sites.read_ref', 'sites.view'],
|
|
$codes,
|
|
);
|
|
}
|
|
|
|
public function testSiteAwareInjectionProcessorIsRegisteredAsDecoratorOfPersistProcessor(): void
|
|
{
|
|
// Garde d'integration : le ticket 4 compte sur le fait que tous
|
|
// les processors existants qui deleguent au persist processor
|
|
// (UserRbacProcessor, RoleProcessor, etc.) passent par notre
|
|
// decorator SiteAwareInjectionProcessor. Si un refactor Symfony
|
|
// change la resolution du service decore, ce test cassera en
|
|
// amont des regressions invisibles dans les tests metier.
|
|
self::bootKernel();
|
|
$container = self::getContainer();
|
|
|
|
$persistProcessor = $container->get('api_platform.doctrine.orm.state.persist_processor');
|
|
|
|
self::assertInstanceOf(
|
|
SiteAwareInjectionProcessor::class,
|
|
$persistProcessor,
|
|
'Le service api_platform.doctrine.orm.state.persist_processor doit etre decore par SiteAwareInjectionProcessor (#[AsDecorator]).',
|
|
);
|
|
}
|
|
}
|