508 lines
12 KiB
Go
508 lines
12 KiB
Go
package repository
|
|
|
|
import (
|
|
"backend/pkg/permission/domain"
|
|
"backend/pkg/permission/domain/entity"
|
|
"backend/pkg/permission/domain/permission"
|
|
domainRepo "backend/pkg/permission/domain/repository"
|
|
"context"
|
|
"fmt"
|
|
"github.com/alicebob/miniredis/v2"
|
|
"github.com/zeromicro/go-zero/core/stores/redis"
|
|
"testing"
|
|
"time"
|
|
|
|
mgo "backend/pkg/library/mongo"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
"github.com/zeromicro/go-zero/core/stores/cache"
|
|
"go.mongodb.org/mongo-driver/v2/bson"
|
|
)
|
|
|
|
func setupPermissionRepo(db string) (domainRepo.PermissionRepository, func(), error) {
|
|
h, p, tearDown, err := startMongoContainer()
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
s, _ := miniredis.Run()
|
|
|
|
conf := &mgo.Conf{
|
|
Schema: mongoSchema,
|
|
Host: fmt.Sprintf("%s:%s", h, p),
|
|
Database: db,
|
|
MaxStaleness: 300,
|
|
MaxPoolSize: 100,
|
|
MinPoolSize: 100,
|
|
MaxConnIdleTime: 300,
|
|
Compressors: []string{},
|
|
EnableStandardReadWriteSplitMode: false,
|
|
ConnectTimeoutMs: 3000,
|
|
}
|
|
|
|
cacheConf := cache.CacheConf{
|
|
cache.NodeConf{
|
|
RedisConf: redis.RedisConf{
|
|
Host: s.Addr(),
|
|
Type: redis.NodeType,
|
|
},
|
|
Weight: 100,
|
|
},
|
|
}
|
|
|
|
cacheOpts := []cache.Option{
|
|
cache.WithExpiry(1000 * time.Microsecond),
|
|
cache.WithNotFoundExpiry(1000 * time.Microsecond),
|
|
}
|
|
|
|
param := PermissionRepositoryParam{
|
|
Conf: conf,
|
|
CacheConf: cacheConf,
|
|
CacheOpts: cacheOpts,
|
|
}
|
|
repo := NewPermissionRepository(param)
|
|
_, _ = repo.Index20251009001UP(context.Background())
|
|
|
|
return repo, tearDown, nil
|
|
}
|
|
|
|
func TestPermissionRepository_FindOne(t *testing.T) {
|
|
repo, tearDown, err := setupPermissionRepo("testDB")
|
|
defer tearDown()
|
|
assert.NoError(t, err)
|
|
|
|
ctx := context.Background()
|
|
// 準備測試數據
|
|
testPerm := &entity.Permission{
|
|
ID: bson.NewObjectID(),
|
|
Name: "test.permission",
|
|
State: domain.RecordActive,
|
|
Type: permission.TypeBackend,
|
|
}
|
|
testPerm.CreateTime = time.Now().Unix()
|
|
testPerm.UpdateTime = testPerm.CreateTime
|
|
|
|
// 插入測試數據
|
|
_, err = repo.(*PermissionRepository).DB.GetClient().InsertOne(ctx, testPerm)
|
|
require.NoError(t, err)
|
|
|
|
tests := []struct {
|
|
name string
|
|
id string
|
|
wantErr error
|
|
check func(*testing.T, *entity.Permission)
|
|
}{
|
|
{
|
|
name: "找到存在的權限",
|
|
id: testPerm.ID.Hex(),
|
|
wantErr: nil,
|
|
check: func(t *testing.T, perm *entity.Permission) {
|
|
assert.Equal(t, testPerm.Name, perm.Name)
|
|
assert.Equal(t, testPerm.State, perm.State)
|
|
},
|
|
},
|
|
{
|
|
name: "無效的 ObjectID",
|
|
id: "invalid-id",
|
|
wantErr: ErrInvalidObjectID,
|
|
check: nil,
|
|
},
|
|
{
|
|
name: "不存在的權限",
|
|
id: bson.NewObjectID().Hex(),
|
|
wantErr: ErrNotFound,
|
|
check: nil,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
perm, err := repo.FindOne(ctx, tt.id)
|
|
|
|
if tt.wantErr != nil {
|
|
assert.ErrorIs(t, err, tt.wantErr)
|
|
assert.Nil(t, perm)
|
|
} else {
|
|
assert.NoError(t, err)
|
|
assert.NotNil(t, perm)
|
|
if tt.check != nil {
|
|
tt.check(t, perm)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestPermissionRepository_FindByName(t *testing.T) {
|
|
repo, tearDown, err := setupPermissionRepo("testDB")
|
|
defer tearDown()
|
|
assert.NoError(t, err)
|
|
|
|
ctx := context.Background()
|
|
|
|
// 準備測試數據
|
|
testPerms := []*entity.Permission{
|
|
{
|
|
ID: bson.NewObjectID(),
|
|
Name: "user.list",
|
|
State: domain.RecordActive,
|
|
Type: permission.TypeBackend,
|
|
},
|
|
{
|
|
ID: bson.NewObjectID(),
|
|
Name: "user.create",
|
|
State: domain.RecordActive,
|
|
Type: permission.TypeBackend,
|
|
},
|
|
}
|
|
|
|
for _, perm := range testPerms {
|
|
perm.CreateTime = time.Now().Unix()
|
|
perm.UpdateTime = perm.CreateTime
|
|
_, err := repo.(*PermissionRepository).DB.GetClient().InsertOne(ctx, perm)
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
tests := []struct {
|
|
name string
|
|
permName string
|
|
wantErr error
|
|
wantName string
|
|
}{
|
|
{
|
|
name: "找到存在的權限",
|
|
permName: "user.list",
|
|
wantErr: nil,
|
|
wantName: "user.list",
|
|
},
|
|
{
|
|
name: "找到另一個權限",
|
|
permName: "user.create",
|
|
wantErr: nil,
|
|
wantName: "user.create",
|
|
},
|
|
{
|
|
name: "不存在的權限",
|
|
permName: "user.delete",
|
|
wantErr: ErrNotFound,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
perm, err := repo.FindByName(ctx, tt.permName)
|
|
|
|
if tt.wantErr != nil {
|
|
assert.ErrorIs(t, err, tt.wantErr)
|
|
assert.Nil(t, perm)
|
|
} else {
|
|
assert.NoError(t, err)
|
|
assert.NotNil(t, perm)
|
|
assert.Equal(t, tt.wantName, perm.Name)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestPermissionRepository_GetByNames(t *testing.T) {
|
|
repo, tearDown, err := setupPermissionRepo("testDB")
|
|
defer tearDown()
|
|
assert.NoError(t, err)
|
|
ctx := context.Background()
|
|
|
|
// 準備測試數據
|
|
testPerms := []*entity.Permission{
|
|
{ID: bson.NewObjectID(), Name: "user.list", State: domain.RecordActive},
|
|
{ID: bson.NewObjectID(), Name: "user.create", State: domain.RecordActive},
|
|
{ID: bson.NewObjectID(), Name: "user.update", State: domain.RecordActive},
|
|
}
|
|
|
|
for _, perm := range testPerms {
|
|
perm.CreateTime = time.Now().Unix()
|
|
perm.UpdateTime = perm.CreateTime
|
|
_, err := repo.(*PermissionRepository).DB.GetClient().InsertOne(ctx, perm)
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
tests := []struct {
|
|
name string
|
|
names []string
|
|
wantCount int
|
|
wantErr error
|
|
}{
|
|
{
|
|
name: "找到多個權限",
|
|
names: []string{"user.list", "user.create"},
|
|
wantCount: 2,
|
|
wantErr: nil,
|
|
},
|
|
{
|
|
name: "找到單一權限",
|
|
names: []string{"user.update"},
|
|
wantCount: 1,
|
|
wantErr: nil,
|
|
},
|
|
{
|
|
name: "找到所有權限",
|
|
names: []string{"user.list", "user.create", "user.update"},
|
|
wantCount: 3,
|
|
wantErr: nil,
|
|
},
|
|
{
|
|
name: "部分存在的權限",
|
|
names: []string{"user.list", "user.delete"},
|
|
wantCount: 1,
|
|
wantErr: nil,
|
|
},
|
|
{
|
|
name: "不存在的權限",
|
|
names: []string{"admin.super"},
|
|
wantCount: 0,
|
|
wantErr: nil,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
perms, err := repo.GetByNames(ctx, tt.names)
|
|
|
|
if tt.wantErr != nil {
|
|
assert.ErrorIs(t, err, tt.wantErr)
|
|
} else {
|
|
assert.NoError(t, err)
|
|
assert.Len(t, perms, tt.wantCount)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestPermissionRepository_FindByHTTP(t *testing.T) {
|
|
repo, tearDown, err := setupPermissionRepo("testDB")
|
|
defer tearDown()
|
|
assert.NoError(t, err)
|
|
|
|
ctx := context.Background()
|
|
|
|
// 準備測試數據
|
|
testPerms := []*entity.Permission{
|
|
{
|
|
ID: bson.NewObjectID(),
|
|
Name: "user.list",
|
|
HTTPPath: "/api/users",
|
|
HTTPMethod: "GET",
|
|
State: domain.RecordActive,
|
|
},
|
|
{
|
|
ID: bson.NewObjectID(),
|
|
Name: "user.create",
|
|
HTTPPath: "/api/users",
|
|
HTTPMethod: "POST",
|
|
State: domain.RecordActive,
|
|
},
|
|
}
|
|
|
|
for _, perm := range testPerms {
|
|
perm.CreateTime = time.Now().Unix()
|
|
perm.UpdateTime = perm.CreateTime
|
|
_, err := repo.(*PermissionRepository).DB.GetClient().InsertOne(ctx, perm)
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
tests := []struct {
|
|
name string
|
|
path string
|
|
method string
|
|
wantName string
|
|
wantErr error
|
|
}{
|
|
{
|
|
name: "找到 GET 權限",
|
|
path: "/api/users",
|
|
method: "GET",
|
|
wantName: "user.list",
|
|
wantErr: nil,
|
|
},
|
|
{
|
|
name: "找到 POST 權限",
|
|
path: "/api/users",
|
|
method: "POST",
|
|
wantName: "user.create",
|
|
wantErr: nil,
|
|
},
|
|
{
|
|
name: "不存在的路徑",
|
|
path: "/api/admin",
|
|
method: "GET",
|
|
wantErr: ErrNotFound,
|
|
},
|
|
{
|
|
name: "不存在的方法",
|
|
path: "/api/users",
|
|
method: "DELETE",
|
|
wantErr: ErrNotFound,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
perm, err := repo.FindByHTTP(ctx, tt.path, tt.method)
|
|
|
|
if tt.wantErr != nil {
|
|
assert.ErrorIs(t, err, tt.wantErr)
|
|
assert.Nil(t, perm)
|
|
} else {
|
|
assert.NoError(t, err)
|
|
assert.NotNil(t, perm)
|
|
assert.Equal(t, tt.wantName, perm.Name)
|
|
assert.Equal(t, tt.path, perm.HTTPPath)
|
|
assert.Equal(t, tt.method, perm.HTTPMethod)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestPermissionRepository_List(t *testing.T) {
|
|
repo, tearDown, err := setupPermissionRepo("testDB")
|
|
defer tearDown()
|
|
assert.NoError(t, err)
|
|
|
|
ctx := context.Background()
|
|
|
|
// 準備測試數據
|
|
parent := &entity.Permission{
|
|
ID: bson.NewObjectID(),
|
|
ParentID: bson.ObjectID{},
|
|
Name: "user",
|
|
State: domain.RecordActive,
|
|
Type: permission.TypeBackend,
|
|
}
|
|
parent.CreateTime = time.Now().Unix()
|
|
parent.UpdateTime = parent.CreateTime
|
|
|
|
child := &entity.Permission{
|
|
ID: bson.NewObjectID(),
|
|
ParentID: parent.ID,
|
|
Name: "user.list",
|
|
State: domain.RecordActive,
|
|
Type: permission.TypeBackend,
|
|
}
|
|
child.CreateTime = time.Now().Unix()
|
|
child.UpdateTime = child.CreateTime
|
|
|
|
inactiveChild := &entity.Permission{
|
|
ID: bson.NewObjectID(),
|
|
ParentID: parent.ID,
|
|
Name: "user.delete",
|
|
State: domain.RecordInactive,
|
|
Type: permission.TypeBackend,
|
|
}
|
|
inactiveChild.CreateTime = time.Now().Unix()
|
|
inactiveChild.UpdateTime = inactiveChild.CreateTime
|
|
|
|
for _, perm := range []*entity.Permission{parent, child, inactiveChild} {
|
|
_, err := repo.(*PermissionRepository).DB.GetClient().InsertOne(ctx, perm)
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
tests := []struct {
|
|
name string
|
|
filter domainRepo.PermissionFilter
|
|
wantCount int
|
|
wantNames []string
|
|
}{
|
|
{
|
|
name: "列出所有權限",
|
|
filter: domainRepo.PermissionFilter{},
|
|
wantCount: 3,
|
|
},
|
|
{
|
|
name: "只列出啟用的權限",
|
|
filter: domainRepo.PermissionFilter{
|
|
Status: func() *permission.RecordState {
|
|
s := domain.RecordActive
|
|
return &s
|
|
}(),
|
|
},
|
|
wantCount: 2,
|
|
wantNames: []string{"user", "user.list"},
|
|
},
|
|
{
|
|
name: "只列出停用的權限",
|
|
filter: domainRepo.PermissionFilter{
|
|
Status: func() *permission.RecordState {
|
|
s := domain.RecordInactive
|
|
return &s
|
|
}(),
|
|
},
|
|
wantCount: 1,
|
|
wantNames: []string{"user.delete"},
|
|
},
|
|
{
|
|
name: "按類型過濾",
|
|
filter: domainRepo.PermissionFilter{
|
|
Type: func() *permission.Type {
|
|
t := permission.TypeBackend
|
|
return &t
|
|
}(),
|
|
},
|
|
wantCount: 3,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
perms, err := repo.List(ctx, tt.filter)
|
|
|
|
assert.NoError(t, err)
|
|
assert.Len(t, perms, tt.wantCount)
|
|
|
|
if len(tt.wantNames) > 0 {
|
|
names := make([]string, len(perms))
|
|
for i, p := range perms {
|
|
names[i] = p.Name
|
|
}
|
|
for _, wantName := range tt.wantNames {
|
|
assert.Contains(t, names, wantName)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestPermissionRepository_ListActive(t *testing.T) {
|
|
repo, tearDown, err := setupPermissionRepo("testDB")
|
|
defer tearDown()
|
|
assert.NoError(t, err)
|
|
|
|
ctx := context.Background()
|
|
|
|
// 準備測試數據
|
|
activePerms := []*entity.Permission{
|
|
{ID: bson.NewObjectID(), Name: "user.list", State: domain.RecordActive},
|
|
{ID: bson.NewObjectID(), Name: "user.create", State: domain.RecordActive},
|
|
}
|
|
|
|
inactivePerms := []*entity.Permission{
|
|
{ID: bson.NewObjectID(), Name: "user.delete", State: domain.RecordInactive},
|
|
{ID: bson.NewObjectID(), Name: "user.admin", State: domain.RecordDeleted},
|
|
}
|
|
|
|
allPerms := append(activePerms, inactivePerms...)
|
|
for _, perm := range allPerms {
|
|
perm.CreateTime = time.Now().Unix()
|
|
perm.UpdateTime = perm.CreateTime
|
|
_, err := repo.(*PermissionRepository).DB.GetClient().InsertOne(ctx, perm)
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
t.Run("只返回啟用的權限", func(t *testing.T) {
|
|
perms, err := repo.ListActive(ctx)
|
|
|
|
assert.NoError(t, err)
|
|
assert.Len(t, perms, 2)
|
|
|
|
for _, perm := range perms {
|
|
assert.Equal(t, domain.RecordActive, perm.State)
|
|
}
|
|
})
|
|
}
|