Skip to content

Commit

Permalink
Created new abstraction IUmbracoWebsiteSecurity and migrated controll…
Browse files Browse the repository at this point in the history
…er's using it (replacing MembershipHelper) to Umbraco.Web.Website.
  • Loading branch information
AndyButland committed Nov 18, 2020
1 parent 6460947 commit 0fbe01c
Show file tree
Hide file tree
Showing 20 changed files with 235 additions and 233 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using System.ComponentModel.DataAnnotations;
using System.Runtime.Serialization;

namespace Umbraco.Web.Models
namespace Umbraco.Core.Models.Security
{
public class LoginModel : PostRedirectModel
{
Expand All @@ -11,7 +11,7 @@ public class LoginModel : PostRedirectModel

[Required]
[DataMember(Name = "password", IsRequired = true)]
[StringLength(maximumLength:256)]
[StringLength(maximumLength: 256)]
public string Password { get; set; }

}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace Umbraco.Web.Models
namespace Umbraco.Core.Models.Security
{
/// <summary>
/// A base model containing a value to indicate to Umbraco where to redirect to after Posting if
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,36 +2,15 @@
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Web.Mvc;
using Current = Umbraco.Web.Composing.Current;
using Umbraco.Web.Models;

namespace Umbraco.Web.Models
namespace Umbraco.Core.Models.Security
{
/// <summary>
/// A readonly member profile model
/// </summary>
[ModelBinder(typeof(ProfileModelBinder))]
public class ProfileModel : PostRedirectModel
{

public static ProfileModel CreateModel()
{
var model = new ProfileModel(false);
return model;
}

private ProfileModel(bool doLookup)
{
MemberProperties = new List<UmbracoProperty>();
if (doLookup && Current.UmbracoContext != null)
{
var helper = Current.MembershipHelper;
var model = helper.GetCurrentMemberProfileModel();
MemberProperties = model.MemberProperties;
}
}


[Required]
[RegularExpression(@"[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?",
ErrorMessage = "Please enter a valid e-mail address")]
Expand Down Expand Up @@ -81,18 +60,6 @@ private ProfileModel(bool doLookup)
/// <remarks>
/// Adding items to this list on the front-end will not add properties to the member in the database.
/// </remarks>
public List<UmbracoProperty> MemberProperties { get; set; }

/// <summary>
/// A custom model binder for MVC because the default ctor performs a lookup!
/// </summary>
internal class ProfileModelBinder : DefaultModelBinder
{
protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)
{
return ProfileModel.CreateModel();
}

}
public List<UmbracoProperty> MemberProperties { get; set; } = new List<UmbracoProperty>();
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
using System;
using System.Collections.Generic;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Web.Mvc;
using Umbraco.Core;
using Umbraco.Web.Models;

namespace Umbraco.Web.Models
namespace Umbraco.Core.Models.Security
{
[ModelBinder(typeof(RegisterModelBinder))]
public class RegisterModel : PostRedirectModel
{
/// <summary>
Expand All @@ -27,7 +24,6 @@ private RegisterModel()
CreatePersistentLoginCookie = true;
}


[Required]
[RegularExpression(@"[A-Za-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[A-Za-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[A-Za-z0-9](?:[A-Za-z0-9-]*[A-Za-z0-9])?\.)+[A-Za-z0-9](?:[A-Za-z0-9-]*[A-Za-z0-9])?",
ErrorMessage = "Please enter a valid e-mail address")]
Expand Down Expand Up @@ -74,16 +70,5 @@ private RegisterModel()
/// Default is true to create a persistent cookie if LoginOnSuccess is true
/// </summary>
public bool CreatePersistentLoginCookie { get; set; }

/// <summary>
/// A custom model binder for MVC because the default ctor performs a lookup!
/// </summary>
internal class RegisterModelBinder : DefaultModelBinder
{
protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)
{
return RegisterModel.CreateModel();
}
}
}
}
2 changes: 0 additions & 2 deletions src/Umbraco.Core/PublishedContentExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,8 @@
using System.Collections.Generic;
using System.Linq;
using Umbraco.Core.Configuration.Models;
using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Core.Models.PublishedContent;
using Umbraco.Core.Services;
using Umbraco.Web;
using Umbraco.Web.PublishedCache;
using Umbraco.Web.Routing;

Expand Down
20 changes: 20 additions & 0 deletions src/Umbraco.Core/Security/IUmbracoWebsiteSecurity.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
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);

// TODO: again, should this return the member?
void UpdateMemberProfile(ProfileModel model, out UpdateMemberProfileStatus status, out string errorMessage);

bool Login(string username, string password);

bool IsLoggedIn();

void LogOut();
}
}
13 changes: 13 additions & 0 deletions src/Umbraco.Core/Security/RegisterMemberStatus.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
namespace Umbraco.Core.Security
{
public enum RegisterMemberStatus
{
Success,
InvalidUserName,
InvalidPassword,
InvalidEmail,
DuplicateUserName,
DuplicateEmail,
Error,
}
}
8 changes: 8 additions & 0 deletions src/Umbraco.Core/Security/UpdateMemberProfileStatus.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace Umbraco.Core.Security
{
public enum UpdateMemberProfileStatus
{
Success,
Error,
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,19 @@
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Umbraco.Core;
using Umbraco.Core.BackOffice;
using Umbraco.Core.Configuration.Models;
using Umbraco.Core.Mapping;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Membership;
using Umbraco.Core.Models.Security;
using Umbraco.Core.Security;
using Umbraco.Core.Services;
using Umbraco.Extensions;
Expand All @@ -25,12 +27,10 @@
using Umbraco.Web.Common.Exceptions;
using Umbraco.Web.Common.Filters;
using Umbraco.Web.Common.Security;
using Umbraco.Web.Editors.Filters;
using Umbraco.Web.Models;
using Umbraco.Web.Models.ContentEditing;
using Umbraco.Web.Security;
using Constants = Umbraco.Core.Constants;
using Microsoft.AspNetCore.Identity;
using Umbraco.Web.Editors.Filters;

namespace Umbraco.Web.BackOffice.Controllers
{
Expand Down
26 changes: 13 additions & 13 deletions src/Umbraco.Web.Website/Controllers/SurfaceController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,13 @@ namespace Umbraco.Web.Website.Controllers
// [MergeParentContextViewData]
public abstract class SurfaceController : PluginController
{
private readonly IPublishedUrlProvider _publishedUrlProvider;
protected SurfaceController(IUmbracoContextAccessor umbracoContextAccessor, IUmbracoDatabaseFactory databaseFactory, ServiceContext services, AppCaches appCaches, IProfilingLogger profilingLogger, IPublishedUrlProvider publishedUrlProvider)
: base(umbracoContextAccessor, databaseFactory, services, appCaches, profilingLogger)
{
PublishedUrlProvider = publishedUrlProvider;
}

protected IPublishedUrlProvider PublishedUrlProvider { get; }

/// <summary>
/// Gets the current page.
Expand All @@ -39,20 +45,14 @@ protected virtual IPublishedContent CurrentPage
}
}

protected SurfaceController(IUmbracoContextAccessor umbracoContextAccessor, IUmbracoDatabaseFactory databaseFactory, ServiceContext services, AppCaches appCaches, IProfilingLogger profilingLogger, IPublishedUrlProvider publishedUrlProvider)
: base(umbracoContextAccessor, databaseFactory, services, appCaches, profilingLogger)
{
_publishedUrlProvider = publishedUrlProvider;
}

/// <summary>
/// Redirects to the Umbraco page with the given id
/// </summary>
/// <param name="contentKey"></param>
/// <returns></returns>
protected RedirectToUmbracoPageResult RedirectToUmbracoPage(Guid contentKey)
{
return new RedirectToUmbracoPageResult(contentKey, _publishedUrlProvider, UmbracoContextAccessor);
return new RedirectToUmbracoPageResult(contentKey, PublishedUrlProvider, UmbracoContextAccessor);
}

/// <summary>
Expand All @@ -63,7 +63,7 @@ protected RedirectToUmbracoPageResult RedirectToUmbracoPage(Guid contentKey)
/// <returns></returns>
protected RedirectToUmbracoPageResult RedirectToUmbracoPage(Guid contentKey, QueryString queryString)
{
return new RedirectToUmbracoPageResult(contentKey, queryString, _publishedUrlProvider, UmbracoContextAccessor);
return new RedirectToUmbracoPageResult(contentKey, queryString, PublishedUrlProvider, UmbracoContextAccessor);
}

/// <summary>
Expand All @@ -73,7 +73,7 @@ protected RedirectToUmbracoPageResult RedirectToUmbracoPage(Guid contentKey, Que
/// <returns></returns>
protected RedirectToUmbracoPageResult RedirectToUmbracoPage(IPublishedContent publishedContent)
{
return new RedirectToUmbracoPageResult(publishedContent, _publishedUrlProvider, UmbracoContextAccessor);
return new RedirectToUmbracoPageResult(publishedContent, PublishedUrlProvider, UmbracoContextAccessor);
}

/// <summary>
Expand All @@ -84,7 +84,7 @@ protected RedirectToUmbracoPageResult RedirectToUmbracoPage(IPublishedContent pu
/// <returns></returns>
protected RedirectToUmbracoPageResult RedirectToUmbracoPage(IPublishedContent publishedContent, QueryString queryString)
{
return new RedirectToUmbracoPageResult(publishedContent, queryString, _publishedUrlProvider, UmbracoContextAccessor);
return new RedirectToUmbracoPageResult(publishedContent, queryString, PublishedUrlProvider, UmbracoContextAccessor);
}

/// <summary>
Expand All @@ -93,7 +93,7 @@ protected RedirectToUmbracoPageResult RedirectToUmbracoPage(IPublishedContent pu
/// <returns></returns>
protected RedirectToUmbracoPageResult RedirectToCurrentUmbracoPage()
{
return new RedirectToUmbracoPageResult(CurrentPage, _publishedUrlProvider, UmbracoContextAccessor);
return new RedirectToUmbracoPageResult(CurrentPage, PublishedUrlProvider, UmbracoContextAccessor);
}

/// <summary>
Expand All @@ -103,7 +103,7 @@ protected RedirectToUmbracoPageResult RedirectToCurrentUmbracoPage()
/// <returns></returns>
protected RedirectToUmbracoPageResult RedirectToCurrentUmbracoPage(QueryString queryString)
{
return new RedirectToUmbracoPageResult(CurrentPage, queryString, _publishedUrlProvider, UmbracoContextAccessor);
return new RedirectToUmbracoPageResult(CurrentPage, queryString, PublishedUrlProvider, UmbracoContextAccessor);
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,62 +1,58 @@
using System.Web.Mvc;
using Umbraco.Web.Models;
using Umbraco.Web.Mvc;
using Microsoft.AspNetCore.Mvc;
using Umbraco.Core;
using Umbraco.Core.Cache;
using Umbraco.Core.Logging;
using Umbraco.Core.Models.Security;
using Umbraco.Core.Persistence;
using Umbraco.Core.Security;
using Umbraco.Core.Services;
using Umbraco.Web.Security;
using Umbraco.Web.Common.Filters;
using Umbraco.Web.Routing;

namespace Umbraco.Web.Controllers
namespace Umbraco.Web.Website.Controllers
{
public class UmbLoginController : SurfaceController
{
private readonly MembershipHelper _membershipHelper;

public UmbLoginController()
{
}
private readonly IUmbracoWebsiteSecurity _websiteSecurity;

public UmbLoginController(IUmbracoContextAccessor umbracoContextAccessor, IUmbracoDatabaseFactory databaseFactory,
ServiceContext services, AppCaches appCaches, IProfilingLogger profilingLogger,
MembershipHelper membershipHelper)
: base(umbracoContextAccessor, databaseFactory, services, appCaches, profilingLogger)
ServiceContext services, AppCaches appCaches, IProfilingLogger profilingLogger, IPublishedUrlProvider publishedUrlProvider,
IUmbracoWebsiteSecurity websiteSecurity)
: base(umbracoContextAccessor, databaseFactory, services, appCaches, profilingLogger, publishedUrlProvider)
{
_membershipHelper = membershipHelper;
_websiteSecurity = websiteSecurity;
}

[HttpPost]
[ValidateAntiForgeryToken]
[ValidateUmbracoFormRouteString]
public ActionResult HandleLogin([Bind(Prefix = "loginModel")]LoginModel model)
public IActionResult HandleLogin([Bind(Prefix = "loginModel")]LoginModel model)
{
if (ModelState.IsValid == false)
{
return CurrentUmbracoPage();
}

if (_membershipHelper.Login(model.Username, model.Password) == false)
if (_websiteSecurity.Login(model.Username, model.Password) == false)
{
//don't add a field level error, just model level
// Don't add a field level error, just model level.
ModelState.AddModelError("loginModel", "Invalid username or password");
return CurrentUmbracoPage();
}

TempData["LoginSuccess"] = true;

//if there is a specified path to redirect to then use it
// If there is a specified path to redirect to then use it.
if (model.RedirectUrl.IsNullOrWhiteSpace() == false)
{
// validate the redirect url
// if it's not a local url we'll redirect to the root of the current site
// Validate the redirect url.
// If it's not a local url we'll redirect to the root of the current site.
return Redirect(Url.IsLocalUrl(model.RedirectUrl)
? model.RedirectUrl
: CurrentPage.AncestorOrSelf(1).Url());
: CurrentPage.AncestorOrSelf(1).Url(PublishedUrlProvider));
}

//redirect to current page by default

// Redirect to current page by default.
return RedirectToCurrentUmbracoPage();
}
}
Expand Down
Loading

0 comments on commit 0fbe01c

Please sign in to comment.