mirror of
https://github.com/mainflux/mainflux.git
synced 2025-04-26 13:48:53 +08:00

* remove owner id Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com> * add users endpoint for retrieving users from group Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com> * remove groups from things and users Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com> * move groups into auth Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com> * separate endpoints for users and things Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com> * fix problems with retrieving members Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com> * add groups test Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com> * remove groups from users Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com> * remove groups from things Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com> * rename constant Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com> * add new errors Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com> * remove unnecessary constants Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com> * fix validation Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com> * create groups db mock Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com> * adding tests Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com> * revert changes to docker related files Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com> * remove groups endpoints from users openapi Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com> * remove groups endpoints from users openapi Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com> * move constant from postgres to groups Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com> * move constant from postgres to groups Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com> * move constant from postgres to groups Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com> * remove testing group Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com> * renam typ to groupType Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com> * add error for max level Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com> * remove print Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com> * remove groups.Member interface Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com> * fix query building and add test cases Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com> * uncomment tests Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com> * move groups package Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com> * remove group type, add bulk assign and unassign Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com> * update openapi, remove parentID from create request, reorder endpoints Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com> * update openapi Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com> * update openapi for users and things Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com> * fix groups test Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com> * fix linter errors Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com> * resolve comments Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com> * rename assignReq structure Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com> * refactor mocks, response, remove type from endpoint Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com> * some refactor, renaming, errors Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com> * simplify check Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com> * remove package alias Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com> * fix naming and comment Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com> * additional comments Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com> * add members grpc endpoint test Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com> * fix retrieving members for different types Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com> * fix retrieving members for different types Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com> * remove unecessary structure Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com> * fix api grpc Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com> * rename const Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com> * refactore retrieve parents and children with common function Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com> * small changes for errors Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com> * fix compile error Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com> * fix sorting in mock Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com> * remove regexp for groups Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com> * revert as change is made by mistake Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com> * revert as change is made by mistake Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com> * refactor groups and keys package Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com> * fix naming Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com> * fix naming Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com> * fix test for timestamp compare Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com> * fix error handling Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com> * remove errors not being used Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com> * var renaming Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com> * resolve comments Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com> * minor changes Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com> * fix test Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com> * add endpoints for groups into nginx Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com> * reorganize endpoints, remove some errors Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com> * reorganize endpoints, remove some errors Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com> * small fix Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com> * fix linter errors Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com> * minor changes Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com> * resolve comments Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com> * fix group save path problem Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com> * description constant Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com> * rename variables Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com> * fix validation Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com> * get back return Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com> * fix compile Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com>
984 lines
28 KiB
Go
984 lines
28 KiB
Go
// Copyright (c) Mainflux
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
package auth_test
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/mainflux/mainflux/auth"
|
|
"github.com/mainflux/mainflux/auth/jwt"
|
|
"github.com/mainflux/mainflux/auth/mocks"
|
|
"github.com/mainflux/mainflux/pkg/errors"
|
|
"github.com/mainflux/mainflux/pkg/uuid"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
var idProvider = uuid.New()
|
|
|
|
const (
|
|
secret = "secret"
|
|
email = "test@example.com"
|
|
id = "testID"
|
|
groupName = "mfx"
|
|
description = "Description"
|
|
)
|
|
|
|
func newService() auth.Service {
|
|
repo := mocks.NewKeyRepository()
|
|
groupRepo := mocks.NewGroupRepository()
|
|
idProvider := uuid.NewMock()
|
|
t := jwt.New(secret)
|
|
return auth.New(repo, groupRepo, idProvider, t)
|
|
}
|
|
|
|
func TestIssue(t *testing.T) {
|
|
svc := newService()
|
|
_, secret, err := svc.Issue(context.Background(), "", auth.Key{Type: auth.UserKey, IssuedAt: time.Now(), IssuerID: id, Subject: email})
|
|
assert.Nil(t, err, fmt.Sprintf("Issuing login key expected to succeed: %s", err))
|
|
|
|
cases := []struct {
|
|
desc string
|
|
key auth.Key
|
|
token string
|
|
err error
|
|
}{
|
|
{
|
|
desc: "issue user key",
|
|
key: auth.Key{
|
|
Type: auth.UserKey,
|
|
IssuedAt: time.Now(),
|
|
},
|
|
token: secret,
|
|
err: nil,
|
|
},
|
|
{
|
|
desc: "issue user key with no time",
|
|
key: auth.Key{
|
|
Type: auth.UserKey,
|
|
},
|
|
token: secret,
|
|
err: auth.ErrInvalidKeyIssuedAt,
|
|
},
|
|
{
|
|
desc: "issue API key",
|
|
key: auth.Key{
|
|
Type: auth.APIKey,
|
|
IssuedAt: time.Now(),
|
|
},
|
|
token: secret,
|
|
err: nil,
|
|
},
|
|
{
|
|
desc: "issue API key unauthorized",
|
|
key: auth.Key{
|
|
Type: auth.APIKey,
|
|
IssuedAt: time.Now(),
|
|
},
|
|
token: "invalid",
|
|
err: auth.ErrUnauthorizedAccess,
|
|
},
|
|
{
|
|
desc: "issue API key with no time",
|
|
key: auth.Key{
|
|
Type: auth.APIKey,
|
|
},
|
|
token: secret,
|
|
err: auth.ErrInvalidKeyIssuedAt,
|
|
},
|
|
{
|
|
desc: "issue recovery key",
|
|
key: auth.Key{
|
|
Type: auth.RecoveryKey,
|
|
IssuedAt: time.Now(),
|
|
},
|
|
token: "",
|
|
err: nil,
|
|
},
|
|
{
|
|
desc: "issue recovery with no issue time",
|
|
key: auth.Key{
|
|
Type: auth.RecoveryKey,
|
|
},
|
|
token: secret,
|
|
err: auth.ErrInvalidKeyIssuedAt,
|
|
},
|
|
}
|
|
|
|
for _, tc := range cases {
|
|
_, _, err := svc.Issue(context.Background(), tc.token, tc.key)
|
|
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s expected %s got %s\n", tc.desc, tc.err, err))
|
|
}
|
|
}
|
|
|
|
func TestRevoke(t *testing.T) {
|
|
svc := newService()
|
|
_, secret, err := svc.Issue(context.Background(), "", auth.Key{Type: auth.UserKey, IssuedAt: time.Now(), IssuerID: id, Subject: email})
|
|
assert.Nil(t, err, fmt.Sprintf("Issuing login key expected to succeed: %s", err))
|
|
key := auth.Key{
|
|
Type: auth.APIKey,
|
|
IssuedAt: time.Now(),
|
|
IssuerID: id,
|
|
Subject: email,
|
|
}
|
|
newKey, _, err := svc.Issue(context.Background(), secret, key)
|
|
assert.Nil(t, err, fmt.Sprintf("Issuing user's key expected to succeed: %s", err))
|
|
|
|
cases := []struct {
|
|
desc string
|
|
id string
|
|
token string
|
|
err error
|
|
}{
|
|
{
|
|
desc: "revoke user key",
|
|
id: newKey.ID,
|
|
token: secret,
|
|
err: nil,
|
|
},
|
|
{
|
|
desc: "revoke non-existing user key",
|
|
id: newKey.ID,
|
|
token: secret,
|
|
err: nil,
|
|
},
|
|
{
|
|
desc: "revoke unauthorized",
|
|
id: newKey.ID,
|
|
token: "",
|
|
err: auth.ErrUnauthorizedAccess,
|
|
},
|
|
}
|
|
|
|
for _, tc := range cases {
|
|
err := svc.Revoke(context.Background(), tc.token, tc.id)
|
|
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s expected %s got %s\n", tc.desc, tc.err, err))
|
|
}
|
|
}
|
|
|
|
func TestRetrieve(t *testing.T) {
|
|
svc := newService()
|
|
_, secret, err := svc.Issue(context.Background(), "", auth.Key{Type: auth.UserKey, IssuedAt: time.Now(), Subject: email, IssuerID: id})
|
|
assert.Nil(t, err, fmt.Sprintf("Issuing login key expected to succeed: %s", err))
|
|
key := auth.Key{
|
|
ID: "id",
|
|
Type: auth.APIKey,
|
|
IssuerID: id,
|
|
Subject: email,
|
|
IssuedAt: time.Now(),
|
|
}
|
|
|
|
_, userToken, err := svc.Issue(context.Background(), "", auth.Key{Type: auth.UserKey, IssuedAt: time.Now(), IssuerID: id, Subject: email})
|
|
assert.Nil(t, err, fmt.Sprintf("Issuing user key expected to succeed: %s", err))
|
|
|
|
apiKey, apiToken, err := svc.Issue(context.Background(), secret, key)
|
|
assert.Nil(t, err, fmt.Sprintf("Issuing user's key expected to succeed: %s", err))
|
|
|
|
_, resetToken, err := svc.Issue(context.Background(), "", auth.Key{Type: auth.RecoveryKey, IssuedAt: time.Now()})
|
|
assert.Nil(t, err, fmt.Sprintf("Issuing reset key expected to succeed: %s", err))
|
|
|
|
cases := []struct {
|
|
desc string
|
|
id string
|
|
token string
|
|
err error
|
|
}{
|
|
{
|
|
desc: "retrieve user key",
|
|
id: apiKey.ID,
|
|
token: userToken,
|
|
err: nil,
|
|
},
|
|
{
|
|
desc: "retrieve non-existing user key",
|
|
id: "invalid",
|
|
token: userToken,
|
|
err: auth.ErrNotFound,
|
|
},
|
|
{
|
|
desc: "retrieve unauthorized",
|
|
id: apiKey.ID,
|
|
token: "wrong",
|
|
err: auth.ErrUnauthorizedAccess,
|
|
},
|
|
{
|
|
desc: "retrieve with API token",
|
|
id: apiKey.ID,
|
|
token: apiToken,
|
|
err: auth.ErrUnauthorizedAccess,
|
|
},
|
|
{
|
|
desc: "retrieve with reset token",
|
|
id: apiKey.ID,
|
|
token: resetToken,
|
|
err: auth.ErrUnauthorizedAccess,
|
|
},
|
|
}
|
|
|
|
for _, tc := range cases {
|
|
_, err := svc.RetrieveKey(context.Background(), tc.token, tc.id)
|
|
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s expected %s got %s\n", tc.desc, tc.err, err))
|
|
}
|
|
}
|
|
|
|
func TestIdentify(t *testing.T) {
|
|
svc := newService()
|
|
|
|
_, loginSecret, err := svc.Issue(context.Background(), "", auth.Key{Type: auth.UserKey, IssuedAt: time.Now(), IssuerID: id, Subject: email})
|
|
assert.Nil(t, err, fmt.Sprintf("Issuing login key expected to succeed: %s", err))
|
|
|
|
_, recoverySecret, err := svc.Issue(context.Background(), "", auth.Key{Type: auth.RecoveryKey, IssuedAt: time.Now(), IssuerID: id, Subject: email})
|
|
assert.Nil(t, err, fmt.Sprintf("Issuing reset key expected to succeed: %s", err))
|
|
|
|
_, apiSecret, err := svc.Issue(context.Background(), loginSecret, auth.Key{Type: auth.APIKey, IssuerID: id, Subject: email, IssuedAt: time.Now(), ExpiresAt: time.Now().Add(time.Minute)})
|
|
assert.Nil(t, err, fmt.Sprintf("Issuing user key expected to succeed: %s", err))
|
|
|
|
exp1 := time.Now().Add(-2 * time.Second)
|
|
_, expSecret, err := svc.Issue(context.Background(), loginSecret, auth.Key{Type: auth.APIKey, IssuedAt: time.Now(), ExpiresAt: exp1})
|
|
assert.Nil(t, err, fmt.Sprintf("Issuing expired user key expected to succeed: %s", err))
|
|
|
|
_, invalidSecret, err := svc.Issue(context.Background(), loginSecret, auth.Key{Type: 22, IssuedAt: time.Now()})
|
|
assert.Nil(t, err, fmt.Sprintf("Issuing user key expected to succeed: %s", err))
|
|
|
|
cases := []struct {
|
|
desc string
|
|
key string
|
|
idt auth.Identity
|
|
err error
|
|
}{
|
|
{
|
|
desc: "identify login key",
|
|
key: loginSecret,
|
|
idt: auth.Identity{id, email},
|
|
err: nil,
|
|
},
|
|
{
|
|
desc: "identify recovery key",
|
|
key: recoverySecret,
|
|
idt: auth.Identity{id, email},
|
|
err: nil,
|
|
},
|
|
{
|
|
desc: "identify API key",
|
|
key: apiSecret,
|
|
idt: auth.Identity{id, email},
|
|
err: nil,
|
|
},
|
|
{
|
|
desc: "identify expired API key",
|
|
key: expSecret,
|
|
idt: auth.Identity{},
|
|
err: auth.ErrAPIKeyExpired,
|
|
},
|
|
{
|
|
desc: "identify expired key",
|
|
key: invalidSecret,
|
|
idt: auth.Identity{},
|
|
err: auth.ErrUnauthorizedAccess,
|
|
},
|
|
{
|
|
desc: "identify invalid key",
|
|
key: "invalid",
|
|
idt: auth.Identity{},
|
|
err: auth.ErrUnauthorizedAccess,
|
|
},
|
|
}
|
|
|
|
for _, tc := range cases {
|
|
idt, err := svc.Identify(context.Background(), tc.key)
|
|
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s expected %s got %s\n", tc.desc, tc.err, err))
|
|
assert.Equal(t, tc.idt, idt, fmt.Sprintf("%s expected %s got %s\n", tc.desc, tc.idt, idt))
|
|
}
|
|
}
|
|
|
|
func TestCreateGroup(t *testing.T) {
|
|
svc := newService()
|
|
_, secret, err := svc.Issue(context.Background(), "", auth.Key{Type: auth.UserKey, IssuedAt: time.Now(), IssuerID: id, Subject: email})
|
|
assert.Nil(t, err, fmt.Sprintf("Issuing login key expected to succeed: %s", err))
|
|
|
|
key := auth.Key{
|
|
ID: "id",
|
|
Type: auth.APIKey,
|
|
IssuerID: id,
|
|
Subject: email,
|
|
IssuedAt: time.Now(),
|
|
}
|
|
|
|
_, apiToken, err := svc.Issue(context.Background(), secret, key)
|
|
assert.Nil(t, err, fmt.Sprintf("Issuing user's key expected to succeed: %s", err))
|
|
|
|
group := auth.Group{
|
|
Name: "Group",
|
|
Description: description,
|
|
}
|
|
|
|
parentGroup := auth.Group{
|
|
Name: "ParentGroup",
|
|
Description: description,
|
|
}
|
|
|
|
parent, err := svc.CreateGroup(context.Background(), apiToken, parentGroup)
|
|
assert.Nil(t, err, fmt.Sprintf("Creating parent group expected to succeed: %s", err))
|
|
|
|
cases := []struct {
|
|
desc string
|
|
group auth.Group
|
|
err error
|
|
}{
|
|
{
|
|
desc: "create new group",
|
|
group: group,
|
|
err: nil,
|
|
},
|
|
{
|
|
desc: "create group with existing name",
|
|
group: group,
|
|
err: nil,
|
|
},
|
|
{
|
|
desc: "create group with parent",
|
|
group: auth.Group{
|
|
Name: groupName,
|
|
ParentID: parent.ID,
|
|
},
|
|
err: nil,
|
|
},
|
|
{
|
|
desc: "create group with invalid parent",
|
|
group: auth.Group{
|
|
Name: groupName,
|
|
ParentID: "xxxxxxxxxx",
|
|
},
|
|
err: auth.ErrCreateGroup,
|
|
},
|
|
}
|
|
|
|
for _, tc := range cases {
|
|
_, err := svc.CreateGroup(context.Background(), apiToken, tc.group)
|
|
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
|
|
}
|
|
}
|
|
|
|
func TestUpdateGroup(t *testing.T) {
|
|
svc := newService()
|
|
_, secret, err := svc.Issue(context.Background(), "", auth.Key{Type: auth.UserKey, IssuedAt: time.Now(), IssuerID: id, Subject: email})
|
|
assert.Nil(t, err, fmt.Sprintf("Issuing login key expected to succeed: %s", err))
|
|
|
|
key := auth.Key{
|
|
ID: "id",
|
|
Type: auth.APIKey,
|
|
IssuerID: id,
|
|
Subject: email,
|
|
IssuedAt: time.Now(),
|
|
}
|
|
|
|
_, apiToken, err := svc.Issue(context.Background(), secret, key)
|
|
assert.Nil(t, err, fmt.Sprintf("Issuing user's key expected to succeed: %s", err))
|
|
|
|
group := auth.Group{
|
|
Name: "Group",
|
|
Description: description,
|
|
Metadata: auth.GroupMetadata{
|
|
"field": "value",
|
|
},
|
|
}
|
|
|
|
group, err = svc.CreateGroup(context.Background(), apiToken, group)
|
|
assert.Nil(t, err, fmt.Sprintf("Creating parent group failed: %s", err))
|
|
|
|
cases := []struct {
|
|
desc string
|
|
group auth.Group
|
|
err error
|
|
}{
|
|
{
|
|
desc: "update group",
|
|
group: auth.Group{
|
|
ID: group.ID,
|
|
Name: "NewName",
|
|
Description: "NewDescription",
|
|
Metadata: auth.GroupMetadata{
|
|
"field": "value2",
|
|
},
|
|
},
|
|
err: nil,
|
|
},
|
|
}
|
|
|
|
for _, tc := range cases {
|
|
g, err := svc.UpdateGroup(context.Background(), apiToken, tc.group)
|
|
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
|
|
assert.Equal(t, g.ID, tc.group.ID, fmt.Sprintf("ID: expected %s got %s\n", g.ID, tc.group.ID))
|
|
assert.Equal(t, g.Name, tc.group.Name, fmt.Sprintf("Name: expected %s got %s\n", g.Name, tc.group.Name))
|
|
assert.Equal(t, g.Description, tc.group.Description, fmt.Sprintf("Description: expected %s got %s\n", g.Description, tc.group.Description))
|
|
assert.Equal(t, g.Metadata["field"], g.Metadata["field"], fmt.Sprintf("Metadata: expected %s got %s\n", g.Metadata, tc.group.Metadata))
|
|
}
|
|
|
|
}
|
|
|
|
func TestViewGroup(t *testing.T) {
|
|
svc := newService()
|
|
_, secret, err := svc.Issue(context.Background(), "", auth.Key{Type: auth.UserKey, IssuedAt: time.Now(), IssuerID: id, Subject: email})
|
|
assert.Nil(t, err, fmt.Sprintf("Issuing login key expected to succeed: %s", err))
|
|
|
|
key := auth.Key{
|
|
ID: "id",
|
|
Type: auth.APIKey,
|
|
IssuerID: id,
|
|
Subject: email,
|
|
IssuedAt: time.Now(),
|
|
}
|
|
|
|
_, apiToken, err := svc.Issue(context.Background(), secret, key)
|
|
assert.Nil(t, err, fmt.Sprintf("Issuing user's key expected to succeed: %s", err))
|
|
|
|
group := auth.Group{
|
|
Name: "Group",
|
|
Description: description,
|
|
Metadata: auth.GroupMetadata{
|
|
"field": "value",
|
|
},
|
|
}
|
|
|
|
group, err = svc.CreateGroup(context.Background(), apiToken, group)
|
|
assert.Nil(t, err, fmt.Sprintf("Creating parent group failed: %s", err))
|
|
|
|
cases := []struct {
|
|
desc string
|
|
token string
|
|
groupID string
|
|
err error
|
|
}{
|
|
{
|
|
|
|
desc: "view group",
|
|
token: apiToken,
|
|
groupID: group.ID,
|
|
err: nil,
|
|
},
|
|
{
|
|
desc: "view group with unauthorized token",
|
|
token: "wrongtoken",
|
|
groupID: group.ID,
|
|
err: auth.ErrUnauthorizedAccess,
|
|
},
|
|
{
|
|
desc: "view group for wrong id",
|
|
token: apiToken,
|
|
groupID: "wrong",
|
|
err: auth.ErrGroupNotFound,
|
|
},
|
|
}
|
|
|
|
for _, tc := range cases {
|
|
_, err := svc.ViewGroup(context.Background(), tc.token, tc.groupID)
|
|
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
|
|
}
|
|
}
|
|
|
|
func TestListGroups(t *testing.T) {
|
|
svc := newService()
|
|
_, secret, err := svc.Issue(context.Background(), "", auth.Key{Type: auth.UserKey, IssuedAt: time.Now(), IssuerID: id, Subject: email})
|
|
assert.Nil(t, err, fmt.Sprintf("Issuing login key expected to succeed: %s", err))
|
|
|
|
key := auth.Key{
|
|
ID: "id",
|
|
Type: auth.APIKey,
|
|
IssuerID: id,
|
|
Subject: email,
|
|
IssuedAt: time.Now(),
|
|
}
|
|
|
|
_, apiToken, err := svc.Issue(context.Background(), secret, key)
|
|
assert.Nil(t, err, fmt.Sprintf("Issuing user's key expected to succeed: %s", err))
|
|
|
|
group := auth.Group{
|
|
Description: description,
|
|
Metadata: auth.GroupMetadata{
|
|
"field": "value",
|
|
},
|
|
}
|
|
n := uint64(10)
|
|
parentID := ""
|
|
for i := uint64(0); i < n; i++ {
|
|
group.Name = fmt.Sprintf("Group%d", i)
|
|
group.ParentID = parentID
|
|
g, err := svc.CreateGroup(context.Background(), apiToken, group)
|
|
require.Nil(t, err, fmt.Sprintf("unexpected error: %s\n", err))
|
|
parentID = g.ID
|
|
}
|
|
|
|
cases := map[string]struct {
|
|
token string
|
|
level uint64
|
|
size uint64
|
|
metadata auth.GroupMetadata
|
|
err error
|
|
}{
|
|
"list all groups": {
|
|
token: apiToken,
|
|
level: 5,
|
|
size: n,
|
|
err: nil,
|
|
},
|
|
"list groups for level 1": {
|
|
token: apiToken,
|
|
level: 1,
|
|
size: n,
|
|
err: nil,
|
|
},
|
|
"list all groups with wrong token": {
|
|
token: "wrongToken",
|
|
level: 5,
|
|
size: 0,
|
|
err: auth.ErrUnauthorizedAccess,
|
|
},
|
|
}
|
|
|
|
for desc, tc := range cases {
|
|
page, err := svc.ListGroups(context.Background(), tc.token, auth.PageMetadata{Level: tc.level, Metadata: tc.metadata})
|
|
size := uint64(len(page.Groups))
|
|
assert.Equal(t, tc.size, size, fmt.Sprintf("%s: expected %d got %d\n", desc, tc.size, size))
|
|
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", desc, tc.err, err))
|
|
}
|
|
|
|
}
|
|
|
|
func TestListChildren(t *testing.T) {
|
|
svc := newService()
|
|
_, secret, err := svc.Issue(context.Background(), "", auth.Key{Type: auth.UserKey, IssuedAt: time.Now(), IssuerID: id, Subject: email})
|
|
assert.Nil(t, err, fmt.Sprintf("Issuing login key expected to succeed: %s", err))
|
|
|
|
key := auth.Key{
|
|
ID: "id",
|
|
Type: auth.APIKey,
|
|
IssuerID: id,
|
|
Subject: email,
|
|
IssuedAt: time.Now(),
|
|
}
|
|
|
|
_, apiToken, err := svc.Issue(context.Background(), secret, key)
|
|
assert.Nil(t, err, fmt.Sprintf("Issuing user's key expected to succeed: %s", err))
|
|
|
|
group := auth.Group{
|
|
Description: description,
|
|
Metadata: auth.GroupMetadata{
|
|
"field": "value",
|
|
},
|
|
}
|
|
n := uint64(10)
|
|
parentID := ""
|
|
groupIDs := make([]string, n)
|
|
for i := uint64(0); i < n; i++ {
|
|
group.Name = fmt.Sprintf("Group%d", i)
|
|
group.ParentID = parentID
|
|
g, err := svc.CreateGroup(context.Background(), apiToken, group)
|
|
require.Nil(t, err, fmt.Sprintf("unexpected error: %s\n", err))
|
|
parentID = g.ID
|
|
groupIDs[i] = g.ID
|
|
}
|
|
|
|
cases := map[string]struct {
|
|
token string
|
|
level uint64
|
|
size uint64
|
|
id string
|
|
metadata auth.GroupMetadata
|
|
err error
|
|
}{
|
|
"list all children": {
|
|
token: apiToken,
|
|
level: 5,
|
|
id: groupIDs[0],
|
|
size: n,
|
|
err: nil,
|
|
},
|
|
"list all groups with wrong token": {
|
|
token: "wrongToken",
|
|
level: 5,
|
|
size: 0,
|
|
err: auth.ErrUnauthorizedAccess,
|
|
},
|
|
}
|
|
|
|
for desc, tc := range cases {
|
|
page, err := svc.ListChildren(context.Background(), tc.token, tc.id, auth.PageMetadata{Level: tc.level, Metadata: tc.metadata})
|
|
size := uint64(len(page.Groups))
|
|
assert.Equal(t, tc.size, size, fmt.Sprintf("%s: expected %d got %d\n", desc, tc.size, size))
|
|
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", desc, tc.err, err))
|
|
}
|
|
}
|
|
|
|
func TestListParents(t *testing.T) {
|
|
svc := newService()
|
|
_, secret, err := svc.Issue(context.Background(), "", auth.Key{Type: auth.UserKey, IssuedAt: time.Now(), IssuerID: id, Subject: email})
|
|
assert.Nil(t, err, fmt.Sprintf("Issuing login key expected to succeed: %s", err))
|
|
|
|
key := auth.Key{
|
|
ID: "id",
|
|
Type: auth.APIKey,
|
|
IssuerID: id,
|
|
Subject: email,
|
|
IssuedAt: time.Now(),
|
|
}
|
|
|
|
_, apiToken, err := svc.Issue(context.Background(), secret, key)
|
|
assert.Nil(t, err, fmt.Sprintf("Issuing user's key expected to succeed: %s", err))
|
|
|
|
group := auth.Group{
|
|
Description: description,
|
|
Metadata: auth.GroupMetadata{
|
|
"field": "value",
|
|
},
|
|
}
|
|
n := uint64(10)
|
|
parentID := ""
|
|
groupIDs := make([]string, n)
|
|
for i := uint64(0); i < n; i++ {
|
|
group.Name = fmt.Sprintf("Group%d", i)
|
|
group.ParentID = parentID
|
|
g, err := svc.CreateGroup(context.Background(), apiToken, group)
|
|
require.Nil(t, err, fmt.Sprintf("unexpected error: %s\n", err))
|
|
parentID = g.ID
|
|
groupIDs[i] = g.ID
|
|
}
|
|
|
|
cases := map[string]struct {
|
|
token string
|
|
level uint64
|
|
size uint64
|
|
id string
|
|
metadata auth.GroupMetadata
|
|
err error
|
|
}{
|
|
"list all parents": {
|
|
token: apiToken,
|
|
level: 5,
|
|
id: groupIDs[n-1],
|
|
size: n,
|
|
err: nil,
|
|
},
|
|
"list all parents with wrong token": {
|
|
token: "wrongToken",
|
|
level: 5,
|
|
size: 0,
|
|
err: auth.ErrUnauthorizedAccess,
|
|
},
|
|
}
|
|
|
|
for desc, tc := range cases {
|
|
page, err := svc.ListParents(context.Background(), tc.token, tc.id, auth.PageMetadata{Level: tc.level, Metadata: tc.metadata})
|
|
size := uint64(len(page.Groups))
|
|
assert.Equal(t, tc.size, size, fmt.Sprintf("%s: expected %d got %d\n", desc, tc.size, size))
|
|
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", desc, tc.err, err))
|
|
}
|
|
}
|
|
|
|
func TestListMembers(t *testing.T) {
|
|
svc := newService()
|
|
_, secret, err := svc.Issue(context.Background(), "", auth.Key{Type: auth.UserKey, IssuedAt: time.Now(), IssuerID: id, Subject: email})
|
|
assert.Nil(t, err, fmt.Sprintf("Issuing login key expected to succeed: %s", err))
|
|
|
|
key := auth.Key{
|
|
ID: "id",
|
|
Type: auth.APIKey,
|
|
IssuerID: id,
|
|
Subject: email,
|
|
IssuedAt: time.Now(),
|
|
}
|
|
|
|
_, apiToken, err := svc.Issue(context.Background(), secret, key)
|
|
assert.Nil(t, err, fmt.Sprintf("Issuing user's key expected to succeed: %s", err))
|
|
|
|
group := auth.Group{
|
|
Description: description,
|
|
Metadata: auth.GroupMetadata{
|
|
"field": "value",
|
|
},
|
|
}
|
|
g, err := svc.CreateGroup(context.Background(), apiToken, group)
|
|
assert.Nil(t, err, fmt.Sprintf("Creating group expected to succeed: %s", err))
|
|
group.ID = g.ID
|
|
|
|
n := uint64(10)
|
|
for i := uint64(0); i < n; i++ {
|
|
uid, err := idProvider.ID()
|
|
require.Nil(t, err, fmt.Sprintf("unexpected error: %s\n", err))
|
|
|
|
err = svc.Assign(context.Background(), apiToken, group.ID, "things", uid)
|
|
require.Nil(t, err, fmt.Sprintf("Assign member expected to succeed: %s\n", err))
|
|
}
|
|
|
|
cases := map[string]struct {
|
|
token string
|
|
size uint64
|
|
offset uint64
|
|
limit uint64
|
|
group auth.Group
|
|
metadata auth.GroupMetadata
|
|
err error
|
|
}{
|
|
"list all members": {
|
|
token: apiToken,
|
|
offset: 0,
|
|
limit: n,
|
|
group: group,
|
|
size: n,
|
|
err: nil,
|
|
},
|
|
"list half members": {
|
|
token: apiToken,
|
|
offset: n / 2,
|
|
limit: n,
|
|
group: group,
|
|
size: n / 2,
|
|
err: nil,
|
|
},
|
|
"list all members with wrong token": {
|
|
token: "wrongToken",
|
|
offset: 0,
|
|
limit: n,
|
|
size: 0,
|
|
err: auth.ErrUnauthorizedAccess,
|
|
},
|
|
}
|
|
|
|
for desc, tc := range cases {
|
|
page, err := svc.ListMembers(context.Background(), tc.token, tc.group.ID, "things", auth.PageMetadata{Offset: tc.offset, Limit: tc.limit, Metadata: tc.metadata})
|
|
size := uint64(len(page.Members))
|
|
assert.Equal(t, tc.size, size, fmt.Sprintf("%s: expected %d got %d\n", desc, tc.size, size))
|
|
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", desc, tc.err, err))
|
|
}
|
|
|
|
}
|
|
|
|
func TestListMemberships(t *testing.T) {
|
|
svc := newService()
|
|
_, secret, err := svc.Issue(context.Background(), "", auth.Key{Type: auth.UserKey, IssuedAt: time.Now(), IssuerID: id, Subject: email})
|
|
assert.Nil(t, err, fmt.Sprintf("Issuing login key expected to succeed: %s", err))
|
|
|
|
key := auth.Key{
|
|
ID: "id",
|
|
Type: auth.APIKey,
|
|
IssuerID: id,
|
|
Subject: email,
|
|
IssuedAt: time.Now(),
|
|
}
|
|
|
|
_, apiToken, err := svc.Issue(context.Background(), secret, key)
|
|
assert.Nil(t, err, fmt.Sprintf("Issuing user's key expected to succeed: %s", err))
|
|
|
|
group := auth.Group{
|
|
Description: description,
|
|
Metadata: auth.GroupMetadata{
|
|
"field": "value",
|
|
},
|
|
}
|
|
|
|
memberID, err := idProvider.ID()
|
|
require.Nil(t, err, fmt.Sprintf("unexpected error: %s\n", err))
|
|
|
|
n := uint64(10)
|
|
for i := uint64(0); i < n; i++ {
|
|
group.Name = fmt.Sprintf("Group%d", i)
|
|
g, err := svc.CreateGroup(context.Background(), apiToken, group)
|
|
require.Nil(t, err, fmt.Sprintf("unexpected error: %s\n", err))
|
|
|
|
err = svc.Assign(context.Background(), apiToken, g.ID, "things", memberID)
|
|
require.Nil(t, err, fmt.Sprintf("Assign member expected to succeed: %s\n", err))
|
|
}
|
|
|
|
cases := map[string]struct {
|
|
token string
|
|
size uint64
|
|
offset uint64
|
|
limit uint64
|
|
group auth.Group
|
|
metadata auth.GroupMetadata
|
|
err error
|
|
}{
|
|
"list all members": {
|
|
token: apiToken,
|
|
offset: 0,
|
|
limit: n,
|
|
group: group,
|
|
size: n,
|
|
err: nil,
|
|
},
|
|
"list half members": {
|
|
token: apiToken,
|
|
offset: n / 2,
|
|
limit: n,
|
|
group: group,
|
|
size: n / 2,
|
|
err: nil,
|
|
},
|
|
"list all members with wrong token": {
|
|
token: "wrongToken",
|
|
offset: 0,
|
|
limit: n,
|
|
size: 0,
|
|
err: auth.ErrUnauthorizedAccess,
|
|
},
|
|
}
|
|
|
|
for desc, tc := range cases {
|
|
page, err := svc.ListMemberships(context.Background(), tc.token, memberID, auth.PageMetadata{Limit: tc.limit, Offset: tc.offset, Metadata: tc.metadata})
|
|
size := uint64(len(page.Groups))
|
|
assert.Equal(t, tc.size, size, fmt.Sprintf("%s: expected %d got %d\n", desc, tc.size, size))
|
|
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", desc, tc.err, err))
|
|
}
|
|
}
|
|
|
|
func TestRemoveGroup(t *testing.T) {
|
|
svc := newService()
|
|
_, secret, err := svc.Issue(context.Background(), "", auth.Key{Type: auth.UserKey, IssuedAt: time.Now(), IssuerID: id, Subject: email})
|
|
assert.Nil(t, err, fmt.Sprintf("Issuing login key expected to succeed: %s", err))
|
|
|
|
key := auth.Key{
|
|
ID: "id",
|
|
Type: auth.APIKey,
|
|
IssuerID: id,
|
|
Subject: email,
|
|
IssuedAt: time.Now(),
|
|
}
|
|
|
|
_, apiToken, err := svc.Issue(context.Background(), secret, key)
|
|
assert.Nil(t, err, fmt.Sprintf("Issuing user's key expected to succeed: %s", err))
|
|
|
|
uid, err := idProvider.ID()
|
|
require.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err))
|
|
|
|
creationTime := time.Now().UTC()
|
|
group := auth.Group{
|
|
Name: groupName,
|
|
OwnerID: uid,
|
|
CreatedAt: creationTime,
|
|
UpdatedAt: creationTime,
|
|
}
|
|
|
|
group, err = svc.CreateGroup(context.Background(), apiToken, group)
|
|
require.Nil(t, err, fmt.Sprintf("group save got unexpected error: %s", err))
|
|
|
|
err = svc.RemoveGroup(context.Background(), "wrongToken", group.ID)
|
|
assert.True(t, errors.Contains(err, auth.ErrUnauthorizedAccess), fmt.Sprintf("Unauthorized access: expected %v got %v", auth.ErrUnauthorizedAccess, err))
|
|
|
|
err = svc.RemoveGroup(context.Background(), apiToken, "wrongID")
|
|
assert.True(t, errors.Contains(err, auth.ErrGroupNotFound), fmt.Sprintf("Remove group with wrong id: expected %v got %v", auth.ErrGroupNotFound, err))
|
|
|
|
gp, err := svc.ListGroups(context.Background(), apiToken, auth.PageMetadata{Level: auth.MaxLevel})
|
|
require.Nil(t, err, fmt.Sprintf("list groups unexpected error: %s", err))
|
|
assert.True(t, gp.Total == 1, fmt.Sprintf("retrieve members of a group: expected %d got %d\n", 1, gp.Total))
|
|
|
|
err = svc.RemoveGroup(context.Background(), apiToken, group.ID)
|
|
assert.True(t, errors.Contains(err, nil), fmt.Sprintf("Unauthorized access: expected %v got %v", nil, err))
|
|
|
|
gp, err = svc.ListGroups(context.Background(), apiToken, auth.PageMetadata{Level: auth.MaxLevel})
|
|
require.Nil(t, err, fmt.Sprintf("list groups save unexpected error: %s", err))
|
|
assert.True(t, gp.Total == 0, fmt.Sprintf("retrieve members of a group: expected %d got %d\n", 0, gp.Total))
|
|
|
|
}
|
|
|
|
func TestAssign(t *testing.T) {
|
|
svc := newService()
|
|
_, secret, err := svc.Issue(context.Background(), "", auth.Key{Type: auth.UserKey, IssuedAt: time.Now(), IssuerID: id, Subject: email})
|
|
assert.Nil(t, err, fmt.Sprintf("Issuing login key expected to succeed: %s", err))
|
|
|
|
key := auth.Key{
|
|
ID: "id",
|
|
Type: auth.APIKey,
|
|
IssuerID: id,
|
|
Subject: email,
|
|
IssuedAt: time.Now(),
|
|
}
|
|
|
|
_, apiToken, err := svc.Issue(context.Background(), secret, key)
|
|
assert.Nil(t, err, fmt.Sprintf("Issuing user's key expected to succeed: %s", err))
|
|
|
|
uid, err := idProvider.ID()
|
|
require.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err))
|
|
|
|
creationTime := time.Now().UTC()
|
|
group := auth.Group{
|
|
Name: groupName + "Updated",
|
|
OwnerID: uid,
|
|
CreatedAt: creationTime,
|
|
UpdatedAt: creationTime,
|
|
}
|
|
|
|
group, err = svc.CreateGroup(context.Background(), apiToken, group)
|
|
require.Nil(t, err, fmt.Sprintf("group save got unexpected error: %s", err))
|
|
|
|
mid, err := idProvider.ID()
|
|
require.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err))
|
|
|
|
err = svc.Assign(context.Background(), apiToken, group.ID, "things", mid)
|
|
require.Nil(t, err, fmt.Sprintf("member assign save unexpected error: %s", err))
|
|
|
|
mp, err := svc.ListMembers(context.Background(), apiToken, group.ID, "things", auth.PageMetadata{Offset: 0, Limit: 10})
|
|
require.Nil(t, err, fmt.Sprintf("member assign save unexpected error: %s", err))
|
|
assert.True(t, mp.Total == 1, fmt.Sprintf("retrieve members of a group: expected %d got %d\n", 1, mp.Total))
|
|
|
|
err = svc.Assign(context.Background(), "wrongToken", group.ID, "things", mid)
|
|
assert.True(t, errors.Contains(err, auth.ErrUnauthorizedAccess), fmt.Sprintf("Unauthorized access: expected %v got %v", auth.ErrUnauthorizedAccess, err))
|
|
|
|
}
|
|
|
|
func TestUnassign(t *testing.T) {
|
|
svc := newService()
|
|
_, secret, err := svc.Issue(context.Background(), "", auth.Key{Type: auth.UserKey, IssuedAt: time.Now(), IssuerID: id, Subject: email})
|
|
assert.Nil(t, err, fmt.Sprintf("Issuing login key expected to succeed: %s", err))
|
|
|
|
key := auth.Key{
|
|
ID: "id",
|
|
Type: auth.APIKey,
|
|
IssuerID: id,
|
|
Subject: email,
|
|
IssuedAt: time.Now(),
|
|
}
|
|
|
|
_, apiToken, err := svc.Issue(context.Background(), secret, key)
|
|
assert.Nil(t, err, fmt.Sprintf("Issuing user's key expected to succeed: %s", err))
|
|
|
|
uid, err := idProvider.ID()
|
|
require.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err))
|
|
|
|
creationTime := time.Now().UTC()
|
|
group := auth.Group{
|
|
Name: groupName + "Updated",
|
|
OwnerID: uid,
|
|
CreatedAt: creationTime,
|
|
UpdatedAt: creationTime,
|
|
}
|
|
|
|
group, err = svc.CreateGroup(context.Background(), apiToken, group)
|
|
require.Nil(t, err, fmt.Sprintf("group save got unexpected error: %s", err))
|
|
|
|
mid, err := idProvider.ID()
|
|
require.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err))
|
|
|
|
err = svc.Assign(context.Background(), apiToken, group.ID, "things", mid)
|
|
require.Nil(t, err, fmt.Sprintf("member assign save unexpected error: %s", err))
|
|
|
|
mp, err := svc.ListMembers(context.Background(), apiToken, group.ID, "things", auth.PageMetadata{Limit: 10, Offset: 0})
|
|
require.Nil(t, err, fmt.Sprintf("member assign save unexpected error: %s", err))
|
|
assert.True(t, mp.Total == 1, fmt.Sprintf("retrieve members of a group: expected %d got %d\n", 1, mp.Total))
|
|
|
|
err = svc.Unassign(context.Background(), apiToken, group.ID, mid)
|
|
require.Nil(t, err, fmt.Sprintf("member unassign save unexpected error: %s", err))
|
|
|
|
mp, err = svc.ListMembers(context.Background(), apiToken, group.ID, "things", auth.PageMetadata{Limit: 10, Offset: 0})
|
|
require.Nil(t, err, fmt.Sprintf("member assign save unexpected error: %s", err))
|
|
assert.True(t, mp.Total == 0, fmt.Sprintf("retrieve members of a group: expected %d got %d\n", 0, mp.Total))
|
|
|
|
err = svc.Unassign(context.Background(), "wrongToken", group.ID, mid)
|
|
assert.True(t, errors.Contains(err, auth.ErrUnauthorizedAccess), fmt.Sprintf("Unauthorized access: expected %v got %v", auth.ErrUnauthorizedAccess, err))
|
|
|
|
err = svc.Unassign(context.Background(), apiToken, group.ID, mid)
|
|
assert.True(t, errors.Contains(err, auth.ErrGroupNotFound), fmt.Sprintf("Unauthorized access: expected %v got %v", nil, err))
|
|
}
|