Browse Source

Merge pull request #390 from Squidex/script/status

Script/status
pull/392/head
Sebastian Stehle 6 years ago
committed by GitHub
parent
commit
b2430abc6f
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 13
      src/Squidex.Domain.Apps.Core.Operations/Scripting/JintScriptEngine.cs
  2. 6
      src/Squidex.Domain.Apps.Core.Operations/Scripting/ScriptContext.cs
  3. 65
      src/Squidex.Domain.Apps.Entities/Contents/ContentGrain.cs
  4. 26
      src/Squidex.Domain.Apps.Entities/Contents/ContentOperationContext.cs
  5. 2
      tests/Squidex.Domain.Apps.Core.Tests/Operations/Scripting/JintScriptEngineTests.cs
  6. 42
      tests/Squidex.Domain.Apps.Entities.Tests/Contents/ContentGrainTests.cs

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

@ -138,9 +138,9 @@ namespace Squidex.Domain.Apps.Core.Scripting
contextInstance.FastAddProperty("data", new ContentDataObject(engine, context.Data), true, true, true);
}
if (context.OldData != null)
if (context.DataOld != null)
{
contextInstance.FastAddProperty("oldData", new ContentDataObject(engine, context.OldData), true, true, true);
contextInstance.FastAddProperty("oldData", new ContentDataObject(engine, context.DataOld), true, true, true);
}
if (context.User != null)
@ -150,7 +150,14 @@ namespace Squidex.Domain.Apps.Core.Scripting
if (!string.IsNullOrWhiteSpace(context.Operation))
{
contextInstance.FastAddProperty("operation", context.Operation, false, true, false);
contextInstance.FastAddProperty("operation", context.Operation, false, false, false);
}
contextInstance.FastAddProperty("status", context.Status.ToString(), false, false, false);
if (context.StatusOld != default)
{
contextInstance.FastAddProperty("oldStatus", context.StatusOld.ToString(), false, false, false);
}
engine.SetValue("ctx", contextInstance);

6
src/Squidex.Domain.Apps.Core.Operations/Scripting/ScriptContext.cs

@ -19,7 +19,11 @@ namespace Squidex.Domain.Apps.Core.Scripting
public NamedContentData Data { get; set; }
public NamedContentData OldData { get; set; }
public NamedContentData DataOld { get; set; }
public Status Status { get; set; }
public Status StatusOld { get; set; }
public string Operation { get; set; }
}

65
src/Squidex.Domain.Apps.Entities/Contents/ContentGrain.cs

@ -66,11 +66,21 @@ namespace Squidex.Domain.Apps.Entities.Contents
case CreateContent createContent:
return CreateReturnAsync(createContent, async c =>
{
var ctx = await CreateContext(c.AppId.Id, c.SchemaId.Id, Guid.Empty, () => "Failed to create content.");
var ctx = await CreateContext(c.AppId.Id, c.SchemaId.Id, c, () => "Failed to create content.");
var status = (await contentWorkflow.GetInitialStatusAsync(ctx.Schema)).Status;
await GuardContent.CanCreate(ctx.Schema, contentWorkflow, c);
await ctx.ExecuteScriptAndTransformAsync(s => s.Create, "Create", c, c.Data);
c.Data = await ctx.ExecuteScriptAndTransformAsync(s => s.Create,
new ScriptContext
{
Operation = "Create",
Data = c.Data,
Status = status,
StatusOld = default
});
await ctx.EnrichAsync(c.Data);
if (!c.DoNotValidate)
@ -80,12 +90,17 @@ namespace Squidex.Domain.Apps.Entities.Contents
if (c.Publish)
{
await ctx.ExecuteScriptAsync(s => s.Change, "Published", c, c.Data);
await ctx.ExecuteScriptAsync(s => s.Change,
new ScriptContext
{
Operation = "Published",
Data = c.Data,
Status = Status.Published,
StatusOld = status
});
}
var statusInfo = await contentWorkflow.GetInitialStatusAsync(ctx.Schema);
Create(c, statusInfo.Status);
Create(c, status);
return Snapshot;
});
@ -117,7 +132,7 @@ namespace Squidex.Domain.Apps.Entities.Contents
{
var isChangeConfirm = Snapshot.IsPending && Snapshot.Status == Status.Published && c.Status == Status.Published;
var ctx = await CreateContext(Snapshot.AppId.Id, Snapshot.SchemaId.Id, Snapshot.Id, () => "Failed to change content.");
var ctx = await CreateContext(Snapshot.AppId.Id, Snapshot.SchemaId.Id, c, () => "Failed to change content.");
await GuardContent.CanChangeStatus(ctx.Schema, Snapshot, contentWorkflow, c, isChangeConfirm);
@ -148,7 +163,14 @@ namespace Squidex.Domain.Apps.Entities.Contents
reason = StatusChange.Change;
}
await ctx.ExecuteScriptAsync(s => s.Change, reason, c, Snapshot.Data);
await ctx.ExecuteScriptAsync(s => s.Change,
new ScriptContext
{
Operation = reason.ToString(),
Data = Snapshot.Data,
Status = c.Status,
StatusOld = Snapshot.Status
});
ChangeStatus(c, reason);
}
@ -182,11 +204,18 @@ namespace Squidex.Domain.Apps.Entities.Contents
case DeleteContent deleteContent:
return UpdateAsync(deleteContent, async c =>
{
var ctx = await CreateContext(Snapshot.AppId.Id, Snapshot.SchemaId.Id, Snapshot.Id, () => "Failed to delete content.");
var ctx = await CreateContext(Snapshot.AppId.Id, Snapshot.SchemaId.Id, c, () => "Failed to delete content.");
GuardContent.CanDelete(ctx.Schema, c);
await ctx.ExecuteScriptAsync(s => s.Delete, "Delete", c, Snapshot.Data);
await ctx.ExecuteScriptAsync(s => s.Delete,
new ScriptContext
{
Operation = "Delete",
Data = Snapshot.Data,
Status = Snapshot.Status,
StatusOld = default
});
Delete(c);
});
@ -207,7 +236,7 @@ namespace Squidex.Domain.Apps.Entities.Contents
if (!currentData.Equals(newData))
{
var ctx = await CreateContext(Snapshot.AppId.Id, Snapshot.SchemaId.Id, Snapshot.Id, () => "Failed to update content.");
var ctx = await CreateContext(Snapshot.AppId.Id, Snapshot.SchemaId.Id, command, () => "Failed to update content.");
if (partial)
{
@ -218,7 +247,15 @@ namespace Squidex.Domain.Apps.Entities.Contents
await ctx.ValidateAsync(command.Data);
}
newData = await ctx.ExecuteScriptAndTransformAsync(s => s.Update, "Update", command, newData, Snapshot.Data);
newData = await ctx.ExecuteScriptAndTransformAsync(s => s.Update,
new ScriptContext
{
Operation = "Create",
Data = newData,
DataOld = currentData,
Status = Snapshot.Status,
StatusOld = default
});
if (isProposal)
{
@ -306,10 +343,10 @@ namespace Squidex.Domain.Apps.Entities.Contents
}
}
private async Task<ContentOperationContext> CreateContext(Guid appId, Guid schemaId, Guid contentId, Func<string> message)
private async Task<ContentOperationContext> CreateContext(Guid appId, Guid schemaId, ContentCommand command, Func<string> message)
{
var operationContext =
await ContentOperationContext.CreateAsync(appId, schemaId, contentId,
await ContentOperationContext.CreateAsync(appId, schemaId, command,
appProvider, assetRepository, contentRepository, scriptEngine, message);
return operationContext;

26
src/Squidex.Domain.Apps.Entities/Contents/ContentOperationContext.cs

@ -30,7 +30,7 @@ namespace Squidex.Domain.Apps.Entities.Contents
private IScriptEngine scriptEngine;
private ISchemaEntity schemaEntity;
private IAppEntity appEntity;
private Guid contentId;
private ContentCommand command;
private Guid schemaId;
private Func<string> message;
@ -42,7 +42,7 @@ namespace Squidex.Domain.Apps.Entities.Contents
public static async Task<ContentOperationContext> CreateAsync(
Guid appId,
Guid schemaId,
Guid contentId,
ContentCommand command,
IAppProvider appProvider,
IAssetRepository assetRepository,
IContentRepository contentRepository,
@ -55,7 +55,7 @@ namespace Squidex.Domain.Apps.Entities.Contents
{
appEntity = appEntity,
assetRepository = assetRepository,
contentId = contentId,
command = command,
contentRepository = contentRepository,
message = message,
schemaId = schemaId,
@ -87,32 +87,34 @@ namespace Squidex.Domain.Apps.Entities.Contents
return data.ValidatePartialAsync(ctx, schemaEntity.SchemaDef, appEntity.PartitionResolver(), message);
}
public Task<NamedContentData> ExecuteScriptAndTransformAsync(Func<SchemaScripts, string> script, object operation, ContentCommand command, NamedContentData data, NamedContentData oldData = null)
public Task<NamedContentData> ExecuteScriptAndTransformAsync(Func<SchemaScripts, string> script, ScriptContext context)
{
var ctx = CreateScriptContext(operation, command, data, oldData);
Enrich(context);
var result = scriptEngine.ExecuteAndTransform(ctx, GetScript(script));
var result = scriptEngine.ExecuteAndTransform(context, GetScript(script));
return Task.FromResult(result);
}
public Task ExecuteScriptAsync(Func<SchemaScripts, string> script, object operation, ContentCommand command, NamedContentData data, NamedContentData oldData = null)
public Task ExecuteScriptAsync(Func<SchemaScripts, string> script, ScriptContext context)
{
var ctx = CreateScriptContext(operation, command, data, oldData);
Enrich(context);
scriptEngine.Execute(ctx, GetScript(script));
scriptEngine.Execute(context, GetScript(script));
return TaskHelper.Done;
}
private static ScriptContext CreateScriptContext(object operation, ContentCommand command, NamedContentData data, NamedContentData oldData)
private void Enrich(ScriptContext context)
{
return new ScriptContext { ContentId = command.ContentId, OldData = oldData, Data = data, User = command.User, Operation = operation.ToString() };
context.ContentId = command.ContentId;
context.User = command.User;
}
private ValidationContext CreateValidationContext()
{
return new ValidationContext(contentId, schemaId, QueryContentsAsync, QueryAssetsAsync);
return new ValidationContext(command.ContentId, schemaId, QueryContentsAsync, QueryAssetsAsync);
}
private async Task<IReadOnlyList<IAssetInfo>> QueryAssetsAsync(IEnumerable<Guid> assetIds)

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

@ -261,7 +261,7 @@ namespace Squidex.Domain.Apps.Core.Operations.Scripting
userIdentity.AddClaim(new Claim(OpenIdClaims.ClientId, "2"));
var context = new ScriptContext { Data = content, OldData = oldContent, User = userPrincipal };
var context = new ScriptContext { Data = content, DataOld = oldContent, User = userPrincipal };
var result = sut.ExecuteAndTransform(context, @"
ctx.data.number0.iv = ctx.data.number0.iv + ctx.oldData.number0.iv * parseInt(ctx.user.id, 10);

42
tests/Squidex.Domain.Apps.Entities.Tests/Contents/ContentGrainTests.cs

@ -134,7 +134,7 @@ namespace Squidex.Domain.Apps.Entities.Contents
CreateContentEvent(new ContentCreated { Data = data, Status = Status.Draft })
);
A.CallTo(() => scriptEngine.ExecuteAndTransform(A<ScriptContext>.Ignored, "<create-script>"))
A.CallTo(() => scriptEngine.ExecuteAndTransform(ScriptContext(data, null, Status.Draft, default), "<create-script>"))
.MustHaveHappened();
A.CallTo(() => scriptEngine.Execute(A<ScriptContext>.Ignored, "<change-script>"))
.MustNotHaveHappened();
@ -157,9 +157,9 @@ namespace Squidex.Domain.Apps.Entities.Contents
CreateContentEvent(new ContentStatusChanged { Status = Status.Published, Change = StatusChange.Published })
);
A.CallTo(() => scriptEngine.ExecuteAndTransform(A<ScriptContext>.Ignored, "<create-script>"))
A.CallTo(() => scriptEngine.ExecuteAndTransform(ScriptContext(data, null, Status.Draft, default), "<create-script>"))
.MustHaveHappened();
A.CallTo(() => scriptEngine.Execute(A<ScriptContext>.Ignored, "<change-script>"))
A.CallTo(() => scriptEngine.Execute(ScriptContext(data, null, Status.Published, Status.Draft), "<change-script>"))
.MustHaveHappened();
}
@ -187,7 +187,7 @@ namespace Squidex.Domain.Apps.Entities.Contents
CreateContentEvent(new ContentUpdated { Data = otherData })
);
A.CallTo(() => scriptEngine.ExecuteAndTransform(A<ScriptContext>.Ignored, "<update-script>"))
A.CallTo(() => scriptEngine.ExecuteAndTransform(ScriptContext(otherData, data, Status.Draft, default), "<update-script>"))
.MustHaveHappened();
}
@ -210,7 +210,7 @@ namespace Squidex.Domain.Apps.Entities.Contents
CreateContentEvent(new ContentUpdateProposed { Data = otherData })
);
A.CallTo(() => scriptEngine.ExecuteAndTransform(A<ScriptContext>.Ignored, "<update-script>"))
A.CallTo(() => scriptEngine.ExecuteAndTransform(ScriptContext(otherData, data, Status.Published, default), "<update-script>"))
.MustHaveHappened();
}
@ -257,7 +257,7 @@ namespace Squidex.Domain.Apps.Entities.Contents
CreateContentEvent(new ContentUpdated { Data = patched })
);
A.CallTo(() => scriptEngine.ExecuteAndTransform(A<ScriptContext>.Ignored, "<update-script>"))
A.CallTo(() => scriptEngine.ExecuteAndTransform(ScriptContext(patched, data, Status.Draft, default), "<update-script>"))
.MustHaveHappened();
}
@ -280,7 +280,7 @@ namespace Squidex.Domain.Apps.Entities.Contents
CreateContentEvent(new ContentUpdateProposed { Data = patched })
);
A.CallTo(() => scriptEngine.ExecuteAndTransform(A<ScriptContext>.Ignored, "<update-script>"))
A.CallTo(() => scriptEngine.ExecuteAndTransform(ScriptContext(patched, data, Status.Published, default), "<update-script>"))
.MustHaveHappened();
}
@ -319,7 +319,7 @@ namespace Squidex.Domain.Apps.Entities.Contents
CreateContentEvent(new ContentStatusChanged { Change = StatusChange.Published, Status = Status.Published })
);
A.CallTo(() => scriptEngine.Execute(A<ScriptContext>.Ignored, "<change-script>"))
A.CallTo(() => scriptEngine.Execute(ScriptContext(data, null, Status.Published, Status.Draft), "<change-script>"))
.MustHaveHappened();
}
@ -341,7 +341,7 @@ namespace Squidex.Domain.Apps.Entities.Contents
CreateContentEvent(new ContentStatusChanged { Status = Status.Archived })
);
A.CallTo(() => scriptEngine.Execute(A<ScriptContext>.Ignored, "<change-script>"))
A.CallTo(() => scriptEngine.Execute(ScriptContext(data, null, Status.Archived, Status.Draft), "<change-script>"))
.MustHaveHappened();
}
@ -364,7 +364,7 @@ namespace Squidex.Domain.Apps.Entities.Contents
CreateContentEvent(new ContentStatusChanged { Change = StatusChange.Unpublished, Status = Status.Draft })
);
A.CallTo(() => scriptEngine.Execute(A<ScriptContext>.Ignored, "<change-script>"))
A.CallTo(() => scriptEngine.Execute(ScriptContext(data, null, Status.Draft, Status.Published), "<change-script>"))
.MustHaveHappened();
}
@ -387,7 +387,7 @@ namespace Squidex.Domain.Apps.Entities.Contents
CreateContentEvent(new ContentStatusChanged { Status = Status.Draft })
);
A.CallTo(() => scriptEngine.Execute(A<ScriptContext>.Ignored, "<change-script>"))
A.CallTo(() => scriptEngine.Execute(ScriptContext(data, null, Status.Draft, Status.Archived), "<change-script>"))
.MustHaveHappened();
}
@ -462,6 +462,9 @@ namespace Squidex.Domain.Apps.Entities.Contents
.ShouldHaveSameEvents(
CreateContentEvent(new ContentSchedulingCancelled())
);
A.CallTo(() => scriptEngine.Execute(A<ScriptContext>.Ignored, "<change-script>"))
.MustNotHaveHappened();
}
[Fact]
@ -482,7 +485,7 @@ namespace Squidex.Domain.Apps.Entities.Contents
CreateContentEvent(new ContentDeleted())
);
A.CallTo(() => scriptEngine.Execute(A<ScriptContext>.Ignored, "<delete-script>"))
A.CallTo(() => scriptEngine.Execute(ScriptContext(data, null, Status.Draft, default), "<delete-script>"))
.MustHaveHappened();
}
@ -542,6 +545,21 @@ namespace Squidex.Domain.Apps.Entities.Contents
return sut.ExecuteAsync(CreateContentCommand(new ChangeContentStatus { Status = Status.Published }));
}
private ScriptContext ScriptContext(NamedContentData newData, NamedContentData oldData, Status newStatus, Status oldStatus)
{
return A<ScriptContext>.That.Matches(x => M(x, newData, oldData, newStatus, oldStatus));
}
private bool M(ScriptContext x, NamedContentData newData, NamedContentData oldData, Status newStatus, Status oldStatus)
{
return
Equals(x.Data, newData) &&
Equals(x.DataOld, oldData) &&
Equals(x.Status, newStatus) &&
Equals(x.StatusOld, oldStatus) &&
x.ContentId == contentId && x.User == User;
}
protected T CreateContentEvent<T>(T @event) where T : ContentEvent
{
@event.ContentId = contentId;

Loading…
Cancel
Save