Browse Source

Started with scripting.

pull/341/head
Sebastian Stehle 7 years ago
parent
commit
522d1192f5
  1. 4
      extensions/Squidex.Extensions/Actions/Fastly/FastlyActionHandler.cs
  2. 4
      src/Squidex.Domain.Apps.Core.Model/Rules/IRuleTriggerVisitor.cs
  3. 10
      src/Squidex.Domain.Apps.Core.Model/Rules/Json/JsonRule.cs
  4. 4
      src/Squidex.Domain.Apps.Core.Model/Rules/RuleJob.cs
  5. 12
      src/Squidex.Domain.Apps.Core.Model/Rules/Triggers/AssetChangedTriggerV2.cs
  6. 16
      src/Squidex.Domain.Apps.Core.Model/Rules/Triggers/ContentChangedTriggerSchemaV2.cs
  7. 6
      src/Squidex.Domain.Apps.Core.Model/Rules/Triggers/ContentChangedTriggerV2.cs
  8. 21
      src/Squidex.Domain.Apps.Core.Operations/HandleRules/EnrichedEvents/EnrichedAssetEvent.cs
  9. 18
      src/Squidex.Domain.Apps.Core.Operations/HandleRules/EnrichedEvents/EnrichedContentEvent.cs
  10. 31
      src/Squidex.Domain.Apps.Core.Operations/HandleRules/EnrichedEvents/EnrichedEntityEvent.cs
  11. 5
      src/Squidex.Domain.Apps.Core.Operations/HandleRules/EnrichedEvents/EnrichedEvent.cs
  12. 2
      src/Squidex.Domain.Apps.Core.Operations/HandleRules/EnrichedEvents/EnrichedSchemaEvent.cs
  13. 5
      src/Squidex.Domain.Apps.Core.Operations/HandleRules/IRuleTriggerHandler.cs
  14. 10
      src/Squidex.Domain.Apps.Core.Operations/HandleRules/RuleService.cs
  15. 7
      src/Squidex.Domain.Apps.Core.Operations/HandleRules/RuleTriggerHandler.cs
  16. 29
      src/Squidex.Domain.Apps.Core.Operations/HandleRules/Triggers/AssetChangedTriggerHandler.cs
  17. 78
      src/Squidex.Domain.Apps.Core.Operations/HandleRules/Triggers/ContentChangedTriggerHandler.cs
  18. 4
      src/Squidex.Domain.Apps.Core.Operations/Scripting/IScriptEngine.cs
  19. 53
      src/Squidex.Domain.Apps.Core.Operations/Scripting/JintScriptEngine.cs
  20. 33
      src/Squidex.Domain.Apps.Core.Operations/Scripting/JintUser.cs
  21. 4
      src/Squidex.Domain.Apps.Entities/Rules/Guards/RuleTriggerValidator.cs
  22. 2
      src/Squidex.Domain.Apps.Entities/Rules/RuleDequeuerGrain.cs
  23. 1
      src/Squidex.Domain.Apps.Entities/Schemas/Guards/GuardSchema.cs
  24. 4
      src/Squidex.Infrastructure/EventSourcing/DefaultEventDataFormatter.cs
  25. 6
      src/Squidex.Infrastructure/IMigrated.cs
  26. 8
      src/Squidex.Infrastructure/Tasks/PartitionedActionBlock.cs
  27. 4
      src/Squidex/Areas/Api/Controllers/Rules/Models/Converters/RuleTriggerDtoFactory.cs
  28. 2
      src/Squidex/Areas/Api/Controllers/Rules/Models/Triggers/AssetChangedRuleTriggerDto.cs
  29. 4
      src/Squidex/Areas/Api/Controllers/Rules/Models/Triggers/ContentChangedRuleTriggerDto.cs
  30. 6
      tests/Squidex.Domain.Apps.Core.Tests/Model/Rules/RuleTests.cs
  31. 12
      tests/Squidex.Domain.Apps.Core.Tests/Operations/HandleRules/RuleServiceTests.cs
  32. 92
      tests/Squidex.Domain.Apps.Core.Tests/Operations/HandleRules/Triggers/AssetChangedTriggerTests.cs
  33. 193
      tests/Squidex.Domain.Apps.Core.Tests/Operations/HandleRules/Triggers/ContentChangedTriggerTests.cs
  34. 2
      tests/Squidex.Domain.Apps.Core.Tests/Operations/Scripting/JintUserTests.cs
  35. 14
      tests/Squidex.Domain.Apps.Entities.Tests/Rules/Guards/GuardRuleTests.cs
  36. 14
      tests/Squidex.Domain.Apps.Entities.Tests/Rules/Guards/Triggers/ContentChangedTriggerTests.cs
  37. 6
      tests/Squidex.Domain.Apps.Entities.Tests/Rules/RuleEnqueuerTests.cs
  38. 8
      tests/Squidex.Domain.Apps.Entities.Tests/Rules/RuleGrainTests.cs
  39. 2
      tests/Squidex.Infrastructure.Tests/EventSourcing/DefaultEventDataFormatterTests.cs
  40. 3
      tools/Migrate_01/OldEvents/AppClientChanged.cs
  41. 3
      tools/Migrate_01/OldEvents/AppClientUpdated.cs
  42. 3
      tools/Migrate_01/OldEvents/AppContributorAssigned.cs
  43. 3
      tools/Migrate_01/OldEvents/ContentArchived.cs
  44. 3
      tools/Migrate_01/OldEvents/ContentPublished.cs
  45. 3
      tools/Migrate_01/OldEvents/ContentRestored.cs
  46. 3
      tools/Migrate_01/OldEvents/ContentUnpublished.cs
  47. 67
      tools/Migrate_01/OldTriggers/AssetChangedTrigger.cs
  48. 45
      tools/Migrate_01/OldTriggers/ContentChangedTrigger.cs
  49. 83
      tools/Migrate_01/OldTriggers/ContentChangedTriggerSchema.cs

4
extensions/Squidex.Extensions/Actions/Fastly/FastlyActionHandler.cs

@ -30,9 +30,11 @@ namespace Squidex.Extensions.Actions.Fastly
protected override (string Description, FastlyJob Data) CreateJob(EnrichedEvent @event, FastlyAction action) protected override (string Description, FastlyJob Data) CreateJob(EnrichedEvent @event, FastlyAction action)
{ {
var id = @event is EnrichedEntityEvent entityEvent ? entityEvent.Id.ToString() : string.Empty;
var ruleJob = new FastlyJob var ruleJob = new FastlyJob
{ {
Key = @event.AggregateId.ToString(), Key = id,
FastlyApiKey = action.ApiKey, FastlyApiKey = action.ApiKey,
FastlyServiceID = action.ServiceId FastlyServiceID = action.ServiceId
}; };

4
src/Squidex.Domain.Apps.Core.Model/Rules/IRuleTriggerVisitor.cs

@ -11,8 +11,8 @@ namespace Squidex.Domain.Apps.Core.Rules
{ {
public interface IRuleTriggerVisitor<out T> public interface IRuleTriggerVisitor<out T>
{ {
T Visit(AssetChangedTrigger trigger); T Visit(AssetChangedTriggerV2 trigger);
T Visit(ContentChangedTrigger trigger); T Visit(ContentChangedTriggerV2 trigger);
} }
} }

10
src/Squidex.Domain.Apps.Core.Model/Rules/Json/JsonRule.cs

@ -6,6 +6,7 @@
// ========================================================================== // ==========================================================================
using Newtonsoft.Json; using Newtonsoft.Json;
using Squidex.Infrastructure;
using Squidex.Infrastructure.Reflection; using Squidex.Infrastructure.Reflection;
namespace Squidex.Domain.Apps.Core.Rules.Json namespace Squidex.Domain.Apps.Core.Rules.Json
@ -32,7 +33,14 @@ namespace Squidex.Domain.Apps.Core.Rules.Json
public Rule ToRule() public Rule ToRule()
{ {
var rule = new Rule(Trigger, Action); var trigger = Trigger;
if (trigger is IMigrated<RuleTrigger> migrated)
{
trigger = migrated.Migrate();
}
var rule = new Rule(trigger, Action);
if (!IsEnabled) if (!IsEnabled)
{ {

4
src/Squidex.Domain.Apps.Core.Model/Rules/RuleJob.cs

@ -16,8 +16,6 @@ namespace Squidex.Domain.Apps.Core.Rules
public Guid AppId { get; set; } public Guid AppId { get; set; }
public Guid AggregateId { get; set; }
public string EventName { get; set; } public string EventName { get; set; }
public string ActionName { get; set; } public string ActionName { get; set; }
@ -26,6 +24,8 @@ namespace Squidex.Domain.Apps.Core.Rules
public string Description { get; set; } public string Description { get; set; }
public long ExecutionPartition { get; set; }
public Instant Created { get; set; } public Instant Created { get; set; }
public Instant Expires { get; set; } public Instant Expires { get; set; }

12
src/Squidex.Domain.Apps.Core.Model/Rules/Triggers/AssetChangedTrigger.cs → src/Squidex.Domain.Apps.Core.Model/Rules/Triggers/AssetChangedTriggerV2.cs

@ -9,16 +9,10 @@ using Squidex.Infrastructure;
namespace Squidex.Domain.Apps.Core.Rules.Triggers namespace Squidex.Domain.Apps.Core.Rules.Triggers
{ {
[TypeName(nameof(AssetChangedTrigger))] [TypeName(nameof(AssetChangedTriggerV2))]
public sealed class AssetChangedTrigger : RuleTrigger public sealed class AssetChangedTriggerV2 : RuleTrigger
{ {
public bool SendCreate { get; set; } public string Condition { get; set; }
public bool SendUpdate { get; set; }
public bool SendRename { get; set; }
public bool SendDelete { get; set; }
public override T Accept<T>(IRuleTriggerVisitor<T> visitor) public override T Accept<T>(IRuleTriggerVisitor<T> visitor)
{ {

16
src/Squidex.Domain.Apps.Core.Model/Rules/Triggers/ContentChangedTriggerSchema.cs → src/Squidex.Domain.Apps.Core.Model/Rules/Triggers/ContentChangedTriggerSchemaV2.cs

@ -9,22 +9,10 @@ using System;
namespace Squidex.Domain.Apps.Core.Rules.Triggers namespace Squidex.Domain.Apps.Core.Rules.Triggers
{ {
public sealed class ContentChangedTriggerSchema : Freezable public sealed class ContentChangedTriggerSchemaV2 : Freezable
{ {
public Guid SchemaId { get; set; } public Guid SchemaId { get; set; }
public bool SendCreate { get; set; } public string Condition { get; set; }
public bool SendUpdate { get; set; }
public bool SendDelete { get; set; }
public bool SendPublish { get; set; }
public bool SendUnpublish { get; set; }
public bool SendArchived { get; set; }
public bool SendRestore { get; set; }
} }
} }

6
src/Squidex.Domain.Apps.Core.Model/Rules/Triggers/ContentChangedTrigger.cs → src/Squidex.Domain.Apps.Core.Model/Rules/Triggers/ContentChangedTriggerV2.cs

@ -10,10 +10,10 @@ using System.Collections.ObjectModel;
namespace Squidex.Domain.Apps.Core.Rules.Triggers namespace Squidex.Domain.Apps.Core.Rules.Triggers
{ {
[TypeName(nameof(ContentChangedTrigger))] [TypeName(nameof(ContentChangedTriggerV2))]
public sealed class ContentChangedTrigger : RuleTrigger public sealed class ContentChangedTriggerV2 : RuleTrigger
{ {
public ReadOnlyCollection<ContentChangedTriggerSchema> Schemas { get; set; } public ReadOnlyCollection<ContentChangedTriggerSchemaV2> Schemas { get; set; }
public bool HandleAll { get; set; } public bool HandleAll { get; set; }

21
src/Squidex.Domain.Apps.Core.Operations/HandleRules/EnrichedEvents/EnrichedAssetEvent.cs

@ -5,26 +5,12 @@
// All rights reserved. Licensed under the MIT license. // All rights reserved. Licensed under the MIT license.
// ========================================================================== // ==========================================================================
using System;
using NodaTime;
using Squidex.Infrastructure;
namespace Squidex.Domain.Apps.Core.HandleRules.EnrichedEvents namespace Squidex.Domain.Apps.Core.HandleRules.EnrichedEvents
{ {
public sealed class EnrichedAssetEvent : EnrichedEvent public sealed class EnrichedAssetEvent : EnrichedEntityEvent
{ {
public EnrichedAssetEventType Type { get; set; } public EnrichedAssetEventType Type { get; set; }
public Guid Id { get; set; }
public Instant Created { get; set; }
public Instant LastModified { get; set; }
public RefToken CreatedBy { get; set; }
public RefToken LastModifiedBy { get; set; }
public string MimeType { get; set; } public string MimeType { get; set; }
public string FileName { get; set; } public string FileName { get; set; }
@ -38,10 +24,5 @@ namespace Squidex.Domain.Apps.Core.HandleRules.EnrichedEvents
public int? PixelWidth { get; set; } public int? PixelWidth { get; set; }
public int? PixelHeight { get; set; } public int? PixelHeight { get; set; }
public override Guid AggregateId
{
get { return Id; }
}
} }
} }

18
src/Squidex.Domain.Apps.Core.Operations/HandleRules/EnrichedEvents/EnrichedContentEvent.cs

@ -5,10 +5,7 @@
// All rights reserved. Licensed under the MIT license. // All rights reserved. Licensed under the MIT license.
// ========================================================================== // ==========================================================================
using System;
using NodaTime;
using Squidex.Domain.Apps.Core.Contents; using Squidex.Domain.Apps.Core.Contents;
using Squidex.Infrastructure;
namespace Squidex.Domain.Apps.Core.HandleRules.EnrichedEvents namespace Squidex.Domain.Apps.Core.HandleRules.EnrichedEvents
{ {
@ -16,23 +13,8 @@ namespace Squidex.Domain.Apps.Core.HandleRules.EnrichedEvents
{ {
public EnrichedContentEventType Type { get; set; } public EnrichedContentEventType Type { get; set; }
public Guid Id { get; set; }
public Instant Created { get; set; }
public Instant LastModified { get; set; }
public RefToken CreatedBy { get; set; }
public RefToken LastModifiedBy { get; set; }
public NamedContentData Data { get; set; } public NamedContentData Data { get; set; }
public Status Status { get; set; } public Status Status { get; set; }
public override Guid AggregateId
{
get { return Id; }
}
} }
} }

31
src/Squidex.Domain.Apps.Core.Operations/HandleRules/EnrichedEvents/EnrichedEntityEvent.cs

@ -0,0 +1,31 @@
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System;
using NodaTime;
using Squidex.Infrastructure;
namespace Squidex.Domain.Apps.Core.HandleRules.EnrichedEvents
{
public abstract class EnrichedEntityEvent : EnrichedEvent
{
public Guid Id { get; set; }
public Instant Created { get; set; }
public Instant LastModified { get; set; }
public RefToken CreatedBy { get; set; }
public RefToken LastModifiedBy { get; set; }
public override void CalculatePartition()
{
Partition = Id.GetHashCode();
}
}
}

5
src/Squidex.Domain.Apps.Core.Operations/HandleRules/EnrichedEvents/EnrichedEvent.cs

@ -25,10 +25,11 @@ namespace Squidex.Domain.Apps.Core.HandleRules.EnrichedEvents
public long Version { get; set; } public long Version { get; set; }
[IgnoreDataMember] public long Partition { get; set; }
public abstract Guid AggregateId { get; }
[IgnoreDataMember] [IgnoreDataMember]
public IUser User { get; set; } public IUser User { get; set; }
public abstract void CalculatePartition();
} }
} }

2
src/Squidex.Domain.Apps.Core.Operations/HandleRules/EnrichedEvents/EnrichedSchemaEvent.cs

@ -10,7 +10,7 @@ using Squidex.Infrastructure;
namespace Squidex.Domain.Apps.Core.HandleRules.EnrichedEvents namespace Squidex.Domain.Apps.Core.HandleRules.EnrichedEvents
{ {
public abstract class EnrichedSchemaEvent : EnrichedEvent public abstract class EnrichedSchemaEvent : EnrichedEntityEvent
{ {
public NamedId<Guid> SchemaId { get; set; } public NamedId<Guid> SchemaId { get; set; }
} }

5
src/Squidex.Domain.Apps.Core.Operations/HandleRules/IRuleTriggerHandler.cs

@ -6,9 +6,8 @@
// ========================================================================== // ==========================================================================
using System; using System;
using Squidex.Domain.Apps.Core.HandleRules.EnrichedEvents;
using Squidex.Domain.Apps.Core.Rules; using Squidex.Domain.Apps.Core.Rules;
using Squidex.Domain.Apps.Events;
using Squidex.Infrastructure.EventSourcing;
namespace Squidex.Domain.Apps.Core.HandleRules namespace Squidex.Domain.Apps.Core.HandleRules
{ {
@ -16,6 +15,6 @@ namespace Squidex.Domain.Apps.Core.HandleRules
{ {
Type TriggerType { get; } Type TriggerType { get; }
bool Triggers(Envelope<AppEvent> @event, RuleTrigger trigger); bool Triggers(EnrichedEvent @event, RuleTrigger trigger);
} }
} }

10
src/Squidex.Domain.Apps.Core.Operations/HandleRules/RuleService.cs

@ -85,7 +85,9 @@ namespace Squidex.Domain.Apps.Core.HandleRules
var appEventEnvelope = @event.To<AppEvent>(); var appEventEnvelope = @event.To<AppEvent>();
if (!triggerHandler.Triggers(appEventEnvelope, rule.Trigger)) var enrichedEvent = await eventEnricher.EnrichAsync(appEventEnvelope);
if (!triggerHandler.Triggers(enrichedEvent, rule.Trigger))
{ {
return null; return null;
} }
@ -104,22 +106,22 @@ namespace Squidex.Domain.Apps.Core.HandleRules
return null; return null;
} }
var enrichedEvent = await eventEnricher.EnrichAsync(appEventEnvelope);
var actionName = typeNameRegistry.GetName(actionType); var actionName = typeNameRegistry.GetName(actionType);
var actionData = await actionHandler.CreateJobAsync(enrichedEvent, rule.Action); var actionData = await actionHandler.CreateJobAsync(enrichedEvent, rule.Action);
var json = jsonSerializer.Serialize(actionData.Data); var json = jsonSerializer.Serialize(actionData.Data);
enrichedEvent.CalculatePartition();
var job = new RuleJob var job = new RuleJob
{ {
JobId = Guid.NewGuid(), JobId = Guid.NewGuid(),
ActionName = actionName, ActionName = actionName,
ActionData = json, ActionData = json,
AggregateId = enrichedEvent.AggregateId,
AppId = appEvent.AppId.Id, AppId = appEvent.AppId.Id,
Created = now, Created = now,
EventName = enrichedEvent.Name, EventName = enrichedEvent.Name,
ExecutionPartition = enrichedEvent.Partition,
Expires = expires, Expires = expires,
Description = actionData.Description Description = actionData.Description
}; };

7
src/Squidex.Domain.Apps.Core.Operations/HandleRules/RuleTriggerHandler.cs

@ -6,9 +6,8 @@
// ========================================================================== // ==========================================================================
using System; using System;
using Squidex.Domain.Apps.Core.HandleRules.EnrichedEvents;
using Squidex.Domain.Apps.Core.Rules; using Squidex.Domain.Apps.Core.Rules;
using Squidex.Domain.Apps.Events;
using Squidex.Infrastructure.EventSourcing;
namespace Squidex.Domain.Apps.Core.HandleRules namespace Squidex.Domain.Apps.Core.HandleRules
{ {
@ -19,11 +18,11 @@ namespace Squidex.Domain.Apps.Core.HandleRules
get { return typeof(T); } get { return typeof(T); }
} }
bool IRuleTriggerHandler.Triggers(Envelope<AppEvent> @event, RuleTrigger trigger) bool IRuleTriggerHandler.Triggers(EnrichedEvent @event, RuleTrigger trigger)
{ {
return Triggers(@event, (T)trigger); return Triggers(@event, (T)trigger);
} }
protected abstract bool Triggers(Envelope<AppEvent> @event, T trigger); protected abstract bool Triggers(EnrichedEvent @event, T trigger);
} }
} }

29
src/Squidex.Domain.Apps.Core.Operations/HandleRules/Triggers/AssetChangedTriggerHandler.cs

@ -5,27 +5,32 @@
// All rights reserved. Licensed under the MIT license. // All rights reserved. Licensed under the MIT license.
// ========================================================================== // ==========================================================================
using Squidex.Domain.Apps.Core.HandleRules.EnrichedEvents;
using Squidex.Domain.Apps.Core.Rules.Triggers; using Squidex.Domain.Apps.Core.Rules.Triggers;
using Squidex.Domain.Apps.Events; using Squidex.Domain.Apps.Core.Scripting;
using Squidex.Domain.Apps.Events.Assets; using Squidex.Infrastructure;
using Squidex.Infrastructure.EventSourcing;
namespace Squidex.Domain.Apps.Core.HandleRules.Triggers namespace Squidex.Domain.Apps.Core.HandleRules.Triggers
{ {
public sealed class AssetChangedTriggerHandler : RuleTriggerHandler<AssetChangedTrigger> public sealed class AssetChangedTriggerHandler : RuleTriggerHandler<AssetChangedTriggerV2>
{ {
protected override bool Triggers(Envelope<AppEvent> @event, AssetChangedTrigger trigger) private readonly IScriptEngine scriptEngine;
public AssetChangedTriggerHandler(IScriptEngine scriptEngine)
{
Guard.NotNull(scriptEngine, nameof(scriptEngine));
this.scriptEngine = scriptEngine;
}
protected override bool Triggers(EnrichedEvent @event, AssetChangedTriggerV2 trigger)
{ {
return @event.Payload is AssetEvent assetEvent && MatchsType(trigger, assetEvent); return @event is EnrichedAssetEvent assetEvent && MatchsType(trigger, assetEvent);
} }
private static bool MatchsType(AssetChangedTrigger trigger, AssetEvent @event) private bool MatchsType(AssetChangedTriggerV2 trigger, EnrichedAssetEvent assetEvent)
{ {
return return string.IsNullOrWhiteSpace(trigger.Condition) || scriptEngine.Evaluate("event", assetEvent, trigger.Condition);
trigger.SendCreate && @event is AssetCreated ||
trigger.SendUpdate && @event is AssetUpdated ||
trigger.SendDelete && @event is AssetDeleted ||
trigger.SendRename && @event is AssetRenamed;
} }
} }
} }

78
src/Squidex.Domain.Apps.Core.Operations/HandleRules/Triggers/ContentChangedTriggerHandler.cs

@ -5,32 +5,36 @@
// All rights reserved. Licensed under the MIT license. // All rights reserved. Licensed under the MIT license.
// ========================================================================== // ==========================================================================
using Squidex.Domain.Apps.Core.Contents; using Squidex.Domain.Apps.Core.HandleRules.EnrichedEvents;
using Squidex.Domain.Apps.Core.Rules.Triggers; using Squidex.Domain.Apps.Core.Rules.Triggers;
using Squidex.Domain.Apps.Events; using Squidex.Domain.Apps.Core.Scripting;
using Squidex.Domain.Apps.Events.Contents; using Squidex.Infrastructure;
using Squidex.Infrastructure.EventSourcing;
namespace Squidex.Domain.Apps.Core.HandleRules.Triggers namespace Squidex.Domain.Apps.Core.HandleRules.Triggers
{ {
public sealed class ContentChangedTriggerHandler : RuleTriggerHandler<ContentChangedTrigger> public sealed class ContentChangedTriggerHandler : RuleTriggerHandler<ContentChangedTriggerV2>
{ {
protected override bool Triggers(Envelope<AppEvent> @event, ContentChangedTrigger trigger) private readonly IScriptEngine scriptEngine;
public ContentChangedTriggerHandler(IScriptEngine scriptEngine)
{ {
if (trigger.HandleAll && Guard.NotNull(scriptEngine, nameof(scriptEngine));
@event.Payload is ContentEvent &&
!(@event.Payload is ContentChangesPublished) && this.scriptEngine = scriptEngine;
!(@event.Payload is ContentChangesDiscarded) && }
!(@event.Payload is ContentUpdateProposed))
protected override bool Triggers(EnrichedEvent @event, ContentChangedTriggerV2 trigger)
{
if (trigger.HandleAll)
{ {
return true; return true;
} }
if (trigger.Schemas != null && @event.Payload is SchemaEvent schemaEvent) if (trigger.Schemas != null && @event is EnrichedSchemaEvent schemaEvent)
{ {
foreach (var schema in trigger.Schemas) foreach (var schema in trigger.Schemas)
{ {
if (MatchsSchema(schema, schemaEvent) && MatchsType(schema, schemaEvent)) if (MatchsSchema(schema, schemaEvent) && MatchsCondition(schema, schemaEvent))
{ {
return true; return true;
} }
@ -40,56 +44,14 @@ namespace Squidex.Domain.Apps.Core.HandleRules.Triggers
return false; return false;
} }
private static bool MatchsSchema(ContentChangedTriggerSchema schema, SchemaEvent @event) private bool MatchsSchema(ContentChangedTriggerSchemaV2 schema, EnrichedSchemaEvent @event)
{ {
return @event.SchemaId.Id == schema.SchemaId; return @event.SchemaId.Id == schema.SchemaId;
} }
private static bool MatchsType(ContentChangedTriggerSchema schema, SchemaEvent @event) private bool MatchsCondition(ContentChangedTriggerSchemaV2 schema, EnrichedSchemaEvent @event)
{
return
IsArchived(schema, @event) ||
IsCreate(schema, @event) ||
IsDelete(schema, @event) ||
IsPublished(schema, @event) ||
IsRestored(schema, @event) ||
IsUpdate(schema, @event) ||
IsUnpublished(schema, @event);
}
private static bool IsPublished(ContentChangedTriggerSchema schema, SchemaEvent @event)
{
return schema.SendPublish && @event is ContentStatusChanged statusChanged && statusChanged.Change == StatusChange.Published;
}
private static bool IsRestored(ContentChangedTriggerSchema schema, SchemaEvent @event)
{
return schema.SendRestore && @event is ContentStatusChanged statusChanged && statusChanged.Change == StatusChange.Restored;
}
private static bool IsArchived(ContentChangedTriggerSchema schema, SchemaEvent @event)
{
return schema.SendArchived && @event is ContentStatusChanged statusChanged && statusChanged.Change == StatusChange.Archived;
}
private static bool IsUnpublished(ContentChangedTriggerSchema schema, SchemaEvent @event)
{
return schema.SendUnpublish && @event is ContentStatusChanged statusChanged && statusChanged.Change == StatusChange.Unpublished;
}
private static bool IsCreate(ContentChangedTriggerSchema schema, SchemaEvent @event)
{
return schema.SendCreate && @event is ContentCreated;
}
private static bool IsUpdate(ContentChangedTriggerSchema schema, SchemaEvent @event)
{
return schema.SendUpdate && @event is ContentUpdated || schema.SendUpdate && @event is ContentChangesPublished;
}
private static bool IsDelete(ContentChangedTriggerSchema schema, SchemaEvent @event)
{ {
return schema.SendDelete && @event is ContentDeleted; return string.IsNullOrWhiteSpace(schema.Condition) || scriptEngine.Evaluate("event", @event, schema.Condition);
} }
} }
} }

4
src/Squidex.Domain.Apps.Core.Operations/Scripting/IScriptEngine.cs

@ -16,5 +16,9 @@ namespace Squidex.Domain.Apps.Core.Scripting
NamedContentData ExecuteAndTransform(ScriptContext context, string script); NamedContentData ExecuteAndTransform(ScriptContext context, string script);
NamedContentData Transform(ScriptContext context, string script); NamedContentData Transform(ScriptContext context, string script);
bool Evaluate(string name, object context, string script);
string Interpolate(string name, object context, string script);
} }
} }

53
src/Squidex.Domain.Apps.Core.Operations/Scripting/JintScriptEngine.cs

@ -6,6 +6,9 @@
// ========================================================================== // ==========================================================================
using System; using System;
using System.Collections.Generic;
using System.Reflection;
using System.Security.Claims;
using Jint; using Jint;
using Jint.Native; using Jint.Native;
using Jint.Native.Object; using Jint.Native.Object;
@ -22,6 +25,14 @@ namespace Squidex.Domain.Apps.Core.Scripting
{ {
public TimeSpan Timeout { get; set; } = TimeSpan.FromMilliseconds(200); public TimeSpan Timeout { get; set; } = TimeSpan.FromMilliseconds(200);
static JintScriptEngine()
{
var typeMappers = (Dictionary<Type, Func<Engine, object, JsValue>>)typeof(Engine).GetField("TypeMappers", BindingFlags.Static | BindingFlags.NonPublic).GetValue(null);
typeMappers.Add(typeof(NamedContentData), (engine, data) => new ContentDataObject(engine, (NamedContentData)data));
typeMappers.Add(typeof(ClaimsPrincipal), (engine, data) => JintUser.Create(engine, (ClaimsPrincipal)data));
}
public void Execute(ScriptContext context, string script) public void Execute(ScriptContext context, string script)
{ {
Guard.NotNull(context, nameof(context)); Guard.NotNull(context, nameof(context));
@ -143,7 +154,7 @@ namespace Squidex.Domain.Apps.Core.Scripting
if (context.User != null) if (context.User != null)
{ {
contextInstance.FastAddProperty("user", new JintUser(engine, context.User), false, true, false); contextInstance.FastAddProperty("user", JintUser.Create(engine, context.User), false, true, false);
} }
if (!string.IsNullOrWhiteSpace(context.Operation)) if (!string.IsNullOrWhiteSpace(context.Operation))
@ -152,7 +163,7 @@ namespace Squidex.Domain.Apps.Core.Scripting
} }
engine.SetValue("ctx", contextInstance); engine.SetValue("ctx", contextInstance);
engine.SetValue("context", contextInstance);
engine.SetValue("slugify", new ClrFunctionInstance(engine, Slugify)); engine.SetValue("slugify", new ClrFunctionInstance(engine, Slugify));
return engine; return engine;
@ -197,5 +208,43 @@ namespace Squidex.Domain.Apps.Core.Scripting
throw new ValidationException("Script rejected the operation.", errors); throw new ValidationException("Script rejected the operation.", errors);
})); }));
} }
public bool Evaluate(string name, object context, string script)
{
try
{
var result =
new Engine(options => options.TimeoutInterval(Timeout).Strict())
.SetValue(name, context)
.Execute(script)
.GetCompletionValue()
.ToObject();
return (bool)result;
}
catch
{
return false;
}
}
public string Interpolate(string name, object context, string script)
{
try
{
var result =
new Engine(options => options.TimeoutInterval(Timeout).Strict())
.SetValue(name, context)
.Execute(script)
.GetCompletionValue()
.ToObject();
return (string)result;
}
catch
{
return string.Empty;
}
}
} }
} }

33
src/Squidex.Domain.Apps.Core.Operations/Scripting/JintUser.cs

@ -8,18 +8,16 @@
using System.Linq; using System.Linq;
using System.Security.Claims; using System.Security.Claims;
using Jint; using Jint;
using Jint.Native; using Jint.Runtime.Interop;
using Jint.Native.Object;
using Squidex.Infrastructure.Security; using Squidex.Infrastructure.Security;
namespace Squidex.Domain.Apps.Core.Scripting namespace Squidex.Domain.Apps.Core.Scripting
{ {
public sealed class JintUser : ObjectInstance public static class JintUser
{ {
private static readonly char[] ClaimSeparators = { '/', '.', ':' }; private static readonly char[] ClaimSeparators = { '/', '.', ':' };
public JintUser(Engine engine, ClaimsPrincipal principal) public static ObjectWrapper Create(Engine engine, ClaimsPrincipal principal)
: base(engine)
{ {
var id = principal.OpenIdSubject(); var id = principal.OpenIdSubject();
@ -30,22 +28,19 @@ namespace Squidex.Domain.Apps.Core.Scripting
id = principal.OpenIdClientId(); id = principal.OpenIdClientId();
} }
FastAddProperty("id", id, false, true, false); var claims =
FastAddProperty("isClient", isClient, false, true, false); principal.Claims.GroupBy(x => x.Type)
.ToDictionary(
x => x.Key.Split(ClaimSeparators).Last(),
x => x.Select(y => y.Value).ToArray());
FastAddProperty("email", principal.OpenIdEmail(), false, true, false); return new ObjectWrapper(engine, new
var claimsInstance = new ObjectInstance(engine);
foreach (var group in principal.Claims.GroupBy(x => x.Type))
{ {
var propertyName = group.Key.Split(ClaimSeparators).Last(); Id = id,
var propertyValue = engine.Array.Construct(group.Select(x => new JsValue(x.Value)).ToArray()); IsClient = isClient,
Email = principal.OpenIdEmail(),
claimsInstance.FastAddProperty(propertyName, propertyValue, false, true, false); Claims = claims,
} });
FastAddProperty("claims", claimsInstance, false, true, false);
} }
} }
} }

4
src/Squidex.Domain.Apps.Entities/Rules/Guards/RuleTriggerValidator.cs

@ -35,12 +35,12 @@ namespace Squidex.Domain.Apps.Entities.Rules.Guards
return action.Accept(visitor); return action.Accept(visitor);
} }
public Task<IEnumerable<ValidationError>> Visit(AssetChangedTrigger trigger) public Task<IEnumerable<ValidationError>> Visit(AssetChangedTriggerV2 trigger)
{ {
return Task.FromResult(Enumerable.Empty<ValidationError>()); return Task.FromResult(Enumerable.Empty<ValidationError>());
} }
public async Task<IEnumerable<ValidationError>> Visit(ContentChangedTrigger trigger) public async Task<IEnumerable<ValidationError>> Visit(ContentChangedTriggerV2 trigger)
{ {
if (trigger.Schemas != null) if (trigger.Schemas != null)
{ {

2
src/Squidex.Domain.Apps.Entities/Rules/RuleDequeuerGrain.cs

@ -45,7 +45,7 @@ namespace Squidex.Domain.Apps.Entities.Rules
this.log = log; this.log = log;
requestBlock = requestBlock =
new PartitionedActionBlock<IRuleEventEntity>(HandleAsync, x => x.Job.AggregateId.GetHashCode(), new PartitionedActionBlock<IRuleEventEntity>(HandleAsync, x => x.Job.ExecutionPartition,
new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = 32, BoundedCapacity = 32 }); new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = 32, BoundedCapacity = 32 });
} }

1
src/Squidex.Domain.Apps.Entities/Schemas/Guards/GuardSchema.cs

@ -5,7 +5,6 @@
// All rights reserved. Licensed under the MIT license. // All rights reserved. Licensed under the MIT license.
// ========================================================================== // ==========================================================================
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;

4
src/Squidex.Infrastructure/EventSourcing/DefaultEventDataFormatter.cs

@ -30,7 +30,7 @@ namespace Squidex.Infrastructure.EventSourcing
var payloadType = typeNameRegistry.GetType(eventData.Type); var payloadType = typeNameRegistry.GetType(eventData.Type);
var payloadObj = serializer.Deserialize<IEvent>(eventData.Payload, payloadType, stringConverter); var payloadObj = serializer.Deserialize<IEvent>(eventData.Payload, payloadType, stringConverter);
if (payloadObj is IMigratedEvent migratedEvent) if (payloadObj is IMigrated<IEvent> migratedEvent)
{ {
payloadObj = migratedEvent.Migrate(); payloadObj = migratedEvent.Migrate();
} }
@ -44,7 +44,7 @@ namespace Squidex.Infrastructure.EventSourcing
{ {
var eventPayload = envelope.Payload; var eventPayload = envelope.Payload;
if (migrate && eventPayload is IMigratedEvent migratedEvent) if (migrate && eventPayload is IMigrated<IEvent> migratedEvent)
{ {
eventPayload = migratedEvent.Migrate(); eventPayload = migratedEvent.Migrate();
} }

6
src/Squidex.Infrastructure/EventSourcing/IMigratedEvent.cs → src/Squidex.Infrastructure/IMigrated.cs

@ -5,10 +5,10 @@
// All rights reserved. Licensed under the MIT license. // All rights reserved. Licensed under the MIT license.
// ========================================================================== // ==========================================================================
namespace Squidex.Infrastructure.EventSourcing namespace Squidex.Infrastructure
{ {
public interface IMigratedEvent public interface IMigrated<T>
{ {
IEvent Migrate(); T Migrate();
} }
} }

8
src/Squidex.Infrastructure/Tasks/PartitionedActionBlock.cs

@ -23,22 +23,22 @@ namespace Squidex.Infrastructure.Tasks
get { return Task.WhenAll(workers.Select(x => x.Completion)); } get { return Task.WhenAll(workers.Select(x => x.Completion)); }
} }
public PartitionedActionBlock(Action<TInput> action, Func<TInput, int> partitioner) public PartitionedActionBlock(Action<TInput> action, Func<TInput, long> partitioner)
: this (action?.ToAsync(), partitioner, new ExecutionDataflowBlockOptions()) : this (action?.ToAsync(), partitioner, new ExecutionDataflowBlockOptions())
{ {
} }
public PartitionedActionBlock(Func<TInput, Task> action, Func<TInput, int> partitioner) public PartitionedActionBlock(Func<TInput, Task> action, Func<TInput, long> partitioner)
: this(action, partitioner, new ExecutionDataflowBlockOptions()) : this(action, partitioner, new ExecutionDataflowBlockOptions())
{ {
} }
public PartitionedActionBlock(Action<TInput> action, Func<TInput, int> partitioner, ExecutionDataflowBlockOptions dataflowBlockOptions) public PartitionedActionBlock(Action<TInput> action, Func<TInput, long> partitioner, ExecutionDataflowBlockOptions dataflowBlockOptions)
: this(action?.ToAsync(), partitioner, dataflowBlockOptions) : this(action?.ToAsync(), partitioner, dataflowBlockOptions)
{ {
} }
public PartitionedActionBlock(Func<TInput, Task> action, Func<TInput, int> partitioner, ExecutionDataflowBlockOptions dataflowBlockOptions) public PartitionedActionBlock(Func<TInput, Task> action, Func<TInput, long> partitioner, ExecutionDataflowBlockOptions dataflowBlockOptions)
{ {
Guard.NotNull(action, nameof(action)); Guard.NotNull(action, nameof(action));
Guard.NotNull(partitioner, nameof(partitioner)); Guard.NotNull(partitioner, nameof(partitioner));

4
src/Squidex/Areas/Api/Controllers/Rules/Models/Converters/RuleTriggerDtoFactory.cs

@ -26,12 +26,12 @@ namespace Squidex.Areas.Api.Controllers.Rules.Models.Converters
return properties.Accept(Instance); return properties.Accept(Instance);
} }
public RuleTriggerDto Visit(AssetChangedTrigger trigger) public RuleTriggerDto Visit(AssetChangedTriggerV2 trigger)
{ {
return SimpleMapper.Map(trigger, new AssetChangedRuleTriggerDto()); return SimpleMapper.Map(trigger, new AssetChangedRuleTriggerDto());
} }
public RuleTriggerDto Visit(ContentChangedTrigger trigger) public RuleTriggerDto Visit(ContentChangedTriggerV2 trigger)
{ {
var schemas = trigger.Schemas.Select(x => SimpleMapper.Map(x, new ContentChangedRuleTriggerSchemaDto())).ToArray(); var schemas = trigger.Schemas.Select(x => SimpleMapper.Map(x, new ContentChangedRuleTriggerSchemaDto())).ToArray();

2
src/Squidex/Areas/Api/Controllers/Rules/Models/Triggers/AssetChangedRuleTriggerDto.cs

@ -35,7 +35,7 @@ namespace Squidex.Areas.Api.Controllers.Rules.Models.Triggers
public override RuleTrigger ToTrigger() public override RuleTrigger ToTrigger()
{ {
return SimpleMapper.Map(this, new AssetChangedTrigger()); return SimpleMapper.Map(this, new AssetChangedTriggerV2());
} }
} }
} }

4
src/Squidex/Areas/Api/Controllers/Rules/Models/Triggers/ContentChangedRuleTriggerDto.cs

@ -29,9 +29,9 @@ namespace Squidex.Areas.Api.Controllers.Rules.Models.Triggers
public override RuleTrigger ToTrigger() public override RuleTrigger ToTrigger()
{ {
var schemas = Schemas.Select(x => SimpleMapper.Map(x, new ContentChangedTriggerSchema())).ToReadOnlyCollection(); var schemas = Schemas.Select(x => SimpleMapper.Map(x, new ContentChangedTriggerSchemaV2())).ToReadOnlyCollection();
return new ContentChangedTrigger { HandleAll = HandleAll, Schemas = schemas }; return new ContentChangedTriggerV2 { HandleAll = HandleAll, Schemas = schemas };
} }
} }
} }

6
tests/Squidex.Domain.Apps.Core.Tests/Model/Rules/RuleTests.cs

@ -26,7 +26,7 @@ namespace Squidex.Domain.Apps.Core.Model.Rules
.Select(x => new[] { x }) .Select(x => new[] { x })
.ToList(); .ToList();
private readonly Rule rule_0 = new Rule(new ContentChangedTrigger(), new TestAction1()); private readonly Rule rule_0 = new Rule(new ContentChangedTriggerV2(), new TestAction1());
public sealed class OtherTrigger : RuleTrigger public sealed class OtherTrigger : RuleTrigger
{ {
@ -49,7 +49,7 @@ namespace Squidex.Domain.Apps.Core.Model.Rules
[Fact] [Fact]
public void Should_create_with_trigger_and_action() public void Should_create_with_trigger_and_action()
{ {
var ruleTrigger = new ContentChangedTrigger(); var ruleTrigger = new ContentChangedTriggerV2();
var ruleAction = new TestAction1(); var ruleAction = new TestAction1();
var newRule = new Rule(ruleTrigger, ruleAction); var newRule = new Rule(ruleTrigger, ruleAction);
@ -83,7 +83,7 @@ namespace Squidex.Domain.Apps.Core.Model.Rules
[Fact] [Fact]
public void Should_replace_trigger_when_updating() public void Should_replace_trigger_when_updating()
{ {
var newTrigger = new ContentChangedTrigger(); var newTrigger = new ContentChangedTriggerV2();
var rule_1 = rule_0.Update(newTrigger); var rule_1 = rule_0.Update(newTrigger);

12
tests/Squidex.Domain.Apps.Core.Tests/Operations/HandleRules/RuleServiceTests.cs

@ -77,7 +77,7 @@ namespace Squidex.Domain.Apps.Core.Operations.HandleRules
.Returns(typeof(ValidData)); .Returns(typeof(ValidData));
A.CallTo(() => ruleTriggerHandler.TriggerType) A.CallTo(() => ruleTriggerHandler.TriggerType)
.Returns(typeof(ContentChangedTrigger)); .Returns(typeof(ContentChangedTriggerV2));
sut = new RuleService(new[] { ruleTriggerHandler }, new[] { ruleActionHandler }, eventEnricher, TestUtils.DefaultSerializer, clock, typeNameRegistry); sut = new RuleService(new[] { ruleTriggerHandler }, new[] { ruleActionHandler }, eventEnricher, TestUtils.DefaultSerializer, clock, typeNameRegistry);
} }
@ -118,7 +118,7 @@ namespace Squidex.Domain.Apps.Core.Operations.HandleRules
[Fact] [Fact]
public async Task Should_not_create_job_if_no_action_handler_registered() public async Task Should_not_create_job_if_no_action_handler_registered()
{ {
var ruleConfig = new Rule(new ContentChangedTrigger(), new InvalidAction()); var ruleConfig = new Rule(new ContentChangedTriggerV2(), new InvalidAction());
var ruleEnvelope = Envelope.Create(new ContentCreated()); var ruleEnvelope = Envelope.Create(new ContentCreated());
var job = await sut.CreateJobAsync(ruleConfig, ruleEnvelope); var job = await sut.CreateJobAsync(ruleConfig, ruleEnvelope);
@ -132,7 +132,7 @@ namespace Squidex.Domain.Apps.Core.Operations.HandleRules
var ruleConfig = ValidRule(); var ruleConfig = ValidRule();
var ruleEnvelope = Envelope.Create(new ContentCreated()); var ruleEnvelope = Envelope.Create(new ContentCreated());
A.CallTo(() => ruleTriggerHandler.Triggers(A<Envelope<AppEvent>>.Ignored, ruleConfig.Trigger)) A.CallTo(() => ruleTriggerHandler.Triggers(A<EnrichedEvent>.Ignored, ruleConfig.Trigger))
.Returns(false); .Returns(false);
var job = await sut.CreateJobAsync(ruleConfig, ruleEnvelope); var job = await sut.CreateJobAsync(ruleConfig, ruleEnvelope);
@ -155,7 +155,7 @@ namespace Squidex.Domain.Apps.Core.Operations.HandleRules
A.CallTo(() => clock.GetCurrentInstant()) A.CallTo(() => clock.GetCurrentInstant())
.Returns(now); .Returns(now);
A.CallTo(() => ruleTriggerHandler.Triggers(A<Envelope<AppEvent>>.Ignored, ruleConfig.Trigger)) A.CallTo(() => ruleTriggerHandler.Triggers(A<EnrichedEvent>.Ignored, ruleConfig.Trigger))
.Returns(true); .Returns(true);
A.CallTo(() => ruleActionHandler.CreateJobAsync(A<EnrichedEvent>.Ignored, ruleConfig.Action)) A.CallTo(() => ruleActionHandler.CreateJobAsync(A<EnrichedEvent>.Ignored, ruleConfig.Action))
@ -181,7 +181,7 @@ namespace Squidex.Domain.Apps.Core.Operations.HandleRules
A.CallTo(() => clock.GetCurrentInstant()) A.CallTo(() => clock.GetCurrentInstant())
.Returns(now); .Returns(now);
A.CallTo(() => ruleTriggerHandler.Triggers(A<Envelope<AppEvent>>.Ignored, ruleConfig.Trigger)) A.CallTo(() => ruleTriggerHandler.Triggers(A<EnrichedEvent>.Ignored, ruleConfig.Trigger))
.Returns(true); .Returns(true);
A.CallTo(() => ruleActionHandler.CreateJobAsync(A<EnrichedEvent>.Ignored, ruleConfig.Action)) A.CallTo(() => ruleActionHandler.CreateJobAsync(A<EnrichedEvent>.Ignored, ruleConfig.Action))
@ -260,7 +260,7 @@ namespace Squidex.Domain.Apps.Core.Operations.HandleRules
private static Rule ValidRule() private static Rule ValidRule()
{ {
return new Rule(new ContentChangedTrigger(), new ValidAction()); return new Rule(new ContentChangedTriggerV2(), new ValidAction());
} }
} }
} }

92
tests/Squidex.Domain.Apps.Core.Tests/Operations/HandleRules/Triggers/AssetChangedTriggerTests.cs

@ -5,56 +5,80 @@
// All rights reserved. Licensed under the MIT license. // All rights reserved. Licensed under the MIT license.
// ========================================================================== // ==========================================================================
using System.Collections.Generic; using FakeItEasy;
using Squidex.Domain.Apps.Core.HandleRules; using Squidex.Domain.Apps.Core.HandleRules;
using Squidex.Domain.Apps.Core.HandleRules.EnrichedEvents;
using Squidex.Domain.Apps.Core.HandleRules.Triggers; using Squidex.Domain.Apps.Core.HandleRules.Triggers;
using Squidex.Domain.Apps.Core.Rules.Triggers; using Squidex.Domain.Apps.Core.Rules.Triggers;
using Squidex.Domain.Apps.Events; using Squidex.Domain.Apps.Core.Scripting;
using Squidex.Domain.Apps.Events.Assets;
using Squidex.Domain.Apps.Events.Rules;
using Squidex.Infrastructure.EventSourcing;
using Xunit; using Xunit;
namespace Squidex.Domain.Apps.Core.Operations.HandleRules.Triggers namespace Squidex.Domain.Apps.Core.Operations.HandleRules.Triggers
{ {
public class AssetChangedTriggerTests public class AssetChangedTriggerTests
{ {
private readonly IRuleTriggerHandler sut = new AssetChangedTriggerHandler(); private readonly IScriptEngine scriptEngine = A.Fake<IScriptEngine>();
private readonly IRuleTriggerHandler sut;
public static IEnumerable<object[]> TestData public AssetChangedTriggerTests()
{ {
get sut = new AssetChangedTriggerHandler(scriptEngine);
{
return new[]
{
new object[] { 0, 1, 1, 1, 1, new RuleCreated() },
new object[] { 1, 1, 0, 0, 0, new AssetCreated() },
new object[] { 0, 0, 0, 0, 0, new AssetCreated() },
new object[] { 1, 0, 1, 0, 0, new AssetUpdated() },
new object[] { 0, 0, 0, 0, 0, new AssetUpdated() },
new object[] { 1, 0, 0, 1, 0, new AssetRenamed() },
new object[] { 0, 0, 0, 0, 0, new AssetRenamed() },
new object[] { 1, 0, 0, 0, 1, new AssetDeleted() },
new object[] { 0, 0, 0, 0, 0, new AssetDeleted() }
};
}
} }
[Theory] [Fact]
[MemberData(nameof(TestData))] public void Should_trigger_when_condition_is_null()
public void Should_return_result_depending_on_event(int expected, int sendCreate, int sendUpdate, int sendRename, int sendDelete, AppEvent @event)
{ {
var trigger = new AssetChangedTrigger var trigger = new AssetChangedTriggerV2();
{
SendCreate = sendCreate == 1,
SendUpdate = sendUpdate == 1,
SendRename = sendRename == 1,
SendDelete = sendDelete == 1
};
var result = sut.Triggers(new Envelope<AppEvent>(@event), trigger); var result = sut.Triggers(new EnrichedAssetEvent(), trigger);
Assert.Equal(expected == 1, result); Assert.True(result);
A.CallTo(() => scriptEngine.Evaluate(A<string>.Ignored, A<object>.Ignored, A<string>.Ignored))
.MustNotHaveHappened();
}
[Fact]
public void Should_trigger_when_condition_is_empty()
{
var trigger = new AssetChangedTriggerV2 { Condition = string.Empty };
var result = sut.Triggers(new EnrichedAssetEvent(), trigger);
Assert.True(result);
A.CallTo(() => scriptEngine.Evaluate(A<string>.Ignored, A<object>.Ignored, A<string>.Ignored))
.MustNotHaveHappened();
}
[Fact]
public void Should_trigger_when_condition_matchs()
{
var trigger = new AssetChangedTriggerV2 { Condition = "true" };
var @event = new EnrichedAssetEvent();
A.CallTo(() => scriptEngine.Evaluate("event", @event, trigger.Condition))
.Returns(true);
var result = sut.Triggers(@event, trigger);
Assert.True(result);
}
[Fact]
public void Should_not_trigger_when_condition_does_not_matchs()
{
var trigger = new AssetChangedTriggerV2 { Condition = "false" };
var @event = new EnrichedAssetEvent();
A.CallTo(() => scriptEngine.Evaluate("event", @event, trigger.Condition))
.Returns(false);
var result = sut.Triggers(@event, trigger);
Assert.False(result);
} }
} }
} }

193
tests/Squidex.Domain.Apps.Core.Tests/Operations/HandleRules/Triggers/ContentChangedTriggerTests.cs

@ -7,17 +7,14 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using Squidex.Domain.Apps.Core.Contents; using System.Collections.ObjectModel;
using FakeItEasy;
using Squidex.Domain.Apps.Core.HandleRules; using Squidex.Domain.Apps.Core.HandleRules;
using Squidex.Domain.Apps.Core.HandleRules.EnrichedEvents;
using Squidex.Domain.Apps.Core.HandleRules.Triggers; using Squidex.Domain.Apps.Core.HandleRules.Triggers;
using Squidex.Domain.Apps.Core.Rules.Triggers; using Squidex.Domain.Apps.Core.Rules.Triggers;
using Squidex.Domain.Apps.Events; using Squidex.Domain.Apps.Core.Scripting;
using Squidex.Domain.Apps.Events.Contents;
using Squidex.Domain.Apps.Events.Rules;
using Squidex.Domain.Apps.Events.Schemas;
using Squidex.Infrastructure; using Squidex.Infrastructure;
using Squidex.Infrastructure.Collections;
using Squidex.Infrastructure.EventSourcing;
using Xunit; using Xunit;
#pragma warning disable SA1401 // Fields must be private #pragma warning disable SA1401 // Fields must be private
@ -26,82 +23,164 @@ namespace Squidex.Domain.Apps.Core.Operations.HandleRules.Triggers
{ {
public class ContentChangedTriggerTests public class ContentChangedTriggerTests
{ {
private readonly IRuleTriggerHandler sut = new ContentChangedTriggerHandler(); private readonly IScriptEngine scriptEngine = A.Fake<IScriptEngine>();
private readonly IRuleTriggerHandler sut;
private static readonly NamedId<Guid> SchemaMatch = NamedId.Of(Guid.NewGuid(), "my-schema1"); private static readonly NamedId<Guid> SchemaMatch = NamedId.Of(Guid.NewGuid(), "my-schema1");
private static readonly NamedId<Guid> SchemaNonMatch = NamedId.Of(Guid.NewGuid(), "my-schema2"); private static readonly NamedId<Guid> SchemaNonMatch = NamedId.Of(Guid.NewGuid(), "my-schema2");
public static IEnumerable<object[]> TestData = new[] public ContentChangedTriggerTests()
{ {
new object[] { 0, 1, 1, 1, 1, 0, 0, 0, new RuleCreated() }, sut = new ContentChangedTriggerHandler(scriptEngine);
new object[] { 0, 1, 1, 1, 1, 0, 0, 0, new ContentCreated { SchemaId = SchemaNonMatch } }, }
new object[] { 1, 1, 0, 0, 0, 0, 0, 0, new ContentCreated { SchemaId = SchemaMatch } },
new object[] { 0, 0, 0, 0, 0, 0, 0, 0, new ContentCreated { SchemaId = SchemaMatch } },
new object[] { 1, 0, 1, 0, 0, 0, 0, 0, new ContentUpdated { SchemaId = SchemaMatch } },
new object[] { 0, 0, 0, 0, 0, 0, 0, 0, new ContentUpdated { SchemaId = SchemaMatch } },
new object[] { 1, 0, 0, 1, 0, 0, 0, 0, new ContentDeleted { SchemaId = SchemaMatch } },
new object[] { 0, 0, 0, 0, 0, 0, 0, 0, new ContentDeleted { SchemaId = SchemaMatch } },
new object[] { 1, 1, 1, 1, 0, 0, 1, 0, new ContentStatusChanged { SchemaId = SchemaMatch, Change = StatusChange.Archived } },
new object[] { 0, 1, 1, 1, 0, 0, 0, 0, new ContentStatusChanged { SchemaId = SchemaMatch, Change = StatusChange.Archived } },
new object[] { 1, 0, 0, 0, 0, 0, 0, 1, new ContentStatusChanged { SchemaId = SchemaMatch, Change = StatusChange.Restored } },
new object[] { 0, 0, 0, 0, 0, 0, 0, 0, new ContentStatusChanged { SchemaId = SchemaMatch, Change = StatusChange.Restored } },
new object[] { 1, 0, 0, 0, 1, 0, 0, 0, new ContentStatusChanged { SchemaId = SchemaMatch, Change = StatusChange.Published } },
new object[] { 0, 0, 0, 0, 0, 0, 0, 0, new ContentStatusChanged { SchemaId = SchemaMatch, Change = StatusChange.Published } },
new object[] { 1, 1, 1, 1, 0, 1, 0, 0, new ContentStatusChanged { SchemaId = SchemaMatch, Change = StatusChange.Unpublished } },
new object[] { 0, 1, 1, 1, 0, 0, 0, 0, new ContentStatusChanged { SchemaId = SchemaMatch, Change = StatusChange.Unpublished } },
new object[] { 0, 1, 1, 1, 1, 0, 0, 0, new SchemaCreated { SchemaId = SchemaNonMatch } }
};
[Fact] [Fact]
public void Should_return_false_when_trigger_contains_no_schemas() public void Should_not_trigger_when_o_contains_no_schemas()
{ {
var trigger = new ContentChangedTrigger(); var trigger = new ContentChangedTriggerV2();
var @event = new EnrichedContentEvent { SchemaId = SchemaMatch };
var result = sut.Triggers(new Envelope<AppEvent>(new ContentCreated()), trigger); var result = sut.Triggers(@event, trigger);
Assert.False(result); Assert.False(result);
A.CallTo(() => scriptEngine.Evaluate(A<string>.Ignored, A<object>.Ignored, A<string>.Ignored))
.MustNotHaveHappened();
} }
[Fact] [Fact]
public void Should_return_true_when_cathing_all_events() public void Should_trigger_when_cathing_all_events()
{ {
var trigger = new ContentChangedTrigger { HandleAll = true }; var trigger = new ContentChangedTriggerV2 { HandleAll = true };
var @event = new EnrichedContentEvent { SchemaId = SchemaMatch };
var result = sut.Triggers(new Envelope<AppEvent>(new ContentCreated()), trigger); var result = sut.Triggers(@event, trigger);
Assert.True(result); Assert.True(result);
A.CallTo(() => scriptEngine.Evaluate(A<string>.Ignored, A<object>.Ignored, A<string>.Ignored))
.MustNotHaveHappened();
} }
[Theory] [Fact]
[MemberData(nameof(TestData))] public void Should_trigger_when_condition_is_null()
public void Should_return_result_depending_on_event(int expected,
int sendCreate,
int sendUpdate,
int sendDelete,
int sendPublish,
int sendUnpublish,
int sendArchive,
int sendRestore,
AppEvent @event)
{ {
var trigger = new ContentChangedTrigger var trigger = new ContentChangedTriggerV2
{ {
Schemas = ReadOnlyCollection.Create( Schemas = new ReadOnlyCollection<ContentChangedTriggerSchemaV2>(new List<ContentChangedTriggerSchemaV2>
new ContentChangedTriggerSchema {
new ContentChangedTriggerSchemaV2
{ {
SendCreate = sendCreate == 1,
SendUpdate = sendUpdate == 1,
SendDelete = sendDelete == 1,
SendPublish = sendPublish == 1,
SendUnpublish = sendUnpublish == 1,
SendArchived = sendArchive == 1,
SendRestore = sendRestore == 1,
SchemaId = SchemaMatch.Id SchemaId = SchemaMatch.Id
}) }
})
}; };
var result = sut.Triggers(new Envelope<AppEvent>(@event), trigger); var @event = new EnrichedContentEvent { SchemaId = SchemaMatch };
var result = sut.Triggers(@event, trigger);
Assert.True(result);
A.CallTo(() => scriptEngine.Evaluate(A<string>.Ignored, A<object>.Ignored, A<string>.Ignored))
.MustNotHaveHappened();
}
[Fact]
public void Should_not_trigger_when_schema_id_does_not_match()
{
var trigger = new ContentChangedTriggerV2
{
Schemas = new ReadOnlyCollection<ContentChangedTriggerSchemaV2>(new List<ContentChangedTriggerSchemaV2>
{
new ContentChangedTriggerSchemaV2
{
SchemaId = SchemaNonMatch.Id
}
})
};
var @event = new EnrichedContentEvent { SchemaId = SchemaMatch };
var result = sut.Triggers(@event, trigger);
Assert.False(result);
A.CallTo(() => scriptEngine.Evaluate(A<string>.Ignored, A<object>.Ignored, A<string>.Ignored))
.MustNotHaveHappened();
}
[Fact]
public void Should_trigger_when_condition_is_empty()
{
var trigger = new ContentChangedTriggerV2
{
Schemas = new ReadOnlyCollection<ContentChangedTriggerSchemaV2>(new List<ContentChangedTriggerSchemaV2>
{
new ContentChangedTriggerSchemaV2
{
SchemaId = SchemaMatch.Id, Condition = string.Empty
}
})
};
Assert.Equal(expected == 1, result); var @event = new EnrichedContentEvent { SchemaId = SchemaMatch };
var result = sut.Triggers(@event, trigger);
Assert.True(result);
A.CallTo(() => scriptEngine.Evaluate(A<string>.Ignored, A<object>.Ignored, A<string>.Ignored))
.MustNotHaveHappened();
}
[Fact]
public void Should_trigger_when_condition_matchs()
{
var trigger = new ContentChangedTriggerV2
{
Schemas = new ReadOnlyCollection<ContentChangedTriggerSchemaV2>(new List<ContentChangedTriggerSchemaV2>
{
new ContentChangedTriggerSchemaV2
{
SchemaId = SchemaMatch.Id, Condition = "true"
}
})
};
var @event = new EnrichedContentEvent { SchemaId = SchemaMatch };
A.CallTo(() => scriptEngine.Evaluate("event", @event, "true"))
.Returns(true);
var result = sut.Triggers(@event, trigger);
Assert.True(result);
}
[Fact]
public void Should_not_trigger_when_condition_does_not_matchs()
{
var trigger = new ContentChangedTriggerV2
{
Schemas = new ReadOnlyCollection<ContentChangedTriggerSchemaV2>(new List<ContentChangedTriggerSchemaV2>
{
new ContentChangedTriggerSchemaV2
{
SchemaId = SchemaMatch.Id, Condition = "false"
}
})
};
var @event = new EnrichedContentEvent { SchemaId = SchemaMatch };
A.CallTo(() => scriptEngine.Evaluate("event", @event, "false"))
.Returns(false);
var result = sut.Triggers(@event, trigger);
Assert.False(result);
} }
} }
} }

2
tests/Squidex.Domain.Apps.Core.Tests/Operations/Scripting/JintUserTests.cs

@ -88,7 +88,7 @@ namespace Squidex.Domain.Apps.Core.Operations.Scripting
{ {
var engine = new Engine(); var engine = new Engine();
engine.SetValue("user", new JintUser(engine, new ClaimsPrincipal(new[] { identity }))); engine.SetValue("user", JintUser.Create(engine, new ClaimsPrincipal(new[] { identity })));
return engine.Execute(script).GetCompletionValue().ToObject(); return engine.Execute(script).GetCompletionValue().ToObject();
} }

14
tests/Squidex.Domain.Apps.Entities.Tests/Rules/Guards/GuardRuleTests.cs

@ -24,7 +24,7 @@ namespace Squidex.Domain.Apps.Entities.Rules.Guards
public class GuardRuleTests public class GuardRuleTests
{ {
private readonly Uri validUrl = new Uri("https://squidex.io"); private readonly Uri validUrl = new Uri("https://squidex.io");
private readonly Rule rule_0 = new Rule(new ContentChangedTrigger(), new TestAction()); private readonly Rule rule_0 = new Rule(new ContentChangedTriggerV2(), new TestAction());
private readonly NamedId<Guid> appId = NamedId.Of(Guid.NewGuid(), "my-app"); private readonly NamedId<Guid> appId = NamedId.Of(Guid.NewGuid(), "my-app");
private readonly IAppProvider appProvider = A.Fake<IAppProvider>(); private readonly IAppProvider appProvider = A.Fake<IAppProvider>();
@ -60,9 +60,9 @@ namespace Squidex.Domain.Apps.Entities.Rules.Guards
{ {
var command = CreateCommand(new CreateRule var command = CreateCommand(new CreateRule
{ {
Trigger = new ContentChangedTrigger Trigger = new ContentChangedTriggerV2
{ {
Schemas = ReadOnlyCollection.Empty<ContentChangedTriggerSchema>() Schemas = ReadOnlyCollection.Empty<ContentChangedTriggerSchemaV2>()
}, },
Action = null Action = null
}); });
@ -76,9 +76,9 @@ namespace Squidex.Domain.Apps.Entities.Rules.Guards
{ {
var command = CreateCommand(new CreateRule var command = CreateCommand(new CreateRule
{ {
Trigger = new ContentChangedTrigger Trigger = new ContentChangedTriggerV2
{ {
Schemas = ReadOnlyCollection.Empty<ContentChangedTriggerSchema>() Schemas = ReadOnlyCollection.Empty<ContentChangedTriggerSchemaV2>()
}, },
Action = new TestAction Action = new TestAction
{ {
@ -103,9 +103,9 @@ namespace Squidex.Domain.Apps.Entities.Rules.Guards
{ {
var command = new UpdateRule var command = new UpdateRule
{ {
Trigger = new ContentChangedTrigger Trigger = new ContentChangedTriggerV2
{ {
Schemas = ReadOnlyCollection.Empty<ContentChangedTriggerSchema>() Schemas = ReadOnlyCollection.Empty<ContentChangedTriggerSchemaV2>()
}, },
Action = new TestAction Action = new TestAction
{ {

14
tests/Squidex.Domain.Apps.Entities.Tests/Rules/Guards/Triggers/ContentChangedTriggerTests.cs

@ -26,10 +26,10 @@ namespace Squidex.Domain.Apps.Entities.Rules.Guards.Triggers
A.CallTo(() => appProvider.GetSchemaAsync(appId, A<Guid>.Ignored, false)) A.CallTo(() => appProvider.GetSchemaAsync(appId, A<Guid>.Ignored, false))
.Returns(Task.FromResult<ISchemaEntity>(null)); .Returns(Task.FromResult<ISchemaEntity>(null));
var trigger = new ContentChangedTrigger var trigger = new ContentChangedTriggerV2
{ {
Schemas = ReadOnlyCollection.Create( Schemas = ReadOnlyCollection.Create(
new ContentChangedTriggerSchema() new ContentChangedTriggerSchemaV2()
) )
}; };
@ -41,7 +41,7 @@ namespace Squidex.Domain.Apps.Entities.Rules.Guards.Triggers
[Fact] [Fact]
public async Task Should_not_add_error_if_schemas_is_null() public async Task Should_not_add_error_if_schemas_is_null()
{ {
var trigger = new ContentChangedTrigger(); var trigger = new ContentChangedTriggerV2();
var errors = await RuleTriggerValidator.ValidateAsync(appId, trigger, appProvider); var errors = await RuleTriggerValidator.ValidateAsync(appId, trigger, appProvider);
@ -51,9 +51,9 @@ namespace Squidex.Domain.Apps.Entities.Rules.Guards.Triggers
[Fact] [Fact]
public async Task Should_not_add_error_if_schemas_is_empty() public async Task Should_not_add_error_if_schemas_is_empty()
{ {
var trigger = new ContentChangedTrigger var trigger = new ContentChangedTriggerV2
{ {
Schemas = ReadOnlyCollection.Empty<ContentChangedTriggerSchema>() Schemas = ReadOnlyCollection.Empty<ContentChangedTriggerSchemaV2>()
}; };
var errors = await RuleTriggerValidator.ValidateAsync(appId, trigger, appProvider); var errors = await RuleTriggerValidator.ValidateAsync(appId, trigger, appProvider);
@ -67,10 +67,10 @@ namespace Squidex.Domain.Apps.Entities.Rules.Guards.Triggers
A.CallTo(() => appProvider.GetSchemaAsync(appId, A<Guid>.Ignored, false)) A.CallTo(() => appProvider.GetSchemaAsync(appId, A<Guid>.Ignored, false))
.Returns(A.Fake<ISchemaEntity>()); .Returns(A.Fake<ISchemaEntity>());
var trigger = new ContentChangedTrigger var trigger = new ContentChangedTriggerV2
{ {
Schemas = ReadOnlyCollection.Create( Schemas = ReadOnlyCollection.Create(
new ContentChangedTriggerSchema() new ContentChangedTriggerSchemaV2()
) )
}; };

6
tests/Squidex.Domain.Apps.Entities.Tests/Rules/RuleEnqueuerTests.cs

@ -70,9 +70,9 @@ namespace Squidex.Domain.Apps.Entities.Rules
{ {
var @event = Envelope.Create(new ContentCreated { AppId = appId }); var @event = Envelope.Create(new ContentCreated { AppId = appId });
var rule1 = new Rule(new ContentChangedTrigger(), new TestAction { Url = new Uri("https://squidex.io") }); var rule1 = new Rule(new ContentChangedTriggerV2(), new TestAction { Url = new Uri("https://squidex.io") });
var rule2 = new Rule(new ContentChangedTrigger(), new TestAction { Url = new Uri("https://squidex.io") }); var rule2 = new Rule(new ContentChangedTriggerV2(), new TestAction { Url = new Uri("https://squidex.io") });
var rule3 = new Rule(new ContentChangedTrigger(), new TestAction { Url = new Uri("https://squidex.io") }); var rule3 = new Rule(new ContentChangedTriggerV2(), new TestAction { Url = new Uri("https://squidex.io") });
var job1 = new RuleJob { Created = now }; var job1 = new RuleJob { Created = now };
var job2 = new RuleJob { Created = now }; var job2 = new RuleJob { Created = now };

8
tests/Squidex.Domain.Apps.Entities.Tests/Rules/RuleGrainTests.cs

@ -189,9 +189,9 @@ namespace Squidex.Domain.Apps.Entities.Rules
private static CreateRule MakeCreateCommand() private static CreateRule MakeCreateCommand()
{ {
var newTrigger = new ContentChangedTrigger var newTrigger = new ContentChangedTriggerV2
{ {
Schemas = ReadOnlyCollection.Empty<ContentChangedTriggerSchema>() Schemas = ReadOnlyCollection.Empty<ContentChangedTriggerSchemaV2>()
}; };
var newAction = new TestAction var newAction = new TestAction
@ -204,9 +204,9 @@ namespace Squidex.Domain.Apps.Entities.Rules
private static UpdateRule MakeUpdateCommand() private static UpdateRule MakeUpdateCommand()
{ {
var newTrigger = new ContentChangedTrigger var newTrigger = new ContentChangedTriggerV2
{ {
Schemas = ReadOnlyCollection.Empty<ContentChangedTriggerSchema>() Schemas = ReadOnlyCollection.Empty<ContentChangedTriggerSchemaV2>()
}; };
var newAction = new TestAction var newAction = new TestAction

2
tests/Squidex.Infrastructure.Tests/EventSourcing/DefaultEventDataFormatterTests.cs

@ -15,7 +15,7 @@ namespace Squidex.Infrastructure.EventSourcing
{ {
public class DefaultEventDataFormatterTests public class DefaultEventDataFormatterTests
{ {
public sealed class MyOldEvent : IEvent, IMigratedEvent public sealed class MyOldEvent : IEvent, IMigrated<IEvent>
{ {
public string MyProperty { get; set; } public string MyProperty { get; set; }

3
tools/Migrate_01/OldEvents/AppClientChanged.cs

@ -7,6 +7,7 @@
using System; using System;
using Squidex.Domain.Apps.Events; using Squidex.Domain.Apps.Events;
using Squidex.Infrastructure;
using Squidex.Infrastructure.EventSourcing; using Squidex.Infrastructure.EventSourcing;
using Squidex.Infrastructure.Reflection; using Squidex.Infrastructure.Reflection;
@ -14,7 +15,7 @@ namespace Migrate_01.OldEvents
{ {
[EventType(nameof(AppClientChanged))] [EventType(nameof(AppClientChanged))]
[Obsolete] [Obsolete]
public sealed class AppClientChanged : AppEvent, IMigratedEvent public sealed class AppClientChanged : AppEvent, IMigrated<IEvent>
{ {
public string Id { get; set; } public string Id { get; set; }

3
tools/Migrate_01/OldEvents/AppClientUpdated.cs

@ -8,6 +8,7 @@
using System; using System;
using Squidex.Domain.Apps.Core.Apps; using Squidex.Domain.Apps.Core.Apps;
using Squidex.Domain.Apps.Events; using Squidex.Domain.Apps.Events;
using Squidex.Infrastructure;
using Squidex.Infrastructure.EventSourcing; using Squidex.Infrastructure.EventSourcing;
using Squidex.Infrastructure.Reflection; using Squidex.Infrastructure.Reflection;
using AppClientUpdatedV2 = Squidex.Domain.Apps.Events.Apps.AppClientUpdated; using AppClientUpdatedV2 = Squidex.Domain.Apps.Events.Apps.AppClientUpdated;
@ -16,7 +17,7 @@ namespace Migrate_01.OldEvents
{ {
[EventType(nameof(AppClientUpdated))] [EventType(nameof(AppClientUpdated))]
[Obsolete] [Obsolete]
public sealed class AppClientUpdated : AppEvent, IMigratedEvent public sealed class AppClientUpdated : AppEvent, IMigrated<IEvent>
{ {
public string Id { get; set; } public string Id { get; set; }

3
tools/Migrate_01/OldEvents/AppContributorAssigned.cs

@ -8,6 +8,7 @@
using System; using System;
using Squidex.Domain.Apps.Core.Apps; using Squidex.Domain.Apps.Core.Apps;
using Squidex.Domain.Apps.Events; using Squidex.Domain.Apps.Events;
using Squidex.Infrastructure;
using Squidex.Infrastructure.EventSourcing; using Squidex.Infrastructure.EventSourcing;
using Squidex.Infrastructure.Reflection; using Squidex.Infrastructure.Reflection;
using AppContributorAssignedV2 = Squidex.Domain.Apps.Events.Apps.AppContributorAssigned; using AppContributorAssignedV2 = Squidex.Domain.Apps.Events.Apps.AppContributorAssigned;
@ -16,7 +17,7 @@ namespace Migrate_01.OldEvents
{ {
[EventType(nameof(AppContributorAssigned))] [EventType(nameof(AppContributorAssigned))]
[Obsolete] [Obsolete]
public sealed class AppContributorAssigned : AppEvent, IMigratedEvent public sealed class AppContributorAssigned : AppEvent, IMigrated<IEvent>
{ {
public string ContributorId { get; set; } public string ContributorId { get; set; }

3
tools/Migrate_01/OldEvents/ContentArchived.cs

@ -8,6 +8,7 @@
using System; using System;
using Squidex.Domain.Apps.Core.Contents; using Squidex.Domain.Apps.Core.Contents;
using Squidex.Domain.Apps.Events.Contents; using Squidex.Domain.Apps.Events.Contents;
using Squidex.Infrastructure;
using Squidex.Infrastructure.EventSourcing; using Squidex.Infrastructure.EventSourcing;
using Squidex.Infrastructure.Reflection; using Squidex.Infrastructure.Reflection;
@ -15,7 +16,7 @@ namespace Migrate_01.OldEvents
{ {
[EventType(nameof(ContentArchived))] [EventType(nameof(ContentArchived))]
[Obsolete] [Obsolete]
public sealed class ContentArchived : ContentEvent, IMigratedEvent public sealed class ContentArchived : ContentEvent, IMigrated<IEvent>
{ {
public IEvent Migrate() public IEvent Migrate()
{ {

3
tools/Migrate_01/OldEvents/ContentPublished.cs

@ -8,6 +8,7 @@
using System; using System;
using Squidex.Domain.Apps.Core.Contents; using Squidex.Domain.Apps.Core.Contents;
using Squidex.Domain.Apps.Events.Contents; using Squidex.Domain.Apps.Events.Contents;
using Squidex.Infrastructure;
using Squidex.Infrastructure.EventSourcing; using Squidex.Infrastructure.EventSourcing;
using Squidex.Infrastructure.Reflection; using Squidex.Infrastructure.Reflection;
@ -15,7 +16,7 @@ namespace Migrate_01.OldEvents
{ {
[EventType(nameof(ContentPublished))] [EventType(nameof(ContentPublished))]
[Obsolete] [Obsolete]
public sealed class ContentPublished : ContentEvent, IMigratedEvent public sealed class ContentPublished : ContentEvent, IMigrated<IEvent>
{ {
public IEvent Migrate() public IEvent Migrate()
{ {

3
tools/Migrate_01/OldEvents/ContentRestored.cs

@ -8,6 +8,7 @@
using System; using System;
using Squidex.Domain.Apps.Core.Contents; using Squidex.Domain.Apps.Core.Contents;
using Squidex.Domain.Apps.Events.Contents; using Squidex.Domain.Apps.Events.Contents;
using Squidex.Infrastructure;
using Squidex.Infrastructure.EventSourcing; using Squidex.Infrastructure.EventSourcing;
using Squidex.Infrastructure.Reflection; using Squidex.Infrastructure.Reflection;
@ -15,7 +16,7 @@ namespace Migrate_01.OldEvents
{ {
[EventType(nameof(ContentRestored))] [EventType(nameof(ContentRestored))]
[Obsolete] [Obsolete]
public sealed class ContentRestored : ContentEvent, IMigratedEvent public sealed class ContentRestored : ContentEvent, IMigrated<IEvent>
{ {
public IEvent Migrate() public IEvent Migrate()
{ {

3
tools/Migrate_01/OldEvents/ContentUnpublished.cs

@ -8,6 +8,7 @@
using System; using System;
using Squidex.Domain.Apps.Core.Contents; using Squidex.Domain.Apps.Core.Contents;
using Squidex.Domain.Apps.Events.Contents; using Squidex.Domain.Apps.Events.Contents;
using Squidex.Infrastructure;
using Squidex.Infrastructure.EventSourcing; using Squidex.Infrastructure.EventSourcing;
using Squidex.Infrastructure.Reflection; using Squidex.Infrastructure.Reflection;
@ -15,7 +16,7 @@ namespace Migrate_01.OldEvents
{ {
[EventType(nameof(ContentUnpublished))] [EventType(nameof(ContentUnpublished))]
[Obsolete] [Obsolete]
public sealed class ContentUnpublished : ContentEvent, IMigratedEvent public sealed class ContentUnpublished : ContentEvent, IMigrated<IEvent>
{ {
public IEvent Migrate() public IEvent Migrate()
{ {

67
tools/Migrate_01/OldTriggers/AssetChangedTrigger.cs

@ -0,0 +1,67 @@
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System;
using System.Collections.Generic;
using Squidex.Domain.Apps.Core.HandleRules.EnrichedEvents;
using Squidex.Domain.Apps.Core.Rules;
using Squidex.Domain.Apps.Core.Rules.Triggers;
using Squidex.Infrastructure;
namespace Migrate_01.OldTriggers
{
[TypeName(nameof(AssetChangedTrigger))]
public sealed class AssetChangedTrigger : RuleTrigger, IMigrated<RuleTrigger>
{
public bool SendCreate { get; set; }
public bool SendUpdate { get; set; }
public bool SendRename { get; set; }
public bool SendDelete { get; set; }
public override T Accept<T>(IRuleTriggerVisitor<T> visitor)
{
throw new NotSupportedException();
}
public RuleTrigger Migrate()
{
var conditions = new List<string>();
if (SendCreate)
{
conditions.Add($"event.type == '{EnrichedAssetEventType.Created}'");
}
if (SendUpdate)
{
conditions.Add($"event.type == '{EnrichedAssetEventType.Updated}'");
}
if (SendRename)
{
conditions.Add($"event.type == '{EnrichedAssetEventType.Renamed}'");
}
if (SendDelete)
{
conditions.Add($"event.type == '{EnrichedAssetEventType.Deleted}'");
}
var condition = "false";
if (conditions.Count > 0)
{
condition = string.Join(" || ", conditions);
}
return new AssetChangedTriggerV2 { Condition = condition };
}
}
}

45
tools/Migrate_01/OldTriggers/ContentChangedTrigger.cs

@ -0,0 +1,45 @@
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschränkt)
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System;
using System.Collections.ObjectModel;
using Squidex.Domain.Apps.Core.Rules;
using Squidex.Infrastructure;
namespace Migrate_01.OldTriggers
{
[TypeName(nameof(ContentChangedTrigger))]
public sealed class ContentChangedTrigger : RuleTrigger, IMigrated<RuleTrigger>
{
public ReadOnlyCollection<ContentChangedTriggerSchema> Schemas { get; set; }
public bool HandleAll { get; set; }
public override T Accept<T>(IRuleTriggerVisitor<T> visitor)
{
throw new NotSupportedException();
}
public override void Freeze()
{
base.Freeze();
if (Schemas != null)
{
foreach (var schema in Schemas)
{
schema.Freeze();
}
}
}
public RuleTrigger Migrate()
{
throw new NotImplementedException();
}
}
}

83
tools/Migrate_01/OldTriggers/ContentChangedTriggerSchema.cs

@ -0,0 +1,83 @@
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschränkt)
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System;
using System.Collections.Generic;
using Squidex.Domain.Apps.Core;
using Squidex.Domain.Apps.Core.HandleRules.EnrichedEvents;
using Squidex.Domain.Apps.Core.Rules.Triggers;
namespace Migrate_01.OldTriggers
{
public sealed class ContentChangedTriggerSchema : Freezable
{
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; }
public bool SendArchived { get; set; }
public bool SendRestore { get; set; }
public ContentChangedTriggerSchemaV2 Migrate()
{
var conditions = new List<string>();
if (SendCreate)
{
conditions.Add($"event.type == '{EnrichedContentEventType.Created}'");
}
if (SendUpdate)
{
conditions.Add($"event.type == '{EnrichedContentEventType.Updated}'");
}
if (SendPublish)
{
conditions.Add($"event.type == '{EnrichedContentEventType.Published}'");
}
if (SendUnpublish)
{
conditions.Add($"event.type == '{EnrichedContentEventType.Unpublished}'");
}
if (SendArchived)
{
conditions.Add($"event.type == '{EnrichedContentEventType.Archived}'");
}
if (SendRestore)
{
conditions.Add($"event.type == '{EnrichedContentEventType.Restored}'");
}
if (SendDelete)
{
conditions.Add($"event.type == '{EnrichedAssetEventType.Deleted}'");
}
var condition = "false";
if (conditions.Count > 0)
{
condition = string.Join(" || ", conditions);
}
return new ContentChangedTriggerSchemaV2 { SchemaId = SchemaId, Condition = condition };
}
}
}
Loading…
Cancel
Save