mirror of https://github.com/Squidex/squidex.git
42 changed files with 633 additions and 602 deletions
@ -1,52 +0,0 @@ |
|||||
// ==========================================================================
|
|
||||
// Squidex Headless CMS
|
|
||||
// ==========================================================================
|
|
||||
// Copyright (c) Squidex UG (haftungsbeschränkt)
|
|
||||
// All rights reserved. Licensed under the MIT license.
|
|
||||
// ==========================================================================
|
|
||||
|
|
||||
using System.Threading.Tasks; |
|
||||
using Squidex.Domain.Apps.Events.Assets; |
|
||||
using Squidex.Domain.Apps.Events.Contents; |
|
||||
using Squidex.Infrastructure.EventSourcing; |
|
||||
using Squidex.Infrastructure.Tasks; |
|
||||
|
|
||||
namespace Squidex.Domain.Apps.Entities.MongoDb.Contents |
|
||||
{ |
|
||||
public partial class MongoContentRepository : IEventConsumer |
|
||||
{ |
|
||||
public string Name |
|
||||
{ |
|
||||
get { return GetType().Name; } |
|
||||
} |
|
||||
|
|
||||
public string EventsFilter |
|
||||
{ |
|
||||
get { return "^(content-)|(asset-)"; } |
|
||||
} |
|
||||
|
|
||||
public bool Handles(StoredEvent @event) |
|
||||
{ |
|
||||
return @event.Data.Type == typeAssetDeleted || @event.Data.Type == typeContentDeleted; |
|
||||
} |
|
||||
|
|
||||
public Task On(Envelope<IEvent> @event) |
|
||||
{ |
|
||||
switch (@event.Payload) |
|
||||
{ |
|
||||
case AssetDeleted e: |
|
||||
return cleanupReferences.DoAsync(e.AssetId); |
|
||||
|
|
||||
case ContentDeleted e: |
|
||||
return cleanupReferences.DoAsync(e.ContentId); |
|
||||
} |
|
||||
|
|
||||
return TaskHelper.Done; |
|
||||
} |
|
||||
|
|
||||
Task IEventConsumer.ClearAsync() |
|
||||
{ |
|
||||
return TaskHelper.Done; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,35 +0,0 @@ |
|||||
// ==========================================================================
|
|
||||
// Squidex Headless CMS
|
|
||||
// ==========================================================================
|
|
||||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|
||||
// All rights reserved. Licensed under the MIT license.
|
|
||||
// ==========================================================================
|
|
||||
|
|
||||
using System; |
|
||||
using System.Threading; |
|
||||
using System.Threading.Tasks; |
|
||||
using MongoDB.Driver; |
|
||||
|
|
||||
namespace Squidex.Domain.Apps.Entities.MongoDb.Contents.Operations |
|
||||
{ |
|
||||
internal sealed class CleanupReferences : OperationBase |
|
||||
{ |
|
||||
protected override Task PrepareAsync(CancellationToken ct = default) |
|
||||
{ |
|
||||
var index = |
|
||||
new CreateIndexModel<MongoContentEntity>( |
|
||||
Index.Ascending(x => x.ReferencedIds)); |
|
||||
|
|
||||
return Collection.Indexes.CreateOneAsync(index, cancellationToken: ct); |
|
||||
} |
|
||||
|
|
||||
public Task DoAsync(Guid id) |
|
||||
{ |
|
||||
return Collection.UpdateManyAsync( |
|
||||
Filter.And( |
|
||||
Filter.AnyEq(x => x.ReferencedIds, id), |
|
||||
Filter.AnyNe(x => x.ReferencedIdsDeleted, id)), |
|
||||
Update.AddToSet(x => x.ReferencedIdsDeleted, id)); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -0,0 +1,31 @@ |
|||||
|
// ==========================================================================
|
||||
|
// Squidex Headless CMS
|
||||
|
// ==========================================================================
|
||||
|
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
||||
|
// All rights reserved. Licensed under the MIT license.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using FakeItEasy; |
||||
|
|
||||
|
namespace Squidex.Domain.Apps.Core.TestHelpers |
||||
|
{ |
||||
|
public static class AExtensions |
||||
|
{ |
||||
|
public static T[] Is<T>(this INegatableArgumentConstraintManager<T[]> that, params T[]? values) |
||||
|
{ |
||||
|
return values == null ? that.IsNull() : that.IsSameSequenceAs(values); |
||||
|
} |
||||
|
|
||||
|
public static HashSet<T> Is<T>(this INegatableArgumentConstraintManager<HashSet<T>> that, IEnumerable<T>? values) |
||||
|
{ |
||||
|
return values == null ? that.IsNull() : that.Matches(x => x.Intersect(values).Count() == values.Count()); |
||||
|
} |
||||
|
|
||||
|
public static HashSet<T> Is<T>(this INegatableArgumentConstraintManager<HashSet<T>> that, params T[]? values) |
||||
|
{ |
||||
|
return values == null ? that.IsNull() : that.Matches(x => x.Intersect(values).Count() == values.Length); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,146 @@ |
|||||
|
// ==========================================================================
|
||||
|
// Squidex Headless CMS
|
||||
|
// ==========================================================================
|
||||
|
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
||||
|
// All rights reserved. Licensed under the MIT license.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Threading.Tasks; |
||||
|
using FakeItEasy; |
||||
|
using Squidex.Domain.Apps.Core; |
||||
|
using Squidex.Domain.Apps.Core.Contents; |
||||
|
using Squidex.Domain.Apps.Core.ConvertContent; |
||||
|
using Squidex.Domain.Apps.Core.Schemas; |
||||
|
using Squidex.Domain.Apps.Entities.Assets.Repositories; |
||||
|
using Squidex.Domain.Apps.Entities.Contents.Queries.Steps; |
||||
|
using Squidex.Domain.Apps.Entities.Contents.Repositories; |
||||
|
using Squidex.Domain.Apps.Entities.Schemas; |
||||
|
using Squidex.Domain.Apps.Entities.TestHelpers; |
||||
|
using Squidex.Infrastructure; |
||||
|
using Squidex.Infrastructure.Json.Objects; |
||||
|
using Xunit; |
||||
|
|
||||
|
namespace Squidex.Domain.Apps.Entities.Contents.Queries |
||||
|
{ |
||||
|
public class ConvertDataTests |
||||
|
{ |
||||
|
private readonly ISchemaEntity schema; |
||||
|
private readonly IAssetUrlGenerator assetUrlGenerator = A.Fake<IAssetUrlGenerator>(); |
||||
|
private readonly IAssetRepository assetRepository = A.Fake<IAssetRepository>(); |
||||
|
private readonly IContentRepository contentRepository = A.Fake<IContentRepository>(); |
||||
|
private readonly Context requestContext; |
||||
|
private readonly NamedId<Guid> appId = NamedId.Of(Guid.NewGuid(), "my-app"); |
||||
|
private readonly NamedId<Guid> schemaId = NamedId.Of(Guid.NewGuid(), "my-schema"); |
||||
|
private readonly ProvideSchema schemaProvider; |
||||
|
private readonly ConvertData sut; |
||||
|
|
||||
|
public ConvertDataTests() |
||||
|
{ |
||||
|
requestContext = new Context(Mocks.ApiUser(), Mocks.App(appId)); |
||||
|
|
||||
|
var schemaDef = |
||||
|
new Schema("my-schema") |
||||
|
.AddReferences(1, "references", Partitioning.Invariant) |
||||
|
.AddAssets(2, "assets", Partitioning.Invariant) |
||||
|
.AddArray(3, "array", Partitioning.Invariant, a => a |
||||
|
.AddAssets(31, "nested")); |
||||
|
|
||||
|
schema = Mocks.Schema(appId, schemaId, schemaDef); |
||||
|
schemaProvider = x => Task.FromResult(schema); |
||||
|
|
||||
|
sut = new ConvertData(assetUrlGenerator, assetRepository, contentRepository); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task Should_convert_data_only() |
||||
|
{ |
||||
|
var source = PublishedContent(); |
||||
|
|
||||
|
await sut.EnrichAsync(requestContext, Enumerable.Repeat(source, 1), schemaProvider); |
||||
|
|
||||
|
Assert.NotNull(source.Data); |
||||
|
Assert.Null(source.DataDraft); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task Should_convert_data_and_data_draft_when_frontend_user() |
||||
|
{ |
||||
|
var source = PublishedContent(); |
||||
|
|
||||
|
var ctx = new Context(Mocks.FrontendUser(), Mocks.App(appId)); |
||||
|
|
||||
|
await sut.EnrichAsync(ctx, Enumerable.Repeat(source, 1), schemaProvider); |
||||
|
|
||||
|
Assert.NotNull(source.Data); |
||||
|
Assert.NotNull(source.DataDraft); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task Should_cleanup_references() |
||||
|
{ |
||||
|
var id1 = Guid.NewGuid(); |
||||
|
var id2 = Guid.NewGuid(); |
||||
|
|
||||
|
var source = |
||||
|
new NamedContentData() |
||||
|
.AddField("references", |
||||
|
new ContentFieldData() |
||||
|
.AddJsonValue(JsonValue.Array(id1, id2))) |
||||
|
.AddField("assets", |
||||
|
new ContentFieldData() |
||||
|
.AddJsonValue(JsonValue.Array(id1))) |
||||
|
.AddField("array", |
||||
|
new ContentFieldData() |
||||
|
.AddJsonValue( |
||||
|
JsonValue.Array( |
||||
|
JsonValue.Object() |
||||
|
.Add("nested", JsonValue.Array(id1, id2))))); |
||||
|
|
||||
|
var expected = |
||||
|
new NamedContentData() |
||||
|
.AddField("references", |
||||
|
new ContentFieldData() |
||||
|
.AddJsonValue(JsonValue.Array(id2))) |
||||
|
.AddField("assets", |
||||
|
new ContentFieldData() |
||||
|
.AddJsonValue(JsonValue.Array())) |
||||
|
.AddField("array", |
||||
|
new ContentFieldData() |
||||
|
.AddJsonValue( |
||||
|
JsonValue.Array( |
||||
|
JsonValue.Object() |
||||
|
.Add("nested", JsonValue.Array(id2))))); |
||||
|
var content = PublishedContent(); |
||||
|
|
||||
|
content.Data = source; |
||||
|
content.DataDraft = source; |
||||
|
|
||||
|
A.CallTo(() => assetRepository.QueryIdsAsync(appId.Id, A<HashSet<Guid>>.That.Is(id1, id2))) |
||||
|
.Returns(new List<Guid> { id2 }); |
||||
|
|
||||
|
A.CallTo(() => contentRepository.QueryIdsAsync(appId.Id, A<HashSet<Guid>>.That.Is(id1, id2))) |
||||
|
.Returns(new List<(Guid, Guid)> { (id2, id2) }); |
||||
|
|
||||
|
var ctx = new Context(Mocks.FrontendUser(), Mocks.App(appId)); |
||||
|
|
||||
|
await sut.EnrichAsync(ctx, Enumerable.Repeat(content, 1), schemaProvider); |
||||
|
|
||||
|
Assert.Equal(expected, content.Data); |
||||
|
Assert.Equal(expected, content.DataDraft); |
||||
|
} |
||||
|
|
||||
|
private ContentEntity PublishedContent() |
||||
|
{ |
||||
|
return new ContentEntity |
||||
|
{ |
||||
|
Status = Status.Published, |
||||
|
Data = new NamedContentData(), |
||||
|
DataDraft = new NamedContentData(), |
||||
|
SchemaId = schemaId |
||||
|
}; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue