Gets content permissions saving per user group

This commit is contained in:
Shannon
2017-06-29 19:15:04 +10:00
parent 5dec4a4a94
commit 4f28cb1917
15 changed files with 175 additions and 43 deletions
@@ -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>
+1 -1
View File
@@ -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>
+2 -2
View File
@@ -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);
}
+69 -23
View File
@@ -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" });
}
}
}
}
+1
View File
@@ -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" />