Updated the security package

This commit is contained in:
Hein
2025-11-24 17:00:05 +02:00
parent 26c175e65e
commit e32ec9e17e
13 changed files with 2981 additions and 1399 deletions

View File

@@ -10,38 +10,72 @@ type contextKey string
const (
// Context keys for user information
UserIDKey contextKey = "user_id"
UserRolesKey contextKey = "user_roles"
UserTokenKey contextKey = "user_token"
UserIDKey contextKey = "user_id"
UserNameKey contextKey = "user_name"
UserLevelKey contextKey = "user_level"
SessionIDKey contextKey = "session_id"
RemoteIDKey contextKey = "remote_id"
UserRolesKey contextKey = "user_roles"
UserEmailKey contextKey = "user_email"
UserContextKey contextKey = "user_context"
)
// AuthMiddleware extracts user authentication from request and adds to context
// This should be applied before the ResolveSpec handler
// Uses GlobalSecurity.AuthenticateCallback if set, otherwise returns error
func AuthMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Check if callback is set
if GlobalSecurity.AuthenticateCallback == nil {
http.Error(w, "AuthenticateCallback not set - you must provide an authentication callback", http.StatusInternalServerError)
return
}
// NewAuthMiddleware creates an authentication middleware with the given security list
// This middleware extracts user authentication from the request and adds it to context
func NewAuthMiddleware(securityList *SecurityList) func(http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Get the security provider
provider := securityList.Provider()
if provider == nil {
http.Error(w, "Security provider not configured", http.StatusInternalServerError)
return
}
// Call the user-provided authentication callback
userID, roles, err := GlobalSecurity.AuthenticateCallback(r)
if err != nil {
http.Error(w, "Authentication failed: "+err.Error(), http.StatusUnauthorized)
return
}
// Call the provider's Authenticate method
userCtx, err := provider.Authenticate(r)
if err != nil {
http.Error(w, "Authentication failed: "+err.Error(), http.StatusUnauthorized)
return
}
// Add user information to context
ctx := context.WithValue(r.Context(), UserIDKey, userID)
if roles != "" {
ctx = context.WithValue(ctx, UserRolesKey, roles)
}
// Add user information to context
ctx := r.Context()
ctx = context.WithValue(ctx, UserContextKey, userCtx)
ctx = context.WithValue(ctx, UserIDKey, userCtx.UserID)
ctx = context.WithValue(ctx, UserNameKey, userCtx.UserName)
ctx = context.WithValue(ctx, UserLevelKey, userCtx.UserLevel)
ctx = context.WithValue(ctx, SessionIDKey, userCtx.SessionID)
ctx = context.WithValue(ctx, RemoteIDKey, userCtx.RemoteID)
// Continue with authenticated context
next.ServeHTTP(w, r.WithContext(ctx))
})
if len(userCtx.Roles) > 0 {
ctx = context.WithValue(ctx, UserRolesKey, userCtx.Roles)
}
if userCtx.Email != "" {
ctx = context.WithValue(ctx, UserEmailKey, userCtx.Email)
}
// Continue with authenticated context
next.ServeHTTP(w, r.WithContext(ctx))
})
}
}
// SetSecurityMiddleware adds security context to requests
// This middleware should be applied after AuthMiddleware
func SetSecurityMiddleware(securityList *SecurityList) func(http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
ctx := context.WithValue(r.Context(), SECURITY_CONTEXT_KEY, securityList)
next.ServeHTTP(w, r.WithContext(ctx))
})
}
}
// GetUserContext extracts the full user context from request context
func GetUserContext(ctx context.Context) (*UserContext, bool) {
userCtx, ok := ctx.Value(UserContextKey).(*UserContext)
return userCtx, ok
}
// GetUserID extracts the user ID from context
@@ -50,8 +84,38 @@ func GetUserID(ctx context.Context) (int, bool) {
return userID, ok
}
// GetUserName extracts the user name from context
func GetUserName(ctx context.Context) (string, bool) {
userName, ok := ctx.Value(UserNameKey).(string)
return userName, ok
}
// GetUserLevel extracts the user level from context
func GetUserLevel(ctx context.Context) (int, bool) {
userLevel, ok := ctx.Value(UserLevelKey).(int)
return userLevel, ok
}
// GetSessionID extracts the session ID from context
func GetSessionID(ctx context.Context) (string, bool) {
sessionID, ok := ctx.Value(SessionIDKey).(string)
return sessionID, ok
}
// GetRemoteID extracts the remote ID from context
func GetRemoteID(ctx context.Context) (string, bool) {
remoteID, ok := ctx.Value(RemoteIDKey).(string)
return remoteID, ok
}
// GetUserRoles extracts user roles from context
func GetUserRoles(ctx context.Context) (string, bool) {
roles, ok := ctx.Value(UserRolesKey).(string)
func GetUserRoles(ctx context.Context) ([]string, bool) {
roles, ok := ctx.Value(UserRolesKey).([]string)
return roles, ok
}
// GetUserEmail extracts user email from context
func GetUserEmail(ctx context.Context) (string, bool) {
email, ok := ctx.Value(UserEmailKey).(string)
return email, ok
}