Skip to content

Commit

Permalink
Merge pull request #64 from marcwittke/develop
Browse files Browse the repository at this point in the history
Develop
  • Loading branch information
marcwittke committed Mar 5, 2019
2 parents 8a0862b + 15160a3 commit b569fc5
Show file tree
Hide file tree
Showing 44 changed files with 726 additions and 910 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
using System;
using System.Linq;
using System.Reflection;
using Backend.Fx.Environment.Authentication;
using Backend.Fx.Logging;
using Backend.Fx.Patterns.DataGeneration;
using Backend.Fx.Patterns.DependencyInjection;
using Backend.Fx.Patterns.EventAggregation.Integration;

namespace Backend.Fx.Environment.MultiTenancy
{
public static class BackendFxApplicationTenantExtensions
{
private static readonly ILogger Logger = LogManager.Create(typeof(BackendFxApplicationTenantExtensions));

public static void RegisterSeedActionForNewlyCreatedTenants(this IBackendFxApplication application, ITenantService tenantService)
{
application.CompositionRoot
.GetInstance<IEventBus>()
.Subscribe(new DelegateIntegrationEventHandler<TenantCreated>(tenantCreated =>
{
try
{
var tenantId = new TenantId(tenantCreated.TenantId);
application.SeedDataForTenant(tenantId, tenantCreated.IsDemoTenant);
tenantService.ActivateTenant(tenantId);
}
catch (Exception ex)
{
Logger.Error(ex, "Handling TenantCreated event failed");
}
}));
}

public static void SeedDataForAllActiveTenants(this IBackendFxApplication application)
{
using (Logger.InfoDuration("Seeding data"))
{
var prodTenantIds = application.TenantIdService.GetActiveProductionTenantIds();
foreach (var prodTenantId in prodTenantIds)
{
application.SeedDataForTenant(prodTenantId, false);
}

var demoTenantIds = application.TenantIdService.GetActiveDemonstrationTenantIds();
foreach (var demoTenantId in demoTenantIds)
{
application.SeedDataForTenant(demoTenantId, true);
}
}
}

private static void SeedDataForTenant(this IBackendFxApplication application, TenantId tenantId, bool isDemoTenant)
{
using (Logger.InfoDuration($"Seeding data for tenant {tenantId.Value}"))
{
Type[] dataGeneratorTypesToRun;

using (application.BeginScope())
{
var dataGenerators = application.CompositionRoot.GetInstances<IDataGenerator>()
.OrderBy(dg => dg.Priority)
.Select(dg => dg.GetType());

if (!isDemoTenant)
{
dataGenerators = dataGenerators.Where(dg => !typeof(IDemoDataGenerator).IsAssignableFrom(dg));
}

dataGeneratorTypesToRun = dataGenerators.ToArray();
}

foreach (var dataGeneratorTypeToRun in dataGeneratorTypesToRun)
{
application.Invoke(() =>
{
IDataGenerator dataGenerator = application
.CompositionRoot
.GetInstances<IDataGenerator>()
.Single(dg => dg.GetType() == dataGeneratorTypeToRun);
dataGenerator.Generate();
}, new SystemIdentity(), tenantId);
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
using System.Linq;

namespace Backend.Fx.Environment.MultiTenancy
{
public interface ITenantIdService
{
TenantId[] GetActiveTenantIds();
TenantId[] GetActiveDemonstrationTenantIds();
TenantId[] GetActiveProductionTenantIds();
}

public class TenantIdService : ITenantIdService
{
private readonly ITenantRepository _tenantRepository;

public TenantIdService(ITenantRepository tenantRepository)
{
_tenantRepository = tenantRepository;
}


public TenantId[] GetActiveTenantIds()
{
return _tenantRepository
.GetTenants()
.Where(t => t.State == TenantState.Active)
.Select(t => new TenantId(t.Id))
.ToArray();
}

public TenantId[] GetActiveDemonstrationTenantIds()
{
return _tenantRepository
.GetTenants()
.Where(t => t.State == TenantState.Active && t.IsDemoTenant)
.Select(t => new TenantId(t.Id))
.ToArray();
}

public TenantId[] GetActiveProductionTenantIds()
{
return _tenantRepository
.GetTenants()
.Where(t => t.State == TenantState.Active && !t.IsDemoTenant)
.Select(t => new TenantId(t.Id))
.ToArray();
}
}

}
111 changes: 0 additions & 111 deletions src/abstractions/Backend.Fx/Environment/MultiTenancy/ITenantManager.cs

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
namespace Backend.Fx.Environment.MultiTenancy
{
public interface ITenantRepository
{
void SaveTenant(Tenant tenant);

Tenant[] GetTenants();

Tenant GetTenant(TenantId tenantId);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
using System;
using System.Linq;
using Backend.Fx.Logging;
using Backend.Fx.Patterns.EventAggregation.Integration;
using JetBrains.Annotations;

namespace Backend.Fx.Environment.MultiTenancy
{
/// <summary>
/// Encapsulates the management of tenants
/// Note that this should not use repositories and other building blocks, but access the persistence layer directly
/// </summary>
public interface ITenantService
{
TenantId CreateDemonstrationTenant(string name, string description, string defaultCultureName);
TenantId CreateProductionTenant(string name, string description, string defaultCultureName);
void ActivateTenant(TenantId tenantId);
void DeactivateTenant(TenantId tenantId);
}

public class TenantService : ITenantService
{
private readonly IEventBus _eventBus;
private readonly ITenantRepository _tenantRepository;
private static readonly ILogger Logger = LogManager.Create<TenantService>();

public TenantService(IEventBus eventBus, ITenantRepository tenantRepository)
{
_eventBus = eventBus;
_tenantRepository = tenantRepository;
}

public TenantId CreateDemonstrationTenant(string name, string description, string defaultCultureName)
{
Logger.Info($"Creating demonstration tenant: {name}");
return CreateTenant(name, description, true, defaultCultureName);
}

public TenantId CreateProductionTenant(string name, string description, string defaultCultureName)
{
Logger.Info($"Creating production tenant: {name}");
return CreateTenant(name, description, false, defaultCultureName);
}

public void ActivateTenant(TenantId tenantId)
{
var tenant = _tenantRepository.GetTenant(tenantId);
tenant.State = TenantState.Active;
_tenantRepository.SaveTenant(tenant);
_eventBus.Publish(new TenantActivated(tenant.Id, tenant.Name, tenant.Description, tenant.IsDemoTenant, tenant.DefaultCultureName));
}

public void DeactivateTenant(TenantId tenantId)
{
var tenant = _tenantRepository.GetTenant(tenantId);
tenant.State = TenantState.Inactive;
_tenantRepository.SaveTenant(tenant);
_eventBus.Publish(new TenantDeactivated(tenant.Id, tenant.Name, tenant.Description, tenant.IsDemoTenant, tenant.DefaultCultureName));
}

protected virtual TenantId CreateTenant([NotNull] string name, string description, bool isDemo, string defaultCultureName)
{
if (string.IsNullOrWhiteSpace(name))
{
throw new ArgumentException("Value cannot be null or whitespace.", nameof(name));
}

if (_tenantRepository.GetTenants().Any(t => t.Name != null && t.Name.ToLowerInvariant() == name.ToLowerInvariant()))
{
throw new ArgumentException($"There is already a tenant named {name}");
}

Tenant tenant = new Tenant(name, description, isDemo, defaultCultureName);
_tenantRepository.SaveTenant(tenant);
var tenantId = new TenantId(tenant.Id);
_eventBus.Publish(new TenantCreated(tenant.Id, tenant.Name, tenant.Description, tenant.IsDemoTenant, tenant.DefaultCultureName));
return tenantId;
}
}
}

0 comments on commit b569fc5

Please sign in to comment.