Browse Source

History API

pull/1/head
Sebastian 9 years ago
parent
commit
4d2ebf310d
  1. 7
      src/Squidex.Core/project.json
  2. 5
      src/Squidex.Events/project.json
  3. 5
      src/Squidex.Infrastructure/project.json
  4. 4
      src/Squidex.Read/History/IHistoryEventEntity.cs
  5. 3
      src/Squidex.Read/History/Repositories/IHistoryEventRepository.cs
  6. 2
      src/Squidex.Read/Users/Repositories/IUserRepository.cs
  7. 5
      src/Squidex.Read/project.json
  8. 5
      src/Squidex.Store.MongoDb/History/MongoHistoryEventEntity.cs
  9. 5
      src/Squidex.Store.MongoDb/History/MongoHistoryEventRepository.cs
  10. 5
      src/Squidex.Store.MongoDb/History/ParsedHistoryEvent.cs
  11. 6
      src/Squidex.Store.MongoDb/MongoDbModule.cs
  12. 2
      src/Squidex.Store.MongoDb/Users/MongoUserRepository.cs
  13. 5
      src/Squidex.Store.MongoDb/project.json
  14. 5
      src/Squidex.Write/project.json
  15. 71
      src/Squidex/Controllers/Api/History/HistoryController.cs
  16. 32
      src/Squidex/Controllers/Api/History/Models/HistoryEventDto.cs
  17. 2
      src/Squidex/Controllers/Api/Users/UsersController.cs
  18. 6
      tests/Squidex.Core.Tests/project.json
  19. 5
      tests/Squidex.Infrastructure.Tests/project.json
  20. 5
      tests/Squidex.Write.Tests/project.json

7
src/Squidex.Core/project.json

@ -3,15 +3,12 @@
"NodaTime": "2.0.0-alpha20160729", "NodaTime": "2.0.0-alpha20160729",
"Squidex.Infrastructure": "1.0.0-*", "Squidex.Infrastructure": "1.0.0-*",
"protobuf-net": "2.1.0", "protobuf-net": "2.1.0",
"NETStandard.Library": "1.6.1" "NETStandard.Library": "1.6.1",
"Microsoft.NETCore.App": "1.1.0"
}, },
"frameworks": { "frameworks": {
"netcoreapp1.0": { "netcoreapp1.0": {
"dependencies": { "dependencies": {
"Microsoft.NETCore.App": {
"type": "platform",
"version": "1.0.1"
}
} }
} }
}, },

5
src/Squidex.Events/project.json

@ -2,6 +2,7 @@
"version": "1.0.0-*", "version": "1.0.0-*",
"dependencies": { "dependencies": {
"Microsoft.NETCore.App": "1.1.0",
"NETStandard.Library": "1.6.1", "NETStandard.Library": "1.6.1",
"NodaTime": "2.0.0-alpha20160729", "NodaTime": "2.0.0-alpha20160729",
"Squidex.Core": "1.0.0-*", "Squidex.Core": "1.0.0-*",
@ -11,10 +12,6 @@
"frameworks": { "frameworks": {
"netcoreapp1.0": { "netcoreapp1.0": {
"dependencies": { "dependencies": {
"Microsoft.NETCore.App": {
"type": "platform",
"version": "1.0.1"
}
} }
} }
}, },

5
src/Squidex.Infrastructure/project.json

@ -4,6 +4,7 @@
"Autofac": "4.2.1", "Autofac": "4.2.1",
"EventStore.ClientAPI.NetCore": "0.0.1-alpha", "EventStore.ClientAPI.NetCore": "0.0.1-alpha",
"Microsoft.Extensions.Logging": "1.1.0", "Microsoft.Extensions.Logging": "1.1.0",
"Microsoft.NETCore.App": "1.1.0",
"NETStandard.Library": "1.6.1", "NETStandard.Library": "1.6.1",
"Newtonsoft.Json": "9.0.2-beta1", "Newtonsoft.Json": "9.0.2-beta1",
"NodaTime": "2.0.0-alpha20160729", "NodaTime": "2.0.0-alpha20160729",
@ -15,10 +16,6 @@
"frameworks": { "frameworks": {
"netcoreapp1.0": { "netcoreapp1.0": {
"dependencies": { "dependencies": {
"Microsoft.NETCore.App": {
"type": "platform",
"version": "1.0.1"
}
} }
} }
}, },

4
src/Squidex.Read/History/IHistoryEventEntity.cs

@ -6,11 +6,13 @@
// All rights reserved. // All rights reserved.
// ========================================================================== // ==========================================================================
using System;
namespace Squidex.Read.History namespace Squidex.Read.History
{ {
public interface IHistoryEventEntity : IEntity public interface IHistoryEventEntity : IEntity
{ {
string Channel { get; } Guid EventId { get; }
string Message { get; } string Message { get; }
} }

3
src/Squidex.Read/History/Repositories/IHistoryEventRepository.cs

@ -6,6 +6,7 @@
// All rights reserved. // All rights reserved.
// ========================================================================== // ==========================================================================
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -13,6 +14,6 @@ namespace Squidex.Read.History.Repositories
{ {
public interface IHistoryEventRepository public interface IHistoryEventRepository
{ {
Task<List<IHistoryEventEntity>> FindHistoryByChannel(string channelPrefix, int count); Task<List<IHistoryEventEntity>> QueryEventsByChannel(Guid appId, string channelPrefix, int count);
} }
} }

2
src/Squidex.Read/Users/Repositories/IUserRepository.cs

@ -13,7 +13,7 @@ namespace Squidex.Read.Users.Repositories
{ {
public interface IUserRepository public interface IUserRepository
{ {
Task<List<IUserEntity>> FindUsersByQuery(string query); Task<List<IUserEntity>> QueryUsersByQuery(string query);
Task<IUserEntity> FindUserByIdAsync(string id); Task<IUserEntity> FindUserByIdAsync(string id);
} }

5
src/Squidex.Read/project.json

@ -3,6 +3,7 @@
"dependencies": { "dependencies": {
"Microsoft.Extensions.Caching.Memory": "1.1.0", "Microsoft.Extensions.Caching.Memory": "1.1.0",
"Microsoft.NETCore.App": "1.1.0",
"MongoDB.Driver": "2.4.0", "MongoDB.Driver": "2.4.0",
"NETStandard.Library": "1.6.1", "NETStandard.Library": "1.6.1",
"NodaTime": "2.0.0-alpha20160729", "NodaTime": "2.0.0-alpha20160729",
@ -14,10 +15,6 @@
"frameworks": { "frameworks": {
"netcoreapp1.0": { "netcoreapp1.0": {
"dependencies": { "dependencies": {
"Microsoft.NETCore.App": {
"type": "platform",
"version": "1.0.1"
}
} }
} }
}, },

5
src/Squidex.Store.MongoDb/History/MongoHistoryEventEntity.cs

@ -6,6 +6,7 @@
// All rights reserved. // All rights reserved.
// ========================================================================== // ==========================================================================
using System;
using System.Collections.Generic; using System.Collections.Generic;
using MongoDB.Bson.Serialization.Attributes; using MongoDB.Bson.Serialization.Attributes;
using Squidex.Infrastructure; using Squidex.Infrastructure;
@ -16,6 +17,10 @@ namespace Squidex.Store.MongoDb.History
{ {
public sealed class MongoHistoryEventEntity : MongoEntity public sealed class MongoHistoryEventEntity : MongoEntity
{ {
[BsonRequired]
[BsonElement]
public Guid AppId { get; set; }
[BsonRequired] [BsonRequired]
[BsonElement] [BsonElement]
public string Channel { get; set; } public string Channel { get; set; }

5
src/Squidex.Store.MongoDb/History/MongoHistoryEventRepository.cs

@ -36,14 +36,15 @@ namespace Squidex.Store.MongoDb.History
protected override Task SetupCollectionAsync(IMongoCollection<MongoHistoryEventEntity> collection) protected override Task SetupCollectionAsync(IMongoCollection<MongoHistoryEventEntity> collection)
{ {
return Task.WhenAll( 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.Channel)),
collection.Indexes.CreateOneAsync(IndexKeys.Ascending(x => x.Created), new CreateIndexOptions { ExpireAfter = TimeSpan.FromDays(365) })); collection.Indexes.CreateOneAsync(IndexKeys.Ascending(x => x.Created), new CreateIndexOptions { ExpireAfter = TimeSpan.FromDays(365) }));
} }
public async Task<List<IHistoryEventEntity>> FindHistoryByChannel(string channelPrefix, int count) public async Task<List<IHistoryEventEntity>> QueryEventsByChannel(Guid appId, string channelPrefix, int count)
{ {
var entities = 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(); return entities.Select(x => (IHistoryEventEntity)new ParsedHistoryEvent(x, MessagesEN.Texts)).ToList();
} }

5
src/Squidex.Store.MongoDb/History/ParsedHistoryEvent.cs

@ -22,6 +22,11 @@ namespace Squidex.Store.MongoDb.History
get { return inner.Id; } get { return inner.Id; }
} }
public Guid EventId
{
get { return inner.Id; }
}
public DateTime Created public DateTime Created
{ {
get { return inner.Created; } get { return inner.Created; }

6
src/Squidex.Store.MongoDb/MongoDbModule.cs

@ -15,9 +15,11 @@ using MongoDB.Driver;
using Squidex.Infrastructure.CQRS.Events; using Squidex.Infrastructure.CQRS.Events;
using Squidex.Infrastructure.CQRS.EventStore; using Squidex.Infrastructure.CQRS.EventStore;
using Squidex.Read.Apps.Repositories; using Squidex.Read.Apps.Repositories;
using Squidex.Read.History.Repositories;
using Squidex.Read.Schemas.Repositories; using Squidex.Read.Schemas.Repositories;
using Squidex.Read.Users.Repositories; using Squidex.Read.Users.Repositories;
using Squidex.Store.MongoDb.Apps; using Squidex.Store.MongoDb.Apps;
using Squidex.Store.MongoDb.History;
using Squidex.Store.MongoDb.Infrastructure; using Squidex.Store.MongoDb.Infrastructure;
using Squidex.Store.MongoDb.Schemas; using Squidex.Store.MongoDb.Schemas;
using Squidex.Store.MongoDb.Users; using Squidex.Store.MongoDb.Users;
@ -65,6 +67,10 @@ namespace Squidex.Store.MongoDb
.As<IStreamPositionStorage>() .As<IStreamPositionStorage>()
.SingleInstance(); .SingleInstance();
builder.RegisterType<MongoHistoryEventRepository>()
.As<IHistoryEventRepository>()
.SingleInstance();
builder.RegisterType<MongoUserRepository>() builder.RegisterType<MongoUserRepository>()
.As<IUserRepository>() .As<IUserRepository>()
.SingleInstance(); .SingleInstance();

2
src/Squidex.Store.MongoDb/Users/MongoUserRepository.cs

@ -28,7 +28,7 @@ namespace Squidex.Store.MongoDb.Users
this.userManager = userManager; this.userManager = userManager;
} }
public Task<List<IUserEntity>> FindUsersByQuery(string query) public Task<List<IUserEntity>> QueryUsersByQuery(string query)
{ {
var users = userManager.Users.Where(x => x.NormalizedEmail.Contains(query.ToUpper())).Take(10).ToList(); var users = userManager.Users.Where(x => x.NormalizedEmail.Contains(query.ToUpper())).Take(10).ToList();

5
src/Squidex.Store.MongoDb/project.json

@ -4,6 +4,7 @@
"IdentityServer4": "1.0.0-rc5", "IdentityServer4": "1.0.0-rc5",
"Microsoft.AspNetCore.Identity": "1.1.0", "Microsoft.AspNetCore.Identity": "1.1.0",
"Microsoft.AspNetCore.Identity.MongoDB": "1.0.2", "Microsoft.AspNetCore.Identity.MongoDB": "1.0.2",
"Microsoft.NETCore.App": "1.1.0",
"MongoDB.Driver": "2.4.0", "MongoDB.Driver": "2.4.0",
"NETStandard.Library": "1.6.1", "NETStandard.Library": "1.6.1",
"Squidex.Core": "1.0.0-*", "Squidex.Core": "1.0.0-*",
@ -14,10 +15,6 @@
"frameworks": { "frameworks": {
"netcoreapp1.0": { "netcoreapp1.0": {
"dependencies": { "dependencies": {
"Microsoft.NETCore.App": {
"type": "platform",
"version": "1.0.1"
}
} }
} }
}, },

5
src/Squidex.Write/project.json

@ -3,6 +3,7 @@
"dependencies": { "dependencies": {
"Microsoft.AspNetCore.Identity": "1.1.0", "Microsoft.AspNetCore.Identity": "1.1.0",
"Microsoft.NETCore.App": "1.1.0",
"NETStandard.Library": "1.6.1", "NETStandard.Library": "1.6.1",
"NodaTime": "2.0.0-alpha20160729", "NodaTime": "2.0.0-alpha20160729",
"Squidex.Core": "1.0.0-*", "Squidex.Core": "1.0.0-*",
@ -15,10 +16,6 @@
"frameworks": { "frameworks": {
"netcoreapp1.0": { "netcoreapp1.0": {
"dependencies": { "dependencies": {
"Microsoft.NETCore.App": {
"type": "platform",
"version": "1.0.1"
}
} }
} }
}, },

71
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
{
/// <summary>
/// Readonly API to get an event stream.
/// </summary>
[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;
}
/// <summary>
/// Get the events from the history
/// </summary>
/// <param name="app">The name of the app.</param>
/// <param name="channel">The name of the channel.</param>
/// <returns>
/// 200 => Events returned.
/// 404 => App not found.
/// </returns>
[HttpGet]
[Route("apps/{app}/history/")]
[ProducesResponseType(typeof(HistoryEventDto), 200)]
public async Task<IActionResult> 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);
}
}
}

32
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
{
/// <summary>
/// The message of the event.
/// </summary>
[Required]
public string Message { get; set; }
/// <summary>
/// Gets a unique id for the event.
/// </summary>
public Guid EventId { get; set; }
/// <summary>
/// The time when the event happened.
/// </summary>
public DateTime Created { get; set; }
}
}

2
src/Squidex/Controllers/Api/Users/UsersController.cs

@ -48,7 +48,7 @@ namespace Squidex.Controllers.Api.Users
[ProducesResponseType(typeof(UserDto[]), 200)] [ProducesResponseType(typeof(UserDto[]), 200)]
public async Task<IActionResult> GetUsers(string query) public async Task<IActionResult> 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(); var response = entities.Select(x => SimpleMapper.Map(x, new UserDto())).ToList();

6
tests/Squidex.Core.Tests/project.json

@ -8,17 +8,17 @@
}, },
"dependencies": { "dependencies": {
"dotnet-test-xunit": "2.2.0-preview2-build1029", "dotnet-test-xunit": "2.2.0-preview2-build1029",
"FluentAssertions": "4.18.0",
"Moq": "4.6.38-alpha", "Moq": "4.6.38-alpha",
"Squidex.Core": "1.0.0-*", "Squidex.Core": "1.0.0-*",
"Squidex.Infrastructure": "1.0.0-*", "Squidex.Infrastructure": "1.0.0-*",
"xunit": "2.2.0-beta4-build3444" "xunit": "2.2.0-beta4-build3444"
}, },
"frameworks": { "frameworks": {
"netcoreapp1.0": { "netcoreapp1.1": {
"dependencies": { "dependencies": {
"Microsoft.NETCore.App": { "Microsoft.NETCore.App": {
"type": "platform", "type": "platform", "version": "1.1.0"
"version": "1.0.1"
} }
} }
} }

5
tests/Squidex.Infrastructure.Tests/project.json

@ -13,11 +13,10 @@
"xunit": "2.2.0-beta4-build3444" "xunit": "2.2.0-beta4-build3444"
}, },
"frameworks": { "frameworks": {
"netcoreapp1.0": { "netcoreapp1.1": {
"dependencies": { "dependencies": {
"Microsoft.NETCore.App": { "Microsoft.NETCore.App": {
"type": "platform", "type": "platform", "version": "1.1.0"
"version": "1.0.1"
} }
} }
} }

5
tests/Squidex.Write.Tests/project.json

@ -16,11 +16,10 @@
"xunit": "2.2.0-beta4-build3444" "xunit": "2.2.0-beta4-build3444"
}, },
"frameworks": { "frameworks": {
"netcoreapp1.0": { "netcoreapp1.1": {
"dependencies": { "dependencies": {
"Microsoft.NETCore.App": { "Microsoft.NETCore.App": {
"type": "platform", "type": "platform", "version": "1.1.0"
"version": "1.0.1"
} }
} }
} }

Loading…
Cancel
Save