diff --git a/src/Squidex.Domain.Apps.Entities/Assets/AssetStatsRepository.cs b/src/Squidex.Domain.Apps.Entities/Assets/AssetUsageTracker.cs similarity index 93% rename from src/Squidex.Domain.Apps.Entities/Assets/AssetStatsRepository.cs rename to src/Squidex.Domain.Apps.Entities/Assets/AssetUsageTracker.cs index 065d1b5e7..d7642e605 100644 --- a/src/Squidex.Domain.Apps.Entities/Assets/AssetStatsRepository.cs +++ b/src/Squidex.Domain.Apps.Entities/Assets/AssetUsageTracker.cs @@ -18,7 +18,7 @@ using Squidex.Infrastructure.UsageTracking; namespace Squidex.Domain.Apps.Entities.Assets { - public partial class AssetStatsRepository : IAssetStatsRepository, IEventConsumer + public partial class AssetUsageTracker : IAssetUsageTracker, IEventConsumer { private const string Category = "Default"; private const string CounterTotalCount = "TotalAssets"; @@ -26,7 +26,7 @@ namespace Squidex.Domain.Apps.Entities.Assets private static readonly DateTime SummaryDate; private readonly IUsageRepository usageStore; - public AssetStatsRepository(IUsageRepository usageStore) + public AssetUsageTracker(IUsageRepository usageStore) { Guard.NotNull(usageStore, nameof(usageStore)); diff --git a/src/Squidex.Domain.Apps.Entities/Assets/AssetStatsRepository_EventHandling.cs b/src/Squidex.Domain.Apps.Entities/Assets/AssetUsageTracker_EventHandling.cs similarity index 98% rename from src/Squidex.Domain.Apps.Entities/Assets/AssetStatsRepository_EventHandling.cs rename to src/Squidex.Domain.Apps.Entities/Assets/AssetUsageTracker_EventHandling.cs index 834265b06..dfefeb9e1 100644 --- a/src/Squidex.Domain.Apps.Entities/Assets/AssetStatsRepository_EventHandling.cs +++ b/src/Squidex.Domain.Apps.Entities/Assets/AssetUsageTracker_EventHandling.cs @@ -15,7 +15,7 @@ using Squidex.Infrastructure.UsageTracking; namespace Squidex.Domain.Apps.Entities.Assets { - public partial class AssetStatsRepository + public partial class AssetUsageTracker { public string Name { diff --git a/src/Squidex.Domain.Apps.Entities/Assets/Repositories/IAssetStatsRepository.cs b/src/Squidex.Domain.Apps.Entities/Assets/IAssetUsageTracker.cs similarity index 85% rename from src/Squidex.Domain.Apps.Entities/Assets/Repositories/IAssetStatsRepository.cs rename to src/Squidex.Domain.Apps.Entities/Assets/IAssetUsageTracker.cs index 5e4697b33..3699a5489 100644 --- a/src/Squidex.Domain.Apps.Entities/Assets/Repositories/IAssetStatsRepository.cs +++ b/src/Squidex.Domain.Apps.Entities/Assets/IAssetUsageTracker.cs @@ -9,9 +9,9 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; -namespace Squidex.Domain.Apps.Entities.Assets.Repositories +namespace Squidex.Domain.Apps.Entities.Assets { - public interface IAssetStatsRepository + public interface IAssetUsageTracker { Task> QueryAsync(Guid appId, DateTime fromDate, DateTime toDate); diff --git a/src/Squidex/Areas/Api/Controllers/Assets/AssetsController.cs b/src/Squidex/Areas/Api/Controllers/Assets/AssetsController.cs index 653cc1b5f..8f3ee8f80 100644 --- a/src/Squidex/Areas/Api/Controllers/Assets/AssetsController.cs +++ b/src/Squidex/Areas/Api/Controllers/Assets/AssetsController.cs @@ -35,7 +35,7 @@ namespace Squidex.Areas.Api.Controllers.Assets public sealed class AssetsController : ApiController { private readonly IAssetQueryService assetQuery; - private readonly IAssetStatsRepository assetStatsRepository; + private readonly IAssetUsageTracker assetStatsRepository; private readonly IAppPlansProvider appPlanProvider; private readonly IOptions controllerOptions; private readonly ITagService tagService; @@ -44,7 +44,7 @@ namespace Squidex.Areas.Api.Controllers.Assets public AssetsController( ICommandBus commandBus, IAssetQueryService assetQuery, - IAssetStatsRepository assetStatsRepository, + IAssetUsageTracker assetStatsRepository, IAppPlansProvider appPlanProvider, IOptions assetOptions, IOptions controllerOptions, diff --git a/src/Squidex/Areas/Api/Controllers/Statistics/UsagesController.cs b/src/Squidex/Areas/Api/Controllers/Statistics/UsagesController.cs index cfb8d6bf9..67d0295df 100644 --- a/src/Squidex/Areas/Api/Controllers/Statistics/UsagesController.cs +++ b/src/Squidex/Areas/Api/Controllers/Statistics/UsagesController.cs @@ -12,7 +12,7 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using Squidex.Areas.Api.Controllers.Statistics.Models; using Squidex.Domain.Apps.Entities.Apps.Services; -using Squidex.Domain.Apps.Entities.Assets.Repositories; +using Squidex.Domain.Apps.Entities.Assets; using Squidex.Infrastructure.Commands; using Squidex.Infrastructure.UsageTracking; using Squidex.Pipeline; @@ -28,13 +28,13 @@ namespace Squidex.Areas.Api.Controllers.Statistics { private readonly IUsageTracker usageTracker; private readonly IAppPlansProvider appPlanProvider; - private readonly IAssetStatsRepository assetStatsRepository; + private readonly IAssetUsageTracker assetStatsRepository; public UsagesController( ICommandBus commandBus, IUsageTracker usageTracker, IAppPlansProvider appPlanProvider, - IAssetStatsRepository assetStatsRepository) + IAssetUsageTracker assetStatsRepository) : base(commandBus) { this.usageTracker = usageTracker; diff --git a/src/Squidex/Config/Domain/EntitiesServices.cs b/src/Squidex/Config/Domain/EntitiesServices.cs index 11d59b365..12cc6608c 100644 --- a/src/Squidex/Config/Domain/EntitiesServices.cs +++ b/src/Squidex/Config/Domain/EntitiesServices.cs @@ -66,9 +66,9 @@ namespace Squidex.Config.Domain .As() .As(); - services.AddSingletonAs() + services.AddSingletonAs() .As() - .As(); + .As(); services.AddSingletonAs() .As(); diff --git a/tests/Squidex.Domain.Users.Tests/DefaultUserResolverTests.cs b/tests/Squidex.Domain.Users.Tests/DefaultUserResolverTests.cs new file mode 100644 index 000000000..dcc2a645f --- /dev/null +++ b/tests/Squidex.Domain.Users.Tests/DefaultUserResolverTests.cs @@ -0,0 +1,113 @@ +// ========================================================================== +// 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.Security.Claims; +using System.Threading.Tasks; +using FakeItEasy; +using Microsoft.AspNetCore.Identity; +using Xunit; + +namespace Squidex.Domain.Users +{ + public class DefaultUserResolverTests + { + private readonly UserManager userManager = A.Fake>(); + private readonly DefaultUserResolver sut; + + public DefaultUserResolverTests() + { + var userFactory = A.Fake(); + + A.CallTo(() => userFactory.IsId(A.That.StartsWith("id"))) + .Returns(true); + + A.CallTo(() => userManager.NormalizeKey(A.Ignored)) + .ReturnsLazily(c => c.GetArgument(0).ToUpperInvariant()); + + sut = new DefaultUserResolver(userManager, userFactory); + } + + [Fact] + public async Task Should_resolve_user_by_email() + { + var (user, claims) = GernerateUser("id1"); + + A.CallTo(() => userManager.FindByEmailAsync(user.Email)) + .Returns(user); + + A.CallTo(() => userManager.GetClaimsAsync(user)) + .Returns(claims); + + var result = await sut.FindByIdOrEmailAsync(user.Email); + + Assert.Equal(user.Id, result.Id); + Assert.Equal(user.Email, result.Email); + + Assert.Equal(claims, result.Claims); + } + + [Fact] + public async Task Should_resolve_user_by_id1() + { + var (user, claims) = GernerateUser("id2"); + + A.CallTo(() => userManager.FindByIdAsync(user.Id)) + .Returns(user); + + A.CallTo(() => userManager.GetClaimsAsync(user)) + .Returns(claims); + + var result = await sut.FindByIdOrEmailAsync(user.Id); + + Assert.Equal(user.Id, result.Id); + Assert.Equal(user.Email, result.Email); + + Assert.Equal(claims, result.Claims); + } + + [Fact] + public async Task Should_query_many_by_email_async() + { + var (user1, claims1) = GernerateUser("id1"); + var (user2, claims2) = GernerateUser("id2"); + + var list = new List { user1, user2 }; + + A.CallTo(() => userManager.Users) + .Returns(list.AsQueryable()); + + A.CallTo(() => userManager.GetClaimsAsync(user2)) + .Returns(claims2); + + var result = await sut.QueryByEmailAsync("2"); + + Assert.Equal(user2.Id, result[0].Id); + Assert.Equal(user2.Email, result[0].Email); + + Assert.Equal(claims2, result[0].Claims); + + A.CallTo(() => userManager.GetClaimsAsync(user1)) + .MustNotHaveHappened(); + } + + private static (IdentityUser, List) GernerateUser(string id) + { + var user = new IdentityUser { Id = id, Email = $"email_{id}", NormalizedEmail = $"EMAIL_{id}" }; + + var claims = new List + { + new Claim($"{id}_a", "1"), + new Claim($"{id}_b", "2"), + }; + + return (user, claims); + } + } +} diff --git a/tests/Squidex.Domain.Users.Tests/DefaultXmlRepositoryTests.cs b/tests/Squidex.Domain.Users.Tests/DefaultXmlRepositoryTests.cs new file mode 100644 index 000000000..9ab5ba0ee --- /dev/null +++ b/tests/Squidex.Domain.Users.Tests/DefaultXmlRepositoryTests.cs @@ -0,0 +1,56 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using System; +using System.Linq; +using System.Threading.Tasks; +using System.Xml.Linq; +using FakeItEasy; +using Squidex.Infrastructure; +using Squidex.Infrastructure.States; +using Xunit; + +namespace Squidex.Domain.Users +{ + public class DefaultXmlRepositoryTests + { + private readonly ISnapshotStore store = A.Fake>(); + private readonly DefaultXmlRepository sut; + + public DefaultXmlRepositoryTests() + { + sut = new DefaultXmlRepository(store); + } + + [Fact] + public void Should_write_new_item_to_store_with_friendly_name() + { + sut.StoreElement(new XElement("a"), "friendly-name"); + + A.CallTo(() => store.WriteAsync("friendly-name", A.That.Matches(x => x.Xml == ""), EtagVersion.Any, EtagVersion.Any)) + .MustHaveHappened(); + } + + [Fact] + public void Should_return_items_from_store() + { + A.CallTo(() => store.ReadAllAsync(A>.Ignored)) + .Invokes((Func callback) => + { + callback(new DefaultXmlRepository.State { Xml = "" }, EtagVersion.Any); + callback(new DefaultXmlRepository.State { Xml = "" }, EtagVersion.Any); + callback(new DefaultXmlRepository.State { Xml = "" }, EtagVersion.Any); + }); + + var result = sut.GetAllElements().ToList(); + + Assert.Equal("", result[0].ToString()); + Assert.Equal("", result[1].ToString()); + Assert.Equal("", result[2].ToString()); + } + } +}