Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6f977d387d | |||
| 1888b70623 |
+1
-1
@@ -1,2 +1,2 @@
|
|||||||
parameters:
|
parameters:
|
||||||
app.version: '0.1.72'
|
app.version: '0.1.73'
|
||||||
|
|||||||
+12
@@ -30,6 +30,8 @@ use function sprintf;
|
|||||||
* - resource != Site::class → no-op (les autres resources sont
|
* - resource != Site::class → no-op (les autres resources sont
|
||||||
* gerees par SiteScopedQueryExtension) ;
|
* gerees par SiteScopedQueryExtension) ;
|
||||||
* - is_granted('sites.bypass_scope') → pas de filtre (admin / bypass) ;
|
* - is_granted('sites.bypass_scope') → pas de filtre (admin / bypass) ;
|
||||||
|
* - is_granted('sites.read_ref') → pas de filtre (lecture-referentiel
|
||||||
|
* transverse complet, ERP-102) ;
|
||||||
* - user non authentifie → no-op (API Platform renvoie 401 avant) ;
|
* - user non authentifie → no-op (API Platform renvoie 401 avant) ;
|
||||||
* - user sans aucun site → WHERE 1 = 0 (aucun acces) ;
|
* - user sans aucun site → WHERE 1 = 0 (aucun acces) ;
|
||||||
* - cas normal → WHERE site.id IN (:allowedSites).
|
* - cas normal → WHERE site.id IN (:allowedSites).
|
||||||
@@ -84,6 +86,16 @@ final class SiteCollectionScopedExtension implements QueryCollectionExtensionInt
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 2bis) Lecture-referentiel transverse (ERP-102) : `sites.read_ref` donne
|
||||||
|
// acces a la LISTE COMPLETE des sites (selects d'adresse des modules Tiers).
|
||||||
|
// Sans ce bypass, le cloisonnement par site rattache reduirait le select
|
||||||
|
// aux seuls sites de l'utilisateur (voire a rien s'il n'en a aucun) et le
|
||||||
|
// referentiel ne serait plus "transverse". `read_ref` est une lecture seule :
|
||||||
|
// il ouvre la visibilite sans permettre la moindre ecriture.
|
||||||
|
if ($this->security->isGranted('sites.read_ref')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// 3) Pas d'user authentifie -> no-op (API Platform gere le 401 en amont).
|
// 3) Pas d'user authentifie -> no-op (API Platform gere le 401 en amont).
|
||||||
$user = $this->security->getUser();
|
$user = $this->security->getUser();
|
||||||
if (!$user instanceof User) {
|
if (!$user instanceof User) {
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ namespace App\Tests\Module\Commercial\Api;
|
|||||||
|
|
||||||
use ApiPlatform\Symfony\Bundle\Test\Client;
|
use ApiPlatform\Symfony\Bundle\Test\Client;
|
||||||
use App\Module\Core\Infrastructure\DataFixtures\RbacDemoFixtures;
|
use App\Module\Core\Infrastructure\DataFixtures\RbacDemoFixtures;
|
||||||
|
use App\Module\Sites\Domain\Entity\Site;
|
||||||
use Symfony\Bundle\FrameworkBundle\Console\Application;
|
use Symfony\Bundle\FrameworkBundle\Console\Application;
|
||||||
use Symfony\Component\Console\Input\ArrayInput;
|
use Symfony\Component\Console\Input\ArrayInput;
|
||||||
use Symfony\Component\Console\Output\NullOutput;
|
use Symfony\Component\Console\Output\NullOutput;
|
||||||
@@ -281,14 +282,32 @@ final class ClientRBACMatrixTest extends AbstractCommercialApiTestCase
|
|||||||
// / sites.read_ref) attachee par la matrice § 2.7 — sans pour autant porter
|
// / sites.read_ref) attachee par la matrice § 2.7 — sans pour autant porter
|
||||||
// la permission d'administration `.view`. Usine, sans aucune permission,
|
// la permission d'administration `.view`. Usine, sans aucune permission,
|
||||||
// reste interdit.
|
// reste interdit.
|
||||||
|
// Le referentiel /sites est TRANSVERSE et COMPLET : le cloisonnement par
|
||||||
|
// site rattache (SiteCollectionScopedExtension) est neutralise par
|
||||||
|
// `sites.read_ref` (ERP-102). Les comptes demo ne sont rattaches qu'a un
|
||||||
|
// seul site (Chatellerault) alors que la base en compte plusieurs : on
|
||||||
|
// verifie donc que le role voit la TOTALITE du referentiel, pas son seul
|
||||||
|
// site rattache. Sans le bypass de scope, totalItems vaudrait 1.
|
||||||
|
$totalSites = $this->getEm()->getRepository(Site::class)->count([]);
|
||||||
|
self::assertGreaterThan(
|
||||||
|
1,
|
||||||
|
$totalSites,
|
||||||
|
'Pre-requis du test : la base doit contenir plusieurs sites pour distinguer scope et bypass.',
|
||||||
|
);
|
||||||
|
|
||||||
foreach (['bureau', 'compta', 'commerciale'] as $role) {
|
foreach (['bureau', 'compta', 'commerciale'] as $role) {
|
||||||
$client = $this->authAs($role);
|
$client = $this->authAs($role);
|
||||||
|
|
||||||
$client->request('GET', '/api/categories', ['headers' => ['Accept' => self::LD]]);
|
$client->request('GET', '/api/categories', ['headers' => ['Accept' => self::LD]]);
|
||||||
self::assertResponseStatusCodeSame(200, sprintf('Le role %s doit pouvoir lister /categories', $role));
|
self::assertResponseStatusCodeSame(200, sprintf('Le role %s doit pouvoir lister /categories', $role));
|
||||||
|
|
||||||
$client->request('GET', '/api/sites', ['headers' => ['Accept' => self::LD]]);
|
$response = $client->request('GET', '/api/sites', ['headers' => ['Accept' => self::LD]]);
|
||||||
self::assertResponseStatusCodeSame(200, sprintf('Le role %s doit pouvoir lister /sites', $role));
|
self::assertResponseStatusCodeSame(200, sprintf('Le role %s doit pouvoir lister /sites', $role));
|
||||||
|
self::assertSame(
|
||||||
|
$totalSites,
|
||||||
|
$response->toArray()['totalItems'] ?? null,
|
||||||
|
sprintf('Le role %s doit voir tout le referentiel sites (%d), pas seulement son site rattache', $role, $totalSites),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Usine : aucune permission -> reste a 403 sur les referentiels.
|
// Usine : aucune permission -> reste a 403 sur les referentiels.
|
||||||
|
|||||||
Reference in New Issue
Block a user