Skip to content

Commit

Permalink
feat: API operations for JWT Templates
Browse files Browse the repository at this point in the history
Added support for the JWT Templates API with Create, Get, Update, Delete
and List operations.
  • Loading branch information
gkats committed Feb 7, 2024
1 parent 3550faf commit d62bbac
Show file tree
Hide file tree
Showing 4 changed files with 346 additions and 0 deletions.
23 changes: 23 additions & 0 deletions jwt_template.go
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"`
}
41 changes: 41 additions & 0 deletions jwttemplate/api.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

111 changes: 111 additions & 0 deletions jwttemplate/client.go
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
}
171 changes: 171 additions & 0 deletions jwttemplate/client_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
package jwttemplate

import (
"context"
"encoding/json"
"fmt"
"net/http"
"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",
},
}
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)
}

0 comments on commit d62bbac

Please sign in to comment.