Files
dev-service/pkg/api/middleware/auth.go
itzaname fecfc520a8
Some checks failed
continuous-integration/drone/push Build is failing
Update package path
2025-06-22 12:43:19 -04:00

122 lines
3.7 KiB
Go

package middleware
import (
"git.itzana.me/StrafesNET/dev-service/pkg/authz"
"github.com/gin-gonic/gin"
log "github.com/sirupsen/logrus"
"net/http"
)
// UserSession is middleware that handles user session validation and setup.
func UserSession(authService *authz.Service) gin.HandlerFunc {
return func(ctx *gin.Context) {
cookie, err := ctx.Request.Cookie("session_id")
if err != nil {
log.WithError(err).Debug("No session cookie found")
ctx.JSON(http.StatusUnauthorized, gin.H{"error": "Unauthorized"})
ctx.Abort()
return
}
sessionId := cookie.Value
// Validate session
valid, err := authService.ValidateSessionID(ctx, sessionId)
if err != nil || !valid {
log.WithError(err).WithField("session_id", sessionId).Info("Invalid session")
ctx.JSON(http.StatusUnauthorized, gin.H{"error": "Unauthorized"})
ctx.Abort()
return
}
// Find or create user using the authz service
user, err := authService.GetOrCreateUserFromSession(ctx, sessionId)
if err != nil {
log.WithError(err).WithField("session_id", sessionId).Error("Failed to get/create user from session")
ctx.JSON(http.StatusInternalServerError, gin.H{"error": "User management failed"})
ctx.Abort()
return
}
// Get user session
userSession, err := authService.GetUserAuthProfile(ctx, sessionId)
if err != nil {
log.WithError(err).WithField("session_id", sessionId).Error("Failed to get user session")
ctx.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to fetch user session"})
}
// GetCurrentUser user roles
userRoles, err := authService.GetUserRoles(ctx, cookie.Value)
if err != nil {
log.WithError(err).WithField("session_id", sessionId).Error("Failed to get user roles")
ctx.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to fetch user roles"})
ctx.Abort()
return
}
// Attach user and admin status to the context
ctx.Set(authz.ContextKeyUser, user)
isAdmin := authService.HasAdminRole(userRoles)
ctx.Set(authz.ContextKeyIsAdmin, isAdmin)
ctx.Set(authz.ContextKeyProfile, userSession)
ctx.Set(authz.ContextKeyRoles, userRoles)
log.WithFields(log.Fields{
"user_id": user.ID,
"username": user.Username,
"is_admin": isAdmin,
"num_roles": len(userRoles),
}).Debug("User session validated")
ctx.Next()
}
}
// RedirectIfNotLoggedIn is a simpler middleware that redirects to a specified URL
// if the user is not logged in, instead of returning a JSON error.
func RedirectIfNotLoggedIn(authService *authz.Service) gin.HandlerFunc {
return func(ctx *gin.Context) {
redirectURL, err := authService.GetLoginUrl(ctx)
if err != nil {
log.WithError(err).Error("Failed to get login url")
ctx.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to fetch login url"})
ctx.Abort()
return
}
cookie, err := ctx.Request.Cookie("session_id")
if err != nil {
log.WithError(err).Debug("No session cookie found, redirecting")
ctx.Redirect(302, redirectURL)
ctx.Abort()
return
}
sessionId := cookie.Value
// Validate session
valid, err := authService.ValidateSessionID(ctx, sessionId)
if err != nil || !valid {
log.WithError(err).WithField("session_id", sessionId).Info("Invalid session, redirecting")
ctx.Redirect(302, redirectURL)
ctx.Abort()
return
}
// Session is valid, continue to the next middleware/handler
ctx.Next()
}
}
// RequireAdmin is middleware that ensures only admin users can access certain routes
func RequireAdmin(authService *authz.Service) gin.HandlerFunc {
return func(ctx *gin.Context) {
// Use the helper function to check if user is admin
if !authService.ContextIsAdmin(ctx) {
ctx.JSON(http.StatusForbidden, gin.H{"error": "Admin access required"})
ctx.Abort()
return
}
ctx.Next()
}
}