-
Notifications
You must be signed in to change notification settings - Fork 20
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: API operations for JWT Templates (#225)
Added support for the JWT Templates API with Create, Get, Update, Delete and List operations.
- Loading branch information
Showing
4 changed files
with
350 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
package clerk | ||
|
||
import "encoding/json" | ||
|
||
type JWTTemplate struct { | ||
APIResource | ||
Object string `json:"object"` | ||
ID string `json:"id"` | ||
Name string `json:"name"` | ||
Claims json.RawMessage `json:"claims"` | ||
Lifetime int64 `json:"lifetime"` | ||
AllowedClockSkew int64 `json:"allowed_clock_skew"` | ||
CustomSigningKey bool `json:"custom_signing_key"` | ||
SigningAlgorithm string `json:"signing_algorithm"` | ||
CreatedAt int64 `json:"created_at"` | ||
UpdatedAt int64 `json:"updated_at"` | ||
} | ||
|
||
type JWTTemplateList struct { | ||
APIResource | ||
JWTTemplates []*JWTTemplate `json:"data"` | ||
TotalCount int64 `json:"total_count"` | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
// Package jwttemplate provides the JWT Templates API. | ||
package jwttemplate | ||
|
||
import ( | ||
"context" | ||
"encoding/json" | ||
"fmt" | ||
"net/http" | ||
|
||
"github.com/clerk/clerk-sdk-go/v2" | ||
) | ||
|
||
//go:generate go run ../cmd/gen/main.go | ||
|
||
const path = "/jwt_templates" | ||
|
||
// Client is used to invoke the JWT Templates API. | ||
type Client struct { | ||
Backend clerk.Backend | ||
} | ||
|
||
type ClientConfig struct { | ||
clerk.BackendConfig | ||
} | ||
|
||
func NewClient(config *ClientConfig) *Client { | ||
return &Client{ | ||
Backend: clerk.NewBackend(&config.BackendConfig), | ||
} | ||
} | ||
|
||
type CreateParams struct { | ||
clerk.APIParams | ||
Name *string `json:"name,omitempty"` | ||
Claims json.RawMessage `json:"claims,omitempty"` | ||
Lifetime *int64 `json:"lifetime,omitempty"` | ||
AllowedClockSkew *int64 `json:"allowed_clock_skew,omitempty"` | ||
CustomSigningKey *bool `json:"custom_signing_key,omitempty"` | ||
SigningKey *string `json:"signing_key,omitempty"` | ||
SigningAlgorithm *string `json:"signing_algorithm,omitempty"` | ||
} | ||
|
||
// Create creates a new JWT template. | ||
func (c *Client) Create(ctx context.Context, params *CreateParams) (*clerk.JWTTemplate, error) { | ||
req := clerk.NewAPIRequest(http.MethodPost, path) | ||
req.SetParams(params) | ||
template := &clerk.JWTTemplate{} | ||
err := c.Backend.Call(ctx, req, template) | ||
return template, err | ||
} | ||
|
||
// Get returns details about a JWT template. | ||
func (c *Client) Get(ctx context.Context, id string) (*clerk.JWTTemplate, error) { | ||
path, err := clerk.JoinPath(path, id) | ||
if err != nil { | ||
return nil, err | ||
} | ||
req := clerk.NewAPIRequest(http.MethodGet, path) | ||
template := &clerk.JWTTemplate{} | ||
err = c.Backend.Call(ctx, req, template) | ||
return template, err | ||
} | ||
|
||
type UpdateParams struct { | ||
clerk.APIParams | ||
Name *string `json:"name,omitempty"` | ||
Claims json.RawMessage `json:"claims,omitempty"` | ||
Lifetime *int64 `json:"lifetime,omitempty"` | ||
AllowedClockSkew *int64 `json:"allowed_clock_skew,omitempty"` | ||
CustomSigningKey *bool `json:"custom_signing_key,omitempty"` | ||
SigningKey *string `json:"signing_key,omitempty"` | ||
SigningAlgorithm *string `json:"signing_algorithm,omitempty"` | ||
} | ||
|
||
// Update updates the JWT template specified by id. | ||
func (c *Client) Update(ctx context.Context, id string, params *UpdateParams) (*clerk.JWTTemplate, error) { | ||
path, err := clerk.JoinPath(path, id) | ||
if err != nil { | ||
return nil, err | ||
} | ||
req := clerk.NewAPIRequest(http.MethodPatch, path) | ||
req.SetParams(params) | ||
template := &clerk.JWTTemplate{} | ||
err = c.Backend.Call(ctx, req, template) | ||
return template, err | ||
} | ||
|
||
// Delete deletes a JWT template. | ||
func (c *Client) Delete(ctx context.Context, id string) (*clerk.DeletedResource, error) { | ||
path, err := clerk.JoinPath(path, id) | ||
if err != nil { | ||
return nil, err | ||
} | ||
req := clerk.NewAPIRequest(http.MethodDelete, path) | ||
template := &clerk.DeletedResource{} | ||
err = c.Backend.Call(ctx, req, template) | ||
return template, err | ||
} | ||
|
||
type ListParams struct { | ||
clerk.APIParams | ||
} | ||
|
||
// List returns a list of JWT templates. | ||
func (c *Client) List(ctx context.Context, params *ListParams) (*clerk.JWTTemplateList, error) { | ||
req := clerk.NewAPIRequest(http.MethodGet, fmt.Sprintf("%s?paginated=true", path)) | ||
req.SetParams(params) | ||
list := &clerk.JWTTemplateList{} | ||
err := c.Backend.Call(ctx, req, list) | ||
return list, err | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,175 @@ | ||
package jwttemplate | ||
|
||
import ( | ||
"context" | ||
"encoding/json" | ||
"fmt" | ||
"net/http" | ||
"net/url" | ||
"testing" | ||
|
||
"github.com/clerk/clerk-sdk-go/v2" | ||
"github.com/clerk/clerk-sdk-go/v2/clerktest" | ||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
func TestJWTTemplateClientCreate(t *testing.T) { | ||
t.Parallel() | ||
name := "the-name" | ||
id := "jtmpl_123" | ||
config := &ClientConfig{} | ||
config.HTTPClient = &http.Client{ | ||
Transport: &clerktest.RoundTripper{ | ||
T: t, | ||
In: json.RawMessage(fmt.Sprintf(`{"name":"%s"}`, name)), | ||
Out: json.RawMessage(fmt.Sprintf(`{"id":"%s","name":"%s"}`, id, name)), | ||
Method: http.MethodPost, | ||
Path: "/v1/jwt_templates", | ||
}, | ||
} | ||
client := NewClient(config) | ||
jwtTemplate, err := client.Create(context.Background(), &CreateParams{ | ||
Name: clerk.String(name), | ||
}) | ||
require.NoError(t, err) | ||
require.Equal(t, id, jwtTemplate.ID) | ||
require.Equal(t, name, jwtTemplate.Name) | ||
} | ||
|
||
func TestJWTTemplateClientCreate_Error(t *testing.T) { | ||
t.Parallel() | ||
config := &ClientConfig{} | ||
config.HTTPClient = &http.Client{ | ||
Transport: &clerktest.RoundTripper{ | ||
T: t, | ||
Status: http.StatusBadRequest, | ||
Out: json.RawMessage(`{ | ||
"errors":[{ | ||
"code":"create-error-code" | ||
}], | ||
"clerk_trace_id":"create-trace-id" | ||
}`), | ||
}, | ||
} | ||
client := NewClient(config) | ||
_, err := client.Create(context.Background(), &CreateParams{}) | ||
require.Error(t, err) | ||
apiErr, ok := err.(*clerk.APIErrorResponse) | ||
require.True(t, ok) | ||
require.Equal(t, "create-trace-id", apiErr.TraceID) | ||
require.Equal(t, 1, len(apiErr.Errors)) | ||
require.Equal(t, "create-error-code", apiErr.Errors[0].Code) | ||
} | ||
|
||
func TestJWTTemplateClientGet(t *testing.T) { | ||
t.Parallel() | ||
id := "jtmpl_123" | ||
name := "the-name" | ||
config := &ClientConfig{} | ||
config.HTTPClient = &http.Client{ | ||
Transport: &clerktest.RoundTripper{ | ||
T: t, | ||
Out: json.RawMessage(fmt.Sprintf(`{"id":"%s","name":"%s"}`, id, name)), | ||
Method: http.MethodGet, | ||
Path: "/v1/jwt_templates/" + id, | ||
}, | ||
} | ||
client := NewClient(config) | ||
jwtTemplate, err := client.Get(context.Background(), id) | ||
require.NoError(t, err) | ||
require.Equal(t, id, jwtTemplate.ID) | ||
require.Equal(t, name, jwtTemplate.Name) | ||
} | ||
|
||
func TestJWTTemplateClientUpdate(t *testing.T) { | ||
t.Parallel() | ||
id := "jtmpl_123" | ||
name := "the-name" | ||
config := &ClientConfig{} | ||
config.HTTPClient = &http.Client{ | ||
Transport: &clerktest.RoundTripper{ | ||
T: t, | ||
In: json.RawMessage(fmt.Sprintf(`{"name":"%s"}`, name)), | ||
Out: json.RawMessage(fmt.Sprintf(`{"id":"%s","name":"%s"}`, id, name)), | ||
Method: http.MethodPatch, | ||
Path: "/v1/jwt_templates/" + id, | ||
}, | ||
} | ||
client := NewClient(config) | ||
jwtTemplate, err := client.Update(context.Background(), id, &UpdateParams{ | ||
Name: clerk.String(name), | ||
}) | ||
require.NoError(t, err) | ||
require.Equal(t, id, jwtTemplate.ID) | ||
require.Equal(t, name, jwtTemplate.Name) | ||
} | ||
|
||
func TestJWTTemplateClientUpdate_Error(t *testing.T) { | ||
t.Parallel() | ||
config := &ClientConfig{} | ||
config.HTTPClient = &http.Client{ | ||
Transport: &clerktest.RoundTripper{ | ||
T: t, | ||
Status: http.StatusBadRequest, | ||
Out: json.RawMessage(`{ | ||
"errors":[{ | ||
"code":"update-error-code" | ||
}], | ||
"clerk_trace_id":"update-trace-id" | ||
}`), | ||
}, | ||
} | ||
client := NewClient(config) | ||
_, err := client.Update(context.Background(), "jtmpl_123", &UpdateParams{}) | ||
require.Error(t, err) | ||
apiErr, ok := err.(*clerk.APIErrorResponse) | ||
require.True(t, ok) | ||
require.Equal(t, "update-trace-id", apiErr.TraceID) | ||
require.Equal(t, 1, len(apiErr.Errors)) | ||
require.Equal(t, "update-error-code", apiErr.Errors[0].Code) | ||
} | ||
|
||
func TestJWTTemplateClientDelete(t *testing.T) { | ||
t.Parallel() | ||
id := "jtmpl_456" | ||
config := &ClientConfig{} | ||
config.HTTPClient = &http.Client{ | ||
Transport: &clerktest.RoundTripper{ | ||
T: t, | ||
Out: json.RawMessage(fmt.Sprintf(`{"id":"%s","deleted":true}`, id)), | ||
Method: http.MethodDelete, | ||
Path: "/v1/jwt_templates/" + id, | ||
}, | ||
} | ||
client := NewClient(config) | ||
jwtTemplate, err := client.Delete(context.Background(), id) | ||
require.NoError(t, err) | ||
require.Equal(t, id, jwtTemplate.ID) | ||
require.True(t, jwtTemplate.Deleted) | ||
} | ||
|
||
func TestJWTTemplateClientList(t *testing.T) { | ||
t.Parallel() | ||
config := &ClientConfig{} | ||
config.HTTPClient = &http.Client{ | ||
Transport: &clerktest.RoundTripper{ | ||
T: t, | ||
Out: json.RawMessage(`{ | ||
"data": [{"id":"jtmpl_123","name":"the-name"}], | ||
"total_count": 1 | ||
}`), | ||
Method: http.MethodGet, | ||
Path: "/v1/jwt_templates", | ||
Query: &url.Values{ | ||
"paginated": []string{"true"}, | ||
}, | ||
}, | ||
} | ||
client := NewClient(config) | ||
list, err := client.List(context.Background(), &ListParams{}) | ||
require.NoError(t, err) | ||
require.Equal(t, int64(1), list.TotalCount) | ||
require.Equal(t, 1, len(list.JWTTemplates)) | ||
require.Equal(t, "jtmpl_123", list.JWTTemplates[0].ID) | ||
require.Equal(t, "the-name", list.JWTTemplates[0].Name) | ||
} |