mirror of https://github.com/Squidex/squidex.git
60 changed files with 323 additions and 195 deletions
@ -0,0 +1,14 @@ |
|||||
|
// ==========================================================================
|
||||
|
// IAppEntity.cs
|
||||
|
// PinkParrot Headless CMS
|
||||
|
// ==========================================================================
|
||||
|
// Copyright (c) PinkParrot Group
|
||||
|
// All rights reserved.
|
||||
|
// ==========================================================================
|
||||
|
namespace PinkParrot.Read.Apps |
||||
|
{ |
||||
|
public interface IAppEntity : IEntity |
||||
|
{ |
||||
|
string Name { get; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,17 @@ |
|||||
|
// ==========================================================================
|
||||
|
// IAppRepository.cs
|
||||
|
// PinkParrot Headless CMS
|
||||
|
// ==========================================================================
|
||||
|
// Copyright (c) PinkParrot Group
|
||||
|
// All rights reserved.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
using System.Threading.Tasks; |
||||
|
|
||||
|
namespace PinkParrot.Read.Apps.Repositories |
||||
|
{ |
||||
|
public interface IAppRepository |
||||
|
{ |
||||
|
Task<IAppEntity> FindAppByNameAsync(string name); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,61 @@ |
|||||
|
// ==========================================================================
|
||||
|
// CachingAppProvider.cs
|
||||
|
// PinkParrot Headless CMS
|
||||
|
// ==========================================================================
|
||||
|
// Copyright (c) PinkParrot Group
|
||||
|
// All rights reserved.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
using System; |
||||
|
using System.Threading.Tasks; |
||||
|
using Microsoft.Extensions.Caching.Memory; |
||||
|
using PinkParrot.Infrastructure; |
||||
|
using PinkParrot.Read.Apps.Repositories; |
||||
|
using PinkParrot.Read.Utils; |
||||
|
// ReSharper disable InvertIf
|
||||
|
|
||||
|
namespace PinkParrot.Read.Apps.Services.Implementations |
||||
|
{ |
||||
|
public class CachingAppProvider : CachingProvider, IAppProvider |
||||
|
{ |
||||
|
private static readonly TimeSpan CacheDuration = TimeSpan.FromMinutes(30); |
||||
|
private readonly IAppRepository appRepository; |
||||
|
|
||||
|
private sealed class CacheItem |
||||
|
{ |
||||
|
public IAppEntity Entity; |
||||
|
} |
||||
|
|
||||
|
public CachingAppProvider(IMemoryCache cache, IAppRepository appRepository) |
||||
|
: base(cache) |
||||
|
{ |
||||
|
Guard.NotNull(cache, nameof(cache)); |
||||
|
|
||||
|
this.appRepository = appRepository; |
||||
|
} |
||||
|
|
||||
|
public async Task<Guid?> FindAppIdByNameAsync(string name) |
||||
|
{ |
||||
|
Guard.NotNullOrEmpty(name, nameof(name)); |
||||
|
|
||||
|
var cacheKey = BulidCacheKey(name); |
||||
|
var cacheItem = Cache.Get<CacheItem>(cacheKey); |
||||
|
|
||||
|
if (cacheItem == null) |
||||
|
{ |
||||
|
var app = await appRepository.FindAppByNameAsync(name); |
||||
|
|
||||
|
cacheItem = new CacheItem { Entity = app }; |
||||
|
|
||||
|
Cache.Set(cacheKey, cacheItem, new MemoryCacheEntryOptions { SlidingExpiration = CacheDuration }); |
||||
|
} |
||||
|
|
||||
|
return cacheItem.Entity?.Id; |
||||
|
} |
||||
|
|
||||
|
private static string BulidCacheKey(string name) |
||||
|
{ |
||||
|
return $"App_{name}"; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -1,21 +0,0 @@ |
|||||
// ==========================================================================
|
|
||||
// TenantProvider.cs
|
|
||||
// PinkParrot Headless CMS
|
|
||||
// ==========================================================================
|
|
||||
// Copyright (c) PinkParrot Group
|
|
||||
// All rights reserved.
|
|
||||
// ==========================================================================
|
|
||||
|
|
||||
using System; |
|
||||
using System.Threading.Tasks; |
|
||||
|
|
||||
namespace PinkParrot.Read.Infrastructure.Services.Implementations |
|
||||
{ |
|
||||
public sealed class TenantProvider : ITenantProvider |
|
||||
{ |
|
||||
public Task<Guid?> ProvideTenantIdByDomainAsync(string domain) |
|
||||
{ |
|
||||
return Task.FromResult<Guid?>(Guid.Empty); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -0,0 +1,30 @@ |
|||||
|
// ==========================================================================
|
||||
|
// CachingProvider.cs
|
||||
|
// PinkParrot Headless CMS
|
||||
|
// ==========================================================================
|
||||
|
// Copyright (c) PinkParrot Group
|
||||
|
// All rights reserved.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
using Microsoft.Extensions.Caching.Memory; |
||||
|
using PinkParrot.Infrastructure; |
||||
|
|
||||
|
namespace PinkParrot.Read.Utils |
||||
|
{ |
||||
|
public abstract class CachingProvider |
||||
|
{ |
||||
|
private readonly IMemoryCache cache; |
||||
|
|
||||
|
protected IMemoryCache Cache |
||||
|
{ |
||||
|
get { return cache; } |
||||
|
} |
||||
|
|
||||
|
protected CachingProvider(IMemoryCache cache) |
||||
|
{ |
||||
|
Guard.NotNull(cache, nameof(cache)); |
||||
|
|
||||
|
this.cache = cache; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,14 @@ |
|||||
|
using System; |
||||
|
|
||||
|
namespace PinkParrot.Pipeline |
||||
|
{ |
||||
|
public sealed class AppFeature : IAppFeature |
||||
|
{ |
||||
|
public Guid AppId { get; } |
||||
|
|
||||
|
public AppFeature(Guid appId) |
||||
|
{ |
||||
|
AppId = appId; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,39 @@ |
|||||
|
// ==========================================================================
|
||||
|
// AppMiddleware.cs
|
||||
|
// PinkParrot Headless CMS
|
||||
|
// ==========================================================================
|
||||
|
// Copyright (c) PinkParrot Group
|
||||
|
// All rights reserved.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
using System.Threading.Tasks; |
||||
|
using Microsoft.AspNetCore.Http; |
||||
|
using PinkParrot.Read.Apps.Services; |
||||
|
|
||||
|
namespace PinkParrot.Pipeline |
||||
|
{ |
||||
|
public sealed class AppMiddleware |
||||
|
{ |
||||
|
private readonly IAppProvider appProvider; |
||||
|
private readonly RequestDelegate next; |
||||
|
|
||||
|
public AppMiddleware(RequestDelegate next, IAppProvider appProvider) |
||||
|
{ |
||||
|
this.next = next; |
||||
|
|
||||
|
this.appProvider = appProvider; |
||||
|
} |
||||
|
|
||||
|
public async Task Invoke(HttpContext context) |
||||
|
{ |
||||
|
var appId = await appProvider.FindAppIdByNameAsync(context.Request.Host.ToString().Split('.')[0]); |
||||
|
|
||||
|
if (appId.HasValue) |
||||
|
{ |
||||
|
context.Features.Set<IAppFeature>(new AppFeature(appId.Value)); |
||||
|
} |
||||
|
|
||||
|
await next(context); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -1,45 +0,0 @@ |
|||||
// ==========================================================================
|
|
||||
// TenantMiddleware.cs
|
|
||||
// PinkParrot Headless CMS
|
|
||||
// ==========================================================================
|
|
||||
// Copyright (c) PinkParrot Group
|
|
||||
// All rights reserved.
|
|
||||
// ==========================================================================
|
|
||||
|
|
||||
using System; |
|
||||
using System.Threading.Tasks; |
|
||||
using Microsoft.AspNetCore.Http; |
|
||||
using PinkParrot.Read.Infrastructure.Services; |
|
||||
|
|
||||
namespace PinkParrot.Pipeline |
|
||||
{ |
|
||||
public sealed class TenantMiddleware |
|
||||
{ |
|
||||
private readonly ITenantProvider tenantProvider; |
|
||||
private readonly RequestDelegate next; |
|
||||
|
|
||||
public TenantMiddleware(RequestDelegate next, ITenantProvider tenantProvider) |
|
||||
{ |
|
||||
this.next = next; |
|
||||
|
|
||||
this.tenantProvider = tenantProvider; |
|
||||
} |
|
||||
|
|
||||
private class TenantFeature : ITenantFeature |
|
||||
{ |
|
||||
public Guid TenantId { get; set; } |
|
||||
} |
|
||||
|
|
||||
public async Task Invoke(HttpContext context) |
|
||||
{ |
|
||||
var tenantId = await tenantProvider.ProvideTenantIdByDomainAsync(context.Request.Host.ToString()); |
|
||||
|
|
||||
if (tenantId.HasValue) |
|
||||
{ |
|
||||
context.Features.Set<ITenantFeature>(new TenantFeature { TenantId = tenantId.Value }); |
|
||||
} |
|
||||
|
|
||||
await next(context); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
Loading…
Reference in new issue