Skip to content

Commit

Permalink
feat(account_members): Add CreateAccountMemberWithStatus
Browse files Browse the repository at this point in the history
The API call for adding members to an account optionally allows a status
field, which can be used to immediately accept an invitation.

The CreateAccountMemberWithStatus method has been added, replacing
CreateAccountMember and taking the extra status parameter, and
CreateAccountMember has been recreated as a wrapper for backwards
compatibility.
  • Loading branch information
jamesog committed Sep 29, 2021
1 parent 64630c8 commit 28df764
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 6 deletions.
24 changes: 18 additions & 6 deletions account_members.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,9 @@ type AccountMemberDetailResponse struct {
// AccountMemberInvitation represents the invitation for a new member to
// the account.
type AccountMemberInvitation struct {
Email string `json:"email"`
Roles []string `json:"roles"`
Email string `json:"email"`
Roles []string `json:"roles"`
Status string `json:"status,omitempty"`
}

// AccountMembers returns all members of an account.
Expand Down Expand Up @@ -89,19 +90,22 @@ func (api *API) AccountMembers(ctx context.Context, accountID string, pageOpts P
return accountMemberListresponse.Result, accountMemberListresponse.ResultInfo, nil
}

// CreateAccountMember invites a new member to join an account.
// CreateAccountMemberWithStatus invites a new member to join an account, allowing setting the status.
//
// Refer to the API reference for valid statuses.
//
// API reference: https://api.cloudflare.com/#account-members-add-member
func (api *API) CreateAccountMember(ctx context.Context, accountID string, emailAddress string, roles []string) (AccountMember, error) {
func (api *API) CreateAccountMemberWithStatus(ctx context.Context, accountID string, emailAddress string, roles []string, status string) (AccountMember, error) {
if accountID == "" {
return AccountMember{}, errors.New(errMissingAccountID)
}

uri := fmt.Sprintf("/accounts/%s/members", accountID)

var newMember = AccountMemberInvitation{
Email: emailAddress,
Roles: roles,
Email: emailAddress,
Roles: roles,
Status: status,
}
res, err := api.makeRequestContext(ctx, http.MethodPost, uri, newMember)
if err != nil {
Expand All @@ -117,6 +121,14 @@ func (api *API) CreateAccountMember(ctx context.Context, accountID string, email
return accountMemberListResponse.Result, nil
}

// CreateAccountMember invites a new member to join an account.
// The member will be placed into "pending" status and receive an email confirmation.
//
// API reference: https://api.cloudflare.com/#account-members-add-member
func (api *API) CreateAccountMember(ctx context.Context, accountID string, emailAddress string, roles []string) (AccountMember, error) {
return api.CreateAccountMemberWithStatus(ctx, accountID, emailAddress, roles, "")
}

// DeleteAccountMember removes a member from an account.
//
// API reference: https://api.cloudflare.com/#account-members-remove-member
Expand Down
72 changes: 72 additions & 0 deletions account_members_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,27 @@ var expectedNewAccountMemberStruct = AccountMember{
},
}

var expectedNewAccountMemberAcceptedStruct = AccountMember{
ID: "4536bcfad5faccb111b47003c79917fa",
Code: "05dd05cce12bbed97c0d87cd78e89bc2fd41a6cee72f27f6fc84af2e45c0fac0",
User: AccountMemberUserDetails{
Email: "[email protected]",
TwoFactorAuthenticationEnabled: false,
},
Status: "accepted",
Roles: []AccountRole{
{
ID: "3536bcfad5faccb999b47003c79917fb",
Name: "Account Administrator",
Description: "Administrative access to the entire Account",
Permissions: map[string]AccountRolePermission{
"analytics": {Read: true, Edit: true},
"billing": {Read: true, Edit: true},
},
},
},
}

var newUpdatedAccountMemberStruct = AccountMember{
ID: "4536bcfad5faccb111b47003c79917fa",
Code: "05dd05cce12bbed97c0d87cd78e89bc2fd41a6cee72f27f6fc84af2e45c0fac0",
Expand Down Expand Up @@ -151,6 +172,57 @@ func TestAccountMembersWithoutAccountID(t *testing.T) {
}
}

func TestCreateAccountMemberWithStatus(t *testing.T) {
setup()
defer teardown()

handler := func(w http.ResponseWriter, r *http.Request) {
assert.Equal(t, http.MethodPost, r.Method, "Expected method 'POST', got %s", r.Method)
w.Header().Set("content-type", "application/json")
fmt.Fprintf(w, `{
"success": true,
"errors": [],
"messages": [],
"result": {
"id": "4536bcfad5faccb111b47003c79917fa",
"code": "05dd05cce12bbed97c0d87cd78e89bc2fd41a6cee72f27f6fc84af2e45c0fac0",
"user": {
"id": null,
"first_name": null,
"last_name": null,
"email": "[email protected]",
"two_factor_authentication_enabled": false
},
"status": "accepted",
"roles": [{
"id": "3536bcfad5faccb999b47003c79917fb",
"name": "Account Administrator",
"description": "Administrative access to the entire Account",
"permissions": {
"analytics": {
"read": true,
"edit": true
},
"billing": {
"read": true,
"edit": true
}
}
}]
}
}
`)
}

mux.HandleFunc("/accounts/01a7362d577a6c3019a474fd6f485823/members", handler)

actual, err := client.CreateAccountMemberWithStatus(context.Background(), "01a7362d577a6c3019a474fd6f485823", "[email protected]", []string{"3536bcfad5faccb999b47003c79917fb"}, "accepted")

if assert.NoError(t, err) {
assert.Equal(t, expectedNewAccountMemberAcceptedStruct, actual)
}
}

func TestCreateAccountMember(t *testing.T) {
setup()
defer teardown()
Expand Down

0 comments on commit 28df764

Please sign in to comment.