Skip to content

Commit

Permalink
feat: Implement organization role assignments for both users and teams (
Browse files Browse the repository at this point in the history
#3281)

Fixes: #3280.
  • Loading branch information
felixlut authored Sep 23, 2024
1 parent c0f5841 commit eda7049
Show file tree
Hide file tree
Showing 2 changed files with 204 additions and 0 deletions.
88 changes: 88 additions & 0 deletions github/orgs_custom_roles.go
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,94 @@ func (s *OrganizationsService) DeleteCustomOrgRole(ctx context.Context, org stri
return resp, nil
}

// AssignOrgRoleToTeam assigns an existing organization role to a team in this organization.
// In order to assign organization roles in an organization, the authenticated user must be an organization owner.
//
// GitHub API docs: https://docs.github.com/rest/orgs/organization-roles#assign-an-organization-role-to-a-team
//
//meta:operation PUT /orgs/{org}/organization-roles/teams/{team_slug}/{role_id}
func (s *OrganizationsService) AssignOrgRoleToTeam(ctx context.Context, org, teamSlug string, roleID int64) (*Response, error) {
u := fmt.Sprintf("orgs/%v/organization-roles/teams/%v/%v", org, teamSlug, roleID)

req, err := s.client.NewRequest("PUT", u, nil)
if err != nil {
return nil, err
}

resp, err := s.client.Do(ctx, req, nil)
if err != nil {
return resp, err
}

return resp, nil
}

// RemoveOrgRoleFromTeam removes an existing organization role assignment from a team in this organization.
// In order to remove organization role assignments in an organization, the authenticated user must be an organization owner.
//
// GitHub API docs: https://docs.github.com/rest/orgs/organization-roles#remove-an-organization-role-from-a-team
//
//meta:operation DELETE /orgs/{org}/organization-roles/teams/{team_slug}/{role_id}
func (s *OrganizationsService) RemoveOrgRoleFromTeam(ctx context.Context, org, teamSlug string, roleID int64) (*Response, error) {
u := fmt.Sprintf("orgs/%v/organization-roles/teams/%v/%v", org, teamSlug, roleID)

req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}

resp, err := s.client.Do(ctx, req, nil)
if err != nil {
return resp, err
}

return resp, nil
}

// AssignOrgRoleToUser assigns an existing organization role to a user in this organization.
// In order to assign organization roles in an organization, the authenticated user must be an organization owner.
//
// GitHub API docs: https://docs.github.com/rest/orgs/organization-roles#assign-an-organization-role-to-a-user
//
//meta:operation PUT /orgs/{org}/organization-roles/users/{username}/{role_id}
func (s *OrganizationsService) AssignOrgRoleToUser(ctx context.Context, org, username string, roleID int64) (*Response, error) {
u := fmt.Sprintf("orgs/%v/organization-roles/users/%v/%v", org, username, roleID)

req, err := s.client.NewRequest("PUT", u, nil)
if err != nil {
return nil, err
}

resp, err := s.client.Do(ctx, req, nil)
if err != nil {
return resp, err
}

return resp, nil
}

// RemoveOrgRoleFromUser removes an existing organization role assignment from a user in this organization.
// In order to remove organization role assignments in an organization, the authenticated user must be an organization owner.
//
// GitHub API docs: https://docs.github.com/rest/orgs/organization-roles#remove-an-organization-role-from-a-user
//
//meta:operation DELETE /orgs/{org}/organization-roles/users/{username}/{role_id}
func (s *OrganizationsService) RemoveOrgRoleFromUser(ctx context.Context, org, username string, roleID int64) (*Response, error) {
u := fmt.Sprintf("orgs/%v/organization-roles/users/%v/%v", org, username, roleID)

req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}

resp, err := s.client.Do(ctx, req, nil)
if err != nil {
return resp, err
}

return resp, nil
}

// ListCustomRepoRoles lists the custom repository roles available in this organization.
// In order to see custom repository roles in an organization, the authenticated user must be an organization owner.
//
Expand Down
116 changes: 116 additions & 0 deletions github/orgs_custom_roles_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,122 @@ func TestOrganizationsService_DeleteCustomOrgRole(t *testing.T) {
})
}

func TestOrganizationsService_AssignOrgRoleToTeam(t *testing.T) {
client, mux, _, teardown := setup()
defer teardown()

mux.HandleFunc("/orgs/o/organization-roles/teams/t/8030", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "PUT")
w.WriteHeader(http.StatusNoContent)
})

ctx := context.Background()
resp, err := client.Organizations.AssignOrgRoleToTeam(ctx, "o", "t", 8030)
if err != nil {
t.Errorf("Organization.AssignOrgRoleToTeam return error: %v", err)
}
if !cmp.Equal(resp.StatusCode, http.StatusNoContent) {
t.Errorf("Organizations.AssignOrgRoleToTeam returned status code %+v, want %+v", resp.StatusCode, http.StatusNoContent)
}

const methodName = "AssignOrgRoleToTeam"
testBadOptions(t, methodName, func() (err error) {
_, err = client.Organizations.AssignOrgRoleToTeam(ctx, "\no", "\nt", -8030)
return err
})

testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
return client.Organizations.AssignOrgRoleToTeam(ctx, "o", "t", 8030)
})
}

func TestOrganizationsService_RemoveOrgRoleFromTeam(t *testing.T) {
client, mux, _, teardown := setup()
defer teardown()

mux.HandleFunc("/orgs/o/organization-roles/teams/t/8030", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "DELETE")
w.WriteHeader(http.StatusNoContent)
})

ctx := context.Background()
resp, err := client.Organizations.RemoveOrgRoleFromTeam(ctx, "o", "t", 8030)
if err != nil {
t.Errorf("Organization.RemoveOrgRoleFromTeam return error: %v", err)
}
if !cmp.Equal(resp.StatusCode, http.StatusNoContent) {
t.Errorf("Organizations.RemoveOrgRoleFromTeam returned status code %+v, want %+v", resp.StatusCode, http.StatusNoContent)
}

const methodName = "RemoveOrgRoleFromTeam"
testBadOptions(t, methodName, func() (err error) {
_, err = client.Organizations.RemoveOrgRoleFromTeam(ctx, "\no", "\nt", -8030)
return err
})

testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
return client.Organizations.RemoveOrgRoleFromTeam(ctx, "o", "t", 8030)
})
}

func TestOrganizationsService_AssignOrgRoleToUser(t *testing.T) {
client, mux, _, teardown := setup()
defer teardown()

mux.HandleFunc("/orgs/o/organization-roles/users/t/8030", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "PUT")
w.WriteHeader(http.StatusNoContent)
})

ctx := context.Background()
resp, err := client.Organizations.AssignOrgRoleToUser(ctx, "o", "t", 8030)
if err != nil {
t.Errorf("Organization.AssignOrgRoleToUser return error: %v", err)
}
if !cmp.Equal(resp.StatusCode, http.StatusNoContent) {
t.Errorf("Organizations.AssignOrgRoleToUser returned status code %+v, want %+v", resp.StatusCode, http.StatusNoContent)
}

const methodName = "AssignOrgRoleToUser"
testBadOptions(t, methodName, func() (err error) {
_, err = client.Organizations.AssignOrgRoleToUser(ctx, "\no", "\nt", -8030)
return err
})

testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
return client.Organizations.AssignOrgRoleToUser(ctx, "o", "t", 8030)
})
}

func TestOrganizationsService_RemoveOrgRoleFromUser(t *testing.T) {
client, mux, _, teardown := setup()
defer teardown()

mux.HandleFunc("/orgs/o/organization-roles/users/t/8030", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "DELETE")
w.WriteHeader(http.StatusNoContent)
})

ctx := context.Background()
resp, err := client.Organizations.RemoveOrgRoleFromUser(ctx, "o", "t", 8030)
if err != nil {
t.Errorf("Organization.RemoveOrgRoleFromUser return error: %v", err)
}
if !cmp.Equal(resp.StatusCode, http.StatusNoContent) {