diff --git a/src/Umbraco.Core/Constants-Examine.cs b/src/Umbraco.Core/Constants-Examine.cs index d982214341..ddc23fc219 100644 --- a/src/Umbraco.Core/Constants-Examine.cs +++ b/src/Umbraco.Core/Constants-Examine.cs @@ -17,7 +17,22 @@ /// /// The alias of the external content indexer /// - public const string ExternalIndexer = "ExternalIndexer"; + public const string ExternalIndexer = "ExternalIndexer"; + + /// + /// The alias of the internal member searcher + /// + public const string InternalMemberSearcher = "InternalMemberSearcher"; + + /// + /// The alias of the internal content searcher + /// + public const string InternalSearcher = "InternalSearcher"; + + /// + /// The alias of the external content searcher + /// + public const string ExternalSearcher = "ExternalSearcher"; } } } diff --git a/src/Umbraco.Core/Exceptions/AuthorizationException.cs b/src/Umbraco.Core/Exceptions/AuthorizationException.cs new file mode 100644 index 0000000000..955fec270b --- /dev/null +++ b/src/Umbraco.Core/Exceptions/AuthorizationException.cs @@ -0,0 +1,14 @@ +using System; + +namespace Umbraco.Core.Exceptions +{ + public class AuthorizationException : Exception + { + public AuthorizationException() + { } + + public AuthorizationException(string message) + : base(message) + { } + } +} diff --git a/src/Umbraco.Core/Models/UmbracoEntity.cs b/src/Umbraco.Core/Models/UmbracoEntity.cs index f003323462..fc2c7ace6a 100644 --- a/src/Umbraco.Core/Models/UmbracoEntity.cs +++ b/src/Umbraco.Core/Models/UmbracoEntity.cs @@ -51,6 +51,8 @@ namespace Umbraco.Core.Models private string _contentTypeIcon; private string _contentTypeThumbnail; + public static readonly UmbracoEntity Root = new UmbracoEntity(false) { Path = "-1", Name = "root", HasChildren = true }; + public UmbracoEntity() { AdditionalData = new Dictionary(); diff --git a/src/Umbraco.Core/Models/UserExtensions.cs b/src/Umbraco.Core/Models/UserExtensions.cs index 19b870feec..66aa3a1078 100644 --- a/src/Umbraco.Core/Models/UserExtensions.cs +++ b/src/Umbraco.Core/Models/UserExtensions.cs @@ -3,11 +3,9 @@ using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Net; -using Umbraco.Core.Exceptions; using Umbraco.Core.Cache; using Umbraco.Core.Composing; -using Umbraco.Core.IO; -using Umbraco.Core.Models.Identity; +using Umbraco.Core.Models.EntityBase; using Umbraco.Core.Models.Membership; using Umbraco.Core.Services; @@ -15,6 +13,17 @@ namespace Umbraco.Core.Models { public static class UserExtensions { + public static IEnumerable GetPermissions(this IUser user, string path, IUserService userService) + { + return userService.GetPermissionsForPath(user, path).GetAllPermissions(); + } + + public static bool HasSectionAccess(this IUser user, string app) + { + var apps = user.AllowedSections; + return apps.Any(uApp => uApp.InvariantEquals(app)); + } + /// /// Determines whether this user is an admin. /// @@ -166,6 +175,19 @@ namespace Umbraco.Core.Models return HasPathAccess(media.Path, user.CalculateMediaStartNodeIds(entityService), Constants.System.RecycleBinMedia); } + internal static bool HasPathAccess(this IUser user, IUmbracoEntity entity, IEntityService entityService, int recycleBinId) + { + switch (recycleBinId) + { + case Constants.System.RecycleBinMedia: + return HasPathAccess(entity.Path, user.CalculateMediaStartNodeIds(entityService), recycleBinId); + case Constants.System.RecycleBinContent: + return HasPathAccess(entity.Path, user.CalculateContentStartNodeIds(entityService), recycleBinId); + default: + throw new NotSupportedException("Path access is only determined on content or media"); + } + } + internal static bool HasPathAccess(string path, int[] startNodeIds, int recycleBinId) { if (string.IsNullOrWhiteSpace(path)) throw new ArgumentException("Value cannot be null or whitespace.", nameof(path)); diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 8da2b86518..8461862f59 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -385,6 +385,7 @@ + diff --git a/src/Umbraco.Web/Cache/CacheRefresherComponent.cs b/src/Umbraco.Web/Cache/CacheRefresherComponent.cs index 3bd8e5235a..c697ca68a7 100644 --- a/src/Umbraco.Web/Cache/CacheRefresherComponent.cs +++ b/src/Umbraco.Web/Cache/CacheRefresherComponent.cs @@ -65,15 +65,17 @@ namespace Umbraco.Web.Cache Bind(() => SectionService.New += SectionService_New, () => SectionService.New -= SectionService_New); - // bind to user and user type events - Bind(() => UserService.SavedUserType += UserService_SavedUserType, - () => UserService.SavedUserType -= UserService_SavedUserType); - Bind(() => UserService.DeletedUserType += UserService_DeletedUserType, - () => UserService.DeletedUserType -= UserService_DeletedUserType); + // bind to user and user group events + Bind(() => UserService.SavedUserGroup += UserService_SavedUserGroup, + () => UserService.SavedUserGroup -= UserService_SavedUserGroup); + Bind(() => UserService.DeletedUserGroup += UserService_DeletedUserGroup, + () => UserService.DeletedUserGroup -= UserService_DeletedUserGroup); Bind(() => UserService.SavedUser += UserService_SavedUser, () => UserService.SavedUser -= UserService_SavedUser); Bind(() => UserService.DeletedUser += UserService_DeletedUser, () => UserService.DeletedUser -= UserService_DeletedUser); + Bind(() => UserService.UserGroupPermissionsAssigned += UserService_UserGroupPermissionsAssigned, + () => UserService.UserGroupPermissionsAssigned -= UserService_UserGroupPermissionsAssigned); // bind to dictionary events Bind(() => LocalizationService.DeletedDictionaryItem += LocalizationService_DeletedDictionaryItem, @@ -114,11 +116,6 @@ namespace Umbraco.Web.Cache Bind(() => MemberTypeService.Changed += MemberTypeService_Changed, () => MemberTypeService.Changed -= MemberTypeService_Changed); - // bind to permission events - // fixme see v7 events? the PermissionNew/Updated/Deleted are not supported here? - Bind(() => PermissionRepository.AssignedPermissions += PermissionRepository_AssignedPermissions, - () => PermissionRepository.AssignedPermissions -= PermissionRepository_AssignedPermissions); - // bind to template events Bind(() => FileService.SavedTemplate += FileService_SavedTemplate, () => FileService.SavedTemplate -= FileService_SavedTemplate); @@ -153,6 +150,12 @@ namespace Umbraco.Web.Cache Bind(() => ContentService.TreeChanged += ContentService_Changed,// handles all content changes () => ContentService.TreeChanged -= ContentService_Changed); + // TreeChanged should also deal with this + //Bind(() => ContentService.SavedBlueprint += ContentService_SavedBlueprint, + // () => ContentService.SavedBlueprint -= ContentService_SavedBlueprint); + //Bind(() => ContentService.DeletedBlueprint += ContentService_DeletedBlueprint, + // () => ContentService.DeletedBlueprint -= ContentService_DeletedBlueprint); + // bind to public access events Bind(() => PublicAccessService.Saved += PublicAccessService_Saved, () => PublicAccessService.Saved -= PublicAccessService_Saved); @@ -279,14 +282,7 @@ namespace Umbraco.Web.Cache /// case then we need to clear all user permissions cache. /// private void ContentService_Copied(IContentService sender, CopyEventArgs e) - { - //check if permissions have changed - var permissionsChanged = ((Content)e.Copy).WasPropertyDirty("PermissionsChanged"); - if (permissionsChanged) - { - _distributedCache.RefreshAllUserPermissionsCache(); - } - } + { } /// /// Handles cache refreshing for when content is saved (not published) @@ -296,32 +292,9 @@ namespace Umbraco.Web.Cache /// /// When an entity is saved we need to notify other servers about the change in order for the Examine indexes to /// stay up-to-date for unpublished content. - /// - /// When an entity is created new permissions may be assigned to it based on it's parent, if that is the - /// case then we need to clear all user permissions cache. /// private void ContentService_Saved(IContentService sender, SaveEventArgs e) - { - var clearUserPermissions = false; - foreach (var entity in e.SavedEntities) - { - //check if it is new - if (entity.IsNewEntity()) - { - //check if permissions have changed - var permissionsChanged = ((Content)entity).WasPropertyDirty("PermissionsChanged"); - if (permissionsChanged) - { - clearUserPermissions = true; - } - } - } - - if (clearUserPermissions) - { - _distributedCache.RefreshAllUserPermissionsCache(); - } - } + { } private void ContentService_Changed(IContentService sender, TreeChange.EventArgs args) { @@ -336,6 +309,16 @@ namespace Umbraco.Web.Cache private void ContentService_Published(IContentService sender, PublishEventArgs e) { } private void ContentService_UnPublished(IContentService sender, PublishEventArgs e) { } + //private void ContentService_SavedBlueprint(IContentService sender, SaveEventArgs e) + //{ + // _distributedCache.RefreshUnpublishedPageCache(e.SavedEntities.ToArray()); + //} + + //private void ContentService_DeletedBlueprint(IContentService sender, DeleteEventArgs e) + //{ + // _distributedCache.RemoveUnpublishedPageCache(e.DeletedEntities.ToArray()); + //} + #endregion #region ApplicationTreeService @@ -371,22 +354,6 @@ namespace Umbraco.Web.Cache #endregion - #region UserService / UserType - - private void UserService_DeletedUserType(IUserService sender, DeleteEventArgs e) - { - foreach (var entity in e.DeletedEntities) - _distributedCache.RemoveUserTypeCache(entity.Id); - } - - private void UserService_SavedUserType(IUserService sender, SaveEventArgs e) - { - foreach (var entity in e.SavedEntities) - _distributedCache.RefreshUserTypeCache(entity.Id); - } - - #endregion - #region LocalizationService / Dictionary private void LocalizationService_SavedDictionaryItem(ILocalizationService sender, SaveEventArgs e) @@ -488,13 +455,16 @@ namespace Umbraco.Web.Cache #endregion - #region UserService & PermissionRepository + #region UserService - private void PermissionRepository_AssignedPermissions(PermissionRepository sender, SaveEventArgs e) + static void UserService_UserGroupPermissionsAssigned(IUserService sender, SaveEventArgs e) { - var userIds = e.SavedEntities.Select(x => x.UserId).Distinct(); - foreach (var id in userIds) - _distributedCache.RefreshUserPermissionsCache(id); + //TODO: Not sure if we need this yet depends if we start caching permissions + //var groupIds = e.SavedEntities.Select(x => x.UserGroupId).Distinct(); + //foreach (var groupId in groupIds) + //{ + // DistributedCache.Instance.RefreshUserGroupPermissionsCache(groupId); + //} } private void UserService_SavedUser(IUserService sender, SaveEventArgs e) @@ -509,6 +479,18 @@ namespace Umbraco.Web.Cache _distributedCache.RemoveUserCache(entity.Id); } + private void UserService_SavedUserGroup(IUserService sender, SaveEventArgs e) + { + foreach (var entity in e.SavedEntities) + _distributedCache.RefreshUserGroupCache(entity.Id); + } + + private void UserService_DeletedUserGroup(IUserService sender, DeleteEventArgs e) + { + foreach (var entity in e.DeletedEntities) + _distributedCache.RemoveUserGroupCache(entity.Id); + } + #endregion #region FileService diff --git a/src/Umbraco.Web/Composing/Current.cs b/src/Umbraco.Web/Composing/Current.cs index 4a78930aad..cc28e41f22 100644 --- a/src/Umbraco.Web/Composing/Current.cs +++ b/src/Umbraco.Web/Composing/Current.cs @@ -178,6 +178,20 @@ namespace Umbraco.Web.Composing #region Web Actions + public static void RestartAppPool() + { + // see notes in overload + + var httpContext = HttpContext.Current; + if (httpContext != null) + { + httpContext.Application.Add("AppPoolRestarting", true); + httpContext.User = null; + } + Thread.CurrentPrincipal = null; + HttpRuntime.UnloadAppDomain(); + } + public static void RestartAppPool(HttpContextBase httpContext) { // we're going to put an application wide flag to show that the application is about to restart. diff --git a/src/Umbraco.Web/Editors/AuthenticationController.cs b/src/Umbraco.Web/Editors/AuthenticationController.cs index 4777cad6da..7ce63e902c 100644 --- a/src/Umbraco.Web/Editors/AuthenticationController.cs +++ b/src/Umbraco.Web/Editors/AuthenticationController.cs @@ -99,7 +99,7 @@ namespace Umbraco.Web.Editors await SignInManager.SignInAsync(identityUser, false, false); - var user = ApplicationContext.Services.UserService.GetUserById(id); + var user = Services.UserService.GetUserById(id); return Mapper.Map(user); } diff --git a/src/Umbraco.Web/Editors/BackOfficeController.cs b/src/Umbraco.Web/Editors/BackOfficeController.cs index 99f9838e7e..905c9fa519 100644 --- a/src/Umbraco.Web/Editors/BackOfficeController.cs +++ b/src/Umbraco.Web/Editors/BackOfficeController.cs @@ -251,7 +251,7 @@ namespace Umbraco.Web.Editors [MinifyJavaScriptResult(Order = 1)] public JavaScriptResult ServerVariables() { - var serverVars = new BackOfficeServerVariables(Url, ApplicationContext, UmbracoConfig.For.UmbracoSettings()); + var serverVars = new BackOfficeServerVariables(Url, Current.RuntimeState); //cache the result if debugging is disabled var result = HttpContext.IsDebuggingEnabled diff --git a/src/Umbraco.Web/Editors/ContentPostValidateAttribute.cs b/src/Umbraco.Web/Editors/ContentPostValidateAttribute.cs index 806836cd53..cc4de58300 100644 --- a/src/Umbraco.Web/Editors/ContentPostValidateAttribute.cs +++ b/src/Umbraco.Web/Editors/ContentPostValidateAttribute.cs @@ -26,45 +26,33 @@ namespace Umbraco.Web.Editors private readonly IEntityService _entityService; public ContentPostValidateAttribute() - { - } - + { } + + // fixme wtf is this? public ContentPostValidateAttribute(IContentService contentService, IUserService userService, IEntityService entityService, WebSecurity security) { - if (contentService == null) throw new ArgumentNullException("contentService"); - if (userService == null) throw new ArgumentNullException("userService"); - if (entityService == null) throw new ArgumentNullException("entityService"); - if (security == null) throw new ArgumentNullException("security"); - _contentService = contentService; - _userService = userService; - _entityService = entityService; - _security = security; + _contentService = contentService ?? throw new ArgumentNullException(nameof(contentService)); + _userService = userService ?? throw new ArgumentNullException(nameof(userService)); + _entityService = entityService ?? throw new ArgumentNullException(nameof(entityService)); + _security = security ?? throw new ArgumentNullException(nameof(security)); } + + // fixme all these should be injected properties - private IContentService ContentService - { - get { return _contentService ?? Current.Services.ContentService; } - } + private IContentService ContentService + => _contentService ?? Current.Services.ContentService; - private WebSecurity Security - { - get { return _security ?? UmbracoContext.Current.Security; } - } + private WebSecurity Security + => _security ?? UmbracoContext.Current.Security; - private IUserService UserService - { - get { return _userService ?? Current.Services.UserService; } - } + private IUserService UserService + => _userService ?? Current.Services.UserService; - private IEntityService EntityService - { - get { return _entityService ?? ApplicationContext.Current.Services.EntityService; } - } + private IEntityService EntityService + => _entityService ?? Current.Services.EntityService; - public override bool AllowMultiple - { - get { return true; } - } + public override bool AllowMultiple + => true; public override void OnActionExecuting(HttpActionContext actionContext) { @@ -147,15 +135,10 @@ namespace Umbraco.Web.Editors if (ContentController.CheckPermissions( actionContext.Request.Properties, Security.CurrentUser, - UserService, - ContentService, - EntityService, - contentIdToCheck, - permissionToCheck.ToArray(), - contentToCheck) == false) + UserService, ContentService, EntityService, + contentIdToCheck, permissionToCheck.ToArray(), contentToCheck) == false) { actionContext.Response = actionContext.Request.CreateUserNoAccessResponse(); - return; } } } diff --git a/src/Umbraco.Web/Editors/MediaPostValidateAttribute.cs b/src/Umbraco.Web/Editors/MediaPostValidateAttribute.cs index 7784129f8a..71bedea030 100644 --- a/src/Umbraco.Web/Editors/MediaPostValidateAttribute.cs +++ b/src/Umbraco.Web/Editors/MediaPostValidateAttribute.cs @@ -26,30 +26,25 @@ namespace Umbraco.Web.Editors public MediaPostValidateAttribute() { } - + + // fixme wtf is this? public MediaPostValidateAttribute(IMediaService mediaService, IEntityService entityService, WebSecurity security) { - if (mediaService == null) throw new ArgumentNullException("mediaService"); - if (security == null) throw new ArgumentNullException("security"); - _mediaService = mediaService; + _mediaService = mediaService ?? throw new ArgumentNullException(nameof(mediaService)); _entityService = entityService; - _security = security; + _security = security ?? throw new ArgumentNullException(nameof(security)); } - private IMediaService MediaService - { - get { return _mediaService ?? Current.Services.MediaService; } - } + // fixme all these should be injected properties + + private IMediaService MediaService + => _mediaService ?? Current.Services.MediaService; - private IEntityService EntityService - { - get { return _entityService ?? ApplicationContext.Current.Services.EntityService; } - } + private IEntityService EntityService + => _entityService ?? Current.Services.EntityService; - private WebSecurity Security - { - get { return _security ?? UmbracoContext.Current.Security; } - } + private WebSecurity Security + => _security ?? UmbracoContext.Current.Security; public override void OnActionExecuting(HttpActionContext actionContext) { @@ -57,7 +52,7 @@ namespace Umbraco.Web.Editors //We now need to validate that the user is allowed to be doing what they are doing. //Then if it is new, we need to lookup those permissions on the parent. - IMedia contentToCheck = null; + IMedia contentToCheck; int contentIdToCheck; switch (mediaItem.Action) { @@ -88,10 +83,8 @@ namespace Umbraco.Web.Editors if (MediaController.CheckPermissions( actionContext.Request.Properties, Security.CurrentUser, - MediaService, - EntityService, - contentIdToCheck, - contentToCheck) == false) + MediaService, EntityService, + contentIdToCheck, contentToCheck) == false) { throw new HttpResponseException(actionContext.Request.CreateUserNoAccessResponse()); } diff --git a/src/Umbraco.Web/Editors/PackageInstallController.cs b/src/Umbraco.Web/Editors/PackageInstallController.cs index 17b46cc849..94647079be 100644 --- a/src/Umbraco.Web/Editors/PackageInstallController.cs +++ b/src/Umbraco.Web/Editors/PackageInstallController.cs @@ -20,6 +20,7 @@ using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Packaging.Models; using Umbraco.Core.Services; +using Umbraco.Web.Composing; using Umbraco.Web.Models; using Umbraco.Web.Models.ContentEditing; using Umbraco.Web.Mvc; @@ -538,7 +539,7 @@ namespace Umbraco.Web.Editors ins.InstallFiles(model.Id, IOHelper.MapPath(model.TemporaryDirectoryPath)); //set a restarting marker and reset the app pool - ApplicationContext.RestartApplicationPool(Request.TryGetHttpContext().Result); + Current.RestartAppPool(Request.TryGetHttpContext().Result); model.IsRestarting = true; diff --git a/src/Umbraco.Web/Editors/UserGroupValidateAttribute.cs b/src/Umbraco.Web/Editors/UserGroupValidateAttribute.cs index 35cf3930ab..0e4362ebe9 100644 --- a/src/Umbraco.Web/Editors/UserGroupValidateAttribute.cs +++ b/src/Umbraco.Web/Editors/UserGroupValidateAttribute.cs @@ -4,6 +4,7 @@ using System.Net.Http; using System.Web.Http.Controllers; using System.Web.Http.Filters; using AutoMapper; +using Umbraco.Core; using Umbraco.Core.Composing; using Umbraco.Core.Models.Membership; using Umbraco.Core.Services; diff --git a/src/Umbraco.Web/Editors/UsersController.cs b/src/Umbraco.Web/Editors/UsersController.cs index 236c669db4..83c1484c74 100644 --- a/src/Umbraco.Web/Editors/UsersController.cs +++ b/src/Umbraco.Web/Editors/UsersController.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Configuration; using System.IO; using System.Linq; using System.Net; @@ -10,21 +9,17 @@ using System.Threading.Tasks; using System.Web; using System.Web.Http; using System.Web.Mvc; -using System.Web.Routing; -using System.Web.Security; -using System.Web.WebPages; using AutoMapper; -using ClientDependency.Core; using Microsoft.AspNet.Identity; using Umbraco.Core; using Umbraco.Core.Cache; +using Umbraco.Core.Composing; using Umbraco.Core.Configuration; using Umbraco.Core.IO; using Umbraco.Core.Models; using Umbraco.Core.Models.Identity; using Umbraco.Core.Models.Membership; using Umbraco.Core.Persistence.DatabaseModelDefinitions; -using Umbraco.Core.Security; using Umbraco.Core.Services; using Umbraco.Web.Models.ContentEditing; using Umbraco.Web.Mvc; @@ -42,36 +37,13 @@ namespace Umbraco.Web.Editors [IsCurrentUserModelFilter] public class UsersController : UmbracoAuthorizedJsonController { - /// - /// Constructor - /// - public UsersController() - : this(UmbracoContext.Current) - { - } - - /// - /// Constructor - /// - /// - public UsersController(UmbracoContext umbracoContext) - : base(umbracoContext) - { - } - - public UsersController(UmbracoContext umbracoContext, UmbracoHelper umbracoHelper, BackOfficeUserManager backOfficeUserManager) - : base(umbracoContext, umbracoHelper, backOfficeUserManager) - { - } - - /// /// Returns a list of the sizes of gravatar urls for the user or null if the gravatar server cannot be reached /// /// public string[] GetCurrentUserAvatarUrls() { - var urls = UmbracoContext.Security.CurrentUser.GetCurrentUserAvatarUrls(Services.UserService, ApplicationContext.ApplicationCache.StaticCache); + var urls = UmbracoContext.Security.CurrentUser.GetCurrentUserAvatarUrls(Services.UserService, ApplicationCache.StaticCache); if (urls == null) throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.BadRequest, "Could not access Gravatar endpoint")); @@ -82,7 +54,7 @@ namespace Umbraco.Web.Editors [FileUploadCleanupFilter(false)] public async Task PostSetAvatar(int id) { - return await PostSetAvatarInternal(Request, Services.UserService, ApplicationContext.ApplicationCache.StaticCache, id); + return await PostSetAvatarInternal(Request, Services.UserService, ApplicationCache.StaticCache, id); } internal static async Task PostSetAvatarInternal(HttpRequestMessage request, IUserService userService, ICacheProvider staticCache, int id) @@ -127,7 +99,7 @@ namespace Umbraco.Web.Editors using (var fs = System.IO.File.OpenRead(file.LocalFileName)) { - FileSystemProviderManager.Current.MediaFileSystem.AddFile(user.Avatar, fs, true); + Current.FileSystems.MediaFileSystem.AddFile(user.Avatar, fs, true); } userService.Save(user); @@ -168,11 +140,11 @@ namespace Umbraco.Web.Editors if (filePath.IsNullOrWhiteSpace() == false) { - if (FileSystemProviderManager.Current.MediaFileSystem.FileExists(filePath)) - FileSystemProviderManager.Current.MediaFileSystem.DeleteFile(filePath); + if (Current.FileSystems.MediaFileSystem.FileExists(filePath)) + Current.FileSystems.MediaFileSystem.DeleteFile(filePath); } - return Request.CreateResponse(HttpStatusCode.OK, found.GetCurrentUserAvatarUrls(Services.UserService, ApplicationContext.ApplicationCache.StaticCache)); + return Request.CreateResponse(HttpStatusCode.OK, found.GetCurrentUserAvatarUrls(Services.UserService, ApplicationCache.StaticCache)); } /// @@ -390,7 +362,7 @@ namespace Umbraco.Web.Editors }); // Construct full URL using configured application URL (which will fall back to request) - var applicationUri = new Uri(ApplicationContext.UmbracoApplicationUrl); + var applicationUri = RuntimeState.ApplicationUrl; var inviteUri = new Uri(applicationUri, action); var emailSubject = Services.TextService.Localize("user/inviteEmailCopySubject", diff --git a/src/Umbraco.Web/HealthCheck/Checks/Config/AbstractConfigCheck.cs b/src/Umbraco.Web/HealthCheck/Checks/Config/AbstractConfigCheck.cs index 06308d724c..42cb575491 100644 --- a/src/Umbraco.Web/HealthCheck/Checks/Config/AbstractConfigCheck.cs +++ b/src/Umbraco.Web/HealthCheck/Checks/Config/AbstractConfigCheck.cs @@ -54,7 +54,7 @@ namespace Umbraco.Web.HealthCheck.Checks.Config protected AbstractConfigCheck(ILocalizedTextService textService) { TextService = textService; - _configurationService = new ConfigurationService(AbsoluteFilePath, XPath, _textService); + _configurationService = new ConfigurationService(AbsoluteFilePath, XPath, textService); } /// diff --git a/src/Umbraco.Web/HealthCheck/Checks/Security/ClickJackingCheck.cs b/src/Umbraco.Web/HealthCheck/Checks/Security/ClickJackingCheck.cs index 2078dfe951..20e211d16d 100644 --- a/src/Umbraco.Web/HealthCheck/Checks/Security/ClickJackingCheck.cs +++ b/src/Umbraco.Web/HealthCheck/Checks/Security/ClickJackingCheck.cs @@ -90,7 +90,7 @@ namespace Umbraco.Web.HealthCheck.Checks.Security } catch (Exception ex) { - message = _textService.Localize("healthcheck/httpsCheckInvalidUrl", new[] { url, ex.Message }); + message = _textService.Localize("healthcheck/httpsCheckInvalidUrl", new[] { url.ToString(), ex.Message }); } var actions = new List(); diff --git a/src/Umbraco.Web/HealthCheck/Checks/Security/ExcessiveHeadersCheck.cs b/src/Umbraco.Web/HealthCheck/Checks/Security/ExcessiveHeadersCheck.cs index aec57ab003..f49af6da7f 100644 --- a/src/Umbraco.Web/HealthCheck/Checks/Security/ExcessiveHeadersCheck.cs +++ b/src/Umbraco.Web/HealthCheck/Checks/Security/ExcessiveHeadersCheck.cs @@ -71,7 +71,7 @@ namespace Umbraco.Web.HealthCheck.Checks.Security } catch (Exception ex) { - message = _textService.Localize("healthcheck/httpsCheckInvalidUrl", new[] { url, ex.Message }); + message = _textService.Localize("healthcheck/httpsCheckInvalidUrl", new[] { url.ToString(), ex.Message }); } var actions = new List(); diff --git a/src/Umbraco.Web/HealthCheck/Checks/Security/HttpsCheck.cs b/src/Umbraco.Web/HealthCheck/Checks/Security/HttpsCheck.cs index e9e39f6ebe..87dad70b67 100644 --- a/src/Umbraco.Web/HealthCheck/Checks/Security/HttpsCheck.cs +++ b/src/Umbraco.Web/HealthCheck/Checks/Security/HttpsCheck.cs @@ -61,8 +61,8 @@ namespace Umbraco.Web.HealthCheck.Checks.Security // Attempt to access the site over HTTPS to see if it HTTPS is supported // and a valid certificate has been configured - var url = _runtime.ApplicationUrl.Replace("http:", "https:"); - var request = (HttpWebRequest)WebRequest.Create(url); + var url = _runtime.ApplicationUrl.ToString().Replace("http:", "https:"); + var request = (HttpWebRequest) WebRequest.Create(url); request.Method = "HEAD"; try @@ -129,7 +129,7 @@ namespace Umbraco.Web.HealthCheck.Checks.Security private HealthCheckStatus CheckIfCurrentSchemeIsHttps() { - var uri = new Uri(HealthCheckContext.SiteUrl); + var uri = _runtime.ApplicationUrl; var success = uri.Scheme == "https"; var actions = new List(); @@ -145,7 +145,7 @@ namespace Umbraco.Web.HealthCheck.Checks.Security private HealthCheckStatus CheckHttpsConfigurationSetting() { var httpsSettingEnabled = Core.Configuration.GlobalSettings.UseSSL; - var uri = new Uri(HealthCheckContext.SiteUrl); + var uri = _runtime.ApplicationUrl; var actions = new List(); string resultMessage; diff --git a/src/Umbraco.Web/HealthCheck/Checks/Services/SmtpCheck.cs b/src/Umbraco.Web/HealthCheck/Checks/Services/SmtpCheck.cs index 882b4cf049..8e3447c79f 100644 --- a/src/Umbraco.Web/HealthCheck/Checks/Services/SmtpCheck.cs +++ b/src/Umbraco.Web/HealthCheck/Checks/Services/SmtpCheck.cs @@ -53,7 +53,7 @@ namespace Umbraco.Web.HealthCheck.Checks.Services // appPath is the virtual application root path on the server var appPath = ""; - var config = WebConfigurationManager.OpenWebConfiguration(_runtime.ApplicationPath); + var config = WebConfigurationManager.OpenWebConfiguration(_runtime.ApplicationVirtualPath); var settings = (MailSettingsSectionGroup)config.GetSectionGroup("system.net/mailSettings"); if (settings == null) { diff --git a/src/Umbraco.Web/HealthCheck/HealthCheckController.cs b/src/Umbraco.Web/HealthCheck/HealthCheckController.cs index a0dcfb57d8..7a7a62e218 100644 --- a/src/Umbraco.Web/HealthCheck/HealthCheckController.cs +++ b/src/Umbraco.Web/HealthCheck/HealthCheckController.cs @@ -83,10 +83,10 @@ namespace Umbraco.Web.HealthCheck private HealthCheck GetCheckById(Guid id) { var check = _checks - .FirstOrDefault(x => x.Id == action.HealthCheckId) - .Where(x => _disabledCheckIds.Contains(x.Id) == false); + .Where(x => _disabledCheckIds.Contains(x.Id) == false) + .FirstOrDefault(x => x.Id == id); - if (check == null) throw new InvalidOperationException(string.Format("No health check found with id {0}", id)); + if (check == null) throw new InvalidOperationException($"No health check found with id {id}"); return check; } diff --git a/src/Umbraco.Web/Install/InstallSteps/StarterKitDownloadStep.cs b/src/Umbraco.Web/Install/InstallSteps/StarterKitDownloadStep.cs index b8ae254c31..3b08b6be74 100644 --- a/src/Umbraco.Web/Install/InstallSteps/StarterKitDownloadStep.cs +++ b/src/Umbraco.Web/Install/InstallSteps/StarterKitDownloadStep.cs @@ -19,14 +19,12 @@ namespace Umbraco.Web.Install.InstallSteps private readonly InstallHelper _installHelper; private readonly IContentService _contentService; private readonly WebSecurity _security; - private readonly HttpContextBase _httpContext; public StarterKitDownloadStep(IContentService contentService, InstallHelper installHelper, WebSecurity security) { _installHelper = installHelper; _contentService = contentService; _security = security; - _httpContext = httpContext; } private const string RepoGuid = "65194810-1f85-11dd-bd0b-0800200c9a66"; @@ -51,7 +49,7 @@ namespace Umbraco.Web.Install.InstallSteps var result = DownloadPackageFiles(starterKitId.Value); - _applicationContext.RestartApplicationPool(_httpContext); + Current.RestartAppPool(); return new InstallSetupResult(new Dictionary { diff --git a/src/Umbraco.Web/Models/Mapping/ContentProfile.cs b/src/Umbraco.Web/Models/Mapping/ContentProfile.cs index ab38258c28..d00138de72 100644 --- a/src/Umbraco.Web/Models/Mapping/ContentProfile.cs +++ b/src/Umbraco.Web/Models/Mapping/ContentProfile.cs @@ -136,7 +136,7 @@ namespace Umbraco.Web.Models.Mapping Label = localizedText.Localize("content/releaseDate"), Value = display.ReleaseDate?.ToIsoString(), //Not editible for people without publish permission (U4-287) - View = display.AllowedActions.Contains(ActionPublish.Instance.Letter) ? "datepicker" : Current.PropertyEditors[Constants.PropertyEditors.NoEditAlias].ValueEditor.View, + View = display.AllowedActions.Contains(ActionPublish.Instance.Letter.ToString(CultureInfo.InvariantCulture)) ? "datepicker" : Current.PropertyEditors[Constants.PropertyEditors.NoEditAlias].ValueEditor.View, Config = new Dictionary { {"offsetTime", "1"} @@ -149,7 +149,7 @@ namespace Umbraco.Web.Models.Mapping Label = localizedText.Localize("content/unpublishDate"), Value = display.ExpireDate.HasValue ? display.ExpireDate.Value.ToIsoString() : null, //Not editible for people without publish permission (U4-287) - View = display.AllowedActions.Contains(ActionPublish.Instance.Letter) ? "datepicker" : Current.PropertyEditors[Constants.PropertyEditors.NoEditAlias].ValueEditor.View, + View = display.AllowedActions.Contains(ActionPublish.Instance.Letter.ToString(CultureInfo.InvariantCulture)) ? "datepicker" : Current.PropertyEditors[Constants.PropertyEditors.NoEditAlias].ValueEditor.View, Config = new Dictionary { {"offsetTime", "1"} diff --git a/src/Umbraco.Web/Models/Mapping/ContentTypeProfile.cs b/src/Umbraco.Web/Models/Mapping/ContentTypeProfile.cs index 624cec675f..08be60b26d 100644 --- a/src/Umbraco.Web/Models/Mapping/ContentTypeProfile.cs +++ b/src/Umbraco.Web/Models/Mapping/ContentTypeProfile.cs @@ -78,16 +78,16 @@ namespace Umbraco.Web.Models.Mapping CreateMap() //do the base mapping .MapBaseContentTypeSaveToEntity() - .ConstructUsing((source) => new MemberType(source.ParentId)) + .ConstructUsing(source => new MemberType(source.ParentId)) .AfterMap((source, dest) => { ContentTypeProfileExtensions.AfterMapContentTypeSaveToEntity(source, dest, _contentTypeService); //map the MemberCanEditProperty,MemberCanViewProperty - foreach (var propertyType in source.Groups.SelectMany(dest => dest.Properties)) + foreach (var propertyType in source.Groups.SelectMany(x => x.Properties)) { var localCopy = propertyType; - var destProp = dest.PropertyTypes.SingleOrDefault(dest => dest.Alias.InvariantEquals(localCopy.Alias)); + var destProp = dest.PropertyTypes.SingleOrDefault(x => x.Alias.InvariantEquals(localCopy.Alias)); if (destProp != null) { dest.SetMemberCanEditProperty(localCopy.Alias, localCopy.MemberCanEditProperty); @@ -216,7 +216,7 @@ namespace Umbraco.Web.Models.Mapping .AfterMap((source, dest) => { //sync templates - var destAllowedTemplateAliases = dest.AllowedTemplates.Select(dest => dest.Alias); + var destAllowedTemplateAliases = dest.AllowedTemplates.Select(x => x.Alias); //if the dest is set and it's the same as the source, then don't change if (destAllowedTemplateAliases.SequenceEqual(source.AllowedTemplates) == false) { diff --git a/src/Umbraco.Web/Models/Mapping/MemberProfile.cs b/src/Umbraco.Web/Models/Mapping/MemberProfile.cs index 12bf18b6c9..b893ab485d 100644 --- a/src/Umbraco.Web/Models/Mapping/MemberProfile.cs +++ b/src/Umbraco.Web/Models/Mapping/MemberProfile.cs @@ -13,7 +13,6 @@ using System.Linq; using Umbraco.Core.Security; using Umbraco.Web.Composing; using Umbraco.Web.Trees; -using UserProfile = Umbraco.Web.Models.ContentEditing.UserProfile; namespace Umbraco.Web.Models.Mapping { @@ -111,7 +110,7 @@ namespace Umbraco.Web.Models.Mapping .ForMember(dest => dest.CreateDate, opt => opt.MapFrom(src => src.CreationDate)) .ForMember(dest => dest.UpdateDate, opt => opt.MapFrom(src => src.LastActivityDate)) .ForMember(dest => dest.Key, opt => opt.MapFrom(src => src.ProviderUserKey.TryConvertTo().Result.ToString("N"))) - .ForMember(dest => dest.Owner, opt => opt.UseValue(new UserProfile {Name = "Admin", UserId = 0})) + .ForMember(dest => dest.Owner, opt => opt.UseValue(new ContentEditing.UserProfile {Name = "Admin", UserId = 0})) .ForMember(dest => dest.Icon, opt => opt.UseValue("icon-user")) .ForMember(dest => dest.Name, opt => opt.MapFrom(src => src.UserName)) .ForMember(dest => dest.Email, opt => opt.MapFrom(src => src.Email)) diff --git a/src/Umbraco.Web/Models/Mapping/UserProfile.cs b/src/Umbraco.Web/Models/Mapping/UserProfile.cs index b223f7ad40..5ca4a6ada5 100644 --- a/src/Umbraco.Web/Models/Mapping/UserProfile.cs +++ b/src/Umbraco.Web/Models/Mapping/UserProfile.cs @@ -345,7 +345,7 @@ namespace Umbraco.Web.Models.Mapping }); - CreateMap() + CreateMap() .ForMember(dest => dest.UserId, opt => opt.MapFrom(profile => GetIntId(profile.Id))); CreateMap() diff --git a/src/Umbraco.Web/PropertyEditors/NestedContentHelper.cs b/src/Umbraco.Web/PropertyEditors/NestedContentHelper.cs index 87780fee12..37f0095327 100644 --- a/src/Umbraco.Web/PropertyEditors/NestedContentHelper.cs +++ b/src/Umbraco.Web/PropertyEditors/NestedContentHelper.cs @@ -105,7 +105,7 @@ namespace Umbraco.Web.PropertyEditors } // find the content type - var contentType = Current.Services.ContentTypeService.GetAllContentTypes().FirstOrDefault(c => c.Key == guid); + var contentType = Current.Services.ContentTypeService.Get(guid); if (contentType == null) { return; diff --git a/src/Umbraco.Web/PropertyEditors/NestedContentPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/NestedContentPropertyEditor.cs index f34980f992..ad5fa3ac29 100644 --- a/src/Umbraco.Web/PropertyEditors/NestedContentPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/NestedContentPropertyEditor.cs @@ -2,9 +2,7 @@ using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; -using System.Text; using System.Text.RegularExpressions; -using System.Threading.Tasks; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Umbraco.Core; @@ -20,6 +18,8 @@ namespace Umbraco.Web.PropertyEditors [PropertyEditor(Constants.PropertyEditors.NestedContentAlias, "Nested Content", "nestedcontent", ValueType = "JSON", Group = "lists", Icon = "icon-thumbnail-list")] public class NestedContentPropertyEditor : PropertyEditor { + private readonly PropertyEditorCollection _propertyEditors; + internal const string ContentTypeAliasPropertyKey = "ncContentTypeAlias"; private IDictionary _defaultPreValues; @@ -29,9 +29,11 @@ namespace Umbraco.Web.PropertyEditors set => _defaultPreValues = value; } - public NestedContentPropertyEditor(ILogger logger) + public NestedContentPropertyEditor(ILogger logger, PropertyEditorCollection propertyEditors) : base (logger) { + _propertyEditors = propertyEditors; + // Setup default values _defaultPreValues = new Dictionary { @@ -87,21 +89,21 @@ namespace Umbraco.Web.PropertyEditors protected override PropertyValueEditor CreateValueEditor() { - return new NestedContentPropertyValueEditor(base.CreateValueEditor()); + return new NestedContentPropertyValueEditor(base.CreateValueEditor(), _propertyEditors); } internal class NestedContentPropertyValueEditor : PropertyValueEditorWrapper { - public NestedContentPropertyValueEditor(PropertyValueEditor wrapped) + private readonly PropertyEditorCollection _propertyEditors; + + public NestedContentPropertyValueEditor(PropertyValueEditor wrapped, PropertyEditorCollection propertyEditors) : base(wrapped) { - Validators.Add(new NestedContentValidator()); + _propertyEditors = propertyEditors; + Validators.Add(new NestedContentValidator(propertyEditors)); } - internal ServiceContext Services - { - get { return Current.Services; } - } + internal ServiceContext Services => Current.Services; public override void ConfigureForDisplay(PreValueCollection preValues) { @@ -167,7 +169,7 @@ namespace Umbraco.Web.PropertyEditors var prop = new Property(propType, propValues[propKey] == null ? null : propValues[propKey].ToString()); // Lookup the property editor - var propEditor = PropertyEditorResolver.Current.GetByAlias(propType.PropertyEditorAlias); + var propEditor = _propertyEditors[propType.PropertyEditorAlias]; // Get the editor to do it's conversion, and store it back propValues[propKey] = propEditor.ValueEditor.ConvertDbToString(prop, propType, dataTypeService); @@ -242,7 +244,7 @@ namespace Umbraco.Web.PropertyEditors var prop = new Property(propType, propValues[propKey] == null ? null : propValues[propKey].ToString()); // Lookup the property editor - var propEditor = PropertyEditorResolver.Current.GetByAlias(propType.PropertyEditorAlias); + var propEditor = _propertyEditors[propType.PropertyEditorAlias]; // Get the editor to do it's conversion var newValue = propEditor.ValueEditor.ConvertDbToEditor(prop, propType, dataTypeService); @@ -319,7 +321,7 @@ namespace Umbraco.Web.PropertyEditors propType.DataTypeDefinitionId); // Lookup the property editor - var propEditor = PropertyEditorResolver.Current.GetByAlias(propType.PropertyEditorAlias); + var propEditor = _propertyEditors[propType.PropertyEditorAlias]; // Create a fake content property data object var contentPropData = new ContentPropertyData( @@ -344,17 +346,24 @@ namespace Umbraco.Web.PropertyEditors internal class NestedContentValidator : IPropertyValidator { + private readonly PropertyEditorCollection _propertyEditors; + + public NestedContentValidator(PropertyEditorCollection propertyEditors) + { + _propertyEditors = propertyEditors; + } + public IEnumerable Validate(object rawValue, PreValueCollection preValues, PropertyEditor editor) { var value = JsonConvert.DeserializeObject>(rawValue.ToString()); if (value == null) yield break; - IDataTypeService dataTypeService = ApplicationContext.Current.Services.DataTypeService; + var dataTypeService = Current.Services.DataTypeService; for (var i = 0; i < value.Count; i++) { var o = value[i]; - var propValues = ((JObject)o); + var propValues = (JObject) o; var contentType = NestedContentHelper.GetContentTypeFromItem(propValues); if (contentType == null) @@ -369,12 +378,12 @@ namespace Umbraco.Web.PropertyEditors var propType = contentType.CompositionPropertyTypes.FirstOrDefault(x => x.Alias == propKey); if (propType != null) { - PreValueCollection propPrevalues = dataTypeService.GetPreValuesCollectionByDataTypeId(propType.DataTypeDefinitionId); - PropertyEditor propertyEditor = PropertyEditorResolver.Current.GetByAlias(propType.PropertyEditorAlias); + var propPrevalues = dataTypeService.GetPreValuesCollectionByDataTypeId(propType.DataTypeDefinitionId); + PropertyEditor propertyEditor = _propertyEditors[propType.PropertyEditorAlias]; - foreach (IPropertyValidator validator in propertyEditor.ValueEditor.Validators) + foreach (var validator in propertyEditor.ValueEditor.Validators) { - foreach (ValidationResult result in validator.Validate(propValues[propKey], propPrevalues, propertyEditor)) + foreach (var result in validator.Validate(propValues[propKey], propPrevalues, propertyEditor)) { result.ErrorMessage = "Item " + (i + 1) + " '" + propType.Name + "' " + result.ErrorMessage; yield return result; diff --git a/src/Umbraco.Web/Search/UmbracoTreeSearcher.cs b/src/Umbraco.Web/Search/UmbracoTreeSearcher.cs index 0dac79590f..a32f6a0497 100644 --- a/src/Umbraco.Web/Search/UmbracoTreeSearcher.cs +++ b/src/Umbraco.Web/Search/UmbracoTreeSearcher.cs @@ -7,6 +7,7 @@ using System.Text.RegularExpressions; using AutoMapper; using Examine; using Umbraco.Core; +using Umbraco.Core.Composing; using Umbraco.Core.Models; using Umbraco.Core.Services; using Umbraco.Web.Models.ContentEditing; @@ -42,7 +43,6 @@ namespace Umbraco.Web.Search var fields = new[] { "id", "__NodeId" }; var umbracoContext = umbracoHelper.UmbracoContext; - var appContext = umbracoContext.Application; //TODO: WE should really just allow passing in a lucene raw query switch (entityType) @@ -60,13 +60,13 @@ namespace Umbraco.Web.Search break; case UmbracoEntityTypes.Media: type = "media"; - var allMediaStartNodes = umbracoContext.Security.CurrentUser.CalculateMediaStartNodeIds(appContext.Services.EntityService); - AppendPath(sb, UmbracoObjectTypes.Media, allMediaStartNodes, searchFrom, appContext.Services.EntityService); + var allMediaStartNodes = umbracoContext.Security.CurrentUser.CalculateMediaStartNodeIds(Current.Services.EntityService); + AppendPath(sb, UmbracoObjectTypes.Media, allMediaStartNodes, searchFrom, Current.Services.EntityService); break; case UmbracoEntityTypes.Document: type = "content"; - var allContentStartNodes = umbracoContext.Security.CurrentUser.CalculateContentStartNodeIds(appContext.Services.EntityService); - AppendPath(sb, UmbracoObjectTypes.Document, allContentStartNodes, searchFrom, appContext.Services.EntityService); + var allContentStartNodes = umbracoContext.Security.CurrentUser.CalculateContentStartNodeIds(Current.Services.EntityService); + AppendPath(sb, UmbracoObjectTypes.Document, allContentStartNodes, searchFrom, Current.Services.EntityService); break; default: throw new NotSupportedException("The " + typeof(UmbracoTreeSearcher) + " currently does not support searching against object type " + entityType); diff --git a/src/Umbraco.Web/Security/MembershipHelper.cs b/src/Umbraco.Web/Security/MembershipHelper.cs index 4f712f013c..ec73f7831d 100644 --- a/src/Umbraco.Web/Security/MembershipHelper.cs +++ b/src/Umbraco.Web/Security/MembershipHelper.cs @@ -12,8 +12,10 @@ using Umbraco.Core.Security; using Umbraco.Web.Models; using Umbraco.Web.PublishedCache; using Umbraco.Core.Cache; +using Umbraco.Core.Composing; using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.Services; +using Umbraco.Web.Editors; using Umbraco.Web.Security.Providers; using MPE = global::Umbraco.Core.Security.MembershipProviderExtensions; @@ -34,6 +36,7 @@ namespace Umbraco.Web.Security private readonly IMemberTypeService _memberTypeService = Current.Services.MemberTypeService; private readonly IUserService _userService = Current.Services.UserService; private readonly CacheHelper _applicationCache = Current.ApplicationCache; + private readonly ILogger _logger = Current.Logger; #region Constructors diff --git a/src/Umbraco.Web/Security/WebSecurity.cs b/src/Umbraco.Web/Security/WebSecurity.cs index cbbddb11ab..eb71156e25 100644 --- a/src/Umbraco.Web/Security/WebSecurity.cs +++ b/src/Umbraco.Web/Security/WebSecurity.cs @@ -184,8 +184,8 @@ namespace Umbraco.Web.Security { var membershipProvider = Core.Security.MembershipProviderExtensions.GetUsersMembershipProvider(); return membershipProvider != null ? membershipProvider.GetUser(username, setOnline) : null; - } - + } + /// /// Validates the current user to see if they have access to the specified app /// diff --git a/src/Umbraco.Web/Trees/ApplicationTreeController.cs b/src/Umbraco.Web/Trees/ApplicationTreeController.cs index 3d24b7258a..5664214465 100644 --- a/src/Umbraco.Web/Trees/ApplicationTreeController.cs +++ b/src/Umbraco.Web/Trees/ApplicationTreeController.cs @@ -122,7 +122,7 @@ namespace Umbraco.Web.Trees //if the root node has a route path, we cannot create a single root section because by specifying the route path this would //override the dashboard route and that means there can be no dashboard for that section which is a breaking change. - if (rootNode.Result.RoutePath.IsNullOrWhiteSpace() == false + if (string.IsNullOrWhiteSpace(rootNode.Result.RoutePath) == false && rootNode.Result.RoutePath != "#" && rootNode.Result.RoutePath != application) { diff --git a/src/Umbraco.Web/Trees/ContentTypeTreeController.cs b/src/Umbraco.Web/Trees/ContentTypeTreeController.cs index 5252f36c1a..96fe203919 100644 --- a/src/Umbraco.Web/Trees/ContentTypeTreeController.cs +++ b/src/Umbraco.Web/Trees/ContentTypeTreeController.cs @@ -10,6 +10,7 @@ using Umbraco.Web.Models.Trees; using Umbraco.Web.WebApi.Filters; using Umbraco.Core.Services; using Umbraco.Web.Models.ContentEditing; +using Umbraco.Web._Legacy.Actions; namespace Umbraco.Web.Trees { diff --git a/src/Umbraco.Web/Trees/LegacyTreeDataConverter.cs b/src/Umbraco.Web/Trees/LegacyTreeDataConverter.cs index a055975fbd..19978fc3db 100644 --- a/src/Umbraco.Web/Trees/LegacyTreeDataConverter.cs +++ b/src/Umbraco.Web/Trees/LegacyTreeDataConverter.cs @@ -34,20 +34,23 @@ namespace Umbraco.Web.Trees var controllerAttempt = appTree.TryGetControllerTree(); if (controllerAttempt.Success) { - var legacyAtt = controllerAttempt.Result.GetCustomAttribute(false); - if (legacyAtt == null) - { - Current.Logger.Warn("Cannot render tree: " + appTree.Alias + ". Cannot render a " + typeof(TreeController) + " tree type with the legacy web services unless attributed with " + typeof(LegacyBaseTreeAttribute)); - return null; - } + Current.Logger.Warn("Cannot render tree: " + appTree.Alias + ". Cannot render a " + typeof(TreeController) + " tree type with the legacy web services."); + return null; + + //var legacyAtt = controllerAttempt.Result.GetCustomAttribute(false); + //if (legacyAtt == null) + //{ + // Current.Logger.Warn("Cannot render tree: " + appTree.Alias + ". Cannot render a " + typeof(TreeController) + " tree type with the legacy web services unless attributed with " + typeof(LegacyBaseTreeAttribute)); + // return null; + //} - var treeDef = new TreeDefinition( - legacyAtt.BaseTreeType, - new ApplicationTree(true, appTree.SortOrder, appTree.ApplicationAlias, appTree.Alias, appTree.Title, appTree.IconClosed, appTree.IconOpened, legacyAtt.BaseTreeType.GetFullNameWithAssembly()), - new Section(appTree.Alias, appTree.Alias, "", 0)); + //var treeDef = new TreeDefinition( + // legacyAtt.BaseTreeType, + // new ApplicationTree(true, appTree.SortOrder, appTree.ApplicationAlias, appTree.Alias, appTree.Title, appTree.IconClosed, appTree.IconOpened, legacyAtt.BaseTreeType.GetFullNameWithAssembly()), + // new Section(appTree.Alias, appTree.Alias, "", 0)); - tree = treeDef.CreateInstance(); - tree.TreeAlias = appTree.Alias; + //tree = treeDef.CreateInstance(); + //tree.TreeAlias = appTree.Alias; } else diff --git a/src/Umbraco.Web/Trees/UserTypesTreeController.cs b/src/Umbraco.Web/Trees/UserTypesTreeController.cs deleted file mode 100644 index f909c91685..0000000000 --- a/src/Umbraco.Web/Trees/UserTypesTreeController.cs +++ /dev/null @@ -1,66 +0,0 @@ -using System; -using System.Globalization; -using System.Linq; -using System.Net.Http.Formatting; -using Umbraco.Core; -using Umbraco.Core.Services; -using Umbraco.Web.Models.Trees; -using Umbraco.Web.Mvc; -using Umbraco.Web.WebApi.Filters; -using Umbraco.Web._Legacy.Actions; -using Constants = Umbraco.Core.Constants; - -namespace Umbraco.Web.Trees -{ - [UmbracoTreeAuthorize(Constants.Trees.UserTypes)] - [Tree(Constants.Applications.Users, Constants.Trees.UserTypes, null, sortOrder: 1)] - [PluginController("UmbracoTrees")] - [CoreTree] - public class UserTypesTreeController : TreeController - { - protected override TreeNodeCollection GetTreeNodes(string id, FormDataCollection queryStrings) - { - var nodes = new TreeNodeCollection(); - - var userTypes = Services.UserService.GetAllUserTypes(); - userTypes = userTypes.OrderBy(ut => ut.Name); - - foreach (var userType in userTypes) - { - nodes.Add( - CreateTreeNode( - userType.Id.ToString(CultureInfo.InvariantCulture), - "-1", - queryStrings, - userType.Name, - "icon-users", - false, - "/" + queryStrings.GetValue("application") + "/framed/" - + Uri.EscapeDataString("users/EditUserType.aspx?id=" + userType.Id))); - } - - return nodes; - } - - protected override MenuItemCollection GetMenuForNode(string id, FormDataCollection queryStrings) - { - var menu = new MenuItemCollection(); - - if (id == Constants.System.Root.ToInvariantString()) - { - // root actions - menu.Items.Add(Services.TextService.Localize("actions", ActionNew.Instance.Alias)) - .ConvertLegacyMenuItem(null, "userTypes", queryStrings.GetValue("application")); - - menu.Items.Add(Services.TextService.Localize("actions", ActionRefresh.Instance.Alias), true); - return menu; - } - - // delete user type - menu.Items.Add(Services.TextService.Localize("actions", ActionDelete.Instance.Alias)) - .ConvertLegacyMenuItem(null, "userTypes", queryStrings.GetValue("application")); - - return menu; - } - } -} diff --git a/src/Umbraco.Web/UI/Pages/UmbracoEnsuredPage.cs b/src/Umbraco.Web/UI/Pages/UmbracoEnsuredPage.cs index 5b0b60cb65..55356abd69 100644 --- a/src/Umbraco.Web/UI/Pages/UmbracoEnsuredPage.cs +++ b/src/Umbraco.Web/UI/Pages/UmbracoEnsuredPage.cs @@ -1,11 +1,16 @@ using System; +using System.Globalization; +using System.Linq; using System.Security; using System.Web; using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Core; +using Umbraco.Core.Exceptions; +using Umbraco.Core.Models; using Umbraco.Core.Security; using Umbraco.Web.Composing; +using Umbraco.Web._Legacy.Actions; namespace Umbraco.Web.UI.Pages { @@ -29,6 +34,39 @@ namespace Umbraco.Web.UI.Pages } } + /// + /// Performs an authorization check for the user against the requested entity/path and permission set, this is only relevant to content and media + /// + /// + /// + /// + protected void CheckPathAndPermissions(int entityId, UmbracoObjectTypes objectType, IAction actionToCheck) + { + if (objectType == UmbracoObjectTypes.Document || objectType == UmbracoObjectTypes.Media) + { + //check path access + + var entity = entityId == Constants.System.Root + ? UmbracoEntity.Root + : Services.EntityService.Get(entityId, objectType); + var hasAccess = Security.CurrentUser.HasPathAccess(entity, Services.EntityService, objectType == UmbracoObjectTypes.Document ? Constants.System.RecycleBinContent : Constants.System.RecycleBinMedia); + if (hasAccess == false) + throw new AuthorizationException($"The current user doesn't have access to the path '{entity.Path}'"); + + //only documents have action permissions + if (objectType == UmbracoObjectTypes.Document) + { + var allActions = Current.Actions; + var perms = Security.CurrentUser.GetPermissions(entity.Path, Services.UserService); + var actions = perms + .Select(x => allActions.FirstOrDefault(y => y.Letter.ToString(CultureInfo.InvariantCulture) == x)) + .WhereNotNull(); + if (actions.Contains(actionToCheck) == false) + throw new AuthorizationException($"The current user doesn't have permission to {actionToCheck.Alias} on the path '{entity.Path}'"); + } + } + } + private bool _hasValidated = false; /// diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index 4c3ead6200..0e1de88d8f 100644 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -59,9 +59,7 @@ - - @@ -337,7 +335,6 @@ - diff --git a/src/Umbraco.Web/UrlHelperExtensions.cs b/src/Umbraco.Web/UrlHelperExtensions.cs index 14e25f0819..f1363f090a 100644 --- a/src/Umbraco.Web/UrlHelperExtensions.cs +++ b/src/Umbraco.Web/UrlHelperExtensions.cs @@ -184,8 +184,8 @@ namespace Umbraco.Web return DateTime.Now.Ticks.ToString(CultureInfo.InvariantCulture).GenerateHash(); } - var version = UmbracoVersion.GetSemanticVersion().ToSemanticString(); - return string.Format("{0}.{1}", version, ClientDependencySettings.Instance.Version).GenerateHash(); + var version = Current.RuntimeState.SemanticVersion.ToSemanticString(); + return $"{version}.{ClientDependencySettings.Instance.Version}".GenerateHash(); } } } diff --git a/src/Umbraco.Web/WebApi/Filters/CheckIfUserTicketDataIsStaleAttribute.cs b/src/Umbraco.Web/WebApi/Filters/CheckIfUserTicketDataIsStaleAttribute.cs index 46c36e9acd..4b44bd4a95 100644 --- a/src/Umbraco.Web/WebApi/Filters/CheckIfUserTicketDataIsStaleAttribute.cs +++ b/src/Umbraco.Web/WebApi/Filters/CheckIfUserTicketDataIsStaleAttribute.cs @@ -6,6 +6,7 @@ using System.Web.Http.Controllers; using System.Web.Http.Filters; using AutoMapper; using Umbraco.Core; +using Umbraco.Core.Composing; using Umbraco.Core.Models.Identity; using Umbraco.Core.Models.Membership; using Umbraco.Core.Security; @@ -62,7 +63,7 @@ namespace Umbraco.Web.WebApi.Filters var userId = identity.Id.TryConvertTo(); if (userId == false) return; - var user = ApplicationContext.Current.Services.UserService.GetUserById(userId.Result); + var user = Current.Services.UserService.GetUserById(userId.Result); if (user == null) return; //a list of checks to execute, if any of them pass then we resync @@ -71,19 +72,19 @@ namespace Umbraco.Web.WebApi.Filters () => user.Username != identity.Username, () => { - var culture = UserExtensions.GetUserCulture(user, ApplicationContext.Current.Services.TextService); + var culture = UserExtensions.GetUserCulture(user, Current.Services.TextService); return culture != null && culture.ToString() != identity.Culture; }, () => user.AllowedSections.UnsortedSequenceEqual(identity.AllowedApplications) == false, () => user.Groups.Select(x => x.Alias).UnsortedSequenceEqual(identity.Roles) == false, () => { - var startContentIds = UserExtensions.CalculateContentStartNodeIds(user, ApplicationContext.Current.Services.EntityService); + var startContentIds = UserExtensions.CalculateContentStartNodeIds(user, Current.Services.EntityService); return startContentIds.UnsortedSequenceEqual(identity.StartContentNodes) == false; }, () => { - var startMediaIds = UserExtensions.CalculateMediaStartNodeIds(user, ApplicationContext.Current.Services.EntityService); + var startMediaIds = UserExtensions.CalculateMediaStartNodeIds(user, Current.Services.EntityService); return startMediaIds.UnsortedSequenceEqual(identity.StartMediaNodes) == false; } }; diff --git a/src/Umbraco.Web/WebApi/Filters/FilterAllowedOutgoingContentAttribute.cs b/src/Umbraco.Web/WebApi/Filters/FilterAllowedOutgoingContentAttribute.cs index 9c083a9c09..42a1353c7e 100644 --- a/src/Umbraco.Web/WebApi/Filters/FilterAllowedOutgoingContentAttribute.cs +++ b/src/Umbraco.Web/WebApi/Filters/FilterAllowedOutgoingContentAttribute.cs @@ -3,7 +3,6 @@ using System.Collections; using System.Collections.Generic; using System.Globalization; using System.Linq; -using System.Reflection; using Umbraco.Core.Models.Membership; using Umbraco.Core.Services; using Umbraco.Core; @@ -24,39 +23,36 @@ namespace Umbraco.Web.WebApi.Filters private readonly char _permissionToCheck; public FilterAllowedOutgoingContentAttribute(Type outgoingType) - : this(outgoingType, ApplicationContext.Current.Services.UserService, ApplicationContext.Current.Services.EntityService) + : this(outgoingType, Current.Services.UserService, Current.Services.EntityService) { _permissionToCheck = ActionBrowse.Instance.Letter; } public FilterAllowedOutgoingContentAttribute(Type outgoingType, char permissionToCheck) - : this(outgoingType, ApplicationContext.Current.Services.UserService, ApplicationContext.Current.Services.EntityService) + : this(outgoingType, Current.Services.UserService, Current.Services.EntityService) { _permissionToCheck = permissionToCheck; } public FilterAllowedOutgoingContentAttribute(Type outgoingType, string propertyName) - : this(outgoingType, propertyName, ApplicationContext.Current.Services.UserService, ApplicationContext.Current.Services.EntityService) + : this(outgoingType, propertyName, Current.Services.UserService, Current.Services.EntityService) { _permissionToCheck = ActionBrowse.Instance.Letter; } - public FilterAllowedOutgoingContentAttribute(Type outgoingType, IUserService userService, IEntityService entityService) : base(outgoingType) { - if (userService == null) throw new ArgumentNullException("userService"); - if (entityService == null) throw new ArgumentNullException("entityService"); - _userService = userService; - _entityService = entityService; + _userService = userService ?? throw new ArgumentNullException(nameof(userService)); + _entityService = entityService ?? throw new ArgumentNullException(nameof(entityService)); _permissionToCheck = ActionBrowse.Instance.Letter; } public FilterAllowedOutgoingContentAttribute(Type outgoingType, char permissionToCheck, IUserService userService, IEntityService entityService) : base(outgoingType) { - if (userService == null) throw new ArgumentNullException("userService"); - if (entityService == null) throw new ArgumentNullException("entityService"); + _userService = userService ?? throw new ArgumentNullException(nameof(userService)); + _entityService = entityService ?? throw new ArgumentNullException(nameof(entityService)); _userService = userService; _entityService = entityService; _permissionToCheck = permissionToCheck; @@ -65,14 +61,13 @@ namespace Umbraco.Web.WebApi.Filters public FilterAllowedOutgoingContentAttribute(Type outgoingType, string propertyName, IUserService userService, IEntityService entityService) : base(outgoingType, propertyName) { - if (userService == null) throw new ArgumentNullException("userService"); - if (entityService == null) throw new ArgumentNullException("entityService"); + _userService = userService ?? throw new ArgumentNullException(nameof(userService)); + _entityService = entityService ?? throw new ArgumentNullException(nameof(entityService)); _userService = userService; _entityService = entityService; _permissionToCheck = ActionBrowse.Instance.Letter; } - protected override void FilterItems(IUser user, IList items) { base.FilterItems(user, items); diff --git a/src/Umbraco.Web/WebApi/Filters/FilterAllowedOutgoingMediaAttribute.cs b/src/Umbraco.Web/WebApi/Filters/FilterAllowedOutgoingMediaAttribute.cs index c404617188..deaf7628e0 100644 --- a/src/Umbraco.Web/WebApi/Filters/FilterAllowedOutgoingMediaAttribute.cs +++ b/src/Umbraco.Web/WebApi/Filters/FilterAllowedOutgoingMediaAttribute.cs @@ -8,7 +8,6 @@ using Umbraco.Core; using Umbraco.Core.Models; using Umbraco.Core.Models.Membership; using Umbraco.Core.Composing; -using Umbraco.Web.Models.ContentEditing; namespace Umbraco.Web.WebApi.Filters { @@ -35,20 +34,14 @@ namespace Umbraco.Web.WebApi.Filters /// /// Returns true so that other filters can execute along with this one /// - public override bool AllowMultiple - { - get { return true; } - } + public override bool AllowMultiple => true; protected virtual int[] GetUserStartNodes(IUser user) { - return user.CalculateMediaStartNodeIds(ApplicationContext.Current.Services.EntityService); + return user.CalculateMediaStartNodeIds(Current.Services.EntityService); } - protected virtual int RecycleBinId - { - get { return Constants.System.RecycleBinMedia; } - } + protected virtual int RecycleBinId => Constants.System.RecycleBinMedia; public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext) { diff --git a/src/Umbraco.Web/WebApi/UmbracoAuthorizedApiController.cs b/src/Umbraco.Web/WebApi/UmbracoAuthorizedApiController.cs index 52830689bd..4f5d7cfb5c 100644 --- a/src/Umbraco.Web/WebApi/UmbracoAuthorizedApiController.cs +++ b/src/Umbraco.Web/WebApi/UmbracoAuthorizedApiController.cs @@ -22,28 +22,9 @@ namespace Umbraco.Web.WebApi private BackOfficeUserManager _userManager; private bool _userisValidated = false; - protected UmbracoAuthorizedApiController() - { } + protected BackOfficeUserManager UserManager + => _userManager ?? (_userManager = TryGetOwinContext().Result.GetBackOfficeUserManager()); - protected UmbracoAuthorizedApiController(UmbracoContext umbracoContext) - : base(umbracoContext) - { } - - protected UmbracoAuthorizedApiController(UmbracoContext umbracoContext, UmbracoHelper umbracoHelper) - : base(umbracoContext, umbracoHelper) - { } - - protected UmbracoAuthorizedApiController(UmbracoContext umbracoContext, UmbracoHelper umbracoHelper, BackOfficeUserManager backOfficeUserManager) - : base(umbracoContext, umbracoHelper) - { - _userManager = backOfficeUserManager; - } - - protected BackOfficeUserManager UserManager - { - get { return _userManager ?? (_userManager = TryGetOwinContext().Result.GetBackOfficeUserManager()); } - } - /// /// Returns the currently logged in Umbraco User /// diff --git a/src/Umbraco.Web/umbraco.presentation/library.cs b/src/Umbraco.Web/umbraco.presentation/library.cs index e768d70238..d6714db3a9 100644 --- a/src/Umbraco.Web/umbraco.presentation/library.cs +++ b/src/Umbraco.Web/umbraco.presentation/library.cs @@ -1095,8 +1095,8 @@ namespace umbraco try { - var nav = Umbraco.Web.UmbracoContext.Current.ContentCache.CreateNavigator(); - var pageId = HttpContext.Current.Items["pageID"]?.ToString(); + var nav = UmbracoContext.Current.ContentCache.CreateNavigator(); + pageId = HttpContext.Current.Items["pageID"]?.ToString(); if (pageId == null) throw new NullReferenceException("pageID not found in the current HTTP context"); diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/actions/delete.aspx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/actions/delete.aspx.cs index 50588775cc..f7bee05d28 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/actions/delete.aspx.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/actions/delete.aspx.cs @@ -18,8 +18,7 @@ namespace umbraco.presentation.actions if (Security.ValidateUserApp(Constants.Applications.Content) == false) throw new ArgumentException("The current user doesn't have access to this application. Please contact the system administrator."); - if (Security.ValidateUserNodeTreePermissions(Security.CurrentUser, c.Path, "D") == false) - throw new ArgumentException("The current user doesn't have permissions to delete this document. Please contact the system administrator."); + CheckPathAndPermissions(c.Id, UmbracoObjectTypes.Document, Umbraco.Web._Legacy.Actions.ActionDelete.Instance); pane_delete.Text = Services.TextService.Localize("delete") + " '" + c.Name + "'"; Panel2.Text = Services.TextService.Localize("delete"); diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/search.aspx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/search.aspx.cs index c75234ad03..4717bc48e3 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/search.aspx.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/search.aspx.cs @@ -79,12 +79,13 @@ namespace umbraco.presentation.dialogs foreach (var word in words) operation = operation.And().GroupedOr(new[] { "__nodeName" }, new[] { word }); - // ensure the user can only find nodes they are allowed to see - if (Security.CurrentUser.StartContentId > 0) + // ensure the user can only find nodes they are allowed to see + // fixme BORKED because we don't deal with all start nodes + if (Security.CurrentUser.StartContentIds.FirstOrDefault() > 0) { //TODO: This is not correct! This will not filter out seearches 'from' this node, this // query is meant to search 'for' a specific node. - operation = operation.And().Id(Security.CurrentUser.StartContentId); + operation = operation.And().Id(Security.CurrentUser.StartContentIds.FirstOrDefault()); } results = internalSearcher.Search(operation.Compile()); diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/sendToTranslation.aspx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/sendToTranslation.aspx.cs index b24f91d259..0bd1374fb2 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/sendToTranslation.aspx.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/sendToTranslation.aspx.cs @@ -73,9 +73,10 @@ namespace umbraco.presentation.dialogs includeSubpages.Enabled = false; // Translators - long totalUsers; - foreach (var u in Services.UserService.GetAll(0, int.MaxValue, out totalUsers)) - if (u.GetGroups().Select(x => x.ToLower()).Contains("translators") || UserHasTranslatePermission(u, _currentPage)) + var translatorsGroup = Services.UserService.GetUserGroupByAlias("translators"); + var users = Services.UserService.GetAllInGroup(translatorsGroup.Id); + foreach (var u in users) + if (UserHasTranslatePermission(u, _currentPage)) translator.Items.Add(new ListItem(u.Name, u.Id.ToString())); if (translator.Items.Count == 0) {