From cc55107da32af3595bf09b3f30612552873ba896 Mon Sep 17 00:00:00 2001 From: Shannon Deminick Date: Wed, 27 Feb 2013 00:19:48 +0600 Subject: [PATCH] Added method to WebSecurity to validate members, updated routes for umbraco api controllers --- .../Mvc/AreaRegistrationExtensions.cs | 42 +++++++------ .../Mvc/MemberAuthorizeAttribute.cs | 49 ++++----------- src/Umbraco.Web/Mvc/PluginControllerArea.cs | 2 +- src/Umbraco.Web/Security/WebSecurity.cs | 62 +++++++++++++++++++ .../WebApi/MemberAuthorizeAttribute.cs | 49 ++++----------- 5 files changed, 111 insertions(+), 93 deletions(-) diff --git a/src/Umbraco.Web/Mvc/AreaRegistrationExtensions.cs b/src/Umbraco.Web/Mvc/AreaRegistrationExtensions.cs index cc7cbbca19..a36c50b3e9 100644 --- a/src/Umbraco.Web/Mvc/AreaRegistrationExtensions.cs +++ b/src/Umbraco.Web/Mvc/AreaRegistrationExtensions.cs @@ -9,26 +9,28 @@ namespace Umbraco.Web.Mvc { internal static class AreaRegistrationExtensions { - /// - /// Creates a custom individual route for the specified controller plugin. Individual routes - /// are required by controller plugins to map to a unique URL based on ID. - /// - /// - /// - /// An existing route collection - /// - /// The suffix name that the controller name must end in before the "Controller" string for example: - /// ContentTreeController has a controllerSuffixName of "Tree", this is used for route constraints. - /// - /// - /// - /// - /// The DataToken value to set for the 'umbraco' key, this defaults to 'backoffice' - /// - /// - internal static Route RouteControllerPlugin(this AreaRegistration area, string controllerName, Type controllerType, RouteCollection routes, + /// + /// Creates a custom individual route for the specified controller plugin. Individual routes + /// are required by controller plugins to map to a unique URL based on ID. + /// + /// + /// + /// An existing route collection + /// + /// The suffix name that the controller name must end in before the "Controller" string for example: + /// ContentTreeController has a controllerSuffixName of "Tree", this is used for route constraints. + /// + /// + /// + /// + /// The DataToken value to set for the 'umbraco' key, this defaults to 'backoffice' + /// By default this value is just {action}/{id} but can be modified for things like web api routes + /// + /// + internal static Route RouteControllerPlugin(this AreaRegistration area, string controllerName, Type controllerType, RouteCollection routes, string controllerSuffixName, string defaultAction, object defaultId, - string umbracoTokenValue = "backoffice") + string umbracoTokenValue = "backoffice", + string routeTokens = "{action}/{id}") { Mandate.ParameterNotNullOrEmpty(controllerName, "controllerName"); Mandate.ParameterNotNullOrEmpty(controllerSuffixName, "controllerSuffixName"); @@ -40,7 +42,7 @@ namespace Umbraco.Web.Mvc var umbracoArea = GlobalSettings.UmbracoMvcArea; //routes are explicitly name with controller names and IDs - var url = umbracoArea + "/" + area.AreaName + "/" + controllerName + "/{action}/{id}"; + var url = umbracoArea + "/" + area.AreaName + "/" + controllerName + "/" + routeTokens; //create a new route with custom name, specified url, and the namespace of the controller plugin var controllerPluginRoute = routes.MapRoute( diff --git a/src/Umbraco.Web/Mvc/MemberAuthorizeAttribute.cs b/src/Umbraco.Web/Mvc/MemberAuthorizeAttribute.cs index 7b071313a5..29db38ade5 100644 --- a/src/Umbraco.Web/Mvc/MemberAuthorizeAttribute.cs +++ b/src/Umbraco.Web/Mvc/MemberAuthorizeAttribute.cs @@ -1,7 +1,9 @@ -using System.Linq; +using System.Collections.Generic; +using System.Linq; using System.Web; using System.Web.Mvc; using System.Web.Security; +using Umbraco.Web.Security; using umbraco.cms.businesslogic.member; using AuthorizeAttribute = System.Web.Mvc.AuthorizeAttribute; @@ -38,45 +40,20 @@ namespace Umbraco.Web.Mvc protected override bool AuthorizeCore(HttpContextBase httpContext) { - // Allow by default - var allowAction = true; - - // If not set to allow all, need to check current loggined in member - if (!AllowAll) + var members = new List(); + foreach (var s in AllowMembers.Split(',')) { - // Get member details - var member = Member.GetCurrentMember(); - if (member == null) + int id; + if (int.TryParse(s, out id)) { - // If not logged on, not allowed - allowAction = false; - } - else - { - // If types defined, check member is of one of those types - if (!string.IsNullOrEmpty(AllowType)) - { - // Allow only if member's type is in list - allowAction = AllowType.ToLower().Split(',').Contains(member.ContentType.Alias.ToLower()); - } - - // If groups defined, check member is of one of those groups - if (allowAction && !string.IsNullOrEmpty(AllowGroup)) - { - // Allow only if member's type is in list - var groups = System.Web.Security.Roles.GetRolesForUser(member.LoginName); - allowAction = groups.Select(s => s.ToLower()).Intersect(AllowGroup.ToLower().Split(',')).Any(); - } - - // If specific members defined, check member is of one of those - if (allowAction && !string.IsNullOrEmpty(AllowMembers)) - { - // Allow only if member's type is in list - allowAction = AllowMembers.ToLower().Split(',').Contains(member.Id.ToString()); - } + members.Add(id); } } - return allowAction; + + return WebSecurity.IsMemberAuthorized(AllowAll, + AllowType.Split(','), + AllowGroup.Split(','), + members); } /// diff --git a/src/Umbraco.Web/Mvc/PluginControllerArea.cs b/src/Umbraco.Web/Mvc/PluginControllerArea.cs index d5f16040a1..abac25d1a0 100644 --- a/src/Umbraco.Web/Mvc/PluginControllerArea.cs +++ b/src/Umbraco.Web/Mvc/PluginControllerArea.cs @@ -85,7 +85,7 @@ namespace Umbraco.Web.Mvc { foreach (var s in apiControllers) { - this.RouteControllerPlugin(s.ControllerName, s.ControllerType, routes, "Api", "Index", UrlParameter.Optional, "api"); + this.RouteControllerPlugin(s.ControllerName, s.ControllerType, routes, "Api", "Index", UrlParameter.Optional, "api", "{id}"); } } } diff --git a/src/Umbraco.Web/Security/WebSecurity.cs b/src/Umbraco.Web/Security/WebSecurity.cs index 4fff822e72..dac7d3a461 100644 --- a/src/Umbraco.Web/Security/WebSecurity.cs +++ b/src/Umbraco.Web/Security/WebSecurity.cs @@ -10,6 +10,7 @@ using Umbraco.Web.UI.Pages; using umbraco; using umbraco.BusinessLogic; using umbraco.DataLayer; +using umbraco.cms.businesslogic.member; namespace Umbraco.Web.Security { @@ -19,6 +20,67 @@ namespace Umbraco.Web.Security /// public static class WebSecurity { + /// + /// Returns true or false if the currently logged in member is authorized based on the parameters provided + /// + /// + /// + /// + /// + /// + public static bool IsMemberAuthorized( + bool allowAll = false, + IEnumerable allowTypes = null, + IEnumerable allowGroups = null, + IEnumerable allowMembers = null) + { + if (allowTypes == null) + allowTypes = Enumerable.Empty(); + if (allowGroups == null) + allowGroups = Enumerable.Empty(); + if (allowMembers == null) + allowMembers = Enumerable.Empty(); + + // Allow by default + var allowAction = true; + + // If not set to allow all, need to check current loggined in member + if (!allowAll) + { + // Get member details + var member = Member.GetCurrentMember(); + if (member == null) + { + // If not logged on, not allowed + allowAction = false; + } + else + { + // If types defined, check member is of one of those types + if (allowTypes.Any()) + { + // Allow only if member's type is in list + allowAction = allowTypes.Select(x => x.ToLowerInvariant()).Contains(member.ContentType.Alias.ToLowerInvariant()); + } + + // If groups defined, check member is of one of those groups + if (allowAction && allowGroups.Any()) + { + // Allow only if member's type is in list + var groups = System.Web.Security.Roles.GetRolesForUser(member.LoginName); + allowAction = groups.Select(s => s.ToLower()).Intersect(allowGroups).Any(); + } + + // If specific members defined, check member is of one of those + if (allowAction && allowMembers.Any()) + { + // Allow only if member's type is in list + allowAction = allowMembers.Contains(member.Id); + } + } + } + return allowAction; + } /// /// Gets the SQL helper. diff --git a/src/Umbraco.Web/WebApi/MemberAuthorizeAttribute.cs b/src/Umbraco.Web/WebApi/MemberAuthorizeAttribute.cs index aab21be1f9..16aa4e8fb9 100644 --- a/src/Umbraco.Web/WebApi/MemberAuthorizeAttribute.cs +++ b/src/Umbraco.Web/WebApi/MemberAuthorizeAttribute.cs @@ -1,6 +1,8 @@ -using System.Linq; +using System.Collections.Generic; +using System.Linq; using System.Web; using System.Web.Http; +using Umbraco.Web.Security; using umbraco.cms.businesslogic.member; namespace Umbraco.Web.WebApi @@ -36,45 +38,20 @@ namespace Umbraco.Web.WebApi protected override bool IsAuthorized(System.Web.Http.Controllers.HttpActionContext actionContext) { - // Allow by default - var allowAction = true; - - // If not set to allow all, need to check current loggined in member - if (!AllowAll) + var members = new List(); + foreach (var s in AllowMembers.Split(',')) { - // Get member details - var member = Member.GetCurrentMember(); - if (member == null) + int id; + if (int.TryParse(s, out id)) { - // If not logged on, not allowed - allowAction = false; - } - else - { - // If types defined, check member is of one of those types - if (!string.IsNullOrEmpty(AllowType)) - { - // Allow only if member's type is in list - allowAction = AllowType.ToLower().Split(',').Contains(member.ContentType.Alias.ToLower()); - } - - // If groups defined, check member is of one of those groups - if (allowAction && !string.IsNullOrEmpty(AllowGroup)) - { - // Allow only if member's type is in list - var groups = System.Web.Security.Roles.GetRolesForUser(member.LoginName); - allowAction = groups.Select(s => s.ToLower()).Intersect(AllowGroup.ToLower().Split(',')).Any(); - } - - // If specific members defined, check member is of one of those - if (allowAction && !string.IsNullOrEmpty(AllowMembers)) - { - // Allow only if member's type is in list - allowAction = AllowMembers.ToLower().Split(',').Contains(member.Id.ToString()); - } + members.Add(id); } } - return allowAction; + + return WebSecurity.IsMemberAuthorized(AllowAll, + AllowType.Split(','), + AllowGroup.Split(','), + members); } }