app-cloudep-permission-server/pkg/repository/casbin_redis_adapter.go

151 lines
3.4 KiB
Go
Raw Normal View History

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
}