diff --git a/.changelog/1276.txt b/.changelog/1276.txt new file mode 100644 index 0000000000..713898c8db --- /dev/null +++ b/.changelog/1276.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +waiting_room: add support for zone-level settings +``` diff --git a/waiting_room.go b/waiting_room.go index a60b5028e3..737e49dc49 100644 --- a/waiting_room.go +++ b/waiting_room.go @@ -76,6 +76,12 @@ type WaitingRoomRule struct { Enabled *bool `json:"enabled"` } +// WaitingRoomSettings describes zone-level waiting room settings. +type WaitingRoomSettings struct { + // Whether to allow verified search engine crawlers to bypass all waiting rooms on this zone + SearchEngineCrawlerBypass bool `json:"search_engine_crawler_bypass"` +} + // WaitingRoomPagePreviewURL describes a WaitingRoomPagePreviewURL object. type WaitingRoomPagePreviewURL struct { PreviewURL string `json:"preview_url"` @@ -98,6 +104,12 @@ type WaitingRoomsResponse struct { Result []WaitingRoom `json:"result"` } +// WaitingRoomSettingsResponse is the API response, containing zone-level Waiting Room settings. +type WaitingRoomSettingsResponse struct { + Response + Result WaitingRoomSettings `json:"result"` +} + // WaitingRoomStatusResponse is the API response, containing the status of a waiting room. type WaitingRoomStatusResponse struct { Response @@ -532,3 +544,76 @@ func (api *API) DeleteWaitingRoomRule(ctx context.Context, rc *ResourceContainer return r.Result, nil } + +// GetWaitingRoomSettings fetches the Waiting Room zone-level settings for a zone. +// +// API reference: https://api.cloudflare.com/#waiting-room-get-zone-settings +func (api *API) GetWaitingRoomSettings(ctx context.Context, rc *ResourceContainer) (WaitingRoomSettings, error) { + if rc.Level != ZoneRouteLevel { + return WaitingRoomSettings{}, fmt.Errorf(errInvalidResourceContainerAccess, rc.Level) + } + + uri := fmt.Sprintf("/zones/%s/waiting_rooms/settings", rc.Identifier) + res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) + if err != nil { + return WaitingRoomSettings{}, err + } + var r WaitingRoomSettingsResponse + err = json.Unmarshal(res, &r) + if err != nil { + return WaitingRoomSettings{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + } + return r.Result, nil +} + +type PatchWaitingRoomSettingsParams struct { + SearchEngineCrawlerBypass *bool `json:"search_engine_crawler_bypass,omitempty"` +} + +// PatchWaitingRoomSettings lets you change individual zone-level Waiting Room settings. This is +// in contrast to UpdateWaitingRoomSettings which replaces all settings. +// +// API reference: https://api.cloudflare.com/#waiting-room-patch-zone-settings +func (api *API) PatchWaitingRoomSettings(ctx context.Context, rc *ResourceContainer, params PatchWaitingRoomSettingsParams) (WaitingRoomSettings, error) { + if rc.Level != ZoneRouteLevel { + return WaitingRoomSettings{}, fmt.Errorf(errInvalidResourceContainerAccess, rc.Level) + } + + uri := fmt.Sprintf("/zones/%s/waiting_rooms/settings", rc.Identifier) + res, err := api.makeRequestContext(ctx, http.MethodPatch, uri, params) + if err != nil { + return WaitingRoomSettings{}, err + } + var r WaitingRoomSettingsResponse + err = json.Unmarshal(res, &r) + if err != nil { + return WaitingRoomSettings{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + } + return r.Result, nil +} + +type UpdateWaitingRoomSettingsParams struct { + SearchEngineCrawlerBypass *bool `json:"search_engine_crawler_bypass,omitempty"` +} + +// UpdateWaitingRoomSettings lets you replace all zone-level Waiting Room settings. This is in contrast to +// PatchWaitingRoomSettings which lets you change individual settings. +// +// API reference: https://api.cloudflare.com/#waiting-room-update-zone-settings +func (api *API) UpdateWaitingRoomSettings(ctx context.Context, rc *ResourceContainer, params UpdateWaitingRoomSettingsParams) (WaitingRoomSettings, error) { + if rc.Level != ZoneRouteLevel { + return WaitingRoomSettings{}, fmt.Errorf(errInvalidResourceContainerAccess, rc.Level) + } + + uri := fmt.Sprintf("/zones/%s/waiting_rooms/settings", rc.Identifier) + res, err := api.makeRequestContext(ctx, http.MethodPut, uri, params) + if err != nil { + return WaitingRoomSettings{}, err + } + var r WaitingRoomSettingsResponse + err = json.Unmarshal(res, &r) + if err != nil { + return WaitingRoomSettings{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + } + return r.Result, nil +} diff --git a/waiting_room_test.go b/waiting_room_test.go index 902510305d..057789906b 100644 --- a/waiting_room_test.go +++ b/waiting_room_test.go @@ -97,6 +97,12 @@ var waitingRoomPagePreviewJSON = ` } ` +var waitingRoomSettingsJSON = ` + { + "search_engine_crawler_bypass": true + } + ` + var waitingRoom = WaitingRoom{ ID: waitingRoomID, CreatedOn: testTimestampWaitingRoom, @@ -160,6 +166,18 @@ var waitingRoomRule = WaitingRoomRule{ LastUpdated: &testTimestampWaitingRoom, } +var waitingRoomSettings = WaitingRoomSettings{ + SearchEngineCrawlerBypass: true, +} + +var waitingRoomSettingsUpdate = UpdateWaitingRoomSettingsParams{ + SearchEngineCrawlerBypass: BoolPtr(true), +} + +var waitingRoomSettingsPatch = PatchWaitingRoomSettingsParams{ + SearchEngineCrawlerBypass: BoolPtr(true), +} + func TestListWaitingRooms(t *testing.T) { setup() defer teardown() @@ -785,3 +803,78 @@ func TestReplaceWaitingRoomRules(t *testing.T) { assert.Equal(t, want, actual) } } + +func TestWaitingRoomSettings(t *testing.T) { + setup() + defer teardown() + + handler := func(w http.ResponseWriter, r *http.Request) { + assert.Equal(t, http.MethodGet, r.Method, "Expected method 'GET', got %s", r.Method) + w.Header().Set("content-type", "application/json") + fmt.Fprintf(w, `{ + "success": true, + "errors": [], + "messages": [], + "result": %s + } + `, waitingRoomSettingsJSON) + } + + mux.HandleFunc("/zones/"+testZoneID+"/waiting_rooms/settings", handler) + want := waitingRoomSettings + + actual, err := client.GetWaitingRoomSettings(context.Background(), ZoneIdentifier(testZoneID)) + if assert.NoError(t, err) { + assert.Equal(t, want, actual) + } +} + +func TestUpdateWaitingRoomSettings(t *testing.T) { + setup() + defer teardown() + + handler := func(w http.ResponseWriter, r *http.Request) { + assert.Equal(t, http.MethodPut, r.Method, "Expected method 'PUT', got %s", r.Method) + w.Header().Set("content-type", "application/json") + fmt.Fprintf(w, `{ + "success": true, + "errors": [], + "messages": [], + "result": %s + } + `, waitingRoomSettingsJSON) + } + + mux.HandleFunc("/zones/"+testZoneID+"/waiting_rooms/settings", handler) + want := waitingRoomSettings + + actual, err := client.UpdateWaitingRoomSettings(context.Background(), ZoneIdentifier(testZoneID), waitingRoomSettingsUpdate) + if assert.NoError(t, err) { + assert.Equal(t, want, actual) + } +} + +func TestChangeWaitingRoomSettings(t *testing.T) { + setup() + defer teardown() + + handler := func(w http.ResponseWriter, r *http.Request) { + assert.Equal(t, http.MethodPatch, r.Method, "Expected method 'PATCH', got %s", r.Method) + w.Header().Set("content-type", "application/json") + fmt.Fprintf(w, `{ + "success": true, + "errors": [], + "messages": [], + "result": %s + } + `, waitingRoomSettingsJSON) + } + + mux.HandleFunc("/zones/"+testZoneID+"/waiting_rooms/settings", handler) + want := waitingRoomSettings + + actual, err := client.PatchWaitingRoomSettings(context.Background(), ZoneIdentifier(testZoneID), waitingRoomSettingsPatch) + if assert.NoError(t, err) { + assert.Equal(t, want, actual) + } +}