mirror of https://github.com/Squidex/squidex.git
12 changed files with 599 additions and 174 deletions
@ -0,0 +1,96 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschränkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Globalization; |
|||
using Jint; |
|||
using Jint.Native; |
|||
using Jint.Native.Date; |
|||
using Jint.Runtime; |
|||
using Jint.Runtime.Interop; |
|||
using Squidex.Infrastructure; |
|||
|
|||
namespace Squidex.Domain.Apps.Core.Scripting |
|||
{ |
|||
internal static class JintHelpers |
|||
{ |
|||
public static Engine AddHelpers(this Engine engine) |
|||
{ |
|||
engine.SetValue("slugify", new ClrFunctionInstance(engine, "slugify", Slugify)); |
|||
engine.SetValue("formatTime", new ClrFunctionInstance(engine, "formatTime", FormatDate)); |
|||
engine.SetValue("formatDate", new ClrFunctionInstance(engine, "formatDate", FormatDate)); |
|||
|
|||
return engine; |
|||
} |
|||
|
|||
public static Engine AddFormatters(this Engine engine, Dictionary<string, Func<string>>? customFormatters = null) |
|||
{ |
|||
if (customFormatters != null) |
|||
{ |
|||
foreach (var (key, value) in customFormatters) |
|||
{ |
|||
engine.SetValue(key, Safe(value)); |
|||
} |
|||
} |
|||
|
|||
engine.AddHelpers(); |
|||
|
|||
return engine; |
|||
} |
|||
|
|||
private static Func<string> Safe(Func<string> func) |
|||
{ |
|||
return () => |
|||
{ |
|||
try |
|||
{ |
|||
return func(); |
|||
} |
|||
catch |
|||
{ |
|||
return "null"; |
|||
} |
|||
}; |
|||
} |
|||
|
|||
private static JsValue Slugify(JsValue thisObject, JsValue[] arguments) |
|||
{ |
|||
try |
|||
{ |
|||
var stringInput = TypeConverter.ToString(arguments.At(0)); |
|||
var single = false; |
|||
|
|||
if (arguments.Length > 1) |
|||
{ |
|||
single = TypeConverter.ToBoolean(arguments.At(1)); |
|||
} |
|||
|
|||
return stringInput.Slugify(null, single); |
|||
} |
|||
catch |
|||
{ |
|||
return JsValue.Undefined; |
|||
} |
|||
} |
|||
|
|||
private static JsValue FormatDate(JsValue thisObject, JsValue[] arguments) |
|||
{ |
|||
try |
|||
{ |
|||
var dateValue = ((DateInstance)arguments.At(0)).ToDateTime(); |
|||
var dateFormat = TypeConverter.ToString(arguments.At(1)); |
|||
|
|||
return dateValue.ToString(dateFormat, CultureInfo.InvariantCulture); |
|||
} |
|||
catch |
|||
{ |
|||
return JsValue.Undefined; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,98 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Net.Http; |
|||
using System.Threading; |
|||
using System.Threading.Tasks; |
|||
using Jint; |
|||
using Jint.Native; |
|||
using Jint.Native.Json; |
|||
using Jint.Runtime; |
|||
using Squidex.Infrastructure.Tasks; |
|||
|
|||
namespace Squidex.Domain.Apps.Core.Scripting |
|||
{ |
|||
internal sealed class JintHttp |
|||
{ |
|||
private delegate void GetJsonDelegate(string url, Action<JsValue> callback, JsValue? headers = null); |
|||
private readonly IHttpClientFactory httpClientFactory; |
|||
private readonly Action<Exception> exceptionHandler; |
|||
private readonly CancellationToken cancellationToken; |
|||
private JsonParser parser; |
|||
|
|||
public JintHttp(IHttpClientFactory httpClientFactory, CancellationToken cancellationToken, Action<Exception> exceptionHandler) |
|||
{ |
|||
this.httpClientFactory = httpClientFactory; |
|||
this.exceptionHandler = exceptionHandler; |
|||
this.cancellationToken = cancellationToken; |
|||
} |
|||
|
|||
public Engine Add(Engine engine) |
|||
{ |
|||
parser = new JsonParser(engine); |
|||
|
|||
engine.SetValue("getJSON", new GetJsonDelegate(GetJson)); |
|||
|
|||
return engine; |
|||
} |
|||
|
|||
private void GetJson(string url, Action<JsValue> callback, JsValue? headers) |
|||
{ |
|||
GetJSONAsync(url, callback, headers).Forget(); |
|||
} |
|||
|
|||
private async Task GetJSONAsync(string url, Action<JsValue> callback, JsValue? headers) |
|||
{ |
|||
try |
|||
{ |
|||
using (var httpClient = httpClientFactory.CreateClient()) |
|||
{ |
|||
if (!Uri.TryCreate(url, UriKind.Absolute, out var uri)) |
|||
{ |
|||
throw new ArgumentException("Url must be an absolute URL"); |
|||
} |
|||
|
|||
var request = new HttpRequestMessage(HttpMethod.Get, uri); |
|||
|
|||
if (headers != null && headers.Type == Types.Object) |
|||
{ |
|||
var obj = headers.AsObject(); |
|||
|
|||
foreach (var (key, property) in obj.GetOwnProperties()) |
|||
{ |
|||
var value = TypeConverter.ToString(property.Value); |
|||
|
|||
if (!string.IsNullOrWhiteSpace(key)) |
|||
{ |
|||
request.Headers.TryAddWithoutValidation(key, value ?? string.Empty); |
|||
} |
|||
} |
|||
} |
|||
|
|||
var response = await httpClient.SendAsync(request, cancellationToken); |
|||
|
|||
response.EnsureSuccessStatusCode(); |
|||
|
|||
cancellationToken.ThrowIfCancellationRequested(); |
|||
|
|||
var responseString = await response.Content.ReadAsStringAsync(); |
|||
|
|||
cancellationToken.ThrowIfCancellationRequested(); |
|||
|
|||
var responseJson = parser.Parse(responseString); |
|||
|
|||
callback(responseJson); |
|||
} |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
exceptionHandler(ex); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,53 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using Jint; |
|||
using Jint.Native.Object; |
|||
using Squidex.Domain.Apps.Core.Scripting.ContentWrapper; |
|||
|
|||
namespace Squidex.Domain.Apps.Core.Scripting |
|||
{ |
|||
internal static class ScriptContextExtensions |
|||
{ |
|||
public static Engine AddContext(this Engine engine, ScriptContext context) |
|||
{ |
|||
var contextInstance = new ObjectInstance(engine); |
|||
|
|||
if (context.Data != null) |
|||
{ |
|||
contextInstance.FastAddProperty("data", new ContentDataObject(engine, context.Data), true, true, true); |
|||
} |
|||
|
|||
if (context.DataOld != null) |
|||
{ |
|||
contextInstance.FastAddProperty("oldData", new ContentDataObject(engine, context.DataOld), true, true, true); |
|||
} |
|||
|
|||
if (context.User != null) |
|||
{ |
|||
contextInstance.FastAddProperty("user", JintUser.Create(engine, context.User), false, true, false); |
|||
} |
|||
|
|||
if (!string.IsNullOrWhiteSpace(context.Operation)) |
|||
{ |
|||
contextInstance.FastAddProperty("operation", context.Operation, false, false, false); |
|||
} |
|||
|
|||
contextInstance.FastAddProperty("status", context.Status.ToString(), false, false, false); |
|||
|
|||
if (context.StatusOld != default) |
|||
{ |
|||
contextInstance.FastAddProperty("oldStatus", context.StatusOld.ToString(), false, false, false); |
|||
} |
|||
|
|||
engine.SetValue("ctx", contextInstance); |
|||
engine.SetValue("context", contextInstance); |
|||
|
|||
return engine; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,48 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using Jint; |
|||
using Squidex.Infrastructure; |
|||
using Squidex.Infrastructure.Validation; |
|||
|
|||
namespace Squidex.Domain.Apps.Core.Scripting |
|||
{ |
|||
internal static class ScriptOperations |
|||
{ |
|||
public static Engine AddDisallow(this Engine engine) |
|||
{ |
|||
engine.SetValue("disallow", new DisallowDelegate(Disallow)); |
|||
|
|||
return engine; |
|||
} |
|||
|
|||
private delegate void DisallowDelegate(string? message); |
|||
|
|||
private static void Disallow(string? message = null) |
|||
{ |
|||
message = !string.IsNullOrWhiteSpace(message) ? message : "Not allowed"; |
|||
|
|||
throw new DomainForbiddenException(message); |
|||
} |
|||
|
|||
public static Engine AddReject(this Engine engine) |
|||
{ |
|||
engine.SetValue("reject", new RejectDelegate(Reject)); |
|||
|
|||
return engine; |
|||
} |
|||
|
|||
private delegate void RejectDelegate(string? message); |
|||
|
|||
private static void Reject(string? message = null) |
|||
{ |
|||
var errors = !string.IsNullOrWhiteSpace(message) ? new[] { new ValidationError(message) } : null; |
|||
|
|||
throw new ValidationException("Script rejected the operation.", errors); |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue