55 lines
2.0 KiB
C#
55 lines
2.0 KiB
C#
public class AttestationService : IAttestationService
|
|
{
|
|
private readonly AppDbContext _db;
|
|
private readonly ILogger<AttestationService> _logger;
|
|
|
|
public AttestationService(AppDbContext db, ILogger<AttestationService> logger)
|
|
{
|
|
_db = db;
|
|
_logger = logger;
|
|
}
|
|
|
|
public async Task<User> ValidateAttestationAsync(
|
|
Guid userId, bool clinicianAttestation, string passwordConfirm)
|
|
{
|
|
// 1. Attestation flag must be explicitly true
|
|
if (!clinicianAttestation)
|
|
throw new ValidationException(
|
|
"Clinician attestation is required for live capture.",
|
|
"ATTESTATION_REQUIRED");
|
|
|
|
// 2. Load user
|
|
var user = await _db.Users.FindAsync(userId);
|
|
if (user is null)
|
|
throw new NotFoundException("User not found.", "USER_NOT_FOUND");
|
|
|
|
// 3. Role check — only Clinician role can use live capture
|
|
if (user.Role != UserRole.Clinician)
|
|
throw new ValidationException(
|
|
"Only users with the Clinician role can perform live capture.",
|
|
"CLINICIAN_ROLE_REQUIRED");
|
|
|
|
// 4. Account must be active
|
|
if (!user.IsActive)
|
|
throw new ConflictException(
|
|
"Account is disabled.", "ACCOUNT_DISABLED");
|
|
|
|
// 5. Password re-confirmation — prevents unattended sessions from
|
|
// submitting clinical data without the clinician present
|
|
if (string.IsNullOrWhiteSpace(passwordConfirm))
|
|
throw new ValidationException(
|
|
"Password re-confirmation is required.",
|
|
"PASSWORD_CONFIRM_REQUIRED");
|
|
|
|
if (!BCrypt.Net.BCrypt.Verify(passwordConfirm, user.PasswordHash))
|
|
throw new ValidationException(
|
|
"Password re-confirmation failed.",
|
|
"PASSWORD_CONFIRM_INVALID");
|
|
|
|
_logger.LogInformation(
|
|
"Clinician attestation validated for user {UserId} ({FullName})",
|
|
user.Id, user.FullName);
|
|
|
|
return user;
|
|
}
|
|
} |