Add owner role and admin management controls
This commit is contained in:
@@ -94,6 +94,82 @@ public class AdminTests
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Admin_can_grant_and_revoke_admin_for_non_owner_accounts()
|
||||
{
|
||||
await using var factory = new TestWebApplicationFactory();
|
||||
var owner = factory.CreateClientWithCookies();
|
||||
await owner.RegisterAsync("owner", admin: true);
|
||||
var player = factory.CreateClientWithCookies();
|
||||
await player.RegisterAsync("player");
|
||||
var playerId = await player.GetProfileIdAsync();
|
||||
|
||||
var grant = await owner.PostAsJsonAsync("/api/admin/player-admin", new
|
||||
{
|
||||
playerId = playerId,
|
||||
isAdmin = true
|
||||
});
|
||||
grant.EnsureSuccessStatusCode();
|
||||
|
||||
await factory.WithDbContextAsync(async db =>
|
||||
{
|
||||
var promoted = await db.Players.AsNoTracking().SingleAsync(p => p.Id == playerId);
|
||||
Assert.True(promoted.IsAdmin);
|
||||
Assert.False(promoted.IsOwner);
|
||||
});
|
||||
|
||||
var revoke = await owner.PostAsJsonAsync("/api/admin/player-admin", new
|
||||
{
|
||||
playerId = playerId,
|
||||
isAdmin = false
|
||||
});
|
||||
revoke.EnsureSuccessStatusCode();
|
||||
|
||||
await factory.WithDbContextAsync(async db =>
|
||||
{
|
||||
var demoted = await db.Players.AsNoTracking().SingleAsync(p => p.Id == playerId);
|
||||
Assert.False(demoted.IsAdmin);
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Owner_admin_role_cannot_be_changed_or_deleted()
|
||||
{
|
||||
await using var factory = new TestWebApplicationFactory();
|
||||
var owner = factory.CreateClientWithCookies();
|
||||
await owner.RegisterAsync("owner", admin: true);
|
||||
var ownerId = await owner.GetProfileIdAsync();
|
||||
|
||||
var toggleOwner = await owner.PostAsJsonAsync("/api/admin/player-admin", new
|
||||
{
|
||||
playerId = ownerId,
|
||||
isAdmin = false
|
||||
});
|
||||
Assert.Equal(HttpStatusCode.BadRequest, toggleOwner.StatusCode);
|
||||
|
||||
var deleteOwner = await owner.SendAsync(new HttpRequestMessage(HttpMethod.Delete, $"/api/admin/players/{ownerId}")
|
||||
{
|
||||
Content = JsonContent.Create(new { password = AdminPassword })
|
||||
});
|
||||
Assert.Equal(HttpStatusCode.BadRequest, deleteOwner.StatusCode);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Set_player_admin_returns_not_found_for_unknown_player()
|
||||
{
|
||||
await using var factory = new TestWebApplicationFactory();
|
||||
var owner = factory.CreateClientWithCookies();
|
||||
await owner.RegisterAsync("owner", admin: true);
|
||||
|
||||
var response = await owner.PostAsJsonAsync("/api/admin/player-admin", new
|
||||
{
|
||||
playerId = Guid.NewGuid(),
|
||||
isAdmin = true
|
||||
});
|
||||
|
||||
Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Admin_player_phase_requires_vote_phase_and_suggest_target()
|
||||
{
|
||||
|
||||
@@ -117,6 +117,13 @@ public class AuthTests
|
||||
response.EnsureSuccessStatusCode();
|
||||
var json = await response.Content.ReadFromJsonAsync<JsonElement>();
|
||||
Assert.True(json.GetProperty("isAdmin").GetBoolean());
|
||||
|
||||
await factory.WithDbContextAsync(async db =>
|
||||
{
|
||||
var owner = await db.Players.AsNoTracking().SingleAsync(p => p.Username == "adminuser");
|
||||
Assert.True(owner.IsOwner);
|
||||
Assert.True(owner.IsAdmin);
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -133,7 +140,23 @@ public class AuthTests
|
||||
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());
|
||||
Assert.Equal("Admin registration via admin key is disabled once an owner account exists.", body.GetProperty("error").GetString());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Auth_options_reports_owner_existence()
|
||||
{
|
||||
await using var factory = new TestWebApplicationFactory();
|
||||
var client = factory.CreateClientWithCookies();
|
||||
|
||||
var before = await client.GetFromJsonAsync<JsonElement>("/api/auth/options");
|
||||
Assert.False(before.GetProperty("ownerExists").GetBoolean());
|
||||
|
||||
var ownerRegister = await client.RegisterAsync("owner", admin: true);
|
||||
ownerRegister.EnsureSuccessStatusCode();
|
||||
|
||||
var after = await client.GetFromJsonAsync<JsonElement>("/api/auth/options");
|
||||
Assert.True(after.GetProperty("ownerExists").GetBoolean());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
||||
Reference in New Issue
Block a user