further refactor base/rest service into Umbraco.Web
This commit is contained in:
@@ -11,7 +11,6 @@ using umbraco.MacroEngines.Iron;
|
||||
using umbraco.businesslogic;
|
||||
using umbraco.cms.businesslogic;
|
||||
using umbraco.editorControls;
|
||||
using umbraco.presentation.umbracobase;
|
||||
using umbraco.uicontrols;
|
||||
using umbraco.cms;
|
||||
|
||||
@@ -128,6 +127,13 @@ namespace Umbraco.Tests
|
||||
Assert.AreEqual(2, types.Count());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Resolves_LegacyRestExtensions()
|
||||
{
|
||||
var types = PluginManager.Current.ResolveLegacyRestExtensions();
|
||||
Assert.AreEqual(1, types.Count());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Resolves_XsltExtensions()
|
||||
{
|
||||
@@ -141,12 +147,18 @@ namespace Umbraco.Tests
|
||||
|
||||
}
|
||||
|
||||
[RestExtension("Blah")]
|
||||
public class MyRestExtension
|
||||
[umbraco.presentation.umbracobase.RestExtension("Blah")]
|
||||
public class MyLegacyRestExtension
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
[Umbraco.Web.BaseRest.RestExtension("Blah")]
|
||||
public class MyRestExtesion
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public interface IFindMe
|
||||
{
|
||||
|
||||
|
||||
@@ -33,12 +33,12 @@
|
||||
<FileSystemProviders configSource="config\FileSystemProviders.config" />
|
||||
|
||||
<appSettings>
|
||||
<add key="umbracoDbDSN" value="server=.\sqlexpress;database=v4;user id=sa;password=test;Application Name=Umbraco41"/>
|
||||
<add key="umbracoConfigurationStatus" value="4.9.0"/>
|
||||
<add key="umbracoDbDSN" value="datalayer=MySql;server=localhost;database=umbraco;user id=root;password=root"/>
|
||||
<add key="umbracoConfigurationStatus" value="4.10.0"/>
|
||||
<add key="umbracoReservedUrls" value="~/config/splashes/booting.aspx,~/install/default.aspx,~/config/splashes/noNodes.aspx,~/VSEnterpriseHelper.axd" />
|
||||
<add key="umbracoReservedPaths" value="~/umbraco,~/install/" />
|
||||
<add key="umbracoContentXML" value="~/App_Data/umbraco.config"/>
|
||||
<add key="umbracoStorageDirectory" value="~/App_Data"/>
|
||||
<add key="umbracoContentXML" value="~/App_Data/umbraco.config" />
|
||||
<add key="umbracoStorageDirectory" value="~/App_Data" />
|
||||
<add key="umbracoPath" value="~/umbraco" />
|
||||
<add key="umbracoEnableStat" value="false" />
|
||||
<add key="umbracoHideTopLevelNodeFromPath" value="true" />
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
<add xdt:Transform="Replace" xdt:Locator="Match(key)" key="umbracoDbDSN"
|
||||
value="datalayer=MySql;server=localhost;database=umbraco;user id=root;password=root"/>
|
||||
<add xdt:Transform="Replace" xdt:Locator="Match(key)" key="umbracoConfigurationStatus"
|
||||
value="4.9.0"/>
|
||||
value="4.10.0"/>
|
||||
</appSettings>
|
||||
|
||||
<system.web>
|
||||
|
||||
122
src/Umbraco.Web/BaseRest/BaseRestHandler.cs
Normal file
122
src/Umbraco.Web/BaseRest/BaseRestHandler.cs
Normal file
@@ -0,0 +1,122 @@
|
||||
using System;
|
||||
using System.Web;
|
||||
using System.Web.SessionState;
|
||||
using System.Reflection;
|
||||
using System.Xml;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
namespace Umbraco.Web.BaseRest
|
||||
{
|
||||
internal class BaseRestHandler : IHttpHandler, IRequiresSessionState
|
||||
{
|
||||
static string _baseUrl;
|
||||
|
||||
static BaseRestHandler()
|
||||
{
|
||||
_baseUrl = UriUtility.ToAbsolute(Umbraco.Core.IO.SystemDirectories.Base).ToLower();
|
||||
if (!_baseUrl.EndsWith("/"))
|
||||
_baseUrl += "/";
|
||||
}
|
||||
|
||||
public bool IsReusable
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a value indicating whether a specified Uri should be routed to the BaseRestHandler.
|
||||
/// </summary>
|
||||
/// <param name="uri">The specified Uri.</param>
|
||||
/// <returns>A value indicating whether the specified Uri should be routed to the BaseRestHandler.</returns>
|
||||
public static bool IsBaseRestRequest(Uri uri)
|
||||
{
|
||||
return Umbraco.Core.Configuration.UmbracoSettings.EnableBaseRestHandler
|
||||
&& uri.AbsolutePath.ToLowerInvariant().StartsWith(_baseUrl);
|
||||
}
|
||||
|
||||
public void ProcessRequest(HttpContext context)
|
||||
{
|
||||
string url = context.Request.RawUrl;
|
||||
|
||||
// sanitize and split the url
|
||||
url = url.Substring(_baseUrl.Length);
|
||||
if (url.ToLower().Contains(".aspx"))
|
||||
url = url.Substring(0, url.IndexOf(".aspx"));
|
||||
if (url.ToLower().Contains("?"))
|
||||
url = url.Substring(0, url.IndexOf("?"));
|
||||
var urlParts = url.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
// by default, return xml content
|
||||
context.Response.ContentType = "text/xml";
|
||||
|
||||
// ensure that we have a valid request ie /base/library/method/[parameter].aspx
|
||||
if (urlParts.Length < 2)
|
||||
{
|
||||
context.Response.Write("<error>Invalid request, missing parts.</error>");
|
||||
context.Response.StatusCode = 400;
|
||||
context.Response.StatusDescription = "Bad Request";
|
||||
context.Response.End();
|
||||
return;
|
||||
}
|
||||
|
||||
string extensionAlias = urlParts[0];
|
||||
string methodName = urlParts[1];
|
||||
|
||||
var method = RestExtensionMethodInfo.GetMethod(extensionAlias, methodName);
|
||||
|
||||
if (!method.Exists)
|
||||
{
|
||||
context.Response.StatusCode = 500;
|
||||
context.Response.StatusDescription = "Internal Server Error";
|
||||
context.Response.Output.Write("<error>Extension or method not found.</error>");
|
||||
}
|
||||
else if (!method.CanBeInvokedByCurrentMember)
|
||||
{
|
||||
context.Response.StatusCode = 500;
|
||||
context.Response.StatusDescription = "Internal Server Error";
|
||||
context.Response.Output.Write("<error>Permission denied.</error>");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!method.ReturnXml)
|
||||
context.Response.ContentType = "text/html";
|
||||
|
||||
TrySetCulture();
|
||||
|
||||
string result = method.Invoke(urlParts.Skip(2).ToArray());
|
||||
if (result.Length >= 7 && result.Substring(0, 7) == "<error>")
|
||||
{
|
||||
context.Response.StatusCode = 500;
|
||||
context.Response.StatusDescription = "Internal Server Error";
|
||||
}
|
||||
context.Response.Output.Write(result);
|
||||
}
|
||||
|
||||
context.Response.End();
|
||||
}
|
||||
|
||||
#region from baseHttpModule.cs
|
||||
|
||||
// fixme - is this ok?
|
||||
|
||||
private static void TrySetCulture()
|
||||
{
|
||||
string domain = HttpContext.Current.Request.Url.Host; // host only
|
||||
if (TrySetCulture(domain)) return;
|
||||
|
||||
domain = HttpContext.Current.Request.Url.Authority; // host with port
|
||||
if (TrySetCulture(domain)) return;
|
||||
}
|
||||
|
||||
private static bool TrySetCulture(string domain)
|
||||
{
|
||||
var uDomain = global::umbraco.cms.businesslogic.web.Domain.GetDomain(domain);
|
||||
if (uDomain == null) return false;
|
||||
System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo(uDomain.Language.CultureAlias);
|
||||
return true;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
160
src/Umbraco.Web/BaseRest/MemberRest.cs
Normal file
160
src/Umbraco.Web/BaseRest/MemberRest.cs
Normal file
@@ -0,0 +1,160 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Xml;
|
||||
using System.Xml.XPath;
|
||||
|
||||
using umbraco.cms.businesslogic;
|
||||
using umbraco.cms.businesslogic.member;
|
||||
using umbraco.cms.businesslogic.property;
|
||||
|
||||
namespace Umbraco.Web.BaseRest
|
||||
{
|
||||
public class MemberRest
|
||||
{
|
||||
public static int GetCurrentMemberId()
|
||||
{
|
||||
return Member.CurrentMemberId();
|
||||
}
|
||||
|
||||
public static Member GetCurrentMember()
|
||||
{
|
||||
return Member.GetCurrentMember();
|
||||
}
|
||||
|
||||
public static int Login(string login, string password)
|
||||
{
|
||||
Member m = Member.GetMemberFromLoginNameAndPassword(login, password);
|
||||
var id = GetCurrentMemberId();
|
||||
if (id == 0)
|
||||
{
|
||||
if (m == null)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
Member.AddMemberToCache(m);
|
||||
return m.Id;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return id;
|
||||
}
|
||||
}
|
||||
|
||||
[Obsolete("Use Login(login, password).", false)]
|
||||
public static int login(string loginname, string password)
|
||||
{
|
||||
return Login(loginname, password);
|
||||
}
|
||||
|
||||
public static int Logout()
|
||||
{
|
||||
var currentId = GetCurrentMemberId();
|
||||
if (currentId > 0)
|
||||
{
|
||||
Member.RemoveMemberFromCache(currentId);
|
||||
Member.ClearMemberFromClient(currentId);
|
||||
return currentId;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
[Obsolete("Use Logout().", false)]
|
||||
public static int logout(int NodeId)
|
||||
{
|
||||
return Logout();
|
||||
}
|
||||
|
||||
[Obsolete("Use Logout().", false)]
|
||||
public static int logout()
|
||||
{
|
||||
return Logout();
|
||||
}
|
||||
|
||||
public static XPathNodeIterator Data()
|
||||
{
|
||||
var m = GetCurrentMember();
|
||||
if (m != null)
|
||||
{
|
||||
XmlDocument doc = new XmlDocument();
|
||||
doc.LoadXml(m.ToXml(doc, false).OuterXml);
|
||||
XPathNavigator nav = doc.CreateNavigator();
|
||||
return nav.Select("/node");
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
[Obsolete("Use Data().", false)]
|
||||
public static XPathNodeIterator data()
|
||||
{
|
||||
return Data();
|
||||
}
|
||||
|
||||
[Obsolete("Use GetCurrentMemberId().", false)]
|
||||
public static int id()
|
||||
{
|
||||
return GetCurrentMemberId();
|
||||
}
|
||||
|
||||
public static string SetProperty(string alias, object value)
|
||||
{
|
||||
string ret = "False";
|
||||
|
||||
try
|
||||
{
|
||||
var m = GetCurrentMember();
|
||||
|
||||
if (m != null)
|
||||
{
|
||||
var prop = m.getProperty(alias);
|
||||
|
||||
if (m.ContentType != null && MemberType.GetByAlias(m.ContentType.Alias).MemberCanEdit(prop.PropertyType))
|
||||
{
|
||||
|
||||
if (prop.PropertyType.ValidationRegExp.Trim() != "")
|
||||
{
|
||||
Regex regex = new Regex(m.getProperty(alias).PropertyType.ValidationRegExp);
|
||||
|
||||
if (regex.IsMatch(value.ToString()))
|
||||
{
|
||||
prop.Value = value;
|
||||
ret = "True";
|
||||
m.XmlGenerate(new XmlDocument());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
prop.Value = value;
|
||||
ret = "True";
|
||||
m.XmlGenerate(new XmlDocument());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
ret = e.Message;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
[Obsolete("Use SetProperty(alias, value).", false)]
|
||||
public static string setProperty(string alias, object value)
|
||||
{
|
||||
return SetProperty(alias, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
18
src/Umbraco.Web/BaseRest/RestExtensionAttribute.cs
Normal file
18
src/Umbraco.Web/BaseRest/RestExtensionAttribute.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Umbraco.Web.BaseRest
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
|
||||
public class RestExtensionAttribute : Attribute
|
||||
{
|
||||
public string Alias { get; private set; }
|
||||
|
||||
public RestExtensionAttribute(string alias)
|
||||
{
|
||||
this.Alias = alias;
|
||||
}
|
||||
}
|
||||
}
|
||||
23
src/Umbraco.Web/BaseRest/RestExtensionMethodAttribute.cs
Normal file
23
src/Umbraco.Web/BaseRest/RestExtensionMethodAttribute.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Umbraco.Web.BaseRest
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
|
||||
public class RestExtensionMethodAttribute : Attribute
|
||||
{
|
||||
public bool AllowAll { get; set; }
|
||||
public string AllowGroup { get; set; }
|
||||
public string AllowType { get; set; }
|
||||
public string AllowMember { get; set; }
|
||||
public bool ReturnXml { get; set; }
|
||||
|
||||
public RestExtensionMethodAttribute()
|
||||
{
|
||||
this.AllowAll = true;
|
||||
this.ReturnXml = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
344
src/Umbraco.Web/BaseRest/RestExtensionMethodInfo.cs
Normal file
344
src/Umbraco.Web/BaseRest/RestExtensionMethodInfo.cs
Normal file
@@ -0,0 +1,344 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Reflection;
|
||||
using System.Xml;
|
||||
using System.IO;
|
||||
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.IO;
|
||||
using umbraco.cms.businesslogic.member;
|
||||
|
||||
namespace Umbraco.Web.BaseRest
|
||||
{
|
||||
class RestExtensionMethodInfo
|
||||
{
|
||||
#region Utilities
|
||||
|
||||
static char[] Split = new char[] { ',' };
|
||||
|
||||
static string[] SplitString(string s)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(s))
|
||||
return new string[] { };
|
||||
else
|
||||
return s.ToLower().Split(Split, StringSplitOptions.RemoveEmptyEntries);
|
||||
}
|
||||
|
||||
static string GetAttribute(XmlNode node, string name)
|
||||
{
|
||||
var attribute = node.Attributes[name];
|
||||
return attribute == null ? null : attribute.Value;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private RestExtensionMethodInfo()
|
||||
{
|
||||
this.Exists = false;
|
||||
}
|
||||
|
||||
private RestExtensionMethodInfo(bool allowAll, string allowGroup, string allowType, string allowMember, bool returnXml, MethodInfo method)
|
||||
{
|
||||
this.Exists = true;
|
||||
_allowAll = allowAll;
|
||||
_allowGroups = SplitString(allowGroup);
|
||||
_allowTypes = SplitString(allowType);
|
||||
_allowMembers = SplitString(allowMember);
|
||||
this.ReturnXml = returnXml;
|
||||
_method = method;
|
||||
}
|
||||
|
||||
static RestExtensionMethodInfo MissingMethod = new RestExtensionMethodInfo();
|
||||
static Dictionary<string, RestExtensionMethodInfo> _cache = new Dictionary<string, RestExtensionMethodInfo>();
|
||||
|
||||
bool _allowAll;
|
||||
string[] _allowGroups;
|
||||
string[] _allowTypes;
|
||||
string[] _allowMembers;
|
||||
MethodInfo _method;
|
||||
|
||||
public bool Exists { get; private set; }
|
||||
public bool ReturnXml { get; private set; }
|
||||
|
||||
#region Discovery
|
||||
|
||||
public static RestExtensionMethodInfo GetMethod(string extensionAlias, string methodName)
|
||||
{
|
||||
return GetFromConfiguration(extensionAlias, methodName)
|
||||
?? GetFromAttribute(extensionAlias, methodName)
|
||||
?? GetFromLegacyAttribute(extensionAlias, methodName)
|
||||
?? MissingMethod;
|
||||
}
|
||||
|
||||
static RestExtensionMethodInfo GetFromConfiguration(string extensionAlias, string methodName)
|
||||
{
|
||||
const string ExtensionXPath = "/RestExtensions/ext [@alias='{0}']";
|
||||
const string MethodXPath = "./permission [@method='{0}']";
|
||||
|
||||
// fixme
|
||||
// because we reload the config file each time we can't really have a cache here
|
||||
// or we'd need to set a watcher on the config file?
|
||||
|
||||
var doc = new XmlDocument();
|
||||
doc.Load(IOHelper.MapPath(SystemFiles.RestextensionsConfig));
|
||||
|
||||
var eNode = doc.SelectSingleNode(string.Format(ExtensionXPath, extensionAlias));
|
||||
|
||||
if (eNode == null)
|
||||
return null; // does not exist
|
||||
|
||||
var mNode = eNode.SelectSingleNode(string.Format(MethodXPath, methodName));
|
||||
|
||||
if (mNode == null)
|
||||
return null; // does not exist
|
||||
|
||||
string assemblyName = eNode.Attributes["assembly"].Value;
|
||||
string assemblyPath = IOHelper.MapPath(string.Format("{0}/{1}.dll", SystemDirectories.Bin, assemblyName.TrimStart('/')));
|
||||
Assembly assembly = Assembly.LoadFrom(assemblyPath);
|
||||
|
||||
string typeName = eNode.Attributes["type"].Value;
|
||||
Type type = assembly.GetType(typeName);
|
||||
|
||||
var method = type.GetMethod(methodName);
|
||||
|
||||
if (method == null)
|
||||
return null; // does not exist
|
||||
|
||||
var allowAll = GetAttribute(mNode, "allowAll");
|
||||
var returnXml = GetAttribute(mNode, "returnXml");
|
||||
|
||||
var info = new RestExtensionMethodInfo(allowAll != null && allowAll.ToLower() == "true",
|
||||
GetAttribute(mNode, "allowGroup"), GetAttribute(mNode, "allowType"), GetAttribute(mNode, "allowMember"),
|
||||
returnXml == null || returnXml.ToLower() != "false",
|
||||
method);
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
static RestExtensionMethodInfo GetFromLegacyAttribute(string extensionAlias, string methodName)
|
||||
{
|
||||
// here we can cache because any change would trigger an app restart
|
||||
|
||||
string cacheKey = extensionAlias + "." + methodName;
|
||||
lock (_cache)
|
||||
{
|
||||
if (_cache.ContainsKey(cacheKey))
|
||||
return _cache[cacheKey];
|
||||
}
|
||||
|
||||
var extensions = PluginManager.Current.ResolveLegacyRestExtensions();
|
||||
var extension = extensions
|
||||
.SingleOrDefault(type => type.GetCustomAttribute<global::umbraco.presentation.umbracobase.RestExtension>(false).GetAlias() == extensionAlias);
|
||||
|
||||
RestExtensionMethodInfo info = null;
|
||||
|
||||
if (extension != null)
|
||||
{
|
||||
var method = extension.GetMethod(methodName);
|
||||
if (method != null)
|
||||
{
|
||||
var attribute = method.GetCustomAttributes(typeof(global::umbraco.presentation.umbracobase.RestExtensionMethod), false).Cast<global::umbraco.presentation.umbracobase.RestExtensionMethod>().SingleOrDefault();
|
||||
if (attribute != null)
|
||||
{
|
||||
info = new RestExtensionMethodInfo(attribute.GetAllowAll(),
|
||||
attribute.GetAllowGroup(), attribute.GetAllowType(), attribute.GetAllowMember(),
|
||||
attribute.returnXml,
|
||||
method);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lock (_cache)
|
||||
{
|
||||
_cache[cacheKey] = info;
|
||||
}
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
static RestExtensionMethodInfo GetFromAttribute(string extensionAlias, string methodName)
|
||||
{
|
||||
// here we can cache because any change would trigger an app restart
|
||||
|
||||
string cacheKey = extensionAlias + "." + methodName;
|
||||
lock (_cache)
|
||||
{
|
||||
if (_cache.ContainsKey(cacheKey))
|
||||
return _cache[cacheKey];
|
||||
}
|
||||
|
||||
var extensions = PluginManager.Current.ResolveRestExtensions();
|
||||
var extension = extensions
|
||||
.SingleOrDefault(type => type.GetCustomAttribute<RestExtensionAttribute>(false).Alias == extensionAlias);
|
||||
|
||||
RestExtensionMethodInfo info = null;
|
||||
|
||||
if (extension != null)
|
||||
{
|
||||
var method = extension.GetMethod(methodName);
|
||||
if (method != null)
|
||||
{
|
||||
var attribute = method.GetCustomAttributes(typeof(RestExtensionMethodAttribute), false).Cast<RestExtensionMethodAttribute>().SingleOrDefault();
|
||||
if (attribute != null)
|
||||
{
|
||||
info = new RestExtensionMethodInfo(attribute.AllowAll,
|
||||
attribute.AllowGroup, attribute.AllowType, attribute.AllowMember,
|
||||
attribute.ReturnXml,
|
||||
method);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lock (_cache)
|
||||
{
|
||||
_cache[cacheKey] = info;
|
||||
}
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Invoke
|
||||
|
||||
public bool CanBeInvokedByCurrentMember
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_allowAll)
|
||||
return true;
|
||||
|
||||
var member = Member.GetCurrentMember();
|
||||
|
||||
if (member == null)
|
||||
return false;
|
||||
|
||||
bool allowed = false;
|
||||
|
||||
if (_allowGroups.Length > 0)
|
||||
{
|
||||
// fixme - are these equivalent?
|
||||
//var groups = member.Groups.Values.Cast<MemberGroup>().Select(group => group.Text);
|
||||
var groups = System.Web.Security.Roles.GetRolesForUser(member.LoginName);
|
||||
allowed = groups.Select(s => s.ToLower()).Intersect(_allowGroups).Any();
|
||||
}
|
||||
|
||||
if (!allowed && _allowTypes.Length > 0)
|
||||
{
|
||||
allowed = _allowTypes.Contains(member.ContentType.Alias);
|
||||
}
|
||||
|
||||
if (!allowed && _allowMembers.Length > 0)
|
||||
{
|
||||
allowed = _allowMembers.Contains(member.Id.ToString());
|
||||
}
|
||||
|
||||
return allowed;
|
||||
}
|
||||
}
|
||||
|
||||
public string Invoke(string[] parameters)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!_method.IsPublic || !_method.IsStatic)
|
||||
{
|
||||
// ensure that method is static public
|
||||
return "<error>Method has to be public and static</error>";
|
||||
}
|
||||
else
|
||||
{
|
||||
// ensure we have the right number of parameters
|
||||
if (_method.GetParameters().Length != parameters.Length)
|
||||
{
|
||||
return "<error>Not Enough parameters in url</error>";
|
||||
}
|
||||
else
|
||||
{
|
||||
// invoke
|
||||
|
||||
// fixme - what is the point?
|
||||
//Create an instance of the type we need to invoke the method from.
|
||||
//**Object obj = Activator.CreateInstance(myExtension.type);
|
||||
|
||||
object response;
|
||||
|
||||
if (_method.GetParameters().Length == 0)
|
||||
{
|
||||
//response = myMethod.method.Invoke(obj, BindingFlags.Public | BindingFlags.Instance, bBinder, null, System.Globalization.CultureInfo.CurrentCulture);
|
||||
response = _method.Invoke(null /*obj*/, null); // invoke with null as parameters as there are none
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
object[] methodParams = new object[parameters.Length];
|
||||
|
||||
int i = 0;
|
||||
|
||||
foreach (ParameterInfo pInfo in _method.GetParameters())
|
||||
{
|
||||
Type myType = Type.GetType(pInfo.ParameterType.ToString());
|
||||
methodParams[(i)] = Convert.ChangeType(parameters[i], myType);
|
||||
i++;
|
||||
}
|
||||
|
||||
//Invoke with methodParams
|
||||
//response = myMethod.method.Invoke(obj, BindingFlags.Public | BindingFlags.Instance, bBinder, methodParams, System.Globalization.CultureInfo.CurrentCulture);
|
||||
response = _method.Invoke(/*obj*/null, methodParams);
|
||||
}
|
||||
|
||||
/*TODO - SOMETHING ALITTLE BETTER THEN ONLY CHECK FOR XPATHNODEITERATOR OR ELSE do ToString() */
|
||||
if (response != null)
|
||||
{
|
||||
switch (_method.ReturnType.ToString())
|
||||
{
|
||||
case "System.Xml.XPath.XPathNodeIterator":
|
||||
return ((System.Xml.XPath.XPathNodeIterator)response).Current.OuterXml;
|
||||
case "System.Xml.Linq.XDocument":
|
||||
return response.ToString();
|
||||
case "System.Xml.XmlDocument":
|
||||
XmlDocument xmlDoc = (XmlDocument)response;
|
||||
StringWriter sw = new StringWriter();
|
||||
XmlTextWriter xw = new XmlTextWriter(sw);
|
||||
xmlDoc.WriteTo(xw);
|
||||
return sw.ToString();
|
||||
default:
|
||||
string strResponse = ((string)response.ToString());
|
||||
|
||||
if (this.ReturnXml)
|
||||
{
|
||||
// do a quick "is this html?" check... if it is add CDATA...
|
||||
if (strResponse.Contains("<") || strResponse.Contains(">"))
|
||||
strResponse = "<![CDATA[" + strResponse + "]]>";
|
||||
return "<value>" + strResponse + "</value>";
|
||||
}
|
||||
else
|
||||
{
|
||||
//HttpContext.Current.Response.ContentType = "text/html";
|
||||
return strResponse;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (this.ReturnXml)
|
||||
return "<error>Null value returned</error>";
|
||||
else
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
catch (Exception ex)
|
||||
{
|
||||
//Overall exception handling...
|
||||
return "<error><![CDATA[MESSAGE:\n" + ex.Message + "\n\nSTACKTRACE:\n" + ex.StackTrace + "\n\nINNEREXCEPTION:\n" + ex.InnerException + "]]></error>";
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,218 +0,0 @@
|
||||
using System;
|
||||
using System.Web;
|
||||
using System.Web.SessionState;
|
||||
using System.Reflection;
|
||||
using System.Xml;
|
||||
using System.IO;
|
||||
|
||||
namespace Umbraco.Web
|
||||
{
|
||||
internal class BaseRestHandler : IHttpHandler, IRequiresSessionState
|
||||
{
|
||||
const int ParametersOffset = 2;
|
||||
static string _baseUrl;
|
||||
|
||||
static BaseRestHandler()
|
||||
{
|
||||
_baseUrl = UriUtility.ToAbsolute(Umbraco.Core.IO.SystemDirectories.Base).ToLower();
|
||||
if (!_baseUrl.EndsWith("/"))
|
||||
_baseUrl += "/";
|
||||
}
|
||||
|
||||
public bool IsReusable
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a value indicating whether a specified Uri should be routed to the BaseRestHandler.
|
||||
/// </summary>
|
||||
/// <param name="uri">The specified Uri.</param>
|
||||
/// <returns>A value indicating whether the specified Uri should be routed to the BaseRestHandler.</returns>
|
||||
public static bool IsBaseRestRequest(Uri uri)
|
||||
{
|
||||
return Umbraco.Core.Configuration.UmbracoSettings.EnableBaseRestHandler
|
||||
&& uri.AbsolutePath.ToLowerInvariant().StartsWith(_baseUrl);
|
||||
}
|
||||
|
||||
public void ProcessRequest(HttpContext context)
|
||||
{
|
||||
string url = context.Request.RawUrl;
|
||||
|
||||
// sanitize and split the url
|
||||
url = url.Substring(_baseUrl.Length);
|
||||
if (url.ToLower().Contains(".aspx"))
|
||||
url = url.Substring(0, url.IndexOf(".aspx"));
|
||||
if (url.ToLower().Contains("?"))
|
||||
url = url.Substring(0, url.IndexOf("?"));
|
||||
var urlParts = url.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
// always return xml content
|
||||
context.Response.ContentType = "text/xml";
|
||||
|
||||
// ensure that we have a valid request ie /base/library/method/[parameter].aspx
|
||||
if (urlParts.Length < ParametersOffset)
|
||||
{
|
||||
context.Response.Write("<error>Invalid request, missing parts.</error>");
|
||||
context.Response.StatusCode = 400;
|
||||
context.Response.StatusDescription = "Bad Request";
|
||||
context.Response.End();
|
||||
return;
|
||||
}
|
||||
|
||||
// fixme - what follows comes straight from baseHttpModule.cs
|
||||
|
||||
string extensionAlias = urlParts[0];
|
||||
string methodName = urlParts[1];
|
||||
|
||||
var myExtension = new global::umbraco.presentation.umbracobase.restExtension(extensionAlias, methodName);
|
||||
|
||||
if (myExtension.isAllowed)
|
||||
{
|
||||
TrySetCulture();
|
||||
|
||||
string response = invokeMethod(myExtension, urlParts);
|
||||
if (response.Length >= 7 && response.Substring(0, 7) == "<error>")
|
||||
{
|
||||
context.Response.StatusCode = 500;
|
||||
context.Response.StatusDescription = "Internal Server Error";
|
||||
}
|
||||
context.Response.Output.Write(response);
|
||||
}
|
||||
else
|
||||
{
|
||||
context.Response.StatusCode = 500;
|
||||
context.Response.StatusDescription = "Internal Server Error";
|
||||
context.Response.Output.Write("<error>Extension not found or permission denied.</error>");
|
||||
}
|
||||
|
||||
context.Response.End();
|
||||
}
|
||||
|
||||
#region from baseHttpModule.cs
|
||||
|
||||
// fixme - these methods have *not* been cleaned up, just partially fixed...
|
||||
|
||||
string invokeMethod(global::umbraco.presentation.umbracobase.restExtension myExtension, string[] urlParts)
|
||||
{
|
||||
try
|
||||
{
|
||||
//So method is either not found or not valid... this should probably be moved...
|
||||
if (!myExtension.method.IsPublic || !myExtension.method.IsStatic)
|
||||
return "<error>Method has to be public and static</error>";
|
||||
else //And if it is lets continue trying to invoke it...
|
||||
{
|
||||
//lets check if we have parameters enough in the url..
|
||||
if (myExtension.method.GetParameters().Length > (urlParts.Length - ParametersOffset)) //Too few
|
||||
return "<error>Not Enough parameters in url</error>";
|
||||
else
|
||||
{
|
||||
|
||||
//We have enough parameters... lets invoke..
|
||||
//Create an instance of the type we need to invoke the method from.
|
||||
//**Object obj = Activator.CreateInstance(myExtension.type);
|
||||
Object response;
|
||||
|
||||
//umbracoBase.baseBinder bBinder = new baseBinder();
|
||||
|
||||
if (myExtension.method.GetParameters().Length == 0)
|
||||
{
|
||||
//response = myMethod.method.Invoke(obj, BindingFlags.Public | BindingFlags.Instance, bBinder, null, System.Globalization.CultureInfo.CurrentCulture);
|
||||
response = myExtension.method.Invoke(null /*obj*/, null); //Invoke with null as parameters as there are none
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
//We only need the parts of the url above the number 4 so we'll
|
||||
//recast those to objects and add them to the object[]
|
||||
|
||||
//Getting the right lenght.. 4 is the magic number dum di dum..
|
||||
object[] methodParams = new object[urlParts.Length - ParametersOffset];
|
||||
|
||||
int i = 0;
|
||||
|
||||
foreach (ParameterInfo pInfo in myExtension.method.GetParameters())
|
||||
{
|
||||
Type myType = Type.GetType(pInfo.ParameterType.ToString());
|
||||
methodParams[(i)] = Convert.ChangeType(urlParts[i + ParametersOffset], myType);
|
||||
i++;
|
||||
}
|
||||
|
||||
//Invoke with methodParams
|
||||
//response = myMethod.method.Invoke(obj, BindingFlags.Public | BindingFlags.Instance, bBinder, methodParams, System.Globalization.CultureInfo.CurrentCulture);
|
||||
response = myExtension.method.Invoke(/*obj*/null, methodParams);
|
||||
}
|
||||
|
||||
/*TODO - SOMETHING ALITTLE BETTER THEN ONLY CHECK FOR XPATHNODEITERATOR OR ELSE do ToString() */
|
||||
if (response != null)
|
||||
{
|
||||
switch (myExtension.method.ReturnType.ToString())
|
||||
{
|
||||
case "System.Xml.XPath.XPathNodeIterator":
|
||||
return ((System.Xml.XPath.XPathNodeIterator)response).Current.OuterXml;
|
||||
case "System.Xml.Linq.XDocument":
|
||||
return response.ToString();
|
||||
case "System.Xml.XmlDocument":
|
||||
XmlDocument xmlDoc = (XmlDocument)response;
|
||||
StringWriter sw = new StringWriter();
|
||||
XmlTextWriter xw = new XmlTextWriter(sw);
|
||||
xmlDoc.WriteTo(xw);
|
||||
return sw.ToString();
|
||||
default:
|
||||
string strResponse = ((string)response.ToString());
|
||||
|
||||
if (myExtension.returnXML)
|
||||
{
|
||||
//do a quick "is this html?" check... if it is add CDATA...
|
||||
if (strResponse.Contains("<") || strResponse.Contains(">"))
|
||||
strResponse = "<![CDATA[" + strResponse + "]]>";
|
||||
return "<value>" + strResponse + "</value>";
|
||||
}
|
||||
else
|
||||
{
|
||||
HttpContext.Current.Response.ContentType = "text/html";
|
||||
return strResponse;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (myExtension.returnXML)
|
||||
return "<error>Null value returned</error>";
|
||||
else
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
catch (Exception ex)
|
||||
{
|
||||
//Overall exception handling...
|
||||
return "<error><![CDATA[MESSAGE:\n" + ex.Message + "\n\nSTACKTRACE:\n" + ex.StackTrace + "\n\nINNEREXCEPTION:\n" + ex.InnerException + "]]></error>";
|
||||
}
|
||||
}
|
||||
|
||||
private static void TrySetCulture()
|
||||
{
|
||||
string domain = HttpContext.Current.Request.Url.Host; //Host only
|
||||
if (TrySetCulture(domain)) return;
|
||||
|
||||
domain = HttpContext.Current.Request.Url.Authority; //Host with port
|
||||
if (TrySetCulture(domain)) return;
|
||||
}
|
||||
|
||||
private static bool TrySetCulture(string domain)
|
||||
{
|
||||
var uDomain = global::umbraco.cms.businesslogic.web.Domain.GetDomain(domain);
|
||||
if (uDomain == null) return false;
|
||||
System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo(uDomain.Language.CultureAlias);
|
||||
return true;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -6,8 +6,6 @@ using Umbraco.Core;
|
||||
using Umbraco.Web.Routing;
|
||||
using umbraco;
|
||||
using umbraco.interfaces;
|
||||
using umbraco.presentation.umbracobase;
|
||||
|
||||
|
||||
namespace Umbraco.Web
|
||||
{
|
||||
@@ -27,13 +25,23 @@ namespace Umbraco.Web
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns all classes attributed with RestExtension attribute
|
||||
/// Returns all classes attributed with legacy RestExtension attribute
|
||||
/// </summary>
|
||||
/// <param name="resolver"></param>
|
||||
/// <returns></returns>
|
||||
internal static IEnumerable<Type> ResolveLegacyRestExtensions(this PluginManager resolver)
|
||||
{
|
||||
return resolver.ResolveAttributedTypes<global::umbraco.presentation.umbracobase.RestExtension>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns all classes attributed with RestExtensionAttribute attribute
|
||||
/// </summary>
|
||||
/// <param name="resolver"></param>
|
||||
/// <returns></returns>
|
||||
internal static IEnumerable<Type> ResolveRestExtensions(this PluginManager resolver)
|
||||
{
|
||||
return resolver.ResolveAttributedTypes<RestExtension>();
|
||||
return resolver.ResolveAttributedTypes<Umbraco.Web.BaseRest.RestExtensionAttribute>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -240,7 +240,11 @@
|
||||
<Link>Properties\SolutionInfo.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="ApplicationEventsResolver.cs" />
|
||||
<Compile Include="BaseRestHandler.cs" />
|
||||
<Compile Include="BaseRest\BaseRestHandler.cs" />
|
||||
<Compile Include="BaseRest\MemberRest.cs" />
|
||||
<Compile Include="BaseRest\RestExtensionAttribute.cs" />
|
||||
<Compile Include="BaseRest\RestExtensionMethodAttribute.cs" />
|
||||
<Compile Include="BaseRest\RestExtensionMethodInfo.cs" />
|
||||
<Compile Include="DefaultDynamicDocumentDataSource.cs" />
|
||||
<Compile Include="DefaultPublishedMediaStore.cs" />
|
||||
<Compile Include="Dictionary\UmbracoCultureDictionary.cs" />
|
||||
|
||||
@@ -67,9 +67,9 @@ namespace Umbraco.Web
|
||||
umbracoContext.RoutingContext = routingContext;
|
||||
|
||||
// remap to handler if it is a base rest request
|
||||
if (BaseRestHandler.IsBaseRestRequest(umbracoContext.RequestUrl))
|
||||
if (BaseRest.BaseRestHandler.IsBaseRestRequest(umbracoContext.RequestUrl))
|
||||
{
|
||||
httpContext.RemapHandler(new BaseRestHandler());
|
||||
httpContext.RemapHandler(new BaseRest.BaseRestHandler());
|
||||
}
|
||||
else
|
||||
|
||||
|
||||
@@ -11,14 +11,14 @@ using umbraco.BusinessLogic;
|
||||
using umbraco.IO;
|
||||
using umbraco.cms.businesslogic.Tags;
|
||||
using umbraco.cms.businesslogic.media;
|
||||
using umbraco.presentation.umbracobase;
|
||||
using Umbraco.Web.BaseRest;
|
||||
|
||||
namespace Umbraco.Web.WebServices
|
||||
{
|
||||
[RestExtension("FolderBrowserService")]
|
||||
public class FolderBrowserService
|
||||
{
|
||||
[RestExtensionMethod(returnXml = false)]
|
||||
[RestExtensionMethod(ReturnXml = false)]
|
||||
public static string GetChildren(int parentId)
|
||||
{
|
||||
var parentMedia = new global::umbraco.cms.businesslogic.media.Media(parentId);
|
||||
@@ -64,7 +64,7 @@ namespace Umbraco.Web.WebServices
|
||||
return new JavaScriptSerializer().Serialize(data);
|
||||
}
|
||||
|
||||
[RestExtensionMethod(returnXml = false)]
|
||||
[RestExtensionMethod(ReturnXml = false)]
|
||||
public static string Delete(string nodeIds)
|
||||
{
|
||||
var nodeIdParts = nodeIds.Split(',');
|
||||
|
||||
@@ -5,6 +5,7 @@ using System.Web;
|
||||
|
||||
namespace umbraco.presentation.umbracobase
|
||||
{
|
||||
[Obsolete("Use Umbraco.Web.BaseRest.RestExtensionAttribute")]
|
||||
[System.AttributeUsage(System.AttributeTargets.Class, AllowMultiple = false)]
|
||||
public class RestExtension : System.Attribute
|
||||
{
|
||||
|
||||
@@ -5,6 +5,7 @@ using System.Web;
|
||||
|
||||
namespace umbraco.presentation.umbracobase
|
||||
{
|
||||
[Obsolete("Use Umbraco.Web.BaseRest.RestExtensionMethodAttribute")]
|
||||
[System.AttributeUsage(System.AttributeTargets.Method, AllowMultiple = false)]
|
||||
public class RestExtensionMethod : System.Attribute
|
||||
{
|
||||
|
||||
@@ -10,6 +10,7 @@ using umbraco.IO;
|
||||
|
||||
namespace umbraco.presentation.umbracobase
|
||||
{
|
||||
[Obsolete]
|
||||
public class restExtension
|
||||
{
|
||||
private Type _type;
|
||||
|
||||
Reference in New Issue
Block a user