-
Notifications
You must be signed in to change notification settings - Fork 18
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
311 additions
and
3 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 @@ | ||
# roles | ||
|
||
[](https://pkg.go.dev/github.com/workos/workos-go/v4/pkg/roles) | ||
|
||
A Go package to make requests to the WorkOS Roles API. | ||
|
||
## Install | ||
|
||
```sh | ||
go get -u github.com/workos/workos-go/v4/pkg/roles | ||
``` | ||
|
||
## How it works | ||
|
||
See the [Roles and Permissions documentation](https://workos.com/docs/user-management/roles-and-permissions). |
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,129 @@ | ||
package roles | ||
|
||
import ( | ||
"bytes" | ||
"context" | ||
"encoding/json" | ||
"fmt" | ||
"net/http" | ||
"sync" | ||
"time" | ||
|
||
"github.com/workos/workos-go/v4/pkg/workos_errors" | ||
|
||
"github.com/workos/workos-go/v4/internal/workos" | ||
) | ||
|
||
// ResponseLimit is the default number of records to limit a response to. | ||
const ResponseLimit = 10 | ||
|
||
// Client represents a client that performs Roles requests to the WorkOS API. | ||
type Client struct { | ||
// The WorkOS API Key. It can be found in https://dashboard.workos.com/api-keys. | ||
APIKey string | ||
|
||
// The http.Client that is used to manage Roles API calls to WorkOS. | ||
// Defaults to http.Client. | ||
HTTPClient *http.Client | ||
|
||
// The endpoint to WorkOS API. Defaults to https://api.workos.com. | ||
Endpoint string | ||
|
||
// The function used to encode in JSON. Defaults to json.Marshal. | ||
JSONEncode func(v interface{}) ([]byte, error) | ||
|
||
once sync.Once | ||
} | ||
|
||
func (c *Client) init() { | ||
if c.HTTPClient == nil { | ||
c.HTTPClient = &http.Client{Timeout: 10 * time.Second} | ||
} | ||
|
||
if c.Endpoint == "" { | ||
c.Endpoint = "https://api.workos.com" | ||
} | ||
|
||
if c.JSONEncode == nil { | ||
c.JSONEncode = json.Marshal | ||
} | ||
} | ||
|
||
// RoleType represents the type of a Role. | ||
type RoleType string | ||
|
||
// Constants that enumerate the type of a Role. | ||
const ( | ||
Environment RoleType = "EnvironmentRole" | ||
Organization RoleType = "OrganizationRole" | ||
) | ||
|
||
// Role contains data about a WorkOS Role. | ||
type Role struct { | ||
// The Role's unique identifier. | ||
ID string `json:"id"` | ||
|
||
Name string `json:"name"` | ||
|
||
// The Role's slug key for referencing it in code. | ||
Slug string `json:"slug"` | ||
|
||
Description string `json:"description"` | ||
|
||
// The type of role | ||
Type RoleType `json:"type"` | ||
|
||
// The timestamp of when the Role was created. | ||
CreatedAt string `json:"created_at"` | ||
|
||
// The timestamp of when the Role was updated. | ||
UpdatedAt string `json:"updated_at"` | ||
} | ||
|
||
// ListRolesOpts contains the options to request Roles. | ||
type ListRolesOpts struct{} | ||
|
||
// ListRolesResponse describes the response structure when requesting Roles. | ||
type ListRolesResponse struct { | ||
// List of provisioned Roles. | ||
Data []Role `json:"data"` | ||
} | ||
|
||
// ListRoles lists all roles in a WorkOS environment. | ||
func (c *Client) ListRoles( | ||
ctx context.Context, | ||
opts ListRolesOpts, | ||
) (ListRolesResponse, error) { | ||
c.once.Do(c.init) | ||
|
||
data, err := c.JSONEncode(opts) | ||
if err != nil { | ||
return ListRolesResponse{}, err | ||
} | ||
|
||
endpoint := fmt.Sprintf("%s/roles", c.Endpoint) | ||
req, err := http.NewRequest(http.MethodGet, endpoint, bytes.NewBuffer(data)) | ||
if err != nil { | ||
return ListRolesResponse{}, err | ||
} | ||
req = req.WithContext(ctx) | ||
req.Header.Set("Content-Type", "application/json") | ||
req.Header.Set("Authorization", "Bearer "+c.APIKey) | ||
req.Header.Set("User-Agent", "workos-go/"+workos.Version) | ||
|
||
res, err := c.HTTPClient.Do(req) | ||
if err != nil { | ||
return ListRolesResponse{}, err | ||
} | ||
defer res.Body.Close() | ||
|
||
if err = workos_errors.TryGetHTTPError(res); err != nil { | ||
return ListRolesResponse{}, err | ||
} | ||
|
||
var body ListRolesResponse | ||
|
||
dec := json.NewDecoder(res.Body) | ||
err = dec.Decode(&body) | ||
return body, 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,98 @@ | ||
package roles | ||
|
||
import ( | ||
"context" | ||
"encoding/json" | ||
"net/http" | ||
"net/http/httptest" | ||
"testing" | ||
|
||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
func TestListRoles(t *testing.T) { | ||
tests := []struct { | ||
scenario string | ||
client *Client | ||
options ListRolesOpts | ||
expected ListRolesResponse | ||
err bool | ||
}{ | ||
{ | ||
scenario: "Request without API Key returns an error", | ||
client: &Client{}, | ||
err: true, | ||
}, | ||
{ | ||
scenario: "Request returns list of roles", | ||
client: &Client{ | ||
APIKey: "test", | ||
}, | ||
options: ListRolesOpts{}, | ||
expected: ListRolesResponse{ | ||
Data: []Role{ | ||
{ | ||
ID: "role_01EHWNCE74X7JSDV0X3SZ3KJNY", | ||
Name: "Member", | ||
Slug: "member", | ||
Description: "The default role for all users.", | ||
Type: Environment, | ||
CreatedAt: "2024-12-01T00:00:00.000Z", | ||
UpdatedAt: "2024-12-01T00:00:00.000Z", | ||
}, | ||
}, | ||
}, | ||
}, | ||
} | ||
|
||
for _, test := range tests { | ||
t.Run(test.scenario, func(t *testing.T) { | ||
server := httptest.NewServer(http.HandlerFunc(listRolesTestHandler)) | ||
defer server.Close() | ||
|
||
client := test.client | ||
client.Endpoint = server.URL | ||
client.HTTPClient = server.Client() | ||
|
||
response, err := client.ListRoles(context.Background(), test.options) | ||
if test.err { | ||
require.Error(t, err) | ||
return | ||
} | ||
require.NoError(t, err) | ||
require.Equal(t, test.expected, response) | ||
}) | ||
} | ||
} | ||
|
||
func listRolesTestHandler(w http.ResponseWriter, r *http.Request) { | ||
auth := r.Header.Get("Authorization") | ||
if auth != "Bearer test" { | ||
http.Error(w, "bad auth", http.StatusUnauthorized) | ||
return | ||
} | ||
|
||
body, err := json.Marshal(struct { | ||
ListRolesResponse | ||
}{ListRolesResponse{ | ||
Data: []Role{ | ||
{ | ||
ID: "role_01EHWNCE74X7JSDV0X3SZ3KJNY", | ||
Name: "Member", | ||
Slug: "member", | ||
Description: "The default role for all users.", | ||
Type: Environment, | ||
CreatedAt: "2024-12-01T00:00:00.000Z", | ||
UpdatedAt: "2024-12-01T00:00:00.000Z", | ||
}, | ||
}, | ||
}}) | ||
|
||
if err != nil { | ||
w.WriteHeader(http.StatusInternalServerError) | ||
return | ||
} | ||
|
||
w.WriteHeader(http.StatusOK) | ||
w.Write(body) | ||
} |
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,26 @@ | ||
// Package `roles` provides a client wrapping the WorkOS Roles API. | ||
package roles | ||
|
||
import ( | ||
"context" | ||
) | ||
|
||
// DefaultClient is the client used by SetAPIKey and Roles functions. | ||
var ( | ||
DefaultClient = &Client{ | ||
Endpoint: "https://api.workos.com", | ||
} | ||
) | ||
|
||
// SetAPIKey sets the WorkOS API key for Roles API requests. | ||
func SetAPIKey(apiKey string) { | ||
DefaultClient.APIKey = apiKey | ||
} | ||
|
||
// ListRoles lists all Roles in an environment. | ||
func ListRoles( | ||
ctx context.Context, | ||
opts ListRolesOpts, | ||
) (ListRolesResponse, error) { | ||
return DefaultClient.ListRoles(ctx, opts) | ||
} |
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,40 @@ | ||
package roles | ||
|
||
import ( | ||
"context" | ||
"net/http" | ||
"net/http/httptest" | ||
"testing" | ||
|
||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
func TestRolesListRoles(t *testing.T) { | ||
server := httptest.NewServer(http.HandlerFunc(listRolesTestHandler)) | ||
defer server.Close() | ||
|
||
DefaultClient = &Client{ | ||
HTTPClient: server.Client(), | ||
Endpoint: server.URL, | ||
} | ||
SetAPIKey("test") | ||
|
||
expectedResponse := ListRolesResponse{ | ||
Data: []Role{ | ||
{ | ||
ID: "role_01EHWNCE74X7JSDV0X3SZ3KJNY", | ||
Name: "Member", | ||
Slug: "member", | ||
Description: "The default role for all users.", | ||
Type: Environment, | ||
CreatedAt: "2024-12-01T00:00:00.000Z", | ||
UpdatedAt: "2024-12-01T00:00:00.000Z", | ||
}, | ||
}, | ||
} | ||
|
||
response, err := ListRoles(context.Background(), ListRolesOpts{}) | ||
|
||
require.NoError(t, err) | ||
require.Equal(t, expectedResponse, response) | ||
} |
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
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