Skip to content

Commit f8f6a95

Browse files
authored
feature #1143 Add API endpoints to interact with organization roles (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
2 parents 00ab97b + 1f77a93 commit f8f6a95

File tree

5 files changed

+363
-0
lines changed

5 files changed

+363
-0
lines changed

doc/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ v3 APIs:
4444
* [Secrets](organization/actions/secrets.md)
4545
* [Variables](organization/actions/variables.md)
4646
* [Secret Scanning Alert](organization/secret-scanning.md)
47+
* [Organization Roles](organization/organization-roles.md)
4748
* [Projects](project/projects.md)
4849
* [Columns](project/columns.md)
4950
* [Cards](project/cards.md)
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
## Organization / Webhooks API
2+
[Back to the navigation](../README.md)
3+
4+
Listing, showing, assigning, and removing orgniazationroles.
5+
Wraps [GitHub Organization Roles API](https://docs.github.com/en/rest/orgs/organization-roles).
6+
7+
Additional APIs:
8+
* [Organization](../doc/organization)
9+
10+
### List all organizaton roles in an organization
11+
12+
> Requires [authentication](../security.md).
13+
14+
```php
15+
$roles = $client->organization()->organizationRoles()->all('acme');
16+
```
17+
18+
Returns a counter and a list of organization roles in the organization.
19+
20+
### Get an organization role in an organization
21+
22+
> Requires [authentication](../security.md).
23+
24+
```php
25+
$role = $client->organization()->organizationRoles()->show('acme', 123);
26+
```
27+
28+
Returns a single organization role in the organization.
29+
30+
### List all teams with role assigned in an organization
31+
32+
> Requires [authentication](../security.md).
33+
34+
```php
35+
$users = $client->organization()->organizationRoles()->listTeamsWithRole('acme', 1);
36+
```
37+
38+
Returns a list of teams with the role assigned to them.
39+
40+
### Assign a single role to a team in an organization
41+
42+
> Requires [authentication](../security.md).
43+
44+
```php
45+
$client->organization()->organizationRoles()->assignRoleToTeam('acme', 1, 'admin-user');
46+
```
47+
48+
No content is returned.
49+
50+
### Remove a single role from a team in an organization
51+
52+
> Requires [authentication](../security.md).
53+
54+
```php
55+
$client->organization()->organizationRoles()->removeRoleFromTeam('acme', 1, 'admin-team');
56+
```
57+
58+
No content is returned.
59+
60+
### Remove all roles from a team in an organization
61+
62+
> Requires [authentication](../security.md).
63+
64+
```php
65+
$client->organization()->organizationRoles()->removeAllRolesFromTeam('acme', 'admin-team');
66+
```
67+
68+
No content is returned.
69+
70+
### List all users with role assigned in an organization
71+
72+
> Requires [authentication](../security.md).
73+
74+
```php
75+
$users = $client->organization()->organizationRoles()->listUsersWithRole('acme', 1);
76+
```
77+
78+
Returns a list of users with the role assigned to them.
79+
80+
### Assign a single role to a user in an organization
81+
82+
> Requires [authentication](../security.md).
83+
84+
```php
85+
$client->organization()->organizationRoles()->assignRoleToUser('acme', 1, 'admin-user');
86+
```
87+
88+
No content is returned.
89+
90+
### Remove a single role from a user in an organization
91+
92+
> Requires [authentication](../security.md).
93+
94+
```php
95+
$client->organization()->organizationRoles()->removeRoleFromUser('acme', 1, 'admin-user');
96+
```
97+
98+
No content is returned.
99+
100+
### Remove all roles from a user in an organization
101+
102+
> Requires [authentication](../security.md).
103+
104+
```php
105+
$client->organization()->organizationRoles()->removeAllRolesFromUser('acme', 'admin-user');
106+
```
107+
108+
No content is returned.

lib/Github/Api/Organization.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use Github\Api\Organization\Actions\Variables;
88
use Github\Api\Organization\Hooks;
99
use Github\Api\Organization\Members;
10+
use Github\Api\Organization\OrganizationRoles;
1011
use Github\Api\Organization\OutsideCollaborators;
1112
use Github\Api\Organization\SecretScanning;
1213
use Github\Api\Organization\Teams;
@@ -158,4 +159,9 @@ public function secretScanning(): SecretScanning
158159
{
159160
return new SecretScanning($this->getClient());
160161
}
162+
163+
public function organizationRoles(): OrganizationRoles
164+
{
165+
return new OrganizationRoles($this->getClient());
166+
}
161167
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
<?php
2+
3+
namespace Github\Api\Organization;
4+
5+
use Github\Api\AbstractApi;
6+
7+
/**
8+
* @link https://docs.github.com/en/rest/orgs/organization-roles
9+
*/
10+
class OrganizationRoles extends AbstractApi
11+
{
12+
public function all(string $organization)
13+
{
14+
return $this->get('/orgs/'.rawurlencode($organization).'/organization-roles');
15+
}
16+
17+
public function show(string $organization, int $roleId)
18+
{
19+
return $this->get('/orgs/'.rawurlencode($organization).'/organization-roles/'.$roleId);
20+
}
21+
22+
public function listTeamsWithRole(string $organization, int $roleId)
23+
{
24+
return $this->get('/orgs/'.rawurlencode($organization).'/organization-roles/'.$roleId.'/teams');
25+
}
26+
27+
public function assignRoleToTeam(string $organization, int $roleId, string $teamSlug): void
28+
{
29+
$this->put('/orgs/'.rawurlencode($organization).'/organization-roles/teams/'.rawurlencode($teamSlug).'/'.$roleId);
30+
}
31+
32+
public function removeRoleFromTeam(string $organization, int $roleId, string $teamSlug): void
33+
{
34+
$this->delete('/orgs/'.rawurlencode($organization).'/organization-roles/teams/'.rawurlencode($teamSlug).'/'.$roleId);
35+
}
36+
37+
public function removeAllRolesFromTeam(string $organization, string $teamSlug): void
38+
{
39+
$this->delete('/orgs/'.rawurlencode($organization).'/organization-roles/teams/'.rawurlencode($teamSlug));
40+
}
41+
42+
public function listUsersWithRole(string $organization, int $roleId): array
43+
{
44+
return $this->get('/orgs/'.rawurlencode($organization).'/organization-roles/'.$roleId.'/users');
45+
}
46+
47+
public function assignRoleToUser(string $organization, int $roleId, string $username): void
48+
{
49+
$this->put('/orgs/'.rawurlencode($organization).'/organization-roles/users/'.rawurlencode($username).'/'.$roleId);
50+
}
51+
52+
public function removeRoleFromUser(string $organization, int $roleId, string $username): void
53+
{
54+
$this->delete('/orgs/'.rawurlencode($organization).'/organization-roles/users/'.rawurlencode($username).'/'.$roleId);
55+
}
56+
57+
public function removeAllRolesFromUser(string $organization, string $username): void
58+
{
59+
$this->delete('/orgs/'.rawurlencode($organization).'/organization-roles/users/'.rawurlencode($username));
60+
}
61+
}
Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Github\Tests\Api\Organization;
6+
7+
use Github\Api\Organization\OrganizationRoles;
8+
use Github\Tests\Api\TestCase;
9+
10+
class OrganizationRolesTest extends TestCase
11+
{
12+
/**
13+
* @test
14+
*/
15+
public function shouldGetAllOrganizationRoles()
16+
{
17+
$expectedValue = [
18+
'total_count' => 1,
19+
'roles' => [[
20+
'id' => 1,
21+
'name' => 'all_repo_admin',
22+
'description' => 'Grants admin access to all repositories in the organization.',
23+
'permissions' => [],
24+
'organization' => null,
25+
'created_at' => '2023-01-01T00:00:00Z',
26+
'updated_at' => '2023-01-01T00:00:00Z',
27+
'source' => 'Predefined',
28+
'base_role' => 'admin',
29+
]],
30+
];
31+
32+
$api = $this->getApiMock();
33+
$api->expects($this->once())
34+
->method('get')
35+
->with('/orgs/acme/organization-roles')
36+
->will($this->returnValue($expectedValue));
37+
38+
$this->assertEquals($expectedValue, $api->all('acme'));
39+
}
40+
41+
/**
42+
* @test
43+
*/
44+
public function shouldShowSingleOrganizationRole()
45+
{
46+
$expectedValue = [
47+
'id' => 1,
48+
'name' => 'all_repo_admin',
49+
'description' => 'Grants admin access to all repositories in the organization.',
50+
'permissions' => [],
51+
'organization' => null,
52+
'created_at' => '2023-01-01T00:00:00Z',
53+
'updated_at' => '2023-01-01T00:00:00Z',
54+
'source' => 'Predefined',
55+
'base_role' => 'admin',
56+
];
57+
58+
$api = $this->getApiMock();
59+
$api->expects($this->once())
60+
->method('get')
61+
->with('/orgs/acme/organization-roles/1')
62+
->will($this->returnValue($expectedValue));
63+
64+
$this->assertEquals($expectedValue, $api->show('acme', 1));
65+
}
66+
67+
/**
68+
* @test
69+
*/
70+
public function shouldGetAllTeamsWithRole()
71+
{
72+
$expectedValue = [['name' => 'Acme Admins']];
73+
74+
$api = $this->getApiMock();
75+
$api->expects($this->once())
76+
->method('get')
77+
->with('/orgs/acme/organization-roles/1/teams')
78+
->will($this->returnValue($expectedValue));
79+
80+
$this->assertEquals($expectedValue, $api->listTeamsWithRole('acme', 1));
81+
}
82+
83+
/**
84+
* @test
85+
*/
86+
public function shouldAssignRoleToTeam()
87+
{
88+
$api = $this->getApiMock();
89+
$api->expects($this->once())
90+
->method('put')
91+
->with('/orgs/acme/organization-roles/teams/acme-admins/1')
92+
->will($this->returnValue(''));
93+
94+
$api->assignRoleToTeam('acme', 1, 'acme-admins');
95+
}
96+
97+
/**
98+
* @test
99+
*/
100+
public function shouldRemoveRoleFromTeam()
101+
{
102+
$api = $this->getApiMock();
103+
$api->expects($this->once())
104+
->method('delete')
105+
->with('/orgs/acme/organization-roles/teams/acme-admins/1')
106+
->will($this->returnValue(''));
107+
108+
$api->removeRoleFromTeam('acme', 1, 'acme-admins');
109+
}
110+
111+
/**
112+
* @test
113+
*/
114+
public function shouldRemoveAllRolesFromTeam()
115+
{
116+
$api = $this->getApiMock();
117+
$api->expects($this->once())
118+
->method('delete')
119+
->with('/orgs/acme/organization-roles/teams/acme-admins')
120+
->will($this->returnValue(''));
121+
122+
$api->removeAllRolesFromTeam('acme', 'acme-admins');
123+
}
124+
125+
/**
126+
* @test
127+
*/
128+
public function shouldGetAllUsersWithRole()
129+
{
130+
$expectedValue = [['username' => 'Admin']];
131+
132+
$api = $this->getApiMock();
133+
$api->expects($this->once())
134+
->method('get')
135+
->with('/orgs/acme/organization-roles/1/users')
136+
->will($this->returnValue($expectedValue));
137+
138+
$this->assertEquals($expectedValue, $api->listUsersWithRole('acme', 1));
139+
}
140+
141+
/**
142+
* @test
143+
*/
144+
public function shouldAssignRoleToUser()
145+
{
146+
$api = $this->getApiMock();
147+
$api->expects($this->once())
148+
->method('put')
149+
->with('/orgs/acme/organization-roles/users/admin/1')
150+
->will($this->returnValue(''));
151+
152+
$api->assignRoleToUser('acme', 1, 'admin');
153+
}
154+
155+
/**
156+
* @test
157+
*/
158+
public function shouldRemoveRoleFromUser()
159+
{
160+
$api = $this->getApiMock();
161+
$api->expects($this->once())
162+
->method('delete')
163+
->with('/orgs/acme/organization-roles/users/admin/1')
164+
->will($this->returnValue(''));
165+
166+
$api->removeRoleFromUser('acme', 1, 'admin');
167+
}
168+
169+
/**
170+
* @test
171+
*/
172+
public function shouldRemoveAllRolesFromUser()
173+
{
174+
$api = $this->getApiMock();
175+
$api->expects($this->once())
176+
->method('delete')
177+
->with('/orgs/acme/organization-roles/users/admin')
178+
->will($this->returnValue(''));
179+
180+
$api->removeAllRolesFromUser('acme', 'admin');
181+
}
182+
183+
protected function getApiClass(): string
184+
{
185+
return OrganizationRoles::class;
186+
}
187+
}

0 commit comments

Comments
 (0)