Files
watcher/Watcher/Controllers/DatabaseController.cs
2025-09-12 11:50:04 +02:00

200 lines
7.4 KiB
C#
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System.Runtime.InteropServices;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Data.Sqlite;
using Microsoft.EntityFrameworkCore;
using System.IO;
using System.Diagnostics;
namespace Watcher.Controllers
{
[Authorize]
public class DatabaseController : Controller
{
// Backup Infos
private readonly string _dbPath = Path.Combine(Directory.GetCurrentDirectory(), "persistence", "watcher.db");
private readonly string _backupFolder = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "downloads", "sqlite");
// Services
private readonly ILogger<DatabaseController> _logger;
public class DumpFileInfo
{
public string? FileName { get; set; }
public long SizeKb { get; set; }
public DateTime Created { get; set; }
}
public DatabaseController(IWebHostEnvironment env, ILogger<DatabaseController> logger)
{
_logger = logger;
_backupFolder = Path.Combine(env.WebRootPath, "downloads", "sqlite");
if (!Directory.Exists(_backupFolder))
{
_logger.LogInformation("Backup-Directory neu erstellt");
Directory.CreateDirectory(_backupFolder);
}
else
{
_logger.LogInformation("Backup-Directory existiert bereits");
}
}
[HttpPost("/maintenance/sqlite-dump")]
public IActionResult CreateSqlDump()
{
try
{
// Zielordner sicherstellen
if (!Directory.Exists(_backupFolder))
Directory.CreateDirectory(_backupFolder);
// Ziel-Dateiname z.B. mit Zeitstempel
var timestamp = DateTime.Now.ToString("yyyyMMdd_HHmmss");
var dumpFileName = $"watcher_dump_{timestamp}.sql";
var dumpFilePath = Path.Combine(_backupFolder, dumpFileName);
using var connection = new SqliteConnection($"Data Source={_dbPath}");
connection.Open();
using var command = connection.CreateCommand();
command.CommandText = "SELECT sql FROM sqlite_master WHERE type='table' AND sql IS NOT NULL;";
using var writer = new StreamWriter(dumpFilePath);
// Write schema
using (var schemaCmd = connection.CreateCommand())
{
schemaCmd.CommandText = "SELECT sql FROM sqlite_master WHERE type='table'";
using var reader = schemaCmd.ExecuteReader();
while (reader.Read())
{
writer.WriteLine(reader.GetString(0) + ";");
}
}
// Write content
using (var tableCmd = connection.CreateCommand())
{
tableCmd.CommandText = "SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%'";
using var tableReader = tableCmd.ExecuteReader();
while (tableReader.Read())
{
var tableName = tableReader.GetString(0);
using var dataCmd = connection.CreateCommand();
dataCmd.CommandText = $"SELECT * FROM {tableName}";
using var dataReader = dataCmd.ExecuteReader();
while (dataReader.Read())
{
var columns = new string[dataReader.FieldCount];
var values = new string[dataReader.FieldCount];
for (int i = 0; i < dataReader.FieldCount; i++)
{
columns[i] = dataReader.GetName(i);
var val = dataReader.GetValue(i);
values[i] = val == null || val == DBNull.Value
? "NULL"
: $"'{val.ToString().Replace("'", "''")}'";
}
writer.WriteLine($"INSERT INTO {tableName} ({string.Join(",", columns)}) VALUES ({string.Join(",", values)});");
}
}
}
writer.Flush();
//return Ok($"Dump erfolgreich erstellt: {dumpFileName}");
TempData["DumpMessage"] = "SQLite-Dump erfolgreich erstellt.";
_logger.LogInformation("SQLite-Dump erfolgreich erstellt.");
return RedirectToAction("Settings", "System");
}
catch (Exception ex)
{
//return StatusCode(500, $"Fehler beim Erstellen des Dumps: {ex.Message}");
TempData["DumpError"] = $"Fehler beim Erstellen des Dumps: {ex.Message}";
_logger.LogError("Fehler beim Erstellen des Dumps: {message}", ex.Message);
return RedirectToAction("UserSettings", "User");
}
}
public IActionResult ManageSqlDumps()
{
var files = Directory.GetFiles(_backupFolder, "*.sql")
.Select(f => new DumpFileInfo
{
FileName = Path.GetFileName(f),
SizeKb = new FileInfo(f).Length / 1024,
Created = System.IO.File.GetCreationTime(f)
})
.OrderByDescending(f => f.Created)
.ToList();
return View(files);
}
[HttpPost]
public IActionResult Delete(string fileName)
{
var filePath = Path.Combine(_backupFolder, fileName);
if (System.IO.File.Exists(filePath))
{
System.IO.File.Delete(filePath);
TempData["Success"] = $"Backup {fileName} wurde gelöscht.";
}
return RedirectToAction("ManageSqlDumps");
}
// 🔹 4. Dump wiederherstellen
[HttpPost]
public IActionResult Restore(string fileName)
{
var filePath = Path.Combine(_backupFolder, fileName);
if (!System.IO.File.Exists(filePath))
{
TempData["Error"] = "Dump nicht gefunden.";
return RedirectToAction("ManageSqlDumps");
}
try
{
var dbPath = Path.Combine(Directory.GetCurrentDirectory(), "persistence", "watcher.db"); // anpassen
// Leere Datenbank
System.IO.File.WriteAllText(dbPath, "");
var psi = new ProcessStartInfo
{
FileName = "sqlite3",
Arguments = $"\"{dbPath}\" \".read \\\"{filePath}\\\"\"",
RedirectStandardOutput = true,
RedirectStandardError = true,
UseShellExecute = false,
CreateNoWindow = true,
};
using var proc = Process.Start(psi);
proc.WaitForExit();
TempData["Success"] = $"Backup {fileName} wurde wiederhergestellt.";
}
catch (Exception ex)
{
TempData["Error"] = $"Fehler beim Wiederherstellen: {ex.Message}";
}
return RedirectToAction("ManageSqlDumps");
}
}
}