Browse Source

Evebt restructuring

pull/1/head
Sebastian 9 years ago
parent
commit
4ad6cf378c
  1. 9
      src/Squidex.Events/AppEvent.cs
  2. 3
      src/Squidex.Events/Apps/AppClientAttached.cs
  3. 3
      src/Squidex.Events/Apps/AppClientRenamed.cs
  4. 3
      src/Squidex.Events/Apps/AppClientRevoked.cs
  5. 3
      src/Squidex.Events/Apps/AppContributorAssigned.cs
  6. 3
      src/Squidex.Events/Apps/AppContributorRemoved.cs
  7. 3
      src/Squidex.Events/Apps/AppCreated.cs
  8. 3
      src/Squidex.Events/Apps/AppLanguageAdded.cs
  9. 3
      src/Squidex.Events/Apps/AppLanguageRemoved.cs
  10. 3
      src/Squidex.Events/Apps/AppMasterLanguageSet.cs
  11. 6
      src/Squidex.Events/Contents/ContentCreated.cs
  12. 3
      src/Squidex.Events/Contents/ContentDeleted.cs
  13. 8
      src/Squidex.Events/Contents/ContentEvent.cs
  14. 3
      src/Squidex.Events/Contents/ContentPublished.cs
  15. 3
      src/Squidex.Events/Contents/ContentUnpublished.cs
  16. 3
      src/Squidex.Events/Contents/ContentUpdated.cs
  17. 41
      src/Squidex.Events/EventExtensions.cs
  18. 12
      src/Squidex.Events/SchemaEvent.cs
  19. 6
      src/Squidex.Events/Schemas/FieldEvent.cs
  20. 3
      src/Squidex.Events/Schemas/SchemaCreated.cs
  21. 3
      src/Squidex.Events/Schemas/SchemaDeleted.cs
  22. 3
      src/Squidex.Events/Schemas/SchemaPublished.cs
  23. 3
      src/Squidex.Events/Schemas/SchemaUnpublished.cs
  24. 3
      src/Squidex.Events/Schemas/SchemaUpdated.cs
  25. 16
      src/Squidex.Events/Schemas/Utils/SchemaEventDispatcher.cs
  26. 18
      src/Squidex.Events/SquidexEvent.cs
  27. 12
      src/Squidex.Infrastructure.MongoDb/EventStore/MongoEventStore.cs
  28. 2
      src/Squidex.Infrastructure/CQRS/Commands/IAggregateCommand.cs
  29. 4
      src/Squidex.Infrastructure/CQRS/DomainObject.cs
  30. 12
      src/Squidex.Infrastructure/CQRS/EnvelopeExtensions.cs
  31. 29
      src/Squidex.Infrastructure/CQRS/Events/EnrichWithActorProcessor.cs
  32. 2
      src/Squidex.Infrastructure/Json/NamedGuidIdConverter.cs
  33. 53
      src/Squidex.Infrastructure/Json/NamedLongIdConverter.cs
  34. 2
      src/Squidex.Infrastructure/Json/NamedStringIdConverter.cs
  35. 2
      src/Squidex.Infrastructure/NamedId.cs
  36. 23
      src/Squidex.Read.MongoDb/Apps/MongoAppRepository_EventHandling.cs
  37. 25
      src/Squidex.Read.MongoDb/Contents/MongoContentRepository_EventHandling.cs
  38. 15
      src/Squidex.Read.MongoDb/History/MongoHistoryEventRepository.cs
  39. 29
      src/Squidex.Read.MongoDb/Schemas/MongoSchemaRepository_EventHandling.cs
  40. 55
      src/Squidex.Read.MongoDb/Utils/CollectionExtensions.cs
  41. 92
      src/Squidex.Read.MongoDb/Utils/EntityMapper.cs
  42. 52
      src/Squidex.Read/Schemas/SchemaHistoryEventsCreator.cs
  43. 14
      src/Squidex.Write/AppAggregateCommand.cs
  44. 5
      src/Squidex.Write/AppCommand.cs
  45. 22
      src/Squidex.Write/Apps/AppDomainObject.cs
  46. 4
      src/Squidex.Write/Apps/Commands/CreateApp.cs
  47. 23
      src/Squidex.Write/Contents/Commands/ContentCommand.cs
  48. 4
      src/Squidex.Write/Contents/Commands/ContentDataCommand.cs
  49. 6
      src/Squidex.Write/Contents/Commands/CreateContent.cs
  50. 2
      src/Squidex.Write/Contents/Commands/DeleteContent.cs
  51. 2
      src/Squidex.Write/Contents/Commands/PublishContent.cs
  52. 2
      src/Squidex.Write/Contents/Commands/UnpublishContent.cs
  53. 9
      src/Squidex.Write/Contents/ContentCommandHandler.cs
  54. 42
      src/Squidex.Write/EnrichWithAppIdProcessor.cs
  55. 42
      src/Squidex.Write/EnrichWithSchemaIdProcessor.cs
  56. 14
      src/Squidex.Write/SchemaAggregateCommand.cs
  57. 5
      src/Squidex.Write/SchemaCommand.cs
  58. 2
      src/Squidex.Write/Schemas/Commands/AddField.cs
  59. 12
      src/Squidex.Write/Schemas/Commands/CreateSchema.cs
  60. 3
      src/Squidex.Write/Schemas/Commands/DeleteField.cs
  61. 3
      src/Squidex.Write/Schemas/Commands/DisableField.cs
  62. 3
      src/Squidex.Write/Schemas/Commands/EnableField.cs
  63. 8
      src/Squidex.Write/Schemas/Commands/FieldCommand.cs
  64. 3
      src/Squidex.Write/Schemas/Commands/HideField.cs
  65. 3
      src/Squidex.Write/Schemas/Commands/ShowField.cs
  66. 4
      src/Squidex.Write/Schemas/Commands/UpdateField.cs
  67. 2
      src/Squidex.Write/Schemas/SchemaCommandHandler.cs
  68. 30
      src/Squidex.Write/Schemas/SchemaDomainObject.cs
  69. 3
      src/Squidex.Write/SquidexCommand.cs
  70. 6
      src/Squidex/Config/Domain/ClusterModule.cs
  71. 4
      src/Squidex/Config/Domain/InfrastructureModule.cs
  72. 10
      src/Squidex/Config/Domain/Serializers.cs
  73. 14
      src/Squidex/Config/Domain/StoreMongoDbModule.cs
  74. 13
      src/Squidex/Config/Domain/WriteModule.cs
  75. 3
      src/Squidex/Controllers/Api/Schemas/SchemasController.cs
  76. 12
      src/Squidex/Controllers/ContentApi/ContentsController.cs
  77. 7
      src/Squidex/Pipeline/CommandHandlers/EnrichWithActorHandler.cs
  78. 5
      src/Squidex/Pipeline/CommandHandlers/EnrichWithAppIdHandler.cs
  79. 7
      src/Squidex/Pipeline/CommandHandlers/EnrichWithSchemaIdHandler.cs
  80. 2
      src/Squidex/appsettings.json

9
src/Squidex.Infrastructure/CQRS/Commands/AggregateCommand.cs → src/Squidex.Events/AppEvent.cs

@ -1,5 +1,5 @@
// ========================================================================== // ==========================================================================
// AggregateCommand.cs // AppEvent.cs
// Squidex Headless CMS // Squidex Headless CMS
// ========================================================================== // ==========================================================================
// Copyright (c) Squidex Group // Copyright (c) Squidex Group
@ -7,11 +7,12 @@
// ========================================================================== // ==========================================================================
using System; using System;
using Squidex.Infrastructure;
namespace Squidex.Infrastructure.CQRS.Commands namespace Squidex.Events
{ {
public class AggregateCommand : IAggregateCommand public abstract class AppEvent : SquidexEvent
{ {
public Guid AggregateId { get; set; } public NamedId<Guid> AppId { get; set; }
} }
} }

3
src/Squidex.Events/Apps/AppClientAttached.cs

@ -8,12 +8,11 @@
using System; using System;
using Squidex.Infrastructure; using Squidex.Infrastructure;
using Squidex.Infrastructure.CQRS.Events;
namespace Squidex.Events.Apps namespace Squidex.Events.Apps
{ {
[TypeName("AppClientAttachedEvent")] [TypeName("AppClientAttachedEvent")]
public sealed class AppClientAttached : IEvent public sealed class AppClientAttached : AppEvent
{ {
public string Id { get; set; } public string Id { get; set; }

3
src/Squidex.Events/Apps/AppClientRenamed.cs

@ -7,12 +7,11 @@
// ========================================================================== // ==========================================================================
using Squidex.Infrastructure; using Squidex.Infrastructure;
using Squidex.Infrastructure.CQRS.Events;
namespace Squidex.Events.Apps namespace Squidex.Events.Apps
{ {
[TypeName("AppClientRenamedEvent")] [TypeName("AppClientRenamedEvent")]
public sealed class AppClientRenamed : IEvent public sealed class AppClientRenamed : AppEvent
{ {
public string Id { get; set; } public string Id { get; set; }

3
src/Squidex.Events/Apps/AppClientRevoked.cs

@ -7,12 +7,11 @@
// ========================================================================== // ==========================================================================
using Squidex.Infrastructure; using Squidex.Infrastructure;
using Squidex.Infrastructure.CQRS.Events;
namespace Squidex.Events.Apps namespace Squidex.Events.Apps
{ {
[TypeName("AppClientRevokedEvent")] [TypeName("AppClientRevokedEvent")]
public sealed class AppClientRevoked : IEvent public sealed class AppClientRevoked : AppEvent
{ {
public string Id { get; set; } public string Id { get; set; }
} }

3
src/Squidex.Events/Apps/AppContributorAssigned.cs

@ -8,12 +8,11 @@
using Squidex.Core.Apps; using Squidex.Core.Apps;
using Squidex.Infrastructure; using Squidex.Infrastructure;
using Squidex.Infrastructure.CQRS.Events;
namespace Squidex.Events.Apps namespace Squidex.Events.Apps
{ {
[TypeName("AppContributorAssignedEvent")] [TypeName("AppContributorAssignedEvent")]
public class AppContributorAssigned : IEvent public class AppContributorAssigned : AppEvent
{ {
public string ContributorId { get; set; } public string ContributorId { get; set; }

3
src/Squidex.Events/Apps/AppContributorRemoved.cs

@ -7,12 +7,11 @@
// ========================================================================== // ==========================================================================
using Squidex.Infrastructure; using Squidex.Infrastructure;
using Squidex.Infrastructure.CQRS.Events;
namespace Squidex.Events.Apps namespace Squidex.Events.Apps
{ {
[TypeName("AppContributorRemovedEvent")] [TypeName("AppContributorRemovedEvent")]
public class AppContributorRemoved : IEvent public class AppContributorRemoved : AppEvent
{ {
public string ContributorId { get; set; } public string ContributorId { get; set; }
} }

3
src/Squidex.Events/Apps/AppCreated.cs

@ -7,12 +7,11 @@
// ========================================================================== // ==========================================================================
using Squidex.Infrastructure; using Squidex.Infrastructure;
using Squidex.Infrastructure.CQRS.Events;
namespace Squidex.Events.Apps namespace Squidex.Events.Apps
{ {
[TypeName("AppCreatedEvent")] [TypeName("AppCreatedEvent")]
public class AppCreated : IEvent public class AppCreated : AppEvent
{ {
public string Name { get; set; } public string Name { get; set; }
} }

3
src/Squidex.Events/Apps/AppLanguageAdded.cs

@ -7,12 +7,11 @@
// ========================================================================== // ==========================================================================
using Squidex.Infrastructure; using Squidex.Infrastructure;
using Squidex.Infrastructure.CQRS.Events;
namespace Squidex.Events.Apps namespace Squidex.Events.Apps
{ {
[TypeName("AppLanguageAddedEvent")] [TypeName("AppLanguageAddedEvent")]
public sealed class AppLanguageAdded : IEvent public sealed class AppLanguageAdded : AppEvent
{ {
public Language Language { get; set; } public Language Language { get; set; }
} }

3
src/Squidex.Events/Apps/AppLanguageRemoved.cs

@ -7,12 +7,11 @@
// ========================================================================== // ==========================================================================
using Squidex.Infrastructure; using Squidex.Infrastructure;
using Squidex.Infrastructure.CQRS.Events;
namespace Squidex.Events.Apps namespace Squidex.Events.Apps
{ {
[TypeName("AppLanguageRemovedEvent")] [TypeName("AppLanguageRemovedEvent")]
public sealed class AppLanguageRemoved : IEvent public sealed class AppLanguageRemoved : AppEvent
{ {
public Language Language { get; set; } public Language Language { get; set; }
} }

3
src/Squidex.Events/Apps/AppMasterLanguageSet.cs

@ -7,12 +7,11 @@
// ========================================================================== // ==========================================================================
using Squidex.Infrastructure; using Squidex.Infrastructure;
using Squidex.Infrastructure.CQRS.Events;
namespace Squidex.Events.Apps namespace Squidex.Events.Apps
{ {
[TypeName("AppMasterLanguageSetEvent")] [TypeName("AppMasterLanguageSetEvent")]
public sealed class AppMasterLanguageSet : IEvent public sealed class AppMasterLanguageSet : AppEvent
{ {
public Language Language { get; set; } public Language Language { get; set; }
} }

6
src/Squidex.Events/Contents/ContentCreated.cs

@ -6,18 +6,14 @@
// All rights reserved. // All rights reserved.
// ========================================================================== // ==========================================================================
using System;
using Squidex.Core.Contents; using Squidex.Core.Contents;
using Squidex.Infrastructure; using Squidex.Infrastructure;
using Squidex.Infrastructure.CQRS.Events;
namespace Squidex.Events.Contents namespace Squidex.Events.Contents
{ {
[TypeName("ContentCreatedEvent")] [TypeName("ContentCreatedEvent")]
public class ContentCreated : IEvent public class ContentCreated : ContentEvent
{ {
public Guid SchemaId { get; set; }
public ContentData Data { get; set; } public ContentData Data { get; set; }
} }
} }

3
src/Squidex.Events/Contents/ContentDeleted.cs

@ -7,12 +7,11 @@
// ========================================================================== // ==========================================================================
using Squidex.Infrastructure; using Squidex.Infrastructure;
using Squidex.Infrastructure.CQRS.Events;
namespace Squidex.Events.Contents namespace Squidex.Events.Contents
{ {
[TypeName("ContentDeletedEvent")] [TypeName("ContentDeletedEvent")]
public class ContentDeleted : IEvent public class ContentDeleted : ContentEvent
{ {
} }
} }

8
src/Squidex.Write/ISchemaCommand.cs → src/Squidex.Events/Contents/ContentEvent.cs

@ -1,5 +1,5 @@
// ========================================================================== // ==========================================================================
// ISchemaCommand.cs // ContentEvent.cs
// Squidex Headless CMS // Squidex Headless CMS
// ========================================================================== // ==========================================================================
// Copyright (c) Squidex Group // Copyright (c) Squidex Group
@ -8,10 +8,10 @@
using System; using System;
namespace Squidex.Write namespace Squidex.Events.Contents
{ {
public interface ISchemaCommand : IAppCommand public abstract class ContentEvent : SchemaEvent
{ {
Guid SchemaId { get; set; } public Guid ContentId { get; set; }
} }
} }

3
src/Squidex.Events/Contents/ContentPublished.cs

@ -7,12 +7,11 @@
// ========================================================================== // ==========================================================================
using Squidex.Infrastructure; using Squidex.Infrastructure;
using Squidex.Infrastructure.CQRS.Events;
namespace Squidex.Events.Contents namespace Squidex.Events.Contents
{ {
[TypeName("ContentPublishedEvent")] [TypeName("ContentPublishedEvent")]
public class ContentPublished : IEvent public class ContentPublished : ContentEvent
{ {
} }
} }

3
src/Squidex.Events/Contents/ContentUnpublished.cs

@ -7,12 +7,11 @@
// ========================================================================== // ==========================================================================
using Squidex.Infrastructure; using Squidex.Infrastructure;
using Squidex.Infrastructure.CQRS.Events;
namespace Squidex.Events.Contents namespace Squidex.Events.Contents
{ {
[TypeName("ContentUnpublishedEvent")] [TypeName("ContentUnpublishedEvent")]
public class ContentUnpublished : IEvent public class ContentUnpublished : ContentEvent
{ {
} }
} }

3
src/Squidex.Events/Contents/ContentUpdated.cs

@ -8,12 +8,11 @@
using Squidex.Core.Contents; using Squidex.Core.Contents;
using Squidex.Infrastructure; using Squidex.Infrastructure;
using Squidex.Infrastructure.CQRS.Events;
namespace Squidex.Events.Contents namespace Squidex.Events.Contents
{ {
[TypeName("ContentUpdatedEvent")] [TypeName("ContentUpdatedEvent")]
public class ContentUpdated : IEvent public class ContentUpdated : ContentEvent
{ {
public ContentData Data { get; set; } public ContentData Data { get; set; }
} }

41
src/Squidex.Events/EventExtensions.cs

@ -1,41 +0,0 @@
// ==========================================================================
// EventExtensions.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using System;
using System.Globalization;
using Squidex.Infrastructure.CQRS;
namespace Squidex.Events
{
public static class EventExtensions
{
public static Guid AppId(this EnvelopeHeaders headers)
{
return headers["AppId"].ToGuid(CultureInfo.InvariantCulture);
}
public static Envelope<T> SetAppId<T>(this Envelope<T> envelope, Guid value) where T : class
{
envelope.Headers.Set("AppId", value);
return envelope;
}
public static Guid SchemaId(this EnvelopeHeaders headers)
{
return headers["SchemaId"].ToGuid(CultureInfo.InvariantCulture);
}
public static Envelope<T> SetSchemaId<T>(this Envelope<T> envelope, Guid value) where T : class
{
envelope.Headers.Set("SchemaId", value);
return envelope;
}
}
}

12
src/Squidex.Write/IAppCommand.cs → src/Squidex.Events/SchemaEvent.cs

@ -1,5 +1,5 @@
// ========================================================================== // ==========================================================================
// IAppCommand.cs // SchemaEvent.cs
// Squidex Headless CMS // Squidex Headless CMS
// ========================================================================== // ==========================================================================
// Copyright (c) Squidex Group // Copyright (c) Squidex Group
@ -7,12 +7,12 @@
// ========================================================================== // ==========================================================================
using System; using System;
using Squidex.Infrastructure.CQRS.Commands; using Squidex.Infrastructure;
namespace Squidex.Write namespace Squidex.Events
{ {
public interface IAppCommand : ICommand public abstract class SchemaEvent : AppEvent
{ {
Guid AppId { get; set; } public NamedId<Guid> SchemaId { get; set; }
} }
} }

6
src/Squidex.Events/Schemas/FieldEvent.cs

@ -6,12 +6,12 @@
// All rights reserved. // All rights reserved.
// ========================================================================== // ==========================================================================
using Squidex.Infrastructure.CQRS.Events; using Squidex.Infrastructure;
namespace Squidex.Events.Schemas namespace Squidex.Events.Schemas
{ {
public abstract class FieldEvent : IEvent public abstract class FieldEvent : SchemaEvent
{ {
public long FieldId { get; set; } public NamedId<long> FieldId { get; set; }
} }
} }

3
src/Squidex.Events/Schemas/SchemaCreated.cs

@ -8,12 +8,11 @@
using Squidex.Core.Schemas; using Squidex.Core.Schemas;
using Squidex.Infrastructure; using Squidex.Infrastructure;
using Squidex.Infrastructure.CQRS.Events;
namespace Squidex.Events.Schemas namespace Squidex.Events.Schemas
{ {
[TypeName("SchemaCreatedEvent")] [TypeName("SchemaCreatedEvent")]
public class SchemaCreated : IEvent public class SchemaCreated : SchemaEvent
{ {
public string Name { get; set; } public string Name { get; set; }

3
src/Squidex.Events/Schemas/SchemaDeleted.cs

@ -7,12 +7,11 @@
// ========================================================================== // ==========================================================================
using Squidex.Infrastructure; using Squidex.Infrastructure;
using Squidex.Infrastructure.CQRS.Events;
namespace Squidex.Events.Schemas namespace Squidex.Events.Schemas
{ {
[TypeName("SchemaDeletedEvent")] [TypeName("SchemaDeletedEvent")]
public class SchemaDeleted : IEvent public class SchemaDeleted : SchemaEvent
{ {
} }
} }

3
src/Squidex.Events/Schemas/SchemaPublished.cs

@ -7,12 +7,11 @@
// ========================================================================== // ==========================================================================
using Squidex.Infrastructure; using Squidex.Infrastructure;
using Squidex.Infrastructure.CQRS.Events;
namespace Squidex.Events.Schemas namespace Squidex.Events.Schemas
{ {
[TypeName("SchemaPublished")] [TypeName("SchemaPublished")]
public class SchemaPublished : IEvent public class SchemaPublished : SchemaEvent
{ {
} }
} }

3
src/Squidex.Events/Schemas/SchemaUnpublished.cs

@ -7,12 +7,11 @@
// ========================================================================== // ==========================================================================
using Squidex.Infrastructure; using Squidex.Infrastructure;
using Squidex.Infrastructure.CQRS.Events;
namespace Squidex.Events.Schemas namespace Squidex.Events.Schemas
{ {
[TypeName("SchemaUnpublished")] [TypeName("SchemaUnpublished")]
public class SchemaUnpublished : IEvent public class SchemaUnpublished : SchemaEvent
{ {
} }
} }

3
src/Squidex.Events/Schemas/SchemaUpdated.cs

@ -8,12 +8,11 @@
using Squidex.Core.Schemas; using Squidex.Core.Schemas;
using Squidex.Infrastructure; using Squidex.Infrastructure;
using Squidex.Infrastructure.CQRS.Events;
namespace Squidex.Events.Schemas namespace Squidex.Events.Schemas
{ {
[TypeName("SchemaUpdatedEvent")] [TypeName("SchemaUpdatedEvent")]
public class SchemaUpdated : IEvent public class SchemaUpdated : SchemaEvent
{ {
public SchemaProperties Properties { get; set; } public SchemaProperties Properties { get; set; }
} }

16
src/Squidex.Events/Schemas/Utils/SchemaEventDispatcher.cs

@ -1,5 +1,5 @@
// ========================================================================== // ==========================================================================
// SchemaUpdater.cs // SchemaEventDispatcher.cs
// Squidex Headless CMS // Squidex Headless CMS
// ========================================================================== // ==========================================================================
// Copyright (c) Squidex Group // Copyright (c) Squidex Group
@ -19,32 +19,32 @@ namespace Squidex.Events.Schemas.Utils
public static Schema Dispatch(FieldAdded @event, Schema schema, FieldRegistry registry) public static Schema Dispatch(FieldAdded @event, Schema schema, FieldRegistry registry)
{ {
return schema.AddOrUpdateField(registry.CreateField(@event.FieldId, @event.Name, @event.Properties)); return schema.AddOrUpdateField(registry.CreateField(@event.FieldId.Id, @event.Name, @event.Properties));
} }
public static Schema Dispatch(FieldUpdated @event, Schema schema) public static Schema Dispatch(FieldUpdated @event, Schema schema)
{ {
return schema.UpdateField(@event.FieldId, @event.Properties); return schema.UpdateField(@event.FieldId.Id, @event.Properties);
} }
public static Schema Dispatch(FieldHidden @event, Schema schema) public static Schema Dispatch(FieldHidden @event, Schema schema)
{ {
return schema.HideField(@event.FieldId); return schema.HideField(@event.FieldId.Id);
} }
public static Schema Dispatch(FieldShown @event, Schema schema) public static Schema Dispatch(FieldShown @event, Schema schema)
{ {
return schema.ShowField(@event.FieldId); return schema.ShowField(@event.FieldId.Id);
} }
public static Schema Dispatch(FieldDisabled @event, Schema schema) public static Schema Dispatch(FieldDisabled @event, Schema schema)
{ {
return schema.DisableField(@event.FieldId); return schema.DisableField(@event.FieldId.Id);
} }
public static Schema Dispatch(FieldEnabled @event, Schema schema) public static Schema Dispatch(FieldEnabled @event, Schema schema)
{ {
return schema.EnableField(@event.FieldId); return schema.EnableField(@event.FieldId.Id);
} }
public static Schema Dispatch(SchemaUpdated @event, Schema schema) public static Schema Dispatch(SchemaUpdated @event, Schema schema)
@ -54,7 +54,7 @@ namespace Squidex.Events.Schemas.Utils
public static Schema Dispatch(FieldDeleted @event, Schema schema) public static Schema Dispatch(FieldDeleted @event, Schema schema)
{ {
return schema.DeleteField(@event.FieldId); return schema.DeleteField(@event.FieldId.Id);
} }
public static Schema Dispatch(SchemaPublished @event, Schema schema) public static Schema Dispatch(SchemaPublished @event, Schema schema)

18
src/Squidex.Events/SquidexEvent.cs

@ -0,0 +1,18 @@
// ==========================================================================
// SquidexEvent.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using Squidex.Infrastructure;
using Squidex.Infrastructure.CQRS.Events;
namespace Squidex.Events
{
public abstract class SquidexEvent : IEvent
{
public RefToken Actor { get; set; }
}
}

12
src/Squidex.Infrastructure.MongoDb/EventStore/MongoEventStore.cs

@ -82,19 +82,21 @@ namespace Squidex.Infrastructure.MongoDb.EventStore
{ {
return Observable.Create<StoredEvent>(async (observer, ct) => return Observable.Create<StoredEvent>(async (observer, ct) =>
{ {
var position = await GetPreviousOffset(lastReceivedPosition); var commitOffset = await GetPreviousOffset(lastReceivedPosition);
await Collection.Find(new BsonDocument()).ForEachAsync(commit => await Collection.Find(x => x.EventsOffset >= commitOffset).SortBy(x => x.EventsOffset).ForEachAsync(commit =>
{ {
var eventNumber = commit.EventsOffset;
foreach (var @event in commit.Events) foreach (var @event in commit.Events)
{ {
position++; eventNumber++;
if (position > lastReceivedPosition) if (eventNumber > lastReceivedPosition)
{ {
var eventData = SimpleMapper.Map(@event, new EventData()); var eventData = SimpleMapper.Map(@event, new EventData());
observer.OnNext(new StoredEvent(position, eventData)); observer.OnNext(new StoredEvent(eventNumber, eventData));
} }
} }
}, ct); }, ct);

2
src/Squidex.Infrastructure/CQRS/Commands/IAggregateCommand.cs

@ -12,6 +12,6 @@ namespace Squidex.Infrastructure.CQRS.Commands
{ {
public interface IAggregateCommand : ICommand public interface IAggregateCommand : ICommand
{ {
Guid AggregateId { get; set; } Guid AggregateId { get; }
} }
} }

4
src/Squidex.Infrastructure/CQRS/DomainObject.cs

@ -45,12 +45,12 @@ namespace Squidex.Infrastructure.CQRS
DispatchEvent(@event); version++; DispatchEvent(@event); version++;
} }
protected void RaiseEvent(IEvent @event) protected virtual void RaiseEvent(IEvent @event)
{ {
RaiseEvent(Envelope<IEvent>.Create(@event)); RaiseEvent(Envelope<IEvent>.Create(@event));
} }
protected void RaiseEvent<TEvent>(Envelope<TEvent> @event) where TEvent : class, IEvent protected virtual void RaiseEvent<TEvent>(Envelope<TEvent> @event) where TEvent : class, IEvent
{ {
Guard.NotNull(@event, nameof(@event)); Guard.NotNull(@event, nameof(@event));

12
src/Squidex.Infrastructure/CQRS/EnvelopeExtensions.cs

@ -62,18 +62,6 @@ namespace Squidex.Infrastructure.CQRS
return envelope; return envelope;
} }
public static RefToken Actor(this EnvelopeHeaders headers)
{
return RefToken.Parse(headers[CommonHeaders.Actor].ToString());
}
public static Envelope<T> SetActor<T>(this Envelope<T> envelope, RefToken value) where T : class
{
envelope.Headers.Set(CommonHeaders.Actor, value.ToString());
return envelope;
}
public static Instant Timestamp(this EnvelopeHeaders headers) public static Instant Timestamp(this EnvelopeHeaders headers)
{ {
return headers[CommonHeaders.Timestamp].ToInstant(CultureInfo.InvariantCulture); return headers[CommonHeaders.Timestamp].ToInstant(CultureInfo.InvariantCulture);

29
src/Squidex.Infrastructure/CQRS/Events/EnrichWithActorProcessor.cs

@ -1,29 +0,0 @@
// ==========================================================================
// EnrichWithActorProcessor.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using System.Threading.Tasks;
using Squidex.Infrastructure.CQRS.Commands;
using Squidex.Infrastructure.Tasks;
namespace Squidex.Infrastructure.CQRS.Events
{
public sealed class EnrichWithActorProcessor : IEventProcessor
{
public Task ProcessEventAsync(Envelope<IEvent> @event, IAggregate aggregate, ICommand command)
{
var actorCommand = command as IActorCommand;
if (actorCommand != null)
{
@event.SetActor(actorCommand.Actor);
}
return TaskHelper.Done;
}
}
}

2
src/Squidex.Infrastructure/Json/NamedGuidIdConverted.cs → src/Squidex.Infrastructure/Json/NamedGuidIdConverter.cs

@ -12,7 +12,7 @@ using Newtonsoft.Json;
namespace Squidex.Infrastructure.Json namespace Squidex.Infrastructure.Json
{ {
public sealed class NamedGuidIdConverted : JsonConverter public sealed class NamedGuidIdConverter : JsonConverter
{ {
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{ {

53
src/Squidex.Infrastructure/Json/NamedLongIdConverter.cs

@ -0,0 +1,53 @@
// ==========================================================================
// NamedLongIdConverter.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using System;
using System.Linq;
using Newtonsoft.Json;
namespace Squidex.Infrastructure.Json
{
public sealed class NamedLongIdConverter : JsonConverter
{
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var namedId = (NamedId<long>)value;
writer.WriteValue($"{namedId.Id},{namedId.Name}");
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null)
{
return null;
}
var parts = ((string)reader.Value).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
if (parts.Length < 2)
{
throw new JsonException("Named id must have more than 2 parts divided by commata");
}
long id;
if (!long.TryParse(parts[0], out id))
{
throw new JsonException("Named id must be a valid long");
}
return new NamedId<long>(id, string.Join(",", parts.Skip(1)));
}
public override bool CanConvert(Type objectType)
{
return objectType == typeof(NamedId<long>);
}
}
}

2
src/Squidex.Infrastructure/Json/NamedStringIdConverted.cs → src/Squidex.Infrastructure/Json/NamedStringIdConverter.cs

@ -12,7 +12,7 @@ using Newtonsoft.Json;
namespace Squidex.Infrastructure.Json namespace Squidex.Infrastructure.Json
{ {
public sealed class NamedStringIdConverted : JsonConverter public sealed class NamedStringIdConverter : JsonConverter
{ {
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{ {

2
src/Squidex.Infrastructure/NamedId.cs

@ -38,7 +38,7 @@ namespace Squidex.Infrastructure
public bool Equals(NamedId<T> other) public bool Equals(NamedId<T> other)
{ {
return other != null && (ReferenceEquals(this, other) || Id.Equals(other.Id))); return other != null && (ReferenceEquals(this, other) || Id.Equals(other.Id));
} }
public override int GetHashCode() public override int GetHashCode()

23
src/Squidex.Read.MongoDb/Apps/MongoAppRepository_EventHandling.cs

@ -8,6 +8,7 @@
using System; using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using Squidex.Events;
using Squidex.Events.Apps; using Squidex.Events.Apps;
using Squidex.Infrastructure; using Squidex.Infrastructure;
using Squidex.Infrastructure.CQRS; using Squidex.Infrastructure.CQRS;
@ -29,7 +30,7 @@ namespace Squidex.Read.MongoDb.Apps
protected async Task On(AppCreated @event, EnvelopeHeaders headers) protected async Task On(AppCreated @event, EnvelopeHeaders headers)
{ {
await Collection.CreateAsync(headers, a => await Collection.CreateAsync(@event, headers, a =>
{ {
SimpleMapper.Map(@event, a); SimpleMapper.Map(@event, a);
}); });
@ -39,7 +40,7 @@ namespace Squidex.Read.MongoDb.Apps
protected Task On(AppContributorAssigned @event, EnvelopeHeaders headers) protected Task On(AppContributorAssigned @event, EnvelopeHeaders headers)
{ {
return UpdateAsync(headers, a => return UpdateAsync(@event, headers, a =>
{ {
var contributor = a.Contributors.GetOrAddNew(@event.ContributorId); var contributor = a.Contributors.GetOrAddNew(@event.ContributorId);
@ -49,7 +50,7 @@ namespace Squidex.Read.MongoDb.Apps
protected Task On(AppContributorRemoved @event, EnvelopeHeaders headers) protected Task On(AppContributorRemoved @event, EnvelopeHeaders headers)
{ {
return UpdateAsync(headers, a => return UpdateAsync(@event, headers, a =>
{ {
a.Contributors.Remove(@event.ContributorId); a.Contributors.Remove(@event.ContributorId);
}); });
@ -57,7 +58,7 @@ namespace Squidex.Read.MongoDb.Apps
protected Task On(AppClientAttached @event, EnvelopeHeaders headers) protected Task On(AppClientAttached @event, EnvelopeHeaders headers)
{ {
return UpdateAsync(headers, a => return UpdateAsync(@event, headers, a =>
{ {
a.Clients[@event.Id] = SimpleMapper.Map(@event, new MongoAppClientEntity()); a.Clients[@event.Id] = SimpleMapper.Map(@event, new MongoAppClientEntity());
}); });
@ -65,7 +66,7 @@ namespace Squidex.Read.MongoDb.Apps
protected Task On(AppClientRevoked @event, EnvelopeHeaders headers) protected Task On(AppClientRevoked @event, EnvelopeHeaders headers)
{ {
return UpdateAsync(headers, a => return UpdateAsync(@event, headers, a =>
{ {
a.Clients.Remove(@event.Id); a.Clients.Remove(@event.Id);
}); });
@ -73,7 +74,7 @@ namespace Squidex.Read.MongoDb.Apps
protected Task On(AppClientRenamed @event, EnvelopeHeaders headers) protected Task On(AppClientRenamed @event, EnvelopeHeaders headers)
{ {
return UpdateAsync(headers, a => return UpdateAsync(@event, headers, a =>
{ {
a.Clients[@event.Id].Name = @event.Name; a.Clients[@event.Id].Name = @event.Name;
}); });
@ -81,7 +82,7 @@ namespace Squidex.Read.MongoDb.Apps
protected Task On(AppLanguageAdded @event, EnvelopeHeaders headers) protected Task On(AppLanguageAdded @event, EnvelopeHeaders headers)
{ {
return UpdateAsync(headers, a => return UpdateAsync(@event, headers, a =>
{ {
a.Languages.Add(@event.Language.Iso2Code); a.Languages.Add(@event.Language.Iso2Code);
}); });
@ -89,7 +90,7 @@ namespace Squidex.Read.MongoDb.Apps
protected Task On(AppLanguageRemoved @event, EnvelopeHeaders headers) protected Task On(AppLanguageRemoved @event, EnvelopeHeaders headers)
{ {
return UpdateAsync(headers, a => return UpdateAsync(@event, headers, a =>
{ {
a.Languages.Remove(@event.Language.Iso2Code); a.Languages.Remove(@event.Language.Iso2Code);
}); });
@ -97,15 +98,15 @@ namespace Squidex.Read.MongoDb.Apps
protected Task On(AppMasterLanguageSet @event, EnvelopeHeaders headers) protected Task On(AppMasterLanguageSet @event, EnvelopeHeaders headers)
{ {
return UpdateAsync(headers, a => return UpdateAsync(@event, headers, a =>
{ {
a.MasterLanguage = @event.Language.Iso2Code; a.MasterLanguage = @event.Language.Iso2Code;
}); });
} }
public async Task UpdateAsync(EnvelopeHeaders headers, Action<MongoAppEntity> updater) public async Task UpdateAsync(SquidexEvent @event, EnvelopeHeaders headers, Action<MongoAppEntity> updater)
{ {
await Collection.UpdateAsync(headers, updater); await Collection.UpdateAsync(@event, headers, updater);
AppSaved?.Invoke(headers.AggregateId()); AppSaved?.Invoke(headers.AggregateId());
} }

25
src/Squidex.Read.MongoDb/Contents/MongoContentRepository_EventHandling.cs

@ -10,7 +10,6 @@ using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using MongoDB.Bson; using MongoDB.Bson;
using MongoDB.Driver; using MongoDB.Driver;
using Squidex.Events;
using Squidex.Events.Contents; using Squidex.Events.Contents;
using Squidex.Events.Schemas; using Squidex.Events.Schemas;
using Squidex.Infrastructure.CQRS; using Squidex.Infrastructure.CQRS;
@ -59,7 +58,7 @@ namespace Squidex.Read.MongoDb.Contents
protected Task On(SchemaCreated @event, EnvelopeHeaders headers) protected Task On(SchemaCreated @event, EnvelopeHeaders headers)
{ {
return ForSchemaIdAsync(headers.AggregateId(), async collection => return ForSchemaIdAsync(@event.SchemaId.Id, async collection =>
{ {
await collection.Indexes.CreateOneAsync(IndexKeys.Ascending(x => x.IsPublished)); await collection.Indexes.CreateOneAsync(IndexKeys.Ascending(x => x.IsPublished));
await collection.Indexes.CreateOneAsync(IndexKeys.Text(x => x.Text)); await collection.Indexes.CreateOneAsync(IndexKeys.Text(x => x.Text));
@ -68,9 +67,9 @@ namespace Squidex.Read.MongoDb.Contents
protected Task On(ContentCreated @event, EnvelopeHeaders headers) protected Task On(ContentCreated @event, EnvelopeHeaders headers)
{ {
return ForSchemaAsync(headers.SchemaId(), (collection, schema) => return ForSchemaAsync(@event.SchemaId.Id, (collection, schema) =>
{ {
return collection.CreateAsync(headers, x => return collection.CreateAsync(@event, headers, x =>
{ {
SimpleMapper.Map(@event, x); SimpleMapper.Map(@event, x);
@ -81,9 +80,9 @@ namespace Squidex.Read.MongoDb.Contents
protected Task On(ContentUpdated @event, EnvelopeHeaders headers) protected Task On(ContentUpdated @event, EnvelopeHeaders headers)
{ {
return ForSchemaAsync(headers.SchemaId(), (collection, schema) => return ForSchemaAsync(@event.SchemaId.Id, (collection, schema) =>
{ {
return collection.UpdateAsync(headers, x => return collection.UpdateAsync(@event, headers, x =>
{ {
x.SetData(schema, @event.Data); x.SetData(schema, @event.Data);
}); });
@ -92,9 +91,9 @@ namespace Squidex.Read.MongoDb.Contents
protected Task On(ContentPublished @event, EnvelopeHeaders headers) protected Task On(ContentPublished @event, EnvelopeHeaders headers)
{ {
return ForSchemaIdAsync(headers.SchemaId(), collection => return ForSchemaIdAsync(@event.SchemaId.Id, collection =>
{ {
return collection.UpdateAsync(headers, x => return collection.UpdateAsync(@event, headers, x =>
{ {
x.IsPublished = true; x.IsPublished = true;
}); });
@ -103,9 +102,9 @@ namespace Squidex.Read.MongoDb.Contents
protected Task On(ContentUnpublished @event, EnvelopeHeaders headers) protected Task On(ContentUnpublished @event, EnvelopeHeaders headers)
{ {
return ForSchemaIdAsync(headers.SchemaId(), collection => return ForSchemaIdAsync(@event.SchemaId.Id, collection =>
{ {
return collection.UpdateAsync(headers, x => return collection.UpdateAsync(@event, headers, x =>
{ {
x.IsPublished = false; x.IsPublished = false;
}); });
@ -114,9 +113,9 @@ namespace Squidex.Read.MongoDb.Contents
protected Task On(ContentDeleted @event, EnvelopeHeaders headers) protected Task On(ContentDeleted @event, EnvelopeHeaders headers)
{ {
return ForSchemaIdAsync(headers.SchemaId(), collection => return ForSchemaIdAsync(@event.SchemaId.Id, collection =>
{ {
return collection.UpdateAsync(headers, x => return collection.UpdateAsync(@event, headers, x =>
{ {
x.IsDeleted = true; x.IsDeleted = true;
}); });
@ -125,7 +124,7 @@ namespace Squidex.Read.MongoDb.Contents
protected Task On(FieldDeleted @event, EnvelopeHeaders headers) protected Task On(FieldDeleted @event, EnvelopeHeaders headers)
{ {
return ForSchemaIdAsync(headers.SchemaId(), collection => return ForSchemaIdAsync(@event.SchemaId.Id, collection =>
{ {
return collection.UpdateManyAsync(new BsonDocument(), Update.Unset(new StringFieldDefinition<MongoContentEntity>($"Data.{@event.FieldId}"))); return collection.UpdateManyAsync(new BsonDocument(), Update.Unset(new StringFieldDefinition<MongoContentEntity>($"Data.{@event.FieldId}")));
}); });

15
src/Squidex.Read.MongoDb/History/MongoHistoryEventRepository.cs

@ -12,6 +12,7 @@ using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using MongoDB.Driver; using MongoDB.Driver;
using Squidex.Events;
using Squidex.Infrastructure.CQRS; using Squidex.Infrastructure.CQRS;
using Squidex.Infrastructure.CQRS.Events; using Squidex.Infrastructure.CQRS.Events;
using Squidex.Infrastructure.MongoDb; using Squidex.Infrastructure.MongoDb;
@ -80,15 +81,17 @@ namespace Squidex.Read.MongoDb.History
if (message != null) if (message != null)
{ {
await Collection.CreateAsync(@event.Headers, x => await Collection.CreateAsync((SquidexEvent)@event.Payload, @event.Headers, entity =>
{ {
x.SessionEventIndex = Interlocked.Increment(ref sessionEventCount); entity.Id = Guid.NewGuid();
x.Channel = message.Channel; entity.SessionEventIndex = Interlocked.Increment(ref sessionEventCount);
x.Message = message.Message;
x.Parameters = message.Parameters.ToDictionary(p => p.Key, p => p.Value); entity.Channel = message.Channel;
}, false); entity.Message = message.Message;
entity.Parameters = message.Parameters.ToDictionary(p => p.Key, p => p.Value);
});
} }
} }
} }

29
src/Squidex.Read.MongoDb/Schemas/MongoSchemaRepository_EventHandling.cs

@ -9,6 +9,7 @@
using System; using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using Squidex.Core.Schemas; using Squidex.Core.Schemas;
using Squidex.Events;
using Squidex.Events.Schemas; using Squidex.Events.Schemas;
using Squidex.Events.Schemas.Utils; using Squidex.Events.Schemas.Utils;
using Squidex.Infrastructure.CQRS; using Squidex.Infrastructure.CQRS;
@ -32,71 +33,71 @@ namespace Squidex.Read.MongoDb.Schemas
{ {
var schema = SchemaEventDispatcher.Dispatch(@event); var schema = SchemaEventDispatcher.Dispatch(@event);
await Collection.CreateAsync(headers, s => { UpdateSchema(s, schema); SimpleMapper.Map(@event, s); }); await Collection.CreateAsync(@event, headers, s => { UpdateSchema(s, schema); SimpleMapper.Map(@event, s); });
SchemaSaved?.Invoke(headers.AggregateId()); SchemaSaved?.Invoke(headers.AggregateId());
} }
protected Task On(FieldDeleted @event, EnvelopeHeaders headers) protected Task On(FieldDeleted @event, EnvelopeHeaders headers)
{ {
return UpdateSchema(headers, s => SchemaEventDispatcher.Dispatch(@event, s)); return UpdateSchema(@event, headers, s => SchemaEventDispatcher.Dispatch(@event, s));
} }
protected Task On(FieldDisabled @event, EnvelopeHeaders headers) protected Task On(FieldDisabled @event, EnvelopeHeaders headers)
{ {
return UpdateSchema(headers, s => SchemaEventDispatcher.Dispatch(@event, s)); return UpdateSchema(@event, headers, s => SchemaEventDispatcher.Dispatch(@event, s));
} }
protected Task On(FieldEnabled @event, EnvelopeHeaders headers) protected Task On(FieldEnabled @event, EnvelopeHeaders headers)
{ {
return UpdateSchema(headers, s => SchemaEventDispatcher.Dispatch(@event, s)); return UpdateSchema(@event, headers, s => SchemaEventDispatcher.Dispatch(@event, s));
} }
protected Task On(FieldHidden @event, EnvelopeHeaders headers) protected Task On(FieldHidden @event, EnvelopeHeaders headers)
{ {
return UpdateSchema(headers, s => SchemaEventDispatcher.Dispatch(@event, s)); return UpdateSchema(@event, headers, s => SchemaEventDispatcher.Dispatch(@event, s));
} }
protected Task On(FieldShown @event, EnvelopeHeaders headers) protected Task On(FieldShown @event, EnvelopeHeaders headers)
{ {
return UpdateSchema(headers, s => SchemaEventDispatcher.Dispatch(@event, s)); return UpdateSchema(@event, headers, s => SchemaEventDispatcher.Dispatch(@event, s));
} }
protected Task On(FieldUpdated @event, EnvelopeHeaders headers) protected Task On(FieldUpdated @event, EnvelopeHeaders headers)
{ {
return UpdateSchema(headers, s => SchemaEventDispatcher.Dispatch(@event, s)); return UpdateSchema(@event, headers, s => SchemaEventDispatcher.Dispatch(@event, s));
} }
protected Task On(SchemaUpdated @event, EnvelopeHeaders headers) protected Task On(SchemaUpdated @event, EnvelopeHeaders headers)
{ {
return UpdateSchema(headers, s => SchemaEventDispatcher.Dispatch(@event, s)); return UpdateSchema(@event, headers, s => SchemaEventDispatcher.Dispatch(@event, s));
} }
protected Task On(SchemaPublished @event, EnvelopeHeaders headers) protected Task On(SchemaPublished @event, EnvelopeHeaders headers)
{ {
return UpdateSchema(headers, s => SchemaEventDispatcher.Dispatch(@event, s)); return UpdateSchema(@event, headers, s => SchemaEventDispatcher.Dispatch(@event, s));
} }
protected Task On(SchemaUnpublished @event, EnvelopeHeaders headers) protected Task On(SchemaUnpublished @event, EnvelopeHeaders headers)
{ {
return UpdateSchema(headers, s => SchemaEventDispatcher.Dispatch(@event, s)); return UpdateSchema(@event, headers, s => SchemaEventDispatcher.Dispatch(@event, s));
} }
protected Task On(FieldAdded @event, EnvelopeHeaders headers) protected Task On(FieldAdded @event, EnvelopeHeaders headers)
{ {
return UpdateSchema(headers, s => SchemaEventDispatcher.Dispatch(@event, s, registry)); return UpdateSchema(@event, headers, s => SchemaEventDispatcher.Dispatch(@event, s, registry));
} }
protected async Task On(SchemaDeleted @event, EnvelopeHeaders headers) protected async Task On(SchemaDeleted @event, EnvelopeHeaders headers)
{ {
await Collection.UpdateAsync(headers, s => s.IsDeleted = true); await Collection.UpdateAsync(@event, headers, s => s.IsDeleted = true);
SchemaSaved?.Invoke(headers.AggregateId()); SchemaSaved?.Invoke(headers.AggregateId());
} }
private async Task UpdateSchema(EnvelopeHeaders headers, Func<Schema, Schema> updater) private async Task UpdateSchema(SquidexEvent @event, EnvelopeHeaders headers, Func<Schema, Schema> updater)
{ {
await Collection.UpdateAsync(headers, e => UpdateSchema(e, updater)); await Collection.UpdateAsync(@event, headers, e => UpdateSchema(e, updater));
SchemaSaved?.Invoke(headers.AggregateId()); SchemaSaved?.Invoke(headers.AggregateId());
} }

55
src/Squidex.Read.MongoDb/Utils/CollectionExtensions.cs

@ -0,0 +1,55 @@
// ==========================================================================
// CollectionExtensions.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using System;
using System.Threading.Tasks;
using MongoDB.Driver;
using Squidex.Events;
using Squidex.Infrastructure;
using Squidex.Infrastructure.CQRS;
using Squidex.Infrastructure.MongoDb;
namespace Squidex.Read.MongoDb.Utils
{
public static class CollectionExtensions
{
public static Task CreateAsync<T>(this IMongoCollection<T> collection, SquidexEvent @event, EnvelopeHeaders headers, Action<T> updater) where T : MongoEntity, new()
{
var entity = EntityMapper.Create<T>(@event, headers);
updater(entity);
return collection.InsertOneIfNotExistsAsync(entity);
}
public static async Task CreateAsync<T>(this IMongoCollection<T> collection, SquidexEvent @event, EnvelopeHeaders headers, Func<T, Task> updater) where T : MongoEntity, new()
{
var entity = EntityMapper.Create<T>(@event, headers);
await updater(entity);
await collection.InsertOneIfNotExistsAsync(entity);
}
public static async Task UpdateAsync<T>(this IMongoCollection<T> collection, SquidexEvent @event, EnvelopeHeaders headers, Action<T> updater) where T : MongoEntity, new()
{
var entity = await collection.Find(t => t.Id == headers.AggregateId()).FirstOrDefaultAsync();
if (entity == null)
{
throw new DomainObjectNotFoundException(headers.AggregateId().ToString(), typeof(T));
}
EntityMapper.Update(@event, headers, entity);
updater(entity);
await collection.ReplaceOneAsync(t => t.Id == entity.Id, entity);
}
}
}

92
src/Squidex.Read.MongoDb/Utils/EntityMapper.cs

@ -6,9 +6,6 @@
// All rights reserved. // All rights reserved.
// ========================================================================== // ==========================================================================
using System;
using System.Threading.Tasks;
using MongoDB.Driver;
using Squidex.Events; using Squidex.Events;
using Squidex.Infrastructure.CQRS; using Squidex.Infrastructure.CQRS;
using Squidex.Infrastructure.MongoDb; using Squidex.Infrastructure.MongoDb;
@ -20,109 +17,72 @@ namespace Squidex.Read.MongoDb.Utils
{ {
public static class EntityMapper public static class EntityMapper
{ {
public static T Create<T>(EnvelopeHeaders headers, bool useAggregateId = true) where T : MongoEntity, new() public static T Create<T>(SquidexEvent @event, EnvelopeHeaders headers) where T : MongoEntity, new()
{ {
var entity = new T(); var entity = new T();
UpdateWithId(headers, entity, useAggregateId); SetId(headers, entity);
UpdateWithAppId(headers, entity);
UpdateWithCreated(headers, entity);
UpdateWithCreatedBy(headers, entity);
return Update(entity, headers); SetCreated(headers, entity);
SetCreatedBy(@event, entity);
SetAppId(@event, entity);
return Update(@event, headers, entity);
} }
public static T Update<T>(T entity, EnvelopeHeaders headers) where T : MongoEntity public static T Update<T>(SquidexEvent @event, EnvelopeHeaders headers, T entity) where T : MongoEntity, new()
{ {
UpdateWithLastModified(headers, entity); SetLastModified(headers, entity);
UpdateWithLastModifiedBy(headers, entity); SetLastModifiedBy(@event, entity);
return entity; return entity;
} }
private static void UpdateWithCreated(EnvelopeHeaders headers, MongoEntity entity) private static void SetId(EnvelopeHeaders headers, MongoEntity entity)
{
entity.Id = headers.AggregateId();
}
private static void SetCreated(EnvelopeHeaders headers, MongoEntity entity)
{ {
entity.Created = headers.Timestamp().ToDateTimeUtc(); entity.Created = headers.Timestamp().ToDateTimeUtc();
} }
private static void UpdateWithLastModified(EnvelopeHeaders headers, MongoEntity entity) private static void SetLastModified(EnvelopeHeaders headers, MongoEntity entity)
{ {
entity.LastModified = headers.Timestamp().ToDateTimeUtc(); entity.LastModified = headers.Timestamp().ToDateTimeUtc();
} }
private static void UpdateWithCreatedBy(EnvelopeHeaders headers, MongoEntity entity) private static void SetCreatedBy(SquidexEvent @event, MongoEntity entity)
{ {
var createdBy = entity as ITrackCreatedByEntity; var createdBy = entity as ITrackCreatedByEntity;
if (createdBy != null) if (createdBy != null)
{ {
createdBy.CreatedBy = headers.Actor(); createdBy.CreatedBy = @event.Actor;
} }
} }
private static void UpdateWithLastModifiedBy(EnvelopeHeaders headers, MongoEntity entity) private static void SetLastModifiedBy(SquidexEvent @event, MongoEntity entity)
{ {
var modifiedBy = entity as ITrackLastModifiedByEntity; var modifiedBy = entity as ITrackLastModifiedByEntity;
if (modifiedBy != null) if (modifiedBy != null)
{ {
modifiedBy.LastModifiedBy = headers.Actor(); modifiedBy.LastModifiedBy = @event.Actor;
} }
} }
private static void UpdateWithAppId(EnvelopeHeaders headers, MongoEntity entity) private static void SetAppId(SquidexEvent @event, MongoEntity entity)
{ {
var appEntity = entity as IAppRefEntity; var appEntity = entity as IAppRefEntity;
var appEvent = @event as AppEvent;
if (appEntity != null) if (appEntity != null && appEvent != null)
{
appEntity.AppId = headers.AppId();
}
}
private static void UpdateWithId(EnvelopeHeaders headers, MongoEntity entity, bool useAggregateId)
{
if (useAggregateId)
{
entity.Id = headers.AggregateId();
}
else
{
entity.Id = Guid.NewGuid();
}
}
public static Task CreateAsync<T>(this IMongoCollection<T> collection, EnvelopeHeaders headers, Action<T> updater, bool useAggregateId = true) where T : MongoEntity, new()
{
var entity = Create<T>(headers, useAggregateId);
updater(entity);
return collection.InsertOneIfNotExistsAsync(entity);
}
public static async Task CreateAsync<T>(this IMongoCollection<T> collection, EnvelopeHeaders headers, Func<T, Task> updater, bool useAggregateId = true) where T : MongoEntity, new()
{
var entity = Create<T>(headers, useAggregateId);
await updater(entity);
await collection.InsertOneIfNotExistsAsync(entity);
}
public static async Task UpdateAsync<T>(this IMongoCollection<T> collection, EnvelopeHeaders headers, Action<T> updater) where T : MongoEntity
{
var entity = await collection.Find(t => t.Id == headers.AggregateId()).FirstOrDefaultAsync();
if (entity == null)
{ {
return; appEntity.AppId = appEvent.AppId.Id;
} }
Update(entity, headers);
updater(entity);
await collection.ReplaceOneAsync(t => t.Id == entity.Id, entity);
} }
} }
} }

52
src/Squidex.Read/Schemas/SchemaHistoryEventsCreator.cs

@ -7,12 +7,12 @@
// ========================================================================== // ==========================================================================
using System.Threading.Tasks; using System.Threading.Tasks;
using Squidex.Events;
using Squidex.Events.Schemas; using Squidex.Events.Schemas;
using Squidex.Infrastructure; using Squidex.Infrastructure;
using Squidex.Infrastructure.CQRS; using Squidex.Infrastructure.CQRS;
using Squidex.Infrastructure.CQRS.Events; using Squidex.Infrastructure.CQRS.Events;
using Squidex.Read.History; using Squidex.Read.History;
using Squidex.Read.Schemas.Services;
// ReSharper disable InvertIf // ReSharper disable InvertIf
@ -20,15 +20,9 @@ namespace Squidex.Read.Schemas
{ {
public sealed class SchemaHistoryEventsCreator : HistoryEventsCreatorBase public sealed class SchemaHistoryEventsCreator : HistoryEventsCreatorBase
{ {
private readonly ISchemaProvider schemaProvider; public SchemaHistoryEventsCreator(TypeNameRegistry typeNameRegistry)
public SchemaHistoryEventsCreator(TypeNameRegistry typeNameRegistry, ISchemaProvider schemaProvider)
: base(typeNameRegistry) : base(typeNameRegistry)
{ {
Guard.NotNull(schemaProvider, nameof(schemaProvider));
this.schemaProvider = schemaProvider;
AddEventMessage<SchemaCreated>( AddEventMessage<SchemaCreated>(
"created schema {[Name]}"); "created schema {[Name]}");
@ -69,45 +63,27 @@ namespace Squidex.Read.Schemas
"deleted field {[Field]} of schema {[Name]}"); "deleted field {[Field]} of schema {[Name]}");
} }
protected override async Task<HistoryEventToStore> CreateEventCoreAsync(Envelope<IEvent> @event) protected override Task<HistoryEventToStore> CreateEventCoreAsync(Envelope<IEvent> @event)
{ {
var schemaCreated = @event.Payload as SchemaCreated; var schemaEvent = @event.Payload as SchemaEvent;
if (schemaCreated != null) if (schemaEvent == null)
{ {
string channel = $"schemas.{schemaCreated.Name}"; return Task.FromResult<HistoryEventToStore>(null);
return ForEvent(@event.Payload, channel).AddParameter("Name", schemaCreated.Name);
} }
else
{
var schemaEntity = await schemaProvider.FindSchemaByIdAsync(@event.Headers.AggregateId());
var schemaName = schemaEntity.Label ?? schemaEntity.Name;
string channel = $"schemas.{schemaName}"; string channel = $"schemas.{schemaEvent.SchemaId.Name}";
var result = ForEvent(@event.Payload, channel).AddParameter("Name", schemaName); var result = ForEvent(@event.Payload, channel).AddParameter("Name", schemaEvent.SchemaId.Name);
var fieldAdded = @event.Payload as FieldAdded; var fieldEvent = schemaEvent as FieldEvent;
if (fieldAdded != null) if (fieldEvent != null)
{ {
result.AddParameter("Field", fieldAdded.Name); result.AddParameter("Field", fieldEvent.FieldId.Name);
}
else
{
var fieldEvent = @event.Payload as FieldEvent;
if (fieldEvent != null)
{
var fieldName = schemaEntity.Schema.Fields.GetOrDefault(fieldEvent.FieldId)?.Name;
result.AddParameter("Field", fieldName);
}
}
return result;
} }
return Task.FromResult(result);
} }
} }
} }

14
src/Squidex.Write/AppAggregateCommand.cs

@ -7,21 +7,15 @@
// ========================================================================== // ==========================================================================
using System; using System;
using Squidex.Infrastructure.CQRS.Commands;
namespace Squidex.Write namespace Squidex.Write
{ {
public class AppAggregateCommand : SquidexCommand, IAppCommand public class AppAggregateCommand : AppCommand, IAggregateCommand
{ {
Guid IAppCommand.AppId Guid IAggregateCommand.AggregateId
{ {
get get { return AppId.Id; }
{
return AggregateId;
}
set
{
AggregateId = value;
}
} }
} }
} }

5
src/Squidex.Write/AppCommand.cs

@ -7,11 +7,12 @@
// ========================================================================== // ==========================================================================
using System; using System;
using Squidex.Infrastructure;
namespace Squidex.Write namespace Squidex.Write
{ {
public abstract class AppCommand : SquidexCommand, IAppCommand public abstract class AppCommand : SquidexCommand
{ {
public Guid AppId { get; set; } public NamedId<Guid> AppId { get; set; }
} }
} }

22
src/Squidex.Write/Apps/AppDomainObject.cs

@ -101,11 +101,13 @@ namespace Squidex.Write.Apps
ThrowIfCreated(); ThrowIfCreated();
RaiseEvent(SimpleMapper.Map(command, new AppCreated())); var appId = new NamedId<Guid>(command.AggregateId, command.Name);
RaiseEvent(CreateInitialOwner(command)); RaiseEvent(SimpleMapper.Map(command, new AppCreated { AppId = appId }));
RaiseEvent(CreateInitialLanguage());
RaiseEvent(CreateInitialMasterLanguage()); RaiseEvent(SimpleMapper.Map(command, CreateInitialOwner(appId, command)));
RaiseEvent(SimpleMapper.Map(command, CreateInitialLanguage(appId)));
RaiseEvent(SimpleMapper.Map(command, CreateInitialMasterLanguage(appId)));
return this; return this;
} }
@ -198,19 +200,19 @@ namespace Squidex.Write.Apps
return this; return this;
} }
private static AppLanguageAdded CreateInitialLanguage() private static AppLanguageAdded CreateInitialLanguage(NamedId<Guid> id)
{ {
return new AppLanguageAdded { Language = DefaultLanguage }; return new AppLanguageAdded { AppId = id, Language = DefaultLanguage };
} }
private static AppMasterLanguageSet CreateInitialMasterLanguage() private static AppMasterLanguageSet CreateInitialMasterLanguage(NamedId<Guid> id)
{ {
return new AppMasterLanguageSet { Language = DefaultLanguage }; return new AppMasterLanguageSet { AppId = id, Language = DefaultLanguage };
} }
private static AppContributorAssigned CreateInitialOwner(IActorCommand command) private static AppContributorAssigned CreateInitialOwner(NamedId<Guid> id, SquidexCommand command)
{ {
return new AppContributorAssigned { ContributorId = command.Actor.Identifier, Permission = PermissionLevel.Owner }; return new AppContributorAssigned { AppId = id, ContributorId = command.Actor.Identifier, Permission = PermissionLevel.Owner };
} }
private void ThrowIfNotCreated() private void ThrowIfNotCreated()

4
src/Squidex.Write/Apps/Commands/CreateApp.cs

@ -13,11 +13,11 @@ using Squidex.Infrastructure.CQRS.Commands;
namespace Squidex.Write.Apps.Commands namespace Squidex.Write.Apps.Commands
{ {
public sealed class CreateApp : AggregateCommand, IActorCommand, IValidatable public sealed class CreateApp : SquidexCommand, IValidatable, IAggregateCommand
{ {
public string Name { get; set; } public string Name { get; set; }
public RefToken Actor { get; set; } public Guid AggregateId { get; set; }
public CreateApp() public CreateApp()
{ {

23
src/Squidex.Write/Contents/Commands/ContentCommand.cs

@ -0,0 +1,23 @@
// ==========================================================================
// ContentCommand.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using System;
using Squidex.Infrastructure.CQRS.Commands;
namespace Squidex.Write.Contents.Commands
{
public abstract class ContentCommand : SchemaCommand, IAggregateCommand
{
public Guid ContentId { get; set; }
Guid IAggregateCommand.AggregateId
{
get { return ContentId; }
}
}
}

4
src/Squidex.Write/Contents/ContentDataCommand.cs → src/Squidex.Write/Contents/Commands/ContentDataCommand.cs

@ -10,9 +10,9 @@ using System.Collections.Generic;
using Squidex.Core.Contents; using Squidex.Core.Contents;
using Squidex.Infrastructure; using Squidex.Infrastructure;
namespace Squidex.Write.Contents namespace Squidex.Write.Contents.Commands
{ {
public class ContentDataCommand : SchemaCommand, IValidatable public abstract class ContentDataCommand : ContentCommand, IValidatable
{ {
public ContentData Data { get; set; } public ContentData Data { get; set; }

6
src/Squidex.Write/Contents/Commands/CreateContent.cs

@ -6,9 +6,15 @@
// All rights reserved. // All rights reserved.
// ========================================================================== // ==========================================================================
using System;
namespace Squidex.Write.Contents.Commands namespace Squidex.Write.Contents.Commands
{ {
public class CreateContent : ContentDataCommand public class CreateContent : ContentDataCommand
{ {
public CreateContent()
{
ContentId = Guid.NewGuid();
}
} }
} }

2
src/Squidex.Write/Contents/Commands/DeleteContent.cs

@ -8,7 +8,7 @@
namespace Squidex.Write.Contents.Commands namespace Squidex.Write.Contents.Commands
{ {
public class DeleteContent : SchemaCommand public class DeleteContent : ContentCommand
{ {
} }
} }

2
src/Squidex.Write/Contents/Commands/PublishContent.cs

@ -8,7 +8,7 @@
namespace Squidex.Write.Contents.Commands namespace Squidex.Write.Contents.Commands
{ {
public class PublishContent : SchemaCommand public class PublishContent : ContentCommand
{ {
} }
} }

2
src/Squidex.Write/Contents/Commands/UnpublishContent.cs

@ -8,7 +8,7 @@
namespace Squidex.Write.Contents.Commands namespace Squidex.Write.Contents.Commands
{ {
public class UnpublishContent : SchemaCommand public class UnpublishContent : ContentCommand
{ {
} }
} }

9
src/Squidex.Write/Contents/ContentCommandHandler.cs

@ -46,7 +46,7 @@ namespace Squidex.Write.Contents
{ {
s.Create(command); s.Create(command);
context.Succeed(command.AggregateId); context.Succeed(command.ContentId);
}); });
} }
@ -88,8 +88,11 @@ namespace Squidex.Write.Contents
{ {
Guard.Valid(command, nameof(command), message); Guard.Valid(command, nameof(command), message);
var taskForApp = appProvider.FindAppByIdAsync(command.AppId); var taskForApp =
var taskForSchema = schemaProvider.FindSchemaByIdAsync(command.SchemaId); appProvider.FindAppByIdAsync(command.AppId.Id);
var taskForSchema =
schemaProvider.FindSchemaByIdAsync(command.SchemaId.Id);
await Task.WhenAll(taskForApp, taskForSchema); await Task.WhenAll(taskForApp, taskForSchema);

42
src/Squidex.Write/EnrichWithAppIdProcessor.cs

@ -1,42 +0,0 @@
// ==========================================================================
// EnrichWithAppIdProcessor.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using System.Threading.Tasks;
using Squidex.Events;
using Squidex.Infrastructure.CQRS;
using Squidex.Infrastructure.CQRS.Commands;
using Squidex.Infrastructure.CQRS.Events;
using Squidex.Infrastructure.Tasks;
using Squidex.Write.Apps;
namespace Squidex.Write
{
public sealed class EnrichWithAppIdProcessor : IEventProcessor
{
public Task ProcessEventAsync(Envelope<IEvent> @event, IAggregate aggregate, ICommand command)
{
var appDomainObject = aggregate as AppDomainObject;
if (appDomainObject != null)
{
@event.SetAppId(aggregate.Id);
}
else
{
var appCommand = command as IAppCommand;
if (appCommand != null)
{
@event.SetAppId(appCommand.AppId);
}
}
return TaskHelper.Done;
}
}
}

42
src/Squidex.Write/EnrichWithSchemaIdProcessor.cs

@ -1,42 +0,0 @@
// ==========================================================================
// EnrichWithSchemaIdProcessor.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using System.Threading.Tasks;
using Squidex.Events;
using Squidex.Infrastructure.CQRS;
using Squidex.Infrastructure.CQRS.Commands;
using Squidex.Infrastructure.CQRS.Events;
using Squidex.Infrastructure.Tasks;
using Squidex.Write.Schemas;
namespace Squidex.Write
{
public sealed class EnrichWithSchemaIdProcessor : IEventProcessor
{
public Task ProcessEventAsync(Envelope<IEvent> @event, IAggregate aggregate, ICommand command)
{
var schemaDomainObject = aggregate as SchemaDomainObject;
if (schemaDomainObject != null)
{
@event.SetSchemaId(aggregate.Id);
}
else
{
var schemaCommand = command as ISchemaCommand;
if (schemaCommand != null)
{
@event.SetSchemaId(schemaCommand.SchemaId);
}
}
return TaskHelper.Done;
}
}
}

14
src/Squidex.Write/SchemaAggregateCommand.cs

@ -7,21 +7,15 @@
// ========================================================================== // ==========================================================================
using System; using System;
using Squidex.Infrastructure.CQRS.Commands;
namespace Squidex.Write namespace Squidex.Write
{ {
public abstract class SchemaAggregateCommand : AppCommand, ISchemaCommand public abstract class SchemaAggregateCommand : SchemaCommand, IAggregateCommand
{ {
Guid ISchemaCommand.SchemaId Guid IAggregateCommand.AggregateId
{ {
get get { return AppId.Id; }
{
return AggregateId;
}
set
{
AggregateId = value;
}
} }
} }
} }

5
src/Squidex.Write/SchemaCommand.cs

@ -7,11 +7,12 @@
// ========================================================================== // ==========================================================================
using System; using System;
using Squidex.Infrastructure;
namespace Squidex.Write namespace Squidex.Write
{ {
public abstract class SchemaCommand : AppCommand, ISchemaCommand public abstract class SchemaCommand : AppCommand
{ {
public Guid SchemaId { get; set; } public NamedId<Guid> SchemaId { get; set; }
} }
} }

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

@ -12,7 +12,7 @@ using Squidex.Infrastructure;
namespace Squidex.Write.Schemas.Commands namespace Squidex.Write.Schemas.Commands
{ {
public class AddField : SchemaAggregateCommand, IValidatable public class AddField : FieldCommand, IValidatable
{ {
public string Name { get; set; } public string Name { get; set; }

12
src/Squidex.Write/Schemas/Commands/CreateSchema.cs

@ -10,10 +10,11 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using Squidex.Core.Schemas; using Squidex.Core.Schemas;
using Squidex.Infrastructure; using Squidex.Infrastructure;
using Squidex.Infrastructure.CQRS.Commands;
namespace Squidex.Write.Schemas.Commands namespace Squidex.Write.Schemas.Commands
{ {
public class CreateSchema : AppCommand, IValidatable public class CreateSchema : AppCommand, IValidatable, IAggregateCommand
{ {
private SchemaProperties properties; private SchemaProperties properties;
@ -31,9 +32,16 @@ namespace Squidex.Write.Schemas.Commands
public string Name { get; set; } public string Name { get; set; }
public Guid SchemaId { get; set; }
Guid IAggregateCommand.AggregateId
{
get { return SchemaId; }
}
public CreateSchema() public CreateSchema()
{ {
AggregateId = Guid.NewGuid(); SchemaId = Guid.NewGuid();
} }
public void Validate(IList<ValidationError> errors) public void Validate(IList<ValidationError> errors)

3
src/Squidex.Write/Schemas/Commands/DeleteField.cs

@ -8,8 +8,7 @@
namespace Squidex.Write.Schemas.Commands namespace Squidex.Write.Schemas.Commands
{ {
public class DeleteField : SchemaAggregateCommand public class DeleteField : FieldCommand
{ {
public long FieldId { get; set; }
} }
} }

3
src/Squidex.Write/Schemas/Commands/DisableField.cs

@ -8,8 +8,7 @@
namespace Squidex.Write.Schemas.Commands namespace Squidex.Write.Schemas.Commands
{ {
public class DisableField : SchemaAggregateCommand public class DisableField : FieldCommand
{ {
public long FieldId { get; set; }
} }
} }

3
src/Squidex.Write/Schemas/Commands/EnableField.cs

@ -8,8 +8,7 @@
namespace Squidex.Write.Schemas.Commands namespace Squidex.Write.Schemas.Commands
{ {
public class EnableField : SchemaAggregateCommand public class EnableField : FieldCommand
{ {
public long FieldId { get; set; }
} }
} }

8
src/Squidex.Infrastructure/CQRS/Commands/IActorCommand.cs → src/Squidex.Write/Schemas/Commands/FieldCommand.cs

@ -1,15 +1,15 @@
// ========================================================================== // ==========================================================================
// IActorCommand.cs // FieldCommand.cs
// Squidex Headless CMS // Squidex Headless CMS
// ========================================================================== // ==========================================================================
// Copyright (c) Squidex Group // Copyright (c) Squidex Group
// All rights reserved. // All rights reserved.
// ========================================================================== // ==========================================================================
namespace Squidex.Infrastructure.CQRS.Commands namespace Squidex.Write.Schemas.Commands
{ {
public interface IActorCommand : ICommand public class FieldCommand : SchemaAggregateCommand
{ {
RefToken Actor { get; set; } public long FieldId { get; set; }
} }
} }

3
src/Squidex.Write/Schemas/Commands/HideField.cs

@ -8,8 +8,7 @@
namespace Squidex.Write.Schemas.Commands namespace Squidex.Write.Schemas.Commands
{ {
public class HideField : SchemaAggregateCommand public class HideField : FieldCommand
{ {
public long FieldId { get; set; }
} }
} }

3
src/Squidex.Write/Schemas/Commands/ShowField.cs

@ -8,8 +8,7 @@
namespace Squidex.Write.Schemas.Commands namespace Squidex.Write.Schemas.Commands
{ {
public class ShowField : SchemaAggregateCommand public class ShowField : FieldCommand
{ {
public long FieldId { get; set; }
} }
} }

4
src/Squidex.Write/Schemas/Commands/UpdateField.cs

@ -12,10 +12,8 @@ using Squidex.Infrastructure;
namespace Squidex.Write.Schemas.Commands namespace Squidex.Write.Schemas.Commands
{ {
public class UpdateField : SchemaAggregateCommand, IValidatable public class UpdateField : FieldCommand, IValidatable
{ {
public long FieldId { get; set; }
public FieldProperties Properties { get; set; } public FieldProperties Properties { get; set; }
public void Validate(IList<ValidationError> errors) public void Validate(IList<ValidationError> errors)

2
src/Squidex.Write/Schemas/SchemaCommandHandler.cs

@ -32,7 +32,7 @@ namespace Squidex.Write.Schemas
protected async Task On(CreateSchema command, CommandContext context) protected async Task On(CreateSchema command, CommandContext context)
{ {
if (await schemas.FindSchemaByNameAsync(command.AppId, command.Name) != null) if (await schemas.FindSchemaByNameAsync(command.AppId.Id, command.Name) != null)
{ {
var error = var error =
new ValidationError($"A schema with name '{command.Name}' already exists", "DisplayName", new ValidationError($"A schema with name '{command.Name}' already exists", "DisplayName",

30
src/Squidex.Write/Schemas/SchemaDomainObject.cs

@ -112,7 +112,7 @@ namespace Squidex.Write.Schemas
VerifyCreatedAndNotDeleted(); VerifyCreatedAndNotDeleted();
RaiseEvent(SimpleMapper.Map(command, new FieldAdded { FieldId = ++totalFields })); RaiseEvent(SimpleMapper.Map(command, new FieldAdded { FieldId = new NamedId<long>(++totalFields, command.Name) }));
return this; return this;
} }
@ -123,7 +123,7 @@ namespace Squidex.Write.Schemas
VerifyCreatedAndNotDeleted(); VerifyCreatedAndNotDeleted();
RaiseEvent(SimpleMapper.Map(command, new FieldUpdated())); RaiseEvent(command, SimpleMapper.Map(command, new FieldUpdated()));
return this; return this;
} }
@ -156,7 +156,7 @@ namespace Squidex.Write.Schemas
VerifyCreatedAndNotDeleted(); VerifyCreatedAndNotDeleted();
RaiseEvent(new FieldHidden { FieldId = command.FieldId }); RaiseEvent(command, new FieldHidden());
return this; return this;
} }
@ -167,7 +167,7 @@ namespace Squidex.Write.Schemas
VerifyCreatedAndNotDeleted(); VerifyCreatedAndNotDeleted();
RaiseEvent(new FieldShown { FieldId = command.FieldId }); RaiseEvent(command, new FieldShown());
return this; return this;
} }
@ -178,7 +178,7 @@ namespace Squidex.Write.Schemas
VerifyCreatedAndNotDeleted(); VerifyCreatedAndNotDeleted();
RaiseEvent(new FieldDisabled { FieldId = command.FieldId }); RaiseEvent(command, new FieldDisabled());
return this; return this;
} }
@ -189,7 +189,7 @@ namespace Squidex.Write.Schemas
VerifyCreatedAndNotDeleted(); VerifyCreatedAndNotDeleted();
RaiseEvent(new FieldEnabled { FieldId = command.FieldId }); RaiseEvent(command, new FieldEnabled());
return this; return this;
} }
@ -200,7 +200,7 @@ namespace Squidex.Write.Schemas
VerifyCreatedAndNotDeleted(); VerifyCreatedAndNotDeleted();
RaiseEvent(new FieldDeleted { FieldId = command.FieldId }); RaiseEvent(command, new FieldDeleted());
return this; return this;
} }
@ -236,6 +236,22 @@ namespace Squidex.Write.Schemas
return this; return this;
} }
protected void RaiseEvent(FieldCommand fieldCommand, FieldEvent @event)
{
Field field;
if (schema.Fields.TryGetValue(fieldCommand.FieldId, out field))
{
@event.FieldId = new NamedId<long>(field.Id, field.Name);
}
else
{
throw new DomainObjectNotFoundException(fieldCommand.FieldId.ToString(), "Fields", typeof(Field));
}
RaiseEvent(@event);
}
private void VerifyNotCreated() private void VerifyNotCreated()
{ {
if (schema != null) if (schema != null)

3
src/Squidex.Write/SquidexCommand.cs

@ -7,11 +7,10 @@
// ========================================================================== // ==========================================================================
using Squidex.Infrastructure; using Squidex.Infrastructure;
using Squidex.Infrastructure.CQRS.Commands;
namespace Squidex.Write namespace Squidex.Write
{ {
public abstract class SquidexCommand : AggregateCommand, IActorCommand public abstract class SquidexCommand
{ {
public RefToken Actor { get; set; } public RefToken Actor { get; set; }
} }

6
src/Squidex/Config/Domain/ClusterModule.cs

@ -46,7 +46,7 @@ namespace Squidex.Config.Domain
throw new ConfigurationException("You must specify the clusterer type in the 'squidex:clusterer:type' configuration section."); throw new ConfigurationException("You must specify the clusterer type in the 'squidex:clusterer:type' configuration section.");
} }
if (string.Equals(clustererType, "Slack", StringComparison.OrdinalIgnoreCase)) if (string.Equals(clustererType, "Redis", StringComparison.OrdinalIgnoreCase))
{ {
var connectionString = Configuration.GetValue<string>("squidex:clusterer:redis:connectionString"); var connectionString = Configuration.GetValue<string>("squidex:clusterer:redis:connectionString");
@ -78,9 +78,9 @@ namespace Squidex.Config.Domain
.As<IMemoryCache>() .As<IMemoryCache>()
.SingleInstance(); .SingleInstance();
} }
else else if (!string.Equals(clustererType, "None", StringComparison.OrdinalIgnoreCase))
{ {
throw new ConfigurationException($"Unsupported clusterer type '{clustererType}' for key 'squidex:clusterer:type', supported: Redis."); throw new ConfigurationException($"Unsupported clusterer type '{clustererType}' for key 'squidex:clusterer:type', supported: Redis, None.");
} }
} }
} }

4
src/Squidex/Config/Domain/InfrastructureModule.cs

@ -64,10 +64,6 @@ namespace Squidex.Config.Domain
.AsSelf() .AsSelf()
.SingleInstance(); .SingleInstance();
builder.RegisterType<EventReceiver>()
.AsSelf()
.SingleInstance();
builder.RegisterType<SchemaJsonSerializer>() builder.RegisterType<SchemaJsonSerializer>()
.AsSelf() .AsSelf()
.SingleInstance(); .SingleInstance();

10
src/Squidex/Config/Domain/Serializers.cs

@ -23,13 +23,21 @@ namespace Squidex.Config.Domain
private static JsonSerializerSettings ConfigureJson(JsonSerializerSettings settings, TypeNameHandling typeNameHandling) private static JsonSerializerSettings ConfigureJson(JsonSerializerSettings settings, TypeNameHandling typeNameHandling)
{ {
settings.SerializationBinder = new TypeNameSerializationBinder(typeNameRegistry); settings.SerializationBinder = new TypeNameSerializationBinder(typeNameRegistry);
settings.ContractResolver = new CamelCasePropertyNamesContractResolver(); settings.ContractResolver = new CamelCasePropertyNamesContractResolver();
settings.Converters.Add(new NamedGuidIdConverter());
settings.Converters.Add(new NamedLongIdConverter());
settings.Converters.Add(new NamedStringIdConverter());
settings.Converters.Add(new LanguageConverter()); settings.Converters.Add(new LanguageConverter());
settings.Converters.Add(new PropertiesBagConverter()); settings.Converters.Add(new PropertiesBagConverter());
settings.Converters.Add(new RefTokenConverter()); settings.Converters.Add(new RefTokenConverter());
settings.NullValueHandling = NullValueHandling.Ignore; settings.NullValueHandling = NullValueHandling.Ignore;
settings.DateFormatHandling = DateFormatHandling.IsoDateFormat; settings.DateFormatHandling = DateFormatHandling.IsoDateFormat;
settings.DateParseHandling = DateParseHandling.DateTime; settings.DateParseHandling = DateParseHandling.DateTime;
settings.TypeNameHandling = typeNameHandling; settings.TypeNameHandling = typeNameHandling;
return settings; return settings;
@ -37,7 +45,7 @@ namespace Squidex.Config.Domain
static Serializers() static Serializers()
{ {
typeNameRegistry.Map(typeof(EventExtensions).GetTypeInfo().Assembly); typeNameRegistry.Map(typeof(SquidexEvent).GetTypeInfo().Assembly);
} }
private static JsonSerializerSettings CreateSettings() private static JsonSerializerSettings CreateSettings()

14
src/Squidex/Config/Domain/StoreMongoDbModule.cs

@ -96,7 +96,6 @@ namespace Squidex.Config.Domain
builder.RegisterType<MongoContentRepository>() builder.RegisterType<MongoContentRepository>()
.WithParameter(ResolvedParameter.ForNamed<IMongoDatabase>(MongoDatabaseName)) .WithParameter(ResolvedParameter.ForNamed<IMongoDatabase>(MongoDatabaseName))
.As<IContentRepository>() .As<IContentRepository>()
.As<IExternalSystem>()
.AsSelf() .AsSelf()
.SingleInstance(); .SingleInstance();
@ -120,7 +119,14 @@ namespace Squidex.Config.Domain
.As<IExternalSystem>() .As<IExternalSystem>()
.AsSelf() .AsSelf()
.SingleInstance(); .SingleInstance();
builder.Register(c =>
new MongoDbConsumerWrapper(
c.ResolveNamed<IMongoDatabase>(MongoDatabaseName),
c.Resolve<MongoAppRepository>()))
.As<IEventCatchConsumer>()
.SingleInstance();
/*
builder.Register(c => builder.Register(c =>
new MongoDbConsumerWrapper( new MongoDbConsumerWrapper(
c.ResolveNamed<IMongoDatabase>(MongoDatabaseName), c.ResolveNamed<IMongoDatabase>(MongoDatabaseName),
@ -138,9 +144,9 @@ namespace Squidex.Config.Domain
builder.Register(c => builder.Register(c =>
new MongoDbConsumerWrapper( new MongoDbConsumerWrapper(
c.ResolveNamed<IMongoDatabase>(MongoDatabaseName), c.ResolveNamed<IMongoDatabase>(MongoDatabaseName),
c.Resolve<MongoAppRepository>())) c.Resolve<MongoHistoryEventRepository>()))
.As<IEventCatchConsumer>() .As<IEventCatchConsumer>()
.SingleInstance(); .SingleInstance();*/
} }
} }
} }

13
src/Squidex/Config/Domain/WriteModule.cs

@ -12,7 +12,6 @@ using Squidex.Core.Schemas;
using Squidex.Infrastructure.CQRS.Commands; using Squidex.Infrastructure.CQRS.Commands;
using Squidex.Infrastructure.CQRS.Events; using Squidex.Infrastructure.CQRS.Events;
using Squidex.Pipeline.CommandHandlers; using Squidex.Pipeline.CommandHandlers;
using Squidex.Write;
using Squidex.Write.Apps; using Squidex.Write.Apps;
using Squidex.Write.Contents; using Squidex.Write.Contents;
using Squidex.Write.Schemas; using Squidex.Write.Schemas;
@ -47,22 +46,10 @@ namespace Squidex.Config.Domain
.SingleInstance(); .SingleInstance();
builder.RegisterType<EnrichWithAppIdProcessor>()
.As<IEventProcessor>()
.SingleInstance();
builder.RegisterType<EnrichWithSchemaIdProcessor>()
.As<IEventProcessor>()
.SingleInstance();
builder.RegisterType<EnrichWithAggregateIdProcessor>() builder.RegisterType<EnrichWithAggregateIdProcessor>()
.As<IEventProcessor>() .As<IEventProcessor>()
.SingleInstance(); .SingleInstance();
builder.RegisterType<EnrichWithActorProcessor>()
.As<IEventProcessor>()
.SingleInstance();
builder.RegisterType<ClientKeyGenerator>() builder.RegisterType<ClientKeyGenerator>()
.AsSelf() .AsSelf()

3
src/Squidex/Controllers/Api/Schemas/SchemasController.cs

@ -6,7 +6,6 @@
// All rights reserved. // All rights reserved.
// ========================================================================== // ==========================================================================
using System;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
@ -100,7 +99,7 @@ namespace Squidex.Controllers.Api.Schemas
[ProducesResponseType(typeof(ErrorDto), 409)] [ProducesResponseType(typeof(ErrorDto), 409)]
public async Task<IActionResult> PostSchema(string app, [FromBody] CreateSchemaDto request) public async Task<IActionResult> PostSchema(string app, [FromBody] CreateSchemaDto request)
{ {
var command = SimpleMapper.Map(request, new CreateSchema { AggregateId = Guid.NewGuid() }); var command = SimpleMapper.Map(request, new CreateSchema());
await CommandBus.PublishAsync(command); await CommandBus.PublishAsync(command);

12
src/Squidex/Controllers/ContentApi/ContentsController.cs

@ -111,7 +111,7 @@ namespace Squidex.Controllers.ContentApi
[Route("content/{app}/{name}/")] [Route("content/{app}/{name}/")]
public async Task<IActionResult> PostContent([FromBody] ContentData request) public async Task<IActionResult> PostContent([FromBody] ContentData request)
{ {
var command = new CreateContent { Data = request, AggregateId = Guid.NewGuid() }; var command = new CreateContent { Data = request, ContentId = Guid.NewGuid() };
var context = await CommandBus.PublishAsync(command); var context = await CommandBus.PublishAsync(command);
var result = context.Result<Guid>(); var result = context.Result<Guid>();
@ -123,7 +123,7 @@ namespace Squidex.Controllers.ContentApi
[Route("content/{app}/{name}/{id}")] [Route("content/{app}/{name}/{id}")]
public async Task<IActionResult> PutContent(Guid id, [FromBody] ContentData request) public async Task<IActionResult> PutContent(Guid id, [FromBody] ContentData request)
{ {
var command = new UpdateContent { AggregateId = id, Data = request }; var command = new UpdateContent { ContentId = id, Data = request };
await CommandBus.PublishAsync(command); await CommandBus.PublishAsync(command);
@ -134,7 +134,7 @@ namespace Squidex.Controllers.ContentApi
[Route("content/{app}/{name}/{id}")] [Route("content/{app}/{name}/{id}")]
public async Task<IActionResult> PatchContent(Guid id, [FromBody] ContentData request) public async Task<IActionResult> PatchContent(Guid id, [FromBody] ContentData request)
{ {
var command = new PatchContent { AggregateId = id, Data = request }; var command = new PatchContent { ContentId = id, Data = request };
await CommandBus.PublishAsync(command); await CommandBus.PublishAsync(command);
@ -145,7 +145,7 @@ namespace Squidex.Controllers.ContentApi
[Route("content/{app}/{name}/{id}/publish")] [Route("content/{app}/{name}/{id}/publish")]
public async Task<IActionResult> PublishContent(Guid id) public async Task<IActionResult> PublishContent(Guid id)
{ {
var command = new PublishContent { AggregateId = id }; var command = new PublishContent { ContentId = id };
await CommandBus.PublishAsync(command); await CommandBus.PublishAsync(command);
@ -156,7 +156,7 @@ namespace Squidex.Controllers.ContentApi
[Route("content/{app}/{name}/{id}/unpublish")] [Route("content/{app}/{name}/{id}/unpublish")]
public async Task<IActionResult> UnpublishContent(Guid id) public async Task<IActionResult> UnpublishContent(Guid id)
{ {
var command = new UnpublishContent { AggregateId = id }; var command = new UnpublishContent { ContentId = id };
await CommandBus.PublishAsync(command); await CommandBus.PublishAsync(command);
@ -167,7 +167,7 @@ namespace Squidex.Controllers.ContentApi
[Route("content/{app}/{name}/{id}")] [Route("content/{app}/{name}/{id}")]
public async Task<IActionResult> PutContent(Guid id) public async Task<IActionResult> PutContent(Guid id)
{ {
var command = new DeleteContent { AggregateId = id }; var command = new DeleteContent { ContentId = id };
await CommandBus.PublishAsync(command); await CommandBus.PublishAsync(command);

7
src/Squidex/Pipeline/CommandHandlers/EnrichWithActorHandler.cs

@ -12,6 +12,7 @@ using Microsoft.AspNetCore.Http;
using Squidex.Infrastructure; using Squidex.Infrastructure;
using Squidex.Infrastructure.CQRS.Commands; using Squidex.Infrastructure.CQRS.Commands;
using Squidex.Infrastructure.Security; using Squidex.Infrastructure.Security;
using Squidex.Write;
// ReSharper disable InvertIf // ReSharper disable InvertIf
@ -28,9 +29,9 @@ namespace Squidex.Pipeline.CommandHandlers
public Task<bool> HandleAsync(CommandContext context) public Task<bool> HandleAsync(CommandContext context)
{ {
var subjectCommand = context.Command as IActorCommand; var squidexCommand = context.Command as SquidexCommand;
if (subjectCommand != null) if (squidexCommand != null)
{ {
var actorToken = var actorToken =
FindActorFromSubject() ?? FindActorFromSubject() ??
@ -41,7 +42,7 @@ namespace Squidex.Pipeline.CommandHandlers
throw new SecurityException("No actor with subject or client id available"); throw new SecurityException("No actor with subject or client id available");
} }
subjectCommand.Actor = actorToken; squidexCommand.Actor = actorToken;
} }
return Task.FromResult(false); return Task.FromResult(false);

5
src/Squidex/Pipeline/CommandHandlers/EnrichWithAppIdHandler.cs

@ -9,6 +9,7 @@
using System; using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Squidex.Infrastructure;
using Squidex.Infrastructure.CQRS.Commands; using Squidex.Infrastructure.CQRS.Commands;
using Squidex.Write; using Squidex.Write;
@ -27,7 +28,7 @@ namespace Squidex.Pipeline.CommandHandlers
public Task<bool> HandleAsync(CommandContext context) public Task<bool> HandleAsync(CommandContext context)
{ {
var appCommand = context.Command as IAppCommand; var appCommand = context.Command as AppCommand;
if (appCommand != null) if (appCommand != null)
{ {
@ -38,7 +39,7 @@ namespace Squidex.Pipeline.CommandHandlers
throw new InvalidOperationException("Cannot resolve app"); throw new InvalidOperationException("Cannot resolve app");
} }
appCommand.AppId = appFeature.App.Id; appCommand.AppId = new NamedId<Guid>(appFeature.App.Id, appFeature.App.Name);
} }
return Task.FromResult(false); return Task.FromResult(false);

7
src/Squidex/Pipeline/CommandHandlers/EnrichWithSchemaIdHandler.cs

@ -6,6 +6,7 @@
// All rights reserved. // All rights reserved.
// ========================================================================== // ==========================================================================
using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.Infrastructure; using Microsoft.AspNetCore.Mvc.Infrastructure;
using Squidex.Infrastructure; using Squidex.Infrastructure;
@ -32,7 +33,7 @@ namespace Squidex.Pipeline.CommandHandlers
public async Task<bool> HandleAsync(CommandContext context) public async Task<bool> HandleAsync(CommandContext context)
{ {
var schemaCommand = context.Command as ISchemaCommand; var schemaCommand = context.Command as SchemaCommand;
if (schemaCommand != null) if (schemaCommand != null)
{ {
@ -42,14 +43,14 @@ namespace Squidex.Pipeline.CommandHandlers
{ {
var schemaName = routeValues["name"].ToString(); var schemaName = routeValues["name"].ToString();
var schema = await schemaProvider.FindSchemaByNameAsync(schemaCommand.AppId, schemaName); var schema = await schemaProvider.FindSchemaByNameAsync(schemaCommand.AppId.Id, schemaName);
if (schema == null) if (schema == null)
{ {
throw new DomainObjectNotFoundException(schemaName, typeof(SchemaDomainObject)); throw new DomainObjectNotFoundException(schemaName, typeof(SchemaDomainObject));
} }
schemaCommand.SchemaId = schema.Id; schemaCommand.SchemaId = new NamedId<Guid>(schema.Id, schema.Name);
} }
} }

2
src/Squidex/appsettings.json

@ -4,7 +4,7 @@
"baseUrl": "http://localhost:5000" "baseUrl": "http://localhost:5000"
}, },
"clusterer": { "clusterer": {
"type": "redis", "type": "none",
"redis": { "redis": {
"connectionString": "redis://localhost:6379" "connectionString": "redis://localhost:6379"
} }

Loading…
Cancel
Save