diff --git a/.env.example b/.env.example index 54d5281..26d280d 100644 --- a/.env.example +++ b/.env.example @@ -4,14 +4,23 @@ # The base URL where the app is hosted. TINYAUTH_APPURL= -# The directory where resources are stored. -TINYAUTH_RESOURCESDIR="./resources" + +# database config + # The path to the database file. -TINYAUTH_DATABASEPATH="./tinyauth.db" -# Disable analytics. -TINYAUTH_DISABLEANALYTICS=false -# Disable resources server. -TINYAUTH_DISABLERESOURCES=false +TINYAUTH_DATABASE_PATH="./tinyauth.db" + +# analytics config + +# Enable periodic version information collection. +TINYAUTH_ANALYTICS_ENABLED=true + +# resources config + +# Enable the resources server. +TINYAUTH_RESOURCES_ENABLED=true +# The directory where resources are stored. +TINYAUTH_RESOURCES_PATH="./resources" # server config @@ -130,8 +139,8 @@ TINYAUTH_UI_TITLE="Tinyauth" TINYAUTH_UI_FORGOTPASSWORDMESSAGE="You can change your password by changing the configuration." # Path to the background image. TINYAUTH_UI_BACKGROUNDIMAGE="/background.jpg" -# Disable UI warnings. -TINYAUTH_UI_DISABLEWARNINGS=false +# Enable UI warnings. +TINYAUTH_UI_WARNINGSENABLED=true # ldap config diff --git a/frontend/src/components/layout/layout.tsx b/frontend/src/components/layout/layout.tsx index 02a01b4..a71a1aa 100644 --- a/frontend/src/components/layout/layout.tsx +++ b/frontend/src/components/layout/layout.tsx @@ -31,7 +31,7 @@ const BaseLayout = ({ children }: { children: React.ReactNode }) => { }; export const Layout = () => { - const { appUrl, disableUiWarnings } = useAppContext(); + const { appUrl, warningsEnabled } = useAppContext(); const [ignoreDomainWarning, setIgnoreDomainWarning] = useState(() => { return window.sessionStorage.getItem("ignoreDomainWarning") === "true"; }); @@ -42,7 +42,7 @@ export const Layout = () => { setIgnoreDomainWarning(true); }, [setIgnoreDomainWarning]); - if (!ignoreDomainWarning && !disableUiWarnings && appUrl !== currentUrl) { + if (!ignoreDomainWarning && warningsEnabled && appUrl !== currentUrl) { return ( { - const { cookieDomain, disableUiWarnings } = useAppContext(); + const { cookieDomain, warningsEnabled } = useAppContext(); const { isLoggedIn } = useUserContext(); const { search } = useLocation(); const { t } = useTranslation(); @@ -35,10 +35,9 @@ export const ContinuePage = () => { const urlHref = url?.href; const hasValidRedirect = valid && allowedProto; - const showUntrustedWarning = - hasValidRedirect && !trusted && !disableUiWarnings; + const showUntrustedWarning = hasValidRedirect && !trusted && warningsEnabled; const showInsecureWarning = - hasValidRedirect && httpsDowngrade && !disableUiWarnings; + hasValidRedirect && httpsDowngrade && warningsEnabled; const shouldAutoRedirect = isLoggedIn && hasValidRedirect && diff --git a/frontend/src/schemas/app-context-schema.ts b/frontend/src/schemas/app-context-schema.ts index 6935ca4..a1dd445 100644 --- a/frontend/src/schemas/app-context-schema.ts +++ b/frontend/src/schemas/app-context-schema.ts @@ -14,7 +14,7 @@ export const appContextSchema = z.object({ forgotPasswordMessage: z.string(), backgroundImage: z.string(), oauthAutoRedirect: z.string(), - disableUiWarnings: z.boolean(), + warningsEnabled: z.boolean(), }); export type AppContextSchema = z.infer; diff --git a/internal/bootstrap/app_bootstrap.go b/internal/bootstrap/app_bootstrap.go index cb2c611..b1598f7 100644 --- a/internal/bootstrap/app_bootstrap.go +++ b/internal/bootstrap/app_bootstrap.go @@ -124,7 +124,7 @@ func (app *BootstrapApp) Setup() error { tlog.App.Trace().Str("redirectCookieName", app.context.redirectCookieName).Msg("Redirect cookie name") // Database - db, err := app.SetupDatabase(app.config.DatabasePath) + db, err := app.SetupDatabase(app.config.Database.Path) if err != nil { return fmt.Errorf("failed to setup database: %w", err) @@ -193,7 +193,7 @@ func (app *BootstrapApp) Setup() error { go app.dbCleanup(queries) // If analytics are not disabled, start heartbeat - if !app.config.DisableAnalytics { + if app.config.Analytics.Enabled { tlog.App.Debug().Msg("Starting heartbeat routine") go app.heartbeat() } diff --git a/internal/bootstrap/router_bootstrap.go b/internal/bootstrap/router_bootstrap.go index 6773d5f..6ae7e94 100644 --- a/internal/bootstrap/router_bootstrap.go +++ b/internal/bootstrap/router_bootstrap.go @@ -71,7 +71,7 @@ func (app *BootstrapApp) setupRouter() (*gin.Engine, error) { ForgotPasswordMessage: app.config.UI.ForgotPasswordMessage, BackgroundImage: app.config.UI.BackgroundImage, OAuthAutoRedirect: app.config.OAuth.AutoRedirect, - DisableUIWarnings: app.config.UI.DisableWarnings, + WarningsEnabled: app.config.UI.WarningsEnabled, }, apiRouter) contextController.SetupRoutes() @@ -103,8 +103,8 @@ func (app *BootstrapApp) setupRouter() (*gin.Engine, error) { userController.SetupRoutes() resourcesController := controller.NewResourcesController(controller.ResourcesControllerConfig{ - ResourcesDir: app.config.ResourcesDir, - ResourcesDisabled: app.config.DisableResources, + Path: app.config.Resources.Path, + Enabled: app.config.Resources.Enabled, }, &engine.RouterGroup) resourcesController.SetupRoutes() diff --git a/internal/config/config.go b/internal/config/config.go index 9403d62..46a81c7 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -3,8 +3,16 @@ package config // Default configuration func NewDefaultConfiguration() *Config { return &Config{ - ResourcesDir: "./resources", - DatabasePath: "./tinyauth.db", + Database: DatabaseConfig{ + Path: "./tinyauth.db", + }, + Analytics: AnalyticsConfig{ + Enabled: true, + }, + Resources: ResourcesConfig{ + Enabled: true, + Path: "./resources", + }, Server: ServerConfig{ Port: 3000, Address: "0.0.0.0", @@ -19,6 +27,7 @@ func NewDefaultConfiguration() *Config { Title: "Tinyauth", ForgotPasswordMessage: "You can change your password by changing the configuration.", BackgroundImage: "/background.jpg", + WarningsEnabled: true, }, Ldap: LdapConfig{ Insecure: false, @@ -68,20 +77,32 @@ var RedirectCookieName = "tinyauth-redirect" // Main app config type Config struct { - AppURL string `description:"The base URL where the app is hosted." yaml:"appUrl"` - ResourcesDir string `description:"The directory where resources are stored." yaml:"resourcesDir"` - DatabasePath string `description:"The path to the database file." yaml:"databasePath"` - DisableAnalytics bool `description:"Disable analytics." yaml:"disableAnalytics"` - DisableResources bool `description:"Disable resources server." yaml:"disableResources"` - Server ServerConfig `description:"Server configuration." yaml:"server"` - Auth AuthConfig `description:"Authentication configuration." yaml:"auth"` - Apps map[string]App `description:"Application ACLs configuration." yaml:"apps"` - OAuth OAuthConfig `description:"OAuth configuration." yaml:"oauth"` - OIDC OIDCConfig `description:"OIDC configuration." yaml:"oidc"` - UI UIConfig `description:"UI customization." yaml:"ui"` - Ldap LdapConfig `description:"LDAP configuration." yaml:"ldap"` - Experimental ExperimentalConfig `description:"Experimental features, use with caution." yaml:"experimental"` - Log LogConfig `description:"Logging configuration." yaml:"log"` + AppURL string `description:"The base URL where the app is hosted." yaml:"appUrl"` + Database DatabaseConfig `description:"Database configuration." yaml:"database"` + Analytics AnalyticsConfig `description:"Analytics configuration." yaml:"analytics"` + Resources ResourcesConfig `description:"Resources configuration." yaml:"resources"` + Server ServerConfig `description:"Server configuration." yaml:"server"` + Auth AuthConfig `description:"Authentication configuration." yaml:"auth"` + Apps map[string]App `description:"Application ACLs configuration." yaml:"apps"` + OAuth OAuthConfig `description:"OAuth configuration." yaml:"oauth"` + OIDC OIDCConfig `description:"OIDC configuration." yaml:"oidc"` + UI UIConfig `description:"UI customization." yaml:"ui"` + Ldap LdapConfig `description:"LDAP configuration." yaml:"ldap"` + Experimental ExperimentalConfig `description:"Experimental features, use with caution." yaml:"experimental"` + Log LogConfig `description:"Logging configuration." yaml:"log"` +} + +type DatabaseConfig struct { + Path string `description:"The path to the database file." yaml:"path"` +} + +type AnalyticsConfig struct { + Enabled bool `description:"Enable periodic version information collection." yaml:"enabled"` +} + +type ResourcesConfig struct { + Enabled bool `description:"Enable the resources server." yaml:"enabled"` + Path string `description:"The directory where resources are stored." yaml:"path"` } type ServerConfig struct { @@ -123,7 +144,7 @@ type UIConfig struct { Title string `description:"The title of the UI." yaml:"title"` ForgotPasswordMessage string `description:"Message displayed on the forgot password page." yaml:"forgotPasswordMessage"` BackgroundImage string `description:"Path to the background image." yaml:"backgroundImage"` - DisableWarnings bool `description:"Disable UI warnings." yaml:"disableWarnings"` + WarningsEnabled bool `description:"Enable UI warnings." yaml:"warningsEnabled"` } type LdapConfig struct { diff --git a/internal/controller/context_controller.go b/internal/controller/context_controller.go index 58651a1..8501bce 100644 --- a/internal/controller/context_controller.go +++ b/internal/controller/context_controller.go @@ -33,7 +33,7 @@ type AppContextResponse struct { ForgotPasswordMessage string `json:"forgotPasswordMessage"` BackgroundImage string `json:"backgroundImage"` OAuthAutoRedirect string `json:"oauthAutoRedirect"` - DisableUIWarnings bool `json:"disableUiWarnings"` + WarningsEnabled bool `json:"warningsEnabled"` } type Provider struct { @@ -50,7 +50,7 @@ type ContextControllerConfig struct { ForgotPasswordMessage string BackgroundImage string OAuthAutoRedirect string - DisableUIWarnings bool + WarningsEnabled bool } type ContextController struct { @@ -59,7 +59,7 @@ type ContextController struct { } func NewContextController(config ContextControllerConfig, router *gin.RouterGroup) *ContextController { - if config.DisableUIWarnings { + if !config.WarningsEnabled { tlog.App.Warn().Msg("UI warnings are disabled. This may expose users to security risks. Proceed with caution.") } @@ -124,6 +124,6 @@ func (controller *ContextController) appContextHandler(c *gin.Context) { ForgotPasswordMessage: controller.config.ForgotPasswordMessage, BackgroundImage: controller.config.BackgroundImage, OAuthAutoRedirect: controller.config.OAuthAutoRedirect, - DisableUIWarnings: controller.config.DisableUIWarnings, + WarningsEnabled: controller.config.WarningsEnabled, }) } diff --git a/internal/controller/context_controller_test.go b/internal/controller/context_controller_test.go index 022d298..5f5e6e9 100644 --- a/internal/controller/context_controller_test.go +++ b/internal/controller/context_controller_test.go @@ -32,7 +32,7 @@ var contextControllerCfg = controller.ContextControllerConfig{ ForgotPasswordMessage: "Contact admin to reset your password.", BackgroundImage: "/assets/bg.jpg", OAuthAutoRedirect: "google", - DisableUIWarnings: false, + WarningsEnabled: true, } var contextCtrlTestContext = config.UserContext{ @@ -82,7 +82,7 @@ func TestAppContextHandler(t *testing.T) { ForgotPasswordMessage: contextControllerCfg.ForgotPasswordMessage, BackgroundImage: contextControllerCfg.BackgroundImage, OAuthAutoRedirect: contextControllerCfg.OAuthAutoRedirect, - DisableUIWarnings: contextControllerCfg.DisableUIWarnings, + WarningsEnabled: contextControllerCfg.WarningsEnabled, } router, recorder := setupContextController(nil) diff --git a/internal/controller/resources_controller.go b/internal/controller/resources_controller.go index bed4fcc..98d3b23 100644 --- a/internal/controller/resources_controller.go +++ b/internal/controller/resources_controller.go @@ -7,8 +7,8 @@ import ( ) type ResourcesControllerConfig struct { - ResourcesDir string - ResourcesDisabled bool + Path string + Enabled bool } type ResourcesController struct { @@ -18,7 +18,7 @@ type ResourcesController struct { } func NewResourcesController(config ResourcesControllerConfig, router *gin.RouterGroup) *ResourcesController { - fileServer := http.StripPrefix("/resources", http.FileServer(http.Dir(config.ResourcesDir))) + fileServer := http.StripPrefix("/resources", http.FileServer(http.Dir(config.Path))) return &ResourcesController{ config: config, @@ -32,14 +32,14 @@ func (controller *ResourcesController) SetupRoutes() { } func (controller *ResourcesController) resourcesHandler(c *gin.Context) { - if controller.config.ResourcesDir == "" { + if controller.config.Path == "" { c.JSON(404, gin.H{ "status": 404, "message": "Resources not found", }) return } - if controller.config.ResourcesDisabled { + if !controller.config.Enabled { c.JSON(403, gin.H{ "status": 403, "message": "Resources are disabled", diff --git a/internal/controller/resources_controller_test.go b/internal/controller/resources_controller_test.go index c27b0a3..5f38528 100644 --- a/internal/controller/resources_controller_test.go +++ b/internal/controller/resources_controller_test.go @@ -18,7 +18,8 @@ func TestResourcesHandler(t *testing.T) { group := router.Group("/") ctrl := controller.NewResourcesController(controller.ResourcesControllerConfig{ - ResourcesDir: "/tmp/tinyauth", + Path: "/tmp/tinyauth", + Enabled: true, }, group) ctrl.SetupRoutes()