Browse Source

Apps

pull/1/head
Sebastian 9 years ago
parent
commit
cac9611906
  1. 21
      PinkParrot.sln
  2. 17
      src/PinkParrot.Events/Apps/AppCreated.cs
  3. 9
      src/PinkParrot.Infrastructure/Guard.cs
  4. 0
      src/PinkParrot.Store.MongoDb/Infrastructure/MongoPositionEntity.cs
  5. 57
      src/PinkParrot.Store.MongoDb/MongoDbModule.cs
  6. 17
      src/PinkParrot.Store.MongoDb/MongoDbOptions.cs
  7. 3
      src/PinkParrot.Store.MongoDb/project.json
  8. 59
      src/PinkParrot.Write/Apps/AppDomainObject.cs
  9. 26
      src/PinkParrot.Write/Apps/Commands/CreateApp.cs
  10. 55
      src/PinkParrot/Configurations/EventStoreModule.cs
  11. 23
      src/PinkParrot/Configurations/EventStoreOptions.cs
  12. 25
      src/PinkParrot/Configurations/EventStoreUsage.cs
  13. 17
      src/PinkParrot/Configurations/IdentityOptions.cs
  14. 43
      src/PinkParrot/Configurations/IdentityUsage.cs
  15. 50
      src/PinkParrot/Configurations/InfrastructureModule.cs
  16. 21
      src/PinkParrot/Configurations/InfrastructureUsage.cs
  17. 28
      src/PinkParrot/Startup.cs
  18. 13
      src/PinkParrot/appsettings.json
  19. 0
      tests/PinkParrot.Infrastructure.Tests/CollectionExtensionsTests.cs
  20. 0
      tests/PinkParrot.Infrastructure.Tests/DispatchingTests.cs
  21. 0
      tests/PinkParrot.Infrastructure.Tests/EnumExtensionsTests.cs
  22. 34
      tests/PinkParrot.Infrastructure.Tests/GuardTests.cs
  23. 2
      tests/PinkParrot.Infrastructure.Tests/PinkParrot.Infrastructure.Tests.xproj
  24. 0
      tests/PinkParrot.Infrastructure.Tests/PropertiesBagTests.cs
  25. 0
      tests/PinkParrot.Infrastructure.Tests/Reflection/PropertiesTypeAccessorTest.cs
  26. 0
      tests/PinkParrot.Infrastructure.Tests/Reflection/SimpleMapperTests.cs
  27. 0
      tests/PinkParrot.Infrastructure.Tests/TypeNameRegistryTests.cs
  28. 0
      tests/PinkParrot.Infrastructure.Tests/project.json
  29. 0
      tests/PinkParrot.Infrastructure.Tests/xunit.runner.json
  30. 32
      tests/PinkParrot.Write.Tests/Apps/AppDomainObjectTest.cs
  31. 19
      tests/PinkParrot.Write.Tests/PinkParrot.Write.Tests.xproj
  32. 19
      tests/PinkParrot.Write.Tests/Properties/AssemblyInfo.cs
  33. 31
      tests/PinkParrot.Write.Tests/project.json

21
PinkParrot.sln

@ -18,8 +18,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "pinkparrot_domain", "pinkpa
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "PinkParrot.Core", "src\PinkParrot.Core\PinkParrot.Core.xproj", "{47F3C27E-698B-4EDF-A7E8-D7F4232AFBB0}"
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "PinkParrot.Infrastructure.Tests", "src\PinkParrot.Infrastructure.Tests\PinkParrot.Infrastructure.Tests.xproj", "{840C02B1-48F8-4C8A-8862-8A3FDEFDE8D5}"
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "PinkParrot.Infrastructure", "src\PinkParrot.Infrastructure\PinkParrot.Infrastructure.xproj", "{BD1C30A8-8FFA-4A92-A9BD-B67B1CDDD84C}"
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "PinkParrot.Events", "src\PinkParrot.Events\PinkParrot.Events.xproj", "{25F66C64-058A-4D44-BC0C-F12A054F9A91}"
@ -32,6 +30,10 @@ Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "PinkParrot.Store.MongoDb",
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "pinkparrot_store", "pinkparrot_store", "{4082AA58-D410-4C52-8E88-3B0A4E860B28}"
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "PinkParrot.Write.Tests", "tests\PinkParrot.Write.Tests\PinkParrot.Write.Tests.xproj", "{9A3DEA7E-1681-4D48-AC5C-1F0DE421A203}"
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "PinkParrot.Infrastructure.Tests", "tests\PinkParrot.Infrastructure.Tests\PinkParrot.Infrastructure.Tests.xproj", "{7FD0A92B-7862-4BB1-932B-B52A9CACB56B}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -46,10 +48,6 @@ Global
{47F3C27E-698B-4EDF-A7E8-D7F4232AFBB0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{47F3C27E-698B-4EDF-A7E8-D7F4232AFBB0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{47F3C27E-698B-4EDF-A7E8-D7F4232AFBB0}.Release|Any CPU.Build.0 = Release|Any CPU
{840C02B1-48F8-4C8A-8862-8A3FDEFDE8D5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{840C02B1-48F8-4C8A-8862-8A3FDEFDE8D5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{840C02B1-48F8-4C8A-8862-8A3FDEFDE8D5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{840C02B1-48F8-4C8A-8862-8A3FDEFDE8D5}.Release|Any CPU.Build.0 = Release|Any CPU
{BD1C30A8-8FFA-4A92-A9BD-B67B1CDDD84C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BD1C30A8-8FFA-4A92-A9BD-B67B1CDDD84C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BD1C30A8-8FFA-4A92-A9BD-B67B1CDDD84C}.Release|Any CPU.ActiveCfg = Release|Any CPU
@ -70,6 +68,14 @@ Global
{28F8E9E2-FE24-41F7-A888-9FC244A9E2DD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{28F8E9E2-FE24-41F7-A888-9FC244A9E2DD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{28F8E9E2-FE24-41F7-A888-9FC244A9E2DD}.Release|Any CPU.Build.0 = Release|Any CPU
{9A3DEA7E-1681-4D48-AC5C-1F0DE421A203}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9A3DEA7E-1681-4D48-AC5C-1F0DE421A203}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9A3DEA7E-1681-4D48-AC5C-1F0DE421A203}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9A3DEA7E-1681-4D48-AC5C-1F0DE421A203}.Release|Any CPU.Build.0 = Release|Any CPU
{7FD0A92B-7862-4BB1-932B-B52A9CACB56B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7FD0A92B-7862-4BB1-932B-B52A9CACB56B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7FD0A92B-7862-4BB1-932B-B52A9CACB56B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7FD0A92B-7862-4BB1-932B-B52A9CACB56B}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -77,11 +83,12 @@ Global
GlobalSection(NestedProjects) = preSolution
{61F6BBCE-A080-4400-B194-70E2F5D2096E} = {24A3171D-2905-49C9-8A49-A473799014E8}
{47F3C27E-698B-4EDF-A7E8-D7F4232AFBB0} = {4C6B06C2-6D77-4E0E-AE32-D7050236433A}
{840C02B1-48F8-4C8A-8862-8A3FDEFDE8D5} = {8CF53B92-5EB1-461D-98F8-70DA9B603FBF}
{BD1C30A8-8FFA-4A92-A9BD-B67B1CDDD84C} = {8CF53B92-5EB1-461D-98F8-70DA9B603FBF}
{25F66C64-058A-4D44-BC0C-F12A054F9A91} = {4C6B06C2-6D77-4E0E-AE32-D7050236433A}
{A85201C6-6AF8-4B63-8365-08F741050438} = {4C6B06C2-6D77-4E0E-AE32-D7050236433A}
{A92B4734-2587-4F6F-97A3-741BE48709A5} = {4C6B06C2-6D77-4E0E-AE32-D7050236433A}
{28F8E9E2-FE24-41F7-A888-9FC244A9E2DD} = {4082AA58-D410-4C52-8E88-3B0A4E860B28}
{9A3DEA7E-1681-4D48-AC5C-1F0DE421A203} = {4C6B06C2-6D77-4E0E-AE32-D7050236433A}
{7FD0A92B-7862-4BB1-932B-B52A9CACB56B} = {8CF53B92-5EB1-461D-98F8-70DA9B603FBF}
EndGlobalSection
EndGlobal

17
src/PinkParrot.Events/Apps/AppCreated.cs

@ -0,0 +1,17 @@
// ==========================================================================
// AppCreated.cs
// PinkParrot Headless CMS
// ==========================================================================
// Copyright (c) PinkParrot Group
// All rights reserved.
// ==========================================================================
using PinkParrot.Infrastructure.CQRS.Events;
namespace PinkParrot.Events.Apps
{
public class AppCreated : IEvent
{
public string Name { get; set; }
}
}

9
src/PinkParrot.Infrastructure/Guard.cs

@ -196,5 +196,14 @@ namespace PinkParrot.Infrastructure
throw new ArgumentException("Value contains an invalid character.", parameterName);
}
}
[DebuggerStepThrough]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Valid(IValidatable target, string parameterName, string message)
{
NotNull(target, parameterName);
target.Validate(() => message);
}
}
}

0
src/PinkParrot.Store.MongoDb/Infrastructure/MongoPosition.cs → src/PinkParrot.Store.MongoDb/Infrastructure/MongoPositionEntity.cs

57
src/PinkParrot.Store.MongoDb/MongoDbModule.cs

@ -0,0 +1,57 @@
// ==========================================================================
// MongoDbModule.cs
// PinkParrot Headless CMS
// ==========================================================================
// Copyright (c) PinkParrot Group
// All rights reserved.
// ==========================================================================
using Autofac;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.MongoDB;
using Microsoft.Extensions.Options;
using MongoDB.Driver;
using PinkParrot.Infrastructure.CQRS.EventStore;
using PinkParrot.Store.MongoDb.Infrastructure;
namespace PinkParrot.Store.MongoDb
{
public class MongoDbModule : Module
{
protected override void Load(ContainerBuilder builder)
{
builder.Register(context =>
{
var options = context.Resolve<IOptions<MongoDbOptions>>().Value;
var mongoDbClient = new MongoClient(options.ConnectionString);
var mongoDatabase = mongoDbClient.GetDatabase(options.DatabaseName);
return mongoDatabase;
}).SingleInstance();
builder.Register<IUserStore<IdentityUser>>(context =>
{
var usersCollection = context.Resolve<IMongoDatabase>().GetCollection<IdentityUser>("Identity_Users");
IndexChecks.EnsureUniqueIndexOnNormalizedEmail(usersCollection);
IndexChecks.EnsureUniqueIndexOnNormalizedUserName(usersCollection);
return new UserStore<IdentityUser>(usersCollection);
}).SingleInstance();
builder.Register<IRoleStore<IdentityRole>>(context =>
{
var rolesCollection = context.Resolve<IMongoDatabase>().GetCollection<IdentityRole>("Identity_Roles");
IndexChecks.EnsureUniqueIndexOnNormalizedRoleName(rolesCollection);
return new RoleStore<IdentityRole>(rolesCollection);
}).SingleInstance();
builder.RegisterType<MongoPositionStorage>()
.As<IStreamPositionStorage>()
.SingleInstance();
}
}
}

17
src/PinkParrot.Store.MongoDb/MongoDbOptions.cs

@ -0,0 +1,17 @@
// ==========================================================================
// MongoDbOptions.cs
// PinkParrot Headless CMS
// ==========================================================================
// Copyright (c) PinkParrot Group
// All rights reserved.
// ==========================================================================
namespace PinkParrot.Store.MongoDb
{
public class MongoDbOptions
{
public string ConnectionString { get; set; }
public string DatabaseName { get; set; }
}
}

3
src/PinkParrot.Store.MongoDb/project.json

@ -1,5 +1,8 @@
{
"dependencies": {
"Autofac": "4.1.1",
"Microsoft.AspNetCore.Identity": "1.0.0",
"Microsoft.AspNetCore.Identity.MongoDB": "1.0.2",
"MongoDB.Driver": "2.4.0-beta1",
"NETStandard.Library": "1.6.0",
"PinkParrot.Core": "1.0.0-*",

59
src/PinkParrot.Write/Apps/AppDomainObject.cs

@ -0,0 +1,59 @@
// ==========================================================================
// AppDomainObject.cs
// PinkParrot Headless CMS
// ==========================================================================
// Copyright (c) PinkParrot Group
// All rights reserved.
// ==========================================================================
using System;
using PinkParrot.Events.Apps;
using PinkParrot.Infrastructure;
using PinkParrot.Infrastructure.CQRS;
using PinkParrot.Infrastructure.CQRS.Events;
using PinkParrot.Infrastructure.Dispatching;
using PinkParrot.Write.Apps.Commands;
namespace PinkParrot.Write.Apps
{
public sealed class AppDomainObject : DomainObject
{
private string name;
public string Name
{
get { return name; }
}
public AppDomainObject(Guid id, int version) : base(id, version)
{
}
public void On(AppCreated @event)
{
name = @event.Name;
}
protected override void DispatchEvent(Envelope<IEvent> @event)
{
this.DispatchAction(@event.Payload);
}
public void Create(CreateApp command)
{
Guard.Valid(command, nameof(command), "Cannot create app");
VerifyNotCreated();
RaiseEvent(new AppCreated { Name = command.Name });
}
private void VerifyNotCreated()
{
if (!string.IsNullOrWhiteSpace(name))
{
throw new DomainException("App has already been created.");
}
}
}
}

26
src/PinkParrot.Write/Apps/Commands/CreateApp.cs

@ -0,0 +1,26 @@
// ==========================================================================
// CreateApp.cs
// PinkParrot Headless CMS
// ==========================================================================
// Copyright (c) PinkParrot Group
// All rights reserved.
// ==========================================================================
using System.Collections.Generic;
using PinkParrot.Infrastructure;
namespace PinkParrot.Write.Apps.Commands
{
public sealed class CreateApp : IValidatable
{
public string Name { get; set; }
public void Validate(IList<ValidationError> errors)
{
if (!Name.IsSlug())
{
errors.Add(new ValidationError("Name must be a valid slug", "Name"));
}
}
}
}

55
src/PinkParrot/Configurations/EventStoreModule.cs

@ -0,0 +1,55 @@
// ==========================================================================
// EventStoreModule.cs
// PinkParrot Headless CMS
// ==========================================================================
// Copyright (c) PinkParrot Group
// All rights reserved.
// ==========================================================================
using System.Net;
using Autofac;
using EventStore.ClientAPI;
using EventStore.ClientAPI.SystemData;
using Microsoft.Extensions.Options;
using PinkParrot.Infrastructure.CQRS.EventStore;
namespace PinkParrot.Configurations
{
public class EventStoreModule : Module
{
protected override void Load(ContainerBuilder builder)
{
builder.Register(context =>
{
var options = context.Resolve<IOptions<EventStoreOptions>>().Value;
var eventStore =
EventStoreConnection.Create(
ConnectionSettings.Create()
.UseConsoleLogger()
.UseDebugLogger()
.KeepReconnecting()
.KeepRetrying(),
new IPEndPoint(IPAddress.Parse(options.IPAddress), options.Port));
eventStore.ConnectAsync().Wait();
return eventStore;
}).SingleInstance();
builder.Register(context =>
{
var options = context.Resolve<IOptions<EventStoreOptions>>().Value;
return new UserCredentials(options.Username, options.Password);
}).SingleInstance();
builder.Register(context =>
{
var options = context.Resolve<IOptions<EventStoreOptions>>().Value;
return new DefaultNameResolver(options.Prefix);
}).SingleInstance();
}
}
}

23
src/PinkParrot/Configurations/EventStoreOptions.cs

@ -0,0 +1,23 @@
// ==========================================================================
// EventStoreOptions.cs
// PinkParrot Headless CMS
// ==========================================================================
// Copyright (c) PinkParrot Group
// All rights reserved.
// ==========================================================================
namespace PinkParrot.Configurations
{
public sealed class EventStoreOptions
{
public string IPAddress { get; set; }
public string Username { get; set; }
public string Password { get; set; }
public string Prefix { get; set; }
public int Port { get; set; }
}
}

25
src/PinkParrot/Configurations/EventStoreUsage.cs

@ -0,0 +1,25 @@
// ==========================================================================
// EventStoreUsage.cs
// PinkParrot Headless CMS
// ==========================================================================
// Copyright (c) PinkParrot Group
// All rights reserved.
// ==========================================================================
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using PinkParrot.Infrastructure.CQRS.EventStore;
namespace PinkParrot.Configurations
{
public static class EventStoreUsage
{
public static void UseEventStore(this IApplicationBuilder app)
{
var options = app.ApplicationServices.GetService<IOptions<EventStoreOptions>>().Value;
app.ApplicationServices.GetService<EventStoreBus>().Subscribe(options.Prefix);
}
}
}

17
src/PinkParrot/Configurations/IdentityOptions.cs

@ -0,0 +1,17 @@
// ==========================================================================
// IdentityOptions.cs
// PinkParrot Headless CMS
// ==========================================================================
// Copyright (c) PinkParrot Group
// All rights reserved.
// ==========================================================================
namespace PinkParrot.Configurations
{
public sealed class IdentityOptions
{
public string DefaultUsername { get; set; }
public string DefaultPassword { get; set; }
}
}

43
src/PinkParrot/Configurations/IdentityUsage.cs

@ -0,0 +1,43 @@
// ==========================================================================
// IdentityUsage.cs
// PinkParrot Headless CMS
// ==========================================================================
// Copyright (c) PinkParrot Group
// All rights reserved.
// ==========================================================================
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.MongoDB;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
namespace PinkParrot.Configurations
{
public static class IdentityUsage
{
public static void UseDefaultUser(this IApplicationBuilder app)
{
var options = app.ApplicationServices.GetService<IOptions<IdentityOptions>>().Value;
var username = options.DefaultUsername;
var userManager = app.ApplicationServices.GetService<UserManager<IdentityUser>>();
if (!string.IsNullOrWhiteSpace(options.DefaultUsername) &&
!string.IsNullOrWhiteSpace(options.DefaultPassword))
{
Task.Run(async () =>
{
if (userManager.SupportsQueryableUsers && !userManager.Users.Any())
{
var user = new IdentityUser { UserName = username, Email = username, EmailConfirmed = true };
await userManager.CreateAsync(user, options.DefaultPassword);
}
}).Wait();
}
}
}
}

50
src/PinkParrot/Configurations/InfrastructureModule.cs

@ -6,20 +6,13 @@
// All rights reserved.
// ==========================================================================
using System.Net;
using Autofac;
using EventStore.ClientAPI;
using EventStore.ClientAPI.SystemData;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Infrastructure;
using Microsoft.Extensions.DependencyInjection;
using MongoDB.Driver;
using PinkParrot.Core.Schemas;
using PinkParrot.Infrastructure.CQRS.Autofac;
using PinkParrot.Infrastructure.CQRS.Commands;
using PinkParrot.Infrastructure.CQRS.EventStore;
using PinkParrot.Pipeline;
using PinkParrot.Store.MongoDb.Infrastructure;
namespace PinkParrot.Configurations
@ -28,24 +21,6 @@ namespace PinkParrot.Configurations
{
protected override void Load(ContainerBuilder builder)
{
var eventStore =
EventStoreConnection.Create(
ConnectionSettings.Create()
.UseConsoleLogger()
.UseDebugLogger()
.KeepReconnecting()
.KeepRetrying(),
new IPEndPoint(IPAddress.Loopback, 1113));
var mongoDbClient = new MongoClient("mongodb://localhost");
var mongoDatabase = mongoDbClient.GetDatabase("PinkParrot");
eventStore.ConnectAsync().Wait();
builder.RegisterInstance(new UserCredentials("admin", "changeit"))
.AsSelf()
.SingleInstance();
builder.RegisterType<HttpContextAccessor>()
.As<IHttpContextAccessor>()
.SingleInstance();
@ -54,10 +29,6 @@ namespace PinkParrot.Configurations
.As<IActionContextAccessor>()
.SingleInstance();
builder.RegisterInstance(mongoDatabase)
.As<IMongoDatabase>()
.SingleInstance();
builder.RegisterType<MongoPositionStorage>()
.As<IStreamPositionStorage>()
.SingleInstance();
@ -66,14 +37,6 @@ namespace PinkParrot.Configurations
.As<IDomainObjectFactory>()
.SingleInstance();
builder.RegisterInstance(new DefaultNameResolver("pinkparrot"))
.As<IStreamNameResolver>()
.SingleInstance();
builder.RegisterInstance(eventStore)
.As<IEventStoreConnection>()
.SingleInstance();
builder.RegisterType<EventStoreDomainObjectRepository>()
.As<IDomainObjectRepository>()
.SingleInstance();
@ -91,17 +54,4 @@ namespace PinkParrot.Configurations
.SingleInstance();
}
}
public static class InfrastructureDependencie
{
public static void UseAppEventBus(this IApplicationBuilder app)
{
app.ApplicationServices.GetService<EventStoreBus>().Subscribe("pinkparrot");
}
public static void UseAppTenants(this IApplicationBuilder app)
{
app.UseMiddleware<TenantMiddleware>();
}
}
}

21
src/PinkParrot/Configurations/InfrastructureUsage.cs

@ -0,0 +1,21 @@
// ==========================================================================
// InfrastructureUsage.cs
// PinkParrot Headless CMS
// ==========================================================================
// Copyright (c) PinkParrot Group
// All rights reserved.
// ==========================================================================
using Microsoft.AspNetCore.Builder;
using PinkParrot.Pipeline;
namespace PinkParrot.Configurations
{
public static class InfrastructureUsage
{
public static void UseTenants(this IApplicationBuilder app)
{
app.UseMiddleware<TenantMiddleware>();
}
}
}

28
src/PinkParrot/Startup.cs

@ -11,9 +11,12 @@ using Autofac;
using Autofac.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Identity.MongoDB;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using PinkParrot.Configurations;
using PinkParrot.Store.MongoDb;
// ReSharper disable AccessToModifiedClosure
@ -21,12 +24,32 @@ namespace PinkParrot
{
public class Startup
{
public IConfigurationRoot Configuration { get; }
public Startup(IHostingEnvironment env)
{
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", true, true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", true)
.AddEnvironmentVariables();
Configuration = builder.Build();
}
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services.AddMvc().AddAppSerializers();
services.AddRouting();
services.AddMemoryCache();
services.AddOptions();
services.AddEventFormatter();
services.AddIdentity<IdentityUser, IdentityRole>().AddDefaultTokenProviders();
services.Configure<MongoDbModule>(
Configuration.GetSection("MongoDb"));
services.Configure<EventStoreOptions>(
Configuration.GetSection("EventStore"));
var builder = new ContainerBuilder();
builder.RegisterModule<InfrastructureModule>();
@ -46,10 +69,11 @@ namespace PinkParrot
app.UseDeveloperExceptionPage();
}
app.UseAppTenants();
app.UseTenants();
app.UseMvc();
app.UseStaticFiles();
app.UseAppEventBus();
app.UseEventStore();
app.UseDefaultUser();
}
}
}

13
src/PinkParrot/appsettings.json

@ -0,0 +1,13 @@
{
"MongoDb": {
"ConnectionString": "mongodb://localhost",
"DatabaseName": "PinkParrot"
},
"EventStore": {
"IPAddress": "127.0.0.1",
"Port": 1113,
"Prefix": "pinkparrot",
"Username": "admin",
"Password": "changeit"
}
}

0
src/PinkParrot.Infrastructure.Tests/CollectionExtensionsTests.cs → tests/PinkParrot.Infrastructure.Tests/CollectionExtensionsTests.cs

0
src/PinkParrot.Infrastructure.Tests/DispatchingTests.cs → tests/PinkParrot.Infrastructure.Tests/DispatchingTests.cs

0
src/PinkParrot.Infrastructure.Tests/EnumExtensionsTests.cs → tests/PinkParrot.Infrastructure.Tests/EnumExtensionsTests.cs

34
src/PinkParrot.Infrastructure.Tests/GuardTests.cs → tests/PinkParrot.Infrastructure.Tests/GuardTests.cs

@ -7,10 +7,26 @@
// ==========================================================================
using System;
using System.Collections.Generic;
using Xunit;
namespace PinkParrot.Infrastructure
{
public sealed class ValidatableValid : IValidatable
{
public void Validate(IList<ValidationError> errors)
{
}
}
public sealed class ValidatableInvalid : IValidatable
{
public void Validate(IList<ValidationError> errors)
{
errors.Add(new ValidationError("error", "error"));
}
}
public class GuardTest
{
[Theory]
@ -301,5 +317,23 @@ namespace PinkParrot.Infrastructure
{
Guard.ValidFileName("FileName", "Parameter");
}
[Fact]
public void Valid_should_throw_if_null()
{
Assert.Throws<ArgumentNullException>(() => Guard.Valid(null, "Parameter", "Message"));
}
[Fact]
public void Valid_should_throw_if_invalid()
{
Assert.Throws<ValidationException>(() => Guard.Valid(new ValidatableInvalid(), "Parameter", "Message"));
}
[Fact]
public void Valid_should_do_nothing_if_valid()
{
Guard.Valid(new ValidatableValid(), "Parameter", "Message");
}
}
}

2
src/PinkParrot.Infrastructure.Tests/PinkParrot.Infrastructure.Tests.xproj → tests/PinkParrot.Infrastructure.Tests/PinkParrot.Infrastructure.Tests.xproj

@ -6,7 +6,7 @@
</PropertyGroup>
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.Props" Condition="'$(VSToolsPath)' != ''" />
<PropertyGroup Label="Globals">
<ProjectGuid>840c02b1-48f8-4c8a-8862-8a3fdefde8d5</ProjectGuid>
<ProjectGuid>7fd0a92b-7862-4bb1-932b-b52a9cacb56b</ProjectGuid>
<RootNamespace>PinkParrot.Infrastructure</RootNamespace>
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">.\obj</BaseIntermediateOutputPath>
<OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath>

0
src/PinkParrot.Infrastructure.Tests/PropertiesBagTests.cs → tests/PinkParrot.Infrastructure.Tests/PropertiesBagTests.cs

0
src/PinkParrot.Infrastructure.Tests/Reflection/PropertiesTypeAccessorTest.cs → tests/PinkParrot.Infrastructure.Tests/Reflection/PropertiesTypeAccessorTest.cs

0
src/PinkParrot.Infrastructure.Tests/Reflection/SimpleMapperTests.cs → tests/PinkParrot.Infrastructure.Tests/Reflection/SimpleMapperTests.cs

0
src/PinkParrot.Infrastructure.Tests/TypeNameRegistryTests.cs → tests/PinkParrot.Infrastructure.Tests/TypeNameRegistryTests.cs

0
src/PinkParrot.Infrastructure.Tests/project.json → tests/PinkParrot.Infrastructure.Tests/project.json

0
src/PinkParrot.Infrastructure.Tests/xunit.runner.json → tests/PinkParrot.Infrastructure.Tests/xunit.runner.json

32
tests/PinkParrot.Write.Tests/Apps/AppDomainObjectTest.cs

@ -0,0 +1,32 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using PinkParrot.Infrastructure;
using PinkParrot.Write.Apps;
using PinkParrot.Write.Apps.Commands;
using Xunit;
namespace PinkParrot.Write.Tests.Apps
{
public class AppDomainObjectTest
{
private readonly AppDomainObject sut = new AppDomainObject(Guid.NewGuid(), 0);
[Fact]
public void Create_should_throw_if_created()
{
sut.Create(new CreateApp { Name = "app" });
Assert.Throws<DomainException>(() => sut.Create(new CreateApp { Name = "app" }));
}
[Fact]
public void Create_should_specify_name()
{
sut.Create(new CreateApp { Name = "app" });
Assert.Equal("app", sut.Name);
}
}
}

19
tests/PinkParrot.Write.Tests/PinkParrot.Write.Tests.xproj

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.Props" Condition="'$(VSToolsPath)' != ''" />
<PropertyGroup Label="Globals">
<ProjectGuid>9a3dea7e-1681-4d48-ac5c-1f0de421a203</ProjectGuid>
<RootNamespace>PinkParrot.Write.Tests</RootNamespace>
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">.\obj</BaseIntermediateOutputPath>
<OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup>
<SchemaVersion>2.0</SchemaVersion>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.targets" Condition="'$(VSToolsPath)' != ''" />
</Project>

19
tests/PinkParrot.Write.Tests/Properties/AssemblyInfo.cs

@ -0,0 +1,19 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("PinkParrot.Write.Tests")]
[assembly: AssemblyTrademark("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("6b9364c6-94a1-4631-9cf1-87616afaf1ea")]

31
tests/PinkParrot.Write.Tests/project.json

@ -0,0 +1,31 @@
{
"buildOptions": {
"copyToOutput": {
"include": [
"xunit.runner.json"
]
}
},
"dependencies": {
"dotnet-test-xunit": "2.2.0-preview2-build1029",
"PinkParrot.Core": "1.0.0-*",
"PinkParrot.Infrastructure": "1.0.0-*",
"PinkParrot.Write": "1.0.0-*",
"xunit": "2.2.0-beta3-build3402"
},
"frameworks": {
"netcoreapp1.0": {
"dependencies": {
"Microsoft.NETCore.App": {
"type": "platform",
"version": "1.0.1"
}
}
}
},
"testRunner": "xunit",
"tooling": {
"defaultNamespace": "PinkParrot.Core.Tests"
},
"version": "1.0.0-*"
}
Loading…
Cancel
Save