auth: split dev-mode auth constructor and wire up dev-login/logout UI
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 4s
Tests / Go tests (push) Successful in 13s

Squeamish about New()'s empty-domain-string sentinel for "dev mode, skip
OIDC discovery" - split into New (always makes a real OIDC discovery
call, all params required) and NewDev (no ctx/domain/credentials at all,
since none are used). main.go now branches on cfg.DevAuthEnabled to pick
the right constructor instead of main.go/config.go coordinating on when
it's safe to pass empty strings.

Also finishes out the dev-auth flow this enables: config.Load reads a
DEV_AUTH_ENABLED-aware env file and only requires Auth0 vars when dev
auth is off; a PORT config var replaces the hardcoded :8082; and the nav
UI (layout/index templates, ui router) points login/logout links at
/api/auth/dev-login and a new /api/auth/dev-logout route when dev auth
is enabled, so the whole login/logout loop works locally without a real
Auth0 app.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-20 00:36:55 -06:00
co-authored by Claude Sonnet 5
parent d2d67b43c1
commit ede7555d43
9 changed files with 275 additions and 64 deletions
+19
View File
@@ -35,6 +35,7 @@ func Routes(
if devAuthEnabled {
logger.Warn("DEV_AUTH_ENABLED is set: /api/auth/dev-login is live and lets any caller authenticate as any user_id with no credentials. Never enable this outside local development.")
r.GET("/dev-login", response.Handler(ls.devLoginPage))
r.GET("/dev-logout", response.Handler(ls.devLogoutPage))
}
}
@@ -135,3 +136,21 @@ func (s *loginSubrouter) logoutPage(c *gin.Context) (response.Response, error) {
return response.TemporaryRedirect(s.auth.GetLogoutURL(host).String()).
Cookie(cookies.Expired("access_token")), nil
}
func (s *loginSubrouter) devLogoutPage(c *gin.Context) (response.Response, error) {
r := c.Request
host := r.Header.Get("X-Forwarded-Host")
if host == "" {
host = r.Host
}
if ck, err := r.Cookie("access_token"); err == nil && ck != nil {
if err := s.auth.DeleteOAuthTokens(r.Context(), ck.Value); err != nil {
s.log.Error("failed to delete auth token", "error", err)
}
}
return response.TemporaryRedirect("/ui").
Cookie(cookies.Expired("access_token")), nil
}
+1
View File
@@ -65,6 +65,7 @@ func NewRouter(
reps,
etsy,
authM.Authenticate(),
devAuthEnabled,
)
// non-html content: scripts, styles, images, etc
+19 -11
View File
@@ -24,13 +24,14 @@ import (
type (
webpageRouter struct {
log *logging.Logger
uiPath string
templater *templater.Templater
rawEvents *raw_events.Store
accts *accounts.Store
reports *reports.Store
etsy *etsy_platform.Platform
log *logging.Logger
uiPath string
templater *templater.Templater
rawEvents *raw_events.Store
accts *accounts.Store
reports *reports.Store
etsy *etsy_platform.Platform
devAuthEnabled bool
}
// ErrTemplateNotFound is returned if the reason the template failed to compile
@@ -49,6 +50,7 @@ func Routes(
reps *reports.Store,
etsy *etsy_platform.Platform,
authenticate gin.HandlerFunc,
devAuthEnabled bool,
) {
s := &webpageRouter{
@@ -177,10 +179,11 @@ func Routes(
}
},
}),
rawEvents: rawEvents,
accts: accts,
reports: reps,
etsy: etsy,
rawEvents: rawEvents,
accts: accts,
reports: reps,
etsy: etsy,
devAuthEnabled: devAuthEnabled,
}
r.GET("", response.Handler(s.redirectToAccountsIfLoggedInWithAnAccount), response.Handler(s.serveTemplate))
@@ -219,6 +222,11 @@ func (s *webpageRouter) serveTemplate(c *gin.Context) (response.Response, error)
args := []any{
"Request",
r,
// dev mode
"DevAuthEnabled",
s.devAuthEnabled,
// add services and data here
"RawEvents",
s.rawEvents.WithContext(ctx),