* Removed obsoletes from IConfigManipulator. * Removed obsolete models builder extensions. * Removed the obsolete ContentDashboardSettings. * Removed the obsolete InstallMissingDatabase setting on GlobalSettings. * Removed obsolete NuCache settings. * Removed obsolete RuntimeMinificationSettings. * Removed obsolete health check constant. * Removed obsolete icon constant. * Removed obsolete telemetry constant. * Removed obsolete property and constructor on UmbracoBuilder. * Removed obsolete constructor on AuditNotificationsHandler. * Removed obsolete constructor on HTTP header health checks. * Removed obsolete constructor on MediaFileManager. * Removed obsolete GetDefaultFileContent on ViewHelper. * Remove obsoleted methods on embed providers. * Fix tests. * Removed obsolete constructors on BlockEditorDataConverter. * Removed obsolete SeedCacheDuration property on CacheSettings. * Removed obsolete PublishCulture on ContentRepositoryExtensions. * Removed obsolete MonitorLock. * Removed obsolete synchronous HasSavedValues from IDataTypeUsageService and IDataTypeUsageRepository. * Removed obsolete HasSavedPropertyValues from IPropertyTypeUsageService and IPropertyTypeUsageRepository. * Removed obsolete methods in ITrackedReferencesService and ITrackedReferencesRepository. * Removed obsolete DateValueEditor constructors. * Removed obsolete GetAutomaticRelationTypesAliases. * Removed obsolete constructor on TextOnlyValueEditor. * Removed obsolete constructors on RegexValidator and RequiredValidator. * Removed obsolete constructs on SliderValueConverter and TagsValueConverter. * Removed obsolete GetContentType methods from IPublishedCache. * Removed ContentFinderByIdPath. * Removed obsolete constructor on DefaultMediaUrlProvider. * Removed obsolete constructor on Domain. * Removed obsolete constructor on PublishedRequest. * Removed obsolete methods on CheckPermissions. * Removed obsolete GetUserId from IBackOfficeSecurity. * Removed obsolete methods on LegacyPasswordSecurity. * Removed obsolete constructors on AuditService. * Removed obsolete methods on IContentEditingService. * Remove obsolete constructors and methods on ContentService/IContentService. * Removed obsolete constructor in ContentTypeEditingService. * Removed obsolete constructor in MediaTypeEditingService. * Removed obsolete constructor in MemberTypeEditingService. * Removed obsolete constructor in ContentTypeService. * Removed obsolete constructors in ContentTypeServiceBase. * Removed obsolete constructors and methods in ContentVersionService. * Removed obsolete constructor in DataTypeUsageService. * Removed obsolete constructor in DomainService. * Removed obsolete constructor in FileService. * Removes obsolete AttemptMove from IContentService. * Removes obsolete SetPreventCleanup from IContentVersionService. * Removes obsolete GetReferences from IDataTypeService. * Removed obsolete SetConsentLevel from IMetricsConsentService. * Removed obsolete methods from IPackageDataInstallation. * Removed obsolete methods from IPackagingService. * Removed obsolete methods on ITwoFactorLoginService. Removed obsolete ITemporaryMediaService. * Removed obsolete constructor from MediaService, MemberTypeService and MediaTypeService. * More obsolete constructors. * Removed obsoleted overloads on IPropertyValidationService. * Fixed build for tests. * Removed obsolete constructor for PublicAccessService, UserService and RelationService. * Removed GetDefaultMemberType. * Removed obsolete user group functionality from IUserService. * Removed obsolete extension methods on IUserService. * Removed obsolete method from ITelemetryService. * Removed obsolete UdiParserServiceConnectors. * Removed obsolete method on ICookieManager. * Removed obsolete DynamicContext. * Removed obsolete XmlHelper. * Fixed failing integration tests. * Removed obsoletes in Umbraco.Cms.Api.Common * Removed obsoletes in Umbraco.Cms.Api.Delivery * Removed obsoletes in Umbraco.Cms.Api.Management * Removed obsoletes in Umbraco.Examine.Lucene * Removed obsoletes in Umbraco.Infrastructure * Fix failing delivery API contract integration test. * Made integration tests internal. * Removed obsoletes from web projects. * Fix build. * Removed Twitter OEmbed provider * Removed obsolete constructor on PublishedDataType. * Removed obsolete constructors on PublishedCacheBase. * Removed the obsolete PropertyEditorTagsExtensions. * Removed obsoletion properties on configuration response models (#18697) * Removed obsolete methods from server-side models. * Update client-side types and sdk. * Update client-side files. * Removed obsoletion of Utf8ToAsciiConverter.ToAsciiString overload. (#18694) * Removed obsolete method in UserService. (#18710) * Removed obsoleted group alias keys from being publicly available. (#18682) * Removed unneceessary ApiVersion attribute. * Clean-up obsoletions on MemberService (#18703) * Removed obsoleted method on MemberService, added future obsoletion to interface and updated all callers. * Removed obsoletion on member service method that's not obsolete on the interface.
266 lines
8.1 KiB
C#
266 lines
8.1 KiB
C#
using System.Globalization;
|
|
using Umbraco.Cms.Core.Cache;
|
|
using Umbraco.Cms.Core.Models;
|
|
using Umbraco.Cms.Core.Models.Entities;
|
|
using Umbraco.Cms.Core.Models.Membership;
|
|
using Umbraco.Cms.Core.Services;
|
|
|
|
namespace Umbraco.Cms.Core.Security;
|
|
|
|
/// <summary>
|
|
/// Checks user access to content
|
|
/// </summary>
|
|
public class ContentPermissions
|
|
{
|
|
private readonly AppCaches _appCaches;
|
|
|
|
public enum ContentAccess
|
|
{
|
|
Granted,
|
|
Denied,
|
|
NotFound,
|
|
}
|
|
|
|
private readonly IContentService _contentService;
|
|
private readonly IEntityService _entityService;
|
|
private readonly IUserService _userService;
|
|
|
|
public ContentPermissions(
|
|
IUserService userService,
|
|
IContentService contentService,
|
|
IEntityService entityService,
|
|
AppCaches appCaches)
|
|
{
|
|
_userService = userService;
|
|
_contentService = contentService;
|
|
_entityService = entityService;
|
|
_appCaches = appCaches;
|
|
}
|
|
|
|
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 is null || 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.ToString(CultureInfo.InvariantCulture), ",")))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// check for a start node in the path
|
|
return startNodeIds.Any(x =>
|
|
formattedPath.Contains(string.Concat(",", x.ToString(CultureInfo.InvariantCulture), ",")));
|
|
}
|
|
|
|
/// <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="entity">The <see cref="IUmbracoEntity" /> item resolved if one was found for the id</param>
|
|
/// <param name="permissionsToCheck"></param>
|
|
/// <returns></returns>
|
|
[Obsolete($"Please use {nameof(IContentPermissionService)} instead, scheduled for removal in V15.")]
|
|
public ContentAccess CheckPermissions(
|
|
int nodeId,
|
|
IUser user,
|
|
out IUmbracoEntity? entity,
|
|
IReadOnlySet<string>? permissionsToCheck = null)
|
|
{
|
|
if (user == null)
|
|
{
|
|
throw new ArgumentNullException(nameof(user));
|
|
}
|
|
|
|
bool hasPathAccess;
|
|
entity = null;
|
|
|
|
if (nodeId == Constants.System.Root)
|
|
{
|
|
hasPathAccess = user.HasContentRootAccess(_entityService, _appCaches);
|
|
}
|
|
else if (nodeId == Constants.System.RecycleBinContent)
|
|
{
|
|
hasPathAccess = user.HasContentBinAccess(_entityService, _appCaches);
|
|
}
|
|
else
|
|
{
|
|
entity = _entityService.Get(nodeId, UmbracoObjectTypes.Document);
|
|
|
|
if (entity == null)
|
|
{
|
|
return ContentAccess.NotFound;
|
|
}
|
|
|
|
hasPathAccess = user.HasContentPathAccess(entity, _entityService, _appCaches);
|
|
}
|
|
|
|
if (hasPathAccess == false)
|
|
{
|
|
return ContentAccess.Denied;
|
|
}
|
|
|
|
if (permissionsToCheck == null || permissionsToCheck.Count == 0)
|
|
{
|
|
return ContentAccess.Granted;
|
|
}
|
|
|
|
// get the implicit/inherited permissions for the user for this path
|
|
// if there is no entity for this id, then just use the id as the path (i.e. -1 or -20)
|
|
return CheckPermissionsPath(entity?.Path ?? nodeId.ToString(CultureInfo.InvariantCulture), user, 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="contentItem">The <see cref="IContent" /> item resolved if one was found for the id</param>
|
|
/// <param name="permissionsToCheck"></param>
|
|
/// <returns></returns>
|
|
[Obsolete($"Please use {nameof(IContentPermissionService)} instead, scheduled for removal in V15.")]
|
|
public ContentAccess CheckPermissions(
|
|
int nodeId,
|
|
IUser? user,
|
|
out IContent? contentItem,
|
|
IReadOnlySet<string>? permissionsToCheck = null)
|
|
{
|
|
if (user == null)
|
|
{
|
|
throw new ArgumentNullException(nameof(user));
|
|
}
|
|
|
|
bool hasPathAccess;
|
|
contentItem = null;
|
|
|
|
if (nodeId == Constants.System.Root)
|
|
{
|
|
hasPathAccess = user.HasContentRootAccess(_entityService, _appCaches);
|
|
}
|
|
else if (nodeId == Constants.System.RecycleBinContent)
|
|
{
|
|
hasPathAccess = user.HasContentBinAccess(_entityService, _appCaches);
|
|
}
|
|
else
|
|
{
|
|
contentItem = _contentService.GetById(nodeId);
|
|
|
|
if (contentItem == null)
|
|
{
|
|
return ContentAccess.NotFound;
|
|
}
|
|
|
|
hasPathAccess = user.HasPathAccess(contentItem, _entityService, _appCaches);
|
|
}
|
|
|
|
if (hasPathAccess == false)
|
|
{
|
|
return ContentAccess.Denied;
|
|
}
|
|
|
|
if (permissionsToCheck == null || permissionsToCheck.Count == 0)
|
|
{
|
|
return ContentAccess.Granted;
|
|
}
|
|
|
|
// get the implicit/inherited permissions for the user for this path
|
|
// if there is no content item for this id, then just use the id as the path (i.e. -1 or -20)
|
|
return CheckPermissionsPath(contentItem?.Path ?? nodeId.ToString(CultureInfo.InvariantCulture), user, permissionsToCheck)
|
|
? ContentAccess.Granted
|
|
: ContentAccess.Denied;
|
|
}
|
|
|
|
[Obsolete($"Please use {nameof(IContentPermissionService)} instead, scheduled for removal in V15.")]
|
|
private bool CheckPermissionsPath(string? path, IUser user, IReadOnlySet<string>? permissionsToCheck = null)
|
|
{
|
|
if (permissionsToCheck == null)
|
|
{
|
|
permissionsToCheck = new HashSet<string>();
|
|
}
|
|
|
|
// get the implicit/inherited permissions for the user for this path
|
|
EntityPermissionSet 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 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) ?? false)
|
|
{
|
|
hasPathAccess = true;
|
|
return true;
|
|
}
|
|
|
|
// is it self?
|
|
var self = startNodePaths?.Any(x => x == path) ?? false;
|
|
if (self)
|
|
{
|
|
hasPathAccess = true;
|
|
return true;
|
|
}
|
|
|
|
// is it ancestor?
|
|
var ancestor = startNodePaths?.Any(x => x.StartsWith(path)) ?? false;
|
|
if (ancestor)
|
|
{
|
|
// hasPathAccess = false;
|
|
return true;
|
|
}
|
|
|
|
// is it descendant?
|
|
var descendant = startNodePaths?.Any(x => path.StartsWith(x)) ?? false;
|
|
if (descendant)
|
|
{
|
|
hasPathAccess = true;
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
}
|