mirror of
https://github.com/absmach/magistrala.git
synced 2026-06-23 04:10:28 +00:00
f8410b8940
Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
2495 lines
67 KiB
Go
2495 lines
67 KiB
Go
// Copyright (c) Abstract Machines
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
package sdk_test
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
grpcTokenV1 "github.com/absmach/supermq/api/grpc/token/v1"
|
|
api "github.com/absmach/supermq/api/http"
|
|
apiutil "github.com/absmach/supermq/api/http/util"
|
|
authmocks "github.com/absmach/supermq/auth/mocks"
|
|
smqlog "github.com/absmach/supermq/logger"
|
|
smqauthn "github.com/absmach/supermq/pkg/authn"
|
|
authnmocks "github.com/absmach/supermq/pkg/authn/mocks"
|
|
"github.com/absmach/supermq/pkg/errors"
|
|
svcerr "github.com/absmach/supermq/pkg/errors/service"
|
|
oauth2mocks "github.com/absmach/supermq/pkg/oauth2/mocks"
|
|
sdk "github.com/absmach/supermq/pkg/sdk"
|
|
"github.com/absmach/supermq/pkg/uuid"
|
|
"github.com/absmach/supermq/users"
|
|
httpapi "github.com/absmach/supermq/users/api"
|
|
umocks "github.com/absmach/supermq/users/mocks"
|
|
"github.com/go-chi/chi/v5"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/mock"
|
|
)
|
|
|
|
var (
|
|
id = generateUUID(&testing.T{})
|
|
domainID = "c717fa97-ffd9-40cb-8cf9-7c2859059395"
|
|
)
|
|
|
|
func setupUsers() (*httptest.Server, *umocks.Service, *authnmocks.Authentication) {
|
|
usvc := new(umocks.Service)
|
|
logger := smqlog.NewMock()
|
|
mux := chi.NewRouter()
|
|
idp := uuid.NewMock()
|
|
provider := new(oauth2mocks.Provider)
|
|
provider.On("Name").Return("test")
|
|
authn := new(authnmocks.Authentication)
|
|
am := smqauthn.NewAuthNMiddleware(authn, smqauthn.WithDomainCheck(false), smqauthn.WithAllowUnverifiedUser(true))
|
|
token := new(authmocks.TokenServiceClient)
|
|
httpapi.MakeHandler(usvc, am, token, true, mux, logger, "", passRegex, idp, provider)
|
|
|
|
return httptest.NewServer(mux), usvc, authn
|
|
}
|
|
|
|
func TestCreateUser(t *testing.T) {
|
|
ts, svc, _ := setupUsers()
|
|
defer ts.Close()
|
|
|
|
createSdkUserReq := sdk.User{
|
|
FirstName: user.FirstName,
|
|
LastName: user.LastName,
|
|
Email: user.Email,
|
|
Tags: user.Tags,
|
|
Credentials: user.Credentials,
|
|
Metadata: user.Metadata,
|
|
PrivateMetadata: user.PrivateMetadata,
|
|
Status: user.Status,
|
|
}
|
|
|
|
conf := sdk.Config{
|
|
UsersURL: ts.URL,
|
|
}
|
|
mgsdk := sdk.NewSDK(conf)
|
|
|
|
cases := []struct {
|
|
desc string
|
|
token string
|
|
createSdkUserReq sdk.User
|
|
svcReq users.User
|
|
svcRes users.User
|
|
svcErr error
|
|
response sdk.User
|
|
err errors.SDKError
|
|
}{
|
|
{
|
|
desc: "register new user successfully",
|
|
token: validToken,
|
|
createSdkUserReq: createSdkUserReq,
|
|
svcReq: convertUser(createSdkUserReq),
|
|
svcRes: convertUser(user),
|
|
svcErr: nil,
|
|
response: user,
|
|
err: nil,
|
|
},
|
|
{
|
|
desc: "register existing user",
|
|
token: validToken,
|
|
createSdkUserReq: createSdkUserReq,
|
|
svcReq: convertUser(createSdkUserReq),
|
|
svcRes: users.User{},
|
|
svcErr: svcerr.ErrCreateEntity,
|
|
response: sdk.User{},
|
|
err: errors.NewSDKErrorWithStatus(svcerr.ErrCreateEntity, http.StatusUnprocessableEntity),
|
|
},
|
|
{
|
|
desc: "register user with invalid token",
|
|
token: invalidToken,
|
|
createSdkUserReq: createSdkUserReq,
|
|
svcReq: convertUser(createSdkUserReq),
|
|
svcRes: users.User{},
|
|
svcErr: svcerr.ErrAuthentication,
|
|
response: sdk.User{},
|
|
err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthentication, http.StatusUnauthorized),
|
|
},
|
|
{
|
|
desc: "register user with empty token",
|
|
token: "",
|
|
createSdkUserReq: createSdkUserReq,
|
|
svcReq: convertUser(createSdkUserReq),
|
|
svcRes: users.User{},
|
|
svcErr: svcerr.ErrAuthentication,
|
|
response: sdk.User{},
|
|
err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthentication, http.StatusUnauthorized),
|
|
},
|
|
{
|
|
desc: "register empty credentials user",
|
|
token: validToken,
|
|
createSdkUserReq: sdk.User{
|
|
FirstName: createSdkUserReq.FirstName,
|
|
LastName: createSdkUserReq.LastName,
|
|
Email: createSdkUserReq.Email,
|
|
Credentials: sdk.Credentials{
|
|
Username: "",
|
|
Secret: "",
|
|
},
|
|
},
|
|
svcReq: users.User{},
|
|
svcRes: users.User{},
|
|
svcErr: nil,
|
|
response: sdk.User{},
|
|
err: errors.NewSDKErrorWithStatus(apiutil.ErrMissingUsername, http.StatusBadRequest),
|
|
},
|
|
{
|
|
desc: "register user with first name too long",
|
|
token: validToken,
|
|
createSdkUserReq: sdk.User{
|
|
FirstName: strings.Repeat("a", 1025),
|
|
Credentials: createSdkUserReq.Credentials,
|
|
PrivateMetadata: createSdkUserReq.PrivateMetadata,
|
|
Metadata: createSdkUserReq.Metadata,
|
|
Tags: createSdkUserReq.Tags,
|
|
},
|
|
svcReq: users.User{},
|
|
svcRes: users.User{},
|
|
svcErr: nil,
|
|
response: sdk.User{},
|
|
err: errors.NewSDKErrorWithStatus(apiutil.ErrNameSize, http.StatusBadRequest),
|
|
},
|
|
{
|
|
desc: "register user with empty userName",
|
|
token: validToken,
|
|
createSdkUserReq: sdk.User{
|
|
FirstName: createSdkUserReq.FirstName,
|
|
LastName: createSdkUserReq.LastName,
|
|
Email: createSdkUserReq.Email,
|
|
Credentials: sdk.Credentials{
|
|
Username: "",
|
|
Secret: createSdkUserReq.Credentials.Secret,
|
|
},
|
|
PrivateMetadata: createSdkUserReq.PrivateMetadata,
|
|
Metadata: createSdkUserReq.Metadata,
|
|
Tags: createSdkUserReq.Tags,
|
|
},
|
|
svcReq: users.User{},
|
|
svcRes: users.User{},
|
|
svcErr: nil,
|
|
response: sdk.User{},
|
|
err: errors.NewSDKErrorWithStatus(apiutil.ErrMissingUsername, http.StatusBadRequest),
|
|
},
|
|
{
|
|
desc: "register user with empty secret",
|
|
token: validToken,
|
|
createSdkUserReq: sdk.User{
|
|
FirstName: createSdkUserReq.FirstName,
|
|
LastName: createSdkUserReq.LastName,
|
|
Email: createSdkUserReq.Email,
|
|
Credentials: sdk.Credentials{
|
|
Username: createSdkUserReq.Credentials.Username,
|
|
Secret: "",
|
|
},
|
|
PrivateMetadata: createSdkUserReq.PrivateMetadata,
|
|
Metadata: createSdkUserReq.Metadata,
|
|
Tags: createSdkUserReq.Tags,
|
|
},
|
|
svcReq: users.User{},
|
|
svcRes: users.User{},
|
|
svcErr: nil,
|
|
response: sdk.User{},
|
|
err: errors.NewSDKErrorWithStatus(apiutil.ErrMissingPass, http.StatusBadRequest),
|
|
},
|
|
{
|
|
desc: "register user with secret that is too short",
|
|
token: validToken,
|
|
createSdkUserReq: sdk.User{
|
|
FirstName: createSdkUserReq.FirstName,
|
|
LastName: createSdkUserReq.LastName,
|
|
Email: createSdkUserReq.Email,
|
|
Credentials: sdk.Credentials{
|
|
Username: createSdkUserReq.Credentials.Username,
|
|
Secret: "weak",
|
|
},
|
|
PrivateMetadata: createSdkUserReq.PrivateMetadata,
|
|
Metadata: createSdkUserReq.Metadata,
|
|
Tags: createSdkUserReq.Tags,
|
|
},
|
|
svcReq: users.User{},
|
|
svcRes: users.User{},
|
|
svcErr: nil,
|
|
response: sdk.User{},
|
|
err: errors.NewSDKErrorWithStatus(apiutil.ErrPasswordFormat, http.StatusBadRequest),
|
|
},
|
|
{
|
|
desc: "register a user with request that can't be marshalled",
|
|
token: validToken,
|
|
createSdkUserReq: sdk.User{
|
|
Credentials: sdk.Credentials{
|
|
Username: "user",
|
|
Secret: "12345678",
|
|
},
|
|
FirstName: createSdkUserReq.FirstName,
|
|
LastName: createSdkUserReq.LastName,
|
|
Email: createSdkUserReq.Email,
|
|
Metadata: map[string]any{
|
|
"test": make(chan int),
|
|
},
|
|
},
|
|
svcReq: users.User{},
|
|
svcRes: users.User{},
|
|
svcErr: nil,
|
|
response: sdk.User{},
|
|
err: errors.NewSDKError(fmt.Errorf("json: unsupported type: chan int")),
|
|
},
|
|
{
|
|
desc: "register a user with response that can't be unmarshalled",
|
|
token: validToken,
|
|
createSdkUserReq: createSdkUserReq,
|
|
svcReq: convertUser(createSdkUserReq),
|
|
svcRes: users.User{
|
|
ID: id,
|
|
FirstName: createSdkUserReq.FirstName,
|
|
LastName: createSdkUserReq.LastName,
|
|
Email: createSdkUserReq.Email,
|
|
Credentials: users.Credentials{
|
|
Username: createSdkUserReq.Credentials.Username,
|
|
Secret: createSdkUserReq.Credentials.Secret,
|
|
},
|
|
Metadata: users.Metadata{
|
|
"key": make(chan int),
|
|
},
|
|
},
|
|
svcErr: nil,
|
|
response: sdk.User{},
|
|
err: errors.NewSDKError(fmt.Errorf("unexpected end of JSON input")),
|
|
},
|
|
}
|
|
for _, tc := range cases {
|
|
t.Run(tc.desc, func(t *testing.T) {
|
|
svcCall := svc.On("Register", mock.Anything, smqauthn.Session{}, tc.svcReq, true).Return(tc.svcRes, tc.svcErr)
|
|
resp, err := mgsdk.CreateUser(context.Background(), tc.createSdkUserReq, tc.token)
|
|
assert.Equal(t, tc.err, err)
|
|
assert.Equal(t, tc.response, resp)
|
|
if tc.err == nil {
|
|
ok := svcCall.Parent.AssertCalled(t, "Register", mock.Anything, smqauthn.Session{}, tc.svcReq, true)
|
|
assert.True(t, ok)
|
|
}
|
|
svcCall.Unset()
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestListUsers(t *testing.T) {
|
|
ts, svc, auth := setupUsers()
|
|
defer ts.Close()
|
|
|
|
var cls []sdk.User
|
|
conf := sdk.Config{
|
|
UsersURL: ts.URL,
|
|
}
|
|
mgsdk := sdk.NewSDK(conf)
|
|
|
|
for i := 10; i < 100; i++ {
|
|
cl := sdk.User{
|
|
ID: generateUUID(t),
|
|
FirstName: fmt.Sprintf("user_%d", i),
|
|
Credentials: sdk.Credentials{
|
|
Username: fmt.Sprintf("Username_%d", i),
|
|
Secret: fmt.Sprintf("password_%d", i),
|
|
},
|
|
Metadata: sdk.Metadata{"name": fmt.Sprintf("user_%d", i)},
|
|
Status: users.EnabledStatus.String(),
|
|
Role: users.UserRole.String(),
|
|
}
|
|
if i == 50 {
|
|
cl.Status = users.DisabledStatus.String()
|
|
cl.Tags = []string{"tag1", "tag2"}
|
|
}
|
|
cls = append(cls, cl)
|
|
}
|
|
|
|
cases := []struct {
|
|
desc string
|
|
token string
|
|
session smqauthn.Session
|
|
pageMeta sdk.PageMetadata
|
|
svcReq users.Page
|
|
svcRes users.UsersPage
|
|
svcErr error
|
|
authenticateErr error
|
|
response sdk.UsersPage
|
|
err errors.SDKError
|
|
}{
|
|
{
|
|
desc: "list users successfully",
|
|
token: validToken,
|
|
pageMeta: sdk.PageMetadata{
|
|
Offset: offset,
|
|
Limit: limit,
|
|
},
|
|
svcReq: users.Page{
|
|
Offset: offset,
|
|
Limit: limit,
|
|
Order: api.DefOrder,
|
|
Dir: api.DefDir,
|
|
},
|
|
svcRes: users.UsersPage{
|
|
Page: users.Page{
|
|
Total: uint64(len(cls[offset:limit])),
|
|
},
|
|
Users: convertUsers(cls[offset:limit]),
|
|
},
|
|
response: sdk.UsersPage{
|
|
PageRes: sdk.PageRes{
|
|
Total: uint64(len(cls[offset:limit])),
|
|
},
|
|
Users: cls[offset:limit],
|
|
},
|
|
err: nil,
|
|
},
|
|
{
|
|
desc: "list users with invalid token",
|
|
token: invalidToken,
|
|
session: smqauthn.Session{},
|
|
pageMeta: sdk.PageMetadata{
|
|
Offset: offset,
|
|
Limit: limit,
|
|
},
|
|
svcReq: users.Page{
|
|
Offset: offset,
|
|
Limit: limit,
|
|
Order: api.DefOrder,
|
|
Dir: api.DefDir,
|
|
},
|
|
svcRes: users.UsersPage{},
|
|
svcErr: svcerr.ErrAuthentication,
|
|
authenticateErr: svcerr.ErrAuthentication,
|
|
response: sdk.UsersPage{},
|
|
err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthentication, http.StatusUnauthorized),
|
|
},
|
|
{
|
|
desc: "list users with empty token",
|
|
token: "",
|
|
pageMeta: sdk.PageMetadata{
|
|
Offset: offset,
|
|
Limit: limit,
|
|
},
|
|
svcReq: users.Page{},
|
|
svcRes: users.UsersPage{},
|
|
svcErr: nil,
|
|
authenticateErr: apiutil.ErrBearerToken,
|
|
response: sdk.UsersPage{},
|
|
err: errors.NewSDKErrorWithStatus(apiutil.ErrBearerToken, http.StatusUnauthorized),
|
|
},
|
|
{
|
|
desc: "list users with zero limit",
|
|
token: validToken,
|
|
pageMeta: sdk.PageMetadata{
|
|
Offset: offset,
|
|
Limit: 0,
|
|
},
|
|
svcReq: users.Page{
|
|
Offset: offset,
|
|
Limit: 10,
|
|
Order: api.DefOrder,
|
|
Dir: api.DefDir,
|
|
},
|
|
svcRes: users.UsersPage{
|
|
Page: users.Page{
|
|
Total: uint64(len(cls[offset:10])),
|
|
},
|
|
Users: convertUsers(cls[offset:10]),
|
|
},
|
|
response: sdk.UsersPage{
|
|
PageRes: sdk.PageRes{
|
|
Total: uint64(len(cls[offset:10])),
|
|
},
|
|
Users: cls[offset:10],
|
|
},
|
|
err: nil,
|
|
},
|
|
{
|
|
desc: "list users with limit greater than max",
|
|
token: validToken,
|
|
pageMeta: sdk.PageMetadata{
|
|
Offset: offset,
|
|
Limit: 101,
|
|
},
|
|
svcReq: users.Page{},
|
|
svcRes: users.UsersPage{},
|
|
svcErr: nil,
|
|
response: sdk.UsersPage{},
|
|
err: errors.NewSDKErrorWithStatus(apiutil.ErrLimitSize, http.StatusBadRequest),
|
|
},
|
|
{
|
|
desc: "list users with given metadata",
|
|
token: validToken,
|
|
pageMeta: sdk.PageMetadata{
|
|
Offset: offset,
|
|
Limit: limit,
|
|
Metadata: sdk.Metadata{"name": "user_99"},
|
|
},
|
|
svcReq: users.Page{
|
|
Offset: offset,
|
|
Limit: limit,
|
|
Metadata: users.Metadata{"name": "user_99"},
|
|
Order: api.DefOrder,
|
|
Dir: api.DefDir,
|
|
},
|
|
svcRes: users.UsersPage{
|
|
Page: users.Page{
|
|
Total: 1,
|
|
},
|
|
Users: []users.User{convertUser(cls[89])},
|
|
},
|
|
svcErr: nil,
|
|
response: sdk.UsersPage{
|
|
PageRes: sdk.PageRes{
|
|
Total: 1,
|
|
},
|
|
Users: []sdk.User{cls[89]},
|
|
},
|
|
err: nil,
|
|
},
|
|
{
|
|
desc: "list users with given status",
|
|
token: validToken,
|
|
pageMeta: sdk.PageMetadata{
|
|
Offset: offset,
|
|
Limit: limit,
|
|
Status: users.DisabledStatus.String(),
|
|
},
|
|
svcReq: users.Page{
|
|
Offset: offset,
|
|
Limit: limit,
|
|
Status: users.DisabledStatus,
|
|
Order: api.DefOrder,
|
|
Dir: api.DefDir,
|
|
},
|
|
svcRes: users.UsersPage{
|
|
Page: users.Page{
|
|
Total: 1,
|
|
},
|
|
Users: []users.User{convertUser(cls[50])},
|
|
},
|
|
svcErr: nil,
|
|
response: sdk.UsersPage{
|
|
PageRes: sdk.PageRes{
|
|
Total: 1,
|
|
},
|
|
Users: []sdk.User{cls[50]},
|
|
},
|
|
err: nil,
|
|
},
|
|
{
|
|
desc: "list users with given tag",
|
|
token: validToken,
|
|
pageMeta: sdk.PageMetadata{
|
|
Offset: offset,
|
|
Limit: limit,
|
|
Tags: sdk.TagsQuery{Elements: []string{"tag1"}, Operator: sdk.OrOp},
|
|
},
|
|
svcReq: users.Page{
|
|
Offset: offset,
|
|
Limit: limit,
|
|
Tags: users.TagsQuery{Elements: []string{"tag1"}, Operator: users.OrOp},
|
|
Order: api.DefOrder,
|
|
Dir: api.DefDir,
|
|
},
|
|
svcRes: users.UsersPage{
|
|
Page: users.Page{
|
|
Total: 1,
|
|
},
|
|
Users: []users.User{convertUser(cls[50])},
|
|
},
|
|
svcErr: nil,
|
|
response: sdk.UsersPage{
|
|
PageRes: sdk.PageRes{
|
|
Total: 1,
|
|
},
|
|
Users: []sdk.User{cls[50]},
|
|
},
|
|
err: nil,
|
|
},
|
|
{
|
|
desc: "list users with CreatedFrom",
|
|
token: validToken,
|
|
pageMeta: sdk.PageMetadata{
|
|
Offset: offset,
|
|
Limit: limit,
|
|
CreatedFrom: time.Date(2024, 1, 1, 0, 0, 0, 0, time.UTC),
|
|
},
|
|
svcReq: users.Page{
|
|
Offset: offset,
|
|
Limit: limit,
|
|
CreatedFrom: time.Date(2024, 1, 1, 0, 0, 0, 0, time.UTC),
|
|
Order: api.DefOrder,
|
|
Dir: api.DefDir,
|
|
},
|
|
svcRes: users.UsersPage{
|
|
Page: users.Page{
|
|
Total: uint64(len(cls[offset:limit])),
|
|
},
|
|
Users: convertUsers(cls[offset:limit]),
|
|
},
|
|
svcErr: nil,
|
|
response: sdk.UsersPage{
|
|
PageRes: sdk.PageRes{
|
|
Total: uint64(len(cls[offset:limit])),
|
|
},
|
|
Users: cls[offset:limit],
|
|
},
|
|
err: nil,
|
|
},
|
|
{
|
|
desc: "list users with CreatedTo",
|
|
token: validToken,
|
|
pageMeta: sdk.PageMetadata{
|
|
Offset: offset,
|
|
Limit: limit,
|
|
CreatedTo: time.Date(2025, 12, 31, 23, 59, 59, 0, time.UTC),
|
|
},
|
|
svcReq: users.Page{
|
|
Offset: offset,
|
|
Limit: limit,
|
|
CreatedTo: time.Date(2025, 12, 31, 23, 59, 59, 0, time.UTC),
|
|
Order: api.DefOrder,
|
|
Dir: api.DefDir,
|
|
},
|
|
svcRes: users.UsersPage{
|
|
Page: users.Page{
|
|
Total: uint64(len(cls[offset:limit])),
|
|
},
|
|
Users: convertUsers(cls[offset:limit]),
|
|
},
|
|
svcErr: nil,
|
|
response: sdk.UsersPage{
|
|
PageRes: sdk.PageRes{
|
|
Total: uint64(len(cls[offset:limit])),
|
|
},
|
|
Users: cls[offset:limit],
|
|
},
|
|
err: nil,
|
|
},
|
|
{
|
|
desc: "list users with both CreatedFrom and CreatedTo",
|
|
token: validToken,
|
|
pageMeta: sdk.PageMetadata{
|
|
Offset: offset,
|
|
Limit: limit,
|
|
CreatedFrom: time.Date(2024, 1, 1, 0, 0, 0, 0, time.UTC),
|
|
CreatedTo: time.Date(2025, 12, 31, 23, 59, 59, 0, time.UTC),
|
|
},
|
|
svcReq: users.Page{
|
|
Offset: offset,
|
|
Limit: limit,
|
|
CreatedFrom: time.Date(2024, 1, 1, 0, 0, 0, 0, time.UTC),
|
|
CreatedTo: time.Date(2025, 12, 31, 23, 59, 59, 0, time.UTC),
|
|
Order: api.DefOrder,
|
|
Dir: api.DefDir,
|
|
},
|
|
svcRes: users.UsersPage{
|
|
Page: users.Page{
|
|
Total: 2,
|
|
},
|
|
Users: []users.User{convertUser(cls[10]), convertUser(cls[20])},
|
|
},
|
|
svcErr: nil,
|
|
response: sdk.UsersPage{
|
|
PageRes: sdk.PageRes{
|
|
Total: 2,
|
|
},
|
|
Users: []sdk.User{cls[10], cls[20]},
|
|
},
|
|
err: nil,
|
|
},
|
|
{
|
|
desc: "list users with request that can't be marshalled",
|
|
token: validToken,
|
|
pageMeta: sdk.PageMetadata{
|
|
Offset: offset,
|
|
Limit: limit,
|
|
Metadata: sdk.Metadata{
|
|
"test": make(chan int),
|
|
},
|
|
},
|
|
svcReq: users.Page{
|
|
Offset: offset,
|
|
Limit: limit,
|
|
Order: api.DefOrder,
|
|
Dir: api.DefDir,
|
|
},
|
|
svcRes: users.UsersPage{},
|
|
svcErr: nil,
|
|
response: sdk.UsersPage{},
|
|
err: errors.NewSDKError(fmt.Errorf("json: unsupported type: chan int")),
|
|
},
|
|
{
|
|
desc: "list users with response that can't be unmarshalled",
|
|
token: validToken,
|
|
pageMeta: sdk.PageMetadata{
|
|
Offset: offset,
|
|
Limit: limit,
|
|
},
|
|
svcReq: users.Page{
|
|
Offset: offset,
|
|
Limit: limit,
|
|
Order: api.DefOrder,
|
|
Dir: api.DefDir,
|
|
},
|
|
svcRes: users.UsersPage{
|
|
Page: users.Page{
|
|
Total: uint64(len(cls[offset:limit])),
|
|
},
|
|
Users: []users.User{
|
|
{
|
|
ID: id,
|
|
FirstName: "user_99",
|
|
Metadata: users.Metadata{
|
|
"key": make(chan int),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
response: sdk.UsersPage{},
|
|
err: errors.NewSDKError(fmt.Errorf("unexpected end of JSON input")),
|
|
},
|
|
}
|
|
|
|
for _, tc := range cases {
|
|
t.Run(tc.desc, func(t *testing.T) {
|
|
if tc.token == validToken {
|
|
tc.session = smqauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}
|
|
}
|
|
authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr)
|
|
svcCall := svc.On("ListUsers", mock.Anything, tc.session, tc.svcReq).Return(tc.svcRes, tc.svcErr)
|
|
resp, err := mgsdk.Users(context.Background(), tc.pageMeta, tc.token)
|
|
assert.Equal(t, tc.err, err)
|
|
assert.Equal(t, tc.response, resp)
|
|
if tc.token != "" {
|
|
ok := authCall.Parent.AssertCalled(t, "Authenticate", mock.Anything, tc.token)
|
|
assert.True(t, ok)
|
|
}
|
|
if tc.err == nil {
|
|
ok := svcCall.Parent.AssertCalled(t, "ListUsers", mock.Anything, tc.session, tc.svcReq)
|
|
assert.True(t, ok)
|
|
}
|
|
svcCall.Unset()
|
|
authCall.Unset()
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestSearchUsers(t *testing.T) {
|
|
ts, svc, auth := setupUsers()
|
|
defer ts.Close()
|
|
|
|
var cls []sdk.User
|
|
conf := sdk.Config{
|
|
UsersURL: ts.URL,
|
|
}
|
|
mgsdk := sdk.NewSDK(conf)
|
|
|
|
for i := 10; i < 100; i++ {
|
|
cl := sdk.User{
|
|
ID: generateUUID(t),
|
|
FirstName: fmt.Sprintf("user_%d", i),
|
|
Email: fmt.Sprintf("email_%d", i),
|
|
Credentials: sdk.Credentials{
|
|
Username: fmt.Sprintf("Username_%d", i),
|
|
Secret: fmt.Sprintf("password_%d", i),
|
|
},
|
|
Metadata: sdk.Metadata{"name": fmt.Sprintf("user_%d", i)},
|
|
Status: users.EnabledStatus.String(),
|
|
Role: users.UserRole.String(),
|
|
}
|
|
if i == 50 {
|
|
cl.Status = users.DisabledStatus.String()
|
|
cl.Tags = []string{"tag1", "tag2"}
|
|
}
|
|
cls = append(cls, cl)
|
|
}
|
|
|
|
cases := []struct {
|
|
desc string
|
|
token string
|
|
page sdk.PageMetadata
|
|
response []sdk.User
|
|
searchreturn users.UsersPage
|
|
err errors.SDKError
|
|
authenticateErr error
|
|
}{
|
|
{
|
|
desc: "search for users",
|
|
token: validToken,
|
|
err: nil,
|
|
page: sdk.PageMetadata{
|
|
Offset: offset,
|
|
Limit: limit,
|
|
Username: "user_20",
|
|
},
|
|
response: []sdk.User{cls[10]},
|
|
searchreturn: users.UsersPage{
|
|
Users: []users.User{convertUser(cls[10])},
|
|
Page: users.Page{
|
|
Total: 1,
|
|
Offset: offset,
|
|
Limit: limit,
|
|
},
|
|
},
|
|
},
|
|
{
|
|
desc: "search for users with invalid token",
|
|
token: invalidToken,
|
|
page: sdk.PageMetadata{
|
|
Offset: offset,
|
|
Limit: limit,
|
|
Username: "user_10",
|
|
},
|
|
err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthentication, http.StatusUnauthorized),
|
|
response: nil,
|
|
authenticateErr: svcerr.ErrAuthentication,
|
|
},
|
|
{
|
|
desc: "search for users with empty token",
|
|
token: "",
|
|
page: sdk.PageMetadata{
|
|
Offset: offset,
|
|
Limit: limit,
|
|
Username: "user_10",
|
|
},
|
|
err: errors.NewSDKErrorWithStatus(apiutil.ErrBearerToken, http.StatusUnauthorized),
|
|
response: nil,
|
|
authenticateErr: svcerr.ErrAuthentication,
|
|
},
|
|
{
|
|
desc: "search for users with empty query",
|
|
token: validToken,
|
|
page: sdk.PageMetadata{
|
|
Offset: offset,
|
|
Limit: limit,
|
|
FirstName: "",
|
|
},
|
|
err: errors.NewSDKErrorWithStatus(apiutil.ErrEmptySearchQuery, http.StatusBadRequest),
|
|
},
|
|
{
|
|
desc: "search for users with invalid length of query",
|
|
token: validToken,
|
|
page: sdk.PageMetadata{
|
|
Offset: offset,
|
|
Limit: limit,
|
|
Username: "a",
|
|
},
|
|
err: errors.NewSDKErrorWithStatus(apiutil.ErrValidation, http.StatusBadRequest),
|
|
},
|
|
{
|
|
desc: "search for users with invalid limit",
|
|
token: validToken,
|
|
page: sdk.PageMetadata{
|
|
Offset: offset,
|
|
Limit: 0,
|
|
Username: "user_10",
|
|
},
|
|
err: errors.NewSDKErrorWithStatus(apiutil.ErrLimitSize, http.StatusBadRequest),
|
|
},
|
|
}
|
|
|
|
for _, tc := range cases {
|
|
t.Run(tc.desc, func(t *testing.T) {
|
|
authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(smqauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}, tc.authenticateErr)
|
|
svcCall := svc.On("SearchUsers", mock.Anything, mock.Anything).Return(tc.searchreturn, tc.err)
|
|
page, err := mgsdk.SearchUsers(context.Background(), tc.page, tc.token)
|
|
assert.Equal(t, tc.err, err, fmt.Sprintf("%s: expected error %v, got %v", tc.desc, tc.err, err))
|
|
assert.Equal(t, tc.response, page.Users, fmt.Sprintf("%s: expected %v got %v\n", tc.desc, tc.response, page.Users))
|
|
svcCall.Unset()
|
|
authCall.Unset()
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestViewUser(t *testing.T) {
|
|
ts, svc, auth := setupUsers()
|
|
defer ts.Close()
|
|
|
|
conf := sdk.Config{
|
|
UsersURL: ts.URL,
|
|
}
|
|
mgsdk := sdk.NewSDK(conf)
|
|
|
|
cases := []struct {
|
|
desc string
|
|
token string
|
|
session smqauthn.Session
|
|
userID string
|
|
svcRes users.User
|
|
svcErr error
|
|
authenticateErr error
|
|
response sdk.User
|
|
err errors.SDKError
|
|
}{
|
|
{
|
|
desc: "view user successfully",
|
|
token: validToken,
|
|
userID: user.ID,
|
|
svcRes: convertUser(user),
|
|
svcErr: nil,
|
|
response: user,
|
|
err: nil,
|
|
},
|
|
{
|
|
desc: "view user with invalid token",
|
|
token: invalidToken,
|
|
userID: user.ID,
|
|
svcRes: users.User{},
|
|
svcErr: svcerr.ErrAuthentication,
|
|
authenticateErr: svcerr.ErrAuthentication,
|
|
response: sdk.User{},
|
|
err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthentication, http.StatusUnauthorized),
|
|
},
|
|
{
|
|
desc: "view user with empty token",
|
|
token: "",
|
|
userID: user.ID,
|
|
svcRes: users.User{},
|
|
svcErr: svcerr.ErrAuthentication,
|
|
response: sdk.User{},
|
|
err: errors.NewSDKErrorWithStatus(apiutil.ErrBearerToken, http.StatusUnauthorized),
|
|
},
|
|
{
|
|
desc: "view user with invalid id",
|
|
token: validToken,
|
|
userID: wrongID,
|
|
svcRes: users.User{},
|
|
svcErr: svcerr.ErrNotFound,
|
|
response: sdk.User{},
|
|
err: errors.NewSDKErrorWithStatus(svcerr.ErrNotFound, http.StatusNotFound),
|
|
},
|
|
{
|
|
desc: "view user with empty id",
|
|
token: validToken,
|
|
userID: "",
|
|
svcRes: users.User{},
|
|
svcErr: nil,
|
|
response: sdk.User{},
|
|
err: errors.NewSDKError(apiutil.ErrMissingID),
|
|
},
|
|
{
|
|
desc: "view user with response that can't be unmarshalled",
|
|
token: validToken,
|
|
userID: user.ID,
|
|
svcRes: users.User{
|
|
ID: id,
|
|
FirstName: user.FirstName,
|
|
LastName: user.LastName,
|
|
Metadata: users.Metadata{
|
|
"key": make(chan int),
|
|
},
|
|
},
|
|
svcErr: nil,
|
|
response: sdk.User{},
|
|
err: errors.NewSDKError(fmt.Errorf("unexpected end of JSON input")),
|
|
},
|
|
}
|
|
for _, tc := range cases {
|
|
t.Run(tc.desc, func(t *testing.T) {
|
|
if tc.token == validToken {
|
|
tc.session = smqauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}
|
|
}
|
|
authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr)
|
|
svcCall := svc.On("View", mock.Anything, tc.session, tc.userID).Return(tc.svcRes, tc.svcErr)
|
|
resp, err := mgsdk.User(context.Background(), tc.userID, tc.token)
|
|
assert.Equal(t, tc.err, err)
|
|
assert.Equal(t, tc.response, resp)
|
|
if tc.err == nil {
|
|
ok := svcCall.Parent.AssertCalled(t, "View", mock.Anything, tc.session, tc.userID)
|
|
assert.True(t, ok)
|
|
}
|
|
svcCall.Unset()
|
|
authCall.Unset()
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestUserProfile(t *testing.T) {
|
|
ts, svc, auth := setupUsers()
|
|
defer ts.Close()
|
|
|
|
conf := sdk.Config{
|
|
UsersURL: ts.URL,
|
|
}
|
|
mgsdk := sdk.NewSDK(conf)
|
|
|
|
cases := []struct {
|
|
desc string
|
|
token string
|
|
session smqauthn.Session
|
|
svcRes users.User
|
|
svcErr error
|
|
authenticateErr error
|
|
response sdk.User
|
|
err errors.SDKError
|
|
}{
|
|
{
|
|
desc: "view user profile successfully",
|
|
token: validToken,
|
|
svcRes: convertUser(user),
|
|
svcErr: nil,
|
|
response: user,
|
|
err: nil,
|
|
},
|
|
{
|
|
desc: "view user profile with invalid token",
|
|
token: invalidToken,
|
|
svcRes: users.User{},
|
|
svcErr: nil,
|
|
authenticateErr: svcerr.ErrAuthentication,
|
|
response: sdk.User{},
|
|
err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthentication, http.StatusUnauthorized),
|
|
},
|
|
{
|
|
desc: "view user profile with empty token",
|
|
token: "",
|
|
svcRes: users.User{},
|
|
svcErr: nil,
|
|
response: sdk.User{},
|
|
err: errors.NewSDKErrorWithStatus(apiutil.ErrBearerToken, http.StatusUnauthorized),
|
|
},
|
|
{
|
|
desc: "view user profile with response that can't be unmarshalled",
|
|
token: validToken,
|
|
svcRes: users.User{
|
|
ID: id,
|
|
FirstName: user.FirstName,
|
|
Metadata: users.Metadata{
|
|
"key": make(chan int),
|
|
},
|
|
},
|
|
svcErr: nil,
|
|
response: sdk.User{},
|
|
err: errors.NewSDKError(fmt.Errorf("unexpected end of JSON input")),
|
|
},
|
|
}
|
|
for _, tc := range cases {
|
|
t.Run(tc.desc, func(t *testing.T) {
|
|
if tc.token == validToken {
|
|
tc.session = smqauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}
|
|
}
|
|
authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr)
|
|
svcCall := svc.On("ViewProfile", mock.Anything, tc.session).Return(tc.svcRes, tc.svcErr)
|
|
resp, err := mgsdk.UserProfile(context.Background(), tc.token)
|
|
assert.Equal(t, tc.err, err)
|
|
assert.Equal(t, tc.response, resp)
|
|
if tc.err == nil {
|
|
ok := svcCall.Parent.AssertCalled(t, "ViewProfile", mock.Anything, tc.session)
|
|
assert.True(t, ok)
|
|
}
|
|
svcCall.Unset()
|
|
authCall.Unset()
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestUpdateUser(t *testing.T) {
|
|
ts, svc, auth := setupUsers()
|
|
defer ts.Close()
|
|
|
|
conf := sdk.Config{
|
|
UsersURL: ts.URL,
|
|
}
|
|
mgsdk := sdk.NewSDK(conf)
|
|
|
|
updatedName := "updatedName"
|
|
updatedUser := user
|
|
updatedUser.FirstName = updatedName
|
|
|
|
cases := []struct {
|
|
desc string
|
|
token string
|
|
session smqauthn.Session
|
|
updateUserReq sdk.User
|
|
userID string
|
|
svcReq users.UserReq
|
|
svcRes users.User
|
|
svcErr error
|
|
authenticateErr error
|
|
response sdk.User
|
|
err errors.SDKError
|
|
}{
|
|
{
|
|
desc: "update user name with valid token",
|
|
token: validToken,
|
|
updateUserReq: sdk.User{
|
|
ID: user.ID,
|
|
FirstName: updatedName,
|
|
},
|
|
userID: user.ID,
|
|
svcReq: users.UserReq{
|
|
FirstName: &updatedName,
|
|
},
|
|
svcRes: convertUser(updatedUser),
|
|
svcErr: nil,
|
|
response: updatedUser,
|
|
err: nil,
|
|
},
|
|
{
|
|
desc: "update user name with invalid token",
|
|
token: invalidToken,
|
|
updateUserReq: sdk.User{
|
|
ID: user.ID,
|
|
FirstName: updatedName,
|
|
},
|
|
userID: user.ID,
|
|
svcReq: users.UserReq{
|
|
FirstName: &updatedName,
|
|
},
|
|
svcRes: users.User{},
|
|
authenticateErr: svcerr.ErrAuthentication,
|
|
response: sdk.User{},
|
|
err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthentication, http.StatusUnauthorized),
|
|
},
|
|
{
|
|
desc: "update user name with invalid id",
|
|
token: validToken,
|
|
updateUserReq: sdk.User{
|
|
ID: wrongID,
|
|
FirstName: updatedName,
|
|
},
|
|
userID: wrongID,
|
|
svcReq: users.UserReq{
|
|
FirstName: &updatedName,
|
|
},
|
|
svcRes: users.User{},
|
|
svcErr: svcerr.ErrUpdateEntity,
|
|
response: sdk.User{},
|
|
err: errors.NewSDKErrorWithStatus(svcerr.ErrUpdateEntity, http.StatusUnprocessableEntity),
|
|
},
|
|
{
|
|
desc: "update user name with empty token",
|
|
token: "",
|
|
updateUserReq: sdk.User{
|
|
ID: user.ID,
|
|
FirstName: updatedName,
|
|
},
|
|
userID: user.ID,
|
|
svcReq: users.UserReq{
|
|
FirstName: &updatedName,
|
|
},
|
|
svcRes: users.User{},
|
|
svcErr: nil,
|
|
response: sdk.User{},
|
|
err: errors.NewSDKErrorWithStatus(apiutil.ErrBearerToken, http.StatusUnauthorized),
|
|
},
|
|
{
|
|
desc: "update user name with empty id",
|
|
token: validToken,
|
|
updateUserReq: sdk.User{
|
|
ID: "",
|
|
FirstName: updatedName,
|
|
},
|
|
userID: "",
|
|
svcReq: users.UserReq{
|
|
FirstName: &updatedName,
|
|
},
|
|
svcRes: users.User{},
|
|
svcErr: nil,
|
|
response: sdk.User{},
|
|
err: errors.NewSDKError(apiutil.ErrMissingID),
|
|
},
|
|
{
|
|
desc: "update user with request that can't be marshalled",
|
|
token: validToken,
|
|
updateUserReq: sdk.User{
|
|
ID: generateUUID(t),
|
|
Metadata: map[string]any{
|
|
"test": make(chan int),
|
|
},
|
|
},
|
|
svcReq: users.UserReq{},
|
|
svcRes: users.User{},
|
|
svcErr: nil,
|
|
response: sdk.User{},
|
|
err: errors.NewSDKError(fmt.Errorf("json: unsupported type: chan int")),
|
|
},
|
|
{
|
|
desc: "update user with response that can't be unmarshalled",
|
|
token: validToken,
|
|
updateUserReq: sdk.User{
|
|
ID: user.ID,
|
|
FirstName: updatedName,
|
|
},
|
|
userID: user.ID,
|
|
svcReq: users.UserReq{
|
|
FirstName: &updatedName,
|
|
},
|
|
svcRes: users.User{
|
|
ID: id,
|
|
FirstName: updatedName,
|
|
Metadata: users.Metadata{
|
|
"key": make(chan int),
|
|
},
|
|
},
|
|
svcErr: nil,
|
|
response: sdk.User{},
|
|
err: errors.NewSDKError(fmt.Errorf("unexpected end of JSON input")),
|
|
},
|
|
}
|
|
|
|
for _, tc := range cases {
|
|
t.Run(tc.desc, func(t *testing.T) {
|
|
if tc.token == validToken {
|
|
tc.session = smqauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}
|
|
}
|
|
authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr)
|
|
svcCall := svc.On("Update", mock.Anything, tc.session, tc.userID, tc.svcReq).Return(tc.svcRes, tc.svcErr)
|
|
resp, err := mgsdk.UpdateUser(context.Background(), tc.updateUserReq, tc.token)
|
|
assert.Equal(t, tc.err, err)
|
|
assert.Equal(t, tc.response, resp)
|
|
if tc.err == nil {
|
|
ok := svcCall.Parent.AssertCalled(t, "Update", mock.Anything, tc.session, tc.userID, tc.svcReq)
|
|
assert.True(t, ok)
|
|
}
|
|
svcCall.Unset()
|
|
authCall.Unset()
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestUpdateUserTags(t *testing.T) {
|
|
ts, svc, auth := setupUsers()
|
|
defer ts.Close()
|
|
|
|
conf := sdk.Config{
|
|
UsersURL: ts.URL,
|
|
}
|
|
mgsdk := sdk.NewSDK(conf)
|
|
|
|
updatedTags := []string{"updatedTag1", "updatedTag2"}
|
|
|
|
updatedUser := user
|
|
updatedUser.Tags = updatedTags
|
|
|
|
cases := []struct {
|
|
desc string
|
|
token string
|
|
session smqauthn.Session
|
|
updateUserReq sdk.User
|
|
userID string
|
|
svcReq users.UserReq
|
|
svcRes users.User
|
|
svcErr error
|
|
authenticateErr error
|
|
response sdk.User
|
|
err errors.SDKError
|
|
}{
|
|
{
|
|
desc: "update user tags with valid token",
|
|
token: validToken,
|
|
updateUserReq: sdk.User{
|
|
ID: user.ID,
|
|
Tags: updatedTags,
|
|
},
|
|
userID: user.ID,
|
|
svcReq: users.UserReq{
|
|
Tags: &updatedTags,
|
|
},
|
|
svcRes: convertUser(updatedUser),
|
|
svcErr: nil,
|
|
response: updatedUser,
|
|
err: nil,
|
|
},
|
|
{
|
|
desc: "update user tags with invalid token",
|
|
token: invalidToken,
|
|
updateUserReq: sdk.User{
|
|
ID: user.ID,
|
|
Tags: updatedTags,
|
|
},
|
|
userID: user.ID,
|
|
svcReq: users.UserReq{
|
|
Tags: &updatedTags,
|
|
},
|
|
svcRes: users.User{},
|
|
authenticateErr: svcerr.ErrAuthentication,
|
|
response: sdk.User{},
|
|
err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthentication, http.StatusUnauthorized),
|
|
},
|
|
{
|
|
desc: "update user tags with empty token",
|
|
token: "",
|
|
updateUserReq: sdk.User{
|
|
ID: user.ID,
|
|
Tags: updatedTags,
|
|
},
|
|
svcReq: users.UserReq{},
|
|
svcRes: users.User{},
|
|
svcErr: nil,
|
|
response: sdk.User{},
|
|
err: errors.NewSDKErrorWithStatus(apiutil.ErrBearerToken, http.StatusUnauthorized),
|
|
},
|
|
{
|
|
desc: "update user tags with invalid id",
|
|
token: validToken,
|
|
updateUserReq: sdk.User{
|
|
ID: wrongID,
|
|
Tags: updatedTags,
|
|
},
|
|
userID: wrongID,
|
|
svcReq: users.UserReq{
|
|
Tags: &updatedTags,
|
|
},
|
|
svcRes: users.User{},
|
|
svcErr: svcerr.ErrUpdateEntity,
|
|
response: sdk.User{},
|
|
err: errors.NewSDKErrorWithStatus(svcerr.ErrUpdateEntity, http.StatusUnprocessableEntity),
|
|
},
|
|
{
|
|
desc: "update user tags with empty id",
|
|
token: validToken,
|
|
updateUserReq: sdk.User{
|
|
ID: "",
|
|
Tags: updatedTags,
|
|
},
|
|
userID: "",
|
|
svcReq: users.UserReq{},
|
|
svcRes: users.User{},
|
|
svcErr: nil,
|
|
response: sdk.User{},
|
|
err: errors.NewSDKErrorWithStatus(apiutil.ErrMissingID, http.StatusBadRequest),
|
|
},
|
|
{
|
|
desc: "update user tags with request that can't be marshalled",
|
|
token: validToken,
|
|
updateUserReq: sdk.User{
|
|
ID: generateUUID(t),
|
|
Metadata: map[string]any{
|
|
"test": make(chan int),
|
|
},
|
|
},
|
|
svcReq: users.UserReq{},
|
|
svcRes: users.User{},
|
|
svcErr: nil,
|
|
response: sdk.User{},
|
|
err: errors.NewSDKError(fmt.Errorf("json: unsupported type: chan int")),
|
|
},
|
|
{
|
|
desc: "update user tags with response that can't be unmarshalled",
|
|
token: validToken,
|
|
updateUserReq: sdk.User{
|
|
ID: user.ID,
|
|
Tags: updatedTags,
|
|
},
|
|
userID: user.ID,
|
|
svcReq: users.UserReq{
|
|
Tags: &updatedTags,
|
|
},
|
|
svcRes: users.User{
|
|
ID: id,
|
|
Tags: updatedTags,
|
|
Metadata: users.Metadata{
|
|
"key": make(chan int),
|
|
},
|
|
},
|
|
svcErr: nil,
|
|
response: sdk.User{},
|
|
err: errors.NewSDKError(fmt.Errorf("unexpected end of JSON input")),
|
|
},
|
|
}
|
|
for _, tc := range cases {
|
|
t.Run(tc.desc, func(t *testing.T) {
|
|
if tc.token == validToken {
|
|
tc.session = smqauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}
|
|
}
|
|
authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr)
|
|
svcCall := svc.On("UpdateTags", mock.Anything, tc.session, tc.userID, tc.svcReq).Return(tc.svcRes, tc.svcErr)
|
|
resp, err := mgsdk.UpdateUserTags(context.Background(), tc.updateUserReq, tc.token)
|
|
assert.Equal(t, tc.err, err)
|
|
assert.Equal(t, tc.response, resp)
|
|
if tc.err == nil {
|
|
ok := svcCall.Parent.AssertCalled(t, "UpdateTags", mock.Anything, tc.session, tc.userID, tc.svcReq)
|
|
assert.True(t, ok)
|
|
}
|
|
svcCall.Unset()
|
|
authCall.Unset()
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestUpdateUserEmail(t *testing.T) {
|
|
ts, svc, auth := setupUsers()
|
|
defer ts.Close()
|
|
|
|
conf := sdk.Config{
|
|
UsersURL: ts.URL,
|
|
}
|
|
mgsdk := sdk.NewSDK(conf)
|
|
|
|
updatedEmail := "updatedEmail@email.com"
|
|
updatedUser := user
|
|
updatedUser.Email = updatedEmail
|
|
|
|
cases := []struct {
|
|
desc string
|
|
token string
|
|
session smqauthn.Session
|
|
updateUserReq sdk.User
|
|
svcReq string
|
|
svcRes users.User
|
|
svcErr error
|
|
authenticateErr error
|
|
response sdk.User
|
|
err errors.SDKError
|
|
}{
|
|
{
|
|
desc: "update email with valid token",
|
|
token: validToken,
|
|
updateUserReq: sdk.User{
|
|
ID: user.ID,
|
|
Email: updatedEmail,
|
|
Credentials: sdk.Credentials{
|
|
Secret: user.Credentials.Secret,
|
|
},
|
|
},
|
|
svcReq: updatedEmail,
|
|
svcRes: convertUser(updatedUser),
|
|
svcErr: nil,
|
|
response: updatedUser,
|
|
err: nil,
|
|
},
|
|
{
|
|
desc: "update email with invalid token",
|
|
token: invalidToken,
|
|
updateUserReq: sdk.User{
|
|
ID: user.ID,
|
|
Email: updatedEmail,
|
|
Credentials: sdk.Credentials{
|
|
Secret: user.Credentials.Secret,
|
|
},
|
|
},
|
|
svcReq: updatedEmail,
|
|
svcRes: users.User{},
|
|
authenticateErr: svcerr.ErrAuthentication,
|
|
response: sdk.User{},
|
|
err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthentication, http.StatusUnauthorized),
|
|
},
|
|
{
|
|
desc: "update email with empty token",
|
|
token: "",
|
|
updateUserReq: sdk.User{
|
|
ID: user.ID,
|
|
Email: updatedEmail,
|
|
Credentials: sdk.Credentials{
|
|
Secret: user.Credentials.Secret,
|
|
},
|
|
},
|
|
svcReq: updatedEmail,
|
|
svcRes: users.User{},
|
|
svcErr: nil,
|
|
response: sdk.User{},
|
|
err: errors.NewSDKErrorWithStatus(apiutil.ErrBearerToken, http.StatusUnauthorized),
|
|
},
|
|
{
|
|
desc: "update email with invalid id",
|
|
token: validToken,
|
|
updateUserReq: sdk.User{
|
|
ID: wrongID,
|
|
Email: updatedEmail,
|
|
Credentials: sdk.Credentials{
|
|
Secret: user.Credentials.Secret,
|
|
},
|
|
},
|
|
svcReq: updatedEmail,
|
|
svcRes: users.User{},
|
|
svcErr: svcerr.ErrUpdateEntity,
|
|
response: sdk.User{},
|
|
err: errors.NewSDKErrorWithStatus(svcerr.ErrUpdateEntity, http.StatusUnprocessableEntity),
|
|
},
|
|
{
|
|
desc: "update email with empty id",
|
|
token: validToken,
|
|
updateUserReq: sdk.User{
|
|
ID: "",
|
|
Email: updatedEmail,
|
|
Credentials: sdk.Credentials{
|
|
Secret: user.Credentials.Secret,
|
|
},
|
|
},
|
|
svcReq: updatedEmail,
|
|
svcRes: users.User{},
|
|
svcErr: nil,
|
|
response: sdk.User{},
|
|
err: errors.NewSDKErrorWithStatus(apiutil.ErrMissingID, http.StatusBadRequest),
|
|
},
|
|
{
|
|
desc: "update email with response that can't be unmarshalled",
|
|
token: validToken,
|
|
updateUserReq: sdk.User{
|
|
ID: user.ID,
|
|
Email: updatedEmail,
|
|
Credentials: sdk.Credentials{
|
|
Secret: user.Credentials.Secret,
|
|
},
|
|
},
|
|
svcReq: updatedEmail,
|
|
svcRes: users.User{
|
|
ID: id,
|
|
FirstName: updatedEmail,
|
|
Metadata: users.Metadata{
|
|
"key": make(chan int),
|
|
},
|
|
},
|
|
svcErr: nil,
|
|
response: sdk.User{},
|
|
err: errors.NewSDKError(fmt.Errorf("unexpected end of JSON input")),
|
|
},
|
|
}
|
|
for _, tc := range cases {
|
|
t.Run(tc.desc, func(t *testing.T) {
|
|
if tc.token == validToken {
|
|
tc.session = smqauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}
|
|
}
|
|
authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr)
|
|
svcCall := svc.On("UpdateEmail", mock.Anything, tc.session, tc.updateUserReq.ID, tc.svcReq).Return(tc.svcRes, tc.svcErr)
|
|
resp, err := mgsdk.UpdateUserEmail(context.Background(), tc.updateUserReq, tc.token)
|
|
assert.Equal(t, tc.err, err)
|
|
assert.Equal(t, tc.response, resp)
|
|
if tc.err == nil {
|
|
ok := svcCall.Parent.AssertCalled(t, "UpdateEmail", mock.Anything, tc.session, tc.updateUserReq.ID, tc.svcReq)
|
|
assert.True(t, ok)
|
|
}
|
|
svcCall.Unset()
|
|
authCall.Unset()
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestResetPasswordRequest(t *testing.T) {
|
|
ts, svc, _ := setupUsers()
|
|
defer ts.Close()
|
|
|
|
defHost := "http://localhost"
|
|
|
|
conf := sdk.Config{
|
|
UsersURL: ts.URL,
|
|
HostURL: defHost,
|
|
}
|
|
mgsdk := sdk.NewSDK(conf)
|
|
|
|
validEmail := "test@email.com"
|
|
|
|
cases := []struct {
|
|
desc string
|
|
email string
|
|
svcRes users.User
|
|
svcErr error
|
|
issueRes *grpcTokenV1.Token
|
|
issueErr error
|
|
err errors.SDKError
|
|
}{
|
|
{
|
|
desc: "reset password request with valid email",
|
|
email: validEmail,
|
|
svcRes: convertUser(user),
|
|
svcErr: nil,
|
|
issueRes: &grpcTokenV1.Token{AccessToken: validToken, RefreshToken: &validToken},
|
|
err: nil,
|
|
},
|
|
{
|
|
desc: "reset password request with invalid email",
|
|
email: "invalidemail",
|
|
svcRes: users.User{},
|
|
svcErr: svcerr.ErrNotFound,
|
|
issueRes: &grpcTokenV1.Token{},
|
|
err: errors.NewSDKErrorWithStatus(svcerr.ErrNotFound, http.StatusNotFound),
|
|
},
|
|
{
|
|
desc: "reset password request with empty email",
|
|
email: "",
|
|
svcRes: users.User{},
|
|
svcErr: nil,
|
|
issueRes: &grpcTokenV1.Token{},
|
|
err: errors.NewSDKErrorWithStatus(apiutil.ErrMissingEmail, http.StatusBadRequest),
|
|
},
|
|
}
|
|
for _, tc := range cases {
|
|
t.Run(tc.desc, func(t *testing.T) {
|
|
svcCall := svc.On("SendPasswordReset", mock.Anything, tc.email).Return(tc.svcErr)
|
|
err := mgsdk.ResetPasswordRequest(context.Background(), tc.email)
|
|
assert.Equal(t, tc.err, err)
|
|
if tc.err == nil {
|
|
ok := svcCall.Parent.AssertCalled(t, "SendPasswordReset", mock.Anything, tc.email)
|
|
assert.True(t, ok)
|
|
}
|
|
svcCall.Unset()
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestResetPassword(t *testing.T) {
|
|
ts, svc, auth := setupUsers()
|
|
defer ts.Close()
|
|
|
|
conf := sdk.Config{
|
|
UsersURL: ts.URL,
|
|
}
|
|
mgsdk := sdk.NewSDK(conf)
|
|
|
|
newPassword := "newPassword"
|
|
|
|
cases := []struct {
|
|
desc string
|
|
token string
|
|
session smqauthn.Session
|
|
newPassword string
|
|
confPassword string
|
|
svcErr error
|
|
authenticateErr error
|
|
err errors.SDKError
|
|
}{
|
|
{
|
|
desc: "reset password successfully",
|
|
token: validToken,
|
|
session: smqauthn.Session{UserID: validID, DomainID: domainID},
|
|
newPassword: newPassword,
|
|
confPassword: newPassword,
|
|
svcErr: nil,
|
|
err: nil,
|
|
},
|
|
{
|
|
desc: "reset password with invalid token",
|
|
token: invalidToken,
|
|
newPassword: newPassword,
|
|
confPassword: newPassword,
|
|
authenticateErr: svcerr.ErrAuthentication,
|
|
err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthentication, http.StatusUnauthorized),
|
|
},
|
|
{
|
|
desc: "reset password with empty token",
|
|
token: "",
|
|
newPassword: newPassword,
|
|
confPassword: newPassword,
|
|
svcErr: nil,
|
|
err: errors.NewSDKErrorWithStatus(apiutil.ErrBearerToken, http.StatusUnauthorized),
|
|
},
|
|
{
|
|
desc: "reset password with empty new password",
|
|
token: validToken,
|
|
session: smqauthn.Session{UserID: validID, DomainID: domainID},
|
|
newPassword: "",
|
|
confPassword: newPassword,
|
|
svcErr: nil,
|
|
err: errors.NewSDKErrorWithStatus(apiutil.ErrMissingPass, http.StatusBadRequest),
|
|
},
|
|
{
|
|
desc: "reset password with empty confirm password",
|
|
token: validToken,
|
|
session: smqauthn.Session{UserID: validID, DomainID: domainID},
|
|
newPassword: newPassword,
|
|
confPassword: "",
|
|
svcErr: nil,
|
|
err: errors.NewSDKErrorWithStatus(apiutil.ErrMissingConfPass, http.StatusBadRequest),
|
|
},
|
|
{
|
|
desc: "reset password with new password not matching confirm password",
|
|
token: validToken,
|
|
session: smqauthn.Session{UserID: validID, DomainID: domainID},
|
|
newPassword: newPassword,
|
|
confPassword: "wrongPassword",
|
|
svcErr: nil,
|
|
err: errors.NewSDKErrorWithStatus(apiutil.ErrInvalidResetPass, http.StatusBadRequest),
|
|
},
|
|
{
|
|
desc: "reset password with weak password",
|
|
token: validToken,
|
|
session: smqauthn.Session{UserID: validID, DomainID: domainID},
|
|
newPassword: "weak",
|
|
confPassword: "weak",
|
|
svcErr: nil,
|
|
err: errors.NewSDKErrorWithStatus(apiutil.ErrPasswordFormat, http.StatusBadRequest),
|
|
},
|
|
}
|
|
for _, tc := range cases {
|
|
t.Run(tc.desc, func(t *testing.T) {
|
|
if tc.token == validToken {
|
|
tc.session = smqauthn.Session{UserID: validID, DomainID: domainID}
|
|
}
|
|
authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr)
|
|
svcCall := svc.On("ResetSecret", mock.Anything, tc.session, tc.newPassword).Return(tc.svcErr)
|
|
err := mgsdk.ResetPassword(context.Background(), tc.newPassword, tc.confPassword, tc.token)
|
|
assert.Equal(t, tc.err, err)
|
|
if tc.err == nil {
|
|
ok := svcCall.Parent.AssertCalled(t, "ResetSecret", mock.Anything, tc.session, tc.newPassword)
|
|
assert.True(t, ok)
|
|
}
|
|
svcCall.Unset()
|
|
authCall.Unset()
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestUpdatePassword(t *testing.T) {
|
|
ts, svc, auth := setupUsers()
|
|
defer ts.Close()
|
|
|
|
conf := sdk.Config{
|
|
UsersURL: ts.URL,
|
|
}
|
|
mgsdk := sdk.NewSDK(conf)
|
|
|
|
newPassword := "newPassword"
|
|
updatedUser := user
|
|
updatedUser.Credentials.Secret = newPassword
|
|
|
|
cases := []struct {
|
|
desc string
|
|
token string
|
|
session smqauthn.Session
|
|
oldPassword string
|
|
newPassword string
|
|
svcRes users.User
|
|
svcErr error
|
|
authenticateErr error
|
|
response sdk.User
|
|
err errors.SDKError
|
|
}{
|
|
{
|
|
desc: "update password successfully",
|
|
token: validToken,
|
|
oldPassword: secret,
|
|
newPassword: newPassword,
|
|
svcRes: convertUser(updatedUser),
|
|
svcErr: nil,
|
|
response: updatedUser,
|
|
err: nil,
|
|
},
|
|
{
|
|
desc: "update password with invalid token",
|
|
token: invalidToken,
|
|
oldPassword: secret,
|
|
newPassword: newPassword,
|
|
svcRes: users.User{},
|
|
authenticateErr: svcerr.ErrAuthentication,
|
|
response: sdk.User{},
|
|
err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthentication, http.StatusUnauthorized),
|
|
},
|
|
{
|
|
desc: "update password with empty token",
|
|
token: "",
|
|
oldPassword: secret,
|
|
newPassword: newPassword,
|
|
svcRes: users.User{},
|
|
svcErr: nil,
|
|
response: sdk.User{},
|
|
err: errors.NewSDKErrorWithStatus(apiutil.ErrBearerToken, http.StatusUnauthorized),
|
|
},
|
|
{
|
|
desc: "update password with empty old password",
|
|
token: validToken,
|
|
oldPassword: "",
|
|
newPassword: newPassword,
|
|
svcRes: users.User{},
|
|
svcErr: nil,
|
|
response: sdk.User{},
|
|
err: errors.NewSDKErrorWithStatus(apiutil.ErrMissingPass, http.StatusBadRequest),
|
|
},
|
|
{
|
|
desc: "update password with empty new password",
|
|
token: validToken,
|
|
oldPassword: secret,
|
|
newPassword: "",
|
|
svcRes: users.User{},
|
|
svcErr: nil,
|
|
response: sdk.User{},
|
|
err: errors.NewSDKErrorWithStatus(apiutil.ErrMissingPass, http.StatusBadRequest),
|
|
},
|
|
{
|
|
desc: "update password with invalid new password",
|
|
token: validToken,
|
|
oldPassword: secret,
|
|
newPassword: "weak",
|
|
svcRes: users.User{},
|
|
svcErr: nil,
|
|
response: sdk.User{},
|
|
err: errors.NewSDKErrorWithStatus(apiutil.ErrPasswordFormat, http.StatusBadRequest),
|
|
},
|
|
{
|
|
desc: "update password with invalid old password",
|
|
token: validToken,
|
|
oldPassword: "wrongPassword",
|
|
newPassword: newPassword,
|
|
svcRes: users.User{},
|
|
svcErr: svcerr.ErrLogin,
|
|
response: sdk.User{},
|
|
err: errors.NewSDKErrorWithStatus(svcerr.ErrLogin, http.StatusUnauthorized),
|
|
},
|
|
{
|
|
desc: "update password with response that can't be unmarshalled",
|
|
token: validToken,
|
|
oldPassword: secret,
|
|
newPassword: newPassword,
|
|
svcRes: users.User{
|
|
ID: id,
|
|
FirstName: user.FirstName,
|
|
Metadata: users.Metadata{
|
|
"key": make(chan int),
|
|
},
|
|
},
|
|
svcErr: nil,
|
|
response: sdk.User{},
|
|
err: errors.NewSDKError(fmt.Errorf("unexpected end of JSON input")),
|
|
},
|
|
}
|
|
for _, tc := range cases {
|
|
t.Run(tc.desc, func(t *testing.T) {
|
|
if tc.token == validToken {
|
|
tc.session = smqauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}
|
|
}
|
|
authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr)
|
|
svcCall := svc.On("UpdateSecret", mock.Anything, tc.session, tc.oldPassword, tc.newPassword).Return(tc.svcRes, tc.svcErr)
|
|
resp, err := mgsdk.UpdatePassword(context.Background(), tc.oldPassword, tc.newPassword, tc.token)
|
|
assert.Equal(t, tc.err, err)
|
|
assert.Equal(t, tc.response, resp)
|
|
if tc.err == nil {
|
|
ok := svcCall.Parent.AssertCalled(t, "UpdateSecret", mock.Anything, tc.session, tc.oldPassword, tc.newPassword)
|
|
assert.True(t, ok)
|
|
}
|
|
svcCall.Unset()
|
|
authCall.Unset()
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestUpdateUserRole(t *testing.T) {
|
|
ts, svc, auth := setupUsers()
|
|
defer ts.Close()
|
|
|
|
conf := sdk.Config{
|
|
UsersURL: ts.URL,
|
|
}
|
|
mgsdk := sdk.NewSDK(conf)
|
|
|
|
updatedUser := user
|
|
updatedRole := users.AdminRole.String()
|
|
updatedUser.Role = updatedRole
|
|
|
|
cases := []struct {
|
|
desc string
|
|
token string
|
|
session smqauthn.Session
|
|
updateUserReq sdk.User
|
|
svcReq users.User
|
|
svcRes users.User
|
|
svcErr error
|
|
authenticateErr error
|
|
response sdk.User
|
|
err errors.SDKError
|
|
}{
|
|
{
|
|
desc: "update user role with valid token",
|
|
token: validToken,
|
|
updateUserReq: sdk.User{
|
|
ID: user.ID,
|
|
Role: updatedRole,
|
|
Email: user.Email,
|
|
},
|
|
svcReq: users.User{
|
|
ID: user.ID,
|
|
Role: users.AdminRole,
|
|
},
|
|
svcRes: convertUser(updatedUser),
|
|
svcErr: nil,
|
|
response: updatedUser,
|
|
err: nil,
|
|
},
|
|
{
|
|
desc: "update user role with invalid token",
|
|
token: invalidToken,
|
|
updateUserReq: sdk.User{
|
|
ID: user.ID,
|
|
Role: updatedRole,
|
|
},
|
|
svcReq: users.User{
|
|
ID: user.ID,
|
|
Role: users.AdminRole,
|
|
},
|
|
svcRes: users.User{},
|
|
authenticateErr: svcerr.ErrAuthentication,
|
|
response: sdk.User{},
|
|
err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthentication, http.StatusUnauthorized),
|
|
},
|
|
{
|
|
desc: "update user role with empty token",
|
|
token: "",
|
|
updateUserReq: sdk.User{
|
|
ID: user.ID,
|
|
Role: updatedRole,
|
|
},
|
|
svcReq: users.User{},
|
|
svcRes: users.User{},
|
|
svcErr: nil,
|
|
response: sdk.User{},
|
|
err: errors.NewSDKErrorWithStatus(apiutil.ErrBearerToken, http.StatusUnauthorized),
|
|
},
|
|
{
|
|
desc: "update user role with invalid id",
|
|
token: validToken,
|
|
updateUserReq: sdk.User{
|
|
ID: wrongID,
|
|
Role: updatedRole,
|
|
},
|
|
svcReq: users.User{
|
|
ID: wrongID,
|
|
Role: users.AdminRole,
|
|
},
|
|
svcRes: users.User{},
|
|
svcErr: svcerr.ErrUpdateEntity,
|
|
response: sdk.User{},
|
|
err: errors.NewSDKErrorWithStatus(svcerr.ErrUpdateEntity, http.StatusUnprocessableEntity),
|
|
},
|
|
{
|
|
desc: "update user role with empty id",
|
|
token: validToken,
|
|
updateUserReq: sdk.User{
|
|
ID: "",
|
|
Role: updatedRole,
|
|
},
|
|
svcReq: users.User{},
|
|
svcRes: users.User{},
|
|
svcErr: nil,
|
|
response: sdk.User{},
|
|
err: errors.NewSDKErrorWithStatus(apiutil.ErrMissingID, http.StatusBadRequest),
|
|
},
|
|
{
|
|
desc: "update user role with request that can't be marshalled",
|
|
token: validToken,
|
|
updateUserReq: sdk.User{
|
|
ID: generateUUID(t),
|
|
Metadata: map[string]any{
|
|
"test": make(chan int),
|
|
},
|
|
},
|
|
svcReq: users.User{},
|
|
svcRes: users.User{},
|
|
svcErr: nil,
|
|
response: sdk.User{},
|
|
err: errors.NewSDKError(fmt.Errorf("json: unsupported type: chan int")),
|
|
},
|
|
{
|
|
desc: "update user role with response that can't be unmarshalled",
|
|
token: validToken,
|
|
updateUserReq: sdk.User{
|
|
ID: user.ID,
|
|
Role: updatedRole,
|
|
},
|
|
svcReq: users.User{
|
|
ID: user.ID,
|
|
Role: users.AdminRole,
|
|
},
|
|
svcRes: users.User{
|
|
ID: id,
|
|
Role: users.AdminRole,
|
|
Metadata: users.Metadata{
|
|
"key": make(chan int),
|
|
},
|
|
},
|
|
svcErr: nil,
|
|
response: sdk.User{},
|
|
err: errors.NewSDKError(fmt.Errorf("unexpected end of JSON input")),
|
|
},
|
|
}
|
|
for _, tc := range cases {
|
|
t.Run(tc.desc, func(t *testing.T) {
|
|
if tc.token == validToken {
|
|
tc.session = smqauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}
|
|
}
|
|
authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr)
|
|
svcCall := svc.On("UpdateRole", mock.Anything, tc.session, tc.svcReq).Return(tc.svcRes, tc.svcErr)
|
|
resp, err := mgsdk.UpdateUserRole(context.Background(), tc.updateUserReq, tc.token)
|
|
assert.Equal(t, tc.err, err)
|
|
assert.Equal(t, tc.response, resp)
|
|
if tc.err == nil {
|
|
ok := svcCall.Parent.AssertCalled(t, "UpdateRole", mock.Anything, tc.session, tc.svcReq)
|
|
assert.True(t, ok)
|
|
}
|
|
svcCall.Unset()
|
|
authCall.Unset()
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestUpdateUsername(t *testing.T) {
|
|
ts, svc, auth := setupUsers()
|
|
defer ts.Close()
|
|
|
|
conf := sdk.Config{
|
|
UsersURL: ts.URL,
|
|
}
|
|
mgsdk := sdk.NewSDK(conf)
|
|
|
|
updatedUser := user
|
|
updatedUsername := "updatedUsername"
|
|
updatedUser.Credentials.Username = updatedUsername
|
|
|
|
cases := []struct {
|
|
desc string
|
|
token string
|
|
session smqauthn.Session
|
|
updateUserReq sdk.User
|
|
svcReq users.User
|
|
svcRes users.User
|
|
svcErr error
|
|
authenticateErr error
|
|
response sdk.User
|
|
err errors.SDKError
|
|
}{
|
|
{
|
|
desc: "update username with valid token",
|
|
token: validToken,
|
|
updateUserReq: sdk.User{
|
|
ID: user.ID,
|
|
Credentials: sdk.Credentials{
|
|
Username: updatedUsername,
|
|
},
|
|
},
|
|
svcReq: users.User{
|
|
ID: user.ID,
|
|
Credentials: users.Credentials{
|
|
Username: updatedUsername,
|
|
},
|
|
},
|
|
svcRes: convertUser(updatedUser),
|
|
svcErr: nil,
|
|
response: updatedUser,
|
|
err: nil,
|
|
},
|
|
{
|
|
desc: "update username with invalid token",
|
|
token: invalidToken,
|
|
updateUserReq: sdk.User{
|
|
ID: user.ID,
|
|
Credentials: sdk.Credentials{
|
|
Username: updatedUsername,
|
|
},
|
|
},
|
|
svcReq: users.User{
|
|
ID: user.ID,
|
|
Credentials: users.Credentials{
|
|
Username: updatedUsername,
|
|
},
|
|
},
|
|
svcRes: users.User{},
|
|
authenticateErr: svcerr.ErrAuthentication,
|
|
response: sdk.User{},
|
|
err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthentication, http.StatusUnauthorized),
|
|
},
|
|
{
|
|
desc: "update username with empty token",
|
|
token: "",
|
|
updateUserReq: sdk.User{
|
|
ID: user.ID,
|
|
Credentials: sdk.Credentials{
|
|
Username: updatedUsername,
|
|
},
|
|
},
|
|
svcReq: users.User{},
|
|
svcRes: users.User{},
|
|
svcErr: nil,
|
|
response: sdk.User{},
|
|
err: errors.NewSDKErrorWithStatus(apiutil.ErrBearerToken, http.StatusUnauthorized),
|
|
},
|
|
{
|
|
desc: "update username with invalid id",
|
|
token: validToken,
|
|
updateUserReq: sdk.User{
|
|
ID: wrongID,
|
|
Credentials: sdk.Credentials{
|
|
Username: updatedUsername,
|
|
},
|
|
},
|
|
svcReq: users.User{
|
|
ID: wrongID,
|
|
Credentials: users.Credentials{
|
|
Username: updatedUsername,
|
|
},
|
|
},
|
|
svcRes: users.User{},
|
|
svcErr: svcerr.ErrUpdateEntity,
|
|
response: sdk.User{},
|
|
err: errors.NewSDKErrorWithStatus(svcerr.ErrUpdateEntity, http.StatusUnprocessableEntity),
|
|
},
|
|
{
|
|
desc: "update username with empty id",
|
|
token: validToken,
|
|
updateUserReq: sdk.User{
|
|
ID: "",
|
|
Credentials: sdk.Credentials{
|
|
Username: updatedUsername,
|
|
},
|
|
},
|
|
svcReq: users.User{},
|
|
svcRes: users.User{},
|
|
svcErr: nil,
|
|
response: sdk.User{},
|
|
err: errors.NewSDKErrorWithStatus(apiutil.ErrMissingID, http.StatusBadRequest),
|
|
},
|
|
{
|
|
desc: "update username with response that can't be unmarshalled",
|
|
token: validToken,
|
|
updateUserReq: sdk.User{
|
|
ID: user.ID,
|
|
Credentials: sdk.Credentials{
|
|
Username: updatedUsername,
|
|
},
|
|
},
|
|
svcReq: users.User{
|
|
ID: user.ID,
|
|
Credentials: users.Credentials{
|
|
Username: updatedUsername,
|
|
},
|
|
},
|
|
svcRes: users.User{
|
|
ID: id,
|
|
Credentials: users.Credentials{
|
|
Username: updatedUsername,
|
|
},
|
|
Metadata: users.Metadata{
|
|
"key": make(chan int),
|
|
},
|
|
},
|
|
svcErr: nil,
|
|
response: sdk.User{},
|
|
err: errors.NewSDKError(fmt.Errorf("unexpected end of JSON input")),
|
|
},
|
|
}
|
|
for _, tc := range cases {
|
|
t.Run(tc.desc, func(t *testing.T) {
|
|
if tc.token == validToken {
|
|
tc.session = smqauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}
|
|
}
|
|
authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr)
|
|
svcCall := svc.On("UpdateUsername", mock.Anything, tc.session, tc.svcReq.ID, tc.svcReq.Credentials.Username).Return(tc.svcRes, tc.svcErr)
|
|
resp, err := mgsdk.UpdateUsername(context.Background(), tc.updateUserReq, tc.token)
|
|
assert.Equal(t, tc.err, err)
|
|
assert.Equal(t, tc.response, resp)
|
|
if tc.err == nil {
|
|
ok := svcCall.Parent.AssertCalled(t, "UpdateUsername", mock.Anything, tc.session, tc.svcReq.ID, tc.svcReq.Credentials.Username)
|
|
assert.True(t, ok)
|
|
}
|
|
svcCall.Unset()
|
|
authCall.Unset()
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestUpdateProfilePicture(t *testing.T) {
|
|
ts, svc, auth := setupUsers()
|
|
defer ts.Close()
|
|
|
|
conf := sdk.Config{
|
|
UsersURL: ts.URL,
|
|
}
|
|
mgsdk := sdk.NewSDK(conf)
|
|
|
|
updatedProfilePicture := "http://updated.com/profile.jpg"
|
|
updatedUser := user
|
|
updatedUser.Email = updatedProfilePicture
|
|
|
|
cases := []struct {
|
|
desc string
|
|
token string
|
|
session smqauthn.Session
|
|
updateUserReq sdk.User
|
|
userID string
|
|
svcReq users.UserReq
|
|
svcRes users.User
|
|
svcErr error
|
|
authenticateErr error
|
|
response sdk.User
|
|
err errors.SDKError
|
|
}{
|
|
{
|
|
desc: "update profile picture with valid token",
|
|
token: validToken,
|
|
updateUserReq: sdk.User{
|
|
ID: user.ID,
|
|
ProfilePicture: updatedProfilePicture,
|
|
},
|
|
userID: user.ID,
|
|
svcReq: users.UserReq{
|
|
ProfilePicture: &updatedProfilePicture,
|
|
},
|
|
svcRes: convertUser(updatedUser),
|
|
svcErr: nil,
|
|
response: updatedUser,
|
|
err: nil,
|
|
},
|
|
{
|
|
desc: "update profile picture with invalid token",
|
|
token: invalidToken,
|
|
updateUserReq: sdk.User{
|
|
ID: user.ID,
|
|
ProfilePicture: updatedProfilePicture,
|
|
},
|
|
userID: user.ID,
|
|
svcReq: users.UserReq{
|
|
ProfilePicture: &updatedProfilePicture,
|
|
},
|
|
svcRes: users.User{},
|
|
authenticateErr: svcerr.ErrAuthentication,
|
|
response: sdk.User{},
|
|
err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthentication, http.StatusUnauthorized),
|
|
},
|
|
{
|
|
desc: "update profile picture with empty token",
|
|
token: "",
|
|
updateUserReq: sdk.User{
|
|
ID: user.ID,
|
|
ProfilePicture: updatedProfilePicture,
|
|
},
|
|
userID: user.ID,
|
|
svcReq: users.UserReq{
|
|
ProfilePicture: &updatedProfilePicture,
|
|
},
|
|
svcRes: users.User{},
|
|
svcErr: nil,
|
|
response: sdk.User{},
|
|
err: errors.NewSDKErrorWithStatus(apiutil.ErrBearerToken, http.StatusUnauthorized),
|
|
},
|
|
{
|
|
desc: "update profile picture with invalid id",
|
|
token: validToken,
|
|
updateUserReq: sdk.User{
|
|
ID: wrongID,
|
|
ProfilePicture: updatedProfilePicture,
|
|
},
|
|
userID: wrongID,
|
|
svcReq: users.UserReq{
|
|
ProfilePicture: &updatedProfilePicture,
|
|
},
|
|
svcRes: users.User{},
|
|
svcErr: svcerr.ErrUpdateEntity,
|
|
response: sdk.User{},
|
|
err: errors.NewSDKErrorWithStatus(svcerr.ErrUpdateEntity, http.StatusUnprocessableEntity),
|
|
},
|
|
{
|
|
desc: "update profile picture with empty id",
|
|
token: validToken,
|
|
updateUserReq: sdk.User{
|
|
ID: "",
|
|
ProfilePicture: updatedProfilePicture,
|
|
},
|
|
userID: "",
|
|
svcReq: users.UserReq{
|
|
ProfilePicture: &updatedProfilePicture,
|
|
},
|
|
svcRes: users.User{},
|
|
svcErr: nil,
|
|
response: sdk.User{},
|
|
err: errors.NewSDKErrorWithStatus(apiutil.ErrMissingID, http.StatusBadRequest),
|
|
},
|
|
{
|
|
desc: "update profile picture with request that can't be marshalled",
|
|
token: validToken,
|
|
updateUserReq: sdk.User{
|
|
ID: generateUUID(t),
|
|
Metadata: map[string]any{
|
|
"test": make(chan int),
|
|
},
|
|
},
|
|
svcReq: users.UserReq{},
|
|
svcRes: users.User{},
|
|
svcErr: nil,
|
|
response: sdk.User{},
|
|
err: errors.NewSDKError(fmt.Errorf("json: unsupported type: chan int")),
|
|
},
|
|
{
|
|
desc: "update profile picture with response that can't be unmarshalled",
|
|
token: validToken,
|
|
updateUserReq: sdk.User{
|
|
ID: user.ID,
|
|
ProfilePicture: updatedProfilePicture,
|
|
},
|
|
userID: user.ID,
|
|
svcReq: users.UserReq{
|
|
ProfilePicture: &updatedProfilePicture,
|
|
},
|
|
svcRes: users.User{
|
|
ID: id,
|
|
Metadata: users.Metadata{
|
|
"key": make(chan int),
|
|
},
|
|
},
|
|
svcErr: nil,
|
|
response: sdk.User{},
|
|
err: errors.NewSDKError(fmt.Errorf("unexpected end of JSON input")),
|
|
},
|
|
}
|
|
for _, tc := range cases {
|
|
t.Run(tc.desc, func(t *testing.T) {
|
|
if tc.token == validToken {
|
|
tc.session = smqauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}
|
|
}
|
|
authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr)
|
|
svcCall := svc.On("UpdateProfilePicture", mock.Anything, tc.session, tc.userID, tc.svcReq).Return(tc.svcRes, tc.svcErr)
|
|
resp, err := mgsdk.UpdateProfilePicture(context.Background(), tc.updateUserReq, tc.token)
|
|
assert.Equal(t, tc.err, err)
|
|
assert.Equal(t, tc.response, resp)
|
|
if tc.err == nil {
|
|
ok := svcCall.Parent.AssertCalled(t, "UpdateProfilePicture", mock.Anything, tc.session, tc.userID, tc.svcReq)
|
|
assert.True(t, ok)
|
|
}
|
|
svcCall.Unset()
|
|
authCall.Unset()
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestEnableUser(t *testing.T) {
|
|
ts, svc, auth := setupUsers()
|
|
defer ts.Close()
|
|
|
|
conf := sdk.Config{
|
|
UsersURL: ts.URL,
|
|
}
|
|
mgsdk := sdk.NewSDK(conf)
|
|
|
|
enabledUser := user
|
|
enabledUser.Status = users.EnabledStatus.String()
|
|
|
|
cases := []struct {
|
|
desc string
|
|
token string
|
|
session smqauthn.Session
|
|
userID string
|
|
svcRes users.User
|
|
svcErr error
|
|
authenticateErr error
|
|
response sdk.User
|
|
err errors.SDKError
|
|
}{
|
|
{
|
|
desc: "enable user with valid token",
|
|
token: validToken,
|
|
userID: user.ID,
|
|
svcRes: convertUser(enabledUser),
|
|
svcErr: nil,
|
|
response: enabledUser,
|
|
err: nil,
|
|
},
|
|
{
|
|
desc: "enable user with invalid token",
|
|
token: invalidToken,
|
|
userID: user.ID,
|
|
svcRes: users.User{},
|
|
authenticateErr: svcerr.ErrAuthentication,
|
|
response: sdk.User{},
|
|
err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthentication, http.StatusUnauthorized),
|
|
},
|
|
{
|
|
desc: "enable user with empty token",
|
|
token: "",
|
|
userID: user.ID,
|
|
svcRes: users.User{},
|
|
svcErr: nil,
|
|
response: sdk.User{},
|
|
err: errors.NewSDKErrorWithStatus(apiutil.ErrBearerToken, http.StatusUnauthorized),
|
|
},
|
|
}
|
|
|
|
for _, tc := range cases {
|
|
t.Run(tc.desc, func(t *testing.T) {
|
|
if tc.token == validToken {
|
|
tc.session = smqauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}
|
|
}
|
|
authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr)
|
|
svcCall := svc.On("Enable", mock.Anything, tc.session, tc.userID).Return(tc.svcRes, tc.svcErr)
|
|
|
|
resp, err := mgsdk.EnableUser(context.Background(), tc.userID, tc.token)
|
|
assert.Equal(t, tc.err, err)
|
|
assert.Equal(t, tc.response, resp)
|
|
if tc.err == nil {
|
|
ok := svcCall.Parent.AssertCalled(t, "Enable", mock.Anything, tc.session, tc.userID)
|
|
assert.True(t, ok)
|
|
}
|
|
svcCall.Unset()
|
|
authCall.Unset()
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestDisableUser(t *testing.T) {
|
|
ts, svc, auth := setupUsers()
|
|
defer ts.Close()
|
|
|
|
conf := sdk.Config{
|
|
UsersURL: ts.URL,
|
|
}
|
|
mgsdk := sdk.NewSDK(conf)
|
|
|
|
disabledUser := user
|
|
disabledUser.Status = users.DisabledStatus.String()
|
|
|
|
cases := []struct {
|
|
desc string
|
|
token string
|
|
session smqauthn.Session
|
|
userID string
|
|
svcRes users.User
|
|
svcErr error
|
|
authenticateErr error
|
|
response sdk.User
|
|
err errors.SDKError
|
|
}{
|
|
{
|
|
desc: "disable user with valid token",
|
|
token: validToken,
|
|
userID: user.ID,
|
|
svcRes: convertUser(disabledUser),
|
|
svcErr: nil,
|
|
|
|
response: disabledUser,
|
|
err: nil,
|
|
},
|
|
{
|
|
desc: "disable user with invalid token",
|
|
token: invalidToken,
|
|
userID: user.ID,
|
|
svcRes: users.User{},
|
|
authenticateErr: svcerr.ErrAuthentication,
|
|
response: sdk.User{},
|
|
err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthentication, http.StatusUnauthorized),
|
|
},
|
|
{
|
|
desc: "disable user with empty token",
|
|
token: "",
|
|
userID: user.ID,
|
|
svcRes: users.User{},
|
|
svcErr: nil,
|
|
response: sdk.User{},
|
|
err: errors.NewSDKErrorWithStatus(apiutil.ErrBearerToken, http.StatusUnauthorized),
|
|
},
|
|
{
|
|
desc: "disable user with invalid id",
|
|
token: validToken,
|
|
userID: wrongID,
|
|
svcRes: users.User{},
|
|
svcErr: svcerr.ErrUpdateEntity,
|
|
response: sdk.User{},
|
|
err: errors.NewSDKErrorWithStatus(svcerr.ErrUpdateEntity, http.StatusUnprocessableEntity),
|
|
},
|
|
{
|
|
desc: "disable user with empty id",
|
|
token: validToken,
|
|
userID: "",
|
|
svcRes: users.User{},
|
|
svcErr: nil,
|
|
response: sdk.User{},
|
|
err: errors.NewSDKErrorWithStatus(apiutil.ErrMissingID, http.StatusBadRequest),
|
|
},
|
|
{
|
|
desc: "disable user with response that can't be unmarshalled",
|
|
token: validToken,
|
|
userID: user.ID,
|
|
svcRes: users.User{
|
|
ID: id,
|
|
Status: users.DisabledStatus,
|
|
Metadata: users.Metadata{
|
|
"key": make(chan int),
|
|
},
|
|
},
|
|
svcErr: nil,
|
|
response: sdk.User{},
|
|
err: errors.NewSDKError(fmt.Errorf("unexpected end of JSON input")),
|
|
},
|
|
}
|
|
for _, tc := range cases {
|
|
t.Run(tc.desc, func(t *testing.T) {
|
|
if tc.token == validToken {
|
|
tc.session = smqauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}
|
|
}
|
|
authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr)
|
|
svcCall := svc.On("Disable", mock.Anything, tc.session, tc.userID).Return(tc.svcRes, tc.svcErr)
|
|
resp, err := mgsdk.DisableUser(context.Background(), tc.userID, tc.token)
|
|
assert.Equal(t, tc.err, err)
|
|
assert.Equal(t, tc.response, resp)
|
|
if tc.err == nil {
|
|
ok := svcCall.Parent.AssertCalled(t, "Disable", mock.Anything, tc.session, tc.userID)
|
|
assert.True(t, ok)
|
|
}
|
|
svcCall.Unset()
|
|
authCall.Unset()
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestDeleteUser(t *testing.T) {
|
|
ts, svc, auth := setupUsers()
|
|
defer ts.Close()
|
|
|
|
conf := sdk.Config{
|
|
UsersURL: ts.URL,
|
|
}
|
|
mgsdk := sdk.NewSDK(conf)
|
|
|
|
cases := []struct {
|
|
desc string
|
|
token string
|
|
session smqauthn.Session
|
|
userID string
|
|
svcErr error
|
|
authenticateErr error
|
|
err errors.SDKError
|
|
}{
|
|
{
|
|
desc: "delete user successfully",
|
|
token: validToken,
|
|
userID: validID,
|
|
svcErr: nil,
|
|
err: nil,
|
|
},
|
|
{
|
|
desc: "delete user with invalid token",
|
|
token: invalidToken,
|
|
userID: validID,
|
|
authenticateErr: svcerr.ErrAuthentication,
|
|
err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthentication, http.StatusUnauthorized),
|
|
},
|
|
{
|
|
desc: "delete user with empty token",
|
|
token: "",
|
|
userID: validID,
|
|
svcErr: nil,
|
|
err: errors.NewSDKErrorWithStatus(apiutil.ErrBearerToken, http.StatusUnauthorized),
|
|
},
|
|
{
|
|
desc: "delete user with invalid id",
|
|
token: validToken,
|
|
userID: wrongID,
|
|
svcErr: svcerr.ErrRemoveEntity,
|
|
err: errors.NewSDKErrorWithStatus(svcerr.ErrRemoveEntity, http.StatusUnprocessableEntity),
|
|
},
|
|
{
|
|
desc: "delete user with empty id",
|
|
token: validToken,
|
|
userID: "",
|
|
svcErr: nil,
|
|
err: errors.NewSDKError(apiutil.ErrMissingID),
|
|
},
|
|
}
|
|
for _, tc := range cases {
|
|
t.Run(tc.desc, func(t *testing.T) {
|
|
if tc.token == validToken {
|
|
tc.session = smqauthn.Session{DomainUserID: validID, UserID: validID, DomainID: domainID}
|
|
}
|
|
authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr)
|
|
svcCall := svc.On("Delete", mock.Anything, tc.session, tc.userID).Return(tc.svcErr)
|
|
err := mgsdk.DeleteUser(context.Background(), tc.userID, tc.token)
|
|
assert.Equal(t, tc.err, err)
|
|
if tc.err == nil {
|
|
ok := svcCall.Parent.AssertCalled(t, "Delete", mock.Anything, tc.session, tc.userID)
|
|
assert.True(t, ok)
|
|
}
|
|
svcCall.Unset()
|
|
authCall.Unset()
|
|
})
|
|
}
|
|
}
|