From c41e69c38770d072d776077d51641fd5ecec5d96 Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Sat, 26 Jan 2019 23:39:37 +0100 Subject: [PATCH] Tests for sync. --- .../Schemas/Json/JsonNestedFieldModel.cs | 8 +- .../Schemas/Json/JsonSchemaModel.cs | 41 +++++++-- .../SchemaSynchronizer.cs | 22 ++--- .../Schemas/Commands/SynchronizeSchema.cs | 3 + .../Schemas/Commands/UpsertCommand.cs | 15 ++++ .../Schemas/Commands/UpsertSchemaField.cs | 3 +- .../Schemas/SchemaGrain.cs | 27 ++++-- .../Schemas/Models/ConfigureScriptsDto.cs | 31 +------ .../Schemas/Models/CreateSchemaDto.cs | 59 +------------ .../Schemas/Models/SynchronizeSchemaDto.cs | 29 +++++++ .../Controllers/Schemas/Models/UpsertDto.cs | 87 +++++++++++++++++++ ...emaFieldDto.cs => UpsertSchemaFieldDto.cs} | 4 +- ...ldDto.cs => UpsertSchemaNestedFieldDto.cs} | 2 +- .../Controllers/Schemas/SchemasController.cs | 22 +++++ .../Model/Schemas/SchemaTests.cs | 13 ++- .../TestUtils.cs | 4 +- .../Schemas/Guards/GuardSchemaTests.cs | 6 +- .../Schemas/SchemaGrainTests.cs | 42 ++++++++- tools/Migrate_01/Rebuilder.cs | 1 - 19 files changed, 295 insertions(+), 124 deletions(-) create mode 100644 src/Squidex/Areas/Api/Controllers/Schemas/Models/SynchronizeSchemaDto.cs create mode 100644 src/Squidex/Areas/Api/Controllers/Schemas/Models/UpsertDto.cs rename src/Squidex/Areas/Api/Controllers/Schemas/Models/{CreateSchemaFieldDto.cs => UpsertSchemaFieldDto.cs} (93%) rename src/Squidex/Areas/Api/Controllers/Schemas/Models/{CreateSchemaNestedFieldDto.cs => UpsertSchemaNestedFieldDto.cs} (96%) diff --git a/src/Squidex.Domain.Apps.Core.Model/Schemas/Json/JsonNestedFieldModel.cs b/src/Squidex.Domain.Apps.Core.Model/Schemas/Json/JsonNestedFieldModel.cs index c7a42baaa..21f28db97 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Schemas/Json/JsonNestedFieldModel.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Schemas/Json/JsonNestedFieldModel.cs @@ -20,17 +20,15 @@ namespace Squidex.Domain.Apps.Core.Schemas.Json [JsonProperty] public bool IsHidden { get; set; } + [JsonProperty] + public bool IsLocked { get; set; } + [JsonProperty] public bool IsDisabled { get; set; } [JsonProperty] public FieldProperties Properties { get; set; } - public bool IsLocked - { - get { return false; } - } - public NestedField ToNestedField() { return Properties.CreateNestedField(Id, Name, this); diff --git a/src/Squidex.Domain.Apps.Core.Model/Schemas/Json/JsonSchemaModel.cs b/src/Squidex.Domain.Apps.Core.Model/Schemas/Json/JsonSchemaModel.cs index c3c04c851..bfbf2c709 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Schemas/Json/JsonSchemaModel.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Schemas/Json/JsonSchemaModel.cs @@ -6,8 +6,11 @@ // ========================================================================== using System; +using System.Collections.Generic; +using System.Linq; using Newtonsoft.Json; using Squidex.Infrastructure; +using Squidex.Infrastructure.Reflection; namespace Squidex.Domain.Apps.Core.Schemas.Json { @@ -16,6 +19,12 @@ namespace Squidex.Domain.Apps.Core.Schemas.Json [JsonProperty] public string Name { get; set; } + [JsonProperty] + public string Category { get; set; } + + [JsonProperty] + public bool IsSingleton { get; set; } + [JsonProperty] public bool IsPublished { get; set; } @@ -25,15 +34,19 @@ namespace Squidex.Domain.Apps.Core.Schemas.Json [JsonProperty] public JsonFieldModel[] Fields { get; set; } + [JsonProperty] + public IReadOnlyDictionary Scripts { get; set; } + + [JsonProperty] + public IReadOnlyDictionary PreviewUrls { get; set; } + public JsonSchemaModel() { } public JsonSchemaModel(Schema schema) { - Name = schema.Name; - - Properties = schema.Properties; + SimpleMapper.Map(schema, this); Fields = schema.Fields.ToArray(x => @@ -48,8 +61,6 @@ namespace Squidex.Domain.Apps.Core.Schemas.Json Partitioning = x.Partitioning.Key, Properties = x.RawProperties }); - - IsPublished = schema.IsPublished; } private static JsonNestedFieldModel[] CreateChildren(IField field) @@ -62,6 +73,7 @@ namespace Squidex.Domain.Apps.Core.Schemas.Json Id = x.Id, Name = x.Name, IsHidden = x.IsHidden, + IsLocked = x.IsLocked, IsDisabled = x.IsDisabled, Properties = x.RawProperties }); @@ -74,7 +86,24 @@ namespace Squidex.Domain.Apps.Core.Schemas.Json { var fields = Fields.ToArray(f => f.ToField()) ?? Array.Empty(); - return new Schema(Name, fields, Properties, IsPublished); + var schema = new Schema(Name, fields, Properties, IsPublished, IsSingleton); + + if (!string.IsNullOrWhiteSpace(Category)) + { + schema = schema.ChangeCategory(Category); + } + + if (Scripts?.Count > 0) + { + schema = schema.ConfigureScripts(Scripts); + } + + if (PreviewUrls?.Count > 0) + { + schema = schema.ConfigurePreviewUrls(PreviewUrls); + } + + return schema; } } } \ No newline at end of file diff --git a/src/Squidex.Domain.Apps.Core.Operations/EventSynchronization/SchemaSynchronizer.cs b/src/Squidex.Domain.Apps.Core.Operations/EventSynchronization/SchemaSynchronizer.cs index 5622b4807..cc693745c 100644 --- a/src/Squidex.Domain.Apps.Core.Operations/EventSynchronization/SchemaSynchronizer.cs +++ b/src/Squidex.Domain.Apps.Core.Operations/EventSynchronization/SchemaSynchronizer.cs @@ -38,13 +38,6 @@ namespace Squidex.Domain.Apps.Core.EventSynchronization return @event; } - var events = SyncFields(source.FieldCollection, target.FieldCollection, serializer, idGenerator, null, options); - - foreach (var @event in events) - { - yield return E(@event); - } - if (!source.Properties.EqualsJson(target.Properties, serializer)) { yield return E(new SchemaUpdated { Properties = target.Properties }); @@ -55,14 +48,14 @@ namespace Squidex.Domain.Apps.Core.EventSynchronization yield return E(new SchemaCategoryChanged { Name = target.Category }); } - if (!source.PreviewUrls.EqualsDictionary(target.PreviewUrls)) + if (!source.Scripts.EqualsDictionary(target.Scripts)) { - yield return E(new SchemaPreviewUrlsConfigured { PreviewUrls = target.PreviewUrls.ToDictionary(x => x.Key, x => x.Value) }); + yield return E(new SchemaScriptsConfigured { Scripts = target.Scripts.ToDictionary(x => x.Key, x => x.Value) }); } - if (!source.Scripts.EqualsDictionary(target.Scripts)) + if (!source.PreviewUrls.EqualsDictionary(target.PreviewUrls)) { - yield return E(new SchemaScriptsConfigured { Scripts = target.Scripts.ToDictionary(x => x.Key, x => x.Value) }); + yield return E(new SchemaPreviewUrlsConfigured { PreviewUrls = target.PreviewUrls.ToDictionary(x => x.Key, x => x.Value) }); } if (source.IsPublished != target.IsPublished) @@ -71,6 +64,13 @@ namespace Squidex.Domain.Apps.Core.EventSynchronization E(new SchemaPublished()) : E(new SchemaUnpublished()); } + + var events = SyncFields(source.FieldCollection, target.FieldCollection, serializer, idGenerator, null, options); + + foreach (var @event in events) + { + yield return E(@event); + } } } diff --git a/src/Squidex.Domain.Apps.Entities/Schemas/Commands/SynchronizeSchema.cs b/src/Squidex.Domain.Apps.Entities/Schemas/Commands/SynchronizeSchema.cs index 97b093dd5..cc185e52b 100644 --- a/src/Squidex.Domain.Apps.Entities/Schemas/Commands/SynchronizeSchema.cs +++ b/src/Squidex.Domain.Apps.Entities/Schemas/Commands/SynchronizeSchema.cs @@ -9,5 +9,8 @@ namespace Squidex.Domain.Apps.Entities.Schemas.Commands { public sealed class SynchronizeSchema : UpsertCommand { + public bool NoFieldDeletion { get; set; } + + public bool NoFieldRecreation { get; set; } } } diff --git a/src/Squidex.Domain.Apps.Entities/Schemas/Commands/UpsertCommand.cs b/src/Squidex.Domain.Apps.Entities/Schemas/Commands/UpsertCommand.cs index 8e4b18427..0ab6fa7cf 100644 --- a/src/Squidex.Domain.Apps.Entities/Schemas/Commands/UpsertCommand.cs +++ b/src/Squidex.Domain.Apps.Entities/Schemas/Commands/UpsertCommand.cs @@ -35,6 +35,21 @@ namespace Squidex.Domain.Apps.Entities.Schemas.Commands schema = schema.Publish(); } + if (Scripts != null) + { + schema = schema.ConfigureScripts(Scripts); + } + + if (PreviewUrls != null) + { + schema = schema.ConfigurePreviewUrls(PreviewUrls); + } + + if (!string.IsNullOrWhiteSpace(Category)) + { + schema = schema.ChangeCategory(Category); + } + var totalFields = 0; if (Fields != null) diff --git a/src/Squidex.Domain.Apps.Entities/Schemas/Commands/UpsertSchemaField.cs b/src/Squidex.Domain.Apps.Entities/Schemas/Commands/UpsertSchemaField.cs index cc92d2e8f..3b6184338 100644 --- a/src/Squidex.Domain.Apps.Entities/Schemas/Commands/UpsertSchemaField.cs +++ b/src/Squidex.Domain.Apps.Entities/Schemas/Commands/UpsertSchemaField.cs @@ -6,12 +6,13 @@ // ========================================================================== using System.Collections.Generic; +using P = Squidex.Domain.Apps.Core.Partitioning; namespace Squidex.Domain.Apps.Entities.Schemas.Commands { public sealed class UpsertSchemaField : UpsertSchemaFieldBase { - public string Partitioning { get; set; } = "invariant"; + public string Partitioning { get; set; } = P.Invariant.Key; public List Nested { get; set; } } diff --git a/src/Squidex.Domain.Apps.Entities/Schemas/SchemaGrain.cs b/src/Squidex.Domain.Apps.Entities/Schemas/SchemaGrain.cs index 86e923b6d..70ec38ddc 100644 --- a/src/Squidex.Domain.Apps.Entities/Schemas/SchemaGrain.cs +++ b/src/Squidex.Domain.Apps.Entities/Schemas/SchemaGrain.cs @@ -76,6 +76,14 @@ namespace Squidex.Domain.Apps.Entities.Schemas Create(c); }); + case SynchronizeSchema synchronizeSchema: + return UpdateAsync(synchronizeSchema, c => + { + GuardSchema.CanSynchronize(c); + + Synchronize(c); + }); + case DeleteField deleteField: return UpdateAsync(deleteField, c => { @@ -203,14 +211,20 @@ namespace Squidex.Domain.Apps.Entities.Schemas public void Synchronize(SynchronizeSchema command) { + var options = new SchemaSynchronizationOptions + { + NoFieldDeletion = command.NoFieldDeletion, + NoFieldRecreation = command.NoFieldRecreation + }; + var schemaSource = Snapshot.SchemaDef; var schemaTarget = command.ToSchema(schemaSource.Name, schemaSource.IsSingleton); - var @events = schemaTarget.Synchronize(schemaSource, serializer, () => Snapshot.SchemaFieldsTotal + 1); + var @events = schemaSource.Synchronize(schemaTarget, serializer, () => Snapshot.SchemaFieldsTotal + 1, options); foreach (var @event in @events) { - RaiseEvent(@event); + RaiseEvent(SimpleMapper.Map(command, (SchemaEvent)@event)); } } @@ -221,7 +235,7 @@ namespace Squidex.Domain.Apps.Entities.Schemas public void Add(AddField command) { - RaiseEvent(command, new FieldAdded { FieldId = NamedId.Of(Snapshot.SchemaFieldsTotal + 1, command.Name) }); + RaiseEvent(command, new FieldAdded { FieldId = CreateFieldId(command) }); } public void UpdateField(UpdateField command) @@ -321,9 +335,12 @@ namespace Squidex.Domain.Apps.Entities.Schemas { pe.ParentFieldId = NamedId.Of(field.Id, field.Name); - if (field is IArrayField arrayField && command is FieldCommand fc && @event is FieldEvent fe && arrayField.FieldsById.TryGetValue(fc.FieldId, out var nestedField)) + if (command is FieldCommand fc && @event is FieldEvent fe) { - fe.FieldId = NamedId.Of(nestedField.Id, nestedField.Name); + if (field is IArrayField arrayField && arrayField.FieldsById.TryGetValue(fc.FieldId, out var nestedField)) + { + fe.FieldId = NamedId.Of(nestedField.Id, nestedField.Name); + } } } } diff --git a/src/Squidex/Areas/Api/Controllers/Schemas/Models/ConfigureScriptsDto.cs b/src/Squidex/Areas/Api/Controllers/Schemas/Models/ConfigureScriptsDto.cs index 51c8c3de1..8247b7179 100644 --- a/src/Squidex/Areas/Api/Controllers/Schemas/Models/ConfigureScriptsDto.cs +++ b/src/Squidex/Areas/Api/Controllers/Schemas/Models/ConfigureScriptsDto.cs @@ -5,41 +5,16 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== +using System.Collections.Generic; using Squidex.Domain.Apps.Entities.Schemas.Commands; -using Squidex.Infrastructure.Reflection; namespace Squidex.Areas.Api.Controllers.Schemas.Models { - public sealed class ConfigureScriptsDto + public sealed class ConfigureScriptsDto : Dictionary { - /// - /// The script that is executed for each query when querying contents. - /// - public string ScriptQuery { get; set; } - - /// - /// The script that is executed when creating a content. - /// - public string ScriptCreate { get; set; } - - /// - /// The script that is executed when updating a content. - /// - public string ScriptUpdate { get; set; } - - /// - /// The script that is executed when deleting a content. - /// - public string ScriptDelete { get; set; } - - /// - /// The script that is executed when change a content status. - /// - public string ScriptChange { get; set; } - public ConfigureScripts ToCommand() { - return SimpleMapper.Map(this, new ConfigureScripts()); + return new ConfigureScripts { Scripts = this }; } } } diff --git a/src/Squidex/Areas/Api/Controllers/Schemas/Models/CreateSchemaDto.cs b/src/Squidex/Areas/Api/Controllers/Schemas/Models/CreateSchemaDto.cs index b18eb7d62..a2b8e3299 100644 --- a/src/Squidex/Areas/Api/Controllers/Schemas/Models/CreateSchemaDto.cs +++ b/src/Squidex/Areas/Api/Controllers/Schemas/Models/CreateSchemaDto.cs @@ -5,15 +5,12 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== -using System.Collections.Generic; using System.ComponentModel.DataAnnotations; -using Squidex.Domain.Apps.Core.Schemas; using Squidex.Domain.Apps.Entities.Schemas.Commands; -using Squidex.Infrastructure.Reflection; namespace Squidex.Areas.Api.Controllers.Schemas.Models { - public sealed class CreateSchemaDto + public sealed class CreateSchemaDto : UpsertDto { /// /// The name of the schema. @@ -22,66 +19,14 @@ namespace Squidex.Areas.Api.Controllers.Schemas.Models [RegularExpression("^[a-z0-9]+(\\-[a-z0-9]+)*$")] public string Name { get; set; } - /// - /// The optional properties. - /// - public SchemaPropertiesDto Properties { get; set; } - - /// - /// Optional fields. - /// - public List Fields { get; set; } - /// /// Set to true to allow a single content item only. /// public bool Singleton { get; set; } - /// - /// Set it to true to autopublish the schema. - /// - public bool Publish { get; set; } - public CreateSchema ToCommand() { - var command = new CreateSchema(); - - SimpleMapper.Map(this, command); - - if (Properties != null) - { - command.Properties = new SchemaProperties(); - - SimpleMapper.Map(Properties, command.Properties); - } - - if (Fields != null) - { - command.Fields = new List(); - - foreach (var fieldDto in Fields) - { - var rootProperties = fieldDto?.Properties.ToProperties(); - var rootField = SimpleMapper.Map(fieldDto, new UpsertSchemaField { Properties = rootProperties }); - - if (fieldDto.Nested != null) - { - rootField.Nested = new List(); - - foreach (var nestedFieldDto in fieldDto.Nested) - { - var nestedProperties = nestedFieldDto?.Properties.ToProperties(); - var nestedField = SimpleMapper.Map(nestedFieldDto, new UpsertSchemaNestedField { Properties = nestedProperties }); - - rootField.Nested.Add(nestedField); - } - } - - command.Fields.Add(rootField); - } - } - - return command; + return ToCommand(this, new CreateSchema()); } } } diff --git a/src/Squidex/Areas/Api/Controllers/Schemas/Models/SynchronizeSchemaDto.cs b/src/Squidex/Areas/Api/Controllers/Schemas/Models/SynchronizeSchemaDto.cs new file mode 100644 index 000000000..e2595140a --- /dev/null +++ b/src/Squidex/Areas/Api/Controllers/Schemas/Models/SynchronizeSchemaDto.cs @@ -0,0 +1,29 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschränkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using Squidex.Domain.Apps.Entities.Schemas.Commands; + +namespace Squidex.Areas.Api.Controllers.Schemas.Models +{ + public sealed class SynchronizeSchemaDto : UpsertDto + { + /// + /// True, when fields should not be deleted. + /// + public bool NoFieldDeletion { get; set; } + + /// + /// True, when fields with different types should not be recreated. + /// + public bool NoFieldRecreation { get; set; } + + public SynchronizeSchema ToCommand() + { + return ToCommand(this, new SynchronizeSchema()); + } + } +} diff --git a/src/Squidex/Areas/Api/Controllers/Schemas/Models/UpsertDto.cs b/src/Squidex/Areas/Api/Controllers/Schemas/Models/UpsertDto.cs new file mode 100644 index 000000000..0e199c6cf --- /dev/null +++ b/src/Squidex/Areas/Api/Controllers/Schemas/Models/UpsertDto.cs @@ -0,0 +1,87 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using System.Collections.Generic; +using Squidex.Domain.Apps.Core.Schemas; +using Squidex.Domain.Apps.Entities.Schemas.Commands; +using Squidex.Infrastructure.Reflection; + +namespace Squidex.Areas.Api.Controllers.Schemas.Models +{ + public abstract class UpsertDto + { + /// + /// The optional properties. + /// + public SchemaPropertiesDto Properties { get; set; } + + /// + /// Optional fields. + /// + public List Fields { get; set; } + + /// + /// The optional scripts. + /// + public Dictionary Scripts { get; set; } + + /// + /// The optional preview urls. + /// + public Dictionary PreviewUrls { get; set; } + + /// + /// The category. + /// + public string Category { get; set; } + + /// + /// Set it to true to autopublish the schema. + /// + public bool Publish { get; set; } + + public static TCommand ToCommand(TDto dto, TCommand command) where TCommand : UpsertCommand where TDto : UpsertDto + { + SimpleMapper.Map(dto, command); + + if (dto.Properties != null) + { + command.Properties = new SchemaProperties(); + + SimpleMapper.Map(dto.Properties, command.Properties); + } + + if (dto.Fields != null) + { + command.Fields = new List(); + + foreach (var fieldDto in dto.Fields) + { + var rootProperties = fieldDto?.Properties.ToProperties(); + var rootField = SimpleMapper.Map(fieldDto, new UpsertSchemaField { Properties = rootProperties }); + + if (fieldDto.Nested != null) + { + rootField.Nested = new List(); + + foreach (var nestedFieldDto in fieldDto.Nested) + { + var nestedProperties = nestedFieldDto?.Properties.ToProperties(); + var nestedField = SimpleMapper.Map(nestedFieldDto, new UpsertSchemaNestedField { Properties = nestedProperties }); + + rootField.Nested.Add(nestedField); + } + } + + command.Fields.Add(rootField); + } + } + + return command; + } + } +} diff --git a/src/Squidex/Areas/Api/Controllers/Schemas/Models/CreateSchemaFieldDto.cs b/src/Squidex/Areas/Api/Controllers/Schemas/Models/UpsertSchemaFieldDto.cs similarity index 93% rename from src/Squidex/Areas/Api/Controllers/Schemas/Models/CreateSchemaFieldDto.cs rename to src/Squidex/Areas/Api/Controllers/Schemas/Models/UpsertSchemaFieldDto.cs index 75a09a657..a42fee220 100644 --- a/src/Squidex/Areas/Api/Controllers/Schemas/Models/CreateSchemaFieldDto.cs +++ b/src/Squidex/Areas/Api/Controllers/Schemas/Models/UpsertSchemaFieldDto.cs @@ -10,7 +10,7 @@ using System.ComponentModel.DataAnnotations; namespace Squidex.Areas.Api.Controllers.Schemas.Models { - public sealed class CreateSchemaFieldDto + public sealed class UpsertSchemaFieldDto { /// /// The name of the field. Must be unique within the schema. @@ -48,6 +48,6 @@ namespace Squidex.Areas.Api.Controllers.Schemas.Models /// /// The nested fields. /// - public List Nested { get; set; } + public List Nested { get; set; } } } \ No newline at end of file diff --git a/src/Squidex/Areas/Api/Controllers/Schemas/Models/CreateSchemaNestedFieldDto.cs b/src/Squidex/Areas/Api/Controllers/Schemas/Models/UpsertSchemaNestedFieldDto.cs similarity index 96% rename from src/Squidex/Areas/Api/Controllers/Schemas/Models/CreateSchemaNestedFieldDto.cs rename to src/Squidex/Areas/Api/Controllers/Schemas/Models/UpsertSchemaNestedFieldDto.cs index 6f4855264..823bddd69 100644 --- a/src/Squidex/Areas/Api/Controllers/Schemas/Models/CreateSchemaNestedFieldDto.cs +++ b/src/Squidex/Areas/Api/Controllers/Schemas/Models/UpsertSchemaNestedFieldDto.cs @@ -9,7 +9,7 @@ using System.ComponentModel.DataAnnotations; namespace Squidex.Areas.Api.Controllers.Schemas.Models { - public sealed class CreateSchemaNestedFieldDto + public sealed class UpsertSchemaNestedFieldDto { /// /// The name of the field. Must be unique within the schema. diff --git a/src/Squidex/Areas/Api/Controllers/Schemas/SchemasController.cs b/src/Squidex/Areas/Api/Controllers/Schemas/SchemasController.cs index d3f034d96..b867cdd2e 100644 --- a/src/Squidex/Areas/Api/Controllers/Schemas/SchemasController.cs +++ b/src/Squidex/Areas/Api/Controllers/Schemas/SchemasController.cs @@ -147,6 +147,28 @@ namespace Squidex.Areas.Api.Controllers.Schemas return NoContent(); } + /// + /// Synchronize a schema. + /// + /// The name of the app. + /// The name of the schema. + /// The schema object that needs to updated. + /// + /// 204 => Schema has been updated. + /// 400 => Schema properties are not valid. + /// 404 => Schema or app not found. + /// + [HttpPut] + [Route("apps/{app}/schemas/{name}/sync")] + [ApiPermission(Permissions.AppSchemasUpdate)] + [ApiCosts(1)] + public async Task PutSchemaSync(string app, string name, [FromBody] SynchronizeSchemaDto request) + { + await CommandBus.PublishAsync(request.ToCommand()); + + return NoContent(); + } + /// /// Update a schema category. /// diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Model/Schemas/SchemaTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Model/Schemas/SchemaTests.cs index 4f426ee04..e8005557e 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/Model/Schemas/SchemaTests.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/Model/Schemas/SchemaTests.cs @@ -278,7 +278,18 @@ namespace Squidex.Domain.Apps.Core.Model.Schemas [Fact] public void Should_serialize_and_deserialize_schema() { - var schemaSource = TestUtils.MixedSchema(); + var schemaSource = + TestUtils.MixedSchema(true) + .ChangeCategory("Category") + .ConfigurePreviewUrls(new Dictionary + { + ["web"] = "Url" + }) + .ConfigureScripts(new Dictionary + { + ["create"] = "" + }); + var schemaTarget = schemaSource.SerializeAndDeserialize(); schemaTarget.Should().BeEquivalentTo(schemaSource); diff --git a/tests/Squidex.Domain.Apps.Core.Tests/TestUtils.cs b/tests/Squidex.Domain.Apps.Core.Tests/TestUtils.cs index dec0ade55..ef69a262a 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/TestUtils.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/TestUtils.cs @@ -59,9 +59,9 @@ namespace Squidex.Domain.Apps.Core return new NewtonsoftJsonSerializer(serializerSettings); } - public static Schema MixedSchema() + public static Schema MixedSchema(bool isSingleton = false) { - var schema = new Schema("user") + var schema = new Schema("user", isSingleton: isSingleton) .Publish() .AddArray(101, "root-array", Partitioning.Language, f => f .AddAssets(201, "nested-assets") diff --git a/tests/Squidex.Domain.Apps.Entities.Tests/Schemas/Guards/GuardSchemaTests.cs b/tests/Squidex.Domain.Apps.Entities.Tests/Schemas/Guards/GuardSchemaTests.cs index 101b9ce3a..2d257f179 100644 --- a/tests/Squidex.Domain.Apps.Entities.Tests/Schemas/Guards/GuardSchemaTests.cs +++ b/tests/Squidex.Domain.Apps.Entities.Tests/Schemas/Guards/GuardSchemaTests.cs @@ -353,19 +353,19 @@ namespace Squidex.Domain.Apps.Entities.Schemas.Guards { Name = "field1", Properties = ValidProperties(), - Partitioning = "invariant" + Partitioning = Partitioning.Invariant.Key }, new UpsertSchemaField { Name = "field2", Properties = ValidProperties(), - Partitioning = "invariant" + Partitioning = Partitioning.Invariant.Key }, new UpsertSchemaField { Name = "field3", Properties = new ArrayFieldProperties(), - Partitioning = "invariant", + Partitioning = Partitioning.Invariant.Key, Nested = new List { new UpsertSchemaNestedField diff --git a/tests/Squidex.Domain.Apps.Entities.Tests/Schemas/SchemaGrainTests.cs b/tests/Squidex.Domain.Apps.Entities.Tests/Schemas/SchemaGrainTests.cs index 5e88d8bae..416a8022e 100644 --- a/tests/Squidex.Domain.Apps.Entities.Tests/Schemas/SchemaGrainTests.cs +++ b/tests/Squidex.Domain.Apps.Entities.Tests/Schemas/SchemaGrainTests.cs @@ -142,7 +142,7 @@ namespace Squidex.Domain.Apps.Entities.Schemas { Scripts = new Dictionary { - ["Query"] = "" + [Scripts.Query] = "" } }; @@ -637,6 +637,46 @@ namespace Squidex.Domain.Apps.Entities.Schemas ); } + [Fact] + public async Task Synchronize_should_create_events_and_update_state() + { + var command = new SynchronizeSchema + { + Scripts = new Dictionary + { + [Scripts.Query] = "" + }, + PreviewUrls = new Dictionary + { + ["Web"] = "web-url" + }, + Fields = new List + { + new UpsertSchemaField { Name = fieldId.Name, Properties = ValidProperties() } + }, + Category = "My-Category" + }; + + await ExecuteCreateAsync(); + + var result = await sut.ExecuteAsync(CreateCommand(command)); + + result.ShouldBeEquivalent(new EntitySavedResult(4)); + + Assert.NotNull(GetField(1)); + Assert.Equal(command.Category, sut.Snapshot.SchemaDef.Category); + Assert.Equal(command.Scripts, sut.Snapshot.SchemaDef.Scripts); + Assert.Equal(command.PreviewUrls, sut.Snapshot.SchemaDef.PreviewUrls); + + LastEvents + .ShouldHaveSameEvents( + CreateEvent(new SchemaCategoryChanged { Name = command.Category }), + CreateEvent(new SchemaScriptsConfigured { Scripts = command.Scripts }), + CreateEvent(new SchemaPreviewUrlsConfigured { PreviewUrls = command.PreviewUrls }), + CreateEvent(new FieldAdded { FieldId = fieldId, Name = fieldId.Name, Properties = command.Fields[0].Properties, Partitioning = Partitioning.Invariant.Key }) + ); + } + private Task ExecuteCreateAsync() { return sut.ExecuteAsync(CreateCommand(new CreateSchema { Name = SchemaName })); diff --git a/tools/Migrate_01/Rebuilder.cs b/tools/Migrate_01/Rebuilder.cs index f29f924c2..ee77eb829 100644 --- a/tools/Migrate_01/Rebuilder.cs +++ b/tools/Migrate_01/Rebuilder.cs @@ -10,7 +10,6 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using System.Threading.Tasks.Dataflow; -using Squidex.Domain.Apps.Core.Schemas; using Squidex.Domain.Apps.Entities.Apps; using Squidex.Domain.Apps.Entities.Apps.State; using Squidex.Domain.Apps.Entities.Assets;