Skip to content

Commit

Permalink
Merge branch 'dev' of https://github.com/rdefreitas/saaskit into rdef…
Browse files Browse the repository at this point in the history
…reitas-dev
  • Loading branch information
Ben Foster committed Jul 2, 2016
2 parents bb5637b + 90d789c commit 4e79e4a
Show file tree
Hide file tree
Showing 23 changed files with 1,581 additions and 126 deletions.
2 changes: 1 addition & 1 deletion SaasKit.sln
@@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.24720.0
VisualStudioVersion = 14.0.25420.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{C3B2A3F2-5EF9-4128-8035-255A1AC1AF7B}"
ProjectSection(SolutionItems) = preProject
Expand Down
1 change: 1 addition & 0 deletions samples/AspNetMvcAuthDemo/Startup.cs
Expand Up @@ -82,6 +82,7 @@ public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerF
ClientId = clientId,
ClientSecret = clientSecret
});
}
});
Expand Down
8 changes: 4 additions & 4 deletions samples/AspNetMvcAuthDemo/project.json
Expand Up @@ -93,9 +93,9 @@
"web.config"
]
},
"scripts": {
"prepublish": [ "bower install", "dotnet bundle" ],
"postpublish": [ "dotnet publish-iis --publish-folder %publish:OutputPath% --framework %publish:FullTargetFramework%" ]
},
"scripts": {
"prepublish": [ "bower install", "dotnet bundle" ],
"postpublish": [ "dotnet publish-iis --publish-folder %publish:OutputPath% --framework %publish:FullTargetFramework%" ]
},
"userSecretsId": "aspnet5-AspNetMvcAuthSample-20160229033356"
}
1 change: 1 addition & 0 deletions samples/AspNetMvcAuthDemo/wwwroot/css/site.min.css

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions samples/AspNetMvcAuthDemo/wwwroot/js/site.min.js
@@ -0,0 +1 @@
// Write your Javascript code.
10 changes: 6 additions & 4 deletions samples/AspNetMvcSample/Controllers/HomeController.cs
Expand Up @@ -4,16 +4,18 @@
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using SaasKit.Multitenancy;

namespace AspNetMvcSample.Controllers
{
public class HomeController : Controller

public class HomeController : Controller
{
private AppTenant tenant;
private readonly AppTenant tenant;

public HomeController(AppTenant tenant)
public HomeController(ITenant<AppTenant> tenant)
{
this.tenant = tenant;
this.tenant = tenant?.Value;
}

public IActionResult Index()
Expand Down
8 changes: 4 additions & 4 deletions samples/AspNetMvcSample/project.json
Expand Up @@ -88,8 +88,8 @@
"web.config"
]
},
"scripts": {
"prepublish": [ "bower install", "dotnet bundle" ],
"postpublish": [ "dotnet publish-iis --publish-folder %publish:OutputPath% --framework %publish:FullTargetFramework%" ]
}
"scripts": {
"prepublish": [ "bower install", "dotnet bundle" ],
"postpublish": [ "dotnet publish-iis --publish-folder %publish:OutputPath% --framework %publish:FullTargetFramework%" ]
}
}
1 change: 1 addition & 0 deletions samples/AspNetMvcSample/wwwroot/css/site.min.css

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions samples/AspNetMvcSample/wwwroot/js/site.min.js
@@ -0,0 +1 @@
// Write your Javascript code.
2 changes: 2 additions & 0 deletions samples/AspNetSample/project.json
Expand Up @@ -27,6 +27,7 @@
}
},
"tools": {
"BundlerMinifier.Core": "2.0.238",
"Microsoft.AspNetCore.Server.IISIntegration.Tools": "1.0.0-preview2-final"
},
"buildOptions": {
Expand All @@ -50,6 +51,7 @@
]
},
"scripts": {
"prepublish": [ "bower install", "dotnet bundle" ],
"postpublish": "dotnet publish-iis --publish-folder %publish:OutputPath% --framework %publish:FullTargetFramework%"
}
}
21 changes: 11 additions & 10 deletions samples/AspNetStructureMapSample/project.json
Expand Up @@ -23,12 +23,13 @@
}
}
},
"tools": {
"Microsoft.AspNetCore.Server.IISIntegration.Tools": {
"version": "1.0.0-preview2-final",
"imports": "portable-net45+win8+dnxcore50"
}
},
"tools": {
"BundlerMinifier.Core": "2.0.238",
"Microsoft.AspNetCore.Server.IISIntegration.Tools": {
"version": "1.0.0-preview2-final",
"imports": "portable-net45+win8+dnxcore50"
}
},
"buildOptions": {
"emitEntryPoint": true,
"preserveCompilationContext": true
Expand All @@ -49,8 +50,8 @@
"web.config"
]
},
"scripts": {
"prepublish": [ "bower install", "dotnet bundle" ],
"postpublish": [ "dotnet publish-iis --publish-folder %publish:OutputPath% --framework %publish:FullTargetFramework%" ]
}
"scripts": {
"prepublish": [ "bower install", "dotnet bundle" ],
"postpublish": [ "dotnet publish-iis --publish-folder %publish:OutputPath% --framework %publish:FullTargetFramework%" ]
}
}
70 changes: 37 additions & 33 deletions src/SaasKit.Multitenancy.StructureMap/project.json
@@ -1,45 +1,49 @@
{
"version": "1.1.3",
"description": "Multi-tenancy support for ASP.NET Core using StructureMap.",
"authors": [ "Ben Foster" ],
"version": "1.1.4",
"description": "Multi-tenancy support for ASP.NET Core using StructureMap.",
"authors": [ "Ben Foster" ],
"packOptions": {
"authors": [ "Ben Foster" ],
"owners": [ "Ben Foster" ],
"tags": [ "Multi-tenancy", "Multi-tenant", "Saas", "StructureMap" ],
"releaseNotes": "Updated to support ASP.NET Core RC-2",
"tags": [ "Multi-tenancy", "Multitenant", "Multitenancy", "Multitenant", "Saas", "StructureMap" ],
"releaseNotes": "Updated to support ASP.NET Core RTM. Resolves an issue with MemoryCache cache dependencies.",
"projectUrl": "http://saaskit.net",
"licenseUrl": "https://github.com/saaskit/saaskit/blob/master/LICENSE.md",
"requireLicenseAcceptance": false,
"repository": {
"type": "git",
"url": "https://github.com/saaskit/saaskit/"
}
},
"dependencies": {
"NETStandard.Library": "1.6.0",
"Microsoft.AspNetCore.Http.Abstractions": "1.0.0",
"Microsoft.AspNetCore.Http.Extensions": "1.0.0",
"Microsoft.Extensions.Caching.Abstractions": "1.0.0",
"Microsoft.Extensions.Caching.Memory": "1.0.0",
"Microsoft.Extensions.Logging.Abstractions": "1.0.0",
"StructureMap.Dnx": "0.5.1-rc2-final",
"SaasKit.Multitenancy": { "target": "project" }
},
"frameworks": {
"net46": { },
"net452": { },
"net451": { },
"netstandard1.6": {
"dependencies": {
"Microsoft.CSharp": "4.0.1-rc2-*",
"System.Collections": "4.0.11-rc2-*",
"System.Linq": "4.1.0-rc2-*",
"System.Runtime": "4.1.0-rc2-*",
"System.Threading": "4.0.11-rc2-*"
},
"imports": [
"dotnet5.4",
"portable-net45+win8"
]
}
}
"dependencies": {
"NETStandard.Library": "1.6.0",
"Microsoft.AspNetCore.Http.Abstractions": "1.0.0",
"Microsoft.AspNetCore.Http.Extensions": "1.0.0",
"Microsoft.Extensions.Caching.Abstractions": "1.0.0",
"Microsoft.Extensions.Caching.Memory": "1.0.0",
"Microsoft.Extensions.Logging.Abstractions": "1.0.0",
"StructureMap.Dnx": "0.5.1-rc2-final",
"SaasKit.Multitenancy": { "target": "project" }
},
"frameworks": {
"net46": {},
"net452": {},
"net451": {},
"netstandard1.6": {
"dependencies": {
"Microsoft.CSharp": "4.0.1",
"System.Collections": "4.0.11",
"System.Linq": "4.1.0",
"System.Runtime": "4.1.0",
"System.Threading": "4.0.11"
},
"imports": [
"dotnet5.4",
"portable-net45+win8"
]
}
},
"buildOptions": {
"optimize": true
}
}
5 changes: 4 additions & 1 deletion src/SaasKit.Multitenancy/Ensure.cs
Expand Up @@ -4,9 +4,12 @@

namespace SaasKit.Multitenancy
{
/// <summary>
using System.Diagnostics;

/// <summary>
/// Helper class that will throw exceptions when conditions are not satisfied.
/// </summary>
[DebuggerStepThrough]
public static class Ensure
{
/// <summary>
Expand Down
7 changes: 7 additions & 0 deletions src/SaasKit.Multitenancy/ITenant.cs
@@ -0,0 +1,7 @@
namespace SaasKit.Multitenancy
{
public interface ITenant<out TTenant>
{
TTenant Value { get; }
}
}
12 changes: 12 additions & 0 deletions src/SaasKit.Multitenancy/Internal/Tenant.cs
@@ -0,0 +1,12 @@
namespace SaasKit.Multitenancy.Internal
{
internal class Tenant<TTenant> : ITenant<TTenant>
{
public Tenant(TTenant value)
{
Value = value;
}

public TTenant Value { get; }
}
}
Expand Up @@ -4,7 +4,9 @@

namespace SaasKit.Multitenancy.Internal
{
public class TenantResolutionMiddleware<TTenant>
using System;

public class TenantResolutionMiddleware<TTenant>
{
private readonly RequestDelegate next;
private readonly ILogger log;
Expand Down
37 changes: 31 additions & 6 deletions src/SaasKit.Multitenancy/MemoryCacheTenantResolver.cs
Expand Up @@ -7,7 +7,11 @@

namespace SaasKit.Multitenancy
{
public abstract class MemoryCacheTenantResolver<TTenant> : ITenantResolver<TTenant>
using System.Threading;

using Microsoft.Extensions.Primitives;

public abstract class MemoryCacheTenantResolver<TTenant> : ITenantResolver<TTenant>
{
protected readonly IMemoryCache cache;
protected readonly ILogger log;
Expand All @@ -24,11 +28,32 @@ public MemoryCacheTenantResolver(IMemoryCache cache, ILoggerFactory loggerFactor
protected virtual MemoryCacheEntryOptions CreateCacheEntryOptions()
{
return new MemoryCacheEntryOptions()
.SetSlidingExpiration(new TimeSpan(1, 0, 0))
.RegisterPostEvictionCallback((key, value, reason, state)
=> DisposeTenantContext(key, value as TenantContext<TTenant>));
.SetSlidingExpiration(new TimeSpan(1, 0, 0));
}

private MemoryCacheEntryOptions GetCacheEntryOptions()
{
var cacheEntryOptions = CreateCacheEntryOptions();

if (DisposeTenantOnExpiration)
{
var changeToken = new CancellationTokenSource();

cacheEntryOptions
.RegisterPostEvictionCallback(
(key, value, reason, state) =>
{
DisposeTenantContext(key, value as TenantContext<TTenant>);
changeToken.Cancel();
})
.AddExpirationToken(new CancellationChangeToken(changeToken.Token));
}

return cacheEntryOptions;
}

protected virtual bool DisposeTenantOnExpiration => true;

protected virtual void DisposeTenantContext(object cacheKey, TenantContext<TTenant> tenantContext)
{
if (tenantContext != null)
Expand Down Expand Up @@ -67,9 +92,9 @@ async Task<TenantContext<TTenant>> ITenantResolver<TTenant>.ResolveAsync(HttpCon

if (tenantIdentifiers != null)
{
var cacheEntryOptions = CreateCacheEntryOptions();
var cacheEntryOptions = GetCacheEntryOptions();

log.LogDebug("TenantContext:{id} resolved. Caching with keys \"{tenantIdentifiers}\".", tenantContext.Id, tenantIdentifiers);
log.LogDebug("TenantContext:{id} resolved. Caching with keys \"{tenantIdentifiers}\".", tenantContext.Id, tenantIdentifiers);

foreach (var identifier in tenantIdentifiers)
{
Expand Down
Expand Up @@ -5,7 +5,9 @@

namespace Microsoft.Extensions.DependencyInjection
{
public static class MultitenancyServiceCollectionExtensions
using SaasKit.Multitenancy.Internal;

public static class MultitenancyServiceCollectionExtensions
{
public static IServiceCollection AddMultitenancy<TTenant, TResolver>(this IServiceCollection services)
where TResolver : class, ITenantResolver<TTenant>
Expand All @@ -18,15 +20,15 @@ public static class MultitenancyServiceCollectionExtensions
// No longer registered by default as of ASP.NET Core RC2
services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();

// Make Tenant and TenantContext injectable
services.AddScoped(prov =>
prov.GetService<IHttpContextAccessor>()?.HttpContext?.GetTenant<TTenant>());
// Make Tenant and TenantContext injectable
services.AddScoped(prov => prov.GetService<IHttpContextAccessor>()?.HttpContext?.GetTenantContext<TTenant>());
services.AddScoped(prov => prov.GetService<TenantContext<TTenant>>()?.Tenant);

services.AddScoped(prov =>
prov.GetService<IHttpContextAccessor>()?.HttpContext?.GetTenantContext<TTenant>());
// Make ITenant injectable for handling null injection, similar to IOptions
services.AddScoped<ITenant<TTenant>>(prov => new Tenant<TTenant>(prov.GetService<TTenant>()));

// Ensure caching is available for caching resolvers
var resolverType = typeof(TResolver);
// Ensure caching is available for caching resolvers
var resolverType = typeof(TResolver);
if (typeof(MemoryCacheTenantResolver<TTenant>).IsAssignableFrom(resolverType))
{
services.AddMemoryCache();
Expand Down
6 changes: 4 additions & 2 deletions src/SaasKit.Multitenancy/TenantContext.cs
Expand Up @@ -3,7 +3,7 @@

namespace SaasKit.Multitenancy
{
public class TenantContext<TTenant> : IDisposable
public class TenantContext<TTenant> : IDisposable
{
private bool disposed;

Expand Down Expand Up @@ -38,7 +38,9 @@ protected virtual void Dispose(bool disposing)
{
TryDisposeProperty(prop.Value as IDisposable);
}
}

TryDisposeProperty(Tenant as IDisposable);
}

disposed = true;
}
Expand Down

0 comments on commit 4e79e4a

Please sign in to comment.