Add /auth/login and /auth/callback handlers. The backend holds the client secret and exchanges the authorization code server-side; the browser never sees the secret. Redirect URI and post-login fragment destination are derived solely from GATEWAY_SERVER_PUBLIC_URL (required when OIDC is set) to prevent host-header injection.
84 lines
2.8 KiB
Go
84 lines
2.8 KiB
Go
// Package api implements the gateway HTTP surface: the OpenAI-compatible proxy
|
|
// (/v1/*) and the admin API (/api/admin/*).
|
|
package api
|
|
|
|
import (
|
|
"context"
|
|
|
|
"github.com/go-chi/chi/v5"
|
|
|
|
"git.govekar.net/LovroG05/localmodelroutex/internal/catalog"
|
|
"git.govekar.net/LovroG05/localmodelroutex/internal/crypto"
|
|
"git.govekar.net/LovroG05/localmodelroutex/internal/providermgr"
|
|
"git.govekar.net/LovroG05/localmodelroutex/internal/ratelimit"
|
|
"git.govekar.net/LovroG05/localmodelroutex/internal/store"
|
|
)
|
|
|
|
// oidcVerifier validates OIDC tokens for admin access.
|
|
// Satisfied by *oidcauth.Verifier; nil means OIDC is not configured.
|
|
type oidcVerifier interface {
|
|
VerifyAdmin(ctx context.Context, rawToken string) error
|
|
}
|
|
|
|
// Deps are the dependencies the API handlers need.
|
|
type Deps struct {
|
|
Store *store.Store
|
|
Cache *catalog.Cache
|
|
Manager *providermgr.Manager
|
|
Cipher *crypto.Cipher
|
|
AdminToken string
|
|
OIDCVerifier oidcVerifier // nil when OIDC is not configured
|
|
OIDCClientID string // empty when OIDC is not configured
|
|
OIDCClientSecret string
|
|
OIDCAuthURL string // authorization_endpoint from discovery
|
|
OIDCTokenURL string // token_endpoint from discovery
|
|
// PublicBaseURL is the canonical external URL of this server (e.g.
|
|
// "https://lmr.example.com"). Required when OIDC is enabled — used to
|
|
// build the redirect_uri and the post-login fragment redirect so neither
|
|
// can be overridden by a forged Host/X-Forwarded-Host header.
|
|
PublicBaseURL string
|
|
Limiter *ratelimit.Limiter
|
|
// SyncNow triggers an immediate provider reload + catalog sync (used after
|
|
// admin changes). May be nil.
|
|
SyncNow func(context.Context) error
|
|
}
|
|
|
|
// API holds handler dependencies.
|
|
type API struct {
|
|
Deps
|
|
}
|
|
|
|
// New returns an API.
|
|
func New(d Deps) *API { return &API{Deps: d} }
|
|
|
|
// Mount registers the proxy and admin routes on r.
|
|
func (a *API) Mount(r chi.Router) {
|
|
r.Route("/v1", func(r chi.Router) {
|
|
r.Use(a.virtualKeyAuth)
|
|
r.Post("/chat/completions", a.chatCompletions)
|
|
r.Post("/embeddings", a.embeddings)
|
|
r.Get("/models", a.listModels)
|
|
})
|
|
|
|
// Public auth endpoints — no auth middleware.
|
|
r.Get("/api/auth/config", a.authConfig)
|
|
r.Get("/auth/login", a.oidcLogin)
|
|
r.Get("/auth/callback", a.oidcCallback)
|
|
|
|
r.Route("/api/admin", func(r chi.Router) {
|
|
r.Use(a.adminAuth)
|
|
r.Get("/providers", a.adminListProviders)
|
|
r.Post("/providers", a.adminCreateProvider)
|
|
r.Delete("/providers/{id}", a.adminDeleteProvider)
|
|
r.Get("/keys", a.adminListKeys)
|
|
r.Post("/keys", a.adminCreateKey)
|
|
r.Delete("/keys/{id}", a.adminRevokeKey)
|
|
r.Get("/logs", a.adminListLogs)
|
|
r.Get("/models", a.adminListModels)
|
|
r.Patch("/models/{id}", a.adminUpdateModel)
|
|
r.Get("/settings", a.adminGetSettings)
|
|
r.Put("/settings/{key}", a.adminPutSetting)
|
|
r.Post("/catalog/refresh", a.adminRefreshCatalog)
|
|
})
|
|
}
|