Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 18 additions & 9 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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

Expand Down
4 changes: 2 additions & 2 deletions frontend/src/components/layout/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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";
});
Expand All @@ -42,7 +42,7 @@ export const Layout = () => {
setIgnoreDomainWarning(true);
}, [setIgnoreDomainWarning]);

if (!ignoreDomainWarning && !disableUiWarnings && appUrl !== currentUrl) {
if (!ignoreDomainWarning && warningsEnabled && appUrl !== currentUrl) {
return (
<BaseLayout>
<DomainWarning
Expand Down
7 changes: 3 additions & 4 deletions frontend/src/pages/continue-page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { useCallback, useEffect, useRef, useState } from "react";
import { useRedirectUri } from "@/lib/hooks/redirect-uri";

export const ContinuePage = () => {
const { cookieDomain, disableUiWarnings } = useAppContext();
const { cookieDomain, warningsEnabled } = useAppContext();
const { isLoggedIn } = useUserContext();
const { search } = useLocation();
const { t } = useTranslation();
Expand All @@ -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 &&
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/schemas/app-context-schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<typeof appContextSchema>;
4 changes: 2 additions & 2 deletions internal/bootstrap/app_bootstrap.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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()
}
Expand Down
6 changes: 3 additions & 3 deletions internal/bootstrap/router_bootstrap.go
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down Expand Up @@ -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()
Expand Down
59 changes: 40 additions & 19 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand All @@ -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,
Expand Down Expand Up @@ -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, including file name." 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 {
Expand Down Expand Up @@ -114,16 +135,16 @@ type OAuthConfig struct {
}

type OIDCConfig struct {
PrivateKeyPath string `description:"Path to the private key file." yaml:"privateKeyPath"`
PublicKeyPath string `description:"Path to the public key file." yaml:"publicKeyPath"`
PrivateKeyPath string `description:"Path to the private key file, including file name." yaml:"privateKeyPath"`
PublicKeyPath string `description:"Path to the public key file, including file name." yaml:"publicKeyPath"`
Clients map[string]OIDCClientConfig `description:"OIDC clients configuration." yaml:"clients"`
}

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 {
Expand Down
8 changes: 4 additions & 4 deletions internal/controller/context_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -50,7 +50,7 @@ type ContextControllerConfig struct {
ForgotPasswordMessage string
BackgroundImage string
OAuthAutoRedirect string
DisableUIWarnings bool
WarningsEnabled bool
}

type ContextController struct {
Expand All @@ -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.")
}

Expand Down Expand Up @@ -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,
})
}
4 changes: 2 additions & 2 deletions internal/controller/context_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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{
Expand Down Expand Up @@ -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)
Expand Down
10 changes: 5 additions & 5 deletions internal/controller/resources_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import (
)

type ResourcesControllerConfig struct {
ResourcesDir string
ResourcesDisabled bool
Path string
Enabled bool
}

type ResourcesController struct {
Expand All @@ -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,
Expand All @@ -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",
Expand Down
3 changes: 2 additions & 1 deletion internal/controller/resources_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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()

Expand Down