Files
bamort/backend/maintenance/handlers.go
T

534 lines
19 KiB
Go
Raw Normal View History

2025-01-03 15:50:56 +01:00
package maintenance
2025-01-02 21:42:20 +01:00
import (
"bamort/config"
2025-01-02 21:42:20 +01:00
"bamort/database"
"bamort/logger"
2025-07-27 23:13:04 +02:00
"bamort/models"
2025-01-02 21:42:20 +01:00
"bamort/user"
2025-07-24 07:39:43 +02:00
"fmt"
2025-01-02 21:42:20 +01:00
"net/http"
2025-07-24 07:39:43 +02:00
"os"
"path/filepath"
"strings"
2025-01-02 21:42:20 +01:00
"github.com/gin-gonic/gin"
2025-07-24 07:39:43 +02:00
"gorm.io/driver/sqlite"
"gorm.io/gorm"
2025-07-29 09:42:53 +02:00
"gorm.io/gorm/clause"
2025-01-02 21:42:20 +01:00
)
2025-07-24 07:39:43 +02:00
// Constants for test data management
var (
testDataDir = database.TestDataDir
preparedTestDB = database.PreparedTestDB
)
func respondWithError(c *gin.Context, status int, message string) {
c.JSON(status, gin.H{"error": message})
}
// migrateAllStructures migrates all database structures to the provided database
func migrateAllStructures(db *gorm.DB) error {
logger.Debug("Starte Migration aller Datenbankstrukturen...")
2025-07-24 07:39:43 +02:00
// Migrate all structures in the correct order
logger.Debug("Migriere Datenbankstrukturen...")
2025-07-24 07:39:43 +02:00
if err := database.MigrateStructure(db); err != nil {
logger.Error("Fehler beim Migrieren der Datenbankstrukturen: %s", err.Error())
2025-07-24 07:39:43 +02:00
return fmt.Errorf("failed to migrate database structures: %w", err)
}
logger.Debug("Migriere Benutzerstrukturen...")
2025-07-24 07:39:43 +02:00
if err := user.MigrateStructure(db); err != nil {
logger.Error("Fehler beim Migrieren der Benutzerstrukturen: %s", err.Error())
2025-07-24 07:39:43 +02:00
return fmt.Errorf("failed to migrate user structures: %w", err)
}
logger.Debug("Migriere GSMaster-Strukturen...")
if err := models.MigrateStructure(db); err != nil {
logger.Error("Fehler beim Migrieren der GSMaster-Strukturen: %s", err.Error())
2025-07-24 07:39:43 +02:00
return fmt.Errorf("failed to migrate gsmaster structures: %w", err)
}
2025-07-29 07:59:40 +02:00
/*if err := importer.MigrateStructure(db); err != nil {
2025-07-24 07:39:43 +02:00
return fmt.Errorf("failed to migrate importer structures: %w", err)
}*/
logger.Info("Migration aller Datenbankstrukturen erfolgreich abgeschlossen")
2025-07-24 07:39:43 +02:00
return nil
}
2025-08-07 09:41:51 +02:00
func migrateDataIfNeeded(db *gorm.DB) error {
logger.Debug("Starte Datenmigration falls erforderlich...")
2025-08-07 09:41:51 +02:00
// Kopiere categorie nach learning_category für Spells, wenn learning_category leer ist
logger.Debug("Migriere Spell Learning Categories...")
2025-08-07 09:41:51 +02:00
err := migrateSpellLearningCategories(db)
if err != nil {
logger.Error("Fehler beim Migrieren der Spell Learning Categories: %s", err.Error())
2025-08-07 09:41:51 +02:00
return fmt.Errorf("failed to migrate spell learning categories: %w", err)
}
logger.Info("Datenmigration erfolgreich abgeschlossen")
2025-08-07 09:41:51 +02:00
return nil
}
// migrateSpellLearningCategories kopiert categorie-Werte in learning_category wenn diese leer sind
func migrateSpellLearningCategories(db *gorm.DB) error {
logger.Debug("Starte Migration der Spell Learning Categories...")
2025-08-07 09:41:51 +02:00
// SQL-Statement um categorie nach learning_category zu kopieren, wo learning_category leer oder NULL ist
sql := `
UPDATE gsm_spells
SET learning_category = category
WHERE (learning_category IS NULL OR learning_category = '')
AND category IS NOT NULL
AND category != ''
`
logger.Debug("Führe SQL-Update aus: %s", strings.ReplaceAll(sql, "\n", " "))
2025-08-07 09:41:51 +02:00
result := db.Exec(sql)
if result.Error != nil {
logger.Error("Fehler beim SQL-Update der Spell Learning Categories: %s", result.Error.Error())
2025-08-07 09:41:51 +02:00
return fmt.Errorf("failed to update spell learning categories: %w", result.Error)
}
// Log der Anzahl der aktualisierten Datensätze
if result.RowsAffected > 0 {
logger.Info("Updated %d spell records with learning_category from categorie", result.RowsAffected)
2025-08-07 09:41:51 +02:00
fmt.Printf("Updated %d spell records with learning_category from categorie\n", result.RowsAffected)
} else {
logger.Debug("Keine Spell-Datensätze benötigten ein Update der learning_category")
2025-08-07 09:41:51 +02:00
}
return nil
}
2025-07-24 07:39:43 +02:00
func MakeTestdataFromLive(c *gin.Context) {
logger.Info("Starte Testdaten-Erstellung aus Live-Datenbank...")
2025-07-29 07:59:40 +02:00
liveDB := database.ConnectDatabase()
if liveDB == nil {
logger.Error("Fehler beim Verbinden mit der Live-Datenbank")
2025-07-29 07:59:40 +02:00
respondWithError(c, http.StatusInternalServerError, "Failed to connect to live database")
2025-01-18 20:59:54 +01:00
return
2025-01-02 21:42:20 +01:00
}
logger.Debug("Erfolgreich mit Live-Datenbank verbunden")
2025-07-24 07:39:43 +02:00
2025-07-29 07:59:40 +02:00
// Live-Datenbank in SQLite-Datei kopieren
backupFile := preparedTestDB
logger.Info("Kopiere Live-Datenbank nach: %s", backupFile)
2025-07-29 07:59:40 +02:00
err := copyLiveDatabaseToFile(liveDB, backupFile)
2025-01-02 21:42:20 +01:00
if err != nil {
logger.Error("Fehler beim Kopieren der Datenbank: %s", err.Error())
2025-07-29 07:59:40 +02:00
respondWithError(c, http.StatusInternalServerError, fmt.Sprintf("Failed to copy database: %v", err))
2025-01-18 20:59:54 +01:00
return
2025-01-02 21:42:20 +01:00
}
2025-07-24 07:39:43 +02:00
logger.Info("Live-Datenbank erfolgreich in Datei kopiert: %s", backupFile)
2025-07-24 07:39:43 +02:00
c.JSON(http.StatusOK, gin.H{
2025-07-29 07:59:40 +02:00
"message": "Live database copied to file successfully",
"test_data_file": backupFile,
2025-07-24 07:39:43 +02:00
})
}
// CopyLiveDatabaseToFile kopiert die MariaDB-Datenbank in eine SQLite-Datei (exported for testing)
func CopyLiveDatabaseToFile(liveDB *gorm.DB, targetFile string) error {
return copyLiveDatabaseToFile(liveDB, targetFile)
}
2025-07-29 07:59:40 +02:00
// copyLiveDatabaseToFile kopiert die MariaDB-Datenbank in eine SQLite-Datei
func copyLiveDatabaseToFile(liveDB *gorm.DB, targetFile string) error {
logger.Debug("Starte Kopiervorgang von Live-DB nach SQLite-Datei: %s", targetFile)
2025-07-29 07:59:40 +02:00
// Verzeichnis erstellen falls es nicht existiert
dir := filepath.Dir(targetFile)
logger.Debug("Erstelle Zielverzeichnis falls erforderlich: %s", dir)
2025-07-29 07:59:40 +02:00
if err := os.MkdirAll(dir, 0755); err != nil {
logger.Error("Fehler beim Erstellen des Verzeichnisses %s: %s", dir, err.Error())
2025-07-29 07:59:40 +02:00
return fmt.Errorf("failed to create directory: %w", err)
2025-07-24 07:39:43 +02:00
}
2025-07-29 07:59:40 +02:00
// Backup der existierenden Datei erstellen
if _, err := os.Stat(targetFile); err == nil {
backupFile := targetFile + ".backup"
logger.Debug("Existierende Datei gefunden, erstelle Backup: %s", backupFile)
2025-07-29 07:59:40 +02:00
os.Remove(backupFile) // Alte Backup entfernen
if err := os.Rename(targetFile, backupFile); err != nil {
logger.Error("Fehler beim Erstellen des Backups %s: %s", backupFile, err.Error())
2025-07-29 07:59:40 +02:00
return fmt.Errorf("failed to backup existing file: %w", err)
}
logger.Debug("Backup erfolgreich erstellt")
2025-07-24 07:39:43 +02:00
}
2025-07-29 07:59:40 +02:00
// SQLite-Zieldatenbank erstellen
logger.Debug("Erstelle neue SQLite-Zieldatenbank: %s", targetFile)
2025-07-29 07:59:40 +02:00
targetDB, err := gorm.Open(sqlite.Open(targetFile), &gorm.Config{})
2025-07-24 07:39:43 +02:00
if err != nil {
logger.Error("Fehler beim Erstellen der SQLite-Zieldatenbank: %s", err.Error())
2025-07-29 07:59:40 +02:00
return fmt.Errorf("failed to create target SQLite database: %w", err)
2025-07-24 07:39:43 +02:00
}
2025-07-29 07:59:40 +02:00
defer func() {
if sqlDB, err := targetDB.DB(); err == nil {
logger.Debug("Schließe SQLite-Datenbankverbindung")
2025-07-29 07:59:40 +02:00
sqlDB.Close()
}
}()
2025-07-24 07:39:43 +02:00
2025-07-29 07:59:40 +02:00
// Strukturen in SQLite-DB migrieren
logger.Debug("Migriere Strukturen in SQLite-Datenbank...")
2025-07-29 07:59:40 +02:00
if err := migrateAllStructures(targetDB); err != nil {
logger.Error("Fehler beim Migrieren der Strukturen in SQLite: %s", err.Error())
2025-07-29 07:59:40 +02:00
return fmt.Errorf("failed to migrate structures to SQLite: %w", err)
2025-07-24 07:39:43 +02:00
}
2025-07-29 07:59:40 +02:00
// Daten von MariaDB zu SQLite kopieren
logger.Info("Kopiere Daten von MariaDB zu SQLite...")
2025-07-29 07:59:40 +02:00
if err := copyMariaDBToSQLite(liveDB, targetDB); err != nil {
logger.Error("Fehler beim Kopieren der Daten von MariaDB zu SQLite: %s", err.Error())
2025-07-29 07:59:40 +02:00
return fmt.Errorf("failed to copy data from MariaDB to SQLite: %w", err)
2025-07-24 07:39:43 +02:00
}
logger.Info("Kopiervorgang erfolgreich abgeschlossen")
2025-07-29 07:59:40 +02:00
return nil
}
2025-07-24 07:39:43 +02:00
2025-07-29 07:59:40 +02:00
// copyMariaDBToSQLite kopiert alle Daten von MariaDB zu SQLite
func copyMariaDBToSQLite(mariaDB, sqliteDB *gorm.DB) error {
logger.Debug("Starte Kopiervorgang aller Daten von MariaDB zu SQLite...")
2025-07-29 07:59:40 +02:00
// Vollständige Liste aller Strukturen mit GORM-Tags in der richtigen Reihenfolge
// (Basis-Tabellen zuerst wegen Foreign Key-Abhängigkeiten)
tables := []interface{}{
// Basis-Strukturen (keine Abhängigkeiten)
&user.User{},
// Learning Costs System - Basis
&models.Source{},
&models.CharacterClass{},
&models.SkillCategory{},
&models.SkillDifficulty{},
&models.SpellSchool{},
// Learning Costs System - Abhängige Tabellen
&models.ClassCategoryEPCost{},
&models.ClassSpellSchoolEPCost{},
&models.SpellLevelLECost{},
&models.SkillCategoryDifficulty{},
&models.SkillImprovementCost{},
// GSMaster Basis-Daten
2025-07-30 05:40:13 +02:00
//&models.LookupList{}, // Basis für Skills, Spells, Equipment
2025-07-29 07:59:40 +02:00
&models.Skill{},
&models.WeaponSkill{},
&models.Spell{},
&models.Equipment{},
&models.Weapon{},
&models.Container{},
&models.Transportation{},
&models.Believe{},
// Charaktere (Basis)
&models.Char{},
// Charakter-Eigenschaften (abhängig von Char)
&models.Eigenschaft{},
&models.Lp{},
&models.Ap{},
&models.B{},
&models.Merkmale{},
&models.Erfahrungsschatz{},
&models.Bennies{},
&models.Vermoegen{},
// Charakter-Skills (abhängig von Char und Skills)
&models.SkFertigkeit{},
&models.SkWaffenfertigkeit{},
&models.SkAngeboreneFertigkeit{},
&models.SkZauber{},
// Charakter-Equipment (abhängig von Char und Equipment)
&models.EqAusruestung{},
&models.EqWaffe{},
&models.EqContainer{},
// View-Strukturen ohne eigene Tabellen werden nicht kopiert:
// SkillLearningInfo, SpellLearningInfo, CharList, FeChar, etc.
}
logger.Info("Kopiere Daten für %d Tabellen...", len(tables))
for i, model := range tables {
logger.Debug("Kopiere Tabelle %d/%d: %T", i+1, len(tables), model)
2025-07-29 07:59:40 +02:00
if err := copyTableData(mariaDB, sqliteDB, model); err != nil {
logger.Error("Fehler beim Kopieren der Tabellendaten für %T: %s", model, err.Error())
2025-07-29 07:59:40 +02:00
return fmt.Errorf("failed to copy table data for %T: %w", model, err)
}
2025-07-24 07:39:43 +02:00
}
logger.Info("Alle Tabellendaten erfolgreich kopiert")
2025-07-29 07:59:40 +02:00
return nil
2025-07-24 07:39:43 +02:00
}
2025-07-29 07:59:40 +02:00
// copyTableData kopiert alle Daten einer Tabelle von MariaDB zu SQLite
func copyTableData(sourceDB, targetDB *gorm.DB, model interface{}) error {
tableName := fmt.Sprintf("%T", model)
logger.Debug("Starte Kopiervorgang für Tabelle: %s", tableName)
2025-07-29 07:59:40 +02:00
// Anzahl der Datensätze prüfen
2025-07-24 07:39:43 +02:00
var count int64
err := sourceDB.Model(model).Count(&count).Error
if err != nil {
// If table doesn't exist, skip silently (useful for testing with partial schemas)
if isTableNotExistError(err) {
logger.Debug("Tabelle %s existiert nicht in der Quelle, überspringe", tableName)
return nil
}
logger.Error("Fehler beim Zählen der Datensätze für %s: %s", tableName, err.Error())
2025-07-29 07:59:40 +02:00
return err
2025-07-24 07:39:43 +02:00
}
if count == 0 {
logger.Debug("Tabelle %s ist leer, keine Daten zu kopieren", tableName)
2025-07-29 07:59:40 +02:00
return nil // Keine Daten zu kopieren
2025-07-24 07:39:43 +02:00
}
logger.Debug("Kopiere %d Datensätze für Tabelle %s", count, tableName)
2025-07-29 07:59:40 +02:00
// Daten in Blöcken kopieren (für große Tabellen)
2025-07-24 07:39:43 +02:00
batchSize := 100
totalBatches := (int(count) + batchSize - 1) / batchSize
2025-07-24 07:39:43 +02:00
for offset := 0; offset < int(count); offset += batchSize {
batchNum := (offset / batchSize) + 1
logger.Debug("Kopiere Batch %d/%d für %s (Offset: %d, Limit: %d)", batchNum, totalBatches, tableName, offset, batchSize)
2025-07-24 07:39:43 +02:00
var records []map[string]interface{}
2025-07-29 07:59:40 +02:00
// Batch aus MariaDB lesen
if err := sourceDB.Model(model).Offset(offset).Limit(batchSize).Find(&records).Error; err != nil {
logger.Error("Fehler beim Lesen von Batch %d für %s: %s", batchNum, tableName, err.Error())
2025-07-29 07:59:40 +02:00
return err
2025-07-24 07:39:43 +02:00
}
if len(records) == 0 {
logger.Debug("Keine weiteren Datensätze für %s", tableName)
2025-07-24 07:39:43 +02:00
break
}
2025-07-29 09:42:53 +02:00
// Batch in SQLite einfügen mit Konflikt-Behandlung
// Verwende Clauses.OnConflict um bestehende Datensätze zu ersetzen
if err := targetDB.Model(model).Clauses(clause.OnConflict{
UpdateAll: true,
}).Create(&records).Error; err != nil {
logger.Error("Fehler beim Einfügen von Batch %d für %s: %s", batchNum, tableName, err.Error())
2025-07-29 07:59:40 +02:00
return err
2025-07-24 07:39:43 +02:00
}
logger.Debug("Batch %d/%d für %s erfolgreich kopiert (%d Datensätze)", batchNum, totalBatches, tableName, len(records))
2025-07-24 07:39:43 +02:00
}
logger.Info("Tabelle %s erfolgreich kopiert (%d Datensätze total)", tableName, count)
2025-07-24 07:39:43 +02:00
return nil
}
// isTableNotExistError checks if the error indicates a table doesn't exist
func isTableNotExistError(err error) bool {
errorMsg := err.Error()
return strings.Contains(errorMsg, "no such table") ||
strings.Contains(errorMsg, "doesn't exist") ||
strings.Contains(errorMsg, "Table") && strings.Contains(errorMsg, "doesn't exist")
}
2025-07-24 07:39:43 +02:00
// LoadPredefinedTestDataFromFile loads predefined test data from a specific file into the provided database
func LoadPredefinedTestDataFromFile(targetDB *gorm.DB, dataFile string) error {
logger.Debug("Lade vordefinierte Testdaten aus Datei: %s", dataFile)
2025-07-24 07:39:43 +02:00
// Check if file exists
if _, err := os.Stat(dataFile); os.IsNotExist(err) {
logger.Error("Vordefinierte Testdaten-Datei nicht gefunden: %s", dataFile)
2025-07-24 07:39:43 +02:00
return fmt.Errorf("predefined test data file not found: %s", dataFile)
}
logger.Debug("Testdaten-Datei existiert: %s", dataFile)
2025-07-24 07:39:43 +02:00
// Migrate structures to target DB
logger.Debug("Migriere Strukturen in Zieldatenbank...")
2025-07-24 07:39:43 +02:00
err := migrateAllStructures(targetDB)
if err != nil {
logger.Error("Fehler beim Migrieren der Strukturen: %s", err.Error())
2025-07-24 07:39:43 +02:00
return fmt.Errorf("failed to migrate structures: %w", err)
}
// Copy data from file database to target database
logger.Info("Kopiere Testdaten in Zieldatenbank...")
2025-07-24 07:39:43 +02:00
err = copyDataFromFileToMemory(dataFile, targetDB)
if err != nil {
logger.Error("Fehler beim Kopieren der Testdaten: %s", err.Error())
2025-07-24 07:39:43 +02:00
return fmt.Errorf("failed to copy test data to database: %w", err)
}
logger.Info("Vordefinierte Testdaten erfolgreich geladen")
2025-07-24 07:39:43 +02:00
return nil
}
// LoadPredefinedTestData creates a new in-memory test database and loads predefined test data into it (HTTP handler)
// Todo I think this don't need to be a handler, but can be called directly
func LoadPredefinedTestData(c *gin.Context) {
testDataFile := filepath.Join(testDataDir, "predefined_test_data.db")
// Check if file exists
if _, err := os.Stat(testDataFile); os.IsNotExist(err) {
respondWithError(c, http.StatusNotFound, "Predefined test data file not found. Run MakeTestdataFromLive first.")
2025-01-18 20:59:54 +01:00
return
2025-01-02 21:42:20 +01:00
}
2025-07-24 07:39:43 +02:00
// Create new in-memory test database using SetupTestDB
database.SetupTestDB(true)
// Load test data using the predefined test data file (includes migrations)
err := LoadPredefinedTestDataFromFile(database.DB, preparedTestDB)
2025-01-02 21:42:20 +01:00
if err != nil {
2025-07-24 07:39:43 +02:00
respondWithError(c, http.StatusInternalServerError, "Failed to load test data: "+err.Error())
2025-01-18 20:59:54 +01:00
return
2025-01-02 21:42:20 +01:00
}
2025-07-24 07:39:43 +02:00
// Get statistics about the loaded data
stats, err := getTestDataStatistics(database.DB)
2025-01-02 21:42:20 +01:00
if err != nil {
2025-07-24 07:39:43 +02:00
respondWithError(c, http.StatusInternalServerError, "Failed to get test data statistics: "+err.Error())
return
}
c.JSON(http.StatusOK, gin.H{
"message": "Predefined test data loaded successfully into in-memory database",
"test_data_file": testDataFile,
"statistics": stats,
})
}
// copyDataFromFileToMemory copies data from a SQLite file to an in-memory database
func copyDataFromFileToMemory(sourceFile string, targetDB *gorm.DB) error {
logger.Debug("Kopiere Daten von SQLite-Datei in Memory-Datenbank: %s", sourceFile)
2025-07-24 07:39:43 +02:00
// Copy all tables using ATTACH and INSERT
attachSQL := fmt.Sprintf("ATTACH DATABASE '%s' AS source", sourceFile)
logger.Debug("Hänge Quell-Datenbank an: %s", attachSQL)
2025-07-24 07:39:43 +02:00
if err := targetDB.Exec(attachSQL).Error; err != nil {
logger.Error("Fehler beim Anhängen der Quell-Datenbank: %s", err.Error())
2025-07-24 07:39:43 +02:00
return fmt.Errorf("failed to attach source database: %w", err)
}
// Get list of tables from source database
logger.Debug("Ermittle Tabellenliste aus Quell-Datenbank...")
2025-07-24 07:39:43 +02:00
var tables []string
if err := targetDB.Raw("SELECT name FROM source.sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%'").Scan(&tables).Error; err != nil {
logger.Error("Fehler beim Ermitteln der Tabellenliste: %s", err.Error())
2025-07-24 07:39:43 +02:00
return fmt.Errorf("failed to get table list: %w", err)
}
logger.Info("Gefundene Tabellen zum Kopieren: %d (%v)", len(tables), tables)
2025-07-24 07:39:43 +02:00
// Copy each table
for i, table := range tables {
logger.Debug("Kopiere Tabelle %d/%d: %s", i+1, len(tables), table)
2025-07-24 07:39:43 +02:00
copySQL := fmt.Sprintf("INSERT OR REPLACE INTO main.%s SELECT * FROM source.%s", table, table)
if err := targetDB.Exec(copySQL).Error; err != nil {
logger.Error("Fehler beim Kopieren der Tabelle %s: %s", table, err.Error())
2025-07-24 07:39:43 +02:00
return fmt.Errorf("failed to copy table %s: %w", table, err)
}
logger.Debug("Tabelle %s erfolgreich kopiert", table)
2025-07-24 07:39:43 +02:00
}
// Detach the source database
logger.Debug("Löse Quell-Datenbank-Verbindung...")
2025-07-24 07:39:43 +02:00
if err := targetDB.Exec("DETACH DATABASE source").Error; err != nil {
logger.Error("Fehler beim Lösen der Quell-Datenbank-Verbindung: %s", err.Error())
2025-07-24 07:39:43 +02:00
return fmt.Errorf("failed to detach source database: %w", err)
}
logger.Info("Daten erfolgreich von Datei in Memory-Datenbank kopiert")
2025-07-24 07:39:43 +02:00
return nil
}
// getTestDataStatistics returns statistics about the test database
func getTestDataStatistics(db *gorm.DB) (map[string]int64, error) {
stats := make(map[string]int64)
// Count records in each table
tables := map[string]interface{}{
"users": &user.User{},
2025-07-28 21:35:29 +02:00
"characters": &models.Char{},
2025-07-27 23:13:04 +02:00
"gsmaster_skills": &models.Skill{},
2025-07-27 23:50:19 +02:00
"gsmaster_spells": &models.Spell{},
2025-07-28 18:56:45 +02:00
"gsmaster_equipment": &models.Equipment{},
2025-07-28 22:08:19 +02:00
"skills_fertigkeiten": &models.SkFertigkeit{},
"skills_waffenfertigkeiten": &models.SkWaffenfertigkeit{},
"skills_zauber": &models.SkZauber{},
"equipment_ausruestung": &models.EqAusruestung{},
"equipment_waffen": &models.EqWaffe{},
2025-07-24 07:39:43 +02:00
}
for name, model := range tables {
var count int64
if err := db.Model(model).Count(&count).Error; err != nil {
return stats, fmt.Errorf("failed to count %s: %w", name, err)
}
stats[name] = count
}
return stats, nil
}
func SetupCheck(c *gin.Context) {
logger.Info("Starte Setup-Check...")
2025-07-24 07:39:43 +02:00
db := database.ConnectDatabase()
if db == nil {
logger.Error("Fehler beim Verbinden mit der Datenbank für Setup-Check")
2025-07-24 07:39:43 +02:00
respondWithError(c, http.StatusInternalServerError, "Failed to connect to DataBase")
2025-01-18 20:59:54 +01:00
return
2025-01-02 21:42:20 +01:00
}
logger.Debug("Erfolgreich mit Datenbank für Setup-Check verbunden")
logger.Debug("Führe Strukturmigration durch...")
2025-07-24 07:39:43 +02:00
err := migrateAllStructures(db)
2025-01-02 21:42:20 +01:00
if err != nil {
logger.Error("Fehler bei der Strukturmigration: %s", err.Error())
2025-07-24 07:39:43 +02:00
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
2025-01-18 20:59:54 +01:00
return
2025-01-02 21:42:20 +01:00
}
2025-08-07 09:41:51 +02:00
logger.Debug("Führe Datenmigration durch...")
2025-08-07 09:41:51 +02:00
err = migrateDataIfNeeded(db)
if err != nil {
logger.Error("Fehler bei der Datenmigration: %s", err.Error())
2025-08-07 09:41:51 +02:00
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to migrate data: " + err.Error()})
return
}
logger.Info("Setup-Check erfolgreich abgeschlossen")
2025-01-18 20:59:54 +01:00
c.JSON(http.StatusOK, gin.H{"message": "Setup Check OK"})
2025-01-02 21:42:20 +01:00
}
2025-07-29 19:21:58 +02:00
func ReconnectDataBase(c *gin.Context) {
logger.Info("Führe Datenbank-Reconnect durch...")
2025-07-29 19:21:58 +02:00
db := database.ConnectDatabase()
if db == nil {
logger.Error("Fehler beim Reconnect zur Datenbank")
respondWithError(c, http.StatusInternalServerError, "Failed to reconnect to DataBase")
2025-07-29 19:21:58 +02:00
return
}
logger.Info("Datenbank-Reconnect erfolgreich")
c.JSON(http.StatusOK, gin.H{"message": "Database reconnected successfully"})
}
2025-07-29 19:21:58 +02:00
func ReloadENV(c *gin.Context) {
logger.Info("Starte Reload der Umgebungsvariablen...")
// Reload the environment variables
config.LoadConfig()
c.JSON(http.StatusOK, gin.H{"message": "Environment variables reloaded successfully"})
2025-07-29 19:21:58 +02:00
}