Documentation
¶
Overview ¶
Package backup provides functionality for creating and restoring SafeShare backups.
Package backup provides functionality for creating and restoring SafeShare backups.
The backup package supports three backup modes:
- config: Settings, webhooks, blocked IPs, admin credentials only
- database: Full database without uploaded files
- full: Database + all uploaded files
Backups are created as directory structures with a manifest.json file that contains metadata, checksums, and information about what's included.
Index ¶
- Constants
- Variables
- func BackupDatabase(sourcePath, destPath string) error
- func CleanupUploadsDir(uploadsDir string, keepFiles map[string]bool) (int, error)
- func ComputeChecksum(filePath string) (string, error)
- func ComputeKeyFingerprint(encryptionKey string) string
- func CopyUploadsDir(srcDir, destDir string, ...) (int, int64, error)
- func CountUploadFiles(uploadsDir string) (int, error)
- func DeleteOrphanedFileRecords(dbPath string, storedFilenames []string) (int, error)
- func FindOrphanedFiles(uploadsDir string, dbStoredFilenames map[string]bool) ([]string, error)
- func GetBackupDirName() string
- func GetDirectorySize(dirPath string) (int64, error)
- func GetFileSize(filePath string) (int64, error)
- func GetTableCounts(db *sql.DB) (map[string]int, error)
- func GetUploadsTotalSize(uploadsDir string) (int64, error)
- func RestoreDatabase(backupPath, destPath string) error
- func RestoreUploadsDir(backupDir, destDir string, ...) (int, error)
- func ValidateCronExpression(cronExpr string) error
- func ValidateDatabase(dbPath string) error
- func ValidateManifest(manifest *BackupManifest) error
- func VerifyChecksum(filePath, expectedChecksum string) error
- func VerifyUploadsIntegrity(uploadsDir string, expectedFiles []string) ([]string, error)
- func WriteManifest(manifest *BackupManifest, backupDir string) error
- type BackupIncludes
- type BackupInfo
- type BackupJob
- type BackupManifest
- type BackupMode
- type BackupResult
- type BackupStats
- type ChecksumMismatch
- type CreateOptions
- type EncryptionInfo
- type FileRecord
- type JobStatus
- type OrphanHandling
- type RestoreOptions
- type RestoreResult
- type Scheduler
- type VerifyResult
Constants ¶
const ( // ManifestFilename is the name of the manifest file in backup directories ManifestFilename = "manifest.json" // DatabaseFilename is the name of the database backup file DatabaseFilename = "safeshare.db" // UploadsDirname is the name of the uploads directory in full backups UploadsDirname = "uploads" )
const ( // BackupDirPerms is the permission mode for backup directories (owner only) BackupDirPerms = 0700 // BackupFilePerms is the permission mode for backup files (owner only) BackupFilePerms = 0600 )
const ManifestVersion = "1.0"
ManifestVersion is the current backup manifest format version
const (
// PartialUploadDir is the directory containing partial uploads (excluded from backup)
PartialUploadDir = ".partial"
)
Variables ¶
var ConfigTables = []string{
"settings",
"admin_credentials",
"blocked_ips",
"webhook_configs",
}
ConfigTables lists tables included in config-only backups
var ErrBackupAlreadyRunning = errors.New("another backup is already running")
ErrBackupAlreadyRunning indicates a backup is already in progress.
var ErrInvalidCronExpression = errors.New("invalid cron expression")
ErrInvalidCronExpression indicates an invalid cron expression.
var ExcludedTables = []string{
"user_sessions",
"admin_sessions",
"partial_uploads",
}
ExcludedTables lists tables that should NOT be backed up
var FullDatabaseTables = []string{
"files",
"users",
"settings",
"admin_credentials",
"blocked_ips",
"webhook_configs",
"api_tokens",
"webhook_deliveries",
}
FullDatabaseTables lists all tables included in database/full backups
Functions ¶
func BackupDatabase ¶
BackupDatabase creates a hot backup of a SQLite database This uses VACUUM INTO which creates a consistent snapshot and handles WAL mode correctly
func CleanupUploadsDir ¶
CleanupUploadsDir removes files from uploads directory that are not in the whitelist This is used during restore to remove files that were uploaded after the backup
func ComputeChecksum ¶
ComputeChecksum computes the SHA256 checksum of a file
func ComputeKeyFingerprint ¶
ComputeKeyFingerprint computes the SHA256 fingerprint of an encryption key This allows verification that the correct key is used without storing the key itself
func CopyUploadsDir ¶
func CopyUploadsDir(srcDir, destDir string, progressCallback func(current, total int, filename string)) (int, int64, error)
CopyUploadsDir copies all files from source uploads directory to destination Excludes the .partial directory which contains temporary chunked uploads
func CountUploadFiles ¶
CountUploadFiles counts the number of files in uploads directory (excluding .partial)
func DeleteOrphanedFileRecords ¶
DeleteOrphanedFileRecords removes file records that don't have corresponding files
func FindOrphanedFiles ¶
FindOrphanedFiles identifies files in uploads that don't have database records
func GetBackupDirName ¶
func GetBackupDirName() string
GetBackupDirName generates a backup directory name based on timestamp
func GetDirectorySize ¶
GetDirectorySize calculates the total size of all files in a directory
func GetFileSize ¶
GetFileSize returns the size of a file in bytes
func GetTableCounts ¶
GetTableCounts returns counts for all tables in the database
func GetUploadsTotalSize ¶
GetUploadsTotalSize calculates total size of files in uploads directory (excluding .partial)
func RestoreDatabase ¶
RestoreDatabase restores a database from a backup file The destination database file will be replaced
func RestoreUploadsDir ¶
func RestoreUploadsDir(backupDir, destDir string, progressCallback func(current, total int, filename string)) (int, error)
RestoreUploadsDir restores files from backup to uploads directory
func ValidateCronExpression ¶
ValidateCronExpression validates a cron expression. Supported format: minute hour day month weekday Examples: "0 2 * * *" (2 AM daily), "0 0 * * 0" (midnight Sunday)
func ValidateDatabase ¶
ValidateDatabase checks if a SQLite database is valid and accessible
func ValidateManifest ¶
func ValidateManifest(manifest *BackupManifest) error
ValidateManifest checks if a manifest is valid and complete
func VerifyChecksum ¶
VerifyChecksum verifies a file's checksum matches the expected value
func VerifyUploadsIntegrity ¶
VerifyUploadsIntegrity checks that all expected files exist in uploads directory
func WriteManifest ¶
func WriteManifest(manifest *BackupManifest, backupDir string) error
WriteManifest writes a manifest to a backup directory
Types ¶
type BackupIncludes ¶
type BackupIncludes struct {
// Settings indicates if runtime settings are included
Settings bool `json:"settings"`
// Users indicates if user accounts are included
Users bool `json:"users"`
// FileMetadata indicates if file records (metadata) are included
FileMetadata bool `json:"file_metadata"`
// Files indicates if actual uploaded files are included
Files bool `json:"files"`
// Webhooks indicates if webhook configurations are included
Webhooks bool `json:"webhooks"`
// APITokens indicates if API tokens are included
APITokens bool `json:"api_tokens"`
// BlockedIPs indicates if IP blocklist is included
BlockedIPs bool `json:"blocked_ips"`
// AdminCredentials indicates if admin credentials are included
AdminCredentials bool `json:"admin_credentials"`
}
BackupIncludes describes what data types are included in the backup
type BackupInfo ¶
type BackupInfo struct {
// Path is the path to the backup directory
Path string `json:"path"`
// Name is the directory name
Name string `json:"name"`
// CreatedAt is when the backup was created
CreatedAt time.Time `json:"created_at"`
// Mode is the backup mode
Mode BackupMode `json:"mode"`
SafeShareVersion string `json:"safeshare_version"`
// TotalSizeBytes is the total backup size
TotalSizeBytes int64 `json:"total_size_bytes"`
// FileRecordsCount is the number of file records
FileRecordsCount int `json:"file_records_count"`
// FilesBackedUp is the number of files (for full backups)
FilesBackedUp int `json:"files_backed_up"`
}
BackupInfo contains summary information about a backup (for listing)
func ListBackups ¶
func ListBackups(backupsDir string) ([]BackupInfo, error)
ListBackups returns information about all backups in a directory
type BackupJob ¶
type BackupJob struct {
// ID is the unique job identifier
ID string `json:"id"`
// Type is either "backup" or "restore"
Type string `json:"type"`
// Mode is the backup mode
Mode BackupMode `json:"mode"`
// Status is the current job status
Status JobStatus `json:"status"`
// Progress is the percentage complete (0-100)
Progress int `json:"progress"`
// OutputPath is the path to the backup (for completed backups)
OutputPath string `json:"output_path,omitempty"`
// Error is the error message (for failed jobs)
Error string `json:"error,omitempty"`
// StartedAt is when the job started
StartedAt time.Time `json:"started_at"`
// CompletedAt is when the job completed (nil if still running)
CompletedAt *time.Time `json:"completed_at,omitempty"`
}
BackupJob represents an async backup or restore job
type BackupManifest ¶
type BackupManifest struct {
// Version of the manifest format
Version string `json:"version"`
// CreatedAt is when the backup was created
CreatedAt time.Time `json:"created_at"`
SafeShareVersion string `json:"safeshare_version"`
// Mode indicates what type of backup this is
Mode BackupMode `json:"mode"`
// Includes describes what data is included in this backup
Includes BackupIncludes `json:"includes"`
// Stats contains counts and sizes of backed up data
Stats BackupStats `json:"stats"`
// Checksums contains SHA256 checksums of backup files
Checksums map[string]string `json:"checksums"`
// Encryption contains information about encryption state
Encryption EncryptionInfo `json:"encryption"`
// Warnings contains any warnings generated during backup
Warnings []string `json:"warnings,omitempty"`
// SourceDBPath is the original database path (informational only)
SourceDBPath string `json:"source_db_path,omitempty"`
// SourceUploadsDir is the original uploads directory (informational only)
SourceUploadsDir string `json:"source_uploads_dir,omitempty"`
}
BackupManifest contains metadata about a backup
func NewManifest ¶
func NewManifest(mode BackupMode, safeShareVersion string) *BackupManifest
NewManifest creates a new backup manifest with default values
func ReadManifest ¶
func ReadManifest(backupDir string) (*BackupManifest, error)
ReadManifest reads and parses a manifest from a backup directory
type BackupMode ¶
type BackupMode string
BackupMode defines the type of backup to create
const ( // ModeConfig backs up only configuration: settings, webhooks, blocked IPs, admin credentials ModeConfig BackupMode = "config" // ModeDatabase backs up the full database without uploaded files ModeDatabase BackupMode = "database" // ModeFull backs up the database and all uploaded files ModeFull BackupMode = "full" )
func (BackupMode) IsValid ¶
func (m BackupMode) IsValid() bool
IsValid returns true if the backup mode is valid
func (BackupMode) String ¶
func (m BackupMode) String() string
String returns the string representation of BackupMode
type BackupResult ¶
type BackupResult struct {
// Success indicates if the backup completed successfully
Success bool `json:"success"`
// BackupPath is the path to the created backup directory
BackupPath string `json:"backup_path,omitempty"`
// Manifest is the backup manifest (included on success)
Manifest *BackupManifest `json:"manifest,omitempty"`
// Error is the error message if backup failed
Error string `json:"error,omitempty"`
// Duration is how long the backup took
Duration time.Duration `json:"duration"`
// DurationString is a human-readable duration
DurationString string `json:"duration_string"`
}
BackupResult contains the result of a backup operation
func Create ¶
func Create(opts CreateOptions) (*BackupResult, error)
Create creates a backup according to the specified options
type BackupStats ¶
type BackupStats struct {
// UsersCount is the number of user accounts
UsersCount int `json:"users_count"`
// FileRecordsCount is the number of file metadata records
FileRecordsCount int `json:"file_records_count"`
// FilesBackedUp is the number of actual files backed up (0 if mode != full)
FilesBackedUp int `json:"files_backed_up"`
// WebhooksCount is the number of webhook configurations
WebhooksCount int `json:"webhooks_count"`
// APITokensCount is the number of API tokens
APITokensCount int `json:"api_tokens_count"`
// BlockedIPsCount is the number of blocked IP entries
BlockedIPsCount int `json:"blocked_ips_count"`
// TotalSizeBytes is the total size of the backup in bytes
TotalSizeBytes int64 `json:"total_size_bytes"`
// DatabaseSizeBytes is the size of the database backup
DatabaseSizeBytes int64 `json:"database_size_bytes"`
// FilesSizeBytes is the total size of backed up files (0 if mode != full)
FilesSizeBytes int64 `json:"files_size_bytes"`
}
BackupStats contains statistics about the backup
func GetDatabaseStats ¶
func GetDatabaseStats(dbPath string) (*BackupStats, error)
GetDatabaseStats retrieves statistics from the database for backup manifest
type ChecksumMismatch ¶
type ChecksumMismatch struct {
// File is the filename
File string `json:"file"`
// Expected is the expected checksum from manifest
Expected string `json:"expected"`
// Actual is the actual computed checksum
Actual string `json:"actual"`
}
ChecksumMismatch represents a file with a checksum mismatch
type CreateOptions ¶
type CreateOptions struct {
// Mode is the type of backup to create
Mode BackupMode
// DBPath is the path to the SQLite database
DBPath string
// UploadsDir is the path to the uploads directory (required for full mode)
UploadsDir string
// OutputDir is the directory where the backup will be created
OutputDir string
// EncryptionKey is the 64-character hex encryption key (for fingerprint)
EncryptionKey string
SafeShareVersion string
// ProgressCallback is called with progress updates during backup
// Parameters: current step, total steps, description
ProgressCallback func(current, total int, description string)
}
CreateOptions contains options for creating a backup
type EncryptionInfo ¶
type EncryptionInfo struct {
// Enabled indicates if encryption was enabled when backup was created
Enabled bool `json:"enabled"`
// KeyFingerprint is the SHA256 hash of the encryption key (for verification)
// This allows verification that the correct key is used during restore
// without storing the actual key in the backup
KeyFingerprint string `json:"key_fingerprint,omitempty"`
}
EncryptionInfo contains information about the encryption state
type FileRecord ¶
type FileRecord struct {
ClaimCode string
OriginalFilename string
StoredFilename string
FileSize int64
}
FileRecord represents a file entry from the database (minimal fields for backup)
func FindMissingFiles ¶
func FindMissingFiles(uploadsDir string, dbRecords []FileRecord) ([]FileRecord, error)
FindMissingFiles identifies database records that don't have corresponding files
func GetFileRecords ¶
func GetFileRecords(dbPath string) ([]FileRecord, error)
GetFileRecords retrieves all file records from the database
type JobStatus ¶
type JobStatus string
JobStatus represents the status of an async backup/restore job
const ( // JobStatusPending indicates the job is queued but not started JobStatusPending JobStatus = "pending" // JobStatusRunning indicates the job is currently executing JobStatusRunning JobStatus = "running" // JobStatusCompleted indicates the job completed successfully JobStatusCompleted JobStatus = "completed" // JobStatusFailed indicates the job failed JobStatusFailed JobStatus = "failed" )
type OrphanHandling ¶
type OrphanHandling string
OrphanHandling defines how to handle orphaned file records during restore
const ( // OrphanKeep keeps orphaned file records (metadata preserved, files not recoverable) OrphanKeep OrphanHandling = "keep" // OrphanRemove removes orphaned file records from the database OrphanRemove OrphanHandling = "remove" // OrphanPrompt prompts the user for each orphaned record (interactive mode only) OrphanPrompt OrphanHandling = "prompt" )
func (OrphanHandling) IsValid ¶
func (o OrphanHandling) IsValid() bool
IsValid returns true if the orphan handling mode is valid
func (OrphanHandling) String ¶
func (o OrphanHandling) String() string
String returns the string representation of OrphanHandling
type RestoreOptions ¶
type RestoreOptions struct {
// InputDir is the path to the backup directory
InputDir string
// DBPath is the path where the database should be restored
DBPath string
// UploadsDir is the path where files should be restored (for full backups)
UploadsDir string
// HandleOrphans defines how to handle orphaned file records
HandleOrphans OrphanHandling
// DryRun previews the restore without making changes
DryRun bool
// Force overwrites existing data without confirmation
Force bool
// EncryptionKey is used to verify against the key fingerprint
EncryptionKey string
// OrphanCallback is called for each orphan when HandleOrphans is OrphanPrompt
// Returns true to keep the record, false to remove it
OrphanCallback func(claimCode, filename string, fileSize int64) bool
// ProgressCallback is called with progress updates during restore
// Parameters: current step, total steps, description
ProgressCallback func(current, total int, description string)
}
RestoreOptions contains options for restoring from a backup
type RestoreResult ¶
type RestoreResult struct {
// Success indicates if the restore completed successfully
Success bool `json:"success"`
// DryRun indicates if this was a dry run
DryRun bool `json:"dry_run"`
// Error is the error message if restore failed
Error string `json:"error,omitempty"`
// Warnings contains any warnings generated during restore
Warnings []string `json:"warnings,omitempty"`
// TablesRestored lists the database tables that were restored
TablesRestored []string `json:"tables_restored,omitempty"`
// FilesRestored is the count of files restored (for full backups)
FilesRestored int `json:"files_restored"`
// OrphansFound is the count of orphaned file records found
OrphansFound int `json:"orphans_found"`
// OrphansRemoved is the count of orphaned records that were removed
OrphansRemoved int `json:"orphans_removed"`
// OrphansKept is the count of orphaned records that were kept
OrphansKept int `json:"orphans_kept"`
// Duration is how long the restore took
Duration time.Duration `json:"duration"`
// DurationString is a human-readable duration
DurationString string `json:"duration_string"`
}
RestoreResult contains the result of a restore operation
func Restore ¶
func Restore(opts RestoreOptions) (*RestoreResult, error)
Restore restores from a backup according to the specified options
type Scheduler ¶
type Scheduler struct {
// contains filtered or unexported fields
}
Scheduler manages automatic backup execution based on configured schedules.
func NewScheduler ¶
func NewScheduler(cfg *config.Config, repos *repository.Repositories) *Scheduler
NewScheduler creates a new backup scheduler.
func (*Scheduler) Start ¶
Start begins the scheduler's background goroutine. It periodically checks for due backup schedules and executes them. This method is non-blocking and returns immediately.
func (*Scheduler) Stop ¶
func (s *Scheduler) Stop()
Stop gracefully stops the scheduler. It waits for any currently running backup to complete before returning.
func (*Scheduler) TriggerBackup ¶
func (s *Scheduler) TriggerBackup(ctx context.Context, mode string, triggerType repository.BackupTriggerType) (*repository.BackupRun, error)
TriggerBackup triggers a manual backup with the specified mode. Returns the backup run record. Uses mutex to prevent race condition between check and execution.
type VerifyResult ¶
type VerifyResult struct {
// Valid indicates if the backup is valid and complete
Valid bool `json:"valid"`
// ManifestValid indicates if the manifest is readable and valid
ManifestValid bool `json:"manifest_valid"`
// DatabaseValid indicates if the database file is present and valid
DatabaseValid bool `json:"database_valid"`
// ChecksumsValid indicates if all checksums match
ChecksumsValid bool `json:"checksums_valid"`
// FilesValid indicates if all expected files are present (for full backups)
FilesValid bool `json:"files_valid"`
// Errors contains any validation errors found
Errors []string `json:"errors,omitempty"`
// Warnings contains any validation warnings
Warnings []string `json:"warnings,omitempty"`
// Manifest is the parsed manifest (if readable)
Manifest *BackupManifest `json:"manifest,omitempty"`
// MissingFiles lists files referenced in manifest but not found
MissingFiles []string `json:"missing_files,omitempty"`
// ChecksumMismatches lists files with checksum mismatches
ChecksumMismatches []ChecksumMismatch `json:"checksum_mismatches,omitempty"`
}
VerifyResult contains the result of a backup verification
func QuickVerify ¶
func QuickVerify(backupDir string) *VerifyResult
QuickVerify performs a fast verification without checksum validation
func VerifyWithProgress ¶
func VerifyWithProgress(backupDir string, progressCallback func(current, total int, description string)) *VerifyResult
VerifyWithProgress performs verification with progress callbacks