175 lines
4.4 KiB
Go
175 lines
4.4 KiB
Go
|
package usecase
|
||
|
|
||
|
import (
|
||
|
"code.30cm.net/digimon/app-cloudep-permission-server/pkg/domain/permission"
|
||
|
"code.30cm.net/digimon/app-cloudep-permission-server/pkg/domain/repository"
|
||
|
"code.30cm.net/digimon/app-cloudep-permission-server/pkg/domain/usecase"
|
||
|
"code.30cm.net/digimon/library-go/errs"
|
||
|
"context"
|
||
|
"fmt"
|
||
|
"github.com/casbin/casbin/v2"
|
||
|
"github.com/casbin/casbin/v2/model"
|
||
|
"github.com/zeromicro/go-zero/core/logx"
|
||
|
"log"
|
||
|
"time"
|
||
|
)
|
||
|
|
||
|
type RBACUseCaseParam struct {
|
||
|
ModulePath string
|
||
|
permissionRepo repository.PermissionRepository
|
||
|
RBACRedisAdapter repository.RBACAdapter
|
||
|
// role permission 之類的
|
||
|
}
|
||
|
|
||
|
type RBACUseCase struct {
|
||
|
permissionRepo repository.PermissionRepository
|
||
|
adapter repository.RBACAdapter
|
||
|
instance *casbin.Enforcer
|
||
|
}
|
||
|
|
||
|
func NewUseCase(param RBACUseCaseParam) usecase.RBACUseCase {
|
||
|
result := &RBACUseCase{
|
||
|
adapter: param.RBACRedisAdapter,
|
||
|
permissionRepo: param.permissionRepo,
|
||
|
}
|
||
|
|
||
|
// 1. 讀取 RBAC 模型 ->
|
||
|
m, err := model.NewModelFromFile(param.ModulePath)
|
||
|
if err != nil {
|
||
|
log.Fatalf("failed to load model: %v", err)
|
||
|
}
|
||
|
|
||
|
// 3. 創建 Casbin Enforcer
|
||
|
enforcer, err := casbin.NewEnforcer(m, result.adapter)
|
||
|
if err != nil {
|
||
|
log.Fatalf("failed to init Enforcer: %v", err)
|
||
|
}
|
||
|
|
||
|
result.instance = enforcer
|
||
|
|
||
|
return result
|
||
|
}
|
||
|
|
||
|
func (use *RBACUseCase) Check(ctx context.Context, role, path, method string) (usecase.CheckRolePermissionStatus, error) {
|
||
|
ok, p, err := use.instance.EnforceEx(role, path, method)
|
||
|
if err != nil {
|
||
|
e := errs.ForbiddenL(logx.WithContext(ctx),
|
||
|
[]logx.LogField{
|
||
|
{Key: "req", Value: fmt.Sprintf("role: %s, path: %s, method: %s", role, path, method)},
|
||
|
{Key: "func", Value: "casbin.EnforceEx"},
|
||
|
{Key: "err", Value: err.Error()},
|
||
|
},
|
||
|
"failed to get permission")
|
||
|
|
||
|
return usecase.CheckRolePermissionStatus{}, e
|
||
|
}
|
||
|
|
||
|
status := usecase.CheckRolePermissionStatus{
|
||
|
Allow: ok,
|
||
|
}
|
||
|
|
||
|
fmt.Println(p)
|
||
|
//// 檢查是否有明碼查詢權限
|
||
|
//if role == domain.AdminRoleUID {
|
||
|
// status.Select.PlainCode = true
|
||
|
//} else if ok && method == http.MethodGet {
|
||
|
// status.Select.PlainCode = use.rbac.GetModel().HasPolicy("p", "p", []string{
|
||
|
// role, path, method, p[3] + ".plain_code",
|
||
|
// })
|
||
|
//}
|
||
|
//
|
||
|
//limit := 4
|
||
|
//if len(p) >= limit {
|
||
|
// status.Select.PermissionName = p[3]
|
||
|
//}
|
||
|
|
||
|
return status, nil
|
||
|
}
|
||
|
|
||
|
func (use *RBACUseCase) LoadPolicy(ctx context.Context) error {
|
||
|
|
||
|
status := permission.Open
|
||
|
// 取得所有permission -> permission tree 拿到有開啟的節點,如果付節點關閉,子節點也就不顯示了
|
||
|
permissions, err := use.permissionRepo.GetAll(ctx, &status)
|
||
|
if err != nil {
|
||
|
return fmt.Errorf("permissionRepo.AllStatus error: %w", err)
|
||
|
}
|
||
|
|
||
|
fmt.Println(permissions)
|
||
|
|
||
|
// 全部permission
|
||
|
//permissionMap := make(map[int64]entity.Permission, len(permissions))
|
||
|
//for _, v := range permissions {
|
||
|
// permissionMap[v.ID] = v
|
||
|
//}
|
||
|
|
||
|
// 全部角色
|
||
|
//roles, err := r.roleRepo.All(ctx, 1)
|
||
|
//if err != nil {
|
||
|
// return fmt.Errorf("roleRepo.AllStatus error: %w", err)
|
||
|
//}
|
||
|
//
|
||
|
//roleMap := make(map[int64]entity.Role, len(roles))
|
||
|
//for _, v := range roles {
|
||
|
// roleMap[v.ID] = v
|
||
|
//}
|
||
|
|
||
|
// 根據角色組合權限表
|
||
|
//for _, v := range roles {
|
||
|
// rolePermissions, err := r.rolePermissionRepo.Get(ctx, v.ID)
|
||
|
// if err != nil {
|
||
|
// return fmt.Errorf("rolePermissionRepo.Get ID: %d error: %w", v.ID, err)
|
||
|
// }
|
||
|
//
|
||
|
// for _, rp := range rolePermissions {
|
||
|
// role, ok := roleMap[rp.RoleID]
|
||
|
// if !ok {
|
||
|
// logrus.WithFields(logrus.Fields{
|
||
|
// "role_id": rp.RoleID,
|
||
|
// }).Error("role not found")
|
||
|
//
|
||
|
// continue
|
||
|
// }
|
||
|
//
|
||
|
// permission, ok := permissionMap[rp.PermissionID]
|
||
|
// if !ok {
|
||
|
// logrus.WithFields(logrus.Fields{
|
||
|
// "permission_id": rp.PermissionID,
|
||
|
// }).Error("permission not found")
|
||
|
//
|
||
|
// continue
|
||
|
// }
|
||
|
//
|
||
|
// if permission.HTTPPath == "" || permission.HTTPMethod == "" {
|
||
|
// continue
|
||
|
// }
|
||
|
//
|
||
|
// // 根據策略model configs/rbac_model.conf填入policy_definition對應參數
|
||
|
// err := persist.LoadPolicyArray([]string{"p", role.UID, permission.HTTPPath, permission.HTTPMethod, permission.Name}, model)
|
||
|
// if err != nil {
|
||
|
// return fmt.Errorf("persist.LoadPolicyArray error: %w", err)
|
||
|
// }
|
||
|
// }
|
||
|
//}
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func (use *RBACUseCase) SyncPolicy(ctx context.Context, cron time.Duration) {
|
||
|
t := time.NewTicker(cron)
|
||
|
|
||
|
for {
|
||
|
select {
|
||
|
case <-t.C:
|
||
|
if err := use.LoadPolicy(ctx); err == nil {
|
||
|
logx.Info("LoadPolicy success")
|
||
|
}
|
||
|
case <-ctx.Done():
|
||
|
t.Stop()
|
||
|
logx.Info("exit Policy success")
|
||
|
|
||
|
return
|
||
|
}
|
||
|
}
|
||
|
}
|