-
Notifications
You must be signed in to change notification settings - Fork 20
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
ORGS-205: Update GO SDK to support organization domains crud (#326)
* feat: implement organization domains CRUD * linter * Apply suggestions from code review Co-authored-by: Giannis Katsanos <[email protected]> * code review * refactor: ensure the same pattern is being followed --------- Co-authored-by: Giannis Katsanos <[email protected]>
- Loading branch information
1 parent
807c124
commit ff233cb
Showing
4 changed files
with
368 additions
and
0 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,29 @@ | ||
package clerk | ||
|
||
type OrganizationDomainVerification struct { | ||
Status string `json:"status"` | ||
Strategy string `json:"strategy"` | ||
Attempts int64 `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 *OrganizationDomainVerification `json:"verification"` | ||
TotalPendingInvitations int64 `json:"total_pending_invitations"` | ||
TotalPendingSuggestions int64 `json:"total_pending_suggestions"` | ||
CreatedAt int64 `json:"created_at"` | ||
UpdatedAt int64 `json:"updated_at"` | ||
} | ||
|
||
type OrganizationDomainList struct { | ||
APIResource | ||
OrganizationDomains []*OrganizationDomain `json:"data"` | ||
TotalCount int64 `json:"total_count"` | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
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,120 @@ | ||
// 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 { | ||
clerk.APIParams | ||
Name *string `json:"name,omitempty"` | ||
EnrollmentMode *string `json:"enrollment_mode,omitempty"` | ||
Verified *bool `json:"verified,omitempty"` | ||
} | ||
|
||
// Create adds a new domain to the organization. | ||
func (c *Client) Create(ctx context.Context, organizationID string, params *CreateParams) (*clerk.OrganizationDomain, error) { | ||
path, err := clerk.JoinPath(path, 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 { | ||
clerk.APIParams | ||
OrganizationID string `json:"-"` | ||
DomainID string `json:"-"` | ||
EnrollmentMode *string `json:"enrollment_mode,omitempty"` | ||
Verified *bool `json:"verified,omitempty"` | ||
} | ||
|
||
// Update updates an organization domain. | ||
func (c *Client) Update(ctx context.Context, params *UpdateParams) (*clerk.OrganizationDomain, error) { | ||
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 | ||
Verified *bool `json:"verified,omitempty"` | ||
EnrollmentModes *[]string `json:"enrollment_mode,omitempty"` | ||
} | ||
|
||
// 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 params.EnrollmentModes != nil && 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, organizationID string, params *ListParams) (*clerk.OrganizationDomainList, error) { | ||
path, err := clerk.JoinPath(path, 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 | ||
} |
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,184 @@ | ||
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(), organizationID, &CreateParams{ | ||
Name: clerk.String(domain), | ||
EnrollmentMode: clerk.String("automatic_invitation"), | ||
Verified: clerk.Bool(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(), "org_123", &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}`, 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: clerk.Bool(verified), | ||
}) | ||
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{ | ||
Verified: &verified, | ||
EnrollmentModes: &[]string{"automatic_invitation"}, | ||
} | ||
params.Limit = clerk.Int64(1) | ||
params.Offset = clerk.Int64(2) | ||
list, err := client.List(context.Background(), organizationID, params) | ||
require.NoError(t, err) | ||
require.Equal(t, id, list.OrganizationDomains[0].ID) | ||
require.Equal(t, organizationID, list.OrganizationDomains[0].OrganizationID) | ||
} |