feat: restrict admin access to club operations and rollout test environment
CI Pipeline / Backend Build & Test (pull_request) Successful in 53s
CI Pipeline / Frontend Lint, Test & Build (pull_request) Failing after 16s
CI Pipeline / Infrastructure Validation (pull_request) Successful in 3s

This commit is contained in:
WorkClub Automation
2026-03-18 09:08:45 +01:00
parent 9cb80e4517
commit 821459966c
22 changed files with 507 additions and 203 deletions
@@ -69,7 +69,7 @@ public class ClubEndpointsTests : IntegrationTestBase
ExternalUserId = adminUserId,
DisplayName = "Admin User",
Email = "admin@test.com",
Role = ClubRole.Admin,
Role = ClubRole.Manager,
ClubId = club1Id,
CreatedAt = DateTimeOffset.UtcNow,
UpdatedAt = DateTimeOffset.UtcNow
@@ -60,7 +60,7 @@ public class MemberEndpointsTests : IntegrationTestBase
ExternalUserId = "admin-user-id",
DisplayName = "Admin User",
Email = "admin@test.com",
Role = ClubRole.Admin,
Role = ClubRole.Manager,
ClubId = club1Id,
CreatedAt = DateTimeOffset.UtcNow,
UpdatedAt = DateTimeOffset.UtcNow
@@ -303,55 +303,7 @@ public class ShiftCrudTests : IntegrationTestBase
}
[Fact]
public async Task DeleteShift_AsAdmin_DeletesShift()
{
// Arrange
var shiftId = Guid.NewGuid();
var clubId = Guid.NewGuid();
var createdBy = Guid.NewGuid();
var now = DateTimeOffset.UtcNow;
using (var scope = Factory.Services.CreateScope())
{
var context = scope.ServiceProvider.GetRequiredService<AppDbContext>();
context.Shifts.Add(new Shift
{
Id = shiftId,
TenantId = "tenant1",
Title = "Test Shift",
StartTime = now.AddDays(1),
EndTime = now.AddDays(1).AddHours(4),
Capacity = 5,
ClubId = clubId,
CreatedById = createdBy,
CreatedAt = now,
UpdatedAt = now
});
await context.SaveChangesAsync();
}
SetTenant("tenant1");
AuthenticateAs("admin@test.com", new Dictionary<string, string> { ["tenant1"] = "Admin" });
// Act
var response = await Client.DeleteAsync($"/api/shifts/{shiftId}");
// Assert
Assert.Equal(HttpStatusCode.NoContent, response.StatusCode);
// Verify shift is deleted
using (var scope = Factory.Services.CreateScope())
{
var context = scope.ServiceProvider.GetRequiredService<AppDbContext>();
var shift = await context.Shifts.FindAsync(shiftId);
Assert.Null(shift);
}
}
[Fact]
public async Task DeleteShift_AsManager_ReturnsForbidden()
public async Task DeleteShift_AsManager_DeletesShift()
{
// Arrange
var shiftId = Guid.NewGuid();
@@ -387,7 +339,15 @@ public class ShiftCrudTests : IntegrationTestBase
var response = await Client.DeleteAsync($"/api/shifts/{shiftId}");
// Assert
Assert.Equal(HttpStatusCode.Forbidden, response.StatusCode);
Assert.Equal(HttpStatusCode.NoContent, response.StatusCode);
// Verify shift is deleted
using (var scope = Factory.Services.CreateScope())
{
var context = scope.ServiceProvider.GetRequiredService<AppDbContext>();
var shift = await context.Shifts.FindAsync(shiftId);
Assert.Null(shift);
}
}
[Fact]
@@ -387,52 +387,7 @@ public class TaskCrudTests : IntegrationTestBase
}
[Fact]
public async Task DeleteTask_AsAdmin_DeletesTask()
{
// Arrange
var taskId = Guid.NewGuid();
var club1 = Guid.NewGuid();
var createdBy = Guid.NewGuid();
using (var scope = Factory.Services.CreateScope())
{
var context = scope.ServiceProvider.GetRequiredService<AppDbContext>();
context.WorkItems.Add(new WorkItem
{
Id = taskId,
TenantId = "tenant1",
Title = "Test Task",
Status = WorkItemStatus.Open,
ClubId = club1,
CreatedById = createdBy,
CreatedAt = DateTimeOffset.UtcNow,
UpdatedAt = DateTimeOffset.UtcNow
});
await context.SaveChangesAsync();
}
SetTenant("tenant1");
AuthenticateAs("admin@test.com", new Dictionary<string, string> { ["tenant1"] = "Admin" });
// Act
var response = await Client.DeleteAsync($"/api/tasks/{taskId}");
// Assert
Assert.Equal(HttpStatusCode.NoContent, response.StatusCode);
// Verify task is deleted
using (var scope = Factory.Services.CreateScope())
{
var context = scope.ServiceProvider.GetRequiredService<AppDbContext>();
var task = await context.WorkItems.FindAsync(taskId);
Assert.Null(task);
}
}
[Fact]
public async Task DeleteTask_AsManager_ReturnsForbidden()
public async Task DeleteTask_AsManager_DeletesTask()
{
// Arrange
var taskId = Guid.NewGuid();
@@ -465,7 +420,15 @@ public class TaskCrudTests : IntegrationTestBase
var response = await Client.DeleteAsync($"/api/tasks/{taskId}");
// Assert
Assert.Equal(HttpStatusCode.Forbidden, response.StatusCode);
Assert.Equal(HttpStatusCode.NoContent, response.StatusCode);
// Verify task is deleted
using (var scope = Factory.Services.CreateScope())
{
var context = scope.ServiceProvider.GetRequiredService<AppDbContext>();
var task = await context.WorkItems.FindAsync(taskId);
Assert.Null(task);
}
}
}