goshort/internal/config/config.go
Gustavo Maronato 371de006ad
All checks were successful
Build / build (push) Successful in 25m7s
add verbose
2023-09-06 18:43:56 -03:00

185 lines
5.3 KiB
Go

//nolint:forbidigo // Allow printing for prettyprint
package config
import (
"fmt"
"net"
"net/url"
"time"
errs "git.maronato.dev/maronato/goshort/internal/errs"
)
const (
DBTypeMemory = "memory"
DBTypeSQLite = "sqlite"
)
func GetDBTypeList() []string {
return []string{
DBTypeMemory,
DBTypeSQLite,
}
}
type VerboseLevel int
const (
VerboseLevelQuiet VerboseLevel = iota - 1
VerboseLevelInfo
VerboseLevelAccessLogs
VerboseLevelDebug
)
const (
// DefaultProd is the default mode.
DefaultProd = false
// DefaultDBType is the default type of database to use.
DefaultDBType = DBTypeSQLite
// DefaultDBURL is the default connection string for the database.
DefaultDBURL = "goshort.db"
// DefaultPort is the default port to listen on.
DefaultPort = "8080"
// DefaultHost is the default host to listen on. This is set to 0.0.0.0 when running in Docker.
DefaultHost = "localhost"
// DefaultUIPort is the default port to listen on for the UI.
DefaultUIPort = "3000"
// DefaultDebug is the default debug mode.
DefaultDebug = false
// DefaultSessionDuration is the default session duration.
DefaultSessionDuration = 7 * 24 * time.Hour
// DefaultDisableRegistration is the default value for diable registration.
DefaultDisableRegistration = false
// DefaultVerbose is the default verbosity level.
DefaultVerbose = VerboseLevelInfo
// DefaultQuiet is the default quiet mode.
DefaultQuiet = false
)
const (
// ReadTimeout is the maximum duration for reading the entire
// request, including the body.
ReadTimeout = 5 * time.Second
// WriteTimeout is the maximum duration before timing out
// writes of the response.
WriteTimeout = 10 * time.Second
// IdleTimeout is the maximum amount of time to wait for the
// next request when keep-alives are enabled.
IdleTimeout = 30 * time.Second
// ReadHeaderTimeout is the amount of time allowed to read
// request headers.
ReadHeaderTimeout = 2 * time.Second
// RequestTimeout is the maximum duration for the entire
// request.
RequestTimeout = 7 * 24 * time.Hour
)
// Config defines the default configuration for the backend.
type Config struct {
// Prod is a flag that indicates if the server is running in production mode.
Prod bool
// Debug is a flag that indicates if the server is running in debug mode.
Debug bool
// Host is the host to listen on.
Host string
// Port is the port to listen on.
Port string
// UiPort is the port to listen on for the UI.
UIPort string
// DBType is the type of database to use.
DBType string
// DBURL is the connection string for the database.
DBURL string
// SessionDuration is the duration of the session.
SessionDuration time.Duration
// DisableRegistration defines whether or not registration are disabled.
DisableRegistration bool
// Verbose defines the verbosity level.
Verbose VerboseLevel
// Quiet defines whether or not the server should be quiet.
Quiet bool
}
func NewConfig() *Config {
return &Config{
Prod: DefaultProd,
Debug: DefaultDebug,
Host: DefaultHost,
Port: DefaultPort,
UIPort: DefaultUIPort,
DBType: DefaultDBType,
DBURL: DefaultDBURL,
SessionDuration: DefaultSessionDuration,
DisableRegistration: DefaultDisableRegistration,
Verbose: DefaultVerbose,
Quiet: DefaultQuiet,
}
}
// Validate validates the configuration modifies user-inaccessible fields.
func Validate(cfg *Config) error {
// Host and port have to be valid.
if _, err := url.ParseRequestURI("http://" + net.JoinHostPort(cfg.Host, cfg.Port)); err != nil {
return errs.Errorf(fmt.Sprintf("invalid host and/or port: %s", err), errs.ErrInvalidConfig)
}
// UI port has to be valid.
if cfg.UIPort != "" {
if _, err := url.ParseRequestURI("http://" + net.JoinHostPort(cfg.Host, cfg.UIPort)); err != nil {
return errs.Errorf(fmt.Sprintf("invalid UI port: %s", err), errs.ErrInvalidConfig)
}
}
// Verbose has to be valid.
if cfg.Verbose < VerboseLevelInfo || cfg.Verbose > VerboseLevelDebug {
return errs.Errorf(fmt.Sprintf("invalid verbosity level: %d", cfg.Verbose), errs.ErrInvalidConfig)
}
if cfg.Verbose != VerboseLevelInfo && cfg.Quiet {
return errs.Errorf("cannot set both verbose and quiet", errs.ErrInvalidConfig)
}
if cfg.DBType != "" {
// DB type has to be valid.
valid := false
for _, dbType := range GetDBTypeList() {
if cfg.DBType == dbType {
valid = true
break
}
}
if !valid {
return errs.Errorf(fmt.Sprintf("invalid database type: %s", cfg.DBType), errs.ErrInvalidConfig)
}
}
// If verbose == 2, set debug to true for backwards compatibility.
if cfg.Verbose >= VerboseLevelDebug {
cfg.Debug = true
}
// If quiet is true, set verbose to -1.
if cfg.Quiet {
cfg.Verbose = VerboseLevelQuiet
}
return nil
}
func (c *Config) PrettyPrint() {
fmt.Println("Configuration:")
fmt.Println(" - Production mode:", c.Prod)
fmt.Println(" - Debug mode:", c.Debug)
fmt.Println(" - Host:", c.Host)
fmt.Println(" - Port:", c.Port)
fmt.Println(" - UI Port:", c.UIPort)
fmt.Println(" - Database type:", c.DBType)
fmt.Println(" - Database URL:", c.DBURL)
fmt.Println(" - Session duration:", c.SessionDuration)
fmt.Println(" - Disable registration:", c.DisableRegistration)
fmt.Println(" - Verbose level:", c.Verbose)
fmt.Println(" - Quiet mode:", c.Quiet)
}