mirror of
https://github.com/steveiliop56/tinyauth.git
synced 2026-02-22 00:42:03 +00:00
feat: auto generate example env file (#647)
* feat: auto generate example env file * refactor: simplify build paths func and better slice handling * chore: forgot to stage everything * chore: review comments * refactor: remove square brackets because they mess up the syntax highlighting * refactor: use lowercase name to mark dynamic values
This commit is contained in:
290
.env.example
290
.env.example
@@ -1,99 +1,221 @@
|
|||||||
# Base Configuration
|
# Tinyauth example configuration
|
||||||
|
|
||||||
# The base URL where Tinyauth is accessible
|
# The base URL where the app is hosted.
|
||||||
TINYAUTH_APPURL="https://auth.example.com"
|
TINYAUTH_APPURL=
|
||||||
# Directory for static resources
|
|
||||||
TINYAUTH_RESOURCESDIR="/data/resources"
|
|
||||||
# Path to SQLite database file
|
|
||||||
TINYAUTH_DATABASEPATH="/data/tinyauth.db"
|
|
||||||
# Disable version heartbeat
|
|
||||||
TINYAUTH_DISABLEANALYTICS="false"
|
|
||||||
# Disable static resource serving
|
|
||||||
TINYAUTH_DISABLERESOURCES="false"
|
|
||||||
|
|
||||||
# Logging Configuration
|
# The directory where resources are stored.
|
||||||
|
TINYAUTH_RESOURCESDIR="./resources"
|
||||||
|
|
||||||
# Log level: trace, debug, info, warn, error
|
# The path to the database file.
|
||||||
TINYAUTH_LOG_LEVEL="info"
|
TINYAUTH_DATABASEPATH="./tinyauth.db"
|
||||||
# Enable JSON formatted logs
|
|
||||||
TINYAUTH_LOG_JSON="false"
|
|
||||||
# Specific Log stream configurations
|
|
||||||
# APP and HTTP log streams are enabled by default, and use the global log level unless overridden
|
|
||||||
TINYAUTH_LOG_STREAMS_APP_ENABLED="true"
|
|
||||||
TINYAUTH_LOG_STREAMS_APP_LEVEL="info"
|
|
||||||
TINYAUTH_LOG_STREAMS_HTTP_ENABLED="true"
|
|
||||||
TINYAUTH_LOG_STREAMS_HTTP_LEVEL="info"
|
|
||||||
TINYAUTH_LOG_STREAMS_AUDIT_ENABLED="false"
|
|
||||||
TINYAUTH_LOG_STREAMS_AUDIT_LEVEL="info"
|
|
||||||
|
|
||||||
# Server Configuration
|
# Disable analytics.
|
||||||
|
TINYAUTH_DISABLEANALYTICS=false
|
||||||
|
|
||||||
# Port to listen on
|
# Disable resources server.
|
||||||
TINYAUTH_SERVER_PORT="3000"
|
TINYAUTH_DISABLERESOURCES=false
|
||||||
# Interface to bind to (0.0.0.0 for all interfaces)
|
|
||||||
|
# The port on which the server listens.
|
||||||
|
TINYAUTH_SERVER_PORT=3000
|
||||||
|
|
||||||
|
# The address on which the server listens.
|
||||||
TINYAUTH_SERVER_ADDRESS="0.0.0.0"
|
TINYAUTH_SERVER_ADDRESS="0.0.0.0"
|
||||||
# Unix socket path (optional, overrides port/address if set)
|
|
||||||
TINYAUTH_SERVER_SOCKETPATH=""
|
|
||||||
|
|
||||||
# Authentication Configuration
|
# The path to the Unix socket.
|
||||||
|
TINYAUTH_SERVER_SOCKETPATH=
|
||||||
|
|
||||||
# Format: username:bcrypt_hash (use bcrypt to generate hash)
|
# List of allowed IPs or CIDR ranges.
|
||||||
TINYAUTH_AUTH_USERS="admin:$2a$10$example_bcrypt_hash_here"
|
TINYAUTH_AUTH_IP_ALLOW=
|
||||||
# Path to external users file (optional)
|
|
||||||
TINYAUTH_AUTH_USERSFILE=""
|
|
||||||
# Enable secure cookies (requires HTTPS)
|
|
||||||
TINYAUTH_AUTH_SECURECOOKIE="true"
|
|
||||||
# Session expiry in seconds (7200 = 2 hours)
|
|
||||||
TINYAUTH_AUTH_SESSIONEXPIRY="7200"
|
|
||||||
# Session maximum lifetime in seconds (0 = unlimited)
|
|
||||||
TINYAUTH_AUTH_SESSIONMAXLIFETIME="0"
|
|
||||||
# Login timeout in seconds (300 = 5 minutes)
|
|
||||||
TINYAUTH_AUTH_LOGINTIMEOUT="300"
|
|
||||||
# Maximum login retries before lockout
|
|
||||||
TINYAUTH_AUTH_LOGINMAXRETRIES="5"
|
|
||||||
# Comma-separated list of trusted proxy IPs/CIDRs
|
|
||||||
TINYAUTH_AUTH_TRUSTEDPROXIES=""
|
|
||||||
|
|
||||||
# OAuth Configuration
|
# List of blocked IPs or CIDR ranges.
|
||||||
|
TINYAUTH_AUTH_IP_BLOCK=
|
||||||
|
|
||||||
# Regex pattern for allowed email addresses (e.g., /@example\.com$/)
|
# Comma-separated list of users (username:hashed_password).
|
||||||
TINYAUTH_OAUTH_WHITELIST=""
|
TINYAUTH_AUTH_USERS=
|
||||||
# Provider ID to auto-redirect to (skips login page)
|
|
||||||
TINYAUTH_OAUTH_AUTOREDIRECT=""
|
|
||||||
# OAuth Provider Configuration (replace MYPROVIDER with your provider name)
|
|
||||||
TINYAUTH_OAUTH_PROVIDERS_MYPROVIDER_CLIENTID="your_client_id_here"
|
|
||||||
TINYAUTH_OAUTH_PROVIDERS_MYPROVIDER_CLIENTSECRET="your_client_secret_here"
|
|
||||||
TINYAUTH_OAUTH_PROVIDERS_MYPROVIDER_AUTHURL="https://provider.example.com/oauth/authorize"
|
|
||||||
TINYAUTH_OAUTH_PROVIDERS_MYPROVIDER_TOKENURL="https://provider.example.com/oauth/token"
|
|
||||||
TINYAUTH_OAUTH_PROVIDERS_MYPROVIDER_USERINFOURL="https://provider.example.com/oauth/userinfo"
|
|
||||||
TINYAUTH_OAUTH_PROVIDERS_MYPROVIDER_REDIRECTURL="https://auth.example.com/oauth/callback/myprovider"
|
|
||||||
TINYAUTH_OAUTH_PROVIDERS_MYPROVIDER_SCOPES="openid email profile"
|
|
||||||
TINYAUTH_OAUTH_PROVIDERS_MYPROVIDER_NAME="My OAuth Provider"
|
|
||||||
# Allow self-signed certificates
|
|
||||||
TINYAUTH_OAUTH_PROVIDERS_MYPROVIDER_INSECURE="false"
|
|
||||||
|
|
||||||
# UI Customization
|
# Path to the users file.
|
||||||
|
TINYAUTH_AUTH_USERSFILE=
|
||||||
|
|
||||||
# Custom title for login page
|
# Enable secure cookies.
|
||||||
|
TINYAUTH_AUTH_SECURECOOKIE=false
|
||||||
|
|
||||||
|
# Session expiry time in seconds.
|
||||||
|
TINYAUTH_AUTH_SESSIONEXPIRY=86400
|
||||||
|
|
||||||
|
# Maximum session lifetime in seconds.
|
||||||
|
TINYAUTH_AUTH_SESSIONMAXLIFETIME=0
|
||||||
|
|
||||||
|
# Login timeout in seconds.
|
||||||
|
TINYAUTH_AUTH_LOGINTIMEOUT=300
|
||||||
|
|
||||||
|
# Maximum login retries.
|
||||||
|
TINYAUTH_AUTH_LOGINMAXRETRIES=3
|
||||||
|
|
||||||
|
# Comma-separated list of trusted proxy addresses.
|
||||||
|
TINYAUTH_AUTH_TRUSTEDPROXIES=
|
||||||
|
|
||||||
|
# The domain of the app.
|
||||||
|
TINYAUTH_APPS_name_CONFIG_DOMAIN=
|
||||||
|
|
||||||
|
# Comma-separated list of allowed users.
|
||||||
|
TINYAUTH_APPS_name_USERS_ALLOW=
|
||||||
|
|
||||||
|
# Comma-separated list of blocked users.
|
||||||
|
TINYAUTH_APPS_name_USERS_BLOCK=
|
||||||
|
|
||||||
|
# Comma-separated list of allowed OAuth groups.
|
||||||
|
TINYAUTH_APPS_name_OAUTH_WHITELIST=
|
||||||
|
|
||||||
|
# Comma-separated list of required OAuth groups.
|
||||||
|
TINYAUTH_APPS_name_OAUTH_GROUPS=
|
||||||
|
|
||||||
|
# List of allowed IPs or CIDR ranges.
|
||||||
|
TINYAUTH_APPS_name_IP_ALLOW=
|
||||||
|
|
||||||
|
# List of blocked IPs or CIDR ranges.
|
||||||
|
TINYAUTH_APPS_name_IP_BLOCK=
|
||||||
|
|
||||||
|
# List of IPs or CIDR ranges that bypass authentication.
|
||||||
|
TINYAUTH_APPS_name_IP_BYPASS=
|
||||||
|
|
||||||
|
# Custom headers to add to the response.
|
||||||
|
TINYAUTH_APPS_name_RESPONSE_HEADERS=
|
||||||
|
|
||||||
|
# Basic auth username.
|
||||||
|
TINYAUTH_APPS_name_RESPONSE_BASICAUTH_USERNAME=
|
||||||
|
|
||||||
|
# Basic auth password.
|
||||||
|
TINYAUTH_APPS_name_RESPONSE_BASICAUTH_PASSWORD=
|
||||||
|
|
||||||
|
# Path to the file containing the basic auth password.
|
||||||
|
TINYAUTH_APPS_name_RESPONSE_BASICAUTH_PASSWORDFILE=
|
||||||
|
|
||||||
|
# Comma-separated list of allowed paths.
|
||||||
|
TINYAUTH_APPS_name_PATH_ALLOW=
|
||||||
|
|
||||||
|
# Comma-separated list of blocked paths.
|
||||||
|
TINYAUTH_APPS_name_PATH_BLOCK=
|
||||||
|
|
||||||
|
# Comma-separated list of required LDAP groups.
|
||||||
|
TINYAUTH_APPS_name_LDAP_GROUPS=
|
||||||
|
|
||||||
|
# Comma-separated list of allowed OAuth domains.
|
||||||
|
TINYAUTH_OAUTH_WHITELIST=
|
||||||
|
|
||||||
|
# The OAuth provider to use for automatic redirection.
|
||||||
|
TINYAUTH_OAUTH_AUTOREDIRECT=
|
||||||
|
|
||||||
|
# OAuth client ID.
|
||||||
|
TINYAUTH_OAUTH_PROVIDERS_name_CLIENTID=
|
||||||
|
|
||||||
|
# OAuth client secret.
|
||||||
|
TINYAUTH_OAUTH_PROVIDERS_name_CLIENTSECRET=
|
||||||
|
|
||||||
|
# Path to the file containing the OAuth client secret.
|
||||||
|
TINYAUTH_OAUTH_PROVIDERS_name_CLIENTSECRETFILE=
|
||||||
|
|
||||||
|
# OAuth scopes.
|
||||||
|
TINYAUTH_OAUTH_PROVIDERS_name_SCOPES=
|
||||||
|
|
||||||
|
# OAuth redirect URL.
|
||||||
|
TINYAUTH_OAUTH_PROVIDERS_name_REDIRECTURL=
|
||||||
|
|
||||||
|
# OAuth authorization URL.
|
||||||
|
TINYAUTH_OAUTH_PROVIDERS_name_AUTHURL=
|
||||||
|
|
||||||
|
# OAuth token URL.
|
||||||
|
TINYAUTH_OAUTH_PROVIDERS_name_TOKENURL=
|
||||||
|
|
||||||
|
# OAuth userinfo URL.
|
||||||
|
TINYAUTH_OAUTH_PROVIDERS_name_USERINFOURL=
|
||||||
|
|
||||||
|
# Allow insecure OAuth connections.
|
||||||
|
TINYAUTH_OAUTH_PROVIDERS_name_INSECURE=false
|
||||||
|
|
||||||
|
# Provider name in UI.
|
||||||
|
TINYAUTH_OAUTH_PROVIDERS_name_NAME=
|
||||||
|
|
||||||
|
# Path to the private key file.
|
||||||
|
TINYAUTH_OIDC_PRIVATEKEYPATH="./tinyauth_oidc_key"
|
||||||
|
|
||||||
|
# Path to the public key file.
|
||||||
|
TINYAUTH_OIDC_PUBLICKEYPATH="./tinyauth_oidc_key.pub"
|
||||||
|
|
||||||
|
# OIDC client ID.
|
||||||
|
TINYAUTH_OIDC_CLIENTS_name_CLIENTID=
|
||||||
|
|
||||||
|
# OIDC client secret.
|
||||||
|
TINYAUTH_OIDC_CLIENTS_name_CLIENTSECRET=
|
||||||
|
|
||||||
|
# Path to the file containing the OIDC client secret.
|
||||||
|
TINYAUTH_OIDC_CLIENTS_name_CLIENTSECRETFILE=
|
||||||
|
|
||||||
|
# List of trusted redirect URIs.
|
||||||
|
TINYAUTH_OIDC_CLIENTS_name_TRUSTEDREDIRECTURIS=
|
||||||
|
|
||||||
|
# Client name in UI.
|
||||||
|
TINYAUTH_OIDC_CLIENTS_name_NAME=
|
||||||
|
|
||||||
|
# The title of the UI.
|
||||||
TINYAUTH_UI_TITLE="Tinyauth"
|
TINYAUTH_UI_TITLE="Tinyauth"
|
||||||
# Message shown on forgot password page
|
|
||||||
TINYAUTH_UI_FORGOTPASSWORDMESSAGE="Contact your administrator to reset your password"
|
|
||||||
# Background image URL for login page
|
|
||||||
TINYAUTH_UI_BACKGROUNDIMAGE=""
|
|
||||||
# Disable UI warning messages
|
|
||||||
TINYAUTH_UI_DISABLEWARNINGS="false"
|
|
||||||
|
|
||||||
# LDAP Configuration
|
# Message displayed on the forgot password page.
|
||||||
|
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
|
||||||
|
|
||||||
|
# LDAP server address.
|
||||||
|
TINYAUTH_LDAP_ADDRESS=
|
||||||
|
|
||||||
|
# Bind DN for LDAP authentication.
|
||||||
|
TINYAUTH_LDAP_BINDDN=
|
||||||
|
|
||||||
|
# Bind password for LDAP authentication.
|
||||||
|
TINYAUTH_LDAP_BINDPASSWORD=
|
||||||
|
|
||||||
|
# Base DN for LDAP searches.
|
||||||
|
TINYAUTH_LDAP_BASEDN=
|
||||||
|
|
||||||
|
# Allow insecure LDAP connections.
|
||||||
|
TINYAUTH_LDAP_INSECURE=false
|
||||||
|
|
||||||
|
# LDAP search filter.
|
||||||
|
TINYAUTH_LDAP_SEARCHFILTER="(uid=%s)"
|
||||||
|
|
||||||
|
# Certificate for mTLS authentication.
|
||||||
|
TINYAUTH_LDAP_AUTHCERT=
|
||||||
|
|
||||||
|
# Certificate key for mTLS authentication.
|
||||||
|
TINYAUTH_LDAP_AUTHKEY=
|
||||||
|
|
||||||
|
# Cache duration for LDAP group membership in seconds.
|
||||||
|
TINYAUTH_LDAP_GROUPCACHETTL=900
|
||||||
|
|
||||||
|
# Log level (trace, debug, info, warn, error).
|
||||||
|
TINYAUTH_LOG_LEVEL="info"
|
||||||
|
|
||||||
|
# Enable JSON formatted logs.
|
||||||
|
TINYAUTH_LOG_JSON=false
|
||||||
|
|
||||||
|
# Enable this log stream.
|
||||||
|
TINYAUTH_LOG_STREAMS_HTTP_ENABLED=true
|
||||||
|
|
||||||
|
# Log level for this stream. Use global if empty.
|
||||||
|
TINYAUTH_LOG_STREAMS_HTTP_LEVEL=
|
||||||
|
|
||||||
|
# Enable this log stream.
|
||||||
|
TINYAUTH_LOG_STREAMS_APP_ENABLED=true
|
||||||
|
|
||||||
|
# Log level for this stream. Use global if empty.
|
||||||
|
TINYAUTH_LOG_STREAMS_APP_LEVEL=
|
||||||
|
|
||||||
|
# Enable this log stream.
|
||||||
|
TINYAUTH_LOG_STREAMS_AUDIT_ENABLED=false
|
||||||
|
|
||||||
|
# Log level for this stream. Use global if empty.
|
||||||
|
TINYAUTH_LOG_STREAMS_AUDIT_LEVEL=
|
||||||
|
|
||||||
# LDAP server address
|
|
||||||
TINYAUTH_LDAP_ADDRESS="ldap://ldap.example.com:389"
|
|
||||||
# DN for binding to LDAP server
|
|
||||||
TINYAUTH_LDAP_BINDDN="cn=readonly,dc=example,dc=com"
|
|
||||||
# Password for bind DN
|
|
||||||
TINYAUTH_LDAP_BINDPASSWORD="your_bind_password"
|
|
||||||
# Base DN for user searches
|
|
||||||
TINYAUTH_LDAP_BASEDN="dc=example,dc=com"
|
|
||||||
# Search filter (%s will be replaced with username)
|
|
||||||
TINYAUTH_LDAP_SEARCHFILTER="(&(uid=%s)(memberOf=cn=users,ou=groups,dc=example,dc=com))"
|
|
||||||
# Allow insecure LDAP connections
|
|
||||||
TINYAUTH_LDAP_INSECURE="false"
|
|
||||||
|
|||||||
8
Makefile
8
Makefile
@@ -60,11 +60,11 @@ test:
|
|||||||
go test -v ./...
|
go test -v ./...
|
||||||
|
|
||||||
# Development
|
# Development
|
||||||
develop:
|
dev:
|
||||||
docker compose -f $(DEV_COMPOSE) up --force-recreate --pull=always --remove-orphans --build
|
docker compose -f $(DEV_COMPOSE) up --force-recreate --pull=always --remove-orphans --build
|
||||||
|
|
||||||
# Development - Infisical
|
# Development - Infisical
|
||||||
develop-infisical:
|
dev-infisical:
|
||||||
infisical run --env=dev -- docker compose -f $(DEV_COMPOSE) up --force-recreate --pull=always --remove-orphans --build
|
infisical run --env=dev -- docker compose -f $(DEV_COMPOSE) up --force-recreate --pull=always --remove-orphans --build
|
||||||
|
|
||||||
# Production
|
# Production
|
||||||
@@ -79,3 +79,7 @@ prod-infisical:
|
|||||||
.PHONY: sql
|
.PHONY: sql
|
||||||
sql:
|
sql:
|
||||||
sqlc generate
|
sqlc generate
|
||||||
|
|
||||||
|
# Go gen
|
||||||
|
generate:
|
||||||
|
go run ./gen
|
||||||
|
|||||||
@@ -12,60 +12,8 @@ import (
|
|||||||
"github.com/traefik/paerser/cli"
|
"github.com/traefik/paerser/cli"
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewTinyauthCmdConfiguration() *config.Config {
|
|
||||||
return &config.Config{
|
|
||||||
ResourcesDir: "./resources",
|
|
||||||
DatabasePath: "./tinyauth.db",
|
|
||||||
Server: config.ServerConfig{
|
|
||||||
Port: 3000,
|
|
||||||
Address: "0.0.0.0",
|
|
||||||
},
|
|
||||||
Auth: config.AuthConfig{
|
|
||||||
SessionExpiry: 86400, // 1 day
|
|
||||||
SessionMaxLifetime: 0, // disabled
|
|
||||||
LoginTimeout: 300, // 5 minutes
|
|
||||||
LoginMaxRetries: 3,
|
|
||||||
},
|
|
||||||
UI: config.UIConfig{
|
|
||||||
Title: "Tinyauth",
|
|
||||||
ForgotPasswordMessage: "You can change your password by changing the configuration.",
|
|
||||||
BackgroundImage: "/background.jpg",
|
|
||||||
},
|
|
||||||
Ldap: config.LdapConfig{
|
|
||||||
Insecure: false,
|
|
||||||
SearchFilter: "(uid=%s)",
|
|
||||||
GroupCacheTTL: 900, // 15 minutes
|
|
||||||
},
|
|
||||||
Log: config.LogConfig{
|
|
||||||
Level: "info",
|
|
||||||
Json: false,
|
|
||||||
Streams: config.LogStreams{
|
|
||||||
HTTP: config.LogStreamConfig{
|
|
||||||
Enabled: true,
|
|
||||||
Level: "",
|
|
||||||
},
|
|
||||||
App: config.LogStreamConfig{
|
|
||||||
Enabled: true,
|
|
||||||
Level: "",
|
|
||||||
},
|
|
||||||
Audit: config.LogStreamConfig{
|
|
||||||
Enabled: false,
|
|
||||||
Level: "",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
OIDC: config.OIDCConfig{
|
|
||||||
PrivateKeyPath: "./tinyauth_oidc_key",
|
|
||||||
PublicKeyPath: "./tinyauth_oidc_key.pub",
|
|
||||||
},
|
|
||||||
Experimental: config.ExperimentalConfig{
|
|
||||||
ConfigFile: "",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
tConfig := NewTinyauthCmdConfiguration()
|
tConfig := config.NewDefaultConfiguration()
|
||||||
|
|
||||||
loaders := []cli.ResourceLoader{
|
loaders := []cli.ResourceLoader{
|
||||||
&loaders.FileLoader{},
|
&loaders.FileLoader{},
|
||||||
|
|||||||
11
gen/gen.go
Normal file
11
gen/gen.go
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log/slog"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
slog.Info("generating example env file")
|
||||||
|
|
||||||
|
generateExampleEnv()
|
||||||
|
}
|
||||||
137
gen/gen_env.go
Normal file
137
gen/gen_env.go
Normal file
@@ -0,0 +1,137 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"log/slog"
|
||||||
|
"os"
|
||||||
|
"reflect"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/steveiliop56/tinyauth/internal/config"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Path struct {
|
||||||
|
Name string
|
||||||
|
Description string
|
||||||
|
Value any
|
||||||
|
}
|
||||||
|
|
||||||
|
func generateExampleEnv() {
|
||||||
|
cfg := config.NewDefaultConfiguration()
|
||||||
|
paths := make([]Path, 0)
|
||||||
|
|
||||||
|
root := reflect.TypeOf(cfg).Elem()
|
||||||
|
rootValue := reflect.ValueOf(cfg).Elem()
|
||||||
|
rootPath := "TINYAUTH_"
|
||||||
|
|
||||||
|
buildPaths(root, rootValue, rootPath, &paths)
|
||||||
|
compiled := compileEnv(paths)
|
||||||
|
|
||||||
|
err := os.Remove(".env.example")
|
||||||
|
if err != nil {
|
||||||
|
slog.Error("failed to remove example env file", "error", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = os.WriteFile(".env.example", compiled, 0644)
|
||||||
|
if err != nil {
|
||||||
|
slog.Error("failed to write example env file", "error", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildPaths(parent reflect.Type, parentValue reflect.Value, parentPath string, paths *[]Path) {
|
||||||
|
for i := 0; i < parent.NumField(); i++ {
|
||||||
|
field := parent.Field(i)
|
||||||
|
fieldType := field.Type
|
||||||
|
fieldValue := parentValue.Field(i)
|
||||||
|
switch fieldType.Kind() {
|
||||||
|
case reflect.Struct:
|
||||||
|
childPath := parentPath + strings.ToUpper(field.Name) + "_"
|
||||||
|
buildPaths(fieldType, fieldValue, childPath, paths)
|
||||||
|
case reflect.Map:
|
||||||
|
buildMapPaths(field, parentPath, paths)
|
||||||
|
case reflect.Bool, reflect.String, reflect.Slice, reflect.Int:
|
||||||
|
buildPath(field, fieldValue, parentPath, paths)
|
||||||
|
default:
|
||||||
|
slog.Info("unknown type", "type", fieldType.Kind())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildPath(field reflect.StructField, fieldValue reflect.Value, parent string, paths *[]Path) {
|
||||||
|
desc := field.Tag.Get("description")
|
||||||
|
yamlTag := field.Tag.Get("yaml")
|
||||||
|
|
||||||
|
// probably internal logic, should be skipped
|
||||||
|
if yamlTag == "-" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
defaultValue := fieldValue.Interface()
|
||||||
|
|
||||||
|
path := Path{
|
||||||
|
Name: parent + strings.ToUpper(field.Name),
|
||||||
|
Description: desc,
|
||||||
|
}
|
||||||
|
|
||||||
|
switch fieldValue.Kind() {
|
||||||
|
case reflect.Slice:
|
||||||
|
sl, ok := defaultValue.([]string)
|
||||||
|
if !ok {
|
||||||
|
slog.Error("invalid default value", "value", defaultValue)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
path.Value = strings.Join(sl, ",")
|
||||||
|
case reflect.String:
|
||||||
|
st, ok := defaultValue.(string)
|
||||||
|
if !ok {
|
||||||
|
slog.Error("invalid default value", "value", defaultValue)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// good idea to escape strings probably
|
||||||
|
if st != "" {
|
||||||
|
path.Value = fmt.Sprintf(`"%s"`, st)
|
||||||
|
} else {
|
||||||
|
path.Value = ""
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
path.Value = defaultValue
|
||||||
|
}
|
||||||
|
*paths = append(*paths, path)
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildMapPaths(field reflect.StructField, parentPath string, paths *[]Path) {
|
||||||
|
fieldType := field.Type
|
||||||
|
|
||||||
|
if fieldType.Key().Kind() != reflect.String {
|
||||||
|
slog.Info("unsupported map key type", "type", fieldType.Key().Kind())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
mapPath := parentPath + strings.ToUpper(field.Name) + "_name_"
|
||||||
|
valueType := fieldType.Elem()
|
||||||
|
|
||||||
|
if valueType.Kind() == reflect.Struct {
|
||||||
|
zeroValue := reflect.New(valueType).Elem()
|
||||||
|
buildPaths(valueType, zeroValue, mapPath, paths)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func compileEnv(paths []Path) []byte {
|
||||||
|
buffer := bytes.Buffer{}
|
||||||
|
buffer.WriteString("# Tinyauth example configuration\n\n")
|
||||||
|
|
||||||
|
for _, path := range paths {
|
||||||
|
buffer.WriteString("# ")
|
||||||
|
buffer.WriteString(path.Description)
|
||||||
|
buffer.WriteString("\n")
|
||||||
|
buffer.WriteString(path.Name)
|
||||||
|
buffer.WriteString("=")
|
||||||
|
fmt.Fprintf(&buffer, "%v", path.Value)
|
||||||
|
buffer.WriteString("\n\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer.Bytes()
|
||||||
|
}
|
||||||
@@ -1,5 +1,58 @@
|
|||||||
package config
|
package config
|
||||||
|
|
||||||
|
// Default configuration
|
||||||
|
func NewDefaultConfiguration() *Config {
|
||||||
|
return &Config{
|
||||||
|
ResourcesDir: "./resources",
|
||||||
|
DatabasePath: "./tinyauth.db",
|
||||||
|
Server: ServerConfig{
|
||||||
|
Port: 3000,
|
||||||
|
Address: "0.0.0.0",
|
||||||
|
},
|
||||||
|
Auth: AuthConfig{
|
||||||
|
SessionExpiry: 86400, // 1 day
|
||||||
|
SessionMaxLifetime: 0, // disabled
|
||||||
|
LoginTimeout: 300, // 5 minutes
|
||||||
|
LoginMaxRetries: 3,
|
||||||
|
},
|
||||||
|
UI: UIConfig{
|
||||||
|
Title: "Tinyauth",
|
||||||
|
ForgotPasswordMessage: "You can change your password by changing the configuration.",
|
||||||
|
BackgroundImage: "/background.jpg",
|
||||||
|
},
|
||||||
|
Ldap: LdapConfig{
|
||||||
|
Insecure: false,
|
||||||
|
SearchFilter: "(uid=%s)",
|
||||||
|
GroupCacheTTL: 900, // 15 minutes
|
||||||
|
},
|
||||||
|
Log: LogConfig{
|
||||||
|
Level: "info",
|
||||||
|
Json: false,
|
||||||
|
Streams: LogStreams{
|
||||||
|
HTTP: LogStreamConfig{
|
||||||
|
Enabled: true,
|
||||||
|
Level: "",
|
||||||
|
},
|
||||||
|
App: LogStreamConfig{
|
||||||
|
Enabled: true,
|
||||||
|
Level: "",
|
||||||
|
},
|
||||||
|
Audit: LogStreamConfig{
|
||||||
|
Enabled: false,
|
||||||
|
Level: "",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
OIDC: OIDCConfig{
|
||||||
|
PrivateKeyPath: "./tinyauth_oidc_key",
|
||||||
|
PublicKeyPath: "./tinyauth_oidc_key.pub",
|
||||||
|
},
|
||||||
|
Experimental: ExperimentalConfig{
|
||||||
|
ConfigFile: "",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Version information, set at build time
|
// Version information, set at build time
|
||||||
|
|
||||||
var Version = "development"
|
var Version = "development"
|
||||||
|
|||||||
Reference in New Issue
Block a user