diff --git a/config/config.js b/cfg/config.js similarity index 100% rename from config/config.js rename to cfg/config.js diff --git a/src/PinkParrot.Store.MongoDb/Apps/MongoAppRepository.cs b/src/PinkParrot.Store.MongoDb/Apps/MongoAppRepository.cs index 94158088e..316de284b 100644 --- a/src/PinkParrot.Store.MongoDb/Apps/MongoAppRepository.cs +++ b/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 collection) { return collection.Indexes.CreateOneAsync(IndexKeys.Ascending(x => x.Name)); diff --git a/src/PinkParrot.Store.MongoDb/Infrastructure/MongoPersistedGrantStore.cs b/src/PinkParrot.Store.MongoDb/Infrastructure/MongoPersistedGrantStore.cs new file mode 100644 index 000000000..5ce4f2a9a --- /dev/null +++ b/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, IPersistedGrantStore + { + static MongoPersistedGrantStore() + { + BsonClassMap.RegisterClassMap(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 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> GetAllAsync(string subjectId) + { + return Collection.Find(x => x.SubjectId == subjectId).ToListAsync().ContinueWith(x => (IEnumerable)x.Result); + } + + public Task 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); + } + } +} diff --git a/src/PinkParrot.Store.MongoDb/Infrastructure/MongoPositionEntity.cs b/src/PinkParrot.Store.MongoDb/Infrastructure/MongoStreamPositionEntity.cs similarity index 89% rename from src/PinkParrot.Store.MongoDb/Infrastructure/MongoPositionEntity.cs rename to src/PinkParrot.Store.MongoDb/Infrastructure/MongoStreamPositionEntity.cs index 8d58c798d..9f5165ffa 100644 --- a/src/PinkParrot.Store.MongoDb/Infrastructure/MongoPositionEntity.cs +++ b/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; } diff --git a/src/PinkParrot.Store.MongoDb/Infrastructure/MongoPositionStorage.cs b/src/PinkParrot.Store.MongoDb/Infrastructure/MongoStreamPositionStorage.cs similarity index 75% rename from src/PinkParrot.Store.MongoDb/Infrastructure/MongoPositionStorage.cs rename to src/PinkParrot.Store.MongoDb/Infrastructure/MongoStreamPositionStorage.cs index 9571f132a..549758444 100644 --- a/src/PinkParrot.Store.MongoDb/Infrastructure/MongoPositionStorage.cs +++ b/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, IStreamPositionStorage + public sealed class MongoStreamPositionStorage : MongoRepositoryBase, 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); } diff --git a/src/PinkParrot.Store.MongoDb/MongoDbModule.cs b/src/PinkParrot.Store.MongoDb/MongoDbModule.cs index b61b8c9bd..2e2201525 100644 --- a/src/PinkParrot.Store.MongoDb/MongoDbModule.cs +++ b/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>().Value; + var options = context.Resolve>().Value; var mongoDbClient = new MongoClient(options.ConnectionString); var mongoDatabase = mongoDbClient.GetDatabase(options.DatabaseName); @@ -54,7 +55,11 @@ namespace PinkParrot.Store.MongoDb return new RoleStore(rolesCollection); }).SingleInstance(); - builder.RegisterType() + builder.RegisterType() + .As() + .SingleInstance(); + + builder.RegisterType() .As() .SingleInstance(); diff --git a/src/PinkParrot.Store.MongoDb/MongoDbOptions.cs b/src/PinkParrot.Store.MongoDb/MyMongoDbOptions.cs similarity index 89% rename from src/PinkParrot.Store.MongoDb/MongoDbOptions.cs rename to src/PinkParrot.Store.MongoDb/MyMongoDbOptions.cs index 56ccbba5f..f4bb4ddd8 100644 --- a/src/PinkParrot.Store.MongoDb/MongoDbOptions.cs +++ b/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; } diff --git a/src/PinkParrot.Store.MongoDb/Schemas/MongoSchemaRepository.cs b/src/PinkParrot.Store.MongoDb/Schemas/MongoSchemaRepository.cs index c834d6ca0..58e102236 100644 --- a/src/PinkParrot.Store.MongoDb/Schemas/MongoSchemaRepository.cs +++ b/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 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 updater) + { + return Collection.UpdateAsync(headers, e => UpdateSchema(e, updater)); + } + private void UpdateSchema(MongoSchemaEntity entity, Func updater) { var currentSchema = Deserialize(entity); @@ -149,11 +159,6 @@ namespace PinkParrot.Store.MongoDb.Schemas Serialize(entity, currentSchema); } - private Task UpdateSchema(EnvelopeHeaders headers, Func updater) - { - return Collection.UpdateAsync(headers, e=> UpdateSchema(e, updater)); - } - private void Serialize(MongoSchemaEntity entity, Schema schema) { var dto = SchemaDto.Create(schema); diff --git a/src/PinkParrot.Store.MongoDb/project.json b/src/PinkParrot.Store.MongoDb/project.json index 58b38c279..6e8989f5f 100644 --- a/src/PinkParrot.Store.MongoDb/project.json +++ b/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", diff --git a/src/PinkParrot/.vscode/settings.json b/src/PinkParrot/.vscode/settings.json new file mode 100644 index 000000000..925e0e312 --- /dev/null +++ b/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 + } +} \ No newline at end of file diff --git a/src/PinkParrot/Configurations/InfrastructureModule.cs b/src/PinkParrot/Configurations/Domain/InfrastructureModule.cs similarity index 94% rename from src/PinkParrot/Configurations/InfrastructureModule.cs rename to src/PinkParrot/Configurations/Domain/InfrastructureModule.cs index b403492aa..a028ca42b 100644 --- a/src/PinkParrot/Configurations/InfrastructureModule.cs +++ b/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() .SingleInstance(); - builder.RegisterType() + builder.RegisterType() .As() .SingleInstance(); diff --git a/src/PinkParrot/Configurations/InfrastructureUsage.cs b/src/PinkParrot/Configurations/Domain/InfrastructureUsage.cs similarity index 78% rename from src/PinkParrot/Configurations/InfrastructureUsage.cs rename to src/PinkParrot/Configurations/Domain/InfrastructureUsage.cs index e306458dc..ed043b63f 100644 --- a/src/PinkParrot/Configurations/InfrastructureUsage.cs +++ b/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(); + + return app; } } } diff --git a/src/PinkParrot/Configurations/ReadModule.cs b/src/PinkParrot/Configurations/Domain/ReadModule.cs similarity index 96% rename from src/PinkParrot/Configurations/ReadModule.cs rename to src/PinkParrot/Configurations/Domain/ReadModule.cs index 8367128f5..e8d177cdd 100644 --- a/src/PinkParrot/Configurations/ReadModule.cs +++ b/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 { diff --git a/src/PinkParrot/Configurations/Serializers.cs b/src/PinkParrot/Configurations/Domain/Serializers.cs similarity index 89% rename from src/PinkParrot/Configurations/Serializers.cs rename to src/PinkParrot/Configurations/Domain/Serializers.cs index 241e011fa..2d1f713d0 100644 --- a/src/PinkParrot/Configurations/Serializers.cs +++ b/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())); services.AddSingleton(); + + return services; } - public static void AddAppSerializers(this IMvcBuilder mvc) + public static IMvcBuilder AddMySerializers(this IMvcBuilder mvc) { mvc.AddJsonOptions(options => { ConfigureJson(options.SerializerSettings); }); + + return mvc; } } } diff --git a/src/PinkParrot/Configurations/EventStoreModule.cs b/src/PinkParrot/Configurations/EventStore/EventStoreModule.cs similarity index 85% rename from src/PinkParrot/Configurations/EventStoreModule.cs rename to src/PinkParrot/Configurations/EventStore/EventStoreModule.cs index 871008e55..9ef0d8186 100644 --- a/src/PinkParrot/Configurations/EventStoreModule.cs +++ b/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>().Value; + var options = context.Resolve>().Value; var eventStore = EventStoreConnection.Create( @@ -39,14 +39,14 @@ namespace PinkParrot.Configurations builder.Register(context => { - var options = context.Resolve>().Value; + var options = context.Resolve>().Value; return new UserCredentials(options.Username, options.Password); }).SingleInstance(); builder.Register(context => { - var options = context.Resolve>().Value; + var options = context.Resolve>().Value; return new DefaultNameResolver(options.Prefix); }).SingleInstance(); diff --git a/src/PinkParrot/Configurations/EventStoreUsage.cs b/src/PinkParrot/Configurations/EventStore/EventStoreUsage.cs similarity index 71% rename from src/PinkParrot/Configurations/EventStoreUsage.cs rename to src/PinkParrot/Configurations/EventStore/EventStoreUsage.cs index 21123e84a..d5848366e 100644 --- a/src/PinkParrot/Configurations/EventStoreUsage.cs +++ b/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>().Value; + var options = app.ApplicationServices.GetRequiredService>().Value; app.ApplicationServices.GetService().Subscribe(options.Prefix); + + return app; } } } diff --git a/src/PinkParrot/Configurations/EventStoreOptions.cs b/src/PinkParrot/Configurations/EventStore/MyEventStoreOptions.cs similarity index 82% rename from src/PinkParrot/Configurations/EventStoreOptions.cs rename to src/PinkParrot/Configurations/EventStore/MyEventStoreOptions.cs index 96b119484..0d2ac4a11 100644 --- a/src/PinkParrot/Configurations/EventStoreOptions.cs +++ b/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; } diff --git a/src/PinkParrot/Configurations/Identity/Cert/IdentityCert.snk b/src/PinkParrot/Configurations/Identity/Cert/IdentityCert.snk new file mode 100644 index 000000000..252e41c3d Binary files /dev/null and b/src/PinkParrot/Configurations/Identity/Cert/IdentityCert.snk differ diff --git a/src/PinkParrot/Configurations/Identity/IdentityServices.cs b/src/PinkParrot/Configurations/Identity/IdentityServices.cs new file mode 100644 index 000000000..d40e1513d --- /dev/null +++ b/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(); + + return services; + } + + public static IServiceCollection AddMyIdentity(this IServiceCollection services) + { + services.AddIdentity() + .AddDefaultTokenProviders(); + + return services; + } + + public static IEnumerable GetScopes() + { + return new List + { + StandardScopes.OpenId, + StandardScopes.Profile, + + new Scope + { + Name = "api1", + Description = "My API" + } + }; + } + + public static IEnumerable GetClients() + { + return new List + { + new Client + { + ClientId = "management-portal", + ClientName = "MVC Client", + RedirectUris = new List + { + "http://localhost:5000/account/client-silent", + "http://localhost:5000/account/client-popup" + }, + AllowedGrantTypes = GrantTypes.Implicit, + AllowedScopes = new List + { + StandardScopes.OpenId.Name, + StandardScopes.Profile.Name + }, + RequireConsent = false + } + }; + } + } +} diff --git a/src/PinkParrot/Configurations/Identity/IdentityUsage.cs b/src/PinkParrot/Configurations/Identity/IdentityUsage.cs new file mode 100644 index 000000000..e3229ba22 --- /dev/null +++ b/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>().Value; + + var username = options.DefaultUsername; + var userManager = app.ApplicationServices.GetService>(); + + 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>().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>().Value; + + if (!string.IsNullOrWhiteSpace(options.BaseUrl)) + { + app.Map("/api", api => + { + api.UseIdentityServerAuthentication(new IdentityServerAuthenticationOptions + { + Authority = options.BaseUrl, + ScopeName = "api", + RequireHttpsMetadata = options.RequiresHttps + }); + }); + } + + return app; + } + } +} diff --git a/src/PinkParrot/Configurations/IdentityOptions.cs b/src/PinkParrot/Configurations/Identity/MyIdentityOptions.cs similarity index 59% rename from src/PinkParrot/Configurations/IdentityOptions.cs rename to src/PinkParrot/Configurations/Identity/MyIdentityOptions.cs index 45a2a2e22..21e238a2d 100644 --- a/src/PinkParrot/Configurations/IdentityOptions.cs +++ b/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; } } } diff --git a/src/PinkParrot/Configurations/IdentityUsage.cs b/src/PinkParrot/Configurations/IdentityUsage.cs deleted file mode 100644 index 229f47d7c..000000000 --- a/src/PinkParrot/Configurations/IdentityUsage.cs +++ /dev/null @@ -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>().Value; - - var username = options.DefaultUsername; - var userManager = app.ApplicationServices.GetService>(); - - 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(); - } - } - } -} diff --git a/src/PinkParrot/Configurations/Web/WebDependencies.cs b/src/PinkParrot/Configurations/Web/WebDependencies.cs new file mode 100644 index 000000000..b3b59d0d5 --- /dev/null +++ b/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(); + } + } +} diff --git a/src/PinkParrot/Configurations/Web/WebpackServices.cs b/src/PinkParrot/Configurations/Web/WebpackServices.cs new file mode 100644 index 000000000..3c045e884 --- /dev/null +++ b/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(); + + return services; + } + } +} diff --git a/src/PinkParrot/Configurations/WebpackUsage.cs b/src/PinkParrot/Configurations/Web/WebpackUsage.cs similarity index 63% rename from src/PinkParrot/Configurations/WebpackUsage.cs rename to src/PinkParrot/Configurations/Web/WebpackUsage.cs index eb71dd50b..d9431f290 100644 --- a/src/PinkParrot/Configurations/WebpackUsage.cs +++ b/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(); + app.ApplicationServices.GetRequiredService().Execute(); - return services; + return app; } - public static IApplicationBuilder UseWebpack(this IApplicationBuilder app) + public static IApplicationBuilder UseWebpackProxy(this IApplicationBuilder app) { - app.ApplicationServices.GetService().Execute(); - app.UseMiddleware(); return app; diff --git a/src/PinkParrot/Configurations/WriteModule.cs b/src/PinkParrot/Configurations/Web/WriteModule.cs similarity index 97% rename from src/PinkParrot/Configurations/WriteModule.cs rename to src/PinkParrot/Configurations/Web/WriteModule.cs index af2669baf..650081d93 100644 --- a/src/PinkParrot/Configurations/WriteModule.cs +++ b/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 { diff --git a/src/PinkParrot/Modules/Api/Apps/AppController.cs b/src/PinkParrot/Modules/Api/Apps/AppController.cs index 43b46b1a4..c706a8daf 100644 --- a/src/PinkParrot/Modules/Api/Apps/AppController.cs +++ b/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 { diff --git a/src/PinkParrot/Modules/Api/Schemas/SchemasController.cs b/src/PinkParrot/Modules/Api/Schemas/SchemasController.cs index f2b6d2159..a8ae9b035 100644 --- a/src/PinkParrot/Modules/Api/Schemas/SchemasController.cs +++ b/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; diff --git a/src/PinkParrot/Modules/UI/Account/AccountController.cs b/src/PinkParrot/Modules/UI/Account/AccountController.cs new file mode 100644 index 000000000..0167d7342 --- /dev/null +++ b/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 signInManager; + private readonly UserManager userManager; + + public AccountController(SignInManager signInManager, UserManager 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 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 AddLoginAsync(IdentityUser user, UserLoginInfo externalLogin) + { + var result = await userManager.AddLoginAsync(user, externalLogin); + + return result.Succeeded; + } + + private async Task AddUserAsync(IdentityUser user) + { + var result = await userManager.CreateAsync(user); + + return result.Succeeded; + } + + private async Task 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 }; + } + } +} diff --git a/src/PinkParrot/Modules/UI/Account/ExternalProvider.cs b/src/PinkParrot/Modules/UI/Account/ExternalProvider.cs new file mode 100644 index 000000000..118579b31 --- /dev/null +++ b/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; + } + } +} \ No newline at end of file diff --git a/src/PinkParrot/Modules/UI/Account/LoginVM.cs b/src/PinkParrot/Modules/UI/Account/LoginVM.cs new file mode 100644 index 000000000..a2cdb7c96 --- /dev/null +++ b/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 ExternalProviders { get; set; } + } +} diff --git a/src/PinkParrot/Pipeline/WebpackMiddleware.cs b/src/PinkParrot/Pipeline/WebpackMiddleware.cs index fd444d854..c5515ce37 100644 --- a/src/PinkParrot/Pipeline/WebpackMiddleware.cs +++ b/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; diff --git a/src/PinkParrot/Startup.cs b/src/PinkParrot/Startup.cs index 48e80edd7..01a760767 100644 --- a/src/PinkParrot/Startup.cs +++ b/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().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( + services.Configure( Configuration.GetSection("stores:mongoDb")); - services.Configure( + services.Configure( Configuration.GetSection("stores:eventStore")); + services.Configure( + Configuration.GetSection("identity")); var builder = new ContainerBuilder(); builder.RegisterModule(); @@ -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 { "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(); + } } } diff --git a/src/PinkParrot/Views/Account/ClientPopup.cshtml b/src/PinkParrot/Views/Account/ClientPopup.cshtml new file mode 100644 index 000000000..76a110915 --- /dev/null +++ b/src/PinkParrot/Views/Account/ClientPopup.cshtml @@ -0,0 +1,12 @@ + + + + + + + diff --git a/src/PinkParrot/Views/Account/ClientSilent.cshtml b/src/PinkParrot/Views/Account/ClientSilent.cshtml new file mode 100644 index 000000000..231806b2c --- /dev/null +++ b/src/PinkParrot/Views/Account/ClientSilent.cshtml @@ -0,0 +1,12 @@ + + + + + + + diff --git a/src/PinkParrot/Views/Account/Login.cshtml b/src/PinkParrot/Views/Account/Login.cshtml new file mode 100644 index 000000000..de417de61 --- /dev/null +++ b/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 + +
+
+

+ @foreach (var provider in Model.ExternalProviders) + { + + } +

+
+
\ No newline at end of file diff --git a/src/PinkParrot/Views/_ViewImports.cshtml b/src/PinkParrot/Views/_ViewImports.cshtml new file mode 100644 index 000000000..7b56072b2 --- /dev/null +++ b/src/PinkParrot/Views/_ViewImports.cshtml @@ -0,0 +1,3 @@ +@using Microsoft.AspNetCore.Identity + +@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers diff --git a/src/PinkParrot/Views/_ViewStart.cshtml b/src/PinkParrot/Views/_ViewStart.cshtml new file mode 100644 index 000000000..be2a4f37a --- /dev/null +++ b/src/PinkParrot/Views/_ViewStart.cshtml @@ -0,0 +1,3 @@ +@{ + Layout = null; +} diff --git a/src/PinkParrot/app/app.component.html b/src/PinkParrot/app/app.component.html index aa8f55823..16227ef88 100644 --- a/src/PinkParrot/app/app.component.html +++ b/src/PinkParrot/app/app.component.html @@ -1,3 +1 @@ -
-

Hello from Angular 2 App with Webpack!

-
\ No newline at end of file + \ No newline at end of file diff --git a/src/PinkParrot/app/app.module.ts b/src/PinkParrot/app/app.module.ts index 7d881ad3b..5b399005e 100644 --- a/src/PinkParrot/app/app.module.ts +++ b/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 { } \ No newline at end of file diff --git a/src/PinkParrot/app/app.routes.ts b/src/PinkParrot/app/app.routes.ts new file mode 100644 index 000000000..d2576843e --- /dev/null +++ b/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 }); \ No newline at end of file diff --git a/src/PinkParrot/app/components/apps/apps.component.html b/src/PinkParrot/app/components/apps/apps.component.html new file mode 100644 index 000000000..aa8f55823 --- /dev/null +++ b/src/PinkParrot/app/components/apps/apps.component.html @@ -0,0 +1,3 @@ +
+

Hello from Angular 2 App with Webpack!

+
\ No newline at end of file diff --git a/src/PinkParrot/app/components/apps/apps.component.ts b/src/PinkParrot/app/components/apps/apps.component.ts new file mode 100644 index 000000000..aea4cf973 --- /dev/null +++ b/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 { + +} \ No newline at end of file diff --git a/src/PinkParrot/app/components/apps/apps.module.ts b/src/PinkParrot/app/components/apps/apps.module.ts new file mode 100644 index 000000000..4862fffe0 --- /dev/null +++ b/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 { } \ No newline at end of file diff --git a/src/PinkParrot/app/components/apps/declarations.ts b/src/PinkParrot/app/components/apps/declarations.ts new file mode 100644 index 000000000..a67c3391e --- /dev/null +++ b/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'; \ No newline at end of file diff --git a/src/PinkParrot/app/components/apps/index.ts b/src/PinkParrot/app/components/apps/index.ts new file mode 100644 index 000000000..ca3a73704 --- /dev/null +++ b/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'; \ No newline at end of file diff --git a/src/PinkParrot/app/components/index.ts b/src/PinkParrot/app/components/index.ts new file mode 100644 index 000000000..81c2f1fa4 --- /dev/null +++ b/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'; \ No newline at end of file diff --git a/src/PinkParrot/app/components/login/declarations.ts b/src/PinkParrot/app/components/login/declarations.ts new file mode 100644 index 000000000..683518d8f --- /dev/null +++ b/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'; \ No newline at end of file diff --git a/src/PinkParrot/app/components/login/index.ts b/src/PinkParrot/app/components/login/index.ts new file mode 100644 index 000000000..a0859bf50 --- /dev/null +++ b/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'; \ No newline at end of file diff --git a/src/PinkParrot/app/components/login/login.component.html b/src/PinkParrot/app/components/login/login.component.html new file mode 100644 index 000000000..27df9f084 --- /dev/null +++ b/src/PinkParrot/app/components/login/login.component.html @@ -0,0 +1,3 @@ +
+ Logging in +
\ No newline at end of file diff --git a/src/PinkParrot/app/components/login/login.component.ts b/src/PinkParrot/app/components/login/login.component.ts new file mode 100644 index 000000000..3d06264ba --- /dev/null +++ b/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; + } + ); + } +} \ No newline at end of file diff --git a/src/PinkParrot/app/components/login/login.module.ts b/src/PinkParrot/app/components/login/login.module.ts new file mode 100644 index 000000000..aa750e43b --- /dev/null +++ b/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 { } \ No newline at end of file diff --git a/src/PinkParrot/app/core/angular/action.spec.ts b/src/PinkParrot/app/framework/angular/action.spec.ts similarity index 97% rename from src/PinkParrot/app/core/angular/action.spec.ts rename to src/PinkParrot/app/framework/angular/action.spec.ts index 695f59cb2..783c8bdee 100644 --- a/src/PinkParrot/app/core/angular/action.spec.ts +++ b/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().map(x => { return { type: 'MOCK_ACTION' }; }); + constructor(private readonly store: any) { } + public init() { this.event2 = new Subject().map(x => { return { type: 'MOCK_ACTION' }; }); } diff --git a/src/PinkParrot/app/core/angular/action.ts b/src/PinkParrot/app/framework/angular/action.ts similarity index 98% rename from src/PinkParrot/app/core/angular/action.ts rename to src/PinkParrot/app/framework/angular/action.ts index 2ee2646c3..370cda411 100644 --- a/src/PinkParrot/app/core/angular/action.ts +++ b/src/PinkParrot/app/framework/angular/action.ts @@ -1,5 +1,5 @@ /* - * Athene Requirements Center + *PinkParrot CMS * * @license * Copyright (c) Sebastian Stehle. All rights reserved diff --git a/src/PinkParrot/app/core/angular/cloak.directive.spec.ts b/src/PinkParrot/app/framework/angular/cloak.directive.spec.ts similarity index 95% rename from src/PinkParrot/app/core/angular/cloak.directive.spec.ts rename to src/PinkParrot/app/framework/angular/cloak.directive.spec.ts index 50e07313a..bb043f035 100644 --- a/src/PinkParrot/app/core/angular/cloak.directive.spec.ts +++ b/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 diff --git a/src/PinkParrot/app/core/angular/cloak.directive.ts b/src/PinkParrot/app/framework/angular/cloak.directive.ts similarity index 92% rename from src/PinkParrot/app/core/angular/cloak.directive.ts rename to src/PinkParrot/app/framework/angular/cloak.directive.ts index f183adfa3..08206dd58 100644 --- a/src/PinkParrot/app/core/angular/cloak.directive.ts +++ b/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 diff --git a/src/PinkParrot/app/core/angular/color-picker.component.html b/src/PinkParrot/app/framework/angular/color-picker.component.html similarity index 100% rename from src/PinkParrot/app/core/angular/color-picker.component.html rename to src/PinkParrot/app/framework/angular/color-picker.component.html diff --git a/src/PinkParrot/app/core/angular/color-picker.component.scss b/src/PinkParrot/app/framework/angular/color-picker.component.scss similarity index 100% rename from src/PinkParrot/app/core/angular/color-picker.component.scss rename to src/PinkParrot/app/framework/angular/color-picker.component.scss diff --git a/src/PinkParrot/app/core/angular/color-picker.component.spec.ts b/src/PinkParrot/app/framework/angular/color-picker.component.spec.ts similarity index 99% rename from src/PinkParrot/app/core/angular/color-picker.component.spec.ts rename to src/PinkParrot/app/framework/angular/color-picker.component.spec.ts index 181cb105f..e973ba83f 100644 --- a/src/PinkParrot/app/core/angular/color-picker.component.spec.ts +++ b/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', () => { diff --git a/src/PinkParrot/app/core/angular/color-picker.component.ts b/src/PinkParrot/app/framework/angular/color-picker.component.ts similarity index 93% rename from src/PinkParrot/app/core/angular/color-picker.component.ts rename to src/PinkParrot/app/framework/angular/color-picker.component.ts index 146a3ef8c..387afe10c 100644 --- a/src/PinkParrot/app/core/angular/color-picker.component.ts +++ b/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', diff --git a/src/PinkParrot/app/core/angular/date-time.pipes.spec.ts b/src/PinkParrot/app/framework/angular/date-time.pipes.spec.ts similarity index 98% rename from src/PinkParrot/app/core/angular/date-time.pipes.spec.ts rename to src/PinkParrot/app/framework/angular/date-time.pipes.spec.ts index 6e1ec86f1..43fa80674 100644 --- a/src/PinkParrot/app/core/angular/date-time.pipes.spec.ts +++ b/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 diff --git a/src/PinkParrot/app/core/angular/date-time.pipes.ts b/src/PinkParrot/app/framework/angular/date-time.pipes.ts similarity index 97% rename from src/PinkParrot/app/core/angular/date-time.pipes.ts rename to src/PinkParrot/app/framework/angular/date-time.pipes.ts index 393320d91..f37c22601 100644 --- a/src/PinkParrot/app/core/angular/date-time.pipes.ts +++ b/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 diff --git a/src/PinkParrot/app/core/angular/drag-model.directive.ts b/src/PinkParrot/app/framework/angular/drag-model.directive.ts similarity index 96% rename from src/PinkParrot/app/core/angular/drag-model.directive.ts rename to src/PinkParrot/app/framework/angular/drag-model.directive.ts index 16a459ea2..3b99c2f47 100644 --- a/src/PinkParrot/app/core/angular/drag-model.directive.ts +++ b/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]' diff --git a/src/PinkParrot/app/core/angular/focus-on-change.directive.spec.ts b/src/PinkParrot/app/framework/angular/focus-on-change.directive.spec.ts similarity index 97% rename from src/PinkParrot/app/core/angular/focus-on-change.directive.spec.ts rename to src/PinkParrot/app/framework/angular/focus-on-change.directive.spec.ts index ed4b8f4b9..205d3a339 100644 --- a/src/PinkParrot/app/core/angular/focus-on-change.directive.spec.ts +++ b/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 diff --git a/src/PinkParrot/app/core/angular/focus-on-change.directive.ts b/src/PinkParrot/app/framework/angular/focus-on-change.directive.ts similarity index 95% rename from src/PinkParrot/app/core/angular/focus-on-change.directive.ts rename to src/PinkParrot/app/framework/angular/focus-on-change.directive.ts index 607cbba5d..6c732e2e7 100644 --- a/src/PinkParrot/app/core/angular/focus-on-change.directive.ts +++ b/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 diff --git a/src/PinkParrot/app/core/angular/image-drop.directive.ts b/src/PinkParrot/app/framework/angular/image-drop.directive.ts similarity index 96% rename from src/PinkParrot/app/core/angular/image-drop.directive.ts rename to src/PinkParrot/app/framework/angular/image-drop.directive.ts index 440e07459..7b4d72c22 100644 --- a/src/PinkParrot/app/core/angular/image-drop.directive.ts +++ b/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' diff --git a/src/PinkParrot/app/core/angular/money.pipe.spec.ts b/src/PinkParrot/app/framework/angular/money.pipe.spec.ts similarity index 98% rename from src/PinkParrot/app/core/angular/money.pipe.spec.ts rename to src/PinkParrot/app/framework/angular/money.pipe.spec.ts index c080ee2cd..6c9569018 100644 --- a/src/PinkParrot/app/core/angular/money.pipe.spec.ts +++ b/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 diff --git a/src/PinkParrot/app/core/angular/money.pipe.ts b/src/PinkParrot/app/framework/angular/money.pipe.ts similarity index 96% rename from src/PinkParrot/app/core/angular/money.pipe.ts rename to src/PinkParrot/app/framework/angular/money.pipe.ts index 6528768f8..4b3ce2c74 100644 --- a/src/PinkParrot/app/core/angular/money.pipe.ts +++ b/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 diff --git a/src/PinkParrot/app/core/angular/shortcut.component.spec.ts b/src/PinkParrot/app/framework/angular/shortcut.component.spec.ts similarity index 94% rename from src/PinkParrot/app/core/angular/shortcut.component.spec.ts rename to src/PinkParrot/app/framework/angular/shortcut.component.spec.ts index 48e30926e..1da172b44 100644 --- a/src/PinkParrot/app/core/angular/shortcut.component.spec.ts +++ b/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; diff --git a/src/PinkParrot/app/core/angular/shortcut.component.ts b/src/PinkParrot/app/framework/angular/shortcut.component.ts similarity index 97% rename from src/PinkParrot/app/core/angular/shortcut.component.ts rename to src/PinkParrot/app/framework/angular/shortcut.component.ts index 5cfb935e5..2c12260c1 100644 --- a/src/PinkParrot/app/core/angular/shortcut.component.ts +++ b/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 diff --git a/src/PinkParrot/app/core/angular/slider.component.html b/src/PinkParrot/app/framework/angular/slider.component.html similarity index 100% rename from src/PinkParrot/app/core/angular/slider.component.html rename to src/PinkParrot/app/framework/angular/slider.component.html diff --git a/src/PinkParrot/app/core/angular/slider.component.scss b/src/PinkParrot/app/framework/angular/slider.component.scss similarity index 100% rename from src/PinkParrot/app/core/angular/slider.component.scss rename to src/PinkParrot/app/framework/angular/slider.component.scss diff --git a/src/PinkParrot/app/core/angular/slider.component.ts b/src/PinkParrot/app/framework/angular/slider.component.ts similarity index 99% rename from src/PinkParrot/app/core/angular/slider.component.ts rename to src/PinkParrot/app/framework/angular/slider.component.ts index 62988c6ed..5030c74a1 100644 --- a/src/PinkParrot/app/core/angular/slider.component.ts +++ b/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 diff --git a/src/PinkParrot/app/core/angular/spinner.component.ts b/src/PinkParrot/app/framework/angular/spinner.component.ts similarity index 96% rename from src/PinkParrot/app/core/angular/spinner.component.ts rename to src/PinkParrot/app/framework/angular/spinner.component.ts index a32df741a..8599c5f2e 100644 --- a/src/PinkParrot/app/core/angular/spinner.component.ts +++ b/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 diff --git a/src/PinkParrot/app/core/angular/user-report.component.ts b/src/PinkParrot/app/framework/angular/user-report.component.ts similarity index 96% rename from src/PinkParrot/app/core/angular/user-report.component.ts rename to src/PinkParrot/app/framework/angular/user-report.component.ts index f96502663..d726e2cbc 100644 --- a/src/PinkParrot/app/core/angular/user-report.component.ts +++ b/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 diff --git a/src/PinkParrot/app/core/angular/validators.spec.ts b/src/PinkParrot/app/framework/angular/validators.spec.ts similarity index 97% rename from src/PinkParrot/app/core/angular/validators.spec.ts rename to src/PinkParrot/app/framework/angular/validators.spec.ts index d6ab3e318..06270c04e 100644 --- a/src/PinkParrot/app/core/angular/validators.spec.ts +++ b/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 diff --git a/src/PinkParrot/app/core/angular/validators.ts b/src/PinkParrot/app/framework/angular/validators.ts similarity index 95% rename from src/PinkParrot/app/core/angular/validators.ts rename to src/PinkParrot/app/framework/angular/validators.ts index fc3f6d67b..90d25c653 100644 --- a/src/PinkParrot/app/core/angular/validators.ts +++ b/src/PinkParrot/app/framework/angular/validators.ts @@ -1,5 +1,5 @@ /* - * Athene Requirements Center + *PinkParrot CMS * * @license * Copyright (c) Sebastian Stehle. All rights reserved diff --git a/src/PinkParrot/app/core/configurations.ts b/src/PinkParrot/app/framework/configurations.ts similarity index 52% rename from src/PinkParrot/app/core/configurations.ts rename to src/PinkParrot/app/framework/configurations.ts index 35067263f..3abc37935 100644 --- a/src/PinkParrot/app/core/configurations.ts +++ b/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, diff --git a/src/PinkParrot/app/framework/declarations.ts b/src/PinkParrot/app/framework/declarations.ts new file mode 100644 index 000000000..5f14245ad --- /dev/null +++ b/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'; \ No newline at end of file diff --git a/src/PinkParrot/app/framework/framework.module.ts b/src/PinkParrot/app/framework/framework.module.ts new file mode 100644 index 000000000..b37e58315 --- /dev/null +++ b/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 { } \ No newline at end of file diff --git a/src/PinkParrot/app/core/index.ts b/src/PinkParrot/app/framework/index.ts similarity index 91% rename from src/PinkParrot/app/core/index.ts rename to src/PinkParrot/app/framework/index.ts index eeb444dd8..877ac0260 100644 --- a/src/PinkParrot/app/core/index.ts +++ b/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'; diff --git a/src/PinkParrot/app/core/plattform.ts b/src/PinkParrot/app/framework/plattform.ts similarity index 90% rename from src/PinkParrot/app/core/plattform.ts rename to src/PinkParrot/app/framework/plattform.ts index a0adf046e..bad3c8655 100644 --- a/src/PinkParrot/app/core/plattform.ts +++ b/src/PinkParrot/app/framework/plattform.ts @@ -1,5 +1,5 @@ /* - * Athene Requirements Center + *PinkParrot CMS * * @license * Copyright (c) Sebastian Stehle. All rights reserved diff --git a/src/PinkParrot/app/core/services/clipboard.service.spec.ts b/src/PinkParrot/app/framework/services/clipboard.service.spec.ts similarity index 97% rename from src/PinkParrot/app/core/services/clipboard.service.spec.ts rename to src/PinkParrot/app/framework/services/clipboard.service.spec.ts index d705b2799..8db083589 100644 --- a/src/PinkParrot/app/core/services/clipboard.service.spec.ts +++ b/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 diff --git a/src/PinkParrot/app/core/services/clipboard.service.ts b/src/PinkParrot/app/framework/services/clipboard.service.ts similarity index 89% rename from src/PinkParrot/app/core/services/clipboard.service.ts rename to src/PinkParrot/app/framework/services/clipboard.service.ts index 94b6fabe9..c766d1cc3 100644 --- a/src/PinkParrot/app/core/services/clipboard.service.ts +++ b/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(''); diff --git a/src/PinkParrot/app/core/services/drag.service.spec.ts b/src/PinkParrot/app/framework/services/drag.service.spec.ts similarity index 96% rename from src/PinkParrot/app/core/services/drag.service.spec.ts rename to src/PinkParrot/app/framework/services/drag.service.spec.ts index a3d9cf2ed..199152c08 100644 --- a/src/PinkParrot/app/core/services/drag.service.spec.ts +++ b/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 diff --git a/src/PinkParrot/app/core/services/drag.service.ts b/src/PinkParrot/app/framework/services/drag.service.ts similarity index 88% rename from src/PinkParrot/app/core/services/drag.service.ts rename to src/PinkParrot/app/framework/services/drag.service.ts index 0e2e3d1d4..8c245208c 100644 --- a/src/PinkParrot/app/core/services/drag.service.ts +++ b/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(); diff --git a/src/PinkParrot/app/core/services/local-store.service.spec.ts b/src/PinkParrot/app/framework/services/local-store.service.spec.ts similarity index 98% rename from src/PinkParrot/app/core/services/local-store.service.spec.ts rename to src/PinkParrot/app/framework/services/local-store.service.spec.ts index 0c49c57a8..98f40d27b 100644 --- a/src/PinkParrot/app/core/services/local-store.service.spec.ts +++ b/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 diff --git a/src/PinkParrot/app/core/services/local-store.service.ts b/src/PinkParrot/app/framework/services/local-store.service.ts similarity index 86% rename from src/PinkParrot/app/core/services/local-store.service.ts rename to src/PinkParrot/app/framework/services/local-store.service.ts index a007b90ab..11e3a6faa 100644 --- a/src/PinkParrot/app/core/services/local-store.service.ts +++ b/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; diff --git a/src/PinkParrot/app/core/services/shortcut.service.spec.ts b/src/PinkParrot/app/framework/services/shortcut.service.spec.ts similarity index 97% rename from src/PinkParrot/app/core/services/shortcut.service.spec.ts rename to src/PinkParrot/app/framework/services/shortcut.service.spec.ts index 04cd457d9..33a2a8529 100644 --- a/src/PinkParrot/app/core/services/shortcut.service.spec.ts +++ b/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 diff --git a/src/PinkParrot/app/core/services/shortcut.service.ts b/src/PinkParrot/app/framework/services/shortcut.service.ts similarity index 87% rename from src/PinkParrot/app/core/services/shortcut.service.ts rename to src/PinkParrot/app/framework/services/shortcut.service.ts index 728a92681..e33880317 100644 --- a/src/PinkParrot/app/core/services/shortcut.service.ts +++ b/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) => { diff --git a/src/PinkParrot/app/core/services/title.service.spec.ts b/src/PinkParrot/app/framework/services/title.service.spec.ts similarity index 98% rename from src/PinkParrot/app/core/services/title.service.spec.ts rename to src/PinkParrot/app/framework/services/title.service.spec.ts index 95c25cd0e..aebd27849 100644 --- a/src/PinkParrot/app/core/services/title.service.spec.ts +++ b/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 diff --git a/src/PinkParrot/app/core/services/title.service.ts b/src/PinkParrot/app/framework/services/title.service.ts similarity index 91% rename from src/PinkParrot/app/core/services/title.service.ts rename to src/PinkParrot/app/framework/services/title.service.ts index ec2921376..017684bac 100644 --- a/src/PinkParrot/app/core/services/title.service.ts +++ b/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) { } diff --git a/src/PinkParrot/app/core/utils/color-palette.spec.ts b/src/PinkParrot/app/framework/utils/color-palette.spec.ts similarity index 91% rename from src/PinkParrot/app/core/utils/color-palette.spec.ts rename to src/PinkParrot/app/framework/utils/color-palette.spec.ts index 1126c3aed..39e297610 100644 --- a/src/PinkParrot/app/core/utils/color-palette.spec.ts +++ b/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 diff --git a/src/PinkParrot/app/core/utils/color-palette.ts b/src/PinkParrot/app/framework/utils/color-palette.ts similarity index 97% rename from src/PinkParrot/app/core/utils/color-palette.ts rename to src/PinkParrot/app/framework/utils/color-palette.ts index 59f04440e..7f2a0bbc2 100644 --- a/src/PinkParrot/app/core/utils/color-palette.ts +++ b/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 diff --git a/src/PinkParrot/app/core/utils/color.spec.ts b/src/PinkParrot/app/framework/utils/color.spec.ts similarity index 99% rename from src/PinkParrot/app/core/utils/color.spec.ts rename to src/PinkParrot/app/framework/utils/color.spec.ts index 52d7d22bc..35d420194 100644 --- a/src/PinkParrot/app/core/utils/color.spec.ts +++ b/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 diff --git a/src/PinkParrot/app/core/utils/color.ts b/src/PinkParrot/app/framework/utils/color.ts similarity index 99% rename from src/PinkParrot/app/core/utils/color.ts rename to src/PinkParrot/app/framework/utils/color.ts index 0d1dcf688..4a7aac8df 100644 --- a/src/PinkParrot/app/core/utils/color.ts +++ b/src/PinkParrot/app/framework/utils/color.ts @@ -1,5 +1,5 @@ /* - * Athene Requirements Center + *PinkParrot CMS * * @license * Copyright (c) Sebastian Stehle. All rights reserved diff --git a/src/PinkParrot/app/core/utils/date-helper.spec.ts b/src/PinkParrot/app/framework/utils/date-helper.spec.ts similarity index 95% rename from src/PinkParrot/app/core/utils/date-helper.spec.ts rename to src/PinkParrot/app/framework/utils/date-helper.spec.ts index 833ba7375..cf1457768 100644 --- a/src/PinkParrot/app/core/utils/date-helper.spec.ts +++ b/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 diff --git a/src/PinkParrot/app/core/utils/date-helper.ts b/src/PinkParrot/app/framework/utils/date-helper.ts similarity index 91% rename from src/PinkParrot/app/core/utils/date-helper.ts rename to src/PinkParrot/app/framework/utils/date-helper.ts index 26ab46c7d..20b4ef832 100644 --- a/src/PinkParrot/app/core/utils/date-helper.ts +++ b/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 diff --git a/src/PinkParrot/app/core/utils/date-time.spec.ts b/src/PinkParrot/app/framework/utils/date-time.spec.ts similarity index 99% rename from src/PinkParrot/app/core/utils/date-time.spec.ts rename to src/PinkParrot/app/framework/utils/date-time.spec.ts index 410478975..b59c7d94f 100644 --- a/src/PinkParrot/app/core/utils/date-time.spec.ts +++ b/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 diff --git a/src/PinkParrot/app/core/utils/date-time.ts b/src/PinkParrot/app/framework/utils/date-time.ts similarity index 99% rename from src/PinkParrot/app/core/utils/date-time.ts rename to src/PinkParrot/app/framework/utils/date-time.ts index 747455e90..9a2972c2d 100644 --- a/src/PinkParrot/app/core/utils/date-time.ts +++ b/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 diff --git a/src/PinkParrot/app/core/utils/duration.spec.ts b/src/PinkParrot/app/framework/utils/duration.spec.ts similarity index 97% rename from src/PinkParrot/app/core/utils/duration.spec.ts rename to src/PinkParrot/app/framework/utils/duration.spec.ts index 57d38fc7f..b95c9b932 100644 --- a/src/PinkParrot/app/core/utils/duration.spec.ts +++ b/src/PinkParrot/app/framework/utils/duration.spec.ts @@ -1,5 +1,5 @@ /* - * Athene Requirements Center + *PinkParrot CMS * * @license * Copyright (c) Sebastian Stehle. All rights reserved diff --git a/src/PinkParrot/app/core/utils/duration.ts b/src/PinkParrot/app/framework/utils/duration.ts similarity index 96% rename from src/PinkParrot/app/core/utils/duration.ts rename to src/PinkParrot/app/framework/utils/duration.ts index ea7b2c8be..0d5c5f609 100644 --- a/src/PinkParrot/app/core/utils/duration.ts +++ b/src/PinkParrot/app/framework/utils/duration.ts @@ -1,5 +1,5 @@ /* - * Athene Requirements Center + *PinkParrot CMS * * @license * Copyright (c) Sebastian Stehle. All rights reserved diff --git a/src/PinkParrot/app/core/utils/immutable-id-map.spec.ts b/src/PinkParrot/app/framework/utils/immutable-id-map.spec.ts similarity index 99% rename from src/PinkParrot/app/core/utils/immutable-id-map.spec.ts rename to src/PinkParrot/app/framework/utils/immutable-id-map.spec.ts index 68f4e8842..802d9a9f0 100644 --- a/src/PinkParrot/app/core/utils/immutable-id-map.spec.ts +++ b/src/PinkParrot/app/framework/utils/immutable-id-map.spec.ts @@ -1,5 +1,5 @@ /* - * Athene Requirements Center + *PinkParrot CMS * * @license * Copyright (c) Sebastian Stehle. All rights reserved diff --git a/src/PinkParrot/app/core/utils/immutable-id-map.ts b/src/PinkParrot/app/framework/utils/immutable-id-map.ts similarity index 99% rename from src/PinkParrot/app/core/utils/immutable-id-map.ts rename to src/PinkParrot/app/framework/utils/immutable-id-map.ts index d2a4398ae..c2cbad167 100644 --- a/src/PinkParrot/app/core/utils/immutable-id-map.ts +++ b/src/PinkParrot/app/framework/utils/immutable-id-map.ts @@ -1,5 +1,5 @@ /* - * Athene Requirements Center + *PinkParrot CMS * * @license * Copyright (c) Sebastian Stehle. All rights reserved diff --git a/src/PinkParrot/app/core/utils/immutable-list.spec.ts b/src/PinkParrot/app/framework/utils/immutable-list.spec.ts similarity index 99% rename from src/PinkParrot/app/core/utils/immutable-list.spec.ts rename to src/PinkParrot/app/framework/utils/immutable-list.spec.ts index 370417a46..d4d6127e5 100644 --- a/src/PinkParrot/app/core/utils/immutable-list.spec.ts +++ b/src/PinkParrot/app/framework/utils/immutable-list.spec.ts @@ -1,5 +1,5 @@ /* - * Athene Requirements Center + *PinkParrot CMS * * @license * Copyright (c) Sebastian Stehle. All rights reserved diff --git a/src/PinkParrot/app/core/utils/immutable-list.ts b/src/PinkParrot/app/framework/utils/immutable-list.ts similarity index 99% rename from src/PinkParrot/app/core/utils/immutable-list.ts rename to src/PinkParrot/app/framework/utils/immutable-list.ts index 59783f2a0..19497fa98 100644 --- a/src/PinkParrot/app/core/utils/immutable-list.ts +++ b/src/PinkParrot/app/framework/utils/immutable-list.ts @@ -1,5 +1,5 @@ /* - * Athene Requirements Center + *PinkParrot CMS * * @license * Copyright (c) Sebastian Stehle. All rights reserved diff --git a/src/PinkParrot/app/core/utils/immutable-object.spec.ts b/src/PinkParrot/app/framework/utils/immutable-object.spec.ts similarity index 96% rename from src/PinkParrot/app/core/utils/immutable-object.spec.ts rename to src/PinkParrot/app/framework/utils/immutable-object.spec.ts index ff630a3d4..8e3aa91e7 100644 --- a/src/PinkParrot/app/core/utils/immutable-object.spec.ts +++ b/src/PinkParrot/app/framework/utils/immutable-object.spec.ts @@ -1,5 +1,5 @@ /* - * Athene Requirements Center + *PinkParrot CMS * * @license * Copyright (c) Sebastian Stehle. All rights reserved diff --git a/src/PinkParrot/app/core/utils/immutable-object.ts b/src/PinkParrot/app/framework/utils/immutable-object.ts similarity index 93% rename from src/PinkParrot/app/core/utils/immutable-object.ts rename to src/PinkParrot/app/framework/utils/immutable-object.ts index 419eca84c..fbf809d8d 100644 --- a/src/PinkParrot/app/core/utils/immutable-object.ts +++ b/src/PinkParrot/app/framework/utils/immutable-object.ts @@ -1,5 +1,5 @@ /* - * Athene Requirements Center + *PinkParrot CMS * * @license * Copyright (c) Sebastian Stehle. All rights reserved diff --git a/src/PinkParrot/app/core/utils/immutable-set.spec.ts b/src/PinkParrot/app/framework/utils/immutable-set.spec.ts similarity index 99% rename from src/PinkParrot/app/core/utils/immutable-set.spec.ts rename to src/PinkParrot/app/framework/utils/immutable-set.spec.ts index de7fdf436..f3c915123 100644 --- a/src/PinkParrot/app/core/utils/immutable-set.spec.ts +++ b/src/PinkParrot/app/framework/utils/immutable-set.spec.ts @@ -1,5 +1,5 @@ /* - * Athene Requirements Center + *PinkParrot CMS * * @license * Copyright (c) Sebastian Stehle. All rights reserved diff --git a/src/PinkParrot/app/core/utils/immutable-set.ts b/src/PinkParrot/app/framework/utils/immutable-set.ts similarity index 98% rename from src/PinkParrot/app/core/utils/immutable-set.ts rename to src/PinkParrot/app/framework/utils/immutable-set.ts index f957386b9..ecf86288b 100644 --- a/src/PinkParrot/app/core/utils/immutable-set.ts +++ b/src/PinkParrot/app/framework/utils/immutable-set.ts @@ -1,5 +1,5 @@ /* - * Athene Requirements Center + *PinkParrot CMS * * @license * Copyright (c) Sebastian Stehle. All rights reserved diff --git a/src/PinkParrot/app/core/utils/math-helper.spec.ts b/src/PinkParrot/app/framework/utils/math-helper.spec.ts similarity index 98% rename from src/PinkParrot/app/core/utils/math-helper.spec.ts rename to src/PinkParrot/app/framework/utils/math-helper.spec.ts index 25bc218d3..a7aa2efb0 100644 --- a/src/PinkParrot/app/core/utils/math-helper.spec.ts +++ b/src/PinkParrot/app/framework/utils/math-helper.spec.ts @@ -1,5 +1,5 @@ /* - * Athene Requirements Center + *PinkParrot CMS * * @license * Copyright (c) Sebastian Stehle. All rights reserved diff --git a/src/PinkParrot/app/core/utils/math-helper.ts b/src/PinkParrot/app/framework/utils/math-helper.ts similarity index 98% rename from src/PinkParrot/app/core/utils/math-helper.ts rename to src/PinkParrot/app/framework/utils/math-helper.ts index fc4d29b24..462b63ee2 100644 --- a/src/PinkParrot/app/core/utils/math-helper.ts +++ b/src/PinkParrot/app/framework/utils/math-helper.ts @@ -1,5 +1,5 @@ /* - * Athene Requirements Center + *PinkParrot CMS * * @license * Copyright (c) Sebastian Stehle. All rights reserved diff --git a/src/PinkParrot/app/core/utils/rect2.spec.ts b/src/PinkParrot/app/framework/utils/rect2.spec.ts similarity index 99% rename from src/PinkParrot/app/core/utils/rect2.spec.ts rename to src/PinkParrot/app/framework/utils/rect2.spec.ts index 6d10ecab4..0b09ce1c3 100644 --- a/src/PinkParrot/app/core/utils/rect2.spec.ts +++ b/src/PinkParrot/app/framework/utils/rect2.spec.ts @@ -1,5 +1,5 @@ /* - * Athene Requirements Center + *PinkParrot CMS * * @license * Copyright (c) Sebastian Stehle. All rights reserved diff --git a/src/PinkParrot/app/core/utils/rect2.ts b/src/PinkParrot/app/framework/utils/rect2.ts similarity index 99% rename from src/PinkParrot/app/core/utils/rect2.ts rename to src/PinkParrot/app/framework/utils/rect2.ts index ed8a915fe..d7a3c1726 100644 --- a/src/PinkParrot/app/core/utils/rect2.ts +++ b/src/PinkParrot/app/framework/utils/rect2.ts @@ -1,5 +1,5 @@ /* - * Athene Requirements Center + *PinkParrot CMS * * @license * Copyright (c) Sebastian Stehle. All rights reserved diff --git a/src/PinkParrot/app/core/utils/rotation.spec.ts b/src/PinkParrot/app/framework/utils/rotation.spec.ts similarity index 98% rename from src/PinkParrot/app/core/utils/rotation.spec.ts rename to src/PinkParrot/app/framework/utils/rotation.spec.ts index d1390f0c4..f17efef2b 100644 --- a/src/PinkParrot/app/core/utils/rotation.spec.ts +++ b/src/PinkParrot/app/framework/utils/rotation.spec.ts @@ -1,5 +1,5 @@ /* - * Athene Requirements Center + *PinkParrot CMS * * @license * Copyright (c) Sebastian Stehle. All rights reserved diff --git a/src/PinkParrot/app/core/utils/rotation.ts b/src/PinkParrot/app/framework/utils/rotation.ts similarity index 97% rename from src/PinkParrot/app/core/utils/rotation.ts rename to src/PinkParrot/app/framework/utils/rotation.ts index 9eb2652e2..e31033999 100644 --- a/src/PinkParrot/app/core/utils/rotation.ts +++ b/src/PinkParrot/app/framework/utils/rotation.ts @@ -1,5 +1,5 @@ /* - * Athene Requirements Center + *PinkParrot CMS * * @license * Copyright (c) Sebastian Stehle. All rights reserved diff --git a/src/PinkParrot/app/core/utils/vec2.spec.ts b/src/PinkParrot/app/framework/utils/vec2.spec.ts similarity index 99% rename from src/PinkParrot/app/core/utils/vec2.spec.ts rename to src/PinkParrot/app/framework/utils/vec2.spec.ts index 6c153ffa3..6b7083bb8 100644 --- a/src/PinkParrot/app/core/utils/vec2.spec.ts +++ b/src/PinkParrot/app/framework/utils/vec2.spec.ts @@ -1,5 +1,5 @@ /* - * Athene Requirements Center + *PinkParrot CMS * * @license * Copyright (c) Sebastian Stehle. All rights reserved diff --git a/src/PinkParrot/app/core/utils/vec2.ts b/src/PinkParrot/app/framework/utils/vec2.ts similarity index 99% rename from src/PinkParrot/app/core/utils/vec2.ts rename to src/PinkParrot/app/framework/utils/vec2.ts index 676a15c07..d47d18d2d 100644 --- a/src/PinkParrot/app/core/utils/vec2.ts +++ b/src/PinkParrot/app/framework/utils/vec2.ts @@ -1,5 +1,5 @@ /* - * Athene Requirements Center + *PinkParrot CMS * * @license * Copyright (c) Sebastian Stehle. All rights reserved diff --git a/src/PinkParrot/app/shared/guards/auth.guard.ts b/src/PinkParrot/app/shared/guards/auth.guard.ts new file mode 100644 index 000000000..2c22af031 --- /dev/null +++ b/src/PinkParrot/app/shared/guards/auth.guard.ts @@ -0,0 +1,24 @@ +import * as Ng2 from '@angular/core'; +import * as Ng2Router from '@angular/router'; + +import { AuthService } from './../services/auth.service'; + +const LOGIN_URL = '/login/'; + +@Ng2.Injectable() +export class AuthGuard implements Ng2Router.CanActivate { + constructor( + private readonly router: Ng2Router.Router, + private readonly authService: AuthService + ) { + } + + public canActivate(route: Ng2Router.ActivatedRouteSnapshot, state: Ng2Router.RouterStateSnapshot): boolean { + if (state.url !== LOGIN_URL && !this.authService.isAuthenticated) { + this.router.navigate([LOGIN_URL]); + return false; + } + + return true; + } +} \ No newline at end of file diff --git a/src/PinkParrot/app/shared/index.ts b/src/PinkParrot/app/shared/index.ts new file mode 100644 index 000000000..08ff9827f --- /dev/null +++ b/src/PinkParrot/app/shared/index.ts @@ -0,0 +1,9 @@ +/* + *PinkParrot CMS + * + * @license + * Copyright (c) Sebastian Stehle. All rights reserved + */ + +export * from './guards/auth.guard'; +export * from './services/auth.service'; \ No newline at end of file diff --git a/src/PinkParrot/app/shared/services/auth.service.ts b/src/PinkParrot/app/shared/services/auth.service.ts new file mode 100644 index 000000000..5e259c7fd --- /dev/null +++ b/src/PinkParrot/app/shared/services/auth.service.ts @@ -0,0 +1,74 @@ +/* + *PinkParrot CMS + * + * @license + * Copyright (c) Sebastian Stehle. All rights reserved + */ + +import * as Ng2 from '@angular/core'; + +import { + Log, + User, + UserManager +} from 'oidc-client'; + +import { Observable } from 'rxjs'; + +import { ApiUrlConfig } from './../../framework'; + +@Ng2.Injectable() +export class AuthService { + private readonly userManager: UserManager; + private currentUser: User | null = null; + + public get user(): User | null { + return this.currentUser; + } + + public get isAuthenticated() { + return this.currentUser; + } + + constructor(apiUrl: ApiUrlConfig) { + Log.logger = console; + + this.userManager = new UserManager({ + client_id: 'management-portal', + silent_redirect_uri: apiUrl.buildUrl('account/client-silent'), + popup_redirect_uri: apiUrl.buildUrl('account/client-popup'), + authority: apiUrl.buildUrl('/'), + }); + + this.userManager.getUser() + .then((user) => { + this.currentUser = user; + }) + .catch((err) => { + this.currentUser = null; + }); + + this.userManager.events.addUserUnloaded(() => { + this.currentUser = null; + }); + } + + public login(): Observable { + let userPromise = + this.userManager.signinSilent() + .then(user => { + if (user) { + return user; + } else { + return this.userManager.signinPopup(); + } + }) + .catch(() => this.userManager.signinPopup()); + + return Observable.fromPromise(userPromise); + } + + public logout(): Observable { + return Observable.fromPromise(this.userManager.signoutRedirectCallback()); + } +} \ No newline at end of file diff --git a/src/PinkParrot/appsettings.json b/src/PinkParrot/appsettings.json index fc6fbd273..f406dbcae 100644 --- a/src/PinkParrot/appsettings.json +++ b/src/PinkParrot/appsettings.json @@ -11,5 +11,10 @@ "username": "admin", "password": "changeit" } + }, + "identity": { + "googleClient": "900148737461-7e3hv5425idg7ql9vlhfubo8hjm7d94h.apps.googleusercontent.com", + "googleSecret": "J1yE5kbw_NsAc759pGSU-WPn", + "baseUrl": "http://localhost:5000" } } \ No newline at end of file diff --git a/src/PinkParrot/package.json b/src/PinkParrot/package.json index 6da04437d..a0a20bd79 100644 --- a/src/PinkParrot/package.json +++ b/src/PinkParrot/package.json @@ -8,6 +8,7 @@ "test": "karma start", "test:coverage": "karma start karma.coverage.conf.js", "test:clean": "rimraf _test-output", + "dev": "webpack-dev-server --inline --hot --port 3000", "build": "webpack --config app-config/webpack.prod.js --progress --display-error-details", "build:clean": "rimraf wwwroot/build" }, @@ -22,13 +23,14 @@ "@angular/router": "3.1.0", "bootstrap": "^4.0.0-alpha.2", "core-js": "^2.4.1", + "font-awesome": "^4.6.3", + "immutable": "^3.8.1", + "mousetrap": "^1.6.0", + "oidc-client": "^1.2.0", "reflect-metadata": "^0.1.3", "rxjs": "5.0.0-beta.12", "systemjs": "0.19.38", - "zone.js": "^0.6.23", - "font-awesome": "^4.6.3", - "immutable": "^3.8.1", - "mousetrap": "^1.6.0" + "zone.js": "^0.6.23" }, "devDependencies": { "@angularclass/conventions-loader": "^1.0.7", @@ -73,4 +75,4 @@ "webpack-dev-server": "^1.14.1", "webpack-merge": "^0.14.0" } -} \ No newline at end of file +} diff --git a/src/PinkParrot/project.json b/src/PinkParrot/project.json index d59db9696..e65bb8f17 100644 --- a/src/PinkParrot/project.json +++ b/src/PinkParrot/project.json @@ -2,6 +2,13 @@ "dependencies": { "Autofac": "4.1.1", "Autofac.Extensions.DependencyInjection": "4.0.0", + "IdentityServer4": "1.0.0-rc2", + "IdentityServer4.AspNetIdentity": "1.0.0-rc2", + "IdentityServer4.AccessTokenValidation": "1.0.1-rc2", + "Microsoft.AspNetCore.Identity": "1.0.0", + "Microsoft.AspNetCore.Authentication.Cookies": "1.0.0", + "Microsoft.AspNetCore.Authentication.Google": "1.0.0", + "Microsoft.AspNetCore.Authentication.OpenIdConnect": "1.0.0", "Microsoft.AspNetCore.Diagnostics": "1.0.0", "Microsoft.AspNetCore.Mvc": "1.0.1", "Microsoft.AspNetCore.Razor.Tools": { diff --git a/src/PinkParrot/wwwroot/scripts/oidc-client.min.js b/src/PinkParrot/wwwroot/scripts/oidc-client.min.js new file mode 100644 index 000000000..a31652edc --- /dev/null +++ b/src/PinkParrot/wwwroot/scripts/oidc-client.min.js @@ -0,0 +1,77 @@ +var Oidc=function(t){function e(r){if(n[r])return n[r].exports;var i=n[r]={exports:{},id:r,loaded:!1};return t[r].call(i.exports,i,i.exports,e),i.loaded=!0,i.exports}var n={};return e.m=t,e.c=n,e.p="",e(0)}([function(t,e,n){n(1),t.exports=n(291)},function(t,e,n){(function(t){"use strict";function e(t,e,n){t[e]||Object[r](t,e,{writable:!0,configurable:!0,value:n})}if(n(2),n(286),n(288),t._babelPolyfill)throw new Error("only one instance of babel-polyfill is allowed");t._babelPolyfill=!0;var r="defineProperty";e(String.prototype,"padLeft","".padStart),e(String.prototype,"padRight","".padEnd),"pop,reverse,shift,keys,values,entries,indexOf,every,some,forEach,map,filter,find,findIndex,includes,join,slice,concat,push,splice,unshift,sort,lastIndexOf,reduce,reduceRight,copyWithin,fill".split(",").forEach(function(t){[][t]&&e(Array,t,Function.call.bind([][t]))})}).call(e,function(){return this}())},function(t,e,n){n(3),n(50),n(51),n(52),n(53),n(55),n(58),n(59),n(60),n(61),n(62),n(63),n(64),n(65),n(66),n(68),n(70),n(72),n(74),n(77),n(78),n(79),n(83),n(85),n(87),n(91),n(92),n(93),n(94),n(96),n(97),n(98),n(99),n(100),n(101),n(102),n(104),n(105),n(106),n(108),n(109),n(110),n(112),n(113),n(114),n(115),n(116),n(117),n(118),n(119),n(120),n(121),n(122),n(123),n(124),n(125),n(130),n(131),n(135),n(136),n(137),n(138),n(140),n(141),n(142),n(143),n(144),n(145),n(146),n(147),n(148),n(149),n(150),n(151),n(152),n(153),n(154),n(155),n(156),n(158),n(159),n(164),n(165),n(167),n(168),n(169),n(172),n(173),n(174),n(175),n(176),n(178),n(179),n(180),n(181),n(184),n(186),n(187),n(188),n(190),n(192),n(194),n(195),n(196),n(198),n(199),n(200),n(201),n(207),n(210),n(211),n(213),n(214),n(217),n(218),n(221),n(222),n(223),n(224),n(225),n(226),n(227),n(228),n(229),n(230),n(231),n(232),n(233),n(234),n(235),n(236),n(237),n(238),n(239),n(241),n(242),n(243),n(244),n(245),n(246),n(248),n(249),n(250),n(251),n(252),n(253),n(255),n(256),n(258),n(259),n(260),n(261),n(264),n(265),n(266),n(267),n(268),n(269),n(270),n(271),n(273),n(274),n(275),n(276),n(277),n(278),n(279),n(280),n(281),n(284),n(285),t.exports=n(5)},function(t,e,n){"use strict";var r=n(4),i=n(5),s=n(6),o=n(7),a=n(9),u=n(18),c=n(22).KEY,f=n(8),h=n(23),l=n(24),d=n(19),p=n(25),g=n(26),y=n(39),v=n(42),m=n(12),S=n(29),b=n(16),w=n(17),E=n(43),x=n(46),_=n(48),A=n(11),F=_.f,P=A.f,O=x.f,C=r.Symbol,I=r.JSON,T=I&&I.stringify,j=!1,R="prototype",D=p("_hidden"),H=p("toPrimitive"),k={}.propertyIsEnumerable,N=h("symbol-registry"),B=h("symbols"),M=Object[R],V="function"==typeof C,L=r.QObject,K=o&&f(function(){return 7!=E(P({},"a",{get:function(){return P(this,"a",{value:7}).a}})).a})?function(t,e,n){var r=F(M,e);r&&delete M[e],P(t,e,n),r&&t!==M&&P(M,e,r)}:P,U=function(t){var e=B[t]=E(C[R]);return e._k=t,o&&j&&K(M,t,{configurable:!0,set:function(e){s(this,D)&&s(this[D],t)&&(this[D][t]=!1),K(this,t,w(1,e))}}),e},q=V&&"symbol"==typeof C.iterator?function(t){return"symbol"==typeof t}:function(t){return t instanceof C},W=function(t,e,n){return m(t),e=b(e,!0),m(n),s(B,e)?(n.enumerable?(s(t,D)&&t[D][e]&&(t[D][e]=!1),n=E(n,{enumerable:w(0,!1)})):(s(t,D)||P(t,D,w(1,{})),t[D][e]=!0),K(t,e,n)):P(t,e,n)},J=function(t,e){m(t);for(var n,r=y(e=S(e)),i=0,s=r.length;s>i;)W(t,n=r[i++],e[n]);return t},z=function(t,e){return void 0===e?E(t):J(E(t),e)},Y=function(t){var e=k.call(this,t=b(t,!0));return e||!s(this,t)||!s(B,t)||s(this,D)&&this[D][t]?e:!0},G=function(t,e){var n=F(t=S(t),e=b(e,!0));return!n||!s(B,e)||s(t,D)&&t[D][e]||(n.enumerable=!0),n},X=function(t){for(var e,n=O(S(t)),r=[],i=0;n.length>i;)s(B,e=n[i++])||e==D||e==c||r.push(e);return r},$=function(t){for(var e,n=O(S(t)),r=[],i=0;n.length>i;)s(B,e=n[i++])&&r.push(B[e]);return r},Z=function(t){if(void 0!==t&&!q(t)){for(var e,n,r=[t],i=1;arguments.length>i;)r.push(arguments[i++]);return e=r[1],"function"==typeof e&&(n=e),!n&&v(e)||(e=function(t,e){return n&&(e=n.call(this,t,e)),q(e)?void 0:e}),r[1]=e,T.apply(I,r)}},Q=f(function(){var t=C();return"[null]"!=T([t])||"{}"!=T({a:t})||"{}"!=T(Object(t))});V||(C=function(){if(this instanceof C)throw TypeError("Symbol is not a constructor!");return U(d(arguments.length>0?arguments[0]:void 0))},u(C[R],"toString",function(){return this._k}),_.f=G,A.f=W,n(47).f=x.f=X,n(41).f=Y,n(40).f=$,o&&!n(49)&&u(M,"propertyIsEnumerable",Y,!0)),a(a.G+a.W+a.F*!V,{Symbol:C});for(var tt="hasInstance,isConcatSpreadable,iterator,match,replace,search,species,split,toPrimitive,toStringTag,unscopables".split(","),et=0;tt.length>et;){var nt=tt[et++],rt=i.Symbol,it=p(nt);nt in rt||P(rt,nt,{value:V?it:U(it)})}L&&L[R]&&L[R].findChild||(j=!0),a(a.S+a.F*!V,"Symbol",{"for":function(t){return s(N,t+="")?N[t]:N[t]=C(t)},keyFor:function(t){if(q(t))return g(N,t);throw TypeError(t+" is not a symbol!")},useSetter:function(){j=!0},useSimple:function(){j=!1}}),a(a.S+a.F*!V,"Object",{create:z,defineProperty:W,defineProperties:J,getOwnPropertyDescriptor:G,getOwnPropertyNames:X,getOwnPropertySymbols:$}),I&&a(a.S+a.F*(!V||Q),"JSON",{stringify:Z}),C[R][H]||n(10)(C[R],H,C[R].valueOf),l(C,"Symbol"),l(Math,"Math",!0),l(r.JSON,"JSON",!0)},function(t,e){var n=t.exports="undefined"!=typeof window&&window.Math==Math?window:"undefined"!=typeof self&&self.Math==Math?self:Function("return this")();"number"==typeof __g&&(__g=n)},function(t,e){var n=t.exports={version:"2.2.1"};"number"==typeof __e&&(__e=n)},function(t,e){var n={}.hasOwnProperty;t.exports=function(t,e){return n.call(t,e)}},function(t,e,n){t.exports=!n(8)(function(){return 7!=Object.defineProperty({},"a",{get:function(){return 7}}).a})},function(t,e){t.exports=function(t){try{return!!t()}catch(e){return!0}}},function(t,e,n){var r=n(4),i=n(5),s=n(10),o=n(18),a=n(20),u="prototype",c=function(t,e,n){var f,h,l,d,p=t&c.F,g=t&c.G,y=t&c.S,v=t&c.P,m=t&c.B,S=g?r:y?r[e]||(r[e]={}):(r[e]||{})[u],b=g?i:i[e]||(i[e]={}),w=b[u]||(b[u]={});g&&(n=e);for(f in n)h=!p&&S&&void 0!==S[f],l=(h?S:n)[f],d=m&&h?a(l,r):v&&"function"==typeof l?a(Function.call,l):l,S&&o(S,f,l,t&c.U),b[f]!=l&&s(b,f,d),v&&w[f]!=l&&(w[f]=l)};r.core=i,c.F=1,c.G=2,c.S=4,c.P=8,c.B=16,c.W=32,c.U=64,c.R=128,t.exports=c},function(t,e,n){var r=n(11),i=n(17);t.exports=n(7)?function(t,e,n){return r.f(t,e,i(1,n))}:function(t,e,n){return t[e]=n,t}},function(t,e,n){var r=n(12),i=n(14),s=n(16),o=Object.defineProperty;e.f=n(7)?Object.defineProperty:function(t,e,n){if(r(t),e=s(e,!0),r(n),i)try{return o(t,e,n)}catch(a){}if("get"in n||"set"in n)throw TypeError("Accessors not supported!");return"value"in n&&(t[e]=n.value),t}},function(t,e,n){var r=n(13);t.exports=function(t){if(!r(t))throw TypeError(t+" is not an object!");return t}},function(t,e){t.exports=function(t){return"object"==typeof t?null!==t:"function"==typeof t}},function(t,e,n){t.exports=!n(7)&&!n(8)(function(){return 7!=Object.defineProperty(n(15)("div"),"a",{get:function(){return 7}}).a})},function(t,e,n){var r=n(13),i=n(4).document,s=r(i)&&r(i.createElement);t.exports=function(t){return s?i.createElement(t):{}}},function(t,e,n){var r=n(13);t.exports=function(t,e){if(!r(t))return t;var n,i;if(e&&"function"==typeof(n=t.toString)&&!r(i=n.call(t)))return i;if("function"==typeof(n=t.valueOf)&&!r(i=n.call(t)))return i;if(!e&&"function"==typeof(n=t.toString)&&!r(i=n.call(t)))return i;throw TypeError("Can't convert object to primitive value")}},function(t,e){t.exports=function(t,e){return{enumerable:!(1&t),configurable:!(2&t),writable:!(4&t),value:e}}},function(t,e,n){var r=n(4),i=n(10),s=n(6),o=n(19)("src"),a="toString",u=Function[a],c=(""+u).split(a);n(5).inspectSource=function(t){return u.call(t)},(t.exports=function(t,e,n,a){var u="function"==typeof n;u&&(s(n,"name")||i(n,"name",e)),t[e]!==n&&(u&&(s(n,o)||i(n,o,t[e]?""+t[e]:c.join(String(e)))),t===r?t[e]=n:a?t[e]?t[e]=n:i(t,e,n):(delete t[e],i(t,e,n)))})(Function.prototype,a,function(){return"function"==typeof this&&this[o]||u.call(this)})},function(t,e){var n=0,r=Math.random();t.exports=function(t){return"Symbol(".concat(void 0===t?"":t,")_",(++n+r).toString(36))}},function(t,e,n){var r=n(21);t.exports=function(t,e,n){if(r(t),void 0===e)return t;switch(n){case 1:return function(n){return t.call(e,n)};case 2:return function(n,r){return t.call(e,n,r)};case 3:return function(n,r,i){return t.call(e,n,r,i)}}return function(){return t.apply(e,arguments)}}},function(t,e){t.exports=function(t){if("function"!=typeof t)throw TypeError(t+" is not a function!");return t}},function(t,e,n){var r=n(19)("meta"),i=n(13),s=n(6),o=n(11).f,a=0,u=Object.isExtensible||function(){return!0},c=!n(8)(function(){return u(Object.preventExtensions({}))}),f=function(t){o(t,r,{value:{i:"O"+ ++a,w:{}}})},h=function(t,e){if(!i(t))return"symbol"==typeof t?t:("string"==typeof t?"S":"P")+t;if(!s(t,r)){if(!u(t))return"F";if(!e)return"E";f(t)}return t[r].i},l=function(t,e){if(!s(t,r)){if(!u(t))return!0;if(!e)return!1;f(t)}return t[r].w},d=function(t){return c&&p.NEED&&u(t)&&!s(t,r)&&f(t),t},p=t.exports={KEY:r,NEED:!1,fastKey:h,getWeak:l,onFreeze:d}},function(t,e,n){var r=n(4),i="__core-js_shared__",s=r[i]||(r[i]={});t.exports=function(t){return s[t]||(s[t]={})}},function(t,e,n){var r=n(11).f,i=n(6),s=n(25)("toStringTag");t.exports=function(t,e,n){t&&!i(t=n?t:t.prototype,s)&&r(t,s,{configurable:!0,value:e})}},function(t,e,n){var r=n(23)("wks"),i=n(19),s=n(4).Symbol,o="function"==typeof s;t.exports=function(t){return r[t]||(r[t]=o&&s[t]||(o?s:i)("Symbol."+t))}},function(t,e,n){var r=n(27),i=n(29);t.exports=function(t,e){for(var n,s=i(t),o=r(s),a=o.length,u=0;a>u;)if(s[n=o[u++]]===e)return n}},function(t,e,n){var r=n(28),i=n(38);t.exports=Object.keys||function(t){return r(t,i)}},function(t,e,n){var r=n(6),i=n(29),s=n(33)(!1),o=n(37)("IE_PROTO");t.exports=function(t,e){var n,a=i(t),u=0,c=[];for(n in a)n!=o&&r(a,n)&&c.push(n);for(;e.length>u;)r(a,n=e[u++])&&(~s(c,n)||c.push(n));return c}},function(t,e,n){var r=n(30),i=n(32);t.exports=function(t){return r(i(t))}},function(t,e,n){var r=n(31);t.exports=Object("z").propertyIsEnumerable(0)?Object:function(t){return"String"==r(t)?t.split(""):Object(t)}},function(t,e){var n={}.toString;t.exports=function(t){return n.call(t).slice(8,-1)}},function(t,e){t.exports=function(t){if(void 0==t)throw TypeError("Can't call method on "+t);return t}},function(t,e,n){var r=n(29),i=n(34),s=n(36);t.exports=function(t){return function(e,n,o){var a,u=r(e),c=i(u.length),f=s(o,c);if(t&&n!=n){for(;c>f;)if(a=u[f++],a!=a)return!0}else for(;c>f;f++)if((t||f in u)&&u[f]===n)return t||f;return!t&&-1}}},function(t,e,n){var r=n(35),i=Math.min;t.exports=function(t){return t>0?i(r(t),9007199254740991):0}},function(t,e){var n=Math.ceil,r=Math.floor;t.exports=function(t){return isNaN(t=+t)?0:(t>0?r:n)(t)}},function(t,e,n){var r=n(35),i=Math.max,s=Math.min;t.exports=function(t,e){return t=r(t),0>t?i(t+e,0):s(t,e)}},function(t,e,n){var r=n(23)("keys"),i=n(19);t.exports=function(t){return r[t]||(r[t]=i(t))}},function(t,e){t.exports="constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString,toString,valueOf".split(",")},function(t,e,n){var r=n(27),i=n(40),s=n(41);t.exports=function(t){var e=r(t),n=i.f;if(n)for(var o,a=n(t),u=s.f,c=0;a.length>c;)u.call(t,o=a[c++])&&e.push(o);return e}},function(t,e){e.f=Object.getOwnPropertySymbols},function(t,e){e.f={}.propertyIsEnumerable},function(t,e,n){var r=n(31);t.exports=Array.isArray||function(t){return"Array"==r(t)}},function(t,e,n){var r=n(12),i=n(44),s=n(38),o=n(37)("IE_PROTO"),a=function(){},u="prototype",c=function(){var t,e=n(15)("iframe"),r=s.length,i=">";for(e.style.display="none",n(45).appendChild(e),e.src="javascript:",t=e.contentWindow.document,t.open(),t.write("