From 81ea67ab9ebcc253554dc552f03993c9ec259260 Mon Sep 17 00:00:00 2001 From: vlastahajek Date: Thu, 23 Apr 2020 15:11:15 +0200 Subject: [PATCH 1/8] chore: Synced with latest important changes in server swagger --- domain/swagger.yml | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/domain/swagger.yml b/domain/swagger.yml index 1baa92e0..653b91f1 100644 --- a/domain/swagger.yml +++ b/domain/swagger.yml @@ -3751,6 +3751,11 @@ paths: schema: type: string description: Filter organizations to a specific organization ID. + - in: query + name: userID + schema: + type: string + description: Filter organizations to a specific user ID. responses: '200': description: A list of organizations @@ -5225,8 +5230,8 @@ paths: schema: $ref: "#/components/schemas/Error" '/users/{userID}/password': - put: - operationId: PutUsersIDPassword + post: + operationId: PostUsersIDPassword tags: - Users summary: Update a password @@ -6293,6 +6298,10 @@ components: - flux dialect: $ref: "#/components/schemas/Dialect" + now: + description: Specifies the time that should be reported as "now" in the query. Default is the server's now time. + type: string + format: date-time InfluxQLQuery: description: Query influx using the InfluxQL language type: object From 3b64a4f4e133badc9d457bff2a7cf7e83b886fb6 Mon Sep 17 00:00:00 2001 From: vlastahajek Date: Thu, 23 Apr 2020 15:11:59 +0200 Subject: [PATCH 2/8] chore: Regenerated from lastest swagger changes --- domain/client.gen.go | 68 +++++++++++++++++++++++++++----------------- domain/types.gen.go | 18 ++++++++---- 2 files changed, 54 insertions(+), 32 deletions(-) diff --git a/domain/client.gen.go b/domain/client.gen.go index 937d14d0..4429081b 100644 --- a/domain/client.gen.go +++ b/domain/client.gen.go @@ -718,10 +718,10 @@ type ClientInterface interface { // GetUsersIDLogs request GetUsersIDLogs(ctx context.Context, userID string, params *GetUsersIDLogsParams) (*http.Response, error) - // PutUsersIDPassword request with any body - PutUsersIDPasswordWithBody(ctx context.Context, userID string, params *PutUsersIDPasswordParams, contentType string, body io.Reader) (*http.Response, error) + // PostUsersIDPassword request with any body + PostUsersIDPasswordWithBody(ctx context.Context, userID string, params *PostUsersIDPasswordParams, contentType string, body io.Reader) (*http.Response, error) - PutUsersIDPassword(ctx context.Context, userID string, params *PutUsersIDPasswordParams, body PutUsersIDPasswordJSONRequestBody) (*http.Response, error) + PostUsersIDPassword(ctx context.Context, userID string, params *PostUsersIDPasswordParams, body PostUsersIDPasswordJSONRequestBody) (*http.Response, error) // GetVariables request GetVariables(ctx context.Context, params *GetVariablesParams) (*http.Response, error) @@ -5029,8 +5029,8 @@ func (c *Client) GetUsersIDLogs(ctx context.Context, userID string, params *GetU return res, nil } -func (c *Client) PutUsersIDPasswordWithBody(ctx context.Context, userID string, params *PutUsersIDPasswordParams, contentType string, body io.Reader) (*http.Response, error) { - req, err := NewPutUsersIDPasswordRequestWithBody(c.service.ServerApiUrl(), userID, params, contentType, body) +func (c *Client) PostUsersIDPasswordWithBody(ctx context.Context, userID string, params *PostUsersIDPasswordParams, contentType string, body io.Reader) (*http.Response, error) { + req, err := NewPostUsersIDPasswordRequestWithBody(c.service.ServerApiUrl(), userID, params, contentType, body) if err != nil { return nil, err } @@ -5046,8 +5046,8 @@ func (c *Client) PutUsersIDPasswordWithBody(ctx context.Context, userID string, return res, nil } -func (c *Client) PutUsersIDPassword(ctx context.Context, userID string, params *PutUsersIDPasswordParams, body PutUsersIDPasswordJSONRequestBody) (*http.Response, error) { - req, err := NewPutUsersIDPasswordRequest(c.service.ServerApiUrl(), userID, params, body) +func (c *Client) PostUsersIDPassword(ctx context.Context, userID string, params *PostUsersIDPasswordParams, body PostUsersIDPasswordJSONRequestBody) (*http.Response, error) { + req, err := NewPostUsersIDPasswordRequest(c.service.ServerApiUrl(), userID, params, body) if err != nil { return nil, err } @@ -10269,6 +10269,22 @@ func NewGetOrgsRequest(server string, params *GetOrgsParams) (*http.Request, err } + if params.UserID != nil { + + if queryFrag, err := runtime.StyleParam("form", true, "userID", *params.UserID); err != nil { + return nil, err + } else if parsed, err := url.ParseQuery(queryFrag); err != nil { + return nil, err + } else { + for k, v := range parsed { + for _, v2 := range v { + queryValues.Add(k, v2) + } + } + } + + } + queryUrl.RawQuery = queryValues.Encode() req, err := http.NewRequest("GET", queryUrl.String(), nil) @@ -15314,19 +15330,19 @@ func NewGetUsersIDLogsRequest(server string, userID string, params *GetUsersIDLo return req, nil } -// NewPutUsersIDPasswordRequest calls the generic PutUsersIDPassword builder with application/json body -func NewPutUsersIDPasswordRequest(server string, userID string, params *PutUsersIDPasswordParams, body PutUsersIDPasswordJSONRequestBody) (*http.Request, error) { +// NewPostUsersIDPasswordRequest calls the generic PostUsersIDPassword builder with application/json body +func NewPostUsersIDPasswordRequest(server string, userID string, params *PostUsersIDPasswordParams, body PostUsersIDPasswordJSONRequestBody) (*http.Request, error) { var bodyReader io.Reader buf, err := json.Marshal(body) if err != nil { return nil, err } bodyReader = bytes.NewReader(buf) - return NewPutUsersIDPasswordRequestWithBody(server, userID, params, "application/json", bodyReader) + return NewPostUsersIDPasswordRequestWithBody(server, userID, params, "application/json", bodyReader) } -// NewPutUsersIDPasswordRequestWithBody generates requests for PutUsersIDPassword with any type of body -func NewPutUsersIDPasswordRequestWithBody(server string, userID string, params *PutUsersIDPasswordParams, contentType string, body io.Reader) (*http.Request, error) { +// NewPostUsersIDPasswordRequestWithBody generates requests for PostUsersIDPassword with any type of body +func NewPostUsersIDPasswordRequestWithBody(server string, userID string, params *PostUsersIDPasswordParams, contentType string, body io.Reader) (*http.Request, error) { var err error var pathParam0 string @@ -15351,7 +15367,7 @@ func NewPutUsersIDPasswordRequestWithBody(server string, userID string, params * return nil, err } - req, err := http.NewRequest("PUT", queryUrl.String(), body) + req, err := http.NewRequest("POST", queryUrl.String(), body) if err != nil { return nil, err } @@ -20198,14 +20214,14 @@ func (r getUsersIDLogsResponse) StatusCode() int { return 0 } -type putUsersIDPasswordResponse struct { +type postUsersIDPasswordResponse struct { Body []byte HTTPResponse *http.Response JSONDefault *Error } // Status returns HTTPResponse.Status -func (r putUsersIDPasswordResponse) Status() string { +func (r postUsersIDPasswordResponse) Status() string { if r.HTTPResponse != nil { return r.HTTPResponse.Status } @@ -20213,7 +20229,7 @@ func (r putUsersIDPasswordResponse) Status() string { } // StatusCode returns HTTPResponse.StatusCode -func (r putUsersIDPasswordResponse) StatusCode() int { +func (r postUsersIDPasswordResponse) StatusCode() int { if r.HTTPResponse != nil { return r.HTTPResponse.StatusCode } @@ -22644,21 +22660,21 @@ func (c *ClientWithResponses) GetUsersIDLogsWithResponse(ctx context.Context, us return ParseGetUsersIDLogsResponse(rsp) } -// PutUsersIDPasswordWithBodyWithResponse request with arbitrary body returning *PutUsersIDPasswordResponse -func (c *ClientWithResponses) PutUsersIDPasswordWithBodyWithResponse(ctx context.Context, userID string, params *PutUsersIDPasswordParams, contentType string, body io.Reader) (*putUsersIDPasswordResponse, error) { - rsp, err := c.PutUsersIDPasswordWithBody(ctx, userID, params, contentType, body) +// PostUsersIDPasswordWithBodyWithResponse request with arbitrary body returning *PostUsersIDPasswordResponse +func (c *ClientWithResponses) PostUsersIDPasswordWithBodyWithResponse(ctx context.Context, userID string, params *PostUsersIDPasswordParams, contentType string, body io.Reader) (*postUsersIDPasswordResponse, error) { + rsp, err := c.PostUsersIDPasswordWithBody(ctx, userID, params, contentType, body) if err != nil { return nil, err } - return ParsePutUsersIDPasswordResponse(rsp) + return ParsePostUsersIDPasswordResponse(rsp) } -func (c *ClientWithResponses) PutUsersIDPasswordWithResponse(ctx context.Context, userID string, params *PutUsersIDPasswordParams, body PutUsersIDPasswordJSONRequestBody) (*putUsersIDPasswordResponse, error) { - rsp, err := c.PutUsersIDPassword(ctx, userID, params, body) +func (c *ClientWithResponses) PostUsersIDPasswordWithResponse(ctx context.Context, userID string, params *PostUsersIDPasswordParams, body PostUsersIDPasswordJSONRequestBody) (*postUsersIDPasswordResponse, error) { + rsp, err := c.PostUsersIDPassword(ctx, userID, params, body) if err != nil { return nil, err } - return ParsePutUsersIDPasswordResponse(rsp) + return ParsePostUsersIDPasswordResponse(rsp) } // GetVariablesWithResponse request returning *GetVariablesResponse @@ -28820,15 +28836,15 @@ func ParseGetUsersIDLogsResponse(rsp *http.Response) (*getUsersIDLogsResponse, e return response, nil } -// ParsePutUsersIDPasswordResponse parses an HTTP response from a PutUsersIDPasswordWithResponse call -func ParsePutUsersIDPasswordResponse(rsp *http.Response) (*putUsersIDPasswordResponse, error) { +// ParsePostUsersIDPasswordResponse parses an HTTP response from a PostUsersIDPasswordWithResponse call +func ParsePostUsersIDPasswordResponse(rsp *http.Response) (*postUsersIDPasswordResponse, error) { bodyBytes, err := ioutil.ReadAll(rsp.Body) defer rsp.Body.Close() if err != nil { return nil, err } - response := &putUsersIDPasswordResponse{ + response := &postUsersIDPasswordResponse{ Body: bodyBytes, HTTPResponse: rsp, } diff --git a/domain/types.gen.go b/domain/types.gen.go index fa212b87..c61da448 100644 --- a/domain/types.gen.go +++ b/domain/types.gen.go @@ -2892,6 +2892,9 @@ type Query struct { // Represents a source from a single file Extern *File `json:"extern,omitempty"` + // Specifies the time that should be reported as "now" in the query. Default is the server's now time. + Now *time.Time `json:"now,omitempty"` + // Query script to execute. Query string `json:"query"` @@ -4965,6 +4968,9 @@ type GetOrgsParams struct { // Filter organizations to a specific organization ID. OrgID *string `json:"orgID,omitempty"` + // Filter organizations to a specific user ID. + UserID *string `json:"userID,omitempty"` + // OpenTracing span context ZapTraceSpan *TraceSpan `json:"Zap-Trace-Span,omitempty"` } @@ -5800,11 +5806,11 @@ type GetUsersIDLogsParams struct { ZapTraceSpan *TraceSpan `json:"Zap-Trace-Span,omitempty"` } -// PutUsersIDPasswordJSONBody defines parameters for PutUsersIDPassword. -type PutUsersIDPasswordJSONBody PasswordResetBody +// PostUsersIDPasswordJSONBody defines parameters for PostUsersIDPassword. +type PostUsersIDPasswordJSONBody PasswordResetBody -// PutUsersIDPasswordParams defines parameters for PutUsersIDPassword. -type PutUsersIDPasswordParams struct { +// PostUsersIDPasswordParams defines parameters for PostUsersIDPassword. +type PostUsersIDPasswordParams struct { // OpenTracing span context ZapTraceSpan *TraceSpan `json:"Zap-Trace-Span,omitempty"` @@ -6138,8 +6144,8 @@ type PostUsersJSONRequestBody PostUsersJSONBody // PatchUsersIDRequestBody defines body for PatchUsersID for application/json ContentType. type PatchUsersIDJSONRequestBody PatchUsersIDJSONBody -// PutUsersIDPasswordRequestBody defines body for PutUsersIDPassword for application/json ContentType. -type PutUsersIDPasswordJSONRequestBody PutUsersIDPasswordJSONBody +// PostUsersIDPasswordRequestBody defines body for PostUsersIDPassword for application/json ContentType. +type PostUsersIDPasswordJSONRequestBody PostUsersIDPasswordJSONBody // PostVariablesRequestBody defines body for PostVariables for application/json ContentType. type PostVariablesJSONRequestBody PostVariablesJSONBody From 2572b96f513f39ce73c74e53cb02f6c556ca1b6e Mon Sep 17 00:00:00 2001 From: vlastahajek Date: Thu, 23 Apr 2020 15:12:31 +0200 Subject: [PATCH 3/8] doc: added swagger download link --- domain/Readme.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/domain/Readme.md b/domain/Readme.md index 455df3cc..150dcdd1 100644 --- a/domain/Readme.md +++ b/domain/Readme.md @@ -2,10 +2,16 @@ `swagger.yml` is copied from InfluxDB and customized. Must be periodically sync with latest changes and types and client must be re-generated + + + ## Install oapi generator `git clone git@github.com:bonitoo-io/oapi-codegen.git` `cd oapi-codegen` -`go build ./cmd/oapi-codegen/oapi-codegen.go` +`go build ./cmd/oapi-codegen/oapi-codegen.go` +## Download and sync latest swagger +`wget https://raw.githubusercontent.com/influxdata/influxdb/master/http/swagger.yml` + ## Generate `cd domain` From cfd1131d9fef11a5fdc7ae9406c0491a3ec1bced Mon Sep 17 00:00:00 2001 From: vlastahajek Date: Thu, 23 Apr 2020 15:14:00 +0200 Subject: [PATCH 4/8] feat: Organizations and users API --- api/organizations.go | 162 ++++++++++++++++++++++++++++++++++++++++++- api/users.go | 156 +++++++++++++++++++++++++++++++++++++++++ client.go | 6 ++ client_e2e_test.go | 122 ++++++++++++++++++++++++++++++++ 4 files changed, 445 insertions(+), 1 deletion(-) create mode 100644 api/users.go diff --git a/api/organizations.go b/api/organizations.go index 24edcb04..2662698f 100644 --- a/api/organizations.go +++ b/api/organizations.go @@ -6,9 +6,36 @@ import ( ihttp "github.com/influxdata/influxdb-client-go/internal/http" ) +// OrganizationsApi provides methods for managing Organizations in a InfluxDB server type OrganizationsApi interface { - // FindOrganizationByName returns organization found using orgNme + // FindOrganizationByName returns all organizations + FindOrganizations(ctx context.Context) (*[]domain.Organization, error) + // FindOrganizationByName returns an organization found using orgNme FindOrganizationByName(ctx context.Context, orgName string) (*domain.Organization, error) + // FindOrganizationByName returns an organization found using orgId + FindOrganizationById(ctx context.Context, orgId string) (*domain.Organization, error) + // CreateOrganization creates new organization + CreateOrganization(ctx context.Context, org *domain.Organization) (*domain.Organization, error) + // CreateOrganizationWithName creates new organization with orgName and with status active + CreateOrganizationWithName(ctx context.Context, orgName string) (*domain.Organization, error) + // UpdateOrganization updates organization + UpdateOrganization(ctx context.Context, org *domain.Organization) (*domain.Organization, error) + // DeleteOrganization deletes an organization + DeleteOrganization(ctx context.Context, org *domain.Organization) error + // DeleteOrganizationWithID deletes an organization with orgId + DeleteOrganizationWithID(ctx context.Context, orgId string) error + // GetMembers returns members of an organization + GetMembers(ctx context.Context, org *domain.Organization) (*[]domain.ResourceMember, error) + // GetMembersWithID returns members of an organization with orgId + GetMembersWithID(ctx context.Context, orgId string) (*[]domain.ResourceMember, error) + // AddMember add a user to an organization + AddMember(ctx context.Context, org *domain.Organization, user *domain.User) (*domain.ResourceMember, error) + // AddMember add a member with id memberId to an organization with orgId + AddMemberWithIDs(ctx context.Context, orgId, memberId string) (*domain.ResourceMember, error) + // RemoveMember add a user from an organization + RemoveMember(ctx context.Context, org *domain.Organization, user *domain.User) error + // RemoveMember removes a member with id memberId from an organization with orgId + RemoveMemberWithIDs(ctx context.Context, orgId, memberId string) error } type organizationsApiImpl struct { @@ -23,6 +50,18 @@ func NewOrganizationsApi(service ihttp.Service) OrganizationsApi { } } +func (o *organizationsApiImpl) FindOrganizations(ctx context.Context) (*[]domain.Organization, error) { + params := &domain.GetOrgsParams{} + response, err := o.apiClient.GetOrgsWithResponse(ctx, params) + if err != nil { + return nil, err + } + if response.JSONDefault != nil { + return nil, domain.DomainErrorToError(response.JSONDefault, response.StatusCode()) + } + return response.JSON200.Orgs, nil +} + func (o *organizationsApiImpl) FindOrganizationByName(ctx context.Context, orgName string) (*domain.Organization, error) { params := &domain.GetOrgsParams{Org: &orgName} response, err := o.apiClient.GetOrgsWithResponse(ctx, params) @@ -34,3 +73,124 @@ func (o *organizationsApiImpl) FindOrganizationByName(ctx context.Context, orgNa } return &(*response.JSON200.Orgs)[0], nil } + +func (o *organizationsApiImpl) FindOrganizationById(ctx context.Context, orgId string) (*domain.Organization, error) { + params := &domain.GetOrgsParams{OrgID: &orgId} + response, err := o.apiClient.GetOrgsWithResponse(ctx, params) + if err != nil { + return nil, err + } + if response.JSONDefault != nil { + return nil, domain.DomainErrorToError(response.JSONDefault, response.StatusCode()) + } + return &(*response.JSON200.Orgs)[0], nil +} + +func (o *organizationsApiImpl) CreateOrganization(ctx context.Context, org *domain.Organization) (*domain.Organization, error) { + params := &domain.PostOrgsParams{} + response, err := o.apiClient.PostOrgsWithResponse(ctx, params, domain.PostOrgsJSONRequestBody(*org)) + if err != nil { + return nil, err + } + if response.JSONDefault != nil { + return nil, domain.DomainErrorToError(response.JSONDefault, response.StatusCode()) + } + return response.JSON201, nil +} + +func (o *organizationsApiImpl) CreateOrganizationWithName(ctx context.Context, orgName string) (*domain.Organization, error) { + params := &domain.PostOrgsParams{} + status := domain.OrganizationStatusActive + org := &domain.Organization{Name: orgName, Status: &status} + response, err := o.apiClient.PostOrgsWithResponse(ctx, params, domain.PostOrgsJSONRequestBody(*org)) + if err != nil { + return nil, err + } + if response.JSONDefault != nil { + return nil, domain.DomainErrorToError(response.JSONDefault, response.StatusCode()) + } + return response.JSON201, nil +} + +func (o *organizationsApiImpl) DeleteOrganization(ctx context.Context, org *domain.Organization) error { + return o.DeleteOrganizationWithID(ctx, *org.Id) +} + +func (o *organizationsApiImpl) DeleteOrganizationWithID(ctx context.Context, orgId string) error { + params := &domain.DeleteOrgsIDParams{} + response, err := o.apiClient.DeleteOrgsIDWithResponse(ctx, orgId, params) + if err != nil { + return err + } + if response.JSONDefault != nil { + return domain.DomainErrorToError(response.JSONDefault, response.StatusCode()) + } + if response.JSON404 != nil { + return domain.DomainErrorToError(response.JSON404, response.StatusCode()) + } + return nil +} + +func (o *organizationsApiImpl) UpdateOrganization(ctx context.Context, org *domain.Organization) (*domain.Organization, error) { + params := &domain.PatchOrgsIDParams{} + response, err := o.apiClient.PatchOrgsIDWithResponse(ctx, *org.Id, params, domain.PatchOrgsIDJSONRequestBody(*org)) + if err != nil { + return nil, err + } + if response.JSONDefault != nil { + return nil, domain.DomainErrorToError(response.JSONDefault, response.StatusCode()) + } + return response.JSON200, nil +} + +func (o *organizationsApiImpl) GetMembers(ctx context.Context, org *domain.Organization) (*[]domain.ResourceMember, error) { + return o.GetMembersWithID(ctx, *org.Id) +} + +func (o *organizationsApiImpl) GetMembersWithID(ctx context.Context, orgId string) (*[]domain.ResourceMember, error) { + params := &domain.GetOrgsIDMembersParams{} + response, err := o.apiClient.GetOrgsIDMembersWithResponse(ctx, orgId, params) + if err != nil { + return nil, err + } + if response.JSONDefault != nil { + return nil, domain.DomainErrorToError(response.JSONDefault, response.StatusCode()) + } + if response.JSON404 != nil { + return nil, domain.DomainErrorToError(response.JSON404, response.StatusCode()) + } + return response.JSON200.Users, nil +} + +func (o *organizationsApiImpl) AddMember(ctx context.Context, org *domain.Organization, user *domain.User) (*domain.ResourceMember, error) { + return o.AddMemberWithIDs(ctx, *org.Id, *user.Id) +} + +func (o *organizationsApiImpl) AddMemberWithIDs(ctx context.Context, orgId, memberId string) (*domain.ResourceMember, error) { + params := &domain.PostOrgsIDMembersParams{} + body := &domain.PostOrgsIDMembersJSONRequestBody{Id: memberId} + response, err := o.apiClient.PostOrgsIDMembersWithResponse(ctx, orgId, params, *body) + if err != nil { + return nil, err + } + if response.JSONDefault != nil { + return nil, domain.DomainErrorToError(response.JSONDefault, response.StatusCode()) + } + return response.JSON201, nil +} + +func (o *organizationsApiImpl) RemoveMember(ctx context.Context, org *domain.Organization, user *domain.User) error { + return o.RemoveMemberWithIDs(ctx, *org.Id, *user.Id) +} + +func (o *organizationsApiImpl) RemoveMemberWithIDs(ctx context.Context, orgId, memberId string) error { + params := &domain.DeleteOrgsIDMembersIDParams{} + response, err := o.apiClient.DeleteOrgsIDMembersIDWithResponse(ctx, orgId, memberId, params) + if err != nil { + return err + } + if response.JSONDefault != nil { + return domain.DomainErrorToError(response.JSONDefault, response.StatusCode()) + } + return nil +} diff --git a/api/users.go b/api/users.go new file mode 100644 index 00000000..7c69826e --- /dev/null +++ b/api/users.go @@ -0,0 +1,156 @@ +package api + +import ( + "context" + "github.com/influxdata/influxdb-client-go/domain" + ihttp "github.com/influxdata/influxdb-client-go/internal/http" +) + +// UsersApi provides methods for managing users in a InfluxDB server +type UsersApi interface { + // FindUsers returns all users + FindUsers(ctx context.Context) (*[]domain.User, error) + // FindUserByID returns user with userID + FindUserByID(ctx context.Context, userID string) (*domain.User, error) + // CreateUser creates new user + CreateUser(ctx context.Context, user *domain.User) (*domain.User, error) + // CreateUserWithName creates new user with userName + CreateUserWithName(ctx context.Context, userName string) (*domain.User, error) + // UpdateUser updates user + UpdateUser(ctx context.Context, user *domain.User) (*domain.User, error) + // UpdateUserPassword sets password for an user + UpdateUserPassword(ctx context.Context, user *domain.User, password string) error + // UpdateUserPasswordWithID sets password for an user with userId + UpdateUserPasswordWithID(ctx context.Context, userID string, password string) error + // DeleteUserWithId deletes an user with userId + DeleteUserWithID(ctx context.Context, userID string) error + // DeleteUser deletes an user + DeleteUser(ctx context.Context, user *domain.User) error + // Me returns actual user + Me(ctx context.Context) (*domain.User, error) + // MeUpdatePassword set password of actual user + MeUpdatePassword(ctx context.Context, password string) error +} + +type usersApiImpl struct { + apiClient *domain.ClientWithResponses +} + +func NewUsersApi(service ihttp.Service) UsersApi { + + apiClient := domain.NewClientWithResponses(service) + return &usersApiImpl{ + apiClient: apiClient, + } +} + +func (u *usersApiImpl) FindUsers(ctx context.Context) (*[]domain.User, error) { + params := &domain.GetUsersParams{} + response, err := u.apiClient.GetUsersWithResponse(ctx, params) + if err != nil { + return nil, err + } + if response.JSONDefault != nil { + return nil, domain.DomainErrorToError(response.JSONDefault, response.StatusCode()) + } + return response.JSON200.Users, nil +} + +func (u *usersApiImpl) FindUserByID(ctx context.Context, userID string) (*domain.User, error) { + params := &domain.GetUsersIDParams{} + response, err := u.apiClient.GetUsersIDWithResponse(ctx, userID, params) + if err != nil { + return nil, err + } + if response.JSONDefault != nil { + return nil, domain.DomainErrorToError(response.JSONDefault, response.StatusCode()) + } + return response.JSON200, nil +} + +func (u *usersApiImpl) CreateUserWithName(ctx context.Context, userName string) (*domain.User, error) { + user := &domain.User{Name: userName} + return u.CreateUser(ctx, user) +} + +func (u *usersApiImpl) CreateUser(ctx context.Context, user *domain.User) (*domain.User, error) { + params := &domain.PostUsersParams{} + response, err := u.apiClient.PostUsersWithResponse(ctx, params, domain.PostUsersJSONRequestBody(*user)) + if err != nil { + return nil, err + } + if response.JSONDefault != nil { + return nil, domain.DomainErrorToError(response.JSONDefault, response.StatusCode()) + } + return response.JSON201, nil +} + +func (u *usersApiImpl) UpdateUser(ctx context.Context, user *domain.User) (*domain.User, error) { + params := &domain.PatchUsersIDParams{} + response, err := u.apiClient.PatchUsersIDWithResponse(ctx, *user.Id, params, domain.PatchUsersIDJSONRequestBody(*user)) + if err != nil { + return nil, err + } + if response.JSONDefault != nil { + return nil, domain.DomainErrorToError(response.JSONDefault, response.StatusCode()) + } + return response.JSON200, nil +} + +func (u *usersApiImpl) UpdateUserPassword(ctx context.Context, user *domain.User, password string) error { + return u.UpdateUserPasswordWithID(ctx, *user.Id, password) +} + +func (u *usersApiImpl) UpdateUserPasswordWithID(ctx context.Context, userID string, password string) error { + params := &domain.PostUsersIDPasswordParams{} + body := &domain.PasswordResetBody{Password: password} + response, err := u.apiClient.PostUsersIDPasswordWithResponse(ctx, userID, params, domain.PostUsersIDPasswordJSONRequestBody(*body)) + if err != nil { + return err + } + if response.JSONDefault != nil { + return domain.DomainErrorToError(response.JSONDefault, response.StatusCode()) + } + return nil +} + +func (u *usersApiImpl) DeleteUser(ctx context.Context, user *domain.User) error { + return u.DeleteUserWithID(ctx, *user.Id) +} + +func (u *usersApiImpl) DeleteUserWithID(ctx context.Context, userID string) error { + params := &domain.DeleteUsersIDParams{} + response, err := u.apiClient.DeleteUsersIDWithResponse(ctx, userID, params) + if err != nil { + return err + } + if response.JSONDefault != nil { + return domain.DomainErrorToError(response.JSONDefault, response.StatusCode()) + } + return nil +} + +func (u *usersApiImpl) Me(ctx context.Context) (*domain.User, error) { + params := &domain.GetMeParams{} + response, err := u.apiClient.GetMeWithResponse(ctx, params) + if err != nil { + return nil, err + } + if response.JSONDefault != nil { + return nil, domain.DomainErrorToError(response.JSONDefault, response.StatusCode()) + } + return response.JSON200, nil +} + +func (u *usersApiImpl) MeUpdatePassword(ctx context.Context, password string) error { + params := &domain.PutMePasswordParams{} + body := &domain.PasswordResetBody{Password: password} + response, err := u.apiClient.PutMePasswordWithResponse(ctx, params, domain.PutMePasswordJSONRequestBody(*body)) + if err != nil { + return err + } + if response.JSONDefault != nil { + return domain.DomainErrorToError(response.JSONDefault, response.StatusCode()) + } + return nil +} diff --git a/client.go b/client.go index 66580da1..cab8f75f 100644 --- a/client.go +++ b/client.go @@ -35,6 +35,8 @@ type InfluxDBClient interface { AuthorizationsApi() api.AuthorizationsApi // OrganizationsApi returns Organizations API client OrganizationsApi() api.OrganizationsApi + // UsersApi returns Users API client + UsersApi() api.UsersApi // Close ensures all ongoing asynchronous write clients finish Close() // Options returns the options associated with client @@ -134,3 +136,7 @@ func (c *client) AuthorizationsApi() api.AuthorizationsApi { func (c *client) OrganizationsApi() api.OrganizationsApi { return api.NewOrganizationsApi(c.httpService) } + +func (c *client) UsersApi() api.UsersApi { + return api.NewUsersApi(c.httpService) +} diff --git a/client_e2e_test.go b/client_e2e_test.go index 36e3cced..cc9a7e23 100644 --- a/client_e2e_test.go +++ b/client_e2e_test.go @@ -205,3 +205,125 @@ func TestAuthorizationsApi(t *testing.T) { assert.Len(t, *listRes, 1) } + +func TestOrganizations(t *testing.T) { + if !e2e { + t.Skip("e2e not enabled. Launch InfluxDB 2 on localhost and run test with -e2e") + } + client := NewClient("http://localhost:9999", authToken) + orgsApi := client.OrganizationsApi() + usersApi := client.UsersApi() + orgName := "my-org-2" + orgDescription := "my-org 2 description" + + orgList, err := orgsApi.FindOrganizations(context.Background()) + require.Nil(t, err) + require.NotNil(t, orgList) + assert.Len(t, *orgList, 1) + + org, err := orgsApi.CreateOrganizationWithName(context.Background(), orgName) + require.Nil(t, err) + require.NotNil(t, org) + assert.Equal(t, orgName, org.Name) + + //test duplicit org + _, err = orgsApi.CreateOrganizationWithName(context.Background(), orgName) + require.NotNil(t, err) + + org.Description = &orgDescription + + org, err = orgsApi.UpdateOrganization(context.Background(), org) + require.Nil(t, err) + require.NotNil(t, org) + assert.Equal(t, orgDescription, *org.Description) + + orgList, err = orgsApi.FindOrganizations(context.Background()) + + require.Nil(t, err) + require.NotNil(t, orgList) + assert.Len(t, *orgList, 2) + + members, err := orgsApi.GetMembers(context.Background(), org) + require.Nil(t, err) + require.NotNil(t, members) + require.Len(t, *members, 0) + + user, err := usersApi.CreateUserWithName(context.Background(), "user-01") + require.Nil(t, err) + require.NotNil(t, user) + + member, err := orgsApi.AddMember(context.Background(), org, user) + require.Nil(t, err) + require.NotNil(t, member) + assert.Equal(t, *user.Id, *member.Id) + assert.Equal(t, user.Name, member.Name) + + members, err = orgsApi.GetMembers(context.Background(), org) + require.Nil(t, err) + require.NotNil(t, members) + require.Len(t, *members, 1) + + err = orgsApi.RemoveMember(context.Background(), org, user) + require.Nil(t, err) + + members, err = orgsApi.GetMembers(context.Background(), org) + require.Nil(t, err) + require.NotNil(t, members) + require.Len(t, *members, 0) + + err = orgsApi.DeleteOrganization(context.Background(), org) + require.Nil(t, err) + + orgList, err = orgsApi.FindOrganizations(context.Background()) + require.Nil(t, err) + require.NotNil(t, orgList) + assert.Len(t, *orgList, 1) + + err = usersApi.DeleteUser(context.Background(), user) + require.Nil(t, err) +} + +func TestUsers(t *testing.T) { + if !e2e { + t.Skip("e2e not enabled. Launch InfluxDB 2 on localhost and run test with -e2e") + } + client := NewClient("http://localhost:9999", authToken) + + usersApi := client.UsersApi() + + me, err := usersApi.Me(context.Background()) + require.Nil(t, err) + require.NotNil(t, me) + + users, err := usersApi.FindUsers(context.Background()) + require.Nil(t, err) + require.NotNil(t, users) + assert.Len(t, *users, 1) + + user, err := usersApi.CreateUserWithName(context.Background(), "user-01") + require.Nil(t, err) + require.NotNil(t, user) + + users, err = usersApi.FindUsers(context.Background()) + require.Nil(t, err) + require.NotNil(t, users) + assert.Len(t, *users, 2) + + status := domain.UserStatusInactive + user.Status = &status + user, err = usersApi.UpdateUser(context.Background(), user) + require.Nil(t, err) + require.NotNil(t, user) + assert.Equal(t, status, *user.Status) + + err = usersApi.UpdateUserPassword(context.Background(), user, "my-password") + require.Nil(t, err) + + err = usersApi.DeleteUser(context.Background(), user) + require.Nil(t, err) + + users, err = usersApi.FindUsers(context.Background()) + require.Nil(t, err) + require.NotNil(t, users) + assert.Len(t, *users, 1) +} From 7a7cd9088d4216c14e317f7b2205b3e6e12b6330 Mon Sep 17 00:00:00 2001 From: vlastahajek Date: Fri, 24 Apr 2020 13:47:47 +0200 Subject: [PATCH 5/8] chore: removed commented code --- internal/http/service.go | 1 - 1 file changed, 1 deletion(-) diff --git a/internal/http/service.go b/internal/http/service.go index f3beec55..46ccd69f 100644 --- a/internal/http/service.go +++ b/internal/http/service.go @@ -41,7 +41,6 @@ type ResponseCallback func(resp *http.Response) error func NewService(serverUrl, authorization string, tlsConfig *tls.Config) Service { apiUrl, err := url.Parse(serverUrl) if err == nil { - //apiUrl.Path = path.Join(apiUrl.Path, "/api/v2/") apiUrl, err = apiUrl.Parse("/api/v2/") if err == nil { serverUrl = apiUrl.String() From 99f2bcc9c54419b4c6d5bda480db9e63bf19df00 Mon Sep 17 00:00:00 2001 From: vlastahajek Date: Fri, 24 Apr 2020 13:52:21 +0200 Subject: [PATCH 6/8] feat: Organizations and Users API improvements --- api/organizations.go | 116 ++++++++++++++++++++++++++++++++++++------- api/users.go | 47 +++++++++++++----- client.go | 24 +++++++-- client_e2e_test.go | 72 ++++++++++++++++++++++++--- 4 files changed, 216 insertions(+), 43 deletions(-) diff --git a/api/organizations.go b/api/organizations.go index 2662698f..11de27e1 100644 --- a/api/organizations.go +++ b/api/organizations.go @@ -8,12 +8,14 @@ import ( // OrganizationsApi provides methods for managing Organizations in a InfluxDB server type OrganizationsApi interface { - // FindOrganizationByName returns all organizations - FindOrganizations(ctx context.Context) (*[]domain.Organization, error) + // GetOrganizations returns all organizations + GetOrganizations(ctx context.Context) (*[]domain.Organization, error) // FindOrganizationByName returns an organization found using orgNme FindOrganizationByName(ctx context.Context, orgName string) (*domain.Organization, error) - // FindOrganizationByName returns an organization found using orgId + // FindOrganizationById returns an organization found using orgId FindOrganizationById(ctx context.Context, orgId string) (*domain.Organization, error) + // FindOrganizationsByUserId returns organizations an user with userID belongs to + FindOrganizationsByUserId(ctx context.Context, orgId string) (*[]domain.Organization, error) // CreateOrganization creates new organization CreateOrganization(ctx context.Context, org *domain.Organization) (*domain.Organization, error) // CreateOrganizationWithName creates new organization with orgName and with status active @@ -22,20 +24,32 @@ type OrganizationsApi interface { UpdateOrganization(ctx context.Context, org *domain.Organization) (*domain.Organization, error) // DeleteOrganization deletes an organization DeleteOrganization(ctx context.Context, org *domain.Organization) error - // DeleteOrganizationWithID deletes an organization with orgId - DeleteOrganizationWithID(ctx context.Context, orgId string) error + // DeleteOrganizationWithId deletes an organization with orgId + DeleteOrganizationWithId(ctx context.Context, orgId string) error // GetMembers returns members of an organization GetMembers(ctx context.Context, org *domain.Organization) (*[]domain.ResourceMember, error) - // GetMembersWithID returns members of an organization with orgId - GetMembersWithID(ctx context.Context, orgId string) (*[]domain.ResourceMember, error) + // GetMembersWithId returns members of an organization with orgId + GetMembersWithId(ctx context.Context, orgId string) (*[]domain.ResourceMember, error) // AddMember add a user to an organization AddMember(ctx context.Context, org *domain.Organization, user *domain.User) (*domain.ResourceMember, error) // AddMember add a member with id memberId to an organization with orgId - AddMemberWithIDs(ctx context.Context, orgId, memberId string) (*domain.ResourceMember, error) - // RemoveMember add a user from an organization + AddMemberWithId(ctx context.Context, orgId, memberId string) (*domain.ResourceMember, error) + // RemoveMember removes a user from an organization RemoveMember(ctx context.Context, org *domain.Organization, user *domain.User) error // RemoveMember removes a member with id memberId from an organization with orgId - RemoveMemberWithIDs(ctx context.Context, orgId, memberId string) error + RemoveMemberWithId(ctx context.Context, orgId, memberId string) error + // GetMembers returns members of an organization + GetOwners(ctx context.Context, org *domain.Organization) (*[]domain.ResourceOwner, error) + // GetMembersWithId returns members of an organization with orgId + GetOwnersWithId(ctx context.Context, orgId string) (*[]domain.ResourceOwner, error) + // AddOwner add a user to an organization + AddOwner(ctx context.Context, org *domain.Organization, user *domain.User) (*domain.ResourceOwner, error) + // AddOwner add an owner with id memberId to an organization with orgId + AddOwnerWithId(ctx context.Context, orgId, memberId string) (*domain.ResourceOwner, error) + // RemoveOwner a user from an organization + RemoveOwner(ctx context.Context, org *domain.Organization, user *domain.User) error + // RemoveOwner removes a member with id memberId from an organization with orgId + RemoveOwnerWithId(ctx context.Context, orgId, memberId string) error } type organizationsApiImpl struct { @@ -50,7 +64,7 @@ func NewOrganizationsApi(service ihttp.Service) OrganizationsApi { } } -func (o *organizationsApiImpl) FindOrganizations(ctx context.Context) (*[]domain.Organization, error) { +func (o *organizationsApiImpl) GetOrganizations(ctx context.Context) (*[]domain.Organization, error) { params := &domain.GetOrgsParams{} response, err := o.apiClient.GetOrgsWithResponse(ctx, params) if err != nil { @@ -86,6 +100,18 @@ func (o *organizationsApiImpl) FindOrganizationById(ctx context.Context, orgId s return &(*response.JSON200.Orgs)[0], nil } +func (o *organizationsApiImpl) FindOrganizationsByUserId(ctx context.Context, userID string) (*[]domain.Organization, error) { + params := &domain.GetOrgsParams{UserID: &userID} + response, err := o.apiClient.GetOrgsWithResponse(ctx, params) + if err != nil { + return nil, err + } + if response.JSONDefault != nil { + return nil, domain.DomainErrorToError(response.JSONDefault, response.StatusCode()) + } + return response.JSON200.Orgs, nil +} + func (o *organizationsApiImpl) CreateOrganization(ctx context.Context, org *domain.Organization) (*domain.Organization, error) { params := &domain.PostOrgsParams{} response, err := o.apiClient.PostOrgsWithResponse(ctx, params, domain.PostOrgsJSONRequestBody(*org)) @@ -113,10 +139,10 @@ func (o *organizationsApiImpl) CreateOrganizationWithName(ctx context.Context, o } func (o *organizationsApiImpl) DeleteOrganization(ctx context.Context, org *domain.Organization) error { - return o.DeleteOrganizationWithID(ctx, *org.Id) + return o.DeleteOrganizationWithId(ctx, *org.Id) } -func (o *organizationsApiImpl) DeleteOrganizationWithID(ctx context.Context, orgId string) error { +func (o *organizationsApiImpl) DeleteOrganizationWithId(ctx context.Context, orgId string) error { params := &domain.DeleteOrgsIDParams{} response, err := o.apiClient.DeleteOrgsIDWithResponse(ctx, orgId, params) if err != nil { @@ -144,10 +170,10 @@ func (o *organizationsApiImpl) UpdateOrganization(ctx context.Context, org *doma } func (o *organizationsApiImpl) GetMembers(ctx context.Context, org *domain.Organization) (*[]domain.ResourceMember, error) { - return o.GetMembersWithID(ctx, *org.Id) + return o.GetMembersWithId(ctx, *org.Id) } -func (o *organizationsApiImpl) GetMembersWithID(ctx context.Context, orgId string) (*[]domain.ResourceMember, error) { +func (o *organizationsApiImpl) GetMembersWithId(ctx context.Context, orgId string) (*[]domain.ResourceMember, error) { params := &domain.GetOrgsIDMembersParams{} response, err := o.apiClient.GetOrgsIDMembersWithResponse(ctx, orgId, params) if err != nil { @@ -163,10 +189,10 @@ func (o *organizationsApiImpl) GetMembersWithID(ctx context.Context, orgId strin } func (o *organizationsApiImpl) AddMember(ctx context.Context, org *domain.Organization, user *domain.User) (*domain.ResourceMember, error) { - return o.AddMemberWithIDs(ctx, *org.Id, *user.Id) + return o.AddMemberWithId(ctx, *org.Id, *user.Id) } -func (o *organizationsApiImpl) AddMemberWithIDs(ctx context.Context, orgId, memberId string) (*domain.ResourceMember, error) { +func (o *organizationsApiImpl) AddMemberWithId(ctx context.Context, orgId, memberId string) (*domain.ResourceMember, error) { params := &domain.PostOrgsIDMembersParams{} body := &domain.PostOrgsIDMembersJSONRequestBody{Id: memberId} response, err := o.apiClient.PostOrgsIDMembersWithResponse(ctx, orgId, params, *body) @@ -180,10 +206,10 @@ func (o *organizationsApiImpl) AddMemberWithIDs(ctx context.Context, orgId, memb } func (o *organizationsApiImpl) RemoveMember(ctx context.Context, org *domain.Organization, user *domain.User) error { - return o.RemoveMemberWithIDs(ctx, *org.Id, *user.Id) + return o.RemoveMemberWithId(ctx, *org.Id, *user.Id) } -func (o *organizationsApiImpl) RemoveMemberWithIDs(ctx context.Context, orgId, memberId string) error { +func (o *organizationsApiImpl) RemoveMemberWithId(ctx context.Context, orgId, memberId string) error { params := &domain.DeleteOrgsIDMembersIDParams{} response, err := o.apiClient.DeleteOrgsIDMembersIDWithResponse(ctx, orgId, memberId, params) if err != nil { @@ -194,3 +220,55 @@ func (o *organizationsApiImpl) RemoveMemberWithIDs(ctx context.Context, orgId, m } return nil } + +func (o *organizationsApiImpl) GetOwners(ctx context.Context, org *domain.Organization) (*[]domain.ResourceOwner, error) { + return o.GetOwnersWithId(ctx, *org.Id) +} + +func (o *organizationsApiImpl) GetOwnersWithId(ctx context.Context, orgId string) (*[]domain.ResourceOwner, error) { + params := &domain.GetOrgsIDOwnersParams{} + response, err := o.apiClient.GetOrgsIDOwnersWithResponse(ctx, orgId, params) + if err != nil { + return nil, err + } + if response.JSONDefault != nil { + return nil, domain.DomainErrorToError(response.JSONDefault, response.StatusCode()) + } + if response.JSON404 != nil { + return nil, domain.DomainErrorToError(response.JSON404, response.StatusCode()) + } + return response.JSON200.Users, nil +} + +func (o *organizationsApiImpl) AddOwner(ctx context.Context, org *domain.Organization, user *domain.User) (*domain.ResourceOwner, error) { + return o.AddOwnerWithId(ctx, *org.Id, *user.Id) +} + +func (o *organizationsApiImpl) AddOwnerWithId(ctx context.Context, orgId, ownerId string) (*domain.ResourceOwner, error) { + params := &domain.PostOrgsIDOwnersParams{} + body := &domain.PostOrgsIDOwnersJSONRequestBody{Id: ownerId} + response, err := o.apiClient.PostOrgsIDOwnersWithResponse(ctx, orgId, params, *body) + if err != nil { + return nil, err + } + if response.JSONDefault != nil { + return nil, domain.DomainErrorToError(response.JSONDefault, response.StatusCode()) + } + return response.JSON201, nil +} + +func (o *organizationsApiImpl) RemoveOwner(ctx context.Context, org *domain.Organization, user *domain.User) error { + return o.RemoveOwnerWithId(ctx, *org.Id, *user.Id) +} + +func (o *organizationsApiImpl) RemoveOwnerWithId(ctx context.Context, orgId, memberId string) error { + params := &domain.DeleteOrgsIDOwnersIDParams{} + response, err := o.apiClient.DeleteOrgsIDOwnersIDWithResponse(ctx, orgId, memberId, params) + if err != nil { + return err + } + if response.JSONDefault != nil { + return domain.DomainErrorToError(response.JSONDefault, response.StatusCode()) + } + return nil +} diff --git a/api/users.go b/api/users.go index 7c69826e..393bda43 100644 --- a/api/users.go +++ b/api/users.go @@ -2,16 +2,19 @@ package api import ( "context" + "fmt" "github.com/influxdata/influxdb-client-go/domain" ihttp "github.com/influxdata/influxdb-client-go/internal/http" ) // UsersApi provides methods for managing users in a InfluxDB server type UsersApi interface { - // FindUsers returns all users - FindUsers(ctx context.Context) (*[]domain.User, error) - // FindUserByID returns user with userID - FindUserByID(ctx context.Context, userID string) (*domain.User, error) + // GetUsers returns all users + GetUsers(ctx context.Context) (*[]domain.User, error) + // FindUserById returns user with userID + FindUserById(ctx context.Context, userID string) (*domain.User, error) + // FindUserByName returns user with name userName + FindUserByName(ctx context.Context, userName string) (*domain.User, error) // CreateUser creates new user CreateUser(ctx context.Context, user *domain.User) (*domain.User, error) // CreateUserWithName creates new user with userName @@ -20,10 +23,10 @@ type UsersApi interface { UpdateUser(ctx context.Context, user *domain.User) (*domain.User, error) // UpdateUserPassword sets password for an user UpdateUserPassword(ctx context.Context, user *domain.User, password string) error - // UpdateUserPasswordWithID sets password for an user with userId - UpdateUserPasswordWithID(ctx context.Context, userID string, password string) error + // UpdateUserPasswordWithId sets password for an user with userId + UpdateUserPasswordWithId(ctx context.Context, userID string, password string) error // DeleteUserWithId deletes an user with userId - DeleteUserWithID(ctx context.Context, userID string) error + DeleteUserWithId(ctx context.Context, userID string) error // DeleteUser deletes an user DeleteUser(ctx context.Context, user *domain.User) error // Me returns actual user @@ -44,7 +47,7 @@ func NewUsersApi(service ihttp.Service) UsersApi { } } -func (u *usersApiImpl) FindUsers(ctx context.Context) (*[]domain.User, error) { +func (u *usersApiImpl) GetUsers(ctx context.Context) (*[]domain.User, error) { params := &domain.GetUsersParams{} response, err := u.apiClient.GetUsersWithResponse(ctx, params) if err != nil { @@ -56,7 +59,7 @@ func (u *usersApiImpl) FindUsers(ctx context.Context) (*[]domain.User, error) { return response.JSON200.Users, nil } -func (u *usersApiImpl) FindUserByID(ctx context.Context, userID string) (*domain.User, error) { +func (u *usersApiImpl) FindUserById(ctx context.Context, userID string) (*domain.User, error) { params := &domain.GetUsersIDParams{} response, err := u.apiClient.GetUsersIDWithResponse(ctx, userID, params) if err != nil { @@ -68,6 +71,24 @@ func (u *usersApiImpl) FindUserByID(ctx context.Context, userID string) (*domain return response.JSON200, nil } +func (u *usersApiImpl) FindUserByName(ctx context.Context, userName string) (*domain.User, error) { + users, err := u.GetUsers(ctx) + if err != nil { + return nil, err + } + var user *domain.User + for _, u := range *users { + if u.Name == userName { + user = &u + break + } + } + if user == nil { + return nil, fmt.Errorf("user '%s' not found", userName) + } + return user, nil +} + func (u *usersApiImpl) CreateUserWithName(ctx context.Context, userName string) (*domain.User, error) { user := &domain.User{Name: userName} return u.CreateUser(ctx, user) @@ -98,10 +119,10 @@ func (u *usersApiImpl) UpdateUser(ctx context.Context, user *domain.User) (*doma } func (u *usersApiImpl) UpdateUserPassword(ctx context.Context, user *domain.User, password string) error { - return u.UpdateUserPasswordWithID(ctx, *user.Id, password) + return u.UpdateUserPasswordWithId(ctx, *user.Id, password) } -func (u *usersApiImpl) UpdateUserPasswordWithID(ctx context.Context, userID string, password string) error { +func (u *usersApiImpl) UpdateUserPasswordWithId(ctx context.Context, userID string, password string) error { params := &domain.PostUsersIDPasswordParams{} body := &domain.PasswordResetBody{Password: password} response, err := u.apiClient.PostUsersIDPasswordWithResponse(ctx, userID, params, domain.PostUsersIDPasswordJSONRequestBody(*body)) @@ -115,10 +136,10 @@ func (u *usersApiImpl) UpdateUserPasswordWithID(ctx context.Context, userID stri } func (u *usersApiImpl) DeleteUser(ctx context.Context, user *domain.User) error { - return u.DeleteUserWithID(ctx, *user.Id) + return u.DeleteUserWithId(ctx, *user.Id) } -func (u *usersApiImpl) DeleteUserWithID(ctx context.Context, userID string) error { +func (u *usersApiImpl) DeleteUserWithId(ctx context.Context, userID string) error { params := &domain.DeleteUsersIDParams{} response, err := u.apiClient.DeleteUsersIDWithResponse(ctx, userID, params) if err != nil { diff --git a/client.go b/client.go index cab8f75f..94b87ccf 100644 --- a/client.go +++ b/client.go @@ -58,6 +58,9 @@ type client struct { writeApis []WriteApi lock sync.Mutex httpService ihttp.Service + authApi api.AuthorizationsApi + orgApi api.OrganizationsApi + usersApi api.UsersApi } // NewClient creates InfluxDBClient for connecting to given serverUrl with provided authentication token, with default options @@ -130,13 +133,28 @@ func (c *client) QueryApi(org string) QueryApi { } func (c *client) AuthorizationsApi() api.AuthorizationsApi { - return api.NewAuthorizationApi(c.httpService) + c.lock.Lock() + defer c.lock.Unlock() + if c.authApi == nil { + c.authApi = api.NewAuthorizationApi(c.httpService) + } + return c.authApi } func (c *client) OrganizationsApi() api.OrganizationsApi { - return api.NewOrganizationsApi(c.httpService) + c.lock.Lock() + defer c.lock.Unlock() + if c.orgApi == nil { + c.orgApi = api.NewOrganizationsApi(c.httpService) + } + return c.orgApi } func (c *client) UsersApi() api.UsersApi { - return api.NewUsersApi(c.httpService) + c.lock.Lock() + defer c.lock.Unlock() + if c.usersApi == nil { + c.usersApi = api.NewUsersApi(c.httpService) + } + return c.usersApi } diff --git a/client_e2e_test.go b/client_e2e_test.go index cc9a7e23..d097341b 100644 --- a/client_e2e_test.go +++ b/client_e2e_test.go @@ -17,6 +17,7 @@ import ( ) var e2e bool +var authToken string func init() { flag.BoolVar(&e2e, "e2e", false, "run the end tests (requires a working influxdb instance on 127.0.0.1)") @@ -38,8 +39,6 @@ func TestReady(t *testing.T) { } } -var authToken string - func TestSetup(t *testing.T) { if !e2e { t.Skip("e2e not enabled. Launch InfluxDB 2 on localhost and run test with -e2e") @@ -216,7 +215,7 @@ func TestOrganizations(t *testing.T) { orgName := "my-org-2" orgDescription := "my-org 2 description" - orgList, err := orgsApi.FindOrganizations(context.Background()) + orgList, err := orgsApi.GetOrganizations(context.Background()) require.Nil(t, err) require.NotNil(t, orgList) assert.Len(t, *orgList, 1) @@ -237,7 +236,7 @@ func TestOrganizations(t *testing.T) { require.NotNil(t, org) assert.Equal(t, orgDescription, *org.Description) - orgList, err = orgsApi.FindOrganizations(context.Background()) + orgList, err = orgsApi.GetOrganizations(context.Background()) require.Nil(t, err) require.NotNil(t, orgList) @@ -263,6 +262,60 @@ func TestOrganizations(t *testing.T) { require.NotNil(t, members) require.Len(t, *members, 1) + org2, err := orgsApi.FindOrganizationById(context.Background(), *org.Id) + require.Nil(t, err) + require.NotNil(t, org2) + assert.Equal(t, org.Name, org2.Name) + + orgs, err := orgsApi.FindOrganizationsByUserId(context.Background(), *user.Id) + require.Nil(t, err) + require.NotNil(t, orgs) + require.Len(t, *orgs, 1) + assert.Equal(t, org.Name, (*orgs)[0].Name) + + orgName2 := "my-org-3" + + org2, err = orgsApi.CreateOrganizationWithName(context.Background(), orgName2) + require.Nil(t, err) + require.NotNil(t, org2) + assert.Equal(t, orgName2, org2.Name) + + orgList, err = orgsApi.GetOrganizations(context.Background()) + require.Nil(t, err) + require.NotNil(t, orgList) + assert.Len(t, *orgList, 3) + + owners, err := orgsApi.GetOwners(context.Background(), org2) + require.Nil(t, err) + require.NotNil(t, owners) + assert.Len(t, *owners, 1) + + owner, err := orgsApi.AddOwner(context.Background(), org2, user) + require.Nil(t, err) + require.NotNil(t, owner) + + owners, err = orgsApi.GetOwners(context.Background(), org2) + require.Nil(t, err) + require.NotNil(t, owners) + assert.Len(t, *owners, 2) + + u, err := usersApi.FindUserByName(context.Background(), "my-user") + require.Nil(t, err) + require.NotNil(t, u) + + err = orgsApi.RemoveOwner(context.Background(), org2, u) + require.Nil(t, err) + + owners, err = orgsApi.GetOwners(context.Background(), org2) + require.Nil(t, err) + require.NotNil(t, owners) + assert.Len(t, *owners, 1) + + orgs, err = orgsApi.FindOrganizationsByUserId(context.Background(), *user.Id) + require.Nil(t, err) + require.NotNil(t, orgs) + require.Len(t, *orgs, 2) + err = orgsApi.RemoveMember(context.Background(), org, user) require.Nil(t, err) @@ -274,7 +327,10 @@ func TestOrganizations(t *testing.T) { err = orgsApi.DeleteOrganization(context.Background(), org) require.Nil(t, err) - orgList, err = orgsApi.FindOrganizations(context.Background()) + err = orgsApi.DeleteOrganization(context.Background(), org2) + require.Nil(t, err) + + orgList, err = orgsApi.GetOrganizations(context.Background()) require.Nil(t, err) require.NotNil(t, orgList) assert.Len(t, *orgList, 1) @@ -295,7 +351,7 @@ func TestUsers(t *testing.T) { require.Nil(t, err) require.NotNil(t, me) - users, err := usersApi.FindUsers(context.Background()) + users, err := usersApi.GetUsers(context.Background()) require.Nil(t, err) require.NotNil(t, users) assert.Len(t, *users, 1) @@ -304,7 +360,7 @@ func TestUsers(t *testing.T) { require.Nil(t, err) require.NotNil(t, user) - users, err = usersApi.FindUsers(context.Background()) + users, err = usersApi.GetUsers(context.Background()) require.Nil(t, err) require.NotNil(t, users) assert.Len(t, *users, 2) @@ -322,7 +378,7 @@ func TestUsers(t *testing.T) { err = usersApi.DeleteUser(context.Background(), user) require.Nil(t, err) - users, err = usersApi.FindUsers(context.Background()) + users, err = usersApi.GetUsers(context.Background()) require.Nil(t, err) require.NotNil(t, users) assert.Len(t, *users, 1) From 7b121081d25ade2cec03ec6f772fb1c03770b22e Mon Sep 17 00:00:00 2001 From: vlastahajek Date: Fri, 24 Apr 2020 13:52:48 +0200 Subject: [PATCH 7/8] test: Fixed composing API url --- writeApiBlocking_test.go | 24 +++++------------- write_test.go | 54 +++++++++++++++++----------------------- 2 files changed, 29 insertions(+), 49 deletions(-) diff --git a/writeApiBlocking_test.go b/writeApiBlocking_test.go index 411fa00c..0dbd80f3 100644 --- a/writeApiBlocking_test.go +++ b/writeApiBlocking_test.go @@ -15,12 +15,8 @@ import ( ) func TestWritePoint(t *testing.T) { - client := &client{serverUrl: "http://locahost:4444", options: DefaultOptions()} - service := &testHttpService{ - t: t, - options: client.Options(), - serverUrl: client.ServerUrl(), - } + client := newTestClient() + service := newTestService(t, client) client.options.SetBatchSize(5) writeApi := newWriteApiBlockingImpl("my-org", "my-bucket", service, client) points := genPoints(10) @@ -36,12 +32,8 @@ func TestWritePoint(t *testing.T) { } func TestWriteRecord(t *testing.T) { - client := &client{serverUrl: "http://locahost:4444", options: DefaultOptions()} - service := &testHttpService{ - t: t, - options: client.Options(), - serverUrl: client.ServerUrl(), - } + client := newTestClient() + service := newTestService(t, client) client.options.SetBatchSize(5) writeApi := newWriteApiBlockingImpl("my-org", "my-bucket", service, client) lines := genRecords(10) @@ -64,12 +56,8 @@ func TestWriteRecord(t *testing.T) { } func TestWriteContextCancel(t *testing.T) { - client := &client{serverUrl: "http://locahost:4444", options: DefaultOptions()} - service := &testHttpService{ - t: t, - options: client.Options(), - serverUrl: client.ServerUrl(), - } + client := newTestClient() + service := newTestService(t, client) client.options.SetBatchSize(5) writeApi := newWriteApiBlockingImpl("my-org", "my-bucket", service, client) lines := genRecords(10) diff --git a/write_test.go b/write_test.go index 1a802ab0..46b4c5bb 100644 --- a/write_test.go +++ b/write_test.go @@ -84,7 +84,7 @@ func (t *testHttpService) PostRequest(_ context.Context, url string, body io.Rea body, _ = gzip.NewReader(body) t.wasGzip = true } - assert.Equal(t.t, url, fmt.Sprintf("%s/api/v2/write?bucket=my-bucket&org=my-org&precision=ns", t.serverUrl)) + assert.Equal(t.t, fmt.Sprintf("%swrite?bucket=my-bucket&org=my-org&precision=ns", t.serverUrl), url) if t.ReplyError() != nil { return t.ReplyError() @@ -121,6 +121,18 @@ func (t *testHttpService) Lines() []string { return t.lines } +func newTestClient() *client { + return &client{serverUrl: "http://locahost:4444", options: DefaultOptions()} +} + +func newTestService(t *testing.T, client InfluxDBClient) *testHttpService { + return &testHttpService{ + t: t, + options: client.Options(), + serverUrl: client.ServerUrl() + "/api/v2/", + } +} + func genPoints(num int) []*Point { points := make([]*Point, num) rand.Seed(321) @@ -165,12 +177,8 @@ func genRecords(num int) []string { } func TestWriteApiImpl_Write(t *testing.T) { - client := &client{serverUrl: "http://locahost:4444", options: DefaultOptions()} - service := &testHttpService{ - t: t, - options: client.Options(), - serverUrl: client.ServerUrl(), - } + client := newTestClient() + service := newTestService(t, client) client.options.SetBatchSize(5) writeApi := newWriteApiImpl("my-org", "my-bucket", service, client) points := genPoints(10) @@ -188,12 +196,8 @@ func TestWriteApiImpl_Write(t *testing.T) { } func TestGzipWithFlushing(t *testing.T) { - client := &client{serverUrl: "http://locahost:4444", options: DefaultOptions()} - service := &testHttpService{ - t: t, - options: client.Options(), - serverUrl: client.ServerUrl(), - } + client := newTestClient() + service := newTestService(t, client) client.options.SetBatchSize(5).SetUseGZip(true) writeApi := newWriteApiImpl("my-org", "my-bucket", service, client) points := genPoints(5) @@ -216,12 +220,8 @@ func TestGzipWithFlushing(t *testing.T) { writeApi.Close() } func TestFlushInterval(t *testing.T) { - client := &client{serverUrl: "http://locahost:4444", options: DefaultOptions()} - service := &testHttpService{ - t: t, - options: client.Options(), - serverUrl: client.ServerUrl(), - } + client := newTestClient() + service := newTestService(t, client) client.options.SetBatchSize(10).SetFlushInterval(500) writeApi := newWriteApiImpl("my-org", "my-bucket", service, client) points := genPoints(5) @@ -247,12 +247,8 @@ func TestFlushInterval(t *testing.T) { } func TestRetry(t *testing.T) { - client := &client{serverUrl: "http://locahost:4444", options: DefaultOptions()} - service := &testHttpService{ - t: t, - options: client.Options(), - serverUrl: client.ServerUrl(), - } + client := newTestClient() + service := newTestService(t, client) client.options.SetLogLevel(3). SetBatchSize(5). SetRetryInterval(10000) @@ -291,12 +287,8 @@ func TestRetry(t *testing.T) { } func TestWriteError(t *testing.T) { - client := &client{serverUrl: "http://locahost:4444", options: DefaultOptions()} - service := &testHttpService{ - t: t, - options: client.Options(), - serverUrl: client.ServerUrl(), - } + client := newTestClient() + service := newTestService(t, client) client.options.SetLogLevel(3).SetBatchSize(5) service.replyError = &ihttp.Error{ StatusCode: 400, From e50b5d1a64eb331e60d081242fedf0758a0d3bb1 Mon Sep 17 00:00:00 2001 From: vlastahajek Date: Fri, 24 Apr 2020 14:28:56 +0200 Subject: [PATCH 8/8] doc: Updated CHANGELOG.md --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b3ba82a2..ef57a7de 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.1.0 +### Features +1. [#99](https://github.com/influxdata/influxdb-client-go/pull/99) Organizations API and Users API + ## 1.0.0 [2020-04-01] ### Core