Skip to content

Commit

Permalink
Merge branch 'master' into aberglund-cf/PA-2107-add_support_for_regio…
Browse files Browse the repository at this point in the history
…nal_hostnames
  • Loading branch information
jacobbednarz committed Apr 19, 2023
2 parents dbc5802 + 9c4dbb4 commit 5d81262
Show file tree
Hide file tree
Showing 10 changed files with 609 additions and 3 deletions.
3 changes: 3 additions & 0 deletions .changelog/1223.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:enhancement
access_application: Add `path_cookie_attribute` app setting
```
3 changes: 3 additions & 0 deletions .changelog/1267.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:enhancement
turnstile: add support for turnstile
```
3 changes: 3 additions & 0 deletions .changelog/1269.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:dependency
deps: bumps dependabot/fetch-metadata from 1.3.6 to 1.4.0
```
2 changes: 1 addition & 1 deletion .github/workflows/dependabot-changelog.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
steps:
- name: Fetch dependabot metadata
id: dependabot-metadata
uses: dependabot/fetch-metadata@v1.3.6
uses: dependabot/fetch-metadata@v1.4.0
- uses: actions/checkout@v3
- run: |
gh pr checkout $PR_URL
Expand Down
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,13 @@

ENHANCEMENTS:

* access_application: Add `path_cookie_attribute` app setting ([#1223](https://github.com/cloudflare/cloudflare-go/issues/1223))
* dns: add support for importing and exporting DNS records using BIND file configurations ([#1266](https://github.com/cloudflare/cloudflare-go/issues/1266))
* turnstile: add support for turnstile ([#1267](https://github.com/cloudflare/cloudflare-go/issues/1267))

DEPENDENCIES:

* deps: bumps dependabot/fetch-metadata from 1.3.6 to 1.4.0 ([#1269](https://github.com/cloudflare/cloudflare-go/issues/1269))

## 0.65.0 (12th April, 2023)

Expand Down
1 change: 1 addition & 0 deletions access_application.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ type AccessApplication struct {
EnableBindingCookie *bool `json:"enable_binding_cookie,omitempty"`
HttpOnlyCookieAttribute *bool `json:"http_only_cookie_attribute,omitempty"`
ServiceAuth401Redirect *bool `json:"service_auth_401_redirect,omitempty"`
PathCookieAttribute *bool `json:"path_cookie_attribute,omitempty"`
}

type AccessApplicationGatewayRule struct {
Expand Down
8 changes: 6 additions & 2 deletions access_application_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ func TestAccessApplications(t *testing.T) {
"logo_url": "https://www.example.com/example.png",
"skip_interstitial": true,
"app_launcher_visible": true,
"service_auth_401_redirect": true
"service_auth_401_redirect": true,
"path_cookie_attribute": true
}
],
"result_info": {
Expand Down Expand Up @@ -77,6 +78,7 @@ func TestAccessApplications(t *testing.T) {
HttpOnlyCookieAttribute: BoolPtr(true),
LogoURL: "https://www.example.com/example.png",
SkipInterstitial: BoolPtr(true),
PathCookieAttribute: BoolPtr(true),
}}

mux.HandleFunc("/accounts/"+testAccountID+"/access/apps", handler)
Expand Down Expand Up @@ -125,7 +127,8 @@ func TestAccessApplication(t *testing.T) {
"skip_interstitial": true,
"app_launcher_visible": true,
"service_auth_401_redirect": true,
"http_only_cookie_attribute": false
"http_only_cookie_attribute": false,
"path_cookie_attribute": false
}
}
`)
Expand Down Expand Up @@ -153,6 +156,7 @@ func TestAccessApplication(t *testing.T) {
LogoURL: "https://www.example.com/example.png",
SkipInterstitial: BoolPtr(true),
HttpOnlyCookieAttribute: BoolPtr(false),
PathCookieAttribute: BoolPtr(false),
}

mux.HandleFunc("/accounts/"+testAccountID+"/access/apps/480f4f69-1a28-4fdd-9240-1ed29f0ac1db", handler)
Expand Down
7 changes: 7 additions & 0 deletions cloudflare.go
Original file line number Diff line number Diff line change
Expand Up @@ -596,3 +596,10 @@ func checkResultInfo(perPage, page, count int, info *ResultInfo) bool {
panic("checkResultInfo: impossible")
}
}

type OrderDirection string

const (
OrderDirectionAsc OrderDirection = "asc"
OrderDirectionDesc OrderDirection = "desc"
)
245 changes: 245 additions & 0 deletions turnstile.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,245 @@
package cloudflare

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

var ErrMissingSiteKey = errors.New("required site key missing")

type TurnstileWidget struct {
SiteKey string `json:"sitekey,omitempty"`
Secret string `json:"secret,omitempty"`
CreatedOn *time.Time `json:"created_on,omitempty"`
ModifiedOn *time.Time `json:"modified_on,omitempty"`
Name string `json:"name,omitempty"`
Domains []string `json:"domains,omitempty"`
Mode string `json:"mode,omitempty"`
BotFightMode bool `json:"bot_fight_mode,omitempty"`
Region string `json:"region,omitempty"`
OffLabel bool `json:"offlabel,omitempty"`
}

type CreateTurnstileWidgetParams struct {
Name string `json:"name,omitempty"`
Domains []string `json:"domains,omitempty"`
Mode string `json:"mode,omitempty"`
BotFightMode bool `json:"bot_fight_mode,omitempty"`
Region string `json:"region,omitempty"`
OffLabel bool `json:"offlabel,omitempty"`
}

type UpdateTurnstileWidgetParams struct {
SiteKey string `json:"sitekey,omitempty"`
Secret string `json:"secret,omitempty"`
Name string `json:"name,omitempty"`
Domains []string `json:"domains,omitempty"`
Mode string `json:"mode,omitempty"`
BotFightMode bool `json:"bot_fight_mode,omitempty"`
Region string `json:"region,omitempty"`
OffLabel bool `json:"offlabel,omitempty"`
}

type TurnstileWidgetResponse struct {
Response
Result TurnstileWidget `json:"result"`
}

type ListTurnstileWidgetParams struct {
ResultInfo
Direction string `url:"direction,omitempty"`
Order OrderDirection `url:"order,omitempty"`
}

type ListTurnstileWidgetResponse struct {
Response
ResultInfo `json:"result_info"`
Result []TurnstileWidget `json:"result"`
}

type RotateTurnstileWidgetParams struct {
SiteKey string
InvalidateImmediately bool `json:"invalidate_immediately,omitempty"`
}

// CreateTurnstileWidget creates a new challenge widgets.
//
// API reference: https://api.cloudflare.com/#challenge-widgets-properties
func (api *API) CreateTurnstileWidget(ctx context.Context, rc *ResourceContainer, params CreateTurnstileWidgetParams) (TurnstileWidget, error) {
if rc.Identifier == "" {
return TurnstileWidget{}, ErrMissingAccountID
}

uri := fmt.Sprintf("/accounts/%s/challenges/widgets", rc.Identifier)
res, err := api.makeRequestContext(ctx, "POST", uri, params)
if err != nil {
return TurnstileWidget{}, fmt.Errorf("%s: %w", errMakeRequestError, err)
}

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

return r.Result, nil
}

// ListTurnstileWidgets lists challenge widgets.
//
// API reference: https://api.cloudflare.com/#challenge-widgets-list-challenge-widgets
func (api *API) ListTurnstileWidgets(ctx context.Context, rc *ResourceContainer, params ListTurnstileWidgetParams) ([]TurnstileWidget, *ResultInfo, error) {
if rc.Identifier == "" {
return []TurnstileWidget{}, &ResultInfo{}, ErrMissingAccountID
}
autoPaginate := true
if params.PerPage >= 1 || params.Page >= 1 {
autoPaginate = false
}

if params.PerPage < 1 {
params.PerPage = 25
}

if params.Page < 1 {
params.Page = 1
}

var widgets []TurnstileWidget
var r ListTurnstileWidgetResponse
for {
uri := buildURI(fmt.Sprintf("/accounts/%s/challenges/widgets", rc.Identifier), params)
res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil)

if err != nil {
return []TurnstileWidget{}, &ResultInfo{}, fmt.Errorf("%s: %w", errMakeRequestError, err)
}
err = json.Unmarshal(res, &r)
if err != nil {
return []TurnstileWidget{}, &ResultInfo{}, fmt.Errorf("%s: %w", errUnmarshalError, err)
}

widgets = append(widgets, r.Result...)
params.ResultInfo = r.ResultInfo.Next()
if params.ResultInfo.Done() || !autoPaginate {
break
}
}

return widgets, &r.ResultInfo, nil
}

// GetTurnstileWidget shows a single challenge widget configuration.
//
// API reference: https://api.cloudflare.com/#challenge-widgets-challenge-widget-details
func (api *API) GetTurnstileWidget(ctx context.Context, rc *ResourceContainer, siteKey string) (TurnstileWidget, error) {
if rc.Identifier == "" {
return TurnstileWidget{}, ErrMissingAccountID
}

if siteKey == "" {
return TurnstileWidget{}, ErrMissingSiteKey
}

uri := fmt.Sprintf("/accounts/%s/challenges/widgets/%s", rc.Identifier, siteKey)
res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil)
if err != nil {
return TurnstileWidget{}, fmt.Errorf("%s: %w", errMakeRequestError, err)
}

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

return r.Result, nil
}

// UpdateTurnstileWidget update the configuration of a widget.
//
// API reference: https://api.cloudflare.com/#challenge-widgets-update-a-challenge-widget
func (api *API) UpdateTurnstileWidget(ctx context.Context, rc *ResourceContainer, params UpdateTurnstileWidgetParams) (TurnstileWidget, error) {
if rc.Identifier == "" {
return TurnstileWidget{}, ErrMissingAccountID
}

if params.SiteKey == "" {
return TurnstileWidget{}, ErrMissingSiteKey
}

uri := fmt.Sprintf("/accounts/%s/challenges/widgets/%s", rc.Identifier, params.SiteKey)
res, err := api.makeRequestContext(ctx, http.MethodPut, uri, params)
if err != nil {
return TurnstileWidget{}, fmt.Errorf("%s: %w", errMakeRequestError, err)
}

var r TurnstileWidgetResponse
err = json.Unmarshal(res, &r)
if err != nil {
return TurnstileWidget{}, fmt.Errorf("%s: %w", errUnmarshalError, err)
}
return r.Result, nil
}

// RotateTurnstileWidget generates a new secret key for this widget. If
// invalidate_immediately is set to false, the previous secret remains valid for
// 2 hours.
//
// Note that secrets cannot be rotated again during the grace period.
//
// API reference: https://api.cloudflare.com/#challenge-widgets-rotate-secret-for-a-challenge-widget
func (api *API) RotateTurnstileWidget(ctx context.Context, rc *ResourceContainer, param RotateTurnstileWidgetParams) (TurnstileWidget, error) {
if rc.Identifier == "" {
return TurnstileWidget{}, ErrMissingAccountID
}
if param.SiteKey == "" {
return TurnstileWidget{}, ErrMissingSiteKey
}

uri := fmt.Sprintf("/accounts/%s/challenges/widgets/%s/rotate_secret", rc.Identifier, param.SiteKey)
res, err := api.makeRequestContext(ctx, http.MethodPost, uri, param)

if err != nil {
return TurnstileWidget{}, fmt.Errorf("%s: %w", errMakeRequestError, err)
}

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

return r.Result, nil
}

// DeleteTurnstileWidget delete a challenge widget.
//
// API reference: https://api.cloudflare.com/#challenge-widgets-delete-a-challenge-widget
func (api *API) DeleteTurnstileWidget(ctx context.Context, rc *ResourceContainer, siteKey string) error {
if rc.Identifier == "" {
return ErrMissingAccountID
}

if siteKey == "" {
return ErrMissingSiteKey
}
uri := fmt.Sprintf("/accounts/%s/challenges/widgets/%s", rc.Identifier, siteKey)

res, err := api.makeRequestContext(ctx, http.MethodDelete, uri, nil)
if err != nil {
return fmt.Errorf("%s: %w", errMakeRequestError, err)
}

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

return nil
}

0 comments on commit 5d81262

Please sign in to comment.