diff --git a/go.mod b/go.mod index 3d1d938..a387f7c 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.23.0 toolchain go1.23.7 require ( - git.mstar.dev/mstar/goutils v1.9.1 + git.mstar.dev/mstar/goutils v1.10.0 github.com/BurntSushi/toml v1.4.0 github.com/dgraph-io/ristretto v0.2.0 github.com/eko/gocache/lib/v4 v4.1.6 @@ -83,10 +83,11 @@ require ( golang.org/x/mod v0.17.0 // indirect golang.org/x/net v0.30.0 // indirect golang.org/x/sync v0.12.0 // indirect - golang.org/x/sys v0.31.0 // indirect + golang.org/x/sys v0.32.0 // indirect golang.org/x/text v0.23.0 // indirect golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect google.golang.org/protobuf v1.33.0 // indirect + gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect gorm.io/datatypes v1.2.5 // indirect gorm.io/driver/mysql v1.5.7 // indirect diff --git a/go.sum b/go.sum index f1df3b0..0867e3b 100644 --- a/go.sum +++ b/go.sum @@ -35,6 +35,8 @@ filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= git.mstar.dev/mstar/goutils v1.9.1 h1:B4km2Xj0Yq8GHIlAYo45NGMRQRdkr+hV9qdvhTJKuuA= git.mstar.dev/mstar/goutils v1.9.1/go.mod h1:juxY0eZEMnA95fedRp2LVXvUBgEjz66nE8SEdGKcxMA= +git.mstar.dev/mstar/goutils v1.10.0 h1:TXTz+RA4c5tNZRtdb4eVGjeL15xSjQOOSxfQ5ZwmKeE= +git.mstar.dev/mstar/goutils v1.10.0/go.mod h1:juxY0eZEMnA95fedRp2LVXvUBgEjz66nE8SEdGKcxMA= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0= github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= @@ -495,6 +497,8 @@ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20= +golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= @@ -645,6 +649,8 @@ gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= +gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/main.go b/main.go index f15dd54..b5a0902 100644 --- a/main.go +++ b/main.go @@ -4,12 +4,14 @@ package main import ( "embed" "flag" + "path" "time" "git.mstar.dev/mstar/goutils/other" "github.com/go-webauthn/webauthn/webauthn" "github.com/mstarongithub/passkey" "github.com/rs/zerolog/log" + "gopkg.in/natefinch/lumberjack.v2" "gorm.io/driver/postgres" "gorm.io/gorm" @@ -21,6 +23,7 @@ import ( "git.mstar.dev/mstar/linstrom/storage-new/dbgen" "git.mstar.dev/mstar/linstrom/storage/cache" webdebug "git.mstar.dev/mstar/linstrom/web/debug" + webpublic "git.mstar.dev/mstar/linstrom/web/public" ) // TODO: Add frontend overwrite @@ -38,7 +41,20 @@ var defaultDuck string func main() { other.SetupFlags() flag.Parse() - other.ConfigureLogging(nil) + logfile := getLogFilePathOrNil() + if logfile == nil { + other.ConfigureLogging(nil) + log.Warn().Msg("Can't write to target logfile, not creating one") + } else { + other.ConfigureLogging(&lumberjack.Logger{ + Filename: *logfile, + MaxSize: 500, // Megabytes + MaxBackups: 3, + MaxAge: 3, // Days + Compress: false, + }) + log.Info().Str("logfile", *logfile).Msg("Logging to stderr and logfile") + } if err := config.ReadAndWriteToGlobal(*shared.FlagConfigFile); err != nil { log.Fatal(). Err(err). @@ -59,6 +75,16 @@ func main() { } } +func getLogFilePathOrNil() *string { + logfile := *shared.FlagLogFile + logPath := path.Dir(logfile) + if shared.IsWritable(logPath) { + return &logfile + } else { + return nil + } +} + func oldServer() { storageCache, err := cache.NewCache( config.GlobalConfig.Storage.MaxInMemoryCacheSize, @@ -126,10 +152,14 @@ func newServer() { log.Fatal().Err(err).Msg("Failed to insert self properly") } if *shared.FlagStartDebugServer { - log.Info().Msg("Starting debug server") - // TODO: Move into goroutine once public server also exists - if err = webdebug.New().Start(); err != nil { - log.Fatal().Err(err).Msg("Debug server failed") - } + go func() { + log.Info().Msg("Starting debug server") + if err = webdebug.New().Start(); err != nil { + log.Fatal().Err(err).Msg("Debug server failed") + } + }() } + log.Info().Msg("Starting public server") + public := webpublic.New(":8080") + public.Start() } diff --git a/shared/flags.go b/shared/flags.go index b1abc10..03fe2ff 100644 --- a/shared/flags.go +++ b/shared/flags.go @@ -25,6 +25,11 @@ var ( false, "Also start the local debugging server", ) + FlagLogFile *string = flag.String( + "logfile", + "/var/log/linstrom/logs", + "Set the target logging file. Linstrom auto-rotates these. If it can't be created, it will be ignored", + ) ) func flagUsage() { @@ -50,5 +55,5 @@ func flagUsage() { } func init() { - flag.Usage = flagUsage + // flag.Usage = flagUsage } diff --git a/shared/isWritable.go b/shared/isWritable.go new file mode 100644 index 0000000..fab473f --- /dev/null +++ b/shared/isWritable.go @@ -0,0 +1,11 @@ +//go:build !windows +// +build !windows + +package shared + +import "golang.org/x/sys/unix" + +// Copied from https://stackoverflow.com/a/20026945 and https://stackoverflow.com/a/49148866 +func IsWritable(path string) bool { + return unix.Access(path, unix.W_OK) == nil +} diff --git a/shared/isWritable_windows.go b/shared/isWritable_windows.go new file mode 100644 index 0000000..7a088c6 --- /dev/null +++ b/shared/isWritable_windows.go @@ -0,0 +1,23 @@ +package shared + +import "os" + +// Copied from https://stackoverflow.com/a/20026945 and https://stackoverflow.com/a/49148866 +func IsWritable(path string) bool { + info, err := os.Stat(path) + if err != nil { + return false + } + + err = nil + if !info.IsDir() { + return false + } + + // Check if the user bit is enabled in file permission + if info.Mode().Perm()&(1<<(uint(7))) == 0 { + return false + } + + return true +} diff --git a/web/public/server.go b/web/public/server.go index 53d8911..0d462b1 100644 --- a/web/public/server.go +++ b/web/public/server.go @@ -26,8 +26,33 @@ // TODO: Decide how long the Linstrom-RPC API will remain backwards compatible package webpublic -import "net/http" +import ( + "context" + "fmt" + "net/http" +) type Server struct { - server http.Server + server *http.Server +} + +func New(addr string) *Server { + handler := http.NewServeMux() + handler.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(500) + fmt.Fprint(w, "not implemented") + }) + server := http.Server{ + Handler: handler, + Addr: addr, + } + return &Server{&server} +} + +func (s *Server) Start() error { + return s.server.ListenAndServe() +} + +func (s *Server) Stop() error { + return s.server.Shutdown(context.Background()) }