mirror of
https://github.com/StarFleetCPTN/GoMFT.git
synced 2026-10-24 15:00:26 +02:00
feat: Refactor Google Drive and Google Photos authentication handling
- Separate built-in authentication options for source and destination in configuration forms. - Update UI components to reflect changes in authentication handling for Google Drive and Google Photos. - Implement path validation for local directories in the configuration forms, enhancing user experience. - Revise README to clarify supported source and destination types, including updated terminology for Google Drive. - Introduce new API endpoint for path validation, improving error handling and user feedback.
This commit is contained in:
1 parent
522699d96a
commit
b1db53b89e
32 files changed
+676
-548
No files matched your search
@@ -0,0 +1,278 @@
|
||||
package migrations
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/go-gormigrate/gormigrate/v2"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
func InitialSchema() *gormigrate.Migration {
|
||||
return &gormigrate.Migration{
|
||||
ID: "001_initial_schema",
|
||||
Migrate: func(tx *gorm.DB) error {
|
||||
// Check if any tables exist (indicating an existing database)
|
||||
var count int64
|
||||
if err := tx.Raw("SELECT count(*) FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%'").Scan(&count).Error; err != nil {
|
||||
return fmt.Errorf("failed to check for existing tables: %v", err)
|
||||
}
|
||||
|
||||
// If tables exist, create a backup
|
||||
if count > 0 {
|
||||
// Get the database path
|
||||
sqlDB, err := tx.DB()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get underlying database: %v", err)
|
||||
}
|
||||
|
||||
var seq int
|
||||
var name, dbPath string
|
||||
if err := sqlDB.QueryRow("PRAGMA database_list").Scan(&seq, &name, &dbPath); err != nil {
|
||||
return fmt.Errorf("failed to get database path: %v", err)
|
||||
}
|
||||
|
||||
// Create backup file with timestamp
|
||||
backupFile := fmt.Sprintf("%s.backup.%s", dbPath, time.Now().Format("20060102_150405"))
|
||||
|
||||
// Read original database
|
||||
data, err := os.ReadFile(dbPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to read database for backup: %v", err)
|
||||
}
|
||||
|
||||
// Write backup
|
||||
if err := os.WriteFile(backupFile, data, 0600); err != nil {
|
||||
return fmt.Errorf("failed to create database backup: %v", err)
|
||||
}
|
||||
|
||||
fmt.Printf("Created database backup at: %s\n", backupFile)
|
||||
}
|
||||
|
||||
// Disable foreign key constraints while creating tables
|
||||
if err := tx.Exec("PRAGMA foreign_keys = OFF").Error; err != nil {
|
||||
return fmt.Errorf("failed to disable foreign key constraints: %v", err)
|
||||
}
|
||||
defer func() {
|
||||
if err := tx.Exec("PRAGMA foreign_keys = ON").Error; err != nil {
|
||||
fmt.Printf("Warning: failed to re-enable foreign key constraints: %v\n", err)
|
||||
}
|
||||
}()
|
||||
|
||||
// Change the table name from job_histories to job_history
|
||||
if err := tx.Raw("SELECT COUNT(*) FROM sqlite_master WHERE type='table' AND name='job_histories'").Scan(&count).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if count > 0 {
|
||||
if err := tx.Exec("ALTER TABLE job_histories RENAME TO job_history").Error; err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Change the table name from password_histories to password_history
|
||||
count = 0
|
||||
if err := tx.Raw("SELECT COUNT(*) FROM sqlite_master WHERE type='table' AND name='password_histories'").Scan(&count).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if count > 0 {
|
||||
if err := tx.Exec("ALTER TABLE password_histories RENAME TO password_history").Error; err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Create Users table
|
||||
if err := tx.Exec(`CREATE TABLE IF NOT EXISTS users (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
email VARCHAR(255) NOT NULL UNIQUE,
|
||||
password_hash VARCHAR(255) NOT NULL,
|
||||
is_admin BOOLEAN DEFAULT FALSE,
|
||||
last_password_change DATETIME,
|
||||
failed_login_attempts INTEGER DEFAULT 0,
|
||||
account_locked BOOLEAN DEFAULT FALSE,
|
||||
lockout_until DATETIME,
|
||||
theme VARCHAR(255) DEFAULT 'light',
|
||||
created_at DATETIME,
|
||||
updated_at DATETIME
|
||||
)`).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Create PasswordHistory table
|
||||
if err := tx.Exec(`CREATE TABLE IF NOT EXISTS password_history (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
user_id INTEGER NOT NULL,
|
||||
password_hash VARCHAR(255) NOT NULL,
|
||||
created_at DATETIME,
|
||||
FOREIGN KEY (user_id) REFERENCES users(id)
|
||||
)`).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Create PasswordResetToken table
|
||||
if err := tx.Exec(`CREATE TABLE IF NOT EXISTS password_reset_tokens (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
user_id INTEGER NOT NULL,
|
||||
token VARCHAR(255) NOT NULL,
|
||||
expires_at DATETIME NOT NULL,
|
||||
used BOOLEAN DEFAULT FALSE,
|
||||
created_at DATETIME,
|
||||
updated_at DATETIME,
|
||||
FOREIGN KEY (user_id) REFERENCES users(id)
|
||||
)`).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Create TransferConfigs table
|
||||
if err := tx.Exec(`CREATE TABLE IF NOT EXISTS transfer_configs (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name VARCHAR(255) NOT NULL,
|
||||
source_type VARCHAR(255) NOT NULL,
|
||||
source_path TEXT NOT NULL,
|
||||
source_host VARCHAR(255),
|
||||
source_port INTEGER DEFAULT 22,
|
||||
source_user VARCHAR(255),
|
||||
source_key_file TEXT,
|
||||
source_bucket VARCHAR(255),
|
||||
source_region VARCHAR(255),
|
||||
source_access_key VARCHAR(255),
|
||||
source_endpoint VARCHAR(255),
|
||||
source_share VARCHAR(255),
|
||||
source_domain VARCHAR(255),
|
||||
source_passive_mode BOOLEAN DEFAULT TRUE,
|
||||
source_client_id VARCHAR(255),
|
||||
source_drive_id VARCHAR(255),
|
||||
source_team_drive VARCHAR(255),
|
||||
source_read_only BOOLEAN,
|
||||
source_start_year INTEGER,
|
||||
source_include_archived BOOLEAN,
|
||||
file_pattern VARCHAR(255) DEFAULT '*',
|
||||
output_pattern TEXT,
|
||||
destination_type VARCHAR(255) NOT NULL,
|
||||
destination_path TEXT NOT NULL,
|
||||
dest_host VARCHAR(255),
|
||||
dest_port INTEGER DEFAULT 22,
|
||||
dest_user VARCHAR(255),
|
||||
dest_key_file TEXT,
|
||||
dest_bucket VARCHAR(255),
|
||||
dest_region VARCHAR(255),
|
||||
dest_access_key VARCHAR(255),
|
||||
dest_endpoint VARCHAR(255),
|
||||
dest_share VARCHAR(255),
|
||||
dest_domain VARCHAR(255),
|
||||
dest_passive_mode BOOLEAN DEFAULT TRUE,
|
||||
dest_client_id VARCHAR(255),
|
||||
dest_drive_id VARCHAR(255),
|
||||
dest_team_drive VARCHAR(255),
|
||||
dest_read_only BOOLEAN,
|
||||
dest_start_year INTEGER,
|
||||
dest_include_archived BOOLEAN,
|
||||
use_builtin_auth_source BOOLEAN DEFAULT TRUE,
|
||||
use_builtin_auth_dest BOOLEAN DEFAULT TRUE,
|
||||
google_drive_authenticated BOOLEAN,
|
||||
archive_path TEXT,
|
||||
archive_enabled BOOLEAN DEFAULT FALSE,
|
||||
rclone_flags TEXT,
|
||||
delete_after_transfer BOOLEAN DEFAULT FALSE,
|
||||
skip_processed_files BOOLEAN DEFAULT TRUE,
|
||||
max_concurrent_transfers INTEGER DEFAULT 4,
|
||||
created_by INTEGER,
|
||||
created_at DATETIME,
|
||||
updated_at DATETIME,
|
||||
FOREIGN KEY (created_by) REFERENCES users(id)
|
||||
)`).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Create Jobs table
|
||||
if err := tx.Exec(`CREATE TABLE IF NOT EXISTS jobs (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name VARCHAR(255),
|
||||
config_id INTEGER NOT NULL,
|
||||
config_ids TEXT,
|
||||
schedule VARCHAR(255) NOT NULL,
|
||||
enabled BOOLEAN DEFAULT TRUE,
|
||||
last_run DATETIME,
|
||||
next_run DATETIME,
|
||||
webhook_enabled BOOLEAN DEFAULT FALSE,
|
||||
webhook_url TEXT,
|
||||
webhook_secret TEXT,
|
||||
webhook_headers TEXT,
|
||||
notify_on_success BOOLEAN DEFAULT TRUE,
|
||||
notify_on_failure BOOLEAN DEFAULT TRUE,
|
||||
created_by INTEGER,
|
||||
created_at DATETIME,
|
||||
updated_at DATETIME,
|
||||
FOREIGN KEY (config_id) REFERENCES transfer_configs(id),
|
||||
FOREIGN KEY (created_by) REFERENCES users(id)
|
||||
)`).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Create JobHistory table
|
||||
if err := tx.Exec(`CREATE TABLE IF NOT EXISTS job_history (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
job_id INTEGER NOT NULL,
|
||||
config_id INTEGER DEFAULT 0,
|
||||
start_time DATETIME NOT NULL,
|
||||
end_time DATETIME,
|
||||
status VARCHAR(255) NOT NULL,
|
||||
bytes_transferred INTEGER,
|
||||
files_transferred INTEGER,
|
||||
error_message TEXT,
|
||||
FOREIGN KEY (job_id) REFERENCES jobs(id)
|
||||
)`).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Create FileMetadata table
|
||||
if err := tx.Exec(`CREATE TABLE IF NOT EXISTS file_metadata (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
job_id INTEGER NOT NULL,
|
||||
config_id INTEGER DEFAULT 0,
|
||||
file_name VARCHAR(255) NOT NULL,
|
||||
original_path TEXT NOT NULL,
|
||||
file_size INTEGER NOT NULL,
|
||||
file_hash VARCHAR(255),
|
||||
creation_time DATETIME,
|
||||
mod_time DATETIME,
|
||||
processed_time DATETIME NOT NULL,
|
||||
destination_path TEXT NOT NULL,
|
||||
status VARCHAR(255) NOT NULL,
|
||||
error_message TEXT,
|
||||
created_at DATETIME,
|
||||
updated_at DATETIME,
|
||||
FOREIGN KEY (job_id) REFERENCES jobs(id)
|
||||
)`).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Re-enable foreign key constraints and verify integrity
|
||||
if err := tx.Exec("PRAGMA foreign_key_check").Error; err != nil {
|
||||
return fmt.Errorf("foreign key integrity check failed: %v", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
Rollback: func(tx *gorm.DB) error {
|
||||
// Drop tables in reverse order to handle foreign key constraints
|
||||
tables := []string{
|
||||
"file_metadata",
|
||||
"job_history",
|
||||
"jobs",
|
||||
"transfer_configs",
|
||||
"password_reset_tokens",
|
||||
"password_history",
|
||||
"users",
|
||||
}
|
||||
for _, table := range tables {
|
||||
if err := tx.Exec(fmt.Sprintf("DROP TABLE IF EXISTS %s", table)).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package migrations
|
||||
|
||||
import (
|
||||
"github.com/go-gormigrate/gormigrate/v2"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// UpdateBuiltinAuthFields updates the use_builtin_auth field to separate source and destination fields
|
||||
func UpdateBuiltinAuthFields() *gormigrate.Migration {
|
||||
return &gormigrate.Migration{
|
||||
ID: "002_update_builtin_auth_fields",
|
||||
Migrate: func(tx *gorm.DB) error {
|
||||
// First, add the new columns
|
||||
if err := tx.Exec(`ALTER TABLE transfer_configs ADD COLUMN use_builtin_auth_source BOOLEAN`).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if err := tx.Exec(`ALTER TABLE transfer_configs ADD COLUMN use_builtin_auth_dest BOOLEAN`).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Copy the old value to both new columns
|
||||
if err := tx.Exec(`UPDATE transfer_configs SET
|
||||
use_builtin_auth_source = use_builtin_auth,
|
||||
use_builtin_auth_dest = use_builtin_auth`).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Drop the old column
|
||||
return tx.Exec(`ALTER TABLE transfer_configs DROP COLUMN use_builtin_auth`).Error
|
||||
},
|
||||
Rollback: func(tx *gorm.DB) error {
|
||||
// Add back the original column
|
||||
if err := tx.Exec(`ALTER TABLE transfer_configs ADD COLUMN use_builtin_auth BOOLEAN`).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Copy the source value back (could also use dest, they should be the same)
|
||||
if err := tx.Exec(`UPDATE transfer_configs SET use_builtin_auth = use_builtin_auth_source`).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Drop the new columns
|
||||
if err := tx.Exec(`ALTER TABLE transfer_configs DROP COLUMN use_builtin_auth_source`).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
return tx.Exec(`ALTER TABLE transfer_configs DROP COLUMN use_builtin_auth_dest`).Error
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package migrations
|
||||
|
||||
import (
|
||||
"github.com/go-gormigrate/gormigrate/v2"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// UpdateGDriveType updates the source_type and destination_type from 'google_drive' to 'gdrive'
|
||||
func UpdateGDriveType() *gormigrate.Migration {
|
||||
return &gormigrate.Migration{
|
||||
ID: "003_update_gdrive_type",
|
||||
Migrate: func(tx *gorm.DB) error {
|
||||
// Update source_type
|
||||
if err := tx.Exec(`UPDATE transfer_configs SET source_type = 'gdrive' WHERE source_type = 'google_drive'`).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Update destination_type
|
||||
return tx.Exec(`UPDATE transfer_configs SET destination_type = 'gdrive' WHERE destination_type = 'google_drive'`).Error
|
||||
},
|
||||
Rollback: func(tx *gorm.DB) error {
|
||||
// Revert source_type
|
||||
if err := tx.Exec(`UPDATE transfer_configs SET source_type = 'google_drive' WHERE source_type = 'gdrive'`).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Revert destination_type
|
||||
return tx.Exec(`UPDATE transfer_configs SET destination_type = 'google_drive' WHERE destination_type = 'gdrive'`).Error
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
package migrations
|
||||
|
||||
import (
|
||||
"github.com/go-gormigrate/gormigrate/v2"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// AddCloudStorageFields adds fields for WebDAV, NextCloud, OneDrive, and Google Drive
|
||||
func AddCloudStorageFields() *gormigrate.Migration {
|
||||
return &gormigrate.Migration{
|
||||
ID: "add_cloud_storage_fields",
|
||||
Migrate: func(tx *gorm.DB) error {
|
||||
// Add source fields
|
||||
if err := tx.Exec("ALTER TABLE transfer_configs ADD COLUMN source_client_id VARCHAR(255)").Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if err := tx.Exec("ALTER TABLE transfer_configs ADD COLUMN source_drive_id VARCHAR(255)").Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if err := tx.Exec("ALTER TABLE transfer_configs ADD COLUMN source_team_drive VARCHAR(255)").Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Add destination fields
|
||||
if err := tx.Exec("ALTER TABLE transfer_configs ADD COLUMN dest_client_id VARCHAR(255)").Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if err := tx.Exec("ALTER TABLE transfer_configs ADD COLUMN dest_drive_id VARCHAR(255)").Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if err := tx.Exec("ALTER TABLE transfer_configs ADD COLUMN dest_team_drive VARCHAR(255)").Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
Rollback: func(tx *gorm.DB) error {
|
||||
// Drop source fields
|
||||
if err := tx.Exec("ALTER TABLE transfer_configs DROP COLUMN source_client_id").Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if err := tx.Exec("ALTER TABLE transfer_configs DROP COLUMN source_drive_id").Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if err := tx.Exec("ALTER TABLE transfer_configs DROP COLUMN source_team_drive").Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Drop destination fields
|
||||
if err := tx.Exec("ALTER TABLE transfer_configs DROP COLUMN dest_client_id").Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if err := tx.Exec("ALTER TABLE transfer_configs DROP COLUMN dest_drive_id").Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if err := tx.Exec("ALTER TABLE transfer_configs DROP COLUMN dest_team_drive").Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
package migrations
|
||||
|
||||
import (
|
||||
"github.com/go-gormigrate/gormigrate/v2"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// AddDeleteAfterTransferColumn adds the delete_after_transfer column to transfer_configs table
|
||||
func AddDeleteAfterTransferColumn() *gormigrate.Migration {
|
||||
return &gormigrate.Migration{
|
||||
ID: "add_delete_after_transfer_column",
|
||||
Migrate: func(tx *gorm.DB) error {
|
||||
return tx.Exec("ALTER TABLE transfer_configs ADD COLUMN delete_after_transfer BOOLEAN NOT NULL DEFAULT false").Error
|
||||
},
|
||||
Rollback: func(tx *gorm.DB) error {
|
||||
return tx.Exec("ALTER TABLE transfer_configs DROP COLUMN delete_after_transfer").Error
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
package migrations
|
||||
|
||||
import (
|
||||
"github.com/go-gormigrate/gormigrate/v2"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// AddGoogleDriveAuthenticated adds the GoogleDriveAuthenticated field to the transfer_configs table
|
||||
func AddGoogleDriveAuthenticated() *gormigrate.Migration {
|
||||
return &gormigrate.Migration{
|
||||
ID: "20240315_add_google_drive_authenticated",
|
||||
Migrate: func(tx *gorm.DB) error {
|
||||
// Add the GoogleDriveAuthenticated column with a default value of false
|
||||
return tx.Exec("ALTER TABLE transfer_configs ADD COLUMN google_drive_authenticated BOOLEAN DEFAULT false").Error
|
||||
},
|
||||
Rollback: func(tx *gorm.DB) error {
|
||||
// Remove the GoogleDriveAuthenticated column
|
||||
return tx.Exec("ALTER TABLE transfer_configs DROP COLUMN google_drive_authenticated").Error
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
package migrations
|
||||
|
||||
import (
|
||||
"github.com/go-gormigrate/gormigrate/v2"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// AddGooglePhotosSupport adds Google Photos related fields to the transfer_configs table
|
||||
func AddGooglePhotosSupport() *gormigrate.Migration {
|
||||
return &gormigrate.Migration{
|
||||
ID: "20240518_add_google_photos_support",
|
||||
Migrate: func(tx *gorm.DB) error {
|
||||
// Add Google Photos source fields
|
||||
if err := tx.Exec("ALTER TABLE transfer_configs ADD COLUMN source_read_only BOOLEAN DEFAULT false").Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if err := tx.Exec("ALTER TABLE transfer_configs ADD COLUMN source_start_year INTEGER DEFAULT 0").Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if err := tx.Exec("ALTER TABLE transfer_configs ADD COLUMN source_include_archived BOOLEAN DEFAULT false").Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Add Google Photos destination fields
|
||||
if err := tx.Exec("ALTER TABLE transfer_configs ADD COLUMN dest_read_only BOOLEAN DEFAULT false").Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if err := tx.Exec("ALTER TABLE transfer_configs ADD COLUMN dest_start_year INTEGER DEFAULT 0").Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if err := tx.Exec("ALTER TABLE transfer_configs ADD COLUMN dest_include_archived BOOLEAN DEFAULT false").Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Add OAuth field
|
||||
return tx.Exec("ALTER TABLE transfer_configs ADD COLUMN use_builtin_auth BOOLEAN DEFAULT true").Error
|
||||
},
|
||||
Rollback: func(tx *gorm.DB) error {
|
||||
// Remove all added columns in reverse order
|
||||
if err := tx.Exec("ALTER TABLE transfer_configs DROP COLUMN use_builtin_auth").Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if err := tx.Exec("ALTER TABLE transfer_configs DROP COLUMN dest_include_archived").Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if err := tx.Exec("ALTER TABLE transfer_configs DROP COLUMN dest_start_year").Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if err := tx.Exec("ALTER TABLE transfer_configs DROP COLUMN dest_read_only").Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if err := tx.Exec("ALTER TABLE transfer_configs DROP COLUMN source_include_archived").Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if err := tx.Exec("ALTER TABLE transfer_configs DROP COLUMN source_start_year").Error; err != nil {
|
||||
return err
|
||||
}
|
||||
return tx.Exec("ALTER TABLE transfer_configs DROP COLUMN source_read_only").Error
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
package migrations
|
||||
|
||||
import (
|
||||
"github.com/go-gormigrate/gormigrate/v2"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// AddMaxConcurrentTransfersColumn adds the max_concurrent_transfers column to transfer_configs table
|
||||
func AddMaxConcurrentTransfersColumn() *gormigrate.Migration {
|
||||
return &gormigrate.Migration{
|
||||
ID: "20250311_add_max_concurrent_transfers",
|
||||
Migrate: func(tx *gorm.DB) error {
|
||||
// Add max_concurrent_transfers column with default value of 4
|
||||
return tx.Exec("ALTER TABLE transfer_configs ADD COLUMN max_concurrent_transfers INTEGER DEFAULT 4").Error
|
||||
},
|
||||
Rollback: func(tx *gorm.DB) error {
|
||||
// Drop the column if needed
|
||||
return tx.Exec("ALTER TABLE transfer_configs DROP COLUMN max_concurrent_transfers").Error
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
package migrations
|
||||
|
||||
import (
|
||||
"github.com/go-gormigrate/gormigrate/v2"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// AddMultiConfigSupport adds support for multiple configurations per job
|
||||
func AddMultiConfigSupport() *gormigrate.Migration {
|
||||
return &gormigrate.Migration{
|
||||
ID: "20250315_add_multi_config_support",
|
||||
Migrate: func(tx *gorm.DB) error {
|
||||
// Add config_ids column to jobs table
|
||||
if err := tx.Exec("ALTER TABLE jobs ADD COLUMN config_ids TEXT").Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Add config_id column to job_histories table
|
||||
if err := tx.Exec("ALTER TABLE job_histories ADD COLUMN config_id INTEGER").Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Add config_id column to file_metadata table
|
||||
if err := tx.Exec("ALTER TABLE file_metadata ADD COLUMN config_id INTEGER").Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Update existing jobs to set the config_ids field to match the current config_id
|
||||
if err := tx.Exec("UPDATE jobs SET config_ids = config_id WHERE config_id > 0").Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
Rollback: func(tx *gorm.DB) error {
|
||||
// Drop the config_id columns from job_histories and file_metadata
|
||||
if err := tx.Exec("ALTER TABLE job_histories DROP COLUMN config_id").Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := tx.Exec("ALTER TABLE file_metadata DROP COLUMN config_id").Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Drop the config_ids column from jobs
|
||||
return tx.Exec("ALTER TABLE jobs DROP COLUMN config_ids").Error
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
package migrations
|
||||
|
||||
import (
|
||||
"github.com/go-gormigrate/gormigrate/v2"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// AddSkipProcessedFilesColumn adds the skip_processed_files column to transfer_configs table
|
||||
func AddSkipProcessedFilesColumn() *gormigrate.Migration {
|
||||
return &gormigrate.Migration{
|
||||
ID: "20250310_add_skip_processed_files",
|
||||
Migrate: func(tx *gorm.DB) error {
|
||||
// Add skip_processed_files column with default value of true
|
||||
return tx.Exec("ALTER TABLE transfer_configs ADD COLUMN skip_processed_files BOOLEAN DEFAULT true").Error
|
||||
},
|
||||
Rollback: func(tx *gorm.DB) error {
|
||||
// Drop the column if needed
|
||||
return tx.Exec("ALTER TABLE transfer_configs DROP COLUMN skip_processed_files").Error
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
package migrations
|
||||
|
||||
import (
|
||||
"github.com/go-gormigrate/gormigrate/v2"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// AddWebhookSupport adds webhook notification fields to the jobs table
|
||||
func AddWebhookSupport() *gormigrate.Migration {
|
||||
return &gormigrate.Migration{
|
||||
ID: "20240618_add_webhook_support",
|
||||
Migrate: func(tx *gorm.DB) error {
|
||||
// Add webhook URL field
|
||||
if err := tx.Exec("ALTER TABLE jobs ADD COLUMN webhook_enabled BOOLEAN DEFAULT false").Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if err := tx.Exec("ALTER TABLE jobs ADD COLUMN webhook_url VARCHAR(255)").Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if err := tx.Exec("ALTER TABLE jobs ADD COLUMN webhook_secret VARCHAR(255)").Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if err := tx.Exec("ALTER TABLE jobs ADD COLUMN webhook_headers TEXT").Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Add notification settings
|
||||
if err := tx.Exec("ALTER TABLE jobs ADD COLUMN notify_on_success BOOLEAN DEFAULT true").Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if err := tx.Exec("ALTER TABLE jobs ADD COLUMN notify_on_failure BOOLEAN DEFAULT true").Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
Rollback: func(tx *gorm.DB) error {
|
||||
// Drop the webhook fields from jobs
|
||||
if err := tx.Exec("ALTER TABLE jobs DROP COLUMN webhook_enabled").Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if err := tx.Exec("ALTER TABLE jobs DROP COLUMN webhook_url").Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if err := tx.Exec("ALTER TABLE jobs DROP COLUMN webhook_secret").Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if err := tx.Exec("ALTER TABLE jobs DROP COLUMN webhook_headers").Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if err := tx.Exec("ALTER TABLE jobs DROP COLUMN notify_on_success").Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if err := tx.Exec("ALTER TABLE jobs DROP COLUMN notify_on_failure").Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -8,16 +8,9 @@ import (
|
||||
// InitMigrations initializes the migrations
|
||||
func InitMigrations(db *gorm.DB) *gormigrate.Gormigrate {
|
||||
migrations := []*gormigrate.Migration{
|
||||
// ... existing migrations
|
||||
AddDeleteAfterTransferColumn(),
|
||||
AddCloudStorageFields(),
|
||||
AddSkipProcessedFilesColumn(),
|
||||
AddMaxConcurrentTransfersColumn(),
|
||||
AddMultiConfigSupport(),
|
||||
UpdateSkipProcessedFilesToNullable(),
|
||||
AddWebhookSupport(),
|
||||
AddGoogleDriveAuthenticated(),
|
||||
AddGooglePhotosSupport(),
|
||||
InitialSchema(),
|
||||
UpdateBuiltinAuthFields(),
|
||||
UpdateGDriveType(),
|
||||
}
|
||||
|
||||
return gormigrate.New(db, gormigrate.DefaultOptions, migrations)
|
||||
|
||||
@@ -1,70 +0,0 @@
|
||||
package migrations
|
||||
|
||||
import (
|
||||
"github.com/go-gormigrate/gormigrate/v2"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// UpdateSkipProcessedFilesToNullable changes the skip_processed_files column to be nullable
|
||||
func UpdateSkipProcessedFilesToNullable() *gormigrate.Migration {
|
||||
return &gormigrate.Migration{
|
||||
ID: "20250515_update_skip_processed_files_to_nullable",
|
||||
Migrate: func(tx *gorm.DB) error {
|
||||
// SQLite specific command - this would need to be adjusted for other databases
|
||||
return tx.Exec("ALTER TABLE transfer_configs RENAME TO transfer_configs_old; " +
|
||||
"CREATE TABLE transfer_configs (" +
|
||||
"id INTEGER PRIMARY KEY AUTOINCREMENT, " +
|
||||
"name VARCHAR(255) NOT NULL, " +
|
||||
"source_type VARCHAR(255) NOT NULL, " +
|
||||
"source_path VARCHAR(255) NOT NULL, " +
|
||||
"source_host VARCHAR(255), " +
|
||||
"source_port INTEGER DEFAULT 22, " +
|
||||
"source_user VARCHAR(255), " +
|
||||
"source_key_file VARCHAR(255), " +
|
||||
"source_bucket VARCHAR(255), " +
|
||||
"source_region VARCHAR(255), " +
|
||||
"source_access_key VARCHAR(255), " +
|
||||
"source_endpoint VARCHAR(255), " +
|
||||
"source_share VARCHAR(255), " +
|
||||
"source_domain VARCHAR(255), " +
|
||||
"source_passive_mode BOOLEAN DEFAULT true, " +
|
||||
"source_client_id VARCHAR(255), " +
|
||||
"source_drive_id VARCHAR(255), " +
|
||||
"source_team_drive VARCHAR(255), " +
|
||||
"file_pattern VARCHAR(255) DEFAULT '*', " +
|
||||
"output_pattern VARCHAR(255), " +
|
||||
"destination_type VARCHAR(255) NOT NULL, " +
|
||||
"destination_path VARCHAR(255) NOT NULL, " +
|
||||
"dest_host VARCHAR(255), " +
|
||||
"dest_port INTEGER DEFAULT 22, " +
|
||||
"dest_user VARCHAR(255), " +
|
||||
"dest_key_file VARCHAR(255), " +
|
||||
"dest_bucket VARCHAR(255), " +
|
||||
"dest_region VARCHAR(255), " +
|
||||
"dest_access_key VARCHAR(255), " +
|
||||
"dest_endpoint VARCHAR(255), " +
|
||||
"dest_share VARCHAR(255), " +
|
||||
"dest_domain VARCHAR(255), " +
|
||||
"dest_passive_mode BOOLEAN DEFAULT true, " +
|
||||
"dest_client_id VARCHAR(255), " +
|
||||
"dest_drive_id VARCHAR(255), " +
|
||||
"dest_team_drive VARCHAR(255), " +
|
||||
"archive_path VARCHAR(255), " +
|
||||
"archive_enabled BOOLEAN DEFAULT false, " +
|
||||
"rclone_flags VARCHAR(255), " +
|
||||
"delete_after_transfer BOOLEAN DEFAULT false, " +
|
||||
"skip_processed_files BOOLEAN DEFAULT true, " + // Keep as BOOLEAN, but now it's nullable
|
||||
"max_concurrent_transfers INTEGER DEFAULT 4, " +
|
||||
"created_by INTEGER, " +
|
||||
"created_at DATETIME, " +
|
||||
"updated_at DATETIME" +
|
||||
"); " +
|
||||
"INSERT INTO transfer_configs SELECT * FROM transfer_configs_old; " +
|
||||
"DROP TABLE transfer_configs_old;").Error
|
||||
},
|
||||
Rollback: func(tx *gorm.DB) error {
|
||||
// No need to rollback as the data structure remains compatible
|
||||
return nil
|
||||
},
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user