diff --git a/src/Squidex.Core/project.json b/src/Squidex.Core/project.json index 001945ae6..8692a4f1a 100644 --- a/src/Squidex.Core/project.json +++ b/src/Squidex.Core/project.json @@ -3,15 +3,12 @@ "NodaTime": "2.0.0-alpha20160729", "Squidex.Infrastructure": "1.0.0-*", "protobuf-net": "2.1.0", - "NETStandard.Library": "1.6.1" + "NETStandard.Library": "1.6.1", + "Microsoft.NETCore.App": "1.1.0" }, "frameworks": { "netcoreapp1.0": { "dependencies": { - "Microsoft.NETCore.App": { - "type": "platform", - "version": "1.0.1" - } } } }, diff --git a/src/Squidex.Events/project.json b/src/Squidex.Events/project.json index 8f2771316..b60240b54 100644 --- a/src/Squidex.Events/project.json +++ b/src/Squidex.Events/project.json @@ -2,6 +2,7 @@ "version": "1.0.0-*", "dependencies": { + "Microsoft.NETCore.App": "1.1.0", "NETStandard.Library": "1.6.1", "NodaTime": "2.0.0-alpha20160729", "Squidex.Core": "1.0.0-*", @@ -11,10 +12,6 @@ "frameworks": { "netcoreapp1.0": { "dependencies": { - "Microsoft.NETCore.App": { - "type": "platform", - "version": "1.0.1" - } } } }, diff --git a/src/Squidex.Infrastructure/project.json b/src/Squidex.Infrastructure/project.json index e085e6508..c6150e385 100644 --- a/src/Squidex.Infrastructure/project.json +++ b/src/Squidex.Infrastructure/project.json @@ -4,6 +4,7 @@ "Autofac": "4.2.1", "EventStore.ClientAPI.NetCore": "0.0.1-alpha", "Microsoft.Extensions.Logging": "1.1.0", + "Microsoft.NETCore.App": "1.1.0", "NETStandard.Library": "1.6.1", "Newtonsoft.Json": "9.0.2-beta1", "NodaTime": "2.0.0-alpha20160729", @@ -15,10 +16,6 @@ "frameworks": { "netcoreapp1.0": { "dependencies": { - "Microsoft.NETCore.App": { - "type": "platform", - "version": "1.0.1" - } } } }, diff --git a/src/Squidex.Read/History/IHistoryEventEntity.cs b/src/Squidex.Read/History/IHistoryEventEntity.cs index f1e9f0f85..1c11d1224 100644 --- a/src/Squidex.Read/History/IHistoryEventEntity.cs +++ b/src/Squidex.Read/History/IHistoryEventEntity.cs @@ -6,11 +6,13 @@ // All rights reserved. // ========================================================================== +using System; + namespace Squidex.Read.History { public interface IHistoryEventEntity : IEntity { - string Channel { get; } + Guid EventId { get; } string Message { get; } } diff --git a/src/Squidex.Read/History/Repositories/IHistoryEventRepository.cs b/src/Squidex.Read/History/Repositories/IHistoryEventRepository.cs index e59b9f5f0..db0c64063 100644 --- a/src/Squidex.Read/History/Repositories/IHistoryEventRepository.cs +++ b/src/Squidex.Read/History/Repositories/IHistoryEventRepository.cs @@ -6,6 +6,7 @@ // All rights reserved. // ========================================================================== +using System; using System.Collections.Generic; using System.Threading.Tasks; @@ -13,6 +14,6 @@ namespace Squidex.Read.History.Repositories { public interface IHistoryEventRepository { - Task> FindHistoryByChannel(string channelPrefix, int count); + Task> QueryEventsByChannel(Guid appId, string channelPrefix, int count); } } diff --git a/src/Squidex.Read/Users/Repositories/IUserRepository.cs b/src/Squidex.Read/Users/Repositories/IUserRepository.cs index e8f96a9bc..92b89a6b2 100644 --- a/src/Squidex.Read/Users/Repositories/IUserRepository.cs +++ b/src/Squidex.Read/Users/Repositories/IUserRepository.cs @@ -13,7 +13,7 @@ namespace Squidex.Read.Users.Repositories { public interface IUserRepository { - Task> FindUsersByQuery(string query); + Task> QueryUsersByQuery(string query); Task FindUserByIdAsync(string id); } diff --git a/src/Squidex.Read/project.json b/src/Squidex.Read/project.json index c172fb848..399d0911f 100644 --- a/src/Squidex.Read/project.json +++ b/src/Squidex.Read/project.json @@ -3,6 +3,7 @@ "dependencies": { "Microsoft.Extensions.Caching.Memory": "1.1.0", + "Microsoft.NETCore.App": "1.1.0", "MongoDB.Driver": "2.4.0", "NETStandard.Library": "1.6.1", "NodaTime": "2.0.0-alpha20160729", @@ -14,10 +15,6 @@ "frameworks": { "netcoreapp1.0": { "dependencies": { - "Microsoft.NETCore.App": { - "type": "platform", - "version": "1.0.1" - } } } }, diff --git a/src/Squidex.Store.MongoDb/History/MongoHistoryEventEntity.cs b/src/Squidex.Store.MongoDb/History/MongoHistoryEventEntity.cs index ecfd33945..bf7baab14 100644 --- a/src/Squidex.Store.MongoDb/History/MongoHistoryEventEntity.cs +++ b/src/Squidex.Store.MongoDb/History/MongoHistoryEventEntity.cs @@ -6,6 +6,7 @@ // All rights reserved. // ========================================================================== +using System; using System.Collections.Generic; using MongoDB.Bson.Serialization.Attributes; using Squidex.Infrastructure; @@ -16,6 +17,10 @@ namespace Squidex.Store.MongoDb.History { public sealed class MongoHistoryEventEntity : MongoEntity { + [BsonRequired] + [BsonElement] + public Guid AppId { get; set; } + [BsonRequired] [BsonElement] public string Channel { get; set; } diff --git a/src/Squidex.Store.MongoDb/History/MongoHistoryEventRepository.cs b/src/Squidex.Store.MongoDb/History/MongoHistoryEventRepository.cs index e3cc20a17..4cdbe6551 100644 --- a/src/Squidex.Store.MongoDb/History/MongoHistoryEventRepository.cs +++ b/src/Squidex.Store.MongoDb/History/MongoHistoryEventRepository.cs @@ -36,14 +36,15 @@ namespace Squidex.Store.MongoDb.History protected override Task SetupCollectionAsync(IMongoCollection collection) { return Task.WhenAll( + collection.Indexes.CreateOneAsync(IndexKeys.Ascending(x => x.AppId)), collection.Indexes.CreateOneAsync(IndexKeys.Ascending(x => x.Channel)), collection.Indexes.CreateOneAsync(IndexKeys.Ascending(x => x.Created), new CreateIndexOptions { ExpireAfter = TimeSpan.FromDays(365) })); } - public async Task> FindHistoryByChannel(string channelPrefix, int count) + public async Task> QueryEventsByChannel(Guid appId, string channelPrefix, int count) { var entities = - await Collection.Find(x => x.Channel.StartsWith(channelPrefix)).Limit(count).ToListAsync(); + await Collection.Find(x => x.AppId == appId && x.Channel.StartsWith(channelPrefix)).Limit(count).ToListAsync(); return entities.Select(x => (IHistoryEventEntity)new ParsedHistoryEvent(x, MessagesEN.Texts)).ToList(); } diff --git a/src/Squidex.Store.MongoDb/History/ParsedHistoryEvent.cs b/src/Squidex.Store.MongoDb/History/ParsedHistoryEvent.cs index 8da989b70..99030c6c3 100644 --- a/src/Squidex.Store.MongoDb/History/ParsedHistoryEvent.cs +++ b/src/Squidex.Store.MongoDb/History/ParsedHistoryEvent.cs @@ -22,6 +22,11 @@ namespace Squidex.Store.MongoDb.History get { return inner.Id; } } + public Guid EventId + { + get { return inner.Id; } + } + public DateTime Created { get { return inner.Created; } diff --git a/src/Squidex.Store.MongoDb/MongoDbModule.cs b/src/Squidex.Store.MongoDb/MongoDbModule.cs index 456a41245..1b5bdc6ee 100644 --- a/src/Squidex.Store.MongoDb/MongoDbModule.cs +++ b/src/Squidex.Store.MongoDb/MongoDbModule.cs @@ -15,9 +15,11 @@ using MongoDB.Driver; using Squidex.Infrastructure.CQRS.Events; using Squidex.Infrastructure.CQRS.EventStore; using Squidex.Read.Apps.Repositories; +using Squidex.Read.History.Repositories; using Squidex.Read.Schemas.Repositories; using Squidex.Read.Users.Repositories; using Squidex.Store.MongoDb.Apps; +using Squidex.Store.MongoDb.History; using Squidex.Store.MongoDb.Infrastructure; using Squidex.Store.MongoDb.Schemas; using Squidex.Store.MongoDb.Users; @@ -65,6 +67,10 @@ namespace Squidex.Store.MongoDb .As() .SingleInstance(); + builder.RegisterType() + .As() + .SingleInstance(); + builder.RegisterType() .As() .SingleInstance(); diff --git a/src/Squidex.Store.MongoDb/Users/MongoUserRepository.cs b/src/Squidex.Store.MongoDb/Users/MongoUserRepository.cs index a799c39d3..de09b9c2e 100644 --- a/src/Squidex.Store.MongoDb/Users/MongoUserRepository.cs +++ b/src/Squidex.Store.MongoDb/Users/MongoUserRepository.cs @@ -28,7 +28,7 @@ namespace Squidex.Store.MongoDb.Users this.userManager = userManager; } - public Task> FindUsersByQuery(string query) + public Task> QueryUsersByQuery(string query) { var users = userManager.Users.Where(x => x.NormalizedEmail.Contains(query.ToUpper())).Take(10).ToList(); diff --git a/src/Squidex.Store.MongoDb/project.json b/src/Squidex.Store.MongoDb/project.json index a84cdfe3a..1644d3e35 100644 --- a/src/Squidex.Store.MongoDb/project.json +++ b/src/Squidex.Store.MongoDb/project.json @@ -4,6 +4,7 @@ "IdentityServer4": "1.0.0-rc5", "Microsoft.AspNetCore.Identity": "1.1.0", "Microsoft.AspNetCore.Identity.MongoDB": "1.0.2", + "Microsoft.NETCore.App": "1.1.0", "MongoDB.Driver": "2.4.0", "NETStandard.Library": "1.6.1", "Squidex.Core": "1.0.0-*", @@ -14,10 +15,6 @@ "frameworks": { "netcoreapp1.0": { "dependencies": { - "Microsoft.NETCore.App": { - "type": "platform", - "version": "1.0.1" - } } } }, diff --git a/src/Squidex.Write/project.json b/src/Squidex.Write/project.json index f9e0bdec8..433ca07ab 100644 --- a/src/Squidex.Write/project.json +++ b/src/Squidex.Write/project.json @@ -3,6 +3,7 @@ "dependencies": { "Microsoft.AspNetCore.Identity": "1.1.0", + "Microsoft.NETCore.App": "1.1.0", "NETStandard.Library": "1.6.1", "NodaTime": "2.0.0-alpha20160729", "Squidex.Core": "1.0.0-*", @@ -15,10 +16,6 @@ "frameworks": { "netcoreapp1.0": { "dependencies": { - "Microsoft.NETCore.App": { - "type": "platform", - "version": "1.0.1" - } } } }, diff --git a/src/Squidex/Controllers/Api/History/HistoryController.cs b/src/Squidex/Controllers/Api/History/HistoryController.cs new file mode 100644 index 000000000..a254675e7 --- /dev/null +++ b/src/Squidex/Controllers/Api/History/HistoryController.cs @@ -0,0 +1,71 @@ +// ========================================================================== +// HistoryController.cs +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex Group +// All rights reserved. +// ========================================================================== + +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using NSwag.Annotations; +using Squidex.Controllers.Api.History.Models; +using Squidex.Infrastructure.CQRS.Commands; +using Squidex.Infrastructure.Reflection; +using Squidex.Pipeline; +using Squidex.Read.Apps.Services; +using Squidex.Read.History.Repositories; + +namespace Squidex.Controllers.Api.History +{ + /// + /// Readonly API to get an event stream. + /// + [Authorize] + [ApiExceptionFilter] + [ServiceFilter(typeof(AppFilterAttribute))] + [SwaggerTag("History")] + public class HistoryController : ControllerBase + { + private readonly IAppProvider appProvider; + private readonly IHistoryEventRepository historyEventRepository; + + public HistoryController(ICommandBus commandBus, IAppProvider appProvider, IHistoryEventRepository historyEventRepository) + : base(commandBus) + { + this.appProvider = appProvider; + + this.historyEventRepository = historyEventRepository; + } + + /// + /// Get the events from the history + /// + /// The name of the app. + /// The name of the channel. + /// + /// 200 => Events returned. + /// 404 => App not found. + /// + [HttpGet] + [Route("apps/{app}/history/")] + [ProducesResponseType(typeof(HistoryEventDto), 200)] + public async Task GetHistory(string app, string channel) + { + var entity = await appProvider.FindAppByNameAsync(app); + + if (entity == null) + { + return NotFound(); + } + + var schemas = await historyEventRepository.QueryEventsByChannel(entity.Id, channel, 100); + + var response = schemas.Select(x => SimpleMapper.Map(x, new HistoryEventDto())).ToList(); + + return Ok(response); + } + } +} diff --git a/src/Squidex/Controllers/Api/History/Models/HistoryEventDto.cs b/src/Squidex/Controllers/Api/History/Models/HistoryEventDto.cs new file mode 100644 index 000000000..c0e8dc4c4 --- /dev/null +++ b/src/Squidex/Controllers/Api/History/Models/HistoryEventDto.cs @@ -0,0 +1,32 @@ +// ========================================================================== +// HistoryEventDto.cs +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex Group +// All rights reserved. +// ========================================================================== + +using System; +using System.ComponentModel.DataAnnotations; + +namespace Squidex.Controllers.Api.History.Models +{ + public class HistoryEventDto + { + /// + /// The message of the event. + /// + [Required] + public string Message { get; set; } + + /// + /// Gets a unique id for the event. + /// + public Guid EventId { get; set; } + + /// + /// The time when the event happened. + /// + public DateTime Created { get; set; } + } +} diff --git a/src/Squidex/Controllers/Api/Users/UsersController.cs b/src/Squidex/Controllers/Api/Users/UsersController.cs index bb2e7bf55..e21db617d 100644 --- a/src/Squidex/Controllers/Api/Users/UsersController.cs +++ b/src/Squidex/Controllers/Api/Users/UsersController.cs @@ -48,7 +48,7 @@ namespace Squidex.Controllers.Api.Users [ProducesResponseType(typeof(UserDto[]), 200)] public async Task GetUsers(string query) { - var entities = await userRepository.FindUsersByQuery(query ?? string.Empty); + var entities = await userRepository.QueryUsersByQuery(query ?? string.Empty); var response = entities.Select(x => SimpleMapper.Map(x, new UserDto())).ToList(); diff --git a/tests/Squidex.Core.Tests/project.json b/tests/Squidex.Core.Tests/project.json index 2c522f292..fd700b753 100644 --- a/tests/Squidex.Core.Tests/project.json +++ b/tests/Squidex.Core.Tests/project.json @@ -8,17 +8,17 @@ }, "dependencies": { "dotnet-test-xunit": "2.2.0-preview2-build1029", + "FluentAssertions": "4.18.0", "Moq": "4.6.38-alpha", "Squidex.Core": "1.0.0-*", "Squidex.Infrastructure": "1.0.0-*", "xunit": "2.2.0-beta4-build3444" }, "frameworks": { - "netcoreapp1.0": { + "netcoreapp1.1": { "dependencies": { "Microsoft.NETCore.App": { - "type": "platform", - "version": "1.0.1" + "type": "platform", "version": "1.1.0" } } } diff --git a/tests/Squidex.Infrastructure.Tests/project.json b/tests/Squidex.Infrastructure.Tests/project.json index eb83c0f1d..e8cea3da6 100644 --- a/tests/Squidex.Infrastructure.Tests/project.json +++ b/tests/Squidex.Infrastructure.Tests/project.json @@ -13,11 +13,10 @@ "xunit": "2.2.0-beta4-build3444" }, "frameworks": { - "netcoreapp1.0": { + "netcoreapp1.1": { "dependencies": { "Microsoft.NETCore.App": { - "type": "platform", - "version": "1.0.1" + "type": "platform", "version": "1.1.0" } } } diff --git a/tests/Squidex.Write.Tests/project.json b/tests/Squidex.Write.Tests/project.json index f475f5f94..e99c4f9e2 100644 --- a/tests/Squidex.Write.Tests/project.json +++ b/tests/Squidex.Write.Tests/project.json @@ -16,11 +16,10 @@ "xunit": "2.2.0-beta4-build3444" }, "frameworks": { - "netcoreapp1.0": { + "netcoreapp1.1": { "dependencies": { "Microsoft.NETCore.App": { - "type": "platform", - "version": "1.0.1" + "type": "platform", "version": "1.1.0" } } }