forked from gongxuegit/tiku-backend.net
feat: harden SaaS authentication and authorization
This commit is contained in:
104
Tiku.UnitTests/Bootstrap/PlatformAdminBootstrapperTests.cs
Normal file
104
Tiku.UnitTests/Bootstrap/PlatformAdminBootstrapperTests.cs
Normal file
@@ -0,0 +1,104 @@
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.AspNetCore.DataProtection;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Tiku.Application.Security;
|
||||
using Tiku.Domain.Identity;
|
||||
using Tiku.Infrastructure.Bootstrap;
|
||||
using Tiku.Infrastructure.Persistence;
|
||||
|
||||
namespace Tiku.UnitTests.Bootstrap;
|
||||
|
||||
public sealed class PlatformAdminBootstrapperTests
|
||||
{
|
||||
private const string TemporaryPassword = "Temporary9Password";
|
||||
|
||||
[Fact]
|
||||
public async Task Bootstrap_creates_forced_enrollment_super_admin_and_audit()
|
||||
{
|
||||
await using var provider = CreateProvider();
|
||||
await using var scope = provider.CreateAsyncScope();
|
||||
var bootstrapper = ActivatorUtilities.CreateInstance<PlatformAdminBootstrapper>(scope.ServiceProvider);
|
||||
|
||||
var result = await bootstrapper.BootstrapAsync(new PlatformAdminBootstrapOptions(
|
||||
"admin@example.com",
|
||||
TemporaryPassword,
|
||||
"Initial Administrator"));
|
||||
|
||||
var context = scope.ServiceProvider.GetRequiredService<TikuDbContext>();
|
||||
var user = await context.Users.SingleAsync(item => item.Id == result.UserId);
|
||||
Assert.True(user.ForcePasswordChange);
|
||||
Assert.False(user.TwoFactorEnabled);
|
||||
Assert.True(user.EmailConfirmed);
|
||||
Assert.Equal(UserStatus.Active, user.Status);
|
||||
var role = await context.PlatformBackendRoles.SingleAsync(item => item.Id == result.RoleId);
|
||||
Assert.Equal(PlatformAdminBootstrapper.SuperAdminRoleCode, role.Code);
|
||||
Assert.True(role.IsSystem);
|
||||
Assert.Equal(BackendPermissions.Platform.Count, await context.PlatformBackendRolePermissions.CountAsync());
|
||||
Assert.True(await context.PlatformBackendUserRoles.AnyAsync(item => item.UserId == user.Id && item.RoleId == role.Id));
|
||||
Assert.True(await context.AuditLogs.AnyAsync(item =>
|
||||
item.ActorUserId == user.Id && item.Action == "platform.bootstrap_admin.created"));
|
||||
|
||||
var userManager = scope.ServiceProvider.GetRequiredService<UserManager<User>>();
|
||||
Assert.True(await userManager.CheckPasswordAsync(user, TemporaryPassword));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Bootstrap_rejects_a_second_platform_administrator_without_mutating_data()
|
||||
{
|
||||
await using var provider = CreateProvider();
|
||||
await using var scope = provider.CreateAsyncScope();
|
||||
var bootstrapper = ActivatorUtilities.CreateInstance<PlatformAdminBootstrapper>(scope.ServiceProvider);
|
||||
await bootstrapper.BootstrapAsync(new PlatformAdminBootstrapOptions("first@example.com", TemporaryPassword));
|
||||
|
||||
var exception = await Assert.ThrowsAsync<PlatformAdminBootstrapException>(() =>
|
||||
bootstrapper.BootstrapAsync(new PlatformAdminBootstrapOptions("second@example.com", TemporaryPassword)));
|
||||
|
||||
Assert.Equal("platform_admin_already_exists", exception.Code);
|
||||
var context = scope.ServiceProvider.GetRequiredService<TikuDbContext>();
|
||||
Assert.Single(context.PlatformBackendUserRoles);
|
||||
Assert.Single(context.PlatformBackendRoles);
|
||||
Assert.Single(context.AuditLogs);
|
||||
Assert.Single(context.Users);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Bootstrap_rejects_an_existing_user_email()
|
||||
{
|
||||
await using var provider = CreateProvider();
|
||||
await using var scope = provider.CreateAsyncScope();
|
||||
var userManager = scope.ServiceProvider.GetRequiredService<UserManager<User>>();
|
||||
var createResult = await userManager.CreateAsync(new User
|
||||
{
|
||||
Email = "existing@example.com",
|
||||
UserName = "existing@example.com"
|
||||
}, TemporaryPassword);
|
||||
Assert.True(createResult.Succeeded);
|
||||
var bootstrapper = ActivatorUtilities.CreateInstance<PlatformAdminBootstrapper>(scope.ServiceProvider);
|
||||
|
||||
var exception = await Assert.ThrowsAsync<PlatformAdminBootstrapException>(() =>
|
||||
bootstrapper.BootstrapAsync(new PlatformAdminBootstrapOptions("existing@example.com", TemporaryPassword)));
|
||||
|
||||
Assert.Equal("bootstrap_user_already_exists", exception.Code);
|
||||
}
|
||||
|
||||
private static ServiceProvider CreateProvider()
|
||||
{
|
||||
var services = new ServiceCollection();
|
||||
services.AddLogging();
|
||||
services.AddDbContext<TikuDbContext>(options =>
|
||||
options.UseInMemoryDatabase(Guid.NewGuid().ToString()));
|
||||
services.AddIdentityCore<User>(options =>
|
||||
{
|
||||
options.Password.RequiredLength = 10;
|
||||
options.Password.RequireDigit = true;
|
||||
options.Password.RequireLowercase = true;
|
||||
options.Password.RequireUppercase = false;
|
||||
options.Password.RequireNonAlphanumeric = false;
|
||||
})
|
||||
.AddEntityFrameworkStores<TikuDbContext>()
|
||||
.AddDefaultTokenProviders();
|
||||
services.AddDataProtection().UseEphemeralDataProtectionProvider();
|
||||
return services.BuildServiceProvider();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user