136 lines
2.9 KiB
Go
Raw Normal View History

2025-03-16 12:05:38 +08:00
package permission
import (
"context"
"github.com/emicklei/go-restful/v3"
"github.com/infraboard/mcube/v2/exception"
"github.com/infraboard/mcube/v2/http/restful/response"
"github.com/infraboard/mcube/v2/ioc"
"github.com/infraboard/mcube/v2/ioc/config/gorestful"
"github.com/infraboard/mcube/v2/ioc/config/log"
"github.com/infraboard/modules/iam/apps/endpoint"
"github.com/infraboard/modules/iam/apps/policy"
"github.com/infraboard/modules/iam/apps/token"
"github.com/rs/zerolog"
)
func Auth(v bool) (string, bool) {
return endpoint.META_REQUIRED_AUTH_KEY, v
}
func Permission(v bool) (string, bool) {
return endpoint.META_REQUIRED_PERM_KEY, v
}
func Required(roles ...string) (string, []string) {
return endpoint.META_REQUIRED_ROLE_KEY, roles
}
func init() {
ioc.Config().Registry(&Checker{})
}
type Checker struct {
ioc.ObjectImpl
log *zerolog.Logger
token token.Service
policy policy.Service
}
func (c *Checker) Name() string {
return "permission_checker"
}
func (c *Checker) Priority() int {
return gorestful.Priority() - 1
}
func (c *Checker) Init() error {
c.log = log.Sub(c.Name())
c.token = token.GetService()
c.policy = policy.GetService()
// 注册认证中间件
gorestful.RootRouter().Filter(c.Check)
return nil
}
func (c *Checker) Check(r *restful.Request, w *restful.Response, next *restful.FilterChain) {
2025-03-16 15:26:12 +08:00
route := endpoint.NewEntryFromRestRouteReader(r.SelectedRoute())
2025-03-16 12:05:38 +08:00
if route.RequiredAuth {
// 校验身份
tk, err := c.CheckToken(r)
if err != nil {
response.Failed(w, err)
return
}
// 校验权限
if err := c.CheckPolicy(r, tk, route); err != nil {
response.Failed(w, err)
return
}
}
next.ProcessFilter(r, w)
}
func (c *Checker) CheckToken(r *restful.Request) (*token.Token, error) {
v := token.GetAccessTokenFromHTTP(r.Request)
if v == "" {
return nil, exception.NewUnauthorized("请先登录")
}
tk, err := c.token.ValiateToken(r.Request.Context(), token.NewValiateTokenRequest(v))
if err != nil {
return nil, err
}
ctx := context.WithValue(r.Request.Context(), token.CTX_TOKEN_KEY, tk)
r.Request = r.Request.WithContext(ctx)
return tk, nil
}
func (c *Checker) CheckPolicy(r *restful.Request, tk *token.Token, route *endpoint.RouteEntry) error {
if tk.IsAdmin {
return nil
}
set, err := c.policy.QueryPolicy(r.Request.Context(),
policy.NewQueryPolicyRequest().
SetNamespaceId(tk.NamespaceId).
SetUserId(tk.UserId).
SetExpired(false).
SetEnabled(true).
SetWithRole(true),
)
if err != nil {
return exception.NewInternalServerError(err.Error())
}
// 角色校验
if route.HasRequiredRole() {
for i := range set.Items {
p := set.Items[i]
if route.IsRequireRole(p.Role.Name) {
return nil
}
}
}
// API权限校验
if route.RequiredPerm {
for i := range set.Items {
p := set.Items[i]
if p.Role == nil {
return exception.NewInternalServerError("policy role is nil")
}
}
}
return nil
}