88 lines
1.7 KiB
Go
88 lines
1.7 KiB
Go
|
package privilege
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
"strings"
|
||
|
|
||
|
"esway/internal/model"
|
||
|
|
||
|
"github.com/loveuer/nf"
|
||
|
"github.com/loveuer/nf/nft/log"
|
||
|
"github.com/loveuer/nf/nft/resp"
|
||
|
"github.com/samber/lo"
|
||
|
)
|
||
|
|
||
|
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()
|
||
|
}
|
||
|
}
|