From 4b196e4a8c4dd89972828f88a2fbe036a90c3b0c Mon Sep 17 00:00:00 2001 From: Giannis Katsanos Date: Thu, 8 Feb 2024 15:35:26 +0200 Subject: [PATCH] feat: Sessions API Added support for the Sessions API. Available operations are Get, List, Revoke and Verify. --- session.go | 6 +++ session/api.go | 41 +++++++++++++++ session/client.go | 112 +++++++++++++++++++++++++++++++++++++++++ session/client_test.go | 111 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 270 insertions(+) create mode 100644 session/api.go create mode 100644 session/client.go create mode 100644 session/client_test.go diff --git a/session.go b/session.go index 23684e5..143873b 100644 --- a/session.go +++ b/session.go @@ -17,3 +17,9 @@ type Session struct { CreatedAt int64 `json:"created_at"` UpdatedAt int64 `json:"updated_at"` } + +type SessionList struct { + APIResource + Sessions []*Session `json:"data"` + TotalCount int64 `json:"total_count"` +} diff --git a/session/api.go b/session/api.go new file mode 100644 index 0000000..82efdff --- /dev/null +++ b/session/api.go @@ -0,0 +1,41 @@ +// Code generated by "gen"; DO NOT EDIT. +// This file is meant to be re-generated in place and/or deleted at any time. +// Last generated at 2024-02-08 13:35:10.578898463 +0000 UTC +package session + +import ( + "context" + + "github.com/clerk/clerk-sdk-go/v2" +) + +// Get retrieves details for a session. +func Get(ctx context.Context, id string) (*clerk.Session, error) { + return getClient().Get(ctx, id) +} + +// List returns a list of sessions. +func List(ctx context.Context, params *ListParams) (*clerk.SessionList, error) { + return getClient().List(ctx, params) +} + +// Revoke marks the session as revoked. +func Revoke(ctx context.Context, params *RevokeParams) (*clerk.Session, error) { + return getClient().Revoke(ctx, params) +} + +// Verify verifies the session. +// +// Deprecated: The operation is deprecated and will be removed in future versions. +// It is recommended to switch to networkless verification using short-lived +// session tokens instead. +// See https://clerk.com/docs/backend-requests/resources/session-tokens +func Verify(ctx context.Context, params *VerifyParams) (*clerk.Session, error) { + return getClient().Verify(ctx, params) +} + +func getClient() *Client { + return &Client{ + Backend: clerk.GetBackend(), + } +} diff --git a/session/client.go b/session/client.go new file mode 100644 index 0000000..14fa684 --- /dev/null +++ b/session/client.go @@ -0,0 +1,112 @@ +// Package session provides the Sessions API. +package session + +import ( + "context" + "fmt" + "net/http" + "net/url" + + "github.com/clerk/clerk-sdk-go/v2" +) + +//go:generate go run ../cmd/gen/main.go + +const path = "/sessions" + +// Client is used to invoke the Sessions API. +type Client struct { + Backend clerk.Backend +} + +type ClientConfig struct { + clerk.BackendConfig +} + +func NewClient(config *ClientConfig) *Client { + return &Client{ + Backend: clerk.NewBackend(&config.BackendConfig), + } +} + +// Get retrieves details for a session. +func (c *Client) Get(ctx context.Context, id string) (*clerk.Session, error) { + path, err := clerk.JoinPath(path, id) + if err != nil { + return nil, err + } + req := clerk.NewAPIRequest(http.MethodGet, path) + session := &clerk.Session{} + err = c.Backend.Call(ctx, req, session) + return session, err +} + +type ListParams struct { + clerk.APIParams + clerk.ListParams + ClientID *string `json:"client_id,omitempty"` + UserID *string `json:"user_id,omitempty"` + Status *string `json:"status,omitempty"` +} + +// ToQuery returns the params as url.Values. +func (params *ListParams) ToQuery() url.Values { + q := params.ListParams.ToQuery() + if params.ClientID != nil { + q.Add("client_id", *params.ClientID) + } + if params.UserID != nil { + q.Add("user_id", *params.UserID) + } + if params.Status != nil { + q.Add("status", *params.Status) + } + return q +} + +// List returns a list of sessions. +func (c *Client) List(ctx context.Context, params *ListParams) (*clerk.SessionList, error) { + req := clerk.NewAPIRequest(http.MethodGet, fmt.Sprintf("%s?paginated=true", path)) + req.SetParams(params) + list := &clerk.SessionList{} + err := c.Backend.Call(ctx, req, list) + return list, err +} + +type RevokeParams struct { + ID string `json:"id"` +} + +// Revoke marks the session as revoked. +func (c *Client) Revoke(ctx context.Context, params *RevokeParams) (*clerk.Session, error) { + path, err := clerk.JoinPath(path, params.ID, "/revoke") + if err != nil { + return nil, err + } + req := clerk.NewAPIRequest(http.MethodPost, path) + session := &clerk.Session{} + err = c.Backend.Call(ctx, req, session) + return session, err +} + +type VerifyParams struct { + ID string `json:"-"` + Token *string `json:"token,omitempty"` +} + +// Verify verifies the session. +// +// Deprecated: The operation is deprecated and will be removed in future versions. +// It is recommended to switch to networkless verification using short-lived +// session tokens instead. +// See https://clerk.com/docs/backend-requests/resources/session-tokens +func (c *Client) Verify(ctx context.Context, params *VerifyParams) (*clerk.Session, error) { + path, err := clerk.JoinPath(path, params.ID, "/verify") + if err != nil { + return nil, err + } + req := clerk.NewAPIRequest(http.MethodPost, path) + session := &clerk.Session{} + err = c.Backend.Call(ctx, req, session) + return session, err +} diff --git a/session/client_test.go b/session/client_test.go new file mode 100644 index 0000000..e726e78 --- /dev/null +++ b/session/client_test.go @@ -0,0 +1,111 @@ +package session + +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 TestSessionClientGet(t *testing.T) { + t.Parallel() + id := "sess_123" + status := "active" + config := &ClientConfig{} + config.HTTPClient = &http.Client{ + Transport: &clerktest.RoundTripper{ + T: t, + Out: json.RawMessage(fmt.Sprintf(`{"id":"%s","status":"%s"}`, id, status)), + Method: http.MethodGet, + Path: "/v1/sessions/" + id, + }, + } + client := NewClient(config) + session, err := client.Get(context.Background(), id) + require.NoError(t, err) + require.Equal(t, id, session.ID) + require.Equal(t, status, session.Status) +} + +func TestSessionClientList(t *testing.T) { + t.Parallel() + config := &ClientConfig{} + config.HTTPClient = &http.Client{ + Transport: &clerktest.RoundTripper{ + T: t, + Out: json.RawMessage(`{ +"data": [{"id":"sess_123","status":"active"}], +"total_count": 1 +}`), + Method: http.MethodGet, + Path: "/v1/sessions", + Query: &url.Values{ + "paginated": []string{"true"}, + "limit": []string{"1"}, + "offset": []string{"2"}, + "status": []string{"active"}, + }, + }, + } + client := NewClient(config) + params := &ListParams{ + Status: clerk.String("active"), + } + params.Limit = clerk.Int64(1) + params.Offset = clerk.Int64(2) + list, err := client.List(context.Background(), params) + require.NoError(t, err) + require.Equal(t, int64(1), list.TotalCount) + require.Equal(t, 1, len(list.Sessions)) + require.Equal(t, "sess_123", list.Sessions[0].ID) + require.Equal(t, "active", list.Sessions[0].Status) +} + +func TestSessionClientRevoke(t *testing.T) { + t.Parallel() + id := "sess_123" + status := "revoked" + config := &ClientConfig{} + config.HTTPClient = &http.Client{ + Transport: &clerktest.RoundTripper{ + T: t, + Out: json.RawMessage(fmt.Sprintf(`{"id":"%s","status":"%s"}`, id, status)), + Method: http.MethodPost, + Path: "/v1/sessions/" + id + "/revoke", + }, + } + client := NewClient(config) + session, err := client.Revoke(context.Background(), &RevokeParams{ + ID: id, + }) + require.NoError(t, err) + require.Equal(t, id, session.ID) + require.Equal(t, status, session.Status) +} + +func TestSessionClientVerify(t *testing.T) { + t.Parallel() + id := "sess_123" + config := &ClientConfig{} + config.HTTPClient = &http.Client{ + Transport: &clerktest.RoundTripper{ + T: t, + Out: json.RawMessage(fmt.Sprintf(`{"id":"%s"}`, id)), + Method: http.MethodPost, + Path: "/v1/sessions/" + id + "/verify", + }, + } + client := NewClient(config) + session, err := client.Verify(context.Background(), &VerifyParams{ + ID: id, + Token: clerk.String("the-token"), + }) + require.NoError(t, err) + require.Equal(t, id, session.ID) +}