Skip to content

Commit

Permalink
feat: Sessions API (#232)
Browse files Browse the repository at this point in the history
Added support for the Sessions API. Available operations are Get, List,
Revoke and Verify.
  • Loading branch information
gkats authored Feb 9, 2024
1 parent 9776f2e commit 2d553d4
Show file tree
Hide file tree
Showing 4 changed files with 270 additions and 0 deletions.
6 changes: 6 additions & 0 deletions session.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"`
}
41 changes: 41 additions & 0 deletions session/api.go

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

112 changes: 112 additions & 0 deletions session/client.go
Original file line number Diff line number Diff line change
@@ -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
}
111 changes: 111 additions & 0 deletions session/client_test.go
Original file line number Diff line number Diff line change
@@ -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)
}

0 comments on commit 2d553d4

Please sign in to comment.