go-quasar-partial-ssr/backend/internal/authorization/controller.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()
}
}