1
0
mirror of https://github.com/fumiama/go-onebot-agent.git synced 2026-06-05 02:00:23 +08:00
Files
go-onebot-agent/perm.go
2025-09-21 14:52:52 +08:00

119 lines
2.4 KiB
Go

package goba
import (
_ "embed"
"os"
"strings"
"github.com/RomiChan/syncx"
"github.com/pkg/errors"
"gopkg.in/yaml.v3"
)
var (
ErrNoSuchPermRole = errors.New("no such perm role")
ErrUnexpectedAction = errors.New("unexpected action")
)
// PermRole 和 yaml config 一一对应
type PermRole string
const (
PermRoleOwner PermRole = "owner" // PermRoleOwner 群主或主人
PermRoleAdmin PermRole = "admin" // PermRoleAdmin 管理
PermRoleUser PermRole = "user" // PermRoleUser 普通用户
)
//go:embed actions.yaml
var innerpermtable []byte
// PermAction 记录 action 的描述和 params
type PermAction struct {
Desc string `yaml:"desc"`
Params string `yaml:"params"`
}
// Perm 即 actions.yaml 的 Go struct 映射
type Perm struct {
Actions map[string]PermAction `yaml:"actions"`
Config map[PermRole][]string `yaml:"config"`
cache syncx.Map[PermRole, actions] `yaml:"-"`
}
func (p *Perm) mdtable(role PermRole) (string, error) {
acs, ok := p.Config[role]
if !ok {
return "", errors.Wrap(ErrNoSuchPermRole, string(role))
}
table := strings.Builder{}
table.WriteString("|功能|action|params|\n|---|---|---|")
var ac actions
if _, ok := p.cache.Load(role); ok {
ac = actions{}
}
for _, act := range acs {
a, ok := p.Actions[act]
if !ok {
panic(errors.Wrap(ErrUnexpectedAction, act))
}
if ac != nil {
ac[act] = struct{}{}
}
table.WriteString("\n|")
table.WriteString(a.Desc)
table.WriteByte('|')
table.WriteString(act)
table.WriteByte('|')
table.WriteString(a.Params)
table.WriteByte('|')
}
if ac != nil {
p.cache.Store(role, ac)
}
return table.String(), nil
}
func (p *Perm) allow(role PermRole, action string) bool {
ac, ok := p.cache.Load(role)
if ok {
return ac.allow(action)
}
acs, ok := p.Config[role]
if !ok {
return false
}
ac = actions{}
for _, act := range acs {
ac[act] = struct{}{}
}
p.cache.Store(role, ac)
return ac.allow(action)
}
type actions map[string]struct{}
func (ac actions) allow(action string) bool {
_, ok := ac[action]
return ok
}
// LoadPermTable 读取 yaml file 并根据权限生成 MD 表格, 参数为空则加载内嵌配置
func (ag *Agent) LoadPermTable(file ...string) error {
var data []byte
if len(file) == 0 {
data = innerpermtable
} else {
var err error
data, err = os.ReadFile(file[0])
if err != nil {
return err
}
}
var cfg Perm
if err := yaml.Unmarshal(data, &cfg); err != nil {
return err
}
ag.perm = &cfg
return nil
}