200 lines
7.4 KiB
C#
200 lines
7.4 KiB
C#
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");
|
||
}
|
||
}
|
||
|
||
} |