From e7f711dbfddcba7c241a803c7a8500c8c60fbc4e Mon Sep 17 00:00:00 2001 From: "daniele.corsini@corsinvest.it" Date: Fri, 14 Jul 2023 16:07:07 +0200 Subject: [PATCH] Improve code --- .../Corsinvest.AppHero.AppBss.csproj | 6 +- src/Corsinvest.AppHero.AppBss/Program.cs | 8 +- .../Corsinvest.AppHero.Auditing.csproj | 2 +- .../AutenticationActiveDirectory.cs | 2 +- .../Corsinvest.AppHero.Authentication.csproj | 6 +- .../OAuth/Controllers/OAuthController.cs | 3 +- .../OptionsBase.cs | 3 + .../Corsinvest.AppHero.Core.FluentUI.csproj | 2 +- ...Corsinvest.AppHero.Core.MudBlazorUI.csproj | 10 +-- .../Extensions/ModularityExtensions.cs | 4 +- .../Module.cs | 1 - .../Pages/Security/Profile.razor.cs | 15 +--- .../Pages/Security/RolePermissions.razor.cs | 2 +- .../Pages/Security/Users.razor.cs | 11 +-- .../Components/AHPasswordsInput.razor.cs | 4 +- .../Shared/Components/AHUserMenu.razor.cs | 2 +- .../Shared/NavMenu.razor | 19 ++-- .../Corsinvest.AppHero.Core.RazdenUI.csproj | 2 +- .../Corsinvest.AppHero.Core.csproj | 12 +-- .../Extensions/LoggerExtensions.cs | 2 +- ...eExtensions.cs => ModularityExtensions.cs} | 9 +- .../Helpers/ApplicationHelper.cs | 1 + .../Helpers/CryptographyHelper.cs | 27 +++--- src/Corsinvest.AppHero.Core/Hubs/HubClient.cs | 2 +- .../Modularity/IModularityService.cs | 4 +- .../Modularity/ModularityService.cs | 17 +--- .../Modularity/ModuleBase.cs | 2 - .../Modularity/ModuleCategory.cs | 20 +++++ .../Security/Auth/AccessTokenProvider.cs | 47 ++++++++++ .../Security/Auth/AccountController.cs | 80 ----------------- .../Security/Auth/AuthenticationService.cs | 88 ++++++++++++------- .../Auth/BlazorCookieLoginMiddleware.cs | 80 +++++++++++++++++ .../Security/Auth/CurrentUserService.cs | 14 +++ .../Security/Auth/IAuthenticationService.cs | 3 +- .../Security/Auth/ICurrentUserService.cs | 1 + .../Security/Identity/IIdentityService.cs | 6 +- .../Security/Identity/IdentityService.cs | 66 ++++++++++++++ .../Security/Module.cs | 37 +++++++- .../Corsinvest.AppHero.HangFire.csproj | 4 +- .../JobActivatorEx.cs | 2 +- .../Corsinvest.AppHero.Localization.csproj | 8 +- ...invest.AppHero.Notification.Discord.csproj | 2 +- .../Corsinvest.AppHero.Serilog.csproj | 4 +- .../Google/Translator.cs | 2 +- .../Microsoft/Translator.cs | 2 +- src/common.props | 2 +- 46 files changed, 419 insertions(+), 227 deletions(-) rename src/Corsinvest.AppHero.Core/Extensions/{ModuleExtensions.cs => ModularityExtensions.cs} (81%) create mode 100644 src/Corsinvest.AppHero.Core/Modularity/ModuleCategory.cs create mode 100644 src/Corsinvest.AppHero.Core/Security/Auth/AccessTokenProvider.cs delete mode 100644 src/Corsinvest.AppHero.Core/Security/Auth/AccountController.cs create mode 100644 src/Corsinvest.AppHero.Core/Security/Auth/BlazorCookieLoginMiddleware.cs diff --git a/src/Corsinvest.AppHero.AppBss/Corsinvest.AppHero.AppBss.csproj b/src/Corsinvest.AppHero.AppBss/Corsinvest.AppHero.AppBss.csproj index 14d9907..705e718 100644 --- a/src/Corsinvest.AppHero.AppBss/Corsinvest.AppHero.AppBss.csproj +++ b/src/Corsinvest.AppHero.AppBss/Corsinvest.AppHero.AppBss.csproj @@ -8,14 +8,14 @@ - + - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Corsinvest.AppHero.AppBss/Program.cs b/src/Corsinvest.AppHero.AppBss/Program.cs index c80357c..c20dbe6 100644 --- a/src/Corsinvest.AppHero.AppBss/Program.cs +++ b/src/Corsinvest.AppHero.AppBss/Program.cs @@ -10,6 +10,7 @@ using Corsinvest.AppHero.Core.SoftwareUpdater; using Microsoft.AspNetCore.DataProtection; using Microsoft.AspNetCore.Http.Connections; +using Microsoft.AspNetCore.HttpOverrides; using Serilog; //appsetting default @@ -83,7 +84,12 @@ #endregion } -app.UseHttpsRedirection(); +//app.UseHttpsRedirection(); + +app.UseForwardedHeaders(new ForwardedHeadersOptions +{ + ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto +}); app.UseRouting(); diff --git a/src/Corsinvest.AppHero.Auditing/Corsinvest.AppHero.Auditing.csproj b/src/Corsinvest.AppHero.Auditing/Corsinvest.AppHero.Auditing.csproj index c03cc96..e5bddb1 100644 --- a/src/Corsinvest.AppHero.Auditing/Corsinvest.AppHero.Auditing.csproj +++ b/src/Corsinvest.AppHero.Auditing/Corsinvest.AppHero.Auditing.csproj @@ -7,7 +7,7 @@ - + diff --git a/src/Corsinvest.AppHero.Authentication/ActiveDirectory/AutenticationActiveDirectory.cs b/src/Corsinvest.AppHero.Authentication/ActiveDirectory/AutenticationActiveDirectory.cs index a886e20..0e7f482 100644 --- a/src/Corsinvest.AppHero.Authentication/ActiveDirectory/AutenticationActiveDirectory.cs +++ b/src/Corsinvest.AppHero.Authentication/ActiveDirectory/AutenticationActiveDirectory.cs @@ -126,7 +126,7 @@ public async Task> LoginAsync(LoginRequestAD loginRequestAD) } //redirect to login - if (ret.IsSuccess) { await _autentication.ExecuteLoginAsync(user!, loginRequestAD.RememberMe); } + if (ret.IsSuccess) { await _autentication.LoginAsync(loginRequestAD); } } } } diff --git a/src/Corsinvest.AppHero.Authentication/Corsinvest.AppHero.Authentication.csproj b/src/Corsinvest.AppHero.Authentication/Corsinvest.AppHero.Authentication.csproj index 534c0ef..4fc880e 100644 --- a/src/Corsinvest.AppHero.Authentication/Corsinvest.AppHero.Authentication.csproj +++ b/src/Corsinvest.AppHero.Authentication/Corsinvest.AppHero.Authentication.csproj @@ -7,9 +7,9 @@ - - - + + + diff --git a/src/Corsinvest.AppHero.Authentication/OAuth/Controllers/OAuthController.cs b/src/Corsinvest.AppHero.Authentication/OAuth/Controllers/OAuthController.cs index faa6591..a5d7685 100644 --- a/src/Corsinvest.AppHero.Authentication/OAuth/Controllers/OAuthController.cs +++ b/src/Corsinvest.AppHero.Authentication/OAuth/Controllers/OAuthController.cs @@ -44,7 +44,8 @@ public IActionResult Challenge(string provider) ["returnUrl"] = "/" , ["scheme"] = provider , } - }, provider); + }, + provider); [AllowAnonymous] diff --git a/src/Corsinvest.AppHero.Authentication/OptionsBase.cs b/src/Corsinvest.AppHero.Authentication/OptionsBase.cs index 0223a57..fd132ac 100644 --- a/src/Corsinvest.AppHero.Authentication/OptionsBase.cs +++ b/src/Corsinvest.AppHero.Authentication/OptionsBase.cs @@ -4,11 +4,14 @@ */ using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication.OAuth.Claims; +using System.ComponentModel.DataAnnotations; +using System.Xml.Linq; namespace Corsinvest.AppHero.Authentication; public class OptionsBase { + [Display(Name = "Default Roles New User must be separated with a comma character (\",\")")] public string DefaultRolesNewUser { get; set; } = default!; public bool AutoImportUser { get; set; } = true; diff --git a/src/Corsinvest.AppHero.Core.FluentUI/Corsinvest.AppHero.Core.FluentUI.csproj b/src/Corsinvest.AppHero.Core.FluentUI/Corsinvest.AppHero.Core.FluentUI.csproj index 1cebf8e..1c198e7 100644 --- a/src/Corsinvest.AppHero.Core.FluentUI/Corsinvest.AppHero.Core.FluentUI.csproj +++ b/src/Corsinvest.AppHero.Core.FluentUI/Corsinvest.AppHero.Core.FluentUI.csproj @@ -7,7 +7,7 @@ - + diff --git a/src/Corsinvest.AppHero.Core.MudBlazorUI/Corsinvest.AppHero.Core.MudBlazorUI.csproj b/src/Corsinvest.AppHero.Core.MudBlazorUI/Corsinvest.AppHero.Core.MudBlazorUI.csproj index 4c7eed1..a82c8e1 100644 --- a/src/Corsinvest.AppHero.Core.MudBlazorUI/Corsinvest.AppHero.Core.MudBlazorUI.csproj +++ b/src/Corsinvest.AppHero.Core.MudBlazorUI/Corsinvest.AppHero.Core.MudBlazorUI.csproj @@ -7,12 +7,12 @@ - - - - + + + + - + diff --git a/src/Corsinvest.AppHero.Core.MudBlazorUI/Extensions/ModularityExtensions.cs b/src/Corsinvest.AppHero.Core.MudBlazorUI/Extensions/ModularityExtensions.cs index 8c3eeb1..8351d66 100644 --- a/src/Corsinvest.AppHero.Core.MudBlazorUI/Extensions/ModularityExtensions.cs +++ b/src/Corsinvest.AppHero.Core.MudBlazorUI/Extensions/ModularityExtensions.cs @@ -8,8 +8,8 @@ namespace Corsinvest.AppHero.Core.MudBlazorUI.Extensions; public static class ModularityExtensions { - public static string ToMBIcon(this IModularityService modularityService, string category) - => MudBlazorHelper.ToMBIcon(modularityService.GetCategoryIcon(category)!); + public static string ToMBIcon(this IModularityService modularityService, string category) + => MudBlazorHelper.ToMBIcon(modularityService.GetCategoryIcon(category)); public static string ToMBIcon(this IGroupableService groupableService) => MudBlazorHelper.ToMBIcon(groupableService.GetGroupIcon()); public static string ToMBIcon(this ModuleMenuItem menuItem) => MudBlazorHelper.ToMBIcon(menuItem.Icon); diff --git a/src/Corsinvest.AppHero.Core.MudBlazorUI/Module.cs b/src/Corsinvest.AppHero.Core.MudBlazorUI/Module.cs index 1f50be1..deb532b 100644 --- a/src/Corsinvest.AppHero.Core.MudBlazorUI/Module.cs +++ b/src/Corsinvest.AppHero.Core.MudBlazorUI/Module.cs @@ -40,7 +40,6 @@ public override void ConfigureServices(IServiceCollection services, IConfigurati services.AddScoped(); services.AddScoped(); services.AddMudExtensions(); - services.AddMudServicesWithExtensions(); services.AddScoped(); services.AddTransient(typeof(IDataGridManager<>), typeof(DataGridManager<>)); services.AddTransient(typeof(IDataGridManagerRepository<>), typeof(DataGridManagerRepository<>)); diff --git a/src/Corsinvest.AppHero.Core.MudBlazorUI/Pages/Security/Profile.razor.cs b/src/Corsinvest.AppHero.Core.MudBlazorUI/Pages/Security/Profile.razor.cs index 6057690..9b8ca70 100644 --- a/src/Corsinvest.AppHero.Core.MudBlazorUI/Pages/Security/Profile.razor.cs +++ b/src/Corsinvest.AppHero.Core.MudBlazorUI/Pages/Security/Profile.razor.cs @@ -33,16 +33,7 @@ private async Task UpdateUserAsync() var result = await UserManager.UpdateAsync(User); UINotifier.Show(result.Succeeded, L["Update successfully."], result.ToStringErrors()); - if (result.Succeeded) - { - //reload page for change language - NavigationManager.NavigateTo(UrlHelper.SetParameter("/api/account/setculture", - new() - { - { "culture", User.DefaultCulture}, - { "redirectUri", NavigationManager.Uri} - }), true); - } + if (result.Succeeded) { CurrentUserService.SetCulture(User.DefaultCulture, NavigationManager.Uri); } } } @@ -57,14 +48,14 @@ private async Task ChangePasswordAsync() } } - private class ChangePasswordModel + class ChangePasswordModel { public string CurrentPassword { get; set; } = string.Empty; public string NewPassword { get; set; } = string.Empty; public string ConfirmPassword { get; set; } = string.Empty; } - private class PasswordFluentValidator : AbstractModelValidator + class PasswordFluentValidator : AbstractModelValidator { public PasswordFluentValidator(Core.Security.Identity.Options identityOptions) { diff --git a/src/Corsinvest.AppHero.Core.MudBlazorUI/Pages/Security/RolePermissions.razor.cs b/src/Corsinvest.AppHero.Core.MudBlazorUI/Pages/Security/RolePermissions.razor.cs index 0edbb38..b521866 100644 --- a/src/Corsinvest.AppHero.Core.MudBlazorUI/Pages/Security/RolePermissions.razor.cs +++ b/src/Corsinvest.AppHero.Core.MudBlazorUI/Pages/Security/RolePermissions.razor.cs @@ -13,7 +13,7 @@ public partial class RolePermissions [Inject] private IModularityService ModularityService { get; set; } = default!; - private class TreeDataPermission + class TreeDataPermission { public string? Key { get; set; } public string Path { get; set; } = default!; diff --git a/src/Corsinvest.AppHero.Core.MudBlazorUI/Pages/Security/Users.razor.cs b/src/Corsinvest.AppHero.Core.MudBlazorUI/Pages/Security/Users.razor.cs index 1766846..93b9db8 100644 --- a/src/Corsinvest.AppHero.Core.MudBlazorUI/Pages/Security/Users.razor.cs +++ b/src/Corsinvest.AppHero.Core.MudBlazorUI/Pages/Security/Users.razor.cs @@ -51,16 +51,7 @@ protected override void OnInitialized() DataGridManager.SaveAfterAsync = async (user, isNew) => { await Task.CompletedTask; - if (user.Id == CurrentUserService.UserId) - { - //reload page for change language - NavigationManager.NavigateTo(UrlHelper.SetParameter("/api/account/setculture", - new() - { - { "culture", user.DefaultCulture}, - { "redirectUri", NavigationManager.Uri} - }), true); - } + if (user.Id == CurrentUserService.UserId) { CurrentUserService.SetCulture(user.DefaultCulture, NavigationManager.Uri); } }; DataGridManager.DeleteAsync = async (items) => diff --git a/src/Corsinvest.AppHero.Core.MudBlazorUI/Shared/Components/AHPasswordsInput.razor.cs b/src/Corsinvest.AppHero.Core.MudBlazorUI/Shared/Components/AHPasswordsInput.razor.cs index 81db5d8..40b8074 100644 --- a/src/Corsinvest.AppHero.Core.MudBlazorUI/Shared/Components/AHPasswordsInput.razor.cs +++ b/src/Corsinvest.AppHero.Core.MudBlazorUI/Shared/Components/AHPasswordsInput.razor.cs @@ -19,7 +19,7 @@ public partial class AHPasswordsInput private PasswordModel Model { get; set; } = new(); private ResetPasswordFormModelValidator ModelValidator { get; set; } = default!; - private class PasswordModel + class PasswordModel { [Required] public string Password { get; set; } = default!; @@ -28,7 +28,7 @@ private class PasswordModel public string ConfirmPassword { get; set; } = default!; } - private class ResetPasswordFormModelValidator : AbstractModelValidator + class ResetPasswordFormModelValidator : AbstractModelValidator { public ResetPasswordFormModelValidator(PasswordOptions passwordOptions) { diff --git a/src/Corsinvest.AppHero.Core.MudBlazorUI/Shared/Components/AHUserMenu.razor.cs b/src/Corsinvest.AppHero.Core.MudBlazorUI/Shared/Components/AHUserMenu.razor.cs index 74e7bac..bb22ad9 100644 --- a/src/Corsinvest.AppHero.Core.MudBlazorUI/Shared/Components/AHUserMenu.razor.cs +++ b/src/Corsinvest.AppHero.Core.MudBlazorUI/Shared/Components/AHUserMenu.razor.cs @@ -36,5 +36,5 @@ protected override async Task OnInitializedAsync() } } - private void Logout() => AuthenticationService.Logout(); + private void Logout() => AuthenticationService.LogoutAsync(); } \ No newline at end of file diff --git a/src/Corsinvest.AppHero.Core.MudBlazorUI/Shared/NavMenu.razor b/src/Corsinvest.AppHero.Core.MudBlazorUI/Shared/NavMenu.razor index f2f6eb9..46676ec 100644 --- a/src/Corsinvest.AppHero.Core.MudBlazorUI/Shared/NavMenu.razor +++ b/src/Corsinvest.AppHero.Core.MudBlazorUI/Shared/NavMenu.razor @@ -7,17 +7,16 @@ @L["Home"] - @foreach (var category in ModularityService.GetCategories().OrderBy(a => a)) + @foreach (var category in ModularityService.Categories.OrderBy(a => a.Order).ThenBy(a => a.Name)) { - if (Authorizations.Any(a => a.Module.Category == category)) + if (Authorizations.Any(a => a.Module.Category == category.Name)) { - - @foreach (var item in GetByCategory(category)) + + @foreach (var item in GetByCategory(category.Name)) { @RenderLinkModule(item.Key.Link!, item.SelectMany(a => a.Links)) } - } } @@ -38,11 +37,11 @@ else { + Icon="@link.ToMBIcon()" + IconColor="@link.IconColor.ToMBColor()" + Match="NavLinkMatch.All" + Target="@(link.IsExternal ? "_blank" : null)" + Disabled="@(!link.Enabled)"> @link.Text } diff --git a/src/Corsinvest.AppHero.Core.RazdenUI/Corsinvest.AppHero.Core.RazdenUI.csproj b/src/Corsinvest.AppHero.Core.RazdenUI/Corsinvest.AppHero.Core.RazdenUI.csproj index 1b55c96..ba48640 100644 --- a/src/Corsinvest.AppHero.Core.RazdenUI/Corsinvest.AppHero.Core.RazdenUI.csproj +++ b/src/Corsinvest.AppHero.Core.RazdenUI/Corsinvest.AppHero.Core.RazdenUI.csproj @@ -7,7 +7,7 @@ - + diff --git a/src/Corsinvest.AppHero.Core/Corsinvest.AppHero.Core.csproj b/src/Corsinvest.AppHero.Core/Corsinvest.AppHero.Core.csproj index 736dd19..7b08da8 100644 --- a/src/Corsinvest.AppHero.Core/Corsinvest.AppHero.Core.csproj +++ b/src/Corsinvest.AppHero.Core/Corsinvest.AppHero.Core.csproj @@ -10,25 +10,27 @@ + - - + + + - + - - + + diff --git a/src/Corsinvest.AppHero.Core/Extensions/LoggerExtensions.cs b/src/Corsinvest.AppHero.Core/Extensions/LoggerExtensions.cs index dd5f4ac..71b2e4b 100644 --- a/src/Corsinvest.AppHero.Core/Extensions/LoggerExtensions.cs +++ b/src/Corsinvest.AppHero.Core/Extensions/LoggerExtensions.cs @@ -8,7 +8,7 @@ namespace Corsinvest.AppHero.Core.Extensions; public static class LoggerExtensions { - private class Operation : IDisposable + class Operation : IDisposable { private readonly Stopwatch _timer; private readonly ILogger _logger; diff --git a/src/Corsinvest.AppHero.Core/Extensions/ModuleExtensions.cs b/src/Corsinvest.AppHero.Core/Extensions/ModularityExtensions.cs similarity index 81% rename from src/Corsinvest.AppHero.Core/Extensions/ModuleExtensions.cs rename to src/Corsinvest.AppHero.Core/Extensions/ModularityExtensions.cs index c2130b0..35abab0 100644 --- a/src/Corsinvest.AppHero.Core/Extensions/ModuleExtensions.cs +++ b/src/Corsinvest.AppHero.Core/Extensions/ModularityExtensions.cs @@ -6,14 +6,15 @@ namespace Corsinvest.AppHero.Core.Extensions; -public static class ModuleExtensions +public static class ModularityExtensions { - #region Linq public static IEnumerable IsType(this IEnumerable modules, ModuleType type) => modules.Where(a => a.Type == type); public static IEnumerable IsCategory(this IEnumerable modules, string category) => modules.Where(a => a.Category == category); public static IEnumerable IsEnabled(this IEnumerable modules) => modules.Where(a => a.Enabled); public static IEnumerable IsConfigured(this IEnumerable modules) => modules.Where(a => a.Configurated); public static IEnumerable Implements(this IEnumerable modules) => modules.Where(a => typeof(T).IsAssignableFrom(a.GetType())); public static IEnumerable NotImplements(this IEnumerable modules) => modules.Where(a => !typeof(T).IsAssignableFrom(a.GetType())); - #endregion -} + + public static string GetCategoryIcon(this IModularityService modularityService, string category) + => modularityService.Categories.FirstOrDefault(a => a.Name == category)?.Icon + ""; +} \ No newline at end of file diff --git a/src/Corsinvest.AppHero.Core/Helpers/ApplicationHelper.cs b/src/Corsinvest.AppHero.Core/Helpers/ApplicationHelper.cs index ad7656d..fb9a82e 100644 --- a/src/Corsinvest.AppHero.Core/Helpers/ApplicationHelper.cs +++ b/src/Corsinvest.AppHero.Core/Helpers/ApplicationHelper.cs @@ -2,6 +2,7 @@ * SPDX-FileCopyrightText: Copyright Corsinvest Srl * SPDX-License-Identifier: AGPL-3.0-only */ +using Microsoft.AspNetCore.Components; using System.Reflection; using System.Security.Cryptography; using System.Text; diff --git a/src/Corsinvest.AppHero.Core/Helpers/CryptographyHelper.cs b/src/Corsinvest.AppHero.Core/Helpers/CryptographyHelper.cs index f98bf73..323e18d 100644 --- a/src/Corsinvest.AppHero.Core/Helpers/CryptographyHelper.cs +++ b/src/Corsinvest.AppHero.Core/Helpers/CryptographyHelper.cs @@ -33,17 +33,22 @@ public static string DecryptString(string encrypted, string? passphrase = null) { if (string.IsNullOrEmpty(encrypted)) { return string.Empty; } - var dataArray = Convert.FromBase64String(encrypted); - - using var tDes = TripleDES.Create(); - tDes.Mode = CipherMode.ECB; - tDes.Key = Encoding.UTF8.GetBytes(passphrase ?? Key); - tDes.Padding = PaddingMode.PKCS7; - - using var cTransform = tDes.CreateDecryptor(); - var resultArray = cTransform.TransformFinalBlock(dataArray, 0, dataArray.Length); - tDes.Clear(); - + var resultArray = Array.Empty(); + + try + { + var dataArray = Convert.FromBase64String(encrypted); + + using var tDes = TripleDES.Create(); + tDes.Mode = CipherMode.ECB; + tDes.Key = Encoding.UTF8.GetBytes(passphrase ?? Key); + tDes.Padding = PaddingMode.PKCS7; + + using var cTransform = tDes.CreateDecryptor(); + resultArray = cTransform.TransformFinalBlock(dataArray, 0, dataArray.Length); + tDes.Clear(); + } + catch (Exception ex) { } return Encoding.UTF8.GetString(resultArray); } } diff --git a/src/Corsinvest.AppHero.Core/Hubs/HubClient.cs b/src/Corsinvest.AppHero.Core/Hubs/HubClient.cs index cf68b2a..fd22898 100644 --- a/src/Corsinvest.AppHero.Core/Hubs/HubClient.cs +++ b/src/Corsinvest.AppHero.Core/Hubs/HubClient.cs @@ -57,7 +57,7 @@ public async Task StartAsync() .Build(); _hubConnection.ServerTimeout = TimeSpan.FromSeconds(30); - _hubConnection.On(SignalRConstants.ForceLogout, _authenticationService.Logout); + _hubConnection.On(SignalRConstants.ForceLogout, _authenticationService.LogoutAsync); _hubConnection.On(SignalRConstants.ConnectUser, (userId) => { _sessionsInfoTracker.SetHubConnectionId(_hubConnection.ConnectionId!); diff --git a/src/Corsinvest.AppHero.Core/Modularity/IModularityService.cs b/src/Corsinvest.AppHero.Core/Modularity/IModularityService.cs index 3e40de7..934c4a5 100644 --- a/src/Corsinvest.AppHero.Core/Modularity/IModularityService.cs +++ b/src/Corsinvest.AppHero.Core/Modularity/IModularityService.cs @@ -15,13 +15,11 @@ public interface IModularityService public static string GeneralCategoryName { get; } = "General"; IEnumerable Modules { get; } Task> GetAuthorizationsAsync(IPermissionService permissionService); - IEnumerable GetCategories(); ModuleBase? GetByClass(string @class); ModuleBase? GetBySlug(string slug); ModuleBase? GetByUrl(string url); ModuleBase? Get() where T : ModuleBase; - string? GetCategoryIcon(string category); - void SetCategoryIcon(string category, string icon); + List Categories { get; } IEnumerable Assemblies { get; } Task RefreshOptionsAsync(IServiceScope scope); Task> GetAuthorizedLinksAsync(IPermissionService permissionService); diff --git a/src/Corsinvest.AppHero.Core/Modularity/ModularityService.cs b/src/Corsinvest.AppHero.Core/Modularity/ModularityService.cs index 1a2f6a8..1f12bf2 100644 --- a/src/Corsinvest.AppHero.Core/Modularity/ModularityService.cs +++ b/src/Corsinvest.AppHero.Core/Modularity/ModularityService.cs @@ -27,8 +27,8 @@ public ModularityService(IServiceCollection services, IEnumerable mo private void Initialize() { - SetCategoryIcon(IModularityService.AdministrationCategoryName, UIIcon.SettingsApplications.GetName()); - SetCategoryIcon(IModularityService.GeneralCategoryName, UIIcon.Folder.GetName()); + Categories.Add(new(IModularityService.AdministrationCategoryName, UIIcon.SettingsApplications.GetName(), 0)); + Categories.Add(new(IModularityService.GeneralCategoryName, UIIcon.Folder.GetName(), 0)); } public IEnumerable Modules { get; private set; } @@ -70,18 +70,7 @@ public async Task> GetAuthorizedLinksAsync(IPermissionSe public async Task> GetAuthorizedMenuItemssAsync(IPermissionService permissionService) => (await GetAuthorizationsAsync(permissionService)).SelectMany(a => a.MenuItems); - public IEnumerable GetCategories() => Modules.Select(a => a.Category).Distinct(); - - private readonly Dictionary _cateoryIcons = new(); - public string? GetCategoryIcon(string category) - => _cateoryIcons.TryGetValue(category, out var icon) - ? icon - : null; - - public void SetCategoryIcon(string category, string icon) - { - if (!_cateoryIcons.TryAdd(category, icon)) { _cateoryIcons[category] = icon; } - } + public List Categories { get; } = new(); public IEnumerable Assemblies => Modules.Select(a => a.GetType().Assembly) diff --git a/src/Corsinvest.AppHero.Core/Modularity/ModuleBase.cs b/src/Corsinvest.AppHero.Core/Modularity/ModuleBase.cs index 10ad9b7..1224732 100644 --- a/src/Corsinvest.AppHero.Core/Modularity/ModuleBase.cs +++ b/src/Corsinvest.AppHero.Core/Modularity/ModuleBase.cs @@ -17,9 +17,7 @@ public abstract class ModuleBase public ModuleLink? Link { get; set; } public IEnumerable GetFlatLinks() => Link?.GetFlatLinks() ?? new List().AsReadOnly(); - public IEnumerable MenuItems { get; set; } = Enumerable.Empty(); - public string? InfoText { get; set; } private string _icon = default!; diff --git a/src/Corsinvest.AppHero.Core/Modularity/ModuleCategory.cs b/src/Corsinvest.AppHero.Core/Modularity/ModuleCategory.cs new file mode 100644 index 0000000..53adf3e --- /dev/null +++ b/src/Corsinvest.AppHero.Core/Modularity/ModuleCategory.cs @@ -0,0 +1,20 @@ +/* + * SPDX-FileCopyrightText: Copyright Corsinvest Srl + * SPDX-License-Identifier: AGPL-3.0-only + */ + +namespace Corsinvest.AppHero.Core.Modularity; + +public class ModuleCategory +{ + public ModuleCategory(string name, string icon, int order) + { + Name = name; + Icon = icon; + Order = order; + } + + public string Name { get; } + public string Icon { get; set; } + public int Order { get; set; } +} diff --git a/src/Corsinvest.AppHero.Core/Security/Auth/AccessTokenProvider.cs b/src/Corsinvest.AppHero.Core/Security/Auth/AccessTokenProvider.cs new file mode 100644 index 0000000..66a6d3c --- /dev/null +++ b/src/Corsinvest.AppHero.Core/Security/Auth/AccessTokenProvider.cs @@ -0,0 +1,47 @@ +using Corsinvest.AppHero.Core.Security.Identity; +using Microsoft.AspNetCore.Components; +using Microsoft.AspNetCore.Components.Server.ProtectedBrowserStorage; +using System.Security.Claims; +using System.Security.Cryptography; + +namespace Corsinvest.AppHero.Core.Security.Auth; + +public class AccessTokenProvider +{ + private readonly string _tokenKey = nameof(_tokenKey); + private readonly ProtectedLocalStorage _localStorage; + private readonly NavigationManager _navigation; + private readonly IIdentityService _identityService; + + public AccessTokenProvider(ProtectedLocalStorage localStorage, NavigationManager navigation, IIdentityService identityService) + { + _localStorage = localStorage; + _navigation = navigation; + _identityService = identityService; + } + + public async Task GenerateJwt(ApplicationUser applicationUser) + => await _localStorage.SetAsync(_tokenKey, await _identityService.GenerateJwtAsync(applicationUser)); + + public async Task GetClaimsPrincipal() + { + try + { + var token = await _localStorage.GetAsync(_tokenKey); + if (token.Success && !string.IsNullOrEmpty(token.Value)) + { + var principal = await _identityService.GetClaimsPrincipal(token.Value); + if (principal?.Identity?.IsAuthenticated ?? false) { return principal!; } + } + } + catch (CryptographicException) { await RemoveAuthDataFromStorage(); } + catch (Exception) { return new ClaimsPrincipal(new ClaimsIdentity()); } + return new ClaimsPrincipal(new ClaimsIdentity()); + } + + public async Task RemoveAuthDataFromStorage() + { + await _localStorage.DeleteAsync(_tokenKey); + _navigation.NavigateTo("/", true); + } +} diff --git a/src/Corsinvest.AppHero.Core/Security/Auth/AccountController.cs b/src/Corsinvest.AppHero.Core/Security/Auth/AccountController.cs deleted file mode 100644 index 33b0e4e..0000000 --- a/src/Corsinvest.AppHero.Core/Security/Auth/AccountController.cs +++ /dev/null @@ -1,80 +0,0 @@ -/* - * SPDX-FileCopyrightText: Copyright Corsinvest Srl - * SPDX-License-Identifier: AGPL-3.0-only - */ -using Corsinvest.AppHero.Core.Security.Identity; -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.DataProtection; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Identity; -using Microsoft.AspNetCore.Localization; -using Microsoft.AspNetCore.Mvc; - -namespace Corsinvest.AppHero.Core.Security.Auth; - -[ApiExplorerSettings(IgnoreApi = true)] -[Route("api/[controller]")] -public class AccountController : ControllerBase -{ - private readonly ILogger _logger; - private readonly SignInManager _signInManager; - private readonly IServiceProvider _serviceProvider; - - public AccountController(SignInManager signInManager, ILogger logger, IServiceProvider serviceProvider) - { - _logger = logger; - _signInManager = signInManager; - _serviceProvider = serviceProvider; - } - - [AllowAnonymous] - [HttpGet(nameof(Login))] - public async Task Login(string token) - { - var dataProtectionProvider = _serviceProvider.GetRequiredService(); - var protector = dataProtectionProvider.CreateProtector("Login"); - var data = protector.Unprotect(token); - var parts = data.Split('|'); - var user = await _signInManager.UserManager.FindByIdAsync(parts[0]); - if (user == null) { return Unauthorized(); } - - if (await _signInManager.UserManager.VerifyUserTokenAsync(user, TokenOptions.DefaultProvider, "Login", parts[1])) - { - await _signInManager.UserManager.ResetAccessFailedCountAsync(user); - await _signInManager.SignInAsync(user, bool.Parse(parts[2])); - - //culture - var defaultCulture = string.IsNullOrWhiteSpace(user.DefaultCulture) - ? "en-US" - - //from user - : user.DefaultCulture; - - HttpContext.Response.Cookies.Append(CookieRequestCultureProvider.DefaultCookieName, - CookieRequestCultureProvider.MakeCookieValue(new RequestCulture(defaultCulture))); - } - - return Redirect("/"); - } - - [Authorize] - [HttpGet(nameof(SetCulture))] - public IActionResult SetCulture(string culture, string redirectUri) - { - if (!string.IsNullOrWhiteSpace(culture)) - { - HttpContext.Response.Cookies.Append(CookieRequestCultureProvider.DefaultCookieName, - CookieRequestCultureProvider.MakeCookieValue(new RequestCulture(culture))); - } - - return Redirect(redirectUri); - } - - [Authorize] - [HttpGet(nameof(Logout))] - public async Task Logout() - { - await _signInManager.SignOutAsync(); - return Redirect("/"); - } -} \ No newline at end of file diff --git a/src/Corsinvest.AppHero.Core/Security/Auth/AuthenticationService.cs b/src/Corsinvest.AppHero.Core/Security/Auth/AuthenticationService.cs index 21ff775..e4c0152 100644 --- a/src/Corsinvest.AppHero.Core/Security/Auth/AuthenticationService.cs +++ b/src/Corsinvest.AppHero.Core/Security/Auth/AuthenticationService.cs @@ -5,66 +5,88 @@ using Corsinvest.AppHero.Core.Security.Identity; using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components.Authorization; -using Microsoft.AspNetCore.DataProtection; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Identity; +using System.Security.Claims; namespace Corsinvest.AppHero.Core.Security.Auth; public class AuthenticationService : AuthenticationStateProvider, IAuthenticationService { - private readonly IHttpContextAccessor _httpContextAccessor; private readonly IServiceProvider _serviceProvider; private readonly NavigationManager _navigationManager; + private readonly AccessTokenProvider _tokenProvider; + private readonly IHttpContextAccessor _httpContextAccessor; + private readonly bool _useToken = false; - public AuthenticationService(IServiceProvider serviceProvider, NavigationManager navigationManager, IHttpContextAccessor httpContextAccessor) + public AuthenticationService(IServiceProvider serviceProvider, + NavigationManager navigationManager, + IHttpContextAccessor httpContextAccessor, + AccessTokenProvider tokenProvider) { - _httpContextAccessor = httpContextAccessor; _serviceProvider = serviceProvider; _navigationManager = navigationManager; + _tokenProvider = tokenProvider; + _httpContextAccessor = httpContextAccessor; } - public override Task GetAuthenticationStateAsync() - { - return Task.FromResult(new AuthenticationState(_httpContextAccessor.HttpContext == null - ? new System.Security.Claims.ClaimsPrincipal() - : _httpContextAccessor.HttpContext.User)); - } - - public async Task ExecuteLoginAsync(ApplicationUser user, bool rememberMe) + public override async Task GetAuthenticationStateAsync() { - var userManager = _serviceProvider.GetRequiredService>(); - var token = await userManager.GenerateUserTokenAsync(user, TokenOptions.DefaultProvider, "Login"); - var data = $"{user.Id}|{token}|{rememberMe}"; - - var dataProtectionProvider = _serviceProvider.GetRequiredService(); - var protector = dataProtectionProvider.CreateProtector("Login"); - var protectedData = protector.Protect(data); - _navigationManager.NavigateTo($"/api/account/login?token=" + protectedData, true); + if (_useToken) + { + _httpContextAccessor.HttpContext.User = await _tokenProvider.GetClaimsPrincipal(); + return new AuthenticationState(_httpContextAccessor.HttpContext.User); + } + else + { + return new AuthenticationState(_httpContextAccessor.HttpContext == null + ? new ClaimsPrincipal() + : _httpContextAccessor.HttpContext.User); + } } public async Task LoginAsync(LoginRequest loginRequest) { var userManager = _serviceProvider.GetRequiredService>(); - var user = await userManager.FindByNameAsync(loginRequest.Username); - var ret = user != null - && user.IsActive - && user.EmailConfirmed - && user.LockoutEnabled - && await userManager.CheckPasswordAsync(user, loginRequest.Password); + var valid = user != null + && user.IsActive + && user.EmailConfirmed + && user.LockoutEnabled + && await userManager.CheckPasswordAsync(user, loginRequest.Password); - if (ret) { await ExecuteLoginAsync(user!, loginRequest.RememberMe); } + if (valid) + { + if (_useToken) + { + await _tokenProvider.GenerateJwt(user!); + _navigationManager.NavigateTo("/", true); + } + else + { + var key = Guid.NewGuid(); + BlazorCookieLoginMiddleware.Logins[key] = loginRequest; + _navigationManager.NavigateTo($"/login?key={key}", true); + } + } - NotifyAuthenticationStateChanged(Task.FromResult(new AuthenticationState(_httpContextAccessor.HttpContext!.User))); + //NotifyAuthenticationStateChanged(Task.FromResult(new AuthenticationState(_httpContextAccessor.HttpContext!.User))); - return ret; + return valid; } - public async Task Logout() + + public async Task LogoutAsync() { - await Task.CompletedTask; - _navigationManager.NavigateTo("/api/account/logout", true); - NotifyAuthenticationStateChanged(Task.FromResult(new AuthenticationState(_httpContextAccessor.HttpContext!.User))); + if (_useToken) + { + await _tokenProvider.RemoveAuthDataFromStorage(); + _navigationManager.NavigateTo("/", true); + } + else + { + _navigationManager.NavigateTo("/logout" ,true); + } + //NotifyAuthenticationStateChanged(Task.FromResult(new AuthenticationState(_httpContextAccessor.HttpContext!.User))); } } \ No newline at end of file diff --git a/src/Corsinvest.AppHero.Core/Security/Auth/BlazorCookieLoginMiddleware.cs b/src/Corsinvest.AppHero.Core/Security/Auth/BlazorCookieLoginMiddleware.cs new file mode 100644 index 0000000..edcfc75 --- /dev/null +++ b/src/Corsinvest.AppHero.Core/Security/Auth/BlazorCookieLoginMiddleware.cs @@ -0,0 +1,80 @@ +/* + * SPDX-FileCopyrightText: Copyright Corsinvest Srl + * SPDX-License-Identifier: AGPL-3.0-only + */ +using Corsinvest.AppHero.Core.Security.Identity; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Identity; +using Microsoft.AspNetCore.Localization; +using System.Collections.Concurrent; + +namespace Corsinvest.AppHero.Core.Security.Auth; + +public class BlazorCookieLoginMiddleware +{ + public static IDictionary Logins { get; } = new ConcurrentDictionary(); + private readonly RequestDelegate _next; + + public BlazorCookieLoginMiddleware(RequestDelegate next) => _next = next; + + public async Task Invoke(HttpContext context, SignInManager signInManager) + { + if (context.Request.Path == "/culture" && context.Request.Query.ContainsKey("culture")) { SetCulture(context); } + else if (context.Request.Path == "/logout") { await Logout(context, signInManager); } + else if (context.Request.Path == "/login" && context.Request.Query.ContainsKey("key")) { await Login(context, signInManager); } + else { await _next.Invoke(context); } + } + + private static void SetCulture(HttpContext context) + { + SetCulture(context, context.Request.Query["culture"] + ""); + + context.Response.Redirect(context.Request.Query.ContainsKey("redirectUri") + ? context.Request.Query["redirectUri"] + "" + : "/"); + } + + private static void SetCulture(HttpContext context, string culture) + => context.Response.Cookies.Append(CookieRequestCultureProvider.DefaultCookieName, + CookieRequestCultureProvider.MakeCookieValue(new RequestCulture(culture))); + + + private static async Task Logout(HttpContext context, SignInManager signInManager) + { + await signInManager.SignOutAsync(); + context.Response.Redirect("/"); + } + + private static async Task Login(HttpContext context, SignInManager signInManager) + { + var key = Guid.Parse(context.Request.Query["key"]!); + var info = Logins[key]; + Logins.Remove(key); + + var result = await signInManager.PasswordSignInAsync(info.Username, info.Password, false, lockoutOnFailure: true); + if (result.Succeeded) + { + var user = await signInManager.UserManager.FindByNameAsync(info.Username); + + //culture + var defaultCulture = string.IsNullOrWhiteSpace(user!.DefaultCulture) + ? "en-US" + + //from user + : user.DefaultCulture; + + SetCulture(context, defaultCulture); + + context.Response.Redirect("/"); + } + //else if (result.RequiresTwoFactor) + //{ + // //TODO: redirect to 2FA razor component + // context.Response.Redirect("/loginwith2fa/" + key); + //} + else + { + context.Response.Redirect("/"); + } + } +} \ No newline at end of file diff --git a/src/Corsinvest.AppHero.Core/Security/Auth/CurrentUserService.cs b/src/Corsinvest.AppHero.Core/Security/Auth/CurrentUserService.cs index e429692..e119852 100644 --- a/src/Corsinvest.AppHero.Core/Security/Auth/CurrentUserService.cs +++ b/src/Corsinvest.AppHero.Core/Security/Auth/CurrentUserService.cs @@ -3,6 +3,7 @@ * SPDX-License-Identifier: AGPL-3.0-only */ using Corsinvest.AppHero.Core.Security.Identity; +using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Identity; using System.Security.Claims; @@ -54,4 +55,17 @@ public string IpAddress return string.IsNullOrWhiteSpace(ip) ? "unknown" : ip; } } + + public void SetCulture(string culture, string redirectUri) + { + using var scope = _scopeFactory.CreateScope(); + var navigationManager = scope.ServiceProvider.GetRequiredService(); + navigationManager.NavigateTo(UrlHelper.SetParameter("/culture", + new() + { + { "culture", culture}, + { "redirectUri", redirectUri} + }), + true); + } } \ No newline at end of file diff --git a/src/Corsinvest.AppHero.Core/Security/Auth/IAuthenticationService.cs b/src/Corsinvest.AppHero.Core/Security/Auth/IAuthenticationService.cs index 6b6558b..178e69b 100644 --- a/src/Corsinvest.AppHero.Core/Security/Auth/IAuthenticationService.cs +++ b/src/Corsinvest.AppHero.Core/Security/Auth/IAuthenticationService.cs @@ -8,7 +8,6 @@ namespace Corsinvest.AppHero.Core.Security.Auth; public interface IAuthenticationService { - Task ExecuteLoginAsync(ApplicationUser user, bool rememberMe); Task LoginAsync(LoginRequest loginRequest); - Task Logout(); + Task LogoutAsync(); } \ No newline at end of file diff --git a/src/Corsinvest.AppHero.Core/Security/Auth/ICurrentUserService.cs b/src/Corsinvest.AppHero.Core/Security/Auth/ICurrentUserService.cs index b016c90..f3c9fce 100644 --- a/src/Corsinvest.AppHero.Core/Security/Auth/ICurrentUserService.cs +++ b/src/Corsinvest.AppHero.Core/Security/Auth/ICurrentUserService.cs @@ -17,4 +17,5 @@ public interface ICurrentUserService : IScopedDependency string UserName { get; } string IpAddress { get; } string HttpConnectionId { get; } + void SetCulture(string culture, string redirectUri); } \ No newline at end of file diff --git a/src/Corsinvest.AppHero.Core/Security/Identity/IIdentityService.cs b/src/Corsinvest.AppHero.Core/Security/Identity/IIdentityService.cs index 48ad2c6..7e8a979 100644 --- a/src/Corsinvest.AppHero.Core/Security/Identity/IIdentityService.cs +++ b/src/Corsinvest.AppHero.Core/Security/Identity/IIdentityService.cs @@ -4,6 +4,7 @@ */ using Corsinvest.AppHero.Core.DependencyInjection; using Microsoft.AspNetCore.Identity; +using System.Security.Claims; namespace Corsinvest.AppHero.Core.Security.Identity; @@ -12,4 +13,7 @@ public interface IIdentityService : ITransientDependency Task SendEmailResetPasswordAsync(string email); Task SendEmailConfirmRegistrationAsync(ApplicationUser user); Task CreateUserAsync(ApplicationUser user, string password, IEnumerable roles); -} \ No newline at end of file + + Task GenerateJwtAsync(ApplicationUser user); + Task GetClaimsPrincipal(string token); +} diff --git a/src/Corsinvest.AppHero.Core/Security/Identity/IdentityService.cs b/src/Corsinvest.AppHero.Core/Security/Identity/IdentityService.cs index e91be34..681d27e 100644 --- a/src/Corsinvest.AppHero.Core/Security/Identity/IdentityService.cs +++ b/src/Corsinvest.AppHero.Core/Security/Identity/IdentityService.cs @@ -6,6 +6,10 @@ using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Identity; using Microsoft.Extensions.Localization; +using Microsoft.IdentityModel.Tokens; +using System.IdentityModel.Tokens.Jwt; +using System.Security.Claims; +using System.Text; namespace Corsinvest.AppHero.Core.Security.Identity; @@ -90,4 +94,66 @@ await mailService.SendAsync(new MailRequest(new List() { user.Email! }, string.Format(L["{0} - Confirm registration"], appOptions.Name), body)); } + + #region JWT + public async Task GenerateJwtAsync(ApplicationUser user) + { + var _userClaimsPrincipalFactory = _serviceProvider.GetRequiredService>(); + var principal = await _userClaimsPrincipalFactory.CreateAsync(user); + + var claims = principal.Claims; + //claims = principal.Claims.Where(a => a.Type == ClaimTypes.NameIdentifier + // || a.Type == ClaimTypes.Name) + // .ToArray(); + + return GenerateEncryptedToken(GetSigningCredentials(), claims); + } + + private static SigningCredentials GetSigningCredentials() + { + var secret = "this is my custom Secret key for authentication"; //_appConfig.Secret + return new(new SymmetricSecurityKey(Encoding.UTF8.GetBytes(secret)), SecurityAlgorithms.HmacSha256); + } + + private static string GenerateEncryptedToken(SigningCredentials signingCredentials, IEnumerable claims) + { + var token = new JwtSecurityToken(claims: claims, + expires: DateTime.UtcNow.AddDays(2), + signingCredentials: signingCredentials); + var tokenHandler = new JwtSecurityTokenHandler(); + var encryptedToken = tokenHandler.WriteToken(token); + return encryptedToken; + } + + public async Task GetClaimsPrincipal(string token) + { + var secret = "this is my custom Secret key for authentication"; //_appConfig.Secret + var tokenValidationParameters = new TokenValidationParameters + { + ValidateIssuerSigningKey = false, + IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(secret)), + ValidateIssuer = false, + ValidateAudience = false, + RoleClaimType = ClaimTypes.Role, + ClockSkew = TimeSpan.Zero, + ValidateLifetime = true + }; + + var tokenHandler = new JwtSecurityTokenHandler(); + var result = await tokenHandler.ValidateTokenAsync(token, tokenValidationParameters); + //if (result.IsValid) + //{ + // var signInManager = _serviceProvider.GetRequiredService>(); + // var ret = await signInManager.ClaimsFactory.CreateAsync(await signInManager.UserManager.GetUserAsync(new ClaimsPrincipal(result.ClaimsIdentity))); + // return ret; + //} + //else + //{ + // return new ClaimsPrincipal(new ClaimsIdentity()); + //} + return new ClaimsPrincipal(result.IsValid ? result.ClaimsIdentity : new ClaimsIdentity()); + } + + #endregion + } \ No newline at end of file diff --git a/src/Corsinvest.AppHero.Core/Security/Module.cs b/src/Corsinvest.AppHero.Core/Security/Module.cs index 65cdfd3..dbf6a4c 100644 --- a/src/Corsinvest.AppHero.Core/Security/Module.cs +++ b/src/Corsinvest.AppHero.Core/Security/Module.cs @@ -78,6 +78,7 @@ public override void ConfigureServices(IServiceCollection services, IConfigurati //Authentication services.AddTransient() .AddScoped() + .AddScoped() .AddScoped(sp => sp.GetRequiredService()); services.AddScoped(); @@ -91,11 +92,43 @@ public override void ConfigureServices(IServiceCollection services, IConfigurati options.ExpireTimeSpan = TimeSpan.FromHours(services.GetOptionsSnapshot().Value.LoginCookieExpirationHours); }); - services.AddAuthentication(); + //services.AddAuthentication(); //Authorization //services.AddTransient(); + //var secret = "S0M3RAN0MS3CR3T!1!MAG1C!1!"; //_appConfig.Secret + //services.AddAuthentication() + // .AddJwtBearer(options => + //{ + // options.SaveToken = true; + // options.RequireHttpsMetadata = false; + // options.TokenValidationParameters = new TokenValidationParameters() + // { + // ValidateIssuerSigningKey = false, + // IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(secret)), + // ValidateIssuer = false, + // ValidateAudience = false, + // RoleClaimType = ClaimTypes.Role, + // ClockSkew = TimeSpan.Zero, + // ValidateLifetime = true + // }; + + // options.Events = new JwtBearerEvents + // { + // OnMessageReceived = context => + // { + // var accessToken = context.Request.Headers.Authorization; + // if (!string.IsNullOrEmpty(accessToken) && + // (context.HttpContext.Request.Path.StartsWithSegments("/signalRHub"))) + // { + // context.Token = accessToken.ToString().Substring(7); + // } + // return Task.CompletedTask; + // } + // }; + //}); + services.AddAuthorization(options => { //create all policy from permissions @@ -120,6 +153,8 @@ public override async Task OnApplicationInitializationAsync(IHost host) app.UseAuthentication(); app.UseAuthorization(); + app.UseMiddleware(); + await Task.CompletedTask; } diff --git a/src/Corsinvest.AppHero.HangFire/Corsinvest.AppHero.HangFire.csproj b/src/Corsinvest.AppHero.HangFire/Corsinvest.AppHero.HangFire.csproj index 1098e22..c635304 100644 --- a/src/Corsinvest.AppHero.HangFire/Corsinvest.AppHero.HangFire.csproj +++ b/src/Corsinvest.AppHero.HangFire/Corsinvest.AppHero.HangFire.csproj @@ -7,11 +7,11 @@ - + - + diff --git a/src/Corsinvest.AppHero.HangFire/JobActivatorEx.cs b/src/Corsinvest.AppHero.HangFire/JobActivatorEx.cs index 3ea54d4..637cb40 100644 --- a/src/Corsinvest.AppHero.HangFire/JobActivatorEx.cs +++ b/src/Corsinvest.AppHero.HangFire/JobActivatorEx.cs @@ -15,7 +15,7 @@ public class JobActivatorEx : JobActivator public JobActivatorEx(IServiceScopeFactory scopeFactory) => _scopeFactory = scopeFactory ?? throw new ArgumentNullException(nameof(scopeFactory)); public override JobActivatorScope BeginScope(PerformContext context) => new Scope(context, _scopeFactory.CreateScope()); - private class Scope : JobActivatorScope, IServiceProvider + class Scope : JobActivatorScope, IServiceProvider { private readonly PerformContext _context; private readonly IServiceScope _scope; diff --git a/src/Corsinvest.AppHero.Localization/Corsinvest.AppHero.Localization.csproj b/src/Corsinvest.AppHero.Localization/Corsinvest.AppHero.Localization.csproj index c988869..e8dc75b 100644 --- a/src/Corsinvest.AppHero.Localization/Corsinvest.AppHero.Localization.csproj +++ b/src/Corsinvest.AppHero.Localization/Corsinvest.AppHero.Localization.csproj @@ -8,13 +8,13 @@ - - - + + + runtime; build; native; contentfiles; analyzers; buildtransitive all - + diff --git a/src/Corsinvest.AppHero.Notification.Discord/Corsinvest.AppHero.Notification.Discord.csproj b/src/Corsinvest.AppHero.Notification.Discord/Corsinvest.AppHero.Notification.Discord.csproj index 6c0b1a0..1419312 100644 --- a/src/Corsinvest.AppHero.Notification.Discord/Corsinvest.AppHero.Notification.Discord.csproj +++ b/src/Corsinvest.AppHero.Notification.Discord/Corsinvest.AppHero.Notification.Discord.csproj @@ -7,7 +7,7 @@ - + diff --git a/src/Corsinvest.AppHero.Serilog/Corsinvest.AppHero.Serilog.csproj b/src/Corsinvest.AppHero.Serilog/Corsinvest.AppHero.Serilog.csproj index d8c9085..de0a3e8 100644 --- a/src/Corsinvest.AppHero.Serilog/Corsinvest.AppHero.Serilog.csproj +++ b/src/Corsinvest.AppHero.Serilog/Corsinvest.AppHero.Serilog.csproj @@ -8,8 +8,8 @@ - - + + diff --git a/src/Corsinvest.AppHero.Translation/Google/Translator.cs b/src/Corsinvest.AppHero.Translation/Google/Translator.cs index 97620e0..52e7a36 100644 --- a/src/Corsinvest.AppHero.Translation/Google/Translator.cs +++ b/src/Corsinvest.AppHero.Translation/Google/Translator.cs @@ -9,7 +9,7 @@ namespace Corsinvest.AppHero.Translation.Google; public class Translator { - private class WebResult + class WebResult { [JsonProperty("data")] public Data_ Data { get; set; } = default!; diff --git a/src/Corsinvest.AppHero.Translation/Microsoft/Translator.cs b/src/Corsinvest.AppHero.Translation/Microsoft/Translator.cs index de0bbb5..6860d2d 100644 --- a/src/Corsinvest.AppHero.Translation/Microsoft/Translator.cs +++ b/src/Corsinvest.AppHero.Translation/Microsoft/Translator.cs @@ -52,7 +52,7 @@ public static async Task>> TranslateAsync(ILoggerenable latest - 0.0.106 + 0.0.108 $(NoWarn);CS1591