Updates
This commit is contained in:
@@ -1,4 +1,6 @@
|
||||
using System.Security.Claims;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Threading.RateLimiting;
|
||||
using Microsoft.AspNetCore.Authentication;
|
||||
using Microsoft.AspNetCore.Authentication.Cookies;
|
||||
@@ -11,6 +13,8 @@ using timetracker.Data;
|
||||
using timetracker.Shared;
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
const string SuperAdminUsername = "marc";
|
||||
const string SuperAdminPassword = "123456";
|
||||
|
||||
// Add Authentication
|
||||
builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
|
||||
@@ -277,6 +281,32 @@ using (var scope = app.Services.CreateScope())
|
||||
Console.WriteLine($"Fehler beim Konvertieren der PostgreSQL-Spaltentypen (IsTenantAdmin/IsApproved/CreatedAt): {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
var superAdmin = await db.Users
|
||||
.IgnoreQueryFilters()
|
||||
.FirstOrDefaultAsync(u => u.TenantId == null && u.Username == SuperAdminUsername);
|
||||
|
||||
if (superAdmin == null)
|
||||
{
|
||||
var (passwordHash, passwordSalt) = HashPassword(SuperAdminPassword);
|
||||
db.Users.Add(new User
|
||||
{
|
||||
Username = SuperAdminUsername,
|
||||
PasswordHash = passwordHash,
|
||||
PasswordSalt = passwordSalt,
|
||||
TenantId = null,
|
||||
IsTenantAdmin = true
|
||||
});
|
||||
await db.SaveChangesAsync();
|
||||
}
|
||||
else if (IsLegacySeedPassword(superAdmin.PasswordHash, superAdmin.PasswordSalt, SuperAdminPassword))
|
||||
{
|
||||
var (passwordHash, passwordSalt) = HashPassword(SuperAdminPassword);
|
||||
superAdmin.PasswordHash = passwordHash;
|
||||
superAdmin.PasswordSalt = passwordSalt;
|
||||
superAdmin.IsTenantAdmin = true;
|
||||
await db.SaveChangesAsync();
|
||||
}
|
||||
}
|
||||
|
||||
var forwardedHeadersOptions = new ForwardedHeadersOptions
|
||||
@@ -821,6 +851,32 @@ superAdminApi.MapDelete("/tenants/{id:int}", async (int id, TimetrackerDbContext
|
||||
|
||||
app.Run();
|
||||
|
||||
static (string Hash, string Salt) HashPassword(string password)
|
||||
{
|
||||
var saltBytes = RandomNumberGenerator.GetBytes(32);
|
||||
var salt = Convert.ToBase64String(saltBytes);
|
||||
var hash = ComputePasswordHash(password, salt);
|
||||
return (hash, salt);
|
||||
}
|
||||
|
||||
static bool IsLegacySeedPassword(string hash, string salt, string password)
|
||||
{
|
||||
var passwordBytes = Encoding.UTF8.GetBytes(password + salt);
|
||||
var legacyHash = Convert.ToBase64String(SHA256.HashData(passwordBytes));
|
||||
return hash == legacyHash;
|
||||
}
|
||||
|
||||
static string ComputePasswordHash(string password, string salt)
|
||||
{
|
||||
var hash = Rfc2898DeriveBytes.Pbkdf2(
|
||||
Encoding.UTF8.GetBytes(password),
|
||||
Convert.FromBase64String(salt),
|
||||
iterations: 200_000,
|
||||
HashAlgorithmName.SHA256,
|
||||
outputLength: 32);
|
||||
return Convert.ToBase64String(hash);
|
||||
}
|
||||
|
||||
// ── Models for Request Bodies ──────────────────────────────────────────────────
|
||||
public record LoginRequest(string Username, string Password);
|
||||
public record RegisterRequest(string Username, string Password, string? Honeypot = null);
|
||||
|
||||
Reference in New Issue
Block a user