86 lines
2.3 KiB
Go
86 lines
2.3 KiB
Go
package authorization
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"server/internal/auth"
|
|
"server/internal/models"
|
|
"strings"
|
|
|
|
"github.com/gofiber/fiber/v3"
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
var Endpoints map[string]int
|
|
|
|
type Permission int
|
|
|
|
type Role struct {
|
|
Name string
|
|
Permissions Permission
|
|
}
|
|
|
|
const (
|
|
SuperAdminPermission Permission = 0b1111111111111111
|
|
AdminPermission Permission = 0b0111111111111111
|
|
ManagerPermission Permission = 0b0010111111111111
|
|
ContentCreatorPermission Permission = 0b0001111111111111
|
|
UserPermission Permission = 0b0000000000000011
|
|
GuestPermission Permission = 0b0000000000000001
|
|
)
|
|
|
|
var Roles = []Role{
|
|
{"superadmin", SuperAdminPermission},
|
|
{"admin", AdminPermission},
|
|
{"manager", ManagerPermission},
|
|
{"content_creator", ContentCreatorPermission},
|
|
{"user", UserPermission},
|
|
{"guest", GuestPermission},
|
|
}
|
|
|
|
func init() {
|
|
Endpoints = make(map[string]int)
|
|
}
|
|
|
|
func RegisterEndpoint(key string, permission int) {
|
|
Endpoints[key] = permission
|
|
}
|
|
|
|
// RequireEndpointPermission enforces permission mapping defined in role config.
|
|
// If the endpoint is not configured, or mapped to "*", it allows the request.
|
|
func RequireEndpointPermission(authService *auth.AuthService, dbConn *gorm.DB) fiber.Handler {
|
|
return func(c fiber.Ctx) error {
|
|
fmt.Printf("Checking permissions for %s%s\n", strings.TrimSpace(c.Method()), strings.TrimSpace(c.Path()))
|
|
perm := Endpoints[strings.TrimSpace(c.Method())+strings.TrimSpace(c.Path())]
|
|
if perm == 0 {
|
|
return c.Next()
|
|
}
|
|
|
|
tokenString := c.Get("Auth-Token")
|
|
if tokenString == "" {
|
|
return fiber.NewError(fiber.StatusUnauthorized, "missing token header")
|
|
}
|
|
|
|
claims, err := authService.ValidateAccessToken(tokenString)
|
|
if err != nil {
|
|
return fiber.NewError(fiber.StatusUnauthorized, err.Error())
|
|
}
|
|
c.Locals("authClaims", claims)
|
|
|
|
var user models.User
|
|
if err := dbConn.Select("roles").Where("email = ?", claims.Username).First(&user).Error; err != nil {
|
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
return fiber.NewError(fiber.StatusUnauthorized, "user not found")
|
|
}
|
|
return fiber.NewError(fiber.StatusInternalServerError, "failed to load user roles")
|
|
}
|
|
|
|
// user need to have at least one role that satisfies the permission requirement
|
|
if user.Roles == nil {
|
|
return fiber.NewError(fiber.StatusForbidden, "insufficient permissions")
|
|
}
|
|
|
|
return c.Next()
|
|
}
|
|
}
|