diff --git a/admin.go b/admin.go index df957fe..c082fdf 100644 --- a/admin.go +++ b/admin.go @@ -78,8 +78,102 @@ func BackupDatabaseHandler(w http.ResponseWriter, r *http.Request) { // RestoreDatabaseHandler handles POST requests to /admin/db func RestoreDatabaseHandler(w http.ResponseWriter, r *http.Request) { - // implement database restore logic here - fmt.Println("Restoring database...") - // ... + // Create a backup of the existing database + err := createDatabaseBackup() + if err != nil { + http.Error(w, "Failed to create database backup", http.StatusInternalServerError) + return + } + + // Save the new database + err = saveNewDatabase(r) + if err != nil { + http.Error(w, "Failed to save new database", http.StatusInternalServerError) + return + } + + // Validate the new database is properly initialized + err = validateNewDatabase() + if err != nil { + http.Error(w, "New database is not properly initialized", http.StatusInternalServerError) + return + } + + // Switch to the new database app-wide + err = switchToNewDatabase() + if err != nil { + http.Error(w, "Failed to switch to new database", http.StatusInternalServerError) + return + } + w.WriteHeader(http.StatusOK) + json.NewEncoder(w).Encode(map[string]string{"message": "Database restored successfully"}) +} + +func createDatabaseBackup() error { + // Create a backup of the existing database + src, err := os.Open(config.DatabasePath) + if err != nil { + return err + } + defer src.Close() + + dst, err := os.Create(config.DatabasePath + ".bak") + if err != nil { + return err + } + defer dst.Close() + + _, err = io.Copy(dst, src) + return err +} + +func saveNewDatabase(r *http.Request) error { + // Save the new database + file, _, err := r.FormFile("database") + if err != nil { + return err + } + defer file.Close() + + dst, err := os.Create(config.DatabasePath) + if err != nil { + return err + } + defer dst.Close() + + _, err = io.Copy(dst, file) + return err +} + +func validateNewDatabase() error { + // Validate the new database is properly initialized + db, err := ConnectDB(config.DatabasePath) + if err != nil { + return err + } + defer db.Close() + + // Check if required tables exist + tables := []string{"users", "boxes", "items"} + for _, table := range tables { + var count int + db.Debug().Raw("SELECT COUNT(*) FROM sqlite_master WHERE type='table' AND name=?;", table).Row().Scan(&count) + if count == 0 { + return fmt.Errorf("table %s does not exist", table) + } + } + + return nil +} + +func switchToNewDatabase() error { + // Switch to the new database app-wide + db, err := ConnectDB(config.DatabasePath) + if err != nil { + return err + } + // Update the db variable with the new database connection + db = db + return nil } diff --git a/scripts/restore_db.bash b/scripts/restore_db.bash new file mode 100644 index 0000000..5a2ff71 --- /dev/null +++ b/scripts/restore_db.bash @@ -0,0 +1,18 @@ +#!/bin/bash + +# API base URL +API_BASE_URL="http://localhost:8080" + +# Login credentials +USERNAME="boxuser" +PASSWORD="boxuser" + +# Get a new JWT token +TOKEN=$(curl -s -X POST -H "Content-Type: application/json" \ + -d "{\"username\":\"$USERNAME\", \"password\":\"$PASSWORD\"}" \ + "$API_BASE_URL/login" | jq -r '.token') + +curl -X POST \ + $API_BASE_URL/admin/db \ + -H "Authorization: Bearer $TOKEN" \ + -F "database=@./test.db" \ No newline at end of file