diff --git a/webapp/src/Controller/API/ContestController.php b/webapp/src/Controller/API/ContestController.php index e43fde023f3..cef0f4352fd 100644 --- a/webapp/src/Controller/API/ContestController.php +++ b/webapp/src/Controller/API/ContestController.php @@ -384,7 +384,7 @@ public function problemsetAction(Request $request, string $cid): Response * Change the start time or unfreeze (thaw) time of the given contest. * @throws NonUniqueResultException */ - #[IsGranted('ROLE_API_WRITER')] + #[IsGranted(new Expression("is_granted('ROLE_API_WRITER') or is_granted('ROLE_API_CONTEST_CHANGE')"))] #[Rest\Patch('/{cid}')] #[OA\RequestBody( required: true, diff --git a/webapp/tests/Unit/Controller/API/BaseTestCase.php b/webapp/tests/Unit/Controller/API/BaseTestCase.php index 1549cfcb806..b58ef2e3a71 100644 --- a/webapp/tests/Unit/Controller/API/BaseTestCase.php +++ b/webapp/tests/Unit/Controller/API/BaseTestCase.php @@ -12,6 +12,7 @@ abstract class BaseTestCase extends BaseBaseTestCase { protected static array $rootEndpoints = ['contests', 'judgehosts', 'users']; + protected static string $testedRole = 'unset'; /** @var KernelBrowser */ protected KernelBrowser $client; @@ -373,4 +374,10 @@ public function provideSingleNotFound(): Generator yield [$id]; } } + + protected function provideAllowedUsers(): Generator + { + yield ['admin', ['admin']]; + yield ['team', [static::$testedRole]]; + } } diff --git a/webapp/tests/Unit/Controller/API/ContestControllerAdminTest.php b/webapp/tests/Unit/Controller/API/ContestControllerAdminTest.php index 5655e97c807..8ca2a9e94a0 100644 --- a/webapp/tests/Unit/Controller/API/ContestControllerAdminTest.php +++ b/webapp/tests/Unit/Controller/API/ContestControllerAdminTest.php @@ -21,6 +21,7 @@ class ContestControllerAdminTest extends ContestControllerTest { protected ?string $apiUser = 'admin'; + protected static string $testedRole = 'api_contest_change'; private function parseSortYaml(string $yamlString): array { @@ -29,7 +30,10 @@ private function parseSortYaml(string $yamlString): array return $new; } - public function testAddYaml(): void + /** + * @dataProvider provideAllowedUsers + */ + public function testAddYaml(string $user, array $newRoles): void { $yaml = <<roles = $newRoles; + self::setUp(); $url = $this->helperGetEndpointURL($this->apiEndpoint); $tempYamlFile = tempnam(sys_get_temp_dir(), "/contest-yaml-"); file_put_contents($tempYamlFile, $yaml); @@ -89,7 +95,10 @@ public function testAddYaml(): void self::assertNull($this->getContest($cid)->getDeactivatetime()); } - public function testAddJson(): void + /** + * @dataProvider provideAllowedUsers + */ + public function testAddJson(string $user, array $newRoles): void { $json = <<roles = $newRoles; + self::setUp(); $url = $this->helperGetEndpointURL($this->apiEndpoint); $tempJsonFile = tempnam(sys_get_temp_dir(), "/contest-json-"); file_put_contents($tempJsonFile, $json); @@ -121,8 +132,13 @@ protected function getContest(int|string $cid): Contest return static::getContainer()->get(EntityManagerInterface::class)->getRepository(Contest::class)->findOneBy(['externalid' => $cid]); } - public function testBannerManagement(): void + /** + * @dataProvider provideAllowedUsers + */ + public function testBannerManagement(string $user, array $newRoles): void { + $this->roles = $newRoles; + self::setUp(); // First, make sure we have no banner $id = 1; if ($this->objectClassForExternalId !== null) { @@ -163,8 +179,13 @@ public function testBannerManagement(): void self::assertArrayNotHasKey('banner', $object); } - public function testProblemsetManagement(): void + /** + * @dataProvider provideAllowedUsers + */ + public function testProblemsetManagement(string $user, array $newRoles): void { + $this->roles = $newRoles; + self::setUp(); // First, make sure we have no problemset document $id = 1; if ($this->objectClassForExternalId !== null) { @@ -233,7 +254,10 @@ public function testChangeTimes( array $extraFixtures = [], bool $checkUnfreezeTime = false, bool $convertRelativeTimes = false, + array $newRoles = [], ): void { + $this->roles = $newRoles; + self::setUp(); $this->loadFixture(DemoPreStartContestFixture::class); $this->loadFixtures($extraFixtures); $id = 1; @@ -299,6 +323,10 @@ public function provideChangeTimes(): Generator yield [['id' => 1, 'scoreboard_thaw_time' => '+15 seconds', 'force' => true], 204, null, [DemoPostUnfreezeContestFixture::class], false, true]; yield [['id' => 1, 'scoreboard_thaw_time' => '+15 seconds'], 204, null, [], false, true]; yield [['id' => 1, 'scoreboard_thaw_time' => '-15 seconds'], 200, 'Demo contest', [], true, true]; + + // Show that this works for both roles + yield [['id' => 1, 'scoreboard_thaw_time' => '-14 seconds'], 200, 'Demo contest', [], true, true, ['admin']]; + yield [['id' => 1, 'scoreboard_thaw_time' => '-13 seconds'], 200, 'Demo contest', [], true, true, ['api_contest_change']]; } /** @@ -306,7 +334,7 @@ public function provideChangeTimes(): Generator */ public function testActivateTimeContestYaml( string $activateTime, string $startTime, ?string $deactivateTime, - bool $setActivate, bool $setDeactivate + bool $setActivate, bool $setDeactivate, array $newRoles = [], ): void { $yaml = <<roles = $newRoles; + self::setUp(); if ($setActivate) { $yaml = "activate_time: ".$activateTime."\n".$yaml; } diff --git a/webapp/tests/Unit/Controller/API/ProblemControllerAdminTest.php b/webapp/tests/Unit/Controller/API/ProblemControllerAdminTest.php index aa7b1ca04e2..822269faaa3 100644 --- a/webapp/tests/Unit/Controller/API/ProblemControllerAdminTest.php +++ b/webapp/tests/Unit/Controller/API/ProblemControllerAdminTest.php @@ -6,12 +6,12 @@ use App\DataFixtures\Test\LockedContestFixture; use App\Entity\Problem; use Doctrine\ORM\EntityManagerInterface; -use Generator; use Symfony\Component\HttpFoundation\File\UploadedFile; class ProblemControllerAdminTest extends ProblemControllerTest { protected ?string $apiUser = 'admin'; + protected static string $testedRole = 'api_problem_change'; protected function setUp(): void { @@ -234,10 +234,4 @@ public function testDeleteFromLocked(string $user, array $newRoles): void $problemResponse = $this->verifyApiJsonResponse('DELETE', $url, 403, $this->apiUser); self::assertStringContainsString('Contest is locked', $problemResponse['message']); } - - private function provideAllowedUsers(): Generator - { - yield ['admin', ['admin']]; - yield ['team', ['api_problem_change']]; - } }