feat: all-season assignments
This commit is contained in:
1 parent
675cec1b69
commit
cf876ed224
119 files changed
+6194
-294
No files matched your search
@@ -0,0 +1,132 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Tests\Security\Voter;
|
||||
|
||||
use App\Entity\SeasonAssignment;
|
||||
use App\Entity\Teamer;
|
||||
use App\Entity\Upload;
|
||||
use App\Entity\User;
|
||||
use App\Security\Voter\UploadVoter;
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Bundle\SecurityBundle\Security;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
||||
use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface;
|
||||
|
||||
/**
|
||||
* A document the office issues for one teamer is the first upload in this app that belongs to a
|
||||
* teamer without being owned by them, so the rules around it are the ones worth pinning: the
|
||||
* intended teamer gets in, every other teamer does not, and the library stays as open as it was.
|
||||
*/
|
||||
class UploadVoterTest extends TestCase
|
||||
{
|
||||
private Security&MockObject $security;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->security = $this->createMock(Security::class);
|
||||
$this->security
|
||||
->method('isGranted')
|
||||
->willReturnCallback(static fn (string $role): bool => 'ROLE_TEAMER' === $role)
|
||||
;
|
||||
}
|
||||
|
||||
public function testATeamerMayDownloadASeasonDocumentIssuedToThem(): void
|
||||
{
|
||||
$teamer = new Teamer();
|
||||
|
||||
$this->assertSame(
|
||||
VoterInterface::ACCESS_GRANTED,
|
||||
$this->vote(UploadVoter::DOWNLOAD, $this->seasonDocument($teamer), $teamer)
|
||||
);
|
||||
}
|
||||
|
||||
public function testATeamerMayNotDownloadAnotherTeamersSeasonDocument(): void
|
||||
{
|
||||
$this->assertSame(
|
||||
VoterInterface::ACCESS_DENIED,
|
||||
$this->vote(UploadVoter::DOWNLOAD, $this->seasonDocument(new Teamer()), new Teamer())
|
||||
);
|
||||
}
|
||||
|
||||
public function testASeasonDocumentOnAnUnstaffedAssignmentReachesNoTeamer(): void
|
||||
{
|
||||
$upload = (new Upload())
|
||||
->setType(Upload::TYPE_SEASON_DOCUMENT_OUT)
|
||||
->setOwner(new User())
|
||||
;
|
||||
$upload->setSeasonAssignment(new SeasonAssignment());
|
||||
|
||||
$this->assertSame(
|
||||
VoterInterface::ACCESS_DENIED,
|
||||
$this->vote(UploadVoter::DOWNLOAD, $upload, new Teamer())
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Downloading is all the new rule grants: the file stays the office's, so the teamer it was
|
||||
* issued to may not delete it or reach it through any other attribute.
|
||||
*
|
||||
* @dataProvider otherAttributes
|
||||
*/
|
||||
public function testTheNewRuleGrantsNothingButDownloading(string $attribute): void
|
||||
{
|
||||
$teamer = new Teamer();
|
||||
|
||||
$this->assertSame(
|
||||
VoterInterface::ACCESS_DENIED,
|
||||
$this->vote($attribute, $this->seasonDocument($teamer), $teamer)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, array{string}>
|
||||
*/
|
||||
public static function otherAttributes(): array
|
||||
{
|
||||
return [
|
||||
'viewing' => [UploadVoter::VIEW],
|
||||
'deleting' => [UploadVoter::DELETE],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* The library is deliberately open to all staff, which is exactly why an individually issued
|
||||
* document must never carry its type - so the blanket rule has to stay untouched.
|
||||
*/
|
||||
public function testTheLibraryStaysReadableByEveryTeamer(): void
|
||||
{
|
||||
$upload = (new Upload())
|
||||
->setType(Upload::TYPE_DOCUMENT)
|
||||
->setOwner(new User())
|
||||
;
|
||||
|
||||
$this->assertSame(
|
||||
VoterInterface::ACCESS_GRANTED,
|
||||
$this->vote(UploadVoter::DOWNLOAD, $upload, new Teamer())
|
||||
);
|
||||
}
|
||||
|
||||
private function seasonDocument(Teamer $teamer): Upload
|
||||
{
|
||||
$seasonAssignment = (new SeasonAssignment())->setTeamer($teamer);
|
||||
|
||||
$upload = (new Upload())
|
||||
->setType(Upload::TYPE_SEASON_DOCUMENT_OUT)
|
||||
->setOwner(new User())
|
||||
;
|
||||
$upload->setSeasonAssignment($seasonAssignment);
|
||||
|
||||
return $upload;
|
||||
}
|
||||
|
||||
private function vote(string $attribute, Upload $upload, Teamer $teamer): int
|
||||
{
|
||||
$token = $this->createMock(TokenInterface::class);
|
||||
$token->method('getUser')->willReturn((new User())->setTeamer($teamer));
|
||||
|
||||
return (new UploadVoter($this->security))->vote($token, $upload, [$attribute]);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user