package server import ( "fmt" "time" "github.com/gin-contrib/gzip" "github.com/gin-gonic/gin" "warpbox/lib/boxstore" "warpbox/lib/config" "warpbox/lib/metastore" "warpbox/lib/routing" ) type App struct { config *config.Config store *metastore.Store adminLoginEnabled bool } func Run(addr string) error { cfg, err := config.Load() if err != nil { return err } if err := cfg.EnsureDirectories(); err != nil { return err } boxstore.SetUploadRoot(cfg.UploadsDir) store, err := metastore.Open(cfg.DBDir) if err != nil { return fmt.Errorf("open metadata database: %w", err) } defer store.Close() overrides, err := store.ListSettings() if err != nil { return fmt.Errorf("load settings overrides: %w", err) } if err := cfg.ApplyOverrides(overrides); err != nil { return fmt.Errorf("apply settings overrides: %w", err) } bootstrap, err := metastore.BootstrapAdmin(cfg, store) if err != nil { return fmt.Errorf("bootstrap admin metadata: %w", err) } app := &App{ config: cfg, store: store, adminLoginEnabled: bootstrap.AdminLoginEnabled, } router := gin.Default() router.LoadHTMLGlob("templates/*.html") routing.Register(router, routing.Handlers{ Index: app.handleIndex, ShowBox: app.handleShowBox, BoxLogin: handleBoxLogin, BoxLoginPost: handleBoxLoginPost, BoxStatus: app.handleBoxStatus, DownloadBox: app.handleDownloadBox, DownloadFile: app.handleDownloadFile, DownloadThumbnail: app.handleDownloadThumbnail, CreateBox: app.handleCreateBox, ManifestFileUpload: app.handleManifestFileUpload, FileStatusUpdate: app.handleFileStatusUpdate, DirectBoxUpload: app.handleDirectBoxUpload, LegacyUpload: app.handleLegacyUpload, }) app.registerAdminRoutes(router) compressed := router.Group("/", gzip.Gzip(gzip.DefaultCompression)) compressed.Static("/static", "./static") boxstore.StartThumbnailWorker(cfg.ThumbnailBatchSize, time.Duration(cfg.ThumbnailIntervalSeconds)*time.Second) return router.Run(addr) }