Skip to content

Add HandlebarsSettings #1271

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Apr 23, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ namespace WireMock.Types;
/// A enum defining the supported Handlebar helpers.
/// </summary>
[Flags]
public enum CustomHandlebarHelpers
public enum CustomHandlebarsHelpers
{
None = 0,

Expand Down
50 changes: 50 additions & 0 deletions src/WireMock.Net/Settings/HandlebarsSettings.cs
Original file line number Diff line number Diff line change
@@ -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;
}
2 changes: 1 addition & 1 deletion src/WireMock.Net/Settings/ProxyAndRecordSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ public string SaveMappingForStatusCodePattern
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; }

Expand Down
2 changes: 1 addition & 1 deletion src/WireMock.Net/Settings/ProxyUrlReplaceSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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; }
}
27 changes: 27 additions & 0 deletions src/WireMock.Net/Settings/SimpleSettingsParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,11 @@
return Arguments.ContainsKey(name);
}

public bool ContainsAny(params string[] names)

Check warning on line 73 in src/WireMock.Net/Settings/SimpleSettingsParser.cs

View check run for this annotation

Codecov / codecov/patch

src/WireMock.Net/Settings/SimpleSettingsParser.cs#L73

Added line #L73 was not covered by tests
{
return names.Any(Arguments.ContainsKey);
}

Check warning on line 77 in src/WireMock.Net/Settings/SimpleSettingsParser.cs

View check run for this annotation

Codecov / codecov/patch

src/WireMock.Net/Settings/SimpleSettingsParser.cs#L77

Added line #L77 was not covered by tests
public string[] GetValues(string name, string[] defaultValue)
{
return Contains(name) ? Arguments[name] : defaultValue;
Expand Down Expand Up @@ -142,6 +147,28 @@
}, defaultValue);
}

public TEnum[] GetEnumValues<TEnum>(string name, TEnum[] defaultValues)
where TEnum : struct

Check warning on line 151 in src/WireMock.Net/Settings/SimpleSettingsParser.cs

View check run for this annotation

Codecov / codecov/patch

src/WireMock.Net/Settings/SimpleSettingsParser.cs#L151

Added line #L151 was not covered by tests
{
var values = GetValues(name);
if (values == null)
{
return defaultValues;

Check warning on line 156 in src/WireMock.Net/Settings/SimpleSettingsParser.cs

View check run for this annotation

Codecov / codecov/patch

src/WireMock.Net/Settings/SimpleSettingsParser.cs#L153-L156

Added lines #L153 - L156 were not covered by tests
}

var enums = new List<TEnum>();

Check warning on line 159 in src/WireMock.Net/Settings/SimpleSettingsParser.cs

View check run for this annotation

Codecov / codecov/patch

src/WireMock.Net/Settings/SimpleSettingsParser.cs#L158-L159

Added lines #L158 - L159 were not covered by tests

foreach (var value in values)
{
if (Enum.TryParse<TEnum>(value, true, out var enumValue))
{
enums.Add(enumValue);
}
}

return enums.ToArray();
}

Check warning on line 171 in src/WireMock.Net/Settings/SimpleSettingsParser.cs

View check run for this annotation

Codecov / codecov/patch

src/WireMock.Net/Settings/SimpleSettingsParser.cs#L170-L171

Added lines #L170 - L171 were not covered by tests
public string GetStringValue(string name, string defaultValue)
{
return GetValue(name, values => values.FirstOrDefault() ?? defaultValue, defaultValue);
Expand Down
4 changes: 2 additions & 2 deletions src/WireMock.Net/Settings/WebProxySettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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; }
Expand Down
7 changes: 2 additions & 5 deletions src/WireMock.Net/Settings/WireMockServerSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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; }
}
17 changes: 15 additions & 2 deletions src/WireMock.Net/Settings/WireMockServerSettingsParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@
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),
Expand Down Expand Up @@ -85,6 +84,7 @@
ParsePortSettings(settings, parser);
ParseProxyAndRecordSettings(settings, parser);
ParseCertificateSettings(settings, parser);
ParseHandlebarsSettings(settings, parser);

return true;
}
Expand Down Expand Up @@ -153,7 +153,7 @@
}
else if (settings.HostingScheme is null)
{
settings.Urls = parser.GetValues("Urls", new[] { "http://*:9091/" });
settings.Urls = parser.GetValues("Urls", ["http://*:9091/"]);
}
}

Expand All @@ -167,12 +167,25 @@
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)
};

Check warning on line 185 in src/WireMock.Net/Settings/WireMockServerSettingsParser.cs

View check run for this annotation

Codecov / codecov/patch

src/WireMock.Net/Settings/WireMockServerSettingsParser.cs#L180-L185

Added lines #L180 - L185 were not covered by tests
}
}

private static void ParseWebProxyAddressSettings(ProxyAndRecordSettings settings, SimpleSettingsParser parser)
{
string? proxyAddress = parser.GetStringValue("WebProxyAddress");
Expand Down
6 changes: 4 additions & 2 deletions src/WireMock.Net/Transformers/Handlebars/FileHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@
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;

Expand All @@ -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)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,9 @@ void Add(string? path, ICollection<string> customHelperPaths)
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));
}
});
}
Expand Down
14 changes: 7 additions & 7 deletions src/WireMock.Net/WireMock.Net.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -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' ">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,13 @@
using System.Threading.Tasks;
using FluentAssertions;
using HandlebarsDotNet;
using HandlebarsDotNet.Helpers;
using Moq;
using Newtonsoft.Json.Linq;
using NFluent;
using WireMock.Handlers;
using WireMock.Models;
using WireMock.ResponseBuilders;
using WireMock.Settings;
using WireMock.Transformers.Handlebars;
using WireMock.Types;
using Xunit;

Expand All @@ -35,7 +33,10 @@ public ResponseWithHandlebarsFileTests()

_settings = new()
{
AllowedCustomHandlebarHelpers = CustomHandlebarHelpers.File,
HandlebarsSettings = new HandlebarsSettings
{
AllowedCustomHandlebarsHelpers = CustomHandlebarsHelpers.File
},
FileSystemHandler = _filesystemHandlerMock.Object
};
}
Expand Down Expand Up @@ -117,7 +118,6 @@ public void Response_ProvideResponseAsync_Handlebars_File_NotAllowed_Throws_Hand
// Assign
var settings = new WireMockServerSettings
{
AllowedCustomHandlebarHelpers = CustomHandlebarHelpers.None,
FileSystemHandler = _filesystemHandlerMock.Object
};
var request = new RequestMessage(new UrlDetails("http://localhost:1234?id=x"), "GET", ClientIp);
Expand Down
Loading