From 19889bee51a32cfec2e949f737a143e0c5afa22a Mon Sep 17 00:00:00 2001 From: Tony Han Date: Sun, 5 May 2024 20:28:57 +0800 Subject: [PATCH] add typepart check #15979 --- .../RecipeSteps/ContentDefinitionStep.cs | 6 ++ .../Services/ContentDefinitionService.cs | 1 + .../OrchardCore.Tests.csproj | 2 + .../Recipes/RecipeExecutorTests.cs | 23 ++++++++ .../Recipes/RecipeFiles/recipe6.json | 58 +++++++++++++++++++ 5 files changed, 90 insertions(+) create mode 100644 test/OrchardCore.Tests/Recipes/RecipeFiles/recipe6.json diff --git a/src/OrchardCore.Modules/OrchardCore.ContentTypes/RecipeSteps/ContentDefinitionStep.cs b/src/OrchardCore.Modules/OrchardCore.ContentTypes/RecipeSteps/ContentDefinitionStep.cs index 1eb43b95749..1f2a2e1b0ed 100644 --- a/src/OrchardCore.Modules/OrchardCore.ContentTypes/RecipeSteps/ContentDefinitionStep.cs +++ b/src/OrchardCore.Modules/OrchardCore.ContentTypes/RecipeSteps/ContentDefinitionStep.cs @@ -1,6 +1,7 @@ using System; using System.Text.Json.Nodes; using System.Threading.Tasks; +using Microsoft.Extensions.Localization; using OrchardCore.ContentManagement.Metadata; using OrchardCore.ContentManagement.Metadata.Models; using OrchardCore.ContentManagement.Metadata.Records; @@ -58,6 +59,11 @@ private Task UpdateContentTypeAsync(ContentTypeDefinition type, ContentTypeDefin foreach (var part in record.ContentTypePartDefinitionRecords) { + if (string.IsNullOrEmpty(part.PartName)) + { + throw new Exception(string.Format("Failed to add part to ContentType '{0}', The PartName property is not allowed to be empty", type.Name)); + } + builder.WithPart(part.Name, part.PartName, partBuilder => partBuilder.MergeSettings(part.Settings)); } }); diff --git a/src/OrchardCore.Modules/OrchardCore.ContentTypes/Services/ContentDefinitionService.cs b/src/OrchardCore.Modules/OrchardCore.ContentTypes/Services/ContentDefinitionService.cs index 21825fefe2a..659be4f07d6 100644 --- a/src/OrchardCore.Modules/OrchardCore.ContentTypes/Services/ContentDefinitionService.cs +++ b/src/OrchardCore.Modules/OrchardCore.ContentTypes/Services/ContentDefinitionService.cs @@ -5,6 +5,7 @@ using Microsoft.Extensions.Localization; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; +using Microsoft.IdentityModel.Tokens; using OrchardCore.ContentManagement; using OrchardCore.ContentManagement.Metadata; using OrchardCore.ContentManagement.Metadata.Models; diff --git a/test/OrchardCore.Tests/OrchardCore.Tests.csproj b/test/OrchardCore.Tests/OrchardCore.Tests.csproj index 97879b76cfe..28995c4eb9f 100644 --- a/test/OrchardCore.Tests/OrchardCore.Tests.csproj +++ b/test/OrchardCore.Tests/OrchardCore.Tests.csproj @@ -29,6 +29,7 @@ + @@ -44,6 +45,7 @@ + diff --git a/test/OrchardCore.Tests/Recipes/RecipeExecutorTests.cs b/test/OrchardCore.Tests/Recipes/RecipeExecutorTests.cs index 3bcdd2d742d..069fc329db9 100644 --- a/test/OrchardCore.Tests/Recipes/RecipeExecutorTests.cs +++ b/test/OrchardCore.Tests/Recipes/RecipeExecutorTests.cs @@ -8,6 +8,7 @@ using OrchardCore.Recipes.Models; using OrchardCore.Recipes.Services; using OrchardCore.Scripting; +using OrchardCore.Tests.Apis.Context; namespace OrchardCore.Recipes { @@ -50,6 +51,28 @@ public async Task ShouldTrimValidScriptExpression(string recipeName, string expe }); } + [Fact] + public async Task IncorrectTypeDefinitionImportsShouldBeBlocked() + { + var context = new BlogContext(); + await context.InitializeAsync(); + await context.UsingTenantScopeAsync(async scope => + { + var recipeExecutor = scope.ServiceProvider.GetRequiredService(); + // Act + var executionId = Guid.NewGuid().ToString("n"); + var recipeDescriptor = new RecipeDescriptor { RecipeFileInfo = GetRecipeFileInfo("recipe6") }; + try + { + await recipeExecutor.ExecuteAsync(executionId, recipeDescriptor, new Dictionary(), CancellationToken.None); + } + catch (Exception ex) + { + Assert.Equal("Failed to add part to ContentType 'Message', The PartName property is not allowed to be empty", ex.Message); + } + }); + } + private static Task GetScopeAsync() => ShellScope.Context.CreateScopeAsync(); private static ShellContext CreateShellContext() => new() diff --git a/test/OrchardCore.Tests/Recipes/RecipeFiles/recipe6.json b/test/OrchardCore.Tests/Recipes/RecipeFiles/recipe6.json new file mode 100644 index 00000000000..aaeecdfe059 --- /dev/null +++ b/test/OrchardCore.Tests/Recipes/RecipeFiles/recipe6.json @@ -0,0 +1,58 @@ +{ + "name": "Recipe6", + "displayName": "Recipe 6", + "description": "This is a recipe for a bug to verify that the type-checking function works as expected", + "author": "Tony Han", + "website": "", + "version": "1.0.0", + "issetuprecipe": false, + "categories": [ "test" ], + "tags": [], + "variables": { + "messageContentItemId": "[js:uuid()]", + "now": "[js: new Date().toISOString()]" + }, + "steps": [ + { + "name": "feature", + "enable": [ + "OrchardCore.Contents", + "OrchardCore.ContentTypes", + "OrchardCore.Title" + ] + }, + { + "name": "ContentDefinition", + "ContentTypes": [ + { + "Name": "Message", + "DisplayName": "Message", + "Settings": { + "ContentTypeSettings": { + "Creatable": true, + "Draftable": true, + "Versionable": true, + "Listable": true, + "Securable": true + } + }, + "ContentTypePartDefinitionRecords": [ + { + "PartName": "Message", + "Name": "Message", + "Settings": { + "ContentTypePartSettings": { + "Position": "5" + } + } + }, + { + //"PartName": "TitlePart",//test part validate + "Name": "TitlePart" + } + ] + } + ] + } + ] +}