Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/dev' into issue/TDEAL-27-main
Browse files Browse the repository at this point in the history
# Conflicts:
#	Lombiq.HelpfulLibraries.AspNetCore/Security/CdnContentSecurityPolicyProvider.cs
  • Loading branch information
sarahelsaig committed Mar 21, 2024
2 parents 0025d72 + 929faca commit f8a2244
Show file tree
Hide file tree
Showing 73 changed files with 1,086 additions and 203 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using Lombiq.HelpfulLibraries.Common.Utilities;
using Lombiq.HelpfulLibraries.Common.Utilities;
using System;
using System.Collections.Generic;
using System.Linq;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using Microsoft.AspNetCore.Html;
using Microsoft.AspNetCore.Razor.TagHelpers;
using System.IO;
using System.Web;

namespace Microsoft.AspNetCore.Mvc.Rendering;

public static class JsonHelperExtensions
{
/// <summary>
/// Returns a full HTML element attribute with the given <paramref name="name"/> prefixed with <c>data-</c> and the
/// value appropriately encoded to prevent XSS attacks.
/// </summary>
public static IHtmlContent DataAttribute(this IJsonHelper helper, string name, object value)
{
using var stringWriter = new StringWriter();
helper.Serialize(value).WriteTo(stringWriter, NullHtmlEncoder.Default);

return new HtmlString($"data-{name}=\"{HttpUtility.HtmlAttributeEncode(stringWriter.ToString())}\"");
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net8.0</TargetFramework>
<DefaultItemExcludes>$(DefaultItemExcludes);.git*</DefaultItemExcludes>
</PropertyGroup>

Expand All @@ -27,6 +27,10 @@
<FrameworkReference Include="Microsoft.AspNetCore.App" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="OrchardCore.Abstractions" Version="1.8.2" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\Lombiq.HelpfulLibraries.Common\Lombiq.HelpfulLibraries.Common.csproj" />
</ItemGroup>
Expand Down
4 changes: 0 additions & 4 deletions Lombiq.HelpfulLibraries.AspNetCore/Mvc/ActionResultHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,7 @@ public static FileResult ZipFile(IDictionary<string, Stream> files, string zipFi
var entry = archive.CreateEntry(fileName, CompressionLevel.Optimal);
using var entryStream = entry.Open();
fileStream.CopyTo(entryStream);

// False positive.
#pragma warning disable S3966 // Objects should not be disposed more than once.
fileStream.Dispose();
#pragma warning restore S3966 // Objects should not be disposed more than once.
}
}

Expand Down
4 changes: 3 additions & 1 deletion Lombiq.HelpfulLibraries.AspNetCore/Mvc/JsonModelBinder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ namespace Lombiq.HelpfulLibraries.AspNetCore.Mvc;

public class JsonModelBinder : IModelBinder
{
private static readonly JsonSerializerOptions DeSerializeOptions = new(JsonSerializerDefaults.Web);

private readonly ILogger<JsonModelBinder> _logger;
private readonly IObjectModelValidator _validator;

Expand All @@ -28,7 +30,7 @@ public Task BindModelAsync(ModelBindingContext bindingContext)
var parsed = value is null ? null : JsonSerializer.Deserialize(
value,
bindingContext.ModelType,
new JsonSerializerOptions(JsonSerializerDefaults.Web));
DeSerializeOptions);

if (parsed is null)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Lombiq.HelpfulLibraries.AspNetCore.Security;
using Lombiq.HelpfulLibraries.AspNetCore.Security;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Primitives;
using System;
Expand Down Expand Up @@ -110,7 +111,7 @@ public static IApplicationBuilder UseNosniffContentTypeOptionsHeader(this IAppli

if (!context.Response.Headers.ContainsKey(key))
{
context.Response.Headers.Add(key, "nosniff");
context.Response.Headers.Append(key, "nosniff");
}

await next();
Expand Down Expand Up @@ -141,7 +142,7 @@ static void UpdateIfMissing(ref string cookie, ref bool changed, string test, st
context.Response.OnStarting(() =>
{
var setCookie = context.Response.Headers[setCookieHeader];
if (!setCookie.Any()) return Task.CompletedTask;
if (setCookie.Count == 0) return Task.CompletedTask;

var newCookies = new List<string>(capacity: setCookie.Count);
var changed = false;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
Expand All @@ -23,6 +23,7 @@ public class CdnContentSecurityPolicyProvider : IContentSecurityPolicyProvider
new Uri("https://fonts.googleapis.com/css"),
new Uri("https://fonts.gstatic.com/"),
new Uri("https://cdn.jsdelivr.net/npm"),
new Uri("https://fastly.jsdelivr.net/npm"),
});

/// <summary>
Expand All @@ -32,6 +33,7 @@ public class CdnContentSecurityPolicyProvider : IContentSecurityPolicyProvider
{
new Uri("https://cdn.jsdelivr.net/npm"),
new Uri("https://code.jquery.com/jquery-3.7.0.js"),
new Uri("https://fastly.jsdelivr.net/npm"),
});

/// <summary>
Expand All @@ -47,19 +49,19 @@ public ValueTask UpdateAsync(IDictionary<string, string> securityPolicies, HttpC
{
var any = false;

if (PermittedStyleSources.Any())
if (!PermittedStyleSources.IsEmpty)
{
any = true;
MergeValues(securityPolicies, StyleSrc, PermittedStyleSources);
}

if (PermittedScriptSources.Any())
if (!PermittedScriptSources.IsEmpty)
{
any = true;
MergeValues(securityPolicies, ScriptSrc, PermittedScriptSources);
}

if (PermittedFontSources.Any())
if (!PermittedFontSources.IsEmpty)
{
any = true;
MergeValues(securityPolicies, FontSrc, PermittedFontSources);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using static Lombiq.HelpfulLibraries.AspNetCore.Security.ContentSecurityPolicyDirectives;

Expand Down Expand Up @@ -30,7 +32,22 @@ public ValueTask<bool> ShouldSuppressHeaderAsync(HttpContext context) =>
/// Returns the first non-empty directive from the <paramref name="names"/> or <see cref="DefaultSrc"/> or an empty
/// string.
/// </summary>
public static string GetDirective(IDictionary<string, string> securityPolicies, params string[] names)
[Obsolete($"Use the method in the {nameof(ContentSecurityPolicyProvider)} static class instead.")]
public static string GetDirective(IDictionary<string, string> securityPolicies, params string[] names) =>
ContentSecurityPolicyProvider.GetDirective(securityPolicies, names.AsEnumerable());
}

public static class ContentSecurityPolicyProvider
{
/// <summary>
/// Returns the first non-empty directive from the <paramref name="names"/> or <see cref="DefaultSrc"/> or an empty
/// string.
/// </summary>
public static string GetDirective(IDictionary<string, string> securityPolicies, params string[] names) =>
GetDirective(securityPolicies, names.AsEnumerable());

/// <inheritdoc cref="GetDirective(System.Collections.Generic.IDictionary{string,string},string[])"/>
public static string GetDirective(IDictionary<string, string> securityPolicies, IEnumerable<string> names)
{
foreach (var name in names)
{
Expand All @@ -42,4 +59,17 @@ public static string GetDirective(IDictionary<string, string> securityPolicies,

return securityPolicies.GetMaybe(DefaultSrc) ?? string.Empty;
}

/// <summary>
/// Updates the directive (the first entry of the <paramref name="directiveNameChain"/>) by merging its space
/// separated values with the values from <paramref name="otherValues"/>.
/// </summary>
public static void MergeDirectiveValues(
IDictionary<string, string> securityPolicies,
IEnumerable<string> directiveNameChain,
params string[] otherValues)
{
var nameChain = directiveNameChain.AsList();
securityPolicies[nameChain[0]] = GetDirective(securityPolicies, nameChain).MergeWordSets(otherValues);
}
}
5 changes: 2 additions & 3 deletions Lombiq.HelpfulLibraries.Cli/Helpers/CliWrapHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading.Tasks;

namespace Lombiq.HelpfulLibraries.Cli.Helpers;
Expand All @@ -19,7 +18,7 @@ public static class CliWrapHelper
/// <param name="name">The application name you can invoke directly in the command line.</param>
public static async Task<IEnumerable<FileInfo>> WhichAsync(string name)
{
var appName = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "where" : "which";
var appName = OperatingSystem.IsWindows() ? "where" : "which";
var result = await CliWrap.Cli.Wrap(appName)
.WithArguments(name)
.WithValidation(CommandResultValidation.None)
Expand All @@ -46,7 +45,7 @@ public static async Task StreamAsync(
Func<Command, Command> configureCommand = null)
{
var command = CliWrap.Cli.Wrap(program);
if (arguments?.Any() == true) command = command.WithArguments(arguments);
if (arguments?.Count != 0) command = command.WithArguments(arguments);
if (configureCommand != null) command = configureCommand(command);

await foreach (var commandEvent in command.ListenAsync()) handler(commandEvent);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net8.0</TargetFramework>
</PropertyGroup>

<PropertyGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,7 @@ public static IEnumerable<T> EmptyIfNull<T>(this IEnumerable<T> collection) =>
/// cref="Array.Empty{TResult}"/>.
/// </summary>
public static IEnumerable<T> EmptyIfNull<T>(this T[] array) =>
array ?? Array.Empty<T>();
array ?? [];

/// <summary>
/// Maps the provided collection of pairs using a selector with separate arguments.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@ public static class ExpressionExtensions
/// Creates a new lambda expression that's identical except it doesn't have a return value.
/// </summary>
public static Expression<Action<TIn>> StripResult<TIn, TOut>(this Expression<Func<TIn, TOut>> expression) =>
Expression.Lambda<Action<TIn>>(expression, expression.Parameters);
Expression.Lambda<Action<TIn>>(expression.Body, expression.Parameters);
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public static class RandomNumberGeneratorExtensions
/// </remarks>
public static int Next(this RandomNumberGenerator randomNumberGenerator, int minValue, int maxValue)
{
if (minValue > maxValue) throw new ArgumentOutOfRangeException(nameof(minValue));
ArgumentOutOfRangeException.ThrowIfGreaterThan(minValue, maxValue);
if (minValue == maxValue) return minValue;

var diff = (long)maxValue - minValue;
Expand Down
4 changes: 2 additions & 2 deletions Lombiq.HelpfulLibraries.Common/Extensions/StringExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -84,13 +84,13 @@ public static string MakeFileSystemFriendly(this string text, bool noSpaceOrDot
/// Returns an array by splitting the input along commas and stripping empty entries.
/// </summary>
public static string[] SplitByCommas(this string? text) =>
text?.Split(',', StringSplitOptions.RemoveEmptyEntries) ?? Array.Empty<string>();
text?.Split(',', StringSplitOptions.RemoveEmptyEntries) ?? [];

/// <summary>
/// Returns the input split into lines (using <see cref="Environment.NewLine"/>).
/// </summary>
public static string[] SplitByNewLines(this string? text) =>
text?.Split(Environment.NewLine) ?? Array.Empty<string>();
text?.Split(Environment.NewLine) ?? [];

/// <summary>
/// A shortcut for <c>string.Contains(string, StringComparison.InvariantCultureIgnoreCase)</c>. It also safely
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net8.0</TargetFramework>
<DefaultItemExcludes>$(DefaultItemExcludes);.git*</DefaultItemExcludes>
</PropertyGroup>

Expand All @@ -24,8 +24,8 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="7.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="7.0.4" />
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="8.0.1" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
</ItemGroup>

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using LinqToDB;
using System.Diagnostics.CodeAnalysis;

namespace Lombiq.HelpfulLibraries.LinqToDb.Extensions;

Expand All @@ -9,16 +8,13 @@ public static class CustomSqlExtensions
// used by the attribute.
[Sql.Expression(ProviderName.SqlServer, "JSON_VALUE({0}, {1})", ServerSideOnly = true, InlineParameters = true)]
[Sql.Expression(ProviderName.SQLite, "json_extract({0}, {1})", ServerSideOnly = true, InlineParameters = true)]
[SuppressMessage("Usage", "CA1801:Review unused parameters", Justification = "Used in the Sql.Expression attribute.")]
public static string JsonValue(object expression, string path) => null;

[Sql.Expression(ProviderName.SqlServer, "JSON_MODIFY({0}, {1}, {2})", ServerSideOnly = true, InlineParameters = true)]
[Sql.Expression(ProviderName.SQLite, "json_replace({0}, {1}, {2})", ServerSideOnly = true, InlineParameters = true)]
[SuppressMessage("Usage", "CA1801:Review unused parameters", Justification = "Used in the Sql.Expression attribute.")]
public static string JsonModify(string json, string path, string newValue) => null;

[Sql.Expression(ProviderName.SqlServer, "JSON_QUERY({0})", ServerSideOnly = true, InlineParameters = true)]
[Sql.Expression(ProviderName.SQLite, "json({0})", ServerSideOnly = true, InlineParameters = true)]
[SuppressMessage("Usage", "CA1801:Review unused parameters", Justification = "Used in the Sql.Expression attribute.")]
public static string JsonQuery(string value) => null;
}
12 changes: 5 additions & 7 deletions Lombiq.HelpfulLibraries.LinqToDb/LinqToDbQueryExecutor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,7 @@ namespace Lombiq.HelpfulLibraries.LinqToDb;

public static class LinqToDbQueryExecutor
{
// We have no control over where these fields are declared.
#pragma warning disable CA1810 // Initialize reference type static fields inline
static LinqToDbQueryExecutor()
#pragma warning restore CA1810 // Initialize reference type static fields inline
{
// Generate aliases for final projection.
Sql.GenerateFinalAliases = true;
Expand Down Expand Up @@ -78,10 +75,11 @@ public static async Task<TResult> LinqQueryAsync<TResult>(
private static string GetDatabaseProviderName(string dbName) =>
dbName switch
{
// Using explicit string instead of LinqToDB.ProviderName.SqlServer because if the "System.Data.SqlClient"
// provider will be used it will cause "Could not load type System.Data.SqlClient.SqlCommandBuilder"
// exception. See: https://github.com/linq2db/linq2db/issues/2191#issuecomment-618450439.
"SqlServer" => "Microsoft.Data.SqlClient",
// Using a concrete SQL Server version here removes the need for an initial auto-detection query that can
// fail, see https://github.com/Lombiq/Helpful-Libraries/issues/236. This needs to be the same version
// YesSql and thus OC supports. You can check it out in YesSql's build workflow:
// https://github.com/sebastienros/yessql/blob/main/.github/workflows/build.yml.
"SqlServer" => ProviderName.SqlServer2019,
"Sqlite" => ProviderName.SQLite,
"MySql" => ProviderName.MySql,
"PostgreSql" => ProviderName.PostgreSQL,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net8.0</TargetFramework>
<DefaultItemExcludes>$(DefaultItemExcludes);.git*</DefaultItemExcludes>
</PropertyGroup>

Expand All @@ -24,7 +24,7 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="linq2db" Version="5.2.2" />
<PackageReference Include="OrchardCore.Data.YesSql" Version="1.7.0" />
<PackageReference Include="linq2db" Version="5.4.0" />
<PackageReference Include="OrchardCore.Data.YesSql" Version="1.8.2" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net8.0</TargetFramework>
<DefaultItemExcludes>$(DefaultItemExcludes);.git*</DefaultItemExcludes>
</PropertyGroup>

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using Microsoft.Extensions.Localization;
using OrchardCore.ContentManagement.Metadata;
using OrchardCore.Environment.Commands;
using System.Threading.Tasks;

namespace Lombiq.HelpfulLibraries.OrchardCore.Contents;

Expand Down Expand Up @@ -28,6 +29,6 @@ public ContentDefinitionCommands(
" /Part:<contentPartName>" +
"\r\n\t" + "Attaches a content part to a content type.")]
[OrchardSwitches(nameof(Type) + ", " + nameof(Part))]
public void AttachContentPart() =>
_contentDefinitionManager.AlterTypeDefinition(Type, type => type.WithPart(Part));
public Task AttachContentPartAsync() =>
_contentDefinitionManager.AlterTypeDefinitionAsync(Type, type => type.WithPart(Part));
}
Loading

0 comments on commit f8a2244

Please sign in to comment.