Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement DELETE /tokens (bulk token deletion) API #302

Merged
merged 1 commit into from
Sep 15, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions fastly/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,10 @@ var ErrMissingYear = NewFieldError("Year")
// struct requires either a "Name" or "Comment" key, but one was not set.
var ErrMissingOptionalNameComment = NewFieldError("Name, Comment").Message("at least one of the available 'optional' fields is required")

// ErrMissingTokensValue is an error that is returned when an input struct
// requires a "Tokens" key, but there needs to be at least one token entry.
var ErrMissingTokensValue = NewFieldError("Tokens").Message("expect at least one token")

// ErrStatusNotOk is an error that indicates the response body returned by the
// Fastly API was not `{"status": "ok"}`
var ErrStatusNotOk = errors.New("unexpected 'status' field in API response body")
Expand Down
254 changes: 254 additions & 0 deletions fastly/fixtures/tokens/create_and_bulk_delete.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,254 @@
---
version: 1
interactions:
- request:
body: name=my-test-token-1&password=foobar&scope=global&username=testing%40fastly.com
form:
name:
- my-test-token-1
password:
- foobar
scope:
- global
username:
- testing@fastly.com
headers:
Content-Type:
- application/x-www-form-urlencoded
User-Agent:
- FastlyGo/3.11.0 (+github.com/fastly/go-fastly; go1.17)
url: https://api.fastly.com/sudo
method: POST
response:
body: '{"expiry_time":"2021-09-15T16:15:56+00:00"}'
headers:
Accept-Ranges:
- bytes
Cache-Control:
- no-store
Content-Type:
- application/json
Date:
- Wed, 15 Sep 2021 16:10:56 GMT
Fastly-Ratelimit-Remaining:
- "4999"
Fastly-Ratelimit-Reset:
- "1631725200"
Status:
- 200 OK
Strict-Transport-Security:
- max-age=31536000
Vary:
- Accept-Encoding
Via:
- 1.1 varnish, 1.1 varnish
X-Cache:
- MISS, MISS
X-Cache-Hits:
- 0, 0
X-Served-By:
- cache-control-slwdc9035-CONTROL-SLWDC, cache-man4150-MAN
X-Timer:
- S1631722256.303142,VS0,VE306
status: 200 OK
code: 200
duration: ""
- request:
body: name=my-test-token-1&password=foobar&scope=global&username=testing%40fastly.com
form:
name:
- my-test-token-1
password:
- foobar
scope:
- global
username:
- testing@fastly.com
headers:
Content-Type:
- application/x-www-form-urlencoded
User-Agent:
- FastlyGo/3.11.0 (+github.com/fastly/go-fastly; go1.17)
url: https://api.fastly.com/tokens
method: POST
response:
body: '{"id":"67WnFZog4TztGgdNfc9mxX","name":"my-test-token-1","user_id":"52LiGaZmbWl4D5xv4tcxON","customer_id":"51MumwLiSJyFTWhtbByYgR","service_id":null,"expires_at":null,"created_at":"2021-09-15T16:10:56Z","updated_at":"2021-09-15T16:10:56Z","scope":"global","services":[],"access_token":"XXXXXXXXXXXXXXXXXXXXXX"}'
headers:
Accept-Ranges:
- bytes
Cache-Control:
- no-store
Content-Type:
- application/json
Date:
- Wed, 15 Sep 2021 16:10:56 GMT
Fastly-Ratelimit-Remaining:
- "4998"
Fastly-Ratelimit-Reset:
- "1631725200"
Status:
- 200 OK
Strict-Transport-Security:
- max-age=31536000
Vary:
- Accept-Encoding
Via:
- 1.1 varnish, 1.1 varnish
X-Cache:
- MISS, MISS
X-Cache-Hits:
- 0, 0
X-Served-By:
- cache-control-slwdc9037-CONTROL-SLWDC, cache-man4150-MAN
X-Timer:
- S1631722257.636563,VS0,VE348
status: 200 OK
code: 200
duration: ""
- request:
body: name=my-test-token-2&password=foobar&scope=global&username=testing%40fastly.com
form:
name:
- my-test-token-2
password:
- foobar
scope:
- global
username:
- testing@fastly.com
headers:
Content-Type:
- application/x-www-form-urlencoded
User-Agent:
- FastlyGo/3.11.0 (+github.com/fastly/go-fastly; go1.17)
url: https://api.fastly.com/sudo
method: POST
response:
body: '{"expiry_time":"2021-09-15T16:15:57+00:00"}'
headers:
Accept-Ranges:
- bytes
Cache-Control:
- no-store
Content-Type:
- application/json
Date:
- Wed, 15 Sep 2021 16:10:57 GMT
Fastly-Ratelimit-Remaining:
- "4997"
Fastly-Ratelimit-Reset:
- "1631725200"
Status:
- 200 OK
Strict-Transport-Security:
- max-age=31536000
Vary:
- Accept-Encoding
Via:
- 1.1 varnish, 1.1 varnish
X-Cache:
- MISS, MISS
X-Cache-Hits:
- 0, 0
X-Served-By:
- cache-control-slwdc9037-CONTROL-SLWDC, cache-man4150-MAN
X-Timer:
- S1631722257.011411,VS0,VE232
status: 200 OK
code: 200
duration: ""
- request:
body: name=my-test-token-2&password=foobar&scope=global&username=testing%40fastly.com
form:
name:
- my-test-token-2
password:
- foobar
scope:
- global
username:
- testing@fastly.com
headers:
Content-Type:
- application/x-www-form-urlencoded
User-Agent:
- FastlyGo/3.11.0 (+github.com/fastly/go-fastly; go1.17)
url: https://api.fastly.com/tokens
method: POST
response:
body: '{"id":"XzkxSPqcUJmf522PeZ1tb","name":"my-test-token-2","user_id":"52LiGaZmbWl4D5xv4tcxON","customer_id":"51MumwLiSJyFTWhtbByYgR","service_id":null,"expires_at":null,"created_at":"2021-09-15T16:10:57Z","updated_at":"2021-09-15T16:10:57Z","scope":"global","services":[],"access_token":"XXXXXXXXXXXXXXXXXXXXXX"}'
headers:
Accept-Ranges:
- bytes
Cache-Control:
- no-store
Content-Type:
- application/json
Date:
- Wed, 15 Sep 2021 16:10:57 GMT
Fastly-Ratelimit-Remaining:
- "4996"
Fastly-Ratelimit-Reset:
- "1631725200"
Status:
- 200 OK
Strict-Transport-Security:
- max-age=31536000
Vary:
- Accept-Encoding
Via:
- 1.1 varnish, 1.1 varnish
X-Cache:
- MISS, MISS
X-Cache-Hits:
- 0, 0
X-Served-By:
- cache-control-slwdc9036-CONTROL-SLWDC, cache-man4150-MAN
X-Timer:
- S1631722257.275500,VS0,VE167
status: 200 OK
code: 200
duration: ""
- request:
body: |
{"data":[{"type":"token","id":"67WnFZog4TztGgdNfc9mxX"},{"type":"token","id":"XzkxSPqcUJmf522PeZ1tb"}]}
form: {}
headers:
Accept:
- application/vnd.api+json; ext=bulk
Content-Type:
- application/vnd.api+json; ext=bulk
User-Agent:
- FastlyGo/3.11.0 (+github.com/fastly/go-fastly; go1.17)
url: https://api.fastly.com/tokens
method: DELETE
response:
body: ""
headers:
Accept-Ranges:
- bytes
Cache-Control:
- no-store
Date:
- Wed, 15 Sep 2021 16:10:57 GMT
Fastly-Ratelimit-Remaining:
- "4995"
Fastly-Ratelimit-Reset:
- "1631725200"
Status:
- 204 No Content
Strict-Transport-Security:
- max-age=31536000
Via:
- 1.1 varnish, 1.1 varnish
X-Cache:
- MISS, MISS
X-Cache-Hits:
- 0, 0
X-Served-By:
- cache-control-slwdc9035-CONTROL-SLWDC, cache-man4150-MAN
X-Timer:
- S1631722257.462874,VS0,VE199
status: 204 No Content
code: 204
duration: ""
20 changes: 20 additions & 0 deletions fastly/token.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,3 +169,23 @@ func (c *Client) DeleteTokenSelf() error {
}
return nil
}

// BatchDeleteTokensInput is used as input to BatchDeleteTokens.
type BatchDeleteTokensInput struct {
Tokens []*BatchToken
}

// BatchToken represents the JSONAPI data to be sent to the API.
// Reference: https://github.com/google/jsonapi#primary
type BatchToken struct {
ID string `jsonapi:"primary,token,omitempty"`
}

// BatchDeleteTokens revokes multiple tokens.
func (c *Client) BatchDeleteTokens(i *BatchDeleteTokensInput) error {
if len(i.Tokens) == 0 {
return ErrMissingTokensValue
}
_, err := c.DeleteJSONAPIBulk("/tokens", i.Tokens, nil)
return err
}
39 changes: 39 additions & 0 deletions fastly/token_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,3 +105,42 @@ func TestClient_DeleteTokenSelf(t *testing.T) {
t.Fatal(err)
}
}

func TestClient_CreateAndBulkDeleteTokens(t *testing.T) {
t.Parallel()

var deleteErr error

record(t, "tokens/create_and_bulk_delete", func(c *Client) {
token1, err := c.CreateToken(&CreateTokenInput{
Name: "my-test-token-1",
Scope: "global",
Username: "testing@fastly.com",
Password: "foobar",
})
if err != nil {
t.Fatal(err)
}

token2, err := c.CreateToken(&CreateTokenInput{
Name: "my-test-token-2",
Scope: "global",
Username: "testing@fastly.com",
Password: "foobar",
})
if err != nil {
t.Fatal(err)
}

deleteErr = c.BatchDeleteTokens(&BatchDeleteTokensInput{
Tokens: []*BatchToken{
{ID: token1.ID},
{ID: token2.ID},
},
})
})

if deleteErr != nil {
t.Fatal(deleteErr)
}
}