From 7c17fafb683b9e6b27fad2839590881c7538637e Mon Sep 17 00:00:00 2001 From: Benjamin Binier Date: Sat, 9 Mar 2024 08:43:15 +0100 Subject: [PATCH 1/2] Add support for groups job token --- job_token_scope.go | 98 +++++++++++++++++++++++++++++++++++++++++ job_token_scope_test.go | 97 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 195 insertions(+) diff --git a/job_token_scope.go b/job_token_scope.go index ff96ba698..16ca62b56 100644 --- a/job_token_scope.go +++ b/job_token_scope.go @@ -184,3 +184,101 @@ func (j *JobTokenScopeService) RemoveProjectFromJobScopeAllowList(pid interface{ return j.client.Do(req, nil) } + +// JobTokenInboundGroupsAllowItem represents a single job token inbound group allowlist item. +// +// GitLab API docs: https://docs.gitlab.com/ee/api/project_job_token_scopes.html +type JobTokenInboundGroupsAllowItem struct { + SourceProjectID int `json:"source_project_id"` + TargetGroupID int `json:"target_group_id"` +} + +// GetJobTokenInboundGroupsAllowListOptions represents the available +// GetJobTokenInboundGroupsAllowList() options. +// +// GitLab API docs: +// https://docs.gitlab.com/ee/api/project_job_token_scopes.html#get-a-projects-cicd-job-token-inbound-allowlist +type GetJobTokenInboundGroupsAllowListOptions struct { + ListOptions +} + +// GetProjectJobTokenInboundGroupsAllowList fetches the CI/CD job token inbound +// groups allowlist (job token scope) of a project. +// +// GitLab API docs: +// https://docs.gitlab.com/ee/api/project_job_token_scopes.html#get-a-projects-cicd-job-token-allowlist-of-groups +func (j *JobTokenScopeService) GetProjectJobTokenInboundGroupsAllowList(pid interface{}, opt *GetJobTokenInboundGroupsAllowListOptions, options ...RequestOptionFunc) ([]*Group, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf(`projects/%s/job_token_scope/groups_allowlist`, PathEscape(project)) + + req, err := j.client.NewRequest(http.MethodGet, u, opt, options) + if err != nil { + return nil, nil, err + } + + var ps []*Group + resp, err := j.client.Do(req, &ps) + if err != nil { + return nil, resp, err + } + + return ps, resp, nil +} + +// AddProjectToJobScopeGroupsAllowListOptions represents the available +// AddProjectToJobScopeGroupsAllowList() options. +// +// GitLab API docs: +// https://docs.gitlab.com/ee/api/project_job_token_scopes.html#add-a-group-to-a-cicd-job-token-allowlist +type JobTokenInboundGroupsAllowOptions struct { + TargetGroupID *int `url:"target_group_id,omitempty" json:"target_group_id,omitempty"` +} + +// AddProjectToJobScopeGroupsAllowList adds a new group to a project's job token +// inbound groups allow list. +// +// GitLab API docs: +// https://docs.gitlab.com/ee/api/project_job_token_scopes.html#add-a-group-to-a-cicd-job-token-allowlist +func (j *JobTokenScopeService) AddGroupToJobScopeGroupsAllowList(pid interface{}, opt *JobTokenInboundGroupsAllowOptions, options ...RequestOptionFunc) (*JobTokenInboundGroupsAllowItem, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf(`projects/%s/job_token_scope/groups_allowlist`, PathEscape(project)) + + req, err := j.client.NewRequest(http.MethodPost, u, opt, options) + if err != nil { + return nil, nil, err + } + + jt := new(JobTokenInboundGroupsAllowItem) + resp, err := j.client.Do(req, jt) + if err != nil { + return nil, resp, err + } + + return jt, resp, nil +} + +// RemoveGroupFromJobScopeAllowList removes a group from a project's job +// token inbound groups allow list. +// +// GitLab API docs: +// https://docs.gitlab.com/ee/api/project_job_token_scopes.html#remove-a-group-from-a-cicd-job-token-allowlist +func (j *JobTokenScopeService) RemoveGroupFromJobScopeGroupsAllowList(pid interface{}, targetGroup int, options ...RequestOptionFunc) (*Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, err + } + u := fmt.Sprintf(`projects/%s/job_token_scope/groups_allowlist/%d`, PathEscape(project), targetGroup) + + req, err := j.client.NewRequest(http.MethodDelete, u, nil, options) + if err != nil { + return nil, err + } + + return j.client.Do(req, nil) +} diff --git a/job_token_scope_test.go b/job_token_scope_test.go index 4300f21cd..4798f2e87 100644 --- a/job_token_scope_test.go +++ b/job_token_scope_test.go @@ -177,3 +177,100 @@ func TestRemoveProjectFromJobScopeAllowList(t *testing.T) { assert.NoError(t, err) assert.Equal(t, 204, resp.StatusCode) } + +// This tests that when calling the GetProjectJobTokenInboundGroupsAllowList, we +// get a list of groups back properly. There isn't a "deep" test with every +// attribute specified, because the object returned is a *Group object, which +// is already tested in groups.go. +func TestGetProjectJobTokenInboundGroupsAllowList(t *testing.T) { + mux, client := setup(t) + + // Handle project ID 1, and print a result of two groups + mux.HandleFunc("/api/v4/projects/1/job_token_scope/groups_allowlist", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, http.MethodGet) + + // Print on the response + fmt.Fprint(w, `[{"id":1},{"id":2}]`) + }) + + want := []*Group{{ID: 1}, {ID: 2}} + groups, _, err := client.JobTokenScope.GetProjectJobTokenInboundGroupsAllowList( + 1, + &GetJobTokenInboundGroupsAllowListOptions{}, + ) + + assert.NoError(t, err) + assert.Equal(t, want, groups) +} + +func TestAddGroupToJobScopeGroupsAllowList(t *testing.T) { + mux, client := setup(t) + + mux.HandleFunc("/api/v4/projects/1/job_token_scope/groups_allowlist", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, http.MethodPost) + + // Read the request to determine which target group is passed in + body, err := io.ReadAll(r.Body) + if err != nil { + t.Fatalf("JobTokenScope.AddGroupToJobScopeGroupsAllowList failed to read body") + } + + // Parse to object to ensure it's sent on the request appropriately. + var createTokenRequest JobTokenInboundGroupsAllowOptions + err = json.Unmarshal(body, &createTokenRequest) + if err != nil { + t.Fatalf("JobTokenScope.AddGroupToJobScopeGroupsAllowList failed to unmarshal body: %v", err) + } + + // Ensure we provide the proper response + w.WriteHeader(http.StatusCreated) + + // Print on the response with the proper target group + fmt.Fprintf(w, `{ + "source_project_id": 1, + "target_group_id": %d + }`, *createTokenRequest.TargetGroupID) + }) + + want := &JobTokenInboundGroupsAllowItem{ + SourceProjectID: 1, + TargetGroupID: 2, + } + + addTokenResponse, resp, err := client.JobTokenScope.AddGroupToJobScopeGroupsAllowList( + 1, + &JobTokenInboundGroupsAllowOptions{TargetGroupID: Ptr(2)}, + ) + assert.NoError(t, err) + assert.Equal(t, want, addTokenResponse) + assert.Equal(t, 201, resp.StatusCode) +} + +func TestRemoveGroupFromJobScopeGroupsAllowList(t *testing.T) { + mux, client := setup(t) + + mux.HandleFunc("/api/v4/projects/1/job_token_scope/groups_allowlist/2", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, http.MethodDelete) + + // Read the request to determine which target group is passed in + body, err := io.ReadAll(r.Body) + if err != nil { + t.Fatalf("JobTokenScope.RemoveGroupFromJobScopeGroupsAllowList failed to read body") + } + + // The body should be empty since all attributes are passed in the path + if body != nil && string(body) != "" { + t.Fatalf("JobTokenScope.RemoveGroupFromJobScopeGroupsAllowList failed to unmarshal body: %v", err) + } + + // Ensure we provide the proper response + w.WriteHeader(http.StatusNoContent) + + // Print an empty body, since that's what the API provides. + fmt.Fprint(w, "") + }) + + resp, err := client.JobTokenScope.RemoveGroupFromJobScopeGroupsAllowList(1, 2) + assert.NoError(t, err) + assert.Equal(t, 204, resp.StatusCode) +} From b6e96f9afe4d796c709794aca9d892902b0e3ca4 Mon Sep 17 00:00:00 2001 From: Sander van Harmelen Date: Sun, 10 Mar 2024 20:04:14 +0100 Subject: [PATCH 2/2] Rename the new structs and functions --- job_token_scope.go | 32 ++++++++++++++++---------------- job_token_scope_test.go | 36 ++++++++++++++++++------------------ 2 files changed, 34 insertions(+), 34 deletions(-) diff --git a/job_token_scope.go b/job_token_scope.go index 16ca62b56..35525b76d 100644 --- a/job_token_scope.go +++ b/job_token_scope.go @@ -185,29 +185,29 @@ func (j *JobTokenScopeService) RemoveProjectFromJobScopeAllowList(pid interface{ return j.client.Do(req, nil) } -// JobTokenInboundGroupsAllowItem represents a single job token inbound group allowlist item. +// JobTokenAllowlistItem represents a single job token allowlist item. // // GitLab API docs: https://docs.gitlab.com/ee/api/project_job_token_scopes.html -type JobTokenInboundGroupsAllowItem struct { +type JobTokenAllowlistItem struct { SourceProjectID int `json:"source_project_id"` TargetGroupID int `json:"target_group_id"` } -// GetJobTokenInboundGroupsAllowListOptions represents the available -// GetJobTokenInboundGroupsAllowList() options. +// GetJobTokenAllowlistGroupsOptions represents the available +// GetJobTokenAllowlistGroups() options. // // GitLab API docs: -// https://docs.gitlab.com/ee/api/project_job_token_scopes.html#get-a-projects-cicd-job-token-inbound-allowlist -type GetJobTokenInboundGroupsAllowListOptions struct { +// https://docs.gitlab.com/ee/api/project_job_token_scopes.html#get-a-projects-cicd-job-token-allowlist-of-groups +type GetJobTokenAllowlistGroupsOptions struct { ListOptions } -// GetProjectJobTokenInboundGroupsAllowList fetches the CI/CD job token inbound -// groups allowlist (job token scope) of a project. +// GetJobTokenAllowListGroups fetches the CI/CD job token allowlist groups +// (job token scopes) of a project. // // GitLab API docs: // https://docs.gitlab.com/ee/api/project_job_token_scopes.html#get-a-projects-cicd-job-token-allowlist-of-groups -func (j *JobTokenScopeService) GetProjectJobTokenInboundGroupsAllowList(pid interface{}, opt *GetJobTokenInboundGroupsAllowListOptions, options ...RequestOptionFunc) ([]*Group, *Response, error) { +func (j *JobTokenScopeService) GetJobTokenAllowlistGroups(pid interface{}, opt *GetJobTokenAllowlistGroupsOptions, options ...RequestOptionFunc) ([]*Group, *Response, error) { project, err := parseID(pid) if err != nil { return nil, nil, err @@ -228,12 +228,12 @@ func (j *JobTokenScopeService) GetProjectJobTokenInboundGroupsAllowList(pid inte return ps, resp, nil } -// AddProjectToJobScopeGroupsAllowListOptions represents the available -// AddProjectToJobScopeGroupsAllowList() options. +// AddGroupToJobTokenAllowlistOptions represents the available +// AddGroupToJobTokenAllowlist() options. // // GitLab API docs: // https://docs.gitlab.com/ee/api/project_job_token_scopes.html#add-a-group-to-a-cicd-job-token-allowlist -type JobTokenInboundGroupsAllowOptions struct { +type AddGroupToJobTokenAllowlistOptions struct { TargetGroupID *int `url:"target_group_id,omitempty" json:"target_group_id,omitempty"` } @@ -242,7 +242,7 @@ type JobTokenInboundGroupsAllowOptions struct { // // GitLab API docs: // https://docs.gitlab.com/ee/api/project_job_token_scopes.html#add-a-group-to-a-cicd-job-token-allowlist -func (j *JobTokenScopeService) AddGroupToJobScopeGroupsAllowList(pid interface{}, opt *JobTokenInboundGroupsAllowOptions, options ...RequestOptionFunc) (*JobTokenInboundGroupsAllowItem, *Response, error) { +func (j *JobTokenScopeService) AddGroupToJobTokenAllowlist(pid interface{}, opt *AddGroupToJobTokenAllowlistOptions, options ...RequestOptionFunc) (*JobTokenAllowlistItem, *Response, error) { project, err := parseID(pid) if err != nil { return nil, nil, err @@ -254,7 +254,7 @@ func (j *JobTokenScopeService) AddGroupToJobScopeGroupsAllowList(pid interface{} return nil, nil, err } - jt := new(JobTokenInboundGroupsAllowItem) + jt := new(JobTokenAllowlistItem) resp, err := j.client.Do(req, jt) if err != nil { return nil, resp, err @@ -263,12 +263,12 @@ func (j *JobTokenScopeService) AddGroupToJobScopeGroupsAllowList(pid interface{} return jt, resp, nil } -// RemoveGroupFromJobScopeAllowList removes a group from a project's job +// RemoveGroupFromJopTokenAllowlist removes a group from a project's job // token inbound groups allow list. // // GitLab API docs: // https://docs.gitlab.com/ee/api/project_job_token_scopes.html#remove-a-group-from-a-cicd-job-token-allowlist -func (j *JobTokenScopeService) RemoveGroupFromJobScopeGroupsAllowList(pid interface{}, targetGroup int, options ...RequestOptionFunc) (*Response, error) { +func (j *JobTokenScopeService) RemoveGroupFromJobTokenAllowlist(pid interface{}, targetGroup int, options ...RequestOptionFunc) (*Response, error) { project, err := parseID(pid) if err != nil { return nil, err diff --git a/job_token_scope_test.go b/job_token_scope_test.go index 4798f2e87..4c3404712 100644 --- a/job_token_scope_test.go +++ b/job_token_scope_test.go @@ -178,11 +178,11 @@ func TestRemoveProjectFromJobScopeAllowList(t *testing.T) { assert.Equal(t, 204, resp.StatusCode) } -// This tests that when calling the GetProjectJobTokenInboundGroupsAllowList, we -// get a list of groups back properly. There isn't a "deep" test with every -// attribute specified, because the object returned is a *Group object, which -// is already tested in groups.go. -func TestGetProjectJobTokenInboundGroupsAllowList(t *testing.T) { +// This tests that when calling the GetJobTokenAllowlistGroups, we get a list +// of groups back. There isn't a "deep" test with every attribute specified, +// because the object returned is a *Group object, which is already tested in +// groups.go. +func TestGetJobTokenAllowlistGroups(t *testing.T) { mux, client := setup(t) // Handle project ID 1, and print a result of two groups @@ -194,16 +194,16 @@ func TestGetProjectJobTokenInboundGroupsAllowList(t *testing.T) { }) want := []*Group{{ID: 1}, {ID: 2}} - groups, _, err := client.JobTokenScope.GetProjectJobTokenInboundGroupsAllowList( + groups, _, err := client.JobTokenScope.GetJobTokenAllowlistGroups( 1, - &GetJobTokenInboundGroupsAllowListOptions{}, + &GetJobTokenAllowlistGroupsOptions{}, ) assert.NoError(t, err) assert.Equal(t, want, groups) } -func TestAddGroupToJobScopeGroupsAllowList(t *testing.T) { +func TestAddGroupToJobTokenAllowlist(t *testing.T) { mux, client := setup(t) mux.HandleFunc("/api/v4/projects/1/job_token_scope/groups_allowlist", func(w http.ResponseWriter, r *http.Request) { @@ -212,14 +212,14 @@ func TestAddGroupToJobScopeGroupsAllowList(t *testing.T) { // Read the request to determine which target group is passed in body, err := io.ReadAll(r.Body) if err != nil { - t.Fatalf("JobTokenScope.AddGroupToJobScopeGroupsAllowList failed to read body") + t.Fatalf("JobTokenScope.AddGroupToJobTokenAllowlist failed to read body") } // Parse to object to ensure it's sent on the request appropriately. - var createTokenRequest JobTokenInboundGroupsAllowOptions + var createTokenRequest AddGroupToJobTokenAllowlistOptions err = json.Unmarshal(body, &createTokenRequest) if err != nil { - t.Fatalf("JobTokenScope.AddGroupToJobScopeGroupsAllowList failed to unmarshal body: %v", err) + t.Fatalf("JobTokenScope.AddGroupToJobTokenAllowlist failed to unmarshal body: %v", err) } // Ensure we provide the proper response @@ -232,21 +232,21 @@ func TestAddGroupToJobScopeGroupsAllowList(t *testing.T) { }`, *createTokenRequest.TargetGroupID) }) - want := &JobTokenInboundGroupsAllowItem{ + want := &JobTokenAllowlistItem{ SourceProjectID: 1, TargetGroupID: 2, } - addTokenResponse, resp, err := client.JobTokenScope.AddGroupToJobScopeGroupsAllowList( + addTokenResponse, resp, err := client.JobTokenScope.AddGroupToJobTokenAllowlist( 1, - &JobTokenInboundGroupsAllowOptions{TargetGroupID: Ptr(2)}, + &AddGroupToJobTokenAllowlistOptions{TargetGroupID: Ptr(2)}, ) assert.NoError(t, err) assert.Equal(t, want, addTokenResponse) assert.Equal(t, 201, resp.StatusCode) } -func TestRemoveGroupFromJobScopeGroupsAllowList(t *testing.T) { +func TestRemoveGroupFromJobTokenAllowlist(t *testing.T) { mux, client := setup(t) mux.HandleFunc("/api/v4/projects/1/job_token_scope/groups_allowlist/2", func(w http.ResponseWriter, r *http.Request) { @@ -255,12 +255,12 @@ func TestRemoveGroupFromJobScopeGroupsAllowList(t *testing.T) { // Read the request to determine which target group is passed in body, err := io.ReadAll(r.Body) if err != nil { - t.Fatalf("JobTokenScope.RemoveGroupFromJobScopeGroupsAllowList failed to read body") + t.Fatalf("JobTokenScope.RemoveGroupFromJobTokenAllowlist failed to read body") } // The body should be empty since all attributes are passed in the path if body != nil && string(body) != "" { - t.Fatalf("JobTokenScope.RemoveGroupFromJobScopeGroupsAllowList failed to unmarshal body: %v", err) + t.Fatalf("JobTokenScope.RemoveGroupFromJobTokenAllowlist failed to unmarshal body: %v", err) } // Ensure we provide the proper response @@ -270,7 +270,7 @@ func TestRemoveGroupFromJobScopeGroupsAllowList(t *testing.T) { fmt.Fprint(w, "") }) - resp, err := client.JobTokenScope.RemoveGroupFromJobScopeGroupsAllowList(1, 2) + resp, err := client.JobTokenScope.RemoveGroupFromJobTokenAllowlist(1, 2) assert.NoError(t, err) assert.Equal(t, 204, resp.StatusCode) }