diff --git a/src/Umbraco.Core/Security/IUmbracoWebsiteSecurity.cs b/src/Umbraco.Core/Security/IUmbracoWebsiteSecurity.cs
index f14adae174..2f35a83dc2 100644
--- a/src/Umbraco.Core/Security/IUmbracoWebsiteSecurity.cs
+++ b/src/Umbraco.Core/Security/IUmbracoWebsiteSecurity.cs
@@ -1,20 +1,51 @@
-using Umbraco.Core.Models.Security;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using Umbraco.Core.Models.Security;
namespace Umbraco.Core.Security
{
public interface IUmbracoWebsiteSecurity
{
- // TODO: this should return the member, but in what form? MembershipUser is in place on MembershipHelper, but
- // isn't appropriate for when we're using ASP.NET Identity.
- void RegisterMember(RegisterModel model, out RegisterMemberStatus status, bool logMemberIn = true);
+ ///
+ /// Registers a new member.
+ ///
+ /// Register member model.
+ /// Flag for whether to log the member in upon successful registration.
+ /// Result of registration operation.
+ Task RegisterMemberAsync(RegisterModel model, bool logMemberIn = true);
- // TODO: again, should this return the member?
- void UpdateMemberProfile(ProfileModel model, out UpdateMemberProfileStatus status, out string errorMessage);
+ ///
+ /// Updates the currently logged in member's profile.
+ ///
+ /// Update member profile model.
+ /// Result of update profile operation.
+ Task UpdateMemberProfileAsync(ProfileModel model);
- bool Login(string username, string password);
+ ///
+ /// A helper method to perform the validation and logging in of a member.
+ ///
+ /// The username.
+ /// The password.
+ /// Result of login operation.
+ Task LoginAsync(string username, string password);
bool IsLoggedIn();
- void LogOut();
+ ///
+ /// Logs out the current member.
+ ///
+ Task LogOutAsync();
+
+ ///
+ /// Checks if the current member is authorized based on the parameters provided.
+ ///
+ /// Allowed types.
+ /// Allowed groups.
+ /// Allowed individual members.
+ /// True or false if the currently logged in member is authorized
+ bool IsMemberAuthorized(
+ IEnumerable allowTypes = null,
+ IEnumerable allowGroups = null,
+ IEnumerable allowMembers = null);
}
}
diff --git a/src/Umbraco.Core/Security/UpdateMemberProfileResult.cs b/src/Umbraco.Core/Security/UpdateMemberProfileResult.cs
new file mode 100644
index 0000000000..1d435378a6
--- /dev/null
+++ b/src/Umbraco.Core/Security/UpdateMemberProfileResult.cs
@@ -0,0 +1,24 @@
+namespace Umbraco.Core.Security
+{
+ public class UpdateMemberProfileResult
+ {
+ private UpdateMemberProfileResult()
+ {
+ }
+
+ public UpdateMemberProfileStatus Status { get; private set; }
+
+ public string ErrorMessage { get; private set; }
+
+ public static UpdateMemberProfileResult Success()
+ {
+ return new UpdateMemberProfileResult { Status = UpdateMemberProfileStatus.Success };
+ }
+
+ public static UpdateMemberProfileResult Error(string message)
+ {
+ return new UpdateMemberProfileResult { Status = UpdateMemberProfileStatus.Error, ErrorMessage = message };
+ }
+ }
+
+}
diff --git a/src/Umbraco.Web.Common/Filters/UmbracoMemberAuthorizeFilter.cs b/src/Umbraco.Web.Common/Filters/UmbracoMemberAuthorizeFilter.cs
index 27c2922637..4019f462eb 100644
--- a/src/Umbraco.Web.Common/Filters/UmbracoMemberAuthorizeFilter.cs
+++ b/src/Umbraco.Web.Common/Filters/UmbracoMemberAuthorizeFilter.cs
@@ -2,6 +2,7 @@
using Microsoft.AspNetCore.Mvc.Filters;
using System.Collections.Generic;
using Umbraco.Core;
+using Umbraco.Core.Security;
using Umbraco.Extensions;
namespace Umbraco.Web.Common.Filters
@@ -12,6 +13,13 @@ namespace Umbraco.Web.Common.Filters
///
public class UmbracoMemberAuthorizeFilter : IAuthorizationFilter
{
+ private readonly IUmbracoWebsiteSecurity _websiteSecurity;
+
+ public UmbracoMemberAuthorizeFilter(IUmbracoWebsiteSecurity websiteSecurity)
+ {
+ _websiteSecurity = websiteSecurity;
+ }
+
///
/// Comma delimited list of allowed member types
///
@@ -27,9 +35,7 @@ namespace Umbraco.Web.Common.Filters
///
public string AllowMembers { get; private set; }
-
- private UmbracoMemberAuthorizeFilter(
- string allowType, string allowGroup, string allowMembers)
+ private UmbracoMemberAuthorizeFilter(string allowType, string allowGroup, string allowMembers)
{
AllowType = allowType;
AllowGroup = allowGroup;
@@ -48,11 +54,19 @@ namespace Umbraco.Web.Common.Filters
private bool IsAuthorized()
{
if (AllowMembers.IsNullOrWhiteSpace())
- AllowMembers = "";
+ {
+ AllowMembers = string.Empty;
+ }
+
if (AllowGroup.IsNullOrWhiteSpace())
- AllowGroup = "";
+ {
+ AllowGroup = string.Empty;
+ }
+
if (AllowType.IsNullOrWhiteSpace())
- AllowType = "";
+ {
+ AllowType = string.Empty;
+ }
var members = new List();
foreach (var s in AllowMembers.Split(','))
@@ -63,7 +77,7 @@ namespace Umbraco.Web.Common.Filters
}
}
- return false;// TODO reintroduce when members are implemented: _memberHelper.IsMemberAuthorized(AllowType.Split(','), AllowGroup.Split(','), members);
+ return _websiteSecurity.IsMemberAuthorized(AllowType.Split(','), AllowGroup.Split(','), members);
}
}
}
diff --git a/src/Umbraco.Web.Website/Controllers/UmbLoginController.cs b/src/Umbraco.Web.Website/Controllers/UmbLoginController.cs
index a986cef77e..51938f00f5 100644
--- a/src/Umbraco.Web.Website/Controllers/UmbLoginController.cs
+++ b/src/Umbraco.Web.Website/Controllers/UmbLoginController.cs
@@ -1,4 +1,5 @@
-using Microsoft.AspNetCore.Mvc;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Mvc;
using Umbraco.Core;
using Umbraco.Core.Cache;
using Umbraco.Core.Logging;
@@ -26,14 +27,14 @@ namespace Umbraco.Web.Website.Controllers
[HttpPost]
[ValidateAntiForgeryToken]
[ValidateUmbracoFormRouteString]
- public IActionResult HandleLogin([Bind(Prefix = "loginModel")]LoginModel model)
+ public async Task HandleLogin([Bind(Prefix = "loginModel")]LoginModel model)
{
if (ModelState.IsValid == false)
{
return CurrentUmbracoPage();
}
- if (_websiteSecurity.Login(model.Username, model.Password) == false)
+ if (await _websiteSecurity.LoginAsync(model.Username, model.Password) == false)
{
// Don't add a field level error, just model level.
ModelState.AddModelError("loginModel", "Invalid username or password");
diff --git a/src/Umbraco.Web.Website/Controllers/UmbLoginStatusController.cs b/src/Umbraco.Web.Website/Controllers/UmbLoginStatusController.cs
index 1c026c7b46..3da1f34282 100644
--- a/src/Umbraco.Web.Website/Controllers/UmbLoginStatusController.cs
+++ b/src/Umbraco.Web.Website/Controllers/UmbLoginStatusController.cs
@@ -1,4 +1,5 @@
-using Microsoft.AspNetCore.Mvc;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Mvc;
using Umbraco.Core;
using Umbraco.Core.Cache;
using Umbraco.Core.Logging;
@@ -11,7 +12,7 @@ using Umbraco.Web.Routing;
namespace Umbraco.Web.Website.Controllers
{
- // TOOO: reinstate [MemberAuthorize]
+ [UmbracoMemberAuthorize]
public class UmbLoginStatusController : SurfaceController
{
private readonly IUmbracoWebsiteSecurity _websiteSecurity;
@@ -27,7 +28,7 @@ namespace Umbraco.Web.Website.Controllers
[HttpPost]
[ValidateAntiForgeryToken]
[ValidateUmbracoFormRouteString]
- public IActionResult HandleLogout([Bind(Prefix = "logoutModel")]PostRedirectModel model)
+ public async Task HandleLogout([Bind(Prefix = "logoutModel")]PostRedirectModel model)
{
if (ModelState.IsValid == false)
{
@@ -36,7 +37,7 @@ namespace Umbraco.Web.Website.Controllers
if (_websiteSecurity.IsLoggedIn())
{
- _websiteSecurity.LogOut();
+ await _websiteSecurity.LogOutAsync();
}
TempData["LogoutSuccess"] = true;
diff --git a/src/Umbraco.Web.Website/Controllers/UmbProfileController.cs b/src/Umbraco.Web.Website/Controllers/UmbProfileController.cs
index e91266f396..69bf77981e 100644
--- a/src/Umbraco.Web.Website/Controllers/UmbProfileController.cs
+++ b/src/Umbraco.Web.Website/Controllers/UmbProfileController.cs
@@ -1,4 +1,5 @@
using System;
+using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Umbraco.Core;
using Umbraco.Core.Cache;
@@ -12,7 +13,7 @@ using Umbraco.Web.Routing;
namespace Umbraco.Web.Website.Controllers
{
- // TOOO: reinstate [MemberAuthorize]
+ [UmbracoMemberAuthorize]
public class UmbProfileController : SurfaceController
{
private readonly IUmbracoWebsiteSecurity _websiteSecurity;
@@ -28,21 +29,21 @@ namespace Umbraco.Web.Website.Controllers
[HttpPost]
[ValidateAntiForgeryToken]
[ValidateUmbracoFormRouteString]
- public IActionResult HandleUpdateProfile([Bind(Prefix = "profileModel")] ProfileModel model)
+ public async Task HandleUpdateProfile([Bind(Prefix = "profileModel")] ProfileModel model)
{
if (ModelState.IsValid == false)
{
return CurrentUmbracoPage();
}
- _websiteSecurity.UpdateMemberProfile(model, out var status, out var errorMessage);
- switch(status)
+ var result = await _websiteSecurity.UpdateMemberProfileAsync(model);
+ switch (result.Status)
{
case UpdateMemberProfileStatus.Success:
break;
case UpdateMemberProfileStatus.Error:
// Don't add a field level error, just model level.
- ModelState.AddModelError("profileModel", errorMessage);
+ ModelState.AddModelError("profileModel", result.ErrorMessage);
return CurrentUmbracoPage();
default:
throw new ArgumentOutOfRangeException();
diff --git a/src/Umbraco.Web.Website/Controllers/UmbRegisterController.cs b/src/Umbraco.Web.Website/Controllers/UmbRegisterController.cs
index e20cb88715..8af2157022 100644
--- a/src/Umbraco.Web.Website/Controllers/UmbRegisterController.cs
+++ b/src/Umbraco.Web.Website/Controllers/UmbRegisterController.cs
@@ -1,4 +1,5 @@
using System;
+using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Umbraco.Core;
using Umbraco.Core.Cache;
@@ -27,7 +28,7 @@ namespace Umbraco.Web.Website.Controllers
[HttpPost]
[ValidateAntiForgeryToken]
[ValidateUmbracoFormRouteString]
- public IActionResult HandleRegisterMember([Bind(Prefix = "registerModel")]RegisterModel model)
+ public async Task HandleRegisterMember([Bind(Prefix = "registerModel")]RegisterModel model)
{
if (ModelState.IsValid == false)
{
@@ -41,9 +42,9 @@ namespace Umbraco.Web.Website.Controllers
model.Name = model.Email;
}
- _websiteSecurity.RegisterMember(model, out var status, model.LoginOnSuccess);
+ var result = await _websiteSecurity.RegisterMemberAsync(model, model.LoginOnSuccess);
- switch (status)
+ switch (result)
{
case RegisterMemberStatus.Success:
@@ -80,7 +81,7 @@ namespace Umbraco.Web.Website.Controllers
break;
case RegisterMemberStatus.Error:
// Don't add a field level error, just model level.
- ModelState.AddModelError("registerModel", "An error occurred creating the member: " + status);
+ ModelState.AddModelError("registerModel", $"An error occurred creating the member: {result}");
break;
default:
throw new ArgumentOutOfRangeException();
diff --git a/src/Umbraco.Web.Website/Security/UmbracoWebsiteSecurity.cs b/src/Umbraco.Web.Website/Security/UmbracoWebsiteSecurity.cs
index cd1d667dc9..90e80537ec 100644
--- a/src/Umbraco.Web.Website/Security/UmbracoWebsiteSecurity.cs
+++ b/src/Umbraco.Web.Website/Security/UmbracoWebsiteSecurity.cs
@@ -1,31 +1,55 @@
-using Umbraco.Core.Models.Security;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Authentication;
+using Microsoft.AspNetCore.Authentication.Cookies;
+using Microsoft.AspNetCore.Http;
+using Umbraco.Core.Models.Security;
using Umbraco.Core.Security;
namespace Umbraco.Web.Website.Security
{
public class UmbracoWebsiteSecurity : IUmbracoWebsiteSecurity
{
- public void RegisterMember(RegisterModel model, out RegisterMemberStatus status, bool logMemberIn = true)
+ private readonly IHttpContextAccessor _httpContextAccessor;
+
+ public UmbracoWebsiteSecurity(IHttpContextAccessor httpContextAccessor)
+ {
+ _httpContextAccessor = httpContextAccessor;
+ }
+
+ ///
+ public Task RegisterMemberAsync(RegisterModel model, bool logMemberIn = true)
{
throw new System.NotImplementedException();
}
- public void UpdateMemberProfile(ProfileModel model, out UpdateMemberProfileStatus status, out string errorMessage)
+ ///
+ public Task UpdateMemberProfileAsync(ProfileModel model)
{
throw new System.NotImplementedException();
}
+ ///
public bool IsLoggedIn()
{
- throw new System.NotImplementedException();
+ var httpContext = _httpContextAccessor.HttpContext;
+ return httpContext?.User != null && httpContext.User.Identity.IsAuthenticated;
}
- public bool Login(string username, string password)
+ ///
+ public Task LoginAsync(string username, string password)
{
throw new System.NotImplementedException();
}
- public void LogOut()
+ ///
+ public async Task LogOutAsync()
+ {
+ await _httpContextAccessor.HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
+ }
+
+ ///
+ public bool IsMemberAuthorized(IEnumerable allowTypes = null, IEnumerable allowGroups = null, IEnumerable allowMembers = null)
{
throw new System.NotImplementedException();
}