2026-04-25 17:40:39 +03:00
|
|
|
package server
|
|
|
|
|
|
2026-04-25 18:04:10 +03:00
|
|
|
import (
|
2026-04-28 21:11:37 +03:00
|
|
|
"fmt"
|
2026-04-28 18:44:16 +03:00
|
|
|
"time"
|
|
|
|
|
|
2026-04-25 18:04:10 +03:00
|
|
|
"github.com/gin-contrib/gzip"
|
|
|
|
|
"github.com/gin-gonic/gin"
|
2026-04-25 17:40:39 +03:00
|
|
|
|
2026-04-28 18:44:16 +03:00
|
|
|
"warpbox/lib/boxstore"
|
2026-04-28 21:11:37 +03:00
|
|
|
"warpbox/lib/config"
|
|
|
|
|
"warpbox/lib/metastore"
|
2026-04-27 17:49:19 +03:00
|
|
|
"warpbox/lib/routing"
|
2026-04-27 17:33:52 +03:00
|
|
|
)
|
|
|
|
|
|
2026-04-28 21:11:37 +03:00
|
|
|
type App struct {
|
|
|
|
|
config *config.Config
|
|
|
|
|
store *metastore.Store
|
|
|
|
|
adminLoginEnabled bool
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-25 17:40:39 +03:00
|
|
|
func Run(addr string) error {
|
2026-04-28 21:11:37 +03:00
|
|
|
cfg, err := config.Load()
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
if err := cfg.EnsureDirectories(); err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-30 04:24:49 +03:00
|
|
|
applyBoxstoreRuntimeConfig(cfg)
|
2026-04-28 21:11:37 +03:00
|
|
|
|
|
|
|
|
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)
|
|
|
|
|
}
|
2026-04-30 04:24:49 +03:00
|
|
|
applyBoxstoreRuntimeConfig(cfg)
|
2026-04-28 21:11:37 +03:00
|
|
|
|
|
|
|
|
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,
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-25 17:40:39 +03:00
|
|
|
router := gin.Default()
|
2026-04-25 18:04:10 +03:00
|
|
|
router.LoadHTMLGlob("templates/*.html")
|
2026-04-25 17:40:39 +03:00
|
|
|
|
2026-04-27 17:49:19 +03:00
|
|
|
routing.Register(router, routing.Handlers{
|
2026-04-28 21:11:37 +03:00
|
|
|
Index: app.handleIndex,
|
|
|
|
|
ShowBox: app.handleShowBox,
|
2026-04-27 18:18:53 +03:00
|
|
|
BoxLogin: handleBoxLogin,
|
|
|
|
|
BoxLoginPost: handleBoxLoginPost,
|
2026-04-28 21:11:37 +03:00
|
|
|
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,
|
2026-04-25 18:46:16 +03:00
|
|
|
})
|
2026-04-28 21:11:37 +03:00
|
|
|
app.registerAdminRoutes(router)
|
2026-04-25 18:46:16 +03:00
|
|
|
|
2026-04-25 18:04:10 +03:00
|
|
|
compressed := router.Group("/", gzip.Gzip(gzip.DefaultCompression))
|
|
|
|
|
compressed.Static("/static", "./static")
|
|
|
|
|
|
2026-04-28 21:11:37 +03:00
|
|
|
boxstore.StartThumbnailWorker(cfg.ThumbnailBatchSize, time.Duration(cfg.ThumbnailIntervalSeconds)*time.Second)
|
2026-04-28 18:44:16 +03:00
|
|
|
|
2026-04-25 17:40:39 +03:00
|
|
|
return router.Run(addr)
|
|
|
|
|
}
|
2026-04-30 04:24:49 +03:00
|
|
|
|
|
|
|
|
func applyBoxstoreRuntimeConfig(cfg *config.Config) {
|
|
|
|
|
boxstore.SetUploadRoot(cfg.UploadsDir)
|
|
|
|
|
boxstore.SetOneTimeDownloadExpiry(cfg.OneTimeDownloadExpirySeconds)
|
|
|
|
|
}
|