mirror of
https://github.com/Dvorinka/Bookra.git
synced 2026-06-03 20:13:00 +00:00
first commit
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"bookra/apps/backend/internal/db"
|
||||
"bookra/apps/backend/internal/domain"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
const principalContextKey = "principal"
|
||||
|
||||
func RequireAuth(verifier *Verifier, repo db.Repository) gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
if verifier == nil || !verifier.Enabled() {
|
||||
c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "auth_not_configured"})
|
||||
return
|
||||
}
|
||||
|
||||
header := c.GetHeader("Authorization")
|
||||
tokenString, ok := strings.CutPrefix(header, "Bearer ")
|
||||
if !ok || strings.TrimSpace(tokenString) == "" {
|
||||
c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "missing_bearer_token"})
|
||||
return
|
||||
}
|
||||
|
||||
claims, err := verifier.Verify(strings.TrimSpace(tokenString))
|
||||
if err != nil {
|
||||
c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "invalid_token"})
|
||||
return
|
||||
}
|
||||
|
||||
subject, _ := claims["sub"].(string)
|
||||
email, _ := claims["email"].(string)
|
||||
name, _ := claims["name"].(string)
|
||||
if name == "" {
|
||||
name, _ = claims["display_name"].(string)
|
||||
}
|
||||
role, _ := claims["role"].(string)
|
||||
if role == "" {
|
||||
role = "authenticated"
|
||||
}
|
||||
if strings.TrimSpace(subject) == "" {
|
||||
c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "invalid_token_subject"})
|
||||
return
|
||||
}
|
||||
if repo != nil {
|
||||
if err := repo.EnsureUserIdentity(c.Request.Context(), subject, email, name); err != nil {
|
||||
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"error": "identity_sync_failed"})
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
c.Set(principalContextKey, domain.Principal{
|
||||
Subject: subject,
|
||||
Email: email,
|
||||
Name: name,
|
||||
Role: role,
|
||||
})
|
||||
|
||||
c.Next()
|
||||
}
|
||||
}
|
||||
|
||||
func PrincipalFromContext(c *gin.Context) domain.Principal {
|
||||
value, ok := c.Get(principalContextKey)
|
||||
if !ok {
|
||||
return domain.Principal{}
|
||||
}
|
||||
principal, _ := value.(domain.Principal)
|
||||
return principal
|
||||
}
|
||||
Reference in New Issue
Block a user