feat(settings): validate BaseUrl + cron on save, add BaseUrl hint

- Reject a non-absolute / non-http(s) BaseUrl and an implausible (not 5- or
  6-field) cron expression before the section is written to disk, mirroring the
  existing storage-path validation (snackbar + early return).
- Add a hint to the BaseUrl field. Cron check is a lightweight UI guard; the
  worker still does the authoritative Cronos parse at startup.
This commit is contained in:
2026-05-29 00:50:49 +03:00
parent e5cd2ab30c
commit 2e53dff853
+24 -1
View File
@@ -49,7 +49,7 @@
<Field Label="@L["Settings.Scraping.RetryBaseDelayMs"]">
<MudNumericField T="int" @bind-Value="_scraping.RetryPolicy.BaseDelayMs" Min="100" Max="60000" Variant="Variant.Outlined" />
</Field>
<Field Label="@L["Settings.Scraping.BaseUrl"]">
<Field Label="@L["Settings.Scraping.BaseUrl"]" Hint="@L["Settings.Scraping.BaseUrl.Hint"]">
<MudTextField T="string" @bind-Value="_scraping.BaseUrl" Variant="Variant.Outlined" />
</Field>
<Field Label="@L["Settings.Scraping.RequestTimeoutSeconds"]">
@@ -242,6 +242,20 @@
}
}
if (payload is ScrapingSettingsForm scraping
&& !(Uri.TryCreate(scraping.BaseUrl, UriKind.Absolute, out var baseUri)
&& (baseUri.Scheme == Uri.UriSchemeHttp || baseUri.Scheme == Uri.UriSchemeHttps)))
{
Snackbar.Add(L["Settings.Scraping.BaseUrl.Invalid"], Severity.Error);
return;
}
if (payload is WorkerOptions workers && !IsPlausibleCron(workers.UpcomingScheduleCron))
{
Snackbar.Add(L["Settings.Workers.Cron.Invalid"], Severity.Error);
return;
}
var confirmed = await ConfirmAsync();
if (!confirmed)
{
@@ -260,6 +274,15 @@
}
}
// Lightweight 5- or 6-field cron sanity check — avoids a Cronos dependency in the
// UI layer; the worker still does the authoritative parse at startup.
private static bool IsPlausibleCron(string? expression)
{
if (string.IsNullOrWhiteSpace(expression)) return false;
var fields = expression.Split(' ', StringSplitOptions.RemoveEmptyEntries);
return fields.Length is 5 or 6;
}
private async Task ResetSectionAsync(string section)
{
var confirmed = await ConfirmAsync();