kra/internal/service/system/casbin.go

131 lines
3.6 KiB
Go

package system
import (
"errors"
"strconv"
"kra/internal/biz/system"
"kra/internal/conf"
"kra/internal/server/middleware"
kerrors "github.com/go-kratos/kratos/v2/errors"
"github.com/go-kratos/kratos/v2/transport/http"
)
// CasbinService Casbin服务
type CasbinService struct {
casbinRepo system.CasbinRepo
authUc *system.AuthorityUsecase
apiUc *system.ApiUsecase
useStrictAuth bool
}
// NewCasbinService 创建Casbin服务
func NewCasbinService(casbinRepo system.CasbinRepo, authUc *system.AuthorityUsecase, apiUc *system.ApiUsecase, useStrictAuth conf.UseStrictAuth) *CasbinService {
return &CasbinService{
casbinRepo: casbinRepo,
authUc: authUc,
apiUc: apiUc,
useStrictAuth: bool(useStrictAuth),
}
}
// UpdateCasbinRequest 更新Casbin请求
type UpdateCasbinRequest struct {
AuthorityId uint `json:"authorityId"`
CasbinInfos []system.CasbinRule `json:"casbinInfos"`
}
// PolicyPathResponse 权限路径响应
type PolicyPathResponse struct {
Paths []system.CasbinRule `json:"paths"`
}
// GetPolicyPathRequest 获取权限路径请求
type GetPolicyPathRequest struct {
AuthorityId uint `json:"authorityId"`
}
// UpdateCasbin 更新Casbin权限
func (s *CasbinService) UpdateCasbin(ctx http.Context, adminAuthorityID uint, req *UpdateCasbinRequest) error {
// 检查权限
if err := s.authUc.CheckAuthorityIDAuth(ctx, adminAuthorityID, req.AuthorityId); err != nil {
return err
}
// 严格模式下检查API权限
if s.useStrictAuth {
apis, err := s.apiUc.GetAllApis(ctx, adminAuthorityID)
if err != nil {
return err
}
for _, info := range req.CasbinInfos {
hasApi := false
for _, api := range apis {
if api.Path == info.Path && api.Method == info.Method {
hasApi = true
break
}
}
if !hasApi {
return errors.New("存在api不在权限列表中")
}
}
}
return s.casbinRepo.UpdateCasbin(adminAuthorityID, req.AuthorityId, req.CasbinInfos)
}
// GetPolicyPathByAuthorityId 获取权限列表
func (s *CasbinService) GetPolicyPathByAuthorityId(authorityId uint) []system.CasbinRule {
return s.casbinRepo.GetPolicyPathByAuthorityId(authorityId)
}
// RegisterRoutes 注册路由
func (s *CasbinService) RegisterRoutes(rg *RouterGroup) {
// 私有路由 + 操作记录(写操作)
rg.PrivateWithRecord.POST("/casbin/updateCasbin", s.handleUpdateCasbin)
// 私有路由(读操作,不记录)
rg.Private.POST("/casbin/getPolicyPathByAuthorityId", s.handleGetPolicyPath)
}
func (s *CasbinService) handleUpdateCasbin(ctx http.Context) error {
var req UpdateCasbinRequest
if err := ctx.Bind(&req); err != nil {
return err
}
if req.AuthorityId == 0 {
return kerrors.BadRequest("INVALID_AUTHORITY", "角色ID不能为空")
}
adminAuthorityID := middleware.GetAuthorityID(ctx)
if adminAuthorityID == 0 {
return kerrors.Unauthorized("UNAUTHORIZED", "请先登录")
}
if err := s.UpdateCasbin(ctx, adminAuthorityID, &req); err != nil {
return kerrors.InternalServer("UPDATE_ERROR", err.Error())
}
return ctx.Result(200, map[string]any{"code": 0, "msg": "更新成功"})
}
func (s *CasbinService) handleGetPolicyPath(ctx http.Context) error {
var req GetPolicyPathRequest
if err := ctx.Bind(&req); err != nil {
return err
}
if req.AuthorityId == 0 {
return kerrors.BadRequest("INVALID_AUTHORITY", "角色ID不能为空")
}
paths := s.GetPolicyPathByAuthorityId(req.AuthorityId)
return ctx.Result(200, map[string]any{
"code": 0,
"msg": "获取成功",
"data": PolicyPathResponse{Paths: paths},
})
}
// 辅助函数
func uintToStr(n uint) string {
return strconv.FormatUint(uint64(n), 10)
}