diff --git a/CHANGELOG.md b/CHANGELOG.md index 22ea89900..bbf4f27bb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,24 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [6.13.0] - 200-08-02 + +### Fkxed + +* **UI**: Fixes the rendering of reference lists. + +## [6.12.0] - 200-08-01 + +### Changed + +* No changes, just meant to run CI again. + +## [6.11.0] - 2022-07-29 + +### Fixed + +* **Assets**: Fix recursive asset deletion. Query was selecting the wrong assets. + ## [7.0.0-rc3] - 2022-07-29 ### Fixed diff --git a/backend/src/Squidex.Domain.Apps.Entities/Contents/DomainObject/ContentsBulkUpdateCommandMiddleware.cs b/backend/src/Squidex.Domain.Apps.Entities/Contents/DomainObject/ContentsBulkUpdateCommandMiddleware.cs index 48f1d3dfe..256d25d93 100644 --- a/backend/src/Squidex.Domain.Apps.Entities/Contents/DomainObject/ContentsBulkUpdateCommandMiddleware.cs +++ b/backend/src/Squidex.Domain.Apps.Entities/Contents/DomainObject/ContentsBulkUpdateCommandMiddleware.cs @@ -270,9 +270,11 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject SimpleMapper.Map(task.Command, command); SimpleMapper.Map(task.CommandJob, command); - if (!string.IsNullOrWhiteSpace(task.CommandJob.Schema)) + var overridenSchema = task.CommandJob.Schema; + + if (!string.IsNullOrWhiteSpace(overridenSchema)) { - var schema = await contentQuery.GetSchemaOrThrowAsync(contextProvider.Context, task.Schema, task.CancellationToken); + var schema = await contentQuery.GetSchemaOrThrowAsync(contextProvider.Context, overridenSchema, task.CancellationToken); command.SchemaId = schema.NamedId(); } diff --git a/backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/DomainObject/ContentsBulkUpdateCommandMiddlewareTests.cs b/backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/DomainObject/ContentsBulkUpdateCommandMiddlewareTests.cs index e4fbfa73c..d6e0cdac2 100644 --- a/backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/DomainObject/ContentsBulkUpdateCommandMiddlewareTests.cs +++ b/backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/DomainObject/ContentsBulkUpdateCommandMiddlewareTests.cs @@ -31,6 +31,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject private readonly ICommandBus commandBus = A.Dummy(); private readonly NamedId appId = NamedId.Of(DomainId.NewGuid(), "my-app"); private readonly NamedId schemaId = NamedId.Of(DomainId.NewGuid(), "my-schema"); + private readonly NamedId schemaCustomId = NamedId.Of(DomainId.NewGuid(), "my-schema2"); private readonly Instant time = Instant.FromDateTimeUtc(DateTime.UtcNow); private readonly ContentsBulkUpdateCommandMiddleware sut; @@ -96,7 +97,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject schemaId.Name, A.That.Matches(x => x.JsonQuery == query), ct)) .Returns(ResultList.CreateFrom(2, CreateContent(id), CreateContent(id))); - var command = BulkCommand(BulkUpdateContentType.ChangeStatus, query); + var command = BulkCommand(BulkUpdateContentType.ChangeStatus, new BulkUpdateJob { Query = query }); var result = await PublishAsync(command); @@ -122,7 +123,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject schemaId.Name, A.That.Matches(x => x.JsonQuery == query), ct)) .Returns(ResultList.CreateFrom(1, CreateContent(id))); - var command = BulkCommand(BulkUpdateContentType.Upsert, query: query, data: data); + var command = BulkCommand(BulkUpdateContentType.Upsert, new BulkUpdateJob { Query = query, Data = data }); var result = await PublishAsync(command); @@ -154,7 +155,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject CreateContent(id1), CreateContent(id2))); - var command = BulkCommand(BulkUpdateContentType.Upsert, query: query, data: data); + var command = BulkCommand(BulkUpdateContentType.Upsert, new BulkUpdateJob { Query = query, Data = data }); command.Jobs![0].ExpectedCount = 2; @@ -180,7 +181,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject var (_, data, _) = CreateTestData(false); - var command = BulkCommand(BulkUpdateContentType.Upsert, data: data); + var command = BulkCommand(BulkUpdateContentType.Upsert, new BulkUpdateJob { Data = data }); var result = await PublishAsync(command); @@ -199,7 +200,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject var (_, data, query) = CreateTestData(true); - var command = BulkCommand(BulkUpdateContentType.Upsert, query: query, data: data); + var command = BulkCommand(BulkUpdateContentType.Upsert, new BulkUpdateJob { Query = query, Data = data }); var result = await PublishAsync(command); @@ -218,7 +219,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject var (id, data, _) = CreateTestData(false); - var command = BulkCommand(BulkUpdateContentType.Upsert, id: id, data: data); + var command = BulkCommand(BulkUpdateContentType.Upsert, new BulkUpdateJob { Data = data }, id); var result = await PublishAsync(command); @@ -237,7 +238,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject var (id, data, _) = CreateTestData(true); - var command = BulkCommand(BulkUpdateContentType.Upsert, id: id, data: data); + var command = BulkCommand(BulkUpdateContentType.Upsert, new BulkUpdateJob { Data = data }, id); var result = await PublishAsync(command); @@ -256,7 +257,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject var (id, data, _) = CreateTestData(false); - var command = BulkCommand(BulkUpdateContentType.Create, id: id, data: data); + var command = BulkCommand(BulkUpdateContentType.Create, new BulkUpdateJob { Data = data }, id); var result = await PublishAsync(command); @@ -275,7 +276,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject var (id, data, _) = CreateTestData(false); - var command = BulkCommand(BulkUpdateContentType.Create, id: id, data: data); + var command = BulkCommand(BulkUpdateContentType.Create, new BulkUpdateJob { Data = data }, id); var result = await PublishAsync(command); @@ -293,7 +294,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject var (id, data, _) = CreateTestData(false); - var command = BulkCommand(BulkUpdateContentType.Update, id: id, data: data); + var command = BulkCommand(BulkUpdateContentType.Update, new BulkUpdateJob { Data = data }, id); var result = await PublishAsync(command); @@ -312,7 +313,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject var (id, data, _) = CreateTestData(false); - var command = BulkCommand(BulkUpdateContentType.Update, id: id, data: data); + var command = BulkCommand(BulkUpdateContentType.Update, new BulkUpdateJob { Data = data }, id); var result = await PublishAsync(command); @@ -330,7 +331,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject var (id, data, _) = CreateTestData(false); - var command = BulkCommand(BulkUpdateContentType.Patch, id: id, data: data); + var command = BulkCommand(BulkUpdateContentType.Patch, new BulkUpdateJob { Data = data }, id); var result = await PublishAsync(command); @@ -349,7 +350,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject var (id, data, _) = CreateTestData(false); - var command = BulkCommand(BulkUpdateContentType.Delete, id: id, data: data); + var command = BulkCommand(BulkUpdateContentType.Delete, new BulkUpdateJob { Data = data }, id); var result = await PublishAsync(command); @@ -386,7 +387,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject var (id, _, _) = CreateTestData(false); - var command = BulkCommand(BulkUpdateContentType.ChangeStatus, id: id, dueTime: time); + var command = BulkCommand(BulkUpdateContentType.ChangeStatus, new BulkUpdateJob { DueTime = time }, id); var result = await PublishAsync(command); @@ -490,6 +491,28 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject .MustNotHaveHappened(); } + [Fact] + public async Task Should_override_schema_name() + { + SetupContext(Permissions.AppContentsDeleteOwn); + + A.CallTo(() => contentQuery.GetSchemaOrThrowAsync(A._, schemaCustomId.Name, ct)) + .Returns(Mocks.Schema(appId, schemaCustomId)); + + var (id, _, _) = CreateTestData(false); + + var command = BulkCommand(BulkUpdateContentType.Delete, new BulkUpdateJob { Schema = schemaCustomId.Name }, id); + + var result = await PublishAsync(command); + + Assert.Single(result); + Assert.Single(result, x => x.JobIndex == 0 && x.Id == id && x.Exception == null); + + A.CallTo(() => commandBus.PublishAsync( + A.That.Matches(x => x.SchemaId == schemaCustomId), ct)) + .MustHaveHappened(); + } + private async Task PublishAsync(ICommand command) { var context = new CommandContext(command, commandBus); @@ -499,22 +522,18 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject return (context.PlainResult as BulkUpdateResult)!; } - private BulkUpdateContents BulkCommand(BulkUpdateContentType type, Query? query = null, - DomainId? id = null, ContentData? data = null, Instant? dueTime = null) + private BulkUpdateContents BulkCommand(BulkUpdateContentType type, BulkUpdateJob? job = null, DomainId? id = null) { + job ??= new BulkUpdateJob(); + job.Id = id; + job.Type = type; + return new BulkUpdateContents { AppId = appId, Jobs = new[] { - new BulkUpdateJob - { - Type = type, - Id = id, - Data = data!, - DueTime = dueTime, - Query = query - } + job }, SchemaId = schemaId }; @@ -522,12 +541,16 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject private Context SetupContext(string id) { - var permission = Permissions.ForApp(id, appId.Name, schemaId.Name).Id; - var claimsIdentity = new ClaimsIdentity(); var claimsPrincipal = new ClaimsPrincipal(claimsIdentity); - claimsIdentity.AddClaim(new Claim(SquidexClaimTypes.Permissions, permission)); + claimsIdentity.AddClaim( + new Claim(SquidexClaimTypes.Permissions, + Permissions.ForApp(id, appId.Name, schemaId.Name).Id)); + + claimsIdentity.AddClaim( + new Claim(SquidexClaimTypes.Permissions, + Permissions.ForApp(id, appId.Name, schemaCustomId.Name).Id)); var requestContext = new Context(claimsPrincipal, Mocks.App(appId)); diff --git a/backend/tools/TestSuite/TestSuite.ApiTests/ContentUpdateTests.cs b/backend/tools/TestSuite/TestSuite.ApiTests/ContentUpdateTests.cs index 501155105..dcf6a54ff 100644 --- a/backend/tools/TestSuite/TestSuite.ApiTests/ContentUpdateTests.cs +++ b/backend/tools/TestSuite/TestSuite.ApiTests/ContentUpdateTests.cs @@ -506,7 +506,7 @@ namespace TestSuite.ApiTests content = await _.Contents.CreateAsync(new TestEntityData { String = "test" }, ContentCreateOptions.AsPublish); - // STEP 2: Path an item. + // STEP 2: Patch an item. await _.Contents.PatchAsync(content.Id, new TestEntityData { Number = 1 }); @@ -591,7 +591,7 @@ namespace TestSuite.ApiTests content = await _.Contents.CreateAsync(new TestEntityData { String = "test" }, ContentCreateOptions.AsPublish); - // STEP 2: Path an item. + // STEP 2: Patch an item. await _.Contents.UpsertAsync(content.Id, new TestEntityData { Number = 1 }, ContentUpsertOptions.AsPatch); @@ -624,7 +624,7 @@ namespace TestSuite.ApiTests content = await _.Contents.CreateAsync(new TestEntityData { String = "test" }, ContentCreateOptions.AsPublish); - // STEP 2: Path an item. + // STEP 2: Patch an item. await _.Contents.BulkUpdateAsync(new BulkUpdate { Jobs = new List @@ -681,6 +681,87 @@ namespace TestSuite.ApiTests } } + [Fact] + public async Task Should_update_content_with_bulk_and_overriden_schema_name() + { + TestEntity content = null; + try + { + var schemaName = $"schema-{Guid.NewGuid()}"; + + // STEP 0: Create dummy schema. + var createSchema = new CreateSchemaDto + { + Name = schemaName, + + // Publish it to avoid validations issues. + IsPublished = true + }; + + await _.Schemas.PostSchemaAsync(_.AppName, createSchema); + + + + // STEP 1: Create a new item. + content = await _.Contents.CreateAsync(new TestEntityData { String = "test" }, ContentCreateOptions.AsPublish); + + + // STEP 2: Patch an item. + var client = _.ClientManager.CreateContentsClient(schemaName); + + await client.BulkUpdateAsync(new BulkUpdate + { + Jobs = new List + { + new BulkUpdateJob + { + Id = content.Id, + Data = new + { + number = new + { + iv = 1 + } + }, + Schema = _.SchemaName + } + } + }); + + + // STEP 3: Update the item and ensure that the data has changed. + await client.BulkUpdateAsync(new BulkUpdate + { + Jobs = new List + { + new BulkUpdateJob + { + Id = content.Id, + Data = new + { + number = new + { + iv = 2 + } + }, + Schema = _.SchemaName + } + } + }); + + var updated = await _.Contents.GetAsync(content.Id); + + Assert.Equal(2, updated.Data.Number); + } + finally + { + if (content != null) + { + await _.Contents.DeleteAsync(content.Id); + } + } + } + [Fact] public async Task Should_create_draft_version() { diff --git a/frontend/src/app/framework/angular/stateful.component.ts b/frontend/src/app/framework/angular/stateful.component.ts index e8bff4405..1b845c095 100644 --- a/frontend/src/app/framework/angular/stateful.component.ts +++ b/frontend/src/app/framework/angular/stateful.component.ts @@ -83,7 +83,7 @@ export abstract class StatefulComponent extends State implements OnD this.changeDetector.detectChanges(); } - public own(subscription: Subscription | UnsubscribeFunction | Observable) { + public own(subscription: Subscription | UnsubscribeFunction | Observable | null | undefined) { this.subscriptions.own(subscription); } } diff --git a/frontend/src/app/shared/components/contents/content-value.component.html b/frontend/src/app/shared/components/contents/content-value.component.html index 00a0619c0..0420e57a7 100644 --- a/frontend/src/app/shared/components/contents/content-value.component.html +++ b/frontend/src/app/shared/components/contents/content-value.component.html @@ -1,6 +1,6 @@
-
{{value}}
+
{{value}}