package middleware import ( "context" "slices" "github.com/break/junhong_cmp_fiber/internal/model" "github.com/break/junhong_cmp_fiber/pkg/constants" "github.com/break/junhong_cmp_fiber/pkg/errors" ) // EnterpriseStoreInterface 企业存储接口 // 用于权限检查时查询企业信息 type EnterpriseStoreInterface interface { GetByID(ctx context.Context, id uint) (*model.Enterprise, error) GetByIDs(ctx context.Context, ids []uint) ([]*model.Enterprise, error) } // CanManageShop 检查当前用户是否有权管理目标店铺 // 超级管理员和平台用户自动通过(SubordinateShopIDs 为 nil) // 代理账号只能管理自己店铺及下级店铺 // 企业账号禁止管理店铺 func CanManageShop(ctx context.Context, targetShopID uint) error { userType := GetUserTypeFromContext(ctx) // 企业账号禁止管理店铺 if userType == constants.UserTypeEnterprise { return errors.New(errors.CodeForbidden, "无权限管理店铺") } // 从 Context 获取预计算的下级店铺 ID 列表 subordinateIDs := GetSubordinateShopIDs(ctx) // nil 表示不受限制(超级管理员/平台用户) if subordinateIDs == nil { return nil } // 检查目标店铺是否在下级列表中 if slices.Contains(subordinateIDs, targetShopID) { return nil } return errors.New(errors.CodeForbidden, "无权限管理该店铺") } // CanManageEnterprise 检查当前用户是否有权管理目标企业 // 超级管理员和平台用户自动通过(SubordinateShopIDs 为 nil) // 代理账号只能管理归属于自己店铺或下级店铺的企业 // 企业账号禁止管理其他企业 func CanManageEnterprise(ctx context.Context, targetEnterpriseID uint, enterpriseStore EnterpriseStoreInterface) error { userType := GetUserTypeFromContext(ctx) // 企业账号禁止管理其他企业 if userType == constants.UserTypeEnterprise { return errors.New(errors.CodeForbidden, "无权限管理企业") } // 从 Context 获取预计算的下级店铺 ID 列表 subordinateIDs := GetSubordinateShopIDs(ctx) // nil 表示不受限制(超级管理员/平台用户) if subordinateIDs == nil { return nil } // 获取目标企业信息 enterprise, err := enterpriseStore.GetByID(ctx, targetEnterpriseID) if err != nil { return errors.New(errors.CodeForbidden, "无权限操作该资源或资源不存在") } // 代理账号不能管理平台级企业(owner_shop_id 为 NULL) if enterprise.OwnerShopID == nil { return errors.New(errors.CodeForbidden, "无权限管理平台级企业") } // 检查企业归属的店铺是否在下级列表中 if slices.Contains(subordinateIDs, *enterprise.OwnerShopID) { return nil } return errors.New(errors.CodeForbidden, "无权限管理该企业") } // ContainsShopID 检查目标店铺 ID 是否在当前用户可管理的店铺列表中 // 平台用户/超管返回 true(不受限制) // 代理用户检查是否在 SubordinateShopIDs 中 func ContainsShopID(ctx context.Context, targetShopID uint) bool { subordinateIDs := GetSubordinateShopIDs(ctx) if subordinateIDs == nil { return true // 不受限制 } return slices.Contains(subordinateIDs, targetShopID) }