From 210d5ed8c4c10c42a138c6e45128314dbadbed59 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Thu, 3 Jan 2019 00:00:46 +0100 Subject: [PATCH] Full compatibility. --- .../HandleRules/RuleEventFormatter.cs | 55 +++++-------------- .../Scripting/JintUser.cs | 6 +- .../Rules/EventEnricher.cs | 12 +++- src/Squidex.Shared/Users/ClientUser.cs | 54 ++++++++++++++++++ .../HandleRules/RuleEventFormatterTests.cs | 42 +++++++------- 5 files changed, 106 insertions(+), 63 deletions(-) create mode 100644 src/Squidex.Shared/Users/ClientUser.cs diff --git a/src/Squidex.Domain.Apps.Core.Operations/HandleRules/RuleEventFormatter.cs b/src/Squidex.Domain.Apps.Core.Operations/HandleRules/RuleEventFormatter.cs index c01feff2e..d2f70267e 100644 --- a/src/Squidex.Domain.Apps.Core.Operations/HandleRules/RuleEventFormatter.cs +++ b/src/Squidex.Domain.Apps.Core.Operations/HandleRules/RuleEventFormatter.cs @@ -22,7 +22,7 @@ namespace Squidex.Domain.Apps.Core.HandleRules { public class RuleEventFormatter { - private const string Undefined = "null"; + private const string Fallback = "null"; private const string ScriptSuffix = ")"; private const string ScriptPrefix = "Script("; private static readonly char[] ContentPlaceholderStartOld = "CONTENT_DATA".ToCharArray(); @@ -84,7 +84,8 @@ namespace Squidex.Domain.Apps.Core.HandleRules var customFunctions = new Dictionary> { - ["contentUrl"] = () => ContentUrl(@event) + ["contentUrl"] = () => ContentUrl(@event), + ["contentAction"] = () => ContentAction(@event) }; return scriptEngine.Interpolate("event", @event, script, customFunctions); @@ -145,7 +146,7 @@ namespace Squidex.Domain.Apps.Core.HandleRules } else { - sb.Append(Undefined); + sb.Append(Fallback); } current = current.Slice(match.Length + 1); @@ -187,7 +188,7 @@ namespace Squidex.Domain.Apps.Core.HandleRules return schemaEvent.SchemaId.Id.ToString(); } - return Undefined; + return Fallback; } private static string SchemaName(EnrichedEvent @event) @@ -197,7 +198,7 @@ namespace Squidex.Domain.Apps.Core.HandleRules return schemaEvent.SchemaId.Name; } - return Undefined; + return Fallback; } private static string ContentAction(EnrichedEvent @event) @@ -207,7 +208,7 @@ namespace Squidex.Domain.Apps.Core.HandleRules return contentEvent.Type.ToString(); } - return Undefined; + return Fallback; } private string ContentUrl(EnrichedEvent @event) @@ -217,43 +218,17 @@ namespace Squidex.Domain.Apps.Core.HandleRules return urlGenerator.GenerateContentUIUrl(contentEvent.AppId, contentEvent.SchemaId, contentEvent.Id); } - return Undefined; + return Fallback; } private static string UserName(EnrichedEvent @event) { - if (@event.Actor != null) - { - if (@event.Actor.Type.Equals(RefTokenType.Client, StringComparison.OrdinalIgnoreCase)) - { - return @event.Actor.ToString(); - } - - if (@event.User != null) - { - return @event.User.DisplayName(); - } - } - - return Undefined; + return @event.User?.DisplayName() ?? Fallback; } private static string UserEmail(EnrichedEvent @event) { - if (@event.Actor != null) - { - if (@event.Actor.Type.Equals(RefTokenType.Client, StringComparison.OrdinalIgnoreCase)) - { - return @event.Actor.ToString(); - } - - if (@event.User != null) - { - return @event.User.Email; - } - } - - return Undefined; + return @event.User?.Email ?? Fallback; } private static string CalculateData(NamedContentData data, Match match) @@ -269,12 +244,12 @@ namespace Squidex.Domain.Apps.Core.HandleRules if (!data.TryGetValue(path[0], out var field)) { - return Undefined; + return Fallback; } if (!field.TryGetValue(path[1], out var value)) { - return Undefined; + return Fallback; } for (var j = 2; j < path.Length; j++) @@ -290,16 +265,16 @@ namespace Squidex.Domain.Apps.Core.HandleRules } else { - return Undefined; + return Fallback; } } if (value == null || value.Type == JsonValueType.Null) { - return Undefined; + return Fallback; } - return value.ToString() ?? Undefined; + return value.ToString() ?? Fallback; } } } diff --git a/src/Squidex.Domain.Apps.Core.Operations/Scripting/JintUser.cs b/src/Squidex.Domain.Apps.Core.Operations/Scripting/JintUser.cs index 083e028c1..3d2177d4b 100644 --- a/src/Squidex.Domain.Apps.Core.Operations/Scripting/JintUser.cs +++ b/src/Squidex.Domain.Apps.Core.Operations/Scripting/JintUser.cs @@ -22,7 +22,11 @@ namespace Squidex.Domain.Apps.Core.Scripting public static ObjectWrapper Create(Engine engine, IUser user) { - return CreateUser(engine, user.Id, false, user.Email, user.DisplayName(), user.Claims); + var clientId = user.Claims.FirstOrDefault(x => x.Type == OpenIdClaims.ClientId)?.Value; + + var isClient = !string.IsNullOrWhiteSpace(clientId); + + return CreateUser(engine, user.Id, isClient, user.Email, user.DisplayName(), user.Claims); } public static ObjectWrapper Create(Engine engine, ClaimsPrincipal principal) diff --git a/src/Squidex.Domain.Apps.Entities/Rules/EventEnricher.cs b/src/Squidex.Domain.Apps.Entities/Rules/EventEnricher.cs index c2a126881..e49411069 100644 --- a/src/Squidex.Domain.Apps.Entities/Rules/EventEnricher.cs +++ b/src/Squidex.Domain.Apps.Entities/Rules/EventEnricher.cs @@ -170,14 +170,22 @@ namespace Squidex.Domain.Apps.Entities.Rules { x.AbsoluteExpirationRelativeToNow = UserCacheDuration; + IUser user = null; try { - return await userResolver.FindByIdOrEmailAsync(actor.Identifier); + user = await userResolver.FindByIdOrEmailAsync(actor.Identifier); } catch { - return null; + user = null; } + + if (user == null && actor.Type.Equals(RefTokenType.Client, StringComparison.OrdinalIgnoreCase)) + { + user = new ClientUser(actor); + } + + return user; }); } } diff --git a/src/Squidex.Shared/Users/ClientUser.cs b/src/Squidex.Shared/Users/ClientUser.cs new file mode 100644 index 000000000..88f840eff --- /dev/null +++ b/src/Squidex.Shared/Users/ClientUser.cs @@ -0,0 +1,54 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using System.Collections.Generic; +using System.Security.Claims; +using Squidex.Infrastructure; +using Squidex.Infrastructure.Security; +using Squidex.Shared.Identity; + +namespace Squidex.Shared.Users +{ + public sealed class ClientUser : IUser + { + private readonly RefToken token; + private readonly List claims; + + public ClientUser(RefToken token) + { + Guard.NotNull(token, nameof(token)); + + this.token = token; + + claims = new List + { + new Claim(OpenIdClaims.ClientId, token.Identifier), + new Claim(SquidexClaimTypes.DisplayName, token.ToString()) + }; + } + + public string Id + { + get { return token.Identifier; } + } + + public string Email + { + get { return token.ToString(); } + } + + public bool IsLocked + { + get { return false; } + } + + public IReadOnlyList Claims + { + get { return claims; } + } + } +} diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Operations/HandleRules/RuleEventFormatterTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Operations/HandleRules/RuleEventFormatterTests.cs index 64ca3d93f..2fc91bd32 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/Operations/HandleRules/RuleEventFormatterTests.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/Operations/HandleRules/RuleEventFormatterTests.cs @@ -137,7 +137,7 @@ namespace Squidex.Domain.Apps.Core.Operations.HandleRules [Theory] [InlineData("From $USER_NAME ($USER_EMAIL)")] - [InlineData("Script(`From ${event.user.name} (${event.user.email})`)", Skip = "Not Supported")] + [InlineData("Script(`From ${event.user.name} (${event.user.email})`)")] public void Should_return_null_if_user_is_not_found_with_scripting(string script) { var @event = new EnrichedContentEvent { Actor = new RefToken(RefTokenType.Subject, "123") }; @@ -147,6 +147,18 @@ namespace Squidex.Domain.Apps.Core.Operations.HandleRules Assert.Equal("From null (null)", result); } + [Theory] + [InlineData("From $USER_NAME ($USER_EMAIL)")] + [InlineData("Script(`From ${event.user.name} (${event.user.email})`)")] + public void Should_format_email_and_display_name_from_client(string script) + { + var @event = new EnrichedContentEvent { User = new ClientUser(new RefToken(RefTokenType.Client, "android")) }; + + var result = sut.Format(script, @event); + + Assert.Equal("From client:android (client:android)", result); + } + [Theory] [InlineData("Go to $CONTENT_URL")] [InlineData("Script(`Go to ${contentUrl()}`)")] @@ -175,6 +187,14 @@ namespace Squidex.Domain.Apps.Core.Operations.HandleRules Assert.Equal("Created", sut.Format(script, new EnrichedContentEvent { Type = EnrichedContentEventType.Created })); } + [Theory] + [InlineData("$CONTENT_ACTION")] + [InlineData("Script(contentAction())")] + public void Should_null_when_content_action_not_found(string script) + { + Assert.Equal("null", sut.Format(script, new EnrichedAssetEvent())); + } + [Theory] [InlineData("$CONTENT_DATA.country.iv")] [InlineData("Script(`${event.data.country.iv}`)")] @@ -311,7 +331,7 @@ namespace Squidex.Domain.Apps.Core.Operations.HandleRules [Theory] [InlineData("$CONTENT_DATA.city.iv")] - [InlineData("Script(`${event.data.city.iv}`)", Skip = "Not Supported")] + [InlineData("Script(`${JSON.stringify(event.data.city.iv)}`)")] public void Should_return_json_string_when_object(string script) { var @event = new EnrichedContentEvent @@ -327,23 +347,5 @@ namespace Squidex.Domain.Apps.Core.Operations.HandleRules Assert.Equal("{\"name\":\"Berlin\"}", result); } - - [Theory] - [InlineData("$CONTENT_ACTION")] - public void Should_null_when_content_action_not_found(string script) - { - Assert.Equal("null", sut.Format(script, new EnrichedAssetEvent())); - } - - [Theory] - [InlineData("From $USER_NAME ($USER_EMAIL)")] - public void Should_format_email_and_display_name_from_client(string script) - { - var @event = new EnrichedContentEvent { Actor = new RefToken(RefTokenType.Client, "android") }; - - var result = sut.Format(script, @event); - - Assert.Equal("From client:android (client:android)", result); - } } }