Files
Dušan Borovčanin 61d0427898 NOISSUE - Rename to Magistrala (#3427)
Signed-off-by: dusan <borovcanindusan1@gmail.com>
2026-04-06 15:23:42 +02:00

3287 lines
96 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"
apiutil "github.com/absmach/magistrala/api/http/util"
"github.com/absmach/magistrala/clients"
api "github.com/absmach/magistrala/clients/api/http"
"github.com/absmach/magistrala/clients/mocks"
"github.com/absmach/magistrala/internal/testsutil"
mglog "github.com/absmach/magistrala/logger"
smqauthn "github.com/absmach/magistrala/pkg/authn"
authnmocks "github.com/absmach/magistrala/pkg/authn/mocks"
"github.com/absmach/magistrala/pkg/errors"
svcerr "github.com/absmach/magistrala/pkg/errors/service"
"github.com/absmach/magistrala/pkg/roles"
sdk "github.com/absmach/magistrala/pkg/sdk"
"github.com/absmach/magistrala/pkg/uuid"
"github.com/go-chi/chi/v5"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
)
var clientID = "fe6b4e92-cc98-425e-b0aa-000000000001"
func setupClients() (*httptest.Server, *mocks.Service, *authnmocks.Authentication) {
tsvc := new(mocks.Service)
logger := mglog.NewMock()
mux := chi.NewRouter()
idp := uuid.NewMock()
authn := new(authnmocks.Authentication)
am := smqauthn.NewAuthNMiddleware(authn, smqauthn.WithAllowUnverifiedUser(true))
api.MakeHandler(tsvc, am, mux, logger, "", idp)
return httptest.NewServer(mux), tsvc, authn
}
func TestCreateClient(t *testing.T) {
ts, tsvc, auth := setupClients()
defer ts.Close()
client := generateTestClient(t, false)
createClientReq := sdk.Client{
Name: client.Name,
Tags: client.Tags,
Credentials: client.Credentials,
Metadata: client.Metadata,
PrivateMetadata: client.PrivateMetadata,
Status: client.Status,
}
conf := sdk.Config{
ClientsURL: ts.URL,
}
mgsdk := sdk.NewSDK(conf)
cases := []struct {
desc string
domainID string
token string
session smqauthn.Session
createClientReq sdk.Client
svcReq clients.Client
svcRes []clients.Client
svcErr error
authenticateErr error
response sdk.Client
err errors.SDKError
}{
{
desc: "create new client successfully",
domainID: domainID,
token: validToken,
createClientReq: createClientReq,
svcReq: convertClient(createClientReq),
svcRes: []clients.Client{convertClient(client)},
svcErr: nil,
response: client,
err: nil,
},
{
desc: "create new client with invalid token",
domainID: domainID,
token: invalidToken,
createClientReq: createClientReq,
svcReq: convertClient(createClientReq),
svcRes: []clients.Client{},
authenticateErr: svcerr.ErrAuthentication,
response: sdk.Client{},
err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthentication, http.StatusUnauthorized),
},
{
desc: "create new client with empty token",
domainID: domainID,
token: "",
createClientReq: createClientReq,
svcReq: convertClient(createClientReq),
svcRes: []clients.Client{},
svcErr: nil,
response: sdk.Client{},
err: errors.NewSDKErrorWithStatus(apiutil.ErrBearerToken, http.StatusUnauthorized),
},
{
desc: "create an existing client",
domainID: domainID,
token: validToken,
createClientReq: createClientReq,
svcReq: convertClient(createClientReq),
svcRes: []clients.Client{},
svcErr: svcerr.ErrCreateEntity,
response: sdk.Client{},
err: errors.NewSDKErrorWithStatus(svcerr.ErrCreateEntity, http.StatusUnprocessableEntity),
},
{
desc: "create a client with name too long",
domainID: domainID,
token: validToken,
createClientReq: sdk.Client{
Name: strings.Repeat("a", 1025),
Tags: client.Tags,
Credentials: client.Credentials,
PrivateMetadata: client.PrivateMetadata,
Metadata: client.Metadata,
Status: client.Status,
},
svcReq: clients.Client{},
svcRes: []clients.Client{},
svcErr: nil,
response: sdk.Client{},
err: errors.NewSDKErrorWithStatus(apiutil.ErrNameSize, http.StatusBadRequest),
},
{
desc: "create a client with invalid id",
domainID: domainID,
token: validToken,
createClientReq: sdk.Client{
ID: "123456789",
Name: client.Name,
Tags: client.Tags,
Credentials: client.Credentials,
PrivateMetadata: client.PrivateMetadata,
Metadata: client.Metadata,
Status: client.Status,
},
svcReq: clients.Client{},
svcRes: []clients.Client{},
svcErr: nil,
response: sdk.Client{},
err: errors.NewSDKErrorWithStatus(apiutil.ErrInvalidIDFormat, http.StatusBadRequest),
},
{
desc: "create a client with a request that can't be marshalled",
domainID: domainID,
token: validToken,
createClientReq: sdk.Client{
Name: valid,
PrivateMetadata: map[string]any{
valid: make(chan int),
},
},
svcReq: clients.Client{},
svcRes: []clients.Client{},
svcErr: nil,
response: sdk.Client{},
err: errors.NewSDKError(fmt.Errorf("json: unsupported type: chan int")),
},
{
desc: "create a client with a response that can't be unmarshalled",
domainID: domainID,
token: validToken,
createClientReq: createClientReq,
svcReq: convertClient(createClientReq),
svcRes: []clients.Client{{
Name: client.Name,
Tags: client.Tags,
Credentials: clients.Credentials(client.Credentials),
PrivateMetadata: clients.Metadata{
"test": make(chan int),
},
}},
svcErr: nil,
response: sdk.Client{},
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: domainID + "_" + validID, UserID: validID, DomainID: domainID}
}
authCall := auth.On("Authenticate", mock.Anything, mock.Anything).Return(tc.session, tc.authenticateErr)
svcCall := tsvc.On("CreateClients", mock.Anything, tc.session, []clients.Client{tc.svcReq}).Return(tc.svcRes, []roles.RoleProvision{}, tc.svcErr)
resp, err := mgsdk.CreateClient(context.Background(), tc.createClientReq, tc.domainID, tc.token)
assert.Equal(t, tc.err, err)
assert.Equal(t, tc.response, resp)
if tc.err == nil {
ok := svcCall.Parent.AssertCalled(t, "CreateClients", mock.Anything, tc.session, []clients.Client{tc.svcReq})
assert.True(t, ok)
}
svcCall.Unset()
authCall.Unset()
})
}
}
func TestCreateClients(t *testing.T) {
ts, tsvc, auth := setupClients()
defer ts.Close()
sdkClients := []sdk.Client{}
for i := 0; i < 3; i++ {
client := generateTestClient(t, false)
sdkClients = append(sdkClients, client)
}
conf := sdk.Config{
ClientsURL: ts.URL,
}
mgsdk := sdk.NewSDK(conf)
cases := []struct {
desc string
domainID string
token string
session smqauthn.Session
createClientsRequest []sdk.Client
svcReq []clients.Client
svcRes []clients.Client
svcErr error
authenticateErr error
response []sdk.Client
err errors.SDKError
}{
{
desc: "create new clients successfully",
domainID: domainID,
token: validToken,
createClientsRequest: sdkClients,
svcReq: convertClients(sdkClients...),
svcRes: convertClients(sdkClients...),
svcErr: nil,
response: sdkClients,
err: nil,
},
{
desc: "create new clients with invalid token",
domainID: domainID,
token: invalidToken,
createClientsRequest: sdkClients,
svcReq: convertClients(sdkClients...),
svcRes: []clients.Client{},
authenticateErr: svcerr.ErrAuthentication,
response: []sdk.Client{},
err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthentication, http.StatusUnauthorized),
},
{
desc: "create new clients with empty token",
domainID: domainID,
token: "",
createClientsRequest: sdkClients,
svcReq: convertClients(sdkClients...),
svcRes: []clients.Client{},
svcErr: nil,
response: []sdk.Client{},
err: errors.NewSDKErrorWithStatus(apiutil.ErrBearerToken, http.StatusUnauthorized),
},
{
desc: "create new clients with a request that can't be marshalled",
domainID: domainID,
token: validToken,
createClientsRequest: []sdk.Client{{Name: "test", PrivateMetadata: map[string]any{"test": make(chan int)}}},
svcReq: convertClients(sdkClients...),
svcRes: []clients.Client{},
svcErr: nil,
response: []sdk.Client{},
err: errors.NewSDKError(fmt.Errorf("json: unsupported type: chan int")),
},
{
desc: "create new clients with a response that can't be unmarshalled",
domainID: domainID,
token: validToken,
createClientsRequest: sdkClients,
svcReq: convertClients(sdkClients...),
svcRes: []clients.Client{{
Name: sdkClients[0].Name,
Tags: sdkClients[0].Tags,
Credentials: clients.Credentials(sdkClients[0].Credentials),
PrivateMetadata: clients.Metadata{
"test": make(chan int),
},
}},
svcErr: nil,
response: []sdk.Client{},
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: domainID + "_" + validID, UserID: validID, DomainID: domainID}
}
authCall := auth.On("Authenticate", mock.Anything, mock.Anything).Return(tc.session, tc.authenticateErr)
svcCall := tsvc.On("CreateClients", mock.Anything, tc.session, tc.svcReq).Return(tc.svcRes, []roles.RoleProvision{}, tc.svcErr)
resp, err := mgsdk.CreateClients(context.Background(), tc.createClientsRequest, tc.domainID, tc.token)
assert.Equal(t, tc.err, err)
assert.Equal(t, tc.response, resp)
if tc.err == nil {
ok := svcCall.Parent.AssertCalled(t, "CreateClients", mock.Anything, tc.session, tc.svcReq)
assert.True(t, ok)
}
svcCall.Unset()
authCall.Unset()
})
}
}
func TestListClients(t *testing.T) {
ts, tsvc, auth := setupClients()
defer ts.Close()
var sdkClients []sdk.Client
for i := 10; i < 100; i++ {
c := generateTestClient(t, false)
if i == 50 {
c.Status = clients.DisabledStatus.String()
c.Tags = []string{"tag1", "tag2"}
}
sdkClients = append(sdkClients, c)
}
conf := sdk.Config{
ClientsURL: ts.URL,
}
mgsdk := sdk.NewSDK(conf)
cases := []struct {
desc string
token string
domainID string
session smqauthn.Session
pageMeta sdk.PageMetadata
svcReq clients.Page
svcRes clients.ClientsPage
svcErr error
authenticateErr error
response sdk.ClientsPage
err errors.SDKError
}{
{
desc: "list all clients successfully",
domainID: domainID,
token: validToken,
pageMeta: sdk.PageMetadata{
Offset: 0,
Limit: 100,
},
svcReq: clients.Page{
Actions: []string{},
Order: "updated_at",
Dir: "desc",
Offset: 0,
Limit: 100,
},
svcRes: clients.ClientsPage{
Page: clients.Page{
Offset: 0,
Limit: 100,
Total: uint64(len(sdkClients)),
},
Clients: convertClients(sdkClients...),
},
svcErr: nil,
response: sdk.ClientsPage{
PageRes: sdk.PageRes{
Limit: 100,
Total: uint64(len(sdkClients)),
},
Clients: sdkClients,
},
},
{
desc: "list all clients with an invalid token",
domainID: domainID,
token: invalidToken,
pageMeta: sdk.PageMetadata{
Offset: 0,
Limit: 100,
},
svcReq: clients.Page{
Actions: []string{},
Order: "updated_at",
Dir: "desc",
Offset: 0,
Limit: 100,
},
svcRes: clients.ClientsPage{},
authenticateErr: svcerr.ErrAuthentication,
response: sdk.ClientsPage{},
err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthentication, http.StatusUnauthorized),
},
{
desc: "list all clients with limit greater than max",
domainID: domainID,
token: validToken,
pageMeta: sdk.PageMetadata{
Offset: 0,
Limit: 1000,
},
svcReq: clients.Page{
Actions: []string{},
Order: "updated_at",
Dir: "desc",
},
svcRes: clients.ClientsPage{},
svcErr: nil,
response: sdk.ClientsPage{},
err: errors.NewSDKErrorWithStatus(apiutil.ErrLimitSize, http.StatusBadRequest),
},
{
desc: "list all clients with name size greater than max",
domainID: domainID,
token: validToken,
pageMeta: sdk.PageMetadata{
Offset: 0,
Limit: 100,
Name: strings.Repeat("a", 1025),
},
svcReq: clients.Page{
Actions: []string{},
Order: "updated_at",
Dir: "desc",
},
svcRes: clients.ClientsPage{},
svcErr: nil,
response: sdk.ClientsPage{},
err: errors.NewSDKErrorWithStatus(apiutil.ErrNameSize, http.StatusBadRequest),
},
{
desc: "list all clients with status",
domainID: domainID,
token: validToken,
pageMeta: sdk.PageMetadata{
Offset: 0,
Limit: 100,
Status: clients.DisabledStatus.String(),
},
svcReq: clients.Page{
Actions: []string{},
Order: "updated_at",
Dir: "desc",
Offset: 0,
Limit: 100,
Status: clients.DisabledStatus,
},
svcRes: clients.ClientsPage{
Page: clients.Page{
Offset: 0,
Limit: 100,
Total: 1,
},
Clients: convertClients(sdkClients[50]),
},
svcErr: nil,
response: sdk.ClientsPage{
PageRes: sdk.PageRes{
Limit: 100,
Total: 1,
},
Clients: []sdk.Client{sdkClients[50]},
},
err: nil,
},
{
desc: "list all clients with tags",
domainID: domainID,
token: validToken,
pageMeta: sdk.PageMetadata{
Offset: 0,
Limit: 100,
Tags: sdk.TagsQuery{Elements: []string{"tag1"}, Operator: sdk.OrOp},
},
svcReq: clients.Page{
Actions: []string{},
Order: "updated_at",
Dir: "desc",
Offset: 0,
Limit: 100,
Tags: clients.TagsQuery{Elements: []string{"tag1"}, Operator: clients.OrOp},
},
svcRes: clients.ClientsPage{
Page: clients.Page{
Offset: 0,
Limit: 100,
Total: 1,
},
Clients: convertClients(sdkClients[50]),
},
svcErr: nil,
response: sdk.ClientsPage{
PageRes: sdk.PageRes{
Limit: 100,
Total: 1,
},
Clients: []sdk.Client{sdkClients[50]},
},
err: nil,
},
{
desc: "list all clients with invalid metadata",
domainID: domainID,
token: validToken,
pageMeta: sdk.PageMetadata{
Offset: 0,
Limit: 100,
Metadata: map[string]any{
"test": make(chan int),
},
},
svcReq: clients.Page{
Actions: []string{},
Order: "updated_at",
Dir: "desc",
},
svcRes: clients.ClientsPage{},
svcErr: nil,
response: sdk.ClientsPage{},
err: errors.NewSDKError(fmt.Errorf("json: unsupported type: chan int")),
},
{
desc: "list all clients with response that can't be unmarshalled",
domainID: domainID,
token: validToken,
pageMeta: sdk.PageMetadata{
Offset: 0,
Limit: 100,
},
svcReq: clients.Page{
Actions: []string{},
Order: "updated_at",
Dir: "desc",
Offset: 0,
Limit: 100,
},
svcRes: clients.ClientsPage{
Page: clients.Page{
Offset: 0,
Limit: 100,
Total: 1,
},
Clients: []clients.Client{{
Name: sdkClients[0].Name,
Tags: sdkClients[0].Tags,
Credentials: clients.Credentials(sdkClients[0].Credentials),
PrivateMetadata: clients.Metadata{
"test": make(chan int),
},
}},
},
svcErr: nil,
response: sdk.ClientsPage{},
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: domainID + "_" + validID, UserID: validID, DomainID: domainID}
}
authCall := auth.On("Authenticate", mock.Anything, mock.Anything).Return(tc.session, tc.authenticateErr)
svcCall := tsvc.On("ListClients", mock.Anything, tc.session, tc.svcReq).Return(tc.svcRes, tc.svcErr)
resp, err := mgsdk.Clients(context.Background(), tc.pageMeta, tc.domainID, tc.token)
assert.Equal(t, tc.err, err)
assert.Equal(t, tc.response, resp)
if tc.err == nil {
ok := svcCall.Parent.AssertCalled(t, "ListClients", mock.Anything, tc.session, tc.svcReq)
assert.True(t, ok)
}
svcCall.Unset()
authCall.Unset()
})
}
}
func TestViewClient(t *testing.T) {
ts, tsvc, auth := setupClients()
defer ts.Close()
sdkClient := generateTestClient(t, false)
sdkClientWithRoles := generateTestClient(t, true)
conf := sdk.Config{
ClientsURL: ts.URL,
}
mgsdk := sdk.NewSDK(conf)
confRoles := sdk.Config{
ClientsURL: ts.URL,
Roles: true,
}
mgsdkRoles := sdk.NewSDK(confRoles)
cases := []struct {
desc string
domainID string
token string
session smqauthn.Session
withRoles bool
clientID string
svcRes clients.Client
svcErr error
authenticateErr error
response sdk.Client
err errors.SDKError
}{
{
desc: "view client successfully",
domainID: domainID,
token: validToken,
withRoles: false,
clientID: sdkClient.ID,
svcRes: convertClient(sdkClient),
svcErr: nil,
response: sdkClient,
err: nil,
},
{
desc: "view client successfully with roles",
domainID: domainID,
token: validToken,
withRoles: true,
clientID: sdkClientWithRoles.ID,
svcRes: convertClient(sdkClientWithRoles),
svcErr: nil,
response: sdkClientWithRoles,
err: nil,
},
{
desc: "view client with an invalid token",
domainID: domainID,
token: invalidToken,
withRoles: false,
clientID: sdkClient.ID,
svcRes: clients.Client{},
authenticateErr: svcerr.ErrAuthorization,
response: sdk.Client{},
err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusUnauthorized),
},
{
desc: "view client with empty token",
domainID: domainID,
token: "",
withRoles: false,
clientID: sdkClient.ID,
svcRes: clients.Client{},
svcErr: nil,
response: sdk.Client{},
err: errors.NewSDKErrorWithStatus(apiutil.ErrBearerToken, http.StatusUnauthorized),
},
{
desc: "view client with an invalid client id",
domainID: domainID,
token: validToken,
withRoles: false,
clientID: wrongID,
svcRes: clients.Client{},
svcErr: svcerr.ErrNotFound,
response: sdk.Client{},
err: errors.NewSDKErrorWithStatus(svcerr.ErrNotFound, http.StatusNotFound),
},
{
desc: "view client with empty client id",
domainID: domainID,
token: validToken,
withRoles: false,
clientID: "",
svcRes: clients.Client{},
svcErr: nil,
response: sdk.Client{},
err: errors.NewSDKError(apiutil.ErrMissingID),
},
{
desc: "view client with response that can't be unmarshalled",
domainID: domainID,
token: validToken,
withRoles: false,
clientID: sdkClient.ID,
svcRes: clients.Client{
Name: sdkClient.Name,
Tags: sdkClient.Tags,
Credentials: clients.Credentials(sdkClient.Credentials),
PrivateMetadata: clients.Metadata{
"test": make(chan int),
},
},
svcErr: nil,
response: sdk.Client{},
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: domainID + "_" + validID, UserID: validID, DomainID: domainID}
}
authCall := auth.On("Authenticate", mock.Anything, mock.Anything).Return(tc.session, tc.authenticateErr)
svcCall := tsvc.On("View", mock.Anything, tc.session, tc.clientID, tc.withRoles).Return(tc.svcRes, tc.svcErr)
var resp sdk.Client
var err error
switch tc.withRoles {
case true:
resp, err = mgsdkRoles.Client(context.Background(), tc.clientID, tc.domainID, tc.token)
default:
resp, err = mgsdk.Client(context.Background(), tc.clientID, tc.domainID, tc.token)
}
assert.Equal(t, tc.err, err)
assert.Equal(t, tc.response, resp)
if tc.withRoles {
assert.Equal(t, resp.Roles, validRoles, fmt.Sprintf("%s: expected %v got %v\n", tc.desc, validRoles, resp.Roles))
}
if tc.err == nil {
ok := svcCall.Parent.AssertCalled(t, "View", mock.Anything, tc.session, tc.clientID, tc.withRoles)
assert.True(t, ok)
}
svcCall.Unset()
authCall.Unset()
})
}
}
func TestUpdateClient(t *testing.T) {
ts, tsvc, auth := setupClients()
defer ts.Close()
sdkClient := generateTestClient(t, false)
updatedClient := sdkClient
updatedClient.Name = "newName"
updatedClient.Metadata = map[string]any{
"newKey": "newValue",
}
updatedClient.PrivateMetadata = map[string]any{
"privateKey": "privateValue",
}
updateClientReq := sdk.Client{
ID: sdkClient.ID,
Name: updatedClient.Name,
Metadata: updatedClient.Metadata,
PrivateMetadata: updatedClient.PrivateMetadata,
}
conf := sdk.Config{
ClientsURL: ts.URL,
}
mgsdk := sdk.NewSDK(conf)
cases := []struct {
desc string
domainID string
token string
session smqauthn.Session
updateClientReq sdk.Client
svcReq clients.Client
svcRes clients.Client
svcErr error
authenticateErr error
response sdk.Client
err errors.SDKError
}{
{
desc: "update client successfully",
domainID: domainID,
token: validToken,
updateClientReq: updateClientReq,
svcReq: convertClient(updateClientReq),
svcRes: convertClient(updatedClient),
svcErr: nil,
response: updatedClient,
err: nil,
},
{
desc: "update client with an invalid token",
domainID: domainID,
token: invalidToken,
updateClientReq: updateClientReq,
svcReq: convertClient(updateClientReq),
svcRes: clients.Client{},
authenticateErr: svcerr.ErrAuthorization,
response: sdk.Client{},
err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusUnauthorized),
},
{
desc: "update client with empty token",
domainID: domainID,
token: "",
updateClientReq: updateClientReq,
svcReq: convertClient(updateClientReq),
svcRes: clients.Client{},
svcErr: nil,
response: sdk.Client{},
err: errors.NewSDKErrorWithStatus(apiutil.ErrBearerToken, http.StatusUnauthorized),
},
{
desc: "update client with an invalid client id",
domainID: domainID,
token: validToken,
updateClientReq: sdk.Client{
ID: wrongID,
Name: updatedClient.Name,
},
svcReq: convertClient(sdk.Client{
ID: wrongID,
Name: updatedClient.Name,
}),
svcRes: clients.Client{},
svcErr: svcerr.ErrUpdateEntity,
response: sdk.Client{},
err: errors.NewSDKErrorWithStatus(svcerr.ErrUpdateEntity, http.StatusUnprocessableEntity),
},
{
desc: "update client with empty client id",
domainID: domainID,
token: validToken,
updateClientReq: sdk.Client{
ID: "",
Name: updatedClient.Name,
},
svcReq: convertClient(sdk.Client{
ID: "",
Name: updatedClient.Name,
}),
svcRes: clients.Client{},
svcErr: nil,
response: sdk.Client{},
err: errors.NewSDKError(apiutil.ErrMissingID),
},
{
desc: "update client with a request that can't be marshalled",
domainID: domainID,
token: validToken,
updateClientReq: sdk.Client{
ID: valid,
Metadata: map[string]any{
"test": make(chan int),
},
},
svcReq: clients.Client{},
svcRes: clients.Client{},
svcErr: nil,
response: sdk.Client{},
err: errors.NewSDKError(fmt.Errorf("json: unsupported type: chan int")),
},
{
desc: "update client with a response that can't be unmarshalled",
domainID: domainID,
token: validToken,
updateClientReq: updateClientReq,
svcReq: convertClient(updateClientReq),
svcRes: clients.Client{
Name: updatedClient.Name,
Tags: updatedClient.Tags,
Credentials: clients.Credentials(updatedClient.Credentials),
Metadata: clients.Metadata{
"test": make(chan int),
},
},
svcErr: nil,
response: sdk.Client{},
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: domainID + "_" + validID, UserID: validID, DomainID: domainID}
}
authCall := auth.On("Authenticate", mock.Anything, mock.Anything).Return(tc.session, tc.authenticateErr)
svcCall := tsvc.On("Update", mock.Anything, tc.session, tc.svcReq).Return(tc.svcRes, tc.svcErr)
resp, err := mgsdk.UpdateClient(context.Background(), tc.updateClientReq, tc.domainID, 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.svcReq)
assert.True(t, ok)
}
svcCall.Unset()
authCall.Unset()
})
}
}
func TestUpdateClientTags(t *testing.T) {
ts, tsvc, auth := setupClients()
defer ts.Close()
sdkClient := generateTestClient(t, false)
updatedClient := sdkClient
updatedClient.Tags = []string{"newTag1", "newTag2"}
updateClientReq := sdk.Client{
ID: sdkClient.ID,
Tags: updatedClient.Tags,
}
conf := sdk.Config{
ClientsURL: ts.URL,
}
mgsdk := sdk.NewSDK(conf)
cases := []struct {
desc string
domainID string
token string
session smqauthn.Session
updateClientReq sdk.Client
svcReq clients.Client
svcRes clients.Client
svcErr error
authenticateErr error
response sdk.Client
err errors.SDKError
}{
{
desc: "update client tags successfully",
domainID: domainID,
token: validToken,
updateClientReq: updateClientReq,
svcReq: convertClient(updateClientReq),
svcRes: convertClient(updatedClient),
svcErr: nil,
response: updatedClient,
err: nil,
},
{
desc: "update client tags with an invalid token",
domainID: domainID,
token: invalidToken,
updateClientReq: updateClientReq,
svcReq: convertClient(updateClientReq),
svcRes: clients.Client{},
authenticateErr: svcerr.ErrAuthorization,
response: sdk.Client{},
err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusUnauthorized),
},
{
desc: "update client tags with empty token",
domainID: domainID,
token: "",
updateClientReq: updateClientReq,
svcReq: convertClient(updateClientReq),
svcRes: clients.Client{},
svcErr: nil,
response: sdk.Client{},
err: errors.NewSDKErrorWithStatus(apiutil.ErrBearerToken, http.StatusUnauthorized),
},
{
desc: "update client tags with an invalid client id",
domainID: domainID,
token: validToken,
updateClientReq: sdk.Client{
ID: wrongID,
Tags: updatedClient.Tags,
},
svcReq: convertClient(sdk.Client{
ID: wrongID,
Tags: updatedClient.Tags,
}),
svcRes: clients.Client{},
svcErr: svcerr.ErrUpdateEntity,
response: sdk.Client{},
err: errors.NewSDKErrorWithStatus(svcerr.ErrUpdateEntity, http.StatusUnprocessableEntity),
},
{
desc: "update client tags with empty client id",
domainID: domainID,
token: validToken,
updateClientReq: sdk.Client{
ID: "",
Tags: updatedClient.Tags,
},
svcReq: convertClient(sdk.Client{
ID: "",
Tags: updatedClient.Tags,
}),
svcRes: clients.Client{},
svcErr: nil,
response: sdk.Client{},
err: errors.NewSDKErrorWithStatus(apiutil.ErrMissingID, http.StatusBadRequest),
},
{
desc: "update client tags with a request that can't be marshalled",
domainID: domainID,
token: validToken,
updateClientReq: sdk.Client{
ID: valid,
Metadata: map[string]any{
"test": make(chan int),
},
},
svcReq: clients.Client{},
svcRes: clients.Client{},
svcErr: nil,
response: sdk.Client{},
err: errors.NewSDKError(fmt.Errorf("json: unsupported type: chan int")),
},
{
desc: "update client tags with a response that can't be unmarshalled",
domainID: domainID,
token: validToken,
updateClientReq: updateClientReq,
svcReq: convertClient(updateClientReq),
svcRes: clients.Client{
Name: updatedClient.Name,
Tags: updatedClient.Tags,
Credentials: clients.Credentials(updatedClient.Credentials),
Metadata: clients.Metadata{
"test": make(chan int),
},
},
svcErr: nil,
response: sdk.Client{},
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: domainID + "_" + validID, UserID: validID, DomainID: domainID}
}
authCall := auth.On("Authenticate", mock.Anything, mock.Anything).Return(tc.session, tc.authenticateErr)
svcCall := tsvc.On("UpdateTags", mock.Anything, tc.session, tc.svcReq).Return(tc.svcRes, tc.svcErr)
resp, err := mgsdk.UpdateClientTags(context.Background(), tc.updateClientReq, tc.domainID, 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.svcReq)
assert.True(t, ok)
}
svcCall.Unset()
authCall.Unset()
})
}
}
func TestUpdateClientSecret(t *testing.T) {
ts, tsvc, auth := setupClients()
defer ts.Close()
sdkClient := generateTestClient(t, false)
newSecret := generateUUID(t)
updatedClient := sdkClient
updatedClient.Credentials.Secret = newSecret
conf := sdk.Config{
ClientsURL: ts.URL,
}
mgsdk := sdk.NewSDK(conf)
cases := []struct {
desc string
domainID string
token string
session smqauthn.Session
clientID string
newSecret string
svcRes clients.Client
svcErr error
authenticateErr error
response sdk.Client
err errors.SDKError
}{
{
desc: "update client secret successfully",
domainID: domainID,
token: validToken,
clientID: sdkClient.ID,
newSecret: newSecret,
svcRes: convertClient(updatedClient),
svcErr: nil,
response: updatedClient,
err: nil,
},
{
desc: "update client secret with an invalid token",
domainID: domainID,
token: invalidToken,
clientID: sdkClient.ID,
newSecret: newSecret,
svcRes: clients.Client{},
authenticateErr: svcerr.ErrAuthorization,
response: sdk.Client{},
err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusUnauthorized),
},
{
desc: "update client secret with empty token",
domainID: domainID,
token: "",
clientID: sdkClient.ID,
newSecret: newSecret,
svcRes: clients.Client{},
svcErr: nil,
response: sdk.Client{},
err: errors.NewSDKErrorWithStatus(apiutil.ErrBearerToken, http.StatusUnauthorized),
},
{
desc: "update client secret with an invalid client id",
domainID: domainID,
token: validToken,
clientID: wrongID,
newSecret: newSecret,
svcRes: clients.Client{},
svcErr: svcerr.ErrUpdateEntity,
response: sdk.Client{},
err: errors.NewSDKErrorWithStatus(svcerr.ErrUpdateEntity, http.StatusUnprocessableEntity),
},
{
desc: "update client secret with empty client id",
domainID: domainID,
token: validToken,
clientID: "",
newSecret: newSecret,
svcRes: clients.Client{},
svcErr: nil,
response: sdk.Client{},
err: errors.NewSDKErrorWithStatus(apiutil.ErrMissingID, http.StatusBadRequest),
},
{
desc: "update client with empty new secret",
domainID: domainID,
token: validToken,
clientID: sdkClient.ID,
newSecret: "",
svcRes: clients.Client{},
svcErr: nil,
response: sdk.Client{},
err: errors.NewSDKErrorWithStatus(apiutil.ErrMissingSecret, http.StatusBadRequest),
},
{
desc: "update client secret with a response that can't be unmarshalled",
domainID: domainID,
token: validToken,
clientID: sdkClient.ID,
newSecret: newSecret,
svcRes: clients.Client{
Name: updatedClient.Name,
Tags: updatedClient.Tags,
Credentials: clients.Credentials(updatedClient.Credentials),
Metadata: clients.Metadata{
"test": make(chan int),
},
},
svcErr: nil,
response: sdk.Client{},
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: domainID + "_" + validID, UserID: validID, DomainID: domainID}
}
authCall := auth.On("Authenticate", mock.Anything, mock.Anything).Return(tc.session, tc.authenticateErr)
svcCall := tsvc.On("UpdateSecret", mock.Anything, tc.session, tc.clientID, tc.newSecret).Return(tc.svcRes, tc.svcErr)
resp, err := mgsdk.UpdateClientSecret(context.Background(), tc.clientID, tc.newSecret, tc.domainID, 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.clientID, tc.newSecret)
assert.True(t, ok)
}
svcCall.Unset()
authCall.Unset()
})
}
}
func TestEnableClient(t *testing.T) {
ts, tsvc, auth := setupClients()
defer ts.Close()
client := generateTestClient(t, false)
enabledClient := client
enabledClient.Status = clients.EnabledStatus.String()
conf := sdk.Config{
ClientsURL: ts.URL,
}
mgsdk := sdk.NewSDK(conf)
cases := []struct {
desc string
domainID string
token string
session smqauthn.Session
clientID string
svcRes clients.Client
svcErr error
authenticateErr error
response sdk.Client
err errors.SDKError
}{
{
desc: "enable client successfully",
domainID: domainID,
token: validToken,
clientID: client.ID,
svcRes: convertClient(enabledClient),
svcErr: nil,
response: enabledClient,
err: nil,
},
{
desc: "enable client with an invalid token",
domainID: domainID,
token: invalidToken,
clientID: client.ID,
svcRes: clients.Client{},
authenticateErr: svcerr.ErrAuthorization,
response: sdk.Client{},
err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusUnauthorized),
},
{
desc: "enable client with an invalid client id",
domainID: domainID,
token: validToken,
clientID: wrongID,
svcRes: clients.Client{},
svcErr: svcerr.ErrEnableClient,
response: sdk.Client{},
err: errors.NewSDKErrorWithStatus(svcerr.ErrEnableClient, http.StatusUnprocessableEntity),
},
{
desc: "enable client with empty client id",
domainID: domainID,
token: validToken,
clientID: "",
svcRes: clients.Client{},
svcErr: nil,
response: sdk.Client{},
err: errors.NewSDKErrorWithStatus(apiutil.ErrMissingID, http.StatusBadRequest),
},
{
desc: "enable client with a response that can't be unmarshalled",
domainID: domainID,
token: validToken,
clientID: client.ID,
svcRes: clients.Client{
Name: enabledClient.Name,
Tags: enabledClient.Tags,
Credentials: clients.Credentials(enabledClient.Credentials),
Metadata: clients.Metadata{
"test": make(chan int),
},
},
svcErr: nil,
response: sdk.Client{},
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: domainID + "_" + validID, UserID: validID, DomainID: domainID}
}
authCall := auth.On("Authenticate", mock.Anything, mock.Anything).Return(tc.session, tc.authenticateErr)
svcCall := tsvc.On("Enable", mock.Anything, tc.session, tc.clientID).Return(tc.svcRes, tc.svcErr)
resp, err := mgsdk.EnableClient(context.Background(), tc.clientID, tc.domainID, 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.clientID)
assert.True(t, ok)
}
svcCall.Unset()
authCall.Unset()
})
}
}
func TestDisableClient(t *testing.T) {
ts, tsvc, auth := setupClients()
defer ts.Close()
client := generateTestClient(t, false)
disabledClient := client
disabledClient.Status = clients.DisabledStatus.String()
conf := sdk.Config{
ClientsURL: ts.URL,
}
mgsdk := sdk.NewSDK(conf)
cases := []struct {
desc string
domainID string
token string
session smqauthn.Session
clientID string
svcRes clients.Client
svcErr error
authenticateErr error
response sdk.Client
err errors.SDKError
}{
{
desc: "disable client successfully",
domainID: domainID,
token: validToken,
clientID: client.ID,
svcRes: convertClient(disabledClient),
svcErr: nil,
response: disabledClient,
err: nil,
},
{
desc: "disable client with an invalid token",
domainID: domainID,
token: invalidToken,
clientID: client.ID,
svcRes: clients.Client{},
authenticateErr: svcerr.ErrAuthorization,
response: sdk.Client{},
err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusUnauthorized),
},
{
desc: "disable client with an invalid client id",
domainID: domainID,
token: validToken,
clientID: wrongID,
svcRes: clients.Client{},
svcErr: svcerr.ErrDisableClient,
response: sdk.Client{},
err: errors.NewSDKErrorWithStatus(svcerr.ErrDisableClient, http.StatusUnprocessableEntity),
},
{
desc: "disable client with empty client id",
domainID: domainID,
token: validToken,
clientID: "",
svcRes: clients.Client{},
svcErr: nil,
response: sdk.Client{},
err: errors.NewSDKErrorWithStatus(apiutil.ErrMissingID, http.StatusBadRequest),
},
{
desc: "disable client with a response that can't be unmarshalled",
domainID: domainID,
token: validToken,
clientID: client.ID,
svcRes: clients.Client{
Name: disabledClient.Name,
Tags: disabledClient.Tags,
Credentials: clients.Credentials(disabledClient.Credentials),
Metadata: clients.Metadata{
"test": make(chan int),
},
},
svcErr: nil,
response: sdk.Client{},
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: domainID + "_" + validID, UserID: validID, DomainID: domainID}
}
authCall := auth.On("Authenticate", mock.Anything, mock.Anything).Return(tc.session, tc.authenticateErr)
svcCall := tsvc.On("Disable", mock.Anything, tc.session, tc.clientID).Return(tc.svcRes, tc.svcErr)
resp, err := mgsdk.DisableClient(context.Background(), tc.clientID, tc.domainID, 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.clientID)
assert.True(t, ok)
}
svcCall.Unset()
authCall.Unset()
})
}
}
func TestDeleteClient(t *testing.T) {
ts, tsvc, auth := setupClients()
defer ts.Close()
client := generateTestClient(t, false)
conf := sdk.Config{
ClientsURL: ts.URL,
}
mgsdk := sdk.NewSDK(conf)
cases := []struct {
desc string
domainID string
token string
session smqauthn.Session
clientID string
svcErr error
authenticateErr error
err errors.SDKError
}{
{
desc: "delete client successfully",
domainID: domainID,
token: validToken,
clientID: client.ID,
svcErr: nil,
err: nil,
},
{
desc: "delete client with an invalid token",
domainID: domainID,
token: invalidToken,
clientID: client.ID,
authenticateErr: svcerr.ErrAuthorization,
err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusUnauthorized),
},
{
desc: "delete client with empty token",
domainID: domainID,
token: "",
clientID: client.ID,
svcErr: svcerr.ErrAuthentication,
err: errors.NewSDKErrorWithStatus(apiutil.ErrBearerToken, http.StatusUnauthorized),
},
{
desc: "delete client with an invalid client id",
domainID: domainID,
token: validToken,
clientID: wrongID,
svcErr: svcerr.ErrRemoveEntity,
err: errors.NewSDKErrorWithStatus(svcerr.ErrRemoveEntity, http.StatusUnprocessableEntity),
},
{
desc: "delete client with empty client id",
domainID: domainID,
token: validToken,
clientID: "",
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: domainID + "_" + validID, UserID: validID, DomainID: domainID}
}
authCall := auth.On("Authenticate", mock.Anything, mock.Anything).Return(tc.session, tc.authenticateErr)
svcCall := tsvc.On("Delete", mock.Anything, tc.session, tc.clientID).Return(tc.svcErr)
err := mgsdk.DeleteClient(context.Background(), tc.clientID, tc.domainID, tc.token)
assert.Equal(t, tc.err, err)
if tc.err == nil {
ok := svcCall.Parent.AssertCalled(t, "Delete", mock.Anything, tc.session, tc.clientID)
assert.True(t, ok)
}
svcCall.Unset()
authCall.Unset()
})
}
}
func TestSetClientParent(t *testing.T) {
ts, csvc, auth := setupClients()
defer ts.Close()
conf := sdk.Config{
ClientsURL: ts.URL,
}
mgsdk := sdk.NewSDK(conf)
parentID := testsutil.GenerateUUID(t)
cases := []struct {
desc string
domainID string
token string
session smqauthn.Session
clientID string
parentID string
svcErr error
authenticateErr error
err errors.SDKError
}{
{
desc: "set client parent successfully",
domainID: domainID,
token: validToken,
clientID: clientID,
parentID: parentID,
svcErr: nil,
err: nil,
},
{
desc: "set client parent with invalid token",
domainID: domainID,
token: invalidToken,
clientID: clientID,
parentID: parentID,
authenticateErr: svcerr.ErrAuthentication,
err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthentication, http.StatusUnauthorized),
},
{
desc: "set client parent with empty token",
domainID: domainID,
token: "",
clientID: clientID,
parentID: parentID,
err: errors.NewSDKErrorWithStatus(apiutil.ErrBearerToken, http.StatusUnauthorized),
},
{
desc: "set client parent with invalid client id",
domainID: domainID,
token: validToken,
clientID: wrongID,
parentID: parentID,
svcErr: svcerr.ErrAuthorization,
err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden),
},
{
desc: "set client parent with empty client id",
domainID: domainID,
token: validToken,
clientID: "",
parentID: parentID,
svcErr: nil,
err: errors.NewSDKErrorWithStatus(apiutil.ErrMissingID, http.StatusBadRequest),
},
{
desc: "set client parent with empty parent id",
domainID: domainID,
token: validToken,
clientID: clientID,
parentID: "",
svcErr: nil,
err: errors.NewSDKErrorWithStatus(apiutil.ErrMissingParentGroupID, http.StatusBadRequest),
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
if tc.token == validToken {
tc.session = smqauthn.Session{DomainUserID: domainID + "_" + validID, UserID: validID, DomainID: domainID}
}
authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr)
svcCall := csvc.On("SetParentGroup", mock.Anything, tc.session, tc.parentID, tc.clientID).Return(tc.svcErr)
err := mgsdk.SetClientParent(context.Background(), tc.clientID, tc.domainID, tc.parentID, tc.token)
assert.Equal(t, tc.err, err)
if tc.err == nil {
ok := svcCall.Parent.AssertCalled(t, "SetParentGroup", mock.Anything, tc.session, tc.parentID, tc.clientID)
assert.True(t, ok)
}
svcCall.Unset()
authCall.Unset()
})
}
}
func TestRemoveClientParent(t *testing.T) {
ts, csvc, auth := setupClients()
defer ts.Close()
conf := sdk.Config{
ClientsURL: ts.URL,
}
mgsdk := sdk.NewSDK(conf)
parentID := testsutil.GenerateUUID(t)
cases := []struct {
desc string
domainID string
token string
session smqauthn.Session
clientID string
parentID string
svcErr error
authenticateErr error
err errors.SDKError
}{
{
desc: "remove client parent successfully",
domainID: domainID,
token: validToken,
clientID: clientID,
parentID: parentID,
svcErr: nil,
err: nil,
},
{
desc: "remove client parent with invalid token",
domainID: domainID,
token: invalidToken,
clientID: clientID,
parentID: parentID,
authenticateErr: svcerr.ErrAuthentication,
err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthentication, http.StatusUnauthorized),
},
{
desc: "remove client parent with empty token",
domainID: domainID,
token: "",
clientID: clientID,
parentID: parentID,
err: errors.NewSDKErrorWithStatus(apiutil.ErrBearerToken, http.StatusUnauthorized),
},
{
desc: "remove client parent with invalid client id",
domainID: domainID,
token: validToken,
clientID: wrongID,
parentID: parentID,
svcErr: svcerr.ErrAuthorization,
err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden),
},
{
desc: "remove client parent with empty client id",
domainID: domainID,
token: validToken,
clientID: "",
parentID: parentID,
svcErr: nil,
err: errors.NewSDKErrorWithStatus(apiutil.ErrMissingID, http.StatusBadRequest),
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
if tc.token == validToken {
tc.session = smqauthn.Session{DomainUserID: domainID + "_" + validID, UserID: validID, DomainID: domainID}
}
authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr)
svcCall := csvc.On("RemoveParentGroup", mock.Anything, tc.session, tc.clientID).Return(tc.svcErr)
err := mgsdk.RemoveClientParent(context.Background(), tc.clientID, tc.domainID, tc.parentID, tc.token)
assert.Equal(t, tc.err, err)
if tc.err == nil {
ok := svcCall.Parent.AssertCalled(t, "RemoveParentGroup", mock.Anything, tc.session, tc.clientID)
assert.True(t, ok)
}
svcCall.Unset()
authCall.Unset()
})
}
}
func TestCreateClientRole(t *testing.T) {
ts, csvc, auth := setupClients()
defer ts.Close()
conf := sdk.Config{
ClientsURL: ts.URL,
}
mgsdk := sdk.NewSDK(conf)
optionalActions := []string{"create", "update"}
optionalMembers := []string{testsutil.GenerateUUID(t), testsutil.GenerateUUID(t)}
rReq := sdk.RoleReq{
RoleName: roleName,
OptionalActions: optionalActions,
OptionalMembers: optionalMembers,
}
userID := testsutil.GenerateUUID(t)
now := time.Now().UTC()
role := roles.Role{
ID: testsutil.GenerateUUID(t),
Name: rReq.RoleName,
EntityID: clientID,
CreatedBy: userID,
CreatedAt: now,
}
roleProvision := roles.RoleProvision{
Role: role,
OptionalActions: optionalActions,
OptionalMembers: optionalMembers,
}
cases := []struct {
desc string
token string
session smqauthn.Session
domainID string
clientID string
roleReq sdk.RoleReq
svcRes roles.RoleProvision
svcErr error
authenticateErr error
response sdk.Role
err errors.SDKError
}{
{
desc: "create client role successfully",
token: validToken,
domainID: domainID,
clientID: clientID,
roleReq: rReq,
svcRes: roleProvision,
svcErr: nil,
response: convertRoleProvision(roleProvision),
err: nil,
},
{
desc: "create client role with invalid token",
token: invalidToken,
domainID: domainID,
clientID: clientID,
roleReq: rReq,
svcRes: roles.RoleProvision{},
authenticateErr: svcerr.ErrAuthentication,
response: sdk.Role{},
err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthentication, http.StatusUnauthorized),
},
{
desc: "create client role with empty token",
token: "",
domainID: domainID,
clientID: clientID,
roleReq: rReq,
svcRes: roles.RoleProvision{},
response: sdk.Role{},
err: errors.NewSDKErrorWithStatus(apiutil.ErrBearerToken, http.StatusUnauthorized),
},
{
desc: "create client role with invalid client id",
token: validToken,
domainID: domainID,
clientID: testsutil.GenerateUUID(t),
roleReq: rReq,
svcRes: roles.RoleProvision{},
svcErr: svcerr.ErrAuthorization,
response: sdk.Role{},
err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden),
},
{
desc: "create client role with empty client id",
token: validToken,
domainID: domainID,
clientID: "",
roleReq: rReq,
svcRes: roles.RoleProvision{},
svcErr: nil,
response: sdk.Role{},
err: errors.NewSDKErrorWithStatus(apiutil.ErrInvalidIDFormat, http.StatusBadRequest),
},
{
desc: "create client role with empty role name",
token: validToken,
domainID: domainID,
clientID: clientID,
roleReq: sdk.RoleReq{
RoleName: "",
OptionalActions: []string{"create", "update"},
OptionalMembers: []string{testsutil.GenerateUUID(t), testsutil.GenerateUUID(t)},
},
svcRes: roles.RoleProvision{},
svcErr: nil,
response: sdk.Role{},
err: errors.NewSDKErrorWithStatus(apiutil.ErrMissingRoleName, http.StatusBadRequest),
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
if tc.token == validToken {
tc.session = smqauthn.Session{DomainUserID: domainID + "_" + validID, UserID: validID, DomainID: domainID}
}
authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr)
svcCall := csvc.On("AddRole", mock.Anything, tc.session, tc.clientID, tc.roleReq.RoleName, tc.roleReq.OptionalActions, tc.roleReq.OptionalMembers).Return(tc.svcRes, tc.svcErr)
resp, err := mgsdk.CreateClientRole(context.Background(), tc.clientID, tc.domainID, tc.roleReq, tc.token)
assert.Equal(t, tc.err, err)
assert.Equal(t, tc.response, resp)
if tc.err == nil {
ok := svcCall.Parent.AssertCalled(t, "AddRole", mock.Anything, tc.session, tc.clientID, tc.roleReq.RoleName, tc.roleReq.OptionalActions, tc.roleReq.OptionalMembers)
assert.True(t, ok)
}
svcCall.Unset()
authCall.Unset()
})
}
}
func TestListClientRoles(t *testing.T) {
ts, csvc, auth := setupClients()
defer ts.Close()
conf := sdk.Config{
ClientsURL: ts.URL,
}
mgsdk := sdk.NewSDK(conf)
role := roles.Role{
ID: testsutil.GenerateUUID(t),
Name: roleName,
EntityID: clientID,
CreatedBy: testsutil.GenerateUUID(t),
CreatedAt: time.Now().UTC(),
}
cases := []struct {
desc string
token string
session smqauthn.Session
domainID string
clientID string
pageMeta sdk.PageMetadata
svcRes roles.RolePage
svcErr error
authenticateErr error
response sdk.RolesPage
err errors.SDKError
}{
{
desc: "list client roles successfully",
token: validToken,
domainID: domainID,
clientID: clientID,
pageMeta: sdk.PageMetadata{
Offset: 0,
Limit: 10,
},
svcRes: roles.RolePage{
Total: 1,
Offset: 0,
Limit: 10,
Roles: []roles.Role{role},
},
svcErr: nil,
response: sdk.RolesPage{
Total: 1,
Offset: 0,
Limit: 10,
Roles: []sdk.Role{convertRole(role)},
},
err: nil,
},
{
desc: "list client roles with invalid token",
token: invalidToken,
domainID: domainID,
clientID: clientID,
pageMeta: sdk.PageMetadata{
Offset: 0,
Limit: 10,
},
svcRes: roles.RolePage{},
authenticateErr: svcerr.ErrAuthentication,
response: sdk.RolesPage{},
err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthentication, http.StatusUnauthorized),
},
{
desc: "list client roles with empty token",
token: "",
domainID: domainID,
clientID: clientID,
pageMeta: sdk.PageMetadata{
Offset: 0,
Limit: 10,
},
svcRes: roles.RolePage{},
response: sdk.RolesPage{},
err: errors.NewSDKErrorWithStatus(apiutil.ErrBearerToken, http.StatusUnauthorized),
},
{
desc: "list client roles with invalid client id",
token: validToken,
domainID: domainID,
clientID: testsutil.GenerateUUID(t),
pageMeta: sdk.PageMetadata{
Offset: 0,
Limit: 10,
},
svcRes: roles.RolePage{},
svcErr: svcerr.ErrAuthorization,
response: sdk.RolesPage{},
err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden),
},
{
desc: "list client roles with empty client id",
token: validToken,
domainID: domainID,
pageMeta: sdk.PageMetadata{
Offset: 0,
Limit: 10,
},
clientID: "",
svcRes: roles.RolePage{},
svcErr: nil,
response: sdk.RolesPage{},
err: errors.NewSDKErrorWithStatus(apiutil.ErrMissingID, http.StatusBadRequest),
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
if tc.token == validToken {
tc.session = smqauthn.Session{DomainUserID: domainID + "_" + validID, UserID: validID, DomainID: domainID}
}
authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr)
svcCall := csvc.On("RetrieveAllRoles", mock.Anything, tc.session, tc.clientID, tc.pageMeta.Limit, tc.pageMeta.Offset).Return(tc.svcRes, tc.svcErr)
resp, err := mgsdk.ClientRoles(context.Background(), tc.clientID, tc.domainID, tc.pageMeta, tc.token)
assert.Equal(t, tc.err, err)
assert.Equal(t, tc.response, resp)
if tc.err == nil {
ok := svcCall.Parent.AssertCalled(t, "RetrieveAllRoles", mock.Anything, tc.session, tc.clientID, tc.pageMeta.Limit, tc.pageMeta.Offset)
assert.True(t, ok)
}
svcCall.Unset()
authCall.Unset()
})
}
}
func TestViewClientRole(t *testing.T) {
ts, csvc, auth := setupClients()
defer ts.Close()
conf := sdk.Config{
ClientsURL: ts.URL,
}
mgsdk := sdk.NewSDK(conf)
role := roles.Role{
ID: testsutil.GenerateUUID(t),
Name: roleName,
EntityID: clientID,
CreatedBy: testsutil.GenerateUUID(t),
CreatedAt: time.Now().UTC(),
}
cases := []struct {
desc string
token string
session smqauthn.Session
domainID string
clientID string
roleID string
svcRes roles.Role
svcErr error
authenticateErr error
response sdk.Role
err errors.SDKError
}{
{
desc: "view client role successfully",
token: validToken,
domainID: domainID,
clientID: clientID,
roleID: role.ID,
svcRes: role,
svcErr: nil,
response: convertRole(role),
err: nil,
},
{
desc: "view client role with invalid token",
token: invalidToken,
domainID: domainID,
clientID: clientID,
roleID: role.ID,
svcRes: roles.Role{},
authenticateErr: svcerr.ErrAuthentication,
response: sdk.Role{},
err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthentication, http.StatusUnauthorized),
},
{
desc: "view client role with empty token",
token: "",
domainID: domainID,
clientID: clientID,
roleID: role.ID,
svcRes: roles.Role{},
response: sdk.Role{},
err: errors.NewSDKErrorWithStatus(apiutil.ErrBearerToken, http.StatusUnauthorized),
},
{
desc: "view client role with invalid client id",
token: validToken,
domainID: domainID,
clientID: testsutil.GenerateUUID(t),
roleID: role.ID,
svcRes: roles.Role{},
svcErr: svcerr.ErrAuthorization,
response: sdk.Role{},
err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden),
},
{
desc: "view client role with empty client id",
token: validToken,
domainID: domainID,
clientID: "",
roleID: role.ID,
svcRes: roles.Role{},
svcErr: nil,
response: sdk.Role{},
err: errors.NewSDKErrorWithStatus(apiutil.ErrMissingID, http.StatusBadRequest),
},
{
desc: "view client role with invalid role id",
token: validToken,
domainID: domainID,
clientID: clientID,
roleID: invalid,
svcRes: roles.Role{},
svcErr: svcerr.ErrAuthorization,
response: sdk.Role{},
err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden),
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
if tc.token == validToken {
tc.session = smqauthn.Session{DomainUserID: domainID + "_" + validID, UserID: validID, DomainID: domainID}
}
authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr)
svcCall := csvc.On("RetrieveRole", mock.Anything, tc.session, tc.clientID, tc.roleID).Return(tc.svcRes, tc.svcErr)
resp, err := mgsdk.ClientRole(context.Background(), tc.clientID, tc.roleID, tc.domainID, tc.token)
assert.Equal(t, tc.err, err)
assert.Equal(t, tc.response, resp)
if tc.err == nil {
ok := svcCall.Parent.AssertCalled(t, "RetrieveRole", mock.Anything, tc.session, tc.clientID, tc.roleID)
assert.True(t, ok)
}
svcCall.Unset()
authCall.Unset()
})
}
}
func TestUpdateClientRole(t *testing.T) {
ts, csvc, auth := setupClients()
defer ts.Close()
conf := sdk.Config{
ClientsURL: ts.URL,
}
mgsdk := sdk.NewSDK(conf)
roleID := testsutil.GenerateUUID(t)
newRoleName := valid
userID := testsutil.GenerateUUID(t)
createdAt := time.Now().UTC().Add(-time.Hour)
role := roles.Role{
ID: testsutil.GenerateUUID(t),
Name: newRoleName,
EntityID: clientID,
CreatedBy: userID,
CreatedAt: createdAt,
UpdatedBy: userID,
UpdatedAt: time.Now().UTC(),
}
cases := []struct {
desc string
token string
session smqauthn.Session
domainID string
clientID string
roleID string
newRoleName string
svcRes roles.Role
svcErr error
authenticateErr error
response sdk.Role
err errors.SDKError
}{
{
desc: "update client role successfully",
token: validToken,
domainID: domainID,
clientID: clientID,
roleID: roleID,
newRoleName: newRoleName,
svcRes: role,
svcErr: nil,
response: convertRole(role),
err: nil,
},
{
desc: "update client role with invalid token",
token: invalidToken,
domainID: domainID,
clientID: clientID,
roleID: roleID,
newRoleName: newRoleName,
svcRes: roles.Role{},
authenticateErr: svcerr.ErrAuthentication,
response: sdk.Role{},
err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthentication, http.StatusUnauthorized),
},
{
desc: "update client role with empty token",
token: "",
domainID: domainID,
clientID: clientID,
roleID: roleID,
newRoleName: newRoleName,
svcRes: roles.Role{},
response: sdk.Role{},
err: errors.NewSDKErrorWithStatus(apiutil.ErrBearerToken, http.StatusUnauthorized),
},
{
desc: "update client role with invalid client id",
token: validToken,
domainID: domainID,
clientID: testsutil.GenerateUUID(t),
roleID: roleID,
newRoleName: newRoleName,
svcRes: roles.Role{},
svcErr: svcerr.ErrAuthorization,
response: sdk.Role{},
err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden),
},
{
desc: "update client role with empty client id",
token: validToken,
domainID: domainID,
clientID: "",
roleID: roleID,
newRoleName: newRoleName,
svcRes: roles.Role{},
svcErr: nil,
response: sdk.Role{},
err: errors.NewSDKErrorWithStatus(apiutil.ErrMissingID, http.StatusBadRequest),
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
if tc.token == validToken {
tc.session = smqauthn.Session{DomainUserID: domainID + "_" + validID, UserID: validID, DomainID: domainID}
}
authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr)
svcCall := csvc.On("UpdateRoleName", mock.Anything, tc.session, tc.clientID, tc.roleID, tc.newRoleName).Return(tc.svcRes, tc.svcErr)
resp, err := mgsdk.UpdateClientRole(context.Background(), tc.clientID, tc.roleID, tc.newRoleName, tc.domainID, tc.token)
assert.Equal(t, tc.err, err)
assert.Equal(t, tc.response, resp)
if tc.err == nil {
ok := svcCall.Parent.AssertCalled(t, "UpdateRoleName", mock.Anything, tc.session, tc.clientID, tc.roleID, tc.newRoleName)
assert.True(t, ok)
}
svcCall.Unset()
authCall.Unset()
})
}
}
func TestDeleteClientRole(t *testing.T) {
ts, csvc, auth := setupClients()
defer ts.Close()
conf := sdk.Config{
ClientsURL: ts.URL,
}
mgsdk := sdk.NewSDK(conf)
roleID := testsutil.GenerateUUID(t)
cases := []struct {
desc string
token string
session smqauthn.Session
domainID string
clientID string
roleID string
svcErr error
authenticateErr error
err errors.SDKError
}{
{
desc: "delete client role successfully",
token: validToken,
domainID: domainID,
clientID: clientID,
roleID: roleID,
svcErr: nil,
err: nil,
},
{
desc: "delete client role with invalid token",
token: invalidToken,
domainID: domainID,
clientID: clientID,
roleID: roleID,
authenticateErr: svcerr.ErrAuthentication,
err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthentication, http.StatusUnauthorized),
},
{
desc: "delete client role with empty token",
token: "",
domainID: domainID,
clientID: clientID,
roleID: roleID,
err: errors.NewSDKErrorWithStatus(apiutil.ErrBearerToken, http.StatusUnauthorized),
},
{
desc: "delete client role with invalid client id",
token: validToken,
domainID: domainID,
clientID: testsutil.GenerateUUID(t),
roleID: roleID,
svcErr: svcerr.ErrAuthorization,
err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden),
},
{
desc: "delete client role with empty client id",
token: validToken,
domainID: domainID,
clientID: "",
roleID: roleID,
err: errors.NewSDKErrorWithStatus(apiutil.ErrMissingID, http.StatusBadRequest),
},
{
desc: "delete client role with invalid role id",
token: validToken,
domainID: domainID,
clientID: clientID,
roleID: invalid,
svcErr: svcerr.ErrAuthorization,
err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden),
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
if tc.token == validToken {
tc.session = smqauthn.Session{DomainUserID: domainID + "_" + validID, UserID: validID, DomainID: domainID}
}
authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr)
svcCall := csvc.On("RemoveRole", mock.Anything, tc.session, tc.clientID, tc.roleID).Return(tc.svcErr)
err := mgsdk.DeleteClientRole(context.Background(), tc.clientID, tc.roleID, tc.domainID, tc.token)
assert.Equal(t, tc.err, err)
if tc.err == nil {
ok := svcCall.Parent.AssertCalled(t, "RemoveRole", mock.Anything, tc.session, tc.clientID, tc.roleID)
assert.True(t, ok)
}
svcCall.Unset()
authCall.Unset()
})
}
}
func TestAddClientRoleActions(t *testing.T) {
ts, csvc, auth := setupClients()
defer ts.Close()
conf := sdk.Config{
ClientsURL: ts.URL,
}
mgsdk := sdk.NewSDK(conf)
roleID := testsutil.GenerateUUID(t)
actions := []string{"create", "update"}
cases := []struct {
desc string
token string
session smqauthn.Session
domainID string
clientID string
roleID string
actions []string
svcRes []string
svcErr error
authenticateErr error
response []string
err errors.SDKError
}{
{
desc: "add client role actions successfully",
token: validToken,
domainID: domainID,
clientID: clientID,
roleID: roleID,
actions: actions,
svcRes: actions,
svcErr: nil,
response: actions,
err: nil,
},
{
desc: "add client role actions with invalid token",
token: invalidToken,
domainID: domainID,
clientID: clientID,
roleID: roleID,
actions: actions,
authenticateErr: svcerr.ErrAuthentication,
response: []string{},
err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthentication, http.StatusUnauthorized),
},
{
desc: "add client role actions with empty token",
token: "",
domainID: domainID,
clientID: clientID,
roleID: roleID,
actions: actions,
response: []string{},
err: errors.NewSDKErrorWithStatus(apiutil.ErrBearerToken, http.StatusUnauthorized),
},
{
desc: "add client role actions with invalid client id",
token: validToken,
domainID: domainID,
clientID: testsutil.GenerateUUID(t),
roleID: roleID,
actions: actions,
svcErr: svcerr.ErrAuthorization,
response: []string{},
err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden),
},
{
desc: "add client role actions with empty client id",
token: validToken,
domainID: domainID,
clientID: "",
roleID: roleID,
actions: actions,
response: []string{},
err: errors.NewSDKErrorWithStatus(apiutil.ErrMissingID, http.StatusBadRequest),
},
{
desc: "add client role actions with invalid role id",
token: validToken,
domainID: domainID,
clientID: clientID,
roleID: invalid,
actions: actions,
svcErr: svcerr.ErrAuthorization,
response: []string{},
err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden),
},
{
desc: "add client role actions with empty actions",
token: validToken,
domainID: domainID,
clientID: clientID,
roleID: roleID,
actions: []string{},
svcErr: nil,
response: []string{},
err: errors.NewSDKErrorWithStatus(apiutil.ErrMissingPolicyEntityType, http.StatusBadRequest),
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
if tc.token == validToken {
tc.session = smqauthn.Session{DomainUserID: domainID + "_" + validID, UserID: validID, DomainID: domainID}
}
authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr)
svcCall := csvc.On("RoleAddActions", mock.Anything, tc.session, tc.clientID, tc.roleID, tc.actions).Return(tc.svcRes, tc.svcErr)
resp, err := mgsdk.AddClientRoleActions(context.Background(), tc.clientID, tc.roleID, tc.domainID, tc.actions, tc.token)
assert.Equal(t, tc.err, err)
assert.Equal(t, tc.response, resp)
if tc.err == nil {
ok := svcCall.Parent.AssertCalled(t, "RoleAddActions", mock.Anything, tc.session, tc.clientID, tc.roleID, tc.actions)
assert.True(t, ok)
}
svcCall.Unset()
authCall.Unset()
})
}
}
func TestListClientRoleActions(t *testing.T) {
ts, csvc, auth := setupClients()
defer ts.Close()
conf := sdk.Config{
ClientsURL: ts.URL,
}
mgsdk := sdk.NewSDK(conf)
roleID := testsutil.GenerateUUID(t)
actions := []string{"create", "update"}
cases := []struct {
desc string
token string
session smqauthn.Session
domainID string
clientID string
roleID string
svcRes []string
svcErr error
authenticateErr error
response []string
err errors.SDKError
}{
{
desc: "list client role actions successfully",
token: validToken,
domainID: domainID,
clientID: clientID,
roleID: roleID,
svcRes: actions,
svcErr: nil,
response: actions,
err: nil,
},
{
desc: "list client role actions with invalid token",
token: invalidToken,
domainID: domainID,
clientID: clientID,
roleID: roleID,
authenticateErr: svcerr.ErrAuthentication,
err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthentication, http.StatusUnauthorized),
},
{
desc: "list client role actions with empty token",
token: "",
domainID: domainID,
clientID: clientID,
roleID: roleID,
err: errors.NewSDKErrorWithStatus(apiutil.ErrBearerToken, http.StatusUnauthorized),
},
{
desc: "list client role actions with invalid client id",
token: validToken,
domainID: domainID,
clientID: testsutil.GenerateUUID(t),
roleID: roleID,
svcErr: svcerr.ErrAuthorization,
err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden),
},
{
desc: "list client role actions with empty client id",
token: validToken,
domainID: domainID,
clientID: "",
roleID: roleID,
err: errors.NewSDKErrorWithStatus(apiutil.ErrMissingID, http.StatusBadRequest),
},
{
desc: "list client role actions with invalid role id",
token: validToken,
domainID: domainID,
clientID: clientID,
roleID: invalid,
svcErr: svcerr.ErrAuthorization,
err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden),
},
{
desc: "list client role actions with empty role id",
token: validToken,
domainID: domainID,
clientID: clientID,
roleID: "",
svcErr: nil,
err: errors.NewSDKErrorWithStatus(apiutil.ErrMissingRoleID, http.StatusBadRequest),
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
if tc.token == validToken {
tc.session = smqauthn.Session{DomainUserID: domainID + "_" + validID, UserID: validID, DomainID: domainID}
}
authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr)
svcCall := csvc.On("RoleListActions", mock.Anything, tc.session, tc.clientID, tc.roleID).Return(tc.svcRes, tc.svcErr)
resp, err := mgsdk.ClientRoleActions(context.Background(), tc.clientID, tc.roleID, tc.domainID, tc.token)
assert.Equal(t, tc.err, err)
assert.Equal(t, tc.response, resp)
if tc.err == nil {
ok := svcCall.Parent.AssertCalled(t, "RoleListActions", mock.Anything, tc.session, tc.clientID, tc.roleID)
assert.True(t, ok)
}
svcCall.Unset()
authCall.Unset()
})
}
}
func TestRemoveClientRoleActions(t *testing.T) {
ts, csvc, auth := setupClients()
defer ts.Close()
conf := sdk.Config{
ClientsURL: ts.URL,
}
mgsdk := sdk.NewSDK(conf)
roleID := testsutil.GenerateUUID(t)
actions := []string{"create", "update"}
cases := []struct {
desc string
token string
session smqauthn.Session
domainID string
clientID string
roleID string
actions []string
svcErr error
authenticateErr error
err errors.SDKError
}{
{
desc: "remove client role actions successfully",
token: validToken,
domainID: domainID,
clientID: clientID,
roleID: roleID,
actions: actions,
svcErr: nil,
err: nil,
},
{
desc: "remove client role actions with invalid token",
token: invalidToken,
domainID: domainID,
clientID: clientID,
roleID: roleID,
actions: actions,
authenticateErr: svcerr.ErrAuthentication,
err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthentication, http.StatusUnauthorized),
},
{
desc: "remove client role actions with empty token",
token: "",
domainID: domainID,
clientID: clientID,
roleID: roleID,
actions: actions,
err: errors.NewSDKErrorWithStatus(apiutil.ErrBearerToken, http.StatusUnauthorized),
},
{
desc: "remove client role actions with invalid client id",
token: validToken,
domainID: domainID,
clientID: testsutil.GenerateUUID(t),
roleID: roleID,
actions: actions,
svcErr: svcerr.ErrAuthorization,
err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden),
},
{
desc: "remove client role actions with empty client id",
token: validToken,
domainID: domainID,
clientID: "",
roleID: roleID,
actions: actions,
err: errors.NewSDKErrorWithStatus(apiutil.ErrMissingID, http.StatusBadRequest),
},
{
desc: "remove client role actions with invalid role id",
token: validToken,
domainID: domainID,
clientID: clientID,
roleID: invalid,
actions: actions,
svcErr: svcerr.ErrAuthorization,
err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden),
},
{
desc: "remove client role actions with empty actions",
token: validToken,
domainID: domainID,
clientID: clientID,
roleID: roleID,
actions: []string{},
svcErr: nil,
err: errors.NewSDKErrorWithStatus(apiutil.ErrMissingPolicyEntityType, http.StatusBadRequest),
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
if tc.token == validToken {
tc.session = smqauthn.Session{DomainUserID: domainID + "_" + validID, UserID: validID, DomainID: domainID}
}
authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr)
svcCall := csvc.On("RoleRemoveActions", mock.Anything, tc.session, tc.clientID, tc.roleID, tc.actions).Return(tc.svcErr)
err := mgsdk.RemoveClientRoleActions(context.Background(), tc.clientID, tc.roleID, tc.domainID, tc.actions, tc.token)
assert.Equal(t, tc.err, err)
if tc.err == nil {
ok := svcCall.Parent.AssertCalled(t, "RoleRemoveActions", mock.Anything, tc.session, tc.clientID, tc.roleID, tc.actions)
assert.True(t, ok)
}
svcCall.Unset()
authCall.Unset()
})
}
}
func TestRemoveAllClientRoleActions(t *testing.T) {
ts, csvc, auth := setupClients()
defer ts.Close()
conf := sdk.Config{
ClientsURL: ts.URL,
}
mgsdk := sdk.NewSDK(conf)
roleID := testsutil.GenerateUUID(t)
cases := []struct {
desc string
token string
session smqauthn.Session
domainID string
clientID string
roleID string
svcErr error
authenticateErr error
err errors.SDKError
}{
{
desc: "remove all client role actions successfully",
token: validToken,
domainID: domainID,
clientID: clientID,
roleID: roleID,
svcErr: nil,
err: nil,
},
{
desc: "remove all client role actions with invalid token",
token: invalidToken,
domainID: domainID,
clientID: clientID,
roleID: roleID,
authenticateErr: svcerr.ErrAuthentication,
err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthentication, http.StatusUnauthorized),
},
{
desc: "remove all client role actions with empty token",
token: "",
domainID: domainID,
clientID: clientID,
roleID: roleID,
err: errors.NewSDKErrorWithStatus(apiutil.ErrBearerToken, http.StatusUnauthorized),
},
{
desc: "remove all client role actions with invalid client id",
token: validToken,
domainID: domainID,
clientID: testsutil.GenerateUUID(t),
roleID: roleID,
svcErr: svcerr.ErrAuthorization,
err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden),
},
{
desc: "remove all client role actions with empty client id",
token: validToken,
domainID: domainID,
clientID: "",
roleID: roleID,
err: errors.NewSDKErrorWithStatus(apiutil.ErrMissingID, http.StatusBadRequest),
},
{
desc: "remove all client role actions with invalid role id",
token: validToken,
domainID: domainID,
clientID: clientID,
roleID: invalid,
svcErr: svcerr.ErrAuthorization,
err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden),
},
{
desc: "remove all client role actions with empty role id",
token: validToken,
domainID: domainID,
clientID: clientID,
roleID: "",
svcErr: nil,
err: errors.NewSDKErrorWithStatus(apiutil.ErrMissingRoleID, http.StatusBadRequest),
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
if tc.token == validToken {
tc.session = smqauthn.Session{DomainUserID: domainID + "_" + validID, UserID: validID, DomainID: domainID}
}
authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr)
svcCall := csvc.On("RoleRemoveAllActions", mock.Anything, tc.session, tc.clientID, tc.roleID).Return(tc.svcErr)
err := mgsdk.RemoveAllClientRoleActions(context.Background(), tc.clientID, tc.roleID, tc.domainID, tc.token)
assert.Equal(t, tc.err, err)
if tc.err == nil {
ok := svcCall.Parent.AssertCalled(t, "RoleRemoveAllActions", mock.Anything, tc.session, tc.clientID, tc.roleID)
assert.True(t, ok)
}
svcCall.Unset()
authCall.Unset()
})
}
}
func TestAddClientRoleMembers(t *testing.T) {
ts, csvc, auth := setupClients()
defer ts.Close()
conf := sdk.Config{
ClientsURL: ts.URL,
}
mgsdk := sdk.NewSDK(conf)
roleID := testsutil.GenerateUUID(t)
members := []string{"user1", "user2"}
cases := []struct {
desc string
token string
session smqauthn.Session
domainID string
clientID string
roleID string
members []string
svcRes []string
svcErr error
authenticateErr error
response []string
err errors.SDKError
}{
{
desc: "add client role members successfully",
token: validToken,
domainID: domainID,
clientID: clientID,
roleID: roleID,
members: members,
svcRes: members,
svcErr: nil,
response: members,
err: nil,
},
{
desc: "add client role members with invalid token",
token: invalidToken,
domainID: domainID,
clientID: clientID,
roleID: roleID,
members: members,
authenticateErr: svcerr.ErrAuthentication,
response: []string{},
err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthentication, http.StatusUnauthorized),
},
{
desc: "add client role members with empty token",
token: "",
domainID: domainID,
clientID: clientID,
roleID: roleID,
members: members,
response: []string{},
err: errors.NewSDKErrorWithStatus(apiutil.ErrBearerToken, http.StatusUnauthorized),
},
{
desc: "add client role members with invalid client id",
token: validToken,
domainID: domainID,
clientID: testsutil.GenerateUUID(t),
roleID: roleID,
members: members,
svcErr: svcerr.ErrAuthorization,
response: []string{},
err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden),
},
{
desc: "add client role members with empty client id",
token: validToken,
domainID: domainID,
clientID: "",
roleID: roleID,
members: members,
response: []string{},
err: errors.NewSDKErrorWithStatus(apiutil.ErrMissingID, http.StatusBadRequest),
},
{
desc: "add client role members with invalid role id",
token: validToken,
domainID: domainID,
clientID: clientID,
roleID: invalid,
members: members,
svcErr: svcerr.ErrAuthorization,
response: []string{},
err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden),
},
{
desc: "add client role members with empty members",
token: validToken,
domainID: domainID,
clientID: clientID,
roleID: roleID,
members: []string{},
svcErr: nil,
response: []string{},
err: errors.NewSDKErrorWithStatus(apiutil.ErrMissingRoleMembers, http.StatusBadRequest),
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
if tc.token == validToken {
tc.session = smqauthn.Session{DomainUserID: domainID + "_" + validID, UserID: validID, DomainID: domainID}
}
authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr)
svcCall := csvc.On("RoleAddMembers", mock.Anything, tc.session, tc.clientID, tc.roleID, tc.members).Return(tc.svcRes, tc.svcErr)
resp, err := mgsdk.AddClientRoleMembers(context.Background(), tc.clientID, tc.roleID, tc.domainID, tc.members, tc.token)
assert.Equal(t, tc.err, err)
assert.Equal(t, tc.response, resp)
if tc.err == nil {
ok := svcCall.Parent.AssertCalled(t, "RoleAddMembers", mock.Anything, tc.session, tc.clientID, tc.roleID, tc.members)
assert.True(t, ok)
}
svcCall.Unset()
authCall.Unset()
})
}
}
func TestListClientRoleMembers(t *testing.T) {
ts, csvc, auth := setupClients()
defer ts.Close()
conf := sdk.Config{
ClientsURL: ts.URL,
}
mgsdk := sdk.NewSDK(conf)
roleID := testsutil.GenerateUUID(t)
members := []string{"user1", "user2"}
cases := []struct {
desc string
token string
session smqauthn.Session
domainID string
clientID string
roleID string
pageMeta sdk.PageMetadata
svcRes roles.MembersPage
svcErr error
authenticateErr error
response sdk.RoleMembersPage
err errors.SDKError
}{
{
desc: "list client role members successfully",
token: validToken,
domainID: domainID,
clientID: clientID,
pageMeta: sdk.PageMetadata{
Offset: 0,
Limit: 5,
},
roleID: roleID,
svcRes: roles.MembersPage{
Total: 2,
Offset: 0,
Limit: 5,
Members: members,
},
svcErr: nil,
response: sdk.RoleMembersPage{
Total: 2,
Offset: 0,
Limit: 5,
Members: members,
},
err: nil,
},
{
desc: "list client role members with invalid token",
token: invalidToken,
domainID: domainID,
clientID: clientID,
pageMeta: sdk.PageMetadata{
Offset: 0,
Limit: 5,
},
roleID: roleID,
authenticateErr: svcerr.ErrAuthentication,
err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthentication, http.StatusUnauthorized),
},
{
desc: "list client role members with empty token",
token: "",
domainID: domainID,
clientID: clientID,
pageMeta: sdk.PageMetadata{
Offset: 0,
Limit: 5,
},
roleID: roleID,
err: errors.NewSDKErrorWithStatus(apiutil.ErrBearerToken, http.StatusUnauthorized),
},
{
desc: "list client role members with invalid client id",
token: validToken,
domainID: domainID,
clientID: testsutil.GenerateUUID(t),
pageMeta: sdk.PageMetadata{
Offset: 0,
Limit: 5,
},
roleID: roleID,
svcErr: svcerr.ErrAuthorization,
err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden),
},
{
desc: "list client role members with empty client id",
token: validToken,
domainID: domainID,
pageMeta: sdk.PageMetadata{
Offset: 0,
Limit: 5,
},
clientID: "",
roleID: roleID,
err: errors.NewSDKErrorWithStatus(apiutil.ErrMissingID, http.StatusBadRequest),
},
{
desc: "list client role members with invalid role id",
token: validToken,
domainID: domainID,
clientID: clientID,
pageMeta: sdk.PageMetadata{
Offset: 0,
Limit: 5,
},
roleID: invalid,
svcErr: svcerr.ErrAuthorization,
err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden),
},
{
desc: "list client role members with empty role id",
token: validToken,
domainID: domainID,
clientID: clientID,
pageMeta: sdk.PageMetadata{
Offset: 0,
Limit: 5,
},
roleID: "",
svcErr: nil,
err: errors.NewSDKErrorWithStatus(apiutil.ErrMissingRoleID, http.StatusBadRequest),
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
if tc.token == validToken {
tc.session = smqauthn.Session{DomainUserID: domainID + "_" + validID, UserID: validID, DomainID: domainID}
}
authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr)
svcCall := csvc.On("RoleListMembers", mock.Anything, tc.session, tc.clientID, tc.roleID, tc.pageMeta.Limit, tc.pageMeta.Offset).Return(tc.svcRes, tc.svcErr)
resp, err := mgsdk.ClientRoleMembers(context.Background(), tc.clientID, tc.roleID, tc.domainID, tc.pageMeta, tc.token)
assert.Equal(t, tc.err, err)
assert.Equal(t, tc.response, resp)
if tc.err == nil {
ok := svcCall.Parent.AssertCalled(t, "RoleListMembers", mock.Anything, tc.session, tc.clientID, tc.roleID, tc.pageMeta.Limit, tc.pageMeta.Offset)
assert.True(t, ok)
}
svcCall.Unset()
authCall.Unset()
})
}
}
func TestRemoveClientRoleMembers(t *testing.T) {
ts, csvc, auth := setupClients()
defer ts.Close()
conf := sdk.Config{
ClientsURL: ts.URL,
}
mgsdk := sdk.NewSDK(conf)
roleID := testsutil.GenerateUUID(t)
members := []string{"user1", "user2"}
cases := []struct {
desc string
token string
session smqauthn.Session
domainID string
clientID string
roleID string
members []string
svcErr error
authenticateErr error
err errors.SDKError
}{
{
desc: "remove client role members successfully",
token: validToken,
domainID: domainID,
clientID: clientID,
roleID: roleID,
members: members,
svcErr: nil,
err: nil,
},
{
desc: "remove client role members with invalid token",
token: invalidToken,
domainID: domainID,
clientID: clientID,
roleID: roleID,
members: members,
authenticateErr: svcerr.ErrAuthentication,
err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthentication, http.StatusUnauthorized),
},
{
desc: "remove client role members with empty token",
token: "",
domainID: domainID,
clientID: clientID,
roleID: roleID,
members: members,
err: errors.NewSDKErrorWithStatus(apiutil.ErrBearerToken, http.StatusUnauthorized),
},
{
desc: "remove client role members with invalid client id",
token: validToken,
domainID: domainID,
clientID: testsutil.GenerateUUID(t),
roleID: roleID,
members: members,
svcErr: svcerr.ErrAuthorization,
err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden),
},
{
desc: "remove client role members with empty client id",
token: validToken,
domainID: domainID,
clientID: "",
roleID: roleID,
members: members,
err: errors.NewSDKErrorWithStatus(apiutil.ErrMissingID, http.StatusBadRequest),
},
{
desc: "remove client role members with invalid role id",
token: validToken,
domainID: domainID,
clientID: clientID,
roleID: invalid,
members: members,
svcErr: svcerr.ErrAuthorization,
err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden),
},
{
desc: "remove client role members with empty members",
token: validToken,
domainID: domainID,
clientID: clientID,
roleID: roleID,
members: []string{},
svcErr: nil,
err: errors.NewSDKErrorWithStatus(apiutil.ErrMissingRoleMembers, http.StatusBadRequest),
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
if tc.token == validToken {
tc.session = smqauthn.Session{DomainUserID: domainID + "_" + validID, UserID: validID, DomainID: domainID}
}
authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr)
svcCall := csvc.On("RoleRemoveMembers", mock.Anything, tc.session, tc.clientID, tc.roleID, tc.members).Return(tc.svcErr)
err := mgsdk.RemoveClientRoleMembers(context.Background(), tc.clientID, tc.roleID, tc.domainID, tc.members, tc.token)
assert.Equal(t, tc.err, err)
if tc.err == nil {
ok := svcCall.Parent.AssertCalled(t, "RoleRemoveMembers", mock.Anything, tc.session, tc.clientID, tc.roleID, tc.members)
assert.True(t, ok)
}
svcCall.Unset()
authCall.Unset()
})
}
}
func TestRemoveAllClientRoleMembers(t *testing.T) {
ts, csvc, auth := setupClients()
defer ts.Close()
conf := sdk.Config{
ClientsURL: ts.URL,
}
mgsdk := sdk.NewSDK(conf)
roleID := testsutil.GenerateUUID(t)
cases := []struct {
desc string
token string
session smqauthn.Session
domainID string
clientID string
roleID string
svcErr error
authenticateErr error
err errors.SDKError
}{
{
desc: "remove all client role members successfully",
token: validToken,
domainID: domainID,
clientID: clientID,
roleID: roleID,
svcErr: nil,
err: nil,
},
{
desc: "remove all client role members with invalid token",
token: invalidToken,
domainID: domainID,
clientID: clientID,
roleID: roleID,
authenticateErr: svcerr.ErrAuthentication,
err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthentication, http.StatusUnauthorized),
},
{
desc: "remove all client role members with empty token",
token: "",
domainID: domainID,
clientID: clientID,
roleID: roleID,
err: errors.NewSDKErrorWithStatus(apiutil.ErrBearerToken, http.StatusUnauthorized),
},
{
desc: "remove all client role members with invalid client id",
token: validToken,
domainID: domainID,
clientID: testsutil.GenerateUUID(t),
roleID: roleID,
svcErr: svcerr.ErrAuthorization,
err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden),
},
{
desc: "remove all client role members with empty client id",
token: validToken,
domainID: domainID,
clientID: "",
roleID: roleID,
err: errors.NewSDKErrorWithStatus(apiutil.ErrMissingID, http.StatusBadRequest),
},
{
desc: "remove all client role members with invalid role id",
token: validToken,
domainID: domainID,
clientID: clientID,
roleID: invalid,
svcErr: svcerr.ErrAuthorization,
err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden),
},
{
desc: "remove all client role members with empty role id",
token: validToken,
domainID: domainID,
clientID: clientID,
roleID: "",
svcErr: nil,
err: errors.NewSDKErrorWithStatus(apiutil.ErrMissingRoleID, http.StatusBadRequest),
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
if tc.token == validToken {
tc.session = smqauthn.Session{DomainUserID: domainID + "_" + validID, UserID: validID, DomainID: domainID}
}
authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr)
svcCall := csvc.On("RoleRemoveAllMembers", mock.Anything, tc.session, tc.clientID, tc.roleID).Return(tc.svcErr)
err := mgsdk.RemoveAllClientRoleMembers(context.Background(), tc.clientID, tc.roleID, tc.domainID, tc.token)
assert.Equal(t, tc.err, err)
if tc.err == nil {
ok := svcCall.Parent.AssertCalled(t, "RoleRemoveAllMembers", mock.Anything, tc.session, tc.clientID, tc.roleID)
assert.True(t, ok)
}
svcCall.Unset()
authCall.Unset()
})
}
}
func TestListAvailableClientRoleActions(t *testing.T) {
ts, csvc, auth := setupClients()
defer ts.Close()
conf := sdk.Config{
ClientsURL: ts.URL,
}
mgsdk := sdk.NewSDK(conf)
actions := []string{"create", "update"}
cases := []struct {
desc string
token string
session smqauthn.Session
domainID string
svcRes []string
svcErr error
authenticateErr error
response []string
err errors.SDKError
}{
{
desc: "list available role actions successfully",
token: validToken,
domainID: domainID,
svcRes: actions,
svcErr: nil,
response: actions,
err: nil,
},
{
desc: "list available role actions with invalid token",
token: invalidToken,
domainID: domainID,
authenticateErr: svcerr.ErrAuthentication,
err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthentication, http.StatusUnauthorized),
},
{
desc: "list available role actions with empty token",
token: "",
domainID: domainID,
err: errors.NewSDKErrorWithStatus(apiutil.ErrBearerToken, http.StatusUnauthorized),
},
{
desc: "list available role actions with empty domain id",
token: validToken,
domainID: "",
err: errors.NewSDKErrorWithStatus(apiutil.ErrMissingDomainID, http.StatusBadRequest),
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
if tc.token == validToken {
tc.session = smqauthn.Session{DomainUserID: domainID + "_" + validID, UserID: validID, DomainID: domainID}
}
authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr)
svcCall := csvc.On("ListAvailableActions", mock.Anything, tc.session).Return(tc.svcRes, tc.svcErr)
resp, err := mgsdk.AvailableClientRoleActions(context.Background(), tc.domainID, tc.token)
assert.Equal(t, tc.err, err)
assert.Equal(t, tc.response, resp)
if tc.err == nil {
ok := svcCall.Parent.AssertCalled(t, "ListAvailableActions", mock.Anything, tc.session)
assert.True(t, ok)
}
svcCall.Unset()
authCall.Unset()
})
}
}
func generateTestClient(t *testing.T, withRoles bool) sdk.Client {
createdAt, err := time.Parse(time.RFC3339, "2023-03-03T00:00:00Z")
assert.Nil(t, err, fmt.Sprintf("unexpected error %s", err))
updatedAt := createdAt
var rl []roles.MemberRoleActions
if withRoles {
rl = validRoles
}
return sdk.Client{
ID: testsutil.GenerateUUID(t),
Name: "clientname",
Credentials: sdk.ClientCredentials{
Identity: "client@example.com",
Secret: generateUUID(t),
},
Tags: []string{"tag1", "tag2"},
Metadata: validMetadata,
PrivateMetadata: validMetadata,
Status: clients.EnabledStatus.String(),
CreatedAt: createdAt,
UpdatedAt: updatedAt,
Roles: rl,
}
}