Files
Aberwyn/Aberwyn/Controllers/SetupController.cs
Elias Jansson 77d3c741b1
All checks were successful
continuous-integration/drone/push Build is passing
Stringbuilder to handle passwords
2025-06-03 22:35:37 +02:00

171 lines
6.4 KiB
C#

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.EntityFrameworkCore;
using MySql.Data.MySqlClient;
using System.Text.Json;
using Aberwyn.Data;
using Aberwyn.Models;
namespace Aberwyn.Controllers
{
[Route("setup")]
public class SetupController : Controller
{
private readonly IWebHostEnvironment _env;
private readonly ILogger<SetupController> _logger;
public SetupController(IWebHostEnvironment env, ILogger<SetupController> logger)
{
_env = env;
_logger = logger;
}
public override void OnActionExecuting(ActionExecutingContext context)
{
ViewBag.IsSetupMode = true;
base.OnActionExecuting(context);
}
[HttpGet]
public IActionResult Index() => View(new SetupSettings());
[Authorize(Roles = "Admin")]
[HttpPost("reset")]
public IActionResult Reset()
{
var path = Path.Combine(_env.ContentRootPath, "infrastructure", "setup.json");
var resetSettings = new SetupSettings
{
IsConfigured = false,
DbHost = "",
DbPort = 3306,
DbName = "",
DbUser = "",
DbPassword = "",
AdminUsername = "admin",
AdminEmail = "admin@localhost",
AdminPassword = "Admin123!"
};
var json = JsonSerializer.Serialize(resetSettings, new JsonSerializerOptions { WriteIndented = true });
System.IO.File.WriteAllText(path, json);
return RedirectToAction("Index");
}
[HttpPost("")]
public async Task<IActionResult> Setup([FromBody] SetupSettings model)
{
if (!ModelState.IsValid)
{
var allErrors = ModelState
.Where(e => e.Value.Errors.Count > 0)
.Select(e => new { Field = e.Key, Errors = e.Value.Errors.Select(x => x.ErrorMessage) });
return BadRequest(new { error = "Modellen är ogiltig", details = allErrors });
}
try
{
// Bygg connection string säkert
var baseConnBuilder = new MySqlConnectionStringBuilder
{
Server = model.DbHost,
Port = (uint)model.DbPort,
UserID = model.DbUser,
Password = model.DbPassword,
Database = "information_schema"
};
// Kontrollera om databasen redan finns
using (var conn = new MySqlConnection(baseConnBuilder.ConnectionString))
{
conn.Open();
var cmd = new MySqlCommand("SELECT SCHEMA_NAME FROM SCHEMATA WHERE SCHEMA_NAME = @dbName", conn);
cmd.Parameters.AddWithValue("@dbName", model.DbName);
var exists = cmd.ExecuteScalar();
if (exists == null)
{
try
{
var createCmd = new MySqlCommand($"CREATE DATABASE `{model.DbName}`", conn);
createCmd.ExecuteNonQuery();
}
catch (Exception ex)
{
_logger.LogError(ex, "Kunde inte skapa databasen.");
return BadRequest(new { error = "Databasen finns inte och kunde inte skapas.", details = ex.Message });
}
}
}
// Bygg EF-connection
var efConnBuilder = new MySqlConnectionStringBuilder
{
Server = model.DbHost,
Port = (uint)model.DbPort,
UserID = model.DbUser,
Password = model.DbPassword,
Database = model.DbName
};
var tempProvider = SetupService.BuildTemporaryServices(efConnBuilder.ConnectionString);
using var scope = tempProvider.CreateScope();
// Skapa databastabeller
var db = scope.ServiceProvider.GetRequiredService<ApplicationDbContext>();
await db.Database.MigrateAsync();
// Sätt konfig-flagga tidigt
model.IsConfigured = true;
// Spara setup.json
var filePath = Path.Combine(_env.ContentRootPath, "infrastructure", "setup.json");
var json = JsonSerializer.Serialize(model, new JsonSerializerOptions { WriteIndented = true });
System.IO.File.WriteAllText(filePath, json);
// Roller och admin
var userManager = scope.ServiceProvider.GetRequiredService<UserManager<ApplicationUser>>();
var roleManager = scope.ServiceProvider.GetRequiredService<RoleManager<IdentityRole>>();
string[] roles = { "Admin", "Chef", "Budget" };
foreach (var role in roles)
{
if (!await roleManager.RoleExistsAsync(role))
await roleManager.CreateAsync(new IdentityRole(role));
}
var existingUser = await userManager.FindByNameAsync(model.AdminUsername);
if (existingUser == null)
{
var adminUser = new ApplicationUser
{
UserName = model.AdminUsername,
Email = model.AdminEmail,
EmailConfirmed = true
};
var result = await userManager.CreateAsync(adminUser, model.AdminPassword);
if (!result.Succeeded)
return BadRequest(new { error = "Kunde inte skapa administratör", details = result.Errors });
await userManager.AddToRoleAsync(adminUser, "Admin");
}
return Ok(new { message = "Installation slutförd!" });
}
catch (Exception ex)
{
_logger.LogError(ex, "Fel vid installation.");
return BadRequest(new { error = "Fel vid installation", details = ex.Message });
}
}
public IActionResult SetupComplete() => View();
}
}