本次提交完成了角色权限体系的重构,主要包括: 1. 数据库迁移 - 添加 tb_permission.platform 字段(all/web/h5) - 更新 tb_role.role_type 注释(1=平台角色,2=客户角色) 2. GORM 模型更新 - Permission 模型添加 Platform 字段 - Role 模型更新 RoleType 注释 3. 常量定义 - 新增角色类型常量(RoleTypePlatform, RoleTypeCustomer) - 新增权限端口常量(PlatformAll, PlatformWeb, PlatformH5) - 添加角色类型与用户类型匹配规则函数 4. Store 层实现 - Permission Store 支持按 platform 过滤 - Account Role Store 添加 CountByAccountID 方法 5. Service 层实现 - 角色分配支持类型匹配校验 - 角色分配支持数量限制(超级管理员0个,平台用户无限制,代理/企业1个) - Permission Service 支持 platform 过滤 6. 权限校验中间件 - 实现 RequirePermission、RequireAnyPermission、RequireAllPermissions - 支持 platform 字段过滤 - 支持跳过超级管理员检查 7. 测试用例 - 角色类型匹配规则单元测试 - 角色分配数量限制单元测试 - 权限 platform 过滤单元测试 - 权限校验中间件集成测试(占位) 8. 代码清理 - 删除过时的 subordinate 测试文件 - 移除 Account.ParentID 相关引用 - 更新 DTO 验证规则 Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
281 lines
7.9 KiB
Go
281 lines
7.9 KiB
Go
package unit
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
"gorm.io/gorm"
|
|
|
|
"github.com/break/junhong_cmp_fiber/internal/model"
|
|
"github.com/break/junhong_cmp_fiber/internal/store/postgres"
|
|
"github.com/break/junhong_cmp_fiber/pkg/constants"
|
|
"github.com/break/junhong_cmp_fiber/tests/testutils"
|
|
)
|
|
|
|
// TestAccountSoftDelete 测试账号软删除功能
|
|
func TestAccountSoftDelete(t *testing.T) {
|
|
db, redisClient := testutils.SetupTestDB(t)
|
|
defer testutils.TeardownTestDB(t, db, redisClient)
|
|
|
|
store := postgres.NewAccountStore(db, redisClient)
|
|
ctx := context.Background()
|
|
|
|
// 创建测试账号
|
|
account := &model.Account{
|
|
Username: "soft_delete_user",
|
|
Phone: "13800000001",
|
|
Password: "hashed_password",
|
|
UserType: constants.UserTypePlatform,
|
|
Status: constants.StatusEnabled,
|
|
}
|
|
err := store.Create(ctx, account)
|
|
require.NoError(t, err)
|
|
|
|
t.Run("软删除账号", func(t *testing.T) {
|
|
err := store.Delete(ctx, account.ID)
|
|
require.NoError(t, err)
|
|
|
|
// 正常查询应该找不到
|
|
_, err = store.GetByID(ctx, account.ID)
|
|
assert.Error(t, err)
|
|
assert.Equal(t, gorm.ErrRecordNotFound, err)
|
|
})
|
|
|
|
t.Run("使用 Unscoped 可以查到已删除账号", func(t *testing.T) {
|
|
var found model.Account
|
|
err := db.Unscoped().First(&found, account.ID).Error
|
|
require.NoError(t, err)
|
|
assert.Equal(t, account.Username, found.Username)
|
|
assert.NotNil(t, found.DeletedAt)
|
|
})
|
|
|
|
t.Run("软删除后可以重用用户名和手机号", func(t *testing.T) {
|
|
// 创建同名账号(因为原账号已软删除)
|
|
newAccount := &model.Account{
|
|
Username: "soft_delete_user", // 重用已删除账号的用户名
|
|
Phone: "13800000001", // 重用已删除账号的手机号
|
|
Password: "hashed_password",
|
|
UserType: constants.UserTypePlatform,
|
|
Status: constants.StatusEnabled,
|
|
}
|
|
err := store.Create(ctx, newAccount)
|
|
require.NoError(t, err)
|
|
assert.NotEqual(t, account.ID, newAccount.ID)
|
|
})
|
|
}
|
|
|
|
// TestRoleSoftDelete 测试角色软删除功能
|
|
func TestRoleSoftDelete(t *testing.T) {
|
|
db, redisClient := testutils.SetupTestDB(t)
|
|
defer testutils.TeardownTestDB(t, db, redisClient)
|
|
|
|
roleStore := postgres.NewRoleStore(db)
|
|
ctx := context.Background()
|
|
|
|
// 创建测试角色
|
|
role := &model.Role{
|
|
RoleName: "test_role",
|
|
RoleDesc: "测试角色",
|
|
RoleType: constants.RoleTypePlatform,
|
|
Status: constants.StatusEnabled,
|
|
}
|
|
err := roleStore.Create(ctx, role)
|
|
require.NoError(t, err)
|
|
|
|
t.Run("软删除角色", func(t *testing.T) {
|
|
err := roleStore.Delete(ctx, role.ID)
|
|
require.NoError(t, err)
|
|
|
|
// 正常查询应该找不到
|
|
_, err = roleStore.GetByID(ctx, role.ID)
|
|
assert.Error(t, err)
|
|
assert.Equal(t, gorm.ErrRecordNotFound, err)
|
|
})
|
|
|
|
t.Run("使用 Unscoped 可以查到已删除角色", func(t *testing.T) {
|
|
var found model.Role
|
|
err := db.Unscoped().First(&found, role.ID).Error
|
|
require.NoError(t, err)
|
|
assert.Equal(t, role.RoleName, found.RoleName)
|
|
assert.NotNil(t, found.DeletedAt)
|
|
})
|
|
}
|
|
|
|
// TestPermissionSoftDelete 测试权限软删除功能
|
|
func TestPermissionSoftDelete(t *testing.T) {
|
|
db, redisClient := testutils.SetupTestDB(t)
|
|
defer testutils.TeardownTestDB(t, db, redisClient)
|
|
|
|
permissionStore := postgres.NewPermissionStore(db)
|
|
ctx := context.Background()
|
|
|
|
// 创建测试权限
|
|
permission := &model.Permission{
|
|
PermName: "测试权限",
|
|
PermCode: "test:permission",
|
|
PermType: constants.PermissionTypeMenu,
|
|
Status: constants.StatusEnabled,
|
|
}
|
|
err := permissionStore.Create(ctx, permission)
|
|
require.NoError(t, err)
|
|
|
|
t.Run("软删除权限", func(t *testing.T) {
|
|
err := permissionStore.Delete(ctx, permission.ID)
|
|
require.NoError(t, err)
|
|
|
|
// 正常查询应该找不到
|
|
_, err = permissionStore.GetByID(ctx, permission.ID)
|
|
assert.Error(t, err)
|
|
assert.Equal(t, gorm.ErrRecordNotFound, err)
|
|
})
|
|
|
|
t.Run("软删除后可以重用权限码", func(t *testing.T) {
|
|
newPermission := &model.Permission{
|
|
PermName: "新测试权限",
|
|
PermCode: "test:permission", // 重用已删除权限的 perm_code
|
|
PermType: constants.PermissionTypeMenu,
|
|
Status: constants.StatusEnabled,
|
|
}
|
|
err := permissionStore.Create(ctx, newPermission)
|
|
require.NoError(t, err)
|
|
assert.NotEqual(t, permission.ID, newPermission.ID)
|
|
})
|
|
}
|
|
|
|
// TestAccountRoleSoftDelete 测试账号-角色关联软删除功能
|
|
func TestAccountRoleSoftDelete(t *testing.T) {
|
|
db, redisClient := testutils.SetupTestDB(t)
|
|
defer testutils.TeardownTestDB(t, db, redisClient)
|
|
|
|
accountStore := postgres.NewAccountStore(db, redisClient)
|
|
roleStore := postgres.NewRoleStore(db)
|
|
accountRoleStore := postgres.NewAccountRoleStore(db)
|
|
ctx := context.Background()
|
|
|
|
// 创建测试账号
|
|
account := &model.Account{
|
|
Username: "ar_user",
|
|
Phone: "13800000001",
|
|
Password: "hashed_password",
|
|
UserType: constants.UserTypePlatform,
|
|
Status: constants.StatusEnabled,
|
|
}
|
|
err := accountStore.Create(ctx, account)
|
|
require.NoError(t, err)
|
|
|
|
// 创建测试角色
|
|
role := &model.Role{
|
|
RoleName: "ar_role",
|
|
RoleDesc: "测试角色",
|
|
RoleType: constants.RoleTypePlatform,
|
|
Status: constants.StatusEnabled,
|
|
}
|
|
err = roleStore.Create(ctx, role)
|
|
require.NoError(t, err)
|
|
|
|
// 创建关联
|
|
accountRole := &model.AccountRole{
|
|
AccountID: account.ID,
|
|
RoleID: role.ID,
|
|
Status: constants.StatusEnabled,
|
|
Creator: 1,
|
|
Updater: 1,
|
|
}
|
|
err = accountRoleStore.Create(ctx, accountRole)
|
|
require.NoError(t, err)
|
|
|
|
t.Run("软删除账号-角色关联", func(t *testing.T) {
|
|
err := accountRoleStore.Delete(ctx, account.ID, role.ID)
|
|
require.NoError(t, err)
|
|
|
|
// 查询应该找不到
|
|
roles, err := accountRoleStore.GetByAccountID(ctx, account.ID)
|
|
require.NoError(t, err)
|
|
assert.Len(t, roles, 0)
|
|
})
|
|
|
|
t.Run("软删除后可以重新关联", func(t *testing.T) {
|
|
newAccountRole := &model.AccountRole{
|
|
AccountID: account.ID,
|
|
RoleID: role.ID,
|
|
Status: constants.StatusEnabled,
|
|
Creator: 1,
|
|
Updater: 1,
|
|
}
|
|
err := accountRoleStore.Create(ctx, newAccountRole)
|
|
require.NoError(t, err)
|
|
|
|
// 验证可以查询到
|
|
roles, err := accountRoleStore.GetByAccountID(ctx, account.ID)
|
|
require.NoError(t, err)
|
|
assert.Len(t, roles, 1)
|
|
})
|
|
}
|
|
|
|
// TestRolePermissionSoftDelete 测试角色-权限关联软删除功能
|
|
func TestRolePermissionSoftDelete(t *testing.T) {
|
|
db, redisClient := testutils.SetupTestDB(t)
|
|
defer testutils.TeardownTestDB(t, db, redisClient)
|
|
|
|
roleStore := postgres.NewRoleStore(db)
|
|
permissionStore := postgres.NewPermissionStore(db)
|
|
rolePermissionStore := postgres.NewRolePermissionStore(db)
|
|
ctx := context.Background()
|
|
|
|
// 创建测试角色
|
|
role := &model.Role{
|
|
RoleName: "rp_role",
|
|
RoleDesc: "测试角色",
|
|
RoleType: constants.RoleTypePlatform,
|
|
Status: constants.StatusEnabled,
|
|
}
|
|
err := roleStore.Create(ctx, role)
|
|
require.NoError(t, err)
|
|
|
|
// 创建测试权限
|
|
permission := &model.Permission{
|
|
PermName: "rp_permission",
|
|
PermCode: "rp:permission",
|
|
PermType: constants.PermissionTypeMenu,
|
|
Status: constants.StatusEnabled,
|
|
}
|
|
err = permissionStore.Create(ctx, permission)
|
|
require.NoError(t, err)
|
|
|
|
// 创建关联
|
|
rolePermission := &model.RolePermission{
|
|
RoleID: role.ID,
|
|
PermID: permission.ID,
|
|
Status: constants.StatusEnabled,
|
|
}
|
|
err = rolePermissionStore.Create(ctx, rolePermission)
|
|
require.NoError(t, err)
|
|
|
|
t.Run("软删除角色-权限关联", func(t *testing.T) {
|
|
err := rolePermissionStore.Delete(ctx, role.ID, permission.ID)
|
|
require.NoError(t, err)
|
|
|
|
// 查询应该找不到
|
|
permissions, err := rolePermissionStore.GetByRoleID(ctx, role.ID)
|
|
require.NoError(t, err)
|
|
assert.Len(t, permissions, 0)
|
|
})
|
|
|
|
t.Run("软删除后可以重新关联", func(t *testing.T) {
|
|
newRolePermission := &model.RolePermission{
|
|
RoleID: role.ID,
|
|
PermID: permission.ID,
|
|
Status: constants.StatusEnabled,
|
|
}
|
|
err := rolePermissionStore.Create(ctx, newRolePermission)
|
|
require.NoError(t, err)
|
|
|
|
// 验证可以查询到
|
|
permissions, err := rolePermissionStore.GetByRoleID(ctx, role.ID)
|
|
require.NoError(t, err)
|
|
assert.Len(t, permissions, 1)
|
|
})
|
|
}
|