264 lines
10 KiB
C#
264 lines
10 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Globalization;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using Umbraco.Core.Models;
|
|
using Umbraco.Core.Models.Entities;
|
|
using Umbraco.Core.Models.Membership;
|
|
using Umbraco.Core.Services;
|
|
|
|
namespace Umbraco.Core.Security
|
|
{
|
|
public class ContentPermissionsHelper
|
|
{
|
|
public enum ContentAccess
|
|
{
|
|
Granted,
|
|
Denied,
|
|
NotFound
|
|
}
|
|
|
|
public static ContentAccess CheckPermissions(
|
|
IContent content,
|
|
IUser user,
|
|
IUserService userService,
|
|
IEntityService entityService,
|
|
params char[] permissionsToCheck)
|
|
{
|
|
if (user == null) throw new ArgumentNullException("user");
|
|
if (userService == null) throw new ArgumentNullException("userService");
|
|
if (entityService == null) throw new ArgumentNullException("entityService");
|
|
|
|
if (content == null) return ContentAccess.NotFound;
|
|
|
|
var hasPathAccess = user.HasPathAccess(content, entityService);
|
|
|
|
if (hasPathAccess == false)
|
|
return ContentAccess.Denied;
|
|
|
|
if (permissionsToCheck == null || permissionsToCheck.Length == 0)
|
|
return ContentAccess.Granted;
|
|
|
|
//get the implicit/inherited permissions for the user for this path
|
|
return CheckPermissionsPath(content.Path, user, userService, permissionsToCheck)
|
|
? ContentAccess.Granted
|
|
: ContentAccess.Denied;
|
|
}
|
|
|
|
public static ContentAccess CheckPermissions(
|
|
IUmbracoEntity entity,
|
|
IUser user,
|
|
IUserService userService,
|
|
IEntityService entityService,
|
|
params char[] permissionsToCheck)
|
|
{
|
|
if (user == null) throw new ArgumentNullException("user");
|
|
if (userService == null) throw new ArgumentNullException("userService");
|
|
if (entityService == null) throw new ArgumentNullException("entityService");
|
|
|
|
if (entity == null) return ContentAccess.NotFound;
|
|
|
|
var hasPathAccess = user.HasContentPathAccess(entity, entityService);
|
|
|
|
if (hasPathAccess == false)
|
|
return ContentAccess.Denied;
|
|
|
|
if (permissionsToCheck == null || permissionsToCheck.Length == 0)
|
|
return ContentAccess.Granted;
|
|
|
|
//get the implicit/inherited permissions for the user for this path
|
|
return CheckPermissionsPath(entity.Path, user, userService, permissionsToCheck)
|
|
? ContentAccess.Granted
|
|
: ContentAccess.Denied;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Checks if the user has access to the specified node and permissions set
|
|
/// </summary>
|
|
/// <param name="nodeId"></param>
|
|
/// <param name="user"></param>
|
|
/// <param name="userService"></param>
|
|
/// <param name="entityService"></param>
|
|
/// <param name="entity">The <see cref="IUmbracoEntity"/> item resolved if one was found for the id</param>
|
|
/// <param name="permissionsToCheck"></param>
|
|
/// <returns></returns>
|
|
public static ContentAccess CheckPermissions(
|
|
int nodeId,
|
|
IUser user,
|
|
IUserService userService,
|
|
IEntityService entityService,
|
|
out IUmbracoEntity entity,
|
|
params char[] permissionsToCheck)
|
|
{
|
|
if (user == null) throw new ArgumentNullException("user");
|
|
if (userService == null) throw new ArgumentNullException("userService");
|
|
if (entityService == null) throw new ArgumentNullException("entityService");
|
|
|
|
bool? hasPathAccess = null;
|
|
entity = null;
|
|
|
|
if (nodeId == Constants.System.Root)
|
|
hasPathAccess = user.HasContentRootAccess(entityService);
|
|
else if (nodeId == Constants.System.RecycleBinContent)
|
|
hasPathAccess = user.HasContentBinAccess(entityService);
|
|
|
|
if (hasPathAccess.HasValue)
|
|
return hasPathAccess.Value ? ContentAccess.Granted : ContentAccess.Denied;
|
|
|
|
entity = entityService.Get(nodeId, UmbracoObjectTypes.Document);
|
|
if (entity == null) return ContentAccess.NotFound;
|
|
hasPathAccess = user.HasContentPathAccess(entity, entityService);
|
|
|
|
if (hasPathAccess == false)
|
|
return ContentAccess.Denied;
|
|
|
|
if (permissionsToCheck == null || permissionsToCheck.Length == 0)
|
|
return ContentAccess.Granted;
|
|
|
|
//get the implicit/inherited permissions for the user for this path
|
|
return CheckPermissionsPath(entity.Path, user, userService, permissionsToCheck)
|
|
? ContentAccess.Granted
|
|
: ContentAccess.Denied;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Checks if the user has access to the specified node and permissions set
|
|
/// </summary>
|
|
/// <param name="nodeId"></param>
|
|
/// <param name="user"></param>
|
|
/// <param name="userService"></param>
|
|
/// <param name="contentService"></param>
|
|
/// <param name="entityService"></param>
|
|
/// <param name="contentItem">The <see cref="IContent"/> item resolved if one was found for the id</param>
|
|
/// <param name="permissionsToCheck"></param>
|
|
/// <returns></returns>
|
|
public static ContentAccess CheckPermissions(
|
|
int nodeId,
|
|
IUser user,
|
|
IUserService userService,
|
|
IContentService contentService,
|
|
IEntityService entityService,
|
|
out IContent contentItem,
|
|
params char[] permissionsToCheck)
|
|
{
|
|
if (user == null) throw new ArgumentNullException("user");
|
|
if (userService == null) throw new ArgumentNullException("userService");
|
|
if (contentService == null) throw new ArgumentNullException("contentService");
|
|
if (entityService == null) throw new ArgumentNullException("entityService");
|
|
|
|
bool? hasPathAccess = null;
|
|
contentItem = null;
|
|
|
|
if (nodeId == Constants.System.Root)
|
|
hasPathAccess = user.HasContentRootAccess(entityService);
|
|
else if (nodeId == Constants.System.RecycleBinContent)
|
|
hasPathAccess = user.HasContentBinAccess(entityService);
|
|
|
|
if (hasPathAccess.HasValue)
|
|
return hasPathAccess.Value ? ContentAccess.Granted : ContentAccess.Denied;
|
|
|
|
contentItem = contentService.GetById(nodeId);
|
|
if (contentItem == null) return ContentAccess.NotFound;
|
|
hasPathAccess = user.HasPathAccess(contentItem, entityService);
|
|
|
|
if (hasPathAccess == false)
|
|
return ContentAccess.Denied;
|
|
|
|
if (permissionsToCheck == null || permissionsToCheck.Length == 0)
|
|
return ContentAccess.Granted;
|
|
|
|
//get the implicit/inherited permissions for the user for this path
|
|
return CheckPermissionsPath(contentItem.Path, user, userService, permissionsToCheck)
|
|
? ContentAccess.Granted
|
|
: ContentAccess.Denied;
|
|
}
|
|
|
|
private static bool CheckPermissionsPath(string path, IUser user, IUserService userService, params char[] permissionsToCheck)
|
|
{
|
|
//get the implicit/inherited permissions for the user for this path,
|
|
//if there is no content item for this id, than just use the id as the path (i.e. -1 or -20)
|
|
var permission = userService.GetPermissionsForPath(user, path);
|
|
|
|
var allowed = true;
|
|
foreach (var p in permissionsToCheck)
|
|
{
|
|
if (permission == null
|
|
|| permission.GetAllPermissions().Contains(p.ToString(CultureInfo.InvariantCulture)) == false)
|
|
{
|
|
allowed = false;
|
|
}
|
|
}
|
|
return allowed;
|
|
}
|
|
|
|
public static bool HasPathAccess(string path, int[] startNodeIds, int recycleBinId)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(path)) throw new ArgumentException("Value cannot be null or whitespace.", nameof(path));
|
|
|
|
// check for no access
|
|
if (startNodeIds.Length == 0)
|
|
return false;
|
|
|
|
// check for root access
|
|
if (startNodeIds.Contains(Constants.System.Root))
|
|
return true;
|
|
|
|
var formattedPath = string.Concat(",", path, ",");
|
|
|
|
// only users with root access have access to the recycle bin,
|
|
// if the above check didn't pass then access is denied
|
|
if (formattedPath.Contains(string.Concat(",", recycleBinId, ",")))
|
|
return false;
|
|
|
|
// check for a start node in the path
|
|
return startNodeIds.Any(x => formattedPath.Contains(string.Concat(",", x, ",")));
|
|
}
|
|
|
|
public static bool IsInBranchOfStartNode(string path, int[] startNodeIds, string[] startNodePaths, out bool hasPathAccess)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(path)) throw new ArgumentException("Value cannot be null or whitespace.", nameof(path));
|
|
|
|
hasPathAccess = false;
|
|
|
|
// check for no access
|
|
if (startNodeIds.Length == 0)
|
|
return false;
|
|
|
|
// check for root access
|
|
if (startNodeIds.Contains(Constants.System.Root))
|
|
{
|
|
hasPathAccess = true;
|
|
return true;
|
|
}
|
|
|
|
//is it self?
|
|
var self = startNodePaths.Any(x => x == path);
|
|
if (self)
|
|
{
|
|
hasPathAccess = true;
|
|
return true;
|
|
}
|
|
|
|
//is it ancestor?
|
|
var ancestor = startNodePaths.Any(x => x.StartsWith(path));
|
|
if (ancestor)
|
|
{
|
|
//hasPathAccess = false;
|
|
return true;
|
|
}
|
|
|
|
//is it descendant?
|
|
var descendant = startNodePaths.Any(x => path.StartsWith(x));
|
|
if (descendant)
|
|
{
|
|
hasPathAccess = true;
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
}
|
|
}
|