From e5693c5b590b02be5d62c0d3dfa2d035ae359c97 Mon Sep 17 00:00:00 2001 From: "David R. Bild" Date: Sun, 19 Apr 2020 10:09:19 -0500 Subject: [PATCH 1/5] enf: support query parameters for delete calls --- enf/dns_zone.go | 2 +- enf/enf.go | 6 +++++- enf/firewall.go | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/enf/dns_zone.go b/enf/dns_zone.go index 283c41b..487d61b 100644 --- a/enf/dns_zone.go +++ b/enf/dns_zone.go @@ -87,7 +87,7 @@ func (s *DNSService) UpdateZone(ctx context.Context, zoneUUID string, req *Updat // DeleteZone deletes a zone given its UUID. func (s *DNSService) DeleteZone(ctx context.Context, zoneUUID string) (*http.Response, error) { path := fmt.Sprintf("api/xdns/2019-05-27/zones/%v", zoneUUID) - resp, err := s.client.delete(ctx, path) + resp, err := s.client.delete(ctx, path, url.Values{}) if err != nil { return resp, err } diff --git a/enf/enf.go b/enf/enf.go index 6b1ab19..45814bd 100644 --- a/enf/enf.go +++ b/enf/enf.go @@ -101,11 +101,15 @@ func (c *Client) put(ctx context.Context, path string, body interface{}, fields } // delete makes delete requests to the given path. -func (c *Client) delete(ctx context.Context, path string) (*http.Response, error) { +func (c *Client) delete(ctx context.Context, path string, queryParameters url.Values) (*http.Response, error) { req, err := c.NewRequest("DELETE", path, nil) if err != nil { return nil, err } + + // Add the query parameters to the request URL. + req.URL.RawQuery = queryParameters.Encode() + return c.Do(ctx, req, nil) } diff --git a/enf/firewall.go b/enf/firewall.go index f418930..c81f977 100644 --- a/enf/firewall.go +++ b/enf/firewall.go @@ -86,5 +86,5 @@ func (s *FirewallService) CreateRule(ctx context.Context, network string, rule * // DeleteRule deletes the firewall rule associated with the given network address and ID. func (s *FirewallService) DeleteRule(ctx context.Context, network string, id string) (*http.Response, error) { path := fmt.Sprintf("api/xfw/v1/%v/rule/%v", network, id) - return s.client.delete(ctx, path) + return s.client.delete(ctx, path, url.Values{}) } From 18fbebcc8b77f839f9c7e742e561a163cbb91570 Mon Sep 17 00:00:00 2001 From: "David R. Bild" Date: Sun, 19 Apr 2020 01:35:49 -0500 Subject: [PATCH 2/5] user: add use roles resource from API v3 --- enf/user_role.go | 90 ++++++++++++++++++++ enf/user_role_test.go | 191 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 281 insertions(+) create mode 100644 enf/user_role.go create mode 100644 enf/user_role_test.go diff --git a/enf/user_role.go b/enf/user_role.go new file mode 100644 index 0000000..64a9ab2 --- /dev/null +++ b/enf/user_role.go @@ -0,0 +1,90 @@ +package enf + +import ( + "context" + "fmt" + "net/http" + "net/url" + "strings" +) + +// UserRole represents an ENF user role. +type UserRole struct { + CIDR *string `json:"cidr"` + Role *string `json:"role"` +} + +// DeleteUserRolesQuery represents the query parameters to delete some +// of a user's roles. +type DeleteUserRolesQuery struct { + roles []string + network *string +} + +type userRoleResponse struct { + Data []*UserRole `json:"data"` + Page map[string]interface{} `json:"page"` +} + +// ListUserRoles get the list of roles for the given user. +func (s *UserService) ListUserRoles(ctx context.Context, userID int) ([]*UserRole, *http.Response, error) { + path := fmt.Sprintf("api/xcr/v3/users/%v/roles", userID) + body, resp, err := s.client.get(ctx, path, url.Values{}, new(userRoleResponse)) + if err != nil { + return nil, resp, err + } + + return body.(*userRoleResponse).Data, resp, nil +} + +// AppendUserRoles adds roles to the user +func (s *UserService) AppendUserRoles(ctx context.Context, userID int, roles []UserRole) ([]*UserRole, *http.Response, error) { + path := fmt.Sprintf("api/xcr/v3/users/%v/roles", userID) + body, resp, err := s.client.post(ctx, path, new(userRoleResponse), roles) + if err != nil { + return nil, resp, err + } + + return body.(*userRoleResponse).Data, resp, nil +} + +// ReplaceUserRoles replaces all roles for the user +func (s *UserService) ReplaceUserRoles(ctx context.Context, userID int, roles []UserRole) ([]*UserRole, *http.Response, error) { + path := fmt.Sprintf("api/xcr/v3/users/%v/roles", userID) + body, resp, err := s.client.put(ctx, path, new(userRoleResponse), roles) + if err != nil { + return nil, resp, err + } + + return body.(*userRoleResponse).Data, resp, nil +} + +// DeleteUserRolesQuery deletes the roles for given user that match the specified query +func (s *UserService) DeleteUserRolesWithQuery(ctx context.Context, userID int, query DeleteUserRolesQuery) (*http.Response, error) { + path := fmt.Sprintf("api/xcr/v3/users/%v/roles", userID) + + queryParameters := url.Values{} + queryParameters.Add("roles", strings.Join(query.roles, ",")) + if query.network != nil { + queryParameters.Add("network_cidr", *query.network) + } + + resp, err := s.client.delete(ctx, path, queryParameters) + if err != nil { + return resp, err + } + + return resp, nil +} + +// DeleteUserRoles deletes all roles from the given user +func (s *UserService) DeleteUserRoles(ctx context.Context, userID int) (*http.Response, error) { + path := fmt.Sprintf("api/xcr/v3/users/%v/roles", userID) + + resp, err := s.client.delete(ctx, path, url.Values{}) + if err != nil { + return resp, err + } + + return resp, nil +} diff --git a/enf/user_role_test.go b/enf/user_role_test.go new file mode 100644 index 0000000..2ea7a33 --- /dev/null +++ b/enf/user_role_test.go @@ -0,0 +1,191 @@ +package enf + +import ( + "context" + "net/http" + "testing" +) + +func TestUserService_ListUserRoles(t *testing.T) { + path := "/api/xcr/v3/users/1/roles" + + responseBodyMock := `{ + "data": [ + { + "cidr": "D/d0", + "role": "DOMAIN_ADMIN" + }, + { + "cidr": "N/n0", + "role": "NETWORK_USER" + } + ] + }` + + expected := []*UserRole{ + { + CIDR: String("D/d0"), + Role: String("DOMAIN_ADMIN"), + }, + { + CIDR: String("N/n0"), + Role: String("NETWORK_USER"), + }, + } + + method := func(client *Client) (interface{}, *http.Response, error) { + return client.User.ListUserRoles(context.Background(), 1) + } + + testParams := &TestParams{ + Path: path, + RequestBody: struct{}{}, + ResponseBodyMock: responseBodyMock, + Expected: expected, + Method: method, + T: t, + } + + getTest(testParams) +} + +func TestUserService_AppendUserRoles(t *testing.T) { + path := "/api/xcr/v3/users/1/roles" + + requestBody := []UserRole{ + {String("N/n0"), String("NETWORK_USER")}, + } + + responseBodyMock := `{ + "data": [ + { + "cidr": "D/d0", + "role": "DOMAIN_ADMIN" + }, + { + "cidr": "N/n0", + "role": "NETWORK_USER" + } + ] + }` + + expected := []*UserRole{ + { + CIDR: String("D/d0"), + Role: String("DOMAIN_ADMIN"), + }, + { + CIDR: String("N/n0"), + Role: String("NETWORK_USER"), + }, + } + + method := func(client *Client) (interface{}, *http.Response, error) { + return client.User.AppendUserRoles(context.Background(), 1, requestBody) + } + + testParams := &TestParams{ + Path: path, + RequestBody: requestBody, + ResponseBodyMock: responseBodyMock, + Expected: expected, + Method: method, + T: t, + } + + postTest(testParams) +} + +func TestUserService_ReplaceUserRoles(t *testing.T) { + path := "/api/xcr/v3/users/1/roles" + + requestBody := []UserRole{ + {String("D/d0"), String("DOMAIN_ADMIN")}, + {String("N/n0"), String("NETWORK_USER")}, + } + + responseBodyMock := `{ + "data": [ + { + "cidr": "D/d0", + "role": "DOMAIN_ADMIN" + }, + { + "cidr": "N/n0", + "role": "NETWORK_USER" + } + ] + }` + + expected := []*UserRole{ + { + CIDR: String("D/d0"), + Role: String("DOMAIN_ADMIN"), + }, + { + CIDR: String("N/n0"), + Role: String("NETWORK_USER"), + }, + } + + method := func(client *Client) (interface{}, *http.Response, error) { + return client.User.ReplaceUserRoles(context.Background(), 1, requestBody) + } + + testParams := &TestParams{ + Path: path, + RequestBody: requestBody, + ResponseBodyMock: responseBodyMock, + Expected: expected, + Method: method, + T: t, + } + + putTest(testParams) +} + +func TestUserService_DeleteUserRoles(t *testing.T) { + path := "/api/xcr/v3/users/1/roles" + + responseBodyMock := `[]` + + method := func(client *Client) (interface{}, *http.Response, error) { + resp, err := client.User.DeleteUserRoles(context.Background(), 1) + return struct{}{}, resp, err + } + + testParams := &TestParams{ + Path: path, + RequestBody: struct{}{}, + ResponseBodyMock: responseBodyMock, + Expected: struct{}{}, + Method: method, + T: t, + } + + deleteTest(testParams) +} + +func TestUserService_DeleteUserRolesWithQuery(t *testing.T) { + path := "/api/xcr/v3/users/1/roles" + + responseBodyMock := `[]` + + query := DeleteUserRolesQuery{[]string{"DOMAIN_*", "*_ADMIN"}, nil} + + method := func(client *Client) (interface{}, *http.Response, error) { + resp, err := client.User.DeleteUserRolesWithQuery(context.Background(), 1, query) + return struct{}{}, resp, err + } + + testParams := &TestParams{ + Path: path, + RequestBody: struct{}{}, + ResponseBodyMock: responseBodyMock, + Expected: struct{}{}, + Method: method, + T: t, + } + + deleteTest(testParams) +} From d41f442a51d8d29b0f917ae6532455fef1c1fdf1 Mon Sep 17 00:00:00 2001 From: "David R. Bild" Date: Sun, 19 Apr 2020 01:48:45 -0500 Subject: [PATCH 3/5] user: update user resource to API v3 --- enf/user.go | 71 ++++++++++++++++------ enf/user_test.go | 154 +++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 194 insertions(+), 31 deletions(-) diff --git a/enf/user.go b/enf/user.go index f52b537..6465d56 100644 --- a/enf/user.go +++ b/enf/user.go @@ -15,16 +15,17 @@ type UserService service // User represents an ENF user. type User struct { - UserID *int `json:"user_id"` - Username *string `json:"username"` - Description *string `json:"description"` - FullName *string `json:"full_name"` - LastLogin *time.Time `json:"last_login"` - DomainID *int `json:"domain_id"` - Type *string `json:"type"` - ResetCode *string `json:"reset_code"` - ResetTime *time.Time `json:"reset_time"` - Status *string `json:"status"` + UserID *int `json:"user_id"` + Username *string `json:"username"` + Description *string `json:"description"` + FullName *string `json:"full_name"` + LastLogin *time.Time `json:"last_login"` + Domain *string `json:"domain"` + DomainID *int `json:"domain_id"` + Roles []*UserRole `json:"roles"` + ResetCode *string `json:"reset_code"` + ResetTime *time.Time `json:"reset_time"` + Status *string `json:"status"` } // UpdateUserStatusRequest represents the body of the request to update a user's status. @@ -46,9 +47,10 @@ type userResponse struct { type emptyResponse []interface{} -// ListUsersForDomainAddress gets the list of users for a given domain address. -func (s *UserService) ListUsersForDomainAddress(ctx context.Context, address string) ([]*User, *http.Response, error) { - path := fmt.Sprintf("api/xcr/v2/domains/%v/users", address) +// ListUsers gets the list of all users. +func (s *UserService) ListUsers(ctx context.Context) ([]*User, *http.Response, error) { + path := fmt.Sprintf("api/xcr/v3/users") + body, resp, err := s.client.get(ctx, path, url.Values{}, new(userResponse)) if err != nil { return nil, resp, err @@ -57,10 +59,29 @@ func (s *UserService) ListUsersForDomainAddress(ctx context.Context, address str return body.(*userResponse).Data, resp, nil } -// ListUsersForDomainID gets a list of users for a given unique domain identifier. -func (s *UserService) ListUsersForDomainID(ctx context.Context, id string) ([]*User, *http.Response, error) { - path := fmt.Sprintf("api/xcr/v2/domains/%v/users", id) - body, resp, err := s.client.get(ctx, path, url.Values{}, new(userResponse)) +// ListUsersForDomain gets the list of users with roles in a given domain. +func (s *UserService) ListUsersForDomain(ctx context.Context, domain string) ([]*User, *http.Response, error) { + path := fmt.Sprintf("api/xcr/v3/users") + + queryParameters := url.Values{} + queryParameters.Add("domain", domain) + + body, resp, err := s.client.get(ctx, path, queryParameters, new(userResponse)) + if err != nil { + return nil, resp, err + } + + return body.(*userResponse).Data, resp, nil +} + +// ListUsersForNetwork gets the list of users with roles in a given network. +func (s *UserService) ListUsersForNetwork(ctx context.Context, network string) ([]*User, *http.Response, error) { + path := fmt.Sprintf("api/xcr/v3/users") + + queryParameters := url.Values{} + queryParameters.Add("network", network) + + body, resp, err := s.client.get(ctx, path, queryParameters, new(userResponse)) if err != nil { return nil, resp, err } @@ -68,9 +89,19 @@ func (s *UserService) ListUsersForDomainID(ctx context.Context, id string) ([]*U return body.(*userResponse).Data, resp, nil } +func (s *UserService) GetUser(ctx context.Context, userID int) (*User, *http.Response, error) { + path := fmt.Sprintf("api/xcr/v3/users/%v", userID) + body, resp, err := s.client.get(ctx, path, url.Values{}, new(userResponse)) + if err != nil { + return nil, resp, err + } + + return body.(*userResponse).Data[0], resp, nil +} + // UpdateUserStatus updates the status of a user to "ACTIVE" or "INACTIVE". func (s *UserService) UpdateUserStatus(ctx context.Context, userID int, updateUserStatusRequest *UpdateUserStatusRequest) (*http.Response, error) { - path := fmt.Sprintf("api/xcr/v2/users/%v/status", userID) + path := fmt.Sprintf("api/xcr/v3/users/%v/status", userID) _, resp, err := s.client.put(ctx, path, new(emptyResponse), updateUserStatusRequest) if err != nil { return resp, err @@ -81,7 +112,7 @@ func (s *UserService) UpdateUserStatus(ctx context.Context, userID int, updateUs // EmailResetPasswordCode emails a reset password code to the given email address. func (s *UserService) EmailResetPasswordCode(ctx context.Context, email string) (*http.Response, error) { - path := "api/xcr/v2/users/reset" + path := "api/xcr/v3/users/reset" queryParameters := url.Values{} queryParameters.Add("email", email) @@ -95,7 +126,7 @@ func (s *UserService) EmailResetPasswordCode(ctx context.Context, email string) // ResetPassword resets a user's password. func (s *UserService) ResetPassword(ctx context.Context, resetPasswordRequest *ResetPasswordRequest) (*http.Response, error) { - path := "api/xcr/v2/users/reset" + path := "api/xcr/v3/users/reset" _, resp, err := s.client.post(ctx, path, new(emptyResponse), resetPasswordRequest) if err != nil { return resp, err diff --git a/enf/user_test.go b/enf/user_test.go index 59c364b..1c00644 100644 --- a/enf/user_test.go +++ b/enf/user_test.go @@ -6,8 +6,8 @@ import ( "testing" ) -func TestUserService_ListUsersForDomainAddress(t *testing.T) { - path := "/api/xcr/v2/domains/N/users" +func TestUserService_ListUsers(t *testing.T) { + path := "/api/xcr/v3/users" responseBodyMock := `{ "data": [ @@ -15,6 +15,12 @@ func TestUserService_ListUsersForDomainAddress(t *testing.T) { "user_id": 1, "username": "user@acme", "full_name": "Xaptum User", + "roles": [ + { + "role" : "DOMAIN_USER", + "cidr" : "D/d0" + } + ], "status": "ACTIVE" } ] @@ -25,12 +31,18 @@ func TestUserService_ListUsersForDomainAddress(t *testing.T) { UserID: Int(1), Username: String("user@acme"), FullName: String("Xaptum User"), - Status: String("ACTIVE"), + Roles: []*UserRole{ + { + Role: String("DOMAIN_USER"), + CIDR: String("D/d0"), + }, + }, + Status: String("ACTIVE"), }, } method := func(client *Client) (interface{}, *http.Response, error) { - return client.User.ListUsersForDomainAddress(context.Background(), "N") + return client.User.ListUsers(context.Background()) } testParams := &TestParams{ @@ -45,8 +57,8 @@ func TestUserService_ListUsersForDomainAddress(t *testing.T) { getTest(testParams) } -func TestUserService_ListUsersForDomainID(t *testing.T) { - path := "/api/xcr/v2/domains/1/users" +func TestUserService_ListUsersForDomain(t *testing.T) { + path := "/api/xcr/v3/users" responseBodyMock := `{ "data": [ @@ -54,6 +66,12 @@ func TestUserService_ListUsersForDomainID(t *testing.T) { "user_id": 1, "username": "user@acme", "full_name": "Xaptum User", + "roles": [ + { + "role" : "DOMAIN_USER", + "cidr" : "D/d0" + } + ], "status": "ACTIVE" } ] @@ -64,12 +82,126 @@ func TestUserService_ListUsersForDomainID(t *testing.T) { UserID: Int(1), Username: String("user@acme"), FullName: String("Xaptum User"), - Status: String("ACTIVE"), + Roles: []*UserRole{ + { + Role: String("DOMAIN_USER"), + CIDR: String("D/d0"), + }, + }, + Status: String("ACTIVE"), }, } method := func(client *Client) (interface{}, *http.Response, error) { - return client.User.ListUsersForDomainID(context.Background(), "1") + return client.User.ListUsersForDomain(context.Background(), "D/d0") + } + + testParams := &TestParams{ + Path: path, + RequestBody: struct{}{}, + ResponseBodyMock: responseBodyMock, + Expected: expected, + Method: method, + T: t, + } + + getTest(testParams) +} + +func TestUserService_ListUsersForNetwork(t *testing.T) { + path := "/api/xcr/v3/users" + + responseBodyMock := `{ + "data": [ + { + "user_id": 1, + "username": "user@acme", + "full_name": "Xaptum User", + "roles": [ + { + "role" : "NETWORK_ADMIN", + "cidr" : "N/n0" + } + ], + "status": "ACTIVE" + } + ] + }` + + expected := []*User{ + { + UserID: Int(1), + Username: String("user@acme"), + FullName: String("Xaptum User"), + Roles: []*UserRole{ + { + Role: String("NETWORK_ADMIN"), + CIDR: String("N/n0"), + }, + }, + Status: String("ACTIVE"), + }, + } + + method := func(client *Client) (interface{}, *http.Response, error) { + return client.User.ListUsersForNetwork(context.Background(), "N/n0") + } + + testParams := &TestParams{ + Path: path, + RequestBody: struct{}{}, + ResponseBodyMock: responseBodyMock, + Expected: expected, + Method: method, + T: t, + } + + getTest(testParams) +} + +func TestUserService_GetUser(t *testing.T) { + path := "/api/xcr/v3/users/1" + + responseBodyMock := `{ + "data": [ + { + "user_id": 1, + "username": "user@acme", + "full_name": "Xaptum User", + "roles": [ + { + "role" : "DOMAIN_USER", + "cidr" : "D/d0" + }, + { + "role" : "NETWORK_ADMIN", + "cidr" : "N/n0" + } + ], + "status": "ACTIVE" + } + ] + }` + + expected := &User{ + UserID: Int(1), + Username: String("user@acme"), + FullName: String("Xaptum User"), + Roles: []*UserRole{ + { + Role: String("DOMAIN_USER"), + CIDR: String("D/d0"), + }, + { + Role: String("NETWORK_ADMIN"), + CIDR: String("N/n0"), + }, + }, + Status: String("ACTIVE"), + } + + method := func(client *Client) (interface{}, *http.Response, error) { + return client.User.GetUser(context.Background(), 1) } testParams := &TestParams{ @@ -85,7 +217,7 @@ func TestUserService_ListUsersForDomainID(t *testing.T) { } func TestUserService_UpdateUserStatus(t *testing.T) { - path := "/api/xcr/v2/users/61/status" + path := "/api/xcr/v3/users/61/status" requestBody := &UpdateUserStatusRequest{ Status: String("INACTIVE"), @@ -111,7 +243,7 @@ func TestUserService_UpdateUserStatus(t *testing.T) { } func TestUserService_EmailResetPasswordCode(t *testing.T) { - path := "/api/xcr/v2/users/reset" + path := "/api/xcr/v3/users/reset" responseBodyMock := `[]` @@ -133,7 +265,7 @@ func TestUserService_EmailResetPasswordCode(t *testing.T) { } func TestUserService_ResetPassword(t *testing.T) { - path := "/api/xcr/v2/users/reset" + path := "/api/xcr/v3/users/reset" requestBody := &ResetPasswordRequest{ Email: String("user@acme.com"), From 71ca1aff061686a11fad311cfad9043a5a366aff Mon Sep 17 00:00:00 2001 From: "David R. Bild" Date: Sun, 19 Apr 2020 10:09:34 -0500 Subject: [PATCH 4/5] user: update invite resource to API v3 --- enf/user_invite.go | 38 ++++++++++++++++++++------------------ enf/user_invite_test.go | 39 +++++++++++++++++++++++++-------------- 2 files changed, 45 insertions(+), 32 deletions(-) diff --git a/enf/user_invite.go b/enf/user_invite.go index b063182..66d3712 100644 --- a/enf/user_invite.go +++ b/enf/user_invite.go @@ -16,18 +16,20 @@ type Invite struct { ModifiedDate *time.Time `json:"modified_data"` Version *int `json:"version"` DomainID *int `json:"domain_id"` + Domain *string `json:"domain"` + Role *UserRole `json:"role"` Email *string `json:"email"` InviteToken *string `json:"invite_token"` InvitedBy *string `json:"invited_by"` Name *string `json:"name"` - Type *string `json:"type"` } // SendInviteRequest represents the body of the request to send an invite. type SendInviteRequest struct { - Email *string `json:"email"` - FullName *string `json:"full_name"` - UserType *string `json:"user_type"` + Email *string `json:"email"` + FullName *string `json:"full_name"` + Domain *string `json:"domain"` + Roles []*UserRole `json:"roles"` } // AcceptInviteRequest represents the body of the request to accept an invite. @@ -43,9 +45,9 @@ type inviteResponse struct { Page map[string]interface{} `json:"page"` } -// ListInvitesForDomainAddress gets a list of active invites for a given domain address. -func (s *UserService) ListInvitesForDomainAddress(ctx context.Context, address string) ([]*Invite, *http.Response, error) { - path := fmt.Sprintf("api/xcr/v2/domains/%v/invites", address) +// ListInvites gets a list of active invites. +func (s *UserService) ListInvites(ctx context.Context) ([]*Invite, *http.Response, error) { + path := fmt.Sprintf("api/xcr/v3/invites") body, resp, err := s.client.get(ctx, path, url.Values{}, new(inviteResponse)) if err != nil { return nil, resp, err @@ -54,9 +56,9 @@ func (s *UserService) ListInvitesForDomainAddress(ctx context.Context, address s return body.(*inviteResponse).Data, resp, nil } -// SendNewInvite sends a new invite for a user to join the domain with the given address. -func (s *UserService) SendNewInvite(ctx context.Context, address string, inviteRequest *SendInviteRequest) (*Invite, *http.Response, error) { - path := fmt.Sprintf("api/xcr/v2/domains/%v/invites", address) +// SendInvite sends an invite for a new user. +func (s *UserService) SendInvite(ctx context.Context, inviteRequest *SendInviteRequest) (*Invite, *http.Response, error) { + path := fmt.Sprintf("api/xcr/v3/invites") body, resp, err := s.client.post(ctx, path, new(inviteResponse), inviteRequest) if err != nil { return nil, resp, err @@ -67,7 +69,7 @@ func (s *UserService) SendNewInvite(ctx context.Context, address string, inviteR // AcceptInvite accepts an invite. func (s *UserService) AcceptInvite(ctx context.Context, acceptInviteRequest *AcceptInviteRequest) (*http.Response, error) { - path := "api/xcr/v2/users/invites" + path := "api/xcr/v3/invites" _, resp, err := s.client.post(ctx, path, new(emptyResponse), acceptInviteRequest) if err != nil { return resp, err @@ -76,9 +78,9 @@ func (s *UserService) AcceptInvite(ctx context.Context, acceptInviteRequest *Acc return resp, nil } -// ResendInvite resends an invite to the given email address. -func (s *UserService) ResendInvite(ctx context.Context, email string) (*http.Response, error) { - path := fmt.Sprintf("api/xcr/v2/invites/%v", email) +// ResendInvite resends the given invite. +func (s *UserService) ResendInvite(ctx context.Context, id int) (*http.Response, error) { + path := fmt.Sprintf("api/xcr/v3/invites/%v", id) _, resp, err := s.client.put(ctx, path, new(emptyResponse), struct{}{}) if err != nil { return resp, err @@ -87,10 +89,10 @@ func (s *UserService) ResendInvite(ctx context.Context, email string) (*http.Res return resp, nil } -// DeleteInvite deletes an invite to the given email address. -func (s *UserService) DeleteInvite(ctx context.Context, email string) (*http.Response, error) { - path := fmt.Sprintf("api/xcr/v2/invites/%v", email) - resp, err := s.client.delete(ctx, path) +// DeleteInvite deletes the given invite +func (s *UserService) DeleteInvite(ctx context.Context, id int) (*http.Response, error) { + path := fmt.Sprintf("api/xcr/v3/invites/%v", id) + resp, err := s.client.delete(ctx, path, url.Values{}) if err != nil { return resp, err } diff --git a/enf/user_invite_test.go b/enf/user_invite_test.go index aad5a74..f888924 100644 --- a/enf/user_invite_test.go +++ b/enf/user_invite_test.go @@ -6,8 +6,8 @@ import ( "testing" ) -func TestUserService_ListInvitesForDomainAddress(t *testing.T) { - path := "/api/xcr/v2/domains/1/invites" +func TestUserService_ListInvites(t *testing.T) { + path := "/api/xcr/v3/invites" responseBodyMock := `{ "data": [ @@ -30,7 +30,7 @@ func TestUserService_ListInvitesForDomainAddress(t *testing.T) { } method := func(client *Client) (interface{}, *http.Response, error) { - return client.User.ListInvitesForDomainAddress(context.Background(), "1") + return client.User.ListInvites(context.Background()) } testParams := &TestParams{ @@ -45,13 +45,18 @@ func TestUserService_ListInvitesForDomainAddress(t *testing.T) { getTest(testParams) } -func TestUserService_SendNewInvite(t *testing.T) { - path := "/api/xcr/v2/domains/1/invites" +func TestUserService_SendInvite(t *testing.T) { + path := "/api/xcr/v3/invites" requestBody := &SendInviteRequest{ Email: String("user@acme.com"), FullName: String("Xaptum User"), - UserType: String("DOMAIN_USER"), + Roles: []*UserRole{ + { + CIDR: String("D/d0"), + Role: String("DOMAIN_USER"), + }, + }, } responseBodyMock := `{ @@ -60,7 +65,10 @@ func TestUserService_SendNewInvite(t *testing.T) { "id": 1, "email": "user@acme.com", "name": "Xaptum User", - "type": "DOMAIN_USER" + "role": { + "cidr" : "D/d0", + "role" : "DOMAIN_USER" + } } ] }` @@ -69,11 +77,14 @@ func TestUserService_SendNewInvite(t *testing.T) { ID: Int(1), Email: String("user@acme.com"), Name: String("Xaptum User"), - Type: String("DOMAIN_USER"), + Role: &UserRole{ + CIDR: String("D/d0"), + Role: String("DOMAIN_USER"), + }, } method := func(client *Client) (interface{}, *http.Response, error) { - return client.User.SendNewInvite(context.Background(), "1", requestBody) + return client.User.SendInvite(context.Background(), requestBody) } testParams := &TestParams{ @@ -89,7 +100,7 @@ func TestUserService_SendNewInvite(t *testing.T) { } func TestUserService_AcceptInvite(t *testing.T) { - path := "/api/xcr/v2/users/invites" + path := "/api/xcr/v3/invites" requestBody := &AcceptInviteRequest{ Email: String("user@acme.com"), @@ -117,12 +128,12 @@ func TestUserService_AcceptInvite(t *testing.T) { } func TestUserService_ResendInvite(t *testing.T) { - path := "/api/xcr/v2/invites/user@acme.com" + path := "/api/xcr/v3/invites/1" responseBodyMock := `[]` method := func(client *Client) (interface{}, *http.Response, error) { - resp, err := client.User.ResendInvite(context.Background(), "user@acme.com") + resp, err := client.User.ResendInvite(context.Background(), 1) return struct{}{}, resp, err } @@ -139,12 +150,12 @@ func TestUserService_ResendInvite(t *testing.T) { } func TestUserService_DeleteInvite(t *testing.T) { - path := "/api/xcr/v2/invites/user@acme.com" + path := "/api/xcr/v3/invites/1" responseBodyMock := `[]` method := func(client *Client) (interface{}, *http.Response, error) { - resp, err := client.User.DeleteInvite(context.Background(), "user@acme.com") + resp, err := client.User.DeleteInvite(context.Background(), 1) return struct{}{}, resp, err } From b3dcd1e70bd00637bedf210879cbb52930c179d4 Mon Sep 17 00:00:00 2001 From: "David R. Bild" Date: Sun, 19 Apr 2020 11:04:14 -0500 Subject: [PATCH 5/5] auth: update auth resource to API v3 --- enf/auth.go | 14 +++++++------- enf/auth_test.go | 19 +++++++++++++++---- 2 files changed, 22 insertions(+), 11 deletions(-) diff --git a/enf/auth.go b/enf/auth.go index e5916eb..70dbcd3 100644 --- a/enf/auth.go +++ b/enf/auth.go @@ -26,12 +26,12 @@ type AuthRequest struct { // Credentials represents the authentication credentials returned by // the auth API. type Credentials struct { - Username *string `json:"username"` - Token *string `json:"token"` - UserID *int64 `json:"user_id"` - UserType *string `json:"type"` - DomainID *int64 `json:"domain_id"` - DomainNetwork *string `json:"domain_network"` + Username *string `json:"username"` + Token *string `json:"token"` + UserID *int64 `json:"user_id"` + Roles []*UserRole `json:"roles"` + DomainID *int64 `json:"domain_id"` + Domain *string `json:"domain"` } type authResponse struct { @@ -49,7 +49,7 @@ func (s *AuthService) Authenticate(ctx context.Context, authReq *AuthRequest) (* return nil, nil, ErrMissingPassword } - endpoint := "/api/xcr/v2/xauth" + endpoint := "/api/xcr/v3/xauth" body, resp, err := s.client.post(ctx, endpoint, new(authResponse), authReq) if err != nil { diff --git a/enf/auth_test.go b/enf/auth_test.go index 7804629..29dc821 100644 --- a/enf/auth_test.go +++ b/enf/auth_test.go @@ -7,7 +7,7 @@ import ( ) func TestAuthService_Authenticate(t *testing.T) { - path := "/api/xcr/v2/xauth" + path := "/api/xcr/v3/xauth" requestBody := &AuthRequest{ Username: String("user"), @@ -19,18 +19,29 @@ func TestAuthService_Authenticate(t *testing.T) { { "username":"user", "token":"12345678", - "user_id":1 + "user_id":1, + "roles": [ + { + "cidr" : "N/n0", + "role" : "NETWORK_USER" + } + ] } ], "page": { - - } + } }` expected := &Credentials{ Username: String("user"), Token: String("12345678"), UserID: Int64(1), + Roles: []*UserRole{ + { + CIDR: String("N/n0"), + Role: String("NETWORK_USER"), + }, + }, } method := func(client *Client) (interface{}, *http.Response, error) {