Browse Source

Login

pull/1/head
Sebastian 10 years ago
parent
commit
1911771c7e
  1. 0
      cfg/config.js
  2. 5
      src/PinkParrot.Store.MongoDb/Apps/MongoAppRepository.cs
  3. 77
      src/PinkParrot.Store.MongoDb/Infrastructure/MongoPersistedGrantStore.cs
  4. 4
      src/PinkParrot.Store.MongoDb/Infrastructure/MongoStreamPositionEntity.cs
  5. 11
      src/PinkParrot.Store.MongoDb/Infrastructure/MongoStreamPositionStorage.cs
  6. 9
      src/PinkParrot.Store.MongoDb/MongoDbModule.cs
  7. 5
      src/PinkParrot.Store.MongoDb/MyMongoDbOptions.cs
  8. 15
      src/PinkParrot.Store.MongoDb/Schemas/MongoSchemaRepository.cs
  9. 1
      src/PinkParrot.Store.MongoDb/project.json
  10. 30
      src/PinkParrot/.vscode/settings.json
  11. 4
      src/PinkParrot/Configurations/Domain/InfrastructureModule.cs
  12. 6
      src/PinkParrot/Configurations/Domain/InfrastructureUsage.cs
  13. 2
      src/PinkParrot/Configurations/Domain/ReadModule.cs
  14. 10
      src/PinkParrot/Configurations/Domain/Serializers.cs
  15. 8
      src/PinkParrot/Configurations/EventStore/EventStoreModule.cs
  16. 8
      src/PinkParrot/Configurations/EventStore/EventStoreUsage.cs
  17. 7
      src/PinkParrot/Configurations/EventStore/MyEventStoreOptions.cs
  18. BIN
      src/PinkParrot/Configurations/Identity/Cert/IdentityCert.snk
  19. 84
      src/PinkParrot/Configurations/Identity/IdentityServices.cs
  20. 106
      src/PinkParrot/Configurations/Identity/IdentityUsage.cs
  21. 15
      src/PinkParrot/Configurations/Identity/MyIdentityOptions.cs
  22. 43
      src/PinkParrot/Configurations/IdentityUsage.cs
  23. 21
      src/PinkParrot/Configurations/Web/WebDependencies.cs
  24. 23
      src/PinkParrot/Configurations/Web/WebpackServices.cs
  25. 13
      src/PinkParrot/Configurations/Web/WebpackUsage.cs
  26. 2
      src/PinkParrot/Configurations/Web/WriteModule.cs
  27. 3
      src/PinkParrot/Modules/Api/Apps/AppController.cs
  28. 3
      src/PinkParrot/Modules/Api/Schemas/SchemasController.cs
  29. 142
      src/PinkParrot/Modules/UI/Account/AccountController.cs
  30. 23
      src/PinkParrot/Modules/UI/Account/ExternalProvider.cs
  31. 19
      src/PinkParrot/Modules/UI/Account/LoginVM.cs
  32. 8
      src/PinkParrot/Pipeline/WebpackMiddleware.cs
  33. 45
      src/PinkParrot/Startup.cs
  34. 12
      src/PinkParrot/Views/Account/ClientPopup.cshtml
  35. 12
      src/PinkParrot/Views/Account/ClientSilent.cshtml
  36. 15
      src/PinkParrot/Views/Account/Login.cshtml
  37. 3
      src/PinkParrot/Views/_ViewImports.cshtml
  38. 3
      src/PinkParrot/Views/_ViewStart.cshtml
  39. 4
      src/PinkParrot/app/app.component.html
  40. 38
      src/PinkParrot/app/app.module.ts
  41. 30
      src/PinkParrot/app/app.routes.ts
  42. 3
      src/PinkParrot/app/components/apps/apps.component.html
  43. 16
      src/PinkParrot/app/components/apps/apps.component.ts
  44. 24
      src/PinkParrot/app/components/apps/apps.module.ts
  45. 8
      src/PinkParrot/app/components/apps/declarations.ts
  46. 9
      src/PinkParrot/app/components/apps/index.ts
  47. 9
      src/PinkParrot/app/components/index.ts
  48. 8
      src/PinkParrot/app/components/login/declarations.ts
  49. 9
      src/PinkParrot/app/components/login/index.ts
  50. 3
      src/PinkParrot/app/components/login/login.component.html
  51. 36
      src/PinkParrot/app/components/login/login.component.ts
  52. 24
      src/PinkParrot/app/components/login/login.module.ts
  53. 6
      src/PinkParrot/app/framework/angular/action.spec.ts
  54. 2
      src/PinkParrot/app/framework/angular/action.ts
  55. 2
      src/PinkParrot/app/framework/angular/cloak.directive.spec.ts
  56. 2
      src/PinkParrot/app/framework/angular/cloak.directive.ts
  57. 0
      src/PinkParrot/app/framework/angular/color-picker.component.html
  58. 0
      src/PinkParrot/app/framework/angular/color-picker.component.scss
  59. 3
      src/PinkParrot/app/framework/angular/color-picker.component.spec.ts
  60. 11
      src/PinkParrot/app/framework/angular/color-picker.component.ts
  61. 2
      src/PinkParrot/app/framework/angular/date-time.pipes.spec.ts
  62. 2
      src/PinkParrot/app/framework/angular/date-time.pipes.ts
  63. 5
      src/PinkParrot/app/framework/angular/drag-model.directive.ts
  64. 2
      src/PinkParrot/app/framework/angular/focus-on-change.directive.spec.ts
  65. 2
      src/PinkParrot/app/framework/angular/focus-on-change.directive.ts
  66. 5
      src/PinkParrot/app/framework/angular/image-drop.directive.ts
  67. 2
      src/PinkParrot/app/framework/angular/money.pipe.spec.ts
  68. 2
      src/PinkParrot/app/framework/angular/money.pipe.ts
  69. 6
      src/PinkParrot/app/framework/angular/shortcut.component.spec.ts
  70. 2
      src/PinkParrot/app/framework/angular/shortcut.component.ts
  71. 0
      src/PinkParrot/app/framework/angular/slider.component.html
  72. 0
      src/PinkParrot/app/framework/angular/slider.component.scss
  73. 2
      src/PinkParrot/app/framework/angular/slider.component.ts
  74. 2
      src/PinkParrot/app/framework/angular/spinner.component.ts
  75. 2
      src/PinkParrot/app/framework/angular/user-report.component.ts
  76. 2
      src/PinkParrot/app/framework/angular/validators.spec.ts
  77. 2
      src/PinkParrot/app/framework/angular/validators.ts
  78. 27
      src/PinkParrot/app/framework/configurations.ts
  79. 13
      src/PinkParrot/app/framework/declarations.ts
  80. 70
      src/PinkParrot/app/framework/framework.module.ts
  81. 3
      src/PinkParrot/app/framework/index.ts
  82. 2
      src/PinkParrot/app/framework/plattform.ts
  83. 2
      src/PinkParrot/app/framework/services/clipboard.service.spec.ts
  84. 5
      src/PinkParrot/app/framework/services/clipboard.service.ts
  85. 2
      src/PinkParrot/app/framework/services/drag.service.spec.ts
  86. 5
      src/PinkParrot/app/framework/services/drag.service.ts
  87. 2
      src/PinkParrot/app/framework/services/local-store.service.spec.ts
  88. 5
      src/PinkParrot/app/framework/services/local-store.service.ts
  89. 2
      src/PinkParrot/app/framework/services/shortcut.service.spec.ts
  90. 5
      src/PinkParrot/app/framework/services/shortcut.service.ts
  91. 2
      src/PinkParrot/app/framework/services/title.service.spec.ts
  92. 5
      src/PinkParrot/app/framework/services/title.service.ts
  93. 2
      src/PinkParrot/app/framework/utils/color-palette.spec.ts
  94. 2
      src/PinkParrot/app/framework/utils/color-palette.ts
  95. 2
      src/PinkParrot/app/framework/utils/color.spec.ts
  96. 2
      src/PinkParrot/app/framework/utils/color.ts
  97. 2
      src/PinkParrot/app/framework/utils/date-helper.spec.ts
  98. 2
      src/PinkParrot/app/framework/utils/date-helper.ts
  99. 2
      src/PinkParrot/app/framework/utils/date-time.spec.ts
  100. 2
      src/PinkParrot/app/framework/utils/date-time.ts

0
config/config.js → cfg/config.js

5
src/PinkParrot.Store.MongoDb/Apps/MongoAppRepository.cs

@ -28,6 +28,11 @@ namespace PinkParrot.Store.MongoDb.Apps
{
}
protected override string CollectionName()
{
return "Apps";
}
protected override Task SetupCollectionAsync(IMongoCollection<MongoAppEntity> collection)
{
return collection.Indexes.CreateOneAsync(IndexKeys.Ascending(x => x.Name));

77
src/PinkParrot.Store.MongoDb/Infrastructure/MongoPersistedGrantStore.cs

@ -0,0 +1,77 @@
// ==========================================================================
// MongoPersistedGrantStore.cs
// PinkParrot Headless CMS
// ==========================================================================
// Copyright (c) PinkParrot Group
// All rights reserved.
// ==========================================================================
using System.Collections.Generic;
using System.Threading.Tasks;
using IdentityServer4.Models;
using IdentityServer4.Stores;
using MongoDB.Bson.Serialization;
using MongoDB.Driver;
using PinkParrot.Store.MongoDb.Utils;
namespace PinkParrot.Store.MongoDb.Infrastructure
{
public class MongoPersistedGrantStore : MongoRepositoryBase<PersistedGrant>, IPersistedGrantStore
{
static MongoPersistedGrantStore()
{
BsonClassMap.RegisterClassMap<PersistedGrant>(map =>
{
map.AutoMap();
map.MapIdProperty(x => x.Key);
});
}
public MongoPersistedGrantStore(IMongoDatabase database)
: base(database)
{
}
protected override string CollectionName()
{
return "PersistedGrants";
}
protected override Task SetupCollectionAsync(IMongoCollection<PersistedGrant> collection)
{
return Task.WhenAll(
collection.Indexes.CreateOneAsync(IndexKeys.Ascending(x => x.ClientId)),
collection.Indexes.CreateOneAsync(IndexKeys.Ascending(x => x.SubjectId)));
}
public Task StoreAsync(PersistedGrant grant)
{
return Collection.ReplaceOneAsync(x => x.Key == grant.Key, grant, new UpdateOptions { IsUpsert = true });
}
public Task<IEnumerable<PersistedGrant>> GetAllAsync(string subjectId)
{
return Collection.Find(x => x.SubjectId == subjectId).ToListAsync().ContinueWith(x => (IEnumerable<PersistedGrant>)x.Result);
}
public Task<PersistedGrant> GetAsync(string key)
{
return Collection.Find(x => x.Key == key).FirstOrDefaultAsync();
}
public Task RemoveAllAsync(string subjectId, string clientId, string type)
{
return Collection.DeleteManyAsync(x => x.SubjectId == subjectId && x.ClientId == clientId && x.Type == type);
}
public Task RemoveAllAsync(string subjectId, string clientId)
{
return Collection.DeleteManyAsync(x => x.SubjectId == subjectId && x.ClientId == clientId);
}
public Task RemoveAsync(string key)
{
return Collection.DeleteManyAsync(x => x.Key == key);
}
}
}

4
src/PinkParrot.Store.MongoDb/Infrastructure/MongoPositionEntity.cs → src/PinkParrot.Store.MongoDb/Infrastructure/MongoStreamPositionEntity.cs

@ -1,5 +1,5 @@
// ==========================================================================
// MongoPosition.cs
// MongoStreamPositionEntity.cs
// PinkParrot Headless CMS
// ==========================================================================
// Copyright (c) PinkParrot Group
@ -13,7 +13,7 @@ using MongoDB.Bson.Serialization.Attributes;
namespace PinkParrot.Store.MongoDb.Infrastructure
{
[DataContract]
public class MongoPosition
public class MongoStreamPositionEntity
{
[BsonId]
public ObjectId Id { get; set; }

11
src/PinkParrot.Store.MongoDb/Infrastructure/MongoPositionStorage.cs → src/PinkParrot.Store.MongoDb/Infrastructure/MongoStreamPositionStorage.cs

@ -15,22 +15,27 @@ using PinkParrot.Store.MongoDb.Utils;
namespace PinkParrot.Store.MongoDb.Infrastructure
{
public sealed class MongoPositionStorage : MongoRepositoryBase<MongoPosition>, IStreamPositionStorage
public sealed class MongoStreamPositionStorage : MongoRepositoryBase<MongoStreamPositionEntity>, IStreamPositionStorage
{
private static readonly ObjectId Id = new ObjectId("507f1f77bcf86cd799439011");
public MongoPositionStorage(IMongoDatabase database)
public MongoStreamPositionStorage(IMongoDatabase database)
: base(database)
{
}
protected override string CollectionName()
{
return "StreamPositions";
}
public int? ReadPosition()
{
var document = Collection.Find(t => t.Id == Id).FirstOrDefault();
if (document == null)
{
document = new MongoPosition { Id = Id };
document = new MongoStreamPositionEntity { Id = Id };
Collection.InsertOne(document);
}

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

@ -7,6 +7,7 @@
// ==========================================================================
using Autofac;
using IdentityServer4.Stores;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.MongoDB;
using Microsoft.Extensions.Options;
@ -27,7 +28,7 @@ namespace PinkParrot.Store.MongoDb
{
builder.Register(context =>
{
var options = context.Resolve<IOptions<MongoDbOptions>>().Value;
var options = context.Resolve<IOptions<MyMongoDbOptions>>().Value;
var mongoDbClient = new MongoClient(options.ConnectionString);
var mongoDatabase = mongoDbClient.GetDatabase(options.DatabaseName);
@ -54,7 +55,11 @@ namespace PinkParrot.Store.MongoDb
return new RoleStore<IdentityRole>(rolesCollection);
}).SingleInstance();
builder.RegisterType<MongoPositionStorage>()
builder.RegisterType<MongoPersistedGrantStore>()
.As<IPersistedGrantStore>()
.SingleInstance();
builder.RegisterType<MongoStreamPositionStorage>()
.As<IStreamPositionStorage>()
.SingleInstance();

5
src/PinkParrot.Store.MongoDb/MongoDbOptions.cs → src/PinkParrot.Store.MongoDb/MyMongoDbOptions.cs

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

15
src/PinkParrot.Store.MongoDb/Schemas/MongoSchemaRepository.cs

@ -40,6 +40,11 @@ namespace PinkParrot.Store.MongoDb.Schemas
this.fieldRegistry = fieldRegistry;
}
protected override string CollectionName()
{
return "Apps";
}
protected override Task SetupCollectionAsync(IMongoCollection<MongoSchemaEntity> collection)
{
return collection.Indexes.CreateOneAsync(IndexKeys.Ascending(x => x.Name));
@ -140,6 +145,11 @@ namespace PinkParrot.Store.MongoDb.Schemas
return this.DispatchActionAsync(@event.Payload, @event.Headers);
}
private Task UpdateSchema(EnvelopeHeaders headers, Func<Schema, Schema> updater)
{
return Collection.UpdateAsync(headers, e => UpdateSchema(e, updater));
}
private void UpdateSchema(MongoSchemaEntity entity, Func<Schema, Schema> updater)
{
var currentSchema = Deserialize(entity);
@ -149,11 +159,6 @@ namespace PinkParrot.Store.MongoDb.Schemas
Serialize(entity, currentSchema);
}
private Task UpdateSchema(EnvelopeHeaders headers, Func<Schema, Schema> updater)
{
return Collection.UpdateAsync(headers, e=> UpdateSchema(e, updater));
}
private void Serialize(MongoSchemaEntity entity, Schema schema)
{
var dto = SchemaDto.Create(schema);

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

@ -1,6 +1,7 @@
{
"dependencies": {
"Autofac": "4.1.1",
"IdentityServer4": "1.0.0-rc2",
"Microsoft.AspNetCore.Identity": "1.0.0",
"Microsoft.AspNetCore.Identity.MongoDB": "1.0.2",
"MongoDB.Driver": "2.4.0-beta1",

30
src/PinkParrot/.vscode/settings.json

@ -0,0 +1,30 @@
{
// Controls if the editor shows reference information for the modes that support it
"editor.referenceInfos": false,
// When opening a file, `editor.tabSize` and `editor.insertSpaces` will be detected based on the file contents.
"editor.detectIndentation": false,
// Typescript version from local package to be consistent
"typescript.tsdk": "node_modules/typescript/lib",
// Configure glob patterns for excluding files and folders.
"files.exclude": {
"_test-output": true,
"**/node_modules": true,
"**/artifacts": true,
"**/build": true,
"**/out": true,
"**/obj": true,
"**/bin": true,
"**/*.lock.json": true,
"**/*.bat": true,
"**/*.sln": true,
"**/*.sln.DotSettings": true,
"**/*.user": true,
"**/*.xproj": true,
"**/*.gitattributes": true,
".vs:": true,
".vscode:": true
}
}

4
src/PinkParrot/Configurations/InfrastructureModule.cs → src/PinkParrot/Configurations/Domain/InfrastructureModule.cs

@ -15,7 +15,7 @@ using PinkParrot.Infrastructure.CQRS.Commands;
using PinkParrot.Infrastructure.CQRS.EventStore;
using PinkParrot.Store.MongoDb.Infrastructure;
namespace PinkParrot.Configurations
namespace PinkParrot.Configurations.Domain
{
public class InfrastructureModule : Module
{
@ -29,7 +29,7 @@ namespace PinkParrot.Configurations
.As<IActionContextAccessor>()
.SingleInstance();
builder.RegisterType<MongoPositionStorage>()
builder.RegisterType<MongoStreamPositionStorage>()
.As<IStreamPositionStorage>()
.SingleInstance();

6
src/PinkParrot/Configurations/InfrastructureUsage.cs → src/PinkParrot/Configurations/Domain/InfrastructureUsage.cs

@ -9,13 +9,15 @@
using Microsoft.AspNetCore.Builder;
using PinkParrot.Pipeline;
namespace PinkParrot.Configurations
namespace PinkParrot.Configurations.Domain
{
public static class InfrastructureUsage
{
public static void UseApps(this IApplicationBuilder app)
public static IApplicationBuilder UseMyApps(this IApplicationBuilder app)
{
app.UseMiddleware<AppMiddleware>();
return app;
}
}
}

2
src/PinkParrot/Configurations/ReadModule.cs → src/PinkParrot/Configurations/Domain/ReadModule.cs

@ -13,7 +13,7 @@ using PinkParrot.Read.Apps.Services.Implementations;
using PinkParrot.Read.Schemas.Services;
using PinkParrot.Read.Schemas.Services.Implementations;
namespace PinkParrot.Configurations
namespace PinkParrot.Configurations.Domain
{
public sealed class ReadModule : Module
{

10
src/PinkParrot/Configurations/Serializers.cs → src/PinkParrot/Configurations/Domain/Serializers.cs

@ -16,7 +16,7 @@ using PinkParrot.Infrastructure;
using PinkParrot.Infrastructure.CQRS.EventStore;
using PinkParrot.Infrastructure.Json;
namespace PinkParrot.Configurations
namespace PinkParrot.Configurations.Domain
{
public static class Serializers
{
@ -43,7 +43,7 @@ namespace PinkParrot.Configurations
return JsonSerializer.Create(settings);
}
public static void AddEventFormatter(this IServiceCollection services)
public static IServiceCollection AddMyEventFormatter(this IServiceCollection services)
{
TypeNameRegistry.Map(typeof(Schema).GetTypeInfo().Assembly);
TypeNameRegistry.Map(typeof(SchemaCreated).GetTypeInfo().Assembly);
@ -51,14 +51,18 @@ namespace PinkParrot.Configurations
services.AddSingleton(t => CreateSettings());
services.AddSingleton(t => CreateSerializer(t.GetRequiredService<JsonSerializerSettings>()));
services.AddSingleton<EventStoreFormatter>();
return services;
}
public static void AddAppSerializers(this IMvcBuilder mvc)
public static IMvcBuilder AddMySerializers(this IMvcBuilder mvc)
{
mvc.AddJsonOptions(options =>
{
ConfigureJson(options.SerializerSettings);
});
return mvc;
}
}
}

8
src/PinkParrot/Configurations/EventStoreModule.cs → src/PinkParrot/Configurations/EventStore/EventStoreModule.cs

@ -13,7 +13,7 @@ using EventStore.ClientAPI.SystemData;
using Microsoft.Extensions.Options;
using PinkParrot.Infrastructure.CQRS.EventStore;
namespace PinkParrot.Configurations
namespace PinkParrot.Configurations.EventStore
{
public class EventStoreModule : Module
{
@ -21,7 +21,7 @@ namespace PinkParrot.Configurations
{
builder.Register(context =>
{
var options = context.Resolve<IOptions<EventStoreOptions>>().Value;
var options = context.Resolve<IOptions<MyEventStoreOptions>>().Value;
var eventStore =
EventStoreConnection.Create(
@ -39,14 +39,14 @@ namespace PinkParrot.Configurations
builder.Register(context =>
{
var options = context.Resolve<IOptions<EventStoreOptions>>().Value;
var options = context.Resolve<IOptions<MyEventStoreOptions>>().Value;
return new UserCredentials(options.Username, options.Password);
}).SingleInstance();
builder.Register(context =>
{
var options = context.Resolve<IOptions<EventStoreOptions>>().Value;
var options = context.Resolve<IOptions<MyEventStoreOptions>>().Value;
return new DefaultNameResolver(options.Prefix);
}).SingleInstance();

8
src/PinkParrot/Configurations/EventStoreUsage.cs → src/PinkParrot/Configurations/EventStore/EventStoreUsage.cs

@ -11,15 +11,17 @@ using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using PinkParrot.Infrastructure.CQRS.EventStore;
namespace PinkParrot.Configurations
namespace PinkParrot.Configurations.EventStore
{
public static class EventStoreUsage
{
public static void UseEventStore(this IApplicationBuilder app)
public static IApplicationBuilder UseMyEventStore(this IApplicationBuilder app)
{
var options = app.ApplicationServices.GetService<IOptions<EventStoreOptions>>().Value;
var options = app.ApplicationServices.GetRequiredService<IOptions<MyEventStoreOptions>>().Value;
app.ApplicationServices.GetService<EventStoreBus>().Subscribe(options.Prefix);
return app;
}
}
}

7
src/PinkParrot/Configurations/EventStoreOptions.cs → src/PinkParrot/Configurations/EventStore/MyEventStoreOptions.cs

@ -1,14 +1,13 @@
// ==========================================================================
// EventStoreOptions.cs
// MyEventStoreOptions.cs
// PinkParrot Headless CMS
// ==========================================================================
// Copyright (c) PinkParrot Group
// All rights reserved.
// ==========================================================================
namespace PinkParrot.Configurations
namespace PinkParrot.Configurations.EventStore
{
public sealed class EventStoreOptions
public sealed class MyEventStoreOptions
{
public string IPAddress { get; set; }

BIN
src/PinkParrot/Configurations/Identity/Cert/IdentityCert.snk

Binary file not shown.

84
src/PinkParrot/Configurations/Identity/IdentityServices.cs

@ -0,0 +1,84 @@
// ==========================================================================
// IdentityDependencies.cs
// PinkParrot Headless CMS
// ==========================================================================
// Copyright (c) PinkParrot Group
// All rights reserved.
// ==========================================================================
using System.Collections.Generic;
using System.IO;
using System.Security.Cryptography.X509Certificates;
using IdentityServer4.Models;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Identity.MongoDB;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.IdentityModel.Tokens;
namespace PinkParrot.Configurations.Identity
{
public static class IdentityServices
{
public static IServiceCollection AddMyIdentityServer(this IServiceCollection services, IHostingEnvironment env)
{
var certPath = Path.Combine(env.ContentRootPath, "Configurations", "Identity", "Cert", "IdentityCert.pfx");
var certificate = new X509Certificate2(certPath, "password");
services.AddIdentityServer()
.SetSigningCredential(certificate)
.AddInMemoryScopes(GetScopes())
.AddInMemoryClients(GetClients())
.AddAspNetIdentity<IdentityUser>();
return services;
}
public static IServiceCollection AddMyIdentity(this IServiceCollection services)
{
services.AddIdentity<IdentityUser, IdentityRole>()
.AddDefaultTokenProviders();
return services;
}
public static IEnumerable<Scope> GetScopes()
{
return new List<Scope>
{
StandardScopes.OpenId,
StandardScopes.Profile,
new Scope
{
Name = "api1",
Description = "My API"
}
};
}
public static IEnumerable<Client> GetClients()
{
return new List<Client>
{
new Client
{
ClientId = "management-portal",
ClientName = "MVC Client",
RedirectUris = new List<string>
{
"http://localhost:5000/account/client-silent",
"http://localhost:5000/account/client-popup"
},
AllowedGrantTypes = GrantTypes.Implicit,
AllowedScopes = new List<string>
{
StandardScopes.OpenId.Name,
StandardScopes.Profile.Name
},
RequireConsent = false
}
};
}
}
}

106
src/PinkParrot/Configurations/Identity/IdentityUsage.cs

@ -0,0 +1,106 @@
// ==========================================================================
// 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;
// ReSharper disable InvertIf
namespace PinkParrot.Configurations.Identity
{
public static class IdentityUsage
{
public static IApplicationBuilder UseMyIdentity(this IApplicationBuilder app)
{
app.UseIdentity();
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationScheme = "Cookies"
});
return app;
}
public static IApplicationBuilder UseMyIdentityServer(this IApplicationBuilder app)
{
app.UseIdentityServer();
return app;
}
public static IApplicationBuilder UseMyDefaultUser(this IApplicationBuilder app)
{
var options = app.ApplicationServices.GetService<IOptions<MyIdentityOptions>>().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();
}
return app;
}
public static IApplicationBuilder UseMyGoogleAuthentication(this IApplicationBuilder app)
{
var options = app.ApplicationServices.GetService<IOptions<MyIdentityOptions>>().Value;
if (!string.IsNullOrWhiteSpace(options.GoogleClient) &&
!string.IsNullOrWhiteSpace(options.GoogleSecret))
{
var googleOptions =
new GoogleOptions
{
ClientId = options.GoogleClient,
ClientSecret = options.GoogleSecret
};
app.UseGoogleAuthentication(googleOptions);
}
return app;
}
public static IApplicationBuilder UseMyApiProtection(this IApplicationBuilder app)
{
var options = app.ApplicationServices.GetService<IOptions<MyIdentityOptions>>().Value;
if (!string.IsNullOrWhiteSpace(options.BaseUrl))
{
app.Map("/api", api =>
{
api.UseIdentityServerAuthentication(new IdentityServerAuthenticationOptions
{
Authority = options.BaseUrl,
ScopeName = "api",
RequireHttpsMetadata = options.RequiresHttps
});
});
}
return app;
}
}
}

15
src/PinkParrot/Configurations/IdentityOptions.cs → src/PinkParrot/Configurations/Identity/MyIdentityOptions.cs

@ -1,17 +1,24 @@
// ==========================================================================
// IdentityOptions.cs
// MyIdentityOptions.cs
// PinkParrot Headless CMS
// ==========================================================================
// Copyright (c) PinkParrot Group
// All rights reserved.
// ==========================================================================
namespace PinkParrot.Configurations
namespace PinkParrot.Configurations.Identity
{
public sealed class IdentityOptions
public sealed class MyIdentityOptions
{
public string DefaultUsername { get; set; }
public string DefaultPassword { get; set; }
public string GoogleClient { get; set; }
public string GoogleSecret { get; set; }
public string BaseUrl { get; set; }
public bool RequiresHttps { get; set; }
}
}

43
src/PinkParrot/Configurations/IdentityUsage.cs

@ -1,43 +0,0 @@
// ==========================================================================
// 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();
}
}
}
}

21
src/PinkParrot/Configurations/Web/WebDependencies.cs

@ -0,0 +1,21 @@
// ==========================================================================
// WebDependencies.cs
// PinkParrot Headless CMS
// ==========================================================================
// Copyright (c) PinkParrot Group
// All rights reserved.
// ==========================================================================
using Microsoft.Extensions.DependencyInjection;
using PinkParrot.Configurations.Domain;
namespace PinkParrot.Configurations.Web
{
public static class WebDependencies
{
public static void AddMyMvc(this IServiceCollection services)
{
services.AddMvc().AddMySerializers();
}
}
}

23
src/PinkParrot/Configurations/Web/WebpackServices.cs

@ -0,0 +1,23 @@
// ==========================================================================
// WebpackServices.cs
// PinkParrot Headless CMS
// ==========================================================================
// Copyright (c) PinkParrot Group
// All rights reserved.
// ==========================================================================
using Microsoft.Extensions.DependencyInjection;
using PinkParrot.Pipeline;
namespace PinkParrot.Configurations.Web
{
public static class WebpackServices
{
public static IServiceCollection AddWebpackBuilder(this IServiceCollection services)
{
services.AddSingleton<WebpackRunner>();
return services;
}
}
}

13
src/PinkParrot/Configurations/WebpackUsage.cs → src/PinkParrot/Configurations/Web/WebpackUsage.cs

@ -10,21 +10,20 @@ using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using PinkParrot.Pipeline;
namespace PinkParrot.Configurations
namespace PinkParrot.Configurations.Web
{
public static class WebpackExtensions
{
public static IServiceCollection AddWebpack(this IServiceCollection services)
public static IApplicationBuilder UseWebpackBuilder(this IApplicationBuilder app)
{
services.AddSingleton<WebpackRunner>();
app.ApplicationServices.GetRequiredService<WebpackRunner>().Execute();
return services;
return app;
}
public static IApplicationBuilder UseWebpack(this IApplicationBuilder app)
public static IApplicationBuilder UseWebpackProxy(this IApplicationBuilder app)
{
app.ApplicationServices.GetService<WebpackRunner>().Execute();
app.UseMiddleware<WebpackMiddleware>();
return app;

2
src/PinkParrot/Configurations/WriteModule.cs → src/PinkParrot/Configurations/Web/WriteModule.cs

@ -12,7 +12,7 @@ using PinkParrot.Pipeline.CommandHandlers;
using PinkParrot.Write.Apps;
using PinkParrot.Write.Schemas;
namespace PinkParrot.Configurations
namespace PinkParrot.Configurations.Web
{
public class WriteModule : Module
{

3
src/PinkParrot/Modules/Api/Apps/AppController.cs

@ -10,6 +10,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using PinkParrot.Infrastructure.CQRS.Commands;
using PinkParrot.Infrastructure.Reflection;
@ -20,6 +21,8 @@ using PinkParrot.Write.Apps.Commands;
namespace PinkParrot.Modules.Api.Apps
{
[Authorize]
[ApiExceptionFilter]
[DeactivateForAppDomain]
public class AppController : ControllerBase
{

3
src/PinkParrot/Modules/Api/Schemas/SchemasController.cs

@ -10,6 +10,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using PinkParrot.Infrastructure.CQRS.Commands;
using PinkParrot.Infrastructure.Reflection;
@ -21,7 +22,9 @@ using PinkParrot.Write.Schemas.Commands;
namespace PinkParrot.Modules.Api.Schemas
{
[Authorize]
[ApiExceptionFilter]
[DeactivateForAppDomain]
public class SchemasController : ControllerBase
{
private readonly ISchemaRepository schemaRepository;

142
src/PinkParrot/Modules/UI/Account/AccountController.cs

@ -0,0 +1,142 @@
// ==========================================================================
// AccountController.cs
// PinkParrot Headless CMS
// ==========================================================================
// Copyright (c) PinkParrot Group
// All rights reserved.
// ==========================================================================
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.MongoDB;
using Microsoft.AspNetCore.Mvc;
// ReSharper disable ConvertIfStatementToReturnStatement
namespace PinkParrot.Modules.UI.Account
{
public sealed class AccountController : Controller
{
private readonly SignInManager<IdentityUser> signInManager;
private readonly UserManager<IdentityUser> userManager;
public AccountController(SignInManager<IdentityUser> signInManager, UserManager<IdentityUser> userManager)
{
this.signInManager = signInManager;
this.userManager = userManager;
}
[Authorize]
[HttpGet]
[Route("account/forbidden")]
public IActionResult Forbidden()
{
return View();
}
[HttpGet]
[Route("account/client-silent/")]
public IActionResult ClientSilent()
{
return View();
}
[HttpGet]
[Route("account/client-popup/")]
public IActionResult ClientPopup()
{
return View();
}
[HttpGet]
[Route("account/login/")]
public IActionResult Login(string returnUrl = null)
{
var providers =
signInManager.GetExternalAuthenticationSchemes()
.Select(x => new ExternalProvider(x.AuthenticationScheme, x.DisplayName))
.ToList();
return View(new LoginVM { ExternalProviders = providers, ReturnUrl = returnUrl });
}
[HttpPost]
[Route("account/external/")]
public IActionResult External(string provider, string returnUrl = null)
{
var properties =
signInManager.ConfigureExternalAuthenticationProperties(provider,
Url.Action(nameof(Callback), new { ReturnUrl = returnUrl }));
return Challenge(properties, provider);
}
[HttpGet]
[Route("account/callback/")]
public async Task<IActionResult> Callback(string returnUrl = null, string remoteError = null)
{
var externalLogin = await signInManager.GetExternalLoginInfoAsync();
if (externalLogin == null)
{
return RedirectToAction(nameof(Login));
}
var isLoggedIn = await LoginAsync(externalLogin);
if (!isLoggedIn)
{
var user = CreateUser(externalLogin);
isLoggedIn =
await AddUserAsync(user) &&
await AddLoginAsync(user, externalLogin) &&
await LoginAsync(externalLogin);
}
if (!isLoggedIn)
{
return RedirectToAction(nameof(Login));
}
else if (!string.IsNullOrWhiteSpace(returnUrl))
{
return Redirect(returnUrl);
}
else
{
return Redirect("~/");
}
}
private async Task<bool> AddLoginAsync(IdentityUser user, UserLoginInfo externalLogin)
{
var result = await userManager.AddLoginAsync(user, externalLogin);
return result.Succeeded;
}
private async Task<bool> AddUserAsync(IdentityUser user)
{
var result = await userManager.CreateAsync(user);
return result.Succeeded;
}
private async Task<bool> LoginAsync(UserLoginInfo externalLogin)
{
var result = await signInManager.ExternalLoginSignInAsync(externalLogin.LoginProvider, externalLogin.ProviderKey, true);
return result.Succeeded;
}
private static IdentityUser CreateUser(ExternalLoginInfo externalLogin)
{
var mail = externalLogin.Principal.FindFirst(ClaimTypes.Email).Value;
return new IdentityUser { Email = mail, UserName = mail };
}
}
}

23
src/PinkParrot/Modules/UI/Account/ExternalProvider.cs

@ -0,0 +1,23 @@
// ==========================================================================
// ExternalProvider.cs
// PinkParrot Headless CMS
// ==========================================================================
// Copyright (c) PinkParrot Group
// All rights reserved.
// ==========================================================================
namespace PinkParrot.Modules.UI.Account
{
public class ExternalProvider
{
public string DisplayName { get; }
public string AuthenticationScheme { get; }
public ExternalProvider(string authenticationSchema, string displayName)
{
AuthenticationScheme = authenticationSchema;
DisplayName = displayName;
}
}
}

19
src/PinkParrot/Modules/UI/Account/LoginVM.cs

@ -0,0 +1,19 @@
// ==========================================================================
// LoginVM.cs
// PinkParrot Headless CMS
// ==========================================================================
// Copyright (c) PinkParrot Group
// All rights reserved.
// ==========================================================================
using System.Collections.Generic;
namespace PinkParrot.Modules.UI.Account
{
public class LoginVM
{
public string ReturnUrl { get; set; }
public IEnumerable<ExternalProvider> ExternalProviders { get; set; }
}
}

8
src/PinkParrot/Pipeline/WebpackMiddleware.cs

@ -6,6 +6,7 @@
// All rights reserved.
// ==========================================================================
using System;
using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
@ -42,7 +43,7 @@ namespace PinkParrot.Pipeline
buffer.Seek(0, SeekOrigin.Begin);
if (context.Response.StatusCode == 200 && IsHtml(context))
if (context.Response.StatusCode == 200 && IsIndex(context) && IsHtml(context))
{
using (var reader = new StreamReader(buffer))
{
@ -121,6 +122,11 @@ namespace PinkParrot.Pipeline
return response;
}
private static bool IsIndex(HttpContext context)
{
return context.Request.Path.Value.Equals("/index.html", StringComparison.OrdinalIgnoreCase);
}
private static bool IsHtml(HttpContext context)
{
return context.Response.ContentType?.ToLower().Contains("text/html") == true;

45
src/PinkParrot/Startup.cs

@ -12,11 +12,13 @@ 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.Configurations.Domain;
using PinkParrot.Configurations.EventStore;
using PinkParrot.Configurations.Identity;
using PinkParrot.Configurations.Web;
using PinkParrot.Store.MongoDb;
// ReSharper disable AccessToModifiedClosure
@ -27,8 +29,12 @@ namespace PinkParrot
{
public IConfigurationRoot Configuration { get; }
public IHostingEnvironment Environment { get; }
public Startup(IHostingEnvironment env)
{
Environment = env;
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", true, true)
@ -40,19 +46,23 @@ namespace PinkParrot
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services.AddEventFormatter();
services.AddIdentity<IdentityUser, IdentityRole>().AddDefaultTokenProviders();
services.AddMyEventFormatter();
services.AddMyIdentity();
services.AddMyIdentityServer(Environment);
services.AddMyMvc();
services.AddLogging();
services.AddMemoryCache();
services.AddMvc().AddAppSerializers();
services.AddOptions();
services.AddRouting();
services.AddWebpack();
services.AddWebpackBuilder();
services.Configure<MongoDbOptions>(
services.Configure<MyMongoDbOptions>(
Configuration.GetSection("stores:mongoDb"));
services.Configure<EventStoreOptions>(
services.Configure<MyEventStoreOptions>(
Configuration.GetSection("stores:eventStore"));
services.Configure<MyIdentityOptions>(
Configuration.GetSection("identity"));
var builder = new ContainerBuilder();
builder.RegisterModule<InfrastructureModule>();
@ -65,15 +75,15 @@ namespace PinkParrot
return new AutofacServiceProvider(builder.Build());
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole();
loggerFactory.AddDebug();
if (env.IsDevelopment())
if (Environment.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseWebpack();
app.UseWebpackProxy();
app.UseDefaultFiles();
}
else
@ -81,11 +91,16 @@ namespace PinkParrot
app.UseDefaultFiles(new DefaultFilesOptions { DefaultFileNames = new List<string> { "build/index.html" } });
}
app.UseApps();
app.UseMvc();
app.UseMyDefaultUser();
app.UseMyEventStore();
app.UseMyIdentity();
app.UseMyIdentityServer();
app.UseMyApiProtection();
app.UseMyGoogleAuthentication();
app.UseMyApps();
app.UseStaticFiles();
app.UseEventStore();
app.UseDefaultUser();
app.UseMvc();
}
}
}

12
src/PinkParrot/Views/Account/ClientPopup.cshtml

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html>
<body>
<script src='~/scripts/oidc-client.min.js'></script>
<script>
Oidc.Log.logger = console;
Oidc.Log.logLevel = Oidc.Log.INFO;
new Oidc.UserManager().signinPopupCallback();
</script>
</body>
</html>

12
src/PinkParrot/Views/Account/ClientSilent.cshtml

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html>
<body>
<script src='~/scripts/oidc-client.min.js'></script>
<script>
Oidc.Log.logger = console;
Oidc.Log.logLevel = Oidc.Log.INFO;
new Oidc.UserManager().signinSilentCallback();
</script>
</body>
</html>

15
src/PinkParrot/Views/Account/Login.cshtml

@ -0,0 +1,15 @@
@using System.Collections.Generic
@using Microsoft.AspNetCore.Http
@using Microsoft.AspNetCore.Http.Authentication
@model PinkParrot.Modules.UI.Account.LoginVM
<form asp-controller="Account" asp-action="External" asp-route-returnurl="@Model.ReturnUrl" method="post" class="form-horizontal">
<div>
<p>
@foreach (var provider in Model.ExternalProviders)
{
<button type="submit" class="btn btn-default" name="provider" value="@provider.AuthenticationScheme" title="Log in using your @provider.DisplayName account">@provider.AuthenticationScheme</button>
}
</p>
</div>
</form>

3
src/PinkParrot/Views/_ViewImports.cshtml

@ -0,0 +1,3 @@
@using Microsoft.AspNetCore.Identity
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

3
src/PinkParrot/Views/_ViewStart.cshtml

@ -0,0 +1,3 @@
@{
Layout = null;
}

4
src/PinkParrot/app/app.component.html

@ -1,3 +1 @@
<main>
<h1>Hello from Angular 2 App with Webpack!</h1>
</main>
<router-outlet></router-outlet>

38
src/PinkParrot/app/app.module.ts

@ -1,16 +1,48 @@
import * as Ng2 from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import * as Ng2Browser from '@angular/platform-browser';
import { AppComponent } from './app.component';
import {
ApiUrlConfig,
CurrencyConfig,
DragService,
DragServiceFactory,
DecimalSeparatorConfig,
} from './framework';
import {
AuthGuard,
AuthService,
} from './shared';
import {
MyAppModule,
MyLoginModule
} from './components';
import { routing } from './app.routes';
const baseUrl = window.location.protocol + '//' + window.location.host + '/';
@Ng2.NgModule({
imports: [
BrowserModule
Ng2Browser.BrowserModule,
MyAppModule,
MyLoginModule,
routing
],
declarations: [
AppComponent
],
providers: [
AuthGuard,
AuthService,
{ provide: ApiUrlConfig, useValue: new ApiUrlConfig(baseUrl) },
{ provide: CurrencyConfig, useValue: new CurrencyConfig('EUR', '€', true) },
{ provide: DecimalSeparatorConfig, useValue: new DecimalSeparatorConfig('.') },
{ provide: DragService, useFactory: DragServiceFactory }
],
bootstrap: [AppComponent]
})
export class AppModule { }

30
src/PinkParrot/app/app.routes.ts

@ -0,0 +1,30 @@
import * as Ng2 from '@angular/core';
import * as Ng2Router from '@angular/router';
import {
AppsComponent,
LoginComponent
} from './components';
import {
AuthGuard
} from './shared';
export const routes: Ng2Router.Routes = [
{
path: '',
redirectTo: 'apps',
pathMatch: 'full'
},
{
path: 'apps',
component: AppsComponent,
canActivate: [AuthGuard]
},
{
path: 'login',
component: LoginComponent
}
];
export const routing: Ng2.ModuleWithProviders = Ng2Router.RouterModule.forRoot(routes, { useHash: true });

3
src/PinkParrot/app/components/apps/apps.component.html

@ -0,0 +1,3 @@
<main>
<h1>Hello from Angular 2 App with Webpack!</h1>
</main>

16
src/PinkParrot/app/components/apps/apps.component.ts

@ -0,0 +1,16 @@
/*
*PinkParrot CMS
*
* @license
* Copyright (c) Sebastian Stehle. All rights reserved
*/
import * as Ng2 from '@angular/core';
@Ng2.Component({
selector: 'apps',
template
})
export class AppsComponent {
}

24
src/PinkParrot/app/components/apps/apps.module.ts

@ -0,0 +1,24 @@
/*
*PinkParrot CMS
*
* @license
* Copyright (c) Sebastian Stehle. All rights reserved
*/
import * as Ng2 from '@angular/core';
import { FrameworkModule } from './../../framework';
import {
AppsComponent
} from './declarations';
@Ng2.NgModule({
imports: [
FrameworkModule
],
declarations: [
AppsComponent
]
})
export class MyAppModule { }

8
src/PinkParrot/app/components/apps/declarations.ts

@ -0,0 +1,8 @@
/*
*PinkParrot CMS
*
* @license
* Copyright (c) Sebastian Stehle. All rights reserved
*/
export * from './apps.component';

9
src/PinkParrot/app/components/apps/index.ts

@ -0,0 +1,9 @@
/*
*PinkParrot CMS
*
* @license
* Copyright (c) Sebastian Stehle. All rights reserved
*/
export * from './apps.component';
export * from './apps.module';

9
src/PinkParrot/app/components/index.ts

@ -0,0 +1,9 @@
/*
*PinkParrot CMS
*
* @license
* Copyright (c) Sebastian Stehle. All rights reserved
*/
export * from './apps';
export * from './login';

8
src/PinkParrot/app/components/login/declarations.ts

@ -0,0 +1,8 @@
/*
*PinkParrot CMS
*
* @license
* Copyright (c) Sebastian Stehle. All rights reserved
*/
export * from './login.component';

9
src/PinkParrot/app/components/login/index.ts

@ -0,0 +1,9 @@
/*
*PinkParrot CMS
*
* @license
* Copyright (c) Sebastian Stehle. All rights reserved
*/
export * from './login.component';
export * from './login.module';

3
src/PinkParrot/app/components/login/login.component.html

@ -0,0 +1,3 @@
<div>
Logging in
</div>

36
src/PinkParrot/app/components/login/login.component.ts

@ -0,0 +1,36 @@
/*
*PinkParrot CMS
*
* @license
* Copyright (c) Sebastian Stehle. All rights reserved
*/
import * as Ng2 from '@angular/core';
import * as Ng2Common from '@angular/common';
import { AuthService } from './../../shared';
@Ng2.Component({
selector: 'login',
template
})
export class LoginComponent implements Ng2.OnInit {
public showFailedError = false;
constructor(
private readonly authService: AuthService,
private readonly location: Ng2Common.Location
) {
}
public ngOnInit() {
this.authService.login().subscribe(
() => {
this.location.back();
},
() => {
this.showFailedError = true;
}
);
}
}

24
src/PinkParrot/app/components/login/login.module.ts

@ -0,0 +1,24 @@
/*
*PinkParrot CMS
*
* @license
* Copyright (c) Sebastian Stehle. All rights reserved
*/
import * as Ng2 from '@angular/core';
import { FrameworkModule } from './../../framework';
import {
LoginComponent
} from './declarations';
@Ng2.NgModule({
imports: [
FrameworkModule
],
declarations: [
LoginComponent
]
})
export class MyLoginModule { }

6
src/PinkParrot/app/core/angular/action.spec.ts → src/PinkParrot/app/framework/angular/action.spec.ts

@ -1,5 +1,5 @@
/*
* Athene Requirements Center
*PinkParrot CMS
*
* @license
* Copyright (c) Sebastian Stehle. All rights reserved
@ -10,8 +10,6 @@ import { Subject } from 'rxjs';
import { Action } from './../';
class MockupObject {
constructor(private readonly store: any) { }
public isDestroyCalled = false;
@Action()
@ -20,6 +18,8 @@ class MockupObject {
@Action()
public event2 = new Subject<string>().map(x => { return { type: 'MOCK_ACTION' }; });
constructor(private readonly store: any) { }
public init() {
this.event2 = new Subject<string>().map(x => { return { type: 'MOCK_ACTION' }; });
}

2
src/PinkParrot/app/core/angular/action.ts → src/PinkParrot/app/framework/angular/action.ts

@ -1,5 +1,5 @@
/*
* Athene Requirements Center
*PinkParrot CMS
*
* @license
* Copyright (c) Sebastian Stehle. All rights reserved

2
src/PinkParrot/app/core/angular/cloak.directive.spec.ts → src/PinkParrot/app/framework/angular/cloak.directive.spec.ts

@ -1,5 +1,5 @@
/*
* Athene Requirements Center
*PinkParrot CMS
*
* @license
* Copyright (c) Sebastian Stehle. All rights reserved

2
src/PinkParrot/app/core/angular/cloak.directive.ts → src/PinkParrot/app/framework/angular/cloak.directive.ts

@ -1,5 +1,5 @@
/*
* Athene Requirements Center
*PinkParrot CMS
*
* @license
* Copyright (c) Sebastian Stehle. All rights reserved

0
src/PinkParrot/app/core/angular/color-picker.component.html → src/PinkParrot/app/framework/angular/color-picker.component.html

0
src/PinkParrot/app/core/angular/color-picker.component.scss → src/PinkParrot/app/framework/angular/color-picker.component.scss

3
src/PinkParrot/app/core/angular/color-picker.component.spec.ts → src/PinkParrot/app/framework/angular/color-picker.component.spec.ts

@ -1,12 +1,11 @@
/*
* Athene Requirements Center
*PinkParrot CMS
*
* @license
* Copyright (c) Sebastian Stehle. All rights reserved
*/
import { Color } from './../';
import { ColorPickerComponent } from './color-picker.component';
describe('ColorPickerComponent', () => {

11
src/PinkParrot/app/core/angular/color-picker.component.ts → src/PinkParrot/app/framework/angular/color-picker.component.ts

@ -1,5 +1,5 @@
/*
* Athene Requirements Center
*PinkParrot CMS
*
* @license
* Copyright (c) Sebastian Stehle. All rights reserved
@ -7,8 +7,13 @@
import * as Ng2 from '@angular/core';
import { Color } from './../utils/color';
import { ColorPalette } from './../utils/color-palette';
import {
Color }
from './../utils/color';
import {
ColorPalette
} from './../utils/color-palette';
@Ng2.Component({
selector: 'gp-color-picker',

2
src/PinkParrot/app/core/angular/date-time.pipes.spec.ts → src/PinkParrot/app/framework/angular/date-time.pipes.spec.ts

@ -1,5 +1,5 @@
/*
* Athene Requirements Center
*PinkParrot CMS
*
* @license
* Copyright (c) Sebastian Stehle. All rights reserved

2
src/PinkParrot/app/core/angular/date-time.pipes.ts → src/PinkParrot/app/framework/angular/date-time.pipes.ts

@ -1,5 +1,5 @@
/*
* Athene Requirements Center
*PinkParrot CMS
*
* @license
* Copyright (c) Sebastian Stehle. All rights reserved

5
src/PinkParrot/app/core/angular/drag-model.directive.ts → src/PinkParrot/app/framework/angular/drag-model.directive.ts

@ -1,5 +1,5 @@
/*
* Athene Requirements Center
*PinkParrot CMS
*
* @license
* Copyright (c) Sebastian Stehle. All rights reserved
@ -7,7 +7,8 @@
import * as Ng2 from '@angular/core';
import { DragService, Vec2 } from './../';
import { DragService } from './../services/drag.service';
import { Vec2 } from './../utils/vec2';
@Ng2.Directive({
selector: '[gpDragModel]'

2
src/PinkParrot/app/core/angular/focus-on-change.directive.spec.ts → src/PinkParrot/app/framework/angular/focus-on-change.directive.spec.ts

@ -1,5 +1,5 @@
/*
* Athene Requirements Center
*PinkParrot CMS
*
* @license
* Copyright (c) Sebastian Stehle. All rights reserved

2
src/PinkParrot/app/core/angular/focus-on-change.directive.ts → src/PinkParrot/app/framework/angular/focus-on-change.directive.ts

@ -1,5 +1,5 @@
/*
* Athene Requirements Center
*PinkParrot CMS
*
* @license
* Copyright (c) Sebastian Stehle. All rights reserved

5
src/PinkParrot/app/core/angular/image-drop.directive.ts → src/PinkParrot/app/framework/angular/image-drop.directive.ts

@ -1,5 +1,5 @@
/*
* Athene Requirements Center
*PinkParrot CMS
*
* @license
* Copyright (c) Sebastian Stehle. All rights reserved
@ -7,7 +7,8 @@
import * as Ng2 from '@angular/core';
import { DragService, Vec2 } from './../';
import { DragService } from './../services/drag.service';
import { Vec2 } from './../utils/vec2';
@Ng2.Directive({
selector: '.gp-image-drop'

2
src/PinkParrot/app/core/angular/money.pipe.spec.ts → src/PinkParrot/app/framework/angular/money.pipe.spec.ts

@ -1,5 +1,5 @@
/*
* Athene Requirements Center
*PinkParrot CMS
*
* @license
* Copyright (c) Sebastian Stehle. All rights reserved

2
src/PinkParrot/app/core/angular/money.pipe.ts → src/PinkParrot/app/framework/angular/money.pipe.ts

@ -1,5 +1,5 @@
/*
* Athene Requirements Center
*PinkParrot CMS
*
* @license
* Copyright (c) Sebastian Stehle. All rights reserved

6
src/PinkParrot/app/core/angular/shortcut.component.spec.ts → src/PinkParrot/app/framework/angular/shortcut.component.spec.ts

@ -1,5 +1,5 @@
/*
* Athene Requirements Center
*PinkParrot CMS
*
* @license
* Copyright (c) Sebastian Stehle. All rights reserved
@ -7,8 +7,8 @@
import * as Ng2 from '@angular/core';
import { ShortcutService } from './../';
import { ShortcutComponent } from './shortcut.component';
import { ShortcutService } from './../';
import { ShortcutComponent } from './shortcut.component';
describe('ShortcutComponent', () => {
let shortcutService: ShortcutService;

2
src/PinkParrot/app/core/angular/shortcut.component.ts → src/PinkParrot/app/framework/angular/shortcut.component.ts

@ -1,5 +1,5 @@
/*
* Athene Requirements Center
*PinkParrot CMS
*
* @license
* Copyright (c) Sebastian Stehle. All rights reserved

0
src/PinkParrot/app/core/angular/slider.component.html → src/PinkParrot/app/framework/angular/slider.component.html

0
src/PinkParrot/app/core/angular/slider.component.scss → src/PinkParrot/app/framework/angular/slider.component.scss

2
src/PinkParrot/app/core/angular/slider.component.ts → src/PinkParrot/app/framework/angular/slider.component.ts

@ -1,5 +1,5 @@
/*
* Athene Requirements Center
*PinkParrot CMS
*
* @license
* Copyright (c) Sebastian Stehle. All rights reserved

2
src/PinkParrot/app/core/angular/spinner.component.ts → src/PinkParrot/app/framework/angular/spinner.component.ts

@ -1,5 +1,5 @@
/*
* Athene Requirements Center
*PinkParrot CMS
*
* @license
* Copyright (c) Sebastian Stehle. All rights reserved

2
src/PinkParrot/app/core/angular/user-report.component.ts → src/PinkParrot/app/framework/angular/user-report.component.ts

@ -1,5 +1,5 @@
/*
* Athene Requirements Center
*PinkParrot CMS
*
* @license
* Copyright (c) Sebastian Stehle. All rights reserved

2
src/PinkParrot/app/core/angular/validators.spec.ts → src/PinkParrot/app/framework/angular/validators.spec.ts

@ -1,5 +1,5 @@
/*
* Athene Requirements Center
*PinkParrot CMS
*
* @license
* Copyright (c) Sebastian Stehle. All rights reserved

2
src/PinkParrot/app/core/angular/validators.ts → src/PinkParrot/app/framework/angular/validators.ts

@ -1,5 +1,5 @@
/*
* Athene Requirements Center
*PinkParrot CMS
*
* @license
* Copyright (c) Sebastian Stehle. All rights reserved

27
src/PinkParrot/app/core/configurations.ts → src/PinkParrot/app/framework/configurations.ts

@ -1,26 +1,49 @@
/*
* Athene Requirements Center
*PinkParrot CMS
*
* @license
* Copyright (c) Sebastian Stehle. All rights reserved
*/
import * as Ng2 from '@angular/core';
@Ng2.Injectable()
export class ApiUrlConfig {
constructor(public readonly value: string) { }
public readonly value: string;
constructor(value: string) {
if (value.indexOf('/', value.length - 1) < 0) {
value = value + '/';
}
this.value = value;
}
public buildUrl(path: string) {
if (path.indexOf('/') === 0) {
path = path.substr(1);
}
return this.value + path;
}
}
@Ng2.Injectable()
export class DecimalSeparatorConfig {
constructor(public readonly value: string) { }
}
@Ng2.Injectable()
export class ProductionModeConfig {
constructor(public readonly isProductionMode: boolean) { }
}
@Ng2.Injectable()
export class UserReportConfig {
constructor(public readonly siteId: string) { }
}
@Ng2.Injectable()
export class CurrencyConfig {
constructor(
public readonly code: string,

13
src/PinkParrot/app/framework/declarations.ts

@ -0,0 +1,13 @@
export * from './angular/cloak.directive';
export * from './angular/color-picker.component';
export * from './angular/date-time.pipes';
export * from './angular/drag-model.directive';
export * from './angular/focus-on-change.directive';
export * from './angular/image-drop.directive';
export * from './angular/money.pipe';
export * from './angular/shortcut.component';
export * from './angular/slider.component';
export * from './angular/spinner.component';
export * from './angular/user-report.component';
export * from './services/drag.service';
export * from './services/title.service';

70
src/PinkParrot/app/framework/framework.module.ts

@ -0,0 +1,70 @@
import * as Ng2 from '@angular/core';
import * as Ng2Http from '@angular/http';
import * as Ng2Forms from '@angular/forms';
import * as Ng2Common from '@angular/common';
import * as Ng2Router from '@angular/router';
import {
CloakDirective,
ColorPickerComponent,
DayOfWeekPipe,
DayPipe,
DragModelDirective,
DurationPipe,
FocusOnChangeDirective,
ImageDropDirective,
MoneyPipe,
MonthPipe,
ShortcutComponent,
ShortDatePipe,
ShortTimePipe,
SliderComponent,
SpinnerComponent,
UserReportComponent
} from './declarations';
@Ng2.NgModule({
imports: [
Ng2Forms.FormsModule,
Ng2Common.CommonModule
],
declarations: [
CloakDirective,
ColorPickerComponent,
DayOfWeekPipe,
DayPipe,
DragModelDirective,
DurationPipe,
FocusOnChangeDirective,
ImageDropDirective,
MoneyPipe,
MonthPipe,
ShortcutComponent,
ShortDatePipe,
ShortTimePipe,
SliderComponent,
SpinnerComponent,
UserReportComponent
],
exports: [
CloakDirective,
ColorPickerComponent,
DayOfWeekPipe,
DayPipe,
DurationPipe,
FocusOnChangeDirective,
MoneyPipe,
MonthPipe,
ShortcutComponent,
ShortDatePipe,
ShortTimePipe,
SliderComponent,
SpinnerComponent,
UserReportComponent,
Ng2Http.HttpModule,
Ng2Forms.FormsModule,
Ng2Common.CommonModule,
Ng2Router.RouterModule
]
})
export class FrameworkModule { }

3
src/PinkParrot/app/core/index.ts → src/PinkParrot/app/framework/index.ts

@ -1,5 +1,5 @@
/*
* Athene Requirements Center
*PinkParrot CMS
*
* @license
* Copyright (c) Sebastian Stehle. All rights reserved
@ -8,6 +8,7 @@
export * from './angular/action';
export * from './angular/validators';
export * from './configurations';
export * from './framework.module';
export * from './plattform';
export * from './services/clipboard.service';
export * from './services/drag.service';

2
src/PinkParrot/app/core/plattform.ts → src/PinkParrot/app/framework/plattform.ts

@ -1,5 +1,5 @@
/*
* Athene Requirements Center
*PinkParrot CMS
*
* @license
* Copyright (c) Sebastian Stehle. All rights reserved

2
src/PinkParrot/app/core/services/clipboard.service.spec.ts → src/PinkParrot/app/framework/services/clipboard.service.spec.ts

@ -1,5 +1,5 @@
/*
* Athene Requirements Center
*PinkParrot CMS
*
* @license
* Copyright (c) Sebastian Stehle. All rights reserved

5
src/PinkParrot/app/core/services/clipboard.service.ts → src/PinkParrot/app/framework/services/clipboard.service.ts

@ -1,16 +1,19 @@
/*
* Athene Requirements Center
*PinkParrot CMS
*
* @license
* Copyright (c) Sebastian Stehle. All rights reserved
*/
import * as Ng2 from '@angular/core';
import { BehaviorSubject, Observable } from 'rxjs';
export const ClipboardServiceFactory = () => {
return new ClipboardService();
};
@Ng2.Injectable()
export class ClipboardService {
private textInstance = new BehaviorSubject<string>('');

2
src/PinkParrot/app/core/services/drag.service.spec.ts → src/PinkParrot/app/framework/services/drag.service.spec.ts

@ -1,5 +1,5 @@
/*
* Athene Requirements Center
*PinkParrot CMS
*
* @license
* Copyright (c) Sebastian Stehle. All rights reserved

5
src/PinkParrot/app/core/services/drag.service.ts → src/PinkParrot/app/framework/services/drag.service.ts

@ -1,10 +1,12 @@
/*
* Athene Requirements Center
*PinkParrot CMS
*
* @license
* Copyright (c) Sebastian Stehle. All rights reserved
*/
import * as Ng2 from '@angular/core';
import { Subject, Observable } from 'rxjs';
import { Vec2 } from './../utils/vec2';
@ -15,6 +17,7 @@ export const DragServiceFactory = () => {
return new DragService();
};
@Ng2.Injectable()
export class DragService {
private readonly dropEvent = new Subject<DropEvent>();

2
src/PinkParrot/app/core/services/local-store.service.spec.ts → src/PinkParrot/app/framework/services/local-store.service.spec.ts

@ -1,5 +1,5 @@
/*
* Athene Requirements Center
*PinkParrot CMS
*
* @license
* Copyright (c) Sebastian Stehle. All rights reserved

5
src/PinkParrot/app/core/services/local-store.service.ts → src/PinkParrot/app/framework/services/local-store.service.ts

@ -1,14 +1,17 @@
/*
* Athene Requirements Center
*PinkParrot CMS
*
* @license
* Copyright (c) Sebastian Stehle. All rights reserved
*/
import * as Ng2 from '@angular/core';
export const LocalStoreServiceFactory = () => {
return new LocalStoreService();
};
@Ng2.Injectable()
export class LocalStoreService {
private store: any = localStorage;

2
src/PinkParrot/app/core/services/shortcut.service.spec.ts → src/PinkParrot/app/framework/services/shortcut.service.spec.ts

@ -1,5 +1,5 @@
/*
* Athene Requirements Center
*PinkParrot CMS
*
* @license
* Copyright (c) Sebastian Stehle. All rights reserved

5
src/PinkParrot/app/core/services/shortcut.service.ts → src/PinkParrot/app/framework/services/shortcut.service.ts

@ -1,14 +1,17 @@
/*
* Athene Requirements Center
*PinkParrot CMS
*
* @license
* Copyright (c) Sebastian Stehle. All rights reserved
*/
import * as Ng2 from '@angular/core';
export const ShortcutServiceFactory = () => {
return new ShortcutService();
};
@Ng2.Injectable()
export class ShortcutService {
public on(keys: string, callback: (e: KeyboardEvent, combo: string) => void) {
return Mousetrap.bind(keys, (event, combo) => {

2
src/PinkParrot/app/core/services/title.service.spec.ts → src/PinkParrot/app/framework/services/title.service.spec.ts

@ -1,5 +1,5 @@
/*
* Athene Requirements Center
*PinkParrot CMS
*
* @license
* Copyright (c) Sebastian Stehle. All rights reserved

5
src/PinkParrot/app/core/services/title.service.ts → src/PinkParrot/app/framework/services/title.service.ts

@ -1,10 +1,12 @@
/*
* Athene Requirements Center
*PinkParrot CMS
*
* @license
* Copyright (c) Sebastian Stehle. All rights reserved
*/
import * as Ng2 from '@angular/core';
export class TitlesConfig {
constructor(public readonly value: { [key: string]: string }) { }
}
@ -13,6 +15,7 @@ export const TitleServiceFactory = (titles: TitlesConfig) => {
return new TitleService(titles);
};
@Ng2.Injectable()
export class TitleService {
constructor(private readonly titles: TitlesConfig) { }

2
src/PinkParrot/app/core/utils/color-palette.spec.ts → src/PinkParrot/app/framework/utils/color-palette.spec.ts

@ -1,5 +1,5 @@
/*
* Athene Requirements Center
*PinkParrot CMS
*
* @license
* Copyright (c) Sebastian Stehle. All rights reserved

2
src/PinkParrot/app/core/utils/color-palette.ts → src/PinkParrot/app/framework/utils/color-palette.ts

@ -1,5 +1,5 @@
/*
* Athene Requirements Center
*PinkParrot CMS
*
* @license
* Copyright (c) Sebastian Stehle. All rights reserved

2
src/PinkParrot/app/core/utils/color.spec.ts → src/PinkParrot/app/framework/utils/color.spec.ts

@ -1,5 +1,5 @@
/*
* Athene Requirements Center
*PinkParrot CMS
*
* @license
* Copyright (c) Sebastian Stehle. All rights reserved

2
src/PinkParrot/app/core/utils/color.ts → src/PinkParrot/app/framework/utils/color.ts

@ -1,5 +1,5 @@
/*
* Athene Requirements Center
*PinkParrot CMS
*
* @license
* Copyright (c) Sebastian Stehle. All rights reserved

2
src/PinkParrot/app/core/utils/date-helper.spec.ts → src/PinkParrot/app/framework/utils/date-helper.spec.ts

@ -1,5 +1,5 @@
/*
* Athene Requirements Center
*PinkParrot CMS
*
* @license
* Copyright (c) Sebastian Stehle. All rights reserved

2
src/PinkParrot/app/core/utils/date-helper.ts → src/PinkParrot/app/framework/utils/date-helper.ts

@ -1,5 +1,5 @@
/*
* Athene Requirements Center
*PinkParrot CMS
*
* @license
* Copyright (c) Sebastian Stehle. All rights reserved

2
src/PinkParrot/app/core/utils/date-time.spec.ts → src/PinkParrot/app/framework/utils/date-time.spec.ts

@ -1,5 +1,5 @@
/*
* Athene Requirements Center
*PinkParrot CMS
*
* @license
* Copyright (c) Sebastian Stehle. All rights reserved

2
src/PinkParrot/app/core/utils/date-time.ts → src/PinkParrot/app/framework/utils/date-time.ts

@ -1,5 +1,5 @@
/*
* Athene Requirements Center
*PinkParrot CMS
*
* @license
* Copyright (c) Sebastian Stehle. All rights reserved

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save