Skip to content

Commit

Permalink
feature #1143 Add API endpoints to interact with organization roles (…
Browse files Browse the repository at this point in the history
…glaubinix)

This PR was merged into the 3.14-dev branch.

Discussion
----------

Organization roles were [introduced in July](https://github.blog/changelog/2024-07-10-pre-defined-organization-roles-that-grant-access-to-all-repositories/) and they have partial API support already https://docs.github.com/en/rest/orgs/organization-roles

Commits
-------

1f77a93 Add API endpoints to interact with organiztion roles
  • Loading branch information
acrobat authored Sep 23, 2024
2 parents 00ab97b + 1f77a93 commit f8f6a95
Show file tree
Hide file tree
Showing 5 changed files with 363 additions and 0 deletions.
1 change: 1 addition & 0 deletions doc/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ v3 APIs:
* [Secrets](organization/actions/secrets.md)
* [Variables](organization/actions/variables.md)
* [Secret Scanning Alert](organization/secret-scanning.md)
* [Organization Roles](organization/organization-roles.md)
* [Projects](project/projects.md)
* [Columns](project/columns.md)
* [Cards](project/cards.md)
Expand Down
108 changes: 108 additions & 0 deletions doc/organization/organization-roles.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
## Organization / Webhooks API
[Back to the navigation](../README.md)

Listing, showing, assigning, and removing orgniazationroles.
Wraps [GitHub Organization Roles API](https://docs.github.com/en/rest/orgs/organization-roles).

Additional APIs:
* [Organization](../doc/organization)

### List all organizaton roles in an organization

> Requires [authentication](../security.md).
```php
$roles = $client->organization()->organizationRoles()->all('acme');
```

Returns a counter and a list of organization roles in the organization.

### Get an organization role in an organization

> Requires [authentication](../security.md).
```php
$role = $client->organization()->organizationRoles()->show('acme', 123);
```

Returns a single organization role in the organization.

### List all teams with role assigned in an organization

> Requires [authentication](../security.md).
```php
$users = $client->organization()->organizationRoles()->listTeamsWithRole('acme', 1);
```

Returns a list of teams with the role assigned to them.

### Assign a single role to a team in an organization

> Requires [authentication](../security.md).
```php
$client->organization()->organizationRoles()->assignRoleToTeam('acme', 1, 'admin-user');
```

No content is returned.

### Remove a single role from a team in an organization

> Requires [authentication](../security.md).
```php
$client->organization()->organizationRoles()->removeRoleFromTeam('acme', 1, 'admin-team');
```

No content is returned.

### Remove all roles from a team in an organization

> Requires [authentication](../security.md).
```php
$client->organization()->organizationRoles()->removeAllRolesFromTeam('acme', 'admin-team');
```

No content is returned.

### List all users with role assigned in an organization

> Requires [authentication](../security.md).
```php
$users = $client->organization()->organizationRoles()->listUsersWithRole('acme', 1);
```

Returns a list of users with the role assigned to them.

### Assign a single role to a user in an organization

> Requires [authentication](../security.md).
```php
$client->organization()->organizationRoles()->assignRoleToUser('acme', 1, 'admin-user');
```

No content is returned.

### Remove a single role from a user in an organization

> Requires [authentication](../security.md).
```php
$client->organization()->organizationRoles()->removeRoleFromUser('acme', 1, 'admin-user');
```

No content is returned.

### Remove all roles from a user in an organization

> Requires [authentication](../security.md).
```php
$client->organization()->organizationRoles()->removeAllRolesFromUser('acme', 'admin-user');
```

No content is returned.
6 changes: 6 additions & 0 deletions lib/Github/Api/Organization.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use Github\Api\Organization\Actions\Variables;
use Github\Api\Organization\Hooks;
use Github\Api\Organization\Members;
use Github\Api\Organization\OrganizationRoles;
use Github\Api\Organization\OutsideCollaborators;
use Github\Api\Organization\SecretScanning;
use Github\Api\Organization\Teams;
Expand Down Expand Up @@ -158,4 +159,9 @@ public function secretScanning(): SecretScanning
{
return new SecretScanning($this->getClient());
}

public function organizationRoles(): OrganizationRoles
{
return new OrganizationRoles($this->getClient());
}
}
61 changes: 61 additions & 0 deletions lib/Github/Api/Organization/OrganizationRoles.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<?php

namespace Github\Api\Organization;

use Github\Api\AbstractApi;

/**
* @link https://docs.github.com/en/rest/orgs/organization-roles
*/
class OrganizationRoles extends AbstractApi
{
public function all(string $organization)
{
return $this->get('/orgs/'.rawurlencode($organization).'/organization-roles');
}

public function show(string $organization, int $roleId)
{
return $this->get('/orgs/'.rawurlencode($organization).'/organization-roles/'.$roleId);
}

public function listTeamsWithRole(string $organization, int $roleId)
{
return $this->get('/orgs/'.rawurlencode($organization).'/organization-roles/'.$roleId.'/teams');
}

public function assignRoleToTeam(string $organization, int $roleId, string $teamSlug): void
{
$this->put('/orgs/'.rawurlencode($organization).'/organization-roles/teams/'.rawurlencode($teamSlug).'/'.$roleId);
}

public function removeRoleFromTeam(string $organization, int $roleId, string $teamSlug): void
{
$this->delete('/orgs/'.rawurlencode($organization).'/organization-roles/teams/'.rawurlencode($teamSlug).'/'.$roleId);
}

public function removeAllRolesFromTeam(string $organization, string $teamSlug): void
{
$this->delete('/orgs/'.rawurlencode($organization).'/organization-roles/teams/'.rawurlencode($teamSlug));
}

public function listUsersWithRole(string $organization, int $roleId): array
{
return $this->get('/orgs/'.rawurlencode($organization).'/organization-roles/'.$roleId.'/users');
}

public function assignRoleToUser(string $organization, int $roleId, string $username): void
{
$this->put('/orgs/'.rawurlencode($organization).'/organization-roles/users/'.rawurlencode($username).'/'.$roleId);
}

public function removeRoleFromUser(string $organization, int $roleId, string $username): void
{
$this->delete('/orgs/'.rawurlencode($organization).'/organization-roles/users/'.rawurlencode($username).'/'.$roleId);
}

public function removeAllRolesFromUser(string $organization, string $username): void
{
$this->delete('/orgs/'.rawurlencode($organization).'/organization-roles/users/'.rawurlencode($username));
}
}
187 changes: 187 additions & 0 deletions test/Github/Tests/Api/Organization/OrganizationRolesTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
<?php

declare(strict_types=1);

namespace Github\Tests\Api\Organization;

use Github\Api\Organization\OrganizationRoles;
use Github\Tests\Api\TestCase;

class OrganizationRolesTest extends TestCase
{
/**
* @test
*/
public function shouldGetAllOrganizationRoles()
{
$expectedValue = [
'total_count' => 1,
'roles' => [[
'id' => 1,
'name' => 'all_repo_admin',
'description' => 'Grants admin access to all repositories in the organization.',
'permissions' => [],
'organization' => null,
'created_at' => '2023-01-01T00:00:00Z',
'updated_at' => '2023-01-01T00:00:00Z',
'source' => 'Predefined',
'base_role' => 'admin',
]],
];

$api = $this->getApiMock();
$api->expects($this->once())
->method('get')
->with('/orgs/acme/organization-roles')
->will($this->returnValue($expectedValue));

$this->assertEquals($expectedValue, $api->all('acme'));
}

/**
* @test
*/
public function shouldShowSingleOrganizationRole()
{
$expectedValue = [
'id' => 1,
'name' => 'all_repo_admin',
'description' => 'Grants admin access to all repositories in the organization.',
'permissions' => [],
'organization' => null,
'created_at' => '2023-01-01T00:00:00Z',
'updated_at' => '2023-01-01T00:00:00Z',
'source' => 'Predefined',
'base_role' => 'admin',
];

$api = $this->getApiMock();
$api->expects($this->once())
->method('get')
->with('/orgs/acme/organization-roles/1')
->will($this->returnValue($expectedValue));

$this->assertEquals($expectedValue, $api->show('acme', 1));
}

/**
* @test
*/
public function shouldGetAllTeamsWithRole()
{
$expectedValue = [['name' => 'Acme Admins']];

$api = $this->getApiMock();
$api->expects($this->once())
->method('get')
->with('/orgs/acme/organization-roles/1/teams')
->will($this->returnValue($expectedValue));

$this->assertEquals($expectedValue, $api->listTeamsWithRole('acme', 1));
}

/**
* @test
*/
public function shouldAssignRoleToTeam()
{
$api = $this->getApiMock();
$api->expects($this->once())
->method('put')
->with('/orgs/acme/organization-roles/teams/acme-admins/1')
->will($this->returnValue(''));

$api->assignRoleToTeam('acme', 1, 'acme-admins');
}

/**
* @test
*/
public function shouldRemoveRoleFromTeam()
{
$api = $this->getApiMock();
$api->expects($this->once())
->method('delete')
->with('/orgs/acme/organization-roles/teams/acme-admins/1')
->will($this->returnValue(''));

$api->removeRoleFromTeam('acme', 1, 'acme-admins');
}

/**
* @test
*/
public function shouldRemoveAllRolesFromTeam()
{
$api = $this->getApiMock();
$api->expects($this->once())
->method('delete')
->with('/orgs/acme/organization-roles/teams/acme-admins')
->will($this->returnValue(''));

$api->removeAllRolesFromTeam('acme', 'acme-admins');
}

/**
* @test
*/
public function shouldGetAllUsersWithRole()
{
$expectedValue = [['username' => 'Admin']];

$api = $this->getApiMock();
$api->expects($this->once())
->method('get')
->with('/orgs/acme/organization-roles/1/users')
->will($this->returnValue($expectedValue));

$this->assertEquals($expectedValue, $api->listUsersWithRole('acme', 1));
}

/**
* @test
*/
public function shouldAssignRoleToUser()
{
$api = $this->getApiMock();
$api->expects($this->once())
->method('put')
->with('/orgs/acme/organization-roles/users/admin/1')
->will($this->returnValue(''));

$api->assignRoleToUser('acme', 1, 'admin');
}

/**
* @test
*/
public function shouldRemoveRoleFromUser()
{
$api = $this->getApiMock();
$api->expects($this->once())
->method('delete')
->with('/orgs/acme/organization-roles/users/admin/1')
->will($this->returnValue(''));

$api->removeRoleFromUser('acme', 1, 'admin');
}

/**
* @test
*/
public function shouldRemoveAllRolesFromUser()
{
$api = $this->getApiMock();
$api->expects($this->once())
->method('delete')
->with('/orgs/acme/organization-roles/users/admin')
->will($this->returnValue(''));

$api->removeAllRolesFromUser('acme', 'admin');
}

protected function getApiClass(): string
{
return OrganizationRoles::class;
}
}

0 comments on commit f8f6a95

Please sign in to comment.