Browse Source

Tenant => App

pull/1/head
Sebastian 9 years ago
parent
commit
22ddd858fc
  1. 6
      src/PinkParrot.Events/AppEvent.cs
  2. 2
      src/PinkParrot.Events/Apps/AppCreated.cs
  3. 2
      src/PinkParrot.Events/Schemas/FieldAdded.cs
  4. 2
      src/PinkParrot.Events/Schemas/FieldDeleted.cs
  5. 2
      src/PinkParrot.Events/Schemas/FieldDisabled.cs
  6. 2
      src/PinkParrot.Events/Schemas/FieldEnabled.cs
  7. 2
      src/PinkParrot.Events/Schemas/FieldHidden.cs
  8. 2
      src/PinkParrot.Events/Schemas/FieldShown.cs
  9. 2
      src/PinkParrot.Events/Schemas/FieldUpdated.cs
  10. 2
      src/PinkParrot.Events/Schemas/SchemaCreated.cs
  11. 2
      src/PinkParrot.Events/Schemas/SchemaDeleted.cs
  12. 2
      src/PinkParrot.Events/Schemas/SchemaUpdated.cs
  13. 2
      src/PinkParrot.Infrastructure/CQRS/CommonHeaders.cs
  14. 8
      src/PinkParrot.Infrastructure/CQRS/EnvelopeExtensions.cs
  15. 6
      src/PinkParrot.Infrastructure/CQRS/EnvelopeFactory.cs
  16. 6
      src/PinkParrot.Infrastructure/CQRS/IAppAggregate.cs
  17. 14
      src/PinkParrot.Read/Apps/IAppEntity.cs
  18. 17
      src/PinkParrot.Read/Apps/Repositories/IAppRepository.cs
  19. 8
      src/PinkParrot.Read/Apps/Services/IAppProvider.cs
  20. 61
      src/PinkParrot.Read/Apps/Services/Implementations/CachingAppProvider.cs
  21. 8
      src/PinkParrot.Read/IAppEntity.cs
  22. 2
      src/PinkParrot.Read/IEntity.cs
  23. 21
      src/PinkParrot.Read/Infrastructure/Services/Implementations/TenantProvider.cs
  24. 2
      src/PinkParrot.Read/Schemas/Repositories/ISchemaEntity.cs
  25. 6
      src/PinkParrot.Read/Schemas/Repositories/ISchemaRepository.cs
  26. 2
      src/PinkParrot.Read/Schemas/Services/ISchemaProvider.cs
  27. 32
      src/PinkParrot.Read/Schemas/Services/Implementations/CachingSchemaProvider.cs
  28. 30
      src/PinkParrot.Read/Utils/CachingProvider.cs
  29. 11
      src/PinkParrot.Store.MongoDb/Properties/AssemblyInfo.cs
  30. 2
      src/PinkParrot.Store.MongoDb/Schemas/MongoSchemaEntity.cs
  31. 12
      src/PinkParrot.Store.MongoDb/Schemas/MongoSchemaRepository.cs
  32. 8
      src/PinkParrot.Store.MongoDb/Utils/EntityMapper.cs
  33. 6
      src/PinkParrot.Write/AppCommand.cs
  34. 6
      src/PinkParrot.Write/IAppCommand.cs
  35. 2
      src/PinkParrot.Write/Schemas/Commands/AddField.cs
  36. 2
      src/PinkParrot.Write/Schemas/Commands/CreateSchema.cs
  37. 2
      src/PinkParrot.Write/Schemas/Commands/DeleteField.cs
  38. 2
      src/PinkParrot.Write/Schemas/Commands/DeleteSchema.cs
  39. 2
      src/PinkParrot.Write/Schemas/Commands/DisableField.cs
  40. 2
      src/PinkParrot.Write/Schemas/Commands/EnableField.cs
  41. 2
      src/PinkParrot.Write/Schemas/Commands/HideField.cs
  42. 2
      src/PinkParrot.Write/Schemas/Commands/ShowField.cs
  43. 2
      src/PinkParrot.Write/Schemas/Commands/UpdateField.cs
  44. 2
      src/PinkParrot.Write/Schemas/Commands/UpdateSchema.cs
  45. 4
      src/PinkParrot.Write/Schemas/SchemaCommandHandler.cs
  46. 14
      src/PinkParrot.Write/Schemas/SchemaDomainObject.cs
  47. 4
      src/PinkParrot/Configurations/InfrastructureUsage.cs
  48. 8
      src/PinkParrot/Configurations/ReadModule.cs
  49. 2
      src/PinkParrot/Configurations/WriteModule.cs
  50. 4
      src/PinkParrot/Modules/Api/Schemas/SchemasController.cs
  51. 10
      src/PinkParrot/Modules/ControllerBase.cs
  52. 14
      src/PinkParrot/Pipeline/AppFeature.cs
  53. 39
      src/PinkParrot/Pipeline/AppMiddleware.cs
  54. 6
      src/PinkParrot/Pipeline/CommandHandlers/EnrichWithAggregateIdHandler.cs
  55. 18
      src/PinkParrot/Pipeline/CommandHandlers/EnrichWithAppIdHandler.cs
  56. 6
      src/PinkParrot/Pipeline/IAppFeature.cs
  57. 45
      src/PinkParrot/Pipeline/TenantMiddleware.cs
  58. 2
      src/PinkParrot/Startup.cs
  59. 13
      tests/PinkParrot.Write.Tests/Apps/AppDomainObjectTest.cs
  60. 11
      tests/PinkParrot.Write.Tests/Properties/AssemblyInfo.cs

6
src/PinkParrot.Events/TenantEvent.cs → src/PinkParrot.Events/AppEvent.cs

@ -1,5 +1,5 @@
// ========================================================================== // ==========================================================================
// TenantEvent.cs // AppEvent.cs
// PinkParrot Headless CMS // PinkParrot Headless CMS
// ========================================================================== // ==========================================================================
// Copyright (c) PinkParrot Group // Copyright (c) PinkParrot Group
@ -11,8 +11,8 @@ using PinkParrot.Infrastructure.CQRS.Events;
namespace PinkParrot.Events namespace PinkParrot.Events
{ {
public class TenantEvent : IEvent public class AppEvent : IEvent
{ {
public Guid TenantId { get; set; } public Guid AppId { get; set; }
} }
} }

2
src/PinkParrot.Events/Apps/AppCreated.cs

@ -6,10 +6,12 @@
// All rights reserved. // All rights reserved.
// ========================================================================== // ==========================================================================
using PinkParrot.Infrastructure;
using PinkParrot.Infrastructure.CQRS.Events; using PinkParrot.Infrastructure.CQRS.Events;
namespace PinkParrot.Events.Apps namespace PinkParrot.Events.Apps
{ {
[TypeName("AppCreated")]
public class AppCreated : IEvent public class AppCreated : IEvent
{ {
public string Name { get; set; } public string Name { get; set; }

2
src/PinkParrot.Events/Schemas/FieldAdded.cs

@ -12,7 +12,7 @@ using PinkParrot.Infrastructure;
namespace PinkParrot.Events.Schemas namespace PinkParrot.Events.Schemas
{ {
[TypeName("FieldAddedEvent")] [TypeName("FieldAddedEvent")]
public class FieldAdded : TenantEvent public class FieldAdded : AppEvent
{ {
public long FieldId { get; set; } public long FieldId { get; set; }

2
src/PinkParrot.Events/Schemas/FieldDeleted.cs

@ -11,7 +11,7 @@ using PinkParrot.Infrastructure;
namespace PinkParrot.Events.Schemas namespace PinkParrot.Events.Schemas
{ {
[TypeName("FieldDeletedEvent")] [TypeName("FieldDeletedEvent")]
public class FieldDeleted : TenantEvent public class FieldDeleted : AppEvent
{ {
public long FieldId { get; set; } public long FieldId { get; set; }
} }

2
src/PinkParrot.Events/Schemas/FieldDisabled.cs

@ -11,7 +11,7 @@ using PinkParrot.Infrastructure;
namespace PinkParrot.Events.Schemas namespace PinkParrot.Events.Schemas
{ {
[TypeName("FieldDisabledEvent")] [TypeName("FieldDisabledEvent")]
public class FieldDisabled : TenantEvent public class FieldDisabled : AppEvent
{ {
public long FieldId { get; set; } public long FieldId { get; set; }
} }

2
src/PinkParrot.Events/Schemas/FieldEnabled.cs

@ -11,7 +11,7 @@ using PinkParrot.Infrastructure;
namespace PinkParrot.Events.Schemas namespace PinkParrot.Events.Schemas
{ {
[TypeName("FieldEnabledEvent")] [TypeName("FieldEnabledEvent")]
public class FieldEnabled : TenantEvent public class FieldEnabled : AppEvent
{ {
public long FieldId { get; set; } public long FieldId { get; set; }
} }

2
src/PinkParrot.Events/Schemas/FieldHidden.cs

@ -11,7 +11,7 @@ using PinkParrot.Infrastructure;
namespace PinkParrot.Events.Schemas namespace PinkParrot.Events.Schemas
{ {
[TypeName("FieldHiddenEvent")] [TypeName("FieldHiddenEvent")]
public class FieldHidden : TenantEvent public class FieldHidden : AppEvent
{ {
public long FieldId { get; set; } public long FieldId { get; set; }
} }

2
src/PinkParrot.Events/Schemas/FieldShown.cs

@ -11,7 +11,7 @@ using PinkParrot.Infrastructure;
namespace PinkParrot.Events.Schemas namespace PinkParrot.Events.Schemas
{ {
[TypeName("FieldShownEvent")] [TypeName("FieldShownEvent")]
public class FieldShown : TenantEvent public class FieldShown : AppEvent
{ {
public long FieldId { get; set; } public long FieldId { get; set; }
} }

2
src/PinkParrot.Events/Schemas/FieldUpdated.cs

@ -12,7 +12,7 @@ using PinkParrot.Infrastructure;
namespace PinkParrot.Events.Schemas namespace PinkParrot.Events.Schemas
{ {
[TypeName("FieldUpdatedEvent")] [TypeName("FieldUpdatedEvent")]
public class FieldUpdated : TenantEvent public class FieldUpdated : AppEvent
{ {
public long FieldId { get; set; } public long FieldId { get; set; }

2
src/PinkParrot.Events/Schemas/SchemaCreated.cs

@ -12,7 +12,7 @@ using PinkParrot.Infrastructure;
namespace PinkParrot.Events.Schemas namespace PinkParrot.Events.Schemas
{ {
[TypeName("SchemaCreatedEvent")] [TypeName("SchemaCreatedEvent")]
public class SchemaCreated : TenantEvent public class SchemaCreated : AppEvent
{ {
public string Name { get; set; } public string Name { get; set; }

2
src/PinkParrot.Events/Schemas/SchemaDeleted.cs

@ -11,7 +11,7 @@ using PinkParrot.Infrastructure;
namespace PinkParrot.Events.Schemas namespace PinkParrot.Events.Schemas
{ {
[TypeName("SchemaDeleted")] [TypeName("SchemaDeleted")]
public class SchemaDeleted : TenantEvent public class SchemaDeleted : AppEvent
{ {
} }
} }

2
src/PinkParrot.Events/Schemas/SchemaUpdated.cs

@ -12,7 +12,7 @@ using PinkParrot.Infrastructure;
namespace PinkParrot.Events.Schemas namespace PinkParrot.Events.Schemas
{ {
[TypeName("SchemaUpdated")] [TypeName("SchemaUpdated")]
public class SchemaUpdated : TenantEvent public class SchemaUpdated : AppEvent
{ {
public SchemaProperties Properties { get; set; } public SchemaProperties Properties { get; set; }
} }

2
src/PinkParrot.Infrastructure/CQRS/CommonHeaders.cs

@ -12,7 +12,7 @@ namespace PinkParrot.Infrastructure.CQRS
public const string AggregateId = "AggregateId"; public const string AggregateId = "AggregateId";
public const string CommitId = "CommitId"; public const string CommitId = "CommitId";
public const string Timestamp = "Timestamp"; public const string Timestamp = "Timestamp";
public const string TenantId = "TenantId"; public const string AppId = "AppId";
public const string EventId = "EventId"; public const string EventId = "EventId";
public const string EventNumber = "EventNumber"; public const string EventNumber = "EventNumber";
} }

8
src/PinkParrot.Infrastructure/CQRS/EnvelopeExtensions.cs

@ -62,14 +62,14 @@ namespace PinkParrot.Infrastructure.CQRS
return envelope; return envelope;
} }
public static Guid TenantId(this EnvelopeHeaders headers) public static Guid AppId(this EnvelopeHeaders headers)
{ {
return headers[CommonHeaders.TenantId].ToGuid(CultureInfo.InvariantCulture); return headers[CommonHeaders.AppId].ToGuid(CultureInfo.InvariantCulture);
} }
public static Envelope<T> SetTenantId<T>(this Envelope<T> envelope, Guid value) where T : class public static Envelope<T> SetAppId<T>(this Envelope<T> envelope, Guid value) where T : class
{ {
envelope.Headers.Set(CommonHeaders.TenantId, value); envelope.Headers.Set(CommonHeaders.AppId, value);
return envelope; return envelope;
} }

6
src/PinkParrot.Infrastructure/CQRS/EnvelopeFactory.cs

@ -24,11 +24,11 @@ namespace PinkParrot.Infrastructure.CQRS
.SetEventId(eventId) .SetEventId(eventId)
.SetTimestamp(SystemClock.Instance.GetCurrentInstant()); .SetTimestamp(SystemClock.Instance.GetCurrentInstant());
var tenantAggregate = aggregate as ITenantAggregate; var appAggregate = aggregate as IAppAggregate;
if (tenantAggregate != null) if (appAggregate != null)
{ {
envelope = envelope.SetTenantId(tenantAggregate.TenantId); envelope = envelope.SetAppId(appAggregate.AppId);
} }
return envelope; return envelope;

6
src/PinkParrot.Infrastructure/CQRS/ITenantAggregate.cs → src/PinkParrot.Infrastructure/CQRS/IAppAggregate.cs

@ -1,5 +1,5 @@
// ========================================================================== // ==========================================================================
// ITenantAggregate.cs // IAppAggregate.cs
// PinkParrot Headless CMS // PinkParrot Headless CMS
// ========================================================================== // ==========================================================================
// Copyright (c) PinkParrot Group // Copyright (c) PinkParrot Group
@ -10,8 +10,8 @@ using System;
namespace PinkParrot.Infrastructure.CQRS namespace PinkParrot.Infrastructure.CQRS
{ {
public interface ITenantAggregate : IAggregate public interface IAppAggregate : IAggregate
{ {
Guid TenantId { get; } Guid AppId { get; }
} }
} }

14
src/PinkParrot.Read/Apps/IAppEntity.cs

@ -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; }
}
}

17
src/PinkParrot.Read/Apps/Repositories/IAppRepository.cs

@ -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);
}
}

8
src/PinkParrot.Read/Infrastructure/Services/ITenantProvider.cs → src/PinkParrot.Read/Apps/Services/IAppProvider.cs

@ -1,5 +1,5 @@
// ========================================================================== // ==========================================================================
// ITenantProvider.cs // IAppProvider.cs
// PinkParrot Headless CMS // PinkParrot Headless CMS
// ========================================================================== // ==========================================================================
// Copyright (c) PinkParrot Group // Copyright (c) PinkParrot Group
@ -9,10 +9,10 @@
using System; using System;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace PinkParrot.Read.Infrastructure.Services namespace PinkParrot.Read.Apps.Services
{ {
public interface ITenantProvider public interface IAppProvider
{ {
Task<Guid?> ProvideTenantIdByDomainAsync(string domain); Task<Guid?> FindAppIdByNameAsync(string name);
} }
} }

61
src/PinkParrot.Read/Apps/Services/Implementations/CachingAppProvider.cs

@ -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}";
}
}
}

8
src/PinkParrot.Read/Schemas/Repositories/ITenantEntity.cs → src/PinkParrot.Read/IAppEntity.cs

@ -1,5 +1,5 @@
// ========================================================================== // ==========================================================================
// ITenantEntity.cs // IAppEntity.cs
// PinkParrot Headless CMS // PinkParrot Headless CMS
// ========================================================================== // ==========================================================================
// Copyright (c) PinkParrot Group // Copyright (c) PinkParrot Group
@ -8,10 +8,10 @@
using System; using System;
namespace PinkParrot.Read.Schemas.Repositories namespace PinkParrot.Read
{ {
public interface ITenantEntity : IEntity public interface IAppEntity : IEntity
{ {
Guid TenantId { get; set; } Guid AppId { get; set; }
} }
} }

2
src/PinkParrot.Read/Schemas/Repositories/IEntity.cs → src/PinkParrot.Read/IEntity.cs

@ -8,7 +8,7 @@
using System; using System;
namespace PinkParrot.Read.Schemas.Repositories namespace PinkParrot.Read
{ {
public interface IEntity public interface IEntity
{ {

21
src/PinkParrot.Read/Infrastructure/Services/Implementations/TenantProvider.cs

@ -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);
}
}
}

2
src/PinkParrot.Read/Schemas/Repositories/ISchemaEntity.cs

@ -7,7 +7,7 @@
// ========================================================================== // ==========================================================================
namespace PinkParrot.Read.Schemas.Repositories namespace PinkParrot.Read.Schemas.Repositories
{ {
public interface ISchemaEntity : ITenantEntity public interface ISchemaEntity : IAppEntity
{ {
string Name { get; } string Name { get; }
} }

6
src/PinkParrot.Read/Schemas/Repositories/ISchemaRepository.cs

@ -14,11 +14,11 @@ namespace PinkParrot.Read.Schemas.Repositories
{ {
public interface ISchemaRepository public interface ISchemaRepository
{ {
Task<List<ISchemaEntity>> QueryAllAsync(Guid tenantId); Task<List<ISchemaEntity>> QueryAllAsync(Guid appId);
Task<Guid?> FindSchemaIdAsync(Guid tenantId, string name); Task<Guid?> FindSchemaIdAsync(Guid appId, string name);
Task<ISchemaEntityWithSchema> FindSchemaAsync(Guid tenantId, string name); Task<ISchemaEntityWithSchema> FindSchemaAsync(Guid appId, string name);
Task<ISchemaEntityWithSchema> FindSchemaAsync(Guid schemaId); Task<ISchemaEntityWithSchema> FindSchemaAsync(Guid schemaId);
} }

2
src/PinkParrot.Read/Schemas/Services/ISchemaProvider.cs

@ -13,6 +13,6 @@ namespace PinkParrot.Read.Schemas.Services
{ {
public interface ISchemaProvider public interface ISchemaProvider
{ {
Task<Guid?> FindSchemaIdByNameAsync(Guid tenantId, string name); Task<Guid?> FindSchemaIdByNameAsync(Guid appId, string name);
} }
} }

32
src/PinkParrot.Read/Schemas/Services/Implementations/CachingSchemaProvider.cs

@ -14,74 +14,72 @@ using PinkParrot.Infrastructure;
using PinkParrot.Infrastructure.CQRS; using PinkParrot.Infrastructure.CQRS;
using PinkParrot.Infrastructure.CQRS.Events; using PinkParrot.Infrastructure.CQRS.Events;
using PinkParrot.Read.Schemas.Repositories; using PinkParrot.Read.Schemas.Repositories;
using PinkParrot.Read.Utils;
// ReSharper disable InvertIf // ReSharper disable InvertIf
namespace PinkParrot.Read.Schemas.Services.Implementations namespace PinkParrot.Read.Schemas.Services.Implementations
{ {
public class CachingSchemaProvider : ISchemaProvider, ILiveEventConsumer public class CachingSchemaProvider : CachingProvider, ISchemaProvider, ILiveEventConsumer
{ {
private static readonly TimeSpan CacheDuration = TimeSpan.FromMinutes(10); private static readonly TimeSpan CacheDuration = TimeSpan.FromMinutes(10);
private readonly IMemoryCache cache;
private readonly ISchemaRepository repository; private readonly ISchemaRepository repository;
public sealed class CacheItem private sealed class CacheItem
{ {
public ISchemaEntityWithSchema Entity; public ISchemaEntityWithSchema Entity;
} }
public CachingSchemaProvider(IMemoryCache cache, ISchemaRepository repository) public CachingSchemaProvider(IMemoryCache cache, ISchemaRepository repository)
: base(cache)
{ {
Guard.NotNull(cache, nameof(cache));
Guard.NotNull(repository, nameof(repository)); Guard.NotNull(repository, nameof(repository));
this.cache = cache;
this.repository = repository; this.repository = repository;
} }
public async Task<Guid?> FindSchemaIdByNameAsync(Guid tenantId, string name) public async Task<Guid?> FindSchemaIdByNameAsync(Guid appId, string name)
{ {
Guard.NotNullOrEmpty(name, nameof(name)); Guard.NotNullOrEmpty(name, nameof(name));
var cacheKey = BuildModelsCacheKey(tenantId, name); var cacheKey = BuildModelsCacheKey(appId, name);
var cacheItem = cache.Get<CacheItem>(cacheKey); var cacheItem = Cache.Get<CacheItem>(cacheKey);
if (cacheItem == null) if (cacheItem == null)
{ {
var schema = await repository.FindSchemaAsync(tenantId, name); var schema = await repository.FindSchemaAsync(appId, name);
cacheItem = new CacheItem { Entity = schema }; cacheItem = new CacheItem { Entity = schema };
cache.Set(cacheKey, cacheItem, CacheDuration); Cache.Set(cacheKey, cacheItem, CacheDuration);
if (cacheItem.Entity != null) if (cacheItem.Entity != null)
{ {
cache.Set(BuildNamesCacheKey(cacheItem.Entity.Id), cacheItem.Entity.Name, CacheDuration); Cache.Set(BuildNamesCacheKey(cacheItem.Entity.Id), cacheItem.Entity.Name, CacheDuration);
} }
} }
return cacheItem?.Entity?.Id; return cacheItem.Entity?.Id;
} }
public Task On(Envelope<IEvent> @event) public Task On(Envelope<IEvent> @event)
{ {
if (@event.Payload is SchemaUpdated || @event.Payload is SchemaDeleted) if (@event.Payload is SchemaUpdated || @event.Payload is SchemaDeleted)
{ {
var oldName = cache.Get<string>(BuildNamesCacheKey(@event.Headers.AggregateId())); var oldName = Cache.Get<string>(BuildNamesCacheKey(@event.Headers.AggregateId()));
if (oldName != null) if (oldName != null)
{ {
cache.Remove(BuildModelsCacheKey(@event.Headers.TenantId(), oldName)); Cache.Remove(BuildModelsCacheKey(@event.Headers.AppId(), oldName));
} }
} }
return Task.FromResult(true); return Task.FromResult(true);
} }
private static string BuildModelsCacheKey(Guid tenantId, string name) private static string BuildModelsCacheKey(Guid appId, string name)
{ {
return $"Schemas_Models_{tenantId}_{name}"; return $"Schemas_Models_{appId}_{name}";
} }
private static string BuildNamesCacheKey(Guid schemaId) private static string BuildNamesCacheKey(Guid schemaId)

30
src/PinkParrot.Read/Utils/CachingProvider.cs

@ -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;
}
}
}

11
src/PinkParrot.Store.MongoDb/Properties/AssemblyInfo.cs

@ -1,5 +1,12 @@
using System.Reflection; // ==========================================================================
using System.Runtime.CompilerServices; // AssemblyInfo.cs
// PinkParrot Headless CMS
// ==========================================================================
// Copyright (c) PinkParrot Group
// All rights reserved.
// ==========================================================================
using System.Reflection;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following // General Information about an assembly is controlled through the following

2
src/PinkParrot.Store.MongoDb/Schemas/MongoSchemaEntity.cs

@ -40,7 +40,7 @@ namespace PinkParrot.Store.MongoDb.Schemas
[BsonRequired] [BsonRequired]
[BsonElement] [BsonElement]
public Guid TenantId { get; set; } public Guid AppId { get; set; }
[BsonRequired] [BsonRequired]
[BsonElement] [BsonElement]

12
src/PinkParrot.Store.MongoDb/Schemas/MongoSchemaRepository.cs

@ -44,17 +44,17 @@ namespace PinkParrot.Store.MongoDb.Schemas
return collection.Indexes.CreateOneAsync(IndexKeys.Ascending(x => x.Name)); return collection.Indexes.CreateOneAsync(IndexKeys.Ascending(x => x.Name));
} }
public async Task<List<ISchemaEntity>> QueryAllAsync(Guid tenantId) public async Task<List<ISchemaEntity>> QueryAllAsync(Guid appId)
{ {
var entities = await Collection.Find(s => s.TenantId == tenantId && !s.IsDeleted).ToListAsync(); var entities = await Collection.Find(s => s.AppId == appId && !s.IsDeleted).ToListAsync();
return entities.OfType<ISchemaEntity>().ToList(); return entities.OfType<ISchemaEntity>().ToList();
} }
public async Task<ISchemaEntityWithSchema> FindSchemaAsync(Guid tenantId, string name) public async Task<ISchemaEntityWithSchema> FindSchemaAsync(Guid appId, string name)
{ {
var entity = var entity =
await Collection.Find(s => s.Name == name && s.TenantId == tenantId && !s.IsDeleted) await Collection.Find(s => s.Name == name && s.AppId == appId && !s.IsDeleted)
.FirstOrDefaultAsync(); .FirstOrDefaultAsync();
entity?.DeserializeSchema(serializerSettings, fieldRegistry); entity?.DeserializeSchema(serializerSettings, fieldRegistry);
@ -73,10 +73,10 @@ namespace PinkParrot.Store.MongoDb.Schemas
return entity; return entity;
} }
public async Task<Guid?> FindSchemaIdAsync(Guid tenantId, string name) public async Task<Guid?> FindSchemaIdAsync(Guid appId, string name)
{ {
var entity = var entity =
await Collection.Find(s => s.Name == name & s.TenantId == tenantId && !s.IsDeleted) await Collection.Find(s => s.Name == name & s.AppId == appId && !s.IsDeleted)
.Project<MongoSchemaEntity>(Projection.Include(x => x.Id)).FirstOrDefaultAsync(); .Project<MongoSchemaEntity>(Projection.Include(x => x.Id)).FirstOrDefaultAsync();
return entity?.Id; return entity?.Id;

8
src/PinkParrot.Store.MongoDb/Utils/EntityMapper.cs

@ -12,7 +12,7 @@ using MongoDB.Bson;
using MongoDB.Driver; using MongoDB.Driver;
using Newtonsoft.Json; using Newtonsoft.Json;
using PinkParrot.Infrastructure.CQRS; using PinkParrot.Infrastructure.CQRS;
using PinkParrot.Read.Schemas.Repositories; using PinkParrot.Read;
namespace PinkParrot.Store.MongoDb.Utils namespace PinkParrot.Store.MongoDb.Utils
{ {
@ -24,11 +24,11 @@ namespace PinkParrot.Store.MongoDb.Utils
var entity = new T { Id = headers.AggregateId(), Created = timestamp }; var entity = new T { Id = headers.AggregateId(), Created = timestamp };
var tenantEntity = entity as ITenantEntity; var appEntity = entity as IAppEntity;
if (tenantEntity != null) if (appEntity != null)
{ {
tenantEntity.TenantId = headers.TenantId(); appEntity.AppId = headers.AppId();
} }
return Update(entity, headers); return Update(entity, headers);

6
src/PinkParrot.Write/TenantCommand.cs → src/PinkParrot.Write/AppCommand.cs

@ -1,5 +1,5 @@
// ========================================================================== // ==========================================================================
// TenantCommand.cs // AppCommand.cs
// PinkParrot Headless CMS // PinkParrot Headless CMS
// ========================================================================== // ==========================================================================
// Copyright (c) PinkParrot Group // Copyright (c) PinkParrot Group
@ -11,8 +11,8 @@ using PinkParrot.Infrastructure.CQRS.Commands;
namespace PinkParrot.Write namespace PinkParrot.Write
{ {
public abstract class TenantCommand : AggregateCommand, ITenantCommand public abstract class AppCommand : AggregateCommand, IAppCommand
{ {
public Guid TenantId { get; set; } public Guid AppId { get; set; }
} }
} }

6
src/PinkParrot.Write/ITenantCommand.cs → src/PinkParrot.Write/IAppCommand.cs

@ -1,5 +1,5 @@
// ========================================================================== // ==========================================================================
// ITenantCommand.cs // IAppCommand.cs
// PinkParrot Headless CMS // PinkParrot Headless CMS
// ========================================================================== // ==========================================================================
// Copyright (c) PinkParrot Group // Copyright (c) PinkParrot Group
@ -11,8 +11,8 @@ using PinkParrot.Infrastructure.CQRS.Commands;
namespace PinkParrot.Write namespace PinkParrot.Write
{ {
public interface ITenantCommand : ICommand public interface IAppCommand : ICommand
{ {
Guid TenantId { get; set; } Guid AppId { get; set; }
} }
} }

2
src/PinkParrot.Write/Schemas/Commands/AddField.cs

@ -10,7 +10,7 @@ using Newtonsoft.Json.Linq;
namespace PinkParrot.Write.Schemas.Commands namespace PinkParrot.Write.Schemas.Commands
{ {
public class AddField : TenantCommand public class AddField : AppCommand
{ {
public string Name { get; set; } public string Name { get; set; }

2
src/PinkParrot.Write/Schemas/Commands/CreateSchema.cs

@ -10,7 +10,7 @@ using PinkParrot.Core.Schemas;
namespace PinkParrot.Write.Schemas.Commands namespace PinkParrot.Write.Schemas.Commands
{ {
public class CreateSchema : TenantCommand public class CreateSchema : AppCommand
{ {
public string Name { get; set; } public string Name { get; set; }

2
src/PinkParrot.Write/Schemas/Commands/DeleteField.cs

@ -7,7 +7,7 @@
// ========================================================================== // ==========================================================================
namespace PinkParrot.Write.Schemas.Commands namespace PinkParrot.Write.Schemas.Commands
{ {
public class DeleteField : TenantCommand public class DeleteField : AppCommand
{ {
public long FieldId { get; set; } public long FieldId { get; set; }
} }

2
src/PinkParrot.Write/Schemas/Commands/DeleteSchema.cs

@ -7,7 +7,7 @@
// ========================================================================== // ==========================================================================
namespace PinkParrot.Write.Schemas.Commands namespace PinkParrot.Write.Schemas.Commands
{ {
public class DeleteSchema : TenantCommand public class DeleteSchema : AppCommand
{ {
} }
} }

2
src/PinkParrot.Write/Schemas/Commands/DisableField.cs

@ -7,7 +7,7 @@
// ========================================================================== // ==========================================================================
namespace PinkParrot.Write.Schemas.Commands namespace PinkParrot.Write.Schemas.Commands
{ {
public class DisableField : TenantCommand public class DisableField : AppCommand
{ {
public long FieldId { get; set; } public long FieldId { get; set; }
} }

2
src/PinkParrot.Write/Schemas/Commands/EnableField.cs

@ -7,7 +7,7 @@
// ========================================================================== // ==========================================================================
namespace PinkParrot.Write.Schemas.Commands namespace PinkParrot.Write.Schemas.Commands
{ {
public class EnableField : TenantCommand public class EnableField : AppCommand
{ {
public long FieldId { get; set; } public long FieldId { get; set; }
} }

2
src/PinkParrot.Write/Schemas/Commands/HideField.cs

@ -7,7 +7,7 @@
// ========================================================================== // ==========================================================================
namespace PinkParrot.Write.Schemas.Commands namespace PinkParrot.Write.Schemas.Commands
{ {
public class HideField : TenantCommand public class HideField : AppCommand
{ {
public long FieldId { get; set; } public long FieldId { get; set; }
} }

2
src/PinkParrot.Write/Schemas/Commands/ShowField.cs

@ -7,7 +7,7 @@
// ========================================================================== // ==========================================================================
namespace PinkParrot.Write.Schemas.Commands namespace PinkParrot.Write.Schemas.Commands
{ {
public class ShowField : TenantCommand public class ShowField : AppCommand
{ {
public long FieldId { get; set; } public long FieldId { get; set; }
} }

2
src/PinkParrot.Write/Schemas/Commands/UpdateField.cs

@ -10,7 +10,7 @@ using Newtonsoft.Json.Linq;
namespace PinkParrot.Write.Schemas.Commands namespace PinkParrot.Write.Schemas.Commands
{ {
public class UpdateField : TenantCommand public class UpdateField : AppCommand
{ {
public long FieldId { get; set; } public long FieldId { get; set; }

2
src/PinkParrot.Write/Schemas/Commands/UpdateSchema.cs

@ -10,7 +10,7 @@ using PinkParrot.Core.Schemas;
namespace PinkParrot.Write.Schemas.Commands namespace PinkParrot.Write.Schemas.Commands
{ {
public class UpdateSchema : TenantCommand public class UpdateSchema : AppCommand
{ {
public SchemaProperties Properties { get; set; } public SchemaProperties Properties { get; set; }
} }

4
src/PinkParrot.Write/Schemas/SchemaCommandHandler.cs

@ -45,13 +45,13 @@ namespace PinkParrot.Write.Schemas
public async Task On(CreateSchema command) public async Task On(CreateSchema command)
{ {
if (await schemaProvider.FindSchemaIdByNameAsync(command.TenantId, command.Name) != null) if (await schemaProvider.FindSchemaIdByNameAsync(command.AppId, command.Name) != null)
{ {
var error = new ValidationError($"A schema with name '{command.Name}' already exists", "Name"); var error = new ValidationError($"A schema with name '{command.Name}' already exists", "Name");
throw new ValidationException("Cannot create a new schema", error); throw new ValidationException("Cannot create a new schema", error);
} }
await CreateAsync(command, s => s.Create(command.TenantId, command.Name, command.Properties)); await CreateAsync(command, s => s.Create(command.AppId, command.Name, command.Properties));
} }
public Task On(DeleteSchema command) public Task On(DeleteSchema command)

14
src/PinkParrot.Write/Schemas/SchemaDomainObject.cs

@ -16,10 +16,10 @@ using PinkParrot.Infrastructure.Dispatching;
namespace PinkParrot.Write.Schemas namespace PinkParrot.Write.Schemas
{ {
public class SchemaDomainObject : DomainObject, ITenantAggregate public class SchemaDomainObject : DomainObject, IAppAggregate
{ {
private readonly FieldRegistry registry; private readonly FieldRegistry registry;
private Guid tenantId; private Guid appId;
private bool isDeleted; private bool isDeleted;
private long totalFields; private long totalFields;
private Schema schema; private Schema schema;
@ -29,9 +29,9 @@ namespace PinkParrot.Write.Schemas
get { return schema; } get { return schema; }
} }
public Guid TenantId public Guid AppId
{ {
get { return tenantId; } get { return appId; }
} }
public bool IsDeleted public bool IsDeleted
@ -56,7 +56,7 @@ namespace PinkParrot.Write.Schemas
public void On(SchemaCreated @event) public void On(SchemaCreated @event)
{ {
tenantId = @event.TenantId; appId = @event.AppId;
schema = Schema.Create(@event.Name, @event.Properties); schema = Schema.Create(@event.Name, @event.Properties);
} }
@ -108,11 +108,11 @@ namespace PinkParrot.Write.Schemas
RaiseEvent(new FieldAdded { FieldId = ++totalFields, Name = name, Properties = properties }); RaiseEvent(new FieldAdded { FieldId = ++totalFields, Name = name, Properties = properties });
} }
public void Create(Guid newTenantId, string name, SchemaProperties properties) public void Create(Guid newAppId, string name, SchemaProperties properties)
{ {
VerifyNotCreated(); VerifyNotCreated();
RaiseEvent(new SchemaCreated { TenantId = newTenantId, Name = name, Properties = properties }); RaiseEvent(new SchemaCreated { AppId = newAppId, Name = name, Properties = properties });
} }
public void Update(SchemaProperties properties) public void Update(SchemaProperties properties)

4
src/PinkParrot/Configurations/InfrastructureUsage.cs

@ -13,9 +13,9 @@ namespace PinkParrot.Configurations
{ {
public static class InfrastructureUsage public static class InfrastructureUsage
{ {
public static void UseTenants(this IApplicationBuilder app) public static void UseApps(this IApplicationBuilder app)
{ {
app.UseMiddleware<TenantMiddleware>(); app.UseMiddleware<AppMiddleware>();
} }
} }
} }

8
src/PinkParrot/Configurations/ReadModule.cs

@ -8,8 +8,8 @@
using Autofac; using Autofac;
using PinkParrot.Infrastructure.CQRS.Events; using PinkParrot.Infrastructure.CQRS.Events;
using PinkParrot.Read.Infrastructure.Services; using PinkParrot.Read.Apps.Services;
using PinkParrot.Read.Infrastructure.Services.Implementations; using PinkParrot.Read.Apps.Services.Implementations;
using PinkParrot.Read.Schemas.Repositories; using PinkParrot.Read.Schemas.Repositories;
using PinkParrot.Read.Schemas.Services; using PinkParrot.Read.Schemas.Services;
using PinkParrot.Read.Schemas.Services.Implementations; using PinkParrot.Read.Schemas.Services.Implementations;
@ -21,8 +21,8 @@ namespace PinkParrot.Configurations
{ {
protected override void Load(ContainerBuilder builder) protected override void Load(ContainerBuilder builder)
{ {
builder.RegisterType<TenantProvider>() builder.RegisterType<CachingAppProvider>()
.As<ITenantProvider>() .As<IAppProvider>()
.SingleInstance(); .SingleInstance();
builder.RegisterType<CachingSchemaProvider>() builder.RegisterType<CachingSchemaProvider>()

2
src/PinkParrot/Configurations/WriteModule.cs

@ -21,7 +21,7 @@ namespace PinkParrot.Configurations
.As<ICommandHandler>() .As<ICommandHandler>()
.SingleInstance(); .SingleInstance();
builder.RegisterType<EnrichWithTenantIdHandler>() builder.RegisterType<EnrichWithAppIdHandler>()
.As<ICommandHandler>() .As<ICommandHandler>()
.SingleInstance(); .SingleInstance();

4
src/PinkParrot/Modules/Api/Schemas/SchemasController.cs

@ -37,7 +37,7 @@ namespace PinkParrot.Modules.Api.Schemas
[Route("api/schemas/")] [Route("api/schemas/")]
public async Task<List<ListSchemaDto>> Query() public async Task<List<ListSchemaDto>> Query()
{ {
var schemas = await schemaRepository.QueryAllAsync(TenantId); var schemas = await schemaRepository.QueryAllAsync(AppId);
return schemas.Select(s => SimpleMapper.Map(s, new ListSchemaDto())).ToList(); return schemas.Select(s => SimpleMapper.Map(s, new ListSchemaDto())).ToList();
} }
@ -46,7 +46,7 @@ namespace PinkParrot.Modules.Api.Schemas
[Route("api/schemas/{name}/")] [Route("api/schemas/{name}/")]
public async Task<ActionResult> Get(string name) public async Task<ActionResult> Get(string name)
{ {
var entity = await schemaRepository.FindSchemaAsync(TenantId, name); var entity = await schemaRepository.FindSchemaAsync(AppId, name);
if (entity == null) if (entity == null)
{ {

10
src/PinkParrot/Modules/ControllerBase.cs

@ -22,18 +22,18 @@ namespace PinkParrot.Modules
CommandBus = commandBus; CommandBus = commandBus;
} }
public Guid TenantId public Guid AppId
{ {
get get
{ {
var tenantFeature = HttpContext.Features.Get<ITenantFeature>(); var appFeature = HttpContext.Features.Get<IAppFeature>();
if (tenantFeature == null) if (appFeature == null)
{ {
throw new InvalidOperationException("Not in a tenant context"); throw new InvalidOperationException("Not in a app context");
} }
return tenantFeature.TenantId; return appFeature.AppId;
} }
} }
} }

14
src/PinkParrot/Pipeline/AppFeature.cs

@ -0,0 +1,14 @@
using System;
namespace PinkParrot.Pipeline
{
public sealed class AppFeature : IAppFeature
{
public Guid AppId { get; }
public AppFeature(Guid appId)
{
AppId = appId;
}
}
}

39
src/PinkParrot/Pipeline/AppMiddleware.cs

@ -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);
}
}
}

6
src/PinkParrot/Pipeline/CommandHandlers/EnrichWithAggregateIdHandler.cs

@ -40,9 +40,9 @@ namespace PinkParrot.Pipeline.CommandHandlers
return false; return false;
} }
var tenantCommand = context.Command as ITenantCommand; var appCommand = context.Command as IAppCommand;
if (tenantCommand == null) if (appCommand == null)
{ {
return false; return false;
} }
@ -53,7 +53,7 @@ namespace PinkParrot.Pipeline.CommandHandlers
{ {
var schemaName = routeValues["name"].ToString(); var schemaName = routeValues["name"].ToString();
var id = await schemaProvider.FindSchemaIdByNameAsync(tenantCommand.TenantId, schemaName); var id = await schemaProvider.FindSchemaIdByNameAsync(appCommand.AppId, schemaName);
if (!id.HasValue) if (!id.HasValue)
{ {

18
src/PinkParrot/Pipeline/CommandHandlers/EnrichWithTenantIdHandler.cs → src/PinkParrot/Pipeline/CommandHandlers/EnrichWithAppIdHandler.cs

@ -1,5 +1,5 @@
// ========================================================================== // ==========================================================================
// EnrichWithTenantIdHandler.cs // EnrichWithAppIdHandler.cs
// PinkParrot Headless CMS // PinkParrot Headless CMS
// ========================================================================== // ==========================================================================
// Copyright (c) PinkParrot Group // Copyright (c) PinkParrot Group
@ -16,29 +16,29 @@ using PinkParrot.Write;
namespace PinkParrot.Pipeline.CommandHandlers namespace PinkParrot.Pipeline.CommandHandlers
{ {
public sealed class EnrichWithTenantIdHandler : ICommandHandler public sealed class EnrichWithAppIdHandler : ICommandHandler
{ {
private readonly IHttpContextAccessor httpContextAccessor; private readonly IHttpContextAccessor httpContextAccessor;
public EnrichWithTenantIdHandler(IHttpContextAccessor httpContextAccessor) public EnrichWithAppIdHandler(IHttpContextAccessor httpContextAccessor)
{ {
this.httpContextAccessor = httpContextAccessor; this.httpContextAccessor = httpContextAccessor;
} }
public Task<bool> HandleAsync(CommandContext context) public Task<bool> HandleAsync(CommandContext context)
{ {
var tenantCommand = context.Command as ITenantCommand; var appCommand = context.Command as IAppCommand;
if (tenantCommand != null) if (appCommand != null)
{ {
var tenantFeature = httpContextAccessor.HttpContext.Features.Get<ITenantFeature>(); var appFeature = httpContextAccessor.HttpContext.Features.Get<IAppFeature>();
if (tenantFeature == null) if (appFeature == null)
{ {
throw new InvalidOperationException("Cannot reslolve tenant"); throw new InvalidOperationException("Cannot resolve app");
} }
tenantCommand.TenantId = tenantFeature.TenantId; appCommand.AppId = appFeature.AppId;
} }
return Task.FromResult(false); return Task.FromResult(false);

6
src/PinkParrot/Pipeline/ITenantFeature.cs → src/PinkParrot/Pipeline/IAppFeature.cs

@ -1,5 +1,5 @@
// ========================================================================== // ==========================================================================
// ITenantFeature.cs // IAppFeature.cs
// PinkParrot Headless CMS // PinkParrot Headless CMS
// ========================================================================== // ==========================================================================
// Copyright (c) PinkParrot Group // Copyright (c) PinkParrot Group
@ -10,8 +10,8 @@ using System;
namespace PinkParrot.Pipeline namespace PinkParrot.Pipeline
{ {
public interface ITenantFeature public interface IAppFeature
{ {
Guid TenantId { get; } Guid AppId { get; }
} }
} }

45
src/PinkParrot/Pipeline/TenantMiddleware.cs

@ -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);
}
}
}

2
src/PinkParrot/Startup.cs

@ -69,7 +69,7 @@ namespace PinkParrot
app.UseDeveloperExceptionPage(); app.UseDeveloperExceptionPage();
} }
app.UseTenants(); app.UseApps();
app.UseMvc(); app.UseMvc();
app.UseStaticFiles(); app.UseStaticFiles();
app.UseEventStore(); app.UseEventStore();

13
tests/PinkParrot.Write.Tests/Apps/AppDomainObjectTest.cs

@ -1,7 +1,12 @@
using System; // ==========================================================================
using System.Collections.Generic; // AppDomainObjectTest.cs
using System.Linq; // PinkParrot Headless CMS
using System.Threading.Tasks; // ==========================================================================
// Copyright (c) PinkParrot Group
// All rights reserved.
// ==========================================================================
using System;
using PinkParrot.Infrastructure; using PinkParrot.Infrastructure;
using PinkParrot.Write.Apps; using PinkParrot.Write.Apps;
using PinkParrot.Write.Apps.Commands; using PinkParrot.Write.Apps.Commands;

11
tests/PinkParrot.Write.Tests/Properties/AssemblyInfo.cs

@ -1,5 +1,12 @@
using System.Reflection; // ==========================================================================
using System.Runtime.CompilerServices; // AssemblyInfo.cs
// PinkParrot Headless CMS
// ==========================================================================
// Copyright (c) PinkParrot Group
// All rights reserved.
// ==========================================================================
using System.Reflection;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following // General Information about an assembly is controlled through the following

Loading…
Cancel
Save