// TODO: Add EUPL banner everywhere 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" "git.mstar.dev/mstar/linstrom/config" "git.mstar.dev/mstar/linstrom/server" "git.mstar.dev/mstar/linstrom/shared" "git.mstar.dev/mstar/linstrom/storage" storagenew "git.mstar.dev/mstar/linstrom/storage-new" "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 // Serve frontend files from a given directory instead of embedded data //go:embed frontend-reactive/dist/* frontend-reactive/dist/assets var reactiveFS embed.FS //go:embed frontend-noscript var nojsFS embed.FS //go:embed duck.webp var defaultDuck string func main() { other.SetupFlags() flag.Parse() 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). Str("config-file", *shared.FlagConfigFile). Msg("Failed to read config and couldn't write default") } // Request to only check config if *shared.FlagConfigOnly { return } if *shared.FlagStartNew { log.Info().Msg("Starting new system") newServer() } else { log.Info().Msg("Starting old system") oldServer() } } 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, config.GlobalConfig.Storage.RedisUrl, ) if err != nil { log.Fatal().Err(err).Msg("Failed to start cache") } // var store *storage.Storage // if config.GlobalConfig.Storage.DbIsPostgres != nil && *config.GlobalConfig.Storage.DbIsPostgres { // store, err = storage.NewStoragePostgres(config.GlobalConfig.Storage.DatabaseUrl, storageCache) // } else { // store, err = storage.NewStorageSqlite(config.GlobalConfig.Storage.DatabaseUrl, storageCache) // } // store, err := storage.NewStorage(config.GlobalConfig.Storage.BuildPostgresDSN(), storageCache) if err != nil { log.Fatal().Err(err).Msg("Failed to setup storage") } pkey, err := passkey.New(passkey.Config{ WebauthnConfig: &webauthn.Config{ RPDisplayName: "Linstrom", RPID: "localhost", RPOrigins: []string{"http://localhost:8000"}, }, UserStore: store, SessionStore: store, SessionMaxAge: time.Hour * 24, }, passkey.WithLogger(&shared.ZerologWrapper{})) if err != nil { log.Fatal().Err(err).Msg("Failed to setup passkey support") } server := server.NewServer( store, pkey, shared.NewFSWrapper(reactiveFS, "frontend-reactive/dist/", false), shared.NewFSWrapper(nojsFS, "frontend-noscript/", false), &defaultDuck, ) server.Start(":8000") // TODO: Set up media server // TODO: Set up queues // TODO: Set up plugins } func newServer() { db, err := gorm.Open( postgres.Open(config.GlobalConfig.Storage.BuildPostgresDSN()), &gorm.Config{ Logger: shared.NewGormLogger(log.Logger), }, ) if err != nil { log.Fatal().Err(err).Msg("Failed to start db") } dbgen.SetDefault(db) if err = storagenew.Migrate(db); err != nil { log.Fatal().Err(err).Msg("Failed to automigrate structure") } if err = storagenew.InsertSelf(); err != nil { log.Fatal().Err(err).Msg("Failed to insert self properly") } if *shared.FlagStartDebugServer { 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", &defaultDuck) public.Start() }