Skip to content

Commit

Permalink
Add support for Bot Management
Browse files Browse the repository at this point in the history
  • Loading branch information
Curtis Lowder committed Aug 7, 2023
1 parent 46a5efb commit c6c1b4f
Show file tree
Hide file tree
Showing 3 changed files with 181 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .changelog/1363.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:enhancement
bot_management: add support for bot_management API
```
90 changes: 90 additions & 0 deletions bot_management.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package cloudflare

import (
"context"
"encoding/json"
"fmt"
"net/http"
)

// BotManagement represents the bots config for a zone

Check failure on line 10 in bot_management.go

View workflow job for this annotation

GitHub Actions / lint

Comment should end in a period (godot)
type BotManagement struct {
EnableJS *bool `json:"enable_js,omitempty"`
FightMode *bool `json:"fight_mode,omitempty"`
SBFMDefinitelyAutomated *string `json:"sbfm_definitely_automated,omitempty"`
SBFMLikelyAutomated *string `json:"sbfm_likely_automated,omitempty"`
SBFMVerifiedBots *string `json:"sbfm_verified_bots,omitempty"`
SBFMStaticResourceProtection *bool `json:"sbfm_static_resource_protection,omitempty"`
OptimizeWordpress *bool `json:"optimize_wordpress,omitempty"`
SuppressSessionScore *bool `json:"suppress_session_score,omitempty"`
AutoUpdateModel *bool `json:"auto_update_model,omitempty"`
UsingLatestModel *bool `json:"using_latest_model,omitempty"`
}

// BotManagementResponse represents the response from the bot_management endpoint.
type BotManagementResponse struct {
Result BotManagement `json:"result"`
Response
}

type UpdateBotManagementParams struct {
EnableJS *bool `json:"enable_js,omitempty"`
FightMode *bool `json:"fight_mode,omitempty"`
SBFMDefinitelyAutomated *string `json:"sbfm_definitely_automated,omitempty"`
SBFMLikelyAutomated *string `json:"sbfm_likely_automated,omitempty"`
SBFMVerifiedBots *string `json:"sbfm_verified_bots,omitempty"`
SBFMStaticResourceProtection *bool `json:"sbfm_static_resource_protection,omitempty"`
OptimizeWordpress *bool `json:"optimize_wordpress,omitempty"`
SuppressSessionScore *bool `json:"suppress_session_score,omitempty"`
AutoUpdateModel *bool `json:"auto_update_model,omitempty"`
}

// GetBotManagement gets a zone API shield configuration.
//
// API documentation: https://developers.cloudflare.com/api/operations/bot-management-for-a-zone-get-config
func (api *API) GetBotManagement(ctx context.Context, rc *ResourceContainer) (BotManagement, error) {
uri := fmt.Sprintf("/zones/%s/bot_management", rc.Identifier)

res, err := api.makeRequestContextWithHeaders(ctx, http.MethodGet, uri, nil, botV2Header())
if err != nil {
return BotManagement{}, err
}
var bmResponse BotManagementResponse
err = json.Unmarshal(res, &bmResponse)
if err != nil {
return BotManagement{}, fmt.Errorf("%s: %w", errUnmarshalError, err)
}

return bmResponse.Result, nil
}

// UpdateBotManagement sets a zone API shield configuration.
//
// API documentation: https://developers.cloudflare.com/api/operations/bot-management-for-a-zone-update-config
func (api *API) UpdateBotManagement(ctx context.Context, rc *ResourceContainer, params UpdateBotManagementParams) (BotManagement, error) {
uri := fmt.Sprintf("/zones/%s/bot_management", rc.Identifier)

res, err := api.makeRequestContextWithHeaders(ctx, http.MethodPut, uri, params, botV2Header())
if err != nil {
return BotManagement{}, err
}

var bmResponse BotManagementResponse
err = json.Unmarshal(res, &bmResponse)
if err != nil {
return BotManagement{}, fmt.Errorf("%s: %w", errUnmarshalError, err)
}

return bmResponse.Result, nil
}

// We are currently undergoing the process of updating the bot management API.
// The older 1.0.0 version of the is still the default version, so we will need
// to explicitly set this special header on all requests. We will eventually
// make 2.0.0 the default version, and later we will remove the 1.0.0 entirely.
func botV2Header() http.Header {
header := make(http.Header)
header.Set("Cloudflare-Version", "2.0.0")

return header
}
88 changes: 88 additions & 0 deletions bot_management_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package cloudflare

import (
"context"
"fmt"
"net/http"
"testing"

"github.com/stretchr/testify/assert"
)

func TestGetBotManagement(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)
assert.Equal(t, "2.0.0", r.Header.Get("Cloudflare-Version"))
w.Header().Set("content-type", "application/json")
fmt.Fprintf(w, `{
"success" : true,
"errors": [],
"messages": [],
"result": {
"enable_js": false,
"fight_mode": true,
"using_latest_model": true
}
}
`)
}

mux.HandleFunc("/zones/"+testZoneID+"/bot_management", handler)

want := BotManagement{
EnableJS: BoolPtr(false),
FightMode: BoolPtr(true),
UsingLatestModel: BoolPtr(true),
}

actual, err := client.GetBotManagement(context.Background(), ZoneIdentifier(testZoneID))

if assert.NoError(t, err) {
assert.Equal(t, want, actual)
}
}

func TestPutBotManagement(t *testing.T) {
setup()
defer teardown()

// now lets do a PUT
handler := func(w http.ResponseWriter, r *http.Request) {
assert.Equal(t, http.MethodPut, r.Method, "Expected method 'PUT', got %s", r.Method)
assert.Equal(t, "2.0.0", r.Header.Get("Cloudflare-Version"))
w.Header().Set("content-type", "application/json")
fmt.Fprintf(w, `{
"success" : true,
"errors": [],
"messages": [],
"result": {
"enable_js": false,
"fight_mode": true,
"using_latest_model": true
}
}
`)
}

mux.HandleFunc("/zones/"+testZoneID+"/bot_management", handler)

bmData := UpdateBotManagementParams{
EnableJS: BoolPtr(false),
FightMode: BoolPtr(true),
}

want := BotManagement{
EnableJS: BoolPtr(false),
FightMode: BoolPtr(true),
UsingLatestModel: BoolPtr(true),
}

actual, err := client.UpdateBotManagement(context.Background(), ZoneIdentifier(testZoneID), bmData)

if assert.NoError(t, err) {
assert.Equal(t, want, actual)
}
}

0 comments on commit c6c1b4f

Please sign in to comment.