Implements a master toggle for security features across config, CLI, and application logic. This allows granular control over whether the advanced security middleware and protections are active globally.
145 lines
4.0 KiB
Go
145 lines
4.0 KiB
Go
package server
|
|
|
|
import (
|
|
"encoding/json"
|
|
"html/template"
|
|
"path/filepath"
|
|
"time"
|
|
|
|
"github.com/gin-contrib/gzip"
|
|
"github.com/gin-gonic/gin"
|
|
|
|
"warpbox/lib/activity"
|
|
"warpbox/lib/alerts"
|
|
"warpbox/lib/boxstore"
|
|
"warpbox/lib/config"
|
|
"warpbox/lib/routing"
|
|
"warpbox/lib/security"
|
|
)
|
|
|
|
type App struct {
|
|
config *config.Config
|
|
settingsOverridesPath string
|
|
activityStore *activity.Store
|
|
alertStore *alerts.Store
|
|
securityGuard *security.Guard
|
|
}
|
|
|
|
func Run(addr string) error {
|
|
cfg, err := config.Load()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if err := cfg.EnsureDirectories(); err != nil {
|
|
return err
|
|
}
|
|
overridesPath := filepath.Join(cfg.DBDir, config.AdminSettingsOverrideFilename)
|
|
overrides, err := config.ReadAdminSettingsOverrides(overridesPath)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if err := cfg.ApplyOverrides(overrides); err != nil {
|
|
return err
|
|
}
|
|
|
|
applyBoxstoreRuntimeConfig(cfg)
|
|
|
|
app := &App{
|
|
config: cfg,
|
|
settingsOverridesPath: overridesPath,
|
|
activityStore: activity.NewStore(filepath.Join(cfg.DBDir, "activity_log.json")),
|
|
alertStore: alerts.NewStore(filepath.Join(cfg.DBDir, "alerts.json")),
|
|
securityGuard: security.NewGuard(),
|
|
}
|
|
if err := app.reloadSecurityConfig(); err != nil {
|
|
return err
|
|
}
|
|
|
|
router := gin.Default()
|
|
router.Use(app.securityMiddleware())
|
|
router.NoRoute(app.handleNoRoute)
|
|
htmlTemplates, err := loadHTMLTemplates()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
router.SetHTMLTemplate(htmlTemplates)
|
|
|
|
routing.Register(router, routing.Handlers{
|
|
Health: app.handleHealth,
|
|
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,
|
|
|
|
AdminLogin: app.handleAdminLogin,
|
|
AdminLoginPost: app.handleAdminLoginPost,
|
|
AdminLogout: app.handleAdminLogout,
|
|
AdminDashboard: app.handleAdminDashboard,
|
|
AdminAlerts: app.handleAdminAlerts,
|
|
AdminBoxes: app.handleAdminBoxes,
|
|
AdminBoxesAction: app.handleAdminBoxesAction,
|
|
AdminUsers: app.handleAdminUsers,
|
|
AdminActivity: app.handleAdminActivity,
|
|
AdminSecurity: app.handleAdminSecurity,
|
|
AdminAlertsAction: app.handleAdminAlertsAction,
|
|
AdminSecurityAction: app.handleAdminSecurityAction,
|
|
AdminSettings: app.handleAdminSettings,
|
|
AdminSettingsExport: app.handleAdminSettingsExport,
|
|
AdminSettingsSave: app.handleAdminSettingsSave,
|
|
AdminSettingsImport: app.handleAdminSettingsImport,
|
|
AdminSettingsReset: app.handleAdminSettingsReset,
|
|
AdminAuth: app.adminAuthMiddleware,
|
|
})
|
|
|
|
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)
|
|
}
|
|
|
|
func loadHTMLTemplates() (*template.Template, error) {
|
|
tmpl := template.New("").Funcs(template.FuncMap{
|
|
"toJSON": func(value any) template.JS {
|
|
data, err := json.Marshal(value)
|
|
if err != nil {
|
|
return template.JS("null")
|
|
}
|
|
return template.JS(data)
|
|
},
|
|
})
|
|
for _, pattern := range []string{
|
|
"templates/*.html",
|
|
"templates/admin/*.html",
|
|
"templates/admin/partials/*.html",
|
|
} {
|
|
var err error
|
|
tmpl, err = tmpl.ParseGlob(pattern)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
return tmpl, nil
|
|
}
|
|
|
|
func applyBoxstoreRuntimeConfig(cfg *config.Config) {
|
|
boxstore.SetUploadRoot(cfg.UploadsDir)
|
|
boxstore.SetOneTimeDownloadExpiry(cfg.OneTimeDownloadExpirySeconds)
|
|
}
|
|
|
|
func (app *App) handleHealth(c *gin.Context) {
|
|
c.JSON(200, gin.H{
|
|
"status": "healthy",
|
|
})
|
|
}
|