sozsoft-platform/api/src/Sozsoft.Platform.HttpApi.Host/Controllers/SetupController.cs
2026-05-03 22:50:51 +03:00

168 lines
5.4 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Diagnostics;
using System.IO;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
namespace Sozsoft.Platform.Controllers;
/// <summary>
/// DB hazır olduğunda bile /setup sayfasından migration çalıştırmaya olanak tanır.
/// </summary>
[Route("api/setup")]
[Authorize(Roles = "admin")]
public class SetupController : ControllerBase
{
private readonly IConfiguration _configuration;
private readonly IHostEnvironment _env;
public SetupController(
IConfiguration configuration,
IHostEnvironment env)
{
_configuration = configuration;
_env = env;
}
[HttpGet("status")]
[AllowAnonymous]
public IActionResult Status()
{
return Ok(new { dbExists = SetupAppRunner.DatabaseIsReady(_configuration) });
}
[HttpPost("migrate")]
public async Task Migrate(CancellationToken ct)
{
Response.ContentType = "text/event-stream; charset=utf-8";
Response.Headers["Cache-Control"] = "no-cache, no-store";
Response.Headers["X-Accel-Buffering"] = "no";
await Response.Body.FlushAsync(ct);
async Task Send(string level, string message)
{
try
{
var payload = JsonSerializer.Serialize(new { level, message });
await Response.WriteAsync($"data: {payload}\n\n", ct);
await Response.Body.FlushAsync(ct);
}
catch { }
}
var migratorPath = _configuration["Setup:MigratorPath"]
?? Path.GetFullPath(Path.Combine(_env.ContentRootPath, "..", "Sozsoft.Platform.DbMigrator"));
await Send("info", "Database migration and seeding are being initiated...");
await Send("info", $"Migrator path: {migratorPath}");
var extraArgs = _configuration["Setup:MigratorArgs"] ?? "--Seed=true";
string fileName;
string arguments;
string workingDirectory;
if (migratorPath.EndsWith(".dll", StringComparison.OrdinalIgnoreCase) && System.IO.File.Exists(migratorPath))
{
fileName = "dotnet";
arguments = $"\"{migratorPath}\" {extraArgs}";
workingDirectory = Path.GetDirectoryName(migratorPath)!;
}
else if (Directory.Exists(migratorPath))
{
var dllFiles = Directory.GetFiles(migratorPath, "*.DbMigrator.dll", SearchOption.TopDirectoryOnly);
if (dllFiles.Length == 0)
dllFiles = Directory.GetFiles(migratorPath, "*Migrator*.dll", SearchOption.TopDirectoryOnly);
if (dllFiles.Length > 0)
{
fileName = "dotnet";
arguments = $"\"{dllFiles[0]}\" {extraArgs}";
workingDirectory = migratorPath;
}
else
{
fileName = "dotnet";
arguments = $"run --project \"{migratorPath}\" -- {extraArgs}";
workingDirectory = migratorPath;
}
}
else
{
await Send("error", $"Migrator yolu bulunamadı veya geçersiz: {migratorPath}");
await Send("done", "Hata ile sonlandı.");
return;
}
await Send("info", $"Çalıştırılıyor: {fileName} {arguments}");
Process? process = null;
try
{
process = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = fileName,
Arguments = arguments,
RedirectStandardOutput = true,
RedirectStandardError = true,
UseShellExecute = false,
CreateNoWindow = true,
WorkingDirectory = workingDirectory,
}
};
process.Start();
async Task ReadStream(StreamReader reader, string level)
{
try
{
while (!reader.EndOfStream)
{
var line = await reader.ReadLineAsync(ct);
if (line != null) await Send(level, line);
}
}
catch (OperationCanceledException) { }
}
await Task.WhenAll(
ReadStream(process.StandardOutput, "info"),
ReadStream(process.StandardError, "warn"));
await process.WaitForExitAsync(ct);
if (process.ExitCode == 0)
{
await Send("success", "Migration ve seed başarıyla tamamlandı.");
await Send("done", "Tamamlandı.");
}
else
{
await Send("error", $"Migration başarısız. Çıkış kodu: {process.ExitCode}");
await Send("done", "Hata ile sonlandı.");
}
}
catch (OperationCanceledException)
{
await Send("warn", "Migration isteği iptal edildi.");
}
catch (Exception ex)
{
await Send("error", $"Migration hatası: {ex.Message}");
await Send("done", "Hata ile sonlandı.");
}
finally
{
process?.Dispose();
}
}
}