From ba8f701223cf1dc87ce70ebf226fa8cbab0e60f7 Mon Sep 17 00:00:00 2001 From: TekH Date: Mon, 17 Aug 2026 15:05:28 +0200 Subject: [PATCH] feat(application): add OAuth2RefreshToken/OAuth2Provider to DTOs; guard refresh token from being overwritten on seed; add OAuth2MappingProfile --- .../Dto/EmailAccounts/EmailAccountDto.cs | 14 ++++++++++++++ .../EmailAccountModificationDto.cs | 14 ++++++++++++++ .../Common/Mappings/EmailMappingProfile.cs | 7 ++++++- .../Common/Mappings/OAuth2MappingProfile.cs | 19 +++++++++++++++++++ 4 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 src/core/DigitalData.MessagingService.Application/Common/Mappings/OAuth2MappingProfile.cs diff --git a/src/core/DigitalData.MessagingService.Application/Common/Dto/EmailAccounts/EmailAccountDto.cs b/src/core/DigitalData.MessagingService.Application/Common/Dto/EmailAccounts/EmailAccountDto.cs index 2a4aa25..84871be 100644 --- a/src/core/DigitalData.MessagingService.Application/Common/Dto/EmailAccounts/EmailAccountDto.cs +++ b/src/core/DigitalData.MessagingService.Application/Common/Dto/EmailAccounts/EmailAccountDto.cs @@ -54,8 +54,22 @@ public record EmailAccountDto public string? OAuth2ClientId { get; set; } + /// + /// OAuth2 refresh token (Google only). Obtained via OAuth Playground or authorization flow. + /// Leave empty for Microsoft. + /// + public string? OAuth2RefreshToken { get; set; } + + /// + /// Tenant ID for Microsoft OAuth2 (GUID, full domain, or "common"). Not used for Google. + /// public string? OAuth2TenantId { get; set; } + /// + /// Identifies which OAuth2 identity provider to use when is true. + /// + public OAuth2Provider OAuth2Provider { get; set; } = OAuth2Provider.None; + /// /// The protocol used to receive (sync) incoming emails. /// diff --git a/src/core/DigitalData.MessagingService.Application/Common/Dto/EmailAccounts/EmailAccountModificationDto.cs b/src/core/DigitalData.MessagingService.Application/Common/Dto/EmailAccounts/EmailAccountModificationDto.cs index 006af07..b37a053 100644 --- a/src/core/DigitalData.MessagingService.Application/Common/Dto/EmailAccounts/EmailAccountModificationDto.cs +++ b/src/core/DigitalData.MessagingService.Application/Common/Dto/EmailAccounts/EmailAccountModificationDto.cs @@ -57,8 +57,22 @@ public record EmailAccountModificationDto public string? OAuth2ClientSecret { get; set; } + /// + /// OAuth2 refresh token (Google only). Obtained via OAuth Playground or authorization flow. + /// Leave empty for Microsoft. + /// + public string? OAuth2RefreshToken { get; set; } + + /// + /// Tenant ID for Microsoft OAuth2 (GUID, full domain, or "common"). Not used for Google. + /// public string? OAuth2TenantId { get; set; } + /// + /// Identifies which OAuth2 identity provider to use when is true. + /// + public OAuth2Provider OAuth2Provider { get; set; } = OAuth2Provider.None; + /// /// The protocol used to receive (sync) incoming emails. /// diff --git a/src/core/DigitalData.MessagingService.Application/Common/Mappings/EmailMappingProfile.cs b/src/core/DigitalData.MessagingService.Application/Common/Mappings/EmailMappingProfile.cs index aafb081..d576944 100644 --- a/src/core/DigitalData.MessagingService.Application/Common/Mappings/EmailMappingProfile.cs +++ b/src/core/DigitalData.MessagingService.Application/Common/Mappings/EmailMappingProfile.cs @@ -32,7 +32,12 @@ public class EmailMappingProfile : Profile // EmailAccountDto -> EmailAccount CreateMap(); - CreateMap(); + CreateMap() + // Do not overwrite OAuth2RefreshToken if the source value is null or empty. + // This prevents the seed process from erasing a token that was obtained via + // the OAuth2 authorization flow and saved to the database at runtime. + .ForMember(dest => dest.OAuth2RefreshToken, + opt => opt.Condition((src, dest, srcMember) => !string.IsNullOrEmpty(srcMember))); // ReceivedEmailDto <-> ReceivedEmail CreateMap() diff --git a/src/core/DigitalData.MessagingService.Application/Common/Mappings/OAuth2MappingProfile.cs b/src/core/DigitalData.MessagingService.Application/Common/Mappings/OAuth2MappingProfile.cs new file mode 100644 index 0000000..61b7d3b --- /dev/null +++ b/src/core/DigitalData.MessagingService.Application/Common/Mappings/OAuth2MappingProfile.cs @@ -0,0 +1,19 @@ +#if NET +using AutoMapper; +using DigitalData.MessagingService.Domain.Entities; + +namespace DigitalData.MessagingService.Application.Common.Mappings; + +/// +/// AutoMapper profile for OAuth2 operations. +/// Registers EmailAccount self-mapping so UpdateSingleAsync can update an account +/// entity using another EmailAccount instance (e.g. after setting OAuth2RefreshToken). +/// +public class OAuth2MappingProfile : Profile +{ + public OAuth2MappingProfile() + { + CreateMap(); + } +} +#endif