From 8990a8fcb05c505adf3b26a8156bb6361d8eaa75 Mon Sep 17 00:00:00 2001 From: Kenn Jacobsen Date: Sat, 1 Dec 2018 09:26:55 +0100 Subject: [PATCH 01/17] Remove the Umbraco core jQuery dependency for macro partials --- .../PartialViewMacros/Templates/EditProfile.cshtml | 6 +++--- .../Umbraco/PartialViewMacros/Templates/Login.cshtml | 6 +++--- .../PartialViewMacros/Templates/LoginStatus.cshtml | 11 ----------- .../PartialViewMacros/Templates/RegisterMember.cshtml | 6 +++--- 4 files changed, 9 insertions(+), 20 deletions(-) diff --git a/src/Umbraco.Web.UI/Umbraco/PartialViewMacros/Templates/EditProfile.cshtml b/src/Umbraco.Web.UI/Umbraco/PartialViewMacros/Templates/EditProfile.cshtml index d74b090c07..79c83a883d 100644 --- a/src/Umbraco.Web.UI/Umbraco/PartialViewMacros/Templates/EditProfile.cshtml +++ b/src/Umbraco.Web.UI/Umbraco/PartialViewMacros/Templates/EditProfile.cshtml @@ -9,9 +9,9 @@ Html.EnableClientValidation(); Html.EnableUnobtrusiveJavaScript(); - Html.RequiresJs("/umbraco/lib/jquery/jquery.min.js"); - Html.RequiresJs("/umbraco/lib/jquery-validate/jquery.validate.min.js"); - Html.RequiresJs("/umbraco/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js"); + Html.RequiresJs("https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"); + Html.RequiresJs("https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.19.0/jquery.validate.min.js"); + Html.RequiresJs("https://cdnjs.cloudflare.com/ajax/libs/jquery-validation-unobtrusive/3.2.11/jquery.validate.unobtrusive.min.js"); var success = TempData["ProfileUpdateSuccess"] != null; } diff --git a/src/Umbraco.Web.UI/Umbraco/PartialViewMacros/Templates/Login.cshtml b/src/Umbraco.Web.UI/Umbraco/PartialViewMacros/Templates/Login.cshtml index 7c5ed032f7..31a3bd604d 100644 --- a/src/Umbraco.Web.UI/Umbraco/PartialViewMacros/Templates/Login.cshtml +++ b/src/Umbraco.Web.UI/Umbraco/PartialViewMacros/Templates/Login.cshtml @@ -10,9 +10,9 @@ Html.EnableClientValidation(); Html.EnableUnobtrusiveJavaScript(); - Html.RequiresJs("/umbraco/lib/jquery/jquery.min.js"); - Html.RequiresJs("/umbraco/lib/jquery-validate/jquery.validate.min.js"); - Html.RequiresJs("/umbraco/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js"); + Html.RequiresJs("https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"); + Html.RequiresJs("https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.19.0/jquery.validate.min.js"); + Html.RequiresJs("https://cdnjs.cloudflare.com/ajax/libs/jquery-validation-unobtrusive/3.2.11/jquery.validate.unobtrusive.min.js"); } @* NOTE: This RenderJsHere code should be put on your main template page where the rest of your script tags are placed *@ diff --git a/src/Umbraco.Web.UI/Umbraco/PartialViewMacros/Templates/LoginStatus.cshtml b/src/Umbraco.Web.UI/Umbraco/PartialViewMacros/Templates/LoginStatus.cshtml index 4fa4bff173..8eadbb342f 100644 --- a/src/Umbraco.Web.UI/Umbraco/PartialViewMacros/Templates/LoginStatus.cshtml +++ b/src/Umbraco.Web.UI/Umbraco/PartialViewMacros/Templates/LoginStatus.cshtml @@ -1,5 +1,4 @@ @using System.Web.Mvc.Html -@using ClientDependency.Core.Mvc @using Umbraco.Web @using Umbraco.Web.Models @using Umbraco.Web.Controllers @@ -7,13 +6,6 @@ @{ var loginStatusModel = Members.GetCurrentLoginStatus(); - - Html.EnableClientValidation(); - Html.EnableUnobtrusiveJavaScript(); - Html.RequiresJs("/umbraco/lib/jquery/jquery.min.js"); - Html.RequiresJs("/umbraco/lib/jquery-validate/jquery.validate.min.js"); - Html.RequiresJs("/umbraco/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js"); - var logoutModel = new PostRedirectModel(); @* @@ -24,9 +16,6 @@ *@ } -@* NOTE: This RenderJsHere code should be put on your main template page where the rest of your script tags are placed *@ -@Html.RenderJsHere() - @if (loginStatusModel.IsLoggedIn) {

You are currently logged in as @loginStatusModel.Name

diff --git a/src/Umbraco.Web.UI/Umbraco/PartialViewMacros/Templates/RegisterMember.cshtml b/src/Umbraco.Web.UI/Umbraco/PartialViewMacros/Templates/RegisterMember.cshtml index b448a992d9..b9fbea4733 100644 --- a/src/Umbraco.Web.UI/Umbraco/PartialViewMacros/Templates/RegisterMember.cshtml +++ b/src/Umbraco.Web.UI/Umbraco/PartialViewMacros/Templates/RegisterMember.cshtml @@ -33,9 +33,9 @@ Html.EnableClientValidation(); Html.EnableUnobtrusiveJavaScript(); - Html.RequiresJs("/umbraco/lib/jquery/jquery.min.js"); - Html.RequiresJs("/umbraco/lib/jquery-validate/jquery.validate.min.js"); - Html.RequiresJs("/umbraco/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js"); + Html.RequiresJs("https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"); + Html.RequiresJs("https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.19.0/jquery.validate.min.js"); + Html.RequiresJs("https://cdnjs.cloudflare.com/ajax/libs/jquery-validation-unobtrusive/3.2.11/jquery.validate.unobtrusive.min.js"); var success = TempData["FormSuccess"] != null; } From d7696e8d91761b586d915b440d0baf00bcbc2377 Mon Sep 17 00:00:00 2001 From: elitsa Date: Tue, 18 Dec 2018 11:34:50 +0100 Subject: [PATCH 02/17] Making a variable const --- src/Umbraco.Core/StringExtensions.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Core/StringExtensions.cs b/src/Umbraco.Core/StringExtensions.cs index d4ad152feb..abe5ae7188 100644 --- a/src/Umbraco.Core/StringExtensions.cs +++ b/src/Umbraco.Core/StringExtensions.cs @@ -540,7 +540,7 @@ namespace Umbraco.Core /// Returns the string without any html tags. public static string StripHtml(this string text) { - string pattern = "[*{}\\/:<>?|\"-+()\\n]"; + const string pattern = "[*{}\\/:<>?|\"-+()\\n]"; return Regex.Replace(text, pattern, String.Empty); } From bb60d5e03508d2cd40491178bd5dc013a81a3173 Mon Sep 17 00:00:00 2001 From: elitsa Date: Thu, 27 Dec 2018 09:57:31 +0100 Subject: [PATCH 03/17] Reverting changes made from merge. --- src/Umbraco.Web/UI/LegacyDialogHandler.cs | 2 +- src/Umbraco.Web/WebServices/SaveFileController.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web/UI/LegacyDialogHandler.cs b/src/Umbraco.Web/UI/LegacyDialogHandler.cs index efcea4bbd5..a3dc6750e9 100644 --- a/src/Umbraco.Web/UI/LegacyDialogHandler.cs +++ b/src/Umbraco.Web/UI/LegacyDialogHandler.cs @@ -207,7 +207,7 @@ namespace Umbraco.Web.UI typeInstance.TypeID = typeId; typeInstance.ParentID = nodeId; - typeInstance.Alias = text; + typeInstance.Alias = text.CleanForXss(); // check for returning url ITaskReturnUrl returnUrlTask = typeInstance as LegacyDialogTask; diff --git a/src/Umbraco.Web/WebServices/SaveFileController.cs b/src/Umbraco.Web/WebServices/SaveFileController.cs index 5f2fcaeb34..359ee6fc31 100644 --- a/src/Umbraco.Web/WebServices/SaveFileController.cs +++ b/src/Umbraco.Web/WebServices/SaveFileController.cs @@ -243,7 +243,7 @@ namespace Umbraco.Web.WebServices // sanitize input - stylesheet names have no extension var svce = (FileService)Services.FileService; - filename = CleanFilename(filename); + filename = CleanFilename(filename.CleanForXss()); oldName = CleanFilename(oldName); if (filename != oldName) From 0aa1dc1dc710f06a0cccb7aa5a0724af8e0f563e Mon Sep 17 00:00:00 2001 From: elitsa Date: Thu, 27 Dec 2018 10:02:49 +0100 Subject: [PATCH 04/17] Adding tests for verifying that malicious code input will be cleaned for XSS. --- src/Umbraco.Tests/Strings/StringExtensionsTests.cs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/Umbraco.Tests/Strings/StringExtensionsTests.cs b/src/Umbraco.Tests/Strings/StringExtensionsTests.cs index 836930c48a..bbf78f09fc 100644 --- a/src/Umbraco.Tests/Strings/StringExtensionsTests.cs +++ b/src/Umbraco.Tests/Strings/StringExtensionsTests.cs @@ -61,6 +61,17 @@ namespace Umbraco.Tests.Strings Assert.AreEqual(stripped, result); } + [TestCase("'+alert(1234)+'", "alert1234")] + [TestCase("'+alert(56+78)+'", "alert5678")] + [TestCase("{{file}}", "file")] + [TestCase("'+alert('hello')+'", "alerthello")] + [TestCase("Test", "Test")] + public void Clean_From_XSS(string input, string result) + { + var cleaned = input.CleanForXss(); + Assert.AreEqual(cleaned, result); + } + [TestCase("This is a string to encrypt")] [TestCase("This is a string to encrypt\nThis is a second line")] [TestCase(" White space is preserved ")] From b2a1b11a5b6e230dd0d5a235de3f620f766120f9 Mon Sep 17 00:00:00 2001 From: Brian Juul Andersen Date: Sat, 29 Dec 2018 05:58:45 +0100 Subject: [PATCH 05/17] Fixed minor grammatical error --- .github/CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 6caeadd0e5..9dc6f9457f 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -16,7 +16,7 @@ This document gives you a quick overview on how to get started, we will link to ## Guidelines for contributions we welcome -Not all changes are wanted, so on occassion we might close a PR without merging it. We will give you feedback why we can't accept your changes and we'll be nice about it, thanking you for spending your valueable time. +Not all changes are wanted, so on occassion we might close a PR without merging it. We will give you feedback why we can't accept your changes and we'll be nice about it, thanking you for spending your valuable time. We have [documented what we consider small and large changes](CONTRIBUTION_GUIDELINES.md). Make sure to talk to us before making large changes. From debbf87a047ee89902b8e938ddfdacf61d86714e Mon Sep 17 00:00:00 2001 From: Kenn Jacobsen Date: Mon, 31 Dec 2018 12:50:27 +0100 Subject: [PATCH 06/17] Support image crop data set when overwriting files using the API --- src/Umbraco.Core/IO/MediaFileSystem.cs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Core/IO/MediaFileSystem.cs b/src/Umbraco.Core/IO/MediaFileSystem.cs index 37fcdeba70..39cd7ba7ad 100644 --- a/src/Umbraco.Core/IO/MediaFileSystem.cs +++ b/src/Umbraco.Core/IO/MediaFileSystem.cs @@ -1,4 +1,6 @@ -using System; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using System; using System.Collections.Generic; using System.Drawing; using System.Drawing.Drawing2D; @@ -293,6 +295,12 @@ namespace Umbraco.Core.IO { var property = GetProperty(content, propertyTypeAlias); var svalue = property.Value as string; + if (svalue != null && svalue.DetectIsJson()) + { + // the property value is a JSON serialized image crop data set - grab the "src" property as the file source + var jObject = JsonConvert.DeserializeObject(svalue); + svalue = jObject != null ? jObject.GetValueAsString("src") : svalue; + } var oldpath = svalue == null ? null : GetRelativePath(svalue); var filepath = StoreFile(content, property.PropertyType, filename, filestream, oldpath); property.Value = GetUrl(filepath); From b852c78861fe50c45a39126d1e881f11e35189fe Mon Sep 17 00:00:00 2001 From: Callum Whyte Date: Fri, 21 Dec 2018 22:17:47 +0000 Subject: [PATCH 07/17] Fixing spelling mistakes in helveticons CSS class names The icon picker uses these class names as labels, kept the old class names for backwards compatibility --- src/Umbraco.Web.UI.Client/src/less/helveticons.less | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/less/helveticons.less b/src/Umbraco.Web.UI.Client/src/less/helveticons.less index 9a317e09fb..fab9614c7e 100644 --- a/src/Umbraco.Web.UI.Client/src/less/helveticons.less +++ b/src/Umbraco.Web.UI.Client/src/less/helveticons.less @@ -17,12 +17,14 @@ -webkit-font-smoothing: antialiased; *margin-right: .3em; } + [class^="icon-"]:before, [class*=" icon-"]:before { text-decoration: inherit; display: inline-block; speak: none; } + /* [class^="icon-"]:before, [class*=" icon-"]:before { font-family: 'icomoon'; @@ -38,7 +40,6 @@ i.large{ font-size: 32px; } - i.medium{ font-size: 24px; } @@ -187,8 +188,6 @@ i.small{ .icon-umb-translation:before, .traytranslation:before { content: "\e1fd"; } - - .icon-tv:before { content: "\e02e"; } @@ -213,7 +212,8 @@ i.small{ .icon-train:before { content: "\e035"; } -.icon-trafic:before { +.icon-trafic:before, +.icon-traffic:before { content: "\e036"; } .icon-traffic-alt:before { @@ -255,6 +255,7 @@ i.small{ .icon-target:before { content: "\e043"; } +.icon-temperature-alt:before, .icon-temperatrure-alt:before { content: "\e044"; } @@ -267,6 +268,7 @@ i.small{ .icon-theater:before { content: "\e047"; } +.icon-thief:before, .icon-theif:before { content: "\e048"; } @@ -375,6 +377,7 @@ i.small{ .icon-shuffle:before { content: "\e06b"; } +.icon-science:before, .icon-sience:before { content: "\e06c"; } @@ -747,6 +750,7 @@ i.small{ .icon-pictures-alt-2:before { content: "\e0e7"; } +.icon-panel-close:before, .icon-pannel-close:before { content: "\e0e8"; } @@ -1627,6 +1631,7 @@ i.small{ .icon-alarm-clock:before { content: "\e20c"; } +.icon-addressbook:before, .icon-adressbook:before { content: "\e20d"; } From 0ce54847b046d0e1c55e276418ffebef5c7e550e Mon Sep 17 00:00:00 2001 From: Dave Woestenborghs Date: Thu, 20 Dec 2018 16:21:15 +0100 Subject: [PATCH 08/17] #3916 mapping to a IEnumerable resulted in all items in the result list being the same. Now map items indiviually. Could be caused by this : https://stackoverflow.com/questions/17268362/automapper-for-a-list-scenario-only-seems-to-repeat-mapping-the-first-object-in --- src/Umbraco.Web/Editors/LogController.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web/Editors/LogController.cs b/src/Umbraco.Web/Editors/LogController.cs index 04e34e91e0..444729b252 100644 --- a/src/Umbraco.Web/Editors/LogController.cs +++ b/src/Umbraco.Web/Editors/LogController.cs @@ -27,7 +27,7 @@ namespace Umbraco.Web.Editors long totalRecords; var dateQuery = sinceDate.HasValue ? Query.Builder.Where(x => x.CreateDate >= sinceDate) : null; var result = Services.AuditService.GetPagedItemsByEntity(id, pageNumber - 1, pageSize, out totalRecords, orderDirection, customFilter: dateQuery); - var mapped = Mapper.Map>(result); + var mapped = result.Select(item => Mapper.Map(item)); // Mapper.Map>(result); var page = new PagedResult(totalRecords, pageNumber, pageSize) { From ee8b4c58847b2363db1fae90c5dc499664e2725d Mon Sep 17 00:00:00 2001 From: Dave Woestenborghs Date: Thu, 20 Dec 2018 16:28:24 +0100 Subject: [PATCH 09/17] #3916 fix multiple enumerations of ienumerable...so usernames and avatars are displayed correctly --- src/Umbraco.Web/Editors/LogController.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Web/Editors/LogController.cs b/src/Umbraco.Web/Editors/LogController.cs index 444729b252..b02d49209e 100644 --- a/src/Umbraco.Web/Editors/LogController.cs +++ b/src/Umbraco.Web/Editors/LogController.cs @@ -85,16 +85,17 @@ namespace Umbraco.Web.Editors private IEnumerable MapAvatarsAndNames(IEnumerable items) { - var userIds = items.Select(x => x.UserId).ToArray(); + var mappedItems = items.ToList(); + var userIds = mappedItems.Select(x => x.UserId).ToArray(); var users = Services.UserService.GetUsersById(userIds) .ToDictionary(x => x.Id, x => x.GetUserAvatarUrls(ApplicationContext.ApplicationCache.RuntimeCache)); var userNames = Services.UserService.GetUsersById(userIds).ToDictionary(x => x.Id, x => x.Name); - foreach (var item in items) + foreach (var item in mappedItems) { item.UserAvatars = users[item.UserId]; item.UserName = userNames[item.UserId]; } - return items; + return mappedItems; } } } From 5e680e80e6b766f02922a30fcb9f7294d7866e61 Mon Sep 17 00:00:00 2001 From: Sebastiaan Janssen Date: Mon, 31 Dec 2018 13:48:34 +0100 Subject: [PATCH 10/17] Deletes commented out code --- src/Umbraco.Web/Editors/LogController.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web/Editors/LogController.cs b/src/Umbraco.Web/Editors/LogController.cs index b02d49209e..c54bd989d4 100644 --- a/src/Umbraco.Web/Editors/LogController.cs +++ b/src/Umbraco.Web/Editors/LogController.cs @@ -27,7 +27,7 @@ namespace Umbraco.Web.Editors long totalRecords; var dateQuery = sinceDate.HasValue ? Query.Builder.Where(x => x.CreateDate >= sinceDate) : null; var result = Services.AuditService.GetPagedItemsByEntity(id, pageNumber - 1, pageSize, out totalRecords, orderDirection, customFilter: dateQuery); - var mapped = result.Select(item => Mapper.Map(item)); // Mapper.Map>(result); + var mapped = result.Select(item => Mapper.Map(item)); var page = new PagedResult(totalRecords, pageNumber, pageSize) { From af2f531d315b5d82ae18bce5bc3b823290da83c3 Mon Sep 17 00:00:00 2001 From: Kenn Jacobsen Date: Mon, 31 Dec 2018 14:37:58 +0100 Subject: [PATCH 11/17] Add missing localization of dialogs (#3844) --- .../src/views/content/content.notify.controller.js | 9 +++++++-- .../src/views/content/copy.html | 7 +++++-- .../src/views/content/move.html | 4 +++- .../src/views/content/notify.html | 4 ++-- src/Umbraco.Web.UI.Client/src/views/media/move.html | 4 +++- src/Umbraco.Web.UI/umbraco/config/lang/da.xml | 9 +++++++-- src/Umbraco.Web.UI/umbraco/config/lang/en.xml | 9 +++++++-- src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml | 13 +++++++------ src/Umbraco.Web.UI/umbraco/dialogs/rollBack.aspx | 2 +- .../umbraco/dialogs/rollBack.aspx.cs | 5 +++++ 10 files changed, 47 insertions(+), 19 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/content/content.notify.controller.js b/src/Umbraco.Web.UI.Client/src/views/content/content.notify.controller.js index c5b2781dd4..04a3a76027 100644 --- a/src/Umbraco.Web.UI.Client/src/views/content/content.notify.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/content/content.notify.controller.js @@ -3,7 +3,8 @@ $scope, contentResource, navigationService, - angularHelper) { + angularHelper, + localizationService) { var vm = this; var currentForm; vm.notifyOptions = []; @@ -11,7 +12,8 @@ vm.cancel = cancel; vm.message = { name: $scope.currentNode.name - };; + }; + vm.labels = {}; function onInit() { vm.loading = true; contentResource.getNotifySettingsById($scope.currentNode.id).then(function (options) { @@ -19,6 +21,9 @@ vm.loading = false; vm.notifyOptions = options; }); + localizationService.localize("notifications_editNotifications", [$scope.currentNode.name]).then(function(value) { + vm.labels.headline = value; + }); } function cancel() { navigationService.hideMenu(); diff --git a/src/Umbraco.Web.UI.Client/src/views/content/copy.html b/src/Umbraco.Web.UI.Client/src/views/content/copy.html index 62116a3e6e..963a0e5df2 100644 --- a/src/Umbraco.Web.UI.Client/src/views/content/copy.html +++ b/src/Umbraco.Web.UI.Client/src/views/content/copy.html @@ -11,14 +11,17 @@
- {{currentNode.name}} was copied to + {{currentNode.name}} + was copied to {{target.name}}

- Choose where to copy {{currentNode.name}} to in the tree structure below + Choose where to copy + {{currentNode.name}} + to in the tree structure below

diff --git a/src/Umbraco.Web.UI.Client/src/views/content/move.html b/src/Umbraco.Web.UI.Client/src/views/content/move.html index 09116a2a6d..fa6dee2ba9 100644 --- a/src/Umbraco.Web.UI.Client/src/views/content/move.html +++ b/src/Umbraco.Web.UI.Client/src/views/content/move.html @@ -11,7 +11,9 @@
- {{currentNode.name}} was moved underneath {{target.name}} + {{currentNode.name}} + was moved to + {{target.name}}
diff --git a/src/Umbraco.Web.UI.Client/src/views/content/notify.html b/src/Umbraco.Web.UI.Client/src/views/content/notify.html index e7c4d4d785..8e2f860661 100644 --- a/src/Umbraco.Web.UI.Client/src/views/content/notify.html +++ b/src/Umbraco.Web.UI.Client/src/views/content/notify.html @@ -13,13 +13,13 @@
- {{currentNode.name}} + {{currentNode.name}}
- Set your notification for {{ currentNode.name }} +
- {{currentNode.name}} was moved underneath {{target.name}} + {{currentNode.name}} + was moved to + {{target.name}}
diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/da.xml b/src/Umbraco.Web.UI/umbraco/config/lang/da.xml index 4f61bf3ee4..658dd091f6 100644 --- a/src/Umbraco.Web.UI/umbraco/config/lang/da.xml +++ b/src/Umbraco.Web.UI/umbraco/config/lang/da.xml @@ -32,8 +32,11 @@ Omdøb Gendan Sæt rettigheder for siden %0% + Vælg hvor du vil kopiere Vælg hvortil du vil flytte - I træstrukturen nedenfor + til i træstrukturen nedenfor + blev flyttet til + blev kopieret til Rettigheder Fortryd ændringer Send til udgivelse @@ -830,7 +833,8 @@ Relater det kopierede element til originalen - Rediger dine notificeringer for %0% + %0%]]> + Notificeringer er gemt for + Vælg en version at sammenligne med den nuværende version Nuværende version Rød tekst vil ikke blive vist i den valgte version. Grøn betyder tilføjet]]> Dokument tilbagerullet diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/en.xml b/src/Umbraco.Web.UI/umbraco/config/lang/en.xml index 76cf013b40..cd5f32da0d 100644 --- a/src/Umbraco.Web.UI/umbraco/config/lang/en.xml +++ b/src/Umbraco.Web.UI/umbraco/config/lang/en.xml @@ -33,8 +33,11 @@ Rename Restore Set permissions for the page %0% + Choose where to copy Choose where to move - In the tree structure below + to in the tree structure below + was moved to + was copied to Permissions Rollback Send To Publish @@ -1038,7 +1041,8 @@ To manage your website, simply open the Umbraco back office and start adding con Relate copied items to original - Edit your notification for %0% + %0%]]> + Notification settings saved for Undo edits + Select a version to compare with the current version Current version Red text will not be shown in the selected version. , green means added]]> Document has been rolled back diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml b/src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml index 47fef59019..88b736a34f 100644 --- a/src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml +++ b/src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml @@ -33,8 +33,11 @@ Rename Restore Set permissions for the page %0% + Choose where to copy Choose where to move - In the tree structure below + to in the tree structure below + was moved to + was copied to Permissions Rollback Send To Publish @@ -1037,7 +1040,8 @@ To manage your website, simply open the Umbraco back office and start adding con Relate copied items to original - Edit your notification for %0% + %0%]]> + Notification settings saved for Undo edits + Select a version to compare with the current version Current version Red text will not be shown in the selected version. , green means added]]> Document has been rolled back @@ -2220,8 +2225,4 @@ To manage your website, simply open the Umbraco back office and start adding con There is no location where this item can be automatically restored. You can move the item manually using the tree below. was restored under - - Select your notifications for - Notification settings saved for - diff --git a/src/Umbraco.Web.UI/umbraco/dialogs/rollBack.aspx b/src/Umbraco.Web.UI/umbraco/dialogs/rollBack.aspx index f596121627..144a840ca5 100644 --- a/src/Umbraco.Web.UI/umbraco/dialogs/rollBack.aspx +++ b/src/Umbraco.Web.UI/umbraco/dialogs/rollBack.aspx @@ -55,7 +55,7 @@
diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/rollBack.aspx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/rollBack.aspx.cs index f6390a9d0b..543c3f8b23 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/rollBack.aspx.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/rollBack.aspx.cs @@ -116,6 +116,11 @@ namespace umbraco.presentation.dialogs currentVersionTitle.Text = currentDoc.Text; currentVersionMeta.Text = ui.Text("content", "createDate") + ": " + currentDoc.VersionDate.ToShortDateString() + " " + currentDoc.VersionDate.ToShortTimeString(); + pp_selectVersion.Text = ui.Text("rollback", "headline"); + pp_currentVersion.Text = ui.Text("rollback", "currentVersion"); + pp_view.Text = ui.Text("rollback", "view"); + pp_rollBackTo.Text = ui.Text("rollback", "rollbackTo"); + if (!IsPostBack) { allVersions.Items.Add(new ListItem(ui.Text("rollback", "selectVersion")+ "...", "")); From 0150b972780cfa39cce58003a92f0f5b9909fb10 Mon Sep 17 00:00:00 2001 From: Kenn Jacobsen Date: Mon, 31 Dec 2018 15:02:59 +0100 Subject: [PATCH 12/17] Show password change validation errors at the correct fields (#3918) * Show password change validation errors at the correct password fields + remove the redundant "Could not reset password, errors: " message text * Explicitly find the user instead of mapping it. --- src/Umbraco.Web/Editors/PasswordChanger.cs | 37 ++++++++++++++-------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/src/Umbraco.Web/Editors/PasswordChanger.cs b/src/Umbraco.Web/Editors/PasswordChanger.cs index 7be14d27d1..266af76454 100644 --- a/src/Umbraco.Web/Editors/PasswordChanger.cs +++ b/src/Umbraco.Web/Editors/PasswordChanger.cs @@ -100,7 +100,7 @@ namespace Umbraco.Web.Editors { var errors = string.Join(". ", resetResult.Errors); _logger.Warn(string.Format("Could not reset user password {0}", errors)); - return Attempt.Fail(new PasswordChangedModel { ChangeError = new ValidationResult("Could not reset password, errors: " + errors, new[] { "resetPassword" }) }); + return Attempt.Fail(new PasswordChangedModel { ChangeError = new ValidationResult(errors, new[] { "resetPassword" }) }); } return Attempt.Succeed(new PasswordChangedModel()); @@ -120,21 +120,30 @@ namespace Umbraco.Web.Editors return Attempt.Fail(new PasswordChangedModel { ChangeError = new ValidationResult("Password cannot be changed without the old password", new[] { "oldPassword" }) }); } - if (passwordModel.OldPassword.IsNullOrWhiteSpace() == false) + //get the user + var backOfficeIdentityUser = await userMgr.FindByIdAsync(savingUser.Id); + if (backOfficeIdentityUser == null) { - //if an old password is suplied try to change it - var changeResult = await userMgr.ChangePasswordAsync(savingUser.Id, passwordModel.OldPassword, passwordModel.NewPassword); - if (changeResult.Succeeded == false) - { - var errors = string.Join(". ", changeResult.Errors); - _logger.Warn(string.Format("Could not change user password {0}", errors)); - return Attempt.Fail(new PasswordChangedModel { ChangeError = new ValidationResult("Could not change password, errors: " + errors, new[] { "oldPassword" }) }); - } - return Attempt.Succeed(new PasswordChangedModel()); + //this really shouldn't ever happen... but just in case + return Attempt.Fail(new PasswordChangedModel { ChangeError = new ValidationResult("Password could not be verified", new[] { "oldPassword" }) }); } - - //We shouldn't really get here - return Attempt.Fail(new PasswordChangedModel { ChangeError = new ValidationResult("Could not change password, invalid information supplied", new[] { "value" }) }); + //is the old password correct? + var validateResult = await userMgr.CheckPasswordAsync(backOfficeIdentityUser, passwordModel.OldPassword); + if(validateResult == false) + { + //no, fail with an error message for "oldPassword" + return Attempt.Fail(new PasswordChangedModel { ChangeError = new ValidationResult("Incorrect password", new[] { "oldPassword" }) }); + } + //can we change to the new password? + var changeResult = await userMgr.ChangePasswordAsync(savingUser.Id, passwordModel.OldPassword, passwordModel.NewPassword); + if (changeResult.Succeeded == false) + { + //no, fail with error messages for "password" + var errors = string.Join(". ", changeResult.Errors); + _logger.Warn(string.Format("Could not change user password {0}", errors)); + return Attempt.Fail(new PasswordChangedModel { ChangeError = new ValidationResult(errors, new[] { "password" }) }); + } + return Attempt.Succeed(new PasswordChangedModel()); } /// From 2dfbb1d555ef717ca3bcfb76ff8c843933f8fd17 Mon Sep 17 00:00:00 2001 From: Kenn Jacobsen Date: Wed, 2 Jan 2019 20:57:18 +0100 Subject: [PATCH 13/17] Don't attempt to apply a filter if none is submitted --- src/Umbraco.Web/Editors/EntityController.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web/Editors/EntityController.cs b/src/Umbraco.Web/Editors/EntityController.cs index 5e73f4140e..993489855f 100644 --- a/src/Umbraco.Web/Editors/EntityController.cs +++ b/src/Umbraco.Web/Editors/EntityController.cs @@ -479,7 +479,9 @@ namespace Umbraco.Web.Editors if (objectType.HasValue) { var entities = Services.EntityService.GetPagedChildren(id, objectType.Value, pageNumber - 1, pageSize, out var totalRecords, - SqlContext.Query().Where(x => x.Name.Contains(filter)), + filter.IsNullOrWhiteSpace() + ? null + : SqlContext.Query().Where(x => x.Name.Contains(filter)), Ordering.By(orderBy, orderDirection)); if (totalRecords == 0) From 525b229b42edf44d4fdff834354721ca5e840d6a Mon Sep 17 00:00:00 2001 From: Kenn Jacobsen Date: Wed, 2 Jan 2019 15:20:25 +0100 Subject: [PATCH 14/17] Fix content creation from list views --- .../listview/listview.controller.js | 23 +++++++++++++------ .../propertyeditors/listview/listview.html | 16 ++++++------- 2 files changed, 24 insertions(+), 15 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.controller.js index 1d8cdfa03f..96e7ccdbfd 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.controller.js @@ -701,16 +701,23 @@ function listViewController($scope, $routeParams, $injector, $timeout, currentUs } getContentTypesCallback(id).then(function (listViewAllowedTypes) { - $scope.listViewAllowedTypes = listViewAllowedTypes; + $scope.listViewAllowedTypes = listViewAllowedTypes; var blueprints = false; _.each(listViewAllowedTypes, function (allowedType) { if (_.isEmpty(allowedType.blueprints)) { - // this helps the view understand that there are no blueprints available - allowedType.blueprints = null; + // this helps the view understand that there are no blueprints available + allowedType.blueprints = null; } else { - blueprints = true; + blueprints = true; + // turn the content type blueprints object into an array of sortable objects for the view + allowedType.blueprints = _.map(_.pairs(allowedType.blueprints || {}), function (pair) { + return { + id: pair[0], + name: pair[1] + }; + }); } }); @@ -776,17 +783,19 @@ function listViewController($scope, $routeParams, $injector, $timeout, currentUs } } - function createBlank(entityType, docTypeAlias) { $location .path("/" + entityType + "/" + entityType + "/edit/" + $scope.contentId) - .search("doctype=" + docTypeAlias + "&create=true"); + .search("doctype", docTypeAlias) + .search("create", "true"); } function createFromBlueprint(entityType, docTypeAlias, blueprintId) { $location .path("/" + entityType + "/" + entityType + "/edit/" + $scope.contentId) - .search("doctype=" + docTypeAlias + "&create=true&blueprintId=" + blueprintId); + .search("doctype", docTypeAlias) + .search("create", "true") + .search("blueprintId", blueprintId); } $scope.createBlank = createBlank; diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.html index 44636d7033..77576cac6a 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.html @@ -27,10 +27,10 @@ - - + + - {{::value}} + {{::blueprint.name}} @@ -48,9 +48,9 @@ {{::contentType.name}} (blank) - +    - {{::value}} + {{::blueprint.name}} @@ -58,11 +58,11 @@
    -
  • - +
  • + - {{value}} + {{blueprint.name}}
  • From 4b60d8bca614ac9a0f8466e84023cdd09810cc90 Mon Sep 17 00:00:00 2001 From: Kenn Jacobsen Date: Wed, 2 Jan 2019 14:58:18 +0100 Subject: [PATCH 15/17] Fix the content template selector in the content tree --- .../src/views/content/content.create.controller.js | 13 ++++++++++--- .../src/views/content/create.html | 8 ++++---- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/content/content.create.controller.js b/src/Umbraco.Web.UI.Client/src/views/content/content.create.controller.js index 6b1021b663..9fbf342435 100644 --- a/src/Umbraco.Web.UI.Client/src/views/content/content.create.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/content/content.create.controller.js @@ -42,14 +42,21 @@ function contentCreateController($scope, } function createOrSelectBlueprintIfAny(docType) { - var blueprintIds = _.keys(docType.blueprints || {}); + // map the blueprints into a collection that's sortable in the view + var blueprints = _.map(_.pairs(docType.blueprints || {}), function (pair) { + return { + id: pair[0], + name: pair[1] + }; + }); $scope.docType = docType; - if (blueprintIds.length) { + if (blueprints.length) { if (blueprintConfig.skipSelect) { - createFromBlueprint(blueprintIds[0]); + createFromBlueprint(blueprints[0].id); } else { $scope.selectContentType = false; $scope.selectBlueprint = true; + $scope.selectableBlueprints = blueprints; } } else { createBlank(docType); diff --git a/src/Umbraco.Web.UI.Client/src/views/content/create.html b/src/Umbraco.Web.UI.Client/src/views/content/create.html index e76d17caa8..94299f6a54 100644 --- a/src/Umbraco.Web.UI.Client/src/views/content/create.html +++ b/src/Umbraco.Web.UI.Client/src/views/content/create.html @@ -25,13 +25,13 @@
-
    +
      -
    • - +
    • + - {{value}} + {{blueprint.name}}
    • From 7ead62730b9c254048af3e521c2d0908f0548fed Mon Sep 17 00:00:00 2001 From: Claus Date: Fri, 4 Jan 2019 09:34:24 +0100 Subject: [PATCH 16/17] reverting changes to StripHtml method. --- src/Umbraco.Core/StringExtensions.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Core/StringExtensions.cs b/src/Umbraco.Core/StringExtensions.cs index abe5ae7188..93ff2aac50 100644 --- a/src/Umbraco.Core/StringExtensions.cs +++ b/src/Umbraco.Core/StringExtensions.cs @@ -540,8 +540,8 @@ namespace Umbraco.Core /// Returns the string without any html tags. public static string StripHtml(this string text) { - const string pattern = "[*{}\\/:<>?|\"-+()\\n]"; - return Regex.Replace(text, pattern, String.Empty); + const string pattern = @"<(.|\n)*?>"; + return Regex.Replace(text, pattern, string.Empty); } /// From 71f2b7ee068f741a649da3d0445ba89eaf515ef0 Mon Sep 17 00:00:00 2001 From: Claus Date: Fri, 4 Jan 2019 09:40:55 +0100 Subject: [PATCH 17/17] updating unit tests. --- src/Umbraco.Tests/Strings/StringExtensionsTests.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Tests/Strings/StringExtensionsTests.cs b/src/Umbraco.Tests/Strings/StringExtensionsTests.cs index bbf78f09fc..53f21b320b 100644 --- a/src/Umbraco.Tests/Strings/StringExtensionsTests.cs +++ b/src/Umbraco.Tests/Strings/StringExtensionsTests.cs @@ -61,10 +61,10 @@ namespace Umbraco.Tests.Strings Assert.AreEqual(stripped, result); } - [TestCase("'+alert(1234)+'", "alert1234")] - [TestCase("'+alert(56+78)+'", "alert5678")] + [TestCase("'+alert(1234)+'", "+alert1234+")] + [TestCase("'+alert(56+78)+'", "+alert56+78+")] [TestCase("{{file}}", "file")] - [TestCase("'+alert('hello')+'", "alerthello")] + [TestCase("'+alert('hello')+'", "+alerthello+")] [TestCase("Test", "Test")] public void Clean_From_XSS(string input, string result) {