mirror of https://github.com/abpframework/abp.git
committed by
GitHub
32 changed files with 466 additions and 95 deletions
@ -0,0 +1,66 @@ |
|||
using System; |
|||
using System.Threading.Tasks; |
|||
using Microsoft.AspNetCore.Http; |
|||
using Microsoft.AspNetCore.Mvc; |
|||
using Microsoft.Extensions.Options; |
|||
using Volo.Abp.AspNetCore.MultiTenancy; |
|||
using Volo.Abp.AspNetCore.Mvc; |
|||
using Volo.Abp.MultiTenancy; |
|||
using Volo.Abp.Ui; |
|||
|
|||
namespace MicroserviceDemo.AuthServer.Controllers |
|||
{ |
|||
/* TODO: This is temporary solution to switch tenant. |
|||
*/ |
|||
|
|||
public class MultiTenancyController : AbpController |
|||
{ |
|||
private readonly ITenantStore _tenantStore; |
|||
private readonly AspNetCoreMultiTenancyOptions _options; |
|||
|
|||
public MultiTenancyController(ITenantStore tenantStore, IOptions<AspNetCoreMultiTenancyOptions> options) |
|||
{ |
|||
_tenantStore = tenantStore; |
|||
_options = options.Value; |
|||
} |
|||
|
|||
public async Task<ActionResult> SwitchTenant(string tenant = "") |
|||
{ |
|||
if (tenant.IsNullOrEmpty()) |
|||
{ |
|||
HttpContext.Response.Cookies.Delete(_options.TenantKey); |
|||
} |
|||
else |
|||
{ |
|||
var tenantInfo = await FindTenantAsync(tenant); |
|||
if (tenantInfo == null) |
|||
{ |
|||
throw new UserFriendlyException("Unknown tenant: " + tenant); |
|||
} |
|||
|
|||
HttpContext.Response.Cookies.Append( |
|||
_options.TenantKey, |
|||
tenantInfo.Id.ToString(), |
|||
new CookieOptions |
|||
{ |
|||
Expires = DateTimeOffset.Now.AddYears(1) |
|||
} |
|||
); |
|||
} |
|||
|
|||
return Redirect("/"); |
|||
} |
|||
|
|||
private async Task<TenantInfo> FindTenantAsync(string tenantIdOrName) |
|||
{ |
|||
if (Guid.TryParse(tenantIdOrName, out var parsedTenantId)) |
|||
{ |
|||
return await _tenantStore.FindAsync(parsedTenantId); |
|||
} |
|||
else |
|||
{ |
|||
return await _tenantStore.FindAsync(tenantIdOrName); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -1,15 +1,17 @@ |
|||
namespace Volo.Abp.AspNetCore.MultiTenancy |
|||
using Volo.Abp.MultiTenancy; |
|||
|
|||
namespace Volo.Abp.AspNetCore.MultiTenancy |
|||
{ |
|||
public class AspNetCoreMultiTenancyOptions |
|||
{ |
|||
/// <summary>
|
|||
/// Default: "__tenant".
|
|||
/// Default: <see cref="TenantResolverConsts.DefaultTenantKey"/>.
|
|||
/// </summary>
|
|||
public string TenantKey { get; set; } |
|||
|
|||
public AspNetCoreMultiTenancyOptions() |
|||
{ |
|||
TenantKey = "__tenant"; |
|||
TenantKey = TenantResolverConsts.DefaultTenantKey; |
|||
} |
|||
} |
|||
} |
|||
@ -1,24 +0,0 @@ |
|||
using System.Linq; |
|||
using Microsoft.AspNetCore.Http; |
|||
using Volo.Abp.MultiTenancy; |
|||
|
|||
namespace Volo.Abp.AspNetCore.MultiTenancy |
|||
{ |
|||
public class ClaimsHttpTenantResolveContributer : HttpTenantResolveContributerBase |
|||
{ |
|||
protected override void ResolveFromHttpContext(ITenantResolveContext context, HttpContext httpContext) |
|||
{ |
|||
if (httpContext.User?.Identity?.IsAuthenticated == true) |
|||
{ |
|||
base.ResolveFromHttpContext(context, httpContext); |
|||
context.Handled = true; |
|||
} |
|||
} |
|||
|
|||
protected override string GetTenantIdOrNameFromHttpContextOrNull(ITenantResolveContext context, HttpContext httpContext) |
|||
{ |
|||
var tenantKey = context.GetAspNetCoreMultiTenancyOptions().TenantKey; |
|||
return httpContext.User.Claims.FirstOrDefault(c => c.Type == tenantKey)?.Value; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,38 @@ |
|||
using System.Linq; |
|||
using System.Security.Claims; |
|||
using System.Threading.Tasks; |
|||
using Microsoft.AspNetCore.Identity; |
|||
using Microsoft.Extensions.Options; |
|||
using Volo.Abp.DependencyInjection; |
|||
using Volo.Abp.Security.Claims; |
|||
using Volo.Abp.Uow; |
|||
|
|||
namespace Volo.Abp.Identity |
|||
{ |
|||
public class AbpUserClaimsPrincipalFactory : UserClaimsPrincipalFactory<IdentityUser, IdentityRole>, ITransientDependency |
|||
{ |
|||
public AbpUserClaimsPrincipalFactory( |
|||
UserManager<IdentityUser> userManager, |
|||
RoleManager<IdentityRole> roleManager, |
|||
IOptions<IdentityOptions> options) |
|||
: base( |
|||
userManager, |
|||
roleManager, |
|||
options) |
|||
{ |
|||
} |
|||
|
|||
[UnitOfWork] |
|||
public override async Task<ClaimsPrincipal> CreateAsync(IdentityUser user) |
|||
{ |
|||
var principal = await base.CreateAsync(user); |
|||
|
|||
if (user.TenantId.HasValue) |
|||
{ |
|||
principal.Identities.First().AddClaim(new Claim(AbpClaimTypes.TenantId, user.TenantId.ToString())); |
|||
} |
|||
|
|||
return principal; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,30 @@ |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Security.Claims; |
|||
using IdentityServer4.Services; |
|||
using Microsoft.Extensions.Logging; |
|||
using Volo.Abp.Security.Claims; |
|||
|
|||
namespace Volo.Abp.IdentityServer |
|||
{ |
|||
public class AbpClaimsService : DefaultClaimsService |
|||
{ |
|||
public AbpClaimsService(IProfileService profile, ILogger<DefaultClaimsService> logger) |
|||
: base(profile, logger) |
|||
{ |
|||
} |
|||
|
|||
protected override IEnumerable<Claim> GetOptionalClaims(ClaimsPrincipal subject) |
|||
{ |
|||
var tenantClaim = subject.FindFirst(AbpClaimTypes.TenantId); |
|||
if (tenantClaim == null) |
|||
{ |
|||
return base.GetOptionalClaims(subject); |
|||
} |
|||
else |
|||
{ |
|||
return base.GetOptionalClaims(subject).Union(new[] { tenantClaim }); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -1,13 +0,0 @@ |
|||
using IdentityServer4.Services; |
|||
using Microsoft.Extensions.Logging; |
|||
|
|||
namespace Volo.Abp.IdentityServer.AspNetIdentity |
|||
{ |
|||
public class AbpClaimsService : DefaultClaimsService |
|||
{ |
|||
public AbpClaimsService(IProfileService profile, ILogger<DefaultClaimsService> logger) |
|||
: base(profile, logger) |
|||
{ |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,21 @@ |
|||
using System.Linq; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Volo.Abp.Security.Claims; |
|||
|
|||
namespace Volo.Abp.MultiTenancy |
|||
{ |
|||
public class CurrentClaimsPrincipalTenantResolveContributer : ITenantResolveContributer |
|||
{ |
|||
public void Resolve(ITenantResolveContext context) |
|||
{ |
|||
var principal = context.ServiceProvider.GetRequiredService<ICurrentPrincipalAccessor>().Principal; |
|||
if (principal?.Identity?.IsAuthenticated != true) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
context.TenantIdOrName = principal.Claims.FirstOrDefault(c => c.Type == AbpClaimTypes.TenantId)?.Value; |
|||
context.Handled = true; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,7 @@ |
|||
namespace Volo.Abp.MultiTenancy |
|||
{ |
|||
public class TenantResolverConsts |
|||
{ |
|||
public const string DefaultTenantKey = "__tenant"; |
|||
} |
|||
} |
|||
@ -0,0 +1,67 @@ |
|||
using System.Linq; |
|||
using System.Security.Claims; |
|||
using JetBrains.Annotations; |
|||
using Volo.Abp; |
|||
using Volo.Abp.Security.Claims; |
|||
|
|||
namespace System.Security.Principal |
|||
{ |
|||
public static class AbpClaimsIdentityExtensions |
|||
{ |
|||
public static Guid? FindUserId([NotNull] this ClaimsPrincipal principal) |
|||
{ |
|||
Check.NotNull(principal, nameof(principal)); |
|||
|
|||
var userIdOrNull = principal.Claims?.FirstOrDefault(c => c.Type == AbpClaimTypes.UserId); |
|||
if (userIdOrNull == null || userIdOrNull.Value.IsNullOrWhiteSpace()) |
|||
{ |
|||
return null; |
|||
} |
|||
|
|||
return Guid.Parse(userIdOrNull.Value); |
|||
} |
|||
|
|||
public static Guid? FindTenantId([NotNull] this ClaimsPrincipal principal) |
|||
{ |
|||
Check.NotNull(principal, nameof(principal)); |
|||
|
|||
var tenantIdOrNull = principal.Claims?.FirstOrDefault(c => c.Type == AbpClaimTypes.TenantId); |
|||
if (tenantIdOrNull == null || tenantIdOrNull.Value.IsNullOrWhiteSpace()) |
|||
{ |
|||
return null; |
|||
} |
|||
|
|||
return Guid.Parse(tenantIdOrNull.Value); |
|||
} |
|||
|
|||
public static Guid? FindUserId([NotNull] this IIdentity identity) |
|||
{ |
|||
Check.NotNull(identity, nameof(identity)); |
|||
|
|||
var claimsIdentity = identity as ClaimsIdentity; |
|||
|
|||
var userIdOrNull = claimsIdentity?.Claims?.FirstOrDefault(c => c.Type == AbpClaimTypes.UserId); |
|||
if (userIdOrNull == null || userIdOrNull.Value.IsNullOrWhiteSpace()) |
|||
{ |
|||
return null; |
|||
} |
|||
|
|||
return Guid.Parse(userIdOrNull.Value); |
|||
} |
|||
|
|||
public static Guid? FindTenantId([NotNull] this IIdentity identity) |
|||
{ |
|||
Check.NotNull(identity, nameof(identity)); |
|||
|
|||
var claimsIdentity = identity as ClaimsIdentity; |
|||
|
|||
var tenantIdOrNull = claimsIdentity?.Claims?.FirstOrDefault(c => c.Type == AbpClaimTypes.TenantId); |
|||
if (tenantIdOrNull == null || tenantIdOrNull.Value.IsNullOrWhiteSpace()) |
|||
{ |
|||
return null; |
|||
} |
|||
|
|||
return Guid.Parse(tenantIdOrNull.Value); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,69 @@ |
|||
using System.Linq; |
|||
using Shouldly; |
|||
using Xunit; |
|||
|
|||
namespace System.Collections.Generic |
|||
{ |
|||
public class AbpListExtensions_Tests |
|||
{ |
|||
[Fact] |
|||
public void InsertAfter() |
|||
{ |
|||
var list = Enumerable.Range(1, 3).ToList(); |
|||
|
|||
list.InsertAfter(i => i == 2, 42); |
|||
|
|||
list.Count.ShouldBe(4); |
|||
list[0].ShouldBe(1); |
|||
list[1].ShouldBe(2); |
|||
list[2].ShouldBe(42); |
|||
list[3].ShouldBe(3); |
|||
|
|||
list.InsertAfter(i => i == 3, 43); |
|||
|
|||
list.Count.ShouldBe(5); |
|||
list[0].ShouldBe(1); |
|||
list[1].ShouldBe(2); |
|||
list[2].ShouldBe(42); |
|||
list[3].ShouldBe(3); |
|||
list[4].ShouldBe(43); |
|||
} |
|||
|
|||
[Fact] |
|||
public void InsertAfter_Should_Insert_To_First_If_Not_Found() |
|||
{ |
|||
var list = Enumerable.Range(1, 3).ToList(); |
|||
|
|||
list.InsertAfter(i => i == 999, 42); |
|||
|
|||
list.Count.ShouldBe(4); |
|||
list[0].ShouldBe(42); |
|||
list[1].ShouldBe(1); |
|||
list[2].ShouldBe(2); |
|||
list[3].ShouldBe(3); |
|||
} |
|||
|
|||
[Fact] |
|||
public void InsertBefore() |
|||
{ |
|||
var list = Enumerable.Range(1, 3).ToList(); |
|||
|
|||
list.InsertBefore(i => i == 2, 42); |
|||
|
|||
list.Count.ShouldBe(4); |
|||
list[0].ShouldBe(1); |
|||
list[1].ShouldBe(42); |
|||
list[2].ShouldBe(2); |
|||
list[3].ShouldBe(3); |
|||
|
|||
list.InsertBefore(i => i == 1, 43); |
|||
|
|||
list.Count.ShouldBe(5); |
|||
list[0].ShouldBe(43); |
|||
list[1].ShouldBe(1); |
|||
list[2].ShouldBe(42); |
|||
list[3].ShouldBe(2); |
|||
list[4].ShouldBe(3); |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue