Gets content permissions saving per user group
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
namespace Umbraco.Core.Models.Membership
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents an entity -> user & permission key value pair collection
|
||||
/// Represents an entity -> user group & permission key value pair collection
|
||||
/// </summary>
|
||||
public class EntityPermissionSet
|
||||
{
|
||||
|
||||
@@ -884,7 +884,12 @@ order by umbracoNode.{2}, umbracoNode.parentID, umbracoNode.sortOrder",
|
||||
var repo = new PermissionRepository<IContent>(UnitOfWork, _cacheHelper, SqlSyntax);
|
||||
repo.AssignEntityPermission(entity, permission, groupIds);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Returns permissions directly assigned to the content item for all user groups
|
||||
/// </summary>
|
||||
/// <param name="entityId"></param>
|
||||
/// <returns></returns>
|
||||
public IEnumerable<UserGroupEntityPermission> GetPermissionsForEntity(int entityId)
|
||||
{
|
||||
var repo = new PermissionRepository<IContent>(UnitOfWork, _cacheHelper, SqlSyntax);
|
||||
|
||||
@@ -130,7 +130,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns permissions for all groups for a given entity
|
||||
/// Returns permissions directly assigned to the content item for all user groups
|
||||
/// </summary>
|
||||
/// <param name="entityId"></param>
|
||||
/// <returns></returns>
|
||||
|
||||
@@ -130,7 +130,7 @@ namespace Umbraco.Core.Services
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the list of permissions for the content item
|
||||
/// Returns permissions directly assigned to the content item for all user groups
|
||||
/// </summary>
|
||||
/// <param name="content"></param>
|
||||
/// <returns></returns>
|
||||
|
||||
@@ -137,7 +137,7 @@ namespace Umbraco.Core.Services
|
||||
|
||||
/// <summary>
|
||||
/// Used to bulk update the permissions set for a content item. This will replace all permissions
|
||||
/// assigned to an entity with a list of user id & permission pairs.
|
||||
/// assigned to an entity with a list of user group id & permission pairs.
|
||||
/// </summary>
|
||||
/// <param name="permissionSet"></param>
|
||||
void ReplaceContentPermissions(EntityPermissionSet permissionSet);
|
||||
@@ -151,7 +151,7 @@ namespace Umbraco.Core.Services
|
||||
void AssignContentPermission(IContent entity, char permission, IEnumerable<int> groupIds);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the list of permissions for the content item
|
||||
/// Returns permissions directly assigned to the content item for all user groups
|
||||
/// </summary>
|
||||
/// <param name="content"></param>
|
||||
/// <returns></returns>
|
||||
|
||||
@@ -7,7 +7,7 @@ namespace Umbraco.Core.Services
|
||||
internal static class UserServiceExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Remove all permissions for this user for all nodes specified
|
||||
/// Remove all permissions for this user group for all nodes specified
|
||||
/// </summary>
|
||||
/// <param name="userService"></param>
|
||||
/// <param name="groupId"></param>
|
||||
@@ -18,7 +18,7 @@ namespace Umbraco.Core.Services
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove all permissions for this user for all nodes
|
||||
/// Remove all permissions for this user group for all nodes
|
||||
/// </summary>
|
||||
/// <param name="userService"></param>
|
||||
/// <param name="groupId"></param>
|
||||
|
||||
@@ -40,7 +40,24 @@ function contentResource($q, $http, umbDataFormatter, umbRequestHelper) {
|
||||
|
||||
return {
|
||||
|
||||
|
||||
|
||||
savePermissions: function (saveModel) {
|
||||
if (!saveModel) {
|
||||
throw "saveModel cannot be null";
|
||||
}
|
||||
if (!saveModel.contentId) {
|
||||
throw "saveModel.contentId cannot be null";
|
||||
}
|
||||
if (!saveModel.permissions) {
|
||||
throw "saveModel.permissions cannot be null";
|
||||
}
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.post(umbRequestHelper.getApiUrl("contentApiBaseUrl", "PostSaveUserGroupPermissions"),
|
||||
saveModel),
|
||||
'Failed to save permissions');
|
||||
},
|
||||
|
||||
|
||||
getRecycleBin: function () {
|
||||
return umbRequestHelper.resourcePromise(
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
"PostSaveUserGroup"),
|
||||
formattedSaveData),
|
||||
"Failed to save user group");
|
||||
}
|
||||
}
|
||||
|
||||
function getUserGroup(id) {
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
vm.setViewSate = setViewSate;
|
||||
vm.editPermissions = editPermissions;
|
||||
vm.setPermissions = setPermissions;
|
||||
vm.save = save;
|
||||
vm.removePermissions = removePermissions;
|
||||
vm.cancelManagePermissions = cancelManagePermissions;
|
||||
|
||||
@@ -35,7 +36,7 @@
|
||||
|
||||
function setPermissions(group) {
|
||||
// clear allowed permissions before we make the list
|
||||
// so we don't have deplicates
|
||||
// so we don't have duplicates
|
||||
group.allowedPermissions = [];
|
||||
|
||||
// get list of checked permissions
|
||||
@@ -67,6 +68,27 @@
|
||||
setViewSate("manageGroups");
|
||||
}
|
||||
|
||||
function save() {
|
||||
|
||||
//this is a dictionary that we need to format
|
||||
var permissionsSave = {};
|
||||
angular.forEach(vm.selectedUserGroups, function(g) {
|
||||
permissionsSave[g.id] = [];
|
||||
angular.forEach(g.allowedPermissions, function(p) {
|
||||
permissionsSave[g.id].push(p.permissionCode);
|
||||
});
|
||||
});
|
||||
|
||||
var saveModel = {
|
||||
contentId: $scope.currentNode.id,
|
||||
permissions: permissionsSave
|
||||
};
|
||||
|
||||
contentResource.savePermissions(saveModel).then(function() {
|
||||
alert("hooray!");
|
||||
});
|
||||
}
|
||||
|
||||
onInit();
|
||||
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
<a class="btn btn-link" ng-click="nav.hideDialog()" ng-if="!busy">
|
||||
<localize key="general_cancel">Cancel</localize>
|
||||
</a>
|
||||
<button class="btn btn-primary" ng-click="save()" ng-disabled="busy">
|
||||
<button class="btn btn-primary" ng-click="vm.save()" ng-disabled="busy">
|
||||
<localize key="buttons_save">Save</localize>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -27,12 +27,12 @@
|
||||
};
|
||||
}
|
||||
|
||||
if (!window.location.search.getParams) {
|
||||
if (!window.location.getParams) {
|
||||
var pl = /\+/g; // Regex for replacing addition symbol with a space
|
||||
var search = /([^&=]+)=?([^&]*)/g;
|
||||
var decode = function(s) { return decodeURIComponent(s.replace(pl, " ")); };
|
||||
|
||||
window.location.search.getParams = function() {
|
||||
window.location.getParams = function() {
|
||||
var match;
|
||||
var query = window.location.search.substring(1);
|
||||
|
||||
@@ -393,7 +393,7 @@
|
||||
xhr.setRequestHeader("X-XSRF-TOKEN", cookieVal);
|
||||
}
|
||||
|
||||
var queryString = window.location.search.getParams();
|
||||
var queryString = window.location.getParams();
|
||||
if (queryString.umbDebug === "true") {
|
||||
xhr.setRequestHeader("X-UMB-DEBUG", cookieVal);
|
||||
}
|
||||
|
||||
@@ -83,6 +83,55 @@ namespace Umbraco.Web.Editors
|
||||
return foundContent.Select(Mapper.Map<IContent, ContentItemDisplay>);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the permissions for a content item for a particular user group
|
||||
/// </summary>
|
||||
/// <param name="saveModel"></param>
|
||||
/// <returns></returns>
|
||||
public IEnumerable<AssignedUserGroupPermissions> PostSaveUserGroupPermissions(UserGroupPermissionsSave saveModel)
|
||||
{
|
||||
if (saveModel.ContentId <= 0) throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotFound));
|
||||
|
||||
var content = Services.ContentService.GetById(saveModel.ContentId);
|
||||
if (content == null) throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotFound));
|
||||
|
||||
//current permissions explicitly assigned to this content item
|
||||
var contentPermissions = Services.ContentService.GetPermissionsForEntity(content)
|
||||
.ToDictionary(x => x.UserGroupId, x => x);
|
||||
|
||||
var allUserGroups = Services.UserService.GetAllUserGroups().ToArray();
|
||||
|
||||
//loop through each user group
|
||||
foreach (var userGroup in allUserGroups)
|
||||
{
|
||||
//check if there's a permission set posted up for this user group
|
||||
IEnumerable<string> groupPermissions;
|
||||
if (saveModel.AssignedPermissions.TryGetValue(userGroup.Id, out groupPermissions))
|
||||
{
|
||||
//create a string collection of the assigned letters
|
||||
var groupPermissionCodes = groupPermissions.ToArray();
|
||||
|
||||
//check if they are the defaults, if so we should just remove them if they exist since it's more overhead having them stored
|
||||
if (userGroup.Permissions.UnsortedSequenceEqual(groupPermissionCodes))
|
||||
{
|
||||
//only remove them if they are actually currently assigned
|
||||
if (contentPermissions.ContainsKey(userGroup.Id))
|
||||
{
|
||||
//remove these permissions from this node for this group since the ones being assigned are the same as the defaults
|
||||
Services.UserService.RemoveUserGroupPermissions(userGroup.Id, content.Id);
|
||||
}
|
||||
}
|
||||
else if (contentPermissions.ContainsKey(userGroup.Id) == false || contentPermissions[userGroup.Id].AssignedPermissions.UnsortedSequenceEqual(groupPermissionCodes) == false)
|
||||
{
|
||||
//if they are different we need to update, otherwise there's nothing to update
|
||||
Services.UserService.ReplaceUserGroupPermissions(userGroup.Id, groupPermissionCodes.Select(x => x[0]), content.Id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return GetDetailedPermissions(content, allUserGroups);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the user group permissions for user groups assigned to this node
|
||||
/// </summary>
|
||||
@@ -93,41 +142,38 @@ namespace Umbraco.Web.Editors
|
||||
/// </remarks>
|
||||
[EnsureUserPermissionForContent("contentId", 'R')]
|
||||
public IEnumerable<AssignedUserGroupPermissions> GetDetailedPermissions(int contentId)
|
||||
{
|
||||
{
|
||||
if (contentId <= 0) throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotFound));
|
||||
var found = Services.ContentService.GetById(contentId);
|
||||
if (found == null) throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotFound));
|
||||
var content = Services.ContentService.GetById(contentId);
|
||||
if (content == null) throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotFound));
|
||||
|
||||
|
||||
//get all user groups and map their default permissions to the AssignedUserGroupPermissions model.
|
||||
//we do this because not all groups will have true assigned permissions for this node so if they don't have assigned permissions, we need to show the defaults.
|
||||
var allUserGroups = Services.UserService.GetAllUserGroups();
|
||||
|
||||
return GetDetailedPermissions(content, allUserGroups);
|
||||
}
|
||||
|
||||
private IEnumerable<AssignedUserGroupPermissions> GetDetailedPermissions(IContent content, IEnumerable<IUserGroup> allUserGroups)
|
||||
{
|
||||
//get all user groups and map their default permissions to the AssignedUserGroupPermissions model.
|
||||
//we do this because not all groups will have true assigned permissions for this node so if they don't have assigned permissions, we need to show the defaults.
|
||||
|
||||
var defaultPermissionsByGroup = Mapper.Map<IEnumerable<AssignedUserGroupPermissions>>(allUserGroups)
|
||||
.ToDictionary(x => Convert.ToInt32(x.Id), x => x);
|
||||
|
||||
|
||||
//get the actual assigned permissions
|
||||
var assignedPermissionsByGroup = Services.ContentService.GetPermissionsForEntity(found).ToArray();
|
||||
|
||||
var assignedPermissionsByGroup = Services.ContentService.GetPermissionsForEntity(content).ToArray();
|
||||
|
||||
//iterate over assigned and update the defaults with the real values
|
||||
foreach (var assignedGroupPermission in assignedPermissionsByGroup)
|
||||
{
|
||||
var defaultUserGroupPermissions = defaultPermissionsByGroup[assignedGroupPermission.UserGroupId];
|
||||
|
||||
//iterate each assigned permission for this group, the permission is essentially the letter of the action
|
||||
foreach (var assignedPermission in assignedGroupPermission.AssignedPermissions)
|
||||
//since there is custom permissions assigned to this node for this group, we need to clear all of the default permissions
|
||||
//and we'll re-check it if it's one of the explicitly assigned ones
|
||||
foreach (var permission in defaultUserGroupPermissions.AssignedPermissions.SelectMany(x => x.Value))
|
||||
{
|
||||
//find this permission letter in the default model
|
||||
|
||||
//iterate through the dictionary
|
||||
foreach (var defaultUserGroupPermissionByGroup in defaultUserGroupPermissions.AssignedPermissions)
|
||||
{
|
||||
//iterate through the key/value pair values
|
||||
foreach (var permissionInGroup in defaultUserGroupPermissionByGroup.Value)
|
||||
{
|
||||
//assigned the checked parameter based on the actual assigned permission
|
||||
permissionInGroup.Checked = permissionInGroup.PermissionCode == assignedPermission;
|
||||
}
|
||||
}
|
||||
permission.Checked = false;
|
||||
permission.Checked = assignedGroupPermission.AssignedPermissions.Contains(permission.PermissionCode, StringComparer.InvariantCulture);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Linq;
|
||||
using System.Runtime.Serialization;
|
||||
using Umbraco.Core;
|
||||
|
||||
namespace Umbraco.Web.Models.ContentEditing
|
||||
{
|
||||
/// <summary>
|
||||
/// Used to assign user group permissions to a content node
|
||||
/// </summary>
|
||||
[DataContract(Name = "contentPermission", Namespace = "")]
|
||||
public class UserGroupPermissionsSave : IValidatableObject
|
||||
{
|
||||
public UserGroupPermissionsSave()
|
||||
{
|
||||
AssignedPermissions = new Dictionary<int, IEnumerable<string>>();
|
||||
}
|
||||
|
||||
//TODO: we should have an option to clear the permissions assigned to this node and instead just have them inherit - yes once we actually have inheritance!
|
||||
|
||||
[DataMember(Name = "contentId", IsRequired = true)]
|
||||
[Required]
|
||||
public int ContentId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A dictionary of permissions to assign, the key is the user group id
|
||||
/// </summary>
|
||||
[DataMember(Name = "permissions")]
|
||||
public IDictionary<int, IEnumerable<string>> AssignedPermissions { get; set; }
|
||||
|
||||
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
|
||||
{
|
||||
if (AssignedPermissions.SelectMany(x => x.Value).Any(x => x.IsNullOrWhiteSpace()))
|
||||
{
|
||||
yield return new ValidationResult("A permission value cannot be null or empty", new[] { "Permissions" });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,9 @@
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Linq;
|
||||
using System.Runtime.Serialization;
|
||||
using Newtonsoft.Json;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.Membership;
|
||||
|
||||
@@ -50,11 +52,10 @@ namespace Umbraco.Web.Models.ContentEditing
|
||||
|
||||
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
|
||||
{
|
||||
//TODO: Add other server side validation
|
||||
//if (CultureInfo.GetCultureInfo(Culture))
|
||||
// yield return new ValidationResult("The culture is invalid", new[] { "Culture" });
|
||||
|
||||
yield break;
|
||||
if (Permissions.Any(x => x.IsNullOrWhiteSpace()))
|
||||
{
|
||||
yield return new ValidationResult("A permission value cannot be null or empty", new[] { "Permissions" });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -398,6 +398,7 @@
|
||||
<Compile Include="Models\ContentEditing\UserBasic.cs" />
|
||||
<Compile Include="Models\ContentEditing\UserGroupBasic.cs" />
|
||||
<Compile Include="Models\ContentEditing\UserGroupDisplay.cs" />
|
||||
<Compile Include="Models\ContentEditing\UserGroupPermissionsSave.cs" />
|
||||
<Compile Include="Models\ContentEditing\UserGroupSave.cs" />
|
||||
<Compile Include="Models\DetachedPublishedContent.cs" />
|
||||
<Compile Include="Models\DetachedPublishedProperty.cs" />
|
||||
|
||||
Reference in New Issue
Block a user