diff --git a/Directory.Build.props b/Directory.Build.props index 52635c8fc2..f9fb83457d 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -14,6 +14,7 @@ en-US enable nullable + true enable true false diff --git a/src/Umbraco.Cms.Api.Common/Umbraco.Cms.Api.Common.csproj b/src/Umbraco.Cms.Api.Common/Umbraco.Cms.Api.Common.csproj index 10cc87c013..a1bd4e1694 100644 --- a/src/Umbraco.Cms.Api.Common/Umbraco.Cms.Api.Common.csproj +++ b/src/Umbraco.Cms.Api.Common/Umbraco.Cms.Api.Common.csproj @@ -3,7 +3,6 @@ Umbraco CMS - API Common Contains the bits and pieces that are shared between the Umbraco CMS APIs. - diff --git a/src/Umbraco.Cms.Api.Delivery/Umbraco.Cms.Api.Delivery.csproj b/src/Umbraco.Cms.Api.Delivery/Umbraco.Cms.Api.Delivery.csproj index 8948a49a1a..5e32b81eeb 100644 --- a/src/Umbraco.Cms.Api.Delivery/Umbraco.Cms.Api.Delivery.csproj +++ b/src/Umbraco.Cms.Api.Delivery/Umbraco.Cms.Api.Delivery.csproj @@ -3,7 +3,10 @@ Umbraco CMS - Delivery API Contains the presentation layer for the Umbraco CMS Delivery API. - + + + ASP0019 + diff --git a/src/Umbraco.Cms.Api.Management/Controllers/Indexer/RebuildIndexerController.cs b/src/Umbraco.Cms.Api.Management/Controllers/Indexer/RebuildIndexerController.cs index b64c252a1a..97131adcb9 100644 --- a/src/Umbraco.Cms.Api.Management/Controllers/Indexer/RebuildIndexerController.cs +++ b/src/Umbraco.Cms.Api.Management/Controllers/Indexer/RebuildIndexerController.cs @@ -1,4 +1,4 @@ -using Asp.Versioning; +using Asp.Versioning; using Examine; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; @@ -38,7 +38,7 @@ public class RebuildIndexerController : IndexerControllerBase [ProducesResponseType(StatusCodes.Status200OK)] public async Task Rebuild(CancellationToken cancellationToken, string indexName) { - if (!_examineManager.TryGetIndex(indexName, out var index)) + if (!_examineManager.TryGetIndex(indexName, out IIndex? index)) { var invalidModelProblem = new ProblemDetails { diff --git a/src/Umbraco.Cms.Api.Management/Controllers/ModelsBuilder/BuildModelsBuilderController.cs b/src/Umbraco.Cms.Api.Management/Controllers/ModelsBuilder/BuildModelsBuilderController.cs index 9d5f67cb1f..14adb70c3b 100644 --- a/src/Umbraco.Cms.Api.Management/Controllers/ModelsBuilder/BuildModelsBuilderController.cs +++ b/src/Umbraco.Cms.Api.Management/Controllers/ModelsBuilder/BuildModelsBuilderController.cs @@ -1,8 +1,9 @@ -using System; +using System; using System.Threading.Tasks; using Asp.Versioning; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using Umbraco.Cms.Core.Configuration.Models; using Umbraco.Cms.Infrastructure.ModelsBuilder; @@ -16,12 +17,13 @@ public class BuildModelsBuilderController : ModelsBuilderControllerBase { private ModelsBuilderSettings _modelsBuilderSettings; private readonly ModelsGenerationError _mbErrors; - private readonly ModelsGenerator _modelGenerator; + private readonly IModelsGenerator _modelGenerator; + [ActivatorUtilitiesConstructor] public BuildModelsBuilderController( IOptionsMonitor modelsBuilderSettings, ModelsGenerationError mbErrors, - ModelsGenerator modelGenerator) + IModelsGenerator modelGenerator) { _mbErrors = mbErrors; _modelGenerator = modelGenerator; @@ -30,6 +32,26 @@ public class BuildModelsBuilderController : ModelsBuilderControllerBase modelsBuilderSettings.OnChange(x => _modelsBuilderSettings = x); } + [Obsolete("Please use the constructor that accepts IModelsGenerator only. Will be removed in V16.")] + public BuildModelsBuilderController( + IOptionsMonitor modelsBuilderSettings, + ModelsGenerationError mbErrors, + ModelsGenerator modelGenerator) + : this(modelsBuilderSettings, mbErrors, (IModelsGenerator)modelGenerator) + { + } + + // this constructor is required for the DI, otherwise it'll throw an "Ambiguous Constructor" errors at boot time. + [Obsolete("Please use the constructor that accepts IModelsGenerator only. Will be removed in V16.")] + public BuildModelsBuilderController( + IOptionsMonitor modelsBuilderSettings, + ModelsGenerationError mbErrors, + IModelsGenerator modelGenerator, + ModelsGenerator notUsed) + : this(modelsBuilderSettings, mbErrors, modelGenerator) + { + } + [HttpPost("build")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status428PreconditionRequired)] diff --git a/src/Umbraco.Cms.Api.Management/Controllers/Security/BackOfficeController.cs b/src/Umbraco.Cms.Api.Management/Controllers/Security/BackOfficeController.cs index fd6d9116c5..5a247a647c 100644 --- a/src/Umbraco.Cms.Api.Management/Controllers/Security/BackOfficeController.cs +++ b/src/Umbraco.Cms.Api.Management/Controllers/Security/BackOfficeController.cs @@ -1,4 +1,4 @@ -using System.Security.Claims; +using System.Security.Claims; using Asp.Versioning; using Microsoft.AspNetCore; using Microsoft.AspNetCore.Authentication; @@ -217,7 +217,7 @@ public class BackOfficeController : SecurityControllerBase /// /// Called when a user links an external login provider in the back office /// - /// + /// /// // This method is marked as AllowAnonymous and protected with a secret (linkKey) inside the model for the following reasons // - when a js client uses the fetch api (or old ajax requests) they can send a bearer token diff --git a/src/Umbraco.Cms.Api.Management/Factories/MediaTypeEditingPresentationFactory.cs b/src/Umbraco.Cms.Api.Management/Factories/MediaTypeEditingPresentationFactory.cs index 11b2d18134..c5cd70ed49 100644 --- a/src/Umbraco.Cms.Api.Management/Factories/MediaTypeEditingPresentationFactory.cs +++ b/src/Umbraco.Cms.Api.Management/Factories/MediaTypeEditingPresentationFactory.cs @@ -1,5 +1,4 @@ -using Umbraco.Cms.Api.Management.ViewModels.MediaType; -using Umbraco.Cms.Core.Models; +using Umbraco.Cms.Api.Management.ViewModels.MediaType; using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Models.ContentTypeEditing; using Umbraco.Cms.Core.Services; diff --git a/src/Umbraco.Cms.Api.Management/Umbraco.Cms.Api.Management.csproj b/src/Umbraco.Cms.Api.Management/Umbraco.Cms.Api.Management.csproj index 37ab3611de..88ee0cef62 100644 --- a/src/Umbraco.Cms.Api.Management/Umbraco.Cms.Api.Management.csproj +++ b/src/Umbraco.Cms.Api.Management/Umbraco.Cms.Api.Management.csproj @@ -7,7 +7,10 @@ Umbraco.Cms.Api.Management Umbraco.Cms.Api.Management - + + + false + diff --git a/src/Umbraco.Cms.Imaging.ImageSharp/Umbraco.Cms.Imaging.ImageSharp.csproj b/src/Umbraco.Cms.Imaging.ImageSharp/Umbraco.Cms.Imaging.ImageSharp.csproj index 549ea5cb40..77aed066d8 100644 --- a/src/Umbraco.Cms.Imaging.ImageSharp/Umbraco.Cms.Imaging.ImageSharp.csproj +++ b/src/Umbraco.Cms.Imaging.ImageSharp/Umbraco.Cms.Imaging.ImageSharp.csproj @@ -3,7 +3,6 @@ Umbraco CMS - Imaging - ImageSharp Adds imaging support using ImageSharp/ImageSharp.Web to Umbraco CMS. - diff --git a/src/Umbraco.Cms.Imaging.ImageSharp2/Umbraco.Cms.Imaging.ImageSharp2.csproj b/src/Umbraco.Cms.Imaging.ImageSharp2/Umbraco.Cms.Imaging.ImageSharp2.csproj index c513082675..16bac191d5 100644 --- a/src/Umbraco.Cms.Imaging.ImageSharp2/Umbraco.Cms.Imaging.ImageSharp2.csproj +++ b/src/Umbraco.Cms.Imaging.ImageSharp2/Umbraco.Cms.Imaging.ImageSharp2.csproj @@ -3,7 +3,6 @@ Umbraco CMS - Imaging - ImageSharp 2 Adds imaging support using ImageSharp/ImageSharp.Web version 2 to Umbraco CMS. - diff --git a/src/Umbraco.Cms.Persistence.EFCore.SqlServer/Umbraco.Cms.Persistence.EFCore.SqlServer.csproj b/src/Umbraco.Cms.Persistence.EFCore.SqlServer/Umbraco.Cms.Persistence.EFCore.SqlServer.csproj index d663ef0197..a1864f636f 100644 --- a/src/Umbraco.Cms.Persistence.EFCore.SqlServer/Umbraco.Cms.Persistence.EFCore.SqlServer.csproj +++ b/src/Umbraco.Cms.Persistence.EFCore.SqlServer/Umbraco.Cms.Persistence.EFCore.SqlServer.csproj @@ -3,7 +3,6 @@ Umbraco CMS - Persistence - Entity Framework Core - SQL Server migrations Adds support for Entity Framework Core SQL Server migrations to Umbraco CMS. - diff --git a/src/Umbraco.Cms.Persistence.EFCore.Sqlite/Umbraco.Cms.Persistence.EFCore.Sqlite.csproj b/src/Umbraco.Cms.Persistence.EFCore.Sqlite/Umbraco.Cms.Persistence.EFCore.Sqlite.csproj index 36751bb869..f847ef4786 100644 --- a/src/Umbraco.Cms.Persistence.EFCore.Sqlite/Umbraco.Cms.Persistence.EFCore.Sqlite.csproj +++ b/src/Umbraco.Cms.Persistence.EFCore.Sqlite/Umbraco.Cms.Persistence.EFCore.Sqlite.csproj @@ -3,7 +3,6 @@ Umbraco CMS - Persistence - Entity Framework Core - SQLite migrations Adds support for Entity Framework Core SQLite migrations to Umbraco CMS. - diff --git a/src/Umbraco.Cms.Persistence.EFCore/Locking/SqliteEFCoreDistributedLockingMechanism.cs b/src/Umbraco.Cms.Persistence.EFCore/Locking/SqliteEFCoreDistributedLockingMechanism.cs index 23b3d8d410..8308ae4d3a 100644 --- a/src/Umbraco.Cms.Persistence.EFCore/Locking/SqliteEFCoreDistributedLockingMechanism.cs +++ b/src/Umbraco.Cms.Persistence.EFCore/Locking/SqliteEFCoreDistributedLockingMechanism.cs @@ -115,12 +115,7 @@ internal class SqliteEFCoreDistributedLockingMechanism : IDistributedLockingM // Mostly no-op just check that we didn't end up ReadUncommitted for real. private void ObtainReadLock() { - IEfCoreScope? efCoreScope = _parent._efCoreScopeAccessor.Value.AmbientScope; - - if (efCoreScope is null) - { - throw new PanicException("No current ambient scope"); - } + IEfCoreScope? efCoreScope = _parent._efCoreScopeAccessor.Value.AmbientScope ?? throw new PanicException("No current ambient scope"); efCoreScope.ExecuteWithContextAsync(async database => { @@ -136,12 +131,7 @@ internal class SqliteEFCoreDistributedLockingMechanism : IDistributedLockingM // lock occurs for entire database as opposed to row/table. private void ObtainWriteLock() { - IEfCoreScope? efCoreScope = _parent._efCoreScopeAccessor.Value.AmbientScope; - - if (efCoreScope is null) - { - throw new PanicException("No ambient scope"); - } + IEfCoreScope? efCoreScope = _parent._efCoreScopeAccessor.Value.AmbientScope ?? throw new PanicException("No ambient scope"); efCoreScope.ExecuteWithContextAsync(async database => { diff --git a/src/Umbraco.Cms.Persistence.EFCore/Umbraco.Cms.Persistence.EFCore.csproj b/src/Umbraco.Cms.Persistence.EFCore/Umbraco.Cms.Persistence.EFCore.csproj index 4500c2812b..d5fc7229b0 100644 --- a/src/Umbraco.Cms.Persistence.EFCore/Umbraco.Cms.Persistence.EFCore.csproj +++ b/src/Umbraco.Cms.Persistence.EFCore/Umbraco.Cms.Persistence.EFCore.csproj @@ -3,8 +3,12 @@ Umbraco CMS - Persistence - Entity Framework Core Adds support for Entity Framework Core to Umbraco CMS. - - + + + IDE0270,CS0108,CS1998 + + diff --git a/src/Umbraco.Cms.Persistence.SqlServer/LocalDb.cs b/src/Umbraco.Cms.Persistence.SqlServer/LocalDb.cs index 6fcdfca76a..a8a6480c89 100644 --- a/src/Umbraco.Cms.Persistence.SqlServer/LocalDb.cs +++ b/src/Umbraco.Cms.Persistence.SqlServer/LocalDb.cs @@ -420,7 +420,13 @@ public class LocalDb /// public bool CreateDatabase(string databaseName, string filesPath) { - GetDatabaseFiles(databaseName, filesPath, out var logName, out _, out _, out var mdfFilename, + GetDatabaseFiles( + databaseName, + filesPath, + out var logName, + out _, + out _, + out var mdfFilename, out var ldfFilename); using (var conn = new SqlConnection(_masterCstr)) @@ -463,7 +469,9 @@ public class LocalDb { conn.Open(); - SetCommand(cmd, @" + SetCommand( + cmd, + @" SELECT name, filename FROM master.dbo.sysdatabases WHERE ('[' + name + ']' = @0 OR name = @0)", databaseName); @@ -554,11 +562,7 @@ public class LocalDb { conn.Open(); - var mdf = GetDatabase(cmd, databaseName); - if (mdf == null) - { - throw new InvalidOperationException("Database does not exist."); - } + var mdf = GetDatabase(cmd, databaseName) ?? throw new InvalidOperationException("Database does not exist."); DetachDatabase(cmd, databaseName); @@ -597,9 +601,12 @@ public class LocalDb /// The LDF logical name. /// The MDF filename. /// The LDF filename. - public void GetFilenames(string databaseName, - out string? mdfName, out string? ldfName, - out string? mdfFilename, out string? ldfFilename) + public void GetFilenames( + string databaseName, + out string? mdfName, + out string? ldfName, + out string? mdfFilename, + out string? ldfFilename) { using (var conn = new SqlConnection(_masterCstr)) using (SqlCommand? cmd = conn.CreateCommand()) @@ -621,7 +628,9 @@ public class LocalDb { conn.Open(); - SetCommand(cmd, @" + SetCommand( + cmd, + @" DECLARE @sql VARCHAR(MAX); SELECT @sql = COALESCE(@sql,'') + 'kill ' + CONVERT(VARCHAR, SPId) + ';' FROM master.sys.sysprocesses @@ -640,7 +649,9 @@ public class LocalDb /// The full filename of the MDF file, if the database exists, otherwise null. private static string? GetDatabase(SqlCommand cmd, string databaseName) { - SetCommand(cmd, @" + SetCommand( + cmd, + @" SELECT name, filename FROM master.dbo.sysdatabases WHERE ('[' + name + ']' = @0 OR name = @0)", databaseName); @@ -707,7 +718,7 @@ public class LocalDb File.Delete(mdf); } - ldf = ldf ?? GetLogFilename(mdf); + ldf ??= GetLogFilename(mdf); if (File.Exists(ldf)) { File.Delete(ldf); @@ -726,7 +737,7 @@ public class LocalDb throw new ArgumentException("Not a valid MDF filename (no .mdf extension).", nameof(mdfFilename)); } - return mdfFilename.Substring(0, mdfFilename.Length - ".mdf".Length) + "_log.ldf"; + return mdfFilename[..^".mdf".Length] + "_log.ldf"; } /// @@ -743,7 +754,9 @@ public class LocalDb var unused1 = cmd.ExecuteNonQuery(); - SetCommand(cmd, @" + SetCommand( + cmd, + @" EXEC sp_detach_db @dbname=@0", databaseName); @@ -758,8 +771,14 @@ public class LocalDb /// The directory containing database files. private static void AttachDatabase(SqlCommand cmd, string databaseName, string filesPath) { - GetDatabaseFiles(databaseName, filesPath, - out var logName, out _, out _, out var mdfFilename, out var ldfFilename); + GetDatabaseFiles( + databaseName, + filesPath, + out var logName, + out _, + out _, + out var mdfFilename, + out var ldfFilename); // cannot use parameters on CREATE DATABASE // ie "CREATE DATABASE @0 ..." does not work @@ -802,13 +821,19 @@ public class LocalDb /// The LDF logical name. /// The MDF filename. /// The LDF filename. - private void GetFilenames(SqlCommand cmd, string databaseName, - out string? mdfName, out string? ldfName, - out string? mdfFilename, out string? ldfFilename) + private void GetFilenames( + SqlCommand cmd, + string databaseName, + out string? mdfName, + out string? ldfName, + out string? mdfFilename, + out string? ldfFilename) { mdfName = ldfName = mdfFilename = ldfFilename = null; - SetCommand(cmd, @" + SetCommand( + cmd, + @" SELECT DB_NAME(database_id), type_desc, name, physical_name FROM master.sys.master_files WHERE database_id=DB_ID(@0)", @@ -854,21 +879,32 @@ public class LocalDb /// . /// Extensions are used eg to copy MyDatabase.mdf to MyDatabase.mdf.temp. /// - public void CopyDatabaseFiles(string databaseName, string filesPath, - string? targetDatabaseName = null, string? targetFilesPath = null, - string? sourceExtension = null, string? targetExtension = null, - bool overwrite = false, bool delete = false) + public void CopyDatabaseFiles( + string databaseName, + string filesPath, + string? targetDatabaseName = null, + string? targetFilesPath = null, + string? sourceExtension = null, + string? targetExtension = null, + bool overwrite = false, + bool delete = false) { var nop = (targetFilesPath == null || targetFilesPath == filesPath) && (targetDatabaseName == null || targetDatabaseName == databaseName) - && (sourceExtension == null && targetExtension == null || sourceExtension == targetExtension); + && ((sourceExtension == null && targetExtension == null) || sourceExtension == targetExtension); if (nop && delete == false) { return; } - GetDatabaseFiles(databaseName, filesPath, - out _, out _, out _, out var mdfFilename, out var ldfFilename); + GetDatabaseFiles( + databaseName, + filesPath, + out _, + out _, + out _, + out var mdfFilename, + out var ldfFilename); if (sourceExtension != null) { @@ -892,8 +928,14 @@ public class LocalDb else { // copy or copy+delete ie move - GetDatabaseFiles(targetDatabaseName ?? databaseName, targetFilesPath ?? filesPath, - out _, out _, out _, out var targetMdfFilename, out var targetLdfFilename); + GetDatabaseFiles( + targetDatabaseName ?? databaseName, + targetFilesPath ?? filesPath, + out _, + out _, + out _, + out var targetMdfFilename, + out var targetLdfFilename); if (targetExtension != null) { @@ -936,8 +978,14 @@ public class LocalDb /// public bool DatabaseFilesExist(string databaseName, string filesPath, string? extension = null) { - GetDatabaseFiles(databaseName, filesPath, - out _, out _, out _, out var mdfFilename, out var ldfFilename); + GetDatabaseFiles( + databaseName, + filesPath, + out _, + out _, + out _, + out var mdfFilename, + out var ldfFilename); if (extension != null) { @@ -958,10 +1006,14 @@ public class LocalDb /// The base log filename (the LDF filename without the .ldf extension). /// The MDF filename. /// The LDF filename. - private static void GetDatabaseFiles(string databaseName, string filesPath, + private static void GetDatabaseFiles( + string databaseName, + string filesPath, out string logName, - out string baseFilename, out string baseLogFilename, - out string mdfFilename, out string ldfFilename) + out string baseFilename, + out string baseLogFilename, + out string mdfFilename, + out string ldfFilename) { logName = databaseName + "_log"; baseFilename = Path.Combine(filesPath, databaseName); diff --git a/src/Umbraco.Cms.Persistence.SqlServer/Umbraco.Cms.Persistence.SqlServer.csproj b/src/Umbraco.Cms.Persistence.SqlServer/Umbraco.Cms.Persistence.SqlServer.csproj index 9aef183cf6..1061c89526 100644 --- a/src/Umbraco.Cms.Persistence.SqlServer/Umbraco.Cms.Persistence.SqlServer.csproj +++ b/src/Umbraco.Cms.Persistence.SqlServer/Umbraco.Cms.Persistence.SqlServer.csproj @@ -3,7 +3,12 @@ Umbraco CMS - Persistence - SQL Server Adds support for SQL Server to Umbraco CMS. - + + + SA1405,SA1121,SA1117,SA1116,IDE1006,CS0618,IDE0270,IDE0057,IDE0054,CSO618,IDE0048,CS1574 + diff --git a/src/Umbraco.Cms.Persistence.Sqlite/Umbraco.Cms.Persistence.Sqlite.csproj b/src/Umbraco.Cms.Persistence.Sqlite/Umbraco.Cms.Persistence.Sqlite.csproj index f9755aad61..0c39c66d64 100644 --- a/src/Umbraco.Cms.Persistence.Sqlite/Umbraco.Cms.Persistence.Sqlite.csproj +++ b/src/Umbraco.Cms.Persistence.Sqlite/Umbraco.Cms.Persistence.Sqlite.csproj @@ -3,7 +3,10 @@ Umbraco CMS - Persistence - SQLite Adds support for SQLite to Umbraco CMS. - + + + CS0114 + diff --git a/src/Umbraco.Cms.StaticAssets/Umbraco.Cms.StaticAssets.csproj b/src/Umbraco.Cms.StaticAssets/Umbraco.Cms.StaticAssets.csproj index e186d9789d..a67dafbac5 100644 --- a/src/Umbraco.Cms.StaticAssets/Umbraco.Cms.StaticAssets.csproj +++ b/src/Umbraco.Cms.StaticAssets/Umbraco.Cms.StaticAssets.csproj @@ -6,6 +6,11 @@ / + + + NU5123 + + @@ -71,4 +76,4 @@ - + \ No newline at end of file diff --git a/src/Umbraco.Cms.Targets/Umbraco.Cms.Targets.csproj b/src/Umbraco.Cms.Targets/Umbraco.Cms.Targets.csproj index a9a7604e7c..0ed86b3564 100644 --- a/src/Umbraco.Cms.Targets/Umbraco.Cms.Targets.csproj +++ b/src/Umbraco.Cms.Targets/Umbraco.Cms.Targets.csproj @@ -5,7 +5,11 @@ false false - + + + IDE0270,CS0108,CS1998 + diff --git a/src/Umbraco.Cms/Umbraco.Cms.csproj b/src/Umbraco.Cms/Umbraco.Cms.csproj index 39a3b03c56..3bc60ebd12 100644 --- a/src/Umbraco.Cms/Umbraco.Cms.csproj +++ b/src/Umbraco.Cms/Umbraco.Cms.csproj @@ -5,7 +5,6 @@ false false - diff --git a/src/Umbraco.Core/Constants-HealthChecks.cs b/src/Umbraco.Core/Constants-HealthChecks.cs index bb18145401..d4b35f4e04 100644 --- a/src/Umbraco.Core/Constants-HealthChecks.cs +++ b/src/Umbraco.Core/Constants-HealthChecks.cs @@ -52,6 +52,7 @@ public static partial class Constants [Obsolete("This link is not used anymore in the XSS protected check.")] public const string XssProtectionCheck = "https://umbra.co/healthchecks-xss-protection"; public const string ExcessiveHeadersCheck = "https://umbra.co/healthchecks-excessive-headers"; + public const string CspHeaderCheck = "https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP"; public static class HttpsCheck { diff --git a/src/Umbraco.Core/EmbeddedResources/Lang/en.xml b/src/Umbraco.Core/EmbeddedResources/Lang/en.xml index 893ab7c242..c05ea72cfc 100644 --- a/src/Umbraco.Core/EmbeddedResources/Lang/en.xml +++ b/src/Umbraco.Core/EmbeddedResources/Lang/en.xml @@ -467,6 +467,12 @@ You can read about this on the Mozilla website ]]> X-XSS-Protection was not found.]]> + + Content-Security-Policy (CSP) was found. ]]> + + + Content-Security-Policy (CSP) used to prevent cross-site scripting (XSS) attacks and other code injection vulnerabilities was not found.]]> + %0%.]]> No headers revealing information about the website technology were found. diff --git a/src/Umbraco.Core/EmbeddedResources/Lang/en_us.xml b/src/Umbraco.Core/EmbeddedResources/Lang/en_us.xml index 69558f72da..dec3809f8d 100644 --- a/src/Umbraco.Core/EmbeddedResources/Lang/en_us.xml +++ b/src/Umbraco.Core/EmbeddedResources/Lang/en_us.xml @@ -455,6 +455,12 @@ You can read about this on the Mozilla website ]]> X-XSS-Protection was not found.]]> + + Content-Security-Policy (CSP) was found. ]]> + + + Content-Security-Policy (CSP) used to prevent cross-site scripting (XSS) attacks and other code injection vulnerabilities was not found.]]> + %0%.]]> No headers revealing information about the website technology were found. diff --git a/src/Umbraco.Core/HealthChecks/Checks/Security/CspCheck.cs b/src/Umbraco.Core/HealthChecks/Checks/Security/CspCheck.cs new file mode 100644 index 0000000000..1ac8cf56f4 --- /dev/null +++ b/src/Umbraco.Core/HealthChecks/Checks/Security/CspCheck.cs @@ -0,0 +1,31 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + +using Umbraco.Cms.Core.Hosting; +using Umbraco.Cms.Core.Services; + +namespace Umbraco.Cms.Core.HealthChecks.Checks.Security; + +/// +/// Health check for the recommended production setup regarding the content-security-policy header. +/// +[HealthCheck( + "10BEBF47-C128-4C5E-9680-5059BEAFBBDF", + "Content Security Policy (CSP)", + Description = "Checks whether the site contains a Content-Security-Policy (CSP) header.", + Group = "Security")] +public class CspCheck : BaseHttpHeaderCheck +{ + private const string LocalizationPrefix = "contentSecurityPolicy"; + + /// + /// Initializes a new instance of the class. + /// + public CspCheck(IHostingEnvironment hostingEnvironment, ILocalizedTextService textService) + : base(hostingEnvironment, textService, "Content-Security-Policy", LocalizationPrefix, false, false) + { + } + + /// + protected override string ReadMoreLink => Constants.HealthChecks.DocumentationLinks.Security.CspHeaderCheck; +} diff --git a/src/Umbraco.Core/Logging/DisposableTimer.cs b/src/Umbraco.Core/Logging/DisposableTimer.cs index 087ae7adb6..7db20a0068 100644 --- a/src/Umbraco.Core/Logging/DisposableTimer.cs +++ b/src/Umbraco.Core/Logging/DisposableTimer.cs @@ -44,7 +44,7 @@ public class DisposableTimer : DisposableObjectSlim _endMessageArgs = endMessageArgs; _failMessageArgs = failMessageArgs; _thresholdMilliseconds = thresholdMilliseconds < 0 ? 0 : thresholdMilliseconds; - _timingId = Guid.NewGuid().ToString("N").Substring(0, 7); // keep it short-ish + _timingId = Guid.NewGuid().ToString("N")[..7]; // keep it short-ish if (thresholdMilliseconds == 0) { @@ -63,7 +63,7 @@ public class DisposableTimer : DisposableObjectSlim var args = new object[startMessageArgs.Length + 1]; startMessageArgs.CopyTo(args, 0); args[^1] = _timingId; - + if (_logger.IsEnabled(Microsoft.Extensions.Logging.LogLevel.Debug)) { logger.LogDebug(startMessage + " [Timing {TimingId}]", args); diff --git a/src/Umbraco.Core/Models/Membership/UserGroup.cs b/src/Umbraco.Core/Models/Membership/UserGroup.cs index c512702d54..95f8dee7b8 100644 --- a/src/Umbraco.Core/Models/Membership/UserGroup.cs +++ b/src/Umbraco.Core/Models/Membership/UserGroup.cs @@ -58,8 +58,6 @@ public class UserGroup : EntityBase, IUserGroup, IReadOnlyUserGroup /// /// /// - /// - /// /// /// public UserGroup( diff --git a/src/Umbraco.Core/Persistence/Repositories/ITrackedReferencesRepository.cs b/src/Umbraco.Core/Persistence/Repositories/ITrackedReferencesRepository.cs index fda745c2f6..4442e5ecf2 100644 --- a/src/Umbraco.Core/Persistence/Repositories/ITrackedReferencesRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/ITrackedReferencesRepository.cs @@ -54,7 +54,7 @@ public interface ITrackedReferencesRepository /// Gets a page of items which are in relation with the current item. /// Basically, shows the items which depend on the current item. /// - /// The identifier of the entity to retrieve relations for. + /// The identifier of the entity to retrieve relations for. /// The amount of items to skip. /// The amount of items to take. /// @@ -81,7 +81,7 @@ public interface ITrackedReferencesRepository /// /// Gets a page of items used in any kind of relation from selected integer ids. /// - /// The identifiers of the entities to check for relations. + /// The identifiers of the entities to check for relations. /// The amount of items to skip. /// The amount of items to take. /// diff --git a/src/Umbraco.Core/PropertyEditors/JsonPropertyIndexValueFactoryBase.cs b/src/Umbraco.Core/PropertyEditors/JsonPropertyIndexValueFactoryBase.cs index a6f3b5739b..e4a7492c5d 100644 --- a/src/Umbraco.Core/PropertyEditors/JsonPropertyIndexValueFactoryBase.cs +++ b/src/Umbraco.Core/PropertyEditors/JsonPropertyIndexValueFactoryBase.cs @@ -2,7 +2,6 @@ using Microsoft.Extensions.Options; using Umbraco.Cms.Core.Configuration.Models; using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Serialization; -using Umbraco.Cms.Core.Serialization; using Umbraco.Extensions; namespace Umbraco.Cms.Core.PropertyEditors; diff --git a/src/Umbraco.Core/Routing/ContentFinderByUrlAndTemplate.cs b/src/Umbraco.Core/Routing/ContentFinderByUrlAndTemplate.cs index 39fc468cee..200a7d7143 100644 --- a/src/Umbraco.Core/Routing/ContentFinderByUrlAndTemplate.cs +++ b/src/Umbraco.Core/Routing/ContentFinderByUrlAndTemplate.cs @@ -77,8 +77,8 @@ public class ContentFinderByUrlAndTemplate : ContentFinderByUrl // look for template in last position var pos = path.LastIndexOf('/'); - var templateAlias = path.Substring(pos + 1); - path = pos == 0 ? "/" : path.Substring(0, pos);; + var templateAlias = path[(pos + 1)..]; + path = pos == 0 ? "/" : path[..pos]; ITemplate? template = _fileService.GetTemplate(templateAlias); diff --git a/src/Umbraco.Core/Routing/DefaultUrlProvider.cs b/src/Umbraco.Core/Routing/DefaultUrlProvider.cs index c30d5453aa..4a5d5d2826 100644 --- a/src/Umbraco.Core/Routing/DefaultUrlProvider.cs +++ b/src/Umbraco.Core/Routing/DefaultUrlProvider.cs @@ -98,7 +98,7 @@ public class DefaultUrlProvider : IUrlProvider // need to strip off the leading ID for the route if it exists (occurs if the route is for a node with a domain assigned) var pos = route.IndexOf('/'); - var path = pos == 0 ? route : route.Substring(pos); + var path = pos == 0 ? route : route[pos..]; var uri = new Uri(CombinePaths(d.Uri.GetLeftPart(UriPartial.Path), path)); uri = _uriUtility.UriFromUmbraco(uri, _requestSettings); diff --git a/src/Umbraco.Core/Services/ContentService.cs b/src/Umbraco.Core/Services/ContentService.cs index dd61585203..cd005b576c 100644 --- a/src/Umbraco.Core/Services/ContentService.cs +++ b/src/Umbraco.Core/Services/ContentService.cs @@ -582,10 +582,7 @@ public class ContentService : RepositoryService, IContentService throw new ArgumentOutOfRangeException(nameof(pageSize)); } - if (ordering == null) - { - ordering = Ordering.By("sortOrder"); - } + ordering ??= Ordering.By("sortOrder"); using (ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true)) { @@ -613,10 +610,7 @@ public class ContentService : RepositoryService, IContentService throw new ArgumentOutOfRangeException(nameof(pageSize)); } - if (ordering == null) - { - ordering = Ordering.By("sortOrder"); - } + ordering ??= Ordering.By("sortOrder"); using (ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true)) { @@ -773,10 +767,7 @@ public class ContentService : RepositoryService, IContentService throw new ArgumentOutOfRangeException(nameof(pageSize)); } - if (ordering == null) - { - ordering = Ordering.By("sortOrder"); - } + ordering ??= Ordering.By("sortOrder"); using (ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true)) { @@ -790,10 +781,7 @@ public class ContentService : RepositoryService, IContentService /// public IEnumerable GetPagedDescendants(int id, long pageIndex, int pageSize, out long totalChildren, IQuery? filter = null, Ordering? ordering = null) { - if (ordering == null) - { - ordering = Ordering.By("Path"); - } + ordering ??= Ordering.By("Path"); using (ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true)) { @@ -931,10 +919,7 @@ public class ContentService : RepositoryService, IContentService { using (ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true)) { - if (ordering == null) - { - ordering = Ordering.By("Path"); - } + ordering ??= Ordering.By("Path"); scope.ReadLock(Constants.Locks.ContentTree); IQuery? query = Query()? @@ -1361,6 +1346,7 @@ public class ContentService : RepositoryService, IContentService /// /// /// + /// /// /// /// @@ -1831,7 +1817,7 @@ public class ContentService : RepositoryService, IContentService // publish the culture values and validate the property values, if validation fails, log the invalid properties so the develeper has an idea of what has failed IProperty[]? invalidProperties = null; - var impact = _cultureImpactFactory.ImpactExplicit(culture, IsDefaultCulture(allLangs.Value, culture)); + CultureImpact impact = _cultureImpactFactory.ImpactExplicit(culture, IsDefaultCulture(allLangs.Value, culture)); var tryPublish = d.PublishCulture(impact) && _propertyValidationService.Value.IsPropertyDataValid(d, out invalidProperties, impact); if (invalidProperties != null && invalidProperties.Length > 0) @@ -1913,7 +1899,7 @@ public class ContentService : RepositoryService, IContentService { return culturesToPublish.All(culture => { - var impact = _cultureImpactFactory.Create(culture, IsDefaultCulture(allLangs, culture), content); + CultureImpact? impact = _cultureImpactFactory.Create(culture, IsDefaultCulture(allLangs, culture), content); return content.PublishCulture(impact) && _propertyValidationService.Value.IsPropertyDataValid(content, out _, impact); }); @@ -1929,10 +1915,7 @@ public class ContentService : RepositoryService, IContentService // if published, republish if (published) { - if (cultures == null) - { - cultures = new HashSet(); // empty means 'already published' - } + cultures ??= new HashSet(); // empty means 'already published' if (edited) { @@ -1948,10 +1931,7 @@ public class ContentService : RepositoryService, IContentService return cultures; // null means 'nothing to do' } - if (cultures == null) - { - cultures = new HashSet(); - } + cultures ??= new HashSet(); cultures.Add(c); // means 'publish this culture' return cultures; @@ -2654,7 +2634,6 @@ public class ContentService : RepositoryService, IContentService /// /// The to copy /// Id of the Content's new Parent - /// Key of the Content's new Parent /// Boolean indicating whether the copy should be related to the original /// A value indicating whether to recursively copy children. /// Optional Id of the User copying the Content @@ -3300,6 +3279,7 @@ public class ContentService : RepositoryService, IContentService /// /// /// + /// /// private PublishResult StrategyCanUnpublish( ICoreScope scope, @@ -3308,7 +3288,7 @@ public class ContentService : RepositoryService, IContentService IDictionary? notificationState) { // raise Unpublishing notification - var notification = new ContentUnpublishingNotification(content, evtMsgs).WithState(notificationState); + ContentUnpublishingNotification notification = new ContentUnpublishingNotification(content, evtMsgs).WithState(notificationState); var notificationResult = scope.Notifications.PublishCancelable(notification); if (notificationResult) diff --git a/src/Umbraco.Core/Services/DataTypeService.cs b/src/Umbraco.Core/Services/DataTypeService.cs index 382238d583..7797a30015 100644 --- a/src/Umbraco.Core/Services/DataTypeService.cs +++ b/src/Umbraco.Core/Services/DataTypeService.cs @@ -330,7 +330,7 @@ namespace Umbraco.Cms.Core.Services.Implement return Task.FromResult(dataTypes); } - + /// public async Task> GetByEditorAliasAsync(string[] propertyEditorAlias) { @@ -555,7 +555,7 @@ namespace Umbraco.Cms.Core.Services.Implement return Attempt.FailWithStatus(DataTypeOperationStatus.DuplicateKey, dataType); } - var result = await SaveAsync(dataType, () => DataTypeOperationStatus.Success, userKey, AuditType.New); + Attempt result = await SaveAsync(dataType, () => DataTypeOperationStatus.Success, userKey, AuditType.New); scope.Complete(); diff --git a/src/Umbraco.Core/Services/IAuditService.cs b/src/Umbraco.Core/Services/IAuditService.cs index e4c973ced0..7481a5e613 100644 --- a/src/Umbraco.Core/Services/IAuditService.cs +++ b/src/Umbraco.Core/Services/IAuditService.cs @@ -105,10 +105,9 @@ public interface IAuditService : IService /// /// Returns paged items in the audit trail for a given user /// - /// - /// - /// - /// + /// + /// + /// /// /// By default this will always be ordered descending (newest first) /// @@ -117,9 +116,7 @@ public interface IAuditService : IService /// or the custom filter /// so we need to do that here /// - /// - /// Optional filter to be applied - /// + /// /// Task> GetPagedItemsByUserAsync( Guid userKey, diff --git a/src/Umbraco.Core/Services/IContentPublishingService.cs b/src/Umbraco.Core/Services/IContentPublishingService.cs index 0d60da7313..701aba3166 100644 --- a/src/Umbraco.Core/Services/IContentPublishingService.cs +++ b/src/Umbraco.Core/Services/IContentPublishingService.cs @@ -1,4 +1,4 @@ -using Umbraco.Cms.Core.Models.ContentPublishing; +using Umbraco.Cms.Core.Models.ContentPublishing; using Umbraco.Cms.Core.Services.OperationStatus; namespace Umbraco.Cms.Core.Services; @@ -9,7 +9,7 @@ public interface IContentPublishingService /// Publishes a single content item. /// /// The key of the root content. - /// The cultures to publish. + /// The cultures to publish and their publishing schedules. /// The identifier of the user performing the operation. /// Result of the publish operation. Task> PublishAsync(Guid key, CultureAndScheduleModel cultureAndSchedule, Guid userKey); diff --git a/src/Umbraco.Core/Services/IRelationService.cs b/src/Umbraco.Core/Services/IRelationService.cs index 04e99528b5..676e7ea17c 100644 --- a/src/Umbraco.Core/Services/IRelationService.cs +++ b/src/Umbraco.Core/Services/IRelationService.cs @@ -177,9 +177,8 @@ public interface IRelationService : IService /// Gets a paged result of /// /// - /// - /// - /// + /// + /// /// /// Task, RelationOperationStatus>> GetPagedByRelationTypeKeyAsync(Guid key, int skip, int take, Ordering? ordering = null); @@ -403,6 +402,8 @@ public interface IRelationService : IService /// Gets the Relation types in a paged manner. /// Currently implements the paging in memory on the name attribute because the underlying repository does not support paging yet /// + /// + /// /// /// Task> GetPagedRelationTypesAsync(int skip, int take, params int[] ids); diff --git a/src/Umbraco.Core/Services/ITrackedReferencesService.cs b/src/Umbraco.Core/Services/ITrackedReferencesService.cs index 2b5dcfb833..7cfcd1c117 100644 --- a/src/Umbraco.Core/Services/ITrackedReferencesService.cs +++ b/src/Umbraco.Core/Services/ITrackedReferencesService.cs @@ -54,7 +54,7 @@ public interface ITrackedReferencesService /// Gets a paged result of items which are in relation with the current item. /// Basically, shows the items which depend on the current item. /// - /// The identifier of the entity to retrieve relations for. + /// The identifier of the entity to retrieve relations for. /// The amount of items to skip /// The amount of items to take. /// diff --git a/src/Umbraco.Core/Services/ImportExport/ContentTypeImportService.cs b/src/Umbraco.Core/Services/ImportExport/ContentTypeImportService.cs index ec9cc5a5ce..c1f97d8d40 100644 --- a/src/Umbraco.Core/Services/ImportExport/ContentTypeImportService.cs +++ b/src/Umbraco.Core/Services/ImportExport/ContentTypeImportService.cs @@ -32,7 +32,7 @@ public class ContentTypeImportService : IContentTypeImportService /// Imports the contentType /// /// - /// + /// /// the id of the contentType to overwrite, null if a new contentType should be created /// public async Task> Import( diff --git a/src/Umbraco.Core/Services/LocalizationService.cs b/src/Umbraco.Core/Services/LocalizationService.cs index e1fcfab220..989b8f8206 100644 --- a/src/Umbraco.Core/Services/LocalizationService.cs +++ b/src/Umbraco.Core/Services/LocalizationService.cs @@ -1,4 +1,4 @@ -using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Umbraco.Cms.Core.DependencyInjection; using Umbraco.Cms.Core.Events; @@ -220,7 +220,7 @@ internal class LocalizationService : RepositoryService, ILocalizationService /// Optional id of the user saving the dictionary item [Obsolete("Please use IDictionaryItemService for dictionary item operations. Will be removed in V15.")] public void Save(IDictionaryItem dictionaryItem, int userId = Constants.Security.SuperUserId) - { ; + { Guid currentUserKey = _userIdKeyResolver.GetAsync(userId).GetAwaiter().GetResult(); if (dictionaryItem.Id > 0) { diff --git a/src/Umbraco.Core/Services/Querying/RecycleBin/RecycleBinQueryResultType.cs b/src/Umbraco.Core/Services/Querying/RecycleBin/RecycleBinQueryResultType.cs index e864020a15..f9f0a34a75 100644 --- a/src/Umbraco.Core/Services/Querying/RecycleBin/RecycleBinQueryResultType.cs +++ b/src/Umbraco.Core/Services/Querying/RecycleBin/RecycleBinQueryResultType.cs @@ -1,7 +1,7 @@ namespace Umbraco.Cms.Core.Services.Querying.RecycleBin; /// -/// < 10 = Success +/// <10 = Success. /// public enum RecycleBinQueryResultType { diff --git a/src/Umbraco.Core/Services/RedirectUrlService.cs b/src/Umbraco.Core/Services/RedirectUrlService.cs index 07646de3de..0944b2a6a1 100644 --- a/src/Umbraco.Core/Services/RedirectUrlService.cs +++ b/src/Umbraco.Core/Services/RedirectUrlService.cs @@ -1,4 +1,4 @@ -using System.Threading.Tasks; +using System.Threading.Tasks; using Microsoft.Extensions.Logging; using Umbraco.Cms.Core.Events; using Umbraco.Cms.Core.Models; @@ -84,7 +84,7 @@ internal class RedirectUrlService : RepositoryService, IRedirectUrlService public async Task GetMostRecentRedirectUrlAsync(string url) { - using (var scope = ScopeProvider.CreateCoreScope(autoComplete: true)) + using (ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true)) { return await _redirectUrlRepository.GetMostRecentUrlAsync(url); } @@ -142,9 +142,9 @@ internal class RedirectUrlService : RepositoryService, IRedirectUrlService return await GetMostRecentRedirectUrlAsync(url); } - using (var scope = ScopeProvider.CreateCoreScope(autoComplete: true)) + using (ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true)) { return await _redirectUrlRepository.GetMostRecentUrlAsync(url, culture); } - } + } } diff --git a/src/Umbraco.Core/Services/UserService.cs b/src/Umbraco.Core/Services/UserService.cs index dd25791d13..0167dc6d92 100644 --- a/src/Umbraco.Core/Services/UserService.cs +++ b/src/Umbraco.Core/Services/UserService.cs @@ -4,14 +4,12 @@ using System.Linq.Expressions; using Microsoft.Extensions.DependencyInjection; using System.Security.Claims; using System.Security.Cryptography; -using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Umbraco.Cms.Core.Cache; using Umbraco.Cms.Core.Configuration.Models; using Umbraco.Cms.Core.DependencyInjection; using Umbraco.Cms.Core.Editors; -using Umbraco.Cms.Core.DependencyInjection; using Umbraco.Cms.Core.Events; using Umbraco.Cms.Core.Exceptions; using Umbraco.Cms.Core.IO; @@ -156,7 +154,7 @@ internal class UserService : RepositoryService, IUserService if (permissions.Any(x => x.EntityId == nodeId)) { EntityPermission found = permissions.First(x => x.EntityId == nodeId); - var assignedPermissionsArray = found.AssignedPermissions; + ISet assignedPermissionsArray = found.AssignedPermissions; // Working with permissions assigned directly to a user AND to their groups, so maybe several per node // and we need to get the most permissive set @@ -668,7 +666,7 @@ internal class UserService : RepositoryService, IUserService return Attempt.FailWithStatus(UserOperationStatus.MissingUser, new UserCreationResult()); } - var userGroups = _userGroupRepository.GetMany().Where(x=>model.UserGroupKeys.Contains(x.Key)).ToArray(); + IUserGroup[] userGroups = _userGroupRepository.GetMany().Where(x=>model.UserGroupKeys.Contains(x.Key)).ToArray(); if (userGroups.Length != model.UserGroupKeys.Count) { @@ -789,7 +787,7 @@ internal class UserService : RepositoryService, IUserService return Attempt.FailWithStatus(UserOperationStatus.MissingUser, new UserInvitationResult()); } - var userGroups = _userGroupRepository.GetMany().Where(x=>model.UserGroupKeys.Contains(x.Key)).ToArray(); + IUserGroup[] userGroups = _userGroupRepository.GetMany().Where(x => model.UserGroupKeys.Contains(x.Key)).ToArray(); if (userGroups.Length != model.UserGroupKeys.Count) { @@ -2298,7 +2296,7 @@ internal class UserService : RepositoryService, IUserService var results = new List(); foreach (KeyValuePair node in nodes) { - var permissions = permissionsCollection.GetAllPermissions(node.Value); + ISet permissions = permissionsCollection.GetAllPermissions(node.Value); results.Add(new NodePermissions { NodeKey = node.Key, Permissions = permissions }); } @@ -2361,7 +2359,7 @@ internal class UserService : RepositoryService, IUserService var results = new List(); foreach (int nodeId in idKeyMap.Keys) { - var permissions = permissionCollection.GetAllPermissions(nodeId); + ISet permissions = permissionCollection.GetAllPermissions(nodeId); results.Add(new NodePermissions { NodeKey = idKeyMap[nodeId], Permissions = permissions }); } diff --git a/src/Umbraco.Core/Services/WebProfilerService.cs b/src/Umbraco.Core/Services/WebProfilerService.cs index 026c2afd38..e895bba6e7 100644 --- a/src/Umbraco.Core/Services/WebProfilerService.cs +++ b/src/Umbraco.Core/Services/WebProfilerService.cs @@ -46,7 +46,11 @@ internal sealed class WebProfilerService : IWebProfilerService //FIXME when we can get current user return Attempt.Succeed(-1); +#pragma warning disable CS0162 // Unreachable code detected +#pragma warning disable CS0618 // Type or member is obsolete Attempt? userIdAttempt = _backOfficeSecurityAccessor?.BackOfficeSecurity?.GetUserId(); +#pragma warning restore CS0618 // Type or member is obsolete +#pragma warning restore CS0162 // Unreachable code detected return (userIdAttempt.HasValue && userIdAttempt.Value.Success) ? Attempt.Succeed(userIdAttempt.Value.Result) diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index e0d0bd79fa..e4b3a7cd04 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -5,7 +5,10 @@ Contains the core assembly needed to run Umbraco CMS. Umbraco.Cms.Core - + + + false + diff --git a/src/Umbraco.Examine.Lucene/Umbraco.Examine.Lucene.csproj b/src/Umbraco.Examine.Lucene/Umbraco.Examine.Lucene.csproj index 7e28eb6971..e036605449 100644 --- a/src/Umbraco.Examine.Lucene/Umbraco.Examine.Lucene.csproj +++ b/src/Umbraco.Examine.Lucene/Umbraco.Examine.Lucene.csproj @@ -5,7 +5,10 @@ Adds Examine searching support using Lucene to Umbraco CMS. Umbraco.Cms.Infrastructure.Examine - + + + CS0618 + diff --git a/src/Umbraco.Infrastructure/BackgroundJobs/IRecurringBackgroundJob.cs b/src/Umbraco.Infrastructure/BackgroundJobs/IRecurringBackgroundJob.cs index c6be3dcec5..db57d02665 100644 --- a/src/Umbraco.Infrastructure/BackgroundJobs/IRecurringBackgroundJob.cs +++ b/src/Umbraco.Infrastructure/BackgroundJobs/IRecurringBackgroundJob.cs @@ -8,15 +8,17 @@ namespace Umbraco.Cms.Infrastructure.BackgroundJobs; public interface IRecurringBackgroundJob { static readonly TimeSpan DefaultDelay = System.TimeSpan.FromMinutes(3); - static readonly ServerRole[] DefaultServerRoles = new[] { ServerRole.Single, ServerRole.SchedulingPublisher }; + static readonly ServerRole[] DefaultServerRoles = new[] { ServerRole.Single, ServerRole.SchedulingPublisher }; - /// Timespan representing how often the task should recur. + /// + /// Timespan representing how often the task should recur. + /// TimeSpan Period { get; } - /// - /// Timespan representing the initial delay after application start-up before the first run of the task - /// occurs. - /// + /// + /// Timespan representing the initial delay after application start-up before the first run of the task + /// occurs. + /// TimeSpan Delay { get => DefaultDelay; } ServerRole[] ServerRoles { get => DefaultServerRoles; } diff --git a/src/Umbraco.Infrastructure/BackgroundJobs/Jobs/HealthCheckNotifierJob.cs b/src/Umbraco.Infrastructure/BackgroundJobs/Jobs/HealthCheckNotifierJob.cs index cf99583fc4..c79a1a0866 100644 --- a/src/Umbraco.Infrastructure/BackgroundJobs/Jobs/HealthCheckNotifierJob.cs +++ b/src/Umbraco.Infrastructure/BackgroundJobs/Jobs/HealthCheckNotifierJob.cs @@ -47,6 +47,7 @@ public class HealthCheckNotifierJob : IRecurringBackgroundJob /// The typed logger. /// The profiling logger. /// Parser of crontab expressions. + /// public HealthCheckNotifierJob( IOptionsMonitor healthChecksSettings, HealthCheckCollection healthChecks, diff --git a/src/Umbraco.Infrastructure/BackgroundJobs/Jobs/LogScrubberJob.cs b/src/Umbraco.Infrastructure/BackgroundJobs/Jobs/LogScrubberJob.cs index 1c745661cb..3fcbe8d3d6 100644 --- a/src/Umbraco.Infrastructure/BackgroundJobs/Jobs/LogScrubberJob.cs +++ b/src/Umbraco.Infrastructure/BackgroundJobs/Jobs/LogScrubberJob.cs @@ -30,7 +30,7 @@ public class LogScrubberJob : IRecurringBackgroundJob private readonly IAuditService _auditService; private readonly ILogger _logger; private readonly IProfilingLogger _profilingLogger; - private readonly ICoreScopeProvider _scopeProvider; + private readonly ICoreScopeProvider _scopeProvider; private LoggingSettings _settings; /// @@ -41,14 +41,14 @@ public class LogScrubberJob : IRecurringBackgroundJob /// Provides scopes for database operations. /// The typed logger. /// The profiling logger. - public LogScrubberJob( + public LogScrubberJob( IAuditService auditService, IOptionsMonitor settings, ICoreScopeProvider scopeProvider, ILogger logger, IProfilingLogger profilingLogger) { - + _auditService = auditService; _settings = settings.CurrentValue; _scopeProvider = scopeProvider; @@ -59,7 +59,7 @@ public class LogScrubberJob : IRecurringBackgroundJob public Task RunJobAsync() { - + // Ensure we use an explicit scope since we are running on a background thread. using (ICoreScope scope = _scopeProvider.CreateCoreScope()) using (_profilingLogger.DebugDuration("Log scrubbing executing", "Log scrubbing complete")) diff --git a/src/Umbraco.Infrastructure/BackgroundJobs/Jobs/ServerRegistration/InstructionProcessJob.cs b/src/Umbraco.Infrastructure/BackgroundJobs/Jobs/ServerRegistration/InstructionProcessJob.cs index cc6e35bf83..87b459d69f 100644 --- a/src/Umbraco.Infrastructure/BackgroundJobs/Jobs/ServerRegistration/InstructionProcessJob.cs +++ b/src/Umbraco.Infrastructure/BackgroundJobs/Jobs/ServerRegistration/InstructionProcessJob.cs @@ -55,5 +55,5 @@ public class InstructionProcessJob : IRecurringBackgroundJob } return Task.CompletedTask; - } + } } diff --git a/src/Umbraco.Infrastructure/Install/FilePermissionHelper.cs b/src/Umbraco.Infrastructure/Install/FilePermissionHelper.cs index d3777d4113..92ed6ced14 100644 --- a/src/Umbraco.Infrastructure/Install/FilePermissionHelper.cs +++ b/src/Umbraco.Infrastructure/Install/FilePermissionHelper.cs @@ -91,10 +91,7 @@ public class FilePermissionHelper : IFilePermissionHelper continue; } - if (temp == null) - { - temp = new List(); - } + temp ??= new List(); temp.Add(dir.TrimStart(_basePath)); success = false; @@ -116,10 +113,7 @@ public class FilePermissionHelper : IFilePermissionHelper continue; } - if (temp == null) - { - temp = new List(); - } + temp ??= new List(); temp.Add(file.TrimStart(_basePath)); success = false; @@ -144,10 +138,7 @@ public class FilePermissionHelper : IFilePermissionHelper continue; } - if (temp == null) - { - temp = new List(); - } + temp ??= new List(); temp.Add(dir); success = false; diff --git a/src/Umbraco.Infrastructure/Logging/Viewer/LogViewerConfig.cs b/src/Umbraco.Infrastructure/Logging/Viewer/LogViewerConfig.cs index 3e4b0b7931..3bd18bc1ac 100644 --- a/src/Umbraco.Infrastructure/Logging/Viewer/LogViewerConfig.cs +++ b/src/Umbraco.Infrastructure/Logging/Viewer/LogViewerConfig.cs @@ -49,7 +49,5 @@ public class LogViewerConfig : ILogViewerConfig IReadOnlyList result = GetSavedSearches()!; scope.Complete(); return result; - scope.Complete(); - return result; } } diff --git a/src/Umbraco.Infrastructure/Migrations/Upgrade/UmbracoPremigrationPlan.cs b/src/Umbraco.Infrastructure/Migrations/Upgrade/UmbracoPremigrationPlan.cs index 23f4aa108c..c9d23acb90 100644 --- a/src/Umbraco.Infrastructure/Migrations/Upgrade/UmbracoPremigrationPlan.cs +++ b/src/Umbraco.Infrastructure/Migrations/Upgrade/UmbracoPremigrationPlan.cs @@ -12,7 +12,6 @@ public class UmbracoPremigrationPlan : MigrationPlan /// /// Initializes a new instance of the class. /// - /// The Umbraco version. public UmbracoPremigrationPlan() : base(Constants.Conventions.Migrations.UmbracoUpgradePlanPremigrationsName) => DefinePlan(); diff --git a/src/Umbraco.Infrastructure/Persistence/Dtos/LogDto.cs b/src/Umbraco.Infrastructure/Persistence/Dtos/LogDto.cs index 89bfeb8612..62f8232da5 100644 --- a/src/Umbraco.Infrastructure/Persistence/Dtos/LogDto.cs +++ b/src/Umbraco.Infrastructure/Persistence/Dtos/LogDto.cs @@ -55,6 +55,6 @@ internal class LogDto /// [Column("parameters")] [NullSetting(NullSetting = NullSettings.Null)] - [Length(500)] + [Length(4000)] public string? Parameters { get; set; } } diff --git a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/UserRepository.cs b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/UserRepository.cs index 332339e49c..892fa78ae4 100644 --- a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/UserRepository.cs +++ b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/UserRepository.cs @@ -411,8 +411,8 @@ SELECT 4 AS [Key], COUNT(id) AS [Value] FROM umbracoUser WHERE userDisabled = 0 List userIds = dtos.Count == 1 ? new List {dtos[0].Id} : dtos.Select(x => x.Id).ToList(); Dictionary? xUsers = dtos.Count == 1 ? null : dtos.ToDictionary(x => x.Id, x => x); - List groupIds = new List(); - List groupKeys = new List(); + var groupIds = new List(); + var groupKeys = new List(); Sql sql; try { @@ -595,9 +595,9 @@ SELECT 4 AS [Key], COUNT(id) AS [Value] FROM umbracoUser WHERE userDisabled = 0 // map languages - foreach (var group in groups.Values) + foreach (UserGroupDto group in groups.Values) { - if (groups2languages.TryGetValue(group.Id, out var list)) + if (groups2languages.TryGetValue(group.Id, out IGrouping? list)) { group.UserGroup2LanguageDtos = list.ToList(); // groups2apps is distinct } diff --git a/src/Umbraco.Infrastructure/PropertyEditors/ImageCropperPropertyEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/ImageCropperPropertyEditor.cs index 449d59ba42..46f02863a9 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/ImageCropperPropertyEditor.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/ImageCropperPropertyEditor.cs @@ -197,7 +197,6 @@ public class ImageCropperPropertyEditor : DataEditor, IMediaUrlGenerator, /// Returns the "src" property from the json structure if the value is formatted correctly /// /// - /// The deserialized value /// Should the path returned be the application relative path /// private string? GetFileSrcFromPropertyValue(object? propVal, bool relative = true) diff --git a/src/Umbraco.Infrastructure/Security/BackOfficeClaimsPrincipalFactory.cs b/src/Umbraco.Infrastructure/Security/BackOfficeClaimsPrincipalFactory.cs index eeac48801d..32a554aff0 100644 --- a/src/Umbraco.Infrastructure/Security/BackOfficeClaimsPrincipalFactory.cs +++ b/src/Umbraco.Infrastructure/Security/BackOfficeClaimsPrincipalFactory.cs @@ -17,6 +17,7 @@ public class BackOfficeClaimsPrincipalFactory : UserClaimsPrincipalFactory /// The user manager /// The + /// public BackOfficeClaimsPrincipalFactory( UserManager userManager, IOptions optionsAccessor, diff --git a/src/Umbraco.Infrastructure/Security/BackOfficeIdentityUser.cs b/src/Umbraco.Infrastructure/Security/BackOfficeIdentityUser.cs index 4c7943c69c..4341b01b79 100644 --- a/src/Umbraco.Infrastructure/Security/BackOfficeIdentityUser.cs +++ b/src/Umbraco.Infrastructure/Security/BackOfficeIdentityUser.cs @@ -62,10 +62,7 @@ public class BackOfficeIdentityUser : UmbracoIdentityUser get => _startContentIds; set { - if (value == null) - { - value = new int[0]; - } + value ??= new int[0]; BeingDirty.SetPropertyValueAndDetectChanges(value, ref _startContentIds!, nameof(StartContentIds), _startIdsComparer); } @@ -79,10 +76,7 @@ public class BackOfficeIdentityUser : UmbracoIdentityUser get => _startMediaIds; set { - if (value == null) - { - value = new int[0]; - } + value ??= Array.Empty(); BeingDirty.SetPropertyValueAndDetectChanges(value, ref _startMediaIds!, nameof(StartMediaIds), _startIdsComparer); } @@ -123,6 +117,7 @@ public class BackOfficeIdentityUser : UmbracoIdentityUser /// This is allowed to be null (but would need to be filled in if trying to persist this instance) /// /// + /// public static BackOfficeIdentityUser CreateNew(GlobalSettings globalSettings, string? username, string email, string culture, string? name = null, Guid? id = null) { if (string.IsNullOrWhiteSpace(username)) diff --git a/src/Umbraco.Infrastructure/Umbraco.Infrastructure.csproj b/src/Umbraco.Infrastructure/Umbraco.Infrastructure.csproj index a3b64b1cc5..cca5a43954 100644 --- a/src/Umbraco.Infrastructure/Umbraco.Infrastructure.csproj +++ b/src/Umbraco.Infrastructure/Umbraco.Infrastructure.csproj @@ -5,7 +5,10 @@ Contains the infrastructure assembly needed to run Umbraco CMS. Umbraco.Cms.Infrastructure - + + + false + $(DefineConstants);TRACE_SCOPES diff --git a/src/Umbraco.PublishedCache.NuCache/Umbraco.PublishedCache.NuCache.csproj b/src/Umbraco.PublishedCache.NuCache/Umbraco.PublishedCache.NuCache.csproj index 4894759e5f..04986712c8 100644 --- a/src/Umbraco.PublishedCache.NuCache/Umbraco.PublishedCache.NuCache.csproj +++ b/src/Umbraco.PublishedCache.NuCache/Umbraco.PublishedCache.NuCache.csproj @@ -5,7 +5,10 @@ Contains the published cache assembly needed to run Umbraco CMS. Umbraco.Cms.Infrastructure.PublishedCache - + + + false + diff --git a/src/Umbraco.Web.Common/ModelsBuilder/DependencyInjection/UmbracoBuilderDependencyInjectionExtensions.cs b/src/Umbraco.Web.Common/ModelsBuilder/DependencyInjection/UmbracoBuilderDependencyInjectionExtensions.cs index 20cd35d0d1..3784781413 100644 --- a/src/Umbraco.Web.Common/ModelsBuilder/DependencyInjection/UmbracoBuilderDependencyInjectionExtensions.cs +++ b/src/Umbraco.Web.Common/ModelsBuilder/DependencyInjection/UmbracoBuilderDependencyInjectionExtensions.cs @@ -126,7 +126,7 @@ public static class UmbracoBuilderDependencyInjectionExtensions builder.AddNotificationHandler(); builder.AddNotificationHandler(); builder.AddNotificationHandler(); - + builder.AddNotificationHandler(); builder.AddNotificationHandler(); } @@ -135,7 +135,7 @@ public static class UmbracoBuilderDependencyInjectionExtensions // Register required services for ModelsBuilderDashboardController builder.Services.AddSingleton(); - + // TODO: Remove in v13 - this is only here in case someone is already using this generator directly builder.Services.AddSingleton(); builder.Services.AddSingleton(); @@ -165,7 +165,7 @@ public static class UmbracoBuilderDependencyInjectionExtensions // This is what the community MB would replace, all of the above services are fine to be registered builder.Services.AddSingleton(factory => factory.CreateDefaultPublishedModelFactory()); - + return builder; } } diff --git a/src/Umbraco.Web.Common/Security/UmbracoSignInManager.cs b/src/Umbraco.Web.Common/Security/UmbracoSignInManager.cs index f0ab7e02e2..b0b2622e16 100644 --- a/src/Umbraco.Web.Common/Security/UmbracoSignInManager.cs +++ b/src/Umbraco.Web.Common/Security/UmbracoSignInManager.cs @@ -165,7 +165,8 @@ public abstract class UmbracoSignInManager : SignInManager public override async Task PasswordSignInAsync(string userName, string password, bool isPersistent, bool lockoutOnFailure) { // override to handle logging/events - TUser? user = await UserManager.FindByNameAsync(userName); + string strippedUsername = userName.Trim(); + TUser? user = await UserManager.FindByNameAsync(strippedUsername); if (user == null) { return await HandleSignIn(null, userName, SignInResult.Failed); diff --git a/src/Umbraco.Web.Common/Umbraco.Web.Common.csproj b/src/Umbraco.Web.Common/Umbraco.Web.Common.csproj index ba92e96fc0..2da3121a5f 100644 --- a/src/Umbraco.Web.Common/Umbraco.Web.Common.csproj +++ b/src/Umbraco.Web.Common/Umbraco.Web.Common.csproj @@ -5,7 +5,10 @@ Contains the web assembly needed to run Umbraco CMS. Umbraco.Cms.Web.Common - + + + false + diff --git a/src/Umbraco.Web.Common/UmbracoHelper.cs b/src/Umbraco.Web.Common/UmbracoHelper.cs index ec726148ec..9b1a9c6275 100644 --- a/src/Umbraco.Web.Common/UmbracoHelper.cs +++ b/src/Umbraco.Web.Common/UmbracoHelper.cs @@ -4,6 +4,7 @@ using Umbraco.Cms.Core.Dictionary; using Umbraco.Cms.Core.Models.PublishedContent; using Umbraco.Cms.Core.Strings; using Umbraco.Cms.Core.Templates; +using Umbraco.Extensions; namespace Umbraco.Cms.Web.Common; @@ -18,7 +19,7 @@ public class UmbracoHelper private readonly IUmbracoComponentRenderer _componentRenderer; private readonly ICultureDictionaryFactory _cultureDictionaryFactory; private readonly IPublishedContentQuery _publishedContentQuery; - private ICultureDictionary? _cultureDictionary; + private readonly Dictionary _cultureDictionaries = []; private IPublishedContent? _currentPage; @@ -103,29 +104,29 @@ public class UmbracoHelper /// /// Returns the dictionary value for the key specified /// - /// - /// - public string? GetDictionaryValue(string key) => CultureDictionary[key]; + /// Key of dictionary item. + /// The dictionary value, should one exist. + public string? GetDictionaryValue(string key) => GetDictionaryValue(key, Thread.CurrentThread.CurrentUICulture); /// /// Returns the dictionary value for the key specified, and if empty returns the specified default fall back value /// - /// key of dictionary item + /// Key of dictionary item. /// the specific culture on which the result well be back upon - /// + /// The dictionary value, should one exist. public string? GetDictionaryValue(string key, CultureInfo specificCulture) { - _cultureDictionary = _cultureDictionaryFactory.CreateDictionary(specificCulture); - return GetDictionaryValue(key); + ICultureDictionary cultureDictionary = GetCultureDictionary(specificCulture); + return cultureDictionary[key]; } /// /// Returns the dictionary value for the key specified, and if empty returns the specified default fall back value /// - /// key of dictionary item - /// fall back text if dictionary item is empty - Name altText to match Umbraco.Field - /// + /// key of dictionary item. + /// fall back text if dictionary item is empty - Name altText to match Umbraco.Field. + /// Returns the dictionary value, or a default value if none exists. public string GetDictionaryValueOrDefault(string key, string defaultValue) { var dictionaryValue = GetDictionaryValue(key); @@ -140,26 +141,51 @@ public class UmbracoHelper /// /// Returns the dictionary value for the key specified, and if empty returns the specified default fall back value /// - /// key of dictionary item - /// the specific culture on which the result well be back upon - /// fall back text if dictionary item is empty - Name altText to match Umbraco.Field - /// + /// Key of dictionary item. + /// The specific culture on which the result well be back upon. + /// Fall back text if dictionary item is empty - Name altText to match Umbraco.Field. + /// Returns the dictionary value, or a default value if none exists. public string GetDictionaryValueOrDefault(string key, CultureInfo specificCulture, string defaultValue) { - _cultureDictionary = _cultureDictionaryFactory.CreateDictionary(specificCulture); - var dictionaryValue = GetDictionaryValue(key); + var dictionaryValue = GetDictionaryValue(key, specificCulture); if (string.IsNullOrWhiteSpace(dictionaryValue)) { dictionaryValue = defaultValue; } + return dictionaryValue; } + /// + /// Gets the ICultureDictionary for the current UI Culture for access to dictionary items + /// + public ICultureDictionary CultureDictionary => GetCultureDictionary(Thread.CurrentThread.CurrentUICulture); /// - /// Returns the ICultureDictionary for access to dictionary items + /// Gets the ICultureDictionary for access to dictionary items for a specific culture /// - public ICultureDictionary CultureDictionary => _cultureDictionary ??= _cultureDictionaryFactory.CreateDictionary(); + /// The culture of the culture dictionary you want to retrieve. + /// Returns the culture dictionary for the specified culture. + public ICultureDictionary GetCultureDictionary(CultureInfo specificCulture) + { + CreateCultureDictionary(specificCulture); + return _cultureDictionaries.GetValue(specificCulture)!; + } + + /// + /// Creates a culture dictionary for a specific culture if it doesn't already exist + /// + /// The culture to create a culture dictionary for. + internal void CreateCultureDictionary(CultureInfo specificCulture) + { + if (_cultureDictionaries.ContainsKey(specificCulture)) + { + return; + } + + ICultureDictionary dictionary = _cultureDictionaryFactory.CreateDictionary(specificCulture); + _cultureDictionaries.Add(specificCulture, dictionary); + } #endregion diff --git a/src/Umbraco.Web.UI.Login/package-lock.json b/src/Umbraco.Web.UI.Login/package-lock.json index 43eaac8a2b..66bfe7a528 100644 --- a/src/Umbraco.Web.UI.Login/package-lock.json +++ b/src/Umbraco.Web.UI.Login/package-lock.json @@ -10,7 +10,7 @@ "@umbraco-ui/uui-css": "^1.8.0", "msw": "^2.3.0", "typescript": "^5.4.5", - "vite": "^5.2.11", + "vite": "^5.4.6", "vite-tsconfig-paths": "^4.3.2" }, "engines": { @@ -525,9 +525,9 @@ "dev": true }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.18.0.tgz", - "integrity": "sha512-Tya6xypR10giZV1XzxmH5wr25VcZSncG0pZIjfePT0OVBvqNEurzValetGNarVrGiq66EBVAFn15iYX4w6FKgQ==", + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.21.3.tgz", + "integrity": "sha512-MmKSfaB9GX+zXl6E8z4koOr/xU63AMVleLEa64v7R0QF/ZloMs5vcD1sHgM64GXXS1csaJutG+ddtzcueI/BLg==", "cpu": [ "arm" ], @@ -538,9 +538,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.18.0.tgz", - "integrity": "sha512-avCea0RAP03lTsDhEyfy+hpfr85KfyTctMADqHVhLAF3MlIkq83CP8UfAHUssgXTYd+6er6PaAhx/QGv4L1EiA==", + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.21.3.tgz", + "integrity": "sha512-zrt8ecH07PE3sB4jPOggweBjJMzI1JG5xI2DIsUbkA+7K+Gkjys6eV7i9pOenNSDJH3eOr/jLb/PzqtmdwDq5g==", "cpu": [ "arm64" ], @@ -551,9 +551,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.18.0.tgz", - "integrity": "sha512-IWfdwU7KDSm07Ty0PuA/W2JYoZ4iTj3TUQjkVsO/6U+4I1jN5lcR71ZEvRh52sDOERdnNhhHU57UITXz5jC1/w==", + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.21.3.tgz", + "integrity": "sha512-P0UxIOrKNBFTQaXTxOH4RxuEBVCgEA5UTNV6Yz7z9QHnUJ7eLX9reOd/NYMO3+XZO2cco19mXTxDMXxit4R/eQ==", "cpu": [ "arm64" ], @@ -564,9 +564,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.18.0.tgz", - "integrity": "sha512-n2LMsUz7Ynu7DoQrSQkBf8iNrjOGyPLrdSg802vk6XT3FtsgX6JbE8IHRvposskFm9SNxzkLYGSq9QdpLYpRNA==", + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.21.3.tgz", + "integrity": "sha512-L1M0vKGO5ASKntqtsFEjTq/fD91vAqnzeaF6sfNAy55aD+Hi2pBI5DKwCO+UNDQHWsDViJLqshxOahXyLSh3EA==", "cpu": [ "x64" ], @@ -577,9 +577,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.18.0.tgz", - "integrity": "sha512-C/zbRYRXFjWvz9Z4haRxcTdnkPt1BtCkz+7RtBSuNmKzMzp3ZxdM28Mpccn6pt28/UWUCTXa+b0Mx1k3g6NOMA==", + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.21.3.tgz", + "integrity": "sha512-btVgIsCjuYFKUjopPoWiDqmoUXQDiW2A4C3Mtmp5vACm7/GnyuprqIDPNczeyR5W8rTXEbkmrJux7cJmD99D2g==", "cpu": [ "arm" ], @@ -590,9 +590,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.18.0.tgz", - "integrity": "sha512-l3m9ewPgjQSXrUMHg93vt0hYCGnrMOcUpTz6FLtbwljo2HluS4zTXFy2571YQbisTnfTKPZ01u/ukJdQTLGh9A==", + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.21.3.tgz", + "integrity": "sha512-zmjbSphplZlau6ZTkxd3+NMtE4UKVy7U4aVFMmHcgO5CUbw17ZP6QCgyxhzGaU/wFFdTfiojjbLG3/0p9HhAqA==", "cpu": [ "arm" ], @@ -603,9 +603,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.18.0.tgz", - "integrity": "sha512-rJ5D47d8WD7J+7STKdCUAgmQk49xuFrRi9pZkWoRD1UeSMakbcepWXPF8ycChBoAqs1pb2wzvbY6Q33WmN2ftw==", + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.21.3.tgz", + "integrity": "sha512-nSZfcZtAnQPRZmUkUQwZq2OjQciR6tEoJaZVFvLHsj0MF6QhNMg0fQ6mUOsiCUpTqxTx0/O6gX0V/nYc7LrgPw==", "cpu": [ "arm64" ], @@ -616,9 +616,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.18.0.tgz", - "integrity": "sha512-be6Yx37b24ZwxQ+wOQXXLZqpq4jTckJhtGlWGZs68TgdKXJgw54lUUoFYrg6Zs/kjzAQwEwYbp8JxZVzZLRepQ==", + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.21.3.tgz", + "integrity": "sha512-MnvSPGO8KJXIMGlQDYfvYS3IosFN2rKsvxRpPO2l2cum+Z3exiExLwVU+GExL96pn8IP+GdH8Tz70EpBhO0sIQ==", "cpu": [ "arm64" ], @@ -629,9 +629,9 @@ ] }, "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.18.0.tgz", - "integrity": "sha512-hNVMQK+qrA9Todu9+wqrXOHxFiD5YmdEi3paj6vP02Kx1hjd2LLYR2eaN7DsEshg09+9uzWi2W18MJDlG0cxJA==", + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.21.3.tgz", + "integrity": "sha512-+W+p/9QNDr2vE2AXU0qIy0qQE75E8RTwTwgqS2G5CRQ11vzq0tbnfBd6brWhS9bCRjAjepJe2fvvkvS3dno+iw==", "cpu": [ "ppc64" ], @@ -642,9 +642,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.18.0.tgz", - "integrity": "sha512-ROCM7i+m1NfdrsmvwSzoxp9HFtmKGHEqu5NNDiZWQtXLA8S5HBCkVvKAxJ8U+CVctHwV2Gb5VUaK7UAkzhDjlg==", + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.21.3.tgz", + "integrity": "sha512-yXH6K6KfqGXaxHrtr+Uoy+JpNlUlI46BKVyonGiaD74ravdnF9BUNC+vV+SIuB96hUMGShhKV693rF9QDfO6nQ==", "cpu": [ "riscv64" ], @@ -655,9 +655,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.18.0.tgz", - "integrity": "sha512-0UyyRHyDN42QL+NbqevXIIUnKA47A+45WyasO+y2bGJ1mhQrfrtXUpTxCOrfxCR4esV3/RLYyucGVPiUsO8xjg==", + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.21.3.tgz", + "integrity": "sha512-R8cwY9wcnApN/KDYWTH4gV/ypvy9yZUHlbJvfaiXSB48JO3KpwSpjOGqO4jnGkLDSk1hgjYkTbTt6Q7uvPf8eg==", "cpu": [ "s390x" ], @@ -668,9 +668,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.18.0.tgz", - "integrity": "sha512-xuglR2rBVHA5UsI8h8UbX4VJ470PtGCf5Vpswh7p2ukaqBGFTnsfzxUBetoWBWymHMxbIG0Cmx7Y9qDZzr648w==", + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.21.3.tgz", + "integrity": "sha512-kZPbX/NOPh0vhS5sI+dR8L1bU2cSO9FgxwM8r7wHzGydzfSjLRCFAT87GR5U9scj2rhzN3JPYVC7NoBbl4FZ0g==", "cpu": [ "x64" ], @@ -681,9 +681,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.18.0.tgz", - "integrity": "sha512-LKaqQL9osY/ir2geuLVvRRs+utWUNilzdE90TpyoX0eNqPzWjRm14oMEE+YLve4k/NAqCdPkGYDaDF5Sw+xBfg==", + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.21.3.tgz", + "integrity": "sha512-S0Yq+xA1VEH66uiMNhijsWAafffydd2X5b77eLHfRmfLsRSpbiAWiRHV6DEpz6aOToPsgid7TI9rGd6zB1rhbg==", "cpu": [ "x64" ], @@ -694,9 +694,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.18.0.tgz", - "integrity": "sha512-7J6TkZQFGo9qBKH0pk2cEVSRhJbL6MtfWxth7Y5YmZs57Pi+4x6c2dStAUvaQkHQLnEQv1jzBUW43GvZW8OFqA==", + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.21.3.tgz", + "integrity": "sha512-9isNzeL34yquCPyerog+IMCNxKR8XYmGd0tHSV+OVx0TmE0aJOo9uw4fZfUuk2qxobP5sug6vNdZR6u7Mw7Q+Q==", "cpu": [ "arm64" ], @@ -707,9 +707,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.18.0.tgz", - "integrity": "sha512-Txjh+IxBPbkUB9+SXZMpv+b/vnTEtFyfWZgJ6iyCmt2tdx0OF5WhFowLmnh8ENGNpfUlUZkdI//4IEmhwPieNg==", + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.21.3.tgz", + "integrity": "sha512-nMIdKnfZfzn1Vsk+RuOvl43ONTZXoAPUUxgcU0tXooqg4YrAqzfKzVenqqk2g5efWh46/D28cKFrOzDSW28gTA==", "cpu": [ "ia32" ], @@ -720,9 +720,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.18.0.tgz", - "integrity": "sha512-UOo5FdvOL0+eIVTgS4tIdbW+TtnBLWg1YBCcU2KWM7nuNwRz9bksDX1bekJJCpu25N1DVWaCwnT39dVQxzqS8g==", + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.21.3.tgz", + "integrity": "sha512-fOvu7PCQjAj4eWDEuD8Xz5gpzFqXzGlxHZozHP4b9Jxv9APtdxL6STqztDzMLuRXEc4UpXGGhx029Xgm91QBeA==", "cpu": [ "x64" ], @@ -2288,15 +2288,15 @@ "dev": true }, "node_modules/picocolors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", - "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz", + "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==", "dev": true }, "node_modules/postcss": { - "version": "8.4.38", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz", - "integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==", + "version": "8.4.47", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz", + "integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==", "dev": true, "funding": [ { @@ -2314,8 +2314,8 @@ ], "dependencies": { "nanoid": "^3.3.7", - "picocolors": "^1.0.0", - "source-map-js": "^1.2.0" + "picocolors": "^1.1.0", + "source-map-js": "^1.2.1" }, "engines": { "node": "^10 || ^12 || >=14" @@ -2331,9 +2331,9 @@ } }, "node_modules/rollup": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.18.0.tgz", - "integrity": "sha512-QmJz14PX3rzbJCN1SG4Xe/bAAX2a6NpCP8ab2vfu2GiUr8AQcr2nCV/oEO3yneFarB67zk8ShlIyWb2LGTb3Sg==", + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.21.3.tgz", + "integrity": "sha512-7sqRtBNnEbcBtMeRVc6VRsJMmpI+JU1z9VTvW8D4gXIYQFz0aLcsE6rRkyghZkLfEgUZgVvOG7A5CVz/VW5GIA==", "dev": true, "dependencies": { "@types/estree": "1.0.5" @@ -2346,22 +2346,22 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.18.0", - "@rollup/rollup-android-arm64": "4.18.0", - "@rollup/rollup-darwin-arm64": "4.18.0", - "@rollup/rollup-darwin-x64": "4.18.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.18.0", - "@rollup/rollup-linux-arm-musleabihf": "4.18.0", - "@rollup/rollup-linux-arm64-gnu": "4.18.0", - "@rollup/rollup-linux-arm64-musl": "4.18.0", - "@rollup/rollup-linux-powerpc64le-gnu": "4.18.0", - "@rollup/rollup-linux-riscv64-gnu": "4.18.0", - "@rollup/rollup-linux-s390x-gnu": "4.18.0", - "@rollup/rollup-linux-x64-gnu": "4.18.0", - "@rollup/rollup-linux-x64-musl": "4.18.0", - "@rollup/rollup-win32-arm64-msvc": "4.18.0", - "@rollup/rollup-win32-ia32-msvc": "4.18.0", - "@rollup/rollup-win32-x64-msvc": "4.18.0", + "@rollup/rollup-android-arm-eabi": "4.21.3", + "@rollup/rollup-android-arm64": "4.21.3", + "@rollup/rollup-darwin-arm64": "4.21.3", + "@rollup/rollup-darwin-x64": "4.21.3", + "@rollup/rollup-linux-arm-gnueabihf": "4.21.3", + "@rollup/rollup-linux-arm-musleabihf": "4.21.3", + "@rollup/rollup-linux-arm64-gnu": "4.21.3", + "@rollup/rollup-linux-arm64-musl": "4.21.3", + "@rollup/rollup-linux-powerpc64le-gnu": "4.21.3", + "@rollup/rollup-linux-riscv64-gnu": "4.21.3", + "@rollup/rollup-linux-s390x-gnu": "4.21.3", + "@rollup/rollup-linux-x64-gnu": "4.21.3", + "@rollup/rollup-linux-x64-musl": "4.21.3", + "@rollup/rollup-win32-arm64-msvc": "4.21.3", + "@rollup/rollup-win32-ia32-msvc": "4.21.3", + "@rollup/rollup-win32-x64-msvc": "4.21.3", "fsevents": "~2.3.2" } }, @@ -2388,9 +2388,9 @@ } }, "node_modules/source-map-js": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", - "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", "dev": true, "engines": { "node": ">=0.10.0" @@ -2536,14 +2536,14 @@ } }, "node_modules/vite": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.3.1.tgz", - "integrity": "sha512-XBmSKRLXLxiaPYamLv3/hnP/KXDai1NDexN0FpkTaZXTfycHvkRHoenpgl/fvuK/kPbB6xAgoyiryAhQNxYmAQ==", + "version": "5.4.6", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.6.tgz", + "integrity": "sha512-IeL5f8OO5nylsgzd9tq4qD2QqI0k2CQLGrWD0rCN0EQJZpBK5vJAx0I+GDkMOXxQX/OfFHMuLIx6ddAxGX/k+Q==", "dev": true, "dependencies": { "esbuild": "^0.21.3", - "postcss": "^8.4.38", - "rollup": "^4.13.0" + "postcss": "^8.4.43", + "rollup": "^4.20.0" }, "bin": { "vite": "bin/vite.js" @@ -2562,6 +2562,7 @@ "less": "*", "lightningcss": "^1.21.0", "sass": "*", + "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.4.0" @@ -2579,6 +2580,9 @@ "sass": { "optional": true }, + "sass-embedded": { + "optional": true + }, "stylus": { "optional": true }, diff --git a/src/Umbraco.Web.UI.Login/package.json b/src/Umbraco.Web.UI.Login/package.json index 7b0e3455c4..38cc5bca58 100644 --- a/src/Umbraco.Web.UI.Login/package.json +++ b/src/Umbraco.Web.UI.Login/package.json @@ -19,7 +19,7 @@ "@umbraco-ui/uui-css": "^1.8.0", "msw": "^2.3.0", "typescript": "^5.4.5", - "vite": "^5.2.11", + "vite": "^5.4.6", "vite-tsconfig-paths": "^4.3.2" }, "msw": { diff --git a/src/Umbraco.Web.UI/Program.cs b/src/Umbraco.Web.UI/Program.cs index 8fca919b0a..ad68d28351 100644 --- a/src/Umbraco.Web.UI/Program.cs +++ b/src/Umbraco.Web.UI/Program.cs @@ -13,7 +13,7 @@ WebApplication app = builder.Build(); await app.BootUmbracoAsync(); -#if (UseHttpsRedirect) +#if UseHttpsRedirect app.UseHttpsRedirection(); #endif diff --git a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj index acd631e1ad..c22b5ae739 100644 --- a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj +++ b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj @@ -5,6 +5,10 @@ false + + + SA1119 + diff --git a/src/Umbraco.Web.Website/DependencyInjection/UmbracoBuilderExtensions.cs b/src/Umbraco.Web.Website/DependencyInjection/UmbracoBuilderExtensions.cs index f182bda7b6..400b288786 100644 --- a/src/Umbraco.Web.Website/DependencyInjection/UmbracoBuilderExtensions.cs +++ b/src/Umbraco.Web.Website/DependencyInjection/UmbracoBuilderExtensions.cs @@ -57,8 +57,7 @@ public static partial class UmbracoBuilderExtensions x.GetRequiredService(), x.GetRequiredService(), x.GetRequiredService(), - x.GetRequiredService>() - )); + x.GetRequiredService>())); builder.Services.AddSingleton(); builder.Services.TryAddEnumerable(Singleton()); builder.Services.AddSingleton(); diff --git a/src/Umbraco.Web.Website/Routing/PublicAccessRequestHandler.cs b/src/Umbraco.Web.Website/Routing/PublicAccessRequestHandler.cs index b7c751d28c..801e4af08f 100644 --- a/src/Umbraco.Web.Website/Routing/PublicAccessRequestHandler.cs +++ b/src/Umbraco.Web.Website/Routing/PublicAccessRequestHandler.cs @@ -148,9 +148,10 @@ public class PublicAccessRequestHandler : IPublicAccessRequestHandler _logger.LogDebug("EnsurePublishedContentAccess: Page is not protected"); } } + } - // loop until we have access or reached max loops - } while (publicAccessStatus != PublicAccessStatus.AccessAccepted && i++ < maxLoop); + // loop until we have access or reached max loops + while (publicAccessStatus != PublicAccessStatus.AccessAccepted && i++ < maxLoop); if (i == maxLoop) { diff --git a/src/Umbraco.Web.Website/Routing/UmbracoRouteValuesFactory.cs b/src/Umbraco.Web.Website/Routing/UmbracoRouteValuesFactory.cs index d8fbca45d4..714024a1bc 100644 --- a/src/Umbraco.Web.Website/Routing/UmbracoRouteValuesFactory.cs +++ b/src/Umbraco.Web.Website/Routing/UmbracoRouteValuesFactory.cs @@ -45,13 +45,8 @@ public class UmbracoRouteValuesFactory : IUmbracoRouteValuesFactory ControllerActionDescriptor? descriptor = _controllerActionSearcher.Find( new DefaultHttpContext(), // this actually makes no difference for this method DefaultControllerName, - UmbracoRouteValues.DefaultActionName); - - if (descriptor == null) - { - throw new InvalidOperationException( + UmbracoRouteValues.DefaultActionName) ?? throw new InvalidOperationException( $"No controller/action found by name {DefaultControllerName}.{UmbracoRouteValues.DefaultActionName}"); - } return descriptor; }); @@ -128,11 +123,12 @@ public class UmbracoRouteValuesFactory : IUmbracoRouteValuesFactory IPublishedRequest request = def.PublishedRequest; // Here we need to check if there is no hijacked route and no template assigned but there is a content item. - // If this is the case we want to return a blank page. + // If this is the case we want to return a blank page, the only exception being if the content item has a redirect field present. // We also check if templates have been disabled since if they are then we're allowed to render even though there's no template, // for example for json rendering in headless. if (request.HasPublishedContent() && !request.HasTemplate() + && !request.IsRedirect() && !_umbracoFeatures.Disabled.DisableTemplates && !hasHijackedRoute) { @@ -150,8 +146,8 @@ public class UmbracoRouteValuesFactory : IUmbracoRouteValuesFactory $"The call to {nameof(IPublishedRouter.UpdateRequestAsync)} cannot return null"); } - string? customActionName = GetTemplateName(request); - + string? customActionName = GetTemplateName(request); + def = new UmbracoRouteValues( request, def.ControllerActionDescriptor, @@ -166,7 +162,7 @@ public class UmbracoRouteValuesFactory : IUmbracoRouteValuesFactory return def; } - + private string? GetTemplateName(IPublishedRequest request) { // check that a template is defined), if it doesn't and there is a hijacked route it will just route diff --git a/src/Umbraco.Web.Website/Umbraco.Web.Website.csproj b/src/Umbraco.Web.Website/Umbraco.Web.Website.csproj index 31c057e7b9..0e8d475725 100644 --- a/src/Umbraco.Web.Website/Umbraco.Web.Website.csproj +++ b/src/Umbraco.Web.Website/Umbraco.Web.Website.csproj @@ -5,7 +5,13 @@ Contains the website assembly needed to run the frontend of Umbraco CMS. Umbraco.Cms.Web.Website - + + + ASP0019,CS0618,SA1401,SA1649,IDE0270,IDE1006 + diff --git a/src/Umbraco.Web.Website/ViewEngines/ProfilingViewEngine.cs b/src/Umbraco.Web.Website/ViewEngines/ProfilingViewEngine.cs index 5862f90d64..33ec4acb33 100644 --- a/src/Umbraco.Web.Website/ViewEngines/ProfilingViewEngine.cs +++ b/src/Umbraco.Web.Website/ViewEngines/ProfilingViewEngine.cs @@ -8,6 +8,8 @@ public class ProfilingViewEngine : IViewEngine { private readonly string _name; private readonly IProfiler _profiler; + + //TODO: can this be made private and with underscore? internal readonly IViewEngine Inner; public ProfilingViewEngine(IViewEngine inner, IProfiler profiler) diff --git a/tests/Umbraco.TestData/Umbraco.TestData.csproj b/tests/Umbraco.TestData/Umbraco.TestData.csproj index 7e19740a31..2b8fc3fca8 100644 --- a/tests/Umbraco.TestData/Umbraco.TestData.csproj +++ b/tests/Umbraco.TestData/Umbraco.TestData.csproj @@ -1,4 +1,9 @@ + + + CS0618,IDE1006,IDE0057 + diff --git a/tests/Umbraco.Tests.AcceptanceTest.UmbracoProject/.gitignore b/tests/Umbraco.Tests.AcceptanceTest.UmbracoProject/.gitignore new file mode 100644 index 0000000000..ff99115ae5 --- /dev/null +++ b/tests/Umbraco.Tests.AcceptanceTest.UmbracoProject/.gitignore @@ -0,0 +1,2 @@ +# Ignore Visual Studio's generated launchSettings file. +Properties/launchSettings.json diff --git a/tests/Umbraco.Tests.Benchmarks/EnumeratorBenchmarks.cs b/tests/Umbraco.Tests.Benchmarks/EnumeratorBenchmarks.cs index 05db4034dd..460e819f18 100644 --- a/tests/Umbraco.Tests.Benchmarks/EnumeratorBenchmarks.cs +++ b/tests/Umbraco.Tests.Benchmarks/EnumeratorBenchmarks.cs @@ -11,7 +11,7 @@ public class EnumeratorBenchmarks { foreach (var t in EnumerateOneWithArray(1)) { - ; + } } @@ -20,7 +20,7 @@ public class EnumeratorBenchmarks { foreach (var t in EnumerateOneWithYield(1)) { - ; + } } diff --git a/tests/Umbraco.Tests.Benchmarks/HashFromStreams.cs b/tests/Umbraco.Tests.Benchmarks/HashFromStreams.cs index cc8ad90877..7b291b88b8 100644 --- a/tests/Umbraco.Tests.Benchmarks/HashFromStreams.cs +++ b/tests/Umbraco.Tests.Benchmarks/HashFromStreams.cs @@ -18,7 +18,7 @@ public class HashFromStreams // the SHA1CryptoServiceProvider is faster, but that is not reflected in these benchmarks. /* - + BenchmarkDotNet=v0.13.0, OS=Windows 10.0.19042.1052 (20H2/October2020Update) Intel Core i7-7700HQ CPU 2.80GHz (Kaby Lake), 1 CPU, 8 logical and 4 physical cores .NET SDK=5.0.300-preview.21258.4 diff --git a/tests/Umbraco.Tests.Benchmarks/Umbraco.Tests.Benchmarks.csproj b/tests/Umbraco.Tests.Benchmarks/Umbraco.Tests.Benchmarks.csproj index 189d69ac31..5b8f2b3b56 100644 --- a/tests/Umbraco.Tests.Benchmarks/Umbraco.Tests.Benchmarks.csproj +++ b/tests/Umbraco.Tests.Benchmarks/Umbraco.Tests.Benchmarks.csproj @@ -5,7 +5,10 @@ false false - + + + false + diff --git a/tests/Umbraco.Tests.Common/Umbraco.Tests.Common.csproj b/tests/Umbraco.Tests.Common/Umbraco.Tests.Common.csproj index bf0dc9ddc1..24e0dce808 100644 --- a/tests/Umbraco.Tests.Common/Umbraco.Tests.Common.csproj +++ b/tests/Umbraco.Tests.Common/Umbraco.Tests.Common.csproj @@ -7,7 +7,10 @@ true $(BaseEnablePackageValidation) - + + + false + diff --git a/tests/Umbraco.Tests.Integration/Implementations/TestHelper.cs b/tests/Umbraco.Tests.Integration/Implementations/TestHelper.cs index 1a4ccacdd1..47d095c02a 100644 --- a/tests/Umbraco.Tests.Integration/Implementations/TestHelper.cs +++ b/tests/Umbraco.Tests.Integration/Implementations/TestHelper.cs @@ -174,16 +174,13 @@ public class TestHelper : TestHelperBase private static void AssertListsAreEqual(PropertyInfo property, IEnumerable expected, IEnumerable actual, Func sorter = null, int dateDeltaMilliseconds = 0) { - if (sorter == null) + // this is pretty hackerific but saves us some code to write + sorter ??= enumerable => { - // this is pretty hackerific but saves us some code to write - sorter = enumerable => - { - // semi-generic way of ensuring any collection of IEntity are sorted by Ids for comparison - var entities = enumerable.OfType().ToList(); - return entities.Count > 0 ? entities.OrderBy(x => x.Id) : entities; - }; - } + // semi-generic way of ensuring any collection of IEntity are sorted by Ids for comparison + var entities = enumerable.OfType().ToList(); + return entities.Count > 0 ? entities.OrderBy(x => x.Id) : entities; + }; var expectedListEx = sorter(expected).Cast().ToList(); var actualListEx = sorter(actual).Cast().ToList(); diff --git a/tests/Umbraco.Tests.Integration/TestServerTest/UmbracoTestServerTestBase.cs b/tests/Umbraco.Tests.Integration/TestServerTest/UmbracoTestServerTestBase.cs index cf321d9498..34445e2446 100644 --- a/tests/Umbraco.Tests.Integration/TestServerTest/UmbracoTestServerTestBase.cs +++ b/tests/Umbraco.Tests.Integration/TestServerTest/UmbracoTestServerTestBase.cs @@ -298,7 +298,7 @@ namespace Umbraco.Cms.Tests.Integration.TestServerTest protected virtual void CustomMvcSetup(IMvcBuilder mvcBuilder) { - + } /// diff --git a/tests/Umbraco.Tests.Integration/Testing/TestWebProfilerRepository.cs b/tests/Umbraco.Tests.Integration/Testing/TestWebProfilerRepository.cs index 3d5dbb2e2b..a3c572ad04 100644 --- a/tests/Umbraco.Tests.Integration/Testing/TestWebProfilerRepository.cs +++ b/tests/Umbraco.Tests.Integration/Testing/TestWebProfilerRepository.cs @@ -5,7 +5,7 @@ namespace Umbraco.Cms.Tests.Integration.Testing; public class TestWebProfilerRepository : IWebProfilerRepository { private bool _status = false; - + public void SetStatus(int userId, bool status) => _status = status; public bool GetStatus(int userId) => _status; diff --git a/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Persistence/Repositories/ContentTypeRepositoryTest.cs b/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Persistence/Repositories/ContentTypeRepositoryTest.cs index 1644a3b1e4..51ade838c6 100644 --- a/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Persistence/Repositories/ContentTypeRepositoryTest.cs +++ b/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Persistence/Repositories/ContentTypeRepositoryTest.cs @@ -404,7 +404,7 @@ public class ContentTypeRepositoryTest : UmbracoIntegrationTest var repository = ContentTypeRepository; // Act - var contentTypes = repository.Get(provider.CreateQuery().Where(x => x.ParentId == contentType.Id)).ToArray();; + var contentTypes = repository.Get(provider.CreateQuery().Where(x => x.ParentId == contentType.Id)).ToArray(); // Assert Assert.That(contentTypes.Count(), Is.EqualTo(3)); diff --git a/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/LanguageServiceTests.cs b/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/LanguageServiceTests.cs index 043ce3d2f4..b04dcdb379 100644 --- a/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/LanguageServiceTests.cs +++ b/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/LanguageServiceTests.cs @@ -1,4 +1,4 @@ -using NUnit.Framework; +using NUnit.Framework; using Umbraco.Cms.Core; using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Services; @@ -262,7 +262,7 @@ public class LanguageServiceTests : UmbracoIntegrationTest Assert.IsFalse(result.Success); Assert.AreEqual(LanguageOperationStatus.InvalidFallbackIsoCode, result.Status); } - + [Test] public async Task Cannot_Create_Language_With_NonExisting_Fallback_Language() { @@ -332,7 +332,7 @@ public class LanguageServiceTests : UmbracoIntegrationTest Assert.IsFalse(result.Success); Assert.AreEqual(LanguageOperationStatus.InvalidFallbackIsoCode, result.Status); } - + [Test] public async Task Cannot_Create_Direct_Cyclic_Fallback_Language() { diff --git a/tests/Umbraco.Tests.Integration/Umbraco.Tests.Integration.csproj b/tests/Umbraco.Tests.Integration/Umbraco.Tests.Integration.csproj index b7ab21b062..a04ee45648 100644 --- a/tests/Umbraco.Tests.Integration/Umbraco.Tests.Integration.csproj +++ b/tests/Umbraco.Tests.Integration/Umbraco.Tests.Integration.csproj @@ -9,7 +9,10 @@ $(BaseEnablePackageValidation) NU5100 - + + + false + diff --git a/tests/Umbraco.Tests.UnitTests/Umbraco.Core/Components/ComponentTests.cs b/tests/Umbraco.Tests.UnitTests/Umbraco.Core/Components/ComponentTests.cs index ca47bfbd97..dd4c46f0a4 100644 --- a/tests/Umbraco.Tests.UnitTests/Umbraco.Core/Components/ComponentTests.cs +++ b/tests/Umbraco.Tests.UnitTests/Umbraco.Core/Components/ComponentTests.cs @@ -157,7 +157,7 @@ public class ComponentTests { return Mock.Of>(); } - + if (type == typeof(ILogger)) { return Mock.Of>(); @@ -324,7 +324,7 @@ public class ComponentTests { return Mock.Of>(); } - + if (type == typeof(IServiceProviderIsService)) { return Mock.Of(); diff --git a/tests/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/BackgroundJobs/Jobs/ServerRegistration/InstructionProcessJobTests.cs b/tests/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/BackgroundJobs/Jobs/ServerRegistration/InstructionProcessJobTests.cs index f2e6e574ef..14311afbe2 100644 --- a/tests/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/BackgroundJobs/Jobs/ServerRegistration/InstructionProcessJobTests.cs +++ b/tests/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/BackgroundJobs/Jobs/ServerRegistration/InstructionProcessJobTests.cs @@ -30,7 +30,7 @@ public class InstructionProcessJobTests private InstructionProcessJob CreateInstructionProcessJob() { - + var mockLogger = new Mock>(); _mockDatabaseServerMessenger = new Mock(); diff --git a/tests/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/BackgroundJobs/Jobs/TempFileCleanupJobTests.cs b/tests/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/BackgroundJobs/Jobs/TempFileCleanupJobTests.cs index c37094e6ac..9c76c7b799 100644 --- a/tests/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/BackgroundJobs/Jobs/TempFileCleanupJobTests.cs +++ b/tests/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/BackgroundJobs/Jobs/TempFileCleanupJobTests.cs @@ -29,7 +29,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Infrastructure.BackgroundJobs.Jobs private TempFileCleanupJob CreateTempFileCleanupJob() { - + _mockIOHelper = new Mock(); _mockIOHelper.Setup(x => x.GetTempFolders()) .Returns(new DirectoryInfo[] { new(_testPath) }); diff --git a/tests/Umbraco.Tests.UnitTests/Umbraco.Tests.UnitTests.csproj b/tests/Umbraco.Tests.UnitTests/Umbraco.Tests.UnitTests.csproj index a411bad38c..6986e03494 100644 --- a/tests/Umbraco.Tests.UnitTests/Umbraco.Tests.UnitTests.csproj +++ b/tests/Umbraco.Tests.UnitTests/Umbraco.Tests.UnitTests.csproj @@ -5,7 +5,10 @@ false false - + + + false + diff --git a/tools/Umbraco.JsonSchema/Umbraco.JsonSchema.csproj b/tools/Umbraco.JsonSchema/Umbraco.JsonSchema.csproj index ce5001608f..471ebff802 100644 --- a/tools/Umbraco.JsonSchema/Umbraco.JsonSchema.csproj +++ b/tools/Umbraco.JsonSchema/Umbraco.JsonSchema.csproj @@ -4,7 +4,10 @@ false false - + + + false +