diff --git a/src/Umbraco.Web/Models/LoginStatusModel.cs b/src/Umbraco.Web/Models/LoginStatusModel.cs index 973630b7f7..5c97aec6cb 100644 --- a/src/Umbraco.Web/Models/LoginStatusModel.cs +++ b/src/Umbraco.Web/Models/LoginStatusModel.cs @@ -6,7 +6,7 @@ using Umbraco.Web.Security; namespace Umbraco.Web.Models { /// - /// The model + /// The model representing the status of a logged in member /// public class LoginStatusModel { @@ -25,7 +25,7 @@ namespace Umbraco.Web.Models if (doLookup && HttpContext.Current != null && ApplicationContext.Current != null) { var helper = new MembershipHelper(ApplicationContext.Current, new HttpContextWrapper(HttpContext.Current)); - var model = helper.GetLoginStatusModel(); + var model = helper.GetCurrentLoginStatus(); if (model != null) { Name = model.Name; @@ -46,9 +46,24 @@ namespace Umbraco.Web.Models } + /// + /// The name of the member + /// public string Name { get; set; } + + /// + /// The username of the member + /// public string Username { get; set; } + + /// + /// The email of the member + /// public string Email { get; set; } + + /// + /// True, if the member is currently logged in + /// public bool IsLoggedIn { get; set; } } } \ No newline at end of file diff --git a/src/Umbraco.Web/Mvc/SurfaceController.cs b/src/Umbraco.Web/Mvc/SurfaceController.cs index 4aa2052519..aa98d190bf 100644 --- a/src/Umbraco.Web/Mvc/SurfaceController.cs +++ b/src/Umbraco.Web/Mvc/SurfaceController.cs @@ -4,6 +4,7 @@ using System.Web.Mvc; using System.Web.Routing; using Umbraco.Core.Models; using Umbraco.Core; +using Umbraco.Web.Security; namespace Umbraco.Web.Mvc { @@ -23,6 +24,7 @@ namespace Umbraco.Web.Mvc protected SurfaceController(UmbracoContext umbracoContext) : base(umbracoContext) { + _membershipHelper = new MembershipHelper(umbracoContext); } /// @@ -31,6 +33,17 @@ namespace Umbraco.Web.Mvc protected SurfaceController() : base(UmbracoContext.Current) { + _membershipHelper = new MembershipHelper(UmbracoContext.Current); + } + + private readonly MembershipHelper _membershipHelper; + + /// + /// Returns the MemberHelper instance + /// + public MembershipHelper Members + { + get { return _membershipHelper; } } /// diff --git a/src/Umbraco.Web/Security/MembershipHelper.cs b/src/Umbraco.Web/Security/MembershipHelper.cs index 0d958e0626..53a0e9906d 100644 --- a/src/Umbraco.Web/Security/MembershipHelper.cs +++ b/src/Umbraco.Web/Security/MembershipHelper.cs @@ -5,15 +5,22 @@ using System.Text; using System.Web; using System.Web.Security; using Umbraco.Core; +using Umbraco.Core.Models; +using Umbraco.Core.Security; using Umbraco.Web.Models; namespace Umbraco.Web.Security { - internal class MembershipHelper + + /// + /// A helper class for handling Members + /// + public class MembershipHelper { private readonly ApplicationContext _applicationContext; private readonly HttpContextBase _httpContext; + #region Constructors public MembershipHelper(ApplicationContext applicationContext, HttpContextBase httpContext) { if (applicationContext == null) throw new ArgumentNullException("applicationContext"); @@ -28,24 +35,130 @@ namespace Umbraco.Web.Security _httpContext = umbracoContext.HttpContext; _applicationContext = umbracoContext.Application; } + #endregion - public LoginStatusModel GetLoginStatusModel() + /// + /// Returns the login status model of the currently logged in member, if no member is logged in it returns null; + /// + /// + public LoginStatusModel GetCurrentLoginStatus() { - if (_httpContext.User == null || _httpContext.User.Identity.IsAuthenticated == false) + if (IsLoggedIn() == false) return null; - var member = _applicationContext.Services.MemberService.GetByUsername( - _httpContext.User.Identity.Name); - var model = LoginStatusModel.CreateModel(); - model.Name = member.Name; - model.Username = member.Username; - model.Email = member.Email; + if (Membership.Provider.IsUmbracoMembershipProvider()) + { + var member = _applicationContext.Services.MemberService.GetByUsername( + _httpContext.User.Identity.Name); + //this shouldn't happen + if (member == null) return null; + model.Name = member.Name; + model.Username = member.Username; + model.Email = member.Email; + } + else + { + var member = Membership.GetUser(); + //this shouldn't happen + if (member == null) return null; + model.Name = member.UserName; + model.Username = member.UserName; + model.Email = member.Email; + } + model.IsLoggedIn = true; return model; } - public MembershipUser UpdateMember(MembershipUser member, MembershipProvider provider, + /// + /// Returns true or false if the currently logged in member is authorized based on the parameters provided + /// + /// + /// + /// + /// + /// + public bool IsMemberAuthorized( + bool allowAll = false, + IEnumerable allowTypes = null, + IEnumerable allowGroups = null, + IEnumerable allowMembers = null) + { + if (allowAll) + return true; + + 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 (IsLoggedIn() == false) + { + // If not logged on, not allowed + allowAction = false; + } + else + { + string username; + if (Membership.Provider.IsUmbracoMembershipProvider()) + { + var member = GetCurrentMember(); + username = member.Username; + // If types defined, check member is of one of those types + var allowTypesList = allowTypes as IList ?? allowTypes.ToList(); + if (allowTypesList.Any(allowType => allowType != string.Empty)) + { + // Allow only if member's type is in list + allowAction = allowTypesList.Select(x => x.ToLowerInvariant()).Contains(member.ContentType.Alias.ToLowerInvariant()); + } + + // If specific members defined, check member is of one of those + if (allowAction && allowMembers.Any()) + { + // Allow only if member's Id is in the list + allowAction = allowMembers.Contains(member.Id); + } + } + else + { + var member = Membership.GetUser(); + username = member.UserName; + } + + // If groups defined, check member is of one of those groups + var allowGroupsList = allowGroups as IList ?? allowGroups.ToList(); + if (allowAction && allowGroupsList.Any(allowGroup => allowGroup != string.Empty)) + { + // Allow only if member is assigned to a group in the list + var groups = Roles.GetRolesForUser(username); + allowAction = allowGroupsList.Select(s => s.ToLowerInvariant()).Intersect(groups.Select(myGroup => myGroup.ToLowerInvariant())).Any(); + } + + + } + + return allowAction; + } + + /// + /// Updates a membership user with all of it's writable properties + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + internal MembershipUser UpdateMember(MembershipUser member, MembershipProvider provider, string email = null, bool? isApproved = null, bool? isLocked = null, @@ -56,11 +169,11 @@ namespace Umbraco.Web.Security //set the writable properties if (email != null) { - member.Email = email; + member.Email = email; } if (isApproved.HasValue) { - member.IsApproved = isApproved.Value; + member.IsApproved = isApproved.Value; } if (lastLoginDate.HasValue) { @@ -80,8 +193,8 @@ namespace Umbraco.Web.Security //there is no 'setter' on IsLockedOut but you can ctor a new membership user with it set, so i guess that's what we'll do, // this does mean however if it was a typed membership user object that it will no longer be typed //membershipUser.IsLockedOut = true; - member = new MembershipUser(member.ProviderName, member.UserName, - member.ProviderUserKey, member.Email, member.PasswordQuestion, member.Comment, member.IsApproved, + member = new MembershipUser(member.ProviderName, member.UserName, + member.ProviderUserKey, member.Email, member.PasswordQuestion, member.Comment, member.IsApproved, isLocked.Value, //new value member.CreationDate, member.LastLoginDate, member.LastActivityDate, member.LastPasswordChangedDate, member.LastLockoutDate); } @@ -91,5 +204,27 @@ namespace Umbraco.Web.Security return member; } + /// + /// Returns the currently logged in IMember object - this should never be exposed to the front-end since it's returning a business logic entity! + /// + /// + private IMember GetCurrentMember() + { + if (Membership.Provider.IsUmbracoMembershipProvider() == false) + { + throw new NotSupportedException("An IMember model can only be retreived when using the built-in Umbraco membership providers"); + } + var member = _applicationContext.Services.MemberService.GetByUsername(_httpContext.User.Identity.Name); + return member; + } + + /// + /// Check if a member is logged in + /// + /// + private bool IsLoggedIn() + { + return _httpContext.User != null && _httpContext.User.Identity.IsAuthenticated; + } } } diff --git a/src/Umbraco.Web/Security/WebSecurity.cs b/src/Umbraco.Web/Security/WebSecurity.cs index 133d5c8955..94d62ba56f 100644 --- a/src/Umbraco.Web/Security/WebSecurity.cs +++ b/src/Umbraco.Web/Security/WebSecurity.cs @@ -20,7 +20,7 @@ using UmbracoSettings = Umbraco.Core.Configuration.UmbracoSettings; namespace Umbraco.Web.Security { /// - /// A utility class used for dealing with security in Umbraco + /// A utility class used for dealing with USER security in Umbraco /// public class WebSecurity { @@ -32,60 +32,19 @@ namespace Umbraco.Web.Security /// /// /// + [Obsolete("Use MembershipHelper.IsMemberAuthorized instead")] public bool IsMemberAuthorized( bool allowAll = false, IEnumerable allowTypes = null, IEnumerable allowGroups = null, IEnumerable allowMembers = null) { - if (allowAll) - return true; - - if (allowTypes == null) - allowTypes = Enumerable.Empty(); - if (allowGroups == null) - allowGroups = Enumerable.Empty(); - if (allowMembers == null) - allowMembers = Enumerable.Empty(); - - // Allow by default - var allowAction = true; - - // Get member details - var member = Member.GetCurrentMember(); - if (member == null) + if (HttpContext.Current == null || ApplicationContext.Current == null) { - // If not logged on, not allowed - allowAction = false; + return false; } - else - { - // If types defined, check member is of one of those types - var allowTypesList = allowTypes as IList ?? allowTypes.ToList(); - if (allowTypesList.Any(allowType => allowType != string.Empty)) - { - // Allow only if member's type is in list - allowAction = allowTypesList.Select(x => x.ToLowerInvariant()).Contains(member.ContentType.Alias.ToLowerInvariant()); - } - - // If groups defined, check member is of one of those groups - var allowGroupsList = allowGroups as IList ?? allowGroups.ToList(); - if (allowAction && allowGroupsList.Any(allowGroup => allowGroup != string.Empty)) - { - // Allow only if member is assigned to a group in the list - var groups = Roles.GetRolesForUser(member.LoginName); - allowAction = allowGroupsList.Select(s => s.ToLowerInvariant()).Intersect(groups.Select(myGroup => myGroup.ToLowerInvariant())).Any(); - } - - // If specific members defined, check member is of one of those - if (allowAction && allowMembers.Any()) - { - // Allow only if member's Id is in the list - allowAction = allowMembers.Contains(member.Id); - } - } - - return allowAction; + var helper = new MembershipHelper(ApplicationContext.Current, new HttpContextWrapper(HttpContext.Current)); + return helper.IsMemberAuthorized(allowAll, allowTypes, allowGroups, allowMembers); } /// @@ -180,6 +139,7 @@ namespace Umbraco.Web.Security return membershipProvider != null && membershipProvider.ValidateUser(username, password); } + //TODO: This could be moved to the MembershipHelper since it's dealing with any membership provider password change /// /// Changes password for a member/user given the membership provider and the password change model /// diff --git a/src/Umbraco.Web/UI/Controls/UmbracoUserControl.cs b/src/Umbraco.Web/UI/Controls/UmbracoUserControl.cs index b97a09a080..4910dcb2d4 100644 --- a/src/Umbraco.Web/UI/Controls/UmbracoUserControl.cs +++ b/src/Umbraco.Web/UI/Controls/UmbracoUserControl.cs @@ -25,6 +25,7 @@ namespace Umbraco.Web.UI.Controls UmbracoContext = umbracoContext; InstanceId = Guid.NewGuid(); Umbraco = new UmbracoHelper(umbracoContext); + _membershipHelper = new MembershipHelper(umbracoContext); } /// @@ -35,6 +36,8 @@ namespace Umbraco.Web.UI.Controls { } + private readonly MembershipHelper _membershipHelper; + /// /// Useful for debugging /// @@ -45,6 +48,14 @@ namespace Umbraco.Web.UI.Controls /// public UmbracoHelper Umbraco { get; private set; } + /// + /// Returns the MemberHelper instance + /// + public MembershipHelper Members + { + get { return _membershipHelper; } + } + /// /// Returns the current WebSecurity instance /// diff --git a/src/Umbraco.Web/WebApi/UmbracoApiController.cs b/src/Umbraco.Web/WebApi/UmbracoApiController.cs index bf25dc0e7c..d13d56f709 100644 --- a/src/Umbraco.Web/WebApi/UmbracoApiController.cs +++ b/src/Umbraco.Web/WebApi/UmbracoApiController.cs @@ -21,8 +21,11 @@ namespace Umbraco.Web.WebApi UmbracoContext = umbracoContext; InstanceId = Guid.NewGuid(); Umbraco = new UmbracoHelper(umbracoContext); + _membershipHelper = new MembershipHelper(UmbracoContext); } + private readonly MembershipHelper _membershipHelper; + /// /// Tries to retreive the current HttpContext if one exists. /// @@ -92,5 +95,13 @@ namespace Umbraco.Web.WebApi { get { return UmbracoContext.Security; } } + + /// + /// Returns the MemberHelper instance + /// + public MembershipHelper Members + { + get { return _membershipHelper; } + } } } \ No newline at end of file