151 lines
3.4 KiB
Go
151 lines
3.4 KiB
Go
package repository
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"time"
|
|
|
|
"code.30cm.net/digimon/app-cloudep-permission-server/pkg/domain"
|
|
"code.30cm.net/digimon/app-cloudep-permission-server/pkg/domain/rbac"
|
|
"code.30cm.net/digimon/app-cloudep-permission-server/pkg/domain/repository"
|
|
"github.com/casbin/casbin/v2/model"
|
|
"github.com/casbin/casbin/v2/persist"
|
|
"github.com/zeromicro/go-zero/core/stores/redis"
|
|
)
|
|
|
|
type RBACAdapterParam struct {
|
|
Redis *redis.Redis
|
|
}
|
|
|
|
type rbacAdapter struct {
|
|
redis *redis.Redis
|
|
}
|
|
|
|
func NewRBACAdapter(param RBACAdapterParam) (repository.RBACAdapter, error) {
|
|
return &rbacAdapter{
|
|
redis: param.Redis,
|
|
}, nil
|
|
}
|
|
|
|
// loadPolicyByString 真正將 Rule 存到 casbin 讓他可以使用的地方
|
|
func loadPolicyByString(line rbac.Rule, model model.Model) error {
|
|
text := line.ToString()
|
|
// 雖然是從Redis 來,不過最終還是有一份會存在記憶體當中,這樣做的原因只是不要存第二次
|
|
err := persist.LoadPolicyArray(text, model)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// LoadPolicy 將檔案從記憶體當中載入本地 Casbin
|
|
func (adapter *rbacAdapter) LoadPolicy(model model.Model) error {
|
|
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
|
defer cancel()
|
|
|
|
rk := domain.GetCasbinRuleRedisKey()
|
|
stop, err := adapter.redis.LlenCtx(ctx, rk)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
rules, err := adapter.redis.LrangeCtx(ctx, rk, 0, stop)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
for _, ruleStr := range rules {
|
|
var rule rbac.Rule
|
|
err := json.Unmarshal([]byte(ruleStr), &rule)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
err = loadPolicyByString(rule, model)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// SavePolicy saves policy to database. 將 Rule 一次就從資料庫中存到 redis 裡面 -> 打API 初始化 Redis 同步的資料
|
|
func (adapter *rbacAdapter) SavePolicy(model model.Model) error {
|
|
rk := domain.GetCasbinRuleRedisKey()
|
|
_, err := adapter.redis.Del(rk)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
var texts []string
|
|
|
|
for policy, ast := range model["p"] {
|
|
for _, rule := range ast.Policy {
|
|
line := rbac.StringToPolicy(policy, rule)
|
|
text, err := json.Marshal(line)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
texts = append(texts, string(text))
|
|
}
|
|
}
|
|
|
|
for policy, ast := range model["g"] {
|
|
for _, rule := range ast.Policy {
|
|
line := rbac.StringToPolicy(policy, rule)
|
|
text, err := json.Marshal(line)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
texts = append(texts, string(text))
|
|
}
|
|
}
|
|
|
|
_, err = adapter.redis.Rpush(rk, texts)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// AddPolicy adds a policy rule to the storage.
|
|
func (adapter *rbacAdapter) AddPolicy(_ string, policyType string, rule []string) error {
|
|
policy := rbac.StringToPolicy(policyType, rule)
|
|
text, err := json.Marshal(policy)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
rk := domain.GetCasbinRuleRedisKey()
|
|
_, err = adapter.redis.Rpush(rk, text)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (adapter *rbacAdapter) RemovePolicy(_ string, policyType string, rule []string) error {
|
|
policy := rbac.StringToPolicy(policyType, rule)
|
|
text, err := json.Marshal(policy)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
rk := domain.GetCasbinRuleRedisKey()
|
|
_, err = adapter.redis.Lrem(rk, 1, string(text))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// RemoveFilteredPolicy 沒用到先不實作
|
|
func (adapter *rbacAdapter) RemoveFilteredPolicy(_ string, _ string, _ int, _ ...string) error {
|
|
return nil
|
|
}
|