mirror of
https://github.com/memohai/Memoh.git
synced 2026-04-27 07:16:19 +09:00
64378d29ed
* feat(web): add provider oauth management ui * feat: add OAuth callback support on port 1455 * feat: enhance reasoning effort options and support for OpenAI Codex OAuth * feat: update twilight-ai dependency to v0.3.4 * refactor: promote openai-codex to first-class client_type, remove auth_type Replace the previous openai-responses + metadata auth_type=openai-codex-oauth combo with a dedicated openai-codex client_type. OAuth requirement is now determined solely by client_type, eliminating the auth_type concept from the LLM provider domain entirely. - Add openai-codex to DB CHECK constraint (migration 0047) with data migration - Add ClientTypeOpenAICodex constant and dedicated SDK/probe branches - Remove AuthType from SDKModelConfig, ModelCredentials, TriggerConfig, etc. - Simplify supportsOAuth to check client_type == openai-codex - Add conf/providers/codex.yaml preset with Codex catalog models - Frontend: replace auth_type selector with client_type-driven OAuth UI --------- Co-authored-by: Acbox <acbox0328@gmail.com>
101 lines
2.0 KiB
Go
101 lines
2.0 KiB
Go
package server
|
|
|
|
import (
|
|
"context"
|
|
"log/slog"
|
|
"strings"
|
|
|
|
"github.com/labstack/echo/v4"
|
|
"github.com/labstack/echo/v4/middleware"
|
|
|
|
"github.com/memohai/memoh/internal/auth"
|
|
)
|
|
|
|
type Server struct {
|
|
echo *echo.Echo
|
|
addr string
|
|
logger *slog.Logger
|
|
}
|
|
|
|
type Handler interface {
|
|
Register(e *echo.Echo)
|
|
}
|
|
|
|
func NewServer(log *slog.Logger, addr string, jwtSecret string,
|
|
handlers ...Handler,
|
|
) *Server {
|
|
if addr == "" {
|
|
addr = ":8080"
|
|
}
|
|
|
|
e := echo.New()
|
|
e.HideBanner = true
|
|
e.Use(middleware.Recover())
|
|
e.Use(middleware.RequestLoggerWithConfig(middleware.RequestLoggerConfig{
|
|
LogStatus: true,
|
|
LogURI: true,
|
|
LogMethod: true,
|
|
LogValuesFunc: func(c echo.Context, v middleware.RequestLoggerValues) error {
|
|
log.Info("request",
|
|
slog.String("method", v.Method),
|
|
slog.String("uri", v.URI),
|
|
slog.Int("status", v.Status),
|
|
slog.Duration("latency", v.Latency),
|
|
slog.String("remote_ip", c.RealIP()),
|
|
)
|
|
return nil
|
|
},
|
|
}))
|
|
e.Use(auth.JWTMiddleware(jwtSecret, func(c echo.Context) bool {
|
|
return shouldSkipJWT(c.Request().URL.Path)
|
|
}))
|
|
|
|
for _, h := range handlers {
|
|
if h != nil {
|
|
h.Register(e)
|
|
}
|
|
}
|
|
|
|
return &Server{
|
|
echo: e,
|
|
addr: addr,
|
|
logger: log.With(slog.String("component", "server")),
|
|
}
|
|
}
|
|
|
|
func (s *Server) Start() error {
|
|
return s.echo.Start(s.addr)
|
|
}
|
|
|
|
func (s *Server) Stop(ctx context.Context) error {
|
|
return s.echo.Shutdown(ctx)
|
|
}
|
|
|
|
func shouldSkipJWT(path string) bool {
|
|
if path == "/" || path == "/ping" || path == "/health" || path == "/api/swagger.json" || path == "/auth/login" {
|
|
return true
|
|
}
|
|
if strings.HasPrefix(path, "/assets/") {
|
|
return true
|
|
}
|
|
if strings.HasPrefix(path, "/api/docs") {
|
|
return true
|
|
}
|
|
if strings.HasPrefix(path, "/channels/feishu/webhook/") {
|
|
return true
|
|
}
|
|
if strings.HasPrefix(path, "/email/mailgun/webhook/") {
|
|
return true
|
|
}
|
|
if strings.HasPrefix(path, "/email/oauth/callback") {
|
|
return true
|
|
}
|
|
if strings.HasPrefix(path, "/providers/oauth/callback") {
|
|
return true
|
|
}
|
|
if strings.HasPrefix(path, "/auth/callback") {
|
|
return true
|
|
}
|
|
return false
|
|
}
|