feat: configurable component-level logging (#575)

* Refactor logging to use centralized logger utility

- Removed direct usage of zerolog in multiple files and replaced it with a centralized logging utility in the `utils` package.
- Introduced `Loggers` struct to manage different loggers (Audit, HTTP, App) with configurable levels and outputs.
- Updated all relevant files to utilize the new logging structure, ensuring consistent logging practices across the application.
- Enhanced error handling and logging messages for better traceability and debugging.

* refactor: update logging implementation to use new logger structure

* Refactor logging to use tlog package

- Replaced instances of utils logging with tlog in various controllers, services, and middleware.
- Introduced audit logging for login success, login failure, and logout events.
- Created tlog package with structured logging capabilities using zerolog.
- Added tests for the new tlog logger functionality.

* refactor: update logging configuration in environment files

* fix: adding coderabbit suggestions

* fix: ensure correct audit caller

* fix: include reason in audit login failure logs
This commit is contained in:
Pushpinder Singh
2026-01-15 08:57:19 -05:00
committed by GitHub
parent ba2d732415
commit 53bd413046
28 changed files with 486 additions and 214 deletions

View File

@@ -8,9 +8,9 @@ import (
"github.com/steveiliop56/tinyauth/internal/config"
"github.com/steveiliop56/tinyauth/internal/service"
"github.com/steveiliop56/tinyauth/internal/utils"
"github.com/steveiliop56/tinyauth/internal/utils/tlog"
"github.com/gin-gonic/gin"
"github.com/rs/zerolog/log"
)
type ContextMiddlewareConfig struct {
@@ -40,7 +40,7 @@ func (m *ContextMiddleware) Middleware() gin.HandlerFunc {
cookie, err := m.auth.GetSessionCookie(c)
if err != nil {
log.Debug().Err(err).Msg("No valid session cookie found")
tlog.App.Debug().Err(err).Msg("No valid session cookie found")
goto basic
}
@@ -62,7 +62,7 @@ func (m *ContextMiddleware) Middleware() gin.HandlerFunc {
userSearch := m.auth.SearchUser(cookie.Username)
if userSearch.Type == "unknown" || userSearch.Type == "error" {
log.Debug().Msg("User from session cookie not found")
tlog.App.Debug().Msg("User from session cookie not found")
m.auth.DeleteSessionCookie(c)
goto basic
}
@@ -81,13 +81,13 @@ func (m *ContextMiddleware) Middleware() gin.HandlerFunc {
_, exists := m.broker.GetService(cookie.Provider)
if !exists {
log.Debug().Msg("OAuth provider from session cookie not found")
tlog.App.Debug().Msg("OAuth provider from session cookie not found")
m.auth.DeleteSessionCookie(c)
goto basic
}
if !m.auth.IsEmailWhitelisted(cookie.Email) {
log.Debug().Msg("Email from session cookie not whitelisted")
tlog.App.Debug().Msg("Email from session cookie not whitelisted")
m.auth.DeleteSessionCookie(c)
goto basic
}
@@ -112,7 +112,7 @@ func (m *ContextMiddleware) Middleware() gin.HandlerFunc {
basic := m.auth.GetBasicAuth(c)
if basic == nil {
log.Debug().Msg("No basic auth provided")
tlog.App.Debug().Msg("No basic auth provided")
c.Next()
return
}
@@ -120,7 +120,7 @@ func (m *ContextMiddleware) Middleware() gin.HandlerFunc {
locked, remaining := m.auth.IsAccountLocked(basic.Username)
if locked {
log.Debug().Msgf("Account for user %s is locked for %d seconds, denying auth", basic.Username, remaining)
tlog.App.Debug().Msgf("Account for user %s is locked for %d seconds, denying auth", basic.Username, remaining)
c.Writer.Header().Add("x-tinyauth-lock-locked", "true")
c.Writer.Header().Add("x-tinyauth-lock-reset", time.Now().Add(time.Duration(remaining)*time.Second).Format(time.RFC3339))
c.Next()
@@ -131,14 +131,14 @@ func (m *ContextMiddleware) Middleware() gin.HandlerFunc {
if userSearch.Type == "unknown" || userSearch.Type == "error" {
m.auth.RecordLoginAttempt(basic.Username, false)
log.Debug().Msg("User from basic auth not found")
tlog.App.Debug().Msg("User from basic auth not found")
c.Next()
return
}
if !m.auth.VerifyUser(userSearch, basic.Password) {
m.auth.RecordLoginAttempt(basic.Username, false)
log.Debug().Msg("Invalid password for basic auth user")
tlog.App.Debug().Msg("Invalid password for basic auth user")
c.Next()
return
}
@@ -147,7 +147,7 @@ func (m *ContextMiddleware) Middleware() gin.HandlerFunc {
switch userSearch.Type {
case "local":
log.Debug().Msg("Basic auth user is local")
tlog.App.Debug().Msg("Basic auth user is local")
user := m.auth.GetLocalUser(basic.Username)
@@ -162,7 +162,7 @@ func (m *ContextMiddleware) Middleware() gin.HandlerFunc {
c.Next()
return
case "ldap":
log.Debug().Msg("Basic auth user is LDAP")
tlog.App.Debug().Msg("Basic auth user is LDAP")
c.Set("context", &config.UserContext{
Username: basic.Username,
Name: utils.Capitalize(basic.Username),