Refactored to async where appropriate.
Added call to new abstraction in member authorize attribute.
This commit is contained in:
@@ -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);
|
||||
/// <summary>
|
||||
/// Registers a new member.
|
||||
/// </summary>
|
||||
/// <param name="model">Register member model.</param>
|
||||
/// <param name="logMemberIn">Flag for whether to log the member in upon successful registration.</param>
|
||||
/// <returns>Result of registration operation.</returns>
|
||||
Task<RegisterMemberStatus> RegisterMemberAsync(RegisterModel model, bool logMemberIn = true);
|
||||
|
||||
// TODO: again, should this return the member?
|
||||
void UpdateMemberProfile(ProfileModel model, out UpdateMemberProfileStatus status, out string errorMessage);
|
||||
/// <summary>
|
||||
/// Updates the currently logged in member's profile.
|
||||
/// </summary>
|
||||
/// <param name="model">Update member profile model.</param>
|
||||
/// <returns>Result of update profile operation.</returns>
|
||||
Task<UpdateMemberProfileResult> UpdateMemberProfileAsync(ProfileModel model);
|
||||
|
||||
bool Login(string username, string password);
|
||||
/// <summary>
|
||||
/// A helper method to perform the validation and logging in of a member.
|
||||
/// </summary>
|
||||
/// <param name="username">The username.</param>
|
||||
/// <param name="password">The password.</param>
|
||||
/// <returns>Result of login operation.</returns>
|
||||
Task<bool> LoginAsync(string username, string password);
|
||||
|
||||
bool IsLoggedIn();
|
||||
|
||||
void LogOut();
|
||||
/// <summary>
|
||||
/// Logs out the current member.
|
||||
/// </summary>
|
||||
Task LogOutAsync();
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the current member is authorized based on the parameters provided.
|
||||
/// </summary>
|
||||
/// <param name="allowTypes">Allowed types.</param>
|
||||
/// <param name="allowGroups">Allowed groups.</param>
|
||||
/// <param name="allowMembers">Allowed individual members.</param>
|
||||
/// <returns>True or false if the currently logged in member is authorized</returns>
|
||||
bool IsMemberAuthorized(
|
||||
IEnumerable<string> allowTypes = null,
|
||||
IEnumerable<string> allowGroups = null,
|
||||
IEnumerable<int> allowMembers = null);
|
||||
}
|
||||
}
|
||||
|
||||
24
src/Umbraco.Core/Security/UpdateMemberProfileResult.cs
Normal file
24
src/Umbraco.Core/Security/UpdateMemberProfileResult.cs
Normal file
@@ -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 };
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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
|
||||
/// </summary>
|
||||
public class UmbracoMemberAuthorizeFilter : IAuthorizationFilter
|
||||
{
|
||||
private readonly IUmbracoWebsiteSecurity _websiteSecurity;
|
||||
|
||||
public UmbracoMemberAuthorizeFilter(IUmbracoWebsiteSecurity websiteSecurity)
|
||||
{
|
||||
_websiteSecurity = websiteSecurity;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Comma delimited list of allowed member types
|
||||
/// </summary>
|
||||
@@ -27,9 +35,7 @@ namespace Umbraco.Web.Common.Filters
|
||||
/// </summary>
|
||||
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<int>();
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<IActionResult> 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");
|
||||
|
||||
@@ -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<IActionResult> 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;
|
||||
|
||||
@@ -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<IActionResult> 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();
|
||||
|
||||
@@ -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<IActionResult> 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();
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Task<RegisterMemberStatus> RegisterMemberAsync(RegisterModel model, bool logMemberIn = true)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
public void UpdateMemberProfile(ProfileModel model, out UpdateMemberProfileStatus status, out string errorMessage)
|
||||
/// <inheritdoc/>
|
||||
public Task<UpdateMemberProfileResult> UpdateMemberProfileAsync(ProfileModel model)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
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)
|
||||
/// <inheritdoc/>
|
||||
public Task<bool> LoginAsync(string username, string password)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
public void LogOut()
|
||||
/// <inheritdoc/>
|
||||
public async Task LogOutAsync()
|
||||
{
|
||||
await _httpContextAccessor.HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool IsMemberAuthorized(IEnumerable<string> allowTypes = null, IEnumerable<string> allowGroups = null, IEnumerable<int> allowMembers = null)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user