Skip to content

Commit

Permalink
Add GET /organization/:orgId/roles support. (#388)
Browse files Browse the repository at this point in the history
  • Loading branch information
mattgd authored Jan 2, 2025
1 parent 90d536f commit 7036673
Show file tree
Hide file tree
Showing 6 changed files with 255 additions and 0 deletions.
50 changes: 50 additions & 0 deletions pkg/organizations/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"sync"
"time"

"github.com/workos/workos-go/v4/pkg/roles"
"github.com/workos/workos-go/v4/pkg/workos_errors"

"github.com/google/go-querystring/query"
Expand Down Expand Up @@ -217,6 +218,17 @@ type UpdateOrganizationOpts struct {
DomainData []OrganizationDomainData `json:"domain_data"`
}

// ListOrganizationsOpts contains the options to request Organizations.
type ListOrganizationRolesOpts struct {
// The Organization's unique identifier.
OrganizationID string
}

type ListOrganizationRolesResponse struct {
// List of roles for the given organization.
Data []roles.Role `json:"data"`
}

// GetOrganization gets an Organization.
func (c *Client) GetOrganization(
ctx context.Context,
Expand Down Expand Up @@ -443,3 +455,41 @@ func (c *Client) DeleteOrganization(

return workos_errors.TryGetHTTPError(res)
}

// ListOrganizationRoles gets a list of roles for the given organization.
func (c *Client) ListOrganizationRoles(
ctx context.Context,
opts ListOrganizationRolesOpts,
) (ListOrganizationRolesResponse, error) {
c.once.Do(c.init)

endpoint := fmt.Sprintf("%s/organizations/%s/roles", c.Endpoint, opts.OrganizationID)
req, err := http.NewRequest(
http.MethodGet,
endpoint,
nil,
)
if err != nil {
return ListOrganizationRolesResponse{}, err
}

req = req.WithContext(ctx)
req.Header.Set("Authorization", "Bearer "+c.APIKey)
req.Header.Set("Content-Type", "application/json")
req.Header.Set("User-Agent", "workos-go/"+workos.Version)

res, err := c.HTTPClient.Do(req)
if err != nil {
return ListOrganizationRolesResponse{}, err
}
defer res.Body.Close()

if err = workos_errors.TryGetHTTPError(res); err != nil {
return ListOrganizationRolesResponse{}, err
}

var body ListOrganizationRolesResponse
dec := json.NewDecoder(res.Body)
err = dec.Decode(&body)
return body, err
}
108 changes: 108 additions & 0 deletions pkg/organizations/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (

"github.com/stretchr/testify/require"
"github.com/workos/workos-go/v4/pkg/common"
"github.com/workos/workos-go/v4/pkg/roles"
)

func TestGetOrganization(t *testing.T) {
Expand Down Expand Up @@ -542,3 +543,110 @@ func updateOrganizationTestHandler(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
w.Write(body)
}

func TestListOrganizationRoles(t *testing.T) {
tests := []struct {
scenario string
client *Client
options ListOrganizationRolesOpts
expected ListOrganizationRolesResponse
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: ListOrganizationRolesOpts{
OrganizationID: "organization_id",
},
expected: ListOrganizationRolesResponse{
Data: []roles.Role{
{
ID: "role_01EHWNCE74X7JSDV0X3SZ3KJNY",
Name: "Member",
Slug: "member",
Description: "The default role for all users.",
Type: roles.Environment,
CreatedAt: "2024-12-01T00:00:00.000Z",
UpdatedAt: "2024-12-01T00:00:00.000Z",
},
{
ID: "role_01EHWNCE74X7JSDV0X3SZ3KJSE",
Name: "Org. Member",
Slug: "org-member",
Description: "The default role for org. members.",
Type: roles.Organization,
CreatedAt: "2024-12-02T00:00:00.000Z",
UpdatedAt: "2024-12-02T00:00:00.000Z",
},
},
},
},
}

for _, test := range tests {
t.Run(test.scenario, func(t *testing.T) {
server := httptest.NewServer(http.HandlerFunc(listOrganizationRolesTestHandler))
defer server.Close()

client := test.client
client.Endpoint = server.URL
client.HTTPClient = server.Client()

response, err := client.ListOrganizationRoles(context.Background(), test.options)
if test.err {
require.Error(t, err)
return
}
require.NoError(t, err)
require.Equal(t, test.expected, response)
})
}
}

func listOrganizationRolesTestHandler(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 {
ListOrganizationRolesResponse
}{ListOrganizationRolesResponse{
Data: []roles.Role{
{
ID: "role_01EHWNCE74X7JSDV0X3SZ3KJNY",
Name: "Member",
Slug: "member",
Description: "The default role for all users.",
Type: roles.Environment,
CreatedAt: "2024-12-01T00:00:00.000Z",
UpdatedAt: "2024-12-01T00:00:00.000Z",
},
{
ID: "role_01EHWNCE74X7JSDV0X3SZ3KJSE",
Name: "Org. Member",
Slug: "org-member",
Description: "The default role for org. members.",
Type: roles.Organization,
CreatedAt: "2024-12-02T00:00:00.000Z",
UpdatedAt: "2024-12-02T00:00:00.000Z",
},
},
}})

if err != nil {
w.WriteHeader(http.StatusInternalServerError)
return
}

w.WriteHeader(http.StatusOK)
w.Write(body)
}
8 changes: 8 additions & 0 deletions pkg/organizations/organizations.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,11 @@ func DeleteOrganization(
) error {
return DefaultClient.DeleteOrganization(ctx, opts)
}

// ListOrganizationRoles lists roles for an Organization.
func ListOrganizationRoles(
ctx context.Context,
opts ListOrganizationRolesOpts,
) (ListOrganizationRolesResponse, error) {
return DefaultClient.ListOrganizationRoles(ctx, opts)
}
42 changes: 42 additions & 0 deletions pkg/organizations/organizations_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (

"github.com/stretchr/testify/require"
"github.com/workos/workos-go/v4/pkg/common"
"github.com/workos/workos-go/v4/pkg/roles"
)

func TestOrganizationsGetOrganization(t *testing.T) {
Expand Down Expand Up @@ -156,3 +157,44 @@ func TestOrganizationsUpdateOrganization(t *testing.T) {
require.NoError(t, err)
require.Equal(t, expectedResponse, organization)
}

func TestOrganizationsListOrganizationRoles(t *testing.T) {
server := httptest.NewServer(http.HandlerFunc(listOrganizationRolesTestHandler))
defer server.Close()

DefaultClient = &Client{
HTTPClient: server.Client(),
Endpoint: server.URL,
}
SetAPIKey("test")

expectedResponse := ListOrganizationRolesResponse{
Data: []roles.Role{
{
ID: "role_01EHWNCE74X7JSDV0X3SZ3KJNY",
Name: "Member",
Slug: "member",
Description: "The default role for all users.",
Type: roles.Environment,
CreatedAt: "2024-12-01T00:00:00.000Z",
UpdatedAt: "2024-12-01T00:00:00.000Z",
},
{
ID: "role_01EHWNCE74X7JSDV0X3SZ3KJSE",
Name: "Org. Member",
Slug: "org-member",
Description: "The default role for org. members.",
Type: roles.Organization,
CreatedAt: "2024-12-02T00:00:00.000Z",
UpdatedAt: "2024-12-02T00:00:00.000Z",
},
},
}

rolesResponse, err := ListOrganizationRoles(context.Background(), ListOrganizationRolesOpts{
OrganizationID: "organization_id",
})

require.NoError(t, err)
require.Equal(t, expectedResponse, rolesResponse)
}
15 changes: 15 additions & 0 deletions pkg/roles/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# roles

[![Go Report Card](https://img.shields.io/badge/dev-reference-007d9c?logo=go&logoColor=white&style=flat)](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 API reference](https://workos.com/docs/reference/roles).
32 changes: 32 additions & 0 deletions pkg/roles/client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package roles

// 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"`
}

0 comments on commit 7036673

Please sign in to comment.