feat(backup): daily server and user backups, restore by section (backend)
Admins switch automatic backups on, pick the time and the retention (default 03:00, 3 days). Each run writes a gzip snapshot of the whole database (VACUUM INTO, consistent while others write) and one MindSift backup ZIP per active user below $DATA_DIR/backups, then deletes files past the retention. A restart after the time catches up on that day. Admins list, download and trigger runs; users list, download and restore their own backups. Import and restore can be limited to sections (notes, tasks, lists, inbox, themes): restore only empties the chosen sections. Export and import now carry custom themes. File names are checked against a fixed pattern, so no other file can be fetched through the API. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
cab5a79f6d
commit
c97765e08e
9 files changed
+632
-68
No files matched your search
@@ -56,6 +56,9 @@ func NewServer(cfg *config.Config, store *storage.Store, wsHub *ws.Hub, staticFS
|
||||
if cfg.DemoMode && cfg.DemoResetMinutes > 0 {
|
||||
go srv.startDemoResetTicker()
|
||||
}
|
||||
if !cfg.DemoMode {
|
||||
go srv.startBackupScheduler()
|
||||
}
|
||||
return srv
|
||||
}
|
||||
|
||||
@@ -130,6 +133,9 @@ func (s *Server) Router() http.Handler {
|
||||
r.Get("/api/v1/stats", s.handleStats)
|
||||
r.Get("/api/v1/search", s.handleSearch)
|
||||
r.Get("/api/v1/export", s.handleExport)
|
||||
r.Get("/api/v1/backups", s.handleListMyBackups)
|
||||
r.Get("/api/v1/backups/{name}", s.handleDownloadMyBackup)
|
||||
r.Post("/api/v1/backups/{name}/restore", s.handleRestoreMyBackup)
|
||||
r.Get("/api/v1/export/markdown", s.handleExportMarkdown)
|
||||
r.Post("/api/v1/import/mindsift", s.handleImportMindSift)
|
||||
r.Delete("/api/v1/user/data", s.handlePurgeOwnData)
|
||||
@@ -256,6 +262,9 @@ func (s *Server) Router() http.Handler {
|
||||
r.Group(func(r chi.Router) {
|
||||
r.Use(s.adminMiddleware)
|
||||
r.Get("/api/v1/admin/settings", s.handleAdminGetSettings)
|
||||
r.Get("/api/v1/admin/backups", s.handleAdminListBackups)
|
||||
r.Post("/api/v1/admin/backups", s.handleAdminRunBackup)
|
||||
r.Get("/api/v1/admin/backups/{name}", s.handleAdminDownloadBackup)
|
||||
r.Put("/api/v1/admin/settings", s.handleAdminUpdateSettings)
|
||||
r.Get("/api/v1/admin/settings/sharing-impact", s.handleAdminSharingImpact)
|
||||
|
||||
|
||||
Reference in new issue
Block a user