-
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.
Added the types and operations for actor tokens. Create and Revoke are supported.
- Loading branch information
Showing
5 changed files
with
231 additions
and
82 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,15 @@ | ||
package clerk | ||
|
||
import "encoding/json" | ||
|
||
type ActorToken struct { | ||
APIResource | ||
Object string `json:"object"` | ||
ID string `json:"id"` | ||
UserID string `json:"user_id"` | ||
Actor json.RawMessage `json:"actor"` | ||
Token string `json:"token,omitempty"` | ||
Status string `json:"status"` | ||
CreatedAt int64 `json:"created_at"` | ||
UpdatedAt int64 `json:"updated_at"` | ||
} |
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,42 @@ | ||
// Package actortoken provides the Actor Tokens API. | ||
package actortoken | ||
|
||
import ( | ||
"context" | ||
"encoding/json" | ||
"net/http" | ||
"net/url" | ||
|
||
"github.com/clerk/clerk-sdk-go/v2" | ||
) | ||
|
||
const path = "/actor_tokens" | ||
|
||
type CreateParams struct { | ||
clerk.APIParams | ||
UserID *string `json:"user_id,omitempty"` | ||
Actor json.RawMessage `json:"actor,omitempty"` | ||
ExpiresInSeconds *int64 `json:"expires_in_seconds,omitempty"` | ||
SessionMaxDurationInSeconds *int64 `json:"session_max_duration_in_seconds,omitempty"` | ||
} | ||
|
||
// Create creates a new actor token. | ||
func Create(ctx context.Context, params *CreateParams) (*clerk.ActorToken, error) { | ||
req := clerk.NewAPIRequest(http.MethodPost, path) | ||
req.SetParams(params) | ||
token := &clerk.ActorToken{} | ||
err := clerk.GetBackend().Call(ctx, req, token) | ||
return token, err | ||
} | ||
|
||
// Revoke revokes a pending actor token. | ||
func Revoke(ctx context.Context, id string) (*clerk.ActorToken, error) { | ||
token := &clerk.ActorToken{} | ||
path, err := url.JoinPath(path, id, "revoke") | ||
if err != nil { | ||
return token, err | ||
} | ||
req := clerk.NewAPIRequest(http.MethodPost, path) | ||
err = clerk.GetBackend().Call(ctx, req, token) | ||
return token, 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,80 @@ | ||
package actortoken | ||
|
||
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 TestActorTokenCreate(t *testing.T) { | ||
userID := "usr_123" | ||
id := "act_123" | ||
clerk.SetBackend(clerk.NewBackend(&clerk.BackendConfig{ | ||
HTTPClient: &http.Client{ | ||
Transport: &clerktest.RoundTripper{ | ||
T: t, | ||
In: json.RawMessage(fmt.Sprintf(`{"user_id":"%s"}`, userID)), | ||
Out: json.RawMessage(fmt.Sprintf(`{"id":"%s","user_id":"%s"}`, id, userID)), | ||
Path: "/v1/actor_tokens", | ||
Method: http.MethodPost, | ||
}, | ||
}, | ||
})) | ||
|
||
actorToken, err := Create(context.Background(), &CreateParams{ | ||
UserID: clerk.String(userID), | ||
}) | ||
require.NoError(t, err) | ||
require.Equal(t, id, actorToken.ID) | ||
require.Equal(t, userID, actorToken.UserID) | ||
} | ||
|
||
func TestActorTokenCreate_Error(t *testing.T) { | ||
clerk.SetBackend(clerk.NewBackend(&clerk.BackendConfig{ | ||
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" | ||
}`), | ||
}, | ||
}, | ||
})) | ||
|
||
_, err := 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 TestActorTokenRevoke(t *testing.T) { | ||
id := "act_456" | ||
clerk.SetBackend(clerk.NewBackend(&clerk.BackendConfig{ | ||
HTTPClient: &http.Client{ | ||
Transport: &clerktest.RoundTripper{ | ||
T: t, | ||
Out: json.RawMessage(fmt.Sprintf(`{"id":"%s","status":"revoked"}`, id)), | ||
Path: fmt.Sprintf("/v1/actor_tokens/%s/revoke", id), | ||
Method: http.MethodPost, | ||
}, | ||
}, | ||
})) | ||
|
||
actorToken, err := Revoke(context.Background(), id) | ||
require.NoError(t, err) | ||
require.Equal(t, id, actorToken.ID) | ||
require.Equal(t, "revoked", actorToken.Status) | ||
} |
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,55 @@ | ||
// Package clerktest provides utilities for testing. | ||
package clerktest | ||
|
||
import ( | ||
"bytes" | ||
"encoding/json" | ||
"io" | ||
"net/http" | ||
"testing" | ||
|
||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
// RoundTripper can be used as a mock Transport for http.Clients. | ||
// Set the RoundTripper's fields accordingly to determine the | ||
// response or perform assertions on the http.Request properties. | ||
type RoundTripper struct { | ||
T *testing.T | ||
// Status is the response Status code. | ||
Status int | ||
// Out is the response body. | ||
Out json.RawMessage | ||
// Set this field to assert on the request method. | ||
Method string | ||
// Set this field to assert that the request path matches. | ||
Path string | ||
// Set this field to assert that the request body matches. | ||
In json.RawMessage | ||
} | ||
|
||
// RoundTrip returns an http.Response based on the RoundTripper's fields. | ||
// It will also perform assertions on the http.Request. | ||
func (rt *RoundTripper) RoundTrip(r *http.Request) (*http.Response, error) { | ||
if rt.Status == 0 { | ||
rt.Status = http.StatusOK | ||
} | ||
if rt.Path != "" { | ||
require.Equal(rt.T, rt.Path, r.URL.Path) | ||
} | ||
if rt.Method != "" { | ||
require.Equal(rt.T, rt.Method, r.Method) | ||
} | ||
if rt.In != nil { | ||
body, err := io.ReadAll(r.Body) | ||
if err != nil { | ||
return nil, err | ||
} | ||
defer r.Body.Close() | ||
require.JSONEq(rt.T, string(rt.In), string(body)) | ||
} | ||
return &http.Response{ | ||
StatusCode: rt.Status, | ||
Body: io.NopCloser(bytes.NewReader(rt.Out)), | ||
}, nil | ||
} |
Oops, something went wrong.