Browse Source

Merge pull request #98 from SebastianStehle/feature-webhooks-matrix

Feature webhooks matrix
pull/103/head
Sebastian Stehle 9 years ago
committed by GitHub
parent
commit
5f98df2da3
  1. 1
      Squidex.sln.DotSettings
  2. 27
      src/Squidex.Domain.Apps.Core/Webhooks/WebhookSchema.cs
  3. 2
      src/Squidex.Domain.Apps.Events/Apps/AppContributorAssigned.cs
  4. 2
      src/Squidex.Domain.Apps.Events/Apps/AppContributorRemoved.cs
  5. 2
      src/Squidex.Domain.Apps.Events/Apps/AppCreated.cs
  6. 2
      src/Squidex.Domain.Apps.Events/Assets/AssetCreated.cs
  7. 2
      src/Squidex.Domain.Apps.Events/Assets/AssetRenamed.cs
  8. 2
      src/Squidex.Domain.Apps.Events/Assets/AssetUpdated.cs
  9. 2
      src/Squidex.Domain.Apps.Events/Contents/ContentCreated.cs
  10. 2
      src/Squidex.Domain.Apps.Events/Contents/ContentDeleted.cs
  11. 2
      src/Squidex.Domain.Apps.Events/Contents/ContentPublished.cs
  12. 2
      src/Squidex.Domain.Apps.Events/Contents/ContentUnpublished.cs
  13. 2
      src/Squidex.Domain.Apps.Events/Contents/ContentUpdated.cs
  14. 2
      src/Squidex.Domain.Apps.Events/Schemas/FieldAdded.cs
  15. 2
      src/Squidex.Domain.Apps.Events/Schemas/FieldDeleted.cs
  16. 2
      src/Squidex.Domain.Apps.Events/Schemas/FieldDisabled.cs
  17. 2
      src/Squidex.Domain.Apps.Events/Schemas/FieldEnabled.cs
  18. 2
      src/Squidex.Domain.Apps.Events/Schemas/FieldHidden.cs
  19. 2
      src/Squidex.Domain.Apps.Events/Schemas/FieldLocked.cs
  20. 2
      src/Squidex.Domain.Apps.Events/Schemas/FieldShown.cs
  21. 2
      src/Squidex.Domain.Apps.Events/Schemas/FieldUpdated.cs
  22. 3
      src/Squidex.Domain.Apps.Events/Schemas/Old/WebhookAdded.cs
  23. 3
      src/Squidex.Domain.Apps.Events/Schemas/Old/WebhookDeleted.cs
  24. 2
      src/Squidex.Domain.Apps.Events/Schemas/SchemaCreated.cs
  25. 2
      src/Squidex.Domain.Apps.Events/Schemas/SchemaDeleted.cs
  26. 2
      src/Squidex.Domain.Apps.Events/Schemas/SchemaFieldsReordered.cs
  27. 2
      src/Squidex.Domain.Apps.Events/Schemas/SchemaPublished.cs
  28. 2
      src/Squidex.Domain.Apps.Events/Schemas/SchemaUnpublished.cs
  29. 2
      src/Squidex.Domain.Apps.Events/Schemas/SchemaUpdated.cs
  30. 18
      src/Squidex.Domain.Apps.Events/Webhooks/WebhookCreated.cs
  31. 17
      src/Squidex.Domain.Apps.Events/Webhooks/WebhookDeleted.cs
  32. 21
      src/Squidex.Domain.Apps.Events/Webhooks/WebhookEditEvent.cs
  33. 14
      src/Squidex.Domain.Apps.Events/Webhooks/WebhookEvent.cs
  34. 17
      src/Squidex.Domain.Apps.Events/Webhooks/WebhookUpdated.cs
  35. 10
      src/Squidex.Domain.Apps.Read.MongoDb/Schemas/MongoSchemaRepository_EventHandling.cs
  36. 68
      src/Squidex.Domain.Apps.Read.MongoDb/Schemas/MongoSchemaWebhookRepository_EventHandling.cs
  37. 43
      src/Squidex.Domain.Apps.Read.MongoDb/Webhooks/MongoWebhookEntity.cs
  38. 6
      src/Squidex.Domain.Apps.Read.MongoDb/Webhooks/MongoWebhookEventEntity.cs
  39. 6
      src/Squidex.Domain.Apps.Read.MongoDb/Webhooks/MongoWebhookEventRepository.cs
  40. 49
      src/Squidex.Domain.Apps.Read.MongoDb/Webhooks/MongoWebhookRepository.cs
  41. 93
      src/Squidex.Domain.Apps.Read.MongoDb/Webhooks/MongoWebhookRepository_EventHandling.cs
  42. 8
      src/Squidex.Domain.Apps.Read/Schemas/Services/Implementations/CachingSchemaProvider.cs
  43. 89
      src/Squidex.Domain.Apps.Read/Schemas/WebhookSender.cs
  44. 14
      src/Squidex.Domain.Apps.Read/Webhooks/IWebhookEntity.cs
  45. 2
      src/Squidex.Domain.Apps.Read/Webhooks/IWebhookEventEntity.cs
  46. 2
      src/Squidex.Domain.Apps.Read/Webhooks/Repositories/IWebhookEventRepository.cs
  47. 8
      src/Squidex.Domain.Apps.Read/Webhooks/Repositories/IWebhookRepository.cs
  48. 8
      src/Squidex.Domain.Apps.Read/Webhooks/WebhookDequeuer.cs
  49. 42
      src/Squidex.Domain.Apps.Read/Webhooks/WebhookEnqueuer.cs
  50. 2
      src/Squidex.Domain.Apps.Read/Webhooks/WebhookJob.cs
  51. 2
      src/Squidex.Domain.Apps.Read/Webhooks/WebhookJobResult.cs
  52. 2
      src/Squidex.Domain.Apps.Read/Webhooks/WebhookResult.cs
  53. 100
      src/Squidex.Domain.Apps.Read/Webhooks/WebhookSender.cs
  54. 2
      src/Squidex.Domain.Apps.Write/Apps/Commands/AssignContributor.cs
  55. 2
      src/Squidex.Domain.Apps.Write/Apps/Commands/RemoveContributor.cs
  56. 2
      src/Squidex.Domain.Apps.Write/Apps/Commands/RevokeClient.cs
  57. 2
      src/Squidex.Domain.Apps.Write/Apps/Commands/UpdateClient.cs
  58. 2
      src/Squidex.Domain.Apps.Write/Assets/Commands/UpdateAsset.cs
  59. 2
      src/Squidex.Domain.Apps.Write/Contents/Commands/CreateContent.cs
  60. 2
      src/Squidex.Domain.Apps.Write/Contents/Commands/DeleteContent.cs
  61. 2
      src/Squidex.Domain.Apps.Write/Contents/Commands/PatchContent.cs
  62. 2
      src/Squidex.Domain.Apps.Write/Contents/Commands/PublishContent.cs
  63. 2
      src/Squidex.Domain.Apps.Write/Contents/Commands/UnpublishContent.cs
  64. 2
      src/Squidex.Domain.Apps.Write/Contents/Commands/UpdateContent.cs
  65. 1
      src/Squidex.Domain.Apps.Write/Contents/ContentCommandMiddleware.cs
  66. 2
      src/Squidex.Domain.Apps.Write/Schemas/Commands/AddField.cs
  67. 2
      src/Squidex.Domain.Apps.Write/Schemas/Commands/CreateSchema.cs
  68. 2
      src/Squidex.Domain.Apps.Write/Schemas/Commands/DeleteField.cs
  69. 2
      src/Squidex.Domain.Apps.Write/Schemas/Commands/DeleteSchema.cs
  70. 2
      src/Squidex.Domain.Apps.Write/Schemas/Commands/DisableField.cs
  71. 2
      src/Squidex.Domain.Apps.Write/Schemas/Commands/EnableField.cs
  72. 2
      src/Squidex.Domain.Apps.Write/Schemas/Commands/HideField.cs
  73. 2
      src/Squidex.Domain.Apps.Write/Schemas/Commands/LockField.cs
  74. 2
      src/Squidex.Domain.Apps.Write/Schemas/Commands/PublishSchema.cs
  75. 2
      src/Squidex.Domain.Apps.Write/Schemas/Commands/ReorderFields.cs
  76. 2
      src/Squidex.Domain.Apps.Write/Schemas/Commands/ShowField.cs
  77. 2
      src/Squidex.Domain.Apps.Write/Schemas/Commands/UnpublishSchema.cs
  78. 2
      src/Squidex.Domain.Apps.Write/Schemas/Commands/UpdateField.cs
  79. 2
      src/Squidex.Domain.Apps.Write/Schemas/Commands/UpdateSchema.cs
  80. 10
      src/Squidex.Domain.Apps.Write/Schemas/SchemaCommandMiddleware.cs
  81. 42
      src/Squidex.Domain.Apps.Write/Schemas/SchemaDomainObject.cs
  82. 23
      src/Squidex.Domain.Apps.Write/Webhooks/Commands/CreateWebhook.cs
  83. 7
      src/Squidex.Domain.Apps.Write/Webhooks/Commands/DeleteWebhook.cs
  84. 14
      src/Squidex.Domain.Apps.Write/Webhooks/Commands/UpdateWebhook.cs
  85. 25
      src/Squidex.Domain.Apps.Write/Webhooks/Commands/WebhookAggregateCommand.cs
  86. 23
      src/Squidex.Domain.Apps.Write/Webhooks/Commands/WebhookEditCommand.cs
  87. 77
      src/Squidex.Domain.Apps.Write/Webhooks/WebhookCommandMiddleware.cs
  88. 88
      src/Squidex.Domain.Apps.Write/Webhooks/WebhookDomainObject.cs
  89. 5
      src/Squidex.Infrastructure/CQRS/Commands/DefaultDomainObjectFactory.cs
  90. 22
      src/Squidex.Infrastructure/Http/DumpFormatter.cs
  91. 1
      src/Squidex/Config/Domain/ReadModule.cs
  92. 6
      src/Squidex/Config/Domain/StoreMongoDbModule.cs
  93. 9
      src/Squidex/Config/Domain/WriteModule.cs
  94. 2
      src/Squidex/Controllers/Api/Apps/AppsController.cs
  95. 4
      src/Squidex/Controllers/Api/Schemas/SchemaFieldsController.cs
  96. 7
      src/Squidex/Controllers/Api/Schemas/SchemasController.cs
  97. 9
      src/Squidex/Controllers/Api/Webhooks/Models/CreateWebhookDto.cs
  98. 29
      src/Squidex/Controllers/Api/Webhooks/Models/UpdateWebhookDto.cs
  99. 4
      src/Squidex/Controllers/Api/Webhooks/Models/WebhookCreatedDto.cs
  100. 35
      src/Squidex/Controllers/Api/Webhooks/Models/WebhookDto.cs

1
Squidex.sln.DotSettings

@ -20,6 +20,7 @@
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=AutoPropertyCanBeMadeGetOnly_002EGlobal/@EntryIndexedValue"></s:String> <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=AutoPropertyCanBeMadeGetOnly_002EGlobal/@EntryIndexedValue"></s:String>
<s:Boolean x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=AutoPropertyCanBeMadeGetOnly_002EGlobal/@EntryIndexRemoved">True</s:Boolean> <s:Boolean x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=AutoPropertyCanBeMadeGetOnly_002EGlobal/@EntryIndexRemoved">True</s:Boolean>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ClassNeverInstantiated_002EGlobal/@EntryIndexedValue">DO_NOT_SHOW</s:String> <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ClassNeverInstantiated_002EGlobal/@EntryIndexedValue">DO_NOT_SHOW</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=CollectionNeverUpdated_002EGlobal/@EntryIndexedValue">WARNING</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ConvertToAutoProperty/@EntryIndexedValue">DO_NOT_SHOW</s:String> <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ConvertToAutoProperty/@EntryIndexedValue">DO_NOT_SHOW</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ConvertToAutoPropertyWhenPossible/@EntryIndexedValue">DO_NOT_SHOW</s:String> <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ConvertToAutoPropertyWhenPossible/@EntryIndexedValue">DO_NOT_SHOW</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ConvertToConstant_002EGlobal/@EntryIndexedValue">DO_NOT_SHOW</s:String> <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ConvertToConstant_002EGlobal/@EntryIndexedValue">DO_NOT_SHOW</s:String>

27
src/Squidex.Domain.Apps.Core/Webhooks/WebhookSchema.cs

@ -0,0 +1,27 @@
// ==========================================================================
// WebhookSchema.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using System;
namespace Squidex.Domain.Apps.Core.Webhooks
{
public sealed class WebhookSchema
{
public Guid SchemaId { get; set; }
public bool SendCreate { get; set; }
public bool SendUpdate { get; set; }
public bool SendDelete { get; set; }
public bool SendPublish { get; set; }
public bool SendUnpublish { get; set; }
}
}

2
src/Squidex.Domain.Apps.Events/Apps/AppContributorAssigned.cs

@ -12,7 +12,7 @@ using Squidex.Infrastructure;
namespace Squidex.Domain.Apps.Events.Apps namespace Squidex.Domain.Apps.Events.Apps
{ {
[TypeName("AppContributorAssignedEvent")] [TypeName("AppContributorAssignedEvent")]
public class AppContributorAssigned : AppEvent public sealed class AppContributorAssigned : AppEvent
{ {
public string ContributorId { get; set; } public string ContributorId { get; set; }

2
src/Squidex.Domain.Apps.Events/Apps/AppContributorRemoved.cs

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

2
src/Squidex.Domain.Apps.Events/Apps/AppCreated.cs

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

2
src/Squidex.Domain.Apps.Events/Assets/AssetCreated.cs

@ -11,7 +11,7 @@ using Squidex.Infrastructure;
namespace Squidex.Domain.Apps.Events.Assets namespace Squidex.Domain.Apps.Events.Assets
{ {
[TypeName("AssetCreatedEvent")] [TypeName("AssetCreatedEvent")]
public class AssetCreated : AssetEvent public sealed class AssetCreated : AssetEvent
{ {
public string FileName { get; set; } public string FileName { get; set; }

2
src/Squidex.Domain.Apps.Events/Assets/AssetRenamed.cs

@ -11,7 +11,7 @@ using Squidex.Infrastructure;
namespace Squidex.Domain.Apps.Events.Assets namespace Squidex.Domain.Apps.Events.Assets
{ {
[TypeName("AssetRenamedEvent")] [TypeName("AssetRenamedEvent")]
public class AssetRenamed : AssetEvent public sealed class AssetRenamed : AssetEvent
{ {
public string FileName { get; set; } public string FileName { get; set; }
} }

2
src/Squidex.Domain.Apps.Events/Assets/AssetUpdated.cs

@ -11,7 +11,7 @@ using Squidex.Infrastructure;
namespace Squidex.Domain.Apps.Events.Assets namespace Squidex.Domain.Apps.Events.Assets
{ {
[TypeName("AssetUpdated")] [TypeName("AssetUpdated")]
public class AssetUpdated : AssetEvent public sealed class AssetUpdated : AssetEvent
{ {
public string MimeType { get; set; } public string MimeType { get; set; }

2
src/Squidex.Domain.Apps.Events/Contents/ContentCreated.cs

@ -12,7 +12,7 @@ using Squidex.Infrastructure;
namespace Squidex.Domain.Apps.Events.Contents namespace Squidex.Domain.Apps.Events.Contents
{ {
[TypeName("ContentCreatedEvent")] [TypeName("ContentCreatedEvent")]
public class ContentCreated : ContentEvent public sealed class ContentCreated : ContentEvent
{ {
public NamedContentData Data { get; set; } public NamedContentData Data { get; set; }
} }

2
src/Squidex.Domain.Apps.Events/Contents/ContentDeleted.cs

@ -11,7 +11,7 @@ using Squidex.Infrastructure;
namespace Squidex.Domain.Apps.Events.Contents namespace Squidex.Domain.Apps.Events.Contents
{ {
[TypeName("ContentDeletedEvent")] [TypeName("ContentDeletedEvent")]
public class ContentDeleted : ContentEvent public sealed class ContentDeleted : ContentEvent
{ {
} }
} }

2
src/Squidex.Domain.Apps.Events/Contents/ContentPublished.cs

@ -11,7 +11,7 @@ using Squidex.Infrastructure;
namespace Squidex.Domain.Apps.Events.Contents namespace Squidex.Domain.Apps.Events.Contents
{ {
[TypeName("ContentPublishedEvent")] [TypeName("ContentPublishedEvent")]
public class ContentPublished : ContentEvent public sealed class ContentPublished : ContentEvent
{ {
} }
} }

2
src/Squidex.Domain.Apps.Events/Contents/ContentUnpublished.cs

@ -11,7 +11,7 @@ using Squidex.Infrastructure;
namespace Squidex.Domain.Apps.Events.Contents namespace Squidex.Domain.Apps.Events.Contents
{ {
[TypeName("ContentUnpublishedEvent")] [TypeName("ContentUnpublishedEvent")]
public class ContentUnpublished : ContentEvent public sealed class ContentUnpublished : ContentEvent
{ {
} }
} }

2
src/Squidex.Domain.Apps.Events/Contents/ContentUpdated.cs

@ -12,7 +12,7 @@ using Squidex.Infrastructure;
namespace Squidex.Domain.Apps.Events.Contents namespace Squidex.Domain.Apps.Events.Contents
{ {
[TypeName("ContentUpdatedEvent")] [TypeName("ContentUpdatedEvent")]
public class ContentUpdated : ContentEvent public sealed class ContentUpdated : ContentEvent
{ {
public NamedContentData Data { get; set; } public NamedContentData Data { get; set; }
} }

2
src/Squidex.Domain.Apps.Events/Schemas/FieldAdded.cs

@ -12,7 +12,7 @@ using Squidex.Infrastructure;
namespace Squidex.Domain.Apps.Events.Schemas namespace Squidex.Domain.Apps.Events.Schemas
{ {
[TypeName("FieldAddedEvent")] [TypeName("FieldAddedEvent")]
public class FieldAdded : FieldEvent public sealed class FieldAdded : FieldEvent
{ {
public string Name { get; set; } public string Name { get; set; }

2
src/Squidex.Domain.Apps.Events/Schemas/FieldDeleted.cs

@ -11,7 +11,7 @@ using Squidex.Infrastructure;
namespace Squidex.Domain.Apps.Events.Schemas namespace Squidex.Domain.Apps.Events.Schemas
{ {
[TypeName("FieldDeletedEvent")] [TypeName("FieldDeletedEvent")]
public class FieldDeleted : FieldEvent public sealed class FieldDeleted : FieldEvent
{ {
} }
} }

2
src/Squidex.Domain.Apps.Events/Schemas/FieldDisabled.cs

@ -11,7 +11,7 @@ using Squidex.Infrastructure;
namespace Squidex.Domain.Apps.Events.Schemas namespace Squidex.Domain.Apps.Events.Schemas
{ {
[TypeName("FieldDisabledEvent")] [TypeName("FieldDisabledEvent")]
public class FieldDisabled : FieldEvent public sealed class FieldDisabled : FieldEvent
{ {
} }
} }

2
src/Squidex.Domain.Apps.Events/Schemas/FieldEnabled.cs

@ -11,7 +11,7 @@ using Squidex.Infrastructure;
namespace Squidex.Domain.Apps.Events.Schemas namespace Squidex.Domain.Apps.Events.Schemas
{ {
[TypeName("FieldEnabledEvent")] [TypeName("FieldEnabledEvent")]
public class FieldEnabled : FieldEvent public sealed class FieldEnabled : FieldEvent
{ {
} }
} }

2
src/Squidex.Domain.Apps.Events/Schemas/FieldHidden.cs

@ -11,7 +11,7 @@ using Squidex.Infrastructure;
namespace Squidex.Domain.Apps.Events.Schemas namespace Squidex.Domain.Apps.Events.Schemas
{ {
[TypeName("FieldHiddenEvent")] [TypeName("FieldHiddenEvent")]
public class FieldHidden : FieldEvent public sealed class FieldHidden : FieldEvent
{ {
} }
} }

2
src/Squidex.Domain.Apps.Events/Schemas/FieldLocked.cs

@ -11,7 +11,7 @@ using Squidex.Infrastructure;
namespace Squidex.Domain.Apps.Events.Schemas namespace Squidex.Domain.Apps.Events.Schemas
{ {
[TypeName("FieldLockedEvent")] [TypeName("FieldLockedEvent")]
public class FieldLocked : FieldEvent public sealed class FieldLocked : FieldEvent
{ {
} }
} }

2
src/Squidex.Domain.Apps.Events/Schemas/FieldShown.cs

@ -11,7 +11,7 @@ using Squidex.Infrastructure;
namespace Squidex.Domain.Apps.Events.Schemas namespace Squidex.Domain.Apps.Events.Schemas
{ {
[TypeName("FieldShownEvent")] [TypeName("FieldShownEvent")]
public class FieldShown : FieldEvent public sealed class FieldShown : FieldEvent
{ {
} }
} }

2
src/Squidex.Domain.Apps.Events/Schemas/FieldUpdated.cs

@ -12,7 +12,7 @@ using Squidex.Infrastructure;
namespace Squidex.Domain.Apps.Events.Schemas namespace Squidex.Domain.Apps.Events.Schemas
{ {
[TypeName("FieldUpdatedEvent")] [TypeName("FieldUpdatedEvent")]
public class FieldUpdated : FieldEvent public sealed class FieldUpdated : FieldEvent
{ {
public FieldProperties Properties { get; set; } public FieldProperties Properties { get; set; }
} }

3
src/Squidex.Domain.Apps.Events/Schemas/WebhookAdded.cs → src/Squidex.Domain.Apps.Events/Schemas/Old/WebhookAdded.cs

@ -9,9 +9,10 @@
using System; using System;
using Squidex.Infrastructure; using Squidex.Infrastructure;
namespace Squidex.Domain.Apps.Events.Schemas namespace Squidex.Domain.Apps.Events.Schemas.Old
{ {
[TypeName("WebhookAddedEvent")] [TypeName("WebhookAddedEvent")]
[Obsolete]
public sealed class WebhookAdded : SchemaEvent public sealed class WebhookAdded : SchemaEvent
{ {
public Guid Id { get; set; } public Guid Id { get; set; }

3
src/Squidex.Domain.Apps.Events/Schemas/WebhookDeleted.cs → src/Squidex.Domain.Apps.Events/Schemas/Old/WebhookDeleted.cs

@ -9,9 +9,10 @@
using System; using System;
using Squidex.Infrastructure; using Squidex.Infrastructure;
namespace Squidex.Domain.Apps.Events.Schemas namespace Squidex.Domain.Apps.Events.Schemas.Old
{ {
[TypeName("WebhookDeletedEvent")] [TypeName("WebhookDeletedEvent")]
[Obsolete]
public sealed class WebhookDeleted : SchemaEvent public sealed class WebhookDeleted : SchemaEvent
{ {
public Guid Id { get; set; } public Guid Id { get; set; }

2
src/Squidex.Domain.Apps.Events/Schemas/SchemaCreated.cs

@ -13,7 +13,7 @@ using SchemaFields = System.Collections.Generic.List<Squidex.Domain.Apps.Events.
namespace Squidex.Domain.Apps.Events.Schemas namespace Squidex.Domain.Apps.Events.Schemas
{ {
[TypeName("SchemaCreatedEvent")] [TypeName("SchemaCreatedEvent")]
public class SchemaCreated : SchemaEvent public sealed class SchemaCreated : SchemaEvent
{ {
public string Name { get; set; } public string Name { get; set; }

2
src/Squidex.Domain.Apps.Events/Schemas/SchemaDeleted.cs

@ -11,7 +11,7 @@ using Squidex.Infrastructure;
namespace Squidex.Domain.Apps.Events.Schemas namespace Squidex.Domain.Apps.Events.Schemas
{ {
[TypeName("SchemaDeletedEvent")] [TypeName("SchemaDeletedEvent")]
public class SchemaDeleted : SchemaEvent public sealed class SchemaDeleted : SchemaEvent
{ {
} }
} }

2
src/Squidex.Domain.Apps.Events/Schemas/SchemaFieldsReordered.cs

@ -12,7 +12,7 @@ using Squidex.Infrastructure;
namespace Squidex.Domain.Apps.Events.Schemas namespace Squidex.Domain.Apps.Events.Schemas
{ {
[TypeName("SchemaFieldsReorderedEvent")] [TypeName("SchemaFieldsReorderedEvent")]
public class SchemaFieldsReordered : SchemaEvent public sealed class SchemaFieldsReordered : SchemaEvent
{ {
public List<long> FieldIds { get; set; } public List<long> FieldIds { get; set; }
} }

2
src/Squidex.Domain.Apps.Events/Schemas/SchemaPublished.cs

@ -11,7 +11,7 @@ using Squidex.Infrastructure;
namespace Squidex.Domain.Apps.Events.Schemas namespace Squidex.Domain.Apps.Events.Schemas
{ {
[TypeName("SchemaPublishedEvent")] [TypeName("SchemaPublishedEvent")]
public class SchemaPublished : SchemaEvent public sealed class SchemaPublished : SchemaEvent
{ {
} }
} }

2
src/Squidex.Domain.Apps.Events/Schemas/SchemaUnpublished.cs

@ -11,7 +11,7 @@ using Squidex.Infrastructure;
namespace Squidex.Domain.Apps.Events.Schemas namespace Squidex.Domain.Apps.Events.Schemas
{ {
[TypeName("SchemaUnpublishedEvent")] [TypeName("SchemaUnpublishedEvent")]
public class SchemaUnpublished : SchemaEvent public sealed class SchemaUnpublished : SchemaEvent
{ {
} }
} }

2
src/Squidex.Domain.Apps.Events/Schemas/SchemaUpdated.cs

@ -12,7 +12,7 @@ using Squidex.Infrastructure;
namespace Squidex.Domain.Apps.Events.Schemas namespace Squidex.Domain.Apps.Events.Schemas
{ {
[TypeName("SchemaUpdatedEvent")] [TypeName("SchemaUpdatedEvent")]
public class SchemaUpdated : SchemaEvent public sealed class SchemaUpdated : SchemaEvent
{ {
public SchemaProperties Properties { get; set; } public SchemaProperties Properties { get; set; }
} }

18
src/Squidex.Domain.Apps.Events/Webhooks/WebhookCreated.cs

@ -0,0 +1,18 @@
// ==========================================================================
// WebhookCreated.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using Squidex.Infrastructure;
namespace Squidex.Domain.Apps.Events.Webhooks
{
[TypeName("WebhookCreatedEvent")]
public sealed class WebhookCreated : WebhookEditEvent
{
public string SharedSecret { get; set; }
}
}

17
src/Squidex.Domain.Apps.Events/Webhooks/WebhookDeleted.cs

@ -0,0 +1,17 @@
// ==========================================================================
// WebhookDeleted.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using Squidex.Infrastructure;
namespace Squidex.Domain.Apps.Events.Webhooks
{
[TypeName("WebhookDeletedEventV2")]
public sealed class WebhookDeleted : WebhookEvent
{
}
}

21
src/Squidex.Domain.Apps.Events/Webhooks/WebhookEditEvent.cs

@ -0,0 +1,21 @@
// ==========================================================================
// WebhookEditEvent.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using System;
using System.Collections.Generic;
using Squidex.Domain.Apps.Core.Webhooks;
namespace Squidex.Domain.Apps.Events.Webhooks
{
public abstract class WebhookEditEvent : WebhookEvent
{
public Uri Url { get; set; }
public List<WebhookSchema> Schemas { get; set; }
}
}

14
src/Squidex.Domain.Apps.Read/Schemas/ISchemaWebhookUrlEntity.cs → src/Squidex.Domain.Apps.Events/Webhooks/WebhookEvent.cs

@ -1,5 +1,5 @@
// ========================================================================== // ==========================================================================
// ISchemaWebhookUrlEntity.cs // WebhookEvent.cs
// Squidex Headless CMS // Squidex Headless CMS
// ========================================================================== // ==========================================================================
// Copyright (c) Squidex Group // Copyright (c) Squidex Group
@ -8,14 +8,10 @@
using System; using System;
namespace Squidex.Domain.Apps.Read.Schemas namespace Squidex.Domain.Apps.Events.Webhooks
{ {
public interface ISchemaWebhookUrlEntity public abstract class WebhookEvent : AppEvent
{ {
Guid Id { get; } public Guid WebhookId { get; set; }
Uri Url { get; }
string SharedSecret { get; }
} }
} }

17
src/Squidex.Domain.Apps.Events/Webhooks/WebhookUpdated.cs

@ -0,0 +1,17 @@
// ==========================================================================
// WebhookUpdated.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using Squidex.Infrastructure;
namespace Squidex.Domain.Apps.Events.Webhooks
{
[TypeName("WebhookUpdatedEvent")]
public sealed class WebhookUpdated : WebhookEditEvent
{
}
}

10
src/Squidex.Domain.Apps.Read.MongoDb/Schemas/MongoSchemaRepository_EventHandling.cs

@ -103,16 +103,6 @@ namespace Squidex.Domain.Apps.Read.MongoDb.Schemas
return UpdateSchema(@event, headers, s => SchemaEventDispatcher.Dispatch(@event, s, registry)); return UpdateSchema(@event, headers, s => SchemaEventDispatcher.Dispatch(@event, s, registry));
} }
protected Task On(WebhookAdded @event, EnvelopeHeaders headers)
{
return UpdateSchema(@event, headers, s => s);
}
protected Task On(WebhookDeleted @event, EnvelopeHeaders headers)
{
return UpdateSchema(@event, headers, s => s);
}
protected Task On(SchemaDeleted @event, EnvelopeHeaders headers) protected Task On(SchemaDeleted @event, EnvelopeHeaders headers)
{ {
return Collection.UpdateAsync(@event, headers, e => e.IsDeleted = true); return Collection.UpdateAsync(@event, headers, e => e.IsDeleted = true);

68
src/Squidex.Domain.Apps.Read.MongoDb/Schemas/MongoSchemaWebhookRepository_EventHandling.cs

@ -1,68 +0,0 @@
// ==========================================================================
// MongoSchemaWebhookRepository_EventHandling.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using System.Threading.Tasks;
using MongoDB.Driver;
using Squidex.Domain.Apps.Events.Schemas;
using Squidex.Infrastructure;
using Squidex.Infrastructure.CQRS.Events;
using Squidex.Infrastructure.Dispatching;
using Squidex.Infrastructure.Reflection;
namespace Squidex.Domain.Apps.Read.MongoDb.Schemas
{
public partial class MongoSchemaWebhookRepository
{
public string Name
{
get { return GetType().Name; }
}
public string EventsFilter
{
get { return "^schema-"; }
}
public Task On(Envelope<IEvent> @event)
{
return this.DispatchActionAsync(@event.Payload, @event.Headers);
}
protected async Task On(WebhookAdded @event, EnvelopeHeaders headers)
{
await EnsureWebooksLoadedAsync();
var theAppId = @event.AppId.Id;
var theSchemaId = @event.SchemaId.Id;
var webhook = SimpleMapper.Map(@event, new MongoSchemaWebhookEntity { AppId = theAppId, SchemaId = theSchemaId });
inMemoryWebhooks.GetOrAddNew(theAppId).GetOrAddNew(theSchemaId).Add(SimpleMapper.Map(@event, new ShortInfo()));
await Collection.InsertOneAsync(webhook);
}
protected async Task On(WebhookDeleted @event, EnvelopeHeaders headers)
{
await EnsureWebooksLoadedAsync();
inMemoryWebhooks.GetOrDefault(@event.AppId.Id)?.Remove(@event.SchemaId.Id);
await Collection.DeleteManyAsync(x => x.Id == @event.Id);
}
protected async Task On(SchemaDeleted @event, EnvelopeHeaders headers)
{
await EnsureWebooksLoadedAsync();
inMemoryWebhooks.GetOrDefault(@event.AppId.Id)?.Remove(@event.SchemaId.Id);
await Collection.DeleteManyAsync(x => x.SchemaId == @event.SchemaId.Id);
}
}
}

43
src/Squidex.Domain.Apps.Read.MongoDb/Schemas/MongoSchemaWebhookEntity.cs → src/Squidex.Domain.Apps.Read.MongoDb/Webhooks/MongoWebhookEntity.cs

@ -1,5 +1,5 @@
// ========================================================================== // ==========================================================================
// MongoSchemaWebhookEntity.cs // MongoWebhookEntity.cs
// Squidex Headless CMS // Squidex Headless CMS
// ========================================================================== // ==========================================================================
// Copyright (c) Squidex Group // Copyright (c) Squidex Group
@ -7,21 +7,19 @@
// ========================================================================== // ==========================================================================
using System; using System;
using MongoDB.Bson; using System.Collections.Generic;
using MongoDB.Bson.Serialization.Attributes; using MongoDB.Bson.Serialization.Attributes;
using Squidex.Domain.Apps.Read.Schemas; using Squidex.Domain.Apps.Core.Webhooks;
using Squidex.Domain.Apps.Read.Webhooks;
using Squidex.Infrastructure;
using Squidex.Infrastructure.MongoDb;
// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global // ReSharper disable CollectionNeverUpdated.Global
namespace Squidex.Domain.Apps.Read.MongoDb.Schemas namespace Squidex.Domain.Apps.Read.MongoDb.Webhooks
{ {
public class MongoSchemaWebhookEntity : ISchemaWebhookEntity public class MongoWebhookEntity : MongoEntity, IWebhookEntity
{ {
[BsonId]
[BsonElement]
[BsonRepresentation(BsonType.String)]
public Guid Id { get; set; }
[BsonRequired] [BsonRequired]
[BsonElement] [BsonElement]
public Uri Url { get; set; } public Uri Url { get; set; }
@ -32,7 +30,15 @@ namespace Squidex.Domain.Apps.Read.MongoDb.Schemas
[BsonRequired] [BsonRequired]
[BsonElement] [BsonElement]
public Guid SchemaId { get; set; } public long Version { get; set; }
[BsonRequired]
[BsonElement]
public RefToken CreatedBy { get; set; }
[BsonRequired]
[BsonElement]
public RefToken LastModifiedBy { get; set; }
[BsonRequired] [BsonRequired]
[BsonElement] [BsonElement]
@ -53,5 +59,18 @@ namespace Squidex.Domain.Apps.Read.MongoDb.Schemas
[BsonRequired] [BsonRequired]
[BsonElement] [BsonElement]
public long TotalRequestTime { get; set; } public long TotalRequestTime { get; set; }
[BsonRequired]
[BsonElement]
public List<WebhookSchema> Schemas { get; set; }
[BsonRequired]
[BsonElement]
public List<Guid> SchemaIds { get; set; }
IEnumerable<WebhookSchema> IWebhookEntity.Schemas
{
get { return Schemas; }
}
} }
} }

6
src/Squidex.Domain.Apps.Read.MongoDb/Schemas/MongoWebhookEventEntity.cs → src/Squidex.Domain.Apps.Read.MongoDb/Webhooks/MongoWebhookEventEntity.cs

@ -9,11 +9,11 @@
using System; using System;
using MongoDB.Bson.Serialization.Attributes; using MongoDB.Bson.Serialization.Attributes;
using NodaTime; using NodaTime;
using Squidex.Domain.Apps.Read.Schemas; using Squidex.Domain.Apps.Read.Webhooks;
using Squidex.Infrastructure.MongoDb; using Squidex.Infrastructure.MongoDb;
using Squidex.Infrastructure.Reflection; using Squidex.Infrastructure.Reflection;
namespace Squidex.Domain.Apps.Read.MongoDb.Schemas namespace Squidex.Domain.Apps.Read.MongoDb.Webhooks
{ {
public sealed class MongoWebhookEventEntity : MongoEntity, IWebhookEventEntity public sealed class MongoWebhookEventEntity : MongoEntity, IWebhookEventEntity
{ {
@ -25,7 +25,7 @@ namespace Squidex.Domain.Apps.Read.MongoDb.Schemas
[BsonRequired] [BsonRequired]
[BsonElement] [BsonElement]
public Guid WebhookId { get; set; } public long Version { get; set; }
[BsonRequired] [BsonRequired]
[BsonElement] [BsonElement]

6
src/Squidex.Domain.Apps.Read.MongoDb/Schemas/MongoWebhookEventRepository.cs → src/Squidex.Domain.Apps.Read.MongoDb/Webhooks/MongoWebhookEventRepository.cs

@ -12,13 +12,13 @@ using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using MongoDB.Driver; using MongoDB.Driver;
using NodaTime; using NodaTime;
using Squidex.Domain.Apps.Read.Schemas; using Squidex.Domain.Apps.Read.Webhooks;
using Squidex.Domain.Apps.Read.Schemas.Repositories; using Squidex.Domain.Apps.Read.Webhooks.Repositories;
using Squidex.Infrastructure; using Squidex.Infrastructure;
using Squidex.Infrastructure.MongoDb; using Squidex.Infrastructure.MongoDb;
using Squidex.Infrastructure.Reflection; using Squidex.Infrastructure.Reflection;
namespace Squidex.Domain.Apps.Read.MongoDb.Schemas namespace Squidex.Domain.Apps.Read.MongoDb.Webhooks
{ {
public sealed class MongoWebhookEventRepository : MongoRepositoryBase<MongoWebhookEventEntity>, IWebhookEventRepository public sealed class MongoWebhookEventRepository : MongoRepositoryBase<MongoWebhookEventEntity>, IWebhookEventRepository
{ {

49
src/Squidex.Domain.Apps.Read.MongoDb/Schemas/MongoSchemaWebhookRepository.cs → src/Squidex.Domain.Apps.Read.MongoDb/Webhooks/MongoWebhookRepository.cs

@ -1,5 +1,5 @@
// ========================================================================== // ==========================================================================
// MongoSchemaWebhookRepository.cs // MongoWebhookRepository.cs
// Squidex Headless CMS // Squidex Headless CMS
// ========================================================================== // ==========================================================================
// Copyright (c) Squidex Group // Copyright (c) Squidex Group
@ -8,38 +8,27 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using MongoDB.Bson; using MongoDB.Bson;
using MongoDB.Driver; using MongoDB.Driver;
using Squidex.Domain.Apps.Read.Schemas; using Squidex.Domain.Apps.Read.Webhooks;
using Squidex.Domain.Apps.Read.Schemas.Repositories; using Squidex.Domain.Apps.Read.Webhooks.Repositories;
using Squidex.Infrastructure; using Squidex.Infrastructure;
using Squidex.Infrastructure.CQRS.Events; using Squidex.Infrastructure.CQRS.Events;
using Squidex.Infrastructure.MongoDb; using Squidex.Infrastructure.MongoDb;
using Squidex.Infrastructure.Reflection;
// ReSharper disable SwitchStatementMissingSomeCases // ReSharper disable SwitchStatementMissingSomeCases
namespace Squidex.Domain.Apps.Read.MongoDb.Schemas namespace Squidex.Domain.Apps.Read.MongoDb.Webhooks
{ {
public partial class MongoSchemaWebhookRepository : MongoRepositoryBase<MongoSchemaWebhookEntity>, ISchemaWebhookRepository, IEventConsumer public partial class MongoWebhookRepository : MongoRepositoryBase<MongoWebhookEntity>, IWebhookRepository, IEventConsumer
{ {
private static readonly List<ShortInfo> EmptyWebhooks = new List<ShortInfo>(); private static readonly List<IWebhookEntity> EmptyWebhooks = new List<IWebhookEntity>();
private Dictionary<Guid, Dictionary<Guid, List<ShortInfo>>> inMemoryWebhooks; private Dictionary<Guid, List<IWebhookEntity>> inMemoryWebhooks;
private readonly SemaphoreSlim lockObject = new SemaphoreSlim(1); private readonly SemaphoreSlim lockObject = new SemaphoreSlim(1);
public sealed class ShortInfo : ISchemaWebhookUrlEntity public MongoWebhookRepository(IMongoDatabase database)
{
public Guid Id { get; set; }
public Uri Url { get; set; }
public string SharedSecret { get; set; }
}
public MongoSchemaWebhookRepository(IMongoDatabase database)
: base(database) : base(database)
{ {
} }
@ -49,21 +38,17 @@ namespace Squidex.Domain.Apps.Read.MongoDb.Schemas
return "Projections_SchemaWebhooks"; return "Projections_SchemaWebhooks";
} }
protected override Task SetupCollectionAsync(IMongoCollection<MongoSchemaWebhookEntity> collection) protected override async Task SetupCollectionAsync(IMongoCollection<MongoWebhookEntity> collection)
{ {
return collection.Indexes.CreateOneAsync(Index.Ascending(x => x.SchemaId)); await collection.Indexes.CreateOneAsync(Index.Ascending(x => x.AppId));
await collection.Indexes.CreateOneAsync(Index.Ascending(x => x.SchemaIds));
} }
public async Task<IReadOnlyList<ISchemaWebhookEntity>> QueryByAppAsync(Guid appId) public async Task<IReadOnlyList<IWebhookEntity>> QueryByAppAsync(Guid appId)
{
return await Collection.Find(Filter.Eq(x => x.AppId, appId)).ToListAsync();
}
public async Task<IReadOnlyList<ISchemaWebhookUrlEntity>> QueryUrlsBySchemaAsync(Guid appId, Guid schemaId)
{ {
await EnsureWebooksLoadedAsync(); await EnsureWebooksLoadedAsync();
return inMemoryWebhooks.GetOrDefault(appId)?.GetOrDefault(schemaId)?.ToList() ?? EmptyWebhooks; return inMemoryWebhooks.GetOrDefault(appId) ?? EmptyWebhooks;
} }
public async Task TraceSentAsync(Guid webhookId, WebhookResult result, TimeSpan elapsed) public async Task TraceSentAsync(Guid webhookId, WebhookResult result, TimeSpan elapsed)
@ -103,18 +88,14 @@ namespace Squidex.Domain.Apps.Read.MongoDb.Schemas
if (inMemoryWebhooks == null) if (inMemoryWebhooks == null)
{ {
var result = new Dictionary<Guid, Dictionary<Guid, List<ShortInfo>>>(); inMemoryWebhooks = new Dictionary<Guid, List<IWebhookEntity>>();
var webhooks = await Collection.Find(new BsonDocument()).ToListAsync(); var webhooks = await Collection.Find(new BsonDocument()).ToListAsync();
foreach (var webhook in webhooks) foreach (var webhook in webhooks)
{ {
var list = result.GetOrAddNew(webhook.AppId).GetOrAddNew(webhook.SchemaId); inMemoryWebhooks.GetOrAddNew(webhook.AppId).Add(webhook);
list.Add(SimpleMapper.Map(webhook, new ShortInfo()));
} }
inMemoryWebhooks = result;
} }
} }
finally finally

93
src/Squidex.Domain.Apps.Read.MongoDb/Webhooks/MongoWebhookRepository_EventHandling.cs

@ -0,0 +1,93 @@
// ==========================================================================
// MongoSchemaWebhookRepository_EventHandling.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using System.Linq;
using System.Threading.Tasks;
using MongoDB.Driver;
using Squidex.Domain.Apps.Events.Schemas;
using Squidex.Infrastructure;
using Squidex.Infrastructure.CQRS.Events;
using Squidex.Infrastructure.Dispatching;
using Squidex.Infrastructure.Reflection;
using Squidex.Domain.Apps.Events.Webhooks;
using Squidex.Domain.Apps.Read.MongoDb.Utils;
namespace Squidex.Domain.Apps.Read.MongoDb.Webhooks
{
public partial class MongoWebhookRepository
{
public string Name
{
get { return GetType().Name; }
}
public string EventsFilter
{
get { return "(^webhook-)|(^schema-)"; }
}
public Task On(Envelope<IEvent> @event)
{
return this.DispatchActionAsync(@event.Payload, @event.Headers);
}
protected async Task On(WebhookCreated @event, EnvelopeHeaders headers)
{
await EnsureWebooksLoadedAsync();
await Collection.CreateAsync(@event, headers, w =>
{
SimpleMapper.Map(@event, w);
w.SchemaIds = w.Schemas.Select(x => x.SchemaId).ToList();
inMemoryWebhooks.GetOrAddNew(w.AppId).RemoveAll(x => x.Id == w.Id);
inMemoryWebhooks.GetOrAddNew(w.AppId).Add(w);
});
}
protected async Task On(WebhookUpdated @event, EnvelopeHeaders headers)
{
await EnsureWebooksLoadedAsync();
await Collection.UpdateAsync(@event, headers, w =>
{
SimpleMapper.Map(@event, w);
w.SchemaIds = w.Schemas.Select(x => x.SchemaId).ToList();
inMemoryWebhooks.GetOrAddNew(w.AppId).RemoveAll(x => x.Id == w.Id);
inMemoryWebhooks.GetOrAddNew(w.AppId).Add(w);
});
}
protected async Task On(SchemaDeleted @event, EnvelopeHeaders headers)
{
await EnsureWebooksLoadedAsync();
await Collection.UpdateAsync(@event, headers, w =>
{
w.Schemas.RemoveAll(s => s.SchemaId == @event.SchemaId.Id);
w.SchemaIds = w.Schemas.Select(x => x.SchemaId).ToList();
inMemoryWebhooks.GetOrAddNew(w.AppId).RemoveAll(x => x.Id == w.Id);
inMemoryWebhooks.GetOrAddNew(w.AppId).Add(w);
});
}
protected async Task On(WebhookDeleted @event, EnvelopeHeaders headers)
{
await EnsureWebooksLoadedAsync();
inMemoryWebhooks.GetOrAddNew(@event.AppId.Id).RemoveAll(x => x.Id == @event.WebhookId);
await Collection.DeleteManyAsync(x => x.Id == @event.WebhookId);
}
}
}

8
src/Squidex.Domain.Apps.Read/Schemas/Services/Implementations/CachingSchemaProvider.cs

@ -125,14 +125,6 @@ namespace Squidex.Domain.Apps.Read.Schemas.Services.Implementations
{ {
Remove(schemaUpdatedEvent.AppId, schemaUpdatedEvent.SchemaId); Remove(schemaUpdatedEvent.AppId, schemaUpdatedEvent.SchemaId);
} }
else if (@event.Payload is WebhookAdded webhookAddedEvent)
{
Remove(webhookAddedEvent.AppId, webhookAddedEvent.SchemaId);
}
else if (@event.Payload is WebhookDeleted webhookDeletedEvent)
{
Remove(webhookDeletedEvent.AppId, webhookDeletedEvent.SchemaId);
}
return TaskHelper.Done; return TaskHelper.Done;
} }

89
src/Squidex.Domain.Apps.Read/Schemas/WebhookSender.cs

@ -1,89 +0,0 @@
// ==========================================================================
// WebhookSender.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using System;
using System.Diagnostics;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using Squidex.Infrastructure.Http;
// ReSharper disable SuggestVarOrType_SimpleTypes
namespace Squidex.Domain.Apps.Read.Schemas
{
public class WebhookSender
{
private static readonly TimeSpan Timeout = TimeSpan.FromSeconds(2);
public virtual async Task<(string Dump, WebhookResult Result, TimeSpan Elapsed)> SendAsync(WebhookJob job)
{
HttpRequestMessage request = BuildRequest(job);
HttpResponseMessage response = null;
var isTimeout = false;
var watch = Stopwatch.StartNew();
try
{
using (var client = new HttpClient { Timeout = Timeout })
{
response = await client.SendAsync(request);
}
}
catch (TimeoutException)
{
isTimeout = true;
}
catch (OperationCanceledException)
{
isTimeout = true;
}
finally
{
watch.Stop();
}
var responseString = string.Empty;
if (response != null)
{
responseString = await response.Content.ReadAsStringAsync();
}
var dump = DumpFormatter.BuildDump(request, response, job.RequestBody, responseString, watch.Elapsed);
var result = WebhookResult.Failed;
if (isTimeout)
{
result = WebhookResult.Timeout;
}
else if (response?.IsSuccessStatusCode == true)
{
result = WebhookResult.Success;
}
return (dump, result, watch.Elapsed);
}
private static HttpRequestMessage BuildRequest(WebhookJob job)
{
var request = new HttpRequestMessage(HttpMethod.Post, job.RequestUrl)
{
Content = new StringContent(job.RequestBody, Encoding.UTF8, "application/json")
};
request.Headers.Add("X-Signature", job.RequestSignature);
request.Headers.Add("User-Agent", "Squidex Webhook");
return request;
}
}
}

14
src/Squidex.Domain.Apps.Read/Schemas/ISchemaWebhookEntity.cs → src/Squidex.Domain.Apps.Read/Webhooks/IWebhookEntity.cs

@ -1,5 +1,5 @@
// ========================================================================== // ==========================================================================
// ISchemaWebhookEntity.cs // IWebhookEntity.cs
// Squidex Headless CMS // Squidex Headless CMS
// ========================================================================== // ==========================================================================
// Copyright (c) Squidex Group // Copyright (c) Squidex Group
@ -7,12 +7,14 @@
// ========================================================================== // ==========================================================================
using System; using System;
using System.Collections.Generic;
using Squidex.Domain.Apps.Core.Webhooks;
namespace Squidex.Domain.Apps.Read.Schemas namespace Squidex.Domain.Apps.Read.Webhooks
{ {
public interface ISchemaWebhookEntity : ISchemaWebhookUrlEntity public interface IWebhookEntity : IAppRefEntity, IEntityWithCreatedBy, IEntityWithLastModifiedBy, IEntityWithVersion
{ {
Guid SchemaId { get; } Uri Url { get; }
long TotalSucceeded { get; } long TotalSucceeded { get; }
@ -21,5 +23,9 @@ namespace Squidex.Domain.Apps.Read.Schemas
long TotalTimedout { get; } long TotalTimedout { get; }
long TotalRequestTime { get; } long TotalRequestTime { get; }
string SharedSecret { get; }
IEnumerable<WebhookSchema> Schemas { get; }
} }
} }

2
src/Squidex.Domain.Apps.Read/Schemas/IWebhookEventEntity.cs → src/Squidex.Domain.Apps.Read/Webhooks/IWebhookEventEntity.cs

@ -8,7 +8,7 @@
using NodaTime; using NodaTime;
namespace Squidex.Domain.Apps.Read.Schemas namespace Squidex.Domain.Apps.Read.Webhooks
{ {
public interface IWebhookEventEntity : IEntity public interface IWebhookEventEntity : IEntity
{ {

2
src/Squidex.Domain.Apps.Read/Schemas/Repositories/IWebhookEventRepository.cs → src/Squidex.Domain.Apps.Read/Webhooks/Repositories/IWebhookEventRepository.cs

@ -12,7 +12,7 @@ using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using NodaTime; using NodaTime;
namespace Squidex.Domain.Apps.Read.Schemas.Repositories namespace Squidex.Domain.Apps.Read.Webhooks.Repositories
{ {
public interface IWebhookEventRepository public interface IWebhookEventRepository
{ {

8
src/Squidex.Domain.Apps.Read/Schemas/Repositories/ISchemaWebhookRepository.cs → src/Squidex.Domain.Apps.Read/Webhooks/Repositories/IWebhookRepository.cs

@ -10,14 +10,12 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace Squidex.Domain.Apps.Read.Schemas.Repositories namespace Squidex.Domain.Apps.Read.Webhooks.Repositories
{ {
public interface ISchemaWebhookRepository public interface IWebhookRepository
{ {
Task TraceSentAsync(Guid webhookId, WebhookResult result, TimeSpan elapsed); Task TraceSentAsync(Guid webhookId, WebhookResult result, TimeSpan elapsed);
Task<IReadOnlyList<ISchemaWebhookUrlEntity>> QueryUrlsBySchemaAsync(Guid appId, Guid schemaId); Task<IReadOnlyList<IWebhookEntity>> QueryByAppAsync(Guid appId);
Task<IReadOnlyList<ISchemaWebhookEntity>> QueryByAppAsync(Guid appId);
} }
} }

8
src/Squidex.Domain.Apps.Read/Schemas/WebhookDequeuer.cs → src/Squidex.Domain.Apps.Read/Webhooks/WebhookDequeuer.cs

@ -11,7 +11,7 @@ using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Threading.Tasks.Dataflow; using System.Threading.Tasks.Dataflow;
using NodaTime; using NodaTime;
using Squidex.Domain.Apps.Read.Schemas.Repositories; using Squidex.Domain.Apps.Read.Webhooks.Repositories;
using Squidex.Infrastructure; using Squidex.Infrastructure;
using Squidex.Infrastructure.Log; using Squidex.Infrastructure.Log;
using Squidex.Infrastructure.Timers; using Squidex.Infrastructure.Timers;
@ -20,14 +20,14 @@ using Squidex.Infrastructure.Timers;
// ReSharper disable MethodSupportsCancellation // ReSharper disable MethodSupportsCancellation
// ReSharper disable InvertIf // ReSharper disable InvertIf
namespace Squidex.Domain.Apps.Read.Schemas namespace Squidex.Domain.Apps.Read.Webhooks
{ {
public sealed class WebhookDequeuer : DisposableObjectBase, IExternalSystem public sealed class WebhookDequeuer : DisposableObjectBase, IExternalSystem
{ {
private readonly ActionBlock<IWebhookEventEntity> requestBlock; private readonly ActionBlock<IWebhookEventEntity> requestBlock;
private readonly TransformBlock<IWebhookEventEntity, IWebhookEventEntity> blockBlock; private readonly TransformBlock<IWebhookEventEntity, IWebhookEventEntity> blockBlock;
private readonly IWebhookEventRepository webhookEventRepository; private readonly IWebhookEventRepository webhookEventRepository;
private readonly ISchemaWebhookRepository webhookRepository; private readonly IWebhookRepository webhookRepository;
private readonly WebhookSender webhookSender; private readonly WebhookSender webhookSender;
private readonly CompletionTimer timer; private readonly CompletionTimer timer;
private readonly ISemanticLog log; private readonly ISemanticLog log;
@ -35,7 +35,7 @@ namespace Squidex.Domain.Apps.Read.Schemas
public WebhookDequeuer(WebhookSender webhookSender, public WebhookDequeuer(WebhookSender webhookSender,
IWebhookEventRepository webhookEventRepository, IWebhookEventRepository webhookEventRepository,
ISchemaWebhookRepository webhookRepository, IWebhookRepository webhookRepository,
IClock clock, IClock clock,
ISemanticLog log) ISemanticLog log)
{ {

42
src/Squidex.Domain.Apps.Read/Schemas/WebhookEnqueuer.cs → src/Squidex.Domain.Apps.Read/Webhooks/WebhookEnqueuer.cs

@ -7,25 +7,27 @@
// ========================================================================== // ==========================================================================
using System; using System;
using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Newtonsoft.Json; using Newtonsoft.Json;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using NodaTime; using NodaTime;
using Squidex.Domain.Apps.Core.Webhooks;
using Squidex.Domain.Apps.Events; using Squidex.Domain.Apps.Events;
using Squidex.Domain.Apps.Events.Contents; using Squidex.Domain.Apps.Events.Contents;
using Squidex.Domain.Apps.Read.Schemas.Repositories; using Squidex.Domain.Apps.Read.Webhooks.Repositories;
using Squidex.Infrastructure; using Squidex.Infrastructure;
using Squidex.Infrastructure.CQRS.Events; using Squidex.Infrastructure.CQRS.Events;
using Squidex.Infrastructure.Tasks; using Squidex.Infrastructure.Tasks;
namespace Squidex.Domain.Apps.Read.Schemas namespace Squidex.Domain.Apps.Read.Webhooks
{ {
public sealed class WebhookEnqueuer : IEventConsumer public sealed class WebhookEnqueuer : IEventConsumer
{ {
private const string ContentPrefix = "Content"; private const string ContentPrefix = "Content";
private static readonly Duration ExpirationTime = Duration.FromDays(2); private static readonly Duration ExpirationTime = Duration.FromDays(2);
private readonly IWebhookEventRepository webhookEventRepository; private readonly IWebhookEventRepository webhookEventRepository;
private readonly ISchemaWebhookRepository webhookRepository; private readonly IWebhookRepository webhookRepository;
private readonly IClock clock; private readonly IClock clock;
private readonly TypeNameRegistry typeNameRegistry; private readonly TypeNameRegistry typeNameRegistry;
private readonly JsonSerializer webhookSerializer; private readonly JsonSerializer webhookSerializer;
@ -42,7 +44,7 @@ namespace Squidex.Domain.Apps.Read.Schemas
public WebhookEnqueuer(TypeNameRegistry typeNameRegistry, public WebhookEnqueuer(TypeNameRegistry typeNameRegistry,
IWebhookEventRepository webhookEventRepository, IWebhookEventRepository webhookEventRepository,
ISchemaWebhookRepository webhookRepository, IWebhookRepository webhookRepository,
IClock clock, IClock clock,
JsonSerializer webhookSerializer) JsonSerializer webhookSerializer)
{ {
@ -72,25 +74,26 @@ namespace Squidex.Domain.Apps.Read.Schemas
{ {
var eventType = typeNameRegistry.GetName(@event.Payload.GetType()); var eventType = typeNameRegistry.GetName(@event.Payload.GetType());
var webhooks = await webhookRepository.QueryUrlsBySchemaAsync(contentEvent.AppId.Id, contentEvent.SchemaId.Id); var webhooks = await webhookRepository.QueryByAppAsync(contentEvent.AppId.Id);
if (webhooks.Count > 0) var matchingWebhooks = webhooks.Where(w => w.Schemas.Any(s => Matchs(s, contentEvent))).ToList();
if (matchingWebhooks.Count > 0)
{ {
var now = clock.GetCurrentInstant(); var now = clock.GetCurrentInstant();
var payload = CreatePayload(@event, eventType); var eventPayload = CreatePayload(@event, eventType);
var eventName = $"{contentEvent.SchemaId.Name.ToPascalCase()}{CreateContentEventName(eventType)}"; var eventName = $"{contentEvent.SchemaId.Name.ToPascalCase()}{CreateContentEventName(eventType)}";
foreach (var webhook in webhooks) foreach (var webhook in matchingWebhooks)
{ {
await EnqueueJobAsync(payload, webhook, contentEvent, eventName, now); await EnqueueJobAsync(eventPayload, webhook, contentEvent, eventName, now);
} }
} }
} }
} }
private async Task EnqueueJobAsync(string payload, ISchemaWebhookUrlEntity webhook, AppEvent contentEvent, string eventName, Instant now) private async Task EnqueueJobAsync(string payload, IWebhookEntity webhook, AppEvent contentEvent, string eventName, Instant now)
{ {
var signature = $"{payload}{webhook.SharedSecret}".Sha256Base64(); var signature = $"{payload}{webhook.SharedSecret}".Sha256Base64();
@ -109,12 +112,23 @@ namespace Squidex.Domain.Apps.Read.Schemas
await webhookEventRepository.EnqueueAsync(job, now); await webhookEventRepository.EnqueueAsync(job, now);
} }
private static bool Matchs(WebhookSchema webhookSchema, SchemaEvent @event)
{
return
(@event.SchemaId.Id == webhookSchema.SchemaId) &&
(@event is ContentCreated && webhookSchema.SendCreate ||
@event is ContentUpdated && webhookSchema.SendUpdate ||
@event is ContentDeleted && webhookSchema.SendDelete ||
@event is ContentPublished && webhookSchema.SendPublish ||
@event is ContentUnpublished && webhookSchema.SendUnpublish);
}
private string CreatePayload(Envelope<IEvent> @event, string eventType) private string CreatePayload(Envelope<IEvent> @event, string eventType)
{ {
return new JObject( return new JObject(
new JProperty("type", eventType), new JProperty("type", eventType),
new JProperty("payload", JObject.FromObject(@event.Payload, webhookSerializer)), new JProperty("payload", JObject.FromObject(@event.Payload, webhookSerializer)),
new JProperty("timestamp", @event.Headers.Timestamp().ToString())) new JProperty("timestamp", @event.Headers.Timestamp().ToString()))
.ToString(Formatting.Indented); .ToString(Formatting.Indented);
} }

2
src/Squidex.Domain.Apps.Read/Schemas/WebhookJob.cs → src/Squidex.Domain.Apps.Read/Webhooks/WebhookJob.cs

@ -9,7 +9,7 @@
using System; using System;
using NodaTime; using NodaTime;
namespace Squidex.Domain.Apps.Read.Schemas namespace Squidex.Domain.Apps.Read.Webhooks
{ {
public sealed class WebhookJob public sealed class WebhookJob
{ {

2
src/Squidex.Domain.Apps.Read/Schemas/WebhookJobResult.cs → src/Squidex.Domain.Apps.Read/Webhooks/WebhookJobResult.cs

@ -6,7 +6,7 @@
// All rights reserved. // All rights reserved.
// ========================================================================== // ==========================================================================
namespace Squidex.Domain.Apps.Read.Schemas namespace Squidex.Domain.Apps.Read.Webhooks
{ {
public enum WebhookJobResult public enum WebhookJobResult
{ {

2
src/Squidex.Domain.Apps.Read/Schemas/WebhookResult.cs → src/Squidex.Domain.Apps.Read/Webhooks/WebhookResult.cs

@ -6,7 +6,7 @@
// All rights reserved. // All rights reserved.
// ========================================================================== // ==========================================================================
namespace Squidex.Domain.Apps.Read.Schemas namespace Squidex.Domain.Apps.Read.Webhooks
{ {
public enum WebhookResult public enum WebhookResult
{ {

100
src/Squidex.Domain.Apps.Read/Webhooks/WebhookSender.cs

@ -0,0 +1,100 @@
// ==========================================================================
// WebhookSender.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using System;
using System.Diagnostics;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using Squidex.Infrastructure.Http;
// ReSharper disable SuggestVarOrType_SimpleTypes
namespace Squidex.Domain.Apps.Read.Webhooks
{
public class WebhookSender
{
private static readonly TimeSpan Timeout = TimeSpan.FromSeconds(2);
public virtual async Task<(string Dump, WebhookResult Result, TimeSpan Elapsed)> SendAsync(WebhookJob job)
{
try
{
HttpRequestMessage request = BuildRequest(job);
HttpResponseMessage response = null;
var responseString = string.Empty;
var isTimeout = false;
var watch = Stopwatch.StartNew();
try
{
using (var client = new HttpClient { Timeout = Timeout })
{
response = await client.SendAsync(request);
}
}
catch (TimeoutException)
{
isTimeout = true;
}
catch (OperationCanceledException)
{
isTimeout = true;
}
catch (Exception ex)
{
responseString = ex.Message;
}
finally
{
watch.Stop();
}
if (response != null)
{
responseString = await response.Content.ReadAsStringAsync();
}
var dump = DumpFormatter.BuildDump(request, response, job.RequestBody, responseString, watch.Elapsed, isTimeout);
var result = WebhookResult.Failed;
if (isTimeout)
{
result = WebhookResult.Timeout;
}
else if (response?.IsSuccessStatusCode == true)
{
result = WebhookResult.Success;
}
return (dump, result, watch.Elapsed);
}
catch (Exception ex)
{
return (ex.Message, WebhookResult.Failed, TimeSpan.Zero);
}
}
private static HttpRequestMessage BuildRequest(WebhookJob job)
{
var request = new HttpRequestMessage(HttpMethod.Post, job.RequestUrl)
{
Content = new StringContent(job.RequestBody, Encoding.UTF8, "application/json")
};
request.Headers.Add("X-Signature", job.RequestSignature);
request.Headers.Add("User-Agent", "Squidex Webhook");
return request;
}
}
}

2
src/Squidex.Domain.Apps.Write/Apps/Commands/AssignContributor.cs

@ -12,7 +12,7 @@ using Squidex.Infrastructure;
namespace Squidex.Domain.Apps.Write.Apps.Commands namespace Squidex.Domain.Apps.Write.Apps.Commands
{ {
public class AssignContributor : AppAggregateCommand, IValidatable public sealed class AssignContributor : AppAggregateCommand, IValidatable
{ {
public string ContributorId { get; set; } public string ContributorId { get; set; }

2
src/Squidex.Domain.Apps.Write/Apps/Commands/RemoveContributor.cs

@ -11,7 +11,7 @@ using Squidex.Infrastructure;
namespace Squidex.Domain.Apps.Write.Apps.Commands namespace Squidex.Domain.Apps.Write.Apps.Commands
{ {
public class RemoveContributor : AppAggregateCommand, IValidatable public sealed class RemoveContributor : AppAggregateCommand, IValidatable
{ {
public string ContributorId { get; set; } public string ContributorId { get; set; }

2
src/Squidex.Domain.Apps.Write/Apps/Commands/RevokeClient.cs

@ -11,7 +11,7 @@ using Squidex.Infrastructure;
namespace Squidex.Domain.Apps.Write.Apps.Commands namespace Squidex.Domain.Apps.Write.Apps.Commands
{ {
public class RevokeClient : AppAggregateCommand, IValidatable public sealed class RevokeClient : AppAggregateCommand, IValidatable
{ {
public string Id { get; set; } public string Id { get; set; }

2
src/Squidex.Domain.Apps.Write/Apps/Commands/UpdateClient.cs

@ -11,7 +11,7 @@ using Squidex.Infrastructure;
namespace Squidex.Domain.Apps.Write.Apps.Commands namespace Squidex.Domain.Apps.Write.Apps.Commands
{ {
public class UpdateClient : AppAggregateCommand, IValidatable public sealed class UpdateClient : AppAggregateCommand, IValidatable
{ {
public string Id { get; set; } public string Id { get; set; }

2
src/Squidex.Domain.Apps.Write/Assets/Commands/UpdateAsset.cs

@ -10,7 +10,7 @@ using Squidex.Infrastructure.Assets;
namespace Squidex.Domain.Apps.Write.Assets.Commands namespace Squidex.Domain.Apps.Write.Assets.Commands
{ {
public class UpdateAsset : AssetAggregateCommand public sealed class UpdateAsset : AssetAggregateCommand
{ {
public AssetFile File { get; set; } public AssetFile File { get; set; }

2
src/Squidex.Domain.Apps.Write/Contents/Commands/CreateContent.cs

@ -10,7 +10,7 @@ using System;
namespace Squidex.Domain.Apps.Write.Contents.Commands namespace Squidex.Domain.Apps.Write.Contents.Commands
{ {
public class CreateContent : ContentDataCommand public sealed class CreateContent : ContentDataCommand
{ {
public bool Publish { get; set; } public bool Publish { get; set; }

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

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

2
src/Squidex.Domain.Apps.Write/Contents/Commands/PatchContent.cs

@ -8,7 +8,7 @@
namespace Squidex.Domain.Apps.Write.Contents.Commands namespace Squidex.Domain.Apps.Write.Contents.Commands
{ {
public class PatchContent : ContentDataCommand public sealed class PatchContent : ContentDataCommand
{ {
} }
} }

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

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

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

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

2
src/Squidex.Domain.Apps.Write/Contents/Commands/UpdateContent.cs

@ -8,7 +8,7 @@
namespace Squidex.Domain.Apps.Write.Contents.Commands namespace Squidex.Domain.Apps.Write.Contents.Commands
{ {
public class UpdateContent : ContentDataCommand public sealed class UpdateContent : ContentDataCommand
{ {
} }
} }

1
src/Squidex.Domain.Apps.Write/Contents/ContentCommandMiddleware.cs

@ -42,7 +42,6 @@ namespace Squidex.Domain.Apps.Write.Contents
{ {
Guard.NotNull(handler, nameof(handler)); Guard.NotNull(handler, nameof(handler));
Guard.NotNull(schemas, nameof(schemas)); Guard.NotNull(schemas, nameof(schemas));
Guard.NotNull(handler, nameof(handler));
Guard.NotNull(appProvider, nameof(appProvider)); Guard.NotNull(appProvider, nameof(appProvider));
Guard.NotNull(assetRepository, nameof(assetRepository)); Guard.NotNull(assetRepository, nameof(assetRepository));
Guard.NotNull(contentRepository, nameof(contentRepository)); Guard.NotNull(contentRepository, nameof(contentRepository));

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

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

2
src/Squidex.Domain.Apps.Write/Schemas/Commands/CreateSchema.cs

@ -15,7 +15,7 @@ using SchemaFields = System.Collections.Generic.List<Squidex.Domain.Apps.Write.S
namespace Squidex.Domain.Apps.Write.Schemas.Commands namespace Squidex.Domain.Apps.Write.Schemas.Commands
{ {
public class CreateSchema : AppCommand, IValidatable, IAggregateCommand public sealed class CreateSchema : AppCommand, IValidatable, IAggregateCommand
{ {
private SchemaProperties properties; private SchemaProperties properties;
private SchemaFields fields; private SchemaFields fields;

2
src/Squidex.Domain.Apps.Write/Schemas/Commands/DeleteField.cs

@ -8,7 +8,7 @@
namespace Squidex.Domain.Apps.Write.Schemas.Commands namespace Squidex.Domain.Apps.Write.Schemas.Commands
{ {
public class DeleteField : FieldCommand public sealed class DeleteField : FieldCommand
{ {
} }
} }

2
src/Squidex.Domain.Apps.Write/Schemas/Commands/DeleteSchema.cs

@ -8,7 +8,7 @@
namespace Squidex.Domain.Apps.Write.Schemas.Commands namespace Squidex.Domain.Apps.Write.Schemas.Commands
{ {
public class DeleteSchema : SchemaAggregateCommand public sealed class DeleteSchema : SchemaAggregateCommand
{ {
} }
} }

2
src/Squidex.Domain.Apps.Write/Schemas/Commands/DisableField.cs

@ -8,7 +8,7 @@
namespace Squidex.Domain.Apps.Write.Schemas.Commands namespace Squidex.Domain.Apps.Write.Schemas.Commands
{ {
public class DisableField : FieldCommand public sealed class DisableField : FieldCommand
{ {
} }
} }

2
src/Squidex.Domain.Apps.Write/Schemas/Commands/EnableField.cs

@ -8,7 +8,7 @@
namespace Squidex.Domain.Apps.Write.Schemas.Commands namespace Squidex.Domain.Apps.Write.Schemas.Commands
{ {
public class EnableField : FieldCommand public sealed class EnableField : FieldCommand
{ {
} }
} }

2
src/Squidex.Domain.Apps.Write/Schemas/Commands/HideField.cs

@ -8,7 +8,7 @@
namespace Squidex.Domain.Apps.Write.Schemas.Commands namespace Squidex.Domain.Apps.Write.Schemas.Commands
{ {
public class HideField : FieldCommand public sealed class HideField : FieldCommand
{ {
} }
} }

2
src/Squidex.Domain.Apps.Write/Schemas/Commands/LockField.cs

@ -8,7 +8,7 @@
namespace Squidex.Domain.Apps.Write.Schemas.Commands namespace Squidex.Domain.Apps.Write.Schemas.Commands
{ {
public class LockField : FieldCommand public sealed class LockField : FieldCommand
{ {
} }
} }

2
src/Squidex.Domain.Apps.Write/Schemas/Commands/PublishSchema.cs

@ -8,7 +8,7 @@
namespace Squidex.Domain.Apps.Write.Schemas.Commands namespace Squidex.Domain.Apps.Write.Schemas.Commands
{ {
public class PublishSchema : SchemaAggregateCommand public sealed class PublishSchema : SchemaAggregateCommand
{ {
} }
} }

2
src/Squidex.Domain.Apps.Write/Schemas/Commands/ReorderFields.cs

@ -11,7 +11,7 @@ using Squidex.Infrastructure;
namespace Squidex.Domain.Apps.Write.Schemas.Commands namespace Squidex.Domain.Apps.Write.Schemas.Commands
{ {
public class ReorderFields : SchemaAggregateCommand, IValidatable public sealed class ReorderFields : SchemaAggregateCommand, IValidatable
{ {
public List<long> FieldIds { get; set; } public List<long> FieldIds { get; set; }

2
src/Squidex.Domain.Apps.Write/Schemas/Commands/ShowField.cs

@ -8,7 +8,7 @@
namespace Squidex.Domain.Apps.Write.Schemas.Commands namespace Squidex.Domain.Apps.Write.Schemas.Commands
{ {
public class ShowField : FieldCommand public sealed class ShowField : FieldCommand
{ {
} }
} }

2
src/Squidex.Domain.Apps.Write/Schemas/Commands/UnpublishSchema.cs

@ -8,7 +8,7 @@
namespace Squidex.Domain.Apps.Write.Schemas.Commands namespace Squidex.Domain.Apps.Write.Schemas.Commands
{ {
public class UnpublishSchema : SchemaAggregateCommand public sealed class UnpublishSchema : SchemaAggregateCommand
{ {
} }
} }

2
src/Squidex.Domain.Apps.Write/Schemas/Commands/UpdateField.cs

@ -12,7 +12,7 @@ using Squidex.Infrastructure;
namespace Squidex.Domain.Apps.Write.Schemas.Commands namespace Squidex.Domain.Apps.Write.Schemas.Commands
{ {
public class UpdateField : FieldCommand, IValidatable public sealed class UpdateField : FieldCommand, IValidatable
{ {
public FieldProperties Properties { get; set; } public FieldProperties Properties { get; set; }

2
src/Squidex.Domain.Apps.Write/Schemas/Commands/UpdateSchema.cs

@ -12,7 +12,7 @@ using Squidex.Infrastructure;
namespace Squidex.Domain.Apps.Write.Schemas.Commands namespace Squidex.Domain.Apps.Write.Schemas.Commands
{ {
public class UpdateSchema : SchemaAggregateCommand, IValidatable public sealed class UpdateSchema : SchemaAggregateCommand, IValidatable
{ {
public SchemaProperties Properties { get; set; } public SchemaProperties Properties { get; set; }

10
src/Squidex.Domain.Apps.Write/Schemas/SchemaCommandMiddleware.cs

@ -60,16 +60,6 @@ namespace Squidex.Domain.Apps.Write.Schemas
}); });
} }
protected Task On(AddWebhook command, CommandContext context)
{
return handler.UpdateAsync<SchemaDomainObject>(context, s => s.AddWebhook(command));
}
protected Task On(DeleteWebhook command, CommandContext context)
{
return handler.UpdateAsync<SchemaDomainObject>(context, s => s.DeleteWebhook(command));
}
protected Task On(DeleteSchema command, CommandContext context) protected Task On(DeleteSchema command, CommandContext context)
{ {
return handler.UpdateAsync<SchemaDomainObject>(context, s => s.Delete(command)); return handler.UpdateAsync<SchemaDomainObject>(context, s => s.Delete(command));

42
src/Squidex.Domain.Apps.Write/Schemas/SchemaDomainObject.cs

@ -23,7 +23,6 @@ namespace Squidex.Domain.Apps.Write.Schemas
public class SchemaDomainObject : DomainObjectBase public class SchemaDomainObject : DomainObjectBase
{ {
private readonly FieldRegistry registry; private readonly FieldRegistry registry;
private readonly HashSet<Guid> webhookIds = new HashSet<Guid>();
private bool isDeleted; private bool isDeleted;
private long totalFields; private long totalFields;
private Schema schema; private Schema schema;
@ -115,16 +114,6 @@ namespace Squidex.Domain.Apps.Write.Schemas
schema = SchemaEventDispatcher.Dispatch(@event, schema); schema = SchemaEventDispatcher.Dispatch(@event, schema);
} }
protected void On(WebhookAdded @event)
{
webhookIds.Add(@event.Id);
}
protected void On(WebhookDeleted @event)
{
webhookIds.Remove(@event.Id);
}
protected void On(SchemaDeleted @event) protected void On(SchemaDeleted @event)
{ {
isDeleted = true; isDeleted = true;
@ -155,29 +144,6 @@ namespace Squidex.Domain.Apps.Write.Schemas
return this; return this;
} }
public SchemaDomainObject DeleteWebhook(DeleteWebhook command)
{
Guard.NotNull(command, nameof(command));
VerifyCreatedAndNotDeleted();
VerifyWebhookExists(command.Id);
RaiseEvent(SimpleMapper.Map(command, new WebhookDeleted()));
return this;
}
public SchemaDomainObject AddWebhook(AddWebhook command)
{
Guard.Valid(command, nameof(command), () => "Cannot add webhook");
VerifyCreatedAndNotDeleted();
RaiseEvent(SimpleMapper.Map(command, new WebhookAdded()));
return this;
}
public SchemaDomainObject AddField(AddField command) public SchemaDomainObject AddField(AddField command)
{ {
Guard.Valid(command, nameof(command), () => $"Cannot add field to schema {Id}"); Guard.Valid(command, nameof(command), () => $"Cannot add field to schema {Id}");
@ -335,14 +301,6 @@ namespace Squidex.Domain.Apps.Write.Schemas
RaiseEvent(@event); RaiseEvent(@event);
} }
private void VerifyWebhookExists(Guid id)
{
if (!webhookIds.Contains(id))
{
throw new DomainObjectNotFoundException(id.ToString(), "Webhooks", typeof(Schema));
}
}
private void VerifyNotCreated() private void VerifyNotCreated()
{ {
if (schema != null) if (schema != null)

23
src/Squidex.Domain.Apps.Write/Webhooks/Commands/CreateWebhook.cs

@ -0,0 +1,23 @@
// ==========================================================================
// CreateWebhook.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using System;
using Squidex.Infrastructure;
namespace Squidex.Domain.Apps.Write.Webhooks.Commands
{
public sealed class CreateWebhook : WebhookEditCommand
{
public string SharedSecret { get; } = RandomHash.New();
public CreateWebhook()
{
WebhookId = Guid.NewGuid();
}
}
}

7
src/Squidex.Domain.Apps.Write/Schemas/Commands/DeleteWebhook.cs → src/Squidex.Domain.Apps.Write/Webhooks/Commands/DeleteWebhook.cs

@ -6,12 +6,9 @@
// All rights reserved. // All rights reserved.
// ========================================================================== // ==========================================================================
using System; namespace Squidex.Domain.Apps.Write.Webhooks.Commands
namespace Squidex.Domain.Apps.Write.Schemas.Commands
{ {
public class DeleteWebhook : SchemaAggregateCommand public sealed class DeleteWebhook : WebhookAggregateCommand
{ {
public Guid Id { get; set; }
} }
} }

14
src/Squidex.Domain.Apps.Write/Webhooks/Commands/UpdateWebhook.cs

@ -0,0 +1,14 @@
// ==========================================================================
// UpdateWebhook.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
namespace Squidex.Domain.Apps.Write.Webhooks.Commands
{
public sealed class UpdateWebhook : WebhookEditCommand
{
}
}

25
src/Squidex.Domain.Apps.Write/Webhooks/Commands/WebhookAggregateCommand.cs

@ -0,0 +1,25 @@
// ==========================================================================
// WebhookAggregateCommand.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using System;
using Squidex.Infrastructure.CQRS.Commands;
// ReSharper disable MemberCanBeProtected.Global
namespace Squidex.Domain.Apps.Write.Webhooks.Commands
{
public abstract class WebhookAggregateCommand : AppCommand, IAggregateCommand
{
public Guid WebhookId { get; set; }
Guid IAggregateCommand.AggregateId
{
get { return WebhookId; }
}
}
}

23
src/Squidex.Domain.Apps.Write/Schemas/Commands/AddWebhook.cs → src/Squidex.Domain.Apps.Write/Webhooks/Commands/WebhookEditCommand.cs

@ -1,5 +1,5 @@
// ========================================================================== // ==========================================================================
// AddWebhook.cs // WebhookEditCommand.cs
// Squidex Headless CMS // Squidex Headless CMS
// ========================================================================== // ==========================================================================
// Copyright (c) Squidex Group // Copyright (c) Squidex Group
@ -8,19 +8,30 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using Squidex.Domain.Apps.Core.Webhooks;
using Squidex.Infrastructure; using Squidex.Infrastructure;
namespace Squidex.Domain.Apps.Write.Schemas.Commands namespace Squidex.Domain.Apps.Write.Webhooks.Commands
{ {
public sealed class AddWebhook : SchemaAggregateCommand, IValidatable public abstract class WebhookEditCommand : WebhookAggregateCommand, IValidatable
{ {
public Guid Id { get; } = Guid.NewGuid(); private List<WebhookSchema> schemas = new List<WebhookSchema>();
public Uri Url { get; set; } public Uri Url { get; set; }
public string SharedSecret { get; } = RandomHash.New(); public List<WebhookSchema> Schemas
{
get
{
return schemas ?? (schemas = new List<WebhookSchema>());
}
set
{
schemas = value;
}
}
public void Validate(IList<ValidationError> errors) public virtual void Validate(IList<ValidationError> errors)
{ {
if (Url == null || !Url.IsAbsoluteUri) if (Url == null || !Url.IsAbsoluteUri)
{ {

77
src/Squidex.Domain.Apps.Write/Webhooks/WebhookCommandMiddleware.cs

@ -0,0 +1,77 @@
// ==========================================================================
// WebhookCommandMiddleware.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using System;
using System.Linq;
using System.Threading.Tasks;
using Squidex.Domain.Apps.Read.Schemas.Services;
using Squidex.Domain.Apps.Write.Webhooks.Commands;
using Squidex.Infrastructure;
using Squidex.Infrastructure.CQRS.Commands;
using Squidex.Infrastructure.Dispatching;
namespace Squidex.Domain.Apps.Write.Webhooks
{
public class WebhookCommandMiddleware : ICommandMiddleware
{
private readonly IAggregateHandler handler;
private readonly ISchemaProvider schemas;
public WebhookCommandMiddleware(IAggregateHandler handler, ISchemaProvider schemas)
{
Guard.NotNull(handler, nameof(handler));
Guard.NotNull(schemas, nameof(schemas));
this.handler = handler;
this.schemas = schemas;
}
protected async Task On(CreateWebhook command, CommandContext context)
{
await ValidateAsync(command, () => "Failed to create webhook");
await handler.CreateAsync<WebhookDomainObject>(context, c => c.Create(command));
}
protected async Task On(UpdateWebhook command, CommandContext context)
{
await ValidateAsync(command, () => "Failed to update content");
await handler.UpdateAsync<WebhookDomainObject>(context, c => c.Update(command));
}
protected Task On(DeleteWebhook command, CommandContext context)
{
return handler.UpdateAsync<WebhookDomainObject>(context, c => c.Delete(command));
}
public async Task HandleAsync(CommandContext context, Func<Task> next)
{
if (!await this.DispatchActionAsync(context.Command, context))
{
await next();
}
}
private async Task ValidateAsync(WebhookEditCommand command, Func<string> message)
{
var results = await Task.WhenAll(
command.Schemas.Select(async schema =>
await schemas.FindSchemaByIdAsync(schema.SchemaId) == null
? new ValidationError($"Schema {schema.SchemaId} does not exist.")
: null));
var errors = results.Where(x => x != null).ToArray();
if (errors.Length > 0)
{
throw new ValidationException(message(), errors);
}
}
}
}

88
src/Squidex.Domain.Apps.Write/Webhooks/WebhookDomainObject.cs

@ -0,0 +1,88 @@
// ==========================================================================
// WebhookDomainObject.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using System;
using Squidex.Domain.Apps.Events.Webhooks;
using Squidex.Domain.Apps.Write.Webhooks.Commands;
using Squidex.Infrastructure;
using Squidex.Infrastructure.CQRS;
using Squidex.Infrastructure.CQRS.Events;
using Squidex.Infrastructure.Dispatching;
using Squidex.Infrastructure.Reflection;
namespace Squidex.Domain.Apps.Write.Webhooks
{
public class WebhookDomainObject : DomainObjectBase
{
private bool isDeleted;
private bool isCreated;
public WebhookDomainObject(Guid id, int version)
: base(id, version)
{
}
protected void On(WebhookCreated @event)
{
isCreated = true;
}
protected void On(WebhookDeleted @event)
{
isDeleted = true;
}
public void Create(CreateWebhook command)
{
Guard.Valid(command, nameof(command), () => "Cannot create webhook");
VerifyNotCreated();
RaiseEvent(SimpleMapper.Map(command, new WebhookCreated()));
}
public void Update(UpdateWebhook command)
{
Guard.Valid(command, nameof(command), () => "Cannot update webhook");
VerifyCreatedAndNotDeleted();
RaiseEvent(SimpleMapper.Map(command, new WebhookUpdated()));
}
public void Delete(DeleteWebhook command)
{
Guard.NotNull(command, nameof(command));
VerifyCreatedAndNotDeleted();
RaiseEvent(SimpleMapper.Map(command, new WebhookDeleted()));
}
private void VerifyNotCreated()
{
if (isCreated)
{
throw new DomainException("Webhook has already been created.");
}
}
private void VerifyCreatedAndNotDeleted()
{
if (isDeleted || !isCreated)
{
throw new DomainException("Webhook has already been deleted or not created yet.");
}
}
protected override void DispatchEvent(Envelope<IEvent> @event)
{
this.DispatchAction(@event.Payload);
}
}
}

5
src/Squidex.Infrastructure/CQRS/Commands/DefaultDomainObjectFactory.cs

@ -27,6 +27,11 @@ namespace Squidex.Infrastructure.CQRS.Commands
{ {
var factoryFunction = (DomainObjectFactoryFunction<T>)serviceProvider.GetService(typeof(DomainObjectFactoryFunction<T>)); var factoryFunction = (DomainObjectFactoryFunction<T>)serviceProvider.GetService(typeof(DomainObjectFactoryFunction<T>));
if (factoryFunction == null)
{
throw new InvalidOperationException($"No factory registered for {typeof(T)}");
}
var domainObject = factoryFunction.Invoke(id); var domainObject = factoryFunction.Invoke(id);
if (domainObject.Version != -1) if (domainObject.Version != -1)

22
src/Squidex.Infrastructure/Http/DumpFormatter.cs

@ -18,7 +18,7 @@ namespace Squidex.Infrastructure.Http
{ {
public static class DumpFormatter public static class DumpFormatter
{ {
public static string BuildDump(HttpRequestMessage request, HttpResponseMessage response, string requestBody, string responseBody, TimeSpan elapsed) public static string BuildDump(HttpRequestMessage request, HttpResponseMessage response, string requestBody, string responseBody, TimeSpan elapsed, bool isTimeout)
{ {
var writer = new StringBuilder(); var writer = new StringBuilder();
@ -29,7 +29,7 @@ namespace Squidex.Infrastructure.Http
writer.AppendLine(); writer.AppendLine();
writer.AppendLine("Response:"); writer.AppendLine("Response:");
writer.AppendResponse(response, responseBody, elapsed); writer.AppendResponse(response, responseBody, elapsed, isTimeout);
return writer.ToString(); return writer.ToString();
} }
@ -50,7 +50,7 @@ namespace Squidex.Infrastructure.Http
} }
} }
private static void AppendResponse(this StringBuilder writer, HttpResponseMessage response, string responseBody, TimeSpan elapsed) private static void AppendResponse(this StringBuilder writer, HttpResponseMessage response, string responseBody, TimeSpan elapsed, bool isTimeout)
{ {
if (response != null) if (response != null)
{ {
@ -61,17 +61,21 @@ namespace Squidex.Infrastructure.Http
writer.AppendHeaders(response.Headers); writer.AppendHeaders(response.Headers);
writer.AppendHeaders(response.Content?.Headers); writer.AppendHeaders(response.Content?.Headers);
}
if (!string.IsNullOrWhiteSpace(responseBody)) if (!string.IsNullOrWhiteSpace(responseBody))
{ {
writer.AppendLine(); writer.AppendLine();
writer.AppendLine(responseBody); writer.AppendLine(responseBody);
} }
if (response != null)
{
writer.AppendLine(); writer.AppendLine();
writer.AppendLine($"Elapsed: {elapsed}"); writer.AppendLine($"Elapsed: {elapsed}");
} }
else
if (isTimeout)
{ {
writer.AppendLine($"Timeout after {elapsed}"); writer.AppendLine($"Timeout after {elapsed}");
} }

1
src/Squidex/Config/Domain/ReadModule.cs

@ -21,6 +21,7 @@ using Squidex.Domain.Apps.Read.History;
using Squidex.Domain.Apps.Read.Schemas; using Squidex.Domain.Apps.Read.Schemas;
using Squidex.Domain.Apps.Read.Schemas.Services; using Squidex.Domain.Apps.Read.Schemas.Services;
using Squidex.Domain.Apps.Read.Schemas.Services.Implementations; using Squidex.Domain.Apps.Read.Schemas.Services.Implementations;
using Squidex.Domain.Apps.Read.Webhooks;
using Squidex.Domain.Users; using Squidex.Domain.Users;
using Squidex.Infrastructure; using Squidex.Infrastructure;
using Squidex.Infrastructure.Assets; using Squidex.Infrastructure.Assets;

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

@ -23,8 +23,10 @@ using Squidex.Domain.Apps.Read.MongoDb.Assets;
using Squidex.Domain.Apps.Read.MongoDb.Contents; using Squidex.Domain.Apps.Read.MongoDb.Contents;
using Squidex.Domain.Apps.Read.MongoDb.History; using Squidex.Domain.Apps.Read.MongoDb.History;
using Squidex.Domain.Apps.Read.MongoDb.Schemas; using Squidex.Domain.Apps.Read.MongoDb.Schemas;
using Squidex.Domain.Apps.Read.MongoDb.Webhooks;
using Squidex.Domain.Apps.Read.Schemas.Repositories; using Squidex.Domain.Apps.Read.Schemas.Repositories;
using Squidex.Domain.Apps.Read.Schemas.Services.Implementations; using Squidex.Domain.Apps.Read.Schemas.Services.Implementations;
using Squidex.Domain.Apps.Read.Webhooks.Repositories;
using Squidex.Domain.Users; using Squidex.Domain.Users;
using Squidex.Domain.Users.MongoDb; using Squidex.Domain.Users.MongoDb;
using Squidex.Domain.Users.MongoDb.Infrastructure; using Squidex.Domain.Users.MongoDb.Infrastructure;
@ -171,9 +173,9 @@ namespace Squidex.Config.Domain
.AsSelf() .AsSelf()
.SingleInstance(); .SingleInstance();
builder.RegisterType<MongoSchemaWebhookRepository>() builder.RegisterType<MongoWebhookRepository>()
.WithParameter(ResolvedParameter.ForNamed<IMongoDatabase>(MongoDatabaseRegistration)) .WithParameter(ResolvedParameter.ForNamed<IMongoDatabase>(MongoDatabaseRegistration))
.As<ISchemaWebhookRepository>() .As<IWebhookRepository>()
.As<IEventConsumer>() .As<IEventConsumer>()
.As<IExternalSystem>() .As<IExternalSystem>()
.AsSelf() .AsSelf()

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

@ -13,6 +13,7 @@ using Squidex.Domain.Apps.Write.Apps;
using Squidex.Domain.Apps.Write.Assets; using Squidex.Domain.Apps.Write.Assets;
using Squidex.Domain.Apps.Write.Contents; using Squidex.Domain.Apps.Write.Contents;
using Squidex.Domain.Apps.Write.Schemas; using Squidex.Domain.Apps.Write.Schemas;
using Squidex.Domain.Apps.Write.Webhooks;
using Squidex.Infrastructure.CQRS.Commands; using Squidex.Infrastructure.CQRS.Commands;
using Squidex.Pipeline.CommandHandlers; using Squidex.Pipeline.CommandHandlers;
@ -71,6 +72,10 @@ namespace Squidex.Config.Domain
.As<ICommandMiddleware>() .As<ICommandMiddleware>()
.SingleInstance(); .SingleInstance();
builder.RegisterType<WebhookCommandMiddleware>()
.As<ICommandMiddleware>()
.SingleInstance();
builder.RegisterType<ETagCommandMiddleware>() builder.RegisterType<ETagCommandMiddleware>()
.As<ICommandMiddleware>() .As<ICommandMiddleware>()
.SingleInstance(); .SingleInstance();
@ -87,6 +92,10 @@ namespace Squidex.Config.Domain
.AsSelf() .AsSelf()
.SingleInstance(); .SingleInstance();
builder.Register<DomainObjectFactoryFunction<WebhookDomainObject>>(c => (id => new WebhookDomainObject(id, -1)))
.AsSelf()
.SingleInstance();
builder.Register<DomainObjectFactoryFunction<SchemaDomainObject>>(c => builder.Register<DomainObjectFactoryFunction<SchemaDomainObject>>(c =>
{ {
var fieldRegistry = c.Resolve<FieldRegistry>(); var fieldRegistry = c.Resolve<FieldRegistry>();

2
src/Squidex/Controllers/Api/Apps/AppsController.cs

@ -96,7 +96,7 @@ namespace Squidex.Controllers.Api.Apps
var context = await CommandBus.PublishAsync(command); var context = await CommandBus.PublishAsync(command);
var result = context.Result<EntityCreatedResult<Guid>>(); var result = context.Result<EntityCreatedResult<Guid>>();
var response = new EntityCreatedDto { Id = result.ToString(), Version = result.Version }; var response = new EntityCreatedDto { Id = result.IdOrValue.ToString(), Version = result.Version };
return CreatedAtAction(nameof(GetApps), response); return CreatedAtAction(nameof(GetApps), response);
} }

4
src/Squidex/Controllers/Api/Schemas/SchemaFieldsController.cs

@ -59,8 +59,8 @@ namespace Squidex.Controllers.Api.Schemas
var context = await CommandBus.PublishAsync(command); var context = await CommandBus.PublishAsync(command);
var result = context.Result<EntityCreatedResult<long>>().IdOrValue; var result = context.Result<EntityCreatedResult<long>>();
var response = new EntityCreatedDto { Id = result.ToString() }; var response = new EntityCreatedDto { Id = result.IdOrValue.ToString(), Version = result.Version };
return StatusCode(201, response); return StatusCode(201, response);
} }

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

@ -122,9 +122,12 @@ namespace Squidex.Controllers.Api.Schemas
{ {
var command = request.ToCommand(); var command = request.ToCommand();
await CommandBus.PublishAsync(command); var context = await CommandBus.PublishAsync(command);
return CreatedAtAction(nameof(GetSchema), new { name = request.Name }, new EntityCreatedDto { Id = command.Name }); var result = context.Result<EntityCreatedResult<Guid>>();
var response = new EntityCreatedDto { Id = command.Name, Version = result.Version };
return CreatedAtAction(nameof(GetSchema), new { name = request.Name }, response);
} }
/// <summary> /// <summary>

9
src/Squidex/Controllers/Api/Webhooks/Models/CreateWebhookDto.cs

@ -7,8 +7,11 @@
// ========================================================================== // ==========================================================================
using System; using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
// ReSharper disable CollectionNeverUpdated.Global
namespace Squidex.Controllers.Api.Webhooks.Models namespace Squidex.Controllers.Api.Webhooks.Models
{ {
public class CreateWebhookDto public class CreateWebhookDto
@ -18,5 +21,11 @@ namespace Squidex.Controllers.Api.Webhooks.Models
/// </summary> /// </summary>
[Required] [Required]
public Uri Url { get; set; } public Uri Url { get; set; }
/// <summary>
/// The schema settings.
/// </summary>
[Required]
public List<WebhookSchemaDto> Schemas { get; set; }
} }
} }

29
src/Squidex/Controllers/Api/Webhooks/Models/UpdateWebhookDto.cs

@ -0,0 +1,29 @@
// ==========================================================================
// UpdateWebhookDto.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
namespace Squidex.Controllers.Api.Webhooks.Models
{
public class UpdateWebhookDto
{
/// <summary>
/// The url of the webhook.
/// </summary>
[Required]
public Uri Url { get; set; }
/// <summary>
/// The schema settings.
/// </summary>
[Required]
public List<WebhookSchemaDto> Schemas { get; set; }
}
}

4
src/Squidex/Controllers/Api/Webhooks/Models/WebhookCreatedDto.cs

@ -25,8 +25,8 @@ namespace Squidex.Controllers.Api.Webhooks.Models
public string SharedSecret { get; set; } public string SharedSecret { get; set; }
/// <summary> /// <summary>
/// The id of the schema. /// The version of the schema.
/// </summary> /// </summary>
public string SchemaId { get; set; } public long Version { get; set; }
} }
} }

35
src/Squidex/Controllers/Api/Webhooks/Models/WebhookDto.cs

@ -8,6 +8,9 @@
using System; using System;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using NodaTime;
using Squidex.Infrastructure;
using System.Collections.Generic;
namespace Squidex.Controllers.Api.Webhooks.Models namespace Squidex.Controllers.Api.Webhooks.Models
{ {
@ -19,9 +22,31 @@ namespace Squidex.Controllers.Api.Webhooks.Models
public Guid Id { get; set; } public Guid Id { get; set; }
/// <summary> /// <summary>
/// The id of the schema. /// The user that has created the webhook.
/// </summary> /// </summary>
public Guid SchemaId { get; set; } [Required]
public RefToken CreatedBy { get; set; }
/// <summary>
/// The user that has updated the webhook.
/// </summary>
[Required]
public RefToken LastModifiedBy { get; set; }
/// <summary>
/// The date and time when the webhook has been created.
/// </summary>
public Instant Created { get; set; }
/// <summary>
/// The date and time when the webhook has been modified last.
/// </summary>
public Instant LastModified { get; set; }
/// <summary>
/// The version of the webhook.
/// </summary>
public int Version { get; set; }
/// <summary> /// <summary>
/// The number of succceeded calls. /// The number of succceeded calls.
@ -54,5 +79,11 @@ namespace Squidex.Controllers.Api.Webhooks.Models
/// </summary> /// </summary>
[Required] [Required]
public string SharedSecret { get; set; } public string SharedSecret { get; set; }
/// <summary>
/// The schema settings.
/// </summary>
[Required]
public List<WebhookSchemaDto> Schemas { get; set; }
} }
} }

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save