diff --git a/build/azure-pipelines.yml b/build/azure-pipelines.yml index 56a630487f..23bc2afc5e 100644 --- a/build/azure-pipelines.yml +++ b/build/azure-pipelines.yml @@ -104,23 +104,8 @@ stages: echo "##vso[task.setvariable variable=majorVersion;isOutput=true]$major" displayName: Set major version name: determineMajorVersion - - task: PowerShell@2 - displayName: Prepare nupkg - inputs: - targetType: inline - script: | - $umbracoVersion = "$(Build.BuildNumber)" -replace "\+",".g" - $templatePaths = Get-ChildItem 'templates/**/.template.config/template.json' - - foreach ($templatePath in $templatePaths) { - $a = Get-Content $templatePath -Raw | ConvertFrom-Json - if ($a.symbols -and $a.symbols.UmbracoVersion) { - $a.symbols.UmbracoVersion.defaultValue = $umbracoVersion - $a | ConvertTo-Json -Depth 32 | Set-Content $templatePath - } - } - - dotnet pack $(solution) --configuration $(buildConfiguration) --no-build --property:PackageOutputPath=$(Build.ArtifactStagingDirectory)/nupkg + - script: dotnet pack $(solution) --configuration $(buildConfiguration) --no-build --property:PackageOutputPath=$(Build.ArtifactStagingDirectory)/nupkg + displayName: Run dotnet pack - script: | sha="$(Build.SourceVersion)" sha=${sha:0:7} diff --git a/src/Umbraco.Cms.Api.Management/OpenApi.json b/src/Umbraco.Cms.Api.Management/OpenApi.json index 4a5c017256..5d8c88d182 100644 --- a/src/Umbraco.Cms.Api.Management/OpenApi.json +++ b/src/Umbraco.Cms.Api.Management/OpenApi.json @@ -441,6 +441,40 @@ } } }, + "/umbraco/management/api/v1/data-type/{id}/is-used": { + "get": { + "tags": [ + "Data Type" + ], + "operationId": "GetDataTypeByIdIsUsed", + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "boolean" + } + } + } + }, + "404": { + "description": "Not Found" + } + } + } + }, "/umbraco/management/api/v1/data-type/{id}/move": { "post": { "tags": [ @@ -4810,6 +4844,53 @@ } } }, + "/umbraco/management/api/v1/property-type/is-used": { + "get": { + "tags": [ + "Property Type" + ], + "operationId": "GetPropertyTypeIsUsed", + "parameters": [ + { + "name": "contentTypeId", + "in": "query", + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "propertyAlias", + "in": "query", + "schema": { + "type": "string" + } + } + ], + "responses": { + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetailsModel" + } + } + } + }, + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PagedBooleanModel" + } + } + } + } + } + } + }, "/umbraco/management/api/v1/published-cache/collect": { "post": { "tags": [ @@ -10124,6 +10205,26 @@ }, "additionalProperties": false }, + "PagedBooleanModel": { + "required": [ + "items", + "total" + ], + "type": "object", + "properties": { + "total": { + "type": "integer", + "format": "int64" + }, + "items": { + "type": "array", + "items": { + "type": "boolean" + } + } + }, + "additionalProperties": false + }, "PagedContentTreeItemResponseModel": { "required": [ "items", diff --git a/src/Umbraco.Cms.Targets/Umbraco.Cms.Targets.csproj b/src/Umbraco.Cms.Targets/Umbraco.Cms.Targets.csproj index d537b116c0..18f9beea96 100644 --- a/src/Umbraco.Cms.Targets/Umbraco.Cms.Targets.csproj +++ b/src/Umbraco.Cms.Targets/Umbraco.Cms.Targets.csproj @@ -50,10 +50,10 @@ - + - + <_PackageFiles Include="$(IntermediateOutputPath)_._" PackagePath="lib\$(TargetFramework)" /> diff --git a/src/Umbraco.Cms/Umbraco.Cms.csproj b/src/Umbraco.Cms/Umbraco.Cms.csproj index 1ff6e848ad..da6be4c30c 100644 --- a/src/Umbraco.Cms/Umbraco.Cms.csproj +++ b/src/Umbraco.Cms/Umbraco.Cms.csproj @@ -14,10 +14,10 @@ - + - + <_PackageFiles Include="$(IntermediateOutputPath)_._" PackagePath="lib\$(TargetFramework)" /> diff --git a/src/Umbraco.Infrastructure/PropertyEditors/RichTextEditorPastedImages.cs b/src/Umbraco.Infrastructure/PropertyEditors/RichTextEditorPastedImages.cs index 569f38139d..5044a5b13e 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/RichTextEditorPastedImages.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/RichTextEditorPastedImages.cs @@ -29,6 +29,7 @@ public sealed class RichTextEditorPastedImages private readonly IPublishedUrlProvider _publishedUrlProvider; private readonly IShortStringHelper _shortStringHelper; private readonly IUmbracoContextAccessor _umbracoContextAccessor; + private readonly string _tempFolderAbsolutePath; public RichTextEditorPastedImages( IUmbracoContextAccessor umbracoContextAccessor, @@ -52,6 +53,9 @@ public sealed class RichTextEditorPastedImages _mediaUrlGenerators = mediaUrlGenerators; _shortStringHelper = shortStringHelper; _publishedUrlProvider = publishedUrlProvider; + + _tempFolderAbsolutePath = _hostingEnvironment.MapPathContentRoot(Constants.SystemDirectories.TempImageUploads); + } /// @@ -85,12 +89,14 @@ public sealed class RichTextEditorPastedImages continue; } - if (IsValidPath(tmpImgPath) == false) + + var absoluteTempImagePath = Path.GetFullPath(_hostingEnvironment.MapPathContentRoot(tmpImgPath)); + + if (IsValidPath(absoluteTempImagePath) == false) { continue; } - var absoluteTempImagePath = _hostingEnvironment.MapPathContentRoot(tmpImgPath); var fileName = Path.GetFileName(absoluteTempImagePath); var safeFileName = fileName.ToSafeFileName(_shortStringHelper); @@ -191,5 +197,8 @@ public sealed class RichTextEditorPastedImages return htmlDoc.DocumentNode.OuterHtml; } - private bool IsValidPath(string imagePath) => imagePath.StartsWith(Constants.SystemDirectories.TempImageUploads); + private bool IsValidPath(string imagePath) + { + return imagePath.StartsWith(_tempFolderAbsolutePath); + } } diff --git a/src/Umbraco.Web.Common/Filters/UmbracoMemberAuthorizeFilter.cs b/src/Umbraco.Web.Common/Filters/UmbracoMemberAuthorizeFilter.cs index 351ea6e1bf..95c4ae5cec 100644 --- a/src/Umbraco.Web.Common/Filters/UmbracoMemberAuthorizeFilter.cs +++ b/src/Umbraco.Web.Common/Filters/UmbracoMemberAuthorizeFilter.cs @@ -54,11 +54,20 @@ public class UmbracoMemberAuthorizeFilter : IAsyncAuthorizationFilter IMemberManager memberManager = context.HttpContext.RequestServices.GetRequiredService(); - if (!await IsAuthorizedAsync(memberManager)) + if (memberManager.IsLoggedIn()) + { + if (!await IsAuthorizedAsync(memberManager)) + { + context.HttpContext.SetReasonPhrase( + "Resource restricted: the member is not of a permitted type or group."); + context.Result = new ForbidResult(); + } + } + else { context.HttpContext.SetReasonPhrase( - "Resource restricted: either member is not logged on or is not of a permitted type or group."); - context.Result = new ForbidResult(); + "Resource restricted: the member is not logged in."); + context.Result = new UnauthorizedResult(); } } diff --git a/src/Umbraco.Web.Common/Security/ConfigureMemberCookieOptions.cs b/src/Umbraco.Web.Common/Security/ConfigureMemberCookieOptions.cs index 5bf7a98749..968f070162 100644 --- a/src/Umbraco.Web.Common/Security/ConfigureMemberCookieOptions.cs +++ b/src/Umbraco.Web.Common/Security/ConfigureMemberCookieOptions.cs @@ -1,4 +1,5 @@ using Microsoft.AspNetCore.Authentication.Cookies; +using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Identity; using Microsoft.Extensions.Options; using Umbraco.Cms.Core.Routing; @@ -44,6 +45,12 @@ public sealed class ConfigureMemberCookieOptions : IConfigureNamedOptions + { + ctx.Response.StatusCode = StatusCodes.Status403Forbidden; + return Task.CompletedTask; }, }; diff --git a/src/Umbraco.Web.UI.New.Client b/src/Umbraco.Web.UI.New.Client index 275e599a61..c48ede4dee 160000 --- a/src/Umbraco.Web.UI.New.Client +++ b/src/Umbraco.Web.UI.New.Client @@ -1 +1 @@ -Subproject commit 275e599a61363fdd2060a1db45f68b13f4484e0f +Subproject commit c48ede4dee5c9f1fd7986042edb67ddee5258054 diff --git a/templates/Umbraco.Templates.csproj b/templates/Umbraco.Templates.csproj index 10bbd666d1..38848d398a 100644 --- a/templates/Umbraco.Templates.csproj +++ b/templates/Umbraco.Templates.csproj @@ -8,10 +8,12 @@ true true . + NU5128 + UmbracoProject\Program.cs @@ -42,4 +44,25 @@ UmbracoProject\wwwroot + + + + + + + + <_TemplateJsonFiles Include="**\.template.config\template.json" Exclude="bin\**;obj\**" /> + <_TemplateJsonFiles> + $(IntermediateOutputPath)%(RelativeDir)%(Filename)%(Extension) + + + + + + <_PackageFiles Remove="@(_TemplateJsonFiles)" /> + <_PackageFiles Include="%(_TemplateJsonFiles.DestinationFile)"> + %(RelativeDir) + + + diff --git a/templates/UmbracoPackage/.template.config/dotnetcli.host.json b/templates/UmbracoPackage/.template.config/dotnetcli.host.json index 6bd79b7fd9..6473c5c643 100644 --- a/templates/UmbracoPackage/.template.config/dotnetcli.host.json +++ b/templates/UmbracoPackage/.template.config/dotnetcli.host.json @@ -3,11 +3,16 @@ "symbolInfo": { "Framework": { "longName": "Framework", - "shortName": "F" + "shortName": "F", + "isHidden": true }, "UmbracoVersion": { "longName": "version", "shortName": "v" + }, + "SkipRestore": { + "longName": "no-restore", + "shortName": "" } } } diff --git a/templates/UmbracoPackage/.template.config/template.json b/templates/UmbracoPackage/.template.config/template.json index 36c93da093..768a7a4bee 100644 --- a/templates/UmbracoPackage/.template.config/template.json +++ b/templates/UmbracoPackage/.template.config/template.json @@ -41,9 +41,16 @@ "description": "The version of Umbraco.Cms to add as PackageReference.", "type": "parameter", "datatype": "string", - "defaultValue": "10.0.0-rc1", + "defaultValue": "*", "replaces": "UMBRACO_VERSION_FROM_TEMPLATE" }, + "SkipRestore": { + "displayName": "Skip restore", + "description": "If specified, skips the automatic restore of the project on create.", + "type": "parameter", + "datatype": "bool", + "defaultValue": "false" + }, "Namespace": { "type": "derived", "valueSource": "name", @@ -83,5 +90,19 @@ { "path": "UmbracoPackage.csproj" } + ], + "postActions": [ + { + "id": "restore", + "condition": "(!SkipRestore)", + "description": "Restore NuGet packages required by this project.", + "manualInstructions": [ + { + "text": "Run 'dotnet restore'" + } + ], + "actionId": "210D431B-A78B-4D2F-B762-4ED3E3EA9025", + "continueOnError": true + } ] } diff --git a/templates/UmbracoPackageRcl/.template.config/dotnetcli.host.json b/templates/UmbracoPackageRcl/.template.config/dotnetcli.host.json new file mode 100644 index 0000000000..9a960b348e --- /dev/null +++ b/templates/UmbracoPackageRcl/.template.config/dotnetcli.host.json @@ -0,0 +1,22 @@ +{ + "$schema": "https://json.schemastore.org/dotnetcli.host.json", + "symbolInfo": { + "Framework": { + "longName": "Framework", + "shortName": "F", + "isHidden": true + }, + "UmbracoVersion": { + "longName": "version", + "shortName": "" + }, + "SkipRestore": { + "longName": "no-restore", + "shortName": "" + }, + "SupportPagesAndViews": { + "longName": "support-pages-and-views", + "shortName": "s" + } + } +} diff --git a/templates/UmbracoPackageRcl/.template.config/ide.host.json b/templates/UmbracoPackageRcl/.template.config/ide.host.json new file mode 100644 index 0000000000..8e630f1e99 --- /dev/null +++ b/templates/UmbracoPackageRcl/.template.config/ide.host.json @@ -0,0 +1,20 @@ +{ + "$schema": "https://json.schemastore.org/ide.host.json", + "order": 0, + "icon": "../../icon.png", + "description": { + "id": "UmbracoPackageRcl", + "text": "Umbraco Package RCL - An empty Umbraco package/plugin (Razor Class Library)." + }, + "symbolInfo": [ + { + "id": "UmbracoVersion", + "isVisible": true + }, + { + "id": "SupportPagesAndViews", + "isVisible": true, + "persistenceScope": "templateGroup" + } + ] +} diff --git a/templates/UmbracoPackageRcl/.template.config/template.json b/templates/UmbracoPackageRcl/.template.config/template.json new file mode 100644 index 0000000000..be7b1c04e8 --- /dev/null +++ b/templates/UmbracoPackageRcl/.template.config/template.json @@ -0,0 +1,82 @@ +{ + "$schema": "https://json.schemastore.org/template.json", + "author": "Umbraco HQ", + "classifications": [ + "Web", + "CMS", + "Umbraco", + "Package", + "Plugin", + "Razor Class Library" + ], + "name": "Umbraco Package RCL", + "description": "An empty Umbraco package/plugin (Razor Class Library).", + "groupIdentity": "Umbraco.Templates.UmbracoPackageRcl", + "identity": "Umbraco.Templates.UmbracoPackageRcl.CSharp", + "shortName": "umbracopackage-rcl", + "tags": { + "language": "C#", + "type": "project" + }, + "sourceName": "UmbracoPackage", + "defaultName": "UmbracoPackage1", + "preferNameDirectory": true, + "symbols": { + "Framework": { + "displayName": "Framework", + "description": "The target framework for the project.", + "type": "parameter", + "datatype": "choice", + "choices": [ + { + "displayName": ".NET 7.0", + "description": "Target net7.0", + "choice": "net7.0" + } + ], + "defaultValue": "net7.0", + "replaces": "net7.0" + }, + "UmbracoVersion": { + "displayName": "Umbraco version", + "description": "The version of Umbraco.Cms to add as PackageReference.", + "type": "parameter", + "datatype": "string", + "defaultValue": "*", + "replaces": "UMBRACO_VERSION_FROM_TEMPLATE" + }, + "SkipRestore": { + "displayName": "Skip restore", + "description": "If specified, skips the automatic restore of the project on create.", + "type": "parameter", + "datatype": "bool", + "defaultValue": "false" + }, + "SupportPagesAndViews": { + "type": "parameter", + "datatype": "bool", + "defaultValue": "false", + "displayName": "Support pages and views", + "description": "Whether to support adding traditional Razor pages and Views to this library." + } + }, + "primaryOutputs": [ + { + "path": "UmbracoPackage.csproj" + } + ], + "postActions": [ + { + "id": "restore", + "condition": "(!SkipRestore)", + "description": "Restore NuGet packages required by this project.", + "manualInstructions": [ + { + "text": "Run 'dotnet restore'" + } + ], + "actionId": "210D431B-A78B-4D2F-B762-4ED3E3EA9025", + "continueOnError": true + } + ] +} diff --git a/templates/UmbracoPackageRcl/UmbracoPackage.csproj b/templates/UmbracoPackageRcl/UmbracoPackage.csproj new file mode 100644 index 0000000000..5c980684ce --- /dev/null +++ b/templates/UmbracoPackageRcl/UmbracoPackage.csproj @@ -0,0 +1,27 @@ + + + net7.0 + enable + enable + true + UmbracoPackage + App_Plugins/UmbracoPackage + + + + UmbracoPackage + UmbracoPackage + UmbracoPackage + ... + umbraco plugin package + + + + + + + + + + + diff --git a/templates/UmbracoPackageRcl/wwwroot/package.manifest b/templates/UmbracoPackageRcl/wwwroot/package.manifest new file mode 100644 index 0000000000..6aadd0cee6 --- /dev/null +++ b/templates/UmbracoPackageRcl/wwwroot/package.manifest @@ -0,0 +1,5 @@ +{ + "name": "UmbracoPackage", + "version": "", + "allowPackageTelemetry": true +} diff --git a/templates/UmbracoProject/.template.config/dotnetcli.host.json b/templates/UmbracoProject/.template.config/dotnetcli.host.json index 7f5479eab0..dfd6f80184 100644 --- a/templates/UmbracoProject/.template.config/dotnetcli.host.json +++ b/templates/UmbracoProject/.template.config/dotnetcli.host.json @@ -3,7 +3,8 @@ "symbolInfo": { "Framework": { "longName": "Framework", - "shortName": "F" + "shortName": "F", + "isHidden": true }, "UmbracoVersion": { "longName": "version", @@ -55,14 +56,15 @@ }, "PackageProjectName": { "longName": "PackageTestSiteName", - "shortName": "p" + "shortName": "p", + "isHidden": true } }, "usageExamples": [ - "dotnet new umbraco -n MyNewProject", - "dotnet new umbraco -n MyNewProject --no-restore", - "dotnet new umbraco -n MyNewProject --development-database-type SQLite", - "dotnet new umbraco -n MyNewProject --development-database-type LocalDB", - "dotnet new umbraco -n MyNewProject --friendly-name \"Friendly Admin User\" --email admin@example.com --password password1234 --connection-string \"Server=ConnectionStringHere\"" + "dotnet new umbraco --name MyNewProject", + "dotnet new umbraco --name MyNewProject --no-restore", + "dotnet new umbraco --name MyNewProject --development-database-type SQLite", + "dotnet new umbraco --name MyNewProject --development-database-type LocalDB", + "dotnet new umbraco --name MyNewProject --friendly-name \"Administrator\" --email admin@example.com --password 1234567890 --connection-string \"Server=(local);Database=MyNewProject;Trusted_Connection=True;\"" ] } diff --git a/templates/UmbracoProject/.template.config/ide.host.json b/templates/UmbracoProject/.template.config/ide.host.json index 617f924f97..1a302779cc 100644 --- a/templates/UmbracoProject/.template.config/ide.host.json +++ b/templates/UmbracoProject/.template.config/ide.host.json @@ -13,19 +13,18 @@ }, { "id": "UseHttpsRedirect", - "isVisible": true - }, - { - "id": "SkipRestore", - "isVisible": true + "isVisible": true, + "persistenceScope": "templateGroup" }, { "id": "ExcludeGitignore", - "isVisible": true + "isVisible": true, + "persistenceScope": "templateGroup" }, { "id": "MinimalGitignore", - "isVisible": true + "isVisible": true, + "persistenceScope": "templateGroup" }, { "id": "ConnectionString", @@ -37,7 +36,8 @@ }, { "id": "DevelopmentDatabaseType", - "isVisible": true + "isVisible": true, + "persistenceScope": "templateGroup" }, { "id": "UnattendedUserName", @@ -54,10 +54,6 @@ { "id": "NoNodesViewPath", "isVisible": true - }, - { - "id": "PackageProjectName", - "isVisible": true } ] } diff --git a/templates/UmbracoProject/.template.config/template.json b/templates/UmbracoProject/.template.config/template.json index befe6d7e5a..d88b23c07d 100644 --- a/templates/UmbracoProject/.template.config/template.json +++ b/templates/UmbracoProject/.template.config/template.json @@ -51,7 +51,7 @@ "description": "The version of Umbraco.Cms to add as PackageReference.", "type": "parameter", "datatype": "string", - "defaultValue": "10.0.0-rc1", + "defaultValue": "*", "replaces": "UMBRACO_VERSION_FROM_TEMPLATE" }, "UseHttpsRedirect": { diff --git a/tests/Umbraco.Tests.Common/CompatibilitySuppressions.xml b/tests/Umbraco.Tests.Common/CompatibilitySuppressions.xml index 657f05d2d7..a709113936 100644 --- a/tests/Umbraco.Tests.Common/CompatibilitySuppressions.xml +++ b/tests/Umbraco.Tests.Common/CompatibilitySuppressions.xml @@ -1,4 +1,5 @@  + CP0002 diff --git a/tests/Umbraco.Tests.Integration/CompatibilitySuppressions.xml b/tests/Umbraco.Tests.Integration/CompatibilitySuppressions.xml index bdfa11824e..2ff5f38afb 100644 --- a/tests/Umbraco.Tests.Integration/CompatibilitySuppressions.xml +++ b/tests/Umbraco.Tests.Integration/CompatibilitySuppressions.xml @@ -1,4 +1,5 @@  + CP0002 diff --git a/tests/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Migrations/MigrationPlanTests.cs b/tests/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Migrations/MigrationPlanTests.cs index c345b05ced..ca2d9bba59 100644 --- a/tests/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Migrations/MigrationPlanTests.cs +++ b/tests/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Migrations/MigrationPlanTests.cs @@ -74,11 +74,10 @@ public class MigrationPlanTests var executor = new MigrationPlanExecutor( scopeProvider, scopeProvider, - loggerFactory, - migrationBuilder, - databaseFactory, - Mock.Of(), - distributedCache); + loggerFactory, + migrationBuilder, + databaseFactory, + Mock.Of(), distributedCache); var plan = new MigrationPlan("default") .From(string.Empty) diff --git a/version.json b/version.json index 06b868d719..8f4e1d83d5 100644 --- a/version.json +++ b/version.json @@ -1,6 +1,6 @@ { "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", - "version": "11.3.0-rc", + "version": "13.0.0-rc", "assemblyVersion": { "precision": "build" },