Enable validation of specific cultures only for document updates (#17087)
* Enable validation of specific cultures only for document updates * Only validate explicitly sent cultures in the create validation endpoint * Fix backwards compat (obsolete old method) --------- Co-authored-by: Mads Rasmussen <madsr@hey.com>
This commit is contained in:
@@ -12,6 +12,7 @@ using Umbraco.Cms.Core.Services.OperationStatus;
|
||||
namespace Umbraco.Cms.Api.Management.Controllers.Document;
|
||||
|
||||
[ApiVersion("1.0")]
|
||||
[ApiVersion("1.1")]
|
||||
public class ValidateUpdateDocumentController : UpdateDocumentControllerBase
|
||||
{
|
||||
private readonly IContentEditingService _contentEditingService;
|
||||
@@ -32,10 +33,35 @@ public class ValidateUpdateDocumentController : UpdateDocumentControllerBase
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)]
|
||||
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)]
|
||||
[Obsolete("Please use version 1.1 of this API. Will be removed in V16.")]
|
||||
public async Task<IActionResult> Validate(CancellationToken cancellationToken, Guid id, UpdateDocumentRequestModel requestModel)
|
||||
=> await HandleRequest(id, requestModel, async () =>
|
||||
{
|
||||
ContentUpdateModel model = _documentEditingPresentationFactory.MapUpdateModel(requestModel);
|
||||
var validateUpdateDocumentRequestModel = new ValidateUpdateDocumentRequestModel
|
||||
{
|
||||
Values = requestModel.Values,
|
||||
Variants = requestModel.Variants,
|
||||
Template = requestModel.Template,
|
||||
Cultures = null
|
||||
};
|
||||
|
||||
ValidateContentUpdateModel model = _documentEditingPresentationFactory.MapValidateUpdateModel(validateUpdateDocumentRequestModel);
|
||||
Attempt<ContentValidationResult, ContentEditingOperationStatus> result = await _contentEditingService.ValidateUpdateAsync(id, model);
|
||||
|
||||
return result.Success
|
||||
? Ok()
|
||||
: DocumentEditingOperationStatusResult(result.Status, requestModel, result.Result);
|
||||
});
|
||||
|
||||
[HttpPut("{id:guid}/validate")]
|
||||
[MapToApiVersion("1.1")]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)]
|
||||
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)]
|
||||
public async Task<IActionResult> ValidateV1_1(CancellationToken cancellationToken, Guid id, ValidateUpdateDocumentRequestModel requestModel)
|
||||
=> await HandleRequest(id, requestModel, async () =>
|
||||
{
|
||||
ValidateContentUpdateModel model = _documentEditingPresentationFactory.MapValidateUpdateModel(requestModel);
|
||||
Attempt<ContentValidationResult, ContentEditingOperationStatus> result = await _contentEditingService.ValidateUpdateAsync(id, model);
|
||||
|
||||
return result.Success
|
||||
|
||||
@@ -17,8 +17,20 @@ internal sealed class DocumentEditingPresentationFactory : ContentEditingPresent
|
||||
}
|
||||
|
||||
public ContentUpdateModel MapUpdateModel(UpdateDocumentRequestModel requestModel)
|
||||
=> MapUpdateContentModel<ContentUpdateModel>(requestModel);
|
||||
|
||||
public ValidateContentUpdateModel MapValidateUpdateModel(ValidateUpdateDocumentRequestModel requestModel)
|
||||
{
|
||||
ContentUpdateModel model = MapContentEditingModel<ContentUpdateModel>(requestModel);
|
||||
ValidateContentUpdateModel model = MapUpdateContentModel<ValidateContentUpdateModel>(requestModel);
|
||||
model.Cultures = requestModel.Cultures;
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
private TUpdateModel MapUpdateContentModel<TUpdateModel>(UpdateDocumentRequestModel requestModel)
|
||||
where TUpdateModel : ContentUpdateModel, new()
|
||||
{
|
||||
TUpdateModel model = MapContentEditingModel<TUpdateModel>(requestModel);
|
||||
model.TemplateKey = requestModel.Template?.Id;
|
||||
|
||||
return model;
|
||||
|
||||
@@ -8,4 +8,6 @@ public interface IDocumentEditingPresentationFactory
|
||||
ContentCreateModel MapCreateModel(CreateDocumentRequestModel requestModel);
|
||||
|
||||
ContentUpdateModel MapUpdateModel(UpdateDocumentRequestModel requestModel);
|
||||
|
||||
ValidateContentUpdateModel MapValidateUpdateModel(ValidateUpdateDocumentRequestModel requestModel);
|
||||
}
|
||||
|
||||
@@ -9372,6 +9372,149 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"deprecated": true,
|
||||
"security": [
|
||||
{
|
||||
"Backoffice User": [ ]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"/umbraco/management/api/v1.1/document/{id}/validate": {
|
||||
"put": {
|
||||
"tags": [
|
||||
"Document"
|
||||
],
|
||||
"operationId": "PutUmbracoManagementApiV1.1DocumentByIdValidate1.1",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"format": "uuid"
|
||||
}
|
||||
}
|
||||
],
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"oneOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/ValidateUpdateDocumentRequestModel"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"text/json": {
|
||||
"schema": {
|
||||
"oneOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/ValidateUpdateDocumentRequestModel"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"application/*+json": {
|
||||
"schema": {
|
||||
"oneOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/ValidateUpdateDocumentRequestModel"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"headers": {
|
||||
"Umb-Notifications": {
|
||||
"description": "The list of notifications produced during the request.",
|
||||
"schema": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/NotificationHeaderModel"
|
||||
},
|
||||
"nullable": true
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Request",
|
||||
"headers": {
|
||||
"Umb-Notifications": {
|
||||
"description": "The list of notifications produced during the request.",
|
||||
"schema": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/NotificationHeaderModel"
|
||||
},
|
||||
"nullable": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"oneOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/ProblemDetails"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"404": {
|
||||
"description": "Not Found",
|
||||
"headers": {
|
||||
"Umb-Notifications": {
|
||||
"description": "The list of notifications produced during the request.",
|
||||
"schema": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/NotificationHeaderModel"
|
||||
},
|
||||
"nullable": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"oneOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/ProblemDetails"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"401": {
|
||||
"description": "The resource is protected and requires an authentication token"
|
||||
},
|
||||
"403": {
|
||||
"description": "The authenticated user do not have access to this resource",
|
||||
"headers": {
|
||||
"Umb-Notifications": {
|
||||
"description": "The list of notifications produced during the request.",
|
||||
"schema": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/NotificationHeaderModel"
|
||||
},
|
||||
"nullable": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"Backoffice User": [ ]
|
||||
@@ -45526,6 +45669,52 @@
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"ValidateUpdateDocumentRequestModel": {
|
||||
"required": [
|
||||
"values",
|
||||
"variants"
|
||||
],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"values": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"oneOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/DocumentValueModel"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"variants": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"oneOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/DocumentVariantRequestModel"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"template": {
|
||||
"oneOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/ReferenceByIdModel"
|
||||
}
|
||||
],
|
||||
"nullable": true
|
||||
},
|
||||
"cultures": {
|
||||
"uniqueItems": true,
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"nullable": true
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"VariantItemResponseModel": {
|
||||
"required": [
|
||||
"name"
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace Umbraco.Cms.Api.Management.ViewModels.Document;
|
||||
|
||||
public class ValidateUpdateDocumentRequestModel : UpdateDocumentRequestModel
|
||||
{
|
||||
public ISet<string>? Cultures { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace Umbraco.Cms.Core.Models.ContentEditing;
|
||||
|
||||
public class ValidateContentUpdateModel : ContentUpdateModel
|
||||
{
|
||||
public ISet<string>? Cultures { get; set; }
|
||||
}
|
||||
@@ -36,6 +36,7 @@ internal sealed class ContentEditingService
|
||||
return await Task.FromResult(content);
|
||||
}
|
||||
|
||||
[Obsolete("Please use the validate update method that is not obsoleted. Will be removed in V16.")]
|
||||
public async Task<Attempt<ContentValidationResult, ContentEditingOperationStatus>> ValidateUpdateAsync(Guid key, ContentUpdateModel updateModel)
|
||||
{
|
||||
IContent? content = ContentService.GetById(key);
|
||||
@@ -44,8 +45,16 @@ internal sealed class ContentEditingService
|
||||
: Attempt.FailWithStatus(ContentEditingOperationStatus.NotFound, new ContentValidationResult());
|
||||
}
|
||||
|
||||
public async Task<Attempt<ContentValidationResult, ContentEditingOperationStatus>> ValidateUpdateAsync(Guid key, ValidateContentUpdateModel updateModel)
|
||||
{
|
||||
IContent? content = ContentService.GetById(key);
|
||||
return content is not null
|
||||
? await ValidateCulturesAndPropertiesAsync(updateModel, content.ContentType.Key, updateModel.Cultures)
|
||||
: Attempt.FailWithStatus(ContentEditingOperationStatus.NotFound, new ContentValidationResult());
|
||||
}
|
||||
|
||||
public async Task<Attempt<ContentValidationResult, ContentEditingOperationStatus>> ValidateCreateAsync(ContentCreateModel createModel)
|
||||
=> await ValidateCulturesAndPropertiesAsync(createModel, createModel.ContentTypeKey);
|
||||
=> await ValidateCulturesAndPropertiesAsync(createModel, createModel.ContentTypeKey, createModel.Variants.Select(variant => variant.Culture));
|
||||
|
||||
public async Task<Attempt<ContentCreateResult, ContentEditingOperationStatus>> CreateAsync(ContentCreateModel createModel, Guid userKey)
|
||||
{
|
||||
@@ -137,10 +146,11 @@ internal sealed class ContentEditingService
|
||||
|
||||
private async Task<Attempt<ContentValidationResult, ContentEditingOperationStatus>> ValidateCulturesAndPropertiesAsync(
|
||||
ContentEditingModelBase contentEditingModelBase,
|
||||
Guid contentTypeKey)
|
||||
Guid contentTypeKey,
|
||||
IEnumerable<string?>? culturesToValidate = null)
|
||||
=> await ValidateCulturesAsync(contentEditingModelBase) is false
|
||||
? Attempt.FailWithStatus(ContentEditingOperationStatus.InvalidCulture, new ContentValidationResult())
|
||||
: await ValidatePropertiesAsync(contentEditingModelBase, contentTypeKey);
|
||||
: await ValidatePropertiesAsync(contentEditingModelBase, contentTypeKey, culturesToValidate);
|
||||
|
||||
private async Task<ContentEditingOperationStatus> UpdateTemplateAsync(IContent content, Guid? templateKey)
|
||||
{
|
||||
|
||||
@@ -113,7 +113,8 @@ internal abstract class ContentEditingServiceBase<TContent, TContentType, TConte
|
||||
|
||||
protected async Task<Attempt<ContentValidationResult, ContentEditingOperationStatus>> ValidatePropertiesAsync(
|
||||
ContentEditingModelBase contentEditingModelBase,
|
||||
Guid contentTypeKey)
|
||||
Guid contentTypeKey,
|
||||
IEnumerable<string?>? culturesToValidate = null)
|
||||
{
|
||||
TContentType? contentType = await ContentTypeService.GetAsync(contentTypeKey);
|
||||
if (contentType is null)
|
||||
@@ -121,14 +122,15 @@ internal abstract class ContentEditingServiceBase<TContent, TContentType, TConte
|
||||
return Attempt.FailWithStatus(ContentEditingOperationStatus.ContentTypeNotFound, new ContentValidationResult());
|
||||
}
|
||||
|
||||
return await ValidatePropertiesAsync(contentEditingModelBase, contentType);
|
||||
return await ValidatePropertiesAsync(contentEditingModelBase, contentType, culturesToValidate);
|
||||
}
|
||||
|
||||
private async Task<Attempt<ContentValidationResult, ContentEditingOperationStatus>> ValidatePropertiesAsync(
|
||||
ContentEditingModelBase contentEditingModelBase,
|
||||
TContentType contentType)
|
||||
TContentType contentType,
|
||||
IEnumerable<string?>? culturesToValidate = null)
|
||||
{
|
||||
ContentValidationResult result = await _validationService.ValidatePropertiesAsync(contentEditingModelBase, contentType);
|
||||
ContentValidationResult result = await _validationService.ValidatePropertiesAsync(contentEditingModelBase, contentType, culturesToValidate);
|
||||
return result.ValidationErrors.Any() is false
|
||||
? Attempt.SucceedWithStatus(ContentEditingOperationStatus.Success, result)
|
||||
: Attempt.FailWithStatus(ContentEditingOperationStatus.PropertyValidationError, result);
|
||||
|
||||
@@ -12,6 +12,7 @@ internal sealed class ContentValidationService : ContentValidationServiceBase<IC
|
||||
|
||||
public async Task<ContentValidationResult> ValidatePropertiesAsync(
|
||||
ContentEditingModelBase contentEditingModelBase,
|
||||
IContentType contentType)
|
||||
=> await HandlePropertiesValidationAsync(contentEditingModelBase, contentType);
|
||||
IContentType contentType,
|
||||
IEnumerable<string?>? culturesToValidate = null)
|
||||
=> await HandlePropertiesValidationAsync(contentEditingModelBase, contentType, culturesToValidate);
|
||||
}
|
||||
|
||||
@@ -23,7 +23,8 @@ internal abstract class ContentValidationServiceBase<TContentType>
|
||||
|
||||
protected async Task<ContentValidationResult> HandlePropertiesValidationAsync(
|
||||
ContentEditingModelBase contentEditingModelBase,
|
||||
TContentType contentType)
|
||||
TContentType contentType,
|
||||
IEnumerable<string?>? culturesToValidate = null)
|
||||
{
|
||||
var validationErrors = new List<PropertyValidationError>();
|
||||
|
||||
@@ -43,7 +44,7 @@ internal abstract class ContentValidationServiceBase<TContentType>
|
||||
return new ContentValidationResult { ValidationErrors = validationErrors };
|
||||
}
|
||||
|
||||
var cultures = await GetCultureCodes();
|
||||
var cultures = culturesToValidate?.ToArray() ?? await GetCultureCodes();
|
||||
// we don't have any managed segments, so we have to make do with the ones passed in the model
|
||||
var segments = contentEditingModelBase.Variants.DistinctBy(variant => variant.Segment).Select(variant => variant.Segment).ToArray();
|
||||
|
||||
|
||||
@@ -10,8 +10,11 @@ public interface IContentEditingService
|
||||
|
||||
Task<Attempt<ContentValidationResult, ContentEditingOperationStatus>> ValidateCreateAsync(ContentCreateModel createModel);
|
||||
|
||||
[Obsolete("Please use the validate update method that is not obsoleted. Will be removed in V16.")]
|
||||
Task<Attempt<ContentValidationResult, ContentEditingOperationStatus>> ValidateUpdateAsync(Guid key, ContentUpdateModel updateModel);
|
||||
|
||||
Task<Attempt<ContentValidationResult, ContentEditingOperationStatus>> ValidateUpdateAsync(Guid key, ValidateContentUpdateModel updateModel);
|
||||
|
||||
Task<Attempt<ContentCreateResult, ContentEditingOperationStatus>> CreateAsync(ContentCreateModel createModel, Guid userKey);
|
||||
|
||||
Task<Attempt<ContentUpdateResult, ContentEditingOperationStatus>> UpdateAsync(Guid key, ContentUpdateModel updateModel, Guid userKey);
|
||||
|
||||
@@ -6,7 +6,7 @@ namespace Umbraco.Cms.Core.Services;
|
||||
internal interface IContentValidationServiceBase<in TContentType>
|
||||
where TContentType : IContentTypeComposition
|
||||
{
|
||||
Task<ContentValidationResult> ValidatePropertiesAsync(ContentEditingModelBase contentEditingModelBase, TContentType contentType);
|
||||
Task<ContentValidationResult> ValidatePropertiesAsync(ContentEditingModelBase contentEditingModelBase, TContentType contentType, IEnumerable<string?>? culturesToValidate = null);
|
||||
|
||||
Task<bool> ValidateCulturesAsync(ContentEditingModelBase contentEditingModelBase);
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ internal sealed class MediaValidationService : ContentValidationServiceBase<IMed
|
||||
|
||||
public async Task<ContentValidationResult> ValidatePropertiesAsync(
|
||||
ContentEditingModelBase contentEditingModelBase,
|
||||
IMediaType mediaType)
|
||||
=> await HandlePropertiesValidationAsync(contentEditingModelBase, mediaType);
|
||||
IMediaType mediaType,
|
||||
IEnumerable<string?>? culturesToValidate = null)
|
||||
=> await HandlePropertiesValidationAsync(contentEditingModelBase, mediaType, culturesToValidate);
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ internal sealed class MemberValidationService : ContentValidationServiceBase<IMe
|
||||
|
||||
public async Task<ContentValidationResult> ValidatePropertiesAsync(
|
||||
ContentEditingModelBase contentEditingModelBase,
|
||||
IMemberType memberType)
|
||||
=> await HandlePropertiesValidationAsync(contentEditingModelBase, memberType);
|
||||
IMemberType memberType,
|
||||
IEnumerable<string?>? culturesToValidate = null)
|
||||
=> await HandlePropertiesValidationAsync(contentEditingModelBase, memberType, culturesToValidate);
|
||||
}
|
||||
|
||||
@@ -317,6 +317,93 @@ public class ContentValidationServiceTests : UmbracoIntegrationTestWithContent
|
||||
Assert.AreEqual(expectedResult, result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Can_Validate_For_All_Languages()
|
||||
{
|
||||
var contentType = await SetupLanguageTest();
|
||||
|
||||
var validationResult = await ContentValidationService.ValidatePropertiesAsync(
|
||||
new ContentCreateModel
|
||||
{
|
||||
ContentTypeKey = contentType.Key,
|
||||
Variants = [
|
||||
new()
|
||||
{
|
||||
Name = "Test Document (EN)",
|
||||
Culture = "en-US",
|
||||
Properties = [
|
||||
new()
|
||||
{
|
||||
Alias = "title",
|
||||
Value = "Invalid value in English",
|
||||
}
|
||||
]
|
||||
},
|
||||
new()
|
||||
{
|
||||
Name = "Test Document (DA)",
|
||||
Culture = "da-DK",
|
||||
Properties = [
|
||||
new()
|
||||
{
|
||||
Alias = "title",
|
||||
Value = "Invalid value in Danish",
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
contentType);
|
||||
|
||||
Assert.AreEqual(2, validationResult.ValidationErrors.Count());
|
||||
Assert.IsNotNull(validationResult.ValidationErrors.SingleOrDefault(r => r.Alias == "title" && r.Culture == "en-US" && r.JsonPath == string.Empty));
|
||||
Assert.IsNotNull(validationResult.ValidationErrors.SingleOrDefault(r => r.Alias == "title" && r.Culture == "da-DK" && r.JsonPath == string.Empty));
|
||||
}
|
||||
|
||||
[TestCase("da-DK")]
|
||||
[TestCase("en-US")]
|
||||
public async Task Can_Validate_For_Specific_Language(string culture)
|
||||
{
|
||||
var contentType = await SetupLanguageTest();
|
||||
|
||||
var validationResult = await ContentValidationService.ValidatePropertiesAsync(
|
||||
new ContentCreateModel
|
||||
{
|
||||
ContentTypeKey = contentType.Key,
|
||||
Variants = [
|
||||
new()
|
||||
{
|
||||
Name = "Test Document (EN)",
|
||||
Culture = "en-US",
|
||||
Properties = [
|
||||
new()
|
||||
{
|
||||
Alias = "title",
|
||||
Value = "Invalid value in English",
|
||||
}
|
||||
]
|
||||
},
|
||||
new()
|
||||
{
|
||||
Name = "Test Document (DA)",
|
||||
Culture = "da-DK",
|
||||
Properties = [
|
||||
new()
|
||||
{
|
||||
Alias = "title",
|
||||
Value = "Invalid value in Danish",
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
contentType,
|
||||
[culture]);
|
||||
|
||||
Assert.AreEqual(1, validationResult.ValidationErrors.Count());
|
||||
Assert.IsNotNull(validationResult.ValidationErrors.SingleOrDefault(r => r.Alias == "title" && r.Culture == culture && r.JsonPath == string.Empty));
|
||||
}
|
||||
|
||||
private async Task<(IContentType DocumentType, IContentType ElementType)> SetupBlockListTest()
|
||||
{
|
||||
var propertyEditorCollection = GetRequiredService<PropertyEditorCollection>();
|
||||
@@ -398,4 +485,22 @@ public class ContentValidationServiceTests : UmbracoIntegrationTestWithContent
|
||||
|
||||
return contentType;
|
||||
}
|
||||
|
||||
private async Task<IContentType> SetupLanguageTest()
|
||||
{
|
||||
var language = new LanguageBuilder()
|
||||
.WithCultureInfo("da-DK")
|
||||
.Build();
|
||||
await LanguageService.CreateAsync(language, Constants.Security.SuperUserKey);
|
||||
|
||||
var contentType = ContentTypeBuilder.CreateSimpleContentType("umbMandatory", "Mandatory Doc Type");
|
||||
contentType.Variations = ContentVariation.Culture;
|
||||
var titlePropertyType = contentType.PropertyTypes.First(pt => pt.Alias == "title");
|
||||
titlePropertyType.Variations = ContentVariation.Culture;
|
||||
titlePropertyType.ValidationRegExp = "^Valid.*$";
|
||||
contentType.AllowedAsRoot = true;
|
||||
await ContentTypeService.CreateAsync(contentType, Constants.Security.SuperUserKey);
|
||||
|
||||
return contentType;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user