Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 54 additions & 24 deletions github/orgs_security_managers.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,57 +7,87 @@ package github

import (
"context"
"fmt"
"errors"
)

// ListSecurityManagerTeams lists all security manager teams for an organization.
// GetSecurityManagerRole retrieves the security manager role for an organization.
//
// GitHub API docs: https://docs.github.com/rest/orgs/security-managers#list-security-manager-teams
// GitHub API docs: https://docs.github.com/rest/orgs/organization-roles#get-all-organization-roles-for-an-organization
//
//meta:operation GET /orgs/{org}/security-managers
func (s *OrganizationsService) ListSecurityManagerTeams(ctx context.Context, org string) ([]*Team, *Response, error) {
u := fmt.Sprintf("orgs/%v/security-managers", org)

req, err := s.client.NewRequest("GET", u, nil)
//meta:operation GET /orgs/{org}/organization-roles
func (s *OrganizationsService) GetSecurityManagerRole(ctx context.Context, org string) (*CustomOrgRoles, *Response, error) {
roles, resp, err := s.ListRoles(ctx, org)
if err != nil {
return nil, nil, err
return nil, resp, err
}

var teams []*Team
resp, err := s.client.Do(ctx, req, &teams)
for _, role := range roles.CustomRepoRoles {
if *role.Name == "security_manager" {
return role, resp, nil
}
}

return nil, resp, errors.New("security manager role not found")
}

// ListSecurityManagerTeams lists all security manager teams for an organization.
//
// GitHub API docs: https://docs.github.com/rest/orgs/organization-roles#get-all-organization-roles-for-an-organization
// GitHub API docs: https://docs.github.com/rest/orgs/organization-roles#list-teams-that-are-assigned-to-an-organization-role
//
//meta:operation GET /orgs/{org}/organization-roles
//meta:operation GET /orgs/{org}/organization-roles/{role_id}/teams
func (s *OrganizationsService) ListSecurityManagerTeams(ctx context.Context, org string) ([]*Team, *Response, error) {
securityManagerRole, resp, err := s.GetSecurityManagerRole(ctx, org)
if err != nil {
return nil, resp, err
}

return teams, resp, nil
options := &ListOptions{PerPage: 100}
securityManagerTeams := make([]*Team, 0)
for {
teams, resp, err := s.ListTeamsAssignedToOrgRole(ctx, org, securityManagerRole.GetID(), options)
if err != nil {
return nil, resp, err
}

securityManagerTeams = append(securityManagerTeams, teams...)
if resp.NextPage == 0 {
return securityManagerTeams, resp, nil
}

options.Page = resp.NextPage
}
}

// AddSecurityManagerTeam adds a team to the list of security managers for an organization.
//
// GitHub API docs: https://docs.github.com/rest/orgs/security-managers#add-a-security-manager-team
// GitHub API docs: https://docs.github.com/rest/orgs/organization-roles#assign-an-organization-role-to-a-team
// GitHub API docs: https://docs.github.com/rest/orgs/organization-roles#get-all-organization-roles-for-an-organization
//
//meta:operation PUT /orgs/{org}/security-managers/teams/{team_slug}
//meta:operation GET /orgs/{org}/organization-roles
//meta:operation PUT /orgs/{org}/organization-roles/teams/{team_slug}/{role_id}
func (s *OrganizationsService) AddSecurityManagerTeam(ctx context.Context, org, team string) (*Response, error) {
u := fmt.Sprintf("orgs/%v/security-managers/teams/%v", org, team)
req, err := s.client.NewRequest("PUT", u, nil)
securityManagerRole, resp, err := s.GetSecurityManagerRole(ctx, org)
if err != nil {
return nil, err
return resp, err
}

return s.client.Do(ctx, req, nil)
return s.AssignOrgRoleToTeam(ctx, org, team, securityManagerRole.GetID())
}

// RemoveSecurityManagerTeam removes a team from the list of security managers for an organization.
//
// GitHub API docs: https://docs.github.com/rest/orgs/security-managers#remove-a-security-manager-team
// GitHub API docs: https://docs.github.com/rest/orgs/organization-roles#get-all-organization-roles-for-an-organization
// GitHub API docs: https://docs.github.com/rest/orgs/organization-roles#remove-an-organization-role-from-a-team
//
//meta:operation DELETE /orgs/{org}/security-managers/teams/{team_slug}
//meta:operation GET /orgs/{org}/organization-roles
//meta:operation DELETE /orgs/{org}/organization-roles/teams/{team_slug}/{role_id}
func (s *OrganizationsService) RemoveSecurityManagerTeam(ctx context.Context, org, team string) (*Response, error) {
u := fmt.Sprintf("orgs/%v/security-managers/teams/%v", org, team)
req, err := s.client.NewRequest("DELETE", u, nil)
securityManagerRole, resp, err := s.GetSecurityManagerRole(ctx, org)
if err != nil {
return nil, err
return resp, err
}

return s.client.Do(ctx, req, nil)
return s.RemoveOrgRoleFromTeam(ctx, org, team, securityManagerRole.GetID())
}
69 changes: 62 additions & 7 deletions github/orgs_security_managers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,53 @@ import (
"github.com/google/go-cmp/cmp"
)

func TestOrganizationService_GetSecurityManagerRole(t *testing.T) {
t.Parallel()
client, mux, _ := setup(t)

handleGetSecurityManagerRole(t, mux, "o")

ctx := context.Background()
role, _, err := client.Organizations.GetSecurityManagerRole(ctx, "o")
if err != nil {
t.Errorf("Organizations.GetSecurityManagerRole returned error: %v", err)
}

want := &CustomOrgRoles{ID: Ptr(int64(138)), Name: Ptr("security_manager")}
if !cmp.Equal(role, want) {
t.Errorf("Organizations.GetSecurityManagerRole returned %+v, want %+v", role, want)
}

const methodName = "GetSecurityManagerRole"
testBadOptions(t, methodName, func() (err error) {
_, _, err = client.Organizations.GetSecurityManagerRole(ctx, "\n")
return err
})

testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
got, resp, err := client.Organizations.GetSecurityManagerRole(ctx, "o")
if got != nil {
t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
}
return resp, err
})
}

func TestOrganizationsService_GetSecurityManagerRole_invalidOrg(t *testing.T) {
t.Parallel()
client, _, _ := setup(t)

ctx := context.Background()
_, _, err := client.Organizations.GetSecurityManagerRole(ctx, "%")
testURLParseError(t, err)
}

func TestOrganizationsService_ListSecurityManagerTeams(t *testing.T) {
t.Parallel()
client, mux, _ := setup(t)

mux.HandleFunc("/orgs/o/security-managers", func(w http.ResponseWriter, r *http.Request) {
handleGetSecurityManagerRole(t, mux, "o")
mux.HandleFunc("/orgs/o/organization-roles/138/teams", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET")
fmt.Fprint(w, `[{"id":1}]`)
})
Expand Down Expand Up @@ -62,7 +104,8 @@ func TestOrganizationsService_AddSecurityManagerTeam(t *testing.T) {
t.Parallel()
client, mux, _ := setup(t)

mux.HandleFunc("/orgs/o/security-managers/teams/t", func(w http.ResponseWriter, r *http.Request) {
handleGetSecurityManagerRole(t, mux, "o")
mux.HandleFunc("/orgs/o/organization-roles/teams/t/138", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "PUT")
})

Expand Down Expand Up @@ -94,18 +137,21 @@ func TestOrganizationsService_AddSecurityManagerTeam_invalidOrg(t *testing.T) {

func TestOrganizationsService_AddSecurityManagerTeam_invalidTeam(t *testing.T) {
t.Parallel()
client, _, _ := setup(t)
client, mux, _ := setup(t)

handleGetSecurityManagerRole(t, mux, "o")

ctx := context.Background()
_, err := client.Organizations.AddSecurityManagerTeam(ctx, "%", "t")
_, err := client.Organizations.AddSecurityManagerTeam(ctx, "o", "%")
testURLParseError(t, err)
}

func TestOrganizationsService_RemoveSecurityManagerTeam(t *testing.T) {
t.Parallel()
client, mux, _ := setup(t)

mux.HandleFunc("/orgs/o/security-managers/teams/t", func(w http.ResponseWriter, r *http.Request) {
handleGetSecurityManagerRole(t, mux, "o")
mux.HandleFunc("/orgs/o/organization-roles/teams/t/138", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "DELETE")
})

Expand Down Expand Up @@ -137,9 +183,18 @@ func TestOrganizationsService_RemoveSecurityManagerTeam_invalidOrg(t *testing.T)

func TestOrganizationsService_RemoveSecurityManagerTeam_invalidTeam(t *testing.T) {
t.Parallel()
client, _, _ := setup(t)
client, mux, _ := setup(t)

handleGetSecurityManagerRole(t, mux, "o")

ctx := context.Background()
_, err := client.Organizations.RemoveSecurityManagerTeam(ctx, "%", "t")
_, err := client.Organizations.RemoveSecurityManagerTeam(ctx, "o", "%")
testURLParseError(t, err)
}

func handleGetSecurityManagerRole(t *testing.T, mux *http.ServeMux, org string) {
mux.HandleFunc(fmt.Sprintf("/orgs/%s/organization-roles", org), func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET")
fmt.Fprint(w, `{"roles":[{"id":138,"name":"security_manager"}]}`)
})
}