Merge branch 'dev-v7' of https://github.com/umbraco/Umbraco-CMS into pr/2507
This commit is contained in:
@@ -24,6 +24,7 @@ Remember, we're a friendly bunch and are happy with whatever contribution you mi
|
||||
* [Working with the source code](#working-with-the-source-code)
|
||||
* [What branch should I target for my contributions?](#what-branch-should-i-target-for-my-contributions)
|
||||
* [Building Umbraco from source code](#building-umbraco-from-source-code)
|
||||
* [Keeping your Umbraco fork in sync with the main repository](#keeping-your-umbraco-fork-in-sync-with-the-main-repository)
|
||||
|
||||
[How do I even begin?](#how-do-i-even-begin)
|
||||
|
||||
@@ -146,6 +147,29 @@ Alternatively, you can open `src\umbraco.sln` in Visual Studio 2017 ([the commun
|
||||
|
||||
After this build completes, you should be able to hit `F5` in Visual Studio to build and run the project. A IISExpress webserver will start and the Umbraco installer will pop up in your browser, follow the directions there to get a working Umbraco install up and running.
|
||||
|
||||
### Keeping your Umbraco fork in sync with the main repository
|
||||
|
||||
We recommend you sync with our repository before you submit your pull request. That way, you can fix any potential merge conflicts and make our lives a little bit easier.
|
||||
|
||||
Also, if you've submitted a pull request three weeks ago and want to work on something new, you'll want to get the latest code to build against of course.
|
||||
|
||||
To sync your fork with this original one, you'll have to add the upstream url, you only have to do this once:
|
||||
|
||||
```
|
||||
git remote add upstream https://github.com/umbraco/Umbraco-CMS.git
|
||||
```
|
||||
|
||||
Then when you want to get the changes from the main repository:
|
||||
|
||||
```
|
||||
git fetch upstream
|
||||
git rebase upstream/dev-v7
|
||||
```
|
||||
|
||||
In this command we're syncing with the `dev-v7` branch, but you can of course choose another one if needed.
|
||||
|
||||
(More info on how this works: [http://robots.thoughtbot.com/post/5133345960/keeping-a-git-fork-updated](http://robots.thoughtbot.com/post/5133345960/keeping-a-git-fork-updated))
|
||||
|
||||
## How do I even begin?
|
||||
|
||||
Great question! The short version goes like this:
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
----------------------------------------------------
|
||||
|
||||
*** IMPORTANT NOTICE FOR 7.7 UPGRADES ***
|
||||
*** IMPORTANT NOTICE FOR UPGRADES FROM VERSIONS BELOW 7.7.0 ***
|
||||
|
||||
Be sure to read the version specific upgrade information before proceeding:
|
||||
https://our.umbraco.org/documentation/Getting-Started/Setup/Upgrading/version-specific#version-7-7-0
|
||||
|
||||
@@ -37,15 +37,15 @@ namespace Umbraco.Core.Security
|
||||
var username = identity.GetUserName();
|
||||
var session = identity.FindFirstValue(Constants.Security.SessionIdClaimType);
|
||||
var securityStamp = identity.FindFirstValue(Microsoft.AspNet.Identity.Constants.DefaultSecurityStampClaimType);
|
||||
var startContentId = identity.FindFirstValue(Constants.Security.StartContentNodeIdClaimType);
|
||||
var startContentId = identity.FindFirstValue(Constants.Security.StartContentNodeIdClaimType);
|
||||
var startMediaId = identity.FindFirstValue(Constants.Security.StartMediaNodeIdClaimType);
|
||||
|
||||
var culture = identity.FindFirstValue(ClaimTypes.Locality);
|
||||
var id = identity.FindFirstValue(ClaimTypes.NameIdentifier);
|
||||
var id = identity.FindFirstValue(ClaimTypes.NameIdentifier);
|
||||
var realName = identity.FindFirstValue(ClaimTypes.GivenName);
|
||||
|
||||
if (username == null || startContentId == null || startMediaId == null
|
||||
|| culture == null || id == null
|
||||
if (username == null || startContentId == null || startMediaId == null
|
||||
|| culture == null || id == null
|
||||
|| realName == null || session == null)
|
||||
throw new InvalidOperationException("Cannot create a " + typeof(UmbracoBackOfficeIdentity) + " from " + typeof(ClaimsIdentity) + " since there are missing required claims");
|
||||
|
||||
@@ -62,7 +62,7 @@ namespace Umbraco.Core.Security
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new InvalidOperationException("Cannot create a " + typeof(UmbracoBackOfficeIdentity) + " from " + typeof(ClaimsIdentity) + " since the data is not formatted correctly - either content or media start Ids could not be parsed as JSON", e);
|
||||
}
|
||||
}
|
||||
|
||||
var roles = identity.FindAll(x => x.Type == DefaultRoleClaimType).Select(role => role.Value).ToList();
|
||||
var allowedApps = identity.FindAll(x => x.Type == Constants.Security.AllowedApplicationsClaimType).Select(app => app.Value).ToList();
|
||||
@@ -165,7 +165,7 @@ namespace Umbraco.Core.Security
|
||||
{
|
||||
foreach (var claim in claimsIdentity.Claims)
|
||||
{
|
||||
//In one special case we will replace a claim if it exists already and that is the
|
||||
//In one special case we will replace a claim if it exists already and that is the
|
||||
// Forms auth claim for name which automatically gets added
|
||||
TryRemoveClaim(FindFirst(x => x.Type == claim.Type && x.Issuer == "Forms"));
|
||||
|
||||
@@ -187,15 +187,15 @@ namespace Umbraco.Core.Security
|
||||
{
|
||||
ClaimTypes.NameIdentifier, //id
|
||||
ClaimTypes.Name, //username
|
||||
ClaimTypes.GivenName,
|
||||
ClaimTypes.GivenName,
|
||||
Constants.Security.StartContentNodeIdClaimType,
|
||||
Constants.Security.StartMediaNodeIdClaimType,
|
||||
ClaimTypes.Locality,
|
||||
Constants.Security.StartMediaNodeIdClaimType,
|
||||
ClaimTypes.Locality,
|
||||
Constants.Security.SessionIdClaimType,
|
||||
Microsoft.AspNet.Identity.Constants.DefaultSecurityStampClaimType
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds claims based on the UserData data
|
||||
@@ -222,23 +222,19 @@ namespace Umbraco.Core.Security
|
||||
AddClaim(new Claim(ClaimTypes.Locality, Culture, ClaimValueTypes.String, Issuer, Issuer, this));
|
||||
|
||||
if (HasClaim(x => x.Type == Constants.Security.SessionIdClaimType) == false && SessionId.IsNullOrWhiteSpace() == false)
|
||||
{
|
||||
AddClaim(new Claim(Constants.Security.SessionIdClaimType, SessionId, ClaimValueTypes.String, Issuer, Issuer, this));
|
||||
|
||||
//The security stamp claim is also required... this is because this claim type is hard coded
|
||||
// by the SecurityStampValidator, see: https://katanaproject.codeplex.com/workitem/444
|
||||
if (HasClaim(x => x.Type == Microsoft.AspNet.Identity.Constants.DefaultSecurityStampClaimType) == false)
|
||||
{
|
||||
AddClaim(new Claim(Microsoft.AspNet.Identity.Constants.DefaultSecurityStampClaimType, SecurityStamp, ClaimValueTypes.String, Issuer, Issuer, this));
|
||||
}
|
||||
}
|
||||
//The security stamp claim is also required... this is because this claim type is hard coded
|
||||
// by the SecurityStampValidator, see: https://katanaproject.codeplex.com/workitem/444
|
||||
if (HasClaim(x => x.Type == Microsoft.AspNet.Identity.Constants.DefaultSecurityStampClaimType) == false)
|
||||
AddClaim(new Claim(Microsoft.AspNet.Identity.Constants.DefaultSecurityStampClaimType, SecurityStamp, ClaimValueTypes.String, Issuer, Issuer, this));
|
||||
|
||||
//Add each app as a separate claim
|
||||
if (HasClaim(x => x.Type == Constants.Security.AllowedApplicationsClaimType) == false)
|
||||
{
|
||||
foreach (var application in AllowedApplications)
|
||||
{
|
||||
AddClaim(new Claim(Constants.Security.AllowedApplicationsClaimType, application, ClaimValueTypes.String, Issuer, Issuer, this));
|
||||
AddClaim(new Claim(Constants.Security.AllowedApplicationsClaimType, application, ClaimValueTypes.String, Issuer, Issuer, this));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -253,8 +249,8 @@ namespace Umbraco.Core.Security
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
protected internal UserData UserData { get; private set; }
|
||||
@@ -332,4 +328,4 @@ namespace Umbraco.Core.Security
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -280,7 +280,6 @@
|
||||
.umb-grid .umb-control {
|
||||
position: relative;
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
margin-left: 10px;
|
||||
margin-right: 10px;
|
||||
margin-bottom: 10px;
|
||||
|
||||
@@ -40,6 +40,16 @@
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.umb-contentpicker__min-max-help {
|
||||
font-size: 13px;
|
||||
margin-top: 5px;
|
||||
color: @gray-4;
|
||||
}
|
||||
|
||||
.show-validation .umb-contentpicker__min-max-help {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.umb-contentpicker small {
|
||||
|
||||
&:not(:last-child) {
|
||||
@@ -109,22 +119,22 @@ ul.color-picker li a {
|
||||
}
|
||||
|
||||
/* pre-value editor */
|
||||
/*.control-group.color-picker-preval:before {
|
||||
content: "";
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
height: 100%;
|
||||
}*/
|
||||
|
||||
/*.control-group.color-picker-preval div.thumbnail {
|
||||
display: inline-block;
|
||||
/*.control-group.color-picker-preval:before {
|
||||
content: "";
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
}*/
|
||||
.control-group.color-picker-preval div.color-picker-prediv {
|
||||
display: inline-block;
|
||||
height: 100%;
|
||||
}*/
|
||||
|
||||
/*.control-group.color-picker-preval div.thumbnail {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
}*/
|
||||
.control-group.color-picker-preval div.color-picker-prediv {
|
||||
display: inline-block;
|
||||
width: 60%;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.control-group.color-picker-preval pre {
|
||||
display: inline;
|
||||
margin-right: 20px;
|
||||
@@ -136,18 +146,18 @@ ul.color-picker li a {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.control-group.color-picker-preval btn {
|
||||
.control-group.color-picker-preval btn {
|
||||
//vertical-align: middle;
|
||||
}
|
||||
}
|
||||
|
||||
.control-group.color-picker-preval input[type="text"] {
|
||||
min-width: 40%;
|
||||
width: 40%;
|
||||
display: inline-block;
|
||||
margin-right: 20px;
|
||||
.control-group.color-picker-preval input[type="text"] {
|
||||
min-width: 40%;
|
||||
width: 40%;
|
||||
display: inline-block;
|
||||
margin-right: 20px;
|
||||
margin-top: 1px;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.control-group.color-picker-preval label {
|
||||
border: solid @white 1px;
|
||||
padding: 6px;
|
||||
@@ -203,10 +213,22 @@ ul.color-picker li a {
|
||||
|
||||
|
||||
|
||||
.umb-thumbnails{
|
||||
position: relative;
|
||||
.umb-thumbnails {
|
||||
position: relative;
|
||||
display: flex;
|
||||
-ms-flex-direction: row;
|
||||
-webkit-flex-direction: row;
|
||||
flex-direction: row;
|
||||
-ms-flex-wrap: wrap;
|
||||
-webkit-flex-wrap: wrap;
|
||||
flex-wrap: wrap;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
.umb-thumbnails > li.icon {
|
||||
width: 14%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.umb-thumbnails i{margin: auto;}
|
||||
.umb-thumbnails a{
|
||||
|
||||
@@ -100,6 +100,27 @@
|
||||
.color-green, .color-green i{color: @green-d1 !important;}
|
||||
.color-yellow, .color-yellow i{color: @yellow-d1 !important;}
|
||||
|
||||
/* Colors based on http://zavoloklom.github.io/material-design-color-palette/colors.html */
|
||||
.color-black, .color-black i { color: #000 !important; }
|
||||
.color-blue-grey, .color-blue-grey i { color: #607d8b !important; }
|
||||
.color-grey, .color-grey i { color: #9e9e9e !important; }
|
||||
.color-brown, .color-brown i { color: #795548 !important; }
|
||||
.color-blue, .color-blue i { color: #2196f3 !important; }
|
||||
.color-light-blue, .color-light-blue i {color: #03a9f4 !important; }
|
||||
.color-cyan, .color-cyan i { color: #00bcd4 !important; }
|
||||
.color-green, .color-green i { color: #4caf50 !important; }
|
||||
.color-light-green, .color-light-green i {color: #8bc34a !important; }
|
||||
.color-lime, .color-lime i { color: #cddc39 !important; }
|
||||
.color-yellow, .color-yellow i { color: #ffeb3b !important; }
|
||||
.color-amber, .color-amber i { color: #ffc107 !important; }
|
||||
.color-orange, .color-orange i { color: #ff9800 !important; }
|
||||
.color-deep-orange, .color-deep-orange i { color: #ff5722 !important; }
|
||||
.color-red, .color-red i { color: #f44336 !important; }
|
||||
.color-pink, .color-pink i { color: #e91e63 !important; }
|
||||
.color-purple,.color-purple i { color: #9c27b0 !important; }
|
||||
.color-deep-purple, .color-deep-purple i { color: #673ab7 !important; }
|
||||
.color-indigo, .color-indigo i { color: #3f51b5 !important; }
|
||||
|
||||
|
||||
// Scaffolding
|
||||
// -------------------------
|
||||
|
||||
@@ -7,14 +7,13 @@ angular.module("umbraco")
|
||||
$scope.icons = icons;
|
||||
});
|
||||
|
||||
$scope.submitClass = function (icon) {
|
||||
$scope.submitClass = function(icon){
|
||||
if($scope.color) {
|
||||
$scope.submit(icon + " " + $scope.color);
|
||||
}
|
||||
else {
|
||||
$scope.submit(icon);
|
||||
else {
|
||||
$scope.submit(icon);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
);
|
||||
@@ -16,24 +16,25 @@
|
||||
|
||||
<div class="umb-control-group">
|
||||
<select ng-model="color" class="input-block-level">
|
||||
<option value="">
|
||||
<localize key="colors_black">Black</localize>
|
||||
</option>
|
||||
<option value="color-green">
|
||||
<localize key="colors_green">Green</localize>
|
||||
</option>
|
||||
<option value="color-yellow">
|
||||
<localize key="colors_yellow">Yellow</localize>
|
||||
</option>
|
||||
<option value="color-orange">
|
||||
<localize key="colors_orange">Orange</localize>
|
||||
</option>
|
||||
<option value="color-blue">
|
||||
<localize key="colors_blue">Blue</localize>
|
||||
</option>
|
||||
<option value="color-red">
|
||||
<localize key="colors_red">Red</localize>
|
||||
</option>
|
||||
<option value=""><localize key="colors_black">Black</localize></option>
|
||||
<option value="color-blue-grey"><localize key="colors_bluegrey">Blue Grey</localize></option>
|
||||
<option value="color-grey"><localize key="colors_grey">Grey</localize></option>
|
||||
<option value="color-brown"><localize key="colors_brown">Brown</localize></option>
|
||||
<option value="color-blue"><localize key="colors_blue">Blue</localize></option>
|
||||
<option value="color-light-blue"><localize key="colors_lightblue">Light Blue</localize></option>
|
||||
<option value="color-cyan"><localize key="colors_cyan">Cyan</localize></option>
|
||||
<option value="color-green"><localize key="colors_green">Green</localize></option>
|
||||
<option value="color-light-green"><localize key="colors_lightgreen">Light Green</localize></option>
|
||||
<option value="color-yellow"><localize key="colors_yellow">Yellow</localize></option>
|
||||
<option value="color-lime"><localize key="colors_lime">Lime</localize></option>
|
||||
<option value="color-amber"><localize key="colors_amber">Amber</localize></option>
|
||||
<option value="color-orange"><localize key="colors_orange">Orange</localize></option>
|
||||
<option value="color-deep-orange"><localize key="colors_deeporange">Deep Orange</localize></option>
|
||||
<option value="color-red"><localize key="colors_red">Red</localize></option>
|
||||
<option value="color-pink"><localize key="colors_pink">Pink</localize></option>
|
||||
<option value="color-purple"><localize key="colors_purple">Purple</localize></option>
|
||||
<option value="color-deep-purple"><localize key="colors_deeppurple">Deep Purple</localize></option>
|
||||
<option value="color-indigo"><localize key="colors_indigo">Indigo</localize></option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -47,7 +47,17 @@
|
||||
</a>
|
||||
</div>
|
||||
<div class="umb-table-cell" ng-repeat="column in itemProperties">
|
||||
<span title="{{column.header}}: {{item[column.alias]}}">{{item[column.alias]}}</span>
|
||||
<span title="{{column.header}}: {{item[column.alias]}}">
|
||||
|
||||
<div ng-if="!column.isSensitive">
|
||||
{{item[column.alias]}}
|
||||
</div>
|
||||
|
||||
<em ng-show="column.isSensitive" class="muted">
|
||||
<localize key="content_isSensitiveValue_short"></localize>
|
||||
</em>
|
||||
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+34
-1
@@ -20,7 +20,7 @@
|
||||
</umb-node-preview>
|
||||
</div>
|
||||
|
||||
<a ng-show="model.config.multiPicker === true || renderModel.length === 0"
|
||||
<a ng-show="model.config.multiPicker === true && renderModel.length < model.config.maxNumber || renderModel.length === 0 || !model.config.maxNumber"
|
||||
class="umb-node-preview-add"
|
||||
href=""
|
||||
ng-click="openContentPicker()"
|
||||
@@ -28,6 +28,39 @@
|
||||
<localize key="general_add">Add</localize>
|
||||
</a>
|
||||
|
||||
<div class="umb-contentpicker__min-max-help">
|
||||
|
||||
<!-- Both min and max items -->
|
||||
<span ng-if="model.config.minNumber && model.config.maxNumber && model.config.minNumber !== model.config.maxNumber">
|
||||
<span ng-if="renderModel.length < model.config.maxNumber">Add between {{model.config.minNumber}} and {{model.config.maxNumber}} items</span>
|
||||
<span ng-if="renderModel.length > model.config.maxNumber">
|
||||
<localize key="validation_maxCount">You can only have</localize> {{model.config.maxNumber}} <localize key="validation_itemsSelected"> items selected</localize>
|
||||
</span>
|
||||
</span>
|
||||
|
||||
<!-- Equal min and max -->
|
||||
<span ng-if="model.config.minNumber && model.config.maxNumber && model.config.minNumber === model.config.maxNumber">
|
||||
<span ng-if="renderModel.length < model.config.maxNumber">Add {{model.config.minNumber - renderModel.length}} item(s)</span>
|
||||
<span ng-if="renderModel.length > model.config.maxNumber">
|
||||
<localize key="validation_maxCount">You can only have</localize> {{model.config.maxNumber}} <localize key="validation_itemsSelected"> items selected</localize>
|
||||
</span>
|
||||
</span>
|
||||
|
||||
<!-- Only max -->
|
||||
<span ng-if="!model.config.minNumber && model.config.maxNumber">
|
||||
<span ng-if="renderModel.length < model.config.maxNumber">Add up to {{model.config.maxNumber}} items</span>
|
||||
<span ng-if="renderModel.length > model.config.maxNumber">
|
||||
<localize key="validation_maxCount">You can only have</localize> {{model.config.maxNumber}} <localize key="validation_itemsSelected">items selected</localize>
|
||||
</span>
|
||||
</span>
|
||||
|
||||
<!-- Only min -->
|
||||
<span ng-if="model.config.minNumber && !model.config.maxNumber && renderModel.length < model.config.minNumber">
|
||||
Add at least {{model.config.minNumber}} item(s)
|
||||
</span>
|
||||
|
||||
</div>
|
||||
|
||||
<!--These are here because we need ng-form fields to validate against-->
|
||||
<input type="hidden" name="minCount" ng-model="renderModel" />
|
||||
<input type="hidden" name="maxCount" ng-model="renderModel" />
|
||||
|
||||
+22
-2
@@ -30,15 +30,14 @@
|
||||
vm.dragLeave = dragLeave;
|
||||
vm.onFilesQueue = onFilesQueue;
|
||||
vm.onUploadComplete = onUploadComplete;
|
||||
markAsSensitive();
|
||||
|
||||
function activate() {
|
||||
|
||||
if ($scope.entityType === 'media') {
|
||||
mediaTypeHelper.getAllowedImagetypes(vm.nodeId).then(function (types) {
|
||||
vm.acceptedMediatypes = types;
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function selectAll($event) {
|
||||
@@ -87,6 +86,27 @@
|
||||
$scope.getContent($scope.contentId);
|
||||
}
|
||||
|
||||
function markAsSensitive() {
|
||||
angular.forEach($scope.options.includeProperties, function (option) {
|
||||
option.isSensitive = false;
|
||||
|
||||
angular.forEach($scope.items,
|
||||
function (item) {
|
||||
|
||||
angular.forEach(item.properties,
|
||||
function (property) {
|
||||
|
||||
if (option.alias === property.alias) {
|
||||
option.isSensitive = property.isSensitive;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
activate();
|
||||
|
||||
}
|
||||
|
||||
+7
-1
@@ -46,6 +46,7 @@ function MarkdownEditorController($scope, $element, assetsService, dialogService
|
||||
// init the md editor after this digest because the DOM needs to be ready first
|
||||
// so run the init on a timeout
|
||||
$timeout(function () {
|
||||
$scope.markdownEditorInitComplete = false;
|
||||
var converter2 = new Markdown.Converter();
|
||||
var editor2 = new Markdown.Editor(converter2, "-" + $scope.model.alias);
|
||||
editor2.run();
|
||||
@@ -59,7 +60,12 @@ function MarkdownEditorController($scope, $element, assetsService, dialogService
|
||||
editor2.hooks.set("onPreviewRefresh", function () {
|
||||
// We must manually update the model as there is no way to hook into the markdown editor events without exstensive edits to the library.
|
||||
if ($scope.model.value !== $("textarea", $element).val()) {
|
||||
angularHelper.getCurrentForm($scope).$setDirty();
|
||||
if ($scope.markdownEditorInitComplete) {
|
||||
//only set dirty after init load to avoid "unsaved" dialogue when we don't want it
|
||||
angularHelper.getCurrentForm($scope).$setDirty();
|
||||
} else {
|
||||
$scope.markdownEditorInitComplete = true;
|
||||
}
|
||||
$scope.model.value = $("textarea", $element).val();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -359,7 +359,8 @@ angular.module("umbraco")
|
||||
//this is instead of doing a watch on the model.value = faster
|
||||
$scope.model.onValueChanged = function (newVal, oldVal) {
|
||||
//update the display val again if it has changed from the server;
|
||||
tinyMceEditor.setContent(newVal, { format: 'raw' });
|
||||
//uses an empty string in the editor when the value is null
|
||||
tinyMceEditor.setContent(newVal || "", { format: 'raw' });
|
||||
//we need to manually fire this event since it is only ever fired based on loading from the DOM, this
|
||||
// is required for our plugins listening to this event to execute
|
||||
tinyMceEditor.fire('LoadContent', null);
|
||||
|
||||
@@ -661,7 +661,7 @@
|
||||
<area alias="graphicheadline">
|
||||
<key alias="backgroundcolor">Baggrundsfarve</key>
|
||||
<key alias="bold">Fed</key>
|
||||
<key alias="color">Tekst farve</key>
|
||||
<key alias="color">Tekstfarve</key>
|
||||
<key alias="font">Skrifttype</key>
|
||||
<key alias="text">Tekst</key>
|
||||
</area>
|
||||
@@ -1259,9 +1259,9 @@ Mange hilsner fra Umbraco robotten
|
||||
|
||||
|
||||
<key alias="styles">Typografi</key>
|
||||
<key alias="stylesDetails">Vælg, hvilke typografiværdier, en redaktør kan ændre</key>
|
||||
<key alias="stylesDetails">Vælg hvilke typografiværdier en redaktør kan ændre</key>
|
||||
|
||||
<key alias="settingDialogDetails">Indstillinger gemmes kun, hvis den indtaste json-konfiguration er gyldig</key>
|
||||
<key alias="settingDialogDetails">Indstillinger gemmes kun, hvis den indtastede json-konfiguration er gyldig</key>
|
||||
|
||||
<key alias="allowAllEditors">Tillad alle editorer</key>
|
||||
<key alias="allowAllRowConfigurations">Tillad alle rækkekonfigurationer</key>
|
||||
@@ -1272,7 +1272,7 @@ Mange hilsner fra Umbraco robotten
|
||||
<key alias="areAdded">er tilføjet</key>
|
||||
|
||||
<key alias="maxItems">Maksimalt emner</key>
|
||||
<key alias="maxItemsDescription">Efterlad blank eller sat til 0 ubegrænset for</key>
|
||||
<key alias="maxItemsDescription">Efterlad blank eller sæt til 0 for ubegrænset</key>
|
||||
|
||||
</area>
|
||||
<area alias="contentTypeEditor">
|
||||
@@ -1282,7 +1282,7 @@ Mange hilsner fra Umbraco robotten
|
||||
<key alias="addNewTab">Tilføj ny fane</key>
|
||||
<key alias="addAnotherTab">Tilføj endnu en fane</key>
|
||||
<key alias="inheritedFrom">Nedarvet fra</key>
|
||||
<key alias="addProperty">Tilføj property</key>
|
||||
<key alias="addProperty">Tilføj egenskab</key>
|
||||
<key alias="requiredLabel">Påkrævet label</key>
|
||||
|
||||
<key alias="enableListViewHeading">Aktiver listevisning</key>
|
||||
@@ -1473,7 +1473,6 @@ Mange hilsner fra Umbraco robotten
|
||||
<key alias="noLogin">har endnu ikke logget ind</key>
|
||||
<key alias="oldPassword">Gammelt kodeord</key>
|
||||
<key alias="password">Adgangskode</key>
|
||||
<key alias="removePhoto">Fjern billede</key>
|
||||
<key alias="resetPassword">Nulstil kodeord</key>
|
||||
<key alias="passwordChanged">Dit kodeord er blevet ændret!</key>
|
||||
<key alias="passwordConfirm">Bekræft venligst dit nye kodeord</key>
|
||||
|
||||
@@ -229,6 +229,7 @@
|
||||
<key alias="removeTextBox">Remove this text box</key>
|
||||
<key alias="contentRoot">Content root</key>
|
||||
<key alias="isSensitiveValue">This value is hidden. If you need access to view this value please contact your website administrator.</key>
|
||||
<key alias="isSensitiveValue_short">This value is hidden.</key>
|
||||
</area>
|
||||
<area alias="blueprints">
|
||||
<key alias="createBlueprintFrom">Create a new Content Template from '%0%'</key>
|
||||
@@ -662,7 +663,20 @@
|
||||
<key alias="yellow">Yellow</key>
|
||||
<key alias="orange">Orange</key>
|
||||
<key alias="blue">Blue</key>
|
||||
<key alias="bluegrey">Blue Grey</key>
|
||||
<key alias="grey">Grey</key>
|
||||
<key alias="brown">Brown</key>
|
||||
<key alias="lightblue">Light Blue</key>
|
||||
<key alias="cyan">Cyan</key>
|
||||
<key alias="lightgreen">Light Green</key>
|
||||
<key alias="lime">Lime</key>
|
||||
<key alias="amber">Amber</key>
|
||||
<key alias="deeporange">Deep Orange</key>
|
||||
<key alias="red">Red</key>
|
||||
<key alias="pink">Pink</key>
|
||||
<key alias="purple">Purple</key>
|
||||
<key alias="deeppurple">Deep Purple</key>
|
||||
<key alias="indigo">Indigo</key>
|
||||
</area>
|
||||
|
||||
<area alias="shortcuts">
|
||||
|
||||
@@ -229,6 +229,7 @@
|
||||
<key alias="removeTextBox">Remove this text box</key>
|
||||
<key alias="contentRoot">Content root</key>
|
||||
<key alias="isSensitiveValue">This value is hidden. If you need access to view this value please contact your website administrator.</key>
|
||||
<key alias="isSensitiveValue_short">This value is hidden.</key>
|
||||
</area>
|
||||
<area alias="blueprints">
|
||||
<key alias="createBlueprintFrom">Create a new Content Template from '%0%'</key>
|
||||
@@ -660,7 +661,20 @@
|
||||
<key alias="yellow">Yellow</key>
|
||||
<key alias="orange">Orange</key>
|
||||
<key alias="blue">Blue</key>
|
||||
<key alias="bluegrey">Blue Grey</key>
|
||||
<key alias="grey">Grey</key>
|
||||
<key alias="brown">Brown</key>
|
||||
<key alias="lightblue">Light Blue</key>
|
||||
<key alias="cyan">Cyan</key>
|
||||
<key alias="lightgreen">Light Green</key>
|
||||
<key alias="lime">Lime</key>
|
||||
<key alias="amber">Amber</key>
|
||||
<key alias="deeporange">Deep Orange</key>
|
||||
<key alias="red">Red</key>
|
||||
<key alias="pink">Pink</key>
|
||||
<key alias="purple">Purple</key>
|
||||
<key alias="deeppurple">Deep Purple</key>
|
||||
<key alias="indigo">Indigo</key>
|
||||
</area>
|
||||
<area alias="shortcuts">
|
||||
<key alias="addTab">Add tab</key>
|
||||
|
||||
@@ -1,29 +1,18 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Formatting;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Reflection;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Web;
|
||||
using System.Web.Http;
|
||||
using System.Web.Http.ModelBinding;
|
||||
using System.Web.Security;
|
||||
using AutoMapper;
|
||||
using Examine.LuceneEngine.SearchCriteria;
|
||||
using Examine.SearchCriteria;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
using Umbraco.Core.Models.Membership;
|
||||
using Umbraco.Core.Persistence;
|
||||
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
|
||||
using Umbraco.Core.Security;
|
||||
using Umbraco.Core.Services;
|
||||
@@ -33,10 +22,7 @@ using Umbraco.Web.Models.ContentEditing;
|
||||
using Umbraco.Web.Mvc;
|
||||
using Umbraco.Web.WebApi.Binders;
|
||||
using Umbraco.Web.WebApi.Filters;
|
||||
using umbraco;
|
||||
using Constants = Umbraco.Core.Constants;
|
||||
using Examine;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Umbraco.Web.Editors
|
||||
{
|
||||
@@ -96,16 +82,18 @@ namespace Umbraco.Web.Editors
|
||||
|
||||
if (MembershipScenario == MembershipScenario.NativeUmbraco)
|
||||
{
|
||||
long totalRecords;
|
||||
var members = Services.MemberService
|
||||
.GetAll((pageNumber - 1), pageSize, out totalRecords, orderBy, orderDirection, orderBySystemField, memberTypeAlias, filter).ToArray();
|
||||
.GetAll((pageNumber - 1), pageSize, out var totalRecords, orderBy, orderDirection, orderBySystemField, memberTypeAlias, filter).ToArray();
|
||||
if (totalRecords == 0)
|
||||
{
|
||||
return new PagedResult<MemberBasic>(0, 0, 0);
|
||||
}
|
||||
var pagedResult = new PagedResult<MemberBasic>(totalRecords, pageNumber, pageSize);
|
||||
pagedResult.Items = members
|
||||
.Select(Mapper.Map<IMember, MemberBasic>);
|
||||
|
||||
var pagedResult = new PagedResult<MemberBasic>(totalRecords, pageNumber, pageSize)
|
||||
{
|
||||
Items = members
|
||||
.Select(x => AutoMapperExtensions.MapWithUmbracoContext<IMember, MemberBasic>(x, UmbracoContext))
|
||||
};
|
||||
return pagedResult;
|
||||
}
|
||||
else
|
||||
@@ -133,10 +121,13 @@ namespace Umbraco.Web.Editors
|
||||
{
|
||||
return new PagedResult<MemberBasic>(0, 0, 0);
|
||||
}
|
||||
var pagedResult = new PagedResult<MemberBasic>(totalRecords, pageNumber, pageSize);
|
||||
pagedResult.Items = members
|
||||
.Cast<MembershipUser>()
|
||||
.Select(Mapper.Map<MembershipUser, MemberBasic>);
|
||||
|
||||
var pagedResult = new PagedResult<MemberBasic>(totalRecords, pageNumber, pageSize)
|
||||
{
|
||||
Items = members
|
||||
.Cast<MembershipUser>()
|
||||
.Select(Mapper.Map<MembershipUser, MemberBasic>)
|
||||
};
|
||||
return pagedResult;
|
||||
}
|
||||
|
||||
@@ -437,7 +428,7 @@ namespace Umbraco.Web.Editors
|
||||
var sensitiveProperties = contentItem.PersistedContent.ContentType
|
||||
.PropertyTypes.Where(x => contentItem.PersistedContent.ContentType.IsSensitiveProperty(x.Alias))
|
||||
.ToList();
|
||||
|
||||
|
||||
foreach (var sensitiveProperty in sensitiveProperties)
|
||||
{
|
||||
//if found, change the value of the contentItem model to the persisted value so it remains unchanged
|
||||
@@ -665,7 +656,7 @@ namespace Umbraco.Web.Editors
|
||||
contentItem.Email,
|
||||
"TEMP", //some membership provider's require something here even if q/a is disabled!
|
||||
"TEMP", //some membership provider's require something here even if q/a is disabled!
|
||||
contentItem.IsApproved,
|
||||
contentItem.IsApproved,
|
||||
contentItem.PersistedContent.Key, //custom membership provider, we'll link that based on the IMember unique id (GUID)
|
||||
out status);
|
||||
|
||||
@@ -682,7 +673,7 @@ namespace Umbraco.Web.Editors
|
||||
contentItem.Email,
|
||||
"TEMP", //some membership provider's require something here even if q/a is disabled!
|
||||
"TEMP", //some membership provider's require something here even if q/a is disabled!
|
||||
contentItem.IsApproved,
|
||||
contentItem.IsApproved,
|
||||
newKey,
|
||||
out status);
|
||||
|
||||
@@ -828,17 +819,17 @@ namespace Umbraco.Web.Editors
|
||||
var member = ((MemberService)Services.MemberService).ExportMember(key);
|
||||
|
||||
var fileName = $"{member.Name}_{member.Email}.txt";
|
||||
|
||||
httpResponseMessage.Content = new ObjectContent<MemberExportModel>(member, new JsonMediaTypeFormatter {Indent = true});
|
||||
|
||||
httpResponseMessage.Content = new ObjectContent<MemberExportModel>(member, new JsonMediaTypeFormatter { Indent = true });
|
||||
httpResponseMessage.Content.Headers.Add("x-filename", fileName);
|
||||
httpResponseMessage.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
|
||||
httpResponseMessage.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
|
||||
httpResponseMessage.Content.Headers.ContentDisposition.FileName = fileName;
|
||||
httpResponseMessage.StatusCode = HttpStatusCode.OK;
|
||||
|
||||
|
||||
return httpResponseMessage;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -30,6 +30,11 @@ namespace Umbraco.Web.Models.ContentEditing
|
||||
[DataMember(Name = "editor", IsRequired = false)]
|
||||
public string Editor { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Flags the property to denote that it can contain sensitive data
|
||||
/// </summary>
|
||||
[DataMember(Name = "isSensitive", IsRequired = false)]
|
||||
public bool IsSensitive { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Used internally during model mapping
|
||||
@@ -38,4 +43,4 @@ namespace Umbraco.Web.Models.ContentEditing
|
||||
internal PropertyEditor PropertyEditor { get; set; }
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,17 +80,21 @@ namespace Umbraco.Web.Models.Mapping
|
||||
|
||||
//FROM IMember TO MemberBasic
|
||||
config.CreateMap<IMember, MemberBasic>()
|
||||
.ForMember(display => display.Udi, expression => expression.MapFrom(content => Udi.Create(Constants.UdiEntityType.Member, content.Key)))
|
||||
.ForMember(display => display.Udi,
|
||||
expression =>
|
||||
expression.MapFrom(content => Udi.Create(Constants.UdiEntityType.Member, content.Key)))
|
||||
.ForMember(dto => dto.Owner, expression => expression.ResolveUsing(new OwnerResolver<IMember>()))
|
||||
.ForMember(dto => dto.Icon, expression => expression.MapFrom(content => content.ContentType.Icon))
|
||||
.ForMember(dto => dto.ContentTypeAlias, expression => expression.MapFrom(content => content.ContentType.Alias))
|
||||
.ForMember(dto => dto.ContentTypeAlias,
|
||||
expression => expression.MapFrom(content => content.ContentType.Alias))
|
||||
.ForMember(dto => dto.Email, expression => expression.MapFrom(content => content.Email))
|
||||
.ForMember(dto => dto.Username, expression => expression.MapFrom(content => content.Username))
|
||||
.ForMember(dto => dto.Trashed, expression => expression.Ignore())
|
||||
.ForMember(dto => dto.Published, expression => expression.Ignore())
|
||||
.ForMember(dto => dto.Updater, expression => expression.Ignore())
|
||||
.ForMember(dto => dto.Alias, expression => expression.Ignore())
|
||||
.ForMember(dto => dto.HasPublishedVersion, expression => expression.Ignore());
|
||||
.ForMember(dto => dto.HasPublishedVersion, expression => expression.Ignore())
|
||||
.ForMember(dto => dto.Properties, expression => expression.ResolveUsing(new MemberBasicPropertiesResolver()));
|
||||
|
||||
//FROM MembershipUser TO MemberBasic
|
||||
config.CreateMap<MembershipUser, MemberBasic>()
|
||||
@@ -395,6 +399,8 @@ namespace Umbraco.Web.Models.Mapping
|
||||
//check permissions for viewing sensitive data
|
||||
if (isSensitiveProperty && umbracoContext.Security.CurrentUser.HasAccessToSensitiveData() == false)
|
||||
{
|
||||
//mark this property as sensitive
|
||||
prop.IsSensitive = true;
|
||||
//mark this property as readonly so that it does not post any data
|
||||
prop.Readonly = true;
|
||||
//replace this editor with a sensitivevalue
|
||||
@@ -477,8 +483,51 @@ namespace Umbraco.Web.Models.Mapping
|
||||
return AutoMapperExtensions.MapWithUmbracoContext<IMember, MemberDisplay>(member, context.GetUmbracoContext());
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A resolver to map <see cref="IMember"/> properties to a collection of <see cref="ContentPropertyBasic"/>
|
||||
/// </summary>
|
||||
internal class MemberBasicPropertiesResolver : IValueResolver
|
||||
{
|
||||
public ResolutionResult Resolve(ResolutionResult source)
|
||||
{
|
||||
if (source.Value != null && (source.Value is IMember) == false)
|
||||
throw new AutoMapperMappingException(string.Format("Value supplied is of type {0} but expected {1}.\nChange the value resolver source type, or redirect the source value supplied to the value resolver using FromMember.", new object[]
|
||||
{
|
||||
source.Value.GetType(),
|
||||
typeof (IMember)
|
||||
}));
|
||||
return source.New(
|
||||
//perform the mapping with the current umbraco context
|
||||
ResolveCore(source.Context.GetUmbracoContext(), (IMember)source.Value), typeof(IEnumerable<ContentPropertyDisplay>));
|
||||
}
|
||||
|
||||
private IEnumerable<ContentPropertyBasic> ResolveCore(UmbracoContext umbracoContext, IMember content)
|
||||
{
|
||||
var result = Mapper.Map<IEnumerable<Property>, IEnumerable<ContentPropertyBasic>>(
|
||||
// Sort properties so items from different compositions appear in correct order (see U4-9298). Map sorted properties.
|
||||
content.Properties.OrderBy(prop => prop.PropertyType.SortOrder))
|
||||
.ToList();
|
||||
|
||||
var member = (IMember)content;
|
||||
var memberType = member.ContentType;
|
||||
|
||||
//now update the IsSensitive value
|
||||
foreach (var prop in result)
|
||||
{
|
||||
//check if this property is flagged as sensitive
|
||||
var isSensitiveProperty = memberType.IsSensitiveProperty(prop.Alias);
|
||||
//check permissions for viewing sensitive data
|
||||
if (isSensitiveProperty && umbracoContext.Security.CurrentUser.HasAccessToSensitiveData() == false)
|
||||
{
|
||||
//mark this property as sensitive
|
||||
prop.IsSensitive = true;
|
||||
//clear the value
|
||||
prop.Value = null;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using AutoMapper;
|
||||
using Umbraco.Core;
|
||||
@@ -9,7 +7,6 @@ using Umbraco.Core.Models;
|
||||
using Umbraco.Core.PropertyEditors;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Web.Models.ContentEditing;
|
||||
using umbraco;
|
||||
|
||||
namespace Umbraco.Web.Models.Mapping
|
||||
{
|
||||
@@ -53,7 +50,7 @@ namespace Umbraco.Web.Models.Mapping
|
||||
//perform the mapping with the current umbraco context
|
||||
ResolveCore(source.Context.GetUmbracoContext(), (TSource)source.Value), typeof(List<Tab<ContentPropertyDisplay>>));
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Adds the container (listview) tab to the document
|
||||
/// </summary>
|
||||
@@ -275,7 +272,7 @@ namespace Umbraco.Web.Models.Mapping
|
||||
|
||||
//now add the user props
|
||||
contentProps.AddRange(currProps);
|
||||
|
||||
|
||||
//re-assign
|
||||
genericProps.Properties = contentProps;
|
||||
|
||||
@@ -308,6 +305,6 @@ namespace Umbraco.Web.Models.Mapping
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user