Add HandlebarsSettings (#1271)

* Add HandlebarsSettings class

* DefaultAllowedHandlebarsHelpers

* HB - 2.5.0-preview-01

* readme

* fix

* readme

* Handlebars.Net.Helpers Version="2.5.0"
This commit is contained in:
Stef Heyenrath
2025-04-23 07:47:37 +02:00
committed by GitHub
parent beabba4064
commit fc0f82db33
13 changed files with 127 additions and 27 deletions

View File

@@ -65,6 +65,17 @@ A breaking change is introduced which is related to System.Linq.Dynamic.Core Dyn
- The `LinqMatcher` is not allowed.
- The [Handlebars.Net.Helpers.DynamicLinq](https://www.nuget.org/packages/Handlebars.Net.Helpers.DynamicLinq) package is not included anymore.
### 1.8.0
Some breaking changes are introduced in this version:
#### Handlebars.Net `File`-helper
By default, the internal Handlebars.Net `File`-helper is not allowed anymore because of potential security issues.
To still enable this feature, you need to set the `AllowedCustomHandlebarHelpers` property to `File` in the `HandlebarsSettings` property in `WireMockServerSettings`.
#### Handlebars.Net `Environment`-helper
By default, the Handlebars.Net `Environment`-helper is not automatically allowed anymore because of potential security issues.
To still enable this feature, you need to add the `Environment` category to the `AllowedHandlebarsHelpers` list-property in the `HandlebarsSettings` property in `WireMockServerSettings`.
---
## :memo: Development

View File

@@ -6,7 +6,7 @@ namespace WireMock.Types;
/// A enum defining the supported Handlebar helpers.
/// </summary>
[Flags]
public enum CustomHandlebarHelpers
public enum CustomHandlebarsHelpers
{
None = 0,

View File

@@ -0,0 +1,50 @@
// Copyright © WireMock.Net
using HandlebarsDotNet.Helpers.Enums;
using JetBrains.Annotations;
using WireMock.Types;
namespace WireMock.Settings;
/// <summary>
/// HandlebarsSettings
/// </summary>
[PublicAPI]
public class HandlebarsSettings
{
internal static readonly Category[] DefaultAllowedHandlebarsHelpers =
[
Category.Boolean,
Category.Constants,
Category.DateTime,
Category.Enumerable,
Category.Humanizer,
Category.JsonPath,
Category.Math,
Category.Object,
Category.Random,
Category.Regex,
Category.String,
Category.Url,
Category.Xeger,
Category.XPath,
Category.Xslt
];
/// <summary>
/// Defines the allowed custom HandlebarsHelpers which can be used. Possible values are:
/// - <see cref="CustomHandlebarsHelpers.None"/> (Default)
/// - <see cref="CustomHandlebarsHelpers.File"/>
/// - <see cref="CustomHandlebarsHelpers.All"/>
/// </summary>
[PublicAPI]
public CustomHandlebarsHelpers AllowedCustomHandlebarsHelpers { get; set; } = CustomHandlebarsHelpers.None;
/// <summary>
/// Defines the allowed HandlebarHelpers which can be used.
///
/// By default, all categories except <see cref="Category.DynamicLinq"/> and <see cref="Category.Environment"/> are registered.
/// </summary>
[PublicAPI]
public Category[] AllowedHandlebarsHelpers { get; set; } = DefaultAllowedHandlebarsHelpers;
}

View File

@@ -98,7 +98,7 @@ public class ProxyAndRecordSettings : HttpClientSettings
public bool UseDefinedRequestMatchers { get; set; }
/// <summary>
/// Append an unique GUID to the filename from the saved mapping file.
/// Append a unique GUID to the filename from the saved mapping file.
/// </summary>
public bool AppendGuidToSavedMappingFile { get; set; }

View File

@@ -18,7 +18,7 @@ public class ProxyUrlReplaceSettings
public string NewValue { get; set; } = null!;
/// <summary>
/// Defines if the case should be ignore when replacing.
/// Defines if the case should be ignored when replacing.
/// </summary>
public bool IgnoreCase { get; set; }
}

View File

@@ -70,6 +70,11 @@ internal class SimpleSettingsParser
return Arguments.ContainsKey(name);
}
public bool ContainsAny(params string[] names)
{
return names.Any(Arguments.ContainsKey);
}
public string[] GetValues(string name, string[] defaultValue)
{
return Contains(name) ? Arguments[name] : defaultValue;
@@ -142,6 +147,28 @@ internal class SimpleSettingsParser
}, defaultValue);
}
public TEnum[] GetEnumValues<TEnum>(string name, TEnum[] defaultValues)
where TEnum : struct
{
var values = GetValues(name);
if (values == null)
{
return defaultValues;
}
var enums = new List<TEnum>();
foreach (var value in values)
{
if (Enum.TryParse<TEnum>(value, true, out var enumValue))
{
enums.Add(enumValue);
}
}
return enums.ToArray();
}
public string GetStringValue(string name, string defaultValue)
{
return GetValue(name, values => values.FirstOrDefault() ?? defaultValue, defaultValue);

View File

@@ -16,13 +16,13 @@ public class WebProxySettings
public string Address { get; set; } = null!;
/// <summary>
/// The user name associated with the credentials.
/// The username associated with the credentials.
/// </summary>
[PublicAPI]
public string? UserName { get; set; }
/// <summary>
/// The password for the user name associated with the credentials.
/// The password for the username associated with the credentials.
/// </summary>
[PublicAPI]
public string? Password { get; set; }

View File

@@ -331,11 +331,8 @@ public class WireMockServerSettings
public string? AdminPath { get; set; }
/// <summary>
/// Defines the allowed custom HandlebarHelpers which can be used. Possible values are:
/// - <see cref="CustomHandlebarHelpers.None"/> (Default)
/// - <see cref="CustomHandlebarHelpers.File"/>
/// - <see cref="CustomHandlebarHelpers.All"/>
/// Defines the additional Handlebars Settings.
/// </summary>
[PublicAPI]
public CustomHandlebarHelpers AllowedCustomHandlebarHelpers { get; set; } = CustomHandlebarHelpers.None;
public HandlebarsSettings? HandlebarsSettings { get; set; }
}

View File

@@ -50,7 +50,6 @@ public static class WireMockServerSettingsParser
AdminPath = parser.GetStringValue(nameof(WireMockServerSettings.AdminPath), "/__admin"),
AllowBodyForAllHttpMethods = parser.GetBoolValue(nameof(WireMockServerSettings.AllowBodyForAllHttpMethods)),
AllowCSharpCodeMatcher = parser.GetBoolValue(nameof(WireMockServerSettings.AllowCSharpCodeMatcher)),
AllowedCustomHandlebarHelpers = parser.GetEnumValue(nameof(WireMockServerSettings.AllowedCustomHandlebarHelpers), CustomHandlebarHelpers.None),
AllowOnlyDefinedHttpStatusCodeInResponse = parser.GetBoolValue(nameof(WireMockServerSettings.AllowOnlyDefinedHttpStatusCodeInResponse)),
AllowPartialMapping = parser.GetBoolValue(nameof(WireMockServerSettings.AllowPartialMapping)),
Culture = parser.GetValue(nameof(WireMockServerSettings.Culture), strings => CultureInfoUtils.Parse(strings.FirstOrDefault()), CultureInfo.CurrentCulture),
@@ -85,6 +84,7 @@ public static class WireMockServerSettingsParser
ParsePortSettings(settings, parser);
ParseProxyAndRecordSettings(settings, parser);
ParseCertificateSettings(settings, parser);
ParseHandlebarsSettings(settings, parser);
return true;
}
@@ -153,7 +153,7 @@ public static class WireMockServerSettingsParser
}
else if (settings.HostingScheme is null)
{
settings.Urls = parser.GetValues("Urls", new[] { "http://*:9091/" });
settings.Urls = parser.GetValues("Urls", ["http://*:9091/"]);
}
}
@@ -167,12 +167,25 @@ public static class WireMockServerSettingsParser
X509CertificateFilePath = parser.GetStringValue("X509CertificateFilePath"),
X509CertificatePassword = parser.GetStringValue("X509CertificatePassword")
};
if (certificateSettings.IsDefined)
{
settings.CertificateSettings = certificateSettings;
}
}
private static void ParseHandlebarsSettings(WireMockServerSettings settings, SimpleSettingsParser parser)
{
if (parser.ContainsAny(nameof(HandlebarsSettings.AllowedCustomHandlebarsHelpers), nameof(HandlebarsSettings.AllowedHandlebarsHelpers)))
{
settings.HandlebarsSettings = new HandlebarsSettings
{
AllowedCustomHandlebarsHelpers = parser.GetEnumValue(nameof(HandlebarsSettings.AllowedCustomHandlebarsHelpers), CustomHandlebarsHelpers.None),
AllowedHandlebarsHelpers = parser.GetEnumValues(nameof(HandlebarsSettings.AllowedHandlebarsHelpers), HandlebarsSettings.DefaultAllowedHandlebarsHelpers)
};
}
}
private static void ParseWebProxyAddressSettings(ProxyAndRecordSettings settings, SimpleSettingsParser parser)
{
string? proxyAddress = parser.GetStringValue("WebProxyAddress");

View File

@@ -4,8 +4,10 @@ using HandlebarsDotNet;
using HandlebarsDotNet.Helpers.Attributes;
using HandlebarsDotNet.Helpers.Enums;
using HandlebarsDotNet.Helpers.Helpers;
using HandlebarsDotNet.Helpers.Options;
using Stef.Validation;
using WireMock.Handlers;
using WireMock.Settings;
namespace WireMock.Transformers.Handlebars;
@@ -15,9 +17,9 @@ internal class FileHelpers : BaseHelpers, IHelpers
private readonly IFileSystemHandler _fileSystemHandler;
public FileHelpers(IHandlebars context, IFileSystemHandler fileSystemHandler) : base(context)
public FileHelpers(IHandlebars context, WireMockServerSettings settings) : base(context, new HandlebarsHelpersOptions())
{
_fileSystemHandler = Guard.NotNull(fileSystemHandler);
_fileSystemHandler = Guard.NotNull(settings.FileSystemHandler);
}
[HandlebarsWriter(WriterType.String, usage: HelperUsage.Both, passContext: true, name: Name)]

View File

@@ -40,9 +40,9 @@ internal static class WireMockHandlebarsHelpers
o.CustomHelperPaths = paths;
o.CustomHelpers = new Dictionary<string, IHelpers>();
if (settings.AllowedCustomHandlebarHelpers.HasFlag(CustomHandlebarHelpers.File))
if (settings.HandlebarsSettings?.AllowedCustomHandlebarsHelpers.HasFlag(CustomHandlebarsHelpers.File) == true)
{
o.CustomHelpers.Add(FileHelpers.Name, new FileHelpers(handlebarsContext, settings.FileSystemHandler));
o.CustomHelpers.Add(FileHelpers.Name, new FileHelpers(handlebarsContext, settings));
}
});
}

View File

@@ -182,13 +182,13 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Handlebars.Net.Helpers" Version="2.4.10" />
<!--<PackageReference Include="Handlebars.Net.Helpers.DynamicLinq" Version="2.4.10" />-->
<PackageReference Include="Handlebars.Net.Helpers.Humanizer" Version="2.4.10" />
<PackageReference Include="Handlebars.Net.Helpers.Json" Version="2.4.10" />
<PackageReference Include="Handlebars.Net.Helpers.Random" Version="2.4.10" />
<PackageReference Include="Handlebars.Net.Helpers.Xeger" Version="2.4.10" />
<PackageReference Include="Handlebars.Net.Helpers.XPath" Version="2.4.10" />
<PackageReference Include="Handlebars.Net.Helpers" Version="2.5.0" />
<!--<PackageReference Include="Handlebars.Net.Helpers.DynamicLinq" Version="2.5.0" />-->
<PackageReference Include="Handlebars.Net.Helpers.Humanizer" Version="2.5.0" />
<PackageReference Include="Handlebars.Net.Helpers.Json" Version="2.5.0" />
<PackageReference Include="Handlebars.Net.Helpers.Random" Version="2.5.0" />
<PackageReference Include="Handlebars.Net.Helpers.Xeger" Version="2.5.0" />
<PackageReference Include="Handlebars.Net.Helpers.XPath" Version="2.5.0" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' != 'netstandard1.3' and '$(TargetFramework)' != 'net451' and '$(TargetFramework)' != 'net452' ">

View File

@@ -4,7 +4,6 @@ using System;
using System.Threading.Tasks;
using FluentAssertions;
using HandlebarsDotNet;
using HandlebarsDotNet.Helpers;
using Moq;
using Newtonsoft.Json.Linq;
using NFluent;
@@ -12,7 +11,6 @@ using WireMock.Handlers;
using WireMock.Models;
using WireMock.ResponseBuilders;
using WireMock.Settings;
using WireMock.Transformers.Handlebars;
using WireMock.Types;
using Xunit;
@@ -35,7 +33,10 @@ public class ResponseWithHandlebarsFileTests
_settings = new()
{
AllowedCustomHandlebarHelpers = CustomHandlebarHelpers.File,
HandlebarsSettings = new HandlebarsSettings
{
AllowedCustomHandlebarsHelpers = CustomHandlebarsHelpers.File
},
FileSystemHandler = _filesystemHandlerMock.Object
};
}
@@ -117,7 +118,6 @@ public class ResponseWithHandlebarsFileTests
// Assign
var settings = new WireMockServerSettings
{
AllowedCustomHandlebarHelpers = CustomHandlebarHelpers.None,
FileSystemHandler = _filesystemHandlerMock.Object
};
var request = new RequestMessage(new UrlDetails("http://localhost:1234?id=x"), "GET", ClientIp);