60 lines
1.8 KiB
Go
60 lines
1.8 KiB
Go
|
|
package middleware
|
||
|
|
|
||
|
|
import (
|
||
|
|
"net/http"
|
||
|
|
|
||
|
|
"haixun-backend/internal/library/authctx"
|
||
|
|
app "haixun-backend/internal/library/errors"
|
||
|
|
"haixun-backend/internal/library/errors/code"
|
||
|
|
"haixun-backend/internal/library/permmatch"
|
||
|
|
memberdomain "haixun-backend/internal/model/member/domain/usecase"
|
||
|
|
permissiondomain "haixun-backend/internal/model/permission/domain/usecase"
|
||
|
|
"haixun-backend/internal/response"
|
||
|
|
)
|
||
|
|
|
||
|
|
// PermissionRBACMiddleware enforces catalog permissions for authenticated members.
|
||
|
|
// Mount after AuthJWT or MemberAuth so actor is present in context.
|
||
|
|
type PermissionRBACMiddleware struct {
|
||
|
|
members memberdomain.UseCase
|
||
|
|
permissions permissiondomain.UseCase
|
||
|
|
}
|
||
|
|
|
||
|
|
func NewPermissionRBACMiddleware(
|
||
|
|
members memberdomain.UseCase,
|
||
|
|
permissions permissiondomain.UseCase,
|
||
|
|
) *PermissionRBACMiddleware {
|
||
|
|
return &PermissionRBACMiddleware{members: members, permissions: permissions}
|
||
|
|
}
|
||
|
|
|
||
|
|
func (m *PermissionRBACMiddleware) Handle(next http.HandlerFunc) http.HandlerFunc {
|
||
|
|
return func(w http.ResponseWriter, r *http.Request) {
|
||
|
|
actor, ok := authctx.ActorFromContext(r.Context())
|
||
|
|
if !ok {
|
||
|
|
response.Write(r.Context(), w, nil, app.For(code.Auth).AuthUnauthorized("missing actor"))
|
||
|
|
return
|
||
|
|
}
|
||
|
|
if m.members == nil || m.permissions == nil {
|
||
|
|
response.Write(r.Context(), w, nil, app.For(code.Permission).SysNotImplemented("permission rbac is not configured"))
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
member, err := m.members.GetByUID(r.Context(), actor.TenantID, actor.UID)
|
||
|
|
if err != nil {
|
||
|
|
response.Write(r.Context(), w, nil, err)
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
me, err := m.permissions.Me(r.Context(), member, false)
|
||
|
|
if err != nil {
|
||
|
|
response.Write(r.Context(), w, nil, err)
|
||
|
|
return
|
||
|
|
}
|
||
|
|
if !permmatch.RequestAllowed(me.Permissions, r.Method, r.URL.Path) {
|
||
|
|
response.Write(r.Context(), w, nil, app.For(code.Permission).AuthForbidden("permission denied"))
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
next(w, r)
|
||
|
|
}
|
||
|
|
}
|