71 lines
2.6 KiB
C#
71 lines
2.6 KiB
C#
using Microsoft.AspNetCore.Identity;
|
|
using Microsoft.EntityFrameworkCore;
|
|
using Tiku.Application.Auth;
|
|
using Tiku.Domain.Identity;
|
|
using Tiku.Domain.Operations;
|
|
using Tiku.Domain.Tenancy;
|
|
using Tiku.Infrastructure.Persistence;
|
|
|
|
namespace Tiku.Infrastructure.Auth;
|
|
|
|
internal sealed class AuthAdministrationService(
|
|
TikuDbContext dbContext,
|
|
UserManager<User> userManager,
|
|
IAuthSessionStore sessionStore) : IAuthAdministrationService
|
|
{
|
|
public async Task ResetPasswordAsync(
|
|
AdministrativePasswordResetRequest request,
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(request.Reason))
|
|
{
|
|
throw new InvalidCredentialsException("password_reset_reason_required");
|
|
}
|
|
|
|
var permitted = request.TenantId is { } tenantId
|
|
? await dbContext.TenantMemberships.AnyAsync(
|
|
item => item.TenantId == tenantId && item.UserId == request.TargetUserId &&
|
|
item.Status == MembershipStatus.Active,
|
|
cancellationToken)
|
|
: await dbContext.PlatformBackendUserRoles.AnyAsync(
|
|
item => item.UserId == request.TargetUserId,
|
|
cancellationToken);
|
|
if (!permitted)
|
|
{
|
|
throw new AuthSessionNotFoundException();
|
|
}
|
|
|
|
var user = await userManager.FindByIdAsync(request.TargetUserId.ToString())
|
|
?? throw new AuthSessionNotFoundException();
|
|
var token = await userManager.GeneratePasswordResetTokenAsync(user);
|
|
var reset = await userManager.ResetPasswordAsync(user, token, request.TemporaryPassword);
|
|
if (!reset.Succeeded)
|
|
{
|
|
throw new InvalidCredentialsException("invalid_new_password");
|
|
}
|
|
|
|
user.ForcePasswordChange = true;
|
|
var updated = await userManager.UpdateAsync(user);
|
|
if (!updated.Succeeded)
|
|
{
|
|
throw new InvalidOperationException("Unable to require a password change after the administrative reset.");
|
|
}
|
|
|
|
await sessionStore.RevokeAllAsync(user.Id, "administrative_password_reset", cancellationToken);
|
|
dbContext.AuditLogs.Add(new AuditLog
|
|
{
|
|
TenantId = request.TenantId,
|
|
ActorUserId = request.ActorUserId,
|
|
Action = "auth.password.reset_by_administrator",
|
|
TargetType = "user",
|
|
TargetId = request.TargetUserId.ToString(),
|
|
Details = System.Text.Json.JsonSerializer.SerializeToElement(new
|
|
{
|
|
request.Reason,
|
|
ForcePasswordChange = true
|
|
})
|
|
});
|
|
await dbContext.SaveChangesAsync(cancellationToken);
|
|
}
|
|
}
|