feat(shop-role): 实现店铺角色继承功能和权限检查优化
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 6m39s

- 新增店铺角色管理 API 和数据模型
- 实现角色继承和权限检查逻辑
- 添加流程测试框架和集成测试
- 更新权限服务和账号管理逻辑
- 添加数据库迁移脚本
- 归档 OpenSpec 变更文档

Ultraworked with Sisyphus
This commit is contained in:
2026-02-03 10:06:13 +08:00
parent bc7e5d6f6d
commit 5a90caa619
61 changed files with 21284 additions and 131 deletions

View File

@@ -224,9 +224,10 @@ func TestAccountAudit(t *testing.T) {
accountRoleStore := postgres.NewAccountRoleStore(env.TX, env.Redis)
shopStore := postgres.NewShopStore(env.TX, env.Redis)
enterpriseStore := postgres.NewEnterpriseStore(env.TX, env.Redis)
shopRoleStore := postgres.NewShopRoleStore(env.TX, env.Redis)
auditLogStore := postgres.NewAccountOperationLogStore(env.TX)
auditService := accountAuditSvc.NewService(auditLogStore)
accountService := accountSvc.New(accountStore, roleStore, accountRoleStore, shopStore, enterpriseStore, auditService)
accountService := accountSvc.New(accountStore, roleStore, accountRoleStore, shopRoleStore, shopStore, enterpriseStore, auditService)
// 调用 RemoveRole
ctx := env.GetSuperAdminContext()

View File

@@ -24,9 +24,10 @@ func TestAccountRoleAssociation_AssignRoles(t *testing.T) {
accountRoleStore := postgresStore.NewAccountRoleStore(env.TX, env.Redis)
shopStore := postgresStore.NewShopStore(env.TX, env.Redis)
enterpriseStore := postgresStore.NewEnterpriseStore(env.TX, env.Redis)
shopRoleStore := postgresStore.NewShopRoleStore(env.TX, env.Redis)
auditLogStore := postgresStore.NewAccountOperationLogStore(env.TX)
auditService := accountAuditService.NewService(auditLogStore)
accService := accountService.New(accountStore, roleStore, accountRoleStore, shopStore, enterpriseStore, auditService)
accService := accountService.New(accountStore, roleStore, accountRoleStore, shopRoleStore, shopStore, enterpriseStore, auditService)
// 获取超级管理员上下文
userCtx := env.GetSuperAdminContext()
@@ -219,10 +220,11 @@ func TestAccountRoleAssociation_SoftDelete(t *testing.T) {
roleStore := postgresStore.NewRoleStore(env.TX)
accountRoleStore := postgresStore.NewAccountRoleStore(env.TX, env.Redis)
shopStore := postgresStore.NewShopStore(env.TX, env.Redis)
shopRoleStore := postgresStore.NewShopRoleStore(env.TX, env.Redis)
enterpriseStore := postgresStore.NewEnterpriseStore(env.TX, env.Redis)
auditLogStore := postgresStore.NewAccountOperationLogStore(env.TX)
auditService := accountAuditService.NewService(auditLogStore)
accService := accountService.New(accountStore, roleStore, accountRoleStore, shopStore, enterpriseStore, auditService)
accService := accountService.New(accountStore, roleStore, accountRoleStore, shopRoleStore, shopStore, enterpriseStore, auditService)
// 获取超级管理员上下文
userCtx := env.GetSuperAdminContext()

View File

@@ -29,7 +29,7 @@ func TestPermissionCache_FirstCallMissSecondHit(t *testing.T) {
accountRoleStore := postgres.NewAccountRoleStore(tx, rdb)
rolePermStore := postgres.NewRolePermissionStore(tx, rdb)
permSvc := permission.New(permStore, accountRoleStore, rolePermStore, rdb)
permSvc := permission.New(permStore, accountRoleStore, rolePermStore, nil, rdb)
testUser := &model.Account{
Username: "testuser",
@@ -112,7 +112,7 @@ func TestPermissionCache_ExpiredAfter30Minutes(t *testing.T) {
accountRoleStore := postgres.NewAccountRoleStore(tx, rdb)
rolePermStore := postgres.NewRolePermissionStore(tx, rdb)
permSvc := permission.New(permStore, accountRoleStore, rolePermStore, rdb)
permSvc := permission.New(permStore, accountRoleStore, rolePermStore, nil, rdb)
testUser := &model.Account{
Username: "testuser2",

View File

@@ -33,7 +33,7 @@ func TestPermissionService_CheckPermission_SuperAdmin(t *testing.T) {
permStore := postgres.NewPermissionStore(tx)
accountRoleStore := postgres.NewAccountRoleStore(tx, rdb)
rolePermStore := postgres.NewRolePermissionStore(tx, rdb)
service := permission.New(permStore, accountRoleStore, rolePermStore, rdb)
service := permission.New(permStore, accountRoleStore, rolePermStore, nil, rdb)
t.Run("超级管理员自动拥有所有权限", func(t *testing.T) {
ctx := createContextWithUserType(1, constants.UserTypeSuperAdmin)
@@ -53,7 +53,7 @@ func TestPermissionService_CheckPermission_NormalUser(t *testing.T) {
accountRoleStore := postgres.NewAccountRoleStore(tx, rdb)
rolePermStore := postgres.NewRolePermissionStore(tx, rdb)
roleStore := postgres.NewRoleStore(tx)
service := permission.New(permStore, accountRoleStore, rolePermStore, rdb)
service := permission.New(permStore, accountRoleStore, rolePermStore, nil, rdb)
ctx := createContextWithUserType(100, constants.UserTypePlatform)
@@ -173,7 +173,7 @@ func TestPermissionService_CheckPermission_NoRole(t *testing.T) {
permStore := postgres.NewPermissionStore(tx)
accountRoleStore := postgres.NewAccountRoleStore(tx, rdb)
rolePermStore := postgres.NewRolePermissionStore(tx, rdb)
service := permission.New(permStore, accountRoleStore, rolePermStore, rdb)
service := permission.New(permStore, accountRoleStore, rolePermStore, nil, rdb)
t.Run("用户无角色应返回false", func(t *testing.T) {
ctx := createContextWithUserType(200, constants.UserTypePlatform)
@@ -193,7 +193,7 @@ func TestPermissionService_CheckPermission_RoleNoPermission(t *testing.T) {
accountRoleStore := postgres.NewAccountRoleStore(tx, rdb)
rolePermStore := postgres.NewRolePermissionStore(tx, rdb)
roleStore := postgres.NewRoleStore(tx)
service := permission.New(permStore, accountRoleStore, rolePermStore, rdb)
service := permission.New(permStore, accountRoleStore, rolePermStore, nil, rdb)
ctx := createContextWithUserType(300, constants.UserTypePlatform)

View File

@@ -25,7 +25,7 @@ func TestPermissionPlatformFilter_List(t *testing.T) {
permissionStore := postgres.NewPermissionStore(tx)
accountRoleStore := postgres.NewAccountRoleStore(tx, rdb)
rolePermStore := postgres.NewRolePermissionStore(tx, rdb)
service := permission.New(permissionStore, accountRoleStore, rolePermStore, rdb)
service := permission.New(permissionStore, accountRoleStore, rolePermStore, nil, rdb)
ctx := context.Background()
ctx = middleware.SetUserContext(ctx, middleware.NewSimpleUserContext(1, constants.UserTypeSuperAdmin, 0))
@@ -109,7 +109,7 @@ func TestPermissionPlatformFilter_CreateWithDefaultPlatform(t *testing.T) {
permissionStore := postgres.NewPermissionStore(tx)
accountRoleStore := postgres.NewAccountRoleStore(tx, rdb)
rolePermStore := postgres.NewRolePermissionStore(tx, rdb)
service := permission.New(permissionStore, accountRoleStore, rolePermStore, rdb)
service := permission.New(permissionStore, accountRoleStore, rolePermStore, nil, rdb)
ctx := context.Background()
ctx = middleware.SetUserContext(ctx, middleware.NewSimpleUserContext(1, constants.UserTypeSuperAdmin, 0))
@@ -136,7 +136,7 @@ func TestPermissionPlatformFilter_CreateWithSpecificPlatform(t *testing.T) {
permissionStore := postgres.NewPermissionStore(tx)
accountRoleStore := postgres.NewAccountRoleStore(tx, rdb)
rolePermStore := postgres.NewRolePermissionStore(tx, rdb)
service := permission.New(permissionStore, accountRoleStore, rolePermStore, rdb)
service := permission.New(permissionStore, accountRoleStore, rolePermStore, nil, rdb)
ctx := context.Background()
ctx = middleware.SetUserContext(ctx, middleware.NewSimpleUserContext(1, constants.UserTypeSuperAdmin, 0))
@@ -176,7 +176,7 @@ func TestPermissionPlatformFilter_Tree(t *testing.T) {
permissionStore := postgres.NewPermissionStore(tx)
accountRoleStore := postgres.NewAccountRoleStore(tx, rdb)
rolePermStore := postgres.NewRolePermissionStore(tx, rdb)
service := permission.New(permissionStore, accountRoleStore, rolePermStore, rdb)
service := permission.New(permissionStore, accountRoleStore, rolePermStore, nil, rdb)
ctx := context.Background()
ctx = middleware.SetUserContext(ctx, middleware.NewSimpleUserContext(1, constants.UserTypeSuperAdmin, 0))

View File

@@ -27,9 +27,10 @@ func TestRoleAssignmentLimit_PlatformUser(t *testing.T) {
accountRoleStore := postgres.NewAccountRoleStore(tx, rdb)
shopStore := postgres.NewShopStore(tx, rdb)
enterpriseStore := postgres.NewEnterpriseStore(tx, rdb)
shopRoleStore := postgres.NewShopRoleStore(tx, rdb)
auditLogStore := postgres.NewAccountOperationLogStore(tx)
auditService := account_audit.NewService(auditLogStore)
service := account.New(accountStore, roleStore, accountRoleStore, shopStore, enterpriseStore, auditService)
service := account.New(accountStore, roleStore, accountRoleStore, shopRoleStore, shopStore, enterpriseStore, auditService)
ctx := context.Background()
ctx = middleware.SetUserContext(ctx, middleware.NewSimpleUserContext(1, constants.UserTypeSuperAdmin, 0))
@@ -71,10 +72,11 @@ func TestRoleAssignmentLimit_AgentUser(t *testing.T) {
roleStore := postgres.NewRoleStore(tx)
accountRoleStore := postgres.NewAccountRoleStore(tx, rdb)
shopStore := postgres.NewShopStore(tx, rdb)
shopRoleStore := postgres.NewShopRoleStore(tx, rdb)
enterpriseStore := postgres.NewEnterpriseStore(tx, rdb)
auditLogStore := postgres.NewAccountOperationLogStore(tx)
auditService := account_audit.NewService(auditLogStore)
service := account.New(accountStore, roleStore, accountRoleStore, shopStore, enterpriseStore, auditService)
service := account.New(accountStore, roleStore, accountRoleStore, shopRoleStore, shopStore, enterpriseStore, auditService)
ctx := context.Background()
ctx = middleware.SetUserContext(ctx, middleware.NewSimpleUserContext(1, constants.UserTypeSuperAdmin, 0))
@@ -118,11 +120,12 @@ func TestRoleAssignmentLimit_EnterpriseUser(t *testing.T) {
accountStore := postgres.NewAccountStore(tx, rdb)
roleStore := postgres.NewRoleStore(tx)
accountRoleStore := postgres.NewAccountRoleStore(tx, rdb)
shopRoleStore := postgres.NewShopRoleStore(tx, rdb)
shopStore := postgres.NewShopStore(tx, rdb)
enterpriseStore := postgres.NewEnterpriseStore(tx, rdb)
auditLogStore := postgres.NewAccountOperationLogStore(tx)
auditService := account_audit.NewService(auditLogStore)
service := account.New(accountStore, roleStore, accountRoleStore, shopStore, enterpriseStore, auditService)
service := account.New(accountStore, roleStore, accountRoleStore, shopRoleStore, shopStore, enterpriseStore, auditService)
ctx := context.Background()
ctx = middleware.SetUserContext(ctx, middleware.NewSimpleUserContext(1, constants.UserTypeSuperAdmin, 0))
@@ -165,12 +168,13 @@ func TestRoleAssignmentLimit_SuperAdmin(t *testing.T) {
accountStore := postgres.NewAccountStore(tx, rdb)
roleStore := postgres.NewRoleStore(tx)
shopRoleStore := postgres.NewShopRoleStore(tx, rdb)
accountRoleStore := postgres.NewAccountRoleStore(tx, rdb)
shopStore := postgres.NewShopStore(tx, rdb)
enterpriseStore := postgres.NewEnterpriseStore(tx, rdb)
auditLogStore := postgres.NewAccountOperationLogStore(tx)
auditService := account_audit.NewService(auditLogStore)
service := account.New(accountStore, roleStore, accountRoleStore, shopStore, enterpriseStore, auditService)
service := account.New(accountStore, roleStore, accountRoleStore, shopRoleStore, shopStore, enterpriseStore, auditService)
ctx := context.Background()
ctx = middleware.SetUserContext(ctx, middleware.NewSimpleUserContext(1, constants.UserTypeSuperAdmin, 0))

View File

@@ -24,7 +24,9 @@ func TestShopService_Create(t *testing.T) {
shopStore := postgres.NewShopStore(tx, rdb)
accountStore := postgres.NewAccountStore(tx, rdb)
service := shop.New(shopStore, accountStore)
shopRoleStore := postgres.NewShopRoleStore(tx, rdb)
roleStore := postgres.NewRoleStore(tx)
service := shop.New(shopStore, accountStore, shopRoleStore, roleStore)
t.Run("创建一级店铺成功", func(t *testing.T) {
ctx := createContextWithUserID(1)
@@ -243,7 +245,9 @@ func TestShopService_Update(t *testing.T) {
shopStore := postgres.NewShopStore(tx, rdb)
accountStore := postgres.NewAccountStore(tx, rdb)
service := shop.New(shopStore, accountStore)
shopRoleStore := postgres.NewShopRoleStore(tx, rdb)
roleStore := postgres.NewRoleStore(tx)
service := shop.New(shopStore, accountStore, shopRoleStore, roleStore)
t.Run("更新店铺信息成功", func(t *testing.T) {
ctx := createContextWithUserID(1)
@@ -373,7 +377,9 @@ func TestShopService_Disable(t *testing.T) {
shopStore := postgres.NewShopStore(tx, rdb)
accountStore := postgres.NewAccountStore(tx, rdb)
service := shop.New(shopStore, accountStore)
shopRoleStore := postgres.NewShopRoleStore(tx, rdb)
roleStore := postgres.NewRoleStore(tx)
service := shop.New(shopStore, accountStore, shopRoleStore, roleStore)
t.Run("禁用店铺成功", func(t *testing.T) {
ctx := createContextWithUserID(1)
@@ -437,7 +443,9 @@ func TestShopService_Enable(t *testing.T) {
shopStore := postgres.NewShopStore(tx, rdb)
accountStore := postgres.NewAccountStore(tx, rdb)
service := shop.New(shopStore, accountStore)
shopRoleStore := postgres.NewShopRoleStore(tx, rdb)
roleStore := postgres.NewRoleStore(tx)
service := shop.New(shopStore, accountStore, shopRoleStore, roleStore)
t.Run("启用店铺成功", func(t *testing.T) {
ctx := createContextWithUserID(1)
@@ -510,7 +518,9 @@ func TestShopService_GetByID(t *testing.T) {
shopStore := postgres.NewShopStore(tx, rdb)
accountStore := postgres.NewAccountStore(tx, rdb)
service := shop.New(shopStore, accountStore)
shopRoleStore := postgres.NewShopRoleStore(tx, rdb)
roleStore := postgres.NewRoleStore(tx)
service := shop.New(shopStore, accountStore, shopRoleStore, roleStore)
t.Run("获取存在的店铺", func(t *testing.T) {
ctx := createContextWithUserID(1)
@@ -559,7 +569,9 @@ func TestShopService_List(t *testing.T) {
shopStore := postgres.NewShopStore(tx, rdb)
accountStore := postgres.NewAccountStore(tx, rdb)
service := shop.New(shopStore, accountStore)
shopRoleStore := postgres.NewShopRoleStore(tx, rdb)
roleStore := postgres.NewRoleStore(tx)
service := shop.New(shopStore, accountStore, shopRoleStore, roleStore)
t.Run("查询店铺列表", func(t *testing.T) {
ctx := createContextWithUserID(1)
@@ -596,7 +608,9 @@ func TestShopService_GetSubordinateShopIDs(t *testing.T) {
shopStore := postgres.NewShopStore(tx, rdb)
accountStore := postgres.NewAccountStore(tx, rdb)
service := shop.New(shopStore, accountStore)
shopRoleStore := postgres.NewShopRoleStore(tx, rdb)
roleStore := postgres.NewRoleStore(tx)
service := shop.New(shopStore, accountStore, shopRoleStore, roleStore)
t.Run("获取下级店铺 ID 列表", func(t *testing.T) {
ctx := createContextWithUserID(1)
@@ -661,7 +675,9 @@ func TestShopService_Delete(t *testing.T) {
shopStore := postgres.NewShopStore(tx, rdb)
accountStore := postgres.NewAccountStore(tx, rdb)
service := shop.New(shopStore, accountStore)
shopRoleStore := postgres.NewShopRoleStore(tx, rdb)
roleStore := postgres.NewRoleStore(tx)
service := shop.New(shopStore, accountStore, shopRoleStore, roleStore)
t.Run("删除店铺成功", func(t *testing.T) {
ctx := createContextWithUserID(1)