From 43db5d683af8378c94f1c08bb3586c10a6aeb8ad Mon Sep 17 00:00:00 2001 From: maliming Date: Tue, 6 Jul 2021 15:58:16 +0800 Subject: [PATCH 1/2] Switch to the tenant if __tenant querystring parameter is sent. Resolve #9383 --- .../AbpMultiTenancyCookieHelper.cs | 32 ++++++++++++++ .../MultiTenancy/MultiTenancyMiddleware.cs | 14 ++++-- .../MultiTenancy/TenantSwitchModal.cshtml.cs | 20 +++------ .../Volo/Abp/Account/ResetPasswordDto.cs | 2 - .../Volo/Abp/Account/AccountAppService.cs | 19 ++++---- .../Abp/Account/Emailing/AccountEmailer.cs | 3 +- .../AbpAccountWebModule.cs | 2 - .../Pages/Account/AccountPageModel.cs | 44 ------------------- .../Pages/Account/ResetPassword.cshtml.cs | 14 +----- .../Volo.Abp.Account.Web.csproj | 1 - .../Themes/Basic/Layouts/Account.cshtml | 3 +- 11 files changed, 60 insertions(+), 94 deletions(-) create mode 100644 framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/AbpMultiTenancyCookieHelper.cs diff --git a/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/AbpMultiTenancyCookieHelper.cs b/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/AbpMultiTenancyCookieHelper.cs new file mode 100644 index 0000000000..ca483930c9 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/AbpMultiTenancyCookieHelper.cs @@ -0,0 +1,32 @@ +using System; +using Microsoft.AspNetCore.Http; + +namespace Volo.Abp.AspNetCore.MultiTenancy +{ + public static class AbpMultiTenancyCookieHelper + { + public static void SetTenantCookie( + HttpContext context, + Guid? tenantId, + string tenantKey) + { + if (tenantId != null) + { + context.Response.Cookies.Append( + tenantKey, + tenantId.ToString(), + new CookieOptions + { + Path = "/", + HttpOnly = false, + Expires = DateTimeOffset.Now.AddYears(10) + } + ); + } + else + { + context.Response.Cookies.Delete(tenantKey); + } + } + } +} diff --git a/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/MultiTenancyMiddleware.cs b/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/MultiTenancyMiddleware.cs index 361826672b..f5541e3b40 100644 --- a/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/MultiTenancyMiddleware.cs +++ b/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/MultiTenancyMiddleware.cs @@ -1,9 +1,6 @@ using System; using System.Globalization; -using System.IO; -using System.Net; using System.Threading.Tasks; -using Microsoft.AspNetCore.Diagnostics; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Localization; using Microsoft.AspNetCore.RequestLocalization; @@ -21,14 +18,17 @@ namespace Volo.Abp.AspNetCore.MultiTenancy private readonly ITenantConfigurationProvider _tenantConfigurationProvider; private readonly ICurrentTenant _currentTenant; private readonly AbpAspNetCoreMultiTenancyOptions _options; + private readonly ITenantResolveResultAccessor _tenantResolveResultAccessor; public MultiTenancyMiddleware( ITenantConfigurationProvider tenantConfigurationProvider, ICurrentTenant currentTenant, - IOptions options) + IOptions options, + ITenantResolveResultAccessor tenantResolveResultAccessor) { _tenantConfigurationProvider = tenantConfigurationProvider; _currentTenant = currentTenant; + _tenantResolveResultAccessor = tenantResolveResultAccessor; _options = options.Value; } @@ -49,6 +49,12 @@ namespace Volo.Abp.AspNetCore.MultiTenancy { using (_currentTenant.Change(tenant?.Id, tenant?.Name)) { + if (_tenantResolveResultAccessor.Result != null && + _tenantResolveResultAccessor.Result.AppliedResolvers.Contains(QueryStringTenantResolveContributor.ContributorName)) + { + AbpMultiTenancyCookieHelper.SetTenantCookie(context, _currentTenant.Id, _options.TenantKey); + } + var requestCulture = await TryGetRequestCultureAsync(context); if (requestCulture != null) { diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Pages/Abp/MultiTenancy/TenantSwitchModal.cshtml.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Pages/Abp/MultiTenancy/TenantSwitchModal.cshtml.cs index f47edab789..1edeadff16 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Pages/Abp/MultiTenancy/TenantSwitchModal.cshtml.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Pages/Abp/MultiTenancy/TenantSwitchModal.cshtml.cs @@ -41,11 +41,8 @@ namespace Pages.Abp.MultiTenancy public async Task OnPostAsync() { - if (Input.Name.IsNullOrEmpty()) - { - Response.Cookies.Delete(Options.TenantKey); - } - else + Guid? tenantId = null; + if (!Input.Name.IsNullOrEmpty()) { var tenant = await TenantStore.FindAsync(Input.Name); if (tenant == null) @@ -58,17 +55,10 @@ namespace Pages.Abp.MultiTenancy throw new UserFriendlyException(L["GivenTenantIsNotAvailable", Input.Name]); } - Response.Cookies.Append( - Options.TenantKey, - tenant.Id.ToString(), - new CookieOptions - { - Path = "/", - HttpOnly = false, - Expires = DateTimeOffset.Now.AddYears(10) - } - ); + tenantId = tenant.Id; } + + AbpMultiTenancyCookieHelper.SetTenantCookie(HttpContext, tenantId, Options.TenantKey); } public class TenantInfoModel diff --git a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/ResetPasswordDto.cs b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/ResetPasswordDto.cs index 695fcfca91..2423e6c778 100644 --- a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/ResetPasswordDto.cs +++ b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/ResetPasswordDto.cs @@ -8,8 +8,6 @@ namespace Volo.Abp.Account { public Guid UserId { get; set; } - public Guid? TenantId { get; set; } - [Required] public string ResetToken { get; set; } diff --git a/modules/account/src/Volo.Abp.Account.Application/Volo/Abp/Account/AccountAppService.cs b/modules/account/src/Volo.Abp.Account.Application/Volo/Abp/Account/AccountAppService.cs index 22c7e20b54..05ff98b35b 100644 --- a/modules/account/src/Volo.Abp.Account.Application/Volo/Abp/Account/AccountAppService.cs +++ b/modules/account/src/Volo.Abp.Account.Application/Volo/Abp/Account/AccountAppService.cs @@ -62,19 +62,16 @@ namespace Volo.Abp.Account public virtual async Task ResetPasswordAsync(ResetPasswordDto input) { - using (CurrentTenant.Change(input.TenantId)) - { - await IdentityOptions.SetAsync(); + await IdentityOptions.SetAsync(); - var user = await UserManager.GetByIdAsync(input.UserId); - (await UserManager.ResetPasswordAsync(user, input.ResetToken, input.Password)).CheckErrors(); + var user = await UserManager.GetByIdAsync(input.UserId); + (await UserManager.ResetPasswordAsync(user, input.ResetToken, input.Password)).CheckErrors(); - await IdentitySecurityLogManager.SaveAsync(new IdentitySecurityLogContext - { - Identity = IdentitySecurityLogIdentityConsts.Identity, - Action = IdentitySecurityLogActionConsts.ChangePassword - }); - } + await IdentitySecurityLogManager.SaveAsync(new IdentitySecurityLogContext + { + Identity = IdentitySecurityLogIdentityConsts.Identity, + Action = IdentitySecurityLogActionConsts.ChangePassword + }); } protected virtual async Task GetUserByEmail(string email) diff --git a/modules/account/src/Volo.Abp.Account.Application/Volo/Abp/Account/Emailing/AccountEmailer.cs b/modules/account/src/Volo.Abp.Account.Application/Volo/Abp/Account/Emailing/AccountEmailer.cs index 1d7379bd04..4edf3ce6fe 100644 --- a/modules/account/src/Volo.Abp.Account.Application/Volo/Abp/Account/Emailing/AccountEmailer.cs +++ b/modules/account/src/Volo.Abp.Account.Application/Volo/Abp/Account/Emailing/AccountEmailer.cs @@ -48,7 +48,8 @@ namespace Volo.Abp.Account.Emailing var url = await AppUrlProvider.GetResetPasswordUrlAsync(appName); - var link = $"{url}?userId={user.Id}&tenantId={user.TenantId}&resetToken={UrlEncoder.Default.Encode(resetToken)}"; + //TODO: Use AbpAspNetCoreMultiTenancyOptions to get the key + var link = $"{url}?userId={user.Id}&{TenantResolverConsts.DefaultTenantKey}={user.TenantId}&resetToken={UrlEncoder.Default.Encode(resetToken)}"; if (!returnUrl.IsNullOrEmpty()) { diff --git a/modules/account/src/Volo.Abp.Account.Web/AbpAccountWebModule.cs b/modules/account/src/Volo.Abp.Account.Web/AbpAccountWebModule.cs index f845b7f273..4a806b9ae2 100644 --- a/modules/account/src/Volo.Abp.Account.Web/AbpAccountWebModule.cs +++ b/modules/account/src/Volo.Abp.Account.Web/AbpAccountWebModule.cs @@ -3,7 +3,6 @@ using Microsoft.Extensions.DependencyInjection; using Volo.Abp.Account.Localization; using Volo.Abp.Account.Web.Pages.Account; using Volo.Abp.Account.Web.ProfileManagement; -using Volo.Abp.AspNetCore.MultiTenancy; using Volo.Abp.AspNetCore.Mvc.Localization; using Volo.Abp.AspNetCore.Mvc.UI.Bundling; using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared; @@ -22,7 +21,6 @@ namespace Volo.Abp.Account.Web typeof(AbpIdentityAspNetCoreModule), typeof(AbpAutoMapperModule), typeof(AbpAspNetCoreMvcUiThemeSharedModule), - typeof(AbpAspNetCoreMultiTenancyModule), typeof(AbpExceptionHandlingModule) )] public class AbpAccountWebModule : AbpModule diff --git a/modules/account/src/Volo.Abp.Account.Web/Pages/Account/AccountPageModel.cs b/modules/account/src/Volo.Abp.Account.Web/Pages/Account/AccountPageModel.cs index 32f2398629..12b219449b 100644 --- a/modules/account/src/Volo.Abp.Account.Web/Pages/Account/AccountPageModel.cs +++ b/modules/account/src/Volo.Abp.Account.Web/Pages/Account/AccountPageModel.cs @@ -1,19 +1,13 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Http.Extensions; using Microsoft.AspNetCore.Identity; -using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Options; using Volo.Abp.Account.Localization; using Volo.Abp.AspNetCore.ExceptionHandling; -using Volo.Abp.AspNetCore.MultiTenancy; using Volo.Abp.AspNetCore.Mvc.UI.RazorPages; using Volo.Abp.ExceptionHandling; using Volo.Abp.Identity; -using Volo.Abp.MultiTenancy; using IdentityUser = Volo.Abp.Identity.IdentityUser; namespace Volo.Abp.Account.Web.Pages.Account @@ -27,50 +21,12 @@ namespace Volo.Abp.Account.Web.Pages.Account public IOptions IdentityOptions { get; set; } public IExceptionToErrorInfoConverter ExceptionToErrorInfoConverter { get; set; } - public ITenantResolveResultAccessor TenantResolveResultAccessor { get; set; } - - public IOptions AspNetCoreMultiTenancyOptions { get; set; } - - public IOptions MultiTenancyOptions { get; set; } - protected AccountPageModel() { LocalizationResourceType = typeof(AccountResource); ObjectMapperContext = typeof(AbpAccountWebModule); } - protected virtual bool SwitchTenant(Guid? tenantId) - { - if (MultiTenancyOptions.Value.IsEnabled && - TenantResolveResultAccessor.Result?.AppliedResolvers?.Contains(CookieTenantResolveContributor.ContributorName) == true) - { - if (CurrentTenant.Id != tenantId) - { - if (tenantId != null) - { - Response.Cookies.Append( - AspNetCoreMultiTenancyOptions.Value.TenantKey, - tenantId.ToString(), - new CookieOptions - { - Path = "/", - HttpOnly = false, - Expires = DateTimeOffset.Now.AddYears(10) - } - ); - } - else - { - Response.Cookies.Delete(AspNetCoreMultiTenancyOptions.Value.TenantKey); - } - - return true; - } - } - - return false; - } - protected virtual void CheckCurrentTenant(Guid? tenantId) { if (CurrentTenant.Id != tenantId) diff --git a/modules/account/src/Volo.Abp.Account.Web/Pages/Account/ResetPassword.cshtml.cs b/modules/account/src/Volo.Abp.Account.Web/Pages/Account/ResetPassword.cshtml.cs index 7067e186ef..b15113c294 100644 --- a/modules/account/src/Volo.Abp.Account.Web/Pages/Account/ResetPassword.cshtml.cs +++ b/modules/account/src/Volo.Abp.Account.Web/Pages/Account/ResetPassword.cshtml.cs @@ -1,7 +1,6 @@ using System; using System.ComponentModel.DataAnnotations; using System.Threading.Tasks; -using Microsoft.AspNetCore.Http.Extensions; using Microsoft.AspNetCore.Mvc; using Volo.Abp.Auditing; using Volo.Abp.Identity; @@ -10,13 +9,8 @@ using Volo.Abp.Validation; namespace Volo.Abp.Account.Web.Pages.Account { //TODO: Implement live password complexity check on the razor view! - public class ResetPasswordModel : AccountPageModel { - [HiddenInput] - [BindProperty(SupportsGet = true)] - public Guid? TenantId { get; set; } - [Required] [HiddenInput] [BindProperty(SupportsGet = true)] @@ -51,11 +45,6 @@ namespace Volo.Abp.Account.Web.Pages.Account public virtual Task OnGetAsync() { - if (SwitchTenant(TenantId)) - { - return Task.FromResult(Redirect(HttpContext.Request.GetEncodedUrl())); - } - return Task.FromResult(Page()); } @@ -70,8 +59,7 @@ namespace Volo.Abp.Account.Web.Pages.Account { UserId = UserId, ResetToken = ResetToken, - Password = Password, - TenantId = TenantId + Password = Password } ); } diff --git a/modules/account/src/Volo.Abp.Account.Web/Volo.Abp.Account.Web.csproj b/modules/account/src/Volo.Abp.Account.Web/Volo.Abp.Account.Web.csproj index da95a01a8a..ac59aa33ba 100644 --- a/modules/account/src/Volo.Abp.Account.Web/Volo.Abp.Account.Web.csproj +++ b/modules/account/src/Volo.Abp.Account.Web/Volo.Abp.Account.Web.csproj @@ -35,7 +35,6 @@ - diff --git a/modules/basic-theme/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Themes/Basic/Layouts/Account.cshtml b/modules/basic-theme/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Themes/Basic/Layouts/Account.cshtml index 06b06c08dc..7c3c26f74f 100644 --- a/modules/basic-theme/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Themes/Basic/Layouts/Account.cshtml +++ b/modules/basic-theme/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Themes/Basic/Layouts/Account.cshtml @@ -57,7 +57,8 @@ @if (MultiTenancyOptions.Value.IsEnabled && - (TenantResolveResultAccessor.Result?.AppliedResolvers?.Contains(CookieTenantResolveContributor.ContributorName) == true)) + (TenantResolveResultAccessor.Result?.AppliedResolvers?.Contains(CookieTenantResolveContributor.ContributorName) == true || + TenantResolveResultAccessor.Result?.AppliedResolvers?.Contains(QueryStringTenantResolveContributor.ContributorName) == true)) {
From 81f1f7cb260a84576c9a439832eb95d17bcd0d35 Mon Sep 17 00:00:00 2001 From: maliming Date: Wed, 7 Jul 2021 15:14:51 +0800 Subject: [PATCH 2/2] Switch to host if the tenant value of querystring is empty. --- .../QueryStringTenantResolveContributor.cs | 23 +++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/QueryStringTenantResolveContributor.cs b/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/QueryStringTenantResolveContributor.cs index 7e9690077e..2edcac0eaf 100644 --- a/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/QueryStringTenantResolveContributor.cs +++ b/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/QueryStringTenantResolveContributor.cs @@ -1,4 +1,5 @@ -using System.Threading.Tasks; +using System; +using System.Threading.Tasks; using Microsoft.AspNetCore.Http; using Volo.Abp.MultiTenancy; @@ -12,9 +13,23 @@ namespace Volo.Abp.AspNetCore.MultiTenancy protected override Task GetTenantIdOrNameFromHttpContextOrNullAsync(ITenantResolveContext context, HttpContext httpContext) { - return Task.FromResult(httpContext.Request.QueryString.HasValue - ? httpContext.Request.Query[context.GetAbpAspNetCoreMultiTenancyOptions().TenantKey].ToString() - : null); + if (httpContext.Request.QueryString.HasValue) + { + var tenantKey = context.GetAbpAspNetCoreMultiTenancyOptions().TenantKey; + if (httpContext.Request.Query.ContainsKey(tenantKey)) + { + var tenantValue = httpContext.Request.Query[tenantKey].ToString(); + if (tenantValue.IsNullOrWhiteSpace()) + { + context.Handled = true; + return Task.FromResult(null); + } + + return Task.FromResult(tenantValue); + } + } + + return Task.FromResult(null); } } }