mirror of https://github.com/abpframework/abp.git
169 changed files with 1512 additions and 794 deletions
|
After Width: | Height: | Size: 7.5 KiB |
|
After Width: | Height: | Size: 8.7 KiB |
|
After Width: | Height: | Size: 154 KiB |
@ -0,0 +1,40 @@ |
|||||
|
using JetBrains.Annotations; |
||||
|
using Microsoft.AspNetCore.Http; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
using Volo.Abp.MultiTenancy; |
||||
|
|
||||
|
namespace Volo.Abp.AspNetCore.MultiTenancy |
||||
|
{ |
||||
|
public class HttpContextTenantResolveResultAccessor : ITenantResolveResultAccessor, ITransientDependency |
||||
|
{ |
||||
|
[CanBeNull] |
||||
|
public TenantResolveResult Result |
||||
|
{ |
||||
|
get |
||||
|
{ |
||||
|
if (_httpContextAccessor.HttpContext == null) |
||||
|
{ |
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
return _httpContextAccessor.HttpContext.Items[""] as TenantResolveResult; |
||||
|
} |
||||
|
set |
||||
|
{ |
||||
|
if (_httpContextAccessor.HttpContext == null) |
||||
|
{ |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
_httpContextAccessor.HttpContext.Items[""] = value; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private readonly IHttpContextAccessor _httpContextAccessor; |
||||
|
|
||||
|
public HttpContextTenantResolveResultAccessor(IHttpContextAccessor httpContextAccessor) |
||||
|
{ |
||||
|
_httpContextAccessor = httpContextAccessor; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,9 @@ |
|||||
|
using Volo.Abp.MultiTenancy; |
||||
|
|
||||
|
namespace Volo.Abp.AspNetCore.MultiTenancy |
||||
|
{ |
||||
|
public interface ITenantResolveResultAccessor |
||||
|
{ |
||||
|
TenantResolveResult Result { get; set; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,23 @@ |
|||||
|
using System.Collections.Generic; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
using Volo.Abp.Localization; |
||||
|
|
||||
|
namespace Volo.Abp.AspNetCore.Mvc.Client |
||||
|
{ |
||||
|
public class RemoteLanguageProvider : ILanguageProvider, ITransientDependency |
||||
|
{ |
||||
|
protected ICachedApplicationConfigurationClient ConfigurationClient { get; } |
||||
|
|
||||
|
public RemoteLanguageProvider(ICachedApplicationConfigurationClient configurationClient) |
||||
|
{ |
||||
|
ConfigurationClient = configurationClient; |
||||
|
} |
||||
|
|
||||
|
public async Task<IReadOnlyList<LanguageInfo>> GetLanguagesAsync() |
||||
|
{ |
||||
|
var configuration = await ConfigurationClient.GetAsync(); |
||||
|
return configuration.Localization.Languages; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -1,16 +1,21 @@ |
|||||
using System; |
using System; |
||||
using System.Collections.Generic; |
using System.Collections.Generic; |
||||
|
using Volo.Abp.Localization; |
||||
|
|
||||
namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations |
namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations |
||||
{ |
{ |
||||
[Serializable] |
[Serializable] |
||||
public class ApplicationLocalizationConfigurationDto |
public class ApplicationLocalizationConfigurationDto |
||||
{ |
{ |
||||
|
//TODO: Rename to Texts?
|
||||
public Dictionary<string, Dictionary<string, string>> Values { get; set; } |
public Dictionary<string, Dictionary<string, string>> Values { get; set; } |
||||
|
|
||||
|
public List<LanguageInfo> Languages { get; set; } |
||||
|
|
||||
public ApplicationLocalizationConfigurationDto() |
public ApplicationLocalizationConfigurationDto() |
||||
{ |
{ |
||||
Values = new Dictionary<string, Dictionary<string, string>>(); |
Values = new Dictionary<string, Dictionary<string, string>>(); |
||||
|
Languages = new List<LanguageInfo>(); |
||||
} |
} |
||||
} |
} |
||||
} |
} |
||||
@ -1,17 +0,0 @@ |
|||||
@using Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy.Components.TenantSwitch |
|
||||
@model TenantSwitchViewComponent.TenantSwitchViewModel |
|
||||
@if (!Model.CurrentUser.IsAuthenticated) |
|
||||
{ |
|
||||
<li class="nav-item"> |
|
||||
<a abp-button="Link" id="TenantSwitchToolbarLink" href="#"> |
|
||||
@if (Model.Tenant == null) |
|
||||
{ |
|
||||
<text>@@host</text> |
|
||||
} |
|
||||
else |
|
||||
{ |
|
||||
<text>@@@Model.Tenant.Name</text> |
|
||||
} |
|
||||
</a> |
|
||||
</li> |
|
||||
} |
|
||||
@ -1,51 +0,0 @@ |
|||||
using System.Threading.Tasks; |
|
||||
using Microsoft.AspNetCore.Mvc; |
|
||||
using Volo.Abp.MultiTenancy; |
|
||||
using Volo.Abp.Users; |
|
||||
|
|
||||
namespace Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy.Components.TenantSwitch |
|
||||
{ |
|
||||
public class TenantSwitchViewComponent : AbpViewComponent |
|
||||
{ |
|
||||
/// <summary>
|
|
||||
/// -1,000,000
|
|
||||
/// </summary>
|
|
||||
public const int Order = -1_000_000; |
|
||||
|
|
||||
protected ITenantStore TenantStore { get; } |
|
||||
protected ICurrentTenant CurrentTenant { get; } |
|
||||
protected ICurrentUser CurrentUser { get; } |
|
||||
|
|
||||
public TenantSwitchViewComponent( |
|
||||
ITenantStore tenantStore, |
|
||||
ICurrentTenant currentTenant, |
|
||||
ICurrentUser currentUser) |
|
||||
{ |
|
||||
TenantStore = tenantStore; |
|
||||
CurrentTenant = currentTenant; |
|
||||
CurrentUser = currentUser; |
|
||||
} |
|
||||
|
|
||||
public async Task<IViewComponentResult> InvokeAsync() |
|
||||
{ |
|
||||
var model = new TenantSwitchViewModel |
|
||||
{ |
|
||||
CurrentUser = CurrentUser |
|
||||
}; |
|
||||
|
|
||||
if (CurrentTenant.Id.HasValue) |
|
||||
{ |
|
||||
model.Tenant = await TenantStore.FindAsync(CurrentTenant.GetId()); |
|
||||
} |
|
||||
|
|
||||
return View("~/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Components/TenantSwitch/Default.cshtml", model); |
|
||||
} |
|
||||
|
|
||||
public class TenantSwitchViewModel |
|
||||
{ |
|
||||
public TenantInfo Tenant { get; set; } |
|
||||
|
|
||||
public ICurrentUser CurrentUser { get; set; } |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,3 +0,0 @@ |
|||||
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers |
|
||||
@addTagHelper *, Volo.Abp.AspNetCore.Mvc.UI.Bootstrap |
|
||||
@addTagHelper *, Volo.Abp.AspNetCore.Mvc.UI.Bundling |
|
||||
@ -1,9 +1,11 @@ |
|||||
{ |
{ |
||||
"culture": "en", |
"culture": "en", |
||||
"texts": { |
"texts": { |
||||
"GivenTenantIsNotAvailable": "Given tenant is not available: {0}", |
"GivenTenantIsNotAvailable": "Given tenant is not available: {0}", |
||||
"SwitchTenant": "Switch tenant", |
"Tenant": "Tenant", |
||||
|
"Switch": "switch", |
||||
"Name": "Name", |
"Name": "Name", |
||||
"SwitchTenantHint": "Leave the name field blank to switch to the host side." |
"SwitchTenantHint": "Leave the name field blank to switch to the host side.", |
||||
|
"NotSelected": "Not selected" |
||||
} |
} |
||||
} |
} |
||||
@ -1,21 +0,0 @@ |
|||||
using System.Threading.Tasks; |
|
||||
using Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy.Components.TenantSwitch; |
|
||||
using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Toolbars; |
|
||||
|
|
||||
namespace Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy |
|
||||
{ |
|
||||
public class MultiTenancyToolbarContributor : IToolbarContributor |
|
||||
{ |
|
||||
public Task ConfigureToolbarAsync(IToolbarConfigurationContext context) |
|
||||
{ |
|
||||
if (context.Toolbar.Name != StandardToolbars.Main) |
|
||||
{ |
|
||||
return Task.CompletedTask; |
|
||||
} |
|
||||
|
|
||||
context.Toolbar.Items.Add(new ToolbarItem(typeof(TenantSwitchViewComponent), TenantSwitchViewComponent.Order)); |
|
||||
|
|
||||
return Task.CompletedTask; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -0,0 +1,48 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using JetBrains.Annotations; |
||||
|
|
||||
|
namespace Volo.Abp.Data |
||||
|
{ |
||||
|
public class DataSeedContext |
||||
|
{ |
||||
|
public Guid? TenantId { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets/sets a key-value on the <see cref="Properties"/>.
|
||||
|
/// </summary>
|
||||
|
/// <param name="name">Name of the property</param>
|
||||
|
/// <returns>
|
||||
|
/// Returns the value in the <see cref="Properties"/> dictionary by given <see cref="name"/>.
|
||||
|
/// Returns null if given <see cref="name"/> is not present in the <see cref="Properties"/> dictionary.
|
||||
|
/// </returns>
|
||||
|
[CanBeNull] |
||||
|
public object this[string name] |
||||
|
{ |
||||
|
get => Properties.GetOrDefault(name); |
||||
|
set => Properties[name] = value; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Can be used to get/set custom properties.
|
||||
|
/// </summary>
|
||||
|
[NotNull] |
||||
|
public Dictionary<string, object> Properties { get; } |
||||
|
|
||||
|
public DataSeedContext(Guid? tenantId = null) |
||||
|
{ |
||||
|
TenantId = tenantId; |
||||
|
Properties = new Dictionary<string, object>(); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Sets a property in the <see cref="Properties"/> dictionary.
|
||||
|
/// This is a shortcut for nested calls on this object.
|
||||
|
/// </summary>
|
||||
|
public virtual DataSeedContext WithProperty(string key, object value) |
||||
|
{ |
||||
|
Properties[key] = value; |
||||
|
return this; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,9 @@ |
|||||
|
using Volo.Abp.Collections; |
||||
|
|
||||
|
namespace Volo.Abp.Data |
||||
|
{ |
||||
|
public class DataSeedContributorList : TypeList<IDataSeedContributor> |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,12 @@ |
|||||
|
namespace Volo.Abp.Data |
||||
|
{ |
||||
|
public class DataSeedOptions |
||||
|
{ |
||||
|
public DataSeedContributorList Contributors { get; } |
||||
|
|
||||
|
public DataSeedOptions() |
||||
|
{ |
||||
|
Contributors = new DataSeedContributorList(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,37 @@ |
|||||
|
using System.Threading.Tasks; |
||||
|
using Microsoft.Extensions.DependencyInjection; |
||||
|
using Microsoft.Extensions.Options; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
|
||||
|
namespace Volo.Abp.Data |
||||
|
{ |
||||
|
//TODO: Create a Volo.Abp.Data.Seeding namespace?
|
||||
|
public class DataSeeder : IDataSeeder, ITransientDependency |
||||
|
{ |
||||
|
protected IHybridServiceScopeFactory ServiceScopeFactory { get; } |
||||
|
protected DataSeedOptions Options { get; } |
||||
|
|
||||
|
public DataSeeder( |
||||
|
IOptions<DataSeedOptions> options, |
||||
|
IHybridServiceScopeFactory serviceScopeFactory) |
||||
|
{ |
||||
|
ServiceScopeFactory = serviceScopeFactory; |
||||
|
Options = options.Value; |
||||
|
} |
||||
|
|
||||
|
public async Task SeedAsync(DataSeedContext context) |
||||
|
{ |
||||
|
using (var scope = ServiceScopeFactory.CreateScope()) |
||||
|
{ |
||||
|
foreach (var contributorType in Options.Contributors) |
||||
|
{ |
||||
|
var contributor = (IDataSeedContributor) scope |
||||
|
.ServiceProvider |
||||
|
.GetRequiredService(contributorType); |
||||
|
|
||||
|
await contributor.SeedAsync(context); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,13 @@ |
|||||
|
using System; |
||||
|
using System.Threading.Tasks; |
||||
|
|
||||
|
namespace Volo.Abp.Data |
||||
|
{ |
||||
|
public static class DataSeederExtensions |
||||
|
{ |
||||
|
public static Task SeedAsync(this IDataSeeder seeder, Guid? tenantId = null) |
||||
|
{ |
||||
|
return seeder.SeedAsync(new DataSeedContext(tenantId)); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,9 @@ |
|||||
|
using System.Threading.Tasks; |
||||
|
|
||||
|
namespace Volo.Abp.Data |
||||
|
{ |
||||
|
public interface IDataSeedContributor |
||||
|
{ |
||||
|
Task SeedAsync(DataSeedContext context); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,9 @@ |
|||||
|
using System.Threading.Tasks; |
||||
|
|
||||
|
namespace Volo.Abp.Data |
||||
|
{ |
||||
|
public interface IDataSeeder |
||||
|
{ |
||||
|
Task SeedAsync(DataSeedContext context); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,8 @@ |
|||||
|
namespace Volo.Abp.Localization |
||||
|
{ |
||||
|
[LocalizationResourceName("Default")] |
||||
|
public class DefaultResource |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
} |
||||
@ -1,15 +0,0 @@ |
|||||
using Volo.Abp.Data; |
|
||||
using Volo.Abp.Modularity; |
|
||||
using Volo.Abp.Security; |
|
||||
|
|
||||
namespace Volo.Abp.MultiTenancy |
|
||||
{ |
|
||||
[DependsOn( |
|
||||
typeof(AbpDataModule), |
|
||||
typeof(AbpSecurityModule) |
|
||||
)] |
|
||||
public class AbpMultiTenancyAbstractionsModule : AbpModule //TODO: Rename to AbpMultiTenancyModule?
|
|
||||
{ |
|
||||
|
|
||||
} |
|
||||
} |
|
||||
@ -1,21 +0,0 @@ |
|||||
using System.Threading; |
|
||||
using Volo.Abp.DependencyInjection; |
|
||||
|
|
||||
namespace Volo.Abp.MultiTenancy |
|
||||
{ |
|
||||
public class AsyncLocalCurrentTenantIdAccessor : ICurrentTenantIdAccessor, ISingletonDependency |
|
||||
{ |
|
||||
public TenantIdWrapper Current |
|
||||
{ |
|
||||
get => _currentScope.Value; |
|
||||
set => _currentScope.Value = value; |
|
||||
} |
|
||||
|
|
||||
private readonly AsyncLocal<TenantIdWrapper> _currentScope; |
|
||||
|
|
||||
public AsyncLocalCurrentTenantIdAccessor() |
|
||||
{ |
|
||||
_currentScope = new AsyncLocal<TenantIdWrapper>(); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,30 +0,0 @@ |
|||||
using System; |
|
||||
using System.Linq; |
|
||||
using System.Threading.Tasks; |
|
||||
using Microsoft.Extensions.Options; |
|
||||
using Volo.Abp.DependencyInjection; |
|
||||
|
|
||||
namespace Volo.Abp.MultiTenancy.ConfigurationStore |
|
||||
{ |
|
||||
//TODO: Move to another package.
|
|
||||
[Dependency(TryRegister = true)] |
|
||||
public class ConfigurationTenantStore : ITenantStore, ITransientDependency |
|
||||
{ |
|
||||
private readonly ConfigurationTenantStoreOptions _options; |
|
||||
|
|
||||
public ConfigurationTenantStore(IOptionsSnapshot<ConfigurationTenantStoreOptions> options) |
|
||||
{ |
|
||||
_options = options.Value; |
|
||||
} |
|
||||
|
|
||||
public Task<TenantInfo> FindAsync(string name) |
|
||||
{ |
|
||||
return Task.FromResult(_options.Tenants.FirstOrDefault(t => t.Name == name)); |
|
||||
} |
|
||||
|
|
||||
public Task<TenantInfo> FindAsync(Guid id) |
|
||||
{ |
|
||||
return Task.FromResult(_options.Tenants.FirstOrDefault(t => t.Id == id)); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,12 +0,0 @@ |
|||||
namespace Volo.Abp.MultiTenancy.ConfigurationStore |
|
||||
{ |
|
||||
public class ConfigurationTenantStoreOptions |
|
||||
{ |
|
||||
public TenantInfo[] Tenants { get; set; } |
|
||||
|
|
||||
public ConfigurationTenantStoreOptions() |
|
||||
{ |
|
||||
Tenants = new TenantInfo[0]; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,34 +0,0 @@ |
|||||
using System; |
|
||||
using Volo.Abp.DependencyInjection; |
|
||||
|
|
||||
namespace Volo.Abp.MultiTenancy |
|
||||
{ |
|
||||
public class CurrentTenant : ICurrentTenant, ITransientDependency |
|
||||
{ |
|
||||
public virtual bool IsAvailable => Id.HasValue; |
|
||||
|
|
||||
public virtual Guid? Id => _currentTenantIdAccessor.Current?.TenantId; |
|
||||
|
|
||||
private readonly ICurrentTenantIdAccessor _currentTenantIdAccessor; |
|
||||
|
|
||||
public CurrentTenant(ICurrentTenantIdAccessor currentTenantIdAccessor) |
|
||||
{ |
|
||||
_currentTenantIdAccessor = currentTenantIdAccessor; |
|
||||
} |
|
||||
|
|
||||
public IDisposable Change(Guid? id) |
|
||||
{ |
|
||||
return SetCurrent(id); |
|
||||
} |
|
||||
|
|
||||
private IDisposable SetCurrent(Guid? tenantId) |
|
||||
{ |
|
||||
var parentScope = _currentTenantIdAccessor.Current; |
|
||||
_currentTenantIdAccessor.Current = new TenantIdWrapper(tenantId); |
|
||||
return new DisposeAction(() => |
|
||||
{ |
|
||||
_currentTenantIdAccessor.Current = parentScope; |
|
||||
}); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,13 +0,0 @@ |
|||||
namespace Volo.Abp.MultiTenancy |
|
||||
{ |
|
||||
/* Uses TenantScopeTenantInfoWrapper instead of TenantInfo because being null of Current is different that being null of Current.Tenant. |
|
||||
* A null Current indicates that we haven't set it explicitly. |
|
||||
* A null Current.Tenant indicates that we have set null tenant value explicitly. |
|
||||
* A non-null Current.Tenant indicates that we have set a tenant value explicitly. |
|
||||
*/ |
|
||||
|
|
||||
public interface ICurrentTenantIdAccessor |
|
||||
{ |
|
||||
TenantIdWrapper Current { get; set; } |
|
||||
} |
|
||||
} |
|
||||
@ -1,18 +0,0 @@ |
|||||
using System; |
|
||||
|
|
||||
namespace Volo.Abp.MultiTenancy |
|
||||
{ |
|
||||
public class TenantIdWrapper |
|
||||
{ |
|
||||
/// <summary>
|
|
||||
/// Null indicates the host.
|
|
||||
/// Not null value for a tenant.
|
|
||||
/// </summary>
|
|
||||
public Guid? TenantId { get; } |
|
||||
|
|
||||
public TenantIdWrapper(Guid? tenantId) |
|
||||
{ |
|
||||
TenantId = tenantId; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -0,0 +1,23 @@ |
|||||
|
using Microsoft.Extensions.DependencyInjection; |
||||
|
using Volo.Abp.Data; |
||||
|
using Volo.Abp.Modularity; |
||||
|
using Volo.Abp.MultiTenancy.ConfigurationStore; |
||||
|
using Volo.Abp.Security; |
||||
|
|
||||
|
namespace Volo.Abp.MultiTenancy |
||||
|
{ |
||||
|
//TODO: Create a Volo.Abp.MultiTenancy.Abstractions package?
|
||||
|
|
||||
|
[DependsOn( |
||||
|
typeof(AbpDataModule), |
||||
|
typeof(AbpSecurityModule) |
||||
|
)] |
||||
|
public class AbpMultiTenancyModule : AbpModule |
||||
|
{ |
||||
|
public override void ConfigureServices(ServiceConfigurationContext context) |
||||
|
{ |
||||
|
var configuration = context.Services.GetConfiguration(); |
||||
|
Configure<DefaultTenantStoreOptions>(configuration); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,21 @@ |
|||||
|
using System.Threading; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
|
||||
|
namespace Volo.Abp.MultiTenancy |
||||
|
{ |
||||
|
public class AsyncLocalCurrentTenantAccessor : ICurrentTenantAccessor, ISingletonDependency |
||||
|
{ |
||||
|
public BasicTenantInfo Current |
||||
|
{ |
||||
|
get => _currentScope.Value; |
||||
|
set => _currentScope.Value = value; |
||||
|
} |
||||
|
|
||||
|
private readonly AsyncLocal<BasicTenantInfo> _currentScope; |
||||
|
|
||||
|
public AsyncLocalCurrentTenantAccessor() |
||||
|
{ |
||||
|
_currentScope = new AsyncLocal<BasicTenantInfo>(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,27 @@ |
|||||
|
using System; |
||||
|
using JetBrains.Annotations; |
||||
|
|
||||
|
namespace Volo.Abp.MultiTenancy |
||||
|
{ |
||||
|
public class BasicTenantInfo |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Null indicates the host.
|
||||
|
/// Not null value for a tenant.
|
||||
|
/// </summary>
|
||||
|
[CanBeNull] |
||||
|
public Guid? TenantId { get; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Name of the tenant if <see cref="TenantId"/> is not null.
|
||||
|
/// </summary>
|
||||
|
[CanBeNull] |
||||
|
public string Name { get; } |
||||
|
|
||||
|
public BasicTenantInfo(Guid? tenantId, string name = null) |
||||
|
{ |
||||
|
TenantId = tenantId; |
||||
|
Name = name; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,29 @@ |
|||||
|
using System; |
||||
|
using System.Linq; |
||||
|
using System.Threading.Tasks; |
||||
|
using Microsoft.Extensions.Options; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
|
||||
|
namespace Volo.Abp.MultiTenancy.ConfigurationStore |
||||
|
{ |
||||
|
[Dependency(TryRegister = true)] |
||||
|
public class DefaultTenantStore : ITenantStore, ITransientDependency |
||||
|
{ |
||||
|
private readonly DefaultTenantStoreOptions _options; |
||||
|
|
||||
|
public DefaultTenantStore(IOptionsSnapshot<DefaultTenantStoreOptions> options) |
||||
|
{ |
||||
|
_options = options.Value; |
||||
|
} |
||||
|
|
||||
|
public Task<TenantConfiguration> FindAsync(string name) |
||||
|
{ |
||||
|
return Task.FromResult(_options.Tenants?.FirstOrDefault(t => t.Name == name)); |
||||
|
} |
||||
|
|
||||
|
public Task<TenantConfiguration> FindAsync(Guid id) |
||||
|
{ |
||||
|
return Task.FromResult(_options.Tenants?.FirstOrDefault(t => t.Id == id)); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,12 @@ |
|||||
|
namespace Volo.Abp.MultiTenancy.ConfigurationStore |
||||
|
{ |
||||
|
public class DefaultTenantStoreOptions |
||||
|
{ |
||||
|
public TenantConfiguration[] Tenants { get; set; } |
||||
|
|
||||
|
public DefaultTenantStoreOptions() |
||||
|
{ |
||||
|
Tenants = new TenantConfiguration[0]; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,36 @@ |
|||||
|
using System; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
|
||||
|
namespace Volo.Abp.MultiTenancy |
||||
|
{ |
||||
|
public class CurrentTenant : ICurrentTenant, ITransientDependency |
||||
|
{ |
||||
|
public virtual bool IsAvailable => Id.HasValue; |
||||
|
|
||||
|
public virtual Guid? Id => _currentTenantAccessor.Current?.TenantId; |
||||
|
|
||||
|
public string Name => _currentTenantAccessor.Current?.Name; |
||||
|
|
||||
|
private readonly ICurrentTenantAccessor _currentTenantAccessor; |
||||
|
|
||||
|
public CurrentTenant(ICurrentTenantAccessor currentTenantAccessor) |
||||
|
{ |
||||
|
_currentTenantAccessor = currentTenantAccessor; |
||||
|
} |
||||
|
|
||||
|
public IDisposable Change(Guid? id, string name = null) |
||||
|
{ |
||||
|
return SetCurrent(id, name); |
||||
|
} |
||||
|
|
||||
|
private IDisposable SetCurrent(Guid? tenantId, string name = null) |
||||
|
{ |
||||
|
var parentScope = _currentTenantAccessor.Current; |
||||
|
_currentTenantAccessor.Current = new BasicTenantInfo(tenantId, name); |
||||
|
return new DisposeAction(() => |
||||
|
{ |
||||
|
_currentTenantAccessor.Current = parentScope; |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,12 @@ |
|||||
|
namespace Volo.Abp.MultiTenancy |
||||
|
{ |
||||
|
/* A null Current indicates that we haven't set it explicitly. |
||||
|
* A null Current.TenantId indicates that we have set null tenant id value explicitly. |
||||
|
* A non-null Current.TenantId indicates that we have set a tenant id value explicitly. |
||||
|
*/ |
||||
|
|
||||
|
public interface ICurrentTenantAccessor |
||||
|
{ |
||||
|
BasicTenantInfo Current { get; set; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,12 @@ |
|||||
|
using System; |
||||
|
|
||||
|
namespace Volo.Abp.MultiTenancy |
||||
|
{ |
||||
|
[Flags] |
||||
|
public enum MultiTenancyDatabaseStyle |
||||
|
{ |
||||
|
Shared = 1, |
||||
|
PerTenant = 2, |
||||
|
Hybrid = Shared | PerTenant |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,17 @@ |
|||||
|
namespace Volo.Abp.MultiTenancy |
||||
|
{ |
||||
|
public class MultiTenancyOptions |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// A central point to enable/disable multi-tenancy.
|
||||
|
/// Default: false.
|
||||
|
/// </summary>
|
||||
|
public bool IsEnabled { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Database style for tenants.
|
||||
|
/// Default: <see cref="MultiTenancyDatabaseStyle.Hybrid"/>.
|
||||
|
/// </summary>
|
||||
|
public MultiTenancyDatabaseStyle DatabaseStyle { get; set; } = MultiTenancyDatabaseStyle.Hybrid; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,26 @@ |
|||||
|
using System; |
||||
|
|
||||
|
namespace Volo.Abp.MultiTenancy |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Represents sides in a multi tenancy application.
|
||||
|
/// </summary>
|
||||
|
[Flags] |
||||
|
public enum MultiTenancySides |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Tenant side.
|
||||
|
/// </summary>
|
||||
|
Tenant = 1, |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Host side.
|
||||
|
/// </summary>
|
||||
|
Host = 2, |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Both sides
|
||||
|
/// </summary>
|
||||
|
Both = Tenant | Host |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,10 @@ |
|||||
|
namespace Volo.Abp.MultiTenancy |
||||
|
{ |
||||
|
public abstract class TenantResolveContributorBase : ITenantResolveContributor |
||||
|
{ |
||||
|
public abstract string Name { get; } |
||||
|
|
||||
|
//TODO: We can make this async
|
||||
|
public abstract void Resolve(ITenantResolveContext context); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,16 @@ |
|||||
|
using System.Collections.Generic; |
||||
|
|
||||
|
namespace Volo.Abp.MultiTenancy |
||||
|
{ |
||||
|
public class TenantResolveResult |
||||
|
{ |
||||
|
public string TenantIdOrName { get; set; } |
||||
|
|
||||
|
public List<string> AppliedResolvers { get; } |
||||
|
|
||||
|
public TenantResolveResult() |
||||
|
{ |
||||
|
AppliedResolvers = new List<string>(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue