ApiKeyAuthenticator, PermissionVoter and UserProvider implement Symfony Security for the API (Bearer token) and admin (session) flows. Domain repository interfaces added for ApiKey, User, AIPipelineJob and Invoice; Doctrine implementations provided. Also adds DatabaseLogHandler for structured DB logging, SerpApiWebSearch, and the LogEntry domain entity. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
60 lines
1.9 KiB
PHP
60 lines
1.9 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Tests\Unit\Infrastructure\Security;
|
|
|
|
use App\Domain\Auth\User;
|
|
use App\Infrastructure\Security\PermissionVoter;
|
|
use PHPUnit\Framework\TestCase;
|
|
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
|
|
use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface;
|
|
|
|
final class PermissionVoterTest extends TestCase
|
|
{
|
|
private PermissionVoter $voter;
|
|
|
|
protected function setUp(): void
|
|
{
|
|
$this->voter = new PermissionVoter();
|
|
}
|
|
|
|
public function testGrantsWhenUserHasPermission(): void
|
|
{
|
|
$user = new User('admin@test.com', 'hash');
|
|
$user->grantPermission('articles.publish');
|
|
|
|
$token = new UsernamePasswordToken($user, 'main', $user->getRoles());
|
|
|
|
self::assertSame(VoterInterface::ACCESS_GRANTED, $this->voter->vote($token, null, ['PERM_articles.publish']));
|
|
}
|
|
|
|
public function testDeniesWhenUserLacksPermission(): void
|
|
{
|
|
$user = new User('user@test.com', 'hash');
|
|
|
|
$token = new UsernamePasswordToken($user, 'main', $user->getRoles());
|
|
|
|
self::assertSame(VoterInterface::ACCESS_DENIED, $this->voter->vote($token, null, ['PERM_articles.publish']));
|
|
}
|
|
|
|
public function testAbstainsForNonPrefixedAttribute(): void
|
|
{
|
|
$user = new User('user@test.com', 'hash');
|
|
|
|
$token = new UsernamePasswordToken($user, 'main', $user->getRoles());
|
|
|
|
self::assertSame(VoterInterface::ACCESS_ABSTAIN, $this->voter->vote($token, null, ['ROLE_ADMIN']));
|
|
}
|
|
|
|
public function testDeniesAfterPermissionRevoked(): void
|
|
{
|
|
$user = new User('user@test.com', 'hash');
|
|
$user->grantPermission('articles.delete');
|
|
$user->revokePermission('articles.delete');
|
|
|
|
$token = new UsernamePasswordToken($user, 'main', $user->getRoles());
|
|
|
|
self::assertSame(VoterInterface::ACCESS_DENIED, $this->voter->vote($token, null, ['PERM_articles.delete']));
|
|
}
|
|
}
|