Files
shorebird-server/internal/api/middleware/auth.go
T
Tony 3bb4ab494e feat: implement database and storage abstractions
- Added `internal/db/store.go` to define the Store interface for database operations, including user, organization, app, channel, release, patch, and artifact management.
- Introduced `internal/models/models.go` changes to reflect updated organization and artifact response structures.
- Created `internal/storage/factory.go`, `local.go`, and `s3.go` to implement storage backends for local filesystem and S3-compatible services.
- Removed deprecated `internal/storage/storage.go` and refactored storage interface into `internal/storage/store.go`.
- Updated frontend JavaScript in `web/js/app.js` to display server health information, including storage and database backend details.
2026-06-12 08:45:01 +08:00

58 lines
1.5 KiB
Go

package middleware
import (
"context"
"net/http"
"strings"
"github.com/shorebird-server/internal/auth"
)
type contextKey string
const (
// ClaimsKey is the context key for auth claims.
ClaimsKey contextKey = "auth_claims"
)
// AuthMiddleware validates JWT tokens and injects claims into the request context.
func AuthMiddleware(authService *auth.Service) func(http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
authHeader := r.Header.Get("Authorization")
if authHeader == "" {
http.Error(w, `{"message":"Missing Authorization header"}`, http.StatusUnauthorized)
return
}
parts := strings.SplitN(authHeader, " ", 2)
if len(parts) != 2 || !strings.EqualFold(parts[0], "bearer") {
http.Error(w, `{"message":"Invalid Authorization header format"}`, http.StatusUnauthorized)
return
}
token := parts[1]
// Strip sb_api_ prefix (self-hosted API key format for Shorebird CLI compatibility)
token = strings.TrimPrefix(token, "sb_api_")
claims, err := authService.ValidateToken(token)
if err != nil {
http.Error(w, `{"message":"Invalid or expired token"}`, http.StatusUnauthorized)
return
}
ctx := context.WithValue(r.Context(), ClaimsKey, claims)
next.ServeHTTP(w, r.WithContext(ctx))
})
}
}
// GetClaims extracts auth claims from the request context.
func GetClaims(r *http.Request) *auth.Claims {
claims, ok := r.Context().Value(ClaimsKey).(*auth.Claims)
if !ok {
return nil
}
return claims
}