142 lines
3.1 KiB
Go
142 lines
3.1 KiB
Go
package middleware
|
|
|
|
import (
|
|
"fmt"
|
|
"leafdev.top/Leaf/leaf-library-3/internal/pkg/response"
|
|
"net/http"
|
|
"strings"
|
|
|
|
userPkg "leafdev.top/Leaf/leaf-library-3/internal/dto/user"
|
|
|
|
"github.com/gofiber/fiber/v2"
|
|
"leafdev.top/Leaf/leaf-library-3/internal/base/conf"
|
|
"leafdev.top/Leaf/leaf-library-3/internal/services/auth"
|
|
)
|
|
|
|
type RBAC struct {
|
|
authService *auth.Service
|
|
config *conf.Config
|
|
}
|
|
|
|
func (m *RBAC) RoutePermission() fiber.Handler {
|
|
return func(c *fiber.Ctx) error {
|
|
user, ok := m.authService.GetUserSafe(c)
|
|
if !ok {
|
|
return response.Ctx(c).Error(nil).Status(http.StatusUnauthorized).Send()
|
|
}
|
|
|
|
if !user.Valid {
|
|
return response.Ctx(c).Error(nil).Status(http.StatusUnauthorized).Send()
|
|
}
|
|
|
|
var path = cleanPath(c.Path())
|
|
act := strings.ToLower(c.Method())
|
|
|
|
permissionName := userPkg.Permission(m.config.App.Name + ":" + path + ":" + act)
|
|
pass := user.HasPermissions(permissionName)
|
|
|
|
if !pass {
|
|
return response.Ctx(c).
|
|
Message(fmt.Sprintf("permission denied, permission name: %s", permissionName)).
|
|
Error(nil).
|
|
Status(http.StatusForbidden).
|
|
Send()
|
|
}
|
|
|
|
return c.Next()
|
|
}
|
|
}
|
|
|
|
func (m *RBAC) RequirePermissions(permissions ...string) fiber.Handler {
|
|
return func(c *fiber.Ctx) error {
|
|
user, ok := m.authService.GetUserSafe(c)
|
|
if !ok {
|
|
return response.Ctx(c).Error(nil).Status(http.StatusUnauthorized).Send()
|
|
}
|
|
|
|
if !user.Valid {
|
|
return response.Ctx(c).Error(nil).Status(http.StatusUnauthorized).Send()
|
|
}
|
|
|
|
var pass = true
|
|
var failedPermissionName string
|
|
|
|
for _, permission := range permissions {
|
|
permissionName := userPkg.Permission(m.config.App.Name + ":" + permission)
|
|
|
|
has := user.HasPermissions(permissionName)
|
|
if !has {
|
|
failedPermissionName = permissionName.String()
|
|
pass = false
|
|
break
|
|
}
|
|
}
|
|
|
|
if !pass {
|
|
return response.Ctx(c).
|
|
Message(fmt.Sprintf("permission denied, required permissions: %s, failed permission: %s",
|
|
permissions, failedPermissionName)).
|
|
Error(nil).
|
|
Status(http.StatusForbidden).
|
|
Send()
|
|
}
|
|
|
|
return c.Next()
|
|
}
|
|
}
|
|
|
|
func (m *RBAC) RequireRoles(roles ...string) fiber.Handler {
|
|
return func(c *fiber.Ctx) error {
|
|
user, ok := m.authService.GetUserSafe(c)
|
|
if !ok {
|
|
return response.Ctx(c).Error(nil).Status(http.StatusUnauthorized).Send()
|
|
}
|
|
|
|
if !user.Valid {
|
|
return response.Ctx(c).Error(nil).Status(http.StatusUnauthorized).Send()
|
|
}
|
|
|
|
var pass = true
|
|
var failedRoleName string
|
|
|
|
for _, role := range roles {
|
|
roleName := userPkg.Role(m.config.App.Name + ":" + role)
|
|
pass = user.HasRoles(roleName)
|
|
|
|
if !pass {
|
|
failedRoleName = roleName.String()
|
|
break
|
|
}
|
|
|
|
}
|
|
|
|
if !pass {
|
|
return response.Ctx(c).
|
|
Message(fmt.Sprintf("permission denied, required roles: %s, failed role %s", roles, failedRoleName)).
|
|
Error(nil).
|
|
Status(http.StatusForbidden).
|
|
Send()
|
|
}
|
|
|
|
return c.Next()
|
|
}
|
|
}
|
|
|
|
func NewRBAC(authService *auth.Service, config *conf.Config) *RBAC {
|
|
return &RBAC{
|
|
authService: authService,
|
|
config: config,
|
|
}
|
|
}
|
|
|
|
func cleanPath(path string) string {
|
|
// 如果第一个字符是 /,则删掉
|
|
if path[0] == '/' {
|
|
path = path[1:]
|
|
}
|
|
|
|
// 将所有的 / 转为 :
|
|
return strings.ReplaceAll(path, "/", ":")
|
|
|
|
}
|