diff --git a/src/Umbraco.Web.BackOffice/Controllers/CodeFileController.cs b/src/Umbraco.Web.BackOffice/Controllers/CodeFileController.cs
index cfb4d94ad4..63a7330c29 100644
--- a/src/Umbraco.Web.BackOffice/Controllers/CodeFileController.cs
+++ b/src/Umbraco.Web.BackOffice/Controllers/CodeFileController.cs
@@ -30,7 +30,7 @@ namespace Umbraco.Web.BackOffice.Controllers
// ref: https://www.exceptionnotfound.net/the-asp-net-web-api-exception-handling-pipeline-a-guided-tour/
[PluginController("UmbracoApi")]
//[PrefixlessBodyModelValidator]
- [UmbracoApplicationAuthorize(Core.Constants.Applications.Settings)]
+ [TypeFilter(typeof(UmbracoApplicationAuthorizeAttribute), Arguments = new object[]{new string []{Constants.Applications.Settings}})]
public class CodeFileController : BackOfficeNotificationsController
{
private readonly IIOHelper _ioHelper;
diff --git a/src/Umbraco.Web/Editors/DataTypeController.cs b/src/Umbraco.Web.BackOffice/Controllers/DataTypeController.cs
similarity index 63%
rename from src/Umbraco.Web/Editors/DataTypeController.cs
rename to src/Umbraco.Web.BackOffice/Controllers/DataTypeController.cs
index 19ad546b2d..8cc5d884bd 100644
--- a/src/Umbraco.Web/Editors/DataTypeController.cs
+++ b/src/Umbraco.Web.BackOffice/Controllers/DataTypeController.cs
@@ -3,28 +3,21 @@ using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Net;
-using System.Web.Http;
using Umbraco.Core;
using Umbraco.Core.Models;
using Umbraco.Core.PropertyEditors;
using Umbraco.Core.Services;
-using Umbraco.Core.Strings;
using Umbraco.Web.Models.ContentEditing;
-using Umbraco.Web.Mvc;
-using Umbraco.Web.WebApi;
using Umbraco.Web.WebApi.Filters;
using System.Net.Http;
using System.Text;
-using Umbraco.Core.Cache;
-using Umbraco.Web.Composing;
-using Umbraco.Core.Configuration;
-using Umbraco.Core.Logging;
-using Umbraco.Core.Persistence;
using Constants = Umbraco.Core.Constants;
using Umbraco.Core.Mapping;
-using System.Web.Http.Controllers;
+using Microsoft.AspNetCore.Mvc;
using Umbraco.Core.Configuration.UmbracoSettings;
-using Umbraco.Web.Routing;
+using Umbraco.Web.BackOffice.Filters;
+using Umbraco.Web.Common.Attributes;
+using Umbraco.Web.Common.Exceptions;
namespace Umbraco.Web.Editors
{
@@ -37,45 +30,44 @@ namespace Umbraco.Web.Editors
/// Content Types, Member Types or Media Types ... and of course to Data Types
///
[PluginController("UmbracoApi")]
- [UmbracoTreeAuthorize(Constants.Trees.DataTypes, Constants.Trees.DocumentTypes, Constants.Trees.MediaTypes, Constants.Trees.MemberTypes)]
- [EnableOverrideAuthorization]
- [DataTypeControllerConfiguration]
+ [TypeFilter(typeof(UmbracoTreeAuthorizeAttribute), Arguments = new object[]{new string[]{Constants.Trees.DataTypes, Constants.Trees.DocumentTypes, Constants.Trees.MediaTypes, Constants.Trees.MemberTypes}})]
public class DataTypeController : BackOfficeNotificationsController
{
private readonly PropertyEditorCollection _propertyEditors;
+ private readonly IDataTypeService _dataTypeService;
private readonly IContentSettings _contentSettings;
+ private readonly UmbracoMapper _umbracoMapper;
+ private readonly PropertyEditorCollection _propertyEditorCollection;
+ private readonly IContentTypeService _contentTypeService;
+ private readonly IMediaTypeService _mediaTypeService;
+ private readonly IMemberTypeService _memberTypeService;
+ private readonly ILocalizedTextService _localizedTextService;
+ private readonly IUmbracoContextAccessor _umbracoContextAccessor;
public DataTypeController(
PropertyEditorCollection propertyEditors,
- IGlobalSettings globalSettings,
- IUmbracoContextAccessor umbracoContextAccessor,
- ISqlContext sqlContext,
- ServiceContext services,
- AppCaches appCaches,
- IProfilingLogger logger,
- IRuntimeState runtimeState,
- IShortStringHelper shortStringHelper,
- UmbracoMapper umbracoMapper,
+ IDataTypeService dataTypeService,
IContentSettings contentSettings,
- IPublishedUrlProvider publishedUrlProvider)
- : base(globalSettings, umbracoContextAccessor, sqlContext, services, appCaches, logger, runtimeState, shortStringHelper, umbracoMapper, publishedUrlProvider)
- {
- _propertyEditors = propertyEditors;
+ UmbracoMapper umbracoMapper,
+ PropertyEditorCollection propertyEditorCollection,
+ IContentTypeService contentTypeService,
+ IMediaTypeService mediaTypeService,
+ IMemberTypeService memberTypeService,
+ ILocalizedTextService localizedTextService,
+ IUmbracoContextAccessor umbracoContextAccessor)
+ {
+ _propertyEditors = propertyEditors ?? throw new ArgumentNullException(nameof(propertyEditors));
+ _dataTypeService = dataTypeService ?? throw new ArgumentNullException(nameof(dataTypeService));
_contentSettings = contentSettings ?? throw new ArgumentNullException(nameof(contentSettings));
- }
+ _umbracoMapper = umbracoMapper ?? throw new ArgumentNullException(nameof(umbracoMapper));
+ _propertyEditorCollection = propertyEditorCollection ?? throw new ArgumentNullException(nameof(propertyEditorCollection));
+ _contentTypeService = contentTypeService ?? throw new ArgumentNullException(nameof(contentTypeService));
+ _mediaTypeService = mediaTypeService ?? throw new ArgumentNullException(nameof(mediaTypeService));
+ _memberTypeService = memberTypeService ?? throw new ArgumentNullException(nameof(memberTypeService));
+ _localizedTextService = localizedTextService ?? throw new ArgumentNullException(nameof(localizedTextService));
+ _umbracoContextAccessor = umbracoContextAccessor ?? throw new ArgumentNullException(nameof(umbracoContextAccessor));
+ }
- ///
- /// Configures this controller with a custom action selector
- ///
- private class DataTypeControllerConfigurationAttribute : Attribute, IControllerConfiguration
- {
- public void Initialize(HttpControllerSettings controllerSettings, HttpControllerDescriptor controllerDescriptor)
- {
- controllerSettings.Services.Replace(typeof(IHttpActionSelector), new ParameterSwapControllerActionSelector(
- new ParameterSwapControllerActionSelector.ParameterSwapInfo("GetById", "id", typeof(int), typeof(Guid), typeof(Udi))
- ));
- }
- }
///
/// Gets data type by name
@@ -84,8 +76,8 @@ namespace Umbraco.Web.Editors
///
public DataTypeDisplay GetByName(string name)
{
- var dataType = Services.DataTypeService.GetDataType(name);
- return dataType == null ? null : Mapper.Map(dataType);
+ var dataType = _dataTypeService.GetDataType(name);
+ return dataType == null ? null : _umbracoMapper.Map(dataType);
}
///
@@ -95,12 +87,12 @@ namespace Umbraco.Web.Editors
///
public DataTypeDisplay GetById(int id)
{
- var dataType = Services.DataTypeService.GetDataType(id);
+ var dataType = _dataTypeService.GetDataType(id);
if (dataType == null)
{
throw new HttpResponseException(HttpStatusCode.NotFound);
}
- return Mapper.Map(dataType);
+ return _umbracoMapper.Map(dataType);
}
///
@@ -110,12 +102,12 @@ namespace Umbraco.Web.Editors
///
public DataTypeDisplay GetById(Guid id)
{
- var dataType = Services.DataTypeService.GetDataType(id);
+ var dataType = _dataTypeService.GetDataType(id);
if (dataType == null)
{
throw new HttpResponseException(HttpStatusCode.NotFound);
}
- return Mapper.Map(dataType);
+ return _umbracoMapper.Map(dataType);
}
///
@@ -129,12 +121,12 @@ namespace Umbraco.Web.Editors
if (guidUdi == null)
throw new HttpResponseException(HttpStatusCode.NotFound);
- var dataType = Services.DataTypeService.GetDataType(guidUdi.Guid);
+ var dataType = _dataTypeService.GetDataType(guidUdi.Guid);
if (dataType == null)
{
throw new HttpResponseException(HttpStatusCode.NotFound);
}
- return Mapper.Map(dataType);
+ return _umbracoMapper.Map(dataType);
}
///
@@ -144,17 +136,17 @@ namespace Umbraco.Web.Editors
///
[HttpDelete]
[HttpPost]
- public HttpResponseMessage DeleteById(int id)
+ public IActionResult DeleteById(int id)
{
- var foundType = Services.DataTypeService.GetDataType(id);
+ var foundType = _dataTypeService.GetDataType(id);
if (foundType == null)
{
throw new HttpResponseException(HttpStatusCode.NotFound);
}
+ var currentUser = _umbracoContextAccessor.GetRequiredUmbracoContext().Security.CurrentUser;
+ _dataTypeService.Delete(foundType, currentUser.Id);
- Services.DataTypeService.Delete(foundType, Security.CurrentUser.Id);
-
- return Request.CreateResponse(HttpStatusCode.OK);
+ return Ok();
}
public DataTypeDisplay GetEmpty(int parentId)
@@ -162,7 +154,7 @@ namespace Umbraco.Web.Editors
// cannot create an "empty" data type, so use something by default.
var editor = _propertyEditors[Constants.PropertyEditors.Aliases.Label];
var dt = new DataType(editor, parentId);
- return Mapper.Map(dt);
+ return _umbracoMapper.Map(dt);
}
///
@@ -172,13 +164,13 @@ namespace Umbraco.Web.Editors
/// a DataTypeDisplay
public DataTypeDisplay GetCustomListView(string contentTypeAlias)
{
- var dt = Services.DataTypeService.GetDataType(Constants.Conventions.DataTypes.ListViewPrefix + contentTypeAlias);
+ var dt = _dataTypeService.GetDataType(Constants.Conventions.DataTypes.ListViewPrefix + contentTypeAlias);
if (dt == null)
{
throw new HttpResponseException(HttpStatusCode.NotFound);
}
- return Mapper.Map(dt);
+ return _umbracoMapper.Map(dt);
}
///
@@ -188,17 +180,17 @@ namespace Umbraco.Web.Editors
///
public DataTypeDisplay PostCreateCustomListView(string contentTypeAlias)
{
- var dt = Services.DataTypeService.GetDataType(Constants.Conventions.DataTypes.ListViewPrefix + contentTypeAlias);
+ var dt = _dataTypeService.GetDataType(Constants.Conventions.DataTypes.ListViewPrefix + contentTypeAlias);
//if it doesn't exist yet, we will create it.
if (dt == null)
{
var editor = _propertyEditors[Constants.PropertyEditors.Aliases.ListView];
dt = new DataType(editor) { Name = Constants.Conventions.DataTypes.ListViewPrefix + contentTypeAlias };
- Services.DataTypeService.Save(dt);
+ _dataTypeService.Save(dt);
}
- return Mapper.Map(dt);
+ return _umbracoMapper.Map(dt);
}
///
@@ -218,11 +210,11 @@ namespace Umbraco.Web.Editors
if (dataTypeId == -1)
{
//this is a new data type, so just return the field editors with default values
- return Mapper.Map>(propEd);
+ return _umbracoMapper.Map>(propEd);
}
//we have a data type associated
- var dataType = Services.DataTypeService.GetDataType(dataTypeId);
+ var dataType = _dataTypeService.GetDataType(dataTypeId);
if (dataType == null)
{
throw new HttpResponseException(HttpStatusCode.NotFound);
@@ -234,11 +226,11 @@ namespace Umbraco.Web.Editors
if (dataType.EditorAlias == editorAlias)
{
//this is the currently assigned pre-value editor, return with values.
- return Mapper.Map>(dataType);
+ return _umbracoMapper.Map>(dataType);
}
//these are new pre-values, so just return the field editors with default values
- return Mapper.Map>(propEd);
+ return _umbracoMapper.Map>(propEd);
}
///
@@ -248,20 +240,23 @@ namespace Umbraco.Web.Editors
///
[HttpDelete]
[HttpPost]
- public HttpResponseMessage DeleteContainer(int id)
+ public IActionResult DeleteContainer(int id)
{
- Services.DataTypeService.DeleteContainer(id, Security.CurrentUser.Id);
- return Request.CreateResponse(HttpStatusCode.OK);
+ var currentUser = _umbracoContextAccessor.GetRequiredUmbracoContext().Security.CurrentUser;
+ _dataTypeService.DeleteContainer(id, currentUser.Id);
+
+ return Ok();
}
- public HttpResponseMessage PostCreateContainer(int parentId, string name)
+ public IActionResult PostCreateContainer(int parentId, string name)
{
- var result = Services.DataTypeService.CreateContainer(parentId, name, Security.CurrentUser.Id);
+ var currentUser = _umbracoContextAccessor.GetRequiredUmbracoContext().Security.CurrentUser;
+ var result = _dataTypeService.CreateContainer(parentId, name, currentUser.Id);
return result
- ? Request.CreateResponse(HttpStatusCode.OK, result.Result) //return the id
- : Request.CreateNotificationValidationErrorResponse(result.Exception.Message);
+ ? Ok(result.Result) //return the id
+ : throw HttpResponseException.CreateNotificationValidationErrorResponse(result.Exception.Message);
}
///
@@ -269,8 +264,8 @@ namespace Umbraco.Web.Editors
///
///
///
- [DataTypeValidate]
- public DataTypeDisplay PostSave(DataTypeSave dataType)
+ [TypeFilter(typeof(DataTypeValidateAttribute))]
+ public IActionResult PostSave(DataTypeSave dataType)
{
//If we've made it here, then everything has been wired up and validated by the attribute
@@ -286,21 +281,23 @@ namespace Umbraco.Web.Editors
dataType.PersistedDataType.Configuration = configuration;
+ var currentUser = _umbracoContextAccessor.GetRequiredUmbracoContext().Security.CurrentUser;
// save the data type
try
{
- Services.DataTypeService.Save(dataType.PersistedDataType, Security.CurrentUser.Id);
+
+ _dataTypeService.Save(dataType.PersistedDataType, currentUser.Id);
}
catch (DuplicateNameException ex)
{
ModelState.AddModelError("Name", ex.Message);
- throw new HttpResponseException(Request.CreateValidationErrorResponse(ModelState));
+ throw HttpResponseException.CreateValidationErrorResponse(ModelState);
}
// map back to display model, and return
- var display = Mapper.Map(dataType.PersistedDataType);
- display.AddSuccessNotification(Services.TextService.Localize("speechBubbles/dataTypeSaved"), "");
- return display;
+ var display = _umbracoMapper.Map(dataType.PersistedDataType);
+ display.AddSuccessNotification(_localizedTextService.Localize("speechBubbles/dataTypeSaved"), "");
+ return Ok(display);
}
///
@@ -308,46 +305,45 @@ namespace Umbraco.Web.Editors
///
///
///
- public HttpResponseMessage PostMove(MoveOrCopy move)
+ public IActionResult PostMove(MoveOrCopy move)
{
- var toMove = Services.DataTypeService.GetDataType(move.Id);
+ var toMove = _dataTypeService.GetDataType(move.Id);
if (toMove == null)
{
- return Request.CreateResponse(HttpStatusCode.NotFound);
+ return NotFound();
}
- var result = Services.DataTypeService.Move(toMove, move.ParentId);
+ var result = _dataTypeService.Move(toMove, move.ParentId);
if (result.Success)
{
- var response = Request.CreateResponse(HttpStatusCode.OK);
- response.Content = new StringContent(toMove.Path, Encoding.UTF8, "text/plain");
- return response;
+ return Content(toMove.Path,"text/plain", Encoding.UTF8);
}
switch (result.Result.Result)
{
case MoveOperationStatusType.FailedParentNotFound:
- return Request.CreateResponse(HttpStatusCode.NotFound);
+ return NotFound();
case MoveOperationStatusType.FailedCancelledByEvent:
//returning an object of INotificationModel will ensure that any pending
// notification messages are added to the response.
- return Request.CreateValidationErrorResponse(new SimpleNotificationModel());
+ throw HttpResponseException.CreateValidationErrorResponse(new SimpleNotificationModel());
case MoveOperationStatusType.FailedNotAllowedByPath:
var notificationModel = new SimpleNotificationModel();
- notificationModel.AddErrorNotification(Services.TextService.Localize("moveOrCopy/notAllowedByPath"), "");
- return Request.CreateValidationErrorResponse(notificationModel);
+ notificationModel.AddErrorNotification(_localizedTextService.Localize("moveOrCopy/notAllowedByPath"), "");
+ throw HttpResponseException.CreateValidationErrorResponse(notificationModel);
default:
throw new ArgumentOutOfRangeException();
}
}
- public HttpResponseMessage PostRenameContainer(int id, string name)
+ public IActionResult PostRenameContainer(int id, string name)
{
- var result = Services.DataTypeService.RenameContainer(id, name, Security.CurrentUser.Id);
+ var currentUser = _umbracoContextAccessor.GetRequiredUmbracoContext().Security.CurrentUser;
+ var result = _dataTypeService.RenameContainer(id, name, currentUser.Id);
return result
- ? Request.CreateResponse(HttpStatusCode.OK, result.Result)
- : Request.CreateNotificationValidationErrorResponse(result.Exception.Message);
+ ? Ok(result.Result)
+ : throw HttpResponseException.CreateNotificationValidationErrorResponse(result.Exception.Message);
}
///
@@ -358,7 +354,7 @@ namespace Umbraco.Web.Editors
public DataTypeReferences GetReferences(int id)
{
var result = new DataTypeReferences();
- var usages = Services.DataTypeService.GetReferences(id);
+ var usages = _dataTypeService.GetReferences(id);
foreach(var groupOfEntityType in usages.GroupBy(x => x.Key.EntityType))
{
@@ -366,11 +362,11 @@ namespace Umbraco.Web.Editors
var guidsAndPropertyAliases = groupOfEntityType.ToDictionary(i => ((GuidUdi)i.Key).Guid, i => i.Value);
if (groupOfEntityType.Key == ObjectTypes.GetUdiType(UmbracoObjectTypes.DocumentType))
- result.DocumentTypes = GetContentTypeUsages(Services.ContentTypeService.GetAll(guidsAndPropertyAliases.Keys), guidsAndPropertyAliases);
+ result.DocumentTypes = GetContentTypeUsages(_contentTypeService.GetAll(guidsAndPropertyAliases.Keys), guidsAndPropertyAliases);
else if (groupOfEntityType.Key == ObjectTypes.GetUdiType(UmbracoObjectTypes.MediaType))
- result.MediaTypes = GetContentTypeUsages(Services.MediaTypeService.GetAll(guidsAndPropertyAliases.Keys), guidsAndPropertyAliases);
+ result.MediaTypes = GetContentTypeUsages(_mediaTypeService.GetAll(guidsAndPropertyAliases.Keys), guidsAndPropertyAliases);
else if (groupOfEntityType.Key == ObjectTypes.GetUdiType(UmbracoObjectTypes.MemberType))
- result.MemberTypes = GetContentTypeUsages(Services.MemberTypeService.GetAll(guidsAndPropertyAliases.Keys), guidsAndPropertyAliases);
+ result.MemberTypes = GetContentTypeUsages(_memberTypeService.GetAll(guidsAndPropertyAliases.Keys), guidsAndPropertyAliases);
}
return result;
@@ -412,14 +408,13 @@ namespace Umbraco.Web.Editors
///
/// Permission is granted to this method if the user has access to any of these sections: Content, media, settings, developer, members
///
- [UmbracoApplicationAuthorize(
- Constants.Applications.Content, Constants.Applications.Media, Constants.Applications.Members,
- Constants.Applications.Settings, Constants.Applications.Packages)]
+ [TypeFilter(typeof(UmbracoApplicationAuthorizeAttribute), Arguments = new object[]{new string []{Constants.Applications.Content, Constants.Applications.Media, Constants.Applications.Members,
+ Constants.Applications.Settings, Constants.Applications.Packages}})]
public IEnumerable GetAll()
{
- return Services.DataTypeService
+ return _dataTypeService
.GetAll()
- .Select(Mapper.Map).Where(x => x.IsSystemDataType == false);
+ .Select(_umbracoMapper.Map).Where(x => x.IsSystemDataType == false);
}
///
@@ -429,17 +424,16 @@ namespace Umbraco.Web.Editors
///
/// Permission is granted to this method if the user has access to any of these sections: Content, media, settings, developer, members
///
- [UmbracoTreeAuthorize(
- Constants.Applications.Content, Constants.Applications.Media, Constants.Applications.Members,
- Constants.Applications.Settings, Constants.Applications.Packages)]
+ [TypeFilter(typeof(UmbracoTreeAuthorizeAttribute), Arguments = new object[]{new string[]{Constants.Applications.Content, Constants.Applications.Media, Constants.Applications.Members,
+ Constants.Applications.Settings, Constants.Applications.Packages}})]
public IDictionary> GetGroupedDataTypes()
{
- var dataTypes = Services.DataTypeService
+ var dataTypes = _dataTypeService
.GetAll()
- .Select(Mapper.Map)
+ .Select(_umbracoMapper.Map)
.ToArray();
- var propertyEditors = Current.PropertyEditors.ToArray();
+ var propertyEditors =_propertyEditorCollection.ToArray();
foreach (var dataType in dataTypes)
{
@@ -462,20 +456,20 @@ namespace Umbraco.Web.Editors
///
/// Permission is granted to this method if the user has access to any of these sections: Content, media, settings, developer, members
///
- [UmbracoTreeAuthorize(
- Constants.Applications.Content, Constants.Applications.Media, Constants.Applications.Members,
- Constants.Applications.Settings, Constants.Applications.Packages)]
+ [TypeFilter(typeof(UmbracoTreeAuthorizeAttribute), Arguments = new object[]{new string[]{Constants.Applications.Content, Constants.Applications.Media, Constants.Applications.Members,
+ Constants.Applications.Settings, Constants.Applications.Packages}})]
+
public IDictionary> GetGroupedPropertyEditors()
{
var datatypes = new List();
var showDeprecatedPropertyEditors = _contentSettings.ShowDeprecatedPropertyEditors;
- var propertyEditors = Current.PropertyEditors
+ var propertyEditors =_propertyEditorCollection
.Where(x=>x.IsDeprecated == false || showDeprecatedPropertyEditors);
foreach (var propertyEditor in propertyEditors)
{
var hasPrevalues = propertyEditor.GetConfigurationEditor().Fields.Any();
- var basic = Mapper.Map(propertyEditor);
+ var basic = _umbracoMapper.Map(propertyEditor);
basic.HasPrevalues = hasPrevalues;
datatypes.Add(basic);
}
@@ -495,14 +489,14 @@ namespace Umbraco.Web.Editors
///
/// Permission is granted to this method if the user has access to any of these sections: Content, media, settings, developer, members
///
- [UmbracoTreeAuthorize(
- Constants.Applications.Content, Constants.Applications.Media, Constants.Applications.Members,
- Constants.Applications.Settings, Constants.Applications.Packages)]
+ [TypeFilter(typeof(UmbracoTreeAuthorizeAttribute), Arguments = new object[]{new string[]{Constants.Applications.Content, Constants.Applications.Media, Constants.Applications.Members,
+ Constants.Applications.Settings, Constants.Applications.Packages}})]
+
public IEnumerable GetAllPropertyEditors()
{
- return Current.PropertyEditors
+ return _propertyEditorCollection
.OrderBy(x => x.Name)
- .Select(Mapper.Map);
+ .Select(_umbracoMapper.Map);
}
#endregion
}
diff --git a/src/Umbraco.Web/Editors/Filters/DataTypeValidateAttribute.cs b/src/Umbraco.Web.BackOffice/Filters/DataTypeValidateAttribute.cs
similarity index 60%
rename from src/Umbraco.Web/Editors/Filters/DataTypeValidateAttribute.cs
rename to src/Umbraco.Web.BackOffice/Filters/DataTypeValidateAttribute.cs
index efdcf93fff..efd45f3a6e 100644
--- a/src/Umbraco.Web/Editors/Filters/DataTypeValidateAttribute.cs
+++ b/src/Umbraco.Web.BackOffice/Filters/DataTypeValidateAttribute.cs
@@ -1,16 +1,15 @@
using System;
using System.Linq;
using System.Net;
-using System.Net.Http;
-using System.Web.Http.Controllers;
-using System.Web.Http.Filters;
+using Microsoft.AspNetCore.Mvc.Filters;
using Umbraco.Core;
-using Umbraco.Web.Composing;
+using Umbraco.Core.Mapping;
using Umbraco.Core.Models;
using Umbraco.Core.PropertyEditors;
using Umbraco.Core.Services;
+using Umbraco.Web.Common.ActionsResults;
+using Umbraco.Web.Common.Exceptions;
using Umbraco.Web.Models.ContentEditing;
-using Umbraco.Web.WebApi;
namespace Umbraco.Web.Editors
{
@@ -19,38 +18,36 @@ namespace Umbraco.Web.Editors
///
internal sealed class DataTypeValidateAttribute : ActionFilterAttribute
{
- public IDataTypeService DataTypeService { get; }
+ private readonly IDataTypeService _dataTypeService;
+ private readonly PropertyEditorCollection _propertyEditorCollection;
+ private readonly UmbracoMapper _umbracoMapper;
- public PropertyEditorCollection PropertyEditors { get; }
-
- public DataTypeValidateAttribute()
- : this(Current.Factory.GetInstance(), Current.Factory.GetInstance())
- {
- }
///
/// For use in unit tests. Not possible to use as attribute ctor.
///
///
- ///
- public DataTypeValidateAttribute(IDataTypeService dataTypeService, PropertyEditorCollection propertyEditors)
+ ///
+ ///
+ public DataTypeValidateAttribute(IDataTypeService dataTypeService, PropertyEditorCollection propertyEditorCollection, UmbracoMapper umbracoMapper)
{
- DataTypeService = dataTypeService;
- PropertyEditors = propertyEditors;
+ _dataTypeService = dataTypeService ?? throw new ArgumentNullException(nameof(dataTypeService));
+ _propertyEditorCollection = propertyEditorCollection ?? throw new ArgumentNullException(nameof(propertyEditorCollection));
+ _umbracoMapper = umbracoMapper ?? throw new ArgumentNullException(nameof(umbracoMapper));
}
- public override void OnActionExecuting(HttpActionContext actionContext)
+ public override void OnActionExecuting(ActionExecutingContext context)
{
- var dataType = (DataTypeSave) actionContext.ActionArguments["dataType"];
+ var dataType = (DataTypeSave) context.ActionArguments["dataType"];
dataType.Name = dataType.Name.CleanForXss('[', ']', '(', ')', ':');
dataType.Alias = dataType.Alias == null ? dataType.Name : dataType.Alias.CleanForXss('[', ']', '(', ')', ':');
// get the property editor, ensuring that it exits
- if (!PropertyEditors.TryGet(dataType.EditorAlias, out var propertyEditor))
+ if (!_propertyEditorCollection.TryGet(dataType.EditorAlias, out var propertyEditor))
{
var message = $"Property editor \"{dataType.EditorAlias}\" was not found.";
- actionContext.Response = actionContext.Request.CreateErrorResponse(HttpStatusCode.NotFound, message);
+ context.Result = new UmbracoProblemResult(message, HttpStatusCode.NotFound);
return;
}
@@ -62,25 +59,25 @@ namespace Umbraco.Web.Editors
switch (dataType.Action)
{
case ContentSaveAction.Save:
- persisted = DataTypeService.GetDataType(Convert.ToInt32(dataType.Id));
+ persisted = _dataTypeService.GetDataType(Convert.ToInt32(dataType.Id));
if (persisted == null)
{
var message = $"Data type with id {dataType.Id} was not found.";
- actionContext.Response = actionContext.Request.CreateErrorResponse(HttpStatusCode.NotFound, message);
+ context.Result = new UmbracoProblemResult(message, HttpStatusCode.NotFound);
return;
}
// map the model to the persisted instance
- Current.Mapper.Map(dataType, persisted);
+ _umbracoMapper.Map(dataType, persisted);
break;
case ContentSaveAction.SaveNew:
// create the persisted model from mapping the saved model
- persisted = Current.Mapper.Map(dataType);
+ persisted = _umbracoMapper.Map(dataType);
((DataType) persisted).ResetIdentity();
break;
default:
- actionContext.Response = actionContext.Request.CreateErrorResponse(HttpStatusCode.NotFound, new ArgumentOutOfRangeException());
+ context.Result = new UmbracoProblemResult($"Data type action {dataType.Action} was not found.", HttpStatusCode.NotFound);
return;
}
@@ -98,13 +95,13 @@ namespace Umbraco.Web.Editors
// run each IValueValidator (with null valueType and dataTypeConfiguration: not relevant here)
foreach (var validator in editorField.Validators)
foreach (var result in validator.Validate(field.Value, null, null))
- actionContext.ModelState.AddValidationError(result, "Properties", field.Key);
+ context.ModelState.AddModelError(field.Key,result.ErrorMessage);
}
- if (actionContext.ModelState.IsValid == false)
+ if (context.ModelState.IsValid == false)
{
// if it is not valid, do not continue and return the model state
- actionContext.Response = actionContext.Request.CreateValidationErrorResponse(actionContext.ModelState);
+ throw HttpResponseException.CreateValidationErrorResponse(context.ModelState);
}
}
}
diff --git a/src/Umbraco.Web.BackOffice/Filters/UmbracoApplicationAuthorizeAttribute.cs b/src/Umbraco.Web.BackOffice/Filters/UmbracoApplicationAuthorizeAttribute.cs
index 88a4c4f8ff..2a9f88c0be 100644
--- a/src/Umbraco.Web.BackOffice/Filters/UmbracoApplicationAuthorizeAttribute.cs
+++ b/src/Umbraco.Web.BackOffice/Filters/UmbracoApplicationAuthorizeAttribute.cs
@@ -14,6 +14,7 @@ namespace Umbraco.Web.BackOffice.Filters
///
internal static bool Enable = true;
+ private readonly IUmbracoContextAccessor _umbracoContextAccessor;
private readonly string[] _appNames;
///
@@ -22,29 +23,29 @@ namespace Umbraco.Web.BackOffice.Filters
///
/// If the user has access to any of the specified apps, they will be authorized.
///
- public UmbracoApplicationAuthorizeAttribute(params string[] appName)
+ public UmbracoApplicationAuthorizeAttribute(IUmbracoContextAccessor umbracoContextAccessor, params string[] appName)
{
+ _umbracoContextAccessor = umbracoContextAccessor;
_appNames = appName;
}
public void OnAuthorization(AuthorizationFilterContext context)
{
- var umbracoContextAccessor = context.HttpContext.RequestServices.GetRequiredService();
- if (!IsAuthorized(umbracoContextAccessor))
+ if (!IsAuthorized())
{
context.Result = new ForbidResult();
}
}
- private bool IsAuthorized(IUmbracoContextAccessor umbracoContextAccessor)
+ private bool IsAuthorized()
{
if (Enable == false)
{
return true;
}
- var umbracoContext = umbracoContextAccessor.GetRequiredUmbracoContext();
+ var umbracoContext = _umbracoContextAccessor.GetRequiredUmbracoContext();
var authorized = umbracoContext.Security.CurrentUser != null
&& _appNames.Any(app => umbracoContext.Security.UserHasSectionAccess(
app, umbracoContext.Security.CurrentUser));
diff --git a/src/Umbraco.Web.BackOffice/Filters/UmbracoTreeAuthorizeAttribute.cs b/src/Umbraco.Web.BackOffice/Filters/UmbracoTreeAuthorizeAttribute.cs
new file mode 100644
index 0000000000..9a8239b637
--- /dev/null
+++ b/src/Umbraco.Web.BackOffice/Filters/UmbracoTreeAuthorizeAttribute.cs
@@ -0,0 +1,71 @@
+using System.Linq;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.AspNetCore.Mvc.Filters;
+using Umbraco.Core;
+using Umbraco.Web.Services;
+
+namespace Umbraco.Web.BackOffice.Filters
+{
+ ///
+ /// Ensures that the current user has access to the application for which the specified tree(s) belongs
+ ///
+ ///
+ /// This would allow a tree to be moved between sections
+ ///
+ public sealed class UmbracoTreeAuthorizeAttribute : IAuthorizationFilter
+ {
+ ///
+ /// Can be used by unit tests to enable/disable this filter
+ ///
+ internal static bool Enable = true;
+
+ private readonly ITreeService _treeService;
+ private readonly IUmbracoContextAccessor _umbracoContextAccessor;
+ private readonly string[] _treeAliases;
+
+ ///
+ /// Constructor to set authorization to be based on a tree alias for which application security will be applied
+ ///
+ ///
+ ///
+ /// If the user has access to the application that the treeAlias is specified in, they will be authorized.
+ /// Multiple trees may be specified.
+ ///
+ ///
+ public UmbracoTreeAuthorizeAttribute(ITreeService treeService, IUmbracoContextAccessor umbracoContextAccessor, params string[] treeAliases)
+ {
+ _treeService = treeService;
+ _umbracoContextAccessor = umbracoContextAccessor;
+ _treeAliases = treeAliases;
+ }
+
+ private bool IsAuthorized()
+ {
+ if (Enable == false)
+ {
+ return true;
+ }
+
+ var apps = _treeAliases.Select(x => _treeService
+ .GetByAlias(x))
+ .WhereNotNull()
+ .Select(x => x.SectionAlias)
+ .Distinct()
+ .ToArray();
+
+ var umbracoContext = _umbracoContextAccessor.GetRequiredUmbracoContext();
+ return umbracoContext.Security.CurrentUser != null
+ && apps.Any(app => umbracoContext.Security.UserHasSectionAccess(
+ app, umbracoContext.Security.CurrentUser));
+ }
+
+ public void OnAuthorization(AuthorizationFilterContext context)
+ {
+ if (!IsAuthorized())
+ {
+
+ context.Result = new ForbidResult();
+ }
+ }
+ }
+}
diff --git a/src/Umbraco.Web.BackOffice/HealthCheck/HealthCheckController.cs b/src/Umbraco.Web.BackOffice/HealthCheck/HealthCheckController.cs
index db2b72f989..00de2db0b6 100644
--- a/src/Umbraco.Web.BackOffice/HealthCheck/HealthCheckController.cs
+++ b/src/Umbraco.Web.BackOffice/HealthCheck/HealthCheckController.cs
@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Mvc;
+using Umbraco.Core;
using Umbraco.Core.Logging;
using Umbraco.Web.Editors;
using Umbraco.Core.Configuration.HealthChecks;
@@ -12,7 +13,7 @@ namespace Umbraco.Web.HealthCheck
///
/// The API controller used to display the health check info and execute any actions
///
- [UmbracoApplicationAuthorize(Core.Constants.Applications.Settings)]
+ [TypeFilter(typeof(UmbracoApplicationAuthorizeAttribute), Arguments = new object[]{new string []{Constants.Applications.Settings}})]
public class HealthCheckController : UmbracoAuthorizedJsonController
{
private readonly HealthCheckCollection _checks;
diff --git a/src/Umbraco.Web.BackOffice/Profiling/WebProfilingController.cs b/src/Umbraco.Web.BackOffice/Profiling/WebProfilingController.cs
index a053c28d42..ba55dcb51c 100644
--- a/src/Umbraco.Web.BackOffice/Profiling/WebProfilingController.cs
+++ b/src/Umbraco.Web.BackOffice/Profiling/WebProfilingController.cs
@@ -1,4 +1,6 @@
-using Umbraco.Core.Hosting;
+using Microsoft.AspNetCore.Mvc;
+using Umbraco.Core;
+using Umbraco.Core.Hosting;
using Umbraco.Web.BackOffice.Filters;
using Umbraco.Web.Editors;
@@ -8,7 +10,7 @@ namespace Umbraco.Web.BackOffice.Profiling
///
/// The API controller used to display the state of the web profiler
///
- [UmbracoApplicationAuthorizeAttribute(Core.Constants.Applications.Settings)]
+ [TypeFilter(typeof(UmbracoApplicationAuthorizeAttribute), Arguments = new object[]{new string []{Constants.Applications.Settings}})]
public class WebProfilingController : UmbracoAuthorizedJsonController
{
private readonly IHostingEnvironment _hosting;
diff --git a/src/Umbraco.Web.Common/Runtime/AspNetCoreComposer.cs b/src/Umbraco.Web.Common/Runtime/AspNetCoreComposer.cs
index babf6cb80d..5ea29cef1d 100644
--- a/src/Umbraco.Web.Common/Runtime/AspNetCoreComposer.cs
+++ b/src/Umbraco.Web.Common/Runtime/AspNetCoreComposer.cs
@@ -21,6 +21,8 @@ using Umbraco.Web.Common.Controllers;
using System;
using Umbraco.Web.Common.Middleware;
using Umbraco.Web.Common.ModelBinding;
+using Umbraco.Web.Search;
+using Umbraco.Web.Trees;
namespace Umbraco.Web.Common.Runtime
{
@@ -79,6 +81,14 @@ namespace Umbraco.Web.Common.Runtime
composition.WithCollectionBuilder()
.Add(umbracoApiControllerTypes);
+ // register back office trees
+ // the collection builder only accepts types inheriting from TreeControllerBase
+ // and will filter out those that are not attributed with TreeAttribute
+ // composition.Trees()
+ // .AddTreeControllers(umbracoApiControllerTypes.Where(x => typeof(TreeControllerBase).IsAssignableFrom(x)));
+ composition.RegisterUnique(); //TODO replace with collection builder above
+
+
composition.RegisterUnique();
composition.RegisterUnique();
@@ -86,6 +96,10 @@ namespace Umbraco.Web.Common.Runtime
composition.RegisterUnique();
composition.RegisterUnique();
+
+
+
+
}
}
}
diff --git a/src/Umbraco.Web.UI.NetCore/Umbraco.Web.UI.NetCore.csproj b/src/Umbraco.Web.UI.NetCore/Umbraco.Web.UI.NetCore.csproj
index 483e38780e..8f7b78b128 100644
--- a/src/Umbraco.Web.UI.NetCore/Umbraco.Web.UI.NetCore.csproj
+++ b/src/Umbraco.Web.UI.NetCore/Umbraco.Web.UI.NetCore.csproj
@@ -60,6 +60,7 @@
Designer
+
diff --git a/src/Umbraco.Web/Editors/BackOfficeServerVariables.cs b/src/Umbraco.Web/Editors/BackOfficeServerVariables.cs
index f79865c881..a509ecfd29 100644
--- a/src/Umbraco.Web/Editors/BackOfficeServerVariables.cs
+++ b/src/Umbraco.Web/Editors/BackOfficeServerVariables.cs
@@ -208,10 +208,10 @@ namespace Umbraco.Web.Editors
"entityApiBaseUrl", _urlHelper.GetUmbracoApiServiceBaseUrl(
controller => controller.GetById(0, UmbracoEntityTypes.Media))
},
- {
- "dataTypeApiBaseUrl", _urlHelper.GetUmbracoApiServiceBaseUrl(
- controller => controller.GetById(0))
- },
+ // {
+ // "dataTypeApiBaseUrl", _urlHelper.GetUmbracoApiServiceBaseUrl(
+ // controller => controller.GetById(0))
+ // },
//TODO Reintroduce
// {
// "dashboardApiBaseUrl", _urlHelper.GetUmbracoApiServiceBaseUrl(
diff --git a/src/Umbraco.Web/Runtime/WebInitialComposer.cs b/src/Umbraco.Web/Runtime/WebInitialComposer.cs
index a427669ed9..7f437c9378 100644
--- a/src/Umbraco.Web/Runtime/WebInitialComposer.cs
+++ b/src/Umbraco.Web/Runtime/WebInitialComposer.cs
@@ -70,7 +70,7 @@ namespace Umbraco.Web.Runtime
//we need to eagerly scan controller types since they will need to be routed
composition.WithCollectionBuilder()
.Add(composition.TypeLoader.GetSurfaceControllers());
-
+
// add all known factories, devs can then modify this list on application
// startup either by binding to events or in their own global.asax
@@ -83,13 +83,7 @@ namespace Umbraco.Web.Runtime
// register preview SignalR hub
composition.RegisterUnique(_ => GlobalHost.ConnectionManager.GetHubContext());
- var umbracoApiControllerTypes = composition.TypeLoader.GetUmbracoApiControllers().ToList();
- // register back office trees
- // the collection builder only accepts types inheriting from TreeControllerBase
- // and will filter out those that are not attributed with TreeAttribute
- composition.Trees()
- .AddTreeControllers(umbracoApiControllerTypes.Where(x => typeof(TreeControllerBase).IsAssignableFrom(x)));
}
diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj
index f8e73bb361..6687660dc6 100755
--- a/src/Umbraco.Web/Umbraco.Web.csproj
+++ b/src/Umbraco.Web/Umbraco.Web.csproj
@@ -152,11 +152,11 @@
+
-
@@ -339,7 +339,6 @@
-
@@ -389,7 +388,6 @@
-
diff --git a/src/Umbraco.Web/WebApi/Filters/UmbracoTreeAuthorizeAttribute.cs b/src/Umbraco.Web/WebApi/Filters/UmbracoTreeAuthorizeAttribute.cs
index 1bea963ee1..07829648c3 100644
--- a/src/Umbraco.Web/WebApi/Filters/UmbracoTreeAuthorizeAttribute.cs
+++ b/src/Umbraco.Web/WebApi/Filters/UmbracoTreeAuthorizeAttribute.cs
@@ -5,6 +5,7 @@ using System.Web.Http.Filters;
using Umbraco.Core;
using Umbraco.Web.Composing;
+//MOVED to netcore
namespace Umbraco.Web.WebApi.Filters
{
///