Files
Umbraco-CMS/src/Umbraco.Web/UI/LegacyDialogHandler.cs

197 lines
7.8 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Web;
using System.Xml;
using Umbraco.Core;
using Umbraco.Core.IO;
using umbraco.BasePages;
using umbraco.BusinessLogic;
using umbraco.interfaces;
using System.Linq;
namespace Umbraco.Web.UI
{
/// <summary>
/// This is used to replace the old umbraco.presentation.create.dialogHandler_temp class which is used
/// to handle sections create/delete actions.
/// </summary>
/// <remarks>
/// We need to overhaul how all of this is handled which is why this is a legacy class
/// http://issues.umbraco.org/issue/U4-1373
/// </remarks>
public static class LegacyDialogHandler
{
private enum Operation
{
Create,
Delete
}
private const string ContextKeyCreate = "LegacyDialogHandler-Create-";
private const string ContextKeyDelete = "LegacyDialogHandler-Delete-";
/// <summary>
/// Gets the ITask for the operation for the node Type
/// </summary>
/// <param name="umbracoUser"></param>
/// <param name="op"></param>
/// <param name="nodeType"></param>
/// <param name="httpContext"></param>
/// <returns></returns>
/// <remarks>
/// This will first check if we've already created the ITask in the current Http request
/// </remarks>
private static ITask GetTaskForOperation(HttpContextBase httpContext, User umbracoUser, Operation op, string nodeType)
{
if (httpContext == null) throw new ArgumentNullException("httpContext");
if (umbracoUser == null) throw new ArgumentNullException("umbracoUser");
if (nodeType == null) throw new ArgumentNullException("nodeType");
var ctxKey = op == Operation.Create ? ContextKeyCreate : ContextKeyDelete;
//check contextual cache
if (httpContext.Items[ctxKey] != null)
{
return (ITask) httpContext.Items[ctxKey];
}
var operationNode = op == Operation.Create ? "create" : "delete";
var createDef = GetXmlDoc();
var def = createDef.SelectSingleNode("//nodeType [@alias = '" + nodeType + "']");
if (def == null)
{
throw new InvalidOperationException("Cannot find an item that matches node type " + nodeType);
}
var del = def.SelectSingleNode("./tasks/" + operationNode);
if (del == null)
{
throw new InvalidOperationException("No delete task found for node type " + nodeType);
}
if (!del.Attributes.HasAttribute("assembly"))
{
throw new InvalidOperationException("No assembly attribute found for delete task for node type " + nodeType);
}
var taskAssembly = del.AttributeValue<string>("assembly");
if (!del.Attributes.HasAttribute("type"))
{
throw new InvalidOperationException("No type attribute found for delete task for node type " + nodeType);
}
var taskType = del.AttributeValue<string>("type");
var assembly = Assembly.LoadFrom(IOHelper.MapPath(SystemDirectories.Bin + "/" + taskAssembly + ".dll"));
var type = assembly.GetType(taskAssembly + "." + taskType);
var typeInstance = Activator.CreateInstance(type) as ITask;
if (typeInstance == null)
{
throw new InvalidOperationException("The type returned (" + type + ") is not an " + typeof(ITask));
}
//set the user/user id for the instance
var dialogTask = typeInstance as LegacyDialogTask;
if (dialogTask != null)
{
dialogTask.User = umbracoUser;
}
else
{
typeInstance.UserId = umbracoUser.Id;
}
//put in contextual cache
httpContext.Items[ctxKey] = typeInstance;
return typeInstance;
}
/// <summary>
/// Checks if the user has access to launch the ITask that matches the node type based on the app assigned
/// </summary>
/// <param name="httpContext"></param>
/// <param name="umbracoUser"></param>
/// <param name="nodeType"></param>
/// <returns></returns>
/// <remarks>
/// If the ITask doesn't implement LegacyDialogTask then we will return 'true' since we cannot validate
/// the application assigned.
///
/// TODO: Create an API to assign a nodeType to an app so developers can manually secure it
/// </remarks>
internal static bool UserHasCreateAccess(HttpContextBase httpContext, User umbracoUser, string nodeType)
{
var task = GetTaskForOperation(httpContext, umbracoUser, Operation.Create, nodeType);
var dialogTask = task as LegacyDialogTask;
if (dialogTask != null)
{
return dialogTask.ValidateUserForApplication();
}
return true;
}
/// <summary>
/// Checks if the user has access to launch the ITask that matches the node type based on the app assigned
/// </summary>
/// <param name="httpContext"></param>
/// <param name="umbracoUser"></param>
/// <param name="nodeType"></param>
/// <returns></returns>
/// <remarks>
/// If the ITask doesn't implement LegacyDialogTask then we will return 'true' since we cannot validate
/// the application assigned.
///
/// TODO: Create an API to assign a nodeType to an app so developers can manually secure it
/// </remarks>
internal static bool UserHasDeleteAccess(HttpContextBase httpContext, User umbracoUser, string nodeType)
{
var task = GetTaskForOperation(httpContext, umbracoUser, Operation.Delete, nodeType);
var dialogTask = task as LegacyDialogTask;
if (dialogTask != null)
{
return dialogTask.ValidateUserForApplication();
}
return true;
}
public static void Delete(HttpContextBase httpContext, User umbracoUser, string nodeType, int nodeId, string text)
{
var typeInstance = GetTaskForOperation(httpContext, umbracoUser, Operation.Delete, nodeType);
typeInstance.ParentID = nodeId;
typeInstance.Alias = text;
typeInstance.Delete();
}
public static string Create(HttpContextBase httpContext, User umbracoUser, string nodeType, int nodeId, string text, int typeId = 0)
{
var typeInstance = GetTaskForOperation(httpContext, umbracoUser, Operation.Create, nodeType);
typeInstance.TypeID = typeId;
typeInstance.ParentID = nodeId;
typeInstance.Alias = text;
typeInstance.Save();
// check for returning url
var returnUrlTask = typeInstance as ITaskReturnUrl;
return returnUrlTask != null
? returnUrlTask.ReturnUrl
: "";
}
private static XmlDocument GetXmlDoc()
{
// Load task settings
var createDef = new XmlDocument();
using (var defReader = new XmlTextReader(IOHelper.MapPath(SystemFiles.CreateUiXml)))
{
createDef.Load(defReader);
defReader.Close();
return createDef;
}
}
}
}