From 3d4fccba54228b703b50e36459a3df5604f054b3 Mon Sep 17 00:00:00 2001 From: mohaldu Date: Fri, 14 Oct 2022 20:32:20 +1100 Subject: [PATCH] add custom role api --- github/orgs_custom_roles.go | 78 ++++++++++++++++++++- github/orgs_custom_roles_test.go | 115 ++++++++++++++++++++++++++++++- 2 files changed, 189 insertions(+), 4 deletions(-) diff --git a/github/orgs_custom_roles.go b/github/orgs_custom_roles.go index 9904685b948..f1bdf90eef9 100644 --- a/github/orgs_custom_roles.go +++ b/github/orgs_custom_roles.go @@ -20,8 +20,11 @@ type OrganizationCustomRepoRoles struct { // See https://docs.github.com/en/enterprise-cloud@latest/organizations/managing-peoples-access-to-your-organization-with-roles/managing-custom-repository-roles-for-an-organization // for more information. type CustomRepoRoles struct { - ID *int64 `json:"id,omitempty"` - Name *string `json:"name,omitempty"` + ID *int64 `json:"id,omitempty"` + Name *string `json:"name,omitempty"` + Description *string `json:"description,omitempty"` + BaseRole *string `json:"base_role,omitempty"` + Permissions *[]string `json:"permissions,omitempty"` } // ListCustomRepoRoles lists the custom repository roles available in this organization. @@ -44,3 +47,74 @@ func (s *OrganizationsService) ListCustomRepoRoles(ctx context.Context, org stri return customRepoRoles, resp, nil } + +// Options required to create or update a custom repository role +type CreateOrUpdateCustomRoleOptions struct { + Name *string `json:"name,omitempty"` + Description *string `json:"description,omitempty"` + BaseRole *string `json:"base_role,omitempty"` + Permissions *[]string `json:"permissions,omitempty"` +} + +// CreateCustomRepoRole creates a custom repository role in this organization +// In order to create custom repository roles in an organization, the authenticated user must be an organization owner. +// +// GitHub API docs: https://docs.github.com/en/rest/orgs/custom-roles#create-a-custom-role +func (s *OrganizationsService) CreateCustomRepoRole(ctx context.Context, org string, opts *CreateOrUpdateCustomRoleOptions) (*CustomRepoRoles, *Response, error) { + u := fmt.Sprintf("orgs/%v/custom_roles", org) + + req, err := s.client.NewRequest("POST", u, opts) + if err != nil { + return nil, nil, err + } + + resultingRole := new(CustomRepoRoles) + resp, err := s.client.Do(ctx, req, resultingRole) + if err != nil { + return nil, resp, err + } + + return resultingRole, resp, err +} + +// CreateCustomRepoRole creates a custom repository role in this organization +// In order to update custom repository roles in an organization, the authenticated user must be an organization owner. +// +// GitHub API docs: https://docs.github.com/en/rest/orgs/custom-roles#update-a-custom-role +func (s *OrganizationsService) UpdateCustomRepoRole(ctx context.Context, org string, roleId string, opts *CreateOrUpdateCustomRoleOptions) (*CustomRepoRoles, *Response, error) { + u := fmt.Sprintf("orgs/%v/custom_roles/%v", org, roleId) + + req, err := s.client.NewRequest("PATCH", u, opts) + if err != nil { + return nil, nil, err + } + + resultingRole := new(CustomRepoRoles) + resp, err := s.client.Do(ctx, req, resultingRole) + if err != nil { + return nil, resp, err + } + + return resultingRole, resp, err +} + +// DeleteCustomRepoRole deletes an existing custom repository role in this organization +// In order to delete custom repository roles in an organization, the authenticated user must be an organization owner. +// +// GitHub API docs: https://docs.github.com/en/rest/orgs/custom-roles#delete-a-custom-role +func (s *OrganizationsService) DeleteCustomRepoRole(ctx context.Context, org string, roleId string) (*Response, error) { + u := fmt.Sprintf("orgs/%v/custom_roles/%v", org, roleId) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + resultingRole := new(CustomRepoRoles) + resp, err := s.client.Do(ctx, req, resultingRole) + if err != nil { + return resp, err + } + + return resp, err +} diff --git a/github/orgs_custom_roles_test.go b/github/orgs_custom_roles_test.go index 7042a5ec829..ace6c45e7a6 100644 --- a/github/orgs_custom_roles_test.go +++ b/github/orgs_custom_roles_test.go @@ -20,7 +20,7 @@ func TestOrganizationsService_ListCustomRepoRoles(t *testing.T) { mux.HandleFunc("/orgs/o/custom_roles", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") - fmt.Fprint(w, `{"total_count": 1, "custom_roles": [{ "id": 1, "name": "Developer"}]}`) + fmt.Fprint(w, `{"total_count": 1, "custom_roles": [{ "id": 1, "name": "Developer", "base_role": "write", "permissions": ["delete_alerts_code_scanning"]}]}`) }) ctx := context.Background() @@ -29,7 +29,7 @@ func TestOrganizationsService_ListCustomRepoRoles(t *testing.T) { t.Errorf("Organizations.ListCustomRepoRoles returned error: %v", err) } - want := &OrganizationCustomRepoRoles{TotalCount: Int(1), CustomRepoRoles: []*CustomRepoRoles{{ID: Int64(1), Name: String("Developer")}}} + want := &OrganizationCustomRepoRoles{TotalCount: Int(1), CustomRepoRoles: []*CustomRepoRoles{{ID: Int64(1), Name: String("Developer"), BaseRole: String("write"), Permissions: &[]string{"delete_alerts_code_scanning"}}}} if !cmp.Equal(apps, want) { t.Errorf("Organizations.ListCustomRepoRoles returned %+v, want %+v", apps, want) } @@ -48,3 +48,114 @@ func TestOrganizationsService_ListCustomRepoRoles(t *testing.T) { return resp, err }) } + +func TestOrganizationsService_CreateCustomRepoRole(t *testing.T) { + client, mux, _, teardown := setup() + defer teardown() + + mux.HandleFunc("/orgs/o/custom_roles", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "POST") + fmt.Fprint(w, `{"id":8030,"name":"Labeler","description":"A role for issue and PR labelers","base_role":"read","permissions":["add_label"]}`) + }) + + ctx := context.Background() + + opts := &CreateOrUpdateCustomRoleOptions{ + Name: String("Labeler"), + Description: String("A role for issue and PR labelers"), + BaseRole: String("read"), + Permissions: &[]string{"add_label"}, + } + apps, _, err := client.Organizations.CreateCustomRepoRole(ctx, "o", opts) + if err != nil { + t.Errorf("Organizations.CreateCustomRepoRole returned error: %v", err) + } + + want := &CustomRepoRoles{ID: Int64(8030), Name: String("Labeler"), BaseRole: String("read"), Permissions: &[]string{"add_label"}, Description: String("A role for issue and PR labelers")} + + if !cmp.Equal(apps, want) { + t.Errorf("Organizations.CreateCustomRepoRole returned %+v, want %+v", apps, want) + } + + const methodName = "CreateCustomRepoRole" + testBadOptions(t, methodName, func() (err error) { + _, _, err = client.Organizations.CreateCustomRepoRole(ctx, "\no", nil) + return err + }) + + testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { + got, resp, err := client.Organizations.CreateCustomRepoRole(ctx, "o", nil) + if got != nil { + t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) + } + return resp, err + }) +} + +func TestOrganizationsService_UpdateCustomRepoRole(t *testing.T) { + client, mux, _, teardown := setup() + defer teardown() + + mux.HandleFunc("/orgs/o/custom_roles/8030", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "PATCH") + fmt.Fprint(w, `{"id":8030,"name":"Updated Name","description":"Updated Description","base_role":"read","permissions":["add_label"]}`) + }) + + ctx := context.Background() + + opts := &CreateOrUpdateCustomRoleOptions{ + Name: String("Updated Name"), + Description: String("Updated Description"), + } + apps, _, err := client.Organizations.UpdateCustomRepoRole(ctx, "o", "8030", opts) + if err != nil { + t.Errorf("Organizations.UpdateCustomRepoRole returned error: %v", err) + } + + want := &CustomRepoRoles{ID: Int64(8030), Name: String("Updated Name"), BaseRole: String("read"), Permissions: &[]string{"add_label"}, Description: String("Updated Description")} + + if !cmp.Equal(apps, want) { + t.Errorf("Organizations.UpdateCustomRepoRole returned %+v, want %+v", apps, want) + } + + const methodName = "UpdateCustomRepoRole" + testBadOptions(t, methodName, func() (err error) { + _, _, err = client.Organizations.UpdateCustomRepoRole(ctx, "\no", "8030", nil) + return err + }) + + testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { + got, resp, err := client.Organizations.UpdateCustomRepoRole(ctx, "o", "8030", nil) + if got != nil { + t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) + } + return resp, err + }) +} + +func TestOrganizationsService_DeleteCustomRepoRole(t *testing.T) { + client, mux, _, teardown := setup() + defer teardown() + + mux.HandleFunc("/orgs/o/custom_roles/8030", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "DELETE") + w.WriteHeader(http.StatusNoContent) + }) + + ctx := context.Background() + + resp, err := client.Organizations.DeleteCustomRepoRole(ctx, "o", "8030") + if err != nil { + t.Errorf("Organizations.DeleteCustomRepoRole returned error: %v", err) + } + + if !cmp.Equal(resp.StatusCode, 204) { + t.Errorf("Organizations.DeleteCustomRepoRole returned status code %+v, want %+v", resp.StatusCode, "204") + } + + const methodName = "DeleteCustomRepoRole" + testBadOptions(t, methodName, func() (err error) { + _, err = client.Organizations.DeleteCustomRepoRole(ctx, "\no", "8030") + return err + }) +}