Skip to content

Commit

Permalink
file scoped namespaces (#565)
Browse files Browse the repository at this point in the history
  • Loading branch information
Tiktack authored Feb 16, 2025
1 parent cf9869b commit 3ddc1a6
Show file tree
Hide file tree
Showing 617 changed files with 27,798 additions and 28,412 deletions.
6 changes: 4 additions & 2 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ csharp_preferred_modifier_order = public,private,protected,internal,static,exter
# Code-block preferences
csharp_prefer_braces = true:silent
csharp_prefer_simple_using_statement = true:suggestion
csharp_style_namespace_declarations = block_scoped:silent
csharp_style_namespace_declarations = file_scoped:error

# Expression-level preferences
csharp_prefer_simple_default_expression = true:suggestion
Expand Down Expand Up @@ -287,4 +287,6 @@ csharp_style_prefer_top_level_statements = true:silent
csharp_style_prefer_utf8_string_literals = true:suggestion
csharp_style_prefer_readonly_struct = true:suggestion
csharp_style_allow_blank_line_after_token_in_conditional_expression_experimental = true:silent
csharp_style_allow_blank_line_after_token_in_arrow_expression_clause_experimental = true:silent
csharp_style_allow_blank_line_after_token_in_arrow_expression_clause_experimental = true:silent
csharp_style_prefer_primary_constructors = true:silent
csharp_prefer_system_threading_lock = true:suggestion
17 changes: 8 additions & 9 deletions Wino.Authentication/BaseAuthenticator.cs
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Interfaces;

namespace Wino.Authentication
namespace Wino.Authentication;

public abstract class BaseAuthenticator
{
public abstract class BaseAuthenticator
{
public abstract MailProviderType ProviderType { get; }
protected IAuthenticatorConfig AuthenticatorConfig { get; }
public abstract MailProviderType ProviderType { get; }
protected IAuthenticatorConfig AuthenticatorConfig { get; }

protected BaseAuthenticator(IAuthenticatorConfig authenticatorConfig)
{
protected BaseAuthenticator(IAuthenticatorConfig authenticatorConfig)
{

AuthenticatorConfig = authenticatorConfig;
}
AuthenticatorConfig = authenticatorConfig;
}
}
59 changes: 29 additions & 30 deletions Wino.Authentication/GmailAuthenticator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,45 +7,44 @@
using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.Models.Authentication;

namespace Wino.Authentication
namespace Wino.Authentication;

public class GmailAuthenticator : BaseAuthenticator, IGmailAuthenticator
{
public class GmailAuthenticator : BaseAuthenticator, IGmailAuthenticator
public GmailAuthenticator(IAuthenticatorConfig authConfig) : base(authConfig)
{
public GmailAuthenticator(IAuthenticatorConfig authConfig) : base(authConfig)
{
}

public string ClientId => AuthenticatorConfig.GmailAuthenticatorClientId;
public bool ProposeCopyAuthURL { get; set; }
}

public override MailProviderType ProviderType => MailProviderType.Gmail;
public string ClientId => AuthenticatorConfig.GmailAuthenticatorClientId;
public bool ProposeCopyAuthURL { get; set; }

/// <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 override MailProviderType ProviderType => MailProviderType.Gmail;

public async Task<TokenInformationEx> GetTokenInformationAsync(MailAccount account)
{
var userCredential = await GetGoogleUserCredentialAsync(account);
/// <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);

if (userCredential.Token.IsStale)
{
await userCredential.RefreshTokenAsync(CancellationToken.None);
}
public async Task<TokenInformationEx> GetTokenInformationAsync(MailAccount account)
{
var userCredential = await GetGoogleUserCredentialAsync(account);

return new TokenInformationEx(userCredential.Token.AccessToken, account.Address);
if (userCredential.Token.IsStale)
{
await userCredential.RefreshTokenAsync(CancellationToken.None);
}

private Task<UserCredential> GetGoogleUserCredentialAsync(MailAccount account)
return new TokenInformationEx(userCredential.Token.AccessToken, account.Address);
}

private Task<UserCredential> GetGoogleUserCredentialAsync(MailAccount account)
{
return GoogleWebAuthorizationBroker.AuthorizeAsync(new ClientSecrets()
{
return GoogleWebAuthorizationBroker.AuthorizeAsync(new ClientSecrets()
{
ClientId = ClientId
}, AuthenticatorConfig.GmailScope, account.Id.ToString(), CancellationToken.None, new FileDataStore(AuthenticatorConfig.GmailTokenStoreIdentifier));
}
ClientId = ClientId
}, AuthenticatorConfig.GmailScope, account.Id.ToString(), CancellationToken.None, new FileDataStore(AuthenticatorConfig.GmailTokenStoreIdentifier));
}
}
161 changes: 80 additions & 81 deletions Wino.Authentication/OutlookAuthenticator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,116 +11,115 @@
using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.Models.Authentication;

namespace Wino.Authentication
namespace Wino.Authentication;

public class OutlookAuthenticator : BaseAuthenticator, IOutlookAuthenticator
{
public class OutlookAuthenticator : BaseAuthenticator, IOutlookAuthenticator
{
private const string TokenCacheFileName = "OutlookCache.bin";
private bool isTokenCacheAttached = false;
private const string TokenCacheFileName = "OutlookCache.bin";
private bool isTokenCacheAttached = false;

// Outlook
private const string Authority = "https://login.microsoftonline.com/common";
// Outlook
private const string Authority = "https://login.microsoftonline.com/common";

public override MailProviderType ProviderType => MailProviderType.Outlook;
public override MailProviderType ProviderType => MailProviderType.Outlook;

private readonly IPublicClientApplication _publicClientApplication;
private readonly IApplicationConfiguration _applicationConfiguration;
private readonly IPublicClientApplication _publicClientApplication;
private readonly IApplicationConfiguration _applicationConfiguration;

public OutlookAuthenticator(INativeAppService nativeAppService,
IApplicationConfiguration applicationConfiguration,
IAuthenticatorConfig authenticatorConfig) : base(authenticatorConfig)
{
_applicationConfiguration = applicationConfiguration;
public OutlookAuthenticator(INativeAppService nativeAppService,
IApplicationConfiguration applicationConfiguration,
IAuthenticatorConfig authenticatorConfig) : base(authenticatorConfig)
{
_applicationConfiguration = applicationConfiguration;

var authenticationRedirectUri = nativeAppService.GetWebAuthenticationBrokerUri();
var authenticationRedirectUri = nativeAppService.GetWebAuthenticationBrokerUri();

var options = new BrokerOptions(BrokerOptions.OperatingSystems.Windows)
{
Title = "Wino Mail",
ListOperatingSystemAccounts = true,
};
var options = new BrokerOptions(BrokerOptions.OperatingSystems.Windows)
{
Title = "Wino Mail",
ListOperatingSystemAccounts = true,
};

var outlookAppBuilder = PublicClientApplicationBuilder.Create(AuthenticatorConfig.OutlookAuthenticatorClientId)
.WithParentActivityOrWindow(nativeAppService.GetCoreWindowHwnd)
.WithBroker(options)
.WithDefaultRedirectUri()
.WithAuthority(Authority);
var outlookAppBuilder = PublicClientApplicationBuilder.Create(AuthenticatorConfig.OutlookAuthenticatorClientId)
.WithParentActivityOrWindow(nativeAppService.GetCoreWindowHwnd)
.WithBroker(options)
.WithDefaultRedirectUri()
.WithAuthority(Authority);

_publicClientApplication = outlookAppBuilder.Build();
}
_publicClientApplication = outlookAppBuilder.Build();
}

public string[] Scope => AuthenticatorConfig.OutlookScope;
public string[] Scope => AuthenticatorConfig.OutlookScope;

private async Task EnsureTokenCacheAttachedAsync()
private async Task EnsureTokenCacheAttachedAsync()
{
if (!isTokenCacheAttached)
{
if (!isTokenCacheAttached)
{
var storageProperties = new StorageCreationPropertiesBuilder(TokenCacheFileName, _applicationConfiguration.PublisherSharedFolderPath).Build();
var msalcachehelper = await MsalCacheHelper.CreateAsync(storageProperties);
msalcachehelper.RegisterCache(_publicClientApplication.UserTokenCache);
var storageProperties = new StorageCreationPropertiesBuilder(TokenCacheFileName, _applicationConfiguration.PublisherSharedFolderPath).Build();
var msalcachehelper = await MsalCacheHelper.CreateAsync(storageProperties);
msalcachehelper.RegisterCache(_publicClientApplication.UserTokenCache);

isTokenCacheAttached = true;
}
isTokenCacheAttached = true;
}
}

public async Task<TokenInformationEx> GetTokenInformationAsync(MailAccount account)
{
await EnsureTokenCacheAttachedAsync();

var storedAccount = (await _publicClientApplication.GetAccountsAsync()).FirstOrDefault(a => a.Username == account.Address);
public async Task<TokenInformationEx> GetTokenInformationAsync(MailAccount account)
{
await EnsureTokenCacheAttachedAsync();

if (storedAccount == null)
return await GenerateTokenInformationAsync(account);
var storedAccount = (await _publicClientApplication.GetAccountsAsync()).FirstOrDefault(a => a.Username == account.Address);

try
{
var authResult = await _publicClientApplication.AcquireTokenSilent(Scope, storedAccount).ExecuteAsync();
if (storedAccount == null)
return await GenerateTokenInformationAsync(account);

return new TokenInformationEx(authResult.AccessToken, authResult.Account.Username);
}
catch (MsalUiRequiredException)
{
// Somehow MSAL is not able to refresh the token silently.
// Force interactive login.
try
{
var authResult = await _publicClientApplication.AcquireTokenSilent(Scope, storedAccount).ExecuteAsync();

return await GenerateTokenInformationAsync(account);
}
catch (Exception)
{
throw;
}
return new TokenInformationEx(authResult.AccessToken, authResult.Account.Username);
}
catch (MsalUiRequiredException)
{
// Somehow MSAL is not able to refresh the token silently.
// Force interactive login.

public async Task<TokenInformationEx> GenerateTokenInformationAsync(MailAccount account)
return await GenerateTokenInformationAsync(account);
}
catch (Exception)
{
try
{
await EnsureTokenCacheAttachedAsync();
throw;
}
}

var authResult = await _publicClientApplication
.AcquireTokenInteractive(Scope)
.ExecuteAsync();
public async Task<TokenInformationEx> GenerateTokenInformationAsync(MailAccount account)
{
try
{
await EnsureTokenCacheAttachedAsync();

// 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.
var authResult = await _publicClientApplication
.AcquireTokenInteractive(Scope)
.ExecuteAsync();

if (account?.Address != null && !account.Address.Equals(authResult.Account.Username, StringComparison.OrdinalIgnoreCase))
{
throw new AuthenticationException("Authenticated address does not match with your 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.

return new TokenInformationEx(authResult.AccessToken, authResult.Account.Username);
}
catch (MsalClientException msalClientException)
if (account?.Address != null && !account.Address.Equals(authResult.Account.Username, StringComparison.OrdinalIgnoreCase))
{
if (msalClientException.ErrorCode == "authentication_canceled" || msalClientException.ErrorCode == "access_denied")
throw new AccountSetupCanceledException();

throw;
throw new AuthenticationException("Authenticated address does not match with your account address.");
}

throw new AuthenticationException(Translator.Exception_UnknowErrorDuringAuthentication, new Exception(Translator.Exception_TokenGenerationFailed));
return new TokenInformationEx(authResult.AccessToken, authResult.Account.Username);
}
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));
}
}
49 changes: 24 additions & 25 deletions Wino.Calendar/Services/CalendarAuthenticatorConfig.cs
Original file line number Diff line number Diff line change
@@ -1,33 +1,32 @@
using Wino.Core.Domain.Interfaces;

namespace Wino.Calendar.Services
namespace Wino.Calendar.Services;

public class CalendarAuthenticatorConfig : IAuthenticatorConfig
{
public class CalendarAuthenticatorConfig : IAuthenticatorConfig
{
public string OutlookAuthenticatorClientId => "b19c2035-d740-49ff-b297-de6ec561b208";
public string OutlookAuthenticatorClientId => "b19c2035-d740-49ff-b297-de6ec561b208";

public string[] OutlookScope => new string[]
{
"Calendars.Read",
"Calendars.Read.Shared",
"offline_access",
"Calendars.ReadBasic",
"Calendars.ReadWrite",
"Calendars.ReadWrite.Shared",
"User.Read"
};
public string[] OutlookScope => new string[]
{
"Calendars.Read",
"Calendars.Read.Shared",
"offline_access",
"Calendars.ReadBasic",
"Calendars.ReadWrite",
"Calendars.ReadWrite.Shared",
"User.Read"
};

public string GmailAuthenticatorClientId => "973025879644-s7b4ur9p3rlgop6a22u7iuptdc0brnrn.apps.googleusercontent.com";
public string GmailAuthenticatorClientId => "973025879644-s7b4ur9p3rlgop6a22u7iuptdc0brnrn.apps.googleusercontent.com";

public string[] GmailScope => new string[]
{
"https://www.googleapis.com/auth/calendar",
"https://www.googleapis.com/auth/calendar.events",
"https://www.googleapis.com/auth/calendar.settings.readonly",
"https://www.googleapis.com/auth/userinfo.profile",
"https://www.googleapis.com/auth/userinfo.email"
};
public string[] GmailScope => new string[]
{
"https://www.googleapis.com/auth/calendar",
"https://www.googleapis.com/auth/calendar.events",
"https://www.googleapis.com/auth/calendar.settings.readonly",
"https://www.googleapis.com/auth/userinfo.profile",
"https://www.googleapis.com/auth/userinfo.email"
};

public string GmailTokenStoreIdentifier => "WinoCalendarGmailTokenStore";
}
public string GmailTokenStoreIdentifier => "WinoCalendarGmailTokenStore";
}
Loading

0 comments on commit 3ddc1a6

Please sign in to comment.