diff --git a/src/Squidex.Domain.Apps.Core.Operations/Scripting/JintUser.cs b/src/Squidex.Domain.Apps.Core.Operations/Scripting/JintUser.cs index 07ab6f0de..36094bd11 100644 --- a/src/Squidex.Domain.Apps.Core.Operations/Scripting/JintUser.cs +++ b/src/Squidex.Domain.Apps.Core.Operations/Scripting/JintUser.cs @@ -16,31 +16,33 @@ namespace Squidex.Domain.Apps.Core.Scripting { public sealed class JintUser : ObjectInstance { + private static readonly char[] ClaimSeparators = { '/', '.', ':' }; + public JintUser(Engine engine, ClaimsPrincipal principal) : base(engine) { - var subjectId = principal.OpenIdSubject(); + var id = principal.OpenIdSubject(); - var isClient = string.IsNullOrWhiteSpace(subjectId); + var isClient = string.IsNullOrWhiteSpace(id); - if (!isClient) - { - FastAddProperty("id", subjectId, false, true, false); - FastAddProperty("isClient", false, false, true, false); - } - else + if (isClient) { - FastAddProperty("id", principal.OpenIdClientId(), false, true, false); - FastAddProperty("isClient", true, false, true, false); + id = principal.OpenIdClientId(); } + FastAddProperty("id", id, false, true, false); + FastAddProperty("isClient", isClient, false, true, false); + FastAddProperty("email", principal.OpenIdEmail(), false, true, false); var claimsInstance = new ObjectInstance(engine); foreach (var group in principal.Claims.GroupBy(x => x.Type)) { - claimsInstance.FastAddProperty(group.Key, engine.Array.Construct(group.Select(x => new JsValue(x.Value)).ToArray()), false, true, false); + var propertyName = group.Key.Split(ClaimSeparators).Last(); + var propertyValue = engine.Array.Construct(group.Select(x => new JsValue(x.Value)).ToArray()); + + claimsInstance.FastAddProperty(propertyName, propertyValue, false, true, false); } FastAddProperty("claims", claimsInstance, false, true, false); diff --git a/src/Squidex/Pipeline/AppResolver.cs b/src/Squidex/Pipeline/AppResolver.cs index 5435b62f3..f6b7d9444 100644 --- a/src/Squidex/Pipeline/AppResolver.cs +++ b/src/Squidex/Pipeline/AppResolver.cs @@ -55,9 +55,12 @@ namespace Squidex.Pipeline return; } - var permissions = - FindByOpenIdSubject(app, user) ?? - FindByOpenIdClient(app, user); + var (role, permissions) = FindByOpenIdSubject(app, user); + + if (permissions == null) + { + (role, permissions) = FindByOpenIdClient(app, user); + } if (permissions == null || permissions.Count == 0) { @@ -74,6 +77,8 @@ namespace Squidex.Pipeline { var identity = user.Identities.First(); + identity.AddClaim(new Claim(ClaimTypes.Role, role)); + foreach (var permission in permissions) { identity.AddClaim(new Claim(SquidexClaimTypes.Permissions, permission.Id)); @@ -91,28 +96,28 @@ namespace Squidex.Pipeline return context.ActionDescriptor.FilterDescriptors.Any(x => x.Filter is AllowAnonymousFilter); } - private static PermissionSet FindByOpenIdClient(IAppEntity app, ClaimsPrincipal user) + private static (string, PermissionSet) FindByOpenIdClient(IAppEntity app, ClaimsPrincipal user) { var clientId = user.GetClientId(); if (clientId != null && app.Clients.TryGetValue(clientId, out var client) && app.Roles.TryGetValue(client.Role, out var role)) { - return role.Permissions; + return (client.Role, role.Permissions); } - return null; + return (null, null); } - private static PermissionSet FindByOpenIdSubject(IAppEntity app, ClaimsPrincipal user) + private static (string, PermissionSet) FindByOpenIdSubject(IAppEntity app, ClaimsPrincipal user) { var subjectId = user.OpenIdSubject(); if (subjectId != null && app.Contributors.TryGetValue(subjectId, out var roleName) && app.Roles.TryGetValue(roleName, out var role)) { - return role.Permissions; + return (roleName, role.Permissions); } - return null; + return (null, null); } } } diff --git a/src/Squidex/app-config/webpack.config.js b/src/Squidex/app-config/webpack.config.js index 0d90b6cca..9079e7ba4 100644 --- a/src/Squidex/app-config/webpack.config.js +++ b/src/Squidex/app-config/webpack.config.js @@ -6,7 +6,9 @@ const plugins = { // https://github.com/webpack-contrib/mini-css-extract-plugin MiniCssExtractPlugin: require('mini-css-extract-plugin'), // https://github.com/dividab/tsconfig-paths-webpack-plugin - TsconfigPathsPlugin: require('tsconfig-paths-webpack-plugin') + TsconfigPathsPlugin: require('tsconfig-paths-webpack-plugin'), + // https://github.com/jrparish/tslint-webpack-plugin + TsLintPlugin: require('tslint-webpack-plugin') }; module.exports = { @@ -56,8 +58,6 @@ module.exports = { loader: 'angular-router-loader' }, { loader: 'angular2-template-loader' - }, { - loader: 'tslint-loader' }], exclude: [/node_modules/] }, { @@ -115,18 +115,6 @@ module.exports = { new webpack.LoaderOptionsPlugin({ options: { - tslint: { - /** - * Run tslint in production build and fail if there is one warning. - * - * See: https://github.com/wbuchwalter/tslint-loader - */ - emitErrors: true, - /** - * Share the configuration file with the IDE - */ - configuration: require('./../tslint.json') - }, htmlLoader: { /** * Define the root for images, so that we can use absolute url's @@ -141,6 +129,14 @@ module.exports = { new webpack.ContextReplacementPlugin(/moment[\/\\]locale$/, /en/), + new plugins.TsLintPlugin({ + files: ['./app/**/*.ts'], + /** + * Path to a configuration file. + */ + config: helpers.root('tslint.json') + }), + /** * Shim additional libraries * diff --git a/src/Squidex/app-config/webpack.test.coverage.js b/src/Squidex/app-config/webpack.test.coverage.js index f4bca1e9f..5e4f8c70b 100644 --- a/src/Squidex/app-config/webpack.test.coverage.js +++ b/src/Squidex/app-config/webpack.test.coverage.js @@ -30,9 +30,7 @@ module.exports = webpackMerge(testConfig, { loader: 'angular-router-loader' }, { loader: 'angular2-template-loader' - }, { - loader: 'tslint-loader' - }], + }], exclude: [/\.(e2e|spec)\.ts$/] }] } diff --git a/src/Squidex/package-lock.json b/src/Squidex/package-lock.json index 3ac986d41..d91aaf932 100644 --- a/src/Squidex/package-lock.json +++ b/src/Squidex/package-lock.json @@ -12213,6 +12213,15 @@ "semver": "^5.3.0" } }, + "tslint-webpack-plugin": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/tslint-webpack-plugin/-/tslint-webpack-plugin-1.3.0.tgz", + "integrity": "sha512-/lGWgmz9TQ7+XdFOrmzRdrpCh96oUt8JmqSzg6RQrjJs+Ga9Fa+pTCWJKlCh7M0ArAyaIKMR5jzLGndqku1m2w==", + "dev": true, + "requires": { + "chalk": "^2.1.0" + } + }, "tsutils": { "version": "2.29.0", "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", diff --git a/src/Squidex/package.json b/src/Squidex/package.json index 20a371c5c..756683eb6 100644 --- a/src/Squidex/package.json +++ b/src/Squidex/package.json @@ -90,8 +90,8 @@ "sass-loader": "7.1.0", "style-loader": "0.23.1", "tsconfig-paths-webpack-plugin": "3.2.0", - "tslint": "5.11.0", - "tslint-loader": "3.6.0", + "tslint": "^5.11.0", + "tslint-webpack-plugin": "^1.3.0", "typemoq": "2.1.0", "typescript": "2.9.1", "uglifyjs-webpack-plugin": "2.0.1", diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Operations/Scripting/JintUserTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Operations/Scripting/JintUserTests.cs index 41105479a..cc32eb797 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/Operations/Scripting/JintUserTests.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/Operations/Scripting/JintUserTests.cs @@ -9,6 +9,7 @@ using System.Security.Claims; using Jint; using Squidex.Domain.Apps.Core.Scripting; using Squidex.Infrastructure.Security; +using Squidex.Shared.Identity; using Xunit; #pragma warning disable xUnit2004 // Do not use equality check to test for boolean conditions @@ -49,6 +50,26 @@ namespace Squidex.Domain.Apps.Core.Operations.Scripting Assert.Equal("hello@squidex.io", GetValue(identity, "user.email")); } + [Fact] + public void Should_simplify_squidex_claims() + { + var identity = new ClaimsIdentity(); + + identity.AddClaim(new Claim(SquidexClaimTypes.PictureUrl, "my-picture")); + + Assert.Equal(new[] { "my-picture" }, GetValue(identity, "user.claims.picture")); + } + + [Fact] + public void Should_simplify_default_claims() + { + var identity = new ClaimsIdentity(); + + identity.AddClaim(new Claim(ClaimTypes.Role, "my-role")); + + Assert.Equal(new[] { "my-role" }, GetValue(identity, "user.claims.role")); + } + [Fact] public void Should_set_claims() {