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 } } }