diff --git a/.changelog/1114.txt b/.changelog/1114.txt new file mode 100644 index 000000000..afef66673 --- /dev/null +++ b/.changelog/1114.txt @@ -0,0 +1,7 @@ +```release-note:breaking-change +teams_list: updated methods to match the experimental client format +``` + +```release-note:enhancement +teams_list: `List` operations now automatically paginate +``` diff --git a/dlp_profile_test.go b/dlp_profile_test.go index 692db6f25..d7c88f571 100644 --- a/dlp_profile_test.go +++ b/dlp_profile_test.go @@ -291,7 +291,7 @@ func TestCreateDLPCustomProfiles(t *testing.T) { }, }, } - actual, err := client.CreateDLPProfiles(context.Background(), AccountIdentifier(testAccountID), CreateDLPProfilesParams{Profiles: profiles}) + actual, err := client.CreateDLPProfiles(context.Background(), AccountIdentifier(testAccountID), CreateDLPProfilesParams{Profiles: profiles, Type: "custom"}) require.NoError(t, err) require.Equal(t, want, actual) } @@ -386,6 +386,7 @@ func TestCreateDLPCustomProfile(t *testing.T) { actual, err := client.CreateDLPProfiles(context.Background(), AccountIdentifier(testAccountID), CreateDLPProfilesParams{ Profiles: profiles, + Type: "custom", }) require.NoError(t, err) require.Equal(t, want, actual) diff --git a/teams_list.go b/teams_list.go index ec1f18bc4..b4699a051 100644 --- a/teams_list.go +++ b/teams_list.go @@ -60,18 +60,47 @@ type TeamsListDetailResponse struct { Result TeamsList `json:"result"` } -type TeamsListItemsParams struct { - AccountID string `url:"-"` - ListID string `url:"-"` +type ListTeamsListItemsParams struct { + ListID string `url:"-"` - PaginationOptions + ResultInfo } -// TeamsLists returns all lists within an account. +type ListTeamListsParams struct{} + +type CreateTeamsListParams struct { + ID string `json:"id,omitempty"` + Name string `json:"name"` + Type string `json:"type"` + Description string `json:"description,omitempty"` + Items []TeamsListItem `json:"items,omitempty"` + Count uint64 `json:"count,omitempty"` + CreatedAt *time.Time `json:"created_at,omitempty"` + UpdatedAt *time.Time `json:"updated_at,omitempty"` +} + +type UpdateTeamsListParams struct { + ID string `json:"id,omitempty"` + Name string `json:"name"` + Type string `json:"type"` + Description string `json:"description,omitempty"` + Items []TeamsListItem `json:"items,omitempty"` + Count uint64 `json:"count,omitempty"` + CreatedAt *time.Time `json:"created_at,omitempty"` + UpdatedAt *time.Time `json:"updated_at,omitempty"` +} + +type PatchTeamsListParams struct { + ID string `json:"id"` + Append []TeamsListItem `json:"append"` + Remove []string `json:"remove"` +} + +// ListTeamsLists returns all lists within an account. // // API reference: https://api.cloudflare.com/#teams-lists-list-teams-lists -func (api *API) TeamsLists(ctx context.Context, accountID string) ([]TeamsList, ResultInfo, error) { - uri := fmt.Sprintf("/%s/%s/gateway/lists", AccountRouteRoot, accountID) +func (api *API) ListTeamsLists(ctx context.Context, rc *ResourceContainer, params ListTeamListsParams) ([]TeamsList, ResultInfo, error) { + uri := fmt.Sprintf("/%s/%s/gateway/lists", AccountRouteRoot, rc.Identifier) res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) if err != nil { @@ -87,14 +116,14 @@ func (api *API) TeamsLists(ctx context.Context, accountID string) ([]TeamsList, return teamsListListResponse.Result, teamsListListResponse.ResultInfo, nil } -// TeamsList returns a single list based on the list ID. +// GetTeamsList returns a single list based on the list ID. // // API reference: https://api.cloudflare.com/#teams-lists-teams-list-details -func (api *API) TeamsList(ctx context.Context, accountID, listID string) (TeamsList, error) { +func (api *API) GetTeamsList(ctx context.Context, rc *ResourceContainer, listID string) (TeamsList, error) { uri := fmt.Sprintf( "/%s/%s/gateway/lists/%s", - AccountRouteRoot, - accountID, + rc.Level, + rc.Identifier, listID, ) @@ -112,11 +141,15 @@ func (api *API) TeamsList(ctx context.Context, accountID, listID string) (TeamsL return teamsListDetailResponse.Result, nil } -// TeamsListItems returns all list items for a list. +// ListTeamsListItems returns all list items for a list. // // API reference: https://api.cloudflare.com/#teams-lists-teams-list-items -func (api *API) TeamsListItems(ctx context.Context, params TeamsListItemsParams) ([]TeamsListItem, ResultInfo, error) { - if params.AccountID == "" { +func (api *API) ListTeamsListItems(ctx context.Context, rc *ResourceContainer, params ListTeamsListItemsParams) ([]TeamsListItem, ResultInfo, error) { + if rc.Level != AccountRouteLevel { + return []TeamsListItem{}, ResultInfo{}, fmt.Errorf(errInvalidResourceContainerAccess, rc.Level) + } + + if rc.Identifier == "" { return []TeamsListItem{}, ResultInfo{}, ErrMissingAccountID } @@ -124,32 +157,63 @@ func (api *API) TeamsListItems(ctx context.Context, params TeamsListItemsParams) return []TeamsListItem{}, ResultInfo{}, ErrMissingListID } - uri := buildURI( - fmt.Sprintf("/%s/%s/gateway/lists/%s/items", AccountRouteRoot, params.AccountID, params.ListID), - params, - ) + autoPaginate := true + if params.PerPage >= 1 || params.Page >= 1 { + autoPaginate = false + } - res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) - if err != nil { - return []TeamsListItem{}, ResultInfo{}, err + if params.PerPage < 1 { + params.PerPage = 50 } - var teamsListItemsListResponse TeamsListItemsListResponse - err = json.Unmarshal(res, &teamsListItemsListResponse) - if err != nil { - return []TeamsListItem{}, ResultInfo{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + if params.Page < 1 { + params.Page = 1 } - return teamsListItemsListResponse.Result, teamsListItemsListResponse.ResultInfo, nil + var teamListItems []TeamsListItem + var lResponse TeamsListItemsListResponse + for { + uri := buildURI( + fmt.Sprintf("/%s/%s/gateway/lists/%s/items", rc.Level, rc.Identifier, params.ListID), + params, + ) + + res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) + if err != nil { + return []TeamsListItem{}, ResultInfo{}, err + } + + err = json.Unmarshal(res, &lResponse) + if err != nil { + return []TeamsListItem{}, ResultInfo{}, fmt.Errorf("failed to unmarshal teams list JSON data: %w", err) + } + + teamListItems = append(teamListItems, lResponse.Result...) + params.ResultInfo = lResponse.ResultInfo.Next() + + if params.ResultInfo.Done() || !autoPaginate { + break + } + } + + return teamListItems, lResponse.ResultInfo, nil } // CreateTeamsList creates a new teams list. // // API reference: https://api.cloudflare.com/#teams-lists-create-teams-list -func (api *API) CreateTeamsList(ctx context.Context, accountID string, teamsList TeamsList) (TeamsList, error) { - uri := fmt.Sprintf("/%s/%s/gateway/lists", AccountRouteRoot, accountID) +func (api *API) CreateTeamsList(ctx context.Context, rc *ResourceContainer, params CreateTeamsListParams) (TeamsList, error) { + if rc.Level != AccountRouteLevel { + return TeamsList{}, fmt.Errorf(errInvalidResourceContainerAccess, rc.Level) + } + + if rc.Identifier == "" { + return TeamsList{}, ErrMissingAccountID + } + + uri := fmt.Sprintf("/%s/%s/gateway/lists", rc.Level, rc.Identifier) - res, err := api.makeRequestContext(ctx, http.MethodPost, uri, teamsList) + res, err := api.makeRequestContext(ctx, http.MethodPost, uri, params) if err != nil { return TeamsList{}, err } @@ -166,19 +230,27 @@ func (api *API) CreateTeamsList(ctx context.Context, accountID string, teamsList // UpdateTeamsList updates an existing teams list. // // API reference: https://api.cloudflare.com/#teams-lists-update-teams-list -func (api *API) UpdateTeamsList(ctx context.Context, accountID string, teamsList TeamsList) (TeamsList, error) { - if teamsList.ID == "" { +func (api *API) UpdateTeamsList(ctx context.Context, rc *ResourceContainer, params UpdateTeamsListParams) (TeamsList, error) { + if rc.Level != AccountRouteLevel { + return TeamsList{}, fmt.Errorf(errInvalidResourceContainerAccess, rc.Level) + } + + if rc.Identifier == "" { + return TeamsList{}, ErrMissingAccountID + } + + if params.ID == "" { return TeamsList{}, fmt.Errorf("teams list ID cannot be empty") } uri := fmt.Sprintf( "/%s/%s/gateway/lists/%s", - AccountRouteRoot, - accountID, - teamsList.ID, + rc.Level, + rc.Identifier, + params.ID, ) - res, err := api.makeRequestContext(ctx, http.MethodPut, uri, teamsList) + res, err := api.makeRequestContext(ctx, http.MethodPut, uri, params) if err != nil { return TeamsList{}, err } @@ -195,7 +267,15 @@ func (api *API) UpdateTeamsList(ctx context.Context, accountID string, teamsList // PatchTeamsList updates the items in an existing teams list. // // API reference: https://api.cloudflare.com/#teams-lists-patch-teams-list -func (api *API) PatchTeamsList(ctx context.Context, accountID string, listPatch PatchTeamsList) (TeamsList, error) { +func (api *API) PatchTeamsList(ctx context.Context, rc *ResourceContainer, listPatch PatchTeamsListParams) (TeamsList, error) { + if rc.Level != AccountRouteLevel { + return TeamsList{}, fmt.Errorf(errInvalidResourceContainerAccess, rc.Level) + } + + if rc.Identifier == "" { + return TeamsList{}, ErrMissingAccountID + } + if listPatch.ID == "" { return TeamsList{}, fmt.Errorf("teams list ID cannot be empty") } @@ -203,7 +283,7 @@ func (api *API) PatchTeamsList(ctx context.Context, accountID string, listPatch uri := fmt.Sprintf( "/%s/%s/gateway/lists/%s", AccountRouteRoot, - accountID, + rc.Identifier, listPatch.ID, ) @@ -224,11 +304,19 @@ func (api *API) PatchTeamsList(ctx context.Context, accountID string, listPatch // DeleteTeamsList deletes a teams list. // // API reference: https://api.cloudflare.com/#teams-lists-delete-teams-list -func (api *API) DeleteTeamsList(ctx context.Context, accountID, teamsListID string) error { +func (api *API) DeleteTeamsList(ctx context.Context, rc *ResourceContainer, teamsListID string) error { + if rc.Level != AccountRouteLevel { + return fmt.Errorf(errInvalidResourceContainerAccess, rc.Level) + } + + if rc.Identifier == "" { + return ErrMissingAccountID + } + uri := fmt.Sprintf( "/%s/%s/gateway/lists/%s", AccountRouteRoot, - accountID, + rc.Identifier, teamsListID, ) diff --git a/teams_list_test.go b/teams_list_test.go index 0129fd7d1..f9d991a00 100644 --- a/teams_list_test.go +++ b/teams_list_test.go @@ -36,7 +36,8 @@ func TestTeamsLists(t *testing.T) { "page": 1, "per_page": 20, "count": 1, - "total_count": 2000 + "total_count": 2000, + "total_pages": 1 } } `) @@ -57,7 +58,7 @@ func TestTeamsLists(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/gateway/lists", handler) - actual, _, err := client.TeamsLists(context.Background(), testAccountID) + actual, _, err := client.ListTeamsLists(context.Background(), AccountIdentifier(testAccountID), ListTeamListsParams{}) if assert.NoError(t, err) { assert.Equal(t, want, actual) @@ -83,6 +84,13 @@ func TestTeamsList(t *testing.T) { "count": 1, "created_at": "2014-01-01T05:20:00.12345Z", "updated_at": "2014-01-01T05:20:00.12345Z" + }, + "result_info": { + "page": 1, + "per_page": 20, + "count": 1, + "total_count": 2000, + "total_pages": 1 } } `) @@ -103,7 +111,7 @@ func TestTeamsList(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/gateway/lists/480f4f69-1a28-4fdd-9240-1ed29f0ac1db", handler) - actual, err := client.TeamsList(context.Background(), testAccountID, "480f4f69-1a28-4fdd-9240-1ed29f0ac1db") + actual, err := client.GetTeamsList(context.Background(), AccountIdentifier(testAccountID), "480f4f69-1a28-4fdd-9240-1ed29f0ac1db") if assert.NoError(t, err) { assert.Equal(t, want, actual) @@ -130,7 +138,14 @@ func TestTeamsListItems(t *testing.T) { "value": "val2", "created_at": "2014-01-01T05:20:00.12345Z" } - ] + ], + "result_info": { + "page": 1, + "per_page": 20, + "count": 1, + "total_count": 2000, + "total_pages": 1 + } } `) } @@ -150,7 +165,7 @@ func TestTeamsListItems(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/gateway/lists/480f4f69-1a28-4fdd-9240-1ed29f0ac1db/items", handler) - actual, _, err := client.TeamsListItems(context.Background(), TeamsListItemsParams{AccountID: testAccountID, ListID: "480f4f69-1a28-4fdd-9240-1ed29f0ac1db"}) + actual, _, err := client.ListTeamsListItems(context.Background(), AccountIdentifier(testAccountID), ListTeamsListItemsParams{ListID: "480f4f69-1a28-4fdd-9240-1ed29f0ac1db"}) if assert.NoError(t, err) { assert.Equal(t, want, actual) } @@ -194,7 +209,7 @@ func TestCreateTeamsList(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/gateway/lists", handler) - actual, err := client.CreateTeamsList(context.Background(), testAccountID, TeamsList{ + actual, err := client.CreateTeamsList(context.Background(), AccountIdentifier(testAccountID), CreateTeamsListParams{ Name: "My Serial List", Description: "My Description", Type: "SERIAL", @@ -244,7 +259,15 @@ func TestUpdateTeamsList(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/gateway/lists/480f4f69-1a28-4fdd-9240-1ed29f0ac1db", handler) - actual, err := client.UpdateTeamsList(context.Background(), testAccountID, teamsList) + actual, err := client.UpdateTeamsList(context.Background(), AccountIdentifier(testAccountID), UpdateTeamsListParams{ + ID: "480f4f69-1a28-4fdd-9240-1ed29f0ac1db", + Name: "My Serial List", + Description: "My Updated Description", + Type: "SERIAL", + Count: 1, + CreatedAt: &createdAt, + UpdatedAt: &updatedAt, + }) if assert.NoError(t, err) { assert.Equal(t, teamsList, actual) @@ -255,7 +278,7 @@ func TestUpdateTeamsListWithMissingID(t *testing.T) { setup() defer teardown() - _, err := client.UpdateTeamsList(context.Background(), testZoneID, TeamsList{}) + _, err := client.UpdateTeamsList(context.Background(), AccountIdentifier(testAccountID), UpdateTeamsListParams{}) assert.EqualError(t, err, "teams list ID cannot be empty") } @@ -297,7 +320,7 @@ func TestPatchTeamsList(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/gateway/lists/480f4f69-1a28-4fdd-9240-1ed29f0ac1db", handler) - actual, err := client.PatchTeamsList(context.Background(), testAccountID, PatchTeamsList{ + actual, err := client.PatchTeamsList(context.Background(), AccountIdentifier(testAccountID), PatchTeamsListParams{ ID: "480f4f69-1a28-4fdd-9240-1ed29f0ac1db", Append: []TeamsListItem{{Value: "abcd-1234"}}, Remove: []string{"def-5678"}, @@ -327,7 +350,7 @@ func TestDeleteTeamsList(t *testing.T) { } mux.HandleFunc("/accounts/"+testAccountID+"/gateway/lists/480f4f69-1a28-4fdd-9240-1ed29f0ac1db", handler) - err := client.DeleteTeamsList(context.Background(), testAccountID, "480f4f69-1a28-4fdd-9240-1ed29f0ac1db") + err := client.DeleteTeamsList(context.Background(), AccountIdentifier(testAccountID), "480f4f69-1a28-4fdd-9240-1ed29f0ac1db") assert.NoError(t, err) }