diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj
index c6c7b482b2..c39de1963a 100644
--- a/src/Umbraco.Web/Umbraco.Web.csproj
+++ b/src/Umbraco.Web/Umbraco.Web.csproj
@@ -1816,9 +1816,11 @@
Reference.map
+
Component
+
Component
diff --git a/src/Umbraco.Web/WebServices/UmbracoAuthorizedHttpHandler.cs b/src/Umbraco.Web/WebServices/UmbracoAuthorizedHttpHandler.cs
new file mode 100644
index 0000000000..4524f1e47c
--- /dev/null
+++ b/src/Umbraco.Web/WebServices/UmbracoAuthorizedHttpHandler.cs
@@ -0,0 +1,153 @@
+using System;
+using System.Linq;
+using System.Web;
+using System.Web.Security;
+using Umbraco.Core;
+using umbraco;
+using umbraco.BasePages;
+using umbraco.BusinessLogic;
+using umbraco.businesslogic.Exceptions;
+
+namespace Umbraco.Web.WebServices
+{
+ public abstract class UmbracoAuthorizedHttpHandler : UmbracoHttpHandler
+ {
+ protected UmbracoAuthorizedHttpHandler()
+ : base()
+ {
+ }
+
+ protected UmbracoAuthorizedHttpHandler(UmbracoContext umbracoContext)
+ : base(umbracoContext)
+ {
+ }
+
+ //IMPORTANT NOTE: !! All of these security bits and pieces have been moved in to one centralized class
+ // in 6.1 called WebSecurity. All this logic is all here temporarily!
+
+ private User _user;
+ private readonly InnerPage _page = new InnerPage();
+
+ ///
+ /// Checks if the umbraco context id is valid
+ ///
+ ///
+ ///
+ protected bool ValidateUserContextId(string currentUmbracoUserContextId)
+ {
+ return BasePage.ValidateUserContextID(currentUmbracoUserContextId);
+ }
+
+ ///
+ /// Checks if the username/password credentials are valid
+ ///
+ ///
+ ///
+ ///
+ protected bool ValidateCredentials(string username, string password)
+ {
+ return Membership.Providers[UmbracoSettings.DefaultBackofficeProvider].ValidateUser(username, password);
+ }
+
+ ///
+ /// Validates the user for access to a certain application
+ ///
+ /// The application alias.
+ /// true if an exception should be thrown if authorization fails
+ ///
+ protected bool AuthorizeRequest(string app, bool throwExceptions = false)
+ {
+ //ensure we have a valid user first!
+ if (!AuthorizeRequest(throwExceptions)) return false;
+
+ //if it is empty, don't validate
+ if (app.IsNullOrWhiteSpace())
+ {
+ return true;
+ }
+ var hasAccess = UserHasAppAccess(app, UmbracoUser);
+ if (!hasAccess && throwExceptions)
+ throw new UserAuthorizationException("The user does not have access to the required application");
+ return hasAccess;
+ }
+
+ ///
+ /// Checks if the specified user as access to the app
+ ///
+ ///
+ ///
+ ///
+ protected bool UserHasAppAccess(string app, User user)
+ {
+ return user.Applications.Any(uApp => uApp.alias == app);
+ }
+
+ ///
+ /// Checks if the specified user by username as access to the app
+ ///
+ ///
+ ///
+ ///
+ protected bool UserHasAppAccess(string app, string username)
+ {
+ var uid = global::umbraco.BusinessLogic.User.getUserId(username);
+ if (uid < 0) return false;
+ var usr = global::umbraco.BusinessLogic.User.GetUser(uid);
+ if (usr == null) return false;
+ return UserHasAppAccess(app, usr);
+ }
+
+ ///
+ /// Returns true if there is a valid logged in user and that ssl is enabled if required
+ ///
+ /// true if an exception should be thrown if authorization fails
+ ///
+ protected bool AuthorizeRequest(bool throwExceptions = false)
+ {
+ // check for secure connection
+ if (GlobalSettings.UseSSL && !HttpContext.Current.Request.IsSecureConnection)
+ {
+ if (throwExceptions)
+ throw new UserAuthorizationException("This installation requires a secure connection (via SSL). Please update the URL to include https://");
+ return false;
+ }
+
+ try
+ {
+ return UmbracoUser != null;
+ }
+ catch (ArgumentException)
+ {
+ if (throwExceptions) throw;
+ //an exception will occur if the user is not valid inside of _page.getUser();
+ return false;
+ }
+ catch (InvalidOperationException)
+ {
+ if (throwExceptions) throw;
+ //an exception will occur if the user is not valid inside of _page.getUser();
+ return false;
+ }
+ }
+
+ ///
+ /// Returns the current user
+ ///
+ protected User UmbracoUser
+ {
+ get
+ {
+ return _user ?? (_user = _page.getUser());
+ }
+ }
+
+ ///
+ /// Used to validate, thie is temporary, in 6.1 we have the WebSecurity class which does all
+ /// authorization stuff for us.
+ ///
+ private class InnerPage : BasePage
+ {
+
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Web/WebServices/UmbracoAuthorizedWebService.cs b/src/Umbraco.Web/WebServices/UmbracoAuthorizedWebService.cs
index 497ad77a6e..ac55ebecbc 100644
--- a/src/Umbraco.Web/WebServices/UmbracoAuthorizedWebService.cs
+++ b/src/Umbraco.Web/WebServices/UmbracoAuthorizedWebService.cs
@@ -9,8 +9,6 @@ using umbraco.BasePages;
using umbraco.BusinessLogic;
using Umbraco.Core;
using umbraco.businesslogic.Exceptions;
-using GlobalSettings = umbraco.GlobalSettings;
-using UmbracoSettings = umbraco.UmbracoSettings;
namespace Umbraco.Web.WebServices
{
@@ -28,6 +26,9 @@ namespace Umbraco.Web.WebServices
: base(umbracoContext)
{
}
+
+ //IMPORTANT NOTE: !! All of these security bits and pieces have been moved in to one centralized class
+ // in 6.1 called WebSecurity. All this logic is all here temporarily!
private User _user;
private readonly InnerPage _page = new InnerPage();
diff --git a/src/Umbraco.Web/WebServices/UmbracoHttpHandler.cs b/src/Umbraco.Web/WebServices/UmbracoHttpHandler.cs
new file mode 100644
index 0000000000..28e7619b04
--- /dev/null
+++ b/src/Umbraco.Web/WebServices/UmbracoHttpHandler.cs
@@ -0,0 +1,74 @@
+using System;
+using System.Web;
+using System.Web.Mvc;
+using System.Web.Routing;
+using Umbraco.Core;
+
+namespace Umbraco.Web.WebServices
+{
+ public abstract class UmbracoHttpHandler : IHttpHandler
+ {
+ public abstract void ProcessRequest(HttpContext context);
+ public abstract bool IsReusable { get; }
+
+ protected UmbracoHttpHandler()
+ : this(UmbracoContext.Current)
+ {
+
+ }
+
+ protected UmbracoHttpHandler(UmbracoContext umbracoContext)
+ {
+ if (umbracoContext == null) throw new ArgumentNullException("umbracoContext");
+ UmbracoContext = umbracoContext;
+ Umbraco = new UmbracoHelper(umbracoContext);
+ }
+
+ ///
+ /// Returns the current ApplicationContext
+ ///
+ public ApplicationContext ApplicationContext
+ {
+ get { return UmbracoContext.Application; }
+ }
+
+ ///
+ /// Returns the current UmbracoContext
+ ///
+ public UmbracoContext UmbracoContext { get; private set; }
+
+ ///
+ /// Returns an UmbracoHelper object
+ ///
+ public UmbracoHelper Umbraco { get; private set; }
+
+ private UrlHelper _url;
+
+ ///
+ /// Returns a UrlHelper
+ ///
+ ///
+ /// This URL helper is created without any route data and an empty request context
+ ///
+ public UrlHelper Url
+ {
+ get { return _url ?? (_url = new UrlHelper(new RequestContext(new HttpContextWrapper(HttpContext.Current), new RouteData()))); }
+ }
+
+ /////
+ ///// Returns a ServiceContext
+ /////
+ //public ServiceContext Services
+ //{
+ // get { return ApplicationContext.Services; }
+ //}
+
+ /////
+ ///// Returns a DatabaseContext
+ /////
+ //public DatabaseContext DatabaseContext
+ //{
+ // get { return ApplicationContext.DatabaseContext; }
+ //}
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/webservices/TreeDataService.ashx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/webservices/TreeDataService.ashx.cs
index 89609703aa..ebd49d7af4 100644
--- a/src/Umbraco.Web/umbraco.presentation/umbraco/webservices/TreeDataService.ashx.cs
+++ b/src/Umbraco.Web/umbraco.presentation/umbraco/webservices/TreeDataService.ashx.cs
@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Web;
using System.Web.Services;
+using Umbraco.Web.WebServices;
using umbraco.cms.presentation.Trees;
using System.Threading;
@@ -13,19 +14,18 @@ namespace umbraco.presentation.webservices
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
- public class TreeDataService : IHttpHandler
+ public class TreeDataService : UmbracoAuthorizedHttpHandler
{
- public void ProcessRequest(HttpContext context)
+ public override void ProcessRequest(HttpContext context)
{
- Authorize();
- //Thread.Sleep(100000);
+ AuthorizeRequest(true);
context.Response.ContentType = "application/json";
context.Response.Write(GetXmlTree().ToString());
}
- public bool IsReusable
+ public override bool IsReusable
{
get
{
@@ -33,6 +33,7 @@ namespace umbraco.presentation.webservices
}
}
+ [Obsolete("Use the base class AuthorizeRequest methods in UmbracoAuthorizedHttpHandler")]
public static void Authorize()
{
if (!BasePages.BasePage.ValidateUserContextID(BasePages.BasePage.umbracoUserContextID))
@@ -46,7 +47,10 @@ namespace umbraco.presentation.webservices
///
public XmlTree GetXmlTree()
{
- TreeRequestParams treeParams = TreeRequestParams.FromQueryStrings();
+ var treeParams = TreeRequestParams.FromQueryStrings();
+
+ //validate the current user for the request app!
+ AuthorizeRequest(treeParams.Application, true);
if (string.IsNullOrEmpty(treeParams.TreeType))
if (!string.IsNullOrEmpty(treeParams.Application))
@@ -56,10 +60,10 @@ namespace umbraco.presentation.webservices
else
LoadTree(treeParams);
- return xTree;
+ return _xTree;
}
- private XmlTree xTree = new XmlTree();
+ private XmlTree _xTree = new XmlTree();
///
/// If the application supports multiple trees, then this function iterates over all of the trees assigned to it
@@ -75,7 +79,7 @@ namespace umbraco.presentation.webservices
{
BaseTree bTree = treeDef.CreateInstance();
bTree.SetTreeParameters(treeParams);
- xTree.Add(bTree.RootNode);
+ _xTree.Add(bTree.RootNode);
}
}
@@ -92,7 +96,7 @@ namespace umbraco.presentation.webservices
{
BaseTree bTree = treeDef.CreateInstance();
bTree.SetTreeParameters(treeParams);
- bTree.Render(ref xTree);
+ bTree.Render(ref _xTree);
}
else
LoadNullTree(treeParams);
@@ -105,7 +109,7 @@ namespace umbraco.presentation.webservices
{
BaseTree nullTree = new NullTree(treeParams.Application);
nullTree.SetTreeParameters(treeParams);
- nullTree.Render(ref xTree);
+ nullTree.Render(ref _xTree);
}
}
}
diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/webservices/UltimatePickerAutoCompleteHandler.ashx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/webservices/UltimatePickerAutoCompleteHandler.ashx.cs
index 97bd1934b5..8fa77e7a8b 100644
--- a/src/Umbraco.Web/umbraco.presentation/umbraco/webservices/UltimatePickerAutoCompleteHandler.ashx.cs
+++ b/src/Umbraco.Web/umbraco.presentation/umbraco/webservices/UltimatePickerAutoCompleteHandler.ashx.cs
@@ -3,6 +3,8 @@ using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;
+using Umbraco.Web.WebServices;
+using umbraco.BusinessLogic;
using umbraco.cms.businesslogic.web;
using umbraco.cms.businesslogic;
@@ -13,19 +15,24 @@ namespace umbraco.presentation.umbraco.webservices
///
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
- public class UltimatePickerAutoCompleteHandler : IHttpHandler
+ public class UltimatePickerAutoCompleteHandler : UmbracoAuthorizedHttpHandler
{
- private int nodeCount;
- private int Counter;
- private string[] output;
- private string prefix;
+ private int _nodeCount;
+ private int _counter;
+ private string[] _output;
+ private string _prefix;
- public void ProcessRequest(HttpContext context)
+ public override void ProcessRequest(HttpContext context)
{
+ //user must be allowed to see content or media
+ if (!AuthorizeRequest(DefaultApps.content.ToString()) && !AuthorizeRequest(DefaultApps.media.ToString()))
+ return;
+
+
context.Response.ContentType = "text/plain";
- prefix = context.Request.QueryString["q"];
+ _prefix = context.Request.QueryString["q"];
int parentNodeId = Convert.ToInt32(context.Request.QueryString["id"]);
bool showGrandChildren = Convert.ToBoolean(context.Request.QueryString["showchildren"]);
@@ -37,7 +44,7 @@ namespace umbraco.presentation.umbraco.webservices
CMSNode parent = new CMSNode(parentNodeId);
if (!showGrandChildren)
{
- nodeCount = 0;
+ _nodeCount = 0;
//store children array here because iterating over an Array property object is very inneficient.
var children = parent.Children;
@@ -45,42 +52,42 @@ namespace umbraco.presentation.umbraco.webservices
{
- nodeChildrenCount(child, false, documentAliasFilters);
+ NodeChildrenCount(child, false, documentAliasFilters);
}
- output = new string[nodeCount];
+ _output = new string[_nodeCount];
- Counter = 0;
+ _counter = 0;
int level = 1;
//why is there a 2nd iteration of the same thing here?
foreach (CMSNode child in children)
{
- addNode(child, level, showGrandChildren, documentAliasFilters);
+ AddNode(child, level, showGrandChildren, documentAliasFilters);
}
}
else
{
- nodeCount = 0;
+ _nodeCount = 0;
//store children array here because iterating over an Array property object is very inneficient.
var children = parent.Children;
foreach (CMSNode child in children)
{
- nodeChildrenCount(child, true, documentAliasFilters);
+ NodeChildrenCount(child, true, documentAliasFilters);
}
- output = new string[nodeCount];
- Counter = 0;
+ _output = new string[_nodeCount];
+ _counter = 0;
int level = 1;
foreach (CMSNode child in children)
{
- addNode(child, level, showGrandChildren, documentAliasFilters);
+ AddNode(child, level, showGrandChildren, documentAliasFilters);
}
@@ -88,21 +95,21 @@ namespace umbraco.presentation.umbraco.webservices
}
- foreach (string item in output)
+ foreach (string item in _output)
{
context.Response.Write(item + Environment.NewLine);
}
}
- private bool validNode(string nodeText)
+ private bool ValidNode(string nodeText)
{
- if (nodeText.Length >= prefix.Length)
+ if (nodeText.Length >= _prefix.Length)
{
- if (nodeText.Substring(0, prefix.Length).ToLower() == prefix.ToLower())
+ if (nodeText.Substring(0, _prefix.Length).ToLower() == _prefix.ToLower())
{
return true;
}
@@ -111,7 +118,7 @@ namespace umbraco.presentation.umbraco.webservices
return false;
}
- private void nodeChildrenCount(CMSNode node, bool countChildren, string[] documentAliasFilters)
+ private void NodeChildrenCount(CMSNode node, bool countChildren, string[] documentAliasFilters)
{
if (documentAliasFilters.Length > 0)
{
@@ -123,9 +130,9 @@ namespace umbraco.presentation.umbraco.webservices
if (new Document(node.Id).ContentType.Alias == trimmedFilter || trimmedFilter == string.Empty)
{
- if (validNode(node.Text))
+ if (ValidNode(node.Text))
{
- nodeCount += 1;
+ _nodeCount += 1;
}
}
@@ -133,9 +140,9 @@ namespace umbraco.presentation.umbraco.webservices
}
else
{
- if (validNode(node.Text))
+ if (ValidNode(node.Text))
{
- nodeCount += 1;
+ _nodeCount += 1;
}
}
@@ -145,13 +152,13 @@ namespace umbraco.presentation.umbraco.webservices
var children = node.Children;
foreach (CMSNode child in children)
{
- nodeChildrenCount(child, countChildren, documentAliasFilters);
+ NodeChildrenCount(child, countChildren, documentAliasFilters);
}
}
}
- private void addNode(CMSNode node, int level, bool showGrandChildren, string[] documentAliasFilters)
+ private void AddNode(CMSNode node, int level, bool showGrandChildren, string[] documentAliasFilters)
{
string preText = string.Empty;
@@ -170,10 +177,10 @@ namespace umbraco.presentation.umbraco.webservices
if (new Document(node.Id).ContentType.Alias == trimmedFilter || trimmedFilter == string.Empty)
{
- if (validNode(node.Text))
+ if (ValidNode(node.Text))
{
- output[Counter] = preText + node.Text + " [" + node.Id + "]";
- Counter++;
+ _output[_counter] = preText + node.Text + " [" + node.Id + "]";
+ _counter++;
}
}
@@ -181,10 +188,10 @@ namespace umbraco.presentation.umbraco.webservices
}
else
{
- if (validNode(node.Text))
+ if (ValidNode(node.Text))
{
- output[Counter] = preText + node.Text + " [" + node.Id + "]";
- Counter++;
+ _output[_counter] = preText + node.Text + " [" + node.Id + "]";
+ _counter++;
}
}
@@ -196,13 +203,13 @@ namespace umbraco.presentation.umbraco.webservices
var children = node.Children;
foreach (CMSNode child in children)
{
- addNode(child, level + 1, showGrandChildren, documentAliasFilters);
+ AddNode(child, level + 1, showGrandChildren, documentAliasFilters);
}
}
}
}
- public bool IsReusable
+ public override bool IsReusable
{
get
{