From b3fb4cf53336d3d8213cf9fb5cc11699a18e0505 Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Sat, 2 Sep 2017 22:25:53 +0200 Subject: [PATCH] Refactoring and separate transform method. --- .../Scripting/IScriptEngine.cs | 4 +- .../Scripting/JurassicScriptEngine.cs | 77 ++++++++---- .../Contents/ContentCommandMiddleware.cs | 6 +- src/Squidex/Config/Domain/WriteModule.cs | 7 +- .../ContentApi/ContentsController.cs | 12 +- .../ETagCommandMiddleware.cs | 2 +- .../EnrichWithActorCommandMiddleware.cs | 2 +- .../EnrichWithAppIdCommandMiddleware.cs | 2 +- .../EnrichWithSchemaIdCommandMiddleware.cs | 2 +- .../app/features/schemas/declarations.ts | 1 + src/Squidex/app/features/schemas/module.ts | 2 + .../pages/schema/schema-page.component.html | 12 ++ .../pages/schema/schema-page.component.ts | 9 ++ .../schema/schema-scripts-form.component.html | 31 +++++ .../schema/schema-scripts-form.component.scss | 10 ++ .../schema/schema-scripts-form.component.ts | 118 ++++++++++++++++++ .../angular/jscript-editor.component.ts | 4 +- .../shared/services/schemas.service.spec.ts | 12 +- .../app/shared/services/schemas.service.ts | 24 ++-- .../Scripting/JurassicScriptEngineTests.cs | 38 +++++- .../Contents/ContentCommandHandlerTests.cs | 20 +-- ...est.cs => InvalidatingMemoryCacheTests.cs} | 6 +- .../CollectionExtensionsTests.cs | 13 +- .../{NamedIdTest.cs => NamedIdTests.cs} | 0 24 files changed, 338 insertions(+), 76 deletions(-) rename src/Squidex/Pipeline/{CommandHandlers => CommandMiddlewares}/ETagCommandMiddleware.cs (97%) rename src/Squidex/Pipeline/{CommandHandlers => CommandMiddlewares}/EnrichWithActorCommandMiddleware.cs (97%) rename src/Squidex/Pipeline/{CommandHandlers => CommandMiddlewares}/EnrichWithAppIdCommandMiddleware.cs (96%) rename src/Squidex/Pipeline/{CommandHandlers => CommandMiddlewares}/EnrichWithSchemaIdCommandMiddleware.cs (98%) create mode 100644 src/Squidex/app/features/schemas/pages/schema/schema-scripts-form.component.html create mode 100644 src/Squidex/app/features/schemas/pages/schema/schema-scripts-form.component.scss create mode 100644 src/Squidex/app/features/schemas/pages/schema/schema-scripts-form.component.ts rename tests/Squidex.Infrastructure.Tests/Caching/{InvalidatingMemoryCacheTest.cs => InvalidatingMemoryCacheTests.cs} (96%) rename tests/Squidex.Infrastructure.Tests/{NamedIdTest.cs => NamedIdTests.cs} (100%) diff --git a/src/Squidex.Domain.Apps.Core/Scripting/IScriptEngine.cs b/src/Squidex.Domain.Apps.Core/Scripting/IScriptEngine.cs index fff7b509c..ab094ad77 100644 --- a/src/Squidex.Domain.Apps.Core/Scripting/IScriptEngine.cs +++ b/src/Squidex.Domain.Apps.Core/Scripting/IScriptEngine.cs @@ -14,6 +14,8 @@ namespace Squidex.Domain.Apps.Core.Scripting { void Execute(ScriptContext context, string script, string operationName); - NamedContentData ExecuteAndTransform(ScriptContext context, string script, string operationName, bool failOnError = false); + NamedContentData ExecuteAndTransform(ScriptContext context, string script, string operationName); + + NamedContentData Transform(ScriptContext context, string script); } } diff --git a/src/Squidex.Domain.Apps.Core/Scripting/JurassicScriptEngine.cs b/src/Squidex.Domain.Apps.Core/Scripting/JurassicScriptEngine.cs index 1db52834e..fffd52b37 100644 --- a/src/Squidex.Domain.Apps.Core/Scripting/JurassicScriptEngine.cs +++ b/src/Squidex.Domain.Apps.Core/Scripting/JurassicScriptEngine.cs @@ -35,13 +35,16 @@ namespace Squidex.Domain.Apps.Core.Scripting if (!string.IsNullOrWhiteSpace(script)) { - var engine = CreateScriptEngine(context, operationName); + var engine = CreateScriptEngine(context); - Execute(script, operationName, engine, true); + EnableDisallow(engine); + EnableReject(engine, operationName); + + Execute(engine, script, operationName); } } - public NamedContentData ExecuteAndTransform(ScriptContext context, string script, string operationName, bool failOnError = false) + public NamedContentData ExecuteAndTransform(ScriptContext context, string script, string operationName) { Guard.NotNull(context, nameof(context)); @@ -49,7 +52,10 @@ namespace Squidex.Domain.Apps.Core.Scripting if (!string.IsNullOrWhiteSpace(script)) { - var engine = CreateScriptEngine(context, operationName); + var engine = CreateScriptEngine(context); + + EnableDisallow(engine); + EnableReject(engine, operationName); engine.SetGlobalFunction("replace", new Action(data => { @@ -63,13 +69,39 @@ namespace Squidex.Domain.Apps.Core.Scripting } })); - Execute(script, operationName, engine, failOnError); + Execute(engine, script, operationName); + } + + return result; + } + + public NamedContentData Transform(ScriptContext context, string script) + { + Guard.NotNull(context, nameof(context)); + + var result = context.Data; + + if (!string.IsNullOrWhiteSpace(script)) + { + try + { + var engine = CreateScriptEngine(context); + + engine.SetGlobalFunction("replace", new Action(data => + { + result = JsonConvert.DeserializeObject(JSONObject.Stringify(engine, data)); + })); + } + catch (Exception) + { + result = context.Data; + } } return result; } - private static void Execute(string script, string operationName, ScriptEngine engine, bool failOnError = false) + private static void Execute(ScriptEngine engine, string script, string operationName) { try { @@ -77,25 +109,22 @@ namespace Squidex.Domain.Apps.Core.Scripting } catch (JavaScriptException ex) { - if (failOnError) - { - throw new ValidationException($"Failed to {operationName} with javascript error.", new ValidationError(ex.Message)); - } + throw new ValidationException($"Failed to {operationName} with javascript error.", new ValidationError(ex.Message)); } } - private ScriptEngine CreateScriptEngine(ScriptContext context, string operationName) + private ScriptEngine CreateScriptEngine(ScriptContext context) { - Guard.NotNullOrEmpty(operationName, nameof(operationName)); - var engine = new ScriptEngine { ForceStrictMode = true }; - engine.SetGlobalFunction("disallow", new Action(message => - { - var exMessage = !string.IsNullOrWhiteSpace(message) ? message : "Not allowed"; + engine.SetGlobalValue("ctx", JSONObject.Parse(engine, JsonConvert.SerializeObject(context, serializerSettings))); - throw new DomainForbiddenException(exMessage); - })); + return engine; + } + + private static void EnableReject(ScriptEngine engine, string operationName) + { + Guard.NotNullOrEmpty(operationName, nameof(operationName)); engine.SetGlobalFunction("reject", new Action(message => { @@ -103,12 +132,16 @@ namespace Squidex.Domain.Apps.Core.Scripting throw new ValidationException($"Script rejected to to {operationName}.", errors); })); + } - var json = JsonConvert.SerializeObject(context, serializerSettings); - - engine.SetGlobalValue("ctx", JSONObject.Parse(engine, json)); + private static void EnableDisallow(ScriptEngine engine) + { + engine.SetGlobalFunction("disallow", new Action(message => + { + var exMessage = !string.IsNullOrWhiteSpace(message) ? message : "Not allowed"; - return engine; + throw new DomainForbiddenException(exMessage); + })); } } } diff --git a/src/Squidex.Domain.Apps.Write/Contents/ContentCommandMiddleware.cs b/src/Squidex.Domain.Apps.Write/Contents/ContentCommandMiddleware.cs index 1d991ce55..09fcdde31 100644 --- a/src/Squidex.Domain.Apps.Write/Contents/ContentCommandMiddleware.cs +++ b/src/Squidex.Domain.Apps.Write/Contents/ContentCommandMiddleware.cs @@ -68,7 +68,7 @@ namespace Squidex.Domain.Apps.Write.Contents var schemaAndApp = await ResolveSchemaAndAppAsync(command); var scriptContext = CreateScriptContext(content, command, command.Data); - command.Data = scriptEngine.ExecuteAndTransform(scriptContext, schemaAndApp.SchemaEntity.ScriptCreate, "create content", true); + command.Data = scriptEngine.ExecuteAndTransform(scriptContext, schemaAndApp.SchemaEntity.ScriptCreate, "create content"); command.Data.Enrich(schemaAndApp.SchemaEntity.Schema, schemaAndApp.AppEntity.PartitionResolver); await ValidateAsync(schemaAndApp, command, () => "Failed to create content", false); @@ -86,7 +86,7 @@ namespace Squidex.Domain.Apps.Write.Contents var schemaAndApp = await ResolveSchemaAndAppAsync(command); var scriptContext = CreateScriptContext(content, command, command.Data); - command.Data = scriptEngine.ExecuteAndTransform(scriptContext, schemaAndApp.SchemaEntity.ScriptUpdate, "update content", true); + command.Data = scriptEngine.ExecuteAndTransform(scriptContext, schemaAndApp.SchemaEntity.ScriptUpdate, "update content"); await ValidateAsync(schemaAndApp, command, () => "Failed to update content", false); @@ -103,7 +103,7 @@ namespace Squidex.Domain.Apps.Write.Contents var schemaAndApp = await ResolveSchemaAndAppAsync(command); var scriptContext = CreateScriptContext(content, command, command.Data); - command.Data = scriptEngine.ExecuteAndTransform(scriptContext, schemaAndApp.SchemaEntity.ScriptUpdate, "patch content", true); + command.Data = scriptEngine.ExecuteAndTransform(scriptContext, schemaAndApp.SchemaEntity.ScriptUpdate, "patch content"); await ValidateAsync(schemaAndApp, command, () => "Failed to patch content", true); diff --git a/src/Squidex/Config/Domain/WriteModule.cs b/src/Squidex/Config/Domain/WriteModule.cs index db7ff6310..f9f009b3c 100644 --- a/src/Squidex/Config/Domain/WriteModule.cs +++ b/src/Squidex/Config/Domain/WriteModule.cs @@ -9,13 +9,14 @@ using Autofac; using Microsoft.Extensions.Configuration; using Squidex.Domain.Apps.Core.Schemas; +using Squidex.Domain.Apps.Core.Scripting; using Squidex.Domain.Apps.Write.Apps; using Squidex.Domain.Apps.Write.Assets; using Squidex.Domain.Apps.Write.Contents; using Squidex.Domain.Apps.Write.Schemas; using Squidex.Domain.Apps.Write.Webhooks; using Squidex.Infrastructure.CQRS.Commands; -using Squidex.Pipeline.CommandHandlers; +using Squidex.Pipeline.CommandMiddlewares; // ReSharper disable UnusedAutoPropertyAccessor.Local @@ -52,6 +53,10 @@ namespace Squidex.Config.Domain .As() .SingleInstance(); + builder.RegisterType() + .As() + .SingleInstance(); + builder.RegisterType() .AsSelf() .SingleInstance(); diff --git a/src/Squidex/Controllers/ContentApi/ContentsController.cs b/src/Squidex/Controllers/ContentApi/ContentsController.cs index 6d5433432..36e10ca6d 100644 --- a/src/Squidex/Controllers/ContentApi/ContentsController.cs +++ b/src/Squidex/Controllers/ContentApi/ContentsController.cs @@ -191,7 +191,7 @@ namespace Squidex.Controllers.ContentApi [ApiCosts(1)] public async Task PostContent([FromBody] NamedContentData request, [FromQuery] bool publish = false) { - var command = new CreateContent { ContentId = Guid.NewGuid(), Data = request.ToCleaned(), Publish = publish }; + var command = new CreateContent { ContentId = Guid.NewGuid(), Principal = User, Data = request.ToCleaned(), Publish = publish }; var context = await CommandBus.PublishAsync(command); @@ -207,7 +207,7 @@ namespace Squidex.Controllers.ContentApi [ApiCosts(1)] public async Task PutContent(Guid id, [FromBody] NamedContentData request) { - var command = new UpdateContent { ContentId = id, Data = request.ToCleaned() }; + var command = new UpdateContent { ContentId = id, Principal = User, Data = request.ToCleaned() }; var context = await CommandBus.PublishAsync(command); @@ -223,7 +223,7 @@ namespace Squidex.Controllers.ContentApi [ApiCosts(1)] public async Task PatchContent(Guid id, [FromBody] NamedContentData request) { - var command = new PatchContent { ContentId = id, Data = request.ToCleaned() }; + var command = new PatchContent { ContentId = id, Principal = User, Data = request.ToCleaned() }; var context = await CommandBus.PublishAsync(command); @@ -239,7 +239,7 @@ namespace Squidex.Controllers.ContentApi [ApiCosts(1)] public async Task PublishContent(Guid id) { - var command = new PublishContent { ContentId = id }; + var command = new PublishContent { ContentId = id, Principal = User }; await CommandBus.PublishAsync(command); @@ -252,7 +252,7 @@ namespace Squidex.Controllers.ContentApi [ApiCosts(1)] public async Task UnpublishContent(Guid id) { - var command = new UnpublishContent { ContentId = id }; + var command = new UnpublishContent { ContentId = id, Principal = User }; await CommandBus.PublishAsync(command); @@ -265,7 +265,7 @@ namespace Squidex.Controllers.ContentApi [ApiCosts(1)] public async Task PutContent(Guid id) { - var command = new DeleteContent { ContentId = id }; + var command = new DeleteContent { ContentId = id, Principal = User }; await CommandBus.PublishAsync(command); diff --git a/src/Squidex/Pipeline/CommandHandlers/ETagCommandMiddleware.cs b/src/Squidex/Pipeline/CommandMiddlewares/ETagCommandMiddleware.cs similarity index 97% rename from src/Squidex/Pipeline/CommandHandlers/ETagCommandMiddleware.cs rename to src/Squidex/Pipeline/CommandMiddlewares/ETagCommandMiddleware.cs index 2bd4f6639..c77a7e509 100644 --- a/src/Squidex/Pipeline/CommandHandlers/ETagCommandMiddleware.cs +++ b/src/Squidex/Pipeline/CommandMiddlewares/ETagCommandMiddleware.cs @@ -13,7 +13,7 @@ using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Primitives; using Squidex.Infrastructure.CQRS.Commands; -namespace Squidex.Pipeline.CommandHandlers +namespace Squidex.Pipeline.CommandMiddlewares { public class ETagCommandMiddleware : ICommandMiddleware { diff --git a/src/Squidex/Pipeline/CommandHandlers/EnrichWithActorCommandMiddleware.cs b/src/Squidex/Pipeline/CommandMiddlewares/EnrichWithActorCommandMiddleware.cs similarity index 97% rename from src/Squidex/Pipeline/CommandHandlers/EnrichWithActorCommandMiddleware.cs rename to src/Squidex/Pipeline/CommandMiddlewares/EnrichWithActorCommandMiddleware.cs index ff172bea3..92edbdf70 100644 --- a/src/Squidex/Pipeline/CommandHandlers/EnrichWithActorCommandMiddleware.cs +++ b/src/Squidex/Pipeline/CommandMiddlewares/EnrichWithActorCommandMiddleware.cs @@ -17,7 +17,7 @@ using Squidex.Infrastructure.Security; // ReSharper disable InvertIf -namespace Squidex.Pipeline.CommandHandlers +namespace Squidex.Pipeline.CommandMiddlewares { public class EnrichWithActorCommandMiddleware : ICommandMiddleware { diff --git a/src/Squidex/Pipeline/CommandHandlers/EnrichWithAppIdCommandMiddleware.cs b/src/Squidex/Pipeline/CommandMiddlewares/EnrichWithAppIdCommandMiddleware.cs similarity index 96% rename from src/Squidex/Pipeline/CommandHandlers/EnrichWithAppIdCommandMiddleware.cs rename to src/Squidex/Pipeline/CommandMiddlewares/EnrichWithAppIdCommandMiddleware.cs index 50a24ae94..d206e95bb 100644 --- a/src/Squidex/Pipeline/CommandHandlers/EnrichWithAppIdCommandMiddleware.cs +++ b/src/Squidex/Pipeline/CommandMiddlewares/EnrichWithAppIdCommandMiddleware.cs @@ -15,7 +15,7 @@ using Squidex.Infrastructure.CQRS.Commands; // ReSharper disable InvertIf -namespace Squidex.Pipeline.CommandHandlers +namespace Squidex.Pipeline.CommandMiddlewares { public sealed class EnrichWithAppIdCommandMiddleware : ICommandMiddleware { diff --git a/src/Squidex/Pipeline/CommandHandlers/EnrichWithSchemaIdCommandMiddleware.cs b/src/Squidex/Pipeline/CommandMiddlewares/EnrichWithSchemaIdCommandMiddleware.cs similarity index 98% rename from src/Squidex/Pipeline/CommandHandlers/EnrichWithSchemaIdCommandMiddleware.cs rename to src/Squidex/Pipeline/CommandMiddlewares/EnrichWithSchemaIdCommandMiddleware.cs index ffd1589e5..e1af82270 100644 --- a/src/Squidex/Pipeline/CommandHandlers/EnrichWithSchemaIdCommandMiddleware.cs +++ b/src/Squidex/Pipeline/CommandMiddlewares/EnrichWithSchemaIdCommandMiddleware.cs @@ -18,7 +18,7 @@ using Squidex.Infrastructure.CQRS.Commands; // ReSharper disable InvertIf -namespace Squidex.Pipeline.CommandHandlers +namespace Squidex.Pipeline.CommandMiddlewares { public sealed class EnrichWithSchemaIdCommandMiddleware : ICommandMiddleware { diff --git a/src/Squidex/app/features/schemas/declarations.ts b/src/Squidex/app/features/schemas/declarations.ts index 48fefa6cb..a5024eedd 100644 --- a/src/Squidex/app/features/schemas/declarations.ts +++ b/src/Squidex/app/features/schemas/declarations.ts @@ -24,5 +24,6 @@ export * from './pages/schema/types/string-validation.component'; export * from './pages/schema/field.component'; export * from './pages/schema/schema-edit-form.component'; export * from './pages/schema/schema-page.component'; +export * from './pages/schema/schema-scripts-form.component'; export * from './pages/schemas/schema-form.component'; export * from './pages/schemas/schemas-page.component'; \ No newline at end of file diff --git a/src/Squidex/app/features/schemas/module.ts b/src/Squidex/app/features/schemas/module.ts index e4e7011ae..9cb8be7dc 100644 --- a/src/Squidex/app/features/schemas/module.ts +++ b/src/Squidex/app/features/schemas/module.ts @@ -37,6 +37,7 @@ import { SchemaFormComponent, SchemaPageComponent, SchemasPageComponent, + SchemaScriptsFormComponent, StringUIComponent, StringValidationComponent } from './declarations'; @@ -101,6 +102,7 @@ const routes: Routes = [ SchemaEditFormComponent, SchemaFormComponent, SchemaPageComponent, + SchemaScriptsFormComponent, SchemasPageComponent, StringUIComponent, StringValidationComponent diff --git a/src/Squidex/app/features/schemas/pages/schema/schema-page.component.html b/src/Squidex/app/features/schemas/pages/schema/schema-page.component.html index 61c1c94b6..bd002ab0c 100644 --- a/src/Squidex/app/features/schemas/pages/schema/schema-page.component.html +++ b/src/Squidex/app/features/schemas/pages/schema/schema-page.component.html @@ -22,6 +22,9 @@ + + \ No newline at end of file diff --git a/src/Squidex/app/features/schemas/pages/schema/schema-page.component.ts b/src/Squidex/app/features/schemas/pages/schema/schema-page.component.ts index a30142527..543ddc443 100644 --- a/src/Squidex/app/features/schemas/pages/schema/schema-page.component.ts +++ b/src/Squidex/app/features/schemas/pages/schema/schema-page.component.ts @@ -27,6 +27,7 @@ import { SchemaPropertiesDto, SchemasService, UpdateFieldDto, + UpdateSchemaScriptsDto, ValidatorsEx } from 'shared'; @@ -49,6 +50,8 @@ export class SchemaPageComponent extends AppComponentBase implements OnInit { public exportSchemaDialog = new ModalView(); + public configureScriptsDialog = new ModalView(); + public editOptionsDropdown = new ModalView(); public editSchemaDialog = new ModalView(); @@ -239,6 +242,12 @@ export class SchemaPageComponent extends AppComponentBase implements OnInit { this.editSchemaDialog.hide(); } + public onSchemaScriptsSaved(scripts: UpdateSchemaScriptsDto) { + this.updateSchema(this.schema.configureScripts(scripts, this.authService.user.token)); + + this.configureScriptsDialog.hide(); + } + private resetFieldForm() { this.addFieldForm.enable(); this.addFieldForm.reset({ type: 'String' }); diff --git a/src/Squidex/app/features/schemas/pages/schema/schema-scripts-form.component.html b/src/Squidex/app/features/schemas/pages/schema/schema-scripts-form.component.html new file mode 100644 index 000000000..fe16016bd --- /dev/null +++ b/src/Squidex/app/features/schemas/pages/schema/schema-scripts-form.component.html @@ -0,0 +1,31 @@ +
+ + + + + +
+ diff --git a/src/Squidex/app/features/schemas/pages/schema/schema-scripts-form.component.scss b/src/Squidex/app/features/schemas/pages/schema/schema-scripts-form.component.scss new file mode 100644 index 000000000..f016991ef --- /dev/null +++ b/src/Squidex/app/features/schemas/pages/schema/schema-scripts-form.component.scss @@ -0,0 +1,10 @@ +@import '_vars'; +@import '_mixins'; + +.nav-link { + cursor: default; +} + +.nav-tabs { + border: 0; +} \ No newline at end of file diff --git a/src/Squidex/app/features/schemas/pages/schema/schema-scripts-form.component.ts b/src/Squidex/app/features/schemas/pages/schema/schema-scripts-form.component.ts new file mode 100644 index 000000000..3063bff03 --- /dev/null +++ b/src/Squidex/app/features/schemas/pages/schema/schema-scripts-form.component.ts @@ -0,0 +1,118 @@ +/* + * Squidex Headless CMS + * + * @license + * Copyright (c) Sebastian Stehle. All rights reserved + */ + +import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; +import { FormBuilder } from '@angular/forms'; + +import { + ComponentBase, + DialogService, + SchemaDetailsDto, + SchemasService, + UpdateSchemaScriptsDto +} from 'shared'; + +@Component({ + selector: 'sqx-schema-scripts-form', + styleUrls: ['./schema-scripts-form.component.scss'], + templateUrl: './schema-scripts-form.component.html' +}) +export class SchemaScriptsFormComponent extends ComponentBase implements OnInit { + @Output() + public saved = new EventEmitter(); + + @Output() + public cancelled = new EventEmitter(); + + @Input() + public schema: SchemaDetailsDto; + + @Input() + public appName: string; + + public selectedField = 'scriptQuery'; + + public scripts = [ + 'Query', + 'Create', + 'Update', + 'Delete', + 'Publish', + 'Unpublish' + ]; + + public editForm = + this.formBuilder.group({ + scriptQuery: '', + scriptCreate: '', + scriptUpdate: '', + scriptDelete: '', + scriptPublish: '', + scriptUnpublish: '' + }); + + constructor(dialogs: DialogService, + private readonly schemas: SchemasService, + private readonly formBuilder: FormBuilder + ) { + super(dialogs); + } + + public ngOnInit() { + this.editForm.patchValue(this.schema); + } + + public cancel() { + this.emitCancelled(); + this.resetEditForm(); + } + + public saveSchema() { + if (this.editForm.valid) { + this.editForm.disable(); + + const requestDto = + new UpdateSchemaScriptsDto( + this.editForm.controls['scriptQuery'].value, + this.editForm.controls['scriptCreate'].value, + this.editForm.controls['scriptUpdate'].value, + this.editForm.controls['scriptDelete'].value, + this.editForm.controls['scriptPublish'].value, + this.editForm.controls['scriptUnpublish'].value); + + this.schemas.putSchemaScripts(this.appName, this.schema.name, requestDto, this.schema.version) + .subscribe(dto => { + this.emitSaved(requestDto); + this.resetEditForm(); + }, error => { + this.notifyError(error); + this.enableEditForm(); + }); + } + } + + private emitCancelled() { + this.cancelled.emit(); + } + + private emitSaved(requestDto: UpdateSchemaScriptsDto) { + this.saved.emit(requestDto); + } + + public selectField(field: string) { + this.selectedField = field; + } + + private enableEditForm() { + this.editForm.enable(); + } + + private resetEditForm() { + this.editForm.reset(); + this.editForm.enable(); + } +} \ No newline at end of file diff --git a/src/Squidex/app/framework/angular/jscript-editor.component.ts b/src/Squidex/app/framework/angular/jscript-editor.component.ts index f151e4e55..be2f225b6 100644 --- a/src/Squidex/app/framework/angular/jscript-editor.component.ts +++ b/src/Squidex/app/framework/angular/jscript-editor.component.ts @@ -101,8 +101,8 @@ export class JscriptEditorComponent implements ControlValueAccessor, AfterViewIn this.oldValue = newValue; } - private setValue(value: any) { - this.aceEditor.setValue(value); + private setValue(value: string) { + this.aceEditor.setValue(value || ''); this.aceEditor.clearSelection(); } } \ No newline at end of file diff --git a/src/Squidex/app/shared/services/schemas.service.spec.ts b/src/Squidex/app/shared/services/schemas.service.spec.ts index 241489dd6..d2ec60e7d 100644 --- a/src/Squidex/app/shared/services/schemas.service.spec.ts +++ b/src/Squidex/app/shared/services/schemas.service.spec.ts @@ -388,12 +388,12 @@ describe('SchemasService', () => { } } ], - scriptsQuery: '', - scriptsCreate: '', - scriptsUpdate: '', - scriptsDelete: '', - scriptsPublish: '', - scriptsUnpublish: '' + scriptQuery: '', + scriptCreate: '', + scriptUpdate: '', + scriptDelete: '', + scriptPublish: '', + scriptUnpublish: '' }); expect(schema).toEqual( diff --git a/src/Squidex/app/shared/services/schemas.service.ts b/src/Squidex/app/shared/services/schemas.service.ts index 17ad6c953..4d15958a1 100644 --- a/src/Squidex/app/shared/services/schemas.service.ts +++ b/src/Squidex/app/shared/services/schemas.service.ts @@ -760,12 +760,12 @@ export class SchemasService { DateTime.parseISO_UTC(response.lastModified), new Version(response.version.toString()), fields, - response.scriptsQuery, - response.scriptsCreate, - response.scriptsUpdate, - response.scriptsDelete, - response.scriptsPublish, - response.scriptsUnpublish); + response.scriptQuery, + response.scriptCreate, + response.scriptUpdate, + response.scriptDelete, + response.scriptPublish, + response.scriptUnpublish); }) .catch(error => { if (error instanceof HttpErrorResponse && error.status === 404) { @@ -799,12 +799,12 @@ export class SchemasService { now, version, dto.fields || [], - response.scriptsQuery, - response.scriptsCreate, - response.scriptsUpdate, - response.scriptsDelete, - response.scriptsPublish, - response.scriptsUnpublish); + response.scriptQuery, + response.scriptCreate, + response.scriptUpdate, + response.scriptDelete, + response.scriptPublish, + response.scriptUnpublish); }) .do(schema => { this.localCache.set(`schema.${appName}.${schema.id}`, schema, 5000); diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Scripting/JurassicScriptEngineTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Scripting/JurassicScriptEngineTests.cs index 7e9b06343..eb16ef818 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/Scripting/JurassicScriptEngineTests.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/Scripting/JurassicScriptEngineTests.cs @@ -50,22 +50,31 @@ namespace Squidex.Domain.Apps.Core.Scripting } [Fact] - public void Should_catch_script_runtime_errors_on_transform() + public void Should_catch_script_runtime_errors_on_execute_and_transform() { - Assert.Throws(() => scriptEngine.ExecuteAndTransform(new ScriptContext(), "throw 'Error';", "update", true)); + Assert.Throws(() => scriptEngine.ExecuteAndTransform(new ScriptContext(), "throw 'Error';", "update")); } [Fact] - public void Should_return_original_content_when_script_failed() + public void Should_return_original_content_when_transform_script_failed() { var content = new NamedContentData(); var context = new ScriptContext { Data = content }; - var result = scriptEngine.ExecuteAndTransform(context, "x => x", "update"); + var result = scriptEngine.Transform(context, "x => x"); Assert.Same(content, result); } + [Fact] + public void Should_throw_when_execute_and_transform_script_failed() + { + var content = new NamedContentData(); + var context = new ScriptContext { Data = content }; + + Assert.Throws(() => scriptEngine.ExecuteAndTransform(context, "x => x", "update")); + } + [Fact] public void Should_return_original_content_when_content_is_not_replaced() { @@ -78,7 +87,26 @@ namespace Squidex.Domain.Apps.Core.Scripting } [Fact] - public void Should_returning_empty_content_when_replacing_with_invalid_content() + public void Should_return_original_content_when_replacing_with_invalid_content_in_transform() + { + var content = + new NamedContentData() + .AddField("number0", + new ContentFieldData() + .AddValue("iv", 1)) + .AddField("number1", + new ContentFieldData() + .AddValue("iv", 1)); + + var context = new ScriptContext { Data = content }; + + var result = scriptEngine.Transform(context, @"replace({ test: 1 });"); + + Assert.Equal(content, result); + } + + [Fact] + public void Should_return_empty_content_when_replacing_with_invalid_content_in_execute_and_transform() { var content = new NamedContentData() diff --git a/tests/Squidex.Domain.Apps.Write.Tests/Contents/ContentCommandHandlerTests.cs b/tests/Squidex.Domain.Apps.Write.Tests/Contents/ContentCommandHandlerTests.cs index 394f7ab84..e839e2515 100644 --- a/tests/Squidex.Domain.Apps.Write.Tests/Contents/ContentCommandHandlerTests.cs +++ b/tests/Squidex.Domain.Apps.Write.Tests/Contents/ContentCommandHandlerTests.cs @@ -65,7 +65,7 @@ namespace Squidex.Domain.Apps.Write.Contents [Fact] public async Task Create_should_throw_exception_if_data_is_not_valid() { - A.CallTo(() => scriptEngine.ExecuteAndTransform(A.Ignored, A.Ignored, A.Ignored, true)).Returns(invalidData); + A.CallTo(() => scriptEngine.ExecuteAndTransform(A.Ignored, A.Ignored, A.Ignored)).Returns(invalidData); var context = CreateContextForCommand(new CreateContent { ContentId = contentId, Data = invalidData }); @@ -78,7 +78,7 @@ namespace Squidex.Domain.Apps.Write.Contents [Fact] public async Task Create_should_create_content() { - A.CallTo(() => scriptEngine.ExecuteAndTransform(A.Ignored, A.Ignored, A.Ignored, true)).Returns(data); + A.CallTo(() => scriptEngine.ExecuteAndTransform(A.Ignored, A.Ignored, A.Ignored)).Returns(data); A.CallTo(() => schemaEntity.ScriptCreate).Returns(""); var context = CreateContextForCommand(new CreateContent { ContentId = contentId, Data = data }); @@ -90,13 +90,13 @@ namespace Squidex.Domain.Apps.Write.Contents Assert.Equal(data, context.Result>().IdOrValue); - A.CallTo(() => scriptEngine.ExecuteAndTransform(A.Ignored, "", "create content", true)).MustHaveHappened(); + A.CallTo(() => scriptEngine.ExecuteAndTransform(A.Ignored, "", "create content")).MustHaveHappened(); } [Fact] public async Task Update_should_throw_exception_if_data_is_not_valid() { - A.CallTo(() => scriptEngine.ExecuteAndTransform(A.Ignored, A.Ignored, A.Ignored, true)).Returns(invalidData); + A.CallTo(() => scriptEngine.ExecuteAndTransform(A.Ignored, A.Ignored, A.Ignored)).Returns(invalidData); CreateContent(); @@ -111,7 +111,7 @@ namespace Squidex.Domain.Apps.Write.Contents [Fact] public async Task Update_should_update_domain_object() { - A.CallTo(() => scriptEngine.ExecuteAndTransform(A.Ignored, A.Ignored, A.Ignored, true)).Returns(data); + A.CallTo(() => scriptEngine.ExecuteAndTransform(A.Ignored, A.Ignored, A.Ignored)).Returns(data); A.CallTo(() => schemaEntity.ScriptUpdate).Returns(""); CreateContent(); @@ -125,13 +125,13 @@ namespace Squidex.Domain.Apps.Write.Contents Assert.Equal(data, context.Result().Data); - A.CallTo(() => scriptEngine.ExecuteAndTransform(A.Ignored, "", "update content", true)).MustHaveHappened(); + A.CallTo(() => scriptEngine.ExecuteAndTransform(A.Ignored, "", "update content")).MustHaveHappened(); } [Fact] public async Task Patch_should_throw_exception_if_data_is_not_valid() { - A.CallTo(() => scriptEngine.ExecuteAndTransform(A.Ignored, A.Ignored, A.Ignored, true)).Returns(invalidData); + A.CallTo(() => scriptEngine.ExecuteAndTransform(A.Ignored, A.Ignored, A.Ignored)).Returns(invalidData); CreateContent(); @@ -146,12 +146,12 @@ namespace Squidex.Domain.Apps.Write.Contents [Fact] public async Task Patch_should_update_domain_object() { - A.CallTo(() => scriptEngine.ExecuteAndTransform(A.Ignored, A.Ignored, A.Ignored, true)).Returns(data); + A.CallTo(() => scriptEngine.ExecuteAndTransform(A.Ignored, A.Ignored, A.Ignored)).Returns(data); A.CallTo(() => schemaEntity.ScriptUpdate).Returns(""); var path = new NamedContentData().AddField("my-field", new ContentFieldData().SetValue(3)); - A.CallTo(() => scriptEngine.ExecuteAndTransform(A.Ignored, A.Ignored, A.Ignored, true)).Returns(path); + A.CallTo(() => scriptEngine.ExecuteAndTransform(A.Ignored, A.Ignored, A.Ignored)).Returns(path); CreateContent(); @@ -164,7 +164,7 @@ namespace Squidex.Domain.Apps.Write.Contents Assert.NotNull(context.Result().Data); - A.CallTo(() => scriptEngine.ExecuteAndTransform(A.Ignored, "", "patch content", true)).MustHaveHappened(); + A.CallTo(() => scriptEngine.ExecuteAndTransform(A.Ignored, "", "patch content")).MustHaveHappened(); } [Fact] diff --git a/tests/Squidex.Infrastructure.Tests/Caching/InvalidatingMemoryCacheTest.cs b/tests/Squidex.Infrastructure.Tests/Caching/InvalidatingMemoryCacheTests.cs similarity index 96% rename from tests/Squidex.Infrastructure.Tests/Caching/InvalidatingMemoryCacheTest.cs rename to tests/Squidex.Infrastructure.Tests/Caching/InvalidatingMemoryCacheTests.cs index 9a29394f7..ac1951162 100644 --- a/tests/Squidex.Infrastructure.Tests/Caching/InvalidatingMemoryCacheTest.cs +++ b/tests/Squidex.Infrastructure.Tests/Caching/InvalidatingMemoryCacheTests.cs @@ -16,7 +16,7 @@ using Xunit; namespace Squidex.Infrastructure.Caching { - public class InvalidatingMemoryCacheTest + public class InvalidatingMemoryCacheTests { internal sealed class MyOptions : IOptions where T : class, new() { @@ -32,7 +32,7 @@ namespace Squidex.Infrastructure.Caching private readonly IMemoryCache cache = A.Fake(); private readonly InvalidatingMemoryCache sut; - public InvalidatingMemoryCacheTest() + public InvalidatingMemoryCacheTests() { sut = new InvalidatingMemoryCache(cache, pubsub); } @@ -99,7 +99,7 @@ namespace Squidex.Infrastructure.Caching [Fact] public void Should_use_inner_cache_to_get_value() { - object outValue; + object outValue = 123; A.CallTo(() => cache.TryGetValue("a-key", out outValue)) .Returns(true); diff --git a/tests/Squidex.Infrastructure.Tests/CollectionExtensionsTests.cs b/tests/Squidex.Infrastructure.Tests/CollectionExtensionsTests.cs index 6242da80e..078743155 100644 --- a/tests/Squidex.Infrastructure.Tests/CollectionExtensionsTests.cs +++ b/tests/Squidex.Infrastructure.Tests/CollectionExtensionsTests.cs @@ -11,7 +11,7 @@ using Xunit; namespace Squidex.Infrastructure { - public class CollectionExtensionTest + public class CollectionExtensionTests { private readonly Dictionary valueDictionary = new Dictionary(); private readonly Dictionary> listDictionary = new Dictionary>(); @@ -257,5 +257,16 @@ namespace Squidex.Infrastructure Assert.NotEqual(lhs.DictionaryHashCode(), rhs.DictionaryHashCode()); } + + [Fact] + public void Foreach_should_call_action_foreach_item() + { + var source = new List { 3, 5, 1 }; + var target = new List(); + + source.Foreach(target.Add); + + Assert.Equal(source, target); + } } } \ No newline at end of file diff --git a/tests/Squidex.Infrastructure.Tests/NamedIdTest.cs b/tests/Squidex.Infrastructure.Tests/NamedIdTests.cs similarity index 100% rename from tests/Squidex.Infrastructure.Tests/NamedIdTest.cs rename to tests/Squidex.Infrastructure.Tests/NamedIdTests.cs