Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
bc8bb30
Remove Lombiq.NodeJs.Extensions references.
sarahelsaig Apr 19, 2025
9784379
remove package.json and pnpm-lock.yaml.
sarahelsaig Apr 19, 2025
00b2f1f
Remove other node references.
sarahelsaig Apr 19, 2025
8470f32
Use MSBuild Copy task to copy the JS assets.
sarahelsaig Apr 19, 2025
5689e85
Copy CSS asset in OrchardCore.Commerce.Payment.
sarahelsaig Apr 19, 2025
29cee73
Organize copy tasks.
sarahelsaig Apr 19, 2025
2d2462c
Backport to CSS.
sarahelsaig Apr 19, 2025
22a79b6
Apply error notification styling everywhere.
sarahelsaig Apr 19, 2025
67b91e4
Merge remote-tracking branch 'origin/main' into issue/OCC-314
sarahelsaig Apr 20, 2025
edca38a
Use lint workflow.
sarahelsaig Apr 22, 2025
1e55f4a
Enable corepack.
sarahelsaig Apr 22, 2025
f732d74
Use --no-frozen-lockfile
sarahelsaig Apr 22, 2025
879f11a
Use --no-frozen-lockfile
sarahelsaig Apr 22, 2025
1d84f9d
Fix script-paths.
sarahelsaig Apr 22, 2025
d9ea0fd
Fix
sarahelsaig Apr 22, 2025
7aa78e4
Fix pwsh code styling.
sarahelsaig Apr 22, 2025
d959efb
Ensure absolute paths.
sarahelsaig Apr 22, 2025
c360351
Add deliberate errors to test validation.
sarahelsaig Apr 23, 2025
9120d17
Revert "Add deliberate errors to test validation."
sarahelsaig Apr 23, 2025
2facb95
Update .github/workflows/build-and-test.yml
sarahelsaig Apr 24, 2025
3b3c11e
Build on net9.0 (working)
Skrypt Apr 28, 2025
c3daa22
Multi-Target build
Skrypt Apr 28, 2025
41936b2
make .NET 8 DefaultTargetFramework
Skrypt Apr 29, 2025
7c3b107
Remove .net 9
Skrypt Apr 29, 2025
8814c9d
Fix formatting with CSharpier
Skrypt Apr 29, 2025
dfd96b3
Fix analysis build issues
Skrypt Apr 29, 2025
d29b884
Specify dotnet-version on github workflow
Skrypt Apr 29, 2025
f68626e
fix version
Skrypt Apr 29, 2025
242b955
format
Skrypt Apr 29, 2025
397930e
suppress warning IDE0055
Skrypt Apr 29, 2025
6217e11
format
Skrypt Apr 29, 2025
4c7b3f6
add #pragma warning disable IDE0055
Skrypt Apr 29, 2025
7bf7c01
Merge branch 'main' into skrypt/build
Skrypt May 6, 2025
5ec1979
Try fix analysis level
Skrypt May 6, 2025
571b16b
Try Fix AnalysisLevel
Skrypt May 6, 2025
dc3e73f
Try Fix AnalysisLevel
Skrypt May 6, 2025
decbd1a
comments
Skrypt May 6, 2025
1b1cf3a
Try fix code analysis
Skrypt May 6, 2025
a652d58
Remove eol=crlf for .cs files
Skrypt May 6, 2025
b10e8a2
Remove #pragma warning disable
Skrypt May 6, 2025
06799c9
Revert changes from bad merge
Skrypt May 6, 2025
183482d
Try AnalysisLevel 9 and LangVersion 13
Skrypt May 6, 2025
3cf9c5d
internal classes
Skrypt May 6, 2025
ce042ae
disable MA0158 for now
Skrypt May 6, 2025
3035ed1
Fix formatting
Skrypt May 6, 2025
aa522d6
sealed
Skrypt May 6, 2025
a3985aa
Fix tests
Skrypt May 6, 2025
efd3f4d
internal sealed
Skrypt May 7, 2025
01a9f9f
internal sealed
Skrypt May 7, 2025
828bcbc
remove disable CA1515
Skrypt May 7, 2025
04c317b
add back
Skrypt May 7, 2025
96b7f61
default to net8.0
Skrypt May 7, 2025
4b65cf2
Add Microsoft.AspNetCore.Mvc.Testing
Skrypt May 7, 2025
5c699d9
Merge branch 'main' into skrypt/build
Skrypt May 7, 2025
315fdc4
Remove SecurityScanningTest
Skrypt May 8, 2025
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
1 change: 0 additions & 1 deletion .gitattributes
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
* text=auto
*.cs text eol=crlf

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This ended up to be the issue with CI. The Analyzer doesn't like it on "comment lines".


# Keep LF line endings in pnpm-lock.yaml files to prevent Git from reporting this file as changed after pnpm touches it.
pnpm-lock.yaml text eol=lf
2 changes: 2 additions & 0 deletions .github/workflows/build-and-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ jobs:
with:
machine-types: '["ubuntu-24.04"]'
timeout-minutes: 60
dotnet-version: 9.0.203

build-and-test-windows:
name: Build and Test (Windows)
Expand All @@ -26,6 +27,7 @@ jobs:
# Running ZAP for security scans in Docker under GHA Windows runners won't work since such virtualization is not
# supported by GHA.
test-filter: "FullyQualifiedName!~SecurityScanningTests"
dotnet-version: 9.0.203

codespell:
name: Codespell
Expand Down
17 changes: 17 additions & 0 deletions Directory.Build.props
Original file line number Diff line number Diff line change
@@ -1,4 +1,21 @@
<Project>
<!-- Default TFMs to use when building and packaging -->
<PropertyGroup>

<!-- TFM used when coding in Visual Studio and when creating templates -->
<!-- All 'template.json' should provide a 'choice' for the default TFM -->
<DefaultTargetFramework Condition="'$(DefaultTargetFramework)' == ''">net8.0</DefaultTargetFramework>

<!-- TFMs used to build the abstractions and modules, by convention the default TFM is at the first position -->
<!-- In a cross-targeting build, some assets are only copied on the first TFM, by convention the default TFM -->
<CommonTargetFrameworks Condition="'$(CommonTargetFrameworks)' == ''">net8.0;net9.0</CommonTargetFrameworks>
</PropertyGroup>

<!-- Detect if the solution is opened in VS to limit the TFMs that are analyzed by Roslyn for performance reasons -->
<PropertyGroup Condition="'$(BuildingInsideVisualStudio)' == 'true' or '$(BuildingByReSharper)' == 'true'">
<CommonTargetFrameworks>$(DefaultTargetFramework)</CommonTargetFrameworks>
</PropertyGroup>

<!-- Uncomment this to run .NET static code analyzers during rebuilds. -->
<!--<PropertyGroup>
<RunAnalyzersDuringBuild>true</RunAnalyzersDuringBuild>
Expand Down
58 changes: 57 additions & 1 deletion Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@

<LombiqHelpfulLibrariesVersion>12.1.0</LombiqHelpfulLibrariesVersion>
<LombiqTestsUIVersion>12.1.1-alpha.14.osoe-1057</LombiqTestsUIVersion>
<LangVersion>13.0</LangVersion>
<AnalysisLevel>9.0</AnalysisLevel>
</PropertyGroup>

<ItemGroup>
Expand Down Expand Up @@ -42,8 +44,62 @@
<PackageVersion Include="OrchardCore.Workflows.Abstractions" Version="$(OrchardCoreVersion)" />
<PackageVersion Include="Shouldly" Version="4.3.0" />
<PackageVersion Include="Stripe.net" Version="48.1.0" />
<PackageVersion Include="System.Text.Json" Version="9.0.4" />
<PackageVersion Include="xunit.v3" Version="2.0.2" />
<PackageVersion Include="xunit.runner.visualstudio" Version="3.1.0" />
</ItemGroup>

<ItemGroup Condition="'$(TargetFramework)' == 'net8.0'" >
<!-- Several transitive dependencies on 8.0.4 and lower which is vulnerable -->
<PackageVersion Include="System.Text.Json" Version="8.0.5" />
<!-- Several transitive dependencies on 8.0.0 which has known vulnerabilities -->
<PackageVersion Include="Microsoft.Extensions.Caching.Memory" Version="8.0.1" />
</ItemGroup>

<ItemGroup Condition="'$(TargetFramework)' != 'net8.0'">
<PackageVersion Include="System.Text.Json" Version="9.0.4" />
<PackageVersion Include="Microsoft.Extensions.Caching.Memory" Version="9.0.4" />
</ItemGroup>

<!-- These versions are used for the NuGet packages that are dependent on the current TFM -->
<!-- There may be no TFM in an evaluation phase so we can't use a conditional 'Property' -->

<ItemGroup Condition="'$(TargetFramework)' != 'net8.0'">
<PackageVersion Include="Microsoft.AspNetCore.Authentication.Facebook" Version="9.0.4" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication.Google" Version="9.0.4" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication.MicrosoftAccount" Version="9.0.4" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="9.0.4" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication.Twitter" Version="9.0.4" />
<PackageVersion Include="Microsoft.AspNetCore.DataProtection.StackExchangeRedis" Version="9.0.4" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="9.0.4" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Testing" Version="9.0.4" />
<PackageVersion Include="Microsoft.AspNetCore.Owin" Version="9.0.4" />
<PackageVersion Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="9.0.4" />
<PackageVersion Include="Microsoft.AspNetCore.Authorization" Version="9.0.4" />

<!-- dotnet/extensions repository -->
<PackageVersion Include="Microsoft.Extensions.Http.Resilience" Version="9.4.0" />

<!-- Serilog.AspNetCore -->
<PackageVersion Include="Serilog.AspNetCore" Version="9.0.0" />
</ItemGroup>

<ItemGroup Condition="'$(TargetFramework)' == 'net8.0'">
<PackageVersion Include="Microsoft.AspNetCore.Authentication.Facebook" Version="8.0.15" />

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could clean some of these as OCC doesn't use them. Not sure though if they could not be potentially used. I've copied OC configs for these.

<PackageVersion Include="Microsoft.AspNetCore.Authentication.Google" Version="8.0.15" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication.MicrosoftAccount" Version="8.0.15" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="8.0.15" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication.Twitter" Version="8.0.15" />
<PackageVersion Include="Microsoft.AspNetCore.DataProtection.StackExchangeRedis" Version="8.0.15" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="8.0.15" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Testing" Version="8.0.15" />
<PackageVersion Include="Microsoft.AspNetCore.Owin" Version="8.0.15" />
<PackageVersion Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="8.0.15" />
<PackageVersion Include="Microsoft.AspNetCore.Authorization" Version="8.0.15" />

<!-- dotnet/extensions repository -->
<PackageVersion Include="Microsoft.Extensions.Http.Resilience" Version="8.10.0" />

<!-- Serilog.AspNetCore -->
<PackageVersion Include="Serilog.AspNetCore" Version="8.0.3" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ namespace OrchardCore.Commerce.Abstractions.Abstractions;
public interface IProductAttributeDeserializer
{
// Not necessary to document as they are not externally accessible.
#pragma warning disable SA1600 // Elements should be documented.
#pragma warning disable SA1600,MA0158 // Elements should be documented.
internal static readonly Dictionary<string, IProductAttributeDeserializer> Deserializers =
new(StringComparer.OrdinalIgnoreCase);

private static readonly object _lock = new();
#pragma warning restore SA1600
#pragma warning restore SA1600,MA0158

/// <summary>
/// Gets the attribute name used to identify this deserializer.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<TargetFrameworks>$(CommonTargetFrameworks)</TargetFrameworks>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
</PropertyGroup>

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<TargetFrameworks>$(CommonTargetFrameworks)</TargetFrameworks>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
</PropertyGroup>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,16 @@ namespace OrchardCore.Commerce.MoneyDataType;

internal static class KnownCurrencyTable
{
#pragma warning disable MA0158
private static readonly object _lockObject = new();
#pragma warning restore MA0158

internal static IDictionary<string, ICurrency> CurrencyTable { get; private set; }

internal static void EnsureCurrencyTable()
{
if (CurrencyTable == null) InitCurrencyCodeTable();
if (CurrencyTable == null)
InitCurrencyCodeTable();
}

internal static ICurrency FromIsoCode(string isoCode)
Expand All @@ -26,39 +29,47 @@ internal static ICurrency FromIsoCode(string isoCode)
private static void InitCurrencyCodeTable()
{
static bool IsValid(CultureInfo cultureInfo) =>
cultureInfo.Name.Contains('-') &&
!cultureInfo.IsNeutralCulture &&
!cultureInfo.EnglishName.StartsWith("Unknown Locale", StringComparison.Ordinal) &&
!cultureInfo.EnglishName.StartsWith("Invariant Language", StringComparison.Ordinal) &&
cultureInfo.TryGetRegionInfo()?.ISOCurrencySymbol != "EUR";
cultureInfo.Name.Contains('-')
&& !cultureInfo.IsNeutralCulture
&& !cultureInfo.EnglishName.StartsWith("Unknown Locale", StringComparison.Ordinal)
&& !cultureInfo.EnglishName.StartsWith("Invariant Language", StringComparison.Ordinal)
&& cultureInfo.TryGetRegionInfo()?.ISOCurrencySymbol != "EUR";

static int RankCultureByExpectedRelevance(CultureInfo cultureInfo)
{
var parts = cultureInfo.Name.Split('-');

// Prioritize when the language and country ISO codes match, e.g. hu-HU, no-NO, etc. This doesn't help with
// cultures like sv-SE, ja-SP or fa-IR.
if (parts.Length == 2 && parts[0].Equals(parts[1], StringComparison.OrdinalIgnoreCase)) return 0;
if (parts.Length == 2 && parts[0].Equals(parts[1], StringComparison.OrdinalIgnoreCase))
return 0;

// English is usually a safe choice on the Internet.
if (cultureInfo.TwoLetterISOLanguageName == "en") return 1;
if (cultureInfo.TwoLetterISOLanguageName == "en")
return 1;

return int.MaxValue; // Fallback, the rest are sorted alphabetically.
}

lock (_lockObject)
{
// Double check in case another thread has already initialized it.
if (CurrencyTable != null) return;
if (CurrencyTable != null)
return;

var cultures = CultureInfo.GetCultures(CultureTypes.AllCultures).Where(IsValid).ToList();
var cultures = CultureInfo
.GetCultures(CultureTypes.AllCultures)
.Where(IsValid)
.ToList();

CurrencyTable = cultures
.GroupBy(culture => culture.Name.Split('-')[^1])
.Select(group => group
.OrderBy(RankCultureByExpectedRelevance)
.ThenBy(culture => culture.EnglishName)
.First())
.Select(group =>
group
.OrderBy(RankCultureByExpectedRelevance)
.ThenBy(culture => culture.EnglishName)
.First()
)
.Select(culture => new Currency(culture))
.Cast<ICurrency>()
.Distinct(new CurrencyEqualityComparer())
Expand All @@ -70,14 +81,19 @@ static int RankCultureByExpectedRelevance(CultureInfo cultureInfo)
}
}

private static void AddCurrency(ICurrency currency) => CurrencyTable.Add(currency.CurrencyIsoCode, currency);
private static void AddCurrency(ICurrency currency) =>
CurrencyTable.Add(currency.CurrencyIsoCode, currency);

private sealed class CurrencyEqualityComparer : IEqualityComparer<ICurrency>
{
public bool Equals(ICurrency left, ICurrency right) =>
(left is null && right is null) ||
StringComparer.OrdinalIgnoreCase.Equals(left?.CurrencyIsoCode, right?.CurrencyIsoCode);

public int GetHashCode(ICurrency obj) => StringComparer.OrdinalIgnoreCase.GetHashCode(obj.CurrencyIsoCode);
(left is null && right is null)
|| StringComparer.OrdinalIgnoreCase.Equals(
left?.CurrencyIsoCode,
right?.CurrencyIsoCode
);

public int GetHashCode(ICurrency obj) =>
StringComparer.OrdinalIgnoreCase.GetHashCode(obj.CurrencyIsoCode);
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<TargetFrameworks>$(CommonTargetFrameworks)</TargetFrameworks>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
</PropertyGroup>

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk.Razor">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<TargetFrameworks>$(CommonTargetFrameworks)</TargetFrameworks>
<AddRazorSupportForMvc>true</AddRazorSupportForMvc>
</PropertyGroup>

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk.Razor">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<TargetFrameworks>$(CommonTargetFrameworks)</TargetFrameworks>
<AddRazorSupportForMvc>true</AddRazorSupportForMvc>
</PropertyGroup>

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk.Razor">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<TargetFrameworks>$(CommonTargetFrameworks)</TargetFrameworks>
<AddRazorSupportForMvc>true</AddRazorSupportForMvc>
</PropertyGroup>

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk.Razor">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<TargetFrameworks>$(CommonTargetFrameworks)</TargetFrameworks>
<AddRazorSupportForMvc>true</AddRazorSupportForMvc>
</PropertyGroup>

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk.Razor">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<TargetFrameworks>$(CommonTargetFrameworks)</TargetFrameworks>
<AddRazorSupportForMvc>true</AddRazorSupportForMvc>
<Nullable>enable</Nullable>
</PropertyGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ public DummyPaymentProvider(
IHttpContextAccessor hca,
Lazy<IPaymentService> paymentServiceLazy,
IShoppingCartHelpers shoppingCartHelpers,
IHtmlLocalizer<DummyPaymentProvider> htmlLocalizer)
IHtmlLocalizer<DummyPaymentProvider> htmlLocalizer
)
{
_clock = clock;
_hca = hca;
Expand All @@ -36,44 +37,57 @@ public DummyPaymentProvider(
H = htmlLocalizer;
}

public Task<object?> CreatePaymentProviderDataAsync(IPaymentViewModel model, bool isPaymentRequest = false) =>
public Task<object?> CreatePaymentProviderDataAsync(
IPaymentViewModel model,
bool isPaymentRequest = false
) =>
// This provider doesn't have any special data, and it should only be displayed during development even if the
// feature is enabled. So if the condition is met a blank object is returned, otherwise null which will cause
// the provider to be skipped when used through the viewModel.WithProviderDataAsync(providers) method.
Task.FromResult(_hca.HttpContext.IsDevelopmentAndLocalhost() ? new object() : null);
Task.FromResult(
_hca.HttpContext?.IsDevelopmentAndLocalhost() == true ? new object() : null
);

public async Task<PaymentOperationStatusViewModel> UpdateAndRedirectToFinishedOrderAsync(
ContentItem order,
string? shoppingCartId
)
)
{
var createdUtc = order.CreatedUtc ?? _clock.UtcNow;
var cart = await _shoppingCartHelpers.CreateShoppingCartViewModelAsync(shoppingCartId, order);
var totals = cart
.GetTotalsOrThrowIfEmpty()
.Select((total, index) => new Commerce.Abstractions.Models.Payment(
Kind: "Dummy Payment",
TransactionId: $"{order.ContentItemId}:{index.ToTechnicalString()}",
ChargeText: $"Dummy transaction of {total.Currency.EnglishName}.",
total,
createdUtc));
var cart = await _shoppingCartHelpers.CreateShoppingCartViewModelAsync(
shoppingCartId,
order
);

var totals = cart.GetTotalsOrThrowIfEmpty()
.Select(
(total, index) =>
new Commerce.Abstractions.Models.Payment(
Kind: "Dummy Payment",
TransactionId: $"{order.ContentItemId}:{index.ToTechnicalString()}",
ChargeText: $"Dummy transaction of {total.Currency.EnglishName}.",
total,
createdUtc
)
);

try
{
return await _paymentServiceLazy
.Value
.UpdateAndRedirectToFinishedOrderAsync(
return await _paymentServiceLazy.Value.UpdateAndRedirectToFinishedOrderAsync(
order,
shoppingCartId,
ProviderName,
_ => totals);
_ => totals
);
}
catch (Exception ex)
{
return new PaymentOperationStatusViewModel
{
Status = PaymentOperationStatus.Failed,
ShowMessage = H["You have paid the bill, but this system did not record it. Please contact the administrators."],
ShowMessage = H[
"You have paid the bill, but this system did not record it. Please contact the administrators."
],
HideMessage = ex.Message,
Content = order,
};
Expand Down
Loading