diff --git a/src/Umbraco.Cms.Api.Management/Controllers/Document/UpdateDomainsController.cs b/src/Umbraco.Cms.Api.Management/Controllers/Document/UpdateDomainsController.cs index a7c7256c6b42..a44289b4c6f7 100644 --- a/src/Umbraco.Cms.Api.Management/Controllers/Document/UpdateDomainsController.cs +++ b/src/Umbraco.Cms.Api.Management/Controllers/Document/UpdateDomainsController.cs @@ -66,6 +66,10 @@ public async Task Update( .WithDetail("One or more of the specified domain names were conflicting with domain assignments to other content items.") .WithExtension("conflictingDomainNames", _domainPresentationFactory.CreateDomainAssignmentModels(result.Result.ConflictingDomains.EmptyNull())) .Build()), + DomainOperationStatus.InvalidDomainName => BadRequest(problemDetailsBuilder + .WithTitle("Invalid domain name detected") + .WithDetail("One or more of the specified domain names were invalid.") + .Build()), _ => StatusCode(StatusCodes.Status500InternalServerError, problemDetailsBuilder .WithTitle("Unknown domain update operation status.") .Build()), diff --git a/src/Umbraco.Core/Services/DomainService.cs b/src/Umbraco.Core/Services/DomainService.cs index b4e103f1a4b0..c527e40b8240 100644 --- a/src/Umbraco.Core/Services/DomainService.cs +++ b/src/Umbraco.Core/Services/DomainService.cs @@ -6,6 +6,7 @@ using Umbraco.Cms.Core.Models.ContentEditing; using Umbraco.Cms.Core.Notifications; using Umbraco.Cms.Core.Persistence.Repositories; +using Umbraco.Cms.Core.Routing; using Umbraco.Cms.Core.Scoping; using Umbraco.Cms.Core.Services.OperationStatus; using Umbraco.Extensions; @@ -201,6 +202,11 @@ public async Task> UpdateDoma foreach (DomainModel domainModel in updateModel.Domains) { domainModel.DomainName = domainModel.DomainName.ToLowerInvariant(); + + if(Uri.IsWellFormedUriString(domainModel.DomainName, UriKind.RelativeOrAbsolute) is false) + { + return Attempt.FailWithStatus(DomainOperationStatus.InvalidDomainName, new DomainUpdateResult()); + } } // make sure we're not attempting to assign duplicate domains diff --git a/src/Umbraco.Core/Services/OperationStatus/DomainOperationStatus.cs b/src/Umbraco.Core/Services/OperationStatus/DomainOperationStatus.cs index a752684b2eb8..ba19e2bc3fa9 100644 --- a/src/Umbraco.Core/Services/OperationStatus/DomainOperationStatus.cs +++ b/src/Umbraco.Core/Services/OperationStatus/DomainOperationStatus.cs @@ -7,5 +7,6 @@ public enum DomainOperationStatus ContentNotFound, LanguageNotFound, DuplicateDomainName, - ConflictingDomainName + ConflictingDomainName, + InvalidDomainName } diff --git a/tests/Umbraco.Tests.Integration/Umbraco.Web.BackOffice/UrlAndDomains/DomainAndUrlsTests.cs b/tests/Umbraco.Tests.Integration/Umbraco.Web.BackOffice/UrlAndDomains/DomainAndUrlsTests.cs index abc4e3894c72..462205b2318f 100644 --- a/tests/Umbraco.Tests.Integration/Umbraco.Web.BackOffice/UrlAndDomains/DomainAndUrlsTests.cs +++ b/tests/Umbraco.Tests.Integration/Umbraco.Web.BackOffice/UrlAndDomains/DomainAndUrlsTests.cs @@ -332,6 +332,22 @@ public async Task Cannot_Assign_Duplicate_Domains(string domainName) Assert.AreEqual(DomainOperationStatus.DuplicateDomainName, result.Status); } + [TestCase("https://*.umbraco.com")] + [TestCase("&#€%#€")] + [TestCase("¢”$¢”¢$≈{")] + public async Task Cannot_Assign_Invalid_Domains(string domainName) + { + var domainService = GetRequiredService(); + var updateModel = new DomainsUpdateModel + { + Domains = new DomainModel { DomainName = domainName, IsoCode = Cultures.First() }.Yield() + }; + + var result = await domainService.UpdateDomainsAsync(Root.Key, updateModel); + Assert.IsFalse(result.Success); + Assert.AreEqual(DomainOperationStatus.InvalidDomainName, result.Status); + } + [Test] public async Task Cannot_Assign_Already_Used_Domains() {