using System; using System.Collections.Generic; using System.Data.Common; using System.Data.Entity; using System.Linq; using System.Threading.Tasks; using Abp; using Abp.Configuration.Startup; using Abp.Domain.Uow; using Abp.Runtime.Session; using Abp.TestBase; using WePlatform.Authorization.Users; using WePlatform.MultiTenancy; using Castle.MicroKernel.Registration; using Effort; using EntityFramework.DynamicFilters; using WePlatform.EF; using WePlatform.SeedData; using IwbZero.Authorization.Base.Users; using IwbZero.MultiTenancy; namespace WePlatform { public abstract class WePlatformTestBase : AbpIntegratedTestBase { private DbConnection _hostDb; private Dictionary _tenantDbs; //only used for db per tenant architecture protected WePlatformTestBase() { //Seed initial data for host //AbpSession.TenantId = null; //UsingDbContext(context => //{ // new InitialDbBuilder(context).Create(); //}); ////Seed initial data for default tenant //AbpSession.TenantId = 1; //UsingDbContext(context => //{ // new RoleAndUserCreator(context).Create(); //}); //UsingDbContext(context => //{ // new TestDataBuilder(context).Create(); //}); LoginAsDefaultTenantAdmin(); } protected override void PreInitialize() { base.PreInitialize(); /* You can switch database architecture here: */ UseSingleDatabase(); //UseDatabasePerTenant(); } /* Uses single database for host and all tenants. */ private void UseSingleDatabase() { _hostDb = DbConnectionFactory.CreateTransient(); LocalIocManager.IocContainer.Register( Component.For() .UsingFactoryMethod(() => _hostDb) .LifestyleSingleton() ); } /* Uses single database for host and Default tenant, * but dedicated databases for all other tenants. */ private void UseDatabasePerTenant() { _hostDb = DbConnectionFactory.CreateTransient(); _tenantDbs = new Dictionary(); LocalIocManager.IocContainer.Register( Component.For() .UsingFactoryMethod((kernel) => { lock (_tenantDbs) { var currentUow = kernel.Resolve().Current; var abpSession = kernel.Resolve(); var tenantId = currentUow != null ? currentUow.GetTenantId() : abpSession.TenantId; if (tenantId == null || tenantId == 1) //host and default tenant are stored in host db { return _hostDb; } if (!_tenantDbs.ContainsKey(tenantId.Value)) { _tenantDbs[tenantId.Value] = DbConnectionFactory.CreateTransient(); } return _tenantDbs[tenantId.Value]; } }, true) .LifestyleTransient() ); } #region UsingDbContext protected IDisposable UsingTenantId(int? tenantId) { var previousTenantId = AbpSession.TenantId; AbpSession.TenantId = tenantId; return new DisposeAction(() => AbpSession.TenantId = previousTenantId); } protected void UsingDbContext(Action action) { UsingDbContext(AbpSession.TenantId, action); } protected Task UsingDbContextAsync(Func action) { return UsingDbContextAsync(AbpSession.TenantId, action); } protected T UsingDbContext(Func func) { return UsingDbContext(AbpSession.TenantId, func); } protected Task UsingDbContextAsync(Func> func) { return UsingDbContextAsync(AbpSession.TenantId, func); } protected void UsingDbContext(int? tenantId, Action action) { using (UsingTenantId(tenantId)) { using (var context = LocalIocManager.Resolve()) { context.DisableAllFilters(); action(context); context.SaveChanges(); } } } protected async Task UsingDbContextAsync(int? tenantId, Func action) { using (UsingTenantId(tenantId)) { using (var context = LocalIocManager.Resolve()) { context.DisableAllFilters(); await action(context); await context.SaveChangesAsync(); } } } protected T UsingDbContext(int? tenantId, Func func) { T result; using (UsingTenantId(tenantId)) { using (var context = LocalIocManager.Resolve()) { context.DisableAllFilters(); result = func(context); context.SaveChanges(); } } return result; } protected async Task UsingDbContextAsync(int? tenantId, Func> func) { T result; using (UsingTenantId(tenantId)) { using (var context = LocalIocManager.Resolve()) { context.DisableAllFilters(); result = await func(context); await context.SaveChangesAsync(); } } return result; } #endregion #region Login protected void LoginAsHostAdmin() { LoginAsHost(UserBase.AdminUserName); } protected void LoginAsDefaultTenantAdmin() { LoginAsTenant(TenantBase.DefaultTenantName, UserBase.AdminUserName); } protected void LogoutAsDefaultTenant() { LogoutAsTenant(TenantBase.DefaultTenantName); } protected void LoginAsHost(string userName) { AbpSession.TenantId = null; var user = UsingDbContext( context => context.Users.FirstOrDefault(u => u.TenantId == AbpSession.TenantId && u.UserName == userName)); if (user == null) { throw new Exception("There is no user: " + userName + " for host."); } AbpSession.UserId = user.Id; } protected void LogoutAsHost() { Resolve().IsEnabled = true; AbpSession.TenantId = null; AbpSession.UserId = null; } protected void LoginAsTenant(string tenancyName, string userName) { var tenant = UsingDbContext(context => context.Tenants.FirstOrDefault(t => t.TenancyName == tenancyName)); if (tenant == null) { throw new Exception("There is no tenant: " + tenancyName); } AbpSession.TenantId = tenant.Id; var user = UsingDbContext( context => context.Users.FirstOrDefault(u => u.TenantId == AbpSession.TenantId && u.UserName == userName)); if (user == null) { throw new Exception("There is no user: " + userName + " for tenant: " + tenancyName); } AbpSession.UserId = user.Id; } protected void LogoutAsTenant(string tenancyName) { var tenant = UsingDbContext(context => context.Tenants.FirstOrDefault(t => t.TenancyName == tenancyName)); if (tenant == null) { throw new Exception("There is no tenant: " + tenancyName); } AbpSession.TenantId = tenant.Id; AbpSession.UserId = null; } #endregion /// /// Gets current user if is not null. /// Throws exception if it's null. /// protected async Task GetCurrentUserAsync() { var userId = AbpSession.GetUserId(); return await UsingDbContext(context => context.Users.SingleAsync(u => u.Id == userId)); } /// /// Gets current tenant if is not null. /// Throws exception if there is no current tenant. /// protected async Task GetCurrentTenantAsync() { var tenantId = AbpSession.GetTenantId(); return await UsingDbContext(context => context.Tenants.SingleAsync(t => t.Id == tenantId)); } } }