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
// ==========================================================================
// Copyright (c) PinkParrot Group
@ -11,8 +11,8 @@ using PinkParrot.Infrastructure.CQRS.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.
// ==========================================================================
using PinkParrot.Infrastructure;
using PinkParrot.Infrastructure.CQRS.Events;
namespace PinkParrot.Events.Apps
{
[TypeName("AppCreated")]
public class AppCreated : IEvent
{
public string Name { get; set; }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

@ -11,7 +11,7 @@ using PinkParrot.Infrastructure;
namespace PinkParrot.Events.Schemas
{
[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
{
[TypeName("SchemaUpdated")]
public class SchemaUpdated : TenantEvent
public class SchemaUpdated : AppEvent
{
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 CommitId = "CommitId";
public const string Timestamp = "Timestamp";
public const string TenantId = "TenantId";
public const string AppId = "AppId";
public const string EventId = "EventId";
public const string EventNumber = "EventNumber";
}

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

@ -62,14 +62,14 @@ namespace PinkParrot.Infrastructure.CQRS
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;
}

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

@ -24,11 +24,11 @@ namespace PinkParrot.Infrastructure.CQRS
.SetEventId(eventId)
.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;

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

@ -1,5 +1,5 @@
// ==========================================================================
// ITenantAggregate.cs
// IAppAggregate.cs
// PinkParrot Headless CMS
// ==========================================================================
// Copyright (c) PinkParrot Group
@ -10,8 +10,8 @@ using System;
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
// ==========================================================================
// Copyright (c) PinkParrot Group
@ -9,10 +9,10 @@
using System;
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
// ==========================================================================
// Copyright (c) PinkParrot Group
@ -8,10 +8,10 @@
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;
namespace PinkParrot.Read.Schemas.Repositories
namespace PinkParrot.Read
{
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
{
public interface ISchemaEntity : ITenantEntity
public interface ISchemaEntity : IAppEntity
{
string Name { get; }
}

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

@ -14,11 +14,11 @@ namespace PinkParrot.Read.Schemas.Repositories
{
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);
}

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

@ -13,6 +13,6 @@ namespace PinkParrot.Read.Schemas.Services
{
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.Events;
using PinkParrot.Read.Schemas.Repositories;
using PinkParrot.Read.Utils;
// ReSharper disable InvertIf
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 readonly IMemoryCache cache;
private readonly ISchemaRepository repository;
public sealed class CacheItem
private sealed class CacheItem
{
public ISchemaEntityWithSchema Entity;
}
public CachingSchemaProvider(IMemoryCache cache, ISchemaRepository repository)
: base(cache)
{
Guard.NotNull(cache, nameof(cache));
Guard.NotNull(repository, nameof(repository));
this.cache = cache;
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));
var cacheKey = BuildModelsCacheKey(tenantId, name);
var cacheItem = cache.Get<CacheItem>(cacheKey);
var cacheKey = BuildModelsCacheKey(appId, name);
var cacheItem = Cache.Get<CacheItem>(cacheKey);
if (cacheItem == null)
{
var schema = await repository.FindSchemaAsync(tenantId, name);
var schema = await repository.FindSchemaAsync(appId, name);
cacheItem = new CacheItem { Entity = schema };
cache.Set(cacheKey, cacheItem, CacheDuration);
Cache.Set(cacheKey, cacheItem, CacheDuration);
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)
{
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)
{
cache.Remove(BuildModelsCacheKey(@event.Headers.TenantId(), oldName));
Cache.Remove(BuildModelsCacheKey(@event.Headers.AppId(), oldName));
}
}
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)

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;
// 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]
[BsonElement]
public Guid TenantId { get; set; }
public Guid AppId { get; set; }
[BsonRequired]
[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));
}
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();
}
public async Task<ISchemaEntityWithSchema> FindSchemaAsync(Guid tenantId, string name)
public async Task<ISchemaEntityWithSchema> FindSchemaAsync(Guid appId, string name)
{
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();
entity?.DeserializeSchema(serializerSettings, fieldRegistry);
@ -73,10 +73,10 @@ namespace PinkParrot.Store.MongoDb.Schemas
return entity;
}
public async Task<Guid?> FindSchemaIdAsync(Guid tenantId, string name)
public async Task<Guid?> FindSchemaIdAsync(Guid appId, string name)
{
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();
return entity?.Id;

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

@ -12,7 +12,7 @@ using MongoDB.Bson;
using MongoDB.Driver;
using Newtonsoft.Json;
using PinkParrot.Infrastructure.CQRS;
using PinkParrot.Read.Schemas.Repositories;
using PinkParrot.Read;
namespace PinkParrot.Store.MongoDb.Utils
{
@ -24,11 +24,11 @@ namespace PinkParrot.Store.MongoDb.Utils
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);

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

@ -1,5 +1,5 @@
// ==========================================================================
// TenantCommand.cs
// AppCommand.cs
// PinkParrot Headless CMS
// ==========================================================================
// Copyright (c) PinkParrot Group
@ -11,8 +11,8 @@ using PinkParrot.Infrastructure.CQRS.Commands;
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
// ==========================================================================
// Copyright (c) PinkParrot Group
@ -11,8 +11,8 @@ using PinkParrot.Infrastructure.CQRS.Commands;
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
{
public class AddField : TenantCommand
public class AddField : AppCommand
{
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
{
public class CreateSchema : TenantCommand
public class CreateSchema : AppCommand
{
public string Name { get; set; }

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

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

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

@ -7,7 +7,7 @@
// ==========================================================================
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
{
public class DisableField : TenantCommand
public class DisableField : AppCommand
{
public long FieldId { get; set; }
}

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

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

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

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

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

@ -7,7 +7,7 @@
// ==========================================================================
namespace PinkParrot.Write.Schemas.Commands
{
public class ShowField : TenantCommand
public class ShowField : AppCommand
{
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
{
public class UpdateField : TenantCommand
public class UpdateField : AppCommand
{
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
{
public class UpdateSchema : TenantCommand
public class UpdateSchema : AppCommand
{
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)
{
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");
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)

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

@ -16,10 +16,10 @@ using PinkParrot.Infrastructure.Dispatching;
namespace PinkParrot.Write.Schemas
{
public class SchemaDomainObject : DomainObject, ITenantAggregate
public class SchemaDomainObject : DomainObject, IAppAggregate
{
private readonly FieldRegistry registry;
private Guid tenantId;
private Guid appId;
private bool isDeleted;
private long totalFields;
private Schema schema;
@ -29,9 +29,9 @@ namespace PinkParrot.Write.Schemas
get { return schema; }
}
public Guid TenantId
public Guid AppId
{
get { return tenantId; }
get { return appId; }
}
public bool IsDeleted
@ -56,7 +56,7 @@ namespace PinkParrot.Write.Schemas
public void On(SchemaCreated @event)
{
tenantId = @event.TenantId;
appId = @event.AppId;
schema = Schema.Create(@event.Name, @event.Properties);
}
@ -108,11 +108,11 @@ namespace PinkParrot.Write.Schemas
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();
RaiseEvent(new SchemaCreated { TenantId = newTenantId, Name = name, Properties = properties });
RaiseEvent(new SchemaCreated { AppId = newAppId, Name = name, Properties = 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 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 PinkParrot.Infrastructure.CQRS.Events;
using PinkParrot.Read.Infrastructure.Services;
using PinkParrot.Read.Infrastructure.Services.Implementations;
using PinkParrot.Read.Apps.Services;
using PinkParrot.Read.Apps.Services.Implementations;
using PinkParrot.Read.Schemas.Repositories;
using PinkParrot.Read.Schemas.Services;
using PinkParrot.Read.Schemas.Services.Implementations;
@ -21,8 +21,8 @@ namespace PinkParrot.Configurations
{
protected override void Load(ContainerBuilder builder)
{
builder.RegisterType<TenantProvider>()
.As<ITenantProvider>()
builder.RegisterType<CachingAppProvider>()
.As<IAppProvider>()
.SingleInstance();
builder.RegisterType<CachingSchemaProvider>()

2
src/PinkParrot/Configurations/WriteModule.cs

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

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

@ -37,7 +37,7 @@ namespace PinkParrot.Modules.Api.Schemas
[Route("api/schemas/")]
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();
}
@ -46,7 +46,7 @@ namespace PinkParrot.Modules.Api.Schemas
[Route("api/schemas/{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)
{

10
src/PinkParrot/Modules/ControllerBase.cs

@ -22,18 +22,18 @@ namespace PinkParrot.Modules
CommandBus = commandBus;
}
public Guid TenantId
public Guid AppId
{
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;
}
var tenantCommand = context.Command as ITenantCommand;
var appCommand = context.Command as IAppCommand;
if (tenantCommand == null)
if (appCommand == null)
{
return false;
}
@ -53,7 +53,7 @@ namespace PinkParrot.Pipeline.CommandHandlers
{
var schemaName = routeValues["name"].ToString();
var id = await schemaProvider.FindSchemaIdByNameAsync(tenantCommand.TenantId, schemaName);
var id = await schemaProvider.FindSchemaIdByNameAsync(appCommand.AppId, schemaName);
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
// ==========================================================================
// Copyright (c) PinkParrot Group
@ -16,29 +16,29 @@ using PinkParrot.Write;
namespace PinkParrot.Pipeline.CommandHandlers
{
public sealed class EnrichWithTenantIdHandler : ICommandHandler
public sealed class EnrichWithAppIdHandler : ICommandHandler
{
private readonly IHttpContextAccessor httpContextAccessor;
public EnrichWithTenantIdHandler(IHttpContextAccessor httpContextAccessor)
public EnrichWithAppIdHandler(IHttpContextAccessor httpContextAccessor)
{
this.httpContextAccessor = httpContextAccessor;
}
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);

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

@ -1,5 +1,5 @@
// ==========================================================================
// ITenantFeature.cs
// IAppFeature.cs
// PinkParrot Headless CMS
// ==========================================================================
// Copyright (c) PinkParrot Group
@ -10,8 +10,8 @@ using System;
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.UseTenants();
app.UseApps();
app.UseMvc();
app.UseStaticFiles();
app.UseEventStore();

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

@ -1,7 +1,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
// ==========================================================================
// AppDomainObjectTest.cs
// PinkParrot Headless CMS
// ==========================================================================
// Copyright (c) PinkParrot Group
// All rights reserved.
// ==========================================================================
using System;
using PinkParrot.Infrastructure;
using PinkParrot.Write.Apps;
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;
// General Information about an assembly is controlled through the following

Loading…
Cancel
Save