80 lines
2.4 KiB
Go
80 lines
2.4 KiB
Go
package auth
|
|
|
|
import (
|
|
"strings"
|
|
|
|
"github.com/gofiber/fiber/v2"
|
|
)
|
|
|
|
func Middleware() fiber.Handler {
|
|
return func(c *fiber.Ctx) error {
|
|
header := c.Get("Authorization")
|
|
if header == "" {
|
|
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{"error": "missing authorization header"})
|
|
}
|
|
parts := strings.SplitN(header, " ", 2)
|
|
if len(parts) != 2 || parts[0] != "Bearer" {
|
|
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{"error": "invalid authorization format"})
|
|
}
|
|
claims, err := ParseToken(parts[1])
|
|
if err != nil {
|
|
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{"error": "invalid token"})
|
|
}
|
|
c.Locals("staffID", claims.StaffID)
|
|
c.Locals("staffName", claims.Name)
|
|
c.Locals("staffRole", claims.Role)
|
|
c.Locals("staffPermissions", claims.Permissions)
|
|
return c.Next()
|
|
}
|
|
}
|
|
|
|
// RequireRole restricts a route to the given roles. Must run after Middleware().
|
|
// Reserved for checks that are about the literal role identity (currently
|
|
// none left in this codebase — the last-owner protection in staff.Update
|
|
// checks the role column directly, not a request's claims) rather than what
|
|
// it's permitted to do; prefer RequirePermission for the latter.
|
|
func RequireRole(roles ...string) fiber.Handler {
|
|
allowed := make(map[string]bool, len(roles))
|
|
for _, r := range roles {
|
|
allowed[r] = true
|
|
}
|
|
return func(c *fiber.Ctx) error {
|
|
role, _ := c.Locals("staffRole").(string)
|
|
if !allowed[role] {
|
|
return c.Status(fiber.StatusForbidden).JSON(fiber.Map{"error": "insufficient role"})
|
|
}
|
|
return c.Next()
|
|
}
|
|
}
|
|
|
|
// RequirePermission restricts a route to staff whose role's permission set
|
|
// (baked into the JWT at login, see GenerateAccessToken) includes key. This
|
|
// is what a custom role's checkbox matrix actually gates — RequireRole
|
|
// only ever matches the three fixed system role names.
|
|
func RequirePermission(key string) fiber.Handler {
|
|
return func(c *fiber.Ctx) error {
|
|
perms, _ := c.Locals("staffPermissions").([]string)
|
|
for _, p := range perms {
|
|
if p == key {
|
|
return c.Next()
|
|
}
|
|
}
|
|
return c.Status(fiber.StatusForbidden).JSON(fiber.Map{"error": "insufficient permissions"})
|
|
}
|
|
}
|
|
|
|
func StaffID(c *fiber.Ctx) string {
|
|
id, _ := c.Locals("staffID").(string)
|
|
return id
|
|
}
|
|
|
|
func StaffRole(c *fiber.Ctx) string {
|
|
role, _ := c.Locals("staffRole").(string)
|
|
return role
|
|
}
|
|
|
|
func StaffPermissions(c *fiber.Ctx) []string {
|
|
perms, _ := c.Locals("staffPermissions").([]string)
|
|
return perms
|
|
}
|