From 6b4bcb005487f512ffa9f5e54f3610aceafb295f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Wed, 26 Aug 2020 13:49:30 +0300 Subject: [PATCH] Implement WebAssemblyCurrentPrincipalAccessor (temporary solution) --- ...blyCachedApplicationConfigurationClient.cs | 35 ++++++++++++----- .../WebAssembly/WebAssemblyCurrentUser.cs | 39 +++++++++++++++++++ .../ICachedApplicationConfigurationClient.cs | 6 ++- .../Client/RemoteLocalizationContributor.cs | 4 +- ...MvcCachedApplicationConfigurationClient.cs | 19 +++++++++ .../Claims/CurrentPrincipalAccessorBase.cs | 30 ++++++++++++++ .../Claims/ThreadCurrentPrincipalAccessor.cs | 26 ++----------- .../App.razor | 9 +++++ .../Pages/RoleManagement.razor | 5 ++- 9 files changed, 137 insertions(+), 36 deletions(-) create mode 100644 framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/WebAssemblyCurrentUser.cs create mode 100644 framework/src/Volo.Abp.Security/Volo/Abp/Security/Claims/CurrentPrincipalAccessorBase.cs diff --git a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/WebAssemblyCachedApplicationConfigurationClient.cs b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/WebAssemblyCachedApplicationConfigurationClient.cs index 1cf46caa7d..ab9b18f812 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/WebAssemblyCachedApplicationConfigurationClient.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/WebAssemblyCachedApplicationConfigurationClient.cs @@ -1,36 +1,53 @@ -using System.Globalization; -using System.Threading.Tasks; +using System.Threading.Tasks; +using Microsoft.Extensions.Caching.Memory; using Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations; using Volo.Abp.AspNetCore.Mvc.Client; using Volo.Abp.DependencyInjection; using Volo.Abp.Http.Client.DynamicProxying; -using Volo.Abp.Users; namespace Volo.Abp.AspNetCore.Components.WebAssembly { public class WebAssemblyCachedApplicationConfigurationClient : ICachedApplicationConfigurationClient, ITransientDependency { protected IHttpClientProxy Proxy { get; } - protected ICurrentUser CurrentUser { get; } + + protected IMemoryCache Cache { get; } public WebAssemblyCachedApplicationConfigurationClient( IHttpClientProxy proxy, - ICurrentUser currentUser) + IMemoryCache cache) { Proxy = proxy; - CurrentUser = currentUser; + Cache = cache; + } + + public async Task InitializeAsync() + { + await GetAsync(); } public async Task GetAsync() { - //TODO: Cache + return await Cache.GetOrCreateAsync( + CreateCacheKey(), + e => Proxy.Service.GetAsync() + ); + } + + public ApplicationConfigurationDto Get() + { + var cacheKey = CreateCacheKey(); + if(Cache.TryGetValue(cacheKey, out ApplicationConfigurationDto value)) + { + return value; + } - return await Proxy.Service.GetAsync(); + throw new AbpException($"Should initialize the {nameof(ICachedApplicationConfigurationClient)} before getting the value!"); } protected virtual string CreateCacheKey() { - return $"ApplicationConfiguration_{CurrentUser.Id?.ToString("N") ?? "Anonymous"}_{CultureInfo.CurrentUICulture.Name}"; + return $"ApplicationConfiguration"; } } } diff --git a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/WebAssemblyCurrentUser.cs b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/WebAssemblyCurrentUser.cs new file mode 100644 index 0000000000..675f01196d --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/WebAssemblyCurrentUser.cs @@ -0,0 +1,39 @@ +using System.Collections.Generic; +using System.Security.Claims; +using Volo.Abp.AspNetCore.Mvc.Client; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Security.Claims; + +namespace Volo.Abp.AspNetCore.Components.WebAssembly +{ + public class WebAssemblyCurrentPrincipalAccessor : CurrentPrincipalAccessorBase, ITransientDependency + { + protected ICachedApplicationConfigurationClient ConfigurationClient { get; } + + public WebAssemblyCurrentPrincipalAccessor(ICachedApplicationConfigurationClient configurationClient) + { + ConfigurationClient = configurationClient; + } + + protected override ClaimsPrincipal GetClaimsPrincipal() + { + //TODO: Should be optimized! Or should be replaced? + + var configuration = ConfigurationClient.Get(); + + var claims = new List(); + + claims.Add(new Claim(AbpClaimTypes.UserName,configuration.CurrentUser.UserName)); + claims.Add(new Claim(AbpClaimTypes.Email,configuration.CurrentUser.Email)); + claims.Add(new Claim(AbpClaimTypes.UserId,configuration.CurrentUser.Id.ToString())); + claims.Add(new Claim(AbpClaimTypes.TenantId,configuration.CurrentUser.TenantId.ToString())); + + foreach (var role in configuration.CurrentUser.Roles) + { + claims.Add(new Claim(AbpClaimTypes.Role, role)); + } + + return new ClaimsPrincipal(new ClaimsIdentity(claims)); + } + } +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/Volo/Abp/AspNetCore/Mvc/Client/ICachedApplicationConfigurationClient.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/Volo/Abp/AspNetCore/Mvc/Client/ICachedApplicationConfigurationClient.cs index 71d9d8cddf..d08ca7013e 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/Volo/Abp/AspNetCore/Mvc/Client/ICachedApplicationConfigurationClient.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/Volo/Abp/AspNetCore/Mvc/Client/ICachedApplicationConfigurationClient.cs @@ -5,6 +5,10 @@ namespace Volo.Abp.AspNetCore.Mvc.Client { public interface ICachedApplicationConfigurationClient { + Task InitializeAsync(); + Task GetAsync(); + + ApplicationConfigurationDto Get(); } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/Volo/Abp/AspNetCore/Mvc/Client/RemoteLocalizationContributor.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/Volo/Abp/AspNetCore/Mvc/Client/RemoteLocalizationContributor.cs index d60256a501..b179856842 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/Volo/Abp/AspNetCore/Mvc/Client/RemoteLocalizationContributor.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/Volo/Abp/AspNetCore/Mvc/Client/RemoteLocalizationContributor.cs @@ -55,7 +55,7 @@ namespace Volo.Abp.AspNetCore.Mvc.Client private Dictionary GetResourceOrNull() { - var applicationConfigurationDto = AsyncHelper.RunSync(() => _applicationConfigurationClient.GetAsync()); + var applicationConfigurationDto = _applicationConfigurationClient.Get(); var resource = applicationConfigurationDto .Localization.Values @@ -69,4 +69,4 @@ namespace Volo.Abp.AspNetCore.Mvc.Client return resource; } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/MvcCachedApplicationConfigurationClient.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/MvcCachedApplicationConfigurationClient.cs index 0c173b5ecf..a357d959b2 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/MvcCachedApplicationConfigurationClient.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/MvcCachedApplicationConfigurationClient.cs @@ -7,6 +7,7 @@ using Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations; using Volo.Abp.Caching; using Volo.Abp.DependencyInjection; using Volo.Abp.Http.Client.DynamicProxying; +using Volo.Abp.Threading; using Volo.Abp.Users; namespace Volo.Abp.AspNetCore.Mvc.Client @@ -30,6 +31,11 @@ namespace Volo.Abp.AspNetCore.Mvc.Client Cache = cache; } + public async Task InitializeAsync() + { + await GetAsync(); + } + public async Task GetAsync() { var cacheKey = CreateCacheKey(); @@ -57,6 +63,19 @@ namespace Volo.Abp.AspNetCore.Mvc.Client return configuration; } + public ApplicationConfigurationDto Get() + { + var cacheKey = CreateCacheKey(); + var httpContext = HttpContextAccessor?.HttpContext; + + if (httpContext != null && httpContext.Items[cacheKey] is ApplicationConfigurationDto configuration) + { + return configuration; + } + + return AsyncHelper.RunSync(GetAsync); + } + protected virtual string CreateCacheKey() { return $"ApplicationConfiguration_{CurrentUser.Id?.ToString("N") ?? "Anonymous"}_{CultureInfo.CurrentUICulture.Name}"; diff --git a/framework/src/Volo.Abp.Security/Volo/Abp/Security/Claims/CurrentPrincipalAccessorBase.cs b/framework/src/Volo.Abp.Security/Volo/Abp/Security/Claims/CurrentPrincipalAccessorBase.cs new file mode 100644 index 0000000000..0ebedc8d44 --- /dev/null +++ b/framework/src/Volo.Abp.Security/Volo/Abp/Security/Claims/CurrentPrincipalAccessorBase.cs @@ -0,0 +1,30 @@ +using System; +using System.Security.Claims; +using System.Threading; + +namespace Volo.Abp.Security.Claims +{ + public abstract class CurrentPrincipalAccessorBase : ICurrentPrincipalAccessor + { + public ClaimsPrincipal Principal => _currentPrincipal.Value ?? GetClaimsPrincipal(); + + private readonly AsyncLocal _currentPrincipal = new AsyncLocal(); + + protected abstract ClaimsPrincipal GetClaimsPrincipal(); + + public virtual IDisposable Change(ClaimsPrincipal principal) + { + return SetCurrent(principal); + } + + private IDisposable SetCurrent(ClaimsPrincipal principal) + { + var parent = Principal; + _currentPrincipal.Value = principal; + return new DisposeAction(() => + { + _currentPrincipal.Value = parent; + }); + } + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Security/Volo/Abp/Security/Claims/ThreadCurrentPrincipalAccessor.cs b/framework/src/Volo.Abp.Security/Volo/Abp/Security/Claims/ThreadCurrentPrincipalAccessor.cs index ad496ba916..ea7ed7106f 100644 --- a/framework/src/Volo.Abp.Security/Volo/Abp/Security/Claims/ThreadCurrentPrincipalAccessor.cs +++ b/framework/src/Volo.Abp.Security/Volo/Abp/Security/Claims/ThreadCurrentPrincipalAccessor.cs @@ -1,34 +1,14 @@ -using System; -using System.Security.Claims; +using System.Security.Claims; using System.Threading; using Volo.Abp.DependencyInjection; namespace Volo.Abp.Security.Claims { - public class ThreadCurrentPrincipalAccessor : ICurrentPrincipalAccessor, ISingletonDependency + public class ThreadCurrentPrincipalAccessor : CurrentPrincipalAccessorBase, ISingletonDependency { - public ClaimsPrincipal Principal => _currentPrincipal.Value ?? GetClaimsPrincipal(); - - private readonly AsyncLocal _currentPrincipal = new AsyncLocal(); - - protected virtual ClaimsPrincipal GetClaimsPrincipal() + protected override ClaimsPrincipal GetClaimsPrincipal() { return Thread.CurrentPrincipal as ClaimsPrincipal; } - - public virtual IDisposable Change(ClaimsPrincipal principal) - { - return SetCurrent(principal); - } - - private IDisposable SetCurrent(ClaimsPrincipal principal) - { - var parent = Principal; - _currentPrincipal.Value = principal; - return new DisposeAction(() => - { - _currentPrincipal.Value = parent; - }); - } } } diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/App.razor b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/App.razor index f5abd22444..f96456573f 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/App.razor +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/App.razor @@ -1,3 +1,5 @@ +@using Volo.Abp.AspNetCore.Mvc.Client +@inject ICachedApplicationConfigurationClient ConfigurationClient @@ -21,3 +23,10 @@ +@code +{ + protected override async Task OnInitializedAsync() + { + await ConfigurationClient.InitializeAsync(); + } +} diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/Pages/RoleManagement.razor b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/Pages/RoleManagement.razor index f72590add0..efb95d799c 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/Pages/RoleManagement.razor +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/Pages/RoleManagement.razor @@ -2,10 +2,13 @@ @attribute [Authorize] @using Volo.Abp.Identity @using Microsoft.AspNetCore.Authorization +@using Microsoft.Extensions.Localization @using Volo.Abp.Application.Dtos +@using Volo.Abp.Identity.Localization @inject IIdentityRoleAppService RoleAppService +@inject IStringLocalizer L -

Roles

+

@L["Roles"]

@if (_roles != null) {