Revert "File scoped namespaces"

This reverts commit d31d8f574e.
This commit is contained in:
Burak Kaan Köse
2025-02-16 11:43:30 +01:00
parent d31d8f574e
commit cf9869b71e
617 changed files with 32097 additions and 31478 deletions

View File

@@ -1,16 +1,17 @@
using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Interfaces;
namespace Wino.Authentication;
public abstract class BaseAuthenticator
namespace Wino.Authentication
{
public abstract MailProviderType ProviderType { get; }
protected IAuthenticatorConfig AuthenticatorConfig { get; }
protected BaseAuthenticator(IAuthenticatorConfig authenticatorConfig)
public abstract class BaseAuthenticator
{
public abstract MailProviderType ProviderType { get; }
protected IAuthenticatorConfig AuthenticatorConfig { get; }
AuthenticatorConfig = authenticatorConfig;
protected BaseAuthenticator(IAuthenticatorConfig authenticatorConfig)
{
AuthenticatorConfig = authenticatorConfig;
}
}
}

View File

@@ -7,44 +7,45 @@ using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.Models.Authentication;
namespace Wino.Authentication;
public class GmailAuthenticator : BaseAuthenticator, IGmailAuthenticator
namespace Wino.Authentication
{
public GmailAuthenticator(IAuthenticatorConfig authConfig) : base(authConfig)
public class GmailAuthenticator : BaseAuthenticator, IGmailAuthenticator
{
}
public string ClientId => AuthenticatorConfig.GmailAuthenticatorClientId;
public bool ProposeCopyAuthURL { get; set; }
public override MailProviderType ProviderType => MailProviderType.Gmail;
/// <summary>
/// Generates the token information for the given account.
/// For gmail, interactivity is automatically handled when you get the token.
/// </summary>
/// <param name="account">Account to get token for.</param>
public Task<TokenInformationEx> GenerateTokenInformationAsync(MailAccount account)
=> GetTokenInformationAsync(account);
public async Task<TokenInformationEx> GetTokenInformationAsync(MailAccount account)
{
var userCredential = await GetGoogleUserCredentialAsync(account);
if (userCredential.Token.IsStale)
public GmailAuthenticator(IAuthenticatorConfig authConfig) : base(authConfig)
{
await userCredential.RefreshTokenAsync(CancellationToken.None);
}
return new TokenInformationEx(userCredential.Token.AccessToken, account.Address);
}
public string ClientId => AuthenticatorConfig.GmailAuthenticatorClientId;
public bool ProposeCopyAuthURL { get; set; }
private Task<UserCredential> GetGoogleUserCredentialAsync(MailAccount account)
{
return GoogleWebAuthorizationBroker.AuthorizeAsync(new ClientSecrets()
public override MailProviderType ProviderType => MailProviderType.Gmail;
/// <summary>
/// Generates the token information for the given account.
/// For gmail, interactivity is automatically handled when you get the token.
/// </summary>
/// <param name="account">Account to get token for.</param>
public Task<TokenInformationEx> GenerateTokenInformationAsync(MailAccount account)
=> GetTokenInformationAsync(account);
public async Task<TokenInformationEx> GetTokenInformationAsync(MailAccount account)
{
ClientId = ClientId
}, AuthenticatorConfig.GmailScope, account.Id.ToString(), CancellationToken.None, new FileDataStore(AuthenticatorConfig.GmailTokenStoreIdentifier));
var userCredential = await GetGoogleUserCredentialAsync(account);
if (userCredential.Token.IsStale)
{
await userCredential.RefreshTokenAsync(CancellationToken.None);
}
return new TokenInformationEx(userCredential.Token.AccessToken, account.Address);
}
private Task<UserCredential> GetGoogleUserCredentialAsync(MailAccount account)
{
return GoogleWebAuthorizationBroker.AuthorizeAsync(new ClientSecrets()
{
ClientId = ClientId
}, AuthenticatorConfig.GmailScope, account.Id.ToString(), CancellationToken.None, new FileDataStore(AuthenticatorConfig.GmailTokenStoreIdentifier));
}
}
}

View File

@@ -11,115 +11,116 @@ using Wino.Core.Domain.Exceptions;
using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.Models.Authentication;
namespace Wino.Authentication;
public class OutlookAuthenticator : BaseAuthenticator, IOutlookAuthenticator
namespace Wino.Authentication
{
private const string TokenCacheFileName = "OutlookCache.bin";
private bool isTokenCacheAttached = false;
// Outlook
private const string Authority = "https://login.microsoftonline.com/common";
public override MailProviderType ProviderType => MailProviderType.Outlook;
private readonly IPublicClientApplication _publicClientApplication;
private readonly IApplicationConfiguration _applicationConfiguration;
public OutlookAuthenticator(INativeAppService nativeAppService,
IApplicationConfiguration applicationConfiguration,
IAuthenticatorConfig authenticatorConfig) : base(authenticatorConfig)
public class OutlookAuthenticator : BaseAuthenticator, IOutlookAuthenticator
{
_applicationConfiguration = applicationConfiguration;
private const string TokenCacheFileName = "OutlookCache.bin";
private bool isTokenCacheAttached = false;
var authenticationRedirectUri = nativeAppService.GetWebAuthenticationBrokerUri();
// Outlook
private const string Authority = "https://login.microsoftonline.com/common";
var options = new BrokerOptions(BrokerOptions.OperatingSystems.Windows)
public override MailProviderType ProviderType => MailProviderType.Outlook;
private readonly IPublicClientApplication _publicClientApplication;
private readonly IApplicationConfiguration _applicationConfiguration;
public OutlookAuthenticator(INativeAppService nativeAppService,
IApplicationConfiguration applicationConfiguration,
IAuthenticatorConfig authenticatorConfig) : base(authenticatorConfig)
{
Title = "Wino Mail",
ListOperatingSystemAccounts = true,
};
_applicationConfiguration = applicationConfiguration;
var outlookAppBuilder = PublicClientApplicationBuilder.Create(AuthenticatorConfig.OutlookAuthenticatorClientId)
.WithParentActivityOrWindow(nativeAppService.GetCoreWindowHwnd)
.WithBroker(options)
.WithDefaultRedirectUri()
.WithAuthority(Authority);
var authenticationRedirectUri = nativeAppService.GetWebAuthenticationBrokerUri();
_publicClientApplication = outlookAppBuilder.Build();
}
var options = new BrokerOptions(BrokerOptions.OperatingSystems.Windows)
{
Title = "Wino Mail",
ListOperatingSystemAccounts = true,
};
public string[] Scope => AuthenticatorConfig.OutlookScope;
var outlookAppBuilder = PublicClientApplicationBuilder.Create(AuthenticatorConfig.OutlookAuthenticatorClientId)
.WithParentActivityOrWindow(nativeAppService.GetCoreWindowHwnd)
.WithBroker(options)
.WithDefaultRedirectUri()
.WithAuthority(Authority);
private async Task EnsureTokenCacheAttachedAsync()
{
if (!isTokenCacheAttached)
{
var storageProperties = new StorageCreationPropertiesBuilder(TokenCacheFileName, _applicationConfiguration.PublisherSharedFolderPath).Build();
var msalcachehelper = await MsalCacheHelper.CreateAsync(storageProperties);
msalcachehelper.RegisterCache(_publicClientApplication.UserTokenCache);
isTokenCacheAttached = true;
_publicClientApplication = outlookAppBuilder.Build();
}
}
public async Task<TokenInformationEx> GetTokenInformationAsync(MailAccount account)
{
await EnsureTokenCacheAttachedAsync();
public string[] Scope => AuthenticatorConfig.OutlookScope;
var storedAccount = (await _publicClientApplication.GetAccountsAsync()).FirstOrDefault(a => a.Username == account.Address);
if (storedAccount == null)
return await GenerateTokenInformationAsync(account);
try
private async Task EnsureTokenCacheAttachedAsync()
{
var authResult = await _publicClientApplication.AcquireTokenSilent(Scope, storedAccount).ExecuteAsync();
if (!isTokenCacheAttached)
{
var storageProperties = new StorageCreationPropertiesBuilder(TokenCacheFileName, _applicationConfiguration.PublisherSharedFolderPath).Build();
var msalcachehelper = await MsalCacheHelper.CreateAsync(storageProperties);
msalcachehelper.RegisterCache(_publicClientApplication.UserTokenCache);
return new TokenInformationEx(authResult.AccessToken, authResult.Account.Username);
isTokenCacheAttached = true;
}
}
catch (MsalUiRequiredException)
{
// Somehow MSAL is not able to refresh the token silently.
// Force interactive login.
return await GenerateTokenInformationAsync(account);
}
catch (Exception)
{
throw;
}
}
public async Task<TokenInformationEx> GenerateTokenInformationAsync(MailAccount account)
{
try
public async Task<TokenInformationEx> GetTokenInformationAsync(MailAccount account)
{
await EnsureTokenCacheAttachedAsync();
var authResult = await _publicClientApplication
.AcquireTokenInteractive(Scope)
.ExecuteAsync();
var storedAccount = (await _publicClientApplication.GetAccountsAsync()).FirstOrDefault(a => a.Username == account.Address);
// If the account is null, it means it's the initial creation of it.
// If not, make sure the authenticated user address matches the username.
// When people refresh their token, accounts must match.
if (storedAccount == null)
return await GenerateTokenInformationAsync(account);
if (account?.Address != null && !account.Address.Equals(authResult.Account.Username, StringComparison.OrdinalIgnoreCase))
try
{
throw new AuthenticationException("Authenticated address does not match with your account address.");
var authResult = await _publicClientApplication.AcquireTokenSilent(Scope, storedAccount).ExecuteAsync();
return new TokenInformationEx(authResult.AccessToken, authResult.Account.Username);
}
catch (MsalUiRequiredException)
{
// Somehow MSAL is not able to refresh the token silently.
// Force interactive login.
return await GenerateTokenInformationAsync(account);
}
catch (Exception)
{
throw;
}
}
public async Task<TokenInformationEx> GenerateTokenInformationAsync(MailAccount account)
{
try
{
await EnsureTokenCacheAttachedAsync();
var authResult = await _publicClientApplication
.AcquireTokenInteractive(Scope)
.ExecuteAsync();
// If the account is null, it means it's the initial creation of it.
// If not, make sure the authenticated user address matches the username.
// When people refresh their token, accounts must match.
if (account?.Address != null && !account.Address.Equals(authResult.Account.Username, StringComparison.OrdinalIgnoreCase))
{
throw new AuthenticationException("Authenticated address does not match with your account address.");
}
return new TokenInformationEx(authResult.AccessToken, authResult.Account.Username);
}
catch (MsalClientException msalClientException)
{
if (msalClientException.ErrorCode == "authentication_canceled" || msalClientException.ErrorCode == "access_denied")
throw new AccountSetupCanceledException();
throw;
}
return new TokenInformationEx(authResult.AccessToken, authResult.Account.Username);
throw new AuthenticationException(Translator.Exception_UnknowErrorDuringAuthentication, new Exception(Translator.Exception_TokenGenerationFailed));
}
catch (MsalClientException msalClientException)
{
if (msalClientException.ErrorCode == "authentication_canceled" || msalClientException.ErrorCode == "access_denied")
throw new AccountSetupCanceledException();
throw;
}
throw new AuthenticationException(Translator.Exception_UnknowErrorDuringAuthentication, new Exception(Translator.Exception_TokenGenerationFailed));
}
}