Merge branch 'dev-v8' into temp8-U4-11219
This commit is contained in:
+1
-1
@@ -41,7 +41,7 @@ This project and everyone participating in it is governed by the [our Code of Co
|
||||
### Reporting Bugs
|
||||
This section guides you through submitting a bug report for Umbraco CMS. Following these guidelines helps maintainers and the community understand your report 📝, reproduce the behavior 💻 💻, and find related reports 🔎.
|
||||
|
||||
Before creating bug reports, please check [this list](#before-submitting-a-bug-report) as you might find out that you don't need to create one. When you are creating a bug report, please [include as many details as possible](#how-do-i-submit-a-good-bug-report). Fill out [the required template](ISSUE_TEMPLATE.md), the information it asks for helps us resolve issues faster.
|
||||
Before creating bug reports, please check [this list](#before-submitting-a-bug-report) as you might find out that you don't need to create one. When you are creating a bug report, please [include as many details as possible](#how-do-i-submit-a-good-bug-report). Fill out [the required template](http://issues.umbraco.org/issues#newissue=61-30118), the information it asks for helps us resolve issues faster.
|
||||
|
||||
> **Note:** If you find a **Closed** issue that seems like it is the same thing that you're experiencing, open a new issue and include a link to the original issue in the body of your new one.
|
||||
|
||||
|
||||
@@ -355,7 +355,7 @@ namespace Umbraco.Core.Scoping
|
||||
}
|
||||
|
||||
var parent = ParentScope;
|
||||
_scopeProvider.AmbientScope = parent;
|
||||
_scopeProvider.AmbientScope = parent; // might be null = this is how scopes are removed from context objects
|
||||
|
||||
#if DEBUG_SCOPES
|
||||
_scopeProvider.Disposed(this);
|
||||
|
||||
@@ -43,17 +43,17 @@ namespace Umbraco.Core.Services
|
||||
/// Creates a new content item from a blueprint.
|
||||
/// </summary>
|
||||
IContent CreateContentFromBlueprint(IContent blueprint, string name, int userId = 0);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Deletes blueprints for a content type.
|
||||
/// </summary>
|
||||
void DeleteBlueprintsOfType(int contentTypeId, int userId = 0);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Deletes blueprints for content types.
|
||||
/// </summary>
|
||||
void DeleteBlueprintsOfTypes(IEnumerable<int> contentTypeIds, int userId = 0);
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region Get, Count Documents
|
||||
@@ -340,7 +340,7 @@ namespace Umbraco.Core.Services
|
||||
/// Sorts documents.
|
||||
/// </summary>
|
||||
bool Sort(IEnumerable<int> ids, int userId = 0, bool raiseEvents = true);
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region Publish Document
|
||||
|
||||
@@ -59,8 +59,9 @@ namespace Umbraco.Core.Services
|
||||
_locker.EnterWriteLock();
|
||||
foreach (var pair in pairs)
|
||||
{
|
||||
_id2Key.Add(pair.id, new TypedId<Guid>(pair.key, umbracoObjectType));
|
||||
_key2Id.Add(pair.key, new TypedId<int>(pair.id, umbracoObjectType));
|
||||
|
||||
_id2Key[pair.id] = new TypedId<Guid>(pair.key, umbracoObjectType);
|
||||
_key2Id[pair.key] = new TypedId<int>(pair.id, umbracoObjectType);
|
||||
}
|
||||
}
|
||||
finally
|
||||
|
||||
+1
@@ -25,6 +25,7 @@ The tour object consist of two parts - The overall tour configuration and a list
|
||||
"group": "My Custom Group" // Used to group tours in the help drawer
|
||||
"groupOrder": 200 // Control the order of tour groups
|
||||
"allowDisable": // Adds a "Don't" show this tour again"-button to the intro step
|
||||
"culture" : // From v7.11+. Specifies the culture of the tour (eg. en-US), if set the tour will only be shown to users with this culture set on their profile. If omitted or left empty the tour will be visible to all users
|
||||
"requiredSections":["content", "media", "mySection"] // Sections that the tour will access while running, if the user does not have access to the required tour sections, the tour will not load.
|
||||
"steps": [] // tour steps - see next example
|
||||
}
|
||||
|
||||
@@ -286,6 +286,7 @@
|
||||
$scope.page.buttonGroupState = "success";
|
||||
|
||||
}, function (err) {
|
||||
formHelper.showNotifications(err.data);
|
||||
$scope.page.buttonGroupState = 'error';
|
||||
});
|
||||
}
|
||||
|
||||
+5
-12
@@ -54,8 +54,6 @@ function umbTreeDirective($compile, $log, $q, $rootScope, treeService, notificat
|
||||
controller: function ($scope, $element) {
|
||||
|
||||
var vm = this;
|
||||
|
||||
var isInitialized = false;
|
||||
|
||||
var registeredCallbacks = {
|
||||
treeNodeExpanded: [],
|
||||
@@ -163,9 +161,7 @@ function umbTreeDirective($compile, $log, $q, $rootScope, treeService, notificat
|
||||
if (!args.path) {
|
||||
throw "args.path cannot be null";
|
||||
}
|
||||
|
||||
var treeNode = loadActiveTree(args.tree);
|
||||
|
||||
|
||||
if (angular.isString(args.path)) {
|
||||
args.path = args.path.replace('"', '').split(',');
|
||||
}
|
||||
@@ -200,6 +196,8 @@ function umbTreeDirective($compile, $log, $q, $rootScope, treeService, notificat
|
||||
|
||||
deleteAnimations = false;
|
||||
|
||||
var treeNode = loadActiveTree(args.tree);
|
||||
|
||||
return treeService.syncTree({
|
||||
node: treeNode,
|
||||
path: args.path,
|
||||
@@ -275,13 +273,6 @@ function umbTreeDirective($compile, $log, $q, $rootScope, treeService, notificat
|
||||
//set the data once we have it
|
||||
$scope.tree = data;
|
||||
|
||||
//call the callback, this allows for hosting controllers to bind to events and use the exposed API
|
||||
if (!isInitialized) {
|
||||
isInitialized = true;
|
||||
$scope.onInit();
|
||||
}
|
||||
|
||||
|
||||
enableDeleteAnimations();
|
||||
|
||||
$scope.loading = false;
|
||||
@@ -433,6 +424,8 @@ function umbTreeDirective($compile, $log, $q, $rootScope, treeService, notificat
|
||||
});
|
||||
|
||||
loadTree();
|
||||
|
||||
$scope.onInit();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ function contentResource($q, $http, umbDataFormatter, umbRequestHelper) {
|
||||
saveModel),
|
||||
'Failed to save permissions');
|
||||
},
|
||||
|
||||
|
||||
|
||||
getRecycleBin: function () {
|
||||
return umbRequestHelper.resourcePromise(
|
||||
@@ -425,7 +425,7 @@ function contentResource($q, $http, umbDataFormatter, umbRequestHelper) {
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"contentApiBaseUrl",
|
||||
"GetEmpty",
|
||||
"GetEmpty",
|
||||
[{ blueprintId: blueprintId }, { parentId: parentId}])),
|
||||
'Failed to retrieve blueprint for id ' + blueprintId);
|
||||
},
|
||||
@@ -489,6 +489,7 @@ function contentResource($q, $http, umbDataFormatter, umbRequestHelper) {
|
||||
getChildren: function (parentId, options) {
|
||||
|
||||
var defaults = {
|
||||
includeProperties: [],
|
||||
pageSize: 0,
|
||||
pageNumber: 0,
|
||||
filter: '',
|
||||
@@ -532,6 +533,7 @@ function contentResource($q, $http, umbDataFormatter, umbRequestHelper) {
|
||||
"GetChildren",
|
||||
{
|
||||
id: parentId,
|
||||
includeProperties: _.pluck(options.includeProperties, 'alias').join(","),
|
||||
pageNumber: options.pageNumber,
|
||||
pageSize: options.pageSize,
|
||||
orderBy: options.orderBy,
|
||||
@@ -581,7 +583,7 @@ function contentResource($q, $http, umbDataFormatter, umbRequestHelper) {
|
||||
"contentApiBaseUrl",
|
||||
"GetDetailedPermissions", { contentId: contentId })),
|
||||
'Failed to retrieve permissions for content item ' + contentId);
|
||||
},
|
||||
},
|
||||
|
||||
getPermissions: function (nodeIds) {
|
||||
return umbRequestHelper.resourcePromise(
|
||||
@@ -742,11 +744,11 @@ function contentResource($q, $http, umbDataFormatter, umbRequestHelper) {
|
||||
|
||||
createBlueprintFromContent: function (contentId, name) {
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.post(
|
||||
$http.post(
|
||||
umbRequestHelper.getApiUrl("contentApiBaseUrl", "CreateBlueprintFromContent", {
|
||||
contentId: contentId, name: name
|
||||
})
|
||||
),
|
||||
})
|
||||
),
|
||||
"Failed to create blueprint from content with id " + contentId
|
||||
);
|
||||
}
|
||||
|
||||
@@ -122,6 +122,18 @@ function mediaTypeResource($q, $http, umbRequestHelper, umbDataFormatter) {
|
||||
'Failed to delete content type contaier');
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.resources.mediaTypeResource#save
|
||||
* @methodOf umbraco.resources.mediaTypeResource
|
||||
*
|
||||
* @description
|
||||
* Saves or update a media type
|
||||
*
|
||||
* @param {Object} content data type object to create/update
|
||||
* @returns {Promise} resourcePromise object.
|
||||
*
|
||||
*/
|
||||
save: function (contentType) {
|
||||
|
||||
var saveModel = umbDataFormatter.formatContentTypePostData(contentType);
|
||||
|
||||
@@ -86,8 +86,8 @@ function memberTypeResource($q, $http, umbRequestHelper, umbDataFormatter) {
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.resources.contentTypeResource#save
|
||||
* @methodOf umbraco.resources.contentTypeResource
|
||||
* @name umbraco.resources.memberTypeResource#save
|
||||
* @methodOf umbraco.resources.memberTypeResource
|
||||
*
|
||||
* @description
|
||||
* Saves or update a member type
|
||||
|
||||
@@ -237,10 +237,11 @@ function contentEditingHelper(fileManager, $q, $location, $routeParams, notifica
|
||||
}
|
||||
|
||||
|
||||
//if we are not creating, then we should add unpublish too,
|
||||
// if we are not creating, then we should add unpublish too,
|
||||
// so long as it's already published and if the user has access to publish
|
||||
// and the user has access to unpublish (may have been removed via Event)
|
||||
if (!args.create) {
|
||||
if (args.content.publishDate && _.contains(args.content.allowedActions, "U")) {
|
||||
if (args.content.publishDate && _.contains(args.content.allowedActions, "U") && _.contains(args.content.allowedActions, "Z")) {
|
||||
buttons.subButtons.push(createButtonDefinition("Z"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
|
||||
|
||||
// Sortabel
|
||||
// Sortable
|
||||
// -------------------------
|
||||
|
||||
// sortable-helper
|
||||
@@ -127,6 +127,16 @@
|
||||
position: relative;
|
||||
margin-bottom: 40px;
|
||||
padding-top: 10px;
|
||||
|
||||
&:hover {
|
||||
background-color: @grayLighter;
|
||||
}
|
||||
|
||||
&[ng-click],
|
||||
&[data-ng-click],
|
||||
&[x-ng-click] {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.umb-grid .row-tools a {
|
||||
@@ -431,7 +441,7 @@
|
||||
background-color: @gray-10;
|
||||
|
||||
.umb-row-title-bar {
|
||||
cursor: default;
|
||||
cursor: inherit;
|
||||
}
|
||||
|
||||
.umb-row-title {
|
||||
|
||||
@@ -16,24 +16,23 @@
|
||||
<i class="large {{docType.icon}}"></i>
|
||||
<span class="menu-label">
|
||||
{{docType.name}}
|
||||
<small>
|
||||
{{docType.description}}
|
||||
</small>
|
||||
<small>{{docType.description}}</small>
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
<!--
|
||||
<li class="add">
|
||||
<a href="#settings/documenttype/create/{{currentNode.id}}?doctype={{docType.alias}}&create=true" ng-click="nav.hideNavigation()">
|
||||
<i class="icon-large icon-plus"></i>
|
||||
<span class="menu-label">
|
||||
Create a new media type
|
||||
<small>
|
||||
Design and configure a new media type
|
||||
</small>
|
||||
</span>
|
||||
</a>
|
||||
</li> -->
|
||||
<!--
|
||||
<li class="add">
|
||||
<a href="#settings/documenttype/create/{{currentNode.id}}?doctype={{docType.alias}}&create=true" ng-click="nav.hideNavigation()">
|
||||
<i class="icon-large icon-plus"></i>
|
||||
<span class="menu-label">
|
||||
Create a new media type
|
||||
<small>
|
||||
Design and configure a new media type
|
||||
</small>
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
-->
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
@@ -6,10 +6,9 @@
|
||||
|
||||
<li ng-repeat="docType in allowedTypes">
|
||||
<a href="#member/member/edit/{{currentNode.id}}?doctype={{docType.alias}}&create=true" ng-click="nav.hideNavigation()">
|
||||
|
||||
<i class="large icon-users"></i>
|
||||
|
||||
<span class="menu-label">{{docType.name}}
|
||||
<i class="large {{docType.icon}}"></i>
|
||||
<span class="menu-label">
|
||||
{{docType.name}}
|
||||
<small>{{docType.description}}</small>
|
||||
</span>
|
||||
</a>
|
||||
@@ -24,4 +23,3 @@
|
||||
<localize key="buttons_somethingElse">Do something else</localize>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
|
||||
+5
-5
@@ -1,6 +1,6 @@
|
||||
|
||||
/**
|
||||
* The controller that is used for a couple different Property Editors: Multi Node Tree Picker, Content Picker,
|
||||
* The controller that is used for a couple different Property Editors: Multi Node Tree Picker, Content Picker,
|
||||
* since this is used by MNTP and it supports content, media and members, there is code to deal with all 3 of those types
|
||||
* @param {any} $scope
|
||||
* @param {any} entityResource
|
||||
@@ -70,7 +70,7 @@ function contentPickerController($scope, entityResource, editorState, iconHelper
|
||||
|
||||
$scope.renderModel = [];
|
||||
|
||||
$scope.dialogEditor = editorState && editorState.current && editorState.current.isDialogEditor === true;
|
||||
$scope.dialogEditor = editorState && editorState.current && editorState.current.isDialogEditor === true;
|
||||
|
||||
//the default pre-values
|
||||
var defaultConfig = {
|
||||
@@ -105,7 +105,7 @@ function contentPickerController($scope, entityResource, editorState, iconHelper
|
||||
$scope.model.config.showOpenButton = Object.toBoolean($scope.model.config.showOpenButton);
|
||||
$scope.model.config.showEditButton = Object.toBoolean($scope.model.config.showEditButton);
|
||||
$scope.model.config.showPathOnHover = Object.toBoolean($scope.model.config.showPathOnHover);
|
||||
|
||||
|
||||
var entityType = $scope.model.config.startNode.type === "member"
|
||||
? "Member"
|
||||
: $scope.model.config.startNode.type === "media"
|
||||
@@ -135,8 +135,8 @@ function contentPickerController($scope, entityResource, editorState, iconHelper
|
||||
},
|
||||
treeAlias: $scope.model.config.startNode.type,
|
||||
section: $scope.model.config.startNode.type,
|
||||
idType: "int",
|
||||
//only show the lang selector for content
|
||||
idType: "int",
|
||||
//only show the lang selector for content
|
||||
showLanguageSelector: $scope.model.config.startNode.type === "content"
|
||||
};
|
||||
|
||||
|
||||
-5
@@ -267,11 +267,6 @@ angular.module("umbraco").controller("Umbraco.PropertyEditors.NestedContent.Prop
|
||||
}
|
||||
|
||||
var notSupported = [
|
||||
"Umbraco.CheckBoxList",
|
||||
"Umbraco.DropDownMultiple",
|
||||
"Umbraco.MacroContainer",
|
||||
"Umbraco.RadioButtonList",
|
||||
"Umbraco.MultipleTextstring",
|
||||
"Umbraco.Tags",
|
||||
"Umbraco.UploadField",
|
||||
"Umbraco.ImageCropper"
|
||||
|
||||
@@ -266,7 +266,7 @@ angular.module("umbraco")
|
||||
|
||||
|
||||
editor.on('ObjectResized', function (e) {
|
||||
var qs = "?width=" + e.width + "&height=" + e.height;
|
||||
var qs = "?width=" + e.width + "&height=" + e.height + "&mode=max";
|
||||
var srcAttr = $(e.target).attr("src");
|
||||
var path = srcAttr.split("?")[0];
|
||||
$(e.target).attr("data-mce-src", path + qs);
|
||||
@@ -384,7 +384,7 @@ angular.module("umbraco")
|
||||
// element might still be there even after the modal has been hidden.
|
||||
$scope.$on('$destroy', function () {
|
||||
unsubscribe();
|
||||
if (tinyMceEditor !== undefined && tinyMceEditor != null) {
|
||||
if (tinyMceEditor !== undefined && tinyMceEditor != null) {
|
||||
tinyMceEditor.destroy()
|
||||
}
|
||||
});
|
||||
|
||||
@@ -368,6 +368,7 @@
|
||||
</Content>
|
||||
<None Include="Umbraco\Config\Create\UI.Release.xml">
|
||||
<DependentUpon>UI.xml</DependentUpon>
|
||||
<SubType>Designer</SubType>
|
||||
</None>
|
||||
<Content Include="Global.asax" />
|
||||
<Content Include="Umbraco\Config\Lang\en_us.xml">
|
||||
|
||||
@@ -1283,7 +1283,7 @@
|
||||
<key alias="xmlDataIntegrityCheckMedia">媒體 - 所有XML:%0%,總共發佈:%1%,不合格:%2%</key>
|
||||
<key alias="xmlDataIntegrityCheckContent">內容 - 所有XML:%0%,總共發佈:%1%,不合格:%2%</key>
|
||||
<key alias="httpsCheckInvalidCertificate">憑證驗證錯誤:%0%</key>
|
||||
<key alias="httpsCheckInvalidUrl">網址探查錯誤:%0% - '%1%'</key>
|
||||
<key alias="healthCheckInvalidUrl">網址探查錯誤:%0% - '%1%'</key>
|
||||
<key alias="httpsCheckIsCurrentSchemeHttps">您目前使用HTTPS瀏覽本站:%0%</key>
|
||||
<key alias="httpsCheckConfigurationRectifyNotPossible">在您的web.config檔案中,appSetting的umbracoUseSSL是設為false。當您開始使用HTTPS時,應將其改為 true。</key>
|
||||
<key alias="httpsCheckConfigurationCheckResult">在您的web.config檔案中,appSetting的umbracoUseSSL是設為 %0%,您的cookies %0% 標成安全。</key>
|
||||
@@ -1316,10 +1316,10 @@
|
||||
<key alias="optionalFilePermissionFailed"><![CDATA[以下檔案必須擁有寫入權限好讓系統可以正常運作,但無法連接:<strong>%0%</strong>。如果無須寫入,不需採取行動。]]></key>
|
||||
<key alias="clickJackingCheckHeaderFound"><![CDATA[標頭或meta-tag的 <strong>X-Frame-Options</strong> 設定能控制網站是否可以被其他人IFRAMEd已找到。]]></key>
|
||||
<key alias="clickJackingCheckHeaderNotFound"><![CDATA[標頭或meta-tag的 <strong>X-Frame-Options</strong> 設定能控制網站是否可以被其他人IFRAMEd沒有找到。]]></key>
|
||||
<key alias="clickJackingSetHeaderInConfig">調整設定的標頭</key>
|
||||
<key alias="setHeaderInConfig">調整設定的標頭</key>
|
||||
<key alias="clickJackingSetHeaderInConfigDescription">在 web.config 的 httpProtocol/customHeaders 區域增加設定來防止本站被別的網站IFRAMEd。</key>
|
||||
<key alias="clickJackingSetHeaderInConfigSuccess">在 web.config 的 httpProtocol/customHeaders 區域已經增加設定來防止本站被別的網站IFRAMEd。</key>
|
||||
<key alias="clickJackingSetHeaderInConfigError">無法更新web.config檔案,錯誤:%0%</key>
|
||||
<key alias="setHeaderInConfigError">無法更新web.config檔案,錯誤:%0%</key>
|
||||
<!-- The following key get these tokens passed in:
|
||||
0: Comma delimitted list of headers found
|
||||
-->
|
||||
|
||||
@@ -30,20 +30,6 @@
|
||||
<delete assembly="umbraco" type="macroTasks" />
|
||||
</tasks>
|
||||
</nodeType>
|
||||
<nodeType alias="xslt">
|
||||
<header>Macro</header>
|
||||
<usercontrol>/create/xslt.ascx</usercontrol>
|
||||
<tasks>
|
||||
<delete assembly="umbraco" type="XsltTasks" />
|
||||
</tasks>
|
||||
</nodeType>
|
||||
<nodeType alias="xsltFolder">
|
||||
<header>Xslt</header>
|
||||
<usercontrol>/create/xslt.ascx</usercontrol>
|
||||
<tasks>
|
||||
<delete assembly="umbraco" type="XsltTasks" />
|
||||
</tasks>
|
||||
</nodeType>
|
||||
<nodeType alias="users">
|
||||
<header>User</header>
|
||||
<usercontrol>/create/user.ascx</usercontrol>
|
||||
|
||||
@@ -30,21 +30,7 @@
|
||||
<delete assembly="Umbraco.Web" type="macroTasks" />
|
||||
</tasks>
|
||||
</nodeType>
|
||||
<nodeType alias="xslt">
|
||||
<header>Macro</header>
|
||||
<usercontrol>/create/xslt.ascx</usercontrol>
|
||||
<tasks>
|
||||
<delete assembly="Umbraco.Web" type="XsltTasks" />
|
||||
</tasks>
|
||||
</nodeType>
|
||||
<nodeType alias="xsltFolder">
|
||||
<header>Xslt</header>
|
||||
<usercontrol>/create/xslt.ascx</usercontrol>
|
||||
<tasks>
|
||||
<create assembly="Umbraco.Web" type="XsltTasks" />
|
||||
<delete assembly="Umbraco.Web" type="XsltTasks" />
|
||||
</tasks>
|
||||
</nodeType>
|
||||
|
||||
<nodeType alias="users">
|
||||
<header>User</header>
|
||||
<usercontrol>/create/user.ascx</usercontrol>
|
||||
|
||||
@@ -1938,7 +1938,7 @@ To manage your website, simply open the Umbraco back office and start adding con
|
||||
<key alias="httpsCheckInvalidCertificate">Certificate validation error: '%0%'</key>
|
||||
<key alias="httpsCheckExpiredCertificate">Your website's SSL certificate has expired.</key>
|
||||
<key alias="httpsCheckExpiringCertificate">Your website's SSL certificate is expiring in %0% days.</key>
|
||||
<key alias="httpsCheckInvalidUrl">Error pinging the URL %0% - '%1%'</key>
|
||||
<key alias="healthCheckInvalidUrl">Error pinging the URL %0% - '%1%'</key>
|
||||
<key alias="httpsCheckIsCurrentSchemeHttps">You are currently %0% viewing the site using the HTTPS scheme.</key>
|
||||
<key alias="httpsCheckConfigurationRectifyNotPossible">The appSetting 'umbracoUseSSL' is set to 'false' in your web.config file. Once you access this site using the HTTPS scheme, that should be set to 'true'.</key>
|
||||
<key alias="httpsCheckConfigurationCheckResult">The appSetting 'umbracoUseSSL' is set to '%0%' in your web.config file, your cookies are %1% marked as secure.</key>
|
||||
@@ -1978,10 +1978,25 @@ To manage your website, simply open the Umbraco back office and start adding con
|
||||
|
||||
<key alias="clickJackingCheckHeaderFound"><![CDATA[The header or meta-tag <strong>X-Frame-Options</strong> used to control whether a site can be IFRAMEd by another was found.]]></key>
|
||||
<key alias="clickJackingCheckHeaderNotFound"><![CDATA[The header or meta-tag <strong>X-Frame-Options</strong> used to control whether a site can be IFRAMEd by another was not found.]]></key>
|
||||
<key alias="clickJackingSetHeaderInConfig">Set Header in Config</key>
|
||||
<key alias="setHeaderInConfig">Set Header in Config</key>
|
||||
<key alias="clickJackingSetHeaderInConfigDescription">Adds a value to the httpProtocol/customHeaders section of web.config to prevent the site being IFRAMEd by other websites.</key>
|
||||
<key alias="clickJackingSetHeaderInConfigSuccess">A setting to create a header preventing IFRAMEing of the site by other websites has been added to your web.config file.</key>
|
||||
<key alias="clickJackingSetHeaderInConfigError">Could not update web.config file. Error: %0%</key>
|
||||
<key alias="setHeaderInConfigError">Could not update web.config file. Error: %0%</key>
|
||||
|
||||
<key alias="noSniffCheckHeaderFound"><![CDATA[The header or meta-tag <strong>X-Content-Type-Options</strong> used to protect against MIME sniffing vulnerabilities was found.]]></key>
|
||||
<key alias="noSniffCheckHeaderNotFound"><![CDATA[The header or meta-tag <strong>X-Content-Type-Options</strong> used to protect against MIME sniffing vulnerabilities was not found.]]></key>
|
||||
<key alias="noSniffSetHeaderInConfigDescription">Adds a value to the httpProtocol/customHeaders section of web.config to protect against MIME sniffing vulnerabilities.</key>
|
||||
<key alias="noSniffSetHeaderInConfigSuccess">A setting to create a header protecting against MIME sniffing vulnerabilities has been added to your web.config file.</key>
|
||||
|
||||
<key alias="hSTSCheckHeaderFound"><![CDATA[The header <strong>Strict-Transport-Security</strong>, also known as the HSTS-header, was found.]]></key>
|
||||
<key alias="hSTSCheckHeaderNotFound"><![CDATA[The header <strong>Strict-Transport-Security</strong> was not found.]]></key>
|
||||
<key alias="hSTSSetHeaderInConfigDescription">Adds the header 'Strict-Transport-Security' with the value 'max-age=10886400; preload' to the httpProtocol/customHeaders section of web.config. Use this fix only if you will have your domains running with https for the next 18 weeks (minimum).</key>
|
||||
<key alias="hSTSSetHeaderInConfigSuccess">The HSTS header has been added to your web.config file.</key>
|
||||
|
||||
<key alias="xssProtectionCheckHeaderFound"><![CDATA[The header <strong>X-XSS-Protection</strong> was found.]]></key>
|
||||
<key alias="xssProtectionCheckHeaderNotFound"><![CDATA[The header <strong>X-XSS-Protection</strong> was not found.]]></key>
|
||||
<key alias="xssProtectionSetHeaderInConfigDescription">Adds the header 'X-XSS-Protection' with the value '1; mode=block' to the httpProtocol/customHeaders section of web.config. </key>
|
||||
<key alias="xssProtectionSetHeaderInConfigSuccess">The X-XSS-Protection header has been added to your web.config file.</key>
|
||||
|
||||
<!-- The following key get these tokens passed in:
|
||||
0: Comma delimitted list of headers found
|
||||
|
||||
@@ -2065,7 +2065,7 @@ To manage your website, simply open the Umbraco back office and start adding con
|
||||
<key alias="httpsCheckInvalidCertificate">Certificate validation error: '%0%'</key>
|
||||
<key alias="httpsCheckExpiredCertificate">Your website's SSL certificate has expired.</key>
|
||||
<key alias="httpsCheckExpiringCertificate">Your website's SSL certificate is expiring in %0% days.</key>
|
||||
<key alias="httpsCheckInvalidUrl">Error pinging the URL %0% - '%1%'</key>
|
||||
<key alias="healthCheckInvalidUrl">Error pinging the URL %0% - '%1%'</key>
|
||||
<key alias="httpsCheckIsCurrentSchemeHttps">You are currently %0% viewing the site using the HTTPS scheme.</key>
|
||||
<key alias="httpsCheckConfigurationRectifyNotPossible">The appSetting 'umbracoUseSSL' is set to 'false' in your web.config file. Once you access this site using the HTTPS scheme, that should be set to 'true'.</key>
|
||||
<key alias="httpsCheckConfigurationCheckResult">The appSetting 'umbracoUseSSL' is set to '%0%' in your web.config file, your cookies are %1% marked as secure.</key>
|
||||
@@ -2105,10 +2105,25 @@ To manage your website, simply open the Umbraco back office and start adding con
|
||||
|
||||
<key alias="clickJackingCheckHeaderFound"><![CDATA[The header or meta-tag <strong>X-Frame-Options</strong> used to control whether a site can be IFRAMEd by another was found.]]></key>
|
||||
<key alias="clickJackingCheckHeaderNotFound"><![CDATA[The header or meta-tag <strong>X-Frame-Options</strong> used to control whether a site can be IFRAMEd by another was not found.]]></key>
|
||||
<key alias="clickJackingSetHeaderInConfig">Set Header in Config</key>
|
||||
<key alias="setHeaderInConfig">Set Header in Config</key>
|
||||
<key alias="clickJackingSetHeaderInConfigDescription">Adds a value to the httpProtocol/customHeaders section of web.config to prevent the site being IFRAMEd by other websites.</key>
|
||||
<key alias="clickJackingSetHeaderInConfigSuccess">A setting to create a header preventing IFRAMEing of the site by other websites has been added to your web.config file.</key>
|
||||
<key alias="clickJackingSetHeaderInConfigError">Could not update web.config file. Error: %0%</key>
|
||||
<key alias="setHeaderInConfigError">Could not update web.config file. Error: %0%</key>
|
||||
|
||||
<key alias="noSniffCheckHeaderFound"><![CDATA[The header or meta-tag <strong>X-Content-Type-Options</strong> used to protect against MIME sniffing vulnerabilities was found.]]></key>
|
||||
<key alias="noSniffCheckHeaderNotFound"><![CDATA[The header or meta-tag <strong>X-Content-Type-Options</strong> used to protect against MIME sniffing vulnerabilities was not found.]]></key>
|
||||
<key alias="noSniffSetHeaderInConfigDescription">Adds a value to the httpProtocol/customHeaders section of web.config to protect against MIME sniffing vulnerabilities.</key>
|
||||
<key alias="noSniffSetHeaderInConfigSuccess">A setting to create a header protecting against MIME sniffing vulnerabilities has been added to your web.config file.</key>
|
||||
|
||||
<key alias="hSTSCheckHeaderFound"><![CDATA[The header <strong>Strict-Transport-Security</strong>, also known as the HSTS-header, was found.]]></key>
|
||||
<key alias="hSTSCheckHeaderNotFound"><![CDATA[The header <strong>Strict-Transport-Security</strong> was not found.]]></key>
|
||||
<key alias="hSTSSetHeaderInConfigDescription">Adds the header 'Strict-Transport-Security' with the value 'max-age=10886400; preload' to the httpProtocol/customHeaders section of web.config. Use this fix only if you will have your domains running with https for the next 18 weeks (minimum).</key>
|
||||
<key alias="hSTSSetHeaderInConfigSuccess">The HSTS header has been added to your web.config file.</key>
|
||||
|
||||
<key alias="xssProtectionCheckHeaderFound"><![CDATA[The header <strong>X-XSS-Protection</strong> was found.]]></key>
|
||||
<key alias="xssProtectionCheckHeaderNotFound"><![CDATA[The header <strong>X-XSS-Protection</strong> was not found.]]></key>
|
||||
<key alias="xssProtectionSetHeaderInConfigDescription">Adds the header 'X-XSS-Protection' with the value '1; mode=block' to the httpProtocol/customHeaders section of web.config. </key>
|
||||
<key alias="xssProtectionSetHeaderInConfigSuccess">The X-XSS-Protection header has been added to your web.config file.</key>
|
||||
|
||||
<!-- The following key get these tokens passed in:
|
||||
0: Comma delimitted list of headers found
|
||||
|
||||
@@ -1798,7 +1798,7 @@
|
||||
<key alias="httpsCheckInvalidCertificate">Error validando certificado: '%0%'</key>
|
||||
<key alias="httpsCheckExpiredCertificate">El ceriticado SSL de tu sitio ha caducado.</key>
|
||||
<key alias="httpsCheckExpiringCertificate">El ceriticado SSL de tu sitio caducará en %0% días.</key>
|
||||
<key alias="httpsCheckInvalidUrl">Error pinging la URL %0% - '%1%'</key>
|
||||
<key alias="healthCheckInvalidUrl">Error pinging la URL %0% - '%1%'</key>
|
||||
<key alias="httpsCheckIsCurrentSchemeHttps">Actualmente estás %0% viendo el sitio usando el esquema HTTPS.</key>
|
||||
<key alias="httpsCheckConfigurationRectifyNotPossible">El appSetting 'umbracoUseSSL' está configurado como 'false' en tu archivo web.config. Una vez que accedes al sitio usando HTTPS, debería ser configuraio como 'true'.</key>
|
||||
<key alias="httpsCheckConfigurationCheckResult">Ele appSetting 'umbracoUseSSL' está configurado como '%0%' en tu archivo your web.config, tus cookies son %1% marcadas como seguras.</key>
|
||||
@@ -1838,10 +1838,10 @@
|
||||
|
||||
<key alias="clickJackingCheckHeaderFound"><![CDATA[El header or meta-tag <strong>X-Frame-Options</strong> usado para controlar si un sitio puede ser IFRAMEd por otra fue encontrado.]]></key>
|
||||
<key alias="clickJackingCheckHeaderNotFound"><![CDATA[El header or meta-tag <strong>X-Frame-Options</strong> usado para controlar si un sitio puede ser IFRAMEd por otra no se ha encontrado.]]></key>
|
||||
<key alias="clickJackingSetHeaderInConfig">Establecer Header en Config</key>
|
||||
<key alias="setHeaderInConfig">Establecer Header en Config</key>
|
||||
<key alias="clickJackingSetHeaderInConfigDescription">Adds a value to the httpProtocol/customHeaders section of web.config to prevent the site being IFRAMEd by other websites.</key>
|
||||
<key alias="clickJackingSetHeaderInConfigSuccess">A setting to create a header preventing IFRAMEing of the site by other websites has been added to your web.config file.</key>
|
||||
<key alias="clickJackingSetHeaderInConfigError">Could not update web.config file. Error: %0%</key>
|
||||
<key alias="setHeaderInConfigError">Could not update web.config file. Error: %0%</key>
|
||||
|
||||
<!-- The following key get these tokens passed in:
|
||||
0: Comma delimitted list of headers found
|
||||
|
||||
@@ -1359,7 +1359,7 @@ Pour gérer votre site, ouvrez simplement le backoffice Umbraco et commencez à
|
||||
<key alias="xmlDataIntegrityCheckContent">Total XML : %0%, Total publié : %1%</key>
|
||||
|
||||
<key alias="httpsCheckInvalidCertificate">Erreur de validation du certificat : '%0%'</key>
|
||||
<key alias="httpsCheckInvalidUrl">Erreur en essayant de contacter l'URL %0% - '%1%'</key>
|
||||
<key alias="healthCheckInvalidUrl">Erreur en essayant de contacter l'URL %0% - '%1%'</key>
|
||||
<key alias="httpsCheckIsCurrentSchemeHttps">Vous êtes actuellement %0% à voir le site via le schéma HTTPS.</key>
|
||||
<key alias="httpsCheckConfigurationRectifyNotPossible">La valeur appSetting 'umbracoUseSSL' est fixée à 'false' dans votre fichier web.config. Une fois que vous donnerez accès à ce site en utilisant le schéma HTTPS, cette valeur devra être mise à 'true'.</key>
|
||||
<key alias="httpsCheckConfigurationCheckResult">La valeur appSetting 'umbracoUseSSL' est fixée à '%0%' dans votre fichier web.config, vos cookies sont %1% marqués comme étant sécurisés.</key>
|
||||
@@ -1399,10 +1399,10 @@ Pour gérer votre site, ouvrez simplement le backoffice Umbraco et commencez à
|
||||
|
||||
<key alias="clickJackingCheckHeaderFound"><![CDATA[Le header ou meta-tag <strong>X-Frame-Options</strong>, utilisé pour contrôler si un site peut être intégré dans un autre via IFRAME, a été trouvé.]]></key>
|
||||
<key alias="clickJackingCheckHeaderNotFound"><![CDATA[Le header ou meta-tag <strong>X-Frame-Options</strong> , utilisé pour contrôler si un site peut être intégré dans un autre via IFRAME, n'a pas été trouvé.]]></key>
|
||||
<key alias="clickJackingSetHeaderInConfig">Configurez le Header dans le fichier Config</key>
|
||||
<key alias="setHeaderInConfig">Configurez le Header dans le fichier Config</key>
|
||||
<key alias="clickJackingSetHeaderInConfigDescription">Ajoute une valeur dans la section httpProtocol/customHeaders du fichier web.config afin d'éviter que le site ne soit intégré dans d'autres sites via IFRAME.</key>
|
||||
<key alias="clickJackingSetHeaderInConfigSuccess">Une configuration générant un header qui empêche l'intégration du site par d'autres sites via IFRAME a été ajoutée à votre fichier web.config.</key>
|
||||
<key alias="clickJackingSetHeaderInConfigError">Impossible de modifier le fichier web.config. Erreur : %0%</key>
|
||||
<key alias="setHeaderInConfigError">Impossible de modifier le fichier web.config. Erreur : %0%</key>
|
||||
|
||||
<!-- The following key get these tokens passed in:
|
||||
0: Comma delimitted list of headers found
|
||||
|
||||
@@ -1368,7 +1368,7 @@ Om een vertalingstaak te sluiten, ga aub naar het detailoverzicht en klik op de
|
||||
|
||||
<key alias="httpsCheckValidCertificate">Het cerficaat van de website is ongeldig.</key>
|
||||
<key alias="httpsCheckInvalidCertificate">Cerficaat validatie foutmelding: '%0%'</key>
|
||||
<key alias="httpsCheckInvalidUrl">Fout bij pingen van URL %0% - '%1%'</key>
|
||||
<key alias="healthCheckInvalidUrl">Fout bij pingen van URL %0% - '%1%'</key>
|
||||
<key alias="httpsCheckIsCurrentSchemeHttps">De site wordt momenteel %0% bekeken via HTTPS.</key>
|
||||
<key alias="httpsCheckConfigurationRectifyNotPossible">De appSetting 'umbracoUseSSL' in web.config staat op 'false'. Indien HTTPS gebruikt wordt moet deze op 'true' staan.</key>
|
||||
<key alias="httpsCheckConfigurationCheckResult">De appSetting 'umbracoUseSSL' in web.config is ingesteld op '%0%'. Cookies zijn %1% ingesteld als secure.</key>
|
||||
@@ -1408,10 +1408,10 @@ Om een vertalingstaak te sluiten, ga aub naar het detailoverzicht en klik op de
|
||||
|
||||
<key alias="clickJackingCheckHeaderFound"><![CDATA[De <strong>X-Frame-Options</strong> header of meta-tag om IFRAMEing door andere websites te voorkomen is aanwezig!]]></key>
|
||||
<key alias="clickJackingCheckHeaderNotFound"><![CDATA[De <strong>X-Frame-Options</strong> header of meta-tag om IFRAMEing door andere websites te voorkomen is NIET aanwezig.]]></key>
|
||||
<key alias="clickJackingSetHeaderInConfig">Voorkom IFRAMEing via web.config</key>
|
||||
<key alias="setHeaderInConfig">Voorkom IFRAMEing via web.config</key>
|
||||
<key alias="clickJackingSetHeaderInConfigDescription">Voegt de instelling toe aan de httpProtocol/customHeaders section in web.config om IFRAMEing door andere websites te voorkomen.</key>
|
||||
<key alias="clickJackingSetHeaderInConfigSuccess">De instelling om IFRAMEing door andere websites te voorkomen is toegevoegd aan de web.config!</key>
|
||||
<key alias="clickJackingSetHeaderInConfigError">Web.config kon niet aangepast worden door error: %0%</key>
|
||||
<key alias="setHeaderInConfigError">Web.config kon niet aangepast worden door error: %0%</key>
|
||||
|
||||
<!-- The following key get these tokens passed in:
|
||||
0: Comma delimitted list of headers found
|
||||
|
||||
@@ -1618,7 +1618,7 @@ Naciśnij przycisk <strong>instaluj</strong>, aby zainstalować bazę danych Umb
|
||||
<key alias="httpsCheckInvalidCertificate">Błąd walidacji certyfikatu: '%0%'</key>
|
||||
<key alias="httpsCheckExpiredCertificate">Certyfikat SSL Twojej strony wygasł.</key>
|
||||
<key alias="httpsCheckExpiringCertificate">Certyfikat SSL Twojej strony wygaśnie za %0% dni.</key>
|
||||
<key alias="httpsCheckInvalidUrl">Błąd pingowania adresu URL %0% - '%1%'</key>
|
||||
<key alias="healthCheckInvalidUrl">Błąd pingowania adresu URL %0% - '%1%'</key>
|
||||
<key alias="httpsCheckIsCurrentSchemeHttps">Oglądasz %0% stronę używając HTTPS.</key>
|
||||
<key alias="httpsCheckConfigurationRectifyNotPossible">appSetting 'umbracoUseSSL' został ustawiony na 'false' w Twoim pliku web.config. Po uzyskaniu dostępu do strony, używając HTTPS, powinieneś go ustawić na 'true'.</key>
|
||||
<key alias="httpsCheckConfigurationCheckResult">appSetting 'umbracoUseSSL' został ustawiony na '%0%' w Twoim pliku web.config, Twoje ciasteczka są %1% ustawione jako bezpieczne.</key>
|
||||
@@ -1658,10 +1658,10 @@ Naciśnij przycisk <strong>instaluj</strong>, aby zainstalować bazę danych Umb
|
||||
|
||||
<key alias="clickJackingCheckHeaderFound"><![CDATA[Nagłówek lub meta-tag <strong>X-Frame-Options</strong> używany do kontrolowania czy strona może być IFRAME'owana przez inną został znaleziony.]]></key>
|
||||
<key alias="clickJackingCheckHeaderNotFound"><![CDATA[Nagłówek lub meta-tag <strong>X-Frame-Options</strong> używany do kontrolowania czy strona może być IFRAME'owana przez inną nie został znaleziony.]]></key>
|
||||
<key alias="clickJackingSetHeaderInConfig">Ustaw nagłówek w Config</key>
|
||||
<key alias="setHeaderInConfig">Ustaw nagłówek w Config</key>
|
||||
<key alias="clickJackingSetHeaderInConfigDescription">Dodaje wartość do sekcji httpProtocol/customHeaders pliku web.config, aby zapobiec IFRAME'owania strony przez inne witryny.</key>
|
||||
<key alias="clickJackingSetHeaderInConfigSuccess">Ustawienie do tworzenia nagłówka, zapobiegającego IFRAME'owania strony przez inne witryny zostało dodane do Twojego pliku web.config.</key>
|
||||
<key alias="clickJackingSetHeaderInConfigError">Nie można zaktualizować pliku web.config. Błąd: %0%</key>
|
||||
<key alias="setHeaderInConfigError">Nie można zaktualizować pliku web.config. Błąd: %0%</key>
|
||||
|
||||
<!-- Następujące klucze spowodują, że tokeny zostaną przekazane:
|
||||
0: Lista znalezionych nagłówków, oddzielonych przecinkami
|
||||
|
||||
@@ -756,7 +756,7 @@
|
||||
|
||||
<key alias="httpsCheckValidCertificate">Сертификат Вашего веб-сайта отмечен как проверенный.</key>
|
||||
<key alias="httpsCheckInvalidCertificate">Ошибка проверки сертификата: '%0%'</key>
|
||||
<key alias="httpsCheckInvalidUrl">Ошибка проверки адреса URL %0% - '%1%'</key>
|
||||
<key alias="healthCheckInvalidUrl">Ошибка проверки адреса URL %0% - '%1%'</key>
|
||||
<key alias="httpsCheckIsCurrentSchemeHttps">Сейчас Вы %0% просматриваете сайт, используя протокол HTTPS.</key>
|
||||
<key alias="httpsCheckConfigurationRectifyNotPossible">Параметр 'umbracoUseSSL' в секции 'appSetting' установлен в 'false' в файле web.config. Если Вам необходим доступ к сайту по протоколу HTTPS, нужно установить данный параметр в 'true'.</key>
|
||||
<key alias="httpsCheckConfigurationCheckResult">Параметр 'umbracoUseSSL' в секции 'appSetting' в файле установлен в '%0%', значения cookies %1% маркированы как безопасные.</key>
|
||||
@@ -796,10 +796,10 @@
|
||||
|
||||
<key alias="clickJackingCheckHeaderFound"><![CDATA[Был обнаружен заголовок или мета-тэг <strong>X-Frame-Options</strong>, использующийся для управления возможностью помещать сайт в IFRAME на другом сайте.]]></key>
|
||||
<key alias="clickJackingCheckHeaderNotFound"><![CDATA[Заголовок или мета-тэг <strong>X-Frame-Options</strong>, использующийся для управления возможностью помещать сайт в IFRAME на другом сайте, не обнаружен.]]></key>
|
||||
<key alias="clickJackingSetHeaderInConfig">Установить заголовок в файле конфигурации</key>
|
||||
<key alias="setHeaderInConfig">Установить заголовок в файле конфигурации</key>
|
||||
<key alias="clickJackingSetHeaderInConfigDescription">Добавляет значение в секцию 'httpProtocol/customHeaders' файла web.config, препятствующее возможному использованию этого сайта внутри IFRAME на другом сайте.</key>
|
||||
<key alias="clickJackingSetHeaderInConfigSuccess">Значение, добавляющее заголовок, препятствующий использованию этого сайта внутри IFRAME другого сайта, успешно добавлено в файл web.config.</key>
|
||||
<key alias="clickJackingSetHeaderInConfigError">Невозможно обновить файл web.config. Ошибка: %0%</key>
|
||||
<key alias="setHeaderInConfigError">Невозможно обновить файл web.config. Ошибка: %0%</key>
|
||||
|
||||
<!-- The following key get these tokens passed in:
|
||||
0: Comma delimitted list of headers found
|
||||
|
||||
@@ -1396,10 +1396,10 @@
|
||||
|
||||
<key alias="clickJackingCheckHeaderFound"><![CDATA[The header or meta-tag <strong>X-Frame-Options</strong> used to control whether a site can be IFRAMEd by another was found.]]></key>
|
||||
<key alias="clickJackingCheckHeaderNotFound"><![CDATA[The header or meta-tag <strong>X-Frame-Options</strong> used to control whether a site can be IFRAMEd by another was not found.]]></key>
|
||||
<key alias="clickJackingSetHeaderInConfig">Set Header in Config</key>
|
||||
<key alias="setHeaderInConfig">Set Header in Config</key>
|
||||
<key alias="clickJackingSetHeaderInConfigDescription">Adds a value to the httpProtocol/customHeaders section of web.config to prevent the site being IFRAMEd by other websites.</key>
|
||||
<key alias="clickJackingSetHeaderInConfigSuccess">A setting to create a header preventing IFRAMEing of the site by other websites has been added to your web.config file.</key>
|
||||
<key alias="clickJackingSetHeaderInConfigError">Could not update web.config file. Error: %0%</key>
|
||||
<key alias="setHeaderInConfigError">Could not update web.config file. Error: %0%</key>
|
||||
|
||||
<!-- The following key get these tokens passed in:
|
||||
0: Comma delimitted list of headers found
|
||||
|
||||
@@ -77,14 +77,18 @@ namespace Umbraco.Web
|
||||
batch.Clear();
|
||||
|
||||
//Write the instructions but only create JSON blobs with a max instruction count equal to MaxProcessingInstructionCount
|
||||
foreach (var instructionsBatch in instructions.InGroupsOf(Options.MaxProcessingInstructionCount))
|
||||
using (var scope = ScopeProvider.CreateScope())
|
||||
{
|
||||
WriteInstructions(instructionsBatch);
|
||||
foreach (var instructionsBatch in instructions.InGroupsOf(Options.MaxProcessingInstructionCount))
|
||||
{
|
||||
WriteInstructions(scope, instructionsBatch);
|
||||
}
|
||||
scope.Complete();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void WriteInstructions(IEnumerable<RefreshInstruction> instructions)
|
||||
private void WriteInstructions(IScope scope, IEnumerable<RefreshInstruction> instructions)
|
||||
{
|
||||
var dto = new CacheInstructionDto
|
||||
{
|
||||
@@ -93,12 +97,7 @@ namespace Umbraco.Web
|
||||
OriginIdentity = LocalIdentity,
|
||||
InstructionCount = instructions.Sum(x => x.JsonIdCount)
|
||||
};
|
||||
|
||||
using (var scope = ScopeProvider.CreateScope())
|
||||
{
|
||||
scope.Database.Insert(dto);
|
||||
scope.Complete();
|
||||
}
|
||||
scope.Database.Insert(dto);
|
||||
}
|
||||
|
||||
protected ICollection<RefreshInstructionEnvelope> GetBatch(bool create)
|
||||
@@ -139,9 +138,13 @@ namespace Umbraco.Web
|
||||
if (batch == null)
|
||||
{
|
||||
//only write the json blob with a maximum count of the MaxProcessingInstructionCount
|
||||
foreach (var maxBatch in instructions.InGroupsOf(Options.MaxProcessingInstructionCount))
|
||||
using (var scope = ScopeProvider.CreateScope())
|
||||
{
|
||||
WriteInstructions(maxBatch);
|
||||
foreach (var maxBatch in instructions.InGroupsOf(Options.MaxProcessingInstructionCount))
|
||||
{
|
||||
WriteInstructions(scope, maxBatch);
|
||||
}
|
||||
scope.Complete();
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
@@ -306,11 +306,11 @@ namespace Umbraco.Web.Editors
|
||||
|
||||
//remove this tab if it exists: umbContainerView
|
||||
var containerTab = mapped.Tabs.FirstOrDefault(x => x.Alias == Constants.Conventions.PropertyGroups.ListViewGroupName);
|
||||
mapped.Tabs = mapped.Tabs.Except(new[] { containerTab });
|
||||
|
||||
//Remove all variants except for the default since currently the default must be saved before other variants can be edited
|
||||
mapped.Tabs = mapped.Tabs.Except(new[] { containerTab });
|
||||
|
||||
//Remove all variants except for the default since currently the default must be saved before other variants can be edited
|
||||
//TODO: Allow for editing all variants at once ... this will be a future task
|
||||
mapped.Variants = new[] {mapped.Variants.First(x => x.IsCurrent)};
|
||||
mapped.Variants = new[] {mapped.Variants.First(x => x.IsCurrent)};
|
||||
|
||||
return mapped;
|
||||
}
|
||||
@@ -390,6 +390,24 @@ namespace Umbraco.Web.Editors
|
||||
Direction orderDirection = Direction.Ascending,
|
||||
bool orderBySystemField = true,
|
||||
string filter = "")
|
||||
{
|
||||
return GetChildren(id, null, pageNumber, pageSize, orderBy, orderDirection, orderBySystemField, filter);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the children for the content id passed in
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[FilterAllowedOutgoingContent(typeof(IEnumerable<ContentItemBasic<ContentPropertyBasic, IContent>>), "Items")]
|
||||
public PagedResult<ContentItemBasic<ContentPropertyBasic, IContent>> GetChildren(
|
||||
int id,
|
||||
string includeProperties,
|
||||
int pageNumber = 0, //TODO: This should be '1' as it's not the index
|
||||
int pageSize = 0,
|
||||
string orderBy = "SortOrder",
|
||||
Direction orderDirection = Direction.Ascending,
|
||||
bool orderBySystemField = true,
|
||||
string filter = "")
|
||||
{
|
||||
long totalChildren;
|
||||
IContent[] children;
|
||||
@@ -422,8 +440,16 @@ namespace Umbraco.Web.Editors
|
||||
}
|
||||
|
||||
var pagedResult = new PagedResult<ContentItemBasic<ContentPropertyBasic, IContent>>(totalChildren, pageNumber, pageSize);
|
||||
pagedResult.Items = children
|
||||
.Select(Mapper.Map<IContent, ContentItemBasic<ContentPropertyBasic, IContent>>);
|
||||
pagedResult.Items = children.Select(content =>
|
||||
Mapper.Map<IContent, ContentItemBasic<ContentPropertyBasic, IContent>>(content,
|
||||
opts =>
|
||||
{
|
||||
// if there's a list of property aliases to map - we will make sure to store this in the mapping context.
|
||||
if (String.IsNullOrWhiteSpace(includeProperties) == false)
|
||||
{
|
||||
opts.Items["IncludeProperties"] = includeProperties.Split(new[] { ", ", "," }, StringSplitOptions.RemoveEmptyEntries);
|
||||
}
|
||||
}));
|
||||
|
||||
return pagedResult;
|
||||
}
|
||||
@@ -618,7 +644,7 @@ namespace Umbraco.Web.Editors
|
||||
{
|
||||
//publish the item and check if it worked, if not we will show a diff msg below
|
||||
contentItem.PersistedContent.PublishValues(contentItem.LanguageId); //we are not checking for a return value here because we've alraedy pre-validated the property values
|
||||
|
||||
|
||||
//check if we are publishing other variants and validate them
|
||||
var allLangs = Services.LocalizationService.GetAllLanguages().ToList();
|
||||
var variantsToValidate = contentItem.PublishVariations.Where(x => x.LanguageId != contentItem.LanguageId).ToList();
|
||||
@@ -629,8 +655,8 @@ namespace Umbraco.Web.Editors
|
||||
var errMsg = Services.TextService.Localize("speechBubbles/contentLangValidationError", new[]{allLangs.First(x => x.Id == publishVariation.LanguageId).CultureName});
|
||||
ModelState.AddModelError("publish_variant_" + publishVariation.LanguageId + "_", errMsg);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//validate any mandatory variants that are not in the list
|
||||
var mandatoryLangs = Mapper.Map<IEnumerable<ILanguage>, IEnumerable<Language>>(allLangs)
|
||||
.Where(x => variantsToValidate.All(v => v.LanguageId != x.Id)) //don't include variants above
|
||||
@@ -643,7 +669,7 @@ namespace Umbraco.Web.Editors
|
||||
var errMsg = Services.TextService.Localize("speechBubbles/contentReqLangValidationError", new[]{allLangs.First(x => x.Id == lang.Id).CultureName});
|
||||
ModelState.AddModelError("publish_variant_" + lang.Id + "_", errMsg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
publishStatus = Services.ContentService.SaveAndPublish(contentItem.PersistedContent, Security.CurrentUser.Id);
|
||||
wasCancelled = publishStatus.Result == PublishResultType.FailedCancelledByEvent;
|
||||
@@ -949,9 +975,9 @@ namespace Umbraco.Web.Editors
|
||||
}
|
||||
}
|
||||
|
||||
base.MapPropertyValues<IContent, ContentItemSave>(
|
||||
contentItem,
|
||||
(save, property) => property.GetValue(save.LanguageId), //get prop val
|
||||
base.MapPropertyValues<IContent, ContentItemSave>(
|
||||
contentItem,
|
||||
(save, property) => property.GetValue(save.LanguageId), //get prop val
|
||||
(save, property, v) => property.SetValue(v, save.LanguageId)); //set prop val
|
||||
}
|
||||
|
||||
@@ -1138,7 +1164,7 @@ namespace Umbraco.Web.Editors
|
||||
}
|
||||
return allowed;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Used to map an <see cref="IContent"/> instance to a <see cref="ContentItemDisplay"/> and ensuring a language is present if required
|
||||
/// </summary>
|
||||
|
||||
@@ -63,7 +63,7 @@ namespace Umbraco.Web.Editors
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deletes a document type wth a given ID
|
||||
/// Deletes a media type with a given ID
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <returns></returns>
|
||||
@@ -120,17 +120,16 @@ namespace Umbraco.Web.Editors
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Returns all member types
|
||||
/// Returns all media types
|
||||
/// </summary>
|
||||
public IEnumerable<ContentTypeBasic> GetAll()
|
||||
{
|
||||
|
||||
return Services.MediaTypeService.GetAll()
|
||||
.Select(Mapper.Map<IMediaType, ContentTypeBasic>);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deletes a document type container wth a given ID
|
||||
/// Deletes a media type container wth a given ID
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <returns></returns>
|
||||
|
||||
@@ -121,13 +121,18 @@ namespace Umbraco.Web.Editors
|
||||
var contents = File.ReadAllText(tourFile);
|
||||
var tours = JsonConvert.DeserializeObject<BackOfficeTour[]>(contents);
|
||||
|
||||
var backOfficeTours = tours.Where(x =>
|
||||
aliasFilters.Count == 0 || aliasFilters.All(filter => filter.IsMatch(x.Alias)) == false);
|
||||
|
||||
var localizedTours = backOfficeTours.Where(x =>
|
||||
string.IsNullOrWhiteSpace(x.Culture) || x.Culture.Equals(Security.CurrentUser.Language,
|
||||
StringComparison.InvariantCultureIgnoreCase)).ToList();
|
||||
|
||||
var tour = new BackOfficeTourFile
|
||||
{
|
||||
FileName = Path.GetFileNameWithoutExtension(tourFile),
|
||||
PluginName = pluginName,
|
||||
Tours = tours
|
||||
.Where(x => aliasFilters.Count == 0 || aliasFilters.All(filter => filter.IsMatch(x.Alias)) == false)
|
||||
.ToArray()
|
||||
Tours = localizedTours
|
||||
};
|
||||
|
||||
//don't add if all of the tours are filtered
|
||||
|
||||
@@ -0,0 +1,221 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Xml.Linq;
|
||||
using System.Xml.XPath;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Services;
|
||||
|
||||
namespace Umbraco.Web.HealthCheck.Checks.Security
|
||||
{
|
||||
public abstract class BaseHttpHeaderCheck : HealthCheck
|
||||
{
|
||||
protected IRuntimeState Runtime { get; }
|
||||
protected ILocalizedTextService TextService { get; }
|
||||
|
||||
private const string SetHeaderInConfigAction = "setHeaderInConfig";
|
||||
|
||||
private readonly string _header;
|
||||
private readonly string _value;
|
||||
private readonly string _localizedTextPrefix;
|
||||
private readonly bool _metaTagOptionAvailable;
|
||||
|
||||
protected BaseHttpHeaderCheck(
|
||||
IRuntimeState runtime,
|
||||
ILocalizedTextService textService,
|
||||
string header, string value, string localizedTextPrefix, bool metaTagOptionAvailable)
|
||||
{
|
||||
Runtime = runtime;
|
||||
TextService = textService ?? throw new ArgumentNullException(nameof(textService));
|
||||
|
||||
_header = header;
|
||||
_value = value;
|
||||
_localizedTextPrefix = localizedTextPrefix;
|
||||
_metaTagOptionAvailable = metaTagOptionAvailable;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the status for this health check
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override IEnumerable<HealthCheckStatus> GetStatus()
|
||||
{
|
||||
//return the statuses
|
||||
return new[] { CheckForHeader() };
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Executes the action and returns it's status
|
||||
/// </summary>
|
||||
/// <param name="action"></param>
|
||||
/// <returns></returns>
|
||||
public override HealthCheckStatus ExecuteAction(HealthCheckAction action)
|
||||
{
|
||||
switch (action.Alias)
|
||||
{
|
||||
case SetHeaderInConfigAction:
|
||||
return SetHeaderInConfig();
|
||||
default:
|
||||
throw new InvalidOperationException("HTTP Header action requested is either not executable or does not exist");
|
||||
}
|
||||
}
|
||||
|
||||
protected HealthCheckStatus CheckForHeader()
|
||||
{
|
||||
var message = string.Empty;
|
||||
var success = false;
|
||||
|
||||
// Access the site home page and check for the click-jack protection header or meta tag
|
||||
var url = Runtime.ApplicationUrl;
|
||||
var request = WebRequest.Create(url);
|
||||
request.Method = "GET";
|
||||
try
|
||||
{
|
||||
var response = request.GetResponse();
|
||||
|
||||
// Check first for header
|
||||
success = DoHttpHeadersContainHeader(response);
|
||||
|
||||
// If not found, and available, check for meta-tag
|
||||
if (success == false && _metaTagOptionAvailable)
|
||||
{
|
||||
success = DoMetaTagsContainKeyForHeader(response);
|
||||
}
|
||||
|
||||
message = success
|
||||
? TextService.Localize($"healthcheck/{_localizedTextPrefix}CheckHeaderFound")
|
||||
: TextService.Localize($"healthcheck/{_localizedTextPrefix}CheckHeaderNotFound");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
message = TextService.Localize("healthcheck/healthCheckInvalidUrl", new[] { url.ToString(), ex.Message });
|
||||
}
|
||||
|
||||
var actions = new List<HealthCheckAction>();
|
||||
if (success == false)
|
||||
{
|
||||
actions.Add(new HealthCheckAction(SetHeaderInConfigAction, Id)
|
||||
{
|
||||
Name = TextService.Localize("healthcheck/setHeaderInConfig"),
|
||||
Description = TextService.Localize($"healthcheck/{_localizedTextPrefix}SetHeaderInConfigDescription")
|
||||
});
|
||||
}
|
||||
|
||||
return
|
||||
new HealthCheckStatus(message)
|
||||
{
|
||||
ResultType = success ? StatusResultType.Success : StatusResultType.Error,
|
||||
Actions = actions
|
||||
};
|
||||
}
|
||||
|
||||
private bool DoHttpHeadersContainHeader(WebResponse response)
|
||||
{
|
||||
return response.Headers.AllKeys.Contains(_header);
|
||||
}
|
||||
|
||||
private bool DoMetaTagsContainKeyForHeader(WebResponse response)
|
||||
{
|
||||
using (var stream = response.GetResponseStream())
|
||||
{
|
||||
if (stream == null) return false;
|
||||
using (var reader = new StreamReader(stream))
|
||||
{
|
||||
var html = reader.ReadToEnd();
|
||||
var metaTags = ParseMetaTags(html);
|
||||
return metaTags.ContainsKey(_header);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static Dictionary<string, string> ParseMetaTags(string html)
|
||||
{
|
||||
var regex = new Regex("<meta http-equiv=\"(.+?)\" content=\"(.+?)\"", RegexOptions.IgnoreCase);
|
||||
|
||||
return regex.Matches(html)
|
||||
.Cast<Match>()
|
||||
.ToDictionary(m => m.Groups[1].Value, m => m.Groups[2].Value);
|
||||
}
|
||||
|
||||
private HealthCheckStatus SetHeaderInConfig()
|
||||
{
|
||||
var errorMessage = string.Empty;
|
||||
var success = SaveHeaderToConfigFile(out errorMessage);
|
||||
|
||||
if (success)
|
||||
{
|
||||
return
|
||||
new HealthCheckStatus(TextService.Localize(string.Format("healthcheck/{0}SetHeaderInConfigSuccess", _localizedTextPrefix)))
|
||||
{
|
||||
ResultType = StatusResultType.Success
|
||||
};
|
||||
}
|
||||
|
||||
return
|
||||
new HealthCheckStatus(TextService.Localize("healthcheck/setHeaderInConfigError", new [] { errorMessage }))
|
||||
{
|
||||
ResultType = StatusResultType.Error
|
||||
};
|
||||
}
|
||||
|
||||
private bool SaveHeaderToConfigFile(out string errorMessage)
|
||||
{
|
||||
try
|
||||
{
|
||||
// There don't look to be any useful classes defined in https://msdn.microsoft.com/en-us/library/system.web.configuration(v=vs.110).aspx
|
||||
// for working with the customHeaders section, so working with the XML directly.
|
||||
var configFile = IOHelper.MapPath("~/Web.config");
|
||||
var doc = XDocument.Load(configFile);
|
||||
var systemWebServerElement = doc.XPathSelectElement("/configuration/system.webServer");
|
||||
var httpProtocolElement = systemWebServerElement.Element("httpProtocol");
|
||||
if (httpProtocolElement == null)
|
||||
{
|
||||
httpProtocolElement = new XElement("httpProtocol");
|
||||
systemWebServerElement.Add(httpProtocolElement);
|
||||
}
|
||||
|
||||
var customHeadersElement = httpProtocolElement.Element("customHeaders");
|
||||
if (customHeadersElement == null)
|
||||
{
|
||||
customHeadersElement = new XElement("customHeaders");
|
||||
httpProtocolElement.Add(customHeadersElement);
|
||||
}
|
||||
|
||||
var removeHeaderElement = customHeadersElement.Elements("remove")
|
||||
.SingleOrDefault(x => x.Attribute("name") != null &&
|
||||
x.Attribute("name")?.Value == _value);
|
||||
if (removeHeaderElement == null)
|
||||
{
|
||||
removeHeaderElement = new XElement("remove");
|
||||
removeHeaderElement.Add(new XAttribute("name", _header));
|
||||
customHeadersElement.Add(removeHeaderElement);
|
||||
}
|
||||
|
||||
var addHeaderElement = customHeadersElement.Elements("add")
|
||||
.SingleOrDefault(x => x.Attribute("name") != null &&
|
||||
x.Attribute("name").Value == _header);
|
||||
if (addHeaderElement == null)
|
||||
{
|
||||
addHeaderElement = new XElement("add");
|
||||
addHeaderElement.Add(new XAttribute("name", _header));
|
||||
addHeaderElement.Add(new XAttribute("value", _value));
|
||||
customHeadersElement.Add(addHeaderElement);
|
||||
}
|
||||
|
||||
doc.Save(configFile);
|
||||
|
||||
errorMessage = string.Empty;
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
errorMessage = ex.Message;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Xml.Linq;
|
||||
using System.Xml.XPath;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Services;
|
||||
|
||||
namespace Umbraco.Web.HealthCheck.Checks.Security
|
||||
@@ -18,202 +8,11 @@ namespace Umbraco.Web.HealthCheck.Checks.Security
|
||||
"Click-Jacking Protection",
|
||||
Description = "Checks if your site is allowed to be IFRAMEd by another site and thus would be susceptible to click-jacking.",
|
||||
Group = "Security")]
|
||||
public class ClickJackingCheck : HealthCheck
|
||||
public class ClickJackingCheck : BaseHttpHeaderCheck
|
||||
{
|
||||
private readonly ILocalizedTextService _textService;
|
||||
private readonly IRuntimeState _runtime;
|
||||
private readonly IHttpContextAccessor _httpContextAccessor;
|
||||
|
||||
private const string SetFrameOptionsHeaderInConfigActiobn = "setFrameOptionsHeaderInConfig";
|
||||
|
||||
private const string XFrameOptionsHeader = "X-Frame-Options";
|
||||
private const string XFrameOptionsValue = "sameorigin"; // Note can't use "deny" as that would prevent Umbraco itself using IFRAMEs
|
||||
|
||||
public ClickJackingCheck(ILocalizedTextService textService, IRuntimeState runtime, IHttpContextAccessor httpContextAccessor)
|
||||
public ClickJackingCheck(IRuntimeState runtime, ILocalizedTextService textService)
|
||||
: base(runtime, textService, "X-Frame-Options", "sameorigin", "clickJacking", true)
|
||||
{
|
||||
_textService = textService;
|
||||
_runtime = runtime;
|
||||
_httpContextAccessor = httpContextAccessor;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the status for this health check
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override IEnumerable<HealthCheckStatus> GetStatus()
|
||||
{
|
||||
//return the statuses
|
||||
return new[] { CheckForFrameOptionsHeader() };
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Executes the action and returns it's status
|
||||
/// </summary>
|
||||
/// <param name="action"></param>
|
||||
/// <returns></returns>
|
||||
public override HealthCheckStatus ExecuteAction(HealthCheckAction action)
|
||||
{
|
||||
switch (action.Alias)
|
||||
{
|
||||
case SetFrameOptionsHeaderInConfigActiobn:
|
||||
return SetFrameOptionsHeaderInConfig();
|
||||
default:
|
||||
throw new InvalidOperationException("HttpsCheck action requested is either not executable or does not exist");
|
||||
}
|
||||
}
|
||||
|
||||
private HealthCheckStatus CheckForFrameOptionsHeader()
|
||||
{
|
||||
var message = string.Empty;
|
||||
var success = false;
|
||||
|
||||
// Access the site home page and check for the click-jack protection header or meta tag
|
||||
var url = _runtime.ApplicationUrl;
|
||||
var request = WebRequest.Create(url);
|
||||
request.Method = "GET";
|
||||
try
|
||||
{
|
||||
var response = request.GetResponse();
|
||||
|
||||
// Check first for header
|
||||
success = DoHeadersContainFrameOptions(response);
|
||||
|
||||
// If not found, check for meta-tag
|
||||
if (success == false)
|
||||
{
|
||||
success = DoMetaTagsContainFrameOptions(response);
|
||||
}
|
||||
|
||||
message = success
|
||||
? _textService.Localize("healthcheck/clickJackingCheckHeaderFound")
|
||||
: _textService.Localize("healthcheck/clickJackingCheckHeaderNotFound");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
message = _textService.Localize("healthcheck/httpsCheckInvalidUrl", new[] { url.ToString(), ex.Message });
|
||||
}
|
||||
|
||||
var actions = new List<HealthCheckAction>();
|
||||
if (success == false)
|
||||
{
|
||||
actions.Add(new HealthCheckAction(SetFrameOptionsHeaderInConfigActiobn, Id)
|
||||
{
|
||||
Name = _textService.Localize("healthcheck/clickJackingSetHeaderInConfig"),
|
||||
Description = _textService.Localize("healthcheck/clickJackingSetHeaderInConfigDescription")
|
||||
});
|
||||
}
|
||||
|
||||
return
|
||||
new HealthCheckStatus(message)
|
||||
{
|
||||
ResultType = success ? StatusResultType.Success : StatusResultType.Error,
|
||||
Actions = actions
|
||||
};
|
||||
}
|
||||
|
||||
private static bool DoHeadersContainFrameOptions(WebResponse response)
|
||||
{
|
||||
return response.Headers.AllKeys.Contains(XFrameOptionsHeader);
|
||||
}
|
||||
|
||||
private static bool DoMetaTagsContainFrameOptions(WebResponse response)
|
||||
{
|
||||
using (var stream = response.GetResponseStream())
|
||||
{
|
||||
if (stream == null) return false;
|
||||
using (var reader = new StreamReader(stream))
|
||||
{
|
||||
var html = reader.ReadToEnd();
|
||||
var metaTags = ParseMetaTags(html);
|
||||
return metaTags.ContainsKey(XFrameOptionsHeader);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static Dictionary<string, string> ParseMetaTags(string html)
|
||||
{
|
||||
var regex = new Regex("<meta http-equiv=\"(.+?)\" content=\"(.+?)\"", RegexOptions.IgnoreCase);
|
||||
|
||||
return regex.Matches(html)
|
||||
.Cast<Match>()
|
||||
.ToDictionary(m => m.Groups[1].Value, m => m.Groups[2].Value);
|
||||
}
|
||||
|
||||
private HealthCheckStatus SetFrameOptionsHeaderInConfig()
|
||||
{
|
||||
var errorMessage = string.Empty;
|
||||
var success = SaveHeaderToConfigFile(out errorMessage);
|
||||
|
||||
if (success)
|
||||
{
|
||||
return
|
||||
new HealthCheckStatus(_textService.Localize("healthcheck/clickJackingSetHeaderInConfigSuccess"))
|
||||
{
|
||||
ResultType = StatusResultType.Success
|
||||
};
|
||||
}
|
||||
|
||||
return
|
||||
new HealthCheckStatus(_textService.Localize("healthcheck/clickJackingSetHeaderInConfigError", new [] { errorMessage }))
|
||||
{
|
||||
ResultType = StatusResultType.Error
|
||||
};
|
||||
}
|
||||
|
||||
private static bool SaveHeaderToConfigFile(out string errorMessage)
|
||||
{
|
||||
try
|
||||
{
|
||||
// There don't look to be any useful classes defined in https://msdn.microsoft.com/en-us/library/system.web.configuration(v=vs.110).aspx
|
||||
// for working with the customHeaders section, so working with the XML directly.
|
||||
var configFile = IOHelper.MapPath("~/Web.config");
|
||||
var doc = XDocument.Load(configFile);
|
||||
var systemWebServerElement = doc.XPathSelectElement("/configuration/system.webServer");
|
||||
var httpProtocolElement = systemWebServerElement.Element("httpProtocol");
|
||||
if (httpProtocolElement == null)
|
||||
{
|
||||
httpProtocolElement = new XElement("httpProtocol");
|
||||
systemWebServerElement.Add(httpProtocolElement);
|
||||
}
|
||||
|
||||
var customHeadersElement = httpProtocolElement.Element("customHeaders");
|
||||
if (customHeadersElement == null)
|
||||
{
|
||||
customHeadersElement = new XElement("customHeaders");
|
||||
httpProtocolElement.Add(customHeadersElement);
|
||||
}
|
||||
|
||||
var removeHeaderElement = customHeadersElement.Elements("remove")
|
||||
.SingleOrDefault(x => x.Attribute("name") != null &&
|
||||
x.Attribute("name").Value == XFrameOptionsHeader);
|
||||
if (removeHeaderElement == null)
|
||||
{
|
||||
removeHeaderElement = new XElement("remove");
|
||||
removeHeaderElement.Add(new XAttribute("name", XFrameOptionsHeader));
|
||||
customHeadersElement.Add(removeHeaderElement);
|
||||
}
|
||||
|
||||
var addHeaderElement = customHeadersElement.Elements("add")
|
||||
.SingleOrDefault(x => x.Attribute("name") != null &&
|
||||
x.Attribute("name").Value == XFrameOptionsHeader);
|
||||
if (addHeaderElement == null)
|
||||
{
|
||||
addHeaderElement = new XElement("add");
|
||||
addHeaderElement.Add(new XAttribute("name", XFrameOptionsHeader));
|
||||
addHeaderElement.Add(new XAttribute("value", XFrameOptionsValue));
|
||||
customHeadersElement.Add(addHeaderElement);
|
||||
}
|
||||
|
||||
doc.Save(configFile);
|
||||
|
||||
errorMessage = string.Empty;
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
errorMessage = ex.Message;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Web;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Services;
|
||||
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Services;
|
||||
|
||||
namespace Umbraco.Web.HealthCheck.Checks.Security
|
||||
{
|
||||
[HealthCheck(
|
||||
"E2048C48-21C5-4BE1-A80B-8062162DF124",
|
||||
"Cookie hijacking and protocol downgrade attacks Protection (Strict-Transport-Security Header (HSTS))",
|
||||
Description = "Checks if your site, when running with HTTPS, contains the Strict-Transport-Security Header (HSTS). If not, it adds with a default of 100 days.",
|
||||
Group = "Security")]
|
||||
public class HstsCheck : BaseHttpHeaderCheck
|
||||
{
|
||||
// The check is mostly based on the instructions in the OWASP CheatSheet
|
||||
// (https://www.owasp.org/index.php/HTTP_Strict_Transport_Security_Cheat_Sheet)
|
||||
// and the blogpost of Troy Hunt (https://www.troyhunt.com/understanding-http-strict-transport/)
|
||||
// If you want do to it perfectly, you have to submit it https://hstspreload.appspot.com/,
|
||||
// but then you should include subdomains and I wouldn't suggest to do that for Umbraco-sites.
|
||||
public HstsCheck(IRuntimeState runtime, ILocalizedTextService textService)
|
||||
: base(runtime, textService, "Strict-Transport-Security", "max-age=10886400; preload", "hSTS", true)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -100,7 +100,7 @@ namespace Umbraco.Web.HealthCheck.Checks.Security
|
||||
else
|
||||
{
|
||||
result = StatusResultType.Error;
|
||||
message = _textService.Localize("healthcheck/httpsCheckInvalidUrl", new[] { url, response.StatusDescription });
|
||||
message = _textService.Localize("healthcheck/healthCheckInvalidUrl", new[] { url, response.StatusDescription });
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -110,11 +110,11 @@ namespace Umbraco.Web.HealthCheck.Checks.Security
|
||||
{
|
||||
message = exception.Status == WebExceptionStatus.TrustFailure
|
||||
? _textService.Localize("healthcheck/httpsCheckInvalidCertificate", new [] { exception.Message })
|
||||
: _textService.Localize("healthcheck/httpsCheckInvalidUrl", new [] { url, exception.Message });
|
||||
: _textService.Localize("healthcheck/healthCheckInvalidUrl", new [] { url, exception.Message });
|
||||
}
|
||||
else
|
||||
{
|
||||
message = _textService.Localize("healthcheck/httpsCheckInvalidUrl", new[] { url, ex.Message });
|
||||
message = _textService.Localize("healthcheck/healthCheckInvalidUrl", new[] { url, ex.Message });
|
||||
}
|
||||
|
||||
result = StatusResultType.Error;
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Services;
|
||||
|
||||
namespace Umbraco.Web.HealthCheck.Checks.Security
|
||||
{
|
||||
[HealthCheck(
|
||||
"1CF27DB3-EFC0-41D7-A1BB-EA912064E071",
|
||||
"Content/MIME Sniffing Protection",
|
||||
Description = "Checks that your site contains a header used to protect against MIME sniffing vulnerabilities.",
|
||||
Group = "Security")]
|
||||
public class NoSniffCheck : BaseHttpHeaderCheck
|
||||
{
|
||||
public NoSniffCheck(IRuntimeState runtime, ILocalizedTextService textService)
|
||||
: base(runtime, textService, "X-Content-Type-Options", "nosniff", "noSniff", false)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Services;
|
||||
|
||||
namespace Umbraco.Web.HealthCheck.Checks.Security
|
||||
{
|
||||
[HealthCheck(
|
||||
"F4D2B02E-28C5-4999-8463-05759FA15C3A",
|
||||
"Cross-site scripting Protection (X-XSS-Protection header)",
|
||||
Description = "This header enables the Cross-site scripting (XSS) filter in your browser. It checks for the presence of the X-XSS-Protection-header.",
|
||||
Group = "Security")]
|
||||
public class XssProtectionCheck : BaseHttpHeaderCheck
|
||||
{
|
||||
// The check is mostly based on the instructions in the OWASP CheatSheet
|
||||
// (https://www.owasp.org/index.php/HTTP_Strict_Transport_Security_Cheat_Sheet)
|
||||
// and the blogpost of Troy Hunt (https://www.troyhunt.com/understanding-http-strict-transport/)
|
||||
// If you want do to it perfectly, you have to submit it https://hstspreload.appspot.com/,
|
||||
// but then you should include subdomains and I wouldn't suggest to do that for Umbraco-sites.
|
||||
public XssProtectionCheck(IRuntimeState runtime, ILocalizedTextService textService)
|
||||
: base(runtime, textService, "X-XSS-Protection", "1; mode=block", "xssProtection", true)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,7 @@ namespace Umbraco.Web.Models
|
||||
{
|
||||
public BackOfficeTour()
|
||||
{
|
||||
RequiredSections = new List<string>();
|
||||
RequiredSections = new List<string>();
|
||||
}
|
||||
|
||||
[DataMember(Name = "name")]
|
||||
@@ -28,5 +28,8 @@ namespace Umbraco.Web.Models
|
||||
public List<string> RequiredSections { get; set; }
|
||||
[DataMember(Name = "steps")]
|
||||
public BackOfficeTourStep[] Steps { get; set; }
|
||||
|
||||
[DataMember(Name = "culture")]
|
||||
public string Culture { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using AutoMapper;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Logging;
|
||||
@@ -50,17 +52,29 @@ namespace Umbraco.Web.Models.Mapping
|
||||
{
|
||||
//a language Id needs to be set for a property type that can be varried by language
|
||||
throw new InvalidOperationException($"No languageId found in mapping operation when one is required for the culture neutral property type {property.PropertyType.Alias}");
|
||||
}
|
||||
}
|
||||
|
||||
var result = new TDestination
|
||||
{
|
||||
Id = property.Id,
|
||||
Value = editor.GetValueEditor().ToEditor(property, DataTypeService, languageId),
|
||||
Alias = property.Alias,
|
||||
PropertyEditor = editor,
|
||||
Editor = editor.Alias
|
||||
};
|
||||
|
||||
// if there's a set of property aliases specified, we will check if the current property's value should be mapped.
|
||||
// if it isn't one of the ones specified in 'includeProperties', we will just return the result without mapping the Value.
|
||||
if (context.Options.Items.ContainsKey("IncludeProperties"))
|
||||
{
|
||||
var includeProperties = context.Options.Items["IncludeProperties"] as IEnumerable<string>;
|
||||
if (includeProperties != null && includeProperties.Contains(property.Alias) == false)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
// if no 'IncludeProperties' were specified or this property is set to be included - we will map the value and return.
|
||||
result.Value = editor.GetValueEditor().ToEditor(property, DataTypeService, languageId);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.PropertyEditors;
|
||||
|
||||
namespace Umbraco.Web.PropertyEditors.ParameterEditors
|
||||
{
|
||||
[ParameterEditor(Constants.PropertyEditors.MultiNodeTreePickerAlias, "Multiple Content Picker", "contentpicker")]
|
||||
public class MultipleContentPickerParameterEditor : ParameterEditor
|
||||
{
|
||||
public MultipleContentPickerParameterEditor()
|
||||
{
|
||||
Configuration.Add("multiPicker", "1");
|
||||
Configuration.Add("minNumber",0 );
|
||||
Configuration.Add("maxNumber", 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,7 @@ using Umbraco.Web.Models.Trees;
|
||||
using Umbraco.Web.WebApi.Filters;
|
||||
using System.Globalization;
|
||||
using Umbraco.Core.Models.Entities;
|
||||
using Umbraco.Web._Legacy.Actions;
|
||||
using Umbraco.Web._Legacy.Actions;
|
||||
|
||||
namespace Umbraco.Web.Trees
|
||||
{
|
||||
@@ -148,7 +148,7 @@ namespace Umbraco.Web.Trees
|
||||
}
|
||||
|
||||
// get child entities - if id is root, but user's start nodes do not contain the
|
||||
// root node, this returns the start nodes instead of root's children
|
||||
// root node, this returns the start nodes instead of root's children
|
||||
var langId = queryStrings["languageId"].TryConvertTo<int?>();
|
||||
var entities = GetChildEntities(id, langId.Success ? langId.Result : null).ToList();
|
||||
nodes.AddRange(entities.Select(x => GetSingleTreeNodeWithAccessCheck(x, id, queryStrings)).Where(x => x != null));
|
||||
@@ -194,8 +194,8 @@ namespace Umbraco.Web.Trees
|
||||
|
||||
entityId = entity.Id;
|
||||
}
|
||||
|
||||
IEntitySlim[] result;
|
||||
|
||||
IEntitySlim[] result;
|
||||
|
||||
// if a request is made for the root node but user has no access to
|
||||
// root node, return start nodes instead
|
||||
@@ -204,31 +204,31 @@ namespace Umbraco.Web.Trees
|
||||
result = UserStartNodes.Length > 0
|
||||
? Services.EntityService.GetAll(UmbracoObjectType, UserStartNodes).ToArray()
|
||||
: Array.Empty<IEntitySlim>();
|
||||
}
|
||||
else
|
||||
{
|
||||
result = Services.EntityService.GetChildren(entityId, UmbracoObjectType).ToArray();
|
||||
}
|
||||
|
||||
if (langId.HasValue)
|
||||
{
|
||||
//need to update all node names
|
||||
//TODO: This is not currently stored, we need to wait until U4-11128 is complete for this to work, in the meantime
|
||||
// we'll mock using this and it will just be some mock data
|
||||
foreach(var e in result)
|
||||
{
|
||||
if (e.AdditionalData.TryGetValue("VariantNames", out var variantNames))
|
||||
{
|
||||
var casted = (IDictionary<int, string>)variantNames;
|
||||
e.Name = casted[langId.Value];
|
||||
}
|
||||
else
|
||||
{
|
||||
e.Name = e.Name + " (lang: " + langId.Value + ")";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
result = Services.EntityService.GetChildren(entityId, UmbracoObjectType).ToArray();
|
||||
}
|
||||
|
||||
if (langId.HasValue)
|
||||
{
|
||||
//need to update all node names
|
||||
//TODO: This is not currently stored, we need to wait until U4-11128 is complete for this to work, in the meantime
|
||||
// we'll mock using this and it will just be some mock data
|
||||
foreach(var e in result)
|
||||
{
|
||||
if (e.AdditionalData.TryGetValue("VariantNames", out var variantNames))
|
||||
{
|
||||
var casted = (IDictionary<int, string>)variantNames;
|
||||
e.Name = casted[langId.Value];
|
||||
}
|
||||
else
|
||||
{
|
||||
e.Name = e.Name + " (lang: " + langId.Value + ")";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -389,7 +389,7 @@ namespace Umbraco.Web.Trees
|
||||
/// <remarks>By default the user must have Browse permissions to see the node in the Content tree</remarks>
|
||||
/// <returns></returns>
|
||||
internal bool CanUserAccessNode(IUmbracoEntity doc, IEnumerable<MenuItem> allowedUserOptions, int? langId)
|
||||
{
|
||||
{
|
||||
//TODO: At some stage when we implement permissions on languages we'll need to take care of langId
|
||||
return allowedUserOptions.Select(x => x.Action).OfType<ActionBrowse>().Any();
|
||||
}
|
||||
|
||||
@@ -140,6 +140,8 @@
|
||||
<Compile Include="Editors\PreviewController.cs" />
|
||||
<Compile Include="Editors\TemplateController.cs" />
|
||||
<Compile Include="Editors\TourController.cs" />
|
||||
<Compile Include="HealthCheck\Checks\Security\XssProtectionCheck.cs" />
|
||||
<Compile Include="HealthCheck\Checks\Security\HstsCheck.cs" />
|
||||
<Compile Include="Editors\UserEditorAuthorizationHelper.cs" />
|
||||
<Compile Include="Editors\UserGroupAuthorizationAttribute.cs" />
|
||||
<Compile Include="Editors\UserGroupEditorAuthorizationHelper.cs" />
|
||||
@@ -186,6 +188,8 @@
|
||||
<Compile Include="HealthCheck\Checks\Config\TraceCheck.cs" />
|
||||
<Compile Include="HealthCheck\Checks\Config\ValueComparisonType.cs" />
|
||||
<Compile Include="HealthCheck\Checks\Config\CompilationDebugCheck.cs" />
|
||||
<Compile Include="HealthCheck\Checks\Security\BaseHttpHeaderCheck.cs" />
|
||||
<Compile Include="HealthCheck\Checks\Security\NoSniffCheck.cs" />
|
||||
<Compile Include="HealthCheck\Checks\Services\SmtpCheck.cs" />
|
||||
<Compile Include="HealthCheck\Checks\Permissions\FolderAndFilePermissionsCheck.cs" />
|
||||
<Compile Include="HealthCheck\Checks\Security\ExcessiveHeadersCheck.cs" />
|
||||
|
||||
Reference in New Issue
Block a user