diff --git a/src/Api/Groups.php b/src/Api/Groups.php index 798871de..6f4b68f7 100644 --- a/src/Api/Groups.php +++ b/src/Api/Groups.php @@ -729,4 +729,75 @@ private function getSubgroupSearchResolver() return $resolver; } + + /** + * @param int|string $group_id + * @param bool|null $active + * + * @return mixed + */ + public function deployTokens($group_id, bool $active = null) + { + return $this->get('groups/'.self::encodePath($group_id).'/deploy_tokens', (null !== $active) ? ['active' => $active] : []); + } + + /** + * @param int|string $group_id + * @param array $parameters { + * + * @var string $name the name of the deploy token + * @var \DateTimeInterface $expires_at expiration date for the deploy token, does not expire if no value is provided + * @var string $username the username for the deploy token + * @var array $scopes the scopes, one or many of: read_repository, read_registry, write_registry, read_package_registry, write_package_registry + * } + * + * @return mixed + */ + public function createDeployToken($group_id, array $parameters = []) + { + $resolver = $this->createOptionsResolver(); + $datetimeNormalizer = function (Options $resolver, \DateTimeInterface $value): string { + return $value->format('c'); + }; + + $resolver->define('name') + ->required() + ; + + $resolver->define('scopes') + ->required() + ->allowedTypes('array') + ->allowedValues(function ($scopes) { + $allowed = ['read_repository', 'read_registry', 'write_registry', 'read_package_registry', 'write_package_registry']; + foreach ($scopes as $scope) { + if (!\in_array($scope, $allowed, true)) { + return false; + } + } + + return true; + }) + ; + $resolver->setDefined('username') + ->setAllowedTypes('username', 'string') + ; + + $resolver->setDefined('expires_at') + ->setAllowedTypes('expires_at', \DateTimeInterface::class) + ->setNormalizer('expires_at', $datetimeNormalizer) + ; + + return $this->post('groups/'.self::encodePath($group_id).'/deploy_tokens', $resolver->resolve($parameters)); + } + + /** + * @param int|string $group_id + * @param int $token_id + * + * @return mixed + */ + public function deleteDeployToken($group_id, int $token_id) + { + return $this->delete('groups/'.self::encodePath($group_id).'/deploy_tokens/'.self::encodePath($token_id)); + } } diff --git a/src/Api/Projects.php b/src/Api/Projects.php index ab2d4b77..0234f82e 100644 --- a/src/Api/Projects.php +++ b/src/Api/Projects.php @@ -783,6 +783,77 @@ public function enableDeployKey($project_id, int $key_id) return $this->post($this->getProjectPath($project_id, 'deploy_keys/'.self::encodePath($key_id).'/enable')); } + /** + * @param int|string $project_id + * @param bool|null $active + * + * @return mixed + */ + public function deployTokens($project_id, bool $active = null) + { + return $this->get($this->getProjectPath($project_id, 'deploy_tokens'), (null !== $active) ? ['active' => $active] : []); + } + + /** + * @param int|string $project_id + * @param array $parameters { + * + * @var string $name the name of the deploy token + * @var \DateTimeInterface $expires_at expiration date for the deploy token, does not expire if no value is provided + * @var string $username the username for the deploy token + * @var array $scopes the scopes, one or many of: read_repository, read_registry, write_registry, read_package_registry, write_package_registry + * } + * + * @return mixed + */ + public function createDeployToken($project_id, array $parameters = []) + { + $resolver = $this->createOptionsResolver(); + $datetimeNormalizer = function (Options $resolver, \DateTimeInterface $value): string { + return $value->format('c'); + }; + + $resolver->define('name') + ->required() + ; + + $resolver->define('scopes') + ->required() + ->allowedTypes('array') + ->allowedValues(function ($scopes) { + $allowed = ['read_repository', 'read_registry', 'write_registry', 'read_package_registry', 'write_package_registry']; + foreach ($scopes as $scope) { + if (!\in_array($scope, $allowed, true)) { + return false; + } + } + + return true; + }) + ; + $resolver->setDefined('username') + ->setAllowedTypes('username', 'string') + ; + + $resolver->setDefined('expires_at') + ->setAllowedTypes('expires_at', \DateTimeInterface::class) + ->setNormalizer('expires_at', $datetimeNormalizer) + ; + + return $this->post($this->getProjectPath($project_id, 'deploy_tokens'), $resolver->resolve($parameters)); + } + + /** + * @param int|string $project_id + * @param int $token_id + * + * @return mixed + */ + public function deleteDeployToken($project_id, int $token_id) + { + return $this->delete($this->getProjectPath($project_id, 'deploy_tokens/'.self::encodePath($token_id))); + } + /** * @param int|string $project_id * @param array $parameters { diff --git a/tests/Api/GroupsTest.php b/tests/Api/GroupsTest.php index 59329d9d..6a5f552d 100644 --- a/tests/Api/GroupsTest.php +++ b/tests/Api/GroupsTest.php @@ -14,6 +14,7 @@ namespace Gitlab\Tests\Api; +use DateTime; use Gitlab\Api\Groups; class GroupsTest extends TestCase @@ -735,4 +736,152 @@ public function shouldGetGroupMergeRequests(): void $this->assertEquals($expectedArray, $api->mergeRequests(1, [])); } + + /** + * @test + */ + public function shouldGetDeployTokens(): void + { + $expectedArray = [ + [ + 'id' => 1, + 'name' => 'MyToken', + 'username' => 'gitlab+deploy-token-1', + 'expires_at' => '2020-02-14T00:00:00.000Z', + 'revoked' => false, + 'expired' => false, + 'scopes' => [ + 'read_repository', + 'read_registry', + ], + ], + ]; + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('groups/1/deploy_tokens') + ->will($this->returnValue($expectedArray)); + + $this->assertEquals($expectedArray, $api->deployTokens(1)); + } + + /** + * @test + */ + public function shouldGetActiveDeployTokens(): void + { + $expectedArray = [ + [ + 'id' => 1, + 'name' => 'MyToken', + 'username' => 'gitlab+deploy-token-1', + 'expires_at' => '2020-02-14T00:00:00.000Z', + 'revoked' => false, + 'expired' => true, + 'scopes' => [ + 'read_repository', + 'read_registry', + ], + ], + ]; + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('groups/1/deploy_tokens', ['active' => true]) + ->will($this->returnValue([])); + + $this->assertEquals([], $api->deployTokens(1, true)); + } + + /** + * @test + */ + public function shouldGetInactiveDeployTokens(): void + { + $expectedArray = [ + [ + 'id' => 1, + 'name' => 'MyToken', + 'username' => 'gitlab+deploy-token-1', + 'expires_at' => '2020-02-14T00:00:00.000Z', + 'revoked' => false, + 'expired' => true, + 'scopes' => [ + 'read_repository', + 'read_registry', + ], + ], + ]; + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('groups/1/deploy_tokens', ['active' => false]) + ->will($this->returnValue([])); + + $this->assertEquals([], $api->deployTokens(1, false)); + } + + /** + * @test + */ + public function shouldCreateDeployToken(): void + { + $expectedArray = [ + 'id' => 1, + 'name' => 'My Deploy Token', + 'username' => 'custom-user', + 'token' => 'jMRvtPNxrn3crTAGukpZ', + 'expires_at' => '2021-01-01T00:00:00.000Z', + 'revoked' => false, + 'expired' => false, + 'scopes' => [ + 'read_repository', + 'read_registry', + ], + ]; + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('post') + ->with( + 'groups/1/deploy_tokens', + [ + 'name' => 'My Deploy Token', + 'scopes' => [ + 'read_repository', + 'read_registry', + ], + 'expires_at' => (new DateTime('2021-01-01'))->format('c'), + ] + ) + ->will($this->returnValue($expectedArray)); + + $this->assertEquals($expectedArray, $api->createDeployToken(1, [ + 'name' => 'My Deploy Token', + 'scopes' => [ + 'read_repository', + 'read_registry', + ], + 'expires_at' => new DateTime('2021-01-01'), + ])); + } + + /** + * @test + */ + public function shouldDeleteDeployToken(): void + { + $expectedBool = true; + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('delete') + ->with('groups/1/deploy_tokens/2') + ->will($this->returnValue($expectedBool)); + + $this->assertEquals($expectedBool, $api->deleteDeployToken(1, 2)); + } } diff --git a/tests/Api/ProjectsTest.php b/tests/Api/ProjectsTest.php index 3599bb00..278aa90d 100644 --- a/tests/Api/ProjectsTest.php +++ b/tests/Api/ProjectsTest.php @@ -1369,6 +1369,154 @@ public function shoudEnableDeployKey(): void $this->assertEquals($expectedBool, $api->enableDeployKey(1, 3)); } + /** + * @test + */ + public function shouldGetDeployTokens(): void + { + $expectedArray = [ + [ + 'id' => 1, + 'name' => 'MyToken', + 'username' => 'gitlab+deploy-token-1', + 'expires_at' => '2020-02-14T00:00:00.000Z', + 'revoked' => false, + 'expired' => false, + 'scopes' => [ + 'read_repository', + 'read_registry', + ], + ], + ]; + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('projects/1/deploy_tokens') + ->will($this->returnValue($expectedArray)); + + $this->assertEquals($expectedArray, $api->deployTokens(1)); + } + + /** + * @test + */ + public function shouldGetActiveDeployTokens(): void + { + $expectedArray = [ + [ + 'id' => 1, + 'name' => 'MyToken', + 'username' => 'gitlab+deploy-token-1', + 'expires_at' => '2020-02-14T00:00:00.000Z', + 'revoked' => false, + 'expired' => true, + 'scopes' => [ + 'read_repository', + 'read_registry', + ], + ], + ]; + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('projects/1/deploy_tokens', ['active' => true]) + ->will($this->returnValue([])); + + $this->assertEquals([], $api->deployTokens(1, true)); + } + + /** + * @test + */ + public function shouldGetInactiveDeployTokens(): void + { + $expectedArray = [ + [ + 'id' => 1, + 'name' => 'MyToken', + 'username' => 'gitlab+deploy-token-1', + 'expires_at' => '2020-02-14T00:00:00.000Z', + 'revoked' => false, + 'expired' => true, + 'scopes' => [ + 'read_repository', + 'read_registry', + ], + ], + ]; + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('projects/1/deploy_tokens', ['active' => false]) + ->will($this->returnValue([])); + + $this->assertEquals([], $api->deployTokens(1, false)); + } + + /** + * @test + */ + public function shouldCreateDeployToken(): void + { + $expectedArray = [ + 'id' => 1, + 'name' => 'My Deploy Token', + 'username' => 'custom-user', + 'token' => 'jMRvtPNxrn3crTAGukpZ', + 'expires_at' => '2021-01-01T00:00:00.000Z', + 'revoked' => false, + 'expired' => false, + 'scopes' => [ + 'read_repository', + 'read_registry', + ], + ]; + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('post') + ->with( + 'projects/1/deploy_tokens', + [ + 'name' => 'My Deploy Token', + 'scopes' => [ + 'read_repository', + 'read_registry', + ], + 'expires_at' => (new DateTime('2021-01-01'))->format('c'), + ] + ) + ->will($this->returnValue($expectedArray)); + + $this->assertEquals($expectedArray, $api->createDeployToken(1, [ + 'name' => 'My Deploy Token', + 'scopes' => [ + 'read_repository', + 'read_registry', + ], + 'expires_at' => new DateTime('2021-01-01'), + ])); + } + + /** + * @test + */ + public function shouldDeleteDeployToken(): void + { + $expectedBool = true; + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('delete') + ->with('projects/1/deploy_tokens/2') + ->will($this->returnValue($expectedBool)); + + $this->assertEquals($expectedBool, $api->deleteDeployToken(1, 2)); + } + /** * @test */