Import functionality for wino accounts, calendar sync UI, bunch of shell improvements

This commit is contained in:
Burak Kaan Köse
2026-04-04 20:23:20 +02:00
parent 1667aa34db
commit 1d0fcfb5b0
68 changed files with 2792 additions and 519 deletions
@@ -1,6 +1,7 @@
using System.Threading.Tasks;
using MailKit.Security;
using Serilog;
using Wino.Core.Domain.Entities.Shared;
using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.Models.Synchronization;
@@ -14,6 +15,12 @@ namespace Wino.Core.Synchronizers.Errors.Imap;
public class ImapAuthenticationFailedHandler : ISynchronizerErrorHandler
{
private readonly ILogger _logger = Log.ForContext<ImapAuthenticationFailedHandler>();
private readonly IAccountService _accountService;
public ImapAuthenticationFailedHandler(IAccountService accountService)
{
_accountService = accountService;
}
public bool CanHandle(SynchronizerErrorContext error)
{
@@ -22,12 +29,17 @@ public class ImapAuthenticationFailedHandler : ISynchronizerErrorHandler
(error.ErrorMessage?.Contains("authentication", System.StringComparison.OrdinalIgnoreCase) ?? false);
}
public Task<bool> HandleAsync(SynchronizerErrorContext error)
public async Task<bool> HandleAsync(SynchronizerErrorContext error)
{
_logger.Warning(error.Exception,
"IMAP authentication failed for account {AccountName} ({AccountId}). User needs to re-authenticate.",
error.Account?.Name, error.Account?.Id);
if (error.Account != null)
{
await PersistInvalidCredentialAttentionAsync(error.Account).ConfigureAwait(false);
}
// Mark as requiring authentication - this will stop sync and notify user
error.Severity = SynchronizerErrorSeverity.AuthRequired;
error.Category = SynchronizerErrorCategory.Authentication;
@@ -35,6 +47,20 @@ public class ImapAuthenticationFailedHandler : ISynchronizerErrorHandler
// No point in retrying auth failures - credentials need to be updated
error.RetryDelay = null;
return Task.FromResult(true);
return true;
}
private async Task PersistInvalidCredentialAttentionAsync(MailAccount account)
{
var persistedAccount = await _accountService.GetAccountAsync(account.Id).ConfigureAwait(false);
if (persistedAccount == null)
return;
if (persistedAccount.AttentionReason == AccountAttentionReason.InvalidCredentials)
return;
persistedAccount.AttentionReason = AccountAttentionReason.InvalidCredentials;
await _accountService.UpdateAccountAsync(persistedAccount).ConfigureAwait(false);
}
}