Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add GET /organization/:orgId/roles support #388

Merged
merged 1 commit into from
Jan 2, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Planning to have APIs housed in this package eventually, but for now it just holds the roles types.


[![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"`
}
Loading