Skip to content

Commit fff5ef3

Browse files
committed
Add security voter to check tenant scope. Fixed doctrine tenant filter
1 parent bba51b7 commit fff5ef3

File tree

3 files changed

+40
-0
lines changed

3 files changed

+40
-0
lines changed

config/packages/security.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ security:
3838
access_control:
3939
- { path: ^/admin, roles: ROLE_EDITOR }
4040

41+
access_decision_manager:
42+
strategy: unanimous
43+
4144
when@test:
4245
security:
4346
password_hashers:

src/Security/TenantScope/Doctrine/TenantFilter.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88
use App\Security\TenantScope\TenantScopeException;
99
use Doctrine\ORM\Mapping\ClassMetadata;
1010
use Doctrine\ORM\Query\Filter\SQLFilter;
11+
use EasyCorp\Bundle\EasyAdminBundle\Factory\FilterFactory;
12+
use Symfony\Bundle\SecurityBundle\Security;
13+
use Symfony\Contracts\Service\Attribute\Required;
1114

1215
/**
1316
* Class TenantFilter.
@@ -27,6 +30,10 @@ public function addFilterConstraint(ClassMetadata $targetEntity, string $targetT
2730
return '';
2831
}
2932

33+
if (!$this->hasParameter('tenant_id')){
34+
return '';
35+
}
36+
3037
try {
3138
return sprintf('%s.tenant_id = %s', $targetTableAlias, $this->getParameter('tenant_id'));
3239
} catch (\Exception $e) {
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?php
2+
3+
namespace App\Security\TenantScope;
4+
5+
use App\Entity\Interfaces\TenantScopedEntityInterface;
6+
use App\Entity\Interfaces\TenantScopedUserInterface;
7+
use EasyCorp\Bundle\EasyAdminBundle\Security\Permission;
8+
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
9+
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
10+
11+
class TenantVoter extends Voter
12+
{
13+
protected function supports(string $attribute, mixed $subject): bool
14+
{
15+
return Permission::EA_EXECUTE_ACTION == $attribute
16+
&& null !== $subject['entity']
17+
&& $subject['entity']->getInstance() instanceof TenantScopedEntityInterface;
18+
}
19+
20+
protected function voteOnAttribute(string $attribute, mixed $subject, TokenInterface $token): bool
21+
{
22+
$user = $token->getUser();
23+
assert($user instanceof TenantScopedUserInterface);
24+
$tenant = $user->getTenant();
25+
26+
$entity = $subject['entity']->getInstance();
27+
28+
return $entity->getTenant() === $tenant;
29+
}
30+
}

0 commit comments

Comments
 (0)