87 lines
1.7 KiB
Go
Raw Normal View History

2024-07-11 16:37:26 +08:00
package privilege
import (
"fmt"
"github.com/loveuer/nf"
"github.com/loveuer/nf/nft/log"
"github.com/loveuer/nf/nft/resp"
"github.com/samber/lo"
"strings"
"ultone/internal/model"
)
type Relation int64
type vf func(user *model.User, ps ...model.Privilege) error
const (
RelationAnd Relation = iota + 1
RelationOr
)
var (
AndFunc vf = func(user *model.User, ps ...model.Privilege) error {
pm := lo.SliceToMap(user.Privileges, func(item model.Privilege) (int64, struct{}) {
return item.Value(), struct{}{}
})
for _, p := range ps {
if _, exist := pm[p.Value()]; !exist {
return fmt.Errorf("缺少权限: %d, %s, %s", p.Value(), p.Code(), p.Label())
}
}
return nil
}
OrFunc vf = func(user *model.User, ps ...model.Privilege) error {
pm := lo.SliceToMap(user.Privileges, func(item model.Privilege) (int64, struct{}) {
return item.Value(), struct{}{}
})
for _, p := range ps {
if _, exist := pm[p.Value()]; exist {
return nil
}
}
return fmt.Errorf("缺少权限: %s", strings.Join(
lo.Map(ps, func(item model.Privilege, index int) string {
return item.Code()
}),
", ",
))
}
)
func Verify(relation Relation, privileges ...model.Privilege) nf.HandlerFunc {
var _vf vf
switch relation {
case RelationAnd:
_vf = AndFunc
case RelationOr:
_vf = OrFunc
default:
log.Panic("middleware.Verify: unknown relation")
}
return func(c *nf.Ctx) error {
if len(privileges) == 0 {
return c.Next()
}
op, ok := c.Locals("user").(*model.User)
if !ok {
return resp.Resp401(c, nil)
}
if err := _vf(op, privileges...); err != nil {
return resp.Resp403(c, err.Error())
}
return c.Next()
}
}