Refactor EnvelopeType handling and improve validation

Removed AutoMapper dependency in `ReadEnvelopeTypesQueryHandler` and replaced it with manual projection to address null-materialization issues. Updated `EnvelopeType` entity properties to nullable types to align with the database schema. Adjusted computed properties to handle null values gracefully.

Enhanced `SenderEditorPage` with authentication checks, improved handling of reminder and expiry settings, and added validation for user input. Introduced `NormalizeSettings` and `ValidateSettings` methods to ensure consistent and valid configurations. Refactored checkbox value parsing for better reliability.

Injected `AuthService` and `IStringLocalizer` for authentication and localization support. Improved error messaging and localized validation errors. Performed minor code cleanup and refactoring for better readability and maintainability.
This commit is contained in:
2026-10-02 01:25:43 +02:00
parent 1e8e5c96c4
commit c7bc9fbcca
3 changed files with 121 additions and 28 deletions

View File

@@ -20,6 +20,7 @@
@inject ReceiverService ReceiverService
@inject EnvelopeService EnvelopeService
@inject EnvelopeTypeService EnvelopeTypeService
@inject AuthService AuthService
@inject IStringLocalizer<Resource> UiLocalizer
<link href="_content/DevExpress.Blazor.Themes/blazing-berry.bs5.min.css" rel="stylesheet" />
@@ -696,6 +697,13 @@
protected override async Task OnInitializedAsync()
{
var hasAccess = await AuthService.CheckSenderAccessAsync();
if (!hasAccess)
{
NavigationManager.NavigateTo("/sender/login");
return;
}
try
{
_envelopeTypes = (await EnvelopeTypeService.GetAsync()).ToList();
@@ -768,12 +776,14 @@
_finalEmailToCreator = envelope.FinalEmailToCreator ?? (int)FinalEmailType.No;
_finalEmailToReceivers = envelope.FinalEmailToReceivers ?? (int)FinalEmailType.No;
_sendReminderEmails = envelope.EnvelopeType?.SendReminderEmails ?? false;
_firstReminderDays = envelope.EnvelopeType?.FirstReminderDays ?? 0;
_reminderIntervalDays = envelope.EnvelopeType?.ReminderIntervalDays ?? 0;
_sendReminderEmails = envelope.SendReminderEmails ?? envelope.EnvelopeType?.SendReminderEmails ?? false;
_firstReminderDays = envelope.FirstReminderDays ?? envelope.EnvelopeType?.FirstReminderDays ?? 0;
_reminderIntervalDays = envelope.ReminderIntervalDays ?? envelope.EnvelopeType?.ReminderIntervalDays ?? 0;
_expiresWhenDays = envelope.ExpiresWhenDays ?? envelope.EnvelopeType?.ExpiresDays ?? 0;
_expiresWarningWhenDays = envelope.ExpiresWarningWhenDays ?? envelope.EnvelopeType?.ExpiresWarningDays ?? 0;
NormalizeSettings();
var envelopeReceivers = envelope.EnvelopeReceivers?.ToList() ?? [];
_receivers = envelopeReceivers
.Select((er, index) => new ReceiverDraft(
@@ -962,7 +972,7 @@
void OnTfaChanged(ChangeEventArgs e)
{
_tfaEnabled = e.Value as bool? ?? false;
_tfaEnabled = ParseCheckboxValue(e);
if (_tfaEnabled)
_useAccessCode = true;
}
@@ -975,12 +985,20 @@
return;
}
_useAccessCode = e.Value as bool? ?? false;
_useAccessCode = ParseCheckboxValue(e);
}
void OnSendReminderEmailsChanged(ChangeEventArgs e)
{
_sendReminderEmails = e.Value as bool? ?? false;
_sendReminderEmails = ParseCheckboxValue(e);
}
static bool ParseCheckboxValue(ChangeEventArgs e)
{
if (e.Value is bool b)
return b;
return bool.TryParse(e.Value?.ToString(), out var parsed) && parsed;
}
// ── PDF area click → place field ──
@@ -1100,6 +1118,13 @@
async Task SaveDraftAsync()
{
if (!ValidateSettings(out var settingsError))
{
_saveErrorMessage = settingsError;
_savePopupVisible = true;
return;
}
_isSaving = true;
_saveErrorMessage = null;
await InvokeAsync(StateHasChanged);
@@ -1140,6 +1165,13 @@
// ── Send envelope ──
async Task SendAsync()
{
if (!ValidateSettings(out var settingsError))
{
_saveErrorMessage = settingsError;
_savePopupVisible = true;
return;
}
// ── Validation ──
_titleTouched = true;
if (!_pdfLoaded || _originalPdfBytes is null)
@@ -1227,6 +1259,8 @@
CreateEnvelopeCommand BuildCreateEnvelopeCommand(bool send)
{
NormalizeSettings();
var envelopeId = _editingEnvelopeId
?? EnvelopeId
?? _loadedEnvelopeId
@@ -1279,6 +1313,48 @@
};
}
void NormalizeSettings()
{
_language = string.IsNullOrWhiteSpace(_language) ? "de-DE" : _language.Trim();
if (_tfaEnabled)
_useAccessCode = true;
_firstReminderDays = Math.Max(0, _firstReminderDays);
_reminderIntervalDays = Math.Max(0, _reminderIntervalDays);
_expiresWhenDays = Math.Max(0, _expiresWhenDays);
_expiresWarningWhenDays = Math.Max(0, _expiresWarningWhenDays);
if (_expiresWhenDays > 0 && _expiresWarningWhenDays > _expiresWhenDays)
_expiresWarningWhenDays = _expiresWhenDays;
}
bool ValidateSettings(out string? message)
{
NormalizeSettings();
if (_sendReminderEmails && _reminderIntervalDays <= 0)
{
message = L("SenderEditor_Validation_ReminderInterval", "Bitte geben Sie ein Erinnerungsintervall groesser als 0 Tage ein.");
return false;
}
if (_sendReminderEmails && _firstReminderDays < 0)
{
message = L("SenderEditor_Validation_FirstReminder", "Bitte geben Sie gueltige Tage fuer die erste Erinnerung ein.");
return false;
}
if (_expiresWhenDays > 0 && _expiresWarningWhenDays > _expiresWhenDays)
{
message = L("SenderEditor_Validation_ExpiryWarning", "Die Ablaufwarnung darf nicht nach dem Ablaufdatum liegen.");
return false;
}
message = null;
return true;
}
int? GetEnvelopeIdFromCurrentUri()
{
try