Harden app security controls from audit

This commit is contained in:
2026-02-08 18:40:13 +01:00
parent a6364b0802
commit 42e60d2a5a
20 changed files with 689 additions and 109 deletions

View File

@@ -62,6 +62,24 @@ public class AuthTests
Assert.Equal(HttpStatusCode.BadRequest, displayResp.StatusCode);
}
[Fact]
public async Task Register_rejects_weak_passwords()
{
await using var factory = new TestWebApplicationFactory();
var client = factory.CreateClientWithCookies();
var weak = await client.PostAsJsonAsync("/api/auth/register", new
{
Username = "weakpw",
Password = "alllowercase1!",
DisplayName = "weak"
});
Assert.Equal(HttpStatusCode.BadRequest, weak.StatusCode);
var json = await weak.Content.ReadFromJsonAsync<JsonElement>();
Assert.Equal("Password must include uppercase, lowercase, number, and symbol.", json.GetProperty("error").GetString());
}
[Fact]
public async Task Login_sets_last_login_and_fills_missing_display_name()
{
@@ -101,6 +119,23 @@ public class AuthTests
Assert.True(json.GetProperty("isAdmin").GetBoolean());
}
[Fact]
public async Task Register_admin_key_is_bootstrap_only()
{
await using var factory = new TestWebApplicationFactory();
var first = factory.CreateClientWithCookies();
var second = factory.CreateClientWithCookies();
var firstAdmin = await first.RegisterAsync("firstadmin", admin: true);
firstAdmin.EnsureSuccessStatusCode();
var secondAdmin = await second.RegisterAsync("secondadmin", admin: true);
Assert.Equal(HttpStatusCode.BadRequest, secondAdmin.StatusCode);
var body = await secondAdmin.Content.ReadFromJsonAsync<JsonElement>();
Assert.Equal("Admin registration via admin key is disabled after the first admin account.", body.GetProperty("error").GetString());
}
[Fact]
public async Task Register_duplicate_username_returns_conflict()
{