// auth.go — /api/auth/* 的 handler 註冊。 // // OB5(2026-04-26)起,OIDC 是唯一認證路徑: // - GET /api/auth/login → 302 to IdP(registerOIDCPublicRoutes 在 apiGroup 之外) // - GET /api/auth/callback → token exchange + cookie session(同上) // - POST /api/auth/login → 410 Gone(指引使用者改用 GET) // - POST /api/auth/logout → 清 cookie session(idempotent) // - GET /api/auth/me → 從 cookie session 拿 user info // - POST /api/auth/register → 501(註冊去 Member Center) // // 對齊 api-spec.md §1(Auth)+ oidc-tdd.md §3 / §4.5。 package api import ( "net/http" "github.com/gin-gonic/gin" ) // registerAuthRoutes 註冊 /api/auth/* 的 routes(OIDC 模式,唯一路徑)。 // // 注意:GET /api/auth/login 與 /api/auth/callback 是「不需登入即可呼叫」的 // public endpoint,由 NewRouter 透過 registerOIDCPublicRoutes 直接註冊在 r 上 // (不在 apiGroup 中),不在這裡。 func registerAuthRoutes(g *gin.RouterGroup, deps Deps) { g.POST("/auth/login", oidcLoginNotSupportedHandler()) g.POST("/auth/logout", oidcLogoutHandler(deps)) g.GET("/auth/me", oidcMeHandler(deps)) g.POST("/auth/register", authRegisterHandler()) } // oidcLoginNotSupportedHandler 回 410 Gone,告訴 caller 改用 GET /api/auth/login。 // // 為什麼選 410 而非 405: // - 405 Method Not Allowed 暗示「同 URL 換 method 就行」 — 但語意上 OIDC login // 是 redirect flow,不只是 method 換掉。 // - 410 Gone 明確表示「此資源已不存在於此 URL/method」,並可在訊息裡指引到正確端點。 func oidcLoginNotSupportedHandler() gin.HandlerFunc { return func(c *gin.Context) { WriteError(c, http.StatusGone, ErrCodeNotImplemented, "OIDC mode: use GET /api/auth/login to start the redirect flow", nil) } } // authRegisterHandler 實作 POST /api/auth/register。 // // OIDC 模式下 visionA 不負責註冊 — 註冊是 Member Center 的職責。 // 一律回 501,前端可顯示「請至 Member Center 註冊」。 func authRegisterHandler() gin.HandlerFunc { return func(c *gin.Context) { WriteNotImplemented(c, "auth.register — registration is handled by Innovedus Member Center") } }