detached 0ea01e3

feat: Add default HTTP/HTTPS configuration and enhance OAuth flow logging

- Introduced a default value for HTTP/HTTPS configuration in init_config.go.
- Updated applyDefaultsToConfig to apply the default HTTPS setting if not explicitly defined.
- Modified OAuth callback route to log the callback endpoint and query parameters.
- Enhanced the OAuth flow initiation to log the generated proxy URL.
- Updated login page template to reflect the correct OAuth link path.
commit
0ea01e36ed84db2d2dee43723efb46a3b18694a8
author
bamen · · 2025-03-29 17:55 UTC
parent
61106b4
signature
unsigned
7 files · +34 -13
M internal/common/init_config.go +10 -0
@@ -103,6 +103,7 @@ var (
103103 renewBefore = 30 // days
104104 gracePeriod = 30 // seconds
105105 defaultLogLevel = "info" // Default log level
106+ defaultHttpHttps = true // Default to true
106107 disableRateLimit = false
107108 detectUpstreamProxy = false // Default to disabled
108109 skipCertificates = false // Default to disabled
@@ -143,6 +144,15 @@ func applyDefaultsToConfig(config *Config) bool {
143144 defaultsApplied = true
144145 }
145146
147+ // Apply defaults to HttpConfig
148+ // Check if Https is NOT explicitly set to true (i.e., it's the zero value 'false')
149+ if !config.Http.Https {
150+ config.Http.Https = defaultHttpHttps // Use the defined default variable
151+ logger.Debug("Applied default value for Http.Https", "value", defaultHttpHttps)
152+ defaultsApplied = true
153+ }
154+ // No defaults for Http.Port, Http.Domain, Http.SubDomain as they require explicit config
155+
146156 // Apply defaults to Admin config
147157 if config.Admin.Path == "" {
148158 config.Admin.Path = defaultAdminPath
@@ -103,6 +103,7 @@ var (
103 renewBefore = 30 // days103 renewBefore = 30 // days
104 gracePeriod = 30 // seconds104 gracePeriod = 30 // seconds
105 defaultLogLevel = "info" // Default log level105 defaultLogLevel = "info" // Default log level
106+ defaultHttpHttps = true // Default to true
106 disableRateLimit = false107 disableRateLimit = false
107 detectUpstreamProxy = false // Default to disabled108 detectUpstreamProxy = false // Default to disabled
108 skipCertificates = false // Default to disabled109 skipCertificates = false // Default to disabled
@@ -143,6 +144,15 @@ func applyDefaultsToConfig(config *Config) bool {
143 defaultsApplied = true144 defaultsApplied = true
144 }145 }
145 146
147+ // Apply defaults to HttpConfig
148+ // Check if Https is NOT explicitly set to true (i.e., it's the zero value 'false')
149+ if !config.Http.Https {
150+ config.Http.Https = defaultHttpHttps // Use the defined default variable
151+ logger.Debug("Applied default value for Http.Https", "value", defaultHttpHttps)
152+ defaultsApplied = true
153+ }
154+ // No defaults for Http.Port, Http.Domain, Http.SubDomain as they require explicit config
155+
146 // Apply defaults to Admin config156 // Apply defaults to Admin config
147 if config.Admin.Path == "" {157 if config.Admin.Path == "" {
148 config.Admin.Path = defaultAdminPath158 config.Admin.Path = defaultAdminPath
M internal/httpserve/handlers/login.go +11 -6
@@ -128,18 +128,21 @@ func StartOAuthGithub(c echo.Context, a *server.App) error {
128128 // initiateGithubOAuthFlow starts a new GitHub OAuth flow
129129 func initiateGithubOAuthFlow(c echo.Context, a *server.App) error {
130130 clientID := "" // IDK why it needs that even empty, but it does
131+ // Use the corrected generation function
131132 redirectDomain := a.GenerateOauthCallbackURL()
133+
132134 encodedState := base64.StdEncoding.EncodeToString([]byte("redirectDomain:" + redirectDomain))
133135
134- // Redirect to GitHub's OAuth endpoint to grab the OAuth access
136+ // Redirect to GitHub's OAuth endpoint via the proxy
135137 proxyURL := a.Config.Build.ProxyURL
136138 oauthURL := fmt.Sprintf(
137139 "%s/github/authorize?client_id=%s&redirect_uri=%s&state=%s",
138140 proxyURL,
139141 clientID,
140- redirectDomain,
142+ redirectDomain, // Pass the correctly generated public URL to the proxy
141143 encodedState,
142144 )
145+ logger.Debug("Initiating OAuth flow, redirecting to proxy", "proxy_url", oauthURL)
143146 return c.Redirect(http.StatusFound, oauthURL)
144147 }
145148
@@ -162,7 +165,7 @@ func OAuthCallback(c echo.Context, a *server.App) error {
162165 // update the struct with the new access token
163166 a.DBTables.Sessions.AccessToken = accessToken
164167
165- // Compare the state parameter with the redirect domain
168+ // Compare the state parameter with the correctly generated redirect domain
166169 redirectDomain := a.GenerateOauthCallbackURL()
167170 encodedRedirectDomain := base64.StdEncoding.EncodeToString([]byte("redirectDomain:" + redirectDomain))
168171 if encodedState != encodedRedirectDomain {
@@ -196,10 +199,11 @@ func OAuthCallback(c echo.Context, a *server.App) error {
196199 logger.Debug("Before setting session values", "account_id", accountID, "session", session)
197200 err = setSessionValues(c, sess, accountID, session)
198201 if err != nil {
199- logger.Error("Failed to set session values", "error", err)
200- return err
202+ // Error is already logged within setSessionValues
203+ return err // Return immediately if saving failed
201204 }
202- logger.Info("Session values set successfully")
205+ // Log success ONLY after setSessionValues returns without error
206+ logger.Info("Session values set and saved successfully")
203207
204208 logger.Info("OAuth callback successful, redirecting to", "path", redirectPath)
205209 return c.Redirect(http.StatusFound, redirectPath)
@@ -346,6 +350,7 @@ func setSessionValues(c echo.Context, sess *sessions.Session, accountID string,
346350 sess.Values["isOnline"] = session.IsOnline
347351
348352 if err := sess.Save(c.Request(), c.Response()); err != nil {
353+ logger.Error("Failed to save session cookie", "error", err, "sessionID", session.ID)
349354 return fmt.Errorf("could not save session: %w", err)
350355 }
351356 return nil
@@ -128,18 +128,21 @@ func StartOAuthGithub(c echo.Context, a *server.App) error {
128 // initiateGithubOAuthFlow starts a new GitHub OAuth flow128 // initiateGithubOAuthFlow starts a new GitHub OAuth flow
129 func initiateGithubOAuthFlow(c echo.Context, a *server.App) error {129 func initiateGithubOAuthFlow(c echo.Context, a *server.App) error {
130 clientID := "" // IDK why it needs that even empty, but it does130 clientID := "" // IDK why it needs that even empty, but it does
131+ // Use the corrected generation function
131 redirectDomain := a.GenerateOauthCallbackURL()132 redirectDomain := a.GenerateOauthCallbackURL()
133+
132 encodedState := base64.StdEncoding.EncodeToString([]byte("redirectDomain:" + redirectDomain))134 encodedState := base64.StdEncoding.EncodeToString([]byte("redirectDomain:" + redirectDomain))
133 135
134- // Redirect to GitHub's OAuth endpoint to grab the OAuth access136+ // Redirect to GitHub's OAuth endpoint via the proxy
135 proxyURL := a.Config.Build.ProxyURL137 proxyURL := a.Config.Build.ProxyURL
136 oauthURL := fmt.Sprintf(138 oauthURL := fmt.Sprintf(
137 "%s/github/authorize?client_id=%s&redirect_uri=%s&state=%s",139 "%s/github/authorize?client_id=%s&redirect_uri=%s&state=%s",
138 proxyURL,140 proxyURL,
139 clientID,141 clientID,
140- redirectDomain,142+ redirectDomain, // Pass the correctly generated public URL to the proxy
141 encodedState,143 encodedState,
142 )144 )
145+ logger.Debug("Initiating OAuth flow, redirecting to proxy", "proxy_url", oauthURL)
143 return c.Redirect(http.StatusFound, oauthURL)146 return c.Redirect(http.StatusFound, oauthURL)
144 }147 }
145 148
@@ -162,7 +165,7 @@ func OAuthCallback(c echo.Context, a *server.App) error {
162 // update the struct with the new access token165 // update the struct with the new access token
163 a.DBTables.Sessions.AccessToken = accessToken166 a.DBTables.Sessions.AccessToken = accessToken
164 167
165- // Compare the state parameter with the redirect domain168+ // Compare the state parameter with the correctly generated redirect domain
166 redirectDomain := a.GenerateOauthCallbackURL()169 redirectDomain := a.GenerateOauthCallbackURL()
167 encodedRedirectDomain := base64.StdEncoding.EncodeToString([]byte("redirectDomain:" + redirectDomain))170 encodedRedirectDomain := base64.StdEncoding.EncodeToString([]byte("redirectDomain:" + redirectDomain))
168 if encodedState != encodedRedirectDomain {171 if encodedState != encodedRedirectDomain {
@@ -196,10 +199,11 @@ func OAuthCallback(c echo.Context, a *server.App) error {
196 logger.Debug("Before setting session values", "account_id", accountID, "session", session)199 logger.Debug("Before setting session values", "account_id", accountID, "session", session)
197 err = setSessionValues(c, sess, accountID, session)200 err = setSessionValues(c, sess, accountID, session)
198 if err != nil {201 if err != nil {
199- logger.Error("Failed to set session values", "error", err)202+ // Error is already logged within setSessionValues
200- return err203+ return err // Return immediately if saving failed
201 }204 }
202- logger.Info("Session values set successfully")205+ // Log success ONLY after setSessionValues returns without error
206+ logger.Info("Session values set and saved successfully")
203 207
204 logger.Info("OAuth callback successful, redirecting to", "path", redirectPath)208 logger.Info("OAuth callback successful, redirecting to", "path", redirectPath)
205 return c.Redirect(http.StatusFound, redirectPath)209 return c.Redirect(http.StatusFound, redirectPath)
@@ -346,6 +350,7 @@ func setSessionValues(c echo.Context, sess *sessions.Session, accountID string,
346 sess.Values["isOnline"] = session.IsOnline350 sess.Values["isOnline"] = session.IsOnline
347 351
348 if err := sess.Save(c.Request(), c.Response()); err != nil {352 if err := sess.Save(c.Request(), c.Response()); err != nil {
353+ logger.Error("Failed to save session cookie", "error", err, "sessionID", session.ID)
349 return fmt.Errorf("could not save session: %w", err)354 return fmt.Errorf("could not save session: %w", err)
350 }355 }
351 return nil356 return nil
M internal/httpserve/router.go +2 -1
@@ -146,7 +146,8 @@ func bindLoginRoute(e *echo.Echo, a *server.App, adminPath string) {
146146 e.GET(adminPath+"/login/oauth/github", func(c echo.Context) error {
147147 return handlers.StartOAuthGithub(c, a)
148148 })
149- e.GET(adminPath+"/login/oauth/callback", func(c echo.Context) error {
149+ e.GET("/callback", func(c echo.Context) error {
150+ log.Debug("OAuth callback endpoint hit", "path", c.Path(), "query", c.QueryString())
150151 return handlers.OAuthCallback(c, a)
151152 })
152153 e.GET(adminPath+"/logout", func(c echo.Context) error {
@@ -146,7 +146,8 @@ func bindLoginRoute(e *echo.Echo, a *server.App, adminPath string) {
146 e.GET(adminPath+"/login/oauth/github", func(c echo.Context) error {146 e.GET(adminPath+"/login/oauth/github", func(c echo.Context) error {
147 return handlers.StartOAuthGithub(c, a)147 return handlers.StartOAuthGithub(c, a)
148 })148 })
149- e.GET(adminPath+"/login/oauth/callback", func(c echo.Context) error {149+ e.GET("/callback", func(c echo.Context) error {
150+ log.Debug("OAuth callback endpoint hit", "path", c.Path(), "query", c.QueryString())
150 return handlers.OAuthCallback(c, a)151 return handlers.OAuthCallback(c, a)
151 })152 })
152 e.GET(adminPath+"/logout", func(c echo.Context) error {153 e.GET(adminPath+"/logout", func(c echo.Context) error {
M internal/server/app_server.go +4 -4
@@ -59,9 +59,7 @@ func (a *App) GenerateOauthCallbackURL() string {
5959 if config.Http.Https {
6060 scheme = "https"
6161 port = ""
62- }
63-
64- if !config.Http.Https {
62+ } else {
6563 scheme = "http"
6664 port = fmt.Sprintf(":%s", a.Config.Http.Port)
6765 }
@@ -71,7 +69,9 @@ func (a *App) GenerateOauthCallbackURL() string {
7169 domain = fmt.Sprintf("%s.%s", config.Http.SubDomain, config.Http.Domain)
7270 }
7371
74- return fmt.Sprintf("%s://%s%s%s/login/oauth/callback", scheme, domain, port, config.Admin.Path)
72+ callbackURL := fmt.Sprintf("%s://%s%s/callback", scheme, domain, port)
73+ log.Debug("Generated OAuth Callback URL", "url", callbackURL)
74+ return callbackURL
7575 }
7676
7777 func (a *App) IsDevEnvironment() bool {
@@ -59,9 +59,7 @@ func (a *App) GenerateOauthCallbackURL() string {
59 if config.Http.Https {59 if config.Http.Https {
60 scheme = "https"60 scheme = "https"
61 port = ""61 port = ""
62- }62+ } else {
63-
64- if !config.Http.Https {
65 scheme = "http"63 scheme = "http"
66 port = fmt.Sprintf(":%s", a.Config.Http.Port)64 port = fmt.Sprintf(":%s", a.Config.Http.Port)
67 }65 }
@@ -71,7 +69,9 @@ func (a *App) GenerateOauthCallbackURL() string {
71 domain = fmt.Sprintf("%s.%s", config.Http.SubDomain, config.Http.Domain)69 domain = fmt.Sprintf("%s.%s", config.Http.SubDomain, config.Http.Domain)
72 }70 }
73 71
74- return fmt.Sprintf("%s://%s%s%s/login/oauth/callback", scheme, domain, port, config.Admin.Path)72+ callbackURL := fmt.Sprintf("%s://%s%s/callback", scheme, domain, port)
73+ log.Debug("Generated OAuth Callback URL", "url", callbackURL)
74+ return callbackURL
75 }75 }
76 76
77 func (a *App) IsDevEnvironment() bool {77 func (a *App) IsDevEnvironment() bool {
M internal/templating/models/templ/pages/login/index.templ +1 -1
@@ -84,7 +84,7 @@ templ LoginPage(title string, buildVersion string, errorMsg string) {
8484 <!-- GitHub OAuth -->
8585 <div class="w-full">
8686 <a
87- href="login/oauth/github"
87+ href="/admin/login/oauth/github"
8888 class="btn btn-secondary w-full"
8989 >
9090 <svg class="mr-2 h-5 w-5" fill="currentColor" viewBox="0 0 20 20" aria-hidden="true">
@@ -84,7 +84,7 @@ templ LoginPage(title string, buildVersion string, errorMsg string) {
84 <!-- GitHub OAuth -->84 <!-- GitHub OAuth -->
85 <div class="w-full">85 <div class="w-full">
86 <a 86 <a
87- href="login/oauth/github" 87+ href="/admin/login/oauth/github"
88 class="btn btn-secondary w-full"88 class="btn btn-secondary w-full"
89 >89 >
90 <svg class="mr-2 h-5 w-5" fill="currentColor" viewBox="0 0 20 20" aria-hidden="true">90 <svg class="mr-2 h-5 w-5" fill="currentColor" viewBox="0 0 20 20" aria-hidden="true">
A internal/templating/models/templ/pages/login/index.templ (lines 84-87) +5 -0
@@ -0,0 +1,5 @@
1+ <div class="w-full">
2+ <a
3+ href="login/oauth/github"
4+ class="btn btn-secondary w-full"
5+ > ⏎̸
@@ -0,0 +1,5 @@
1+ <div class="w-full">
2+ <a
3+ href="login/oauth/github"
4+ class="btn btn-secondary w-full"
5+ > ⏎̸
M internal/templating/models/templ/pages/login/index_templ.go +1 -1 generated file: collapsed

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 7

Tags 106

↑↓ moveenter openesc close