From fcf113462998ca8c7a988139e1f66d3f85774356 Mon Sep 17 00:00:00 2001 From: andreaangiolillo Date: Mon, 28 Jun 2021 14:10:00 +0200 Subject: [PATCH 1/8] CLOUDP-93381: Add Programmatic Invite Management for organization to the atlas go client --- mongodbatlas/organizations.go | 150 ++++++++++++++ mongodbatlas/organizations_test.go | 309 +++++++++++++++++++++++++++-- 2 files changed, 441 insertions(+), 18 deletions(-) diff --git a/mongodbatlas/organizations.go b/mongodbatlas/organizations.go index d023b2484..aa8c75a3b 100644 --- a/mongodbatlas/organizations.go +++ b/mongodbatlas/organizations.go @@ -22,6 +22,7 @@ import ( const ( orgsBasePath = "api/atlas/v1.0/orgs" + invitationBasePath = orgsBasePath + "/%s/invites" ) // OrganizationsService provides access to the organization related functions in the Atlas API. @@ -29,10 +30,15 @@ const ( // See more: https://docs.atlas.mongodb.com/reference/api/organizations/ type OrganizationsService interface { List(context.Context, *OrganizationsListOptions) (*Organizations, *Response, error) + ListUnacceptedInvitations(context.Context, string, *InvitationOptions) (*[]Invitation, *Response, error) Get(context.Context, string) (*Organization, *Response, error) + GetUnacceptedInvitation(context.Context, string, string) (*Invitation, *Response, error) Projects(context.Context, string, *ListOptions) (*Projects, *Response, error) Users(context.Context, string, *ListOptions) (*AtlasUsersResponse, *Response, error) Delete(context.Context, string) (*Response, error) + InviteUser(context.Context, *Invitation) (*Invitation, *Response, error) + UpdateInvitation(context.Context, *Invitation) (*Invitation, *Response, error) + DeleteInvitation(context.Context, string, string) (*Response, error) } // OrganizationsServiceOp provides an implementation of the OrganizationsService interface. @@ -62,6 +68,24 @@ type Organizations struct { TotalCount int `json:"totalCount"` } +// InvitationOptions filtering options for invitations. +type InvitationOptions struct { + Username string `url:"username,omitempty"` +} + +// Invitation represents the structure of an Invitation. +type Invitation struct { + ID string `json:"id,omitempty"` + OrgID string `json:"orgId,omitempty"` + OrgName string `json:"orgName,omitempty"` + CreatedAt string `json:"createdAt,omitempty"` + ExpiresAt string `json:"expiresAt,omitempty"` + InviterUserName string `json:"inviterUserName,omitempty"` + Username string `json:"username,omitempty"` + Roles []string `json:"roles,omitempty"` + TeamIDs []string `json:"teamIds,omitempty"` +} + // List gets all organizations. // // See more: https://docs.atlas.mongodb.com/reference/api/organization-get-all/ @@ -188,3 +212,129 @@ func (s *OrganizationsServiceOp) Delete(ctx context.Context, orgID string) (*Res return resp, err } + +// ListUnacceptedInvitations gets all unaccepted invitations to the specified Atlas organization. +// +// See more: https://docs.atlas.mongodb.com/reference/api/organization-get-invitations/ +func (s *OrganizationsServiceOp) ListUnacceptedInvitations(ctx context.Context, orgID string, opts *InvitationOptions) (*[]Invitation, *Response, error) { + if orgID == "" { + return nil, nil, NewArgError("orgID", "must be set") + } + + basePath := fmt.Sprintf(invitationBasePath, orgID) + path, err := setListOptions(basePath, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.Client.NewRequest(ctx, http.MethodGet, path, nil) + if err != nil { + return nil, nil, err + } + + root := new([]Invitation) + resp, err := s.Client.Do(ctx, req, root) + if err != nil { + return nil, resp, err + } + + return root, resp, nil +} + +// GetUnacceptedInvitation gets details for one unaccepted invitation to the specified Atlas organization. +// +// See more: https://docs.atlas.mongodb.com/reference/api/organization-get-one-invitation/ +func (s *OrganizationsServiceOp) GetUnacceptedInvitation(ctx context.Context, orgID, invitationID string) (*Invitation, *Response, error) { + if orgID == "" { + return nil, nil, NewArgError("orgID", "must be set") + } + + basePath := fmt.Sprintf(invitationBasePath, orgID) + path := fmt.Sprintf("%s/%s", basePath, invitationID) + + req, err := s.Client.NewRequest(ctx, http.MethodGet, path, nil) + if err != nil { + return nil, nil, err + } + + root := new(Invitation) + resp, err := s.Client.Do(ctx, req, root) + if err != nil { + return nil, resp, err + } + + return root, resp, nil +} + +// InviteUser invites one user to the Atlas organization that you specify. +// +// See more: https://docs-atlas-staging.mongodb.com/cloud-docs/docsworker-xlarge/DOCSP-14695/reference/api/organization-create-one-invitation/ +func (s *OrganizationsServiceOp) InviteUser(ctx context.Context, invitation *Invitation) (*Invitation, *Response, error) { + if invitation.OrgID == "" { + return nil, nil, NewArgError("orgID", "must be set") + } + + path := fmt.Sprintf(invitationBasePath, invitation.OrgID) + + req, err := s.Client.NewRequest(ctx, http.MethodPost, path, invitation) + if err != nil { + return nil, nil, err + } + + root := new(Invitation) + resp, err := s.Client.Do(ctx, req, root) + if err != nil { + return nil, resp, err + } + + return root, resp, nil +} + +// InviteUser invites one user to the Atlas organization that you specify. +// +// See more: https://docs-atlas-staging.mongodb.com/cloud-docs/docsworker-xlarge/DOCSP-14695/reference/api/organization-create-one-invitation/ +func (s *OrganizationsServiceOp) UpdateInvitation(ctx context.Context, invitation *Invitation) (*Invitation, *Response, error) { + if invitation.OrgID == "" { + return nil, nil, NewArgError("orgID", "must be set") + } + + path := fmt.Sprintf(invitationBasePath, invitation.OrgID) + + if invitation.ID != "" { + path = fmt.Sprintf("%s/%s", path, invitation.ID) + } + + req, err := s.Client.NewRequest(ctx, http.MethodPatch, path, invitation) + if err != nil { + return nil, nil, err + } + + root := new(Invitation) + resp, err := s.Client.Do(ctx, req, root) + if err != nil { + return nil, resp, err + } + + return root, resp, nil +} + +// Delete deletes one unaccepted invitation to the specified Atlas organization. You can't delete an invitation that a user has accepted. +// +// See more: https://docs-atlas-staging.mongodb.com/cloud-docs/docsworker-xlarge/DOCSP-14695/reference/api/organization-delete-invitation/ +func (s *OrganizationsServiceOp) DeleteInvitation(ctx context.Context, orgID, invitationID string) (*Response, error) { + if orgID == "" { + return nil, NewArgError("orgID", "must be set") + } + + basePath := fmt.Sprintf(invitationBasePath, orgID) + path := fmt.Sprintf("%s/%s", basePath, invitationID) + + req, err := s.Client.NewRequest(ctx, http.MethodDelete, path, nil) + if err != nil { + return nil, err + } + + resp, err := s.Client.Do(ctx, req, nil) + + return resp, err +} \ No newline at end of file diff --git a/mongodbatlas/organizations_test.go b/mongodbatlas/organizations_test.go index c3653bcc4..2fa9f886a 100644 --- a/mongodbatlas/organizations_test.go +++ b/mongodbatlas/organizations_test.go @@ -22,6 +22,11 @@ import ( "github.com/go-test/deep" ) +const ( + orgID = "5a0a1e7e0f2912c554080adc" + invitationID = "1" +) + func TestOrganizationsServiceOp_List(t *testing.T) { t.Run("default", func(t *testing.T) { client, mux, teardown := setup() @@ -174,9 +179,7 @@ func TestOrganizationsServiceOp_Get(t *testing.T) { client, mux, teardown := setup() defer teardown() - ID := "5a0a1e7e0f2912c554080adc" - - mux.HandleFunc(fmt.Sprintf("/%s/%s", orgsBasePath, ID), func(w http.ResponseWriter, r *http.Request) { + mux.HandleFunc(fmt.Sprintf("/%s/%s", orgsBasePath, orgID), func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, http.MethodGet) _, _ = fmt.Fprint(w, `{ "id": "5a0a1e7e0f2912c554080adc", @@ -189,7 +192,7 @@ func TestOrganizationsServiceOp_Get(t *testing.T) { }`) }) - response, _, err := client.Organizations.Get(ctx, ID) + response, _, err := client.Organizations.Get(ctx, orgID) if err != nil { t.Fatalf("Organizations.Get returned error: %v", err) } @@ -214,13 +217,11 @@ func TestOrganizationsServiceOp_Projects(t *testing.T) { client, mux, teardown := setup() defer teardown() - ID := "5980cfdf0b6d97029d82f86e" - - mux.HandleFunc(fmt.Sprintf("/%s/%s/groups", orgsBasePath, ID), func(w http.ResponseWriter, r *http.Request) { + mux.HandleFunc(fmt.Sprintf("/%s/%s/groups", orgsBasePath, orgID), func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, http.MethodGet) _, _ = fmt.Fprint(w, `{ "links": [{ - "href": "https://cloud.mongodb.com/api/public/v1.0/orgs/5980cfdf0b6d97029d82f86e/groups", + "href": "https://cloud.mongodb.com/api/public/v1.0/orgs/5a0a1e7e0f2912c554080adc/groups", "rel": "self" }], "results": [{ @@ -230,13 +231,13 @@ func TestOrganizationsServiceOp_Projects(t *testing.T) { "rel": "self" }], "name": "012i3091203jioawjioej", - "orgId": "5980cfdf0b6d97029d82f86e" + "orgId": "5a0a1e7e0f2912c554080adc" }], "totalCount": 1 }`) }) - projects, _, err := client.Organizations.Projects(ctx, ID, nil) + projects, _, err := client.Organizations.Projects(ctx, orgID, nil) if err != nil { t.Fatalf("Organizations.GetProjects returned error: %v", err) } @@ -244,7 +245,7 @@ func TestOrganizationsServiceOp_Projects(t *testing.T) { expected := &Projects{ Links: []*Link{ { - Href: "https://cloud.mongodb.com/api/public/v1.0/orgs/5980cfdf0b6d97029d82f86e/groups", + Href: "https://cloud.mongodb.com/api/public/v1.0/orgs/5a0a1e7e0f2912c554080adc/groups", Rel: "self", }, }, @@ -258,7 +259,7 @@ func TestOrganizationsServiceOp_Projects(t *testing.T) { }, }, Name: "012i3091203jioawjioej", - OrgID: "5980cfdf0b6d97029d82f86e", + OrgID: "5a0a1e7e0f2912c554080adc", }, }, TotalCount: 1, @@ -273,9 +274,7 @@ func TestOrganizationsServiceOp_Users(t *testing.T) { client, mux, teardown := setup() defer teardown() - ID := "5980cfdf0b6d97029d82f86e" - - mux.HandleFunc(fmt.Sprintf("/%s/%s/users", orgsBasePath, ID), func(w http.ResponseWriter, r *http.Request) { + mux.HandleFunc(fmt.Sprintf("/%s/%s/users", orgsBasePath, orgID), func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, http.MethodGet) _, _ = fmt.Fprint(w, `{ "links": [ @@ -343,7 +342,7 @@ func TestOrganizationsServiceOp_Users(t *testing.T) { }`) }) - users, _, err := client.Organizations.Users(ctx, ID, nil) + users, _, err := client.Organizations.Users(ctx, orgID, nil) if err != nil { t.Fatalf("Organizations.Users returned error: %v", err) } @@ -402,8 +401,6 @@ func TestOrganizations_Delete(t *testing.T) { client, mux, teardown := setup() defer teardown() - orgID := "5a0a1e7e0f2912c554080adc" - mux.HandleFunc(fmt.Sprintf("/api/atlas/v1.0/orgs/%s", orgID), func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, http.MethodDelete) }) @@ -413,3 +410,279 @@ func TestOrganizations_Delete(t *testing.T) { t.Fatalf("Organizations.Delete returned error: %v", err) } } + +func TestOrganizations_ListUnacceptedInvitations(t *testing.T) { + client, mux, teardown := setup() + defer teardown() + + mux.HandleFunc(fmt.Sprintf("/api/atlas/v1.0/orgs/%s/invites", orgID), func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, http.MethodGet) + _, _ = fmt.Fprint(w, `[ + { + "createdAt": "2021-02-18T21:05:40Z", + "expiresAt": "2021-03-20T21:05:40Z", + "id": "5a0a1e7e0f2912c554080adc", + "inviterUsername": "admin@example.com", + "orgId": "5df7a168f10fab3a149357fb", + "orgName": "jww-12-16", + "roles": [ + "ORG_OWNER" + ], + "username": "wyatt.smith@example.com"}, + {"createdAt": "2021-02-18T21:05:40Z", + "expiresAt": "2021-03-20T21:05:40Z", + "id": "5a0a1e7e0f2912c554080adc", + "inviterUsername": "admin@example.com", + "orgId": "5df7a168f10fab3a149357fb", + "orgName": "jww-12-16", + "roles": [ + "ORG_OWNER" + ], + "teamIds": ["2"], + "username": "wyatt.smith@example.com"}]`) + }) + + invitation, _, err := client.Organizations.ListUnacceptedInvitations(ctx, orgID, nil) + if err != nil { + t.Fatalf("Organizations.GetUnacceptedInvitation returned error: %v", err) + } + + expected := &[]Invitation{ + { + ID: "5a0a1e7e0f2912c554080adc", + OrgID: "5df7a168f10fab3a149357fb", + OrgName: "jww-12-16", + CreatedAt: "2021-02-18T21:05:40Z", + ExpiresAt: "2021-03-20T21:05:40Z", + InviterUserName: "admin@example.com", + Username: "wyatt.smith@example.com", + Roles: []string{"ORG_OWNER"}, + }, + { + ID: "5a0a1e7e0f2912c554080adc", + OrgID: "5df7a168f10fab3a149357fb", + OrgName: "jww-12-16", + CreatedAt: "2021-02-18T21:05:40Z", + ExpiresAt: "2021-03-20T21:05:40Z", + InviterUserName: "admin@example.com", + Username: "wyatt.smith@example.com", + Roles: []string{"ORG_OWNER"}, + TeamIDs:[]string{"2"}, + }, + + } + + if diff := deep.Equal(invitation, expected); diff != nil { + t.Error(diff) + } +} + +func TestOrganizations_GetUnacceptedInvitation(t *testing.T) { + client, mux, teardown := setup() + defer teardown() + + mux.HandleFunc(fmt.Sprintf("/api/atlas/v1.0/orgs/%s/invites/%s", orgID, invitationID), func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, http.MethodGet) + _, _ = fmt.Fprint(w, `{ + "createdAt": "2021-02-18T21:05:40Z", + "expiresAt": "2021-03-20T21:05:40Z", + "id": "5a0a1e7e0f2912c554080adc", + "inviterUsername": "admin@example.com", + "orgId": "5df7a168f10fab3a149357fb", + "orgName": "jww-12-16", + "roles": [ + "ORG_OWNER" + ], + "username": "wyatt.smith@example.com" + }`) + }) + + invitation, _, err := client.Organizations.GetUnacceptedInvitation(ctx, orgID, invitationID) + if err != nil { + t.Fatalf("Organizations.GetUnacceptedInvitation returned error: %v", err) + } + + expected := &Invitation{ + ID: "5a0a1e7e0f2912c554080adc", + OrgID: "5df7a168f10fab3a149357fb", + OrgName: "jww-12-16", + CreatedAt: "2021-02-18T21:05:40Z", + ExpiresAt: "2021-03-20T21:05:40Z", + InviterUserName: "admin@example.com", + Username: "wyatt.smith@example.com", + Roles: []string{"ORG_OWNER"}, + } + + if diff := deep.Equal(invitation, expected); diff != nil { + t.Error(diff) + } +} + +func TestOrganizations_InviteUser(t *testing.T) { + client, mux, teardown := setup() + defer teardown() + + mux.HandleFunc(fmt.Sprintf("/api/atlas/v1.0/orgs/%s/invites", orgID), func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, http.MethodPost) + _, _ = fmt.Fprint(w, `{ + "createdAt": "2021-02-18T21:05:40Z", + "expiresAt": "2021-03-20T21:05:40Z", + "id": "5a0a1e7e0f2912c554080adc", + "inviterUsername": "admin@example.com", + "orgId": "5df7a168f10fab3a149357fb", + "orgName": "jww-12-16", + "roles": [ + "ORG_OWNER" + ], + "username": "wyatt.smith@example.com" + }`) + }) + + body := &Invitation{ + OrgID: orgID, + OrgName: "jww-12-16", + CreatedAt: "2021-02-18T21:05:40Z", + ExpiresAt: "2021-03-20T21:05:40Z", + InviterUserName: "admin@example.com", + Username: "wyatt.smith@example.com", + Roles: []string{"ORG_OWNER"}, + } + + invitation, _, err := client.Organizations.InviteUser(ctx, body) + if err != nil { + t.Fatalf("Organizations.InviteUser returned error: %v", err) + } + + expected := &Invitation{ + ID: "5a0a1e7e0f2912c554080adc", + OrgID: "5df7a168f10fab3a149357fb", + OrgName: "jww-12-16", + CreatedAt: "2021-02-18T21:05:40Z", + ExpiresAt: "2021-03-20T21:05:40Z", + InviterUserName: "admin@example.com", + Username: "wyatt.smith@example.com", + Roles: []string{"ORG_OWNER"}, + } + + if diff := deep.Equal(invitation, expected); diff != nil { + t.Error(diff) + } +} + + +func TestOrganizations_UpdateInvitation(t *testing.T) { + client, mux, teardown := setup() + defer teardown() + + mux.HandleFunc(fmt.Sprintf("/api/atlas/v1.0/orgs/%s/invites", orgID), func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, http.MethodPatch) + _, _ = fmt.Fprint(w, `{ + "createdAt": "2021-02-18T21:05:40Z", + "expiresAt": "2021-03-20T21:05:40Z", + "id": "5a0a1e7e0f2912c554080adc", + "inviterUsername": "admin@example.com", + "orgId": "5df7a168f10fab3a149357fb", + "orgName": "jww-12-16", + "roles": [ + "ORG_OWNER" + ], + "username": "wyatt.smith@example.com" + }`) + }) + + body := &Invitation{ + OrgID: orgID, + OrgName: "jww-12-16", + CreatedAt: "2021-02-18T21:05:40Z", + ExpiresAt: "2021-03-20T21:05:40Z", + InviterUserName: "admin@example.com", + Username: "wyatt.smith@example.com", + Roles: []string{"ORG_OWNER"}, + } + + invitation, _, err := client.Organizations.UpdateInvitation(ctx, body) + if err != nil { + t.Fatalf("Organizations.UpdateInvitation returned error: %v", err) + } + + expected := &Invitation{ + ID: "5a0a1e7e0f2912c554080adc", + OrgID: "5df7a168f10fab3a149357fb", + OrgName: "jww-12-16", + CreatedAt: "2021-02-18T21:05:40Z", + ExpiresAt: "2021-03-20T21:05:40Z", + InviterUserName: "admin@example.com", + Username: "wyatt.smith@example.com", + Roles: []string{"ORG_OWNER"}, + } + + if diff := deep.Equal(invitation, expected); diff != nil { + t.Error(diff) + } +} + +func TestOrganizations_UpdateInvitationByID(t *testing.T) { + client, mux, teardown := setup() + defer teardown() + + mux.HandleFunc(fmt.Sprintf("/api/atlas/v1.0/orgs/%s/invites/%s", orgID, invitationID), func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, http.MethodPatch) + _, _ = fmt.Fprint(w, `{ + "createdAt": "2021-02-18T21:05:40Z", + "expiresAt": "2021-03-20T21:05:40Z", + "id": "5a0a1e7e0f2912c554080adc", + "inviterUsername": "admin@example.com", + "orgId": "5df7a168f10fab3a149357fb", + "orgName": "jww-12-16", + "roles": [ + "ORG_OWNER" + ], + "username": "wyatt.smith@example.com" + }`) + }) + + body := &Invitation{ + OrgID: orgID, + ID: invitationID, + OrgName: "jww-12-16", + CreatedAt: "2021-02-18T21:05:40Z", + ExpiresAt: "2021-03-20T21:05:40Z", + InviterUserName: "admin@example.com", + Username: "wyatt.smith@example.com", + Roles: []string{"ORG_OWNER"}, + } + + invitation, _, err := client.Organizations.UpdateInvitation(ctx, body) + if err != nil { + t.Fatalf("Organizations.UpdateInvitation returned error: %v", err) + } + + expected := &Invitation{ + ID: "5a0a1e7e0f2912c554080adc", + OrgID: "5df7a168f10fab3a149357fb", + OrgName: "jww-12-16", + CreatedAt: "2021-02-18T21:05:40Z", + ExpiresAt: "2021-03-20T21:05:40Z", + InviterUserName: "admin@example.com", + Username: "wyatt.smith@example.com", + Roles: []string{"ORG_OWNER"}, + } + + if diff := deep.Equal(invitation, expected); diff != nil { + t.Error(diff) + } +} + +func TestOrganizations_DeleteInvitation(t *testing.T) { + client, mux, teardown := setup() + defer teardown() + + mux.HandleFunc(fmt.Sprintf("/api/atlas/v1.0/orgs/%s/invites/%s", orgID, invitationID), func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, http.MethodDelete) + }) + + _, err := client.Organizations.DeleteInvitation(ctx, orgID, invitationID) + if err != nil { + t.Fatalf("Organizations.DeleteInvitation returned error: %v", err) + } +} From 7e585157fbfeddc2a767b2f20d10d2a8fcce02b0 Mon Sep 17 00:00:00 2001 From: andreaangiolillo Date: Mon, 28 Jun 2021 14:11:40 +0200 Subject: [PATCH 2/8] make fmt --- mongodbatlas/organizations.go | 20 ++++++++++---------- mongodbatlas/organizations_test.go | 8 +++----- 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/mongodbatlas/organizations.go b/mongodbatlas/organizations.go index aa8c75a3b..484b27aea 100644 --- a/mongodbatlas/organizations.go +++ b/mongodbatlas/organizations.go @@ -21,7 +21,7 @@ import ( ) const ( - orgsBasePath = "api/atlas/v1.0/orgs" + orgsBasePath = "api/atlas/v1.0/orgs" invitationBasePath = orgsBasePath + "/%s/invites" ) @@ -70,18 +70,18 @@ type Organizations struct { // InvitationOptions filtering options for invitations. type InvitationOptions struct { - Username string `url:"username,omitempty"` + Username string `url:"username,omitempty"` } // Invitation represents the structure of an Invitation. type Invitation struct { - ID string `json:"id,omitempty"` - OrgID string `json:"orgId,omitempty"` - OrgName string `json:"orgName,omitempty"` - CreatedAt string `json:"createdAt,omitempty"` - ExpiresAt string `json:"expiresAt,omitempty"` - InviterUserName string `json:"inviterUserName,omitempty"` - Username string `json:"username,omitempty"` + ID string `json:"id,omitempty"` + OrgID string `json:"orgId,omitempty"` + OrgName string `json:"orgName,omitempty"` + CreatedAt string `json:"createdAt,omitempty"` + ExpiresAt string `json:"expiresAt,omitempty"` + InviterUserName string `json:"inviterUserName,omitempty"` + Username string `json:"username,omitempty"` Roles []string `json:"roles,omitempty"` TeamIDs []string `json:"teamIds,omitempty"` } @@ -337,4 +337,4 @@ func (s *OrganizationsServiceOp) DeleteInvitation(ctx context.Context, orgID, in resp, err := s.Client.Do(ctx, req, nil) return resp, err -} \ No newline at end of file +} diff --git a/mongodbatlas/organizations_test.go b/mongodbatlas/organizations_test.go index 2fa9f886a..e8bc73285 100644 --- a/mongodbatlas/organizations_test.go +++ b/mongodbatlas/organizations_test.go @@ -23,7 +23,7 @@ import ( ) const ( - orgID = "5a0a1e7e0f2912c554080adc" + orgID = "5a0a1e7e0f2912c554080adc" invitationID = "1" ) @@ -467,9 +467,8 @@ func TestOrganizations_ListUnacceptedInvitations(t *testing.T) { InviterUserName: "admin@example.com", Username: "wyatt.smith@example.com", Roles: []string{"ORG_OWNER"}, - TeamIDs:[]string{"2"}, + TeamIDs: []string{"2"}, }, - } if diff := deep.Equal(invitation, expected); diff != nil { @@ -569,7 +568,6 @@ func TestOrganizations_InviteUser(t *testing.T) { } } - func TestOrganizations_UpdateInvitation(t *testing.T) { client, mux, teardown := setup() defer teardown() @@ -643,7 +641,7 @@ func TestOrganizations_UpdateInvitationByID(t *testing.T) { body := &Invitation{ OrgID: orgID, - ID: invitationID, + ID: invitationID, OrgName: "jww-12-16", CreatedAt: "2021-02-18T21:05:40Z", ExpiresAt: "2021-03-20T21:05:40Z", From 3989fe4abcbbe12656a24f8fc5857e3a91ed4f3f Mon Sep 17 00:00:00 2001 From: andreaangiolillo Date: Mon, 28 Jun 2021 14:17:01 +0200 Subject: [PATCH 3/8] Update organizations.go --- mongodbatlas/organizations.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/mongodbatlas/organizations.go b/mongodbatlas/organizations.go index 484b27aea..50173de65 100644 --- a/mongodbatlas/organizations.go +++ b/mongodbatlas/organizations.go @@ -290,9 +290,10 @@ func (s *OrganizationsServiceOp) InviteUser(ctx context.Context, invitation *Inv return root, resp, nil } -// InviteUser invites one user to the Atlas organization that you specify. +// UpdateInvitation updates one pending invitation to the Atlas organization that you specify. // -// See more: https://docs-atlas-staging.mongodb.com/cloud-docs/docsworker-xlarge/DOCSP-14695/reference/api/organization-create-one-invitation/ +// See more: https://docs-atlas-staging.mongodb.com/cloud-docs/docsworker-xlarge/DOCSP-14695/reference/api/organization-update-one-invitation/ +// See more: https://docs-atlas-staging.mongodb.com/cloud-docs/docsworker-xlarge/DOCSP-14695/reference/api/organization-update-one-invitation-by-id/ func (s *OrganizationsServiceOp) UpdateInvitation(ctx context.Context, invitation *Invitation) (*Invitation, *Response, error) { if invitation.OrgID == "" { return nil, nil, NewArgError("orgID", "must be set") From 9378fe9b0ca5766631cfd169f7d7e8b0fd471338 Mon Sep 17 00:00:00 2001 From: andreaangiolillo Date: Mon, 28 Jun 2021 14:18:06 +0200 Subject: [PATCH 4/8] Update organizations.go --- mongodbatlas/organizations.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mongodbatlas/organizations.go b/mongodbatlas/organizations.go index 50173de65..5fab8ca59 100644 --- a/mongodbatlas/organizations.go +++ b/mongodbatlas/organizations.go @@ -319,7 +319,7 @@ func (s *OrganizationsServiceOp) UpdateInvitation(ctx context.Context, invitatio return root, resp, nil } -// Delete deletes one unaccepted invitation to the specified Atlas organization. You can't delete an invitation that a user has accepted. +// DeleteInvitation deletes one unaccepted invitation to the specified Atlas organization. You can't delete an invitation that a user has accepted. // // See more: https://docs-atlas-staging.mongodb.com/cloud-docs/docsworker-xlarge/DOCSP-14695/reference/api/organization-delete-invitation/ func (s *OrganizationsServiceOp) DeleteInvitation(ctx context.Context, orgID, invitationID string) (*Response, error) { From aed60230ed962ea5da19e922857c04999e342033 Mon Sep 17 00:00:00 2001 From: andreaangiolillo Date: Mon, 28 Jun 2021 14:32:05 +0200 Subject: [PATCH 5/8] Update organizations.go --- mongodbatlas/organizations.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/mongodbatlas/organizations.go b/mongodbatlas/organizations.go index 5fab8ca59..851abfb65 100644 --- a/mongodbatlas/organizations.go +++ b/mongodbatlas/organizations.go @@ -249,6 +249,10 @@ func (s *OrganizationsServiceOp) GetUnacceptedInvitation(ctx context.Context, or return nil, nil, NewArgError("orgID", "must be set") } + if invitationID == "" { + return nil, nil, NewArgError("invitationID", "must be set") + } + basePath := fmt.Sprintf(invitationBasePath, orgID) path := fmt.Sprintf("%s/%s", basePath, invitationID) @@ -327,6 +331,10 @@ func (s *OrganizationsServiceOp) DeleteInvitation(ctx context.Context, orgID, in return nil, NewArgError("orgID", "must be set") } + if invitationID == "" { + return nil, NewArgError("invitationID", "must be set") + } + basePath := fmt.Sprintf(invitationBasePath, orgID) path := fmt.Sprintf("%s/%s", basePath, invitationID) From 81b1ada5fe50211484bb1358ef40363b388c9c7d Mon Sep 17 00:00:00 2001 From: andreaangiolillo Date: Mon, 28 Jun 2021 15:34:02 +0200 Subject: [PATCH 6/8] Addressed PR comments --- mongodbatlas/organizations.go | 163 +--------- mongodbatlas/organizations_invitations.go | 196 ++++++++++++ .../organizations_invitations_test.go | 299 ++++++++++++++++++ mongodbatlas/organizations_test.go | 279 +--------------- 4 files changed, 500 insertions(+), 437 deletions(-) create mode 100644 mongodbatlas/organizations_invitations.go create mode 100644 mongodbatlas/organizations_invitations_test.go diff --git a/mongodbatlas/organizations.go b/mongodbatlas/organizations.go index 851abfb65..4367eab1c 100644 --- a/mongodbatlas/organizations.go +++ b/mongodbatlas/organizations.go @@ -20,24 +20,22 @@ import ( "net/http" ) -const ( - orgsBasePath = "api/atlas/v1.0/orgs" - invitationBasePath = orgsBasePath + "/%s/invites" -) +const orgsBasePath = "api/atlas/v1.0/orgs" // OrganizationsService provides access to the organization related functions in the Atlas API. // // See more: https://docs.atlas.mongodb.com/reference/api/organizations/ type OrganizationsService interface { List(context.Context, *OrganizationsListOptions) (*Organizations, *Response, error) - ListUnacceptedInvitations(context.Context, string, *InvitationOptions) (*[]Invitation, *Response, error) + Invitations(context.Context, string, *InvitationOptions) ([]*Invitation, *Response, error) Get(context.Context, string) (*Organization, *Response, error) - GetUnacceptedInvitation(context.Context, string, string) (*Invitation, *Response, error) + Invitation(context.Context, string, string) (*Invitation, *Response, error) Projects(context.Context, string, *ListOptions) (*Projects, *Response, error) Users(context.Context, string, *ListOptions) (*AtlasUsersResponse, *Response, error) Delete(context.Context, string) (*Response, error) InviteUser(context.Context, *Invitation) (*Invitation, *Response, error) UpdateInvitation(context.Context, *Invitation) (*Invitation, *Response, error) + UpdateInvitationByID(context.Context, string, *Invitation) (*Invitation, *Response, error) DeleteInvitation(context.Context, string, string) (*Response, error) } @@ -68,24 +66,6 @@ type Organizations struct { TotalCount int `json:"totalCount"` } -// InvitationOptions filtering options for invitations. -type InvitationOptions struct { - Username string `url:"username,omitempty"` -} - -// Invitation represents the structure of an Invitation. -type Invitation struct { - ID string `json:"id,omitempty"` - OrgID string `json:"orgId,omitempty"` - OrgName string `json:"orgName,omitempty"` - CreatedAt string `json:"createdAt,omitempty"` - ExpiresAt string `json:"expiresAt,omitempty"` - InviterUserName string `json:"inviterUserName,omitempty"` - Username string `json:"username,omitempty"` - Roles []string `json:"roles,omitempty"` - TeamIDs []string `json:"teamIds,omitempty"` -} - // List gets all organizations. // // See more: https://docs.atlas.mongodb.com/reference/api/organization-get-all/ @@ -212,138 +192,3 @@ func (s *OrganizationsServiceOp) Delete(ctx context.Context, orgID string) (*Res return resp, err } - -// ListUnacceptedInvitations gets all unaccepted invitations to the specified Atlas organization. -// -// See more: https://docs.atlas.mongodb.com/reference/api/organization-get-invitations/ -func (s *OrganizationsServiceOp) ListUnacceptedInvitations(ctx context.Context, orgID string, opts *InvitationOptions) (*[]Invitation, *Response, error) { - if orgID == "" { - return nil, nil, NewArgError("orgID", "must be set") - } - - basePath := fmt.Sprintf(invitationBasePath, orgID) - path, err := setListOptions(basePath, opts) - if err != nil { - return nil, nil, err - } - - req, err := s.Client.NewRequest(ctx, http.MethodGet, path, nil) - if err != nil { - return nil, nil, err - } - - root := new([]Invitation) - resp, err := s.Client.Do(ctx, req, root) - if err != nil { - return nil, resp, err - } - - return root, resp, nil -} - -// GetUnacceptedInvitation gets details for one unaccepted invitation to the specified Atlas organization. -// -// See more: https://docs.atlas.mongodb.com/reference/api/organization-get-one-invitation/ -func (s *OrganizationsServiceOp) GetUnacceptedInvitation(ctx context.Context, orgID, invitationID string) (*Invitation, *Response, error) { - if orgID == "" { - return nil, nil, NewArgError("orgID", "must be set") - } - - if invitationID == "" { - return nil, nil, NewArgError("invitationID", "must be set") - } - - basePath := fmt.Sprintf(invitationBasePath, orgID) - path := fmt.Sprintf("%s/%s", basePath, invitationID) - - req, err := s.Client.NewRequest(ctx, http.MethodGet, path, nil) - if err != nil { - return nil, nil, err - } - - root := new(Invitation) - resp, err := s.Client.Do(ctx, req, root) - if err != nil { - return nil, resp, err - } - - return root, resp, nil -} - -// InviteUser invites one user to the Atlas organization that you specify. -// -// See more: https://docs-atlas-staging.mongodb.com/cloud-docs/docsworker-xlarge/DOCSP-14695/reference/api/organization-create-one-invitation/ -func (s *OrganizationsServiceOp) InviteUser(ctx context.Context, invitation *Invitation) (*Invitation, *Response, error) { - if invitation.OrgID == "" { - return nil, nil, NewArgError("orgID", "must be set") - } - - path := fmt.Sprintf(invitationBasePath, invitation.OrgID) - - req, err := s.Client.NewRequest(ctx, http.MethodPost, path, invitation) - if err != nil { - return nil, nil, err - } - - root := new(Invitation) - resp, err := s.Client.Do(ctx, req, root) - if err != nil { - return nil, resp, err - } - - return root, resp, nil -} - -// UpdateInvitation updates one pending invitation to the Atlas organization that you specify. -// -// See more: https://docs-atlas-staging.mongodb.com/cloud-docs/docsworker-xlarge/DOCSP-14695/reference/api/organization-update-one-invitation/ -// See more: https://docs-atlas-staging.mongodb.com/cloud-docs/docsworker-xlarge/DOCSP-14695/reference/api/organization-update-one-invitation-by-id/ -func (s *OrganizationsServiceOp) UpdateInvitation(ctx context.Context, invitation *Invitation) (*Invitation, *Response, error) { - if invitation.OrgID == "" { - return nil, nil, NewArgError("orgID", "must be set") - } - - path := fmt.Sprintf(invitationBasePath, invitation.OrgID) - - if invitation.ID != "" { - path = fmt.Sprintf("%s/%s", path, invitation.ID) - } - - req, err := s.Client.NewRequest(ctx, http.MethodPatch, path, invitation) - if err != nil { - return nil, nil, err - } - - root := new(Invitation) - resp, err := s.Client.Do(ctx, req, root) - if err != nil { - return nil, resp, err - } - - return root, resp, nil -} - -// DeleteInvitation deletes one unaccepted invitation to the specified Atlas organization. You can't delete an invitation that a user has accepted. -// -// See more: https://docs-atlas-staging.mongodb.com/cloud-docs/docsworker-xlarge/DOCSP-14695/reference/api/organization-delete-invitation/ -func (s *OrganizationsServiceOp) DeleteInvitation(ctx context.Context, orgID, invitationID string) (*Response, error) { - if orgID == "" { - return nil, NewArgError("orgID", "must be set") - } - - if invitationID == "" { - return nil, NewArgError("invitationID", "must be set") - } - - basePath := fmt.Sprintf(invitationBasePath, orgID) - path := fmt.Sprintf("%s/%s", basePath, invitationID) - - req, err := s.Client.NewRequest(ctx, http.MethodDelete, path, nil) - if err != nil { - return nil, err - } - - resp, err := s.Client.Do(ctx, req, nil) - - return resp, err -} diff --git a/mongodbatlas/organizations_invitations.go b/mongodbatlas/organizations_invitations.go new file mode 100644 index 000000000..ae7445b9e --- /dev/null +++ b/mongodbatlas/organizations_invitations.go @@ -0,0 +1,196 @@ +// Copyright 2021 MongoDB Inc +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package mongodbatlas + +import ( + "context" + "fmt" + "net/http" +) + +const invitationBasePath = orgsBasePath + "/%s/invites" + +// InvitationOptions filtering options for invitations. +type InvitationOptions struct { + Username string `url:"username,omitempty"` +} + +// Invitation represents the structure of an Invitation. +type Invitation struct { + ID string `json:"id,omitempty"` + OrgID string `json:"orgId,omitempty"` + OrgName string `json:"orgName,omitempty"` + CreatedAt string `json:"createdAt,omitempty"` + ExpiresAt string `json:"expiresAt,omitempty"` + InviterUserName string `json:"inviterUsername,omitempty"` + Username string `json:"username,omitempty"` + Roles []string `json:"roles,omitempty"` + TeamIDs []string `json:"teamIds,omitempty"` +} + +// Invitations gets all unaccepted invitations to the specified Atlas organization. +// +// See more: https://docs.atlas.mongodb.com/reference/api/organization-get-invitations/ +func (s *OrganizationsServiceOp) Invitations(ctx context.Context, orgID string, opts *InvitationOptions) ([]*Invitation, *Response, error) { + if orgID == "" { + return nil, nil, NewArgError("orgID", "must be set") + } + + basePath := fmt.Sprintf(invitationBasePath, orgID) + path, err := setListOptions(basePath, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.Client.NewRequest(ctx, http.MethodGet, path, nil) + if err != nil { + return nil, nil, err + } + + var root []*Invitation + resp, err := s.Client.Do(ctx, req, &root) + if err != nil { + return nil, resp, err + } + + return root, resp, nil +} + +// Invitation gets details for one unaccepted invitation to the specified Atlas organization. +// +// See more: https://docs.atlas.mongodb.com/reference/api/organization-get-one-invitation/ +func (s *OrganizationsServiceOp) Invitation(ctx context.Context, orgID, invitationID string) (*Invitation, *Response, error) { + if orgID == "" { + return nil, nil, NewArgError("orgID", "must be set") + } + + if invitationID == "" { + return nil, nil, NewArgError("invitationID", "must be set") + } + + basePath := fmt.Sprintf(invitationBasePath, orgID) + path := fmt.Sprintf("%s/%s", basePath, invitationID) + + req, err := s.Client.NewRequest(ctx, http.MethodGet, path, nil) + if err != nil { + return nil, nil, err + } + + root := new(Invitation) + resp, err := s.Client.Do(ctx, req, root) + if err != nil { + return nil, resp, err + } + + return root, resp, nil +} + +// InviteUser invites one user to the Atlas organization that you specify. +// +// See more: https://docs.atlas.mongodb.com/reference/api/organization-create-one-invitation/ +func (s *OrganizationsServiceOp) InviteUser(ctx context.Context, invitation *Invitation) (*Invitation, *Response, error) { + if invitation.OrgID == "" { + return nil, nil, NewArgError("orgID", "must be set") + } + + path := fmt.Sprintf(invitationBasePath, invitation.OrgID) + + req, err := s.Client.NewRequest(ctx, http.MethodPost, path, invitation) + if err != nil { + return nil, nil, err + } + + root := new(Invitation) + resp, err := s.Client.Do(ctx, req, root) + if err != nil { + return nil, resp, err + } + + return root, resp, nil +} + +// UpdateInvitation updates one pending invitation to the Atlas organization that you specify. +// +// See more: https://docs-atlas-staging.mongodb.com/cloud-docs/docsworker-xlarge/DOCSP-14695/reference/api/organization-update-one-invitation/ +func (s *OrganizationsServiceOp) UpdateInvitation(ctx context.Context, invitation *Invitation) (*Invitation, *Response, error) { + if invitation.OrgID == "" { + return nil, nil, NewArgError("orgID", "must be set") + } + + return s.updateInvitation(ctx, invitation) +} + +// UpdateInvitationByID updates one invitation to the Atlas organization. +// +// See more: https://docs-atlas-staging.mongodb.com/cloud-docs/docsworker-xlarge/DOCSP-14695/reference/api/organization-update-one-invitation-by-id/ +func (s *OrganizationsServiceOp) UpdateInvitationByID(ctx context.Context, invitationID string, invitation *Invitation) (*Invitation, *Response, error) { + if invitation.OrgID == "" { + return nil, nil, NewArgError("orgID", "must be set") + } + + if invitationID == "" { + return nil, nil, NewArgError("invitationID", "must be set") + } + + invitation.ID = invitationID + + return s.updateInvitation(ctx, invitation) +} + +// DeleteInvitation deletes one unaccepted invitation to the specified Atlas organization. You can't delete an invitation that a user has accepted. +// +// See more: https://docs.atlas.mongodb.com/reference/api/organization-delete-invitation/ +func (s *OrganizationsServiceOp) DeleteInvitation(ctx context.Context, orgID, invitationID string) (*Response, error) { + if orgID == "" { + return nil, NewArgError("orgID", "must be set") + } + + if invitationID == "" { + return nil, NewArgError("invitationID", "must be set") + } + + basePath := fmt.Sprintf(invitationBasePath, orgID) + path := fmt.Sprintf("%s/%s", basePath, invitationID) + + req, err := s.Client.NewRequest(ctx, http.MethodDelete, path, nil) + if err != nil { + return nil, err + } + + resp, err := s.Client.Do(ctx, req, nil) + + return resp, err +} + +func (s *OrganizationsServiceOp) updateInvitation(ctx context.Context, invitation *Invitation) (*Invitation, *Response, error) { + path := fmt.Sprintf(invitationBasePath, invitation.OrgID) + + if invitation.ID != "" { + path = fmt.Sprintf("%s/%s", path, invitation.ID) + } + + req, err := s.Client.NewRequest(ctx, http.MethodPatch, path, invitation) + if err != nil { + return nil, nil, err + } + + root := new(Invitation) + resp, err := s.Client.Do(ctx, req, root) + if err != nil { + return nil, resp, err + } + + return root, resp, nil +} diff --git a/mongodbatlas/organizations_invitations_test.go b/mongodbatlas/organizations_invitations_test.go new file mode 100644 index 000000000..db2c8a14c --- /dev/null +++ b/mongodbatlas/organizations_invitations_test.go @@ -0,0 +1,299 @@ +// Copyright 2021 MongoDB Inc +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package mongodbatlas + +import ( + "fmt" + "net/http" + "testing" + + "github.com/go-test/deep" +) + +const invitationID = "1" + +func TestOrganizations_Invitations(t *testing.T) { + client, mux, teardown := setup() + defer teardown() + + mux.HandleFunc(fmt.Sprintf("/api/atlas/v1.0/orgs/%s/invites", orgID), func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, http.MethodGet) + _, _ = fmt.Fprint(w, `[ + { + "createdAt": "2021-02-18T21:05:40Z", + "expiresAt": "2021-03-20T21:05:40Z", + "id": "5a0a1e7e0f2912c554080adc", + "inviterUsername": "admin@example.com", + "orgId": "5df7a168f10fab3a149357fb", + "orgName": "jww-12-16", + "roles": [ + "ORG_OWNER" + ], + "username": "wyatt.smith@example.com"}, + {"createdAt": "2021-02-18T21:05:40Z", + "expiresAt": "2021-03-20T21:05:40Z", + "id": "5a0a1e7e0f2912c554080adc", + "inviterUsername": "admin@example.com", + "orgId": "5df7a168f10fab3a149357fb", + "orgName": "jww-12-16", + "roles": [ + "ORG_OWNER" + ], + "teamIds": ["2"], + "username": "wyatt.smith@example.com"}]`) + }) + + invitation, _, err := client.Organizations.Invitations(ctx, orgID, nil) + if err != nil { + t.Fatalf("Organizations.Invitations returned error: %v", err) + } + + expected := []*Invitation{ + { + ID: "5a0a1e7e0f2912c554080adc", + OrgID: "5df7a168f10fab3a149357fb", + OrgName: "jww-12-16", + CreatedAt: "2021-02-18T21:05:40Z", + ExpiresAt: "2021-03-20T21:05:40Z", + InviterUserName: "admin@example.com", + Username: "wyatt.smith@example.com", + Roles: []string{"ORG_OWNER"}, + }, + { + ID: "5a0a1e7e0f2912c554080adc", + OrgID: "5df7a168f10fab3a149357fb", + OrgName: "jww-12-16", + CreatedAt: "2021-02-18T21:05:40Z", + ExpiresAt: "2021-03-20T21:05:40Z", + InviterUserName: "admin@example.com", + Username: "wyatt.smith@example.com", + Roles: []string{"ORG_OWNER"}, + TeamIDs: []string{"2"}, + }, + } + + if diff := deep.Equal(invitation, expected); diff != nil { + t.Error(diff) + } +} + +func TestOrganizations_Invitation(t *testing.T) { + client, mux, teardown := setup() + defer teardown() + + mux.HandleFunc(fmt.Sprintf("/api/atlas/v1.0/orgs/%s/invites/%s", orgID, invitationID), func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, http.MethodGet) + _, _ = fmt.Fprint(w, `{ + "createdAt": "2021-02-18T21:05:40Z", + "expiresAt": "2021-03-20T21:05:40Z", + "id": "5a0a1e7e0f2912c554080adc", + "inviterUsername": "admin@example.com", + "orgId": "5df7a168f10fab3a149357fb", + "orgName": "jww-12-16", + "roles": [ + "ORG_OWNER" + ], + "username": "wyatt.smith@example.com" + }`) + }) + + invitation, _, err := client.Organizations.Invitation(ctx, orgID, invitationID) + if err != nil { + t.Fatalf("Organizations.Invitation returned error: %v", err) + } + + expected := &Invitation{ + ID: "5a0a1e7e0f2912c554080adc", + OrgID: "5df7a168f10fab3a149357fb", + OrgName: "jww-12-16", + CreatedAt: "2021-02-18T21:05:40Z", + ExpiresAt: "2021-03-20T21:05:40Z", + InviterUserName: "admin@example.com", + Username: "wyatt.smith@example.com", + Roles: []string{"ORG_OWNER"}, + } + + if diff := deep.Equal(invitation, expected); diff != nil { + t.Error(diff) + } +} + +func TestOrganizations_InviteUser(t *testing.T) { + client, mux, teardown := setup() + defer teardown() + + mux.HandleFunc(fmt.Sprintf("/api/atlas/v1.0/orgs/%s/invites", orgID), func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, http.MethodPost) + _, _ = fmt.Fprint(w, `{ + "createdAt": "2021-02-18T21:05:40Z", + "expiresAt": "2021-03-20T21:05:40Z", + "id": "5a0a1e7e0f2912c554080adc", + "inviterUsername": "admin@example.com", + "orgId": "5df7a168f10fab3a149357fb", + "orgName": "jww-12-16", + "roles": [ + "ORG_OWNER" + ], + "username": "wyatt.smith@example.com" + }`) + }) + + body := &Invitation{ + OrgID: orgID, + OrgName: "jww-12-16", + CreatedAt: "2021-02-18T21:05:40Z", + ExpiresAt: "2021-03-20T21:05:40Z", + InviterUserName: "admin@example.com", + Username: "wyatt.smith@example.com", + Roles: []string{"ORG_OWNER"}, + } + + invitation, _, err := client.Organizations.InviteUser(ctx, body) + if err != nil { + t.Fatalf("Organizations.InviteUser returned error: %v", err) + } + + expected := &Invitation{ + ID: "5a0a1e7e0f2912c554080adc", + OrgID: "5df7a168f10fab3a149357fb", + OrgName: "jww-12-16", + CreatedAt: "2021-02-18T21:05:40Z", + ExpiresAt: "2021-03-20T21:05:40Z", + InviterUserName: "admin@example.com", + Username: "wyatt.smith@example.com", + Roles: []string{"ORG_OWNER"}, + } + + if diff := deep.Equal(invitation, expected); diff != nil { + t.Error(diff) + } +} + +func TestOrganizations_UpdateInvitation(t *testing.T) { + client, mux, teardown := setup() + defer teardown() + + mux.HandleFunc(fmt.Sprintf("/api/atlas/v1.0/orgs/%s/invites", orgID), func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, http.MethodPatch) + _, _ = fmt.Fprint(w, `{ + "createdAt": "2021-02-18T21:05:40Z", + "expiresAt": "2021-03-20T21:05:40Z", + "id": "5a0a1e7e0f2912c554080adc", + "inviterUsername": "admin@example.com", + "orgId": "5df7a168f10fab3a149357fb", + "orgName": "jww-12-16", + "roles": [ + "ORG_OWNER" + ], + "username": "wyatt.smith@example.com" + }`) + }) + + body := &Invitation{ + OrgID: orgID, + OrgName: "jww-12-16", + CreatedAt: "2021-02-18T21:05:40Z", + ExpiresAt: "2021-03-20T21:05:40Z", + InviterUserName: "admin@example.com", + Username: "wyatt.smith@example.com", + Roles: []string{"ORG_OWNER"}, + } + + invitation, _, err := client.Organizations.UpdateInvitation(ctx, body) + if err != nil { + t.Fatalf("Organizations.UpdateInvitation returned error: %v", err) + } + + expected := &Invitation{ + ID: "5a0a1e7e0f2912c554080adc", + OrgID: "5df7a168f10fab3a149357fb", + OrgName: "jww-12-16", + CreatedAt: "2021-02-18T21:05:40Z", + ExpiresAt: "2021-03-20T21:05:40Z", + InviterUserName: "admin@example.com", + Username: "wyatt.smith@example.com", + Roles: []string{"ORG_OWNER"}, + } + + if diff := deep.Equal(invitation, expected); diff != nil { + t.Error(diff) + } +} + +func TestOrganizations_UpdateInvitationByID(t *testing.T) { + client, mux, teardown := setup() + defer teardown() + + mux.HandleFunc(fmt.Sprintf("/api/atlas/v1.0/orgs/%s/invites/%s", orgID, invitationID), func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, http.MethodPatch) + _, _ = fmt.Fprint(w, `{ + "createdAt": "2021-02-18T21:05:40Z", + "expiresAt": "2021-03-20T21:05:40Z", + "id": "5a0a1e7e0f2912c554080adc", + "inviterUsername": "admin@example.com", + "orgId": "5df7a168f10fab3a149357fb", + "orgName": "jww-12-16", + "roles": [ + "ORG_OWNER" + ], + "username": "wyatt.smith@example.com" + }`) + }) + + body := &Invitation{ + OrgID: orgID, + ID: invitationID, + OrgName: "jww-12-16", + CreatedAt: "2021-02-18T21:05:40Z", + ExpiresAt: "2021-03-20T21:05:40Z", + InviterUserName: "admin@example.com", + Username: "wyatt.smith@example.com", + Roles: []string{"ORG_OWNER"}, + } + + invitation, _, err := client.Organizations.UpdateInvitationByID(ctx, invitationID, body) + if err != nil { + t.Fatalf("Organizations.UpdateInvitationByID returned error: %v", err) + } + + expected := &Invitation{ + ID: "5a0a1e7e0f2912c554080adc", + OrgID: "5df7a168f10fab3a149357fb", + OrgName: "jww-12-16", + CreatedAt: "2021-02-18T21:05:40Z", + ExpiresAt: "2021-03-20T21:05:40Z", + InviterUserName: "admin@example.com", + Username: "wyatt.smith@example.com", + Roles: []string{"ORG_OWNER"}, + } + + if diff := deep.Equal(invitation, expected); diff != nil { + t.Error(diff) + } +} + +func TestOrganizations_DeleteInvitation(t *testing.T) { + client, mux, teardown := setup() + defer teardown() + + mux.HandleFunc(fmt.Sprintf("/api/atlas/v1.0/orgs/%s/invites/%s", orgID, invitationID), func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, http.MethodDelete) + }) + + _, err := client.Organizations.DeleteInvitation(ctx, orgID, invitationID) + if err != nil { + t.Fatalf("Organizations.DeleteInvitation returned error: %v", err) + } +} diff --git a/mongodbatlas/organizations_test.go b/mongodbatlas/organizations_test.go index e8bc73285..5bc6fe7a0 100644 --- a/mongodbatlas/organizations_test.go +++ b/mongodbatlas/organizations_test.go @@ -22,10 +22,7 @@ import ( "github.com/go-test/deep" ) -const ( - orgID = "5a0a1e7e0f2912c554080adc" - invitationID = "1" -) +const orgID = "5a0a1e7e0f2912c554080adc" func TestOrganizationsServiceOp_List(t *testing.T) { t.Run("default", func(t *testing.T) { @@ -410,277 +407,3 @@ func TestOrganizations_Delete(t *testing.T) { t.Fatalf("Organizations.Delete returned error: %v", err) } } - -func TestOrganizations_ListUnacceptedInvitations(t *testing.T) { - client, mux, teardown := setup() - defer teardown() - - mux.HandleFunc(fmt.Sprintf("/api/atlas/v1.0/orgs/%s/invites", orgID), func(w http.ResponseWriter, r *http.Request) { - testMethod(t, r, http.MethodGet) - _, _ = fmt.Fprint(w, `[ - { - "createdAt": "2021-02-18T21:05:40Z", - "expiresAt": "2021-03-20T21:05:40Z", - "id": "5a0a1e7e0f2912c554080adc", - "inviterUsername": "admin@example.com", - "orgId": "5df7a168f10fab3a149357fb", - "orgName": "jww-12-16", - "roles": [ - "ORG_OWNER" - ], - "username": "wyatt.smith@example.com"}, - {"createdAt": "2021-02-18T21:05:40Z", - "expiresAt": "2021-03-20T21:05:40Z", - "id": "5a0a1e7e0f2912c554080adc", - "inviterUsername": "admin@example.com", - "orgId": "5df7a168f10fab3a149357fb", - "orgName": "jww-12-16", - "roles": [ - "ORG_OWNER" - ], - "teamIds": ["2"], - "username": "wyatt.smith@example.com"}]`) - }) - - invitation, _, err := client.Organizations.ListUnacceptedInvitations(ctx, orgID, nil) - if err != nil { - t.Fatalf("Organizations.GetUnacceptedInvitation returned error: %v", err) - } - - expected := &[]Invitation{ - { - ID: "5a0a1e7e0f2912c554080adc", - OrgID: "5df7a168f10fab3a149357fb", - OrgName: "jww-12-16", - CreatedAt: "2021-02-18T21:05:40Z", - ExpiresAt: "2021-03-20T21:05:40Z", - InviterUserName: "admin@example.com", - Username: "wyatt.smith@example.com", - Roles: []string{"ORG_OWNER"}, - }, - { - ID: "5a0a1e7e0f2912c554080adc", - OrgID: "5df7a168f10fab3a149357fb", - OrgName: "jww-12-16", - CreatedAt: "2021-02-18T21:05:40Z", - ExpiresAt: "2021-03-20T21:05:40Z", - InviterUserName: "admin@example.com", - Username: "wyatt.smith@example.com", - Roles: []string{"ORG_OWNER"}, - TeamIDs: []string{"2"}, - }, - } - - if diff := deep.Equal(invitation, expected); diff != nil { - t.Error(diff) - } -} - -func TestOrganizations_GetUnacceptedInvitation(t *testing.T) { - client, mux, teardown := setup() - defer teardown() - - mux.HandleFunc(fmt.Sprintf("/api/atlas/v1.0/orgs/%s/invites/%s", orgID, invitationID), func(w http.ResponseWriter, r *http.Request) { - testMethod(t, r, http.MethodGet) - _, _ = fmt.Fprint(w, `{ - "createdAt": "2021-02-18T21:05:40Z", - "expiresAt": "2021-03-20T21:05:40Z", - "id": "5a0a1e7e0f2912c554080adc", - "inviterUsername": "admin@example.com", - "orgId": "5df7a168f10fab3a149357fb", - "orgName": "jww-12-16", - "roles": [ - "ORG_OWNER" - ], - "username": "wyatt.smith@example.com" - }`) - }) - - invitation, _, err := client.Organizations.GetUnacceptedInvitation(ctx, orgID, invitationID) - if err != nil { - t.Fatalf("Organizations.GetUnacceptedInvitation returned error: %v", err) - } - - expected := &Invitation{ - ID: "5a0a1e7e0f2912c554080adc", - OrgID: "5df7a168f10fab3a149357fb", - OrgName: "jww-12-16", - CreatedAt: "2021-02-18T21:05:40Z", - ExpiresAt: "2021-03-20T21:05:40Z", - InviterUserName: "admin@example.com", - Username: "wyatt.smith@example.com", - Roles: []string{"ORG_OWNER"}, - } - - if diff := deep.Equal(invitation, expected); diff != nil { - t.Error(diff) - } -} - -func TestOrganizations_InviteUser(t *testing.T) { - client, mux, teardown := setup() - defer teardown() - - mux.HandleFunc(fmt.Sprintf("/api/atlas/v1.0/orgs/%s/invites", orgID), func(w http.ResponseWriter, r *http.Request) { - testMethod(t, r, http.MethodPost) - _, _ = fmt.Fprint(w, `{ - "createdAt": "2021-02-18T21:05:40Z", - "expiresAt": "2021-03-20T21:05:40Z", - "id": "5a0a1e7e0f2912c554080adc", - "inviterUsername": "admin@example.com", - "orgId": "5df7a168f10fab3a149357fb", - "orgName": "jww-12-16", - "roles": [ - "ORG_OWNER" - ], - "username": "wyatt.smith@example.com" - }`) - }) - - body := &Invitation{ - OrgID: orgID, - OrgName: "jww-12-16", - CreatedAt: "2021-02-18T21:05:40Z", - ExpiresAt: "2021-03-20T21:05:40Z", - InviterUserName: "admin@example.com", - Username: "wyatt.smith@example.com", - Roles: []string{"ORG_OWNER"}, - } - - invitation, _, err := client.Organizations.InviteUser(ctx, body) - if err != nil { - t.Fatalf("Organizations.InviteUser returned error: %v", err) - } - - expected := &Invitation{ - ID: "5a0a1e7e0f2912c554080adc", - OrgID: "5df7a168f10fab3a149357fb", - OrgName: "jww-12-16", - CreatedAt: "2021-02-18T21:05:40Z", - ExpiresAt: "2021-03-20T21:05:40Z", - InviterUserName: "admin@example.com", - Username: "wyatt.smith@example.com", - Roles: []string{"ORG_OWNER"}, - } - - if diff := deep.Equal(invitation, expected); diff != nil { - t.Error(diff) - } -} - -func TestOrganizations_UpdateInvitation(t *testing.T) { - client, mux, teardown := setup() - defer teardown() - - mux.HandleFunc(fmt.Sprintf("/api/atlas/v1.0/orgs/%s/invites", orgID), func(w http.ResponseWriter, r *http.Request) { - testMethod(t, r, http.MethodPatch) - _, _ = fmt.Fprint(w, `{ - "createdAt": "2021-02-18T21:05:40Z", - "expiresAt": "2021-03-20T21:05:40Z", - "id": "5a0a1e7e0f2912c554080adc", - "inviterUsername": "admin@example.com", - "orgId": "5df7a168f10fab3a149357fb", - "orgName": "jww-12-16", - "roles": [ - "ORG_OWNER" - ], - "username": "wyatt.smith@example.com" - }`) - }) - - body := &Invitation{ - OrgID: orgID, - OrgName: "jww-12-16", - CreatedAt: "2021-02-18T21:05:40Z", - ExpiresAt: "2021-03-20T21:05:40Z", - InviterUserName: "admin@example.com", - Username: "wyatt.smith@example.com", - Roles: []string{"ORG_OWNER"}, - } - - invitation, _, err := client.Organizations.UpdateInvitation(ctx, body) - if err != nil { - t.Fatalf("Organizations.UpdateInvitation returned error: %v", err) - } - - expected := &Invitation{ - ID: "5a0a1e7e0f2912c554080adc", - OrgID: "5df7a168f10fab3a149357fb", - OrgName: "jww-12-16", - CreatedAt: "2021-02-18T21:05:40Z", - ExpiresAt: "2021-03-20T21:05:40Z", - InviterUserName: "admin@example.com", - Username: "wyatt.smith@example.com", - Roles: []string{"ORG_OWNER"}, - } - - if diff := deep.Equal(invitation, expected); diff != nil { - t.Error(diff) - } -} - -func TestOrganizations_UpdateInvitationByID(t *testing.T) { - client, mux, teardown := setup() - defer teardown() - - mux.HandleFunc(fmt.Sprintf("/api/atlas/v1.0/orgs/%s/invites/%s", orgID, invitationID), func(w http.ResponseWriter, r *http.Request) { - testMethod(t, r, http.MethodPatch) - _, _ = fmt.Fprint(w, `{ - "createdAt": "2021-02-18T21:05:40Z", - "expiresAt": "2021-03-20T21:05:40Z", - "id": "5a0a1e7e0f2912c554080adc", - "inviterUsername": "admin@example.com", - "orgId": "5df7a168f10fab3a149357fb", - "orgName": "jww-12-16", - "roles": [ - "ORG_OWNER" - ], - "username": "wyatt.smith@example.com" - }`) - }) - - body := &Invitation{ - OrgID: orgID, - ID: invitationID, - OrgName: "jww-12-16", - CreatedAt: "2021-02-18T21:05:40Z", - ExpiresAt: "2021-03-20T21:05:40Z", - InviterUserName: "admin@example.com", - Username: "wyatt.smith@example.com", - Roles: []string{"ORG_OWNER"}, - } - - invitation, _, err := client.Organizations.UpdateInvitation(ctx, body) - if err != nil { - t.Fatalf("Organizations.UpdateInvitation returned error: %v", err) - } - - expected := &Invitation{ - ID: "5a0a1e7e0f2912c554080adc", - OrgID: "5df7a168f10fab3a149357fb", - OrgName: "jww-12-16", - CreatedAt: "2021-02-18T21:05:40Z", - ExpiresAt: "2021-03-20T21:05:40Z", - InviterUserName: "admin@example.com", - Username: "wyatt.smith@example.com", - Roles: []string{"ORG_OWNER"}, - } - - if diff := deep.Equal(invitation, expected); diff != nil { - t.Error(diff) - } -} - -func TestOrganizations_DeleteInvitation(t *testing.T) { - client, mux, teardown := setup() - defer teardown() - - mux.HandleFunc(fmt.Sprintf("/api/atlas/v1.0/orgs/%s/invites/%s", orgID, invitationID), func(w http.ResponseWriter, r *http.Request) { - testMethod(t, r, http.MethodDelete) - }) - - _, err := client.Organizations.DeleteInvitation(ctx, orgID, invitationID) - if err != nil { - t.Fatalf("Organizations.DeleteInvitation returned error: %v", err) - } -} From 7ac6fb54945d2847e1b91f51bb34a5749f9d0372 Mon Sep 17 00:00:00 2001 From: andreaangiolillo Date: Mon, 28 Jun 2021 15:36:12 +0200 Subject: [PATCH 7/8] renamed files --- .../{organizations_invitations.go => organization_invitations.go} | 0 ...tions_invitations_test.go => organization_invitations_test.go} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename mongodbatlas/{organizations_invitations.go => organization_invitations.go} (100%) rename mongodbatlas/{organizations_invitations_test.go => organization_invitations_test.go} (100%) diff --git a/mongodbatlas/organizations_invitations.go b/mongodbatlas/organization_invitations.go similarity index 100% rename from mongodbatlas/organizations_invitations.go rename to mongodbatlas/organization_invitations.go diff --git a/mongodbatlas/organizations_invitations_test.go b/mongodbatlas/organization_invitations_test.go similarity index 100% rename from mongodbatlas/organizations_invitations_test.go rename to mongodbatlas/organization_invitations_test.go From f3fc6a188e2ef1ad260a2a29ba014d7bc0e877c6 Mon Sep 17 00:00:00 2001 From: andreaangiolillo Date: Mon, 28 Jun 2021 15:41:46 +0200 Subject: [PATCH 8/8] Refactoring --- mongodbatlas/organization_invitations.go | 6 +++--- mongodbatlas/organization_invitations_test.go | 18 +++++++++--------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/mongodbatlas/organization_invitations.go b/mongodbatlas/organization_invitations.go index ae7445b9e..c9de4b2e7 100644 --- a/mongodbatlas/organization_invitations.go +++ b/mongodbatlas/organization_invitations.go @@ -34,7 +34,7 @@ type Invitation struct { OrgName string `json:"orgName,omitempty"` CreatedAt string `json:"createdAt,omitempty"` ExpiresAt string `json:"expiresAt,omitempty"` - InviterUserName string `json:"inviterUsername,omitempty"` + InviterUsername string `json:"inviterUsername,omitempty"` Username string `json:"username,omitempty"` Roles []string `json:"roles,omitempty"` TeamIDs []string `json:"teamIds,omitempty"` @@ -123,7 +123,7 @@ func (s *OrganizationsServiceOp) InviteUser(ctx context.Context, invitation *Inv // UpdateInvitation updates one pending invitation to the Atlas organization that you specify. // -// See more: https://docs-atlas-staging.mongodb.com/cloud-docs/docsworker-xlarge/DOCSP-14695/reference/api/organization-update-one-invitation/ +// See more: https://docs.atlas.mongodb.com/reference/api/organization-update-one-invitation/ func (s *OrganizationsServiceOp) UpdateInvitation(ctx context.Context, invitation *Invitation) (*Invitation, *Response, error) { if invitation.OrgID == "" { return nil, nil, NewArgError("orgID", "must be set") @@ -134,7 +134,7 @@ func (s *OrganizationsServiceOp) UpdateInvitation(ctx context.Context, invitatio // UpdateInvitationByID updates one invitation to the Atlas organization. // -// See more: https://docs-atlas-staging.mongodb.com/cloud-docs/docsworker-xlarge/DOCSP-14695/reference/api/organization-update-one-invitation-by-id/ +// See more: https://docs.atlas.mongodb.com/reference/api/organization-update-one-invitation-by-id/ func (s *OrganizationsServiceOp) UpdateInvitationByID(ctx context.Context, invitationID string, invitation *Invitation) (*Invitation, *Response, error) { if invitation.OrgID == "" { return nil, nil, NewArgError("orgID", "must be set") diff --git a/mongodbatlas/organization_invitations_test.go b/mongodbatlas/organization_invitations_test.go index db2c8a14c..8dce88fc6 100644 --- a/mongodbatlas/organization_invitations_test.go +++ b/mongodbatlas/organization_invitations_test.go @@ -67,7 +67,7 @@ func TestOrganizations_Invitations(t *testing.T) { OrgName: "jww-12-16", CreatedAt: "2021-02-18T21:05:40Z", ExpiresAt: "2021-03-20T21:05:40Z", - InviterUserName: "admin@example.com", + InviterUsername: "admin@example.com", Username: "wyatt.smith@example.com", Roles: []string{"ORG_OWNER"}, }, @@ -77,7 +77,7 @@ func TestOrganizations_Invitations(t *testing.T) { OrgName: "jww-12-16", CreatedAt: "2021-02-18T21:05:40Z", ExpiresAt: "2021-03-20T21:05:40Z", - InviterUserName: "admin@example.com", + InviterUsername: "admin@example.com", Username: "wyatt.smith@example.com", Roles: []string{"ORG_OWNER"}, TeamIDs: []string{"2"}, @@ -120,7 +120,7 @@ func TestOrganizations_Invitation(t *testing.T) { OrgName: "jww-12-16", CreatedAt: "2021-02-18T21:05:40Z", ExpiresAt: "2021-03-20T21:05:40Z", - InviterUserName: "admin@example.com", + InviterUsername: "admin@example.com", Username: "wyatt.smith@example.com", Roles: []string{"ORG_OWNER"}, } @@ -155,7 +155,7 @@ func TestOrganizations_InviteUser(t *testing.T) { OrgName: "jww-12-16", CreatedAt: "2021-02-18T21:05:40Z", ExpiresAt: "2021-03-20T21:05:40Z", - InviterUserName: "admin@example.com", + InviterUsername: "admin@example.com", Username: "wyatt.smith@example.com", Roles: []string{"ORG_OWNER"}, } @@ -171,7 +171,7 @@ func TestOrganizations_InviteUser(t *testing.T) { OrgName: "jww-12-16", CreatedAt: "2021-02-18T21:05:40Z", ExpiresAt: "2021-03-20T21:05:40Z", - InviterUserName: "admin@example.com", + InviterUsername: "admin@example.com", Username: "wyatt.smith@example.com", Roles: []string{"ORG_OWNER"}, } @@ -206,7 +206,7 @@ func TestOrganizations_UpdateInvitation(t *testing.T) { OrgName: "jww-12-16", CreatedAt: "2021-02-18T21:05:40Z", ExpiresAt: "2021-03-20T21:05:40Z", - InviterUserName: "admin@example.com", + InviterUsername: "admin@example.com", Username: "wyatt.smith@example.com", Roles: []string{"ORG_OWNER"}, } @@ -222,7 +222,7 @@ func TestOrganizations_UpdateInvitation(t *testing.T) { OrgName: "jww-12-16", CreatedAt: "2021-02-18T21:05:40Z", ExpiresAt: "2021-03-20T21:05:40Z", - InviterUserName: "admin@example.com", + InviterUsername: "admin@example.com", Username: "wyatt.smith@example.com", Roles: []string{"ORG_OWNER"}, } @@ -258,7 +258,7 @@ func TestOrganizations_UpdateInvitationByID(t *testing.T) { OrgName: "jww-12-16", CreatedAt: "2021-02-18T21:05:40Z", ExpiresAt: "2021-03-20T21:05:40Z", - InviterUserName: "admin@example.com", + InviterUsername: "admin@example.com", Username: "wyatt.smith@example.com", Roles: []string{"ORG_OWNER"}, } @@ -274,7 +274,7 @@ func TestOrganizations_UpdateInvitationByID(t *testing.T) { OrgName: "jww-12-16", CreatedAt: "2021-02-18T21:05:40Z", ExpiresAt: "2021-03-20T21:05:40Z", - InviterUserName: "admin@example.com", + InviterUsername: "admin@example.com", Username: "wyatt.smith@example.com", Roles: []string{"ORG_OWNER"}, }