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

ORGS-205: Update GO SDK to support organization domains crud #326

Merged
Show file tree
Hide file tree
Changes from 2 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
29 changes: 29 additions & 0 deletions organization_domain.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package clerk

type organizationDomainVerificationResponse struct {
NicolasLopes7 marked this conversation as resolved.
Show resolved Hide resolved
Status string `json:"status"`
Strategy string `json:"strategy"`
Attempts *int `json:"attempts"`
ExpireAt *int64 `json:"expire_at"`
}

type OrganizationDomain struct {
APIResource
Object string `json:"object"`
ID string `json:"id"`
OrganizationID string `json:"organization_id"`
Name string `json:"name"`
EnrollmentMode string `json:"enrollment_mode"`
AffiliationEmailAddress *string `json:"affiliation_email_address"`
Verification *organizationDomainVerificationResponse `json:"verification"`
TotalPendingInvitations int `json:"total_pending_invitations"`
TotalPendingSuggestions int `json:"total_pending_suggestions"`
CreatedAt int64 `json:"created_at"`
UpdatedAt int64
NicolasLopes7 marked this conversation as resolved.
Show resolved Hide resolved
}

type OrganizationDomainList struct {
APIResource
OrganizationDomains []*OrganizationDomain `json:"data"`
TotalCount int64 `json:"total_count"`
}
35 changes: 35 additions & 0 deletions organizationdomain/api.go

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

122 changes: 122 additions & 0 deletions organizationdomain/client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
// Package organizationdomain provides the Organization Domains API.
package organizationdomain

import (
"context"
"net/http"
"net/url"
"strconv"

"github.com/clerk/clerk-sdk-go/v2"
)

//go:generate go run ../cmd/gen/main.go

const path = "/organizations"

// Client is used to invoke the Organization Domains API.
type Client struct {
Backend clerk.Backend
}

func NewClient(config *clerk.ClientConfig) *Client {
return &Client{
Backend: clerk.NewBackend(&config.BackendConfig),
}
}

type CreateParams struct {
NicolasLopes7 marked this conversation as resolved.
Show resolved Hide resolved
clerk.APIParams
Name string `json:"name" form:"name"`
NicolasLopes7 marked this conversation as resolved.
Show resolved Hide resolved
OrganizationID string `json:"-" form:"-"`
NicolasLopes7 marked this conversation as resolved.
Show resolved Hide resolved
EnrollmentMode string `json:"enrollment_mode" form:"enrollment_mode"`
Verified *bool `json:"verified" form:"verified"`
}

// Create adds a new domain to the organization.
func (c *Client) Create(ctx context.Context, params *CreateParams) (*clerk.OrganizationDomain, error) {
path, err := clerk.JoinPath(path, params.OrganizationID, "/domains")
if err != nil {
return nil, err
}
req := clerk.NewAPIRequest(http.MethodPost, path)
req.SetParams(params)
domain := &clerk.OrganizationDomain{}
err = c.Backend.Call(ctx, req, domain)
return domain, err
}

type UpdateParams struct {
NicolasLopes7 marked this conversation as resolved.
Show resolved Hide resolved
clerk.APIParams
OrganizationID string `json:"-" form:"-"`
NicolasLopes7 marked this conversation as resolved.
Show resolved Hide resolved
DomainID string `json:"-" form:"-"`
EnrollmentMode *string `json:"enrollment_mode" form:"enrollment_mode"`
Verified *bool `json:"verified" form:"verified"`
NicolasLopes7 marked this conversation as resolved.
Show resolved Hide resolved
}

// Update updates an organization domain.
func (c *Client) Update(ctx context.Context, params *UpdateParams) (*clerk.OrganizationDomain, error) {
NicolasLopes7 marked this conversation as resolved.
Show resolved Hide resolved
path, err := clerk.JoinPath(path, params.OrganizationID, "/domains", params.DomainID)
if err != nil {
return nil, err
}
req := clerk.NewAPIRequest(http.MethodPatch, path)
req.SetParams(params)
domain := &clerk.OrganizationDomain{}
err = c.Backend.Call(ctx, req, domain)
return domain, err
}

type DeleteParams struct {
clerk.APIParams
OrganizationID string `json:"-"`
DomainID string `json:"-"`
}

// Delete removes a domain from an organization.
func (c *Client) Delete(ctx context.Context, params *DeleteParams) (*clerk.DeletedResource, error) {
path, err := clerk.JoinPath(path, params.OrganizationID, "/domains", params.DomainID)
if err != nil {
return nil, err
}
req := clerk.NewAPIRequest(http.MethodDelete, path)
res := &clerk.DeletedResource{}
err = c.Backend.Call(ctx, req, res)
return res, err
}

type ListParams struct {
clerk.APIParams
clerk.ListParams
OrganizationID string `json:"-" form:"-"`
Verified *bool `json:"verified" form:"verified"`
EnrollmentModes []string `json:"enrollment_mode" form:"enrollment_mode"`
NicolasLopes7 marked this conversation as resolved.
Show resolved Hide resolved
}

// ToQuery returns the parameters as url.Values so they can be used
// in a URL query string.
func (params *ListParams) ToQuery() url.Values {
q := params.ListParams.ToQuery()

if params.Verified != nil {
q.Set("verified", strconv.FormatBool(*params.Verified))
}

if len(params.EnrollmentModes) > 0 {
q["enrollment_mode"] = params.EnrollmentModes
}
return q
}

// List returns a list of organization domains.
func (c *Client) List(ctx context.Context, params *ListParams) (*clerk.OrganizationDomainList, error) {
path, err := clerk.JoinPath(path, params.OrganizationID, "/domains")
if err != nil {
return nil, err
}
req := clerk.NewAPIRequest(http.MethodGet, path)
req.SetParams(params)
domains := &clerk.OrganizationDomainList{}
err = c.Backend.Call(ctx, req, domains)
return domains, err
}
187 changes: 187 additions & 0 deletions organizationdomain/client_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
package organizationdomain

import (
"context"
"encoding/json"
"fmt"
"net/http"
"net/url"
"strconv"
"testing"

"github.com/clerk/clerk-sdk-go/v2"
"github.com/clerk/clerk-sdk-go/v2/clerktest"
"github.com/stretchr/testify/require"
)

func TestOrganizationDomainClientCreate(t *testing.T) {
t.Parallel()
id := "orgdm_123"
organizationID := "org_123"
domain := "mydomain.com"
verified := false
config := &clerk.ClientConfig{}
config.HTTPClient = &http.Client{
Transport: &clerktest.RoundTripper{
T: t,
In: json.RawMessage(fmt.Sprintf(`{"name": "%s", "enrollment_mode": "automatic_invitation", "verified": %s}`, domain, strconv.FormatBool(verified))),
Out: json.RawMessage(fmt.Sprintf(`{"enrollment_mode":"automatic_invitation","id":"%s","name":"%s","object":"organization_domain","organization_id":"%s","verification":{"status":"unverified"}}`,
id, domain, organizationID)),
Method: http.MethodPost,
Path: "/v1/organizations/" + organizationID + "/domains",
},
}
client := NewClient(config)
response, err := client.Create(context.Background(), &CreateParams{
OrganizationID: organizationID,
Name: domain,
EnrollmentMode: "automatic_invitation",
Verified: &verified,
})
require.NoError(t, err)
require.Equal(t, id, response.ID)
require.Equal(t, domain, response.Name)
require.Equal(t, "automatic_invitation", response.EnrollmentMode)
require.Equal(t, "unverified", response.Verification.Status)
}

func TestOrganizationDomainClientCreate_Error(t *testing.T) {
t.Parallel()
config := &clerk.ClientConfig{}
config.HTTPClient = &http.Client{
Transport: &clerktest.RoundTripper{
T: t,
Status: http.StatusBadRequest,
Out: json.RawMessage(`{
"errors":[{
"code":"create-error-code"
}],
"clerk_trace_id":"create-trace-id"
}`),
},
}
client := NewClient(config)
_, err := client.Create(context.Background(), &CreateParams{})
require.Error(t, err)
apiErr, ok := err.(*clerk.APIErrorResponse)
require.True(t, ok)
require.Equal(t, "create-trace-id", apiErr.TraceID)
require.Equal(t, 1, len(apiErr.Errors))
require.Equal(t, "create-error-code", apiErr.Errors[0].Code)
}

func TestOrganizationDomainClientUpdate(t *testing.T) {
t.Parallel()
id := "orgdm_123"
organizationID := "org_123"
verified := true
config := &clerk.ClientConfig{}
config.HTTPClient = &http.Client{
Transport: &clerktest.RoundTripper{
T: t,
In: json.RawMessage(fmt.Sprintf(`{"verified": %s, "enrollment_mode": null}`, strconv.FormatBool(verified))),
Out: json.RawMessage(fmt.Sprintf(`{"id":"%s","verification":{"status": "verified"}}`, id)),
Method: http.MethodPatch,
Path: "/v1/organizations/" + organizationID + "/domains/" + id,
},
}
client := NewClient(config)
domain, err := client.Update(context.Background(), &UpdateParams{
OrganizationID: organizationID,
DomainID: id,
Verified: &verified,
EnrollmentMode: nil,
})
require.NoError(t, err)
require.Equal(t, id, domain.ID)
require.Equal(t, "verified", domain.Verification.Status)
}

func TestOrganizationDomainClientUpdate_Error(t *testing.T) {
t.Parallel()
config := &clerk.ClientConfig{}
config.HTTPClient = &http.Client{
Transport: &clerktest.RoundTripper{
T: t,
Status: http.StatusBadRequest,
Out: json.RawMessage(`{
"errors":[{
"code":"update-error-code"
}],
"clerk_trace_id":"update-trace-id"
}`),
},
}
client := NewClient(config)
_, err := client.Update(context.Background(), &UpdateParams{})
require.Error(t, err)
apiErr, ok := err.(*clerk.APIErrorResponse)
require.True(t, ok)
require.Equal(t, "update-trace-id", apiErr.TraceID)
require.Equal(t, 1, len(apiErr.Errors))
require.Equal(t, "update-error-code", apiErr.Errors[0].Code)
}

func TestOrganizationDomainClientDelete(t *testing.T) {
t.Parallel()
id := "orgdm_123"
organizationID := "org_123"
config := &clerk.ClientConfig{}
config.HTTPClient = &http.Client{
Transport: &clerktest.RoundTripper{
T: t,
Out: json.RawMessage(fmt.Sprintf(`{"id":"%s","object":"organization_domain"}`, id)),
Method: http.MethodDelete,
Path: "/v1/organizations/" + organizationID + "/domains/" + id,
},
}
client := NewClient(config)
deletedResource, err := client.Delete(context.Background(), &DeleteParams{
OrganizationID: organizationID,
DomainID: id,
})
require.NoError(t, err)
require.Equal(t, id, deletedResource.ID)
}

func TestOrganizationDomainClientList(t *testing.T) {
t.Parallel()
id := "orgdm_123"
domain := "mydomain.com"
organizationID := "org_123"
verified := true

config := &clerk.ClientConfig{}
config.HTTPClient = &http.Client{
Transport: &clerktest.RoundTripper{
T: t,
Out: json.RawMessage(fmt.Sprintf(`{
"data": [
{"enrollment_mode":"automatic_suggestion","id":"%s","name":"%s","object":"organization_domain","organization_id":"%s","verification":{"status":"unverified"}}
],
"total_count": 1
}`,
id, domain, organizationID)),
Method: http.MethodGet,
Path: "/v1/organizations/" + organizationID + "/domains",
Query: &url.Values{
"limit": []string{"1"},
"offset": []string{"2"},
"verified": []string{"true"},
"enrollment_mode": []string{"automatic_invitation"},
},
},
}
client := NewClient(config)
params := &ListParams{
OrganizationID: organizationID,
Verified: &verified,
EnrollmentModes: []string{"automatic_invitation"},
}
params.Limit = clerk.Int64(1)
params.Offset = clerk.Int64(2)
list, err := client.List(context.Background(), params)
require.NoError(t, err)
require.Equal(t, id, list.OrganizationDomains[0].ID)
require.Equal(t, organizationID, list.OrganizationDomains[0].OrganizationID)
}
Loading