Ensures that the auth cookie data contains all of the user's start nodes, fixes persisting the user group icon
This commit is contained in:
@@ -5,6 +5,7 @@ using System.Collections.Specialized;
|
||||
using System.Security.Claims;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.Identity;
|
||||
using Umbraco.Core.Models.Membership;
|
||||
using Umbraco.Core.Security;
|
||||
|
||||
namespace Umbraco.Core.Models.Identity
|
||||
@@ -16,7 +17,7 @@ namespace Umbraco.Core.Models.Identity
|
||||
{
|
||||
StartMediaIds = new int[] { };
|
||||
StartContentIds = new int[] { };
|
||||
Groups = new string[] { };
|
||||
Groups = new IReadOnlyUserGroup[] { };
|
||||
AllowedSections = new string[] { };
|
||||
Culture = Configuration.GlobalSettings.DefaultUILanguage;
|
||||
}
|
||||
@@ -44,7 +45,7 @@ namespace Umbraco.Core.Models.Identity
|
||||
/// </summary>
|
||||
public int[] StartMediaIds { get; set; }
|
||||
public string[] AllowedSections { get; set; }
|
||||
public string[] Groups { get; set; }
|
||||
public IReadOnlyUserGroup[] Groups { get; set; }
|
||||
public string Culture { get; set; }
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace Umbraco.Core.Models.Identity
|
||||
.ForMember(user => user.StartMediaIds, expression => expression.MapFrom(user => user.StartMediaIds))
|
||||
.ForMember(user => user.StartContentIds, expression => expression.MapFrom(user => user.StartContentIds))
|
||||
.ForMember(user => user.AccessFailedCount, expression => expression.MapFrom(user => user.FailedPasswordAttempts))
|
||||
.ForMember(user => user.Groups, expression => expression.MapFrom(user => user.Groups.Select(x => x.Alias).ToArray()))
|
||||
.ForMember(user => user.Groups, expression => expression.MapFrom(user => user.Groups.ToArray()))
|
||||
.ForMember(user => user.AllowedSections, expression => expression.MapFrom(user => user.AllowedSections.ToArray()));
|
||||
|
||||
config.CreateMap<BackOfficeIdentityUser, UserData>()
|
||||
@@ -34,8 +34,10 @@ namespace Umbraco.Core.Models.Identity
|
||||
.ForMember(detail => detail.AllowedApplications, opt => opt.MapFrom(user => user.AllowedSections))
|
||||
.ForMember(detail => detail.Roles, opt => opt.MapFrom(user => user.Groups))
|
||||
.ForMember(detail => detail.RealName, opt => opt.MapFrom(user => user.Name))
|
||||
.ForMember(detail => detail.StartContentNodes, opt => opt.MapFrom(user => user.StartContentIds))
|
||||
.ForMember(detail => detail.StartMediaNodes, opt => opt.MapFrom(user => user.StartMediaIds))
|
||||
//When mapping to UserData which is used in the authcookie we want ALL start nodes including ones defined on the groups
|
||||
.ForMember(detail => detail.StartContentNodes, opt => opt.MapFrom(user => user.GetCombinedStartContentIds()))
|
||||
//When mapping to UserData which is used in the authcookie we want ALL start nodes including ones defined on the groups
|
||||
.ForMember(detail => detail.StartMediaNodes, opt => opt.MapFrom(user => user.GetCombinedStartMediaIds()))
|
||||
.ForMember(detail => detail.Username, opt => opt.MapFrom(user => user.UserName))
|
||||
.ForMember(detail => detail.Culture, opt => opt.MapFrom(user => user.Culture))
|
||||
.ForMember(detail => detail.SessionId, opt => opt.MapFrom(user => user.SecurityStamp.IsNullOrWhiteSpace() ? Guid.NewGuid().ToString("N") : user.SecurityStamp));
|
||||
|
||||
@@ -5,6 +5,7 @@ using System.Linq;
|
||||
using System.Net;
|
||||
using Umbraco.Core.Cache;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Models.Identity;
|
||||
using Umbraco.Core.Models.Membership;
|
||||
using Umbraco.Core.Services;
|
||||
|
||||
@@ -21,11 +22,29 @@ namespace Umbraco.Core.Models
|
||||
return user.StartContentIds.Concat(user.Groups.Select(x => x.StartContentId)).Distinct();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns all of the user's assigned start node ids based on ids assigned directly to the BackOfficeIdentityUser object and it's groups
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static IEnumerable<int> GetCombinedStartContentIds(this BackOfficeIdentityUser user)
|
||||
{
|
||||
return user.StartContentIds.Concat(user.Groups.Select(x => x.StartContentId)).Distinct();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns all of the user's assigned start node ids based on ids assigned directly to the IUser object and it's groups
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static IEnumerable<int> GetCombinedStartMediaIds(this IUser user)
|
||||
{
|
||||
return user.StartMediaIds.Concat(user.Groups.Select(x => x.StartMediaId)).Distinct();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns all of the user's assigned start node ids based on ids assigned directly to the BackOfficeIdentityUser object and it's groups
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static IEnumerable<int> GetCombinedStartMediaIds(this BackOfficeIdentityUser user)
|
||||
{
|
||||
return user.StartMediaIds.Concat(user.Groups.Select(x => x.StartMediaId)).Distinct();
|
||||
}
|
||||
|
||||
@@ -399,12 +399,16 @@ namespace Umbraco.Core.Security
|
||||
throw new InvalidOperationException("The user id must be an integer to work with the Umbraco");
|
||||
}
|
||||
|
||||
var foundUser = _userService.GetUserById(asInt.Result);
|
||||
var foundGroup = _userService.GetUserGroupByAlias(roleName);
|
||||
var foundUser = _userService.GetUserById(asInt.Result);
|
||||
|
||||
if (foundUser != null && foundGroup != null)
|
||||
if (foundUser != null)
|
||||
{
|
||||
foundUser.AddGroup(foundGroup.ToReadOnlyGroup());
|
||||
var foundGroup = _userService.GetUserGroupByAlias(roleName);
|
||||
|
||||
if (foundGroup != null)
|
||||
{
|
||||
foundUser.AddGroup(foundGroup.ToReadOnlyGroup());
|
||||
}
|
||||
}
|
||||
|
||||
return Task.FromResult(0);
|
||||
@@ -428,12 +432,16 @@ namespace Umbraco.Core.Security
|
||||
throw new InvalidOperationException("The user id must be an integer to work with the Umbraco");
|
||||
}
|
||||
|
||||
var foundUser = _userService.GetUserById(asInt.Result);
|
||||
var foundGroup = _userService.GetUserGroupByAlias(roleName);
|
||||
var foundUser = _userService.GetUserById(asInt.Result);
|
||||
|
||||
if (foundUser != null && foundGroup != null)
|
||||
if (foundUser != null)
|
||||
{
|
||||
foundUser.RemoveGroup(foundGroup.Alias);
|
||||
var foundGroup = _userService.GetUserGroupByAlias(roleName);
|
||||
|
||||
if (foundGroup != null)
|
||||
{
|
||||
foundUser.RemoveGroup(foundGroup.Alias);
|
||||
}
|
||||
}
|
||||
|
||||
return Task.FromResult(0);
|
||||
@@ -448,7 +456,7 @@ namespace Umbraco.Core.Security
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
if (user == null) throw new ArgumentNullException("user");
|
||||
return Task.FromResult((IList<string>)user.Groups.ToList());
|
||||
return Task.FromResult((IList<string>)user.Groups.Select(x => x.Alias).ToList());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -460,7 +468,7 @@ namespace Umbraco.Core.Security
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
if (user == null) throw new ArgumentNullException("user");
|
||||
return Task.FromResult(user.Groups.InvariantContains(roleName));
|
||||
return Task.FromResult(user.Groups.Select(x => x.Alias).InvariantContains(roleName));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -691,21 +699,21 @@ namespace Umbraco.Core.Security
|
||||
user.SecurityStamp = identityUser.SecurityStamp;
|
||||
}
|
||||
|
||||
var userGroups = user.Groups.Select(x => x.Alias).ToArray();
|
||||
var userGroupAliases = user.Groups.Select(x => x.Alias).ToArray();
|
||||
var identityUserGroupAliases = identityUser.Groups.Select(x => x.Alias).ToArray();
|
||||
|
||||
if (userGroups.ContainsAll(identityUser.Groups) == false
|
||||
|| identityUser.Groups.ContainsAll(userGroups) == false)
|
||||
if (userGroupAliases.ContainsAll(identityUserGroupAliases) == false
|
||||
|| identityUserGroupAliases.ContainsAll(userGroupAliases) == false)
|
||||
{
|
||||
anythingChanged = true;
|
||||
|
||||
//clear out the current groups (need to ToArray since we are modifying the iterator)
|
||||
user.ClearGroups();
|
||||
|
||||
//get all of the ones found by alias and add them
|
||||
var foundGroups = _userService.GetUserGroupsByAlias(identityUser.Groups);
|
||||
foreach (var group in foundGroups)
|
||||
//use all of the ones assigned and add them
|
||||
foreach (var group in identityUser.Groups)
|
||||
{
|
||||
user.AddGroup(group.ToReadOnlyGroup());
|
||||
user.AddGroup(group);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -46,10 +46,16 @@ namespace Umbraco.Core.Security
|
||||
|
||||
[DataMember(Name = "name")]
|
||||
public string RealName { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The start nodes on the UserData object for the auth ticket contains all of the user's start nodes including ones assigned to their user groups
|
||||
/// </summary>
|
||||
[DataMember(Name = "startContent")]
|
||||
public int[] StartContentNodes { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The start nodes on the UserData object for the auth ticket contains all of the user's start nodes including ones assigned to their user groups
|
||||
/// </summary>
|
||||
[DataMember(Name = "startMedia")]
|
||||
public int[] StartMediaNodes { get; set; }
|
||||
|
||||
|
||||
@@ -0,0 +1,303 @@
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* @ngdoc service
|
||||
* @name umbraco.services.umbDataFormatter
|
||||
* @description A helper object used to format/transform JSON Umbraco data, mostly used for persisting data to the server
|
||||
**/
|
||||
function umbDataFormatter() {
|
||||
return {
|
||||
|
||||
formatContentTypePostData: function (displayModel, action) {
|
||||
|
||||
//create the save model from the display model
|
||||
var saveModel = _.pick(displayModel,
|
||||
'compositeContentTypes', 'isContainer', 'allowAsRoot', 'allowedTemplates', 'allowedContentTypes',
|
||||
'alias', 'description', 'thumbnail', 'name', 'id', 'icon', 'trashed',
|
||||
'key', 'parentId', 'alias', 'path');
|
||||
|
||||
//TODO: Map these
|
||||
saveModel.allowedTemplates = _.map(displayModel.allowedTemplates, function (t) { return t.alias; });
|
||||
saveModel.defaultTemplate = displayModel.defaultTemplate ? displayModel.defaultTemplate.alias : null;
|
||||
var realGroups = _.reject(displayModel.groups, function (g) {
|
||||
//do not include these tabs
|
||||
return g.tabState === "init";
|
||||
});
|
||||
saveModel.groups = _.map(realGroups, function (g) {
|
||||
|
||||
var saveGroup = _.pick(g, 'inherited', 'id', 'sortOrder', 'name');
|
||||
|
||||
var realProperties = _.reject(g.properties, function (p) {
|
||||
//do not include these properties
|
||||
return p.propertyState === "init" || p.inherited === true;
|
||||
});
|
||||
|
||||
var saveProperties = _.map(realProperties, function (p) {
|
||||
var saveProperty = _.pick(p, 'id', 'alias', 'description', 'validation', 'label', 'sortOrder', 'dataTypeId', 'groupId', 'memberCanEdit', 'showOnMemberProfile');
|
||||
return saveProperty;
|
||||
});
|
||||
|
||||
saveGroup.properties = saveProperties;
|
||||
|
||||
//if this is an inherited group and there are not non-inherited properties on it, then don't send up the data
|
||||
if (saveGroup.inherited === true && saveProperties.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return saveGroup;
|
||||
});
|
||||
|
||||
//we don't want any null groups
|
||||
saveModel.groups = _.reject(saveModel.groups, function (g) {
|
||||
return !g;
|
||||
});
|
||||
|
||||
return saveModel;
|
||||
},
|
||||
|
||||
/** formats the display model used to display the data type to the model used to save the data type */
|
||||
formatDataTypePostData: function (displayModel, preValues, action) {
|
||||
var saveModel = {
|
||||
parentId: displayModel.parentId,
|
||||
id: displayModel.id,
|
||||
name: displayModel.name,
|
||||
selectedEditor: displayModel.selectedEditor,
|
||||
//set the action on the save model
|
||||
action: action,
|
||||
preValues: []
|
||||
};
|
||||
for (var i = 0; i < preValues.length; i++) {
|
||||
|
||||
saveModel.preValues.push({
|
||||
key: preValues[i].alias,
|
||||
value: preValues[i].value
|
||||
});
|
||||
}
|
||||
return saveModel;
|
||||
},
|
||||
|
||||
/** formats the display model used to display the user to the model used to save the user */
|
||||
formatUserPostData: function (displayModel) {
|
||||
|
||||
//create the save model from the display model
|
||||
var saveModel = _.pick(displayModel, 'id', 'parentId', 'name', 'username', 'culture', 'email', 'startContentIds', 'startMediaIds', 'userGroups', 'message');
|
||||
|
||||
//make sure the userGroups are just a string array
|
||||
var currGroups = saveModel.userGroups;
|
||||
var formattedGroups = [];
|
||||
for (var i = 0; i < currGroups.length; i++) {
|
||||
if (!angular.isString(currGroups[i])) {
|
||||
formattedGroups.push(currGroups[i].alias);
|
||||
}
|
||||
else {
|
||||
formattedGroups.push(currGroups[i]);
|
||||
}
|
||||
}
|
||||
saveModel.userGroups = formattedGroups;
|
||||
|
||||
//make sure the startnodes are just a string array
|
||||
var props = ["startContentIds", "startMediaIds"];
|
||||
for (var m = 0; m < props.length; m++) {
|
||||
var startIds = saveModel[props[m]];
|
||||
if (!startIds) {
|
||||
continue;
|
||||
}
|
||||
var formattedIds = [];
|
||||
for (var j = 0; j < startIds.length; j++) {
|
||||
formattedIds.push(startIds[j].id);
|
||||
}
|
||||
saveModel[props[m]] = formattedIds;
|
||||
}
|
||||
|
||||
return saveModel;
|
||||
},
|
||||
|
||||
/** formats the display model used to display the user group to the model used to save the user group*/
|
||||
formatUserGroupPostData: function (displayModel, action) {
|
||||
|
||||
//create the save model from the display model
|
||||
var saveModel = _.pick(displayModel, 'id', 'alias', 'name', 'icon', 'sections', 'users', 'startContentId', 'startMediaId');
|
||||
//set the action on the save model
|
||||
saveModel.action = action;
|
||||
if (!saveModel.id) {
|
||||
saveModel.id = 0;
|
||||
}
|
||||
|
||||
//make sure the sections are just a string array
|
||||
var currSections = saveModel.sections;
|
||||
var formattedSections = [];
|
||||
for (var i = 0; i < currSections.length; i++) {
|
||||
if (!angular.isString(currSections[i])) {
|
||||
formattedSections.push(currSections[i].alias);
|
||||
}
|
||||
else {
|
||||
formattedSections.push(currSections[i]);
|
||||
}
|
||||
}
|
||||
saveModel.sections = formattedSections;
|
||||
|
||||
//make sure the user are just an int array
|
||||
var currUsers = saveModel.users;
|
||||
var formattedUsers = [];
|
||||
for (var j = 0; j < currUsers.length; j++) {
|
||||
if (!angular.isNumber(currUsers[j])) {
|
||||
formattedUsers.push(currUsers[j].id);
|
||||
}
|
||||
else {
|
||||
formattedUsers.push(currUsers[j]);
|
||||
}
|
||||
}
|
||||
saveModel.users = formattedUsers;
|
||||
|
||||
//make sure the startnodes are just an int
|
||||
var props = ["startContentId", "startMediaId"];
|
||||
for (var m = 0; m < props.length; m++) {
|
||||
var startId = saveModel[props[m]];
|
||||
if (!startId) {
|
||||
continue;
|
||||
}
|
||||
saveModel[props[m]] = startId.id;
|
||||
}
|
||||
|
||||
saveModel.parentId = -1;
|
||||
if (!saveModel.startContentId) {
|
||||
saveModel.startContentId = -1;
|
||||
}
|
||||
if (!saveModel.startMediaId) {
|
||||
saveModel.startMediaId = -1;
|
||||
}
|
||||
|
||||
return saveModel;
|
||||
},
|
||||
|
||||
/** formats the display model used to display the member to the model used to save the member */
|
||||
formatMemberPostData: function (displayModel, action) {
|
||||
//this is basically the same as for media but we need to explicitly add the username,email, password to the save model
|
||||
|
||||
var saveModel = this.formatMediaPostData(displayModel, action);
|
||||
|
||||
saveModel.key = displayModel.key;
|
||||
|
||||
var genericTab = _.find(displayModel.tabs, function (item) {
|
||||
return item.id === 0;
|
||||
});
|
||||
|
||||
//map the member login, email, password and groups
|
||||
var propLogin = _.find(genericTab.properties, function (item) {
|
||||
return item.alias === "_umb_login";
|
||||
});
|
||||
var propEmail = _.find(genericTab.properties, function (item) {
|
||||
return item.alias === "_umb_email";
|
||||
});
|
||||
var propPass = _.find(genericTab.properties, function (item) {
|
||||
return item.alias === "_umb_password";
|
||||
});
|
||||
var propGroups = _.find(genericTab.properties, function (item) {
|
||||
return item.alias === "_umb_membergroup";
|
||||
});
|
||||
saveModel.email = propEmail.value;
|
||||
saveModel.username = propLogin.value;
|
||||
saveModel.password = propPass.value;
|
||||
|
||||
var selectedGroups = [];
|
||||
for (var n in propGroups.value) {
|
||||
if (propGroups.value[n] === true) {
|
||||
selectedGroups.push(n);
|
||||
}
|
||||
}
|
||||
saveModel.memberGroups = selectedGroups;
|
||||
|
||||
//turn the dictionary into an array of pairs
|
||||
var memberProviderPropAliases = _.pairs(displayModel.fieldConfig);
|
||||
_.each(displayModel.tabs, function (tab) {
|
||||
_.each(tab.properties, function (prop) {
|
||||
var foundAlias = _.find(memberProviderPropAliases, function (item) {
|
||||
return prop.alias === item[1];
|
||||
});
|
||||
if (foundAlias) {
|
||||
//we know the current property matches an alias, now we need to determine which membership provider property it was for
|
||||
// by looking at the key
|
||||
switch (foundAlias[0]) {
|
||||
case "umbracoMemberLockedOut":
|
||||
saveModel.isLockedOut = prop.value.toString() === "1" ? true : false;
|
||||
break;
|
||||
case "umbracoMemberApproved":
|
||||
saveModel.isApproved = prop.value.toString() === "1" ? true : false;
|
||||
break;
|
||||
case "umbracoMemberComments":
|
||||
saveModel.comments = prop.value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
||||
return saveModel;
|
||||
},
|
||||
|
||||
/** formats the display model used to display the media to the model used to save the media */
|
||||
formatMediaPostData: function (displayModel, action) {
|
||||
//NOTE: the display model inherits from the save model so we can in theory just post up the display model but
|
||||
// we don't want to post all of the data as it is unecessary.
|
||||
var saveModel = {
|
||||
id: displayModel.id,
|
||||
properties: [],
|
||||
name: displayModel.name,
|
||||
contentTypeAlias: displayModel.contentTypeAlias,
|
||||
parentId: displayModel.parentId,
|
||||
//set the action on the save model
|
||||
action: action
|
||||
};
|
||||
|
||||
_.each(displayModel.tabs, function (tab) {
|
||||
|
||||
_.each(tab.properties, function (prop) {
|
||||
|
||||
//don't include the custom generic tab properties
|
||||
if (!prop.alias.startsWith("_umb_")) {
|
||||
saveModel.properties.push({
|
||||
id: prop.id,
|
||||
alias: prop.alias,
|
||||
value: prop.value
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
return saveModel;
|
||||
},
|
||||
|
||||
/** formats the display model used to display the content to the model used to save the content */
|
||||
formatContentPostData: function (displayModel, action) {
|
||||
|
||||
//this is basically the same as for media but we need to explicitly add some extra properties
|
||||
var saveModel = this.formatMediaPostData(displayModel, action);
|
||||
|
||||
var genericTab = _.find(displayModel.tabs, function (item) {
|
||||
return item.id === 0;
|
||||
});
|
||||
|
||||
var propExpireDate = _.find(genericTab.properties, function (item) {
|
||||
return item.alias === "_umb_expiredate";
|
||||
});
|
||||
var propReleaseDate = _.find(genericTab.properties, function (item) {
|
||||
return item.alias === "_umb_releasedate";
|
||||
});
|
||||
var propTemplate = _.find(genericTab.properties, function (item) {
|
||||
return item.alias === "_umb_template";
|
||||
});
|
||||
saveModel.expireDate = propExpireDate.value;
|
||||
saveModel.releaseDate = propReleaseDate.value;
|
||||
saveModel.templateAlias = propTemplate.value;
|
||||
|
||||
return saveModel;
|
||||
}
|
||||
};
|
||||
}
|
||||
angular.module('umbraco.services').factory('umbDataFormatter', umbDataFormatter);
|
||||
|
||||
})();
|
||||
@@ -575,303 +575,6 @@ function umbPropEditorHelper() {
|
||||
angular.module('umbraco.services').factory('umbPropEditorHelper', umbPropEditorHelper);
|
||||
|
||||
|
||||
/**
|
||||
* @ngdoc service
|
||||
* @name umbraco.services.umbDataFormatter
|
||||
* @description A helper object used to format/transform JSON Umbraco data, mostly used for persisting data to the server
|
||||
**/
|
||||
function umbDataFormatter() {
|
||||
return {
|
||||
|
||||
formatContentTypePostData: function (displayModel, action) {
|
||||
|
||||
//create the save model from the display model
|
||||
var saveModel = _.pick(displayModel,
|
||||
'compositeContentTypes', 'isContainer', 'allowAsRoot', 'allowedTemplates', 'allowedContentTypes',
|
||||
'alias', 'description', 'thumbnail', 'name', 'id', 'icon', 'trashed',
|
||||
'key', 'parentId', 'alias', 'path');
|
||||
|
||||
//TODO: Map these
|
||||
saveModel.allowedTemplates = _.map(displayModel.allowedTemplates, function (t) { return t.alias; });
|
||||
saveModel.defaultTemplate = displayModel.defaultTemplate ? displayModel.defaultTemplate.alias : null;
|
||||
var realGroups = _.reject(displayModel.groups, function (g) {
|
||||
//do not include these tabs
|
||||
return g.tabState === "init";
|
||||
});
|
||||
saveModel.groups = _.map(realGroups, function (g) {
|
||||
|
||||
var saveGroup = _.pick(g, 'inherited', 'id', 'sortOrder', 'name');
|
||||
|
||||
var realProperties = _.reject(g.properties, function (p) {
|
||||
//do not include these properties
|
||||
return p.propertyState === "init" || p.inherited === true;
|
||||
});
|
||||
|
||||
var saveProperties = _.map(realProperties, function (p) {
|
||||
var saveProperty = _.pick(p, 'id', 'alias', 'description', 'validation', 'label', 'sortOrder', 'dataTypeId', 'groupId', 'memberCanEdit', 'showOnMemberProfile');
|
||||
return saveProperty;
|
||||
});
|
||||
|
||||
saveGroup.properties = saveProperties;
|
||||
|
||||
//if this is an inherited group and there are not non-inherited properties on it, then don't send up the data
|
||||
if (saveGroup.inherited === true && saveProperties.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return saveGroup;
|
||||
});
|
||||
|
||||
//we don't want any null groups
|
||||
saveModel.groups = _.reject(saveModel.groups, function (g) {
|
||||
return !g;
|
||||
});
|
||||
|
||||
return saveModel;
|
||||
},
|
||||
|
||||
/** formats the display model used to display the data type to the model used to save the data type */
|
||||
formatDataTypePostData: function (displayModel, preValues, action) {
|
||||
var saveModel = {
|
||||
parentId: displayModel.parentId,
|
||||
id: displayModel.id,
|
||||
name: displayModel.name,
|
||||
selectedEditor: displayModel.selectedEditor,
|
||||
//set the action on the save model
|
||||
action: action,
|
||||
preValues: []
|
||||
};
|
||||
for (var i = 0; i < preValues.length; i++) {
|
||||
|
||||
saveModel.preValues.push({
|
||||
key: preValues[i].alias,
|
||||
value: preValues[i].value
|
||||
});
|
||||
}
|
||||
return saveModel;
|
||||
},
|
||||
|
||||
/** formats the display model used to display the user to the model used to save the user */
|
||||
formatUserPostData: function (displayModel) {
|
||||
|
||||
//create the save model from the display model
|
||||
var saveModel = _.pick(displayModel, 'id', 'parentId', 'name', 'username', 'culture', 'email', 'startContentIds', 'startMediaIds', 'userGroups', 'message');
|
||||
|
||||
//make sure the userGroups are just a string array
|
||||
var currGroups = saveModel.userGroups;
|
||||
var formattedGroups = [];
|
||||
for (var i = 0; i < currGroups.length; i++) {
|
||||
if (!angular.isString(currGroups[i])) {
|
||||
formattedGroups.push(currGroups[i].alias);
|
||||
}
|
||||
else {
|
||||
formattedGroups.push(currGroups[i]);
|
||||
}
|
||||
}
|
||||
saveModel.userGroups = formattedGroups;
|
||||
|
||||
//make sure the startnodes are just a string array
|
||||
var props = ["startContentIds", "startMediaIds"];
|
||||
for (var m = 0; m < props.length; m++) {
|
||||
var startIds = saveModel[props[m]];
|
||||
if (!startIds) {
|
||||
continue;
|
||||
}
|
||||
var formattedIds = [];
|
||||
for (var j = 0; j < startIds.length; j++) {
|
||||
formattedIds.push(startIds[j].id);
|
||||
}
|
||||
saveModel[props[m]] = formattedIds;
|
||||
}
|
||||
|
||||
return saveModel;
|
||||
},
|
||||
|
||||
/** formats the display model used to display the user group to the model used to save the user group*/
|
||||
formatUserGroupPostData: function (displayModel, action) {
|
||||
|
||||
//create the save model from the display model
|
||||
var saveModel = _.pick(displayModel, 'id', 'alias', 'name', 'sections', 'users', 'startContentId', 'startMediaId');
|
||||
//set the action on the save model
|
||||
saveModel.action = action;
|
||||
if (!saveModel.id) {
|
||||
saveModel.id = 0;
|
||||
}
|
||||
|
||||
//make sure the sections are just a string array
|
||||
var currSections = saveModel.sections;
|
||||
var formattedSections = [];
|
||||
for (var i = 0; i < currSections.length; i++) {
|
||||
if (!angular.isString(currSections[i])) {
|
||||
formattedSections.push(currSections[i].alias);
|
||||
}
|
||||
else {
|
||||
formattedSections.push(currSections[i]);
|
||||
}
|
||||
}
|
||||
saveModel.sections = formattedSections;
|
||||
|
||||
//make sure the user are just an int array
|
||||
var currUsers = saveModel.users;
|
||||
var formattedUsers = [];
|
||||
for (var j = 0; j < currUsers.length; j++) {
|
||||
if (!angular.isNumber(currUsers[j])) {
|
||||
formattedUsers.push(currUsers[j].id);
|
||||
}
|
||||
else {
|
||||
formattedUsers.push(currUsers[j]);
|
||||
}
|
||||
}
|
||||
saveModel.users = formattedUsers;
|
||||
|
||||
//make sure the startnodes are just an int
|
||||
var props = ["startContentId", "startMediaId"];
|
||||
for (var m = 0; m < props.length; m++) {
|
||||
var startId = saveModel[props[m]];
|
||||
if (!startId) {
|
||||
continue;
|
||||
}
|
||||
saveModel[props[m]] = startId.id;
|
||||
}
|
||||
|
||||
saveModel.parentId = -1;
|
||||
if (!saveModel.startContentId) {
|
||||
saveModel.startContentId = -1;
|
||||
}
|
||||
if (!saveModel.startMediaId) {
|
||||
saveModel.startMediaId = -1;
|
||||
}
|
||||
|
||||
return saveModel;
|
||||
},
|
||||
|
||||
/** formats the display model used to display the member to the model used to save the member */
|
||||
formatMemberPostData: function (displayModel, action) {
|
||||
//this is basically the same as for media but we need to explicitly add the username,email, password to the save model
|
||||
|
||||
var saveModel = this.formatMediaPostData(displayModel, action);
|
||||
|
||||
saveModel.key = displayModel.key;
|
||||
|
||||
var genericTab = _.find(displayModel.tabs, function (item) {
|
||||
return item.id === 0;
|
||||
});
|
||||
|
||||
//map the member login, email, password and groups
|
||||
var propLogin = _.find(genericTab.properties, function (item) {
|
||||
return item.alias === "_umb_login";
|
||||
});
|
||||
var propEmail = _.find(genericTab.properties, function (item) {
|
||||
return item.alias === "_umb_email";
|
||||
});
|
||||
var propPass = _.find(genericTab.properties, function (item) {
|
||||
return item.alias === "_umb_password";
|
||||
});
|
||||
var propGroups = _.find(genericTab.properties, function (item) {
|
||||
return item.alias === "_umb_membergroup";
|
||||
});
|
||||
saveModel.email = propEmail.value;
|
||||
saveModel.username = propLogin.value;
|
||||
saveModel.password = propPass.value;
|
||||
|
||||
var selectedGroups = [];
|
||||
for (var n in propGroups.value) {
|
||||
if (propGroups.value[n] === true) {
|
||||
selectedGroups.push(n);
|
||||
}
|
||||
}
|
||||
saveModel.memberGroups = selectedGroups;
|
||||
|
||||
//turn the dictionary into an array of pairs
|
||||
var memberProviderPropAliases = _.pairs(displayModel.fieldConfig);
|
||||
_.each(displayModel.tabs, function (tab) {
|
||||
_.each(tab.properties, function (prop) {
|
||||
var foundAlias = _.find(memberProviderPropAliases, function (item) {
|
||||
return prop.alias === item[1];
|
||||
});
|
||||
if (foundAlias) {
|
||||
//we know the current property matches an alias, now we need to determine which membership provider property it was for
|
||||
// by looking at the key
|
||||
switch (foundAlias[0]) {
|
||||
case "umbracoMemberLockedOut":
|
||||
saveModel.isLockedOut = prop.value.toString() === "1" ? true : false;
|
||||
break;
|
||||
case "umbracoMemberApproved":
|
||||
saveModel.isApproved = prop.value.toString() === "1" ? true : false;
|
||||
break;
|
||||
case "umbracoMemberComments":
|
||||
saveModel.comments = prop.value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
||||
return saveModel;
|
||||
},
|
||||
|
||||
/** formats the display model used to display the media to the model used to save the media */
|
||||
formatMediaPostData: function (displayModel, action) {
|
||||
//NOTE: the display model inherits from the save model so we can in theory just post up the display model but
|
||||
// we don't want to post all of the data as it is unecessary.
|
||||
var saveModel = {
|
||||
id: displayModel.id,
|
||||
properties: [],
|
||||
name: displayModel.name,
|
||||
contentTypeAlias: displayModel.contentTypeAlias,
|
||||
parentId: displayModel.parentId,
|
||||
//set the action on the save model
|
||||
action: action
|
||||
};
|
||||
|
||||
_.each(displayModel.tabs, function (tab) {
|
||||
|
||||
_.each(tab.properties, function (prop) {
|
||||
|
||||
//don't include the custom generic tab properties
|
||||
if (!prop.alias.startsWith("_umb_")) {
|
||||
saveModel.properties.push({
|
||||
id: prop.id,
|
||||
alias: prop.alias,
|
||||
value: prop.value
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
return saveModel;
|
||||
},
|
||||
|
||||
/** formats the display model used to display the content to the model used to save the content */
|
||||
formatContentPostData: function (displayModel, action) {
|
||||
|
||||
//this is basically the same as for media but we need to explicitly add some extra properties
|
||||
var saveModel = this.formatMediaPostData(displayModel, action);
|
||||
|
||||
var genericTab = _.find(displayModel.tabs, function (item) {
|
||||
return item.id === 0;
|
||||
});
|
||||
|
||||
var propExpireDate = _.find(genericTab.properties, function (item) {
|
||||
return item.alias === "_umb_expiredate";
|
||||
});
|
||||
var propReleaseDate = _.find(genericTab.properties, function (item) {
|
||||
return item.alias === "_umb_releasedate";
|
||||
});
|
||||
var propTemplate = _.find(genericTab.properties, function (item) {
|
||||
return item.alias === "_umb_template";
|
||||
});
|
||||
saveModel.expireDate = propExpireDate.value;
|
||||
saveModel.releaseDate = propReleaseDate.value;
|
||||
saveModel.templateAlias = propTemplate.value;
|
||||
|
||||
return saveModel;
|
||||
}
|
||||
};
|
||||
}
|
||||
angular.module('umbraco.services').factory('umbDataFormatter', umbDataFormatter);
|
||||
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ namespace Umbraco.Web.Models.Mapping
|
||||
.IgnoreAllUnmapped()
|
||||
.ForMember(user => user.Alias, expression => expression.MapFrom(save => save.Alias))
|
||||
.ForMember(user => user.Name, expression => expression.MapFrom(save => save.Name))
|
||||
.ForMember(user => user.Icon, expression => expression.MapFrom(save => save.Icon))
|
||||
.ForMember(user => user.StartMediaId, expression => expression.MapFrom(save => save.StartMediaId))
|
||||
.ForMember(user => user.StartContentId, expression => expression.MapFrom(save => save.StartContentId))
|
||||
.AfterMap((save, userGroup) =>
|
||||
|
||||
Reference in New Issue
Block a user