--HG--
branch : dev
This commit is contained in:
Louis DeJardin
2010-05-03 11:19:34 -07:00
26 changed files with 398 additions and 244 deletions

View File

@@ -3,16 +3,31 @@ using Orchard.ContentManagement;
using Orchard.ContentManagement.Drivers;
using Orchard.Core.Common.Models;
using Orchard.Core.Common.ViewModels;
using Orchard.Core.Common.Services;
using Orchard.Localization;
using Orchard.UI.Notify;
namespace Orchard.Core.Common.Drivers {
[UsedImplicitly]
public class Routable : ContentPartDriver<RoutableAspect> {
private const string TemplateName = "Parts/Common.Routable";
private readonly IOrchardServices _services;
private readonly IRoutableService _routableService;
private Localizer T { get; set; }
protected override string Prefix {
get { return "Routable"; }
}
public Routable(IOrchardServices services, IRoutableService routableService)
{
_services = services;
_routableService = routableService;
T = NullLocalizer.Instance;
}
protected override DriverResult Editor(RoutableAspect part) {
var model = new RoutableEditorViewModel { Prefix = Prefix, RoutableAspect = part };
return ContentPartTemplate(model, TemplateName, Prefix).Location("primary", "before.5");
@@ -21,7 +36,19 @@ namespace Orchard.Core.Common.Drivers {
protected override DriverResult Editor(RoutableAspect part, IUpdateModel updater) {
var model = new RoutableEditorViewModel { Prefix = Prefix, RoutableAspect = part };
updater.TryUpdateModel(model, Prefix, null, null);
if (!_routableService.IsSlugValid(part.Slug)){
updater.AddModelError("Routable.Slug", T("Please do not use any of the following characters in your slugs: \"/\", \":\", \"?\", \"#\", \"[\", \"]\", \"@\", \"!\", \"$\", \"&\", \"'\", \"(\", \")\", \"*\", \"+\", \",\", \";\", \"=\". No spaces are allowed (please use dashes or underscores instead).").ToString());
}
string originalSlug = part.Slug;
if(!_routableService.ProcessSlug(part)) {
_services.Notifier.Warning(T("Slugs in conflict. \"{0}\" is already set for a previously created {2} so now it has the slug \"{1}\"",
originalSlug, part.Slug, part.ContentItem.ContentType));
}
return ContentPartTemplate(model, TemplateName, Prefix).Location("primary", "before.5");
}
}
}

View File

@@ -129,6 +129,10 @@ namespace Orchard.Core.Common.Handlers {
return user;
});
// Force call to setter if we had already set a value
if (aspect.OwnerField.Value != null)
aspect.OwnerField.Value = aspect.OwnerField.Value;
aspect.ContainerField.Setter(container => {
if (container == null) {
aspect.Record.Container = null;
@@ -138,6 +142,10 @@ namespace Orchard.Core.Common.Handlers {
}
return container;
});
// Force call to setter if we had already set a value
if (aspect.ContainerField.Value != null)
aspect.ContainerField.Value = aspect.ContainerField.Value;
}
@@ -172,7 +180,7 @@ namespace Orchard.Core.Common.Handlers {
var priorOwner = viewModel.Owner;
context.Updater.TryUpdateModel(viewModel, "CommonAspect", null, null);
if (viewModel.Owner != priorOwner) {
if (viewModel.Owner != null && viewModel.Owner != priorOwner) {
var newOwner = _membershipService.GetUser(viewModel.Owner);
if (newOwner == null) {
context.Updater.AddModelError("CommonAspect.Owner", T("Invalid user name"));
@@ -181,6 +189,7 @@ namespace Orchard.Core.Common.Handlers {
instance.Owner = newOwner;
}
}
context.AddEditor(new TemplateViewModel(viewModel, "CommonAspect") { TemplateName = "Parts/Common.Owner", ZoneName = "primary", Position = "999" });
}
}

View File

@@ -7,6 +7,7 @@ using Orchard.ContentManagement;
using Orchard.ContentManagement.Drivers;
using Orchard.ContentManagement.Handlers;
using Orchard.Core.Common.Models;
using Orchard.Core.Common.Services;
using Orchard.Data;
namespace Orchard.Core.Common.Handlers {
@@ -14,7 +15,7 @@ namespace Orchard.Core.Common.Handlers {
public class RoutableAspectHandler : ContentHandler {
private readonly IEnumerable<IContentItemDriver> _contentItemDrivers;
public RoutableAspectHandler(IRepository<RoutableRecord> repository, IEnumerable<IContentItemDriver> contentItemDrivers, UrlHelper urlHelper) {
public RoutableAspectHandler(IRepository<RoutableRecord> repository, IEnumerable<IContentItemDriver> contentItemDrivers, IRoutableService routableService, UrlHelper urlHelper) {
_contentItemDrivers = contentItemDrivers;
Filters.Add(StorageFilter.For(repository));
@@ -32,6 +33,9 @@ namespace Orchard.Core.Common.Handlers {
routable.ContentItemBasePath = url;
});
OnCreated<RoutableAspect>((context, ra) => routableService.ProcessSlug(ra));
}
private static RouteValueDictionary GetRouteValues(IContentItemDriver driver, ContentItem contentItem) {

View File

@@ -7,5 +7,22 @@ namespace Orchard.Core.Common.Services {
void FillSlug<TModel>(TModel model) where TModel : RoutableAspect;
void FillSlug<TModel>(TModel model, Func<string, string> generateSlug) where TModel : RoutableAspect;
string GenerateUniqueSlug(string slugCandidate, IEnumerable<string> existingSlugs);
/// <summary>
/// Returns any content item of the specified content type with similar slugs
/// </summary>
string[] GetSimilarSlugs(string contentType, string slug);
/// <summary>
/// Validates the given slug
/// </summary>
bool IsSlugValid(string slug);
/// <summary>
/// Defines the slug of a RoutableAspect and validate its unicity
/// </summary>
/// <returns>True if the slug has been created, False if a conflict occured</returns>
bool ProcessSlug(RoutableAspect part);
}
}

View File

@@ -4,10 +4,19 @@ using System.Linq;
using System.Text.RegularExpressions;
using JetBrains.Annotations;
using Orchard.Core.Common.Models;
using Orchard.ContentManagement;
using Orchard.Localization;
using Orchard.UI.Notify;
namespace Orchard.Core.Common.Services {
[UsedImplicitly]
public class RoutableService : IRoutableService {
private readonly IContentManager _contentManager;
public RoutableService(IContentManager contentManager) {
_contentManager = contentManager;
}
public void FillSlug<TModel>(TModel model) where TModel : RoutableAspect {
if (!string.IsNullOrEmpty(model.Slug) || string.IsNullOrEmpty(model.Title))
return;
@@ -31,8 +40,6 @@ namespace Orchard.Core.Common.Services {
model.Slug = generateSlug(model.Title).ToLowerInvariant();
}
public string GenerateUniqueSlug(string slugCandidate, IEnumerable<string> existingSlugs) {
if (existingSlugs == null || !existingSlugs.Contains(slugCandidate))
return slugCandidate;
@@ -55,5 +62,46 @@ namespace Orchard.Core.Common.Services {
? (int?)++v
: null;
}
public string[] GetSimilarSlugs(string contentType, string slug)
{
return
_contentManager.Query(contentType).Join<RoutableRecord>()
.List()
.Select(i => i.As<RoutableAspect>().Slug)
.Where(rr => rr.StartsWith(slug, StringComparison.OrdinalIgnoreCase)) // todo: for some reason the filter doesn't work within the query, even without StringComparison or StartsWith
.ToArray();
}
public bool IsSlugValid(string slug) {
// see http://tools.ietf.org/html/rfc3987 for prohibited chars
return slug == null || String.IsNullOrEmpty(slug.Trim()) || Regex.IsMatch(slug, @"^[^/:?#\[\]@!$&'()*+,;=\s]+$");
}
public bool ProcessSlug(RoutableAspect part)
{
FillSlug(part);
if (string.IsNullOrEmpty(part.Slug))
{
return true;
}
var slugsLikeThis = GetSimilarSlugs(part.ContentItem.ContentType, part.Slug);
//todo: (heskew) need better messages
if (slugsLikeThis.Length > 0)
{
var originalSlug = part.Slug;
//todo: (heskew) make auto-uniqueness optional
part.Slug = GenerateUniqueSlug(part.Slug, slugsLikeThis);
if (originalSlug != part.Slug) {
return false;
}
}
return true;
}
}
}

View File

@@ -27,14 +27,12 @@ namespace Orchard.Blogs.Drivers {
private readonly IContentManager _contentManager;
private readonly IBlogService _blogService;
private readonly IBlogPostService _blogPostService;
private readonly IRoutableService _routableService;
public BlogDriver(IOrchardServices services, IContentManager contentManager, IBlogService blogService, IBlogPostService blogPostService, IRoutableService routableService) {
public BlogDriver(IOrchardServices services, IContentManager contentManager, IBlogService blogService, IBlogPostService blogPostService) {
Services = services;
_contentManager = contentManager;
_blogService = blogService;
_blogPostService = blogPostService;
_routableService = routableService;
T = NullLocalizer.Instance;
}
@@ -97,47 +95,9 @@ namespace Orchard.Blogs.Drivers {
protected override DriverResult Editor(Blog blog, IUpdateModel updater) {
updater.TryUpdateModel(blog, Prefix, null, null);
//todo: (heskew) something better needs to be done with this...still feels shoehorned in here
ProcessSlug(blog, updater);
return Combined(
ContentItemTemplate("Items/Blogs.Blog"),
ContentPartTemplate(blog, "Parts/Blogs.Blog.Fields").Location("primary", "1"));
}
private void ProcessSlug(Blog blog, IUpdateModel updater) {
_routableService.FillSlug(blog.As<RoutableAspect>());
if (string.IsNullOrEmpty(blog.Slug)) {
return;
// OR
// updater.AddModelError("Routable.Slug", T("The slug is required.").ToString());
// return;
}
if (!Regex.IsMatch(blog.Slug, @"^[^/:?#\[\]@!$&'()*+,;=\s]+$")) {
//todo: (heskew) get rid of the hard-coded prefix
updater.AddModelError("Routable.Slug", T("Please do not use any of the following characters in your slugs: \"/\", \":\", \"?\", \"#\", \"[\", \"]\", \"@\", \"!\", \"$\", \"&\", \"'\", \"(\", \")\", \"*\", \"+\", \",\", \";\", \"=\". No spaces are allowed (please use dashes or underscores instead).").ToString());
}
var slugsLikeThis = _blogService.Get().Where(
b => b.Slug.StartsWith(blog.Slug, StringComparison.OrdinalIgnoreCase) &&
b.Id != blog.Id).Select(b => b.Slug);
//todo: (heskew) need better messages
if (slugsLikeThis.Count() > 0) {
var originalSlug = blog.Slug;
//todo: (heskew) make auto-uniqueness optional
blog.Slug = _routableService.GenerateUniqueSlug(blog.Slug, slugsLikeThis);
if (originalSlug != blog.Slug)
Services.Notifier.Warning(T("Slugs in conflict. \"{0}\" is already set for a previously created blog so this blog now has the slug \"{1}\"",
originalSlug, blog.Slug));
}
}
}
}

View File

@@ -1,19 +1,15 @@
using System;
using System.Linq;
using System.Text.RegularExpressions;
using System.Web.Routing;
using JetBrains.Annotations;
using Orchard.Blogs.Models;
using Orchard.Blogs.Services;
using Orchard.ContentManagement;
using Orchard.ContentManagement.Drivers;
using Orchard.Core.Common.Models;
using Orchard.Core.Common.Services;
using Orchard.Localization;
using Orchard.UI.Notify;
namespace Orchard.Blogs.Drivers {
[UsedImplicitly]
[UsedImplicitly]
public class BlogPostDriver : ContentItemDriver<BlogPost> {
public IOrchardServices Services { get; set; }
private readonly IBlogPostService _blogPostService;
@@ -78,54 +74,11 @@ namespace Orchard.Blogs.Drivers {
protected override DriverResult Editor(BlogPost post, IUpdateModel updater) {
updater.TryUpdateModel(post, Prefix, null, null);
//todo: (heskew) something better needs to be done with this...still feels shoehorned in here
ProcessSlug(post, updater);
DateTime scheduled;
if (DateTime.TryParse(string.Format("{0} {1}", post.ScheduledPublishUtcDate, post.ScheduledPublishUtcTime), out scheduled))
post.ScheduledPublishUtc = scheduled;
return Editor(post);
}
private void ProcessSlug(BlogPost post, IUpdateModel updater) {
_routableService.FillSlug(post.As<RoutableAspect>());
if (string.IsNullOrEmpty(post.Slug)) {
return;
// OR
//updater.AddModelError("Routable.Slug", T("The slug is required.").ToString());
//return;
}
if (!Regex.IsMatch(post.Slug, @"^[^/:?#\[\]@!$&'()*+,;=\s]+$")) {
//todo: (heskew) get rid of the hard-coded prefix
updater.AddModelError("Routable.Slug", T("Please do not use any of the following characters in your slugs: \"/\", \":\", \"?\", \"#\", \"[\", \"]\", \"@\", \"!\", \"$\", \"&\", \"'\", \"(\", \")\", \"*\", \"+\", \",\", \";\", \"=\". No spaces are allowed (please use dashes or underscores instead).").ToString());
return;
}
var slugsLikeThis = _blogPostService.Get(post.Blog, VersionOptions.Published).Where(
p => p.Slug.StartsWith(post.Slug, StringComparison.OrdinalIgnoreCase) &&
p.Id != post.Id).Select(p => p.Slug);
//todo: (heskew) need better messages
if (slugsLikeThis.Count() > 0) {
//todo: (heskew) need better messages
Services.Notifier.Warning(T("A different blog post is already published with this same slug."));
if (post.ContentItem.VersionRecord == null || post.ContentItem.VersionRecord.Published)
{
var originalSlug = post.Slug;
//todo: (heskew) make auto-uniqueness optional
post.Slug = _routableService.GenerateUniqueSlug(post.Slug, slugsLikeThis);
if (originalSlug != post.Slug)
Services.Notifier.Warning(T("Slugs in conflict. \"{0}\" is already set for a previously created blog post so this post now has the slug \"{1}\"",
originalSlug, post.Slug));
}
}
}
}
}

View File

@@ -16,12 +16,10 @@ namespace Orchard.Blogs.Handlers {
[UsedImplicitly]
public class BlogPostHandler : ContentHandler {
private readonly IBlogPostService _blogPostService;
private readonly IRoutableService _routableService;
private readonly IOrchardServices _orchardServices;
public BlogPostHandler(IBlogService blogService, IBlogPostService blogPostService, IRoutableService routableService, IOrchardServices orchardServices, RequestContext requestContext) {
public BlogPostHandler(IBlogService blogService, IBlogPostService blogPostService, IOrchardServices orchardServices, RequestContext requestContext) {
_blogPostService = blogPostService;
_routableService = routableService;
_orchardServices = orchardServices;
T = NullLocalizer.Instance;
@@ -63,8 +61,6 @@ namespace Orchard.Blogs.Handlers {
OnVersioned<BlogPost>((context, bp1, bp2) => updateBlogPostCount(bp2.Blog));
OnRemoved<BlogPost>((context, bp) => updateBlogPostCount(bp.Blog));
OnPublished<BlogPost>((context, bp) => ProcessSlug(bp));
OnRemoved<Blog>(
(context, b) =>
blogPostService.Get(context.ContentItem.As<Blog>()).ToList().ForEach(
@@ -72,23 +68,5 @@ namespace Orchard.Blogs.Handlers {
}
Localizer T { get; set; }
private void ProcessSlug(BlogPost post) {
_routableService.FillSlug(post.As<RoutableAspect>());
var slugsLikeThis = _blogPostService.Get(post.Blog, VersionOptions.Published).Where(
p => p.Slug.StartsWith(post.Slug, StringComparison.OrdinalIgnoreCase) &&
p.Id != post.Id).Select(p => p.Slug);
//todo: (heskew) need better messages
if (slugsLikeThis.Count() > 0) {
//todo: (heskew) need better messages
var originalSlug = post.Slug;
post.Slug = _routableService.GenerateUniqueSlug(post.Slug, slugsLikeThis);
if (originalSlug != post.Slug)
_orchardServices.Notifier.Warning(T("A different blog post is already published with this same slug ({0}) so a unique slug ({1}) was generated for this post.", originalSlug, post.Slug));
}
}
}
}

View File

@@ -9,6 +9,7 @@ using Orchard.Localization;
using Orchard.Security;
using Orchard.Settings;
using Orchard.UI.Notify;
using Orchard.Utility.Extensions;
namespace Orchard.Comments.Controllers {
public class CommentController : Controller {
@@ -42,7 +43,15 @@ namespace Orchard.Comments.Controllers {
var viewModel = new CommentsCreateViewModel();
try {
UpdateModel(viewModel);
// UpdateModel(viewModel);
if(!TryUpdateModel(viewModel)) {
if (Request.Form["Name"].IsNullOrEmptyTrimmed()) {
_notifier.Error("You must provide a Name in order to comment");
}
return Redirect(returnUrl);
}
var context = new CreateCommentContext {
Author = viewModel.Name,
@@ -63,7 +72,8 @@ namespace Orchard.Comments.Controllers {
}
catch (Exception exception) {
_notifier.Error(T("Creating Comment failed: " + exception.Message));
return View(viewModel);
// return View(viewModel);
return Redirect(returnUrl);
}
}
}

View File

@@ -76,74 +76,11 @@ namespace Orchard.Pages.Drivers {
protected override DriverResult Editor(Page page, IUpdateModel updater) {
updater.TryUpdateModel(page, Prefix, null, null);
//todo: (heskew) something better needs to be done with this...still feels shoehorned in here
ProcessSlug(page, updater);
DateTime scheduled;
if (DateTime.TryParse(string.Format("{0} {1}", page.ScheduledPublishUtcDate, page.ScheduledPublishUtcTime), out scheduled))
page.ScheduledPublishUtc = scheduled;
return Editor(page);
}
private void ProcessSlug(Page page, IUpdateModel updater) {
_routableService.FillSlug(page.As<RoutableAspect>(), Slugify);
if (string.IsNullOrEmpty(page.Slug)) {
return;
// OR
//updater.AddModelError("Routable.Slug", T("The slug is required.").ToString());
//return;
}
if (!Regex.IsMatch(page.Slug, @"^[^/:?#\[\]@!$&'()*+,;=\s](?(?=/)/[^/:?#\[\]@!$&'()*+,;=\s]|[^:?#\[\]@!$&'()*+,;=\s])*$")) {
updater.AddModelError("Routable.Slug", T("Please do not use any of the following characters in your slugs: \":\", \"?\", \"#\", \"[\", \"]\", \"@\", \"!\", \"$\", \"&\", \"'\", \"(\", \")\", \"*\", \"+\", \",\", \";\", \"=\". No spaces are allowed (please use dashes or underscores instead).").ToString());
return;
}
var slugsLikeThis = _pageService.Get(PageStatus.Published).Where(
p => p.Slug.StartsWith(page.Slug, StringComparison.OrdinalIgnoreCase) &&
p.Id != page.Id).Select(p => p.Slug);
if (slugsLikeThis.Count() > 0) {
//todo: (heskew) need better messages
Services.Notifier.Warning(T("A different page is already published with this same slug."));
if (page.ContentItem.VersionRecord == null || page.ContentItem.VersionRecord.Published) {
var originalSlug = page.Slug;
//todo: (heskew) make auto-uniqueness optional
page.Slug = _routableService.GenerateUniqueSlug(page.Slug, slugsLikeThis);
//todo: (heskew) need better messages
if (originalSlug != page.Slug)
Services.Notifier.Warning(T("Slugs in conflict. \"{0}\" is already set for a previously published page so this page now has the slug \"{1}\"",
originalSlug, page.Slug));
}
}
}
private static string Slugify(string value)
{
if (!string.IsNullOrEmpty(value))
{
//todo: (heskew) improve - just doing multi-pass regex replaces for now with the simple rules of
// (1) can't begin with a '/', (2) can't have adjacent '/'s and (3) can't have these characters
var startsoffbad = new Regex(@"^[\s/]+");
var slashhappy = new Regex("/{2,}");
var dissallowed = new Regex(@"[:?#\[\]@!$&'()*+,;=\s]+");
value = startsoffbad.Replace(value, "-");
value = slashhappy.Replace(value, "/");
value = dissallowed.Replace(value, "-");
value = value.Trim('-');
if (value.Length > 1000)
value = value.Substring(0, 1000);
}
return value;
}
}
}

View File

@@ -15,12 +15,10 @@ namespace Orchard.Pages.Handlers {
[UsedImplicitly]
public class PageHandler : ContentHandler {
private readonly IPageService _pageService;
private readonly IRoutableService _routableService;
private readonly IOrchardServices _orchardServices;
public PageHandler(IPageService pageService, IRoutableService routableService, IOrchardServices orchardServices) {
public PageHandler(IPageService pageService, IOrchardServices orchardServices) {
_pageService = pageService;
_routableService = routableService;
_orchardServices = orchardServices;
T = NullLocalizer.Instance;
@@ -31,27 +29,8 @@ namespace Orchard.Pages.Handlers {
Filters.Add(new ActivatingFilter<BodyAspect>(PageDriver.ContentType.Name));
OnLoaded<Page>((context, p) => p.ScheduledPublishUtc = _pageService.GetScheduledPublishUtc(p));
OnPublished<Page>((context, p) => ProcessSlug(p));
}
Localizer T { get; set; }
private void ProcessSlug(Page page) {
_routableService.FillSlug(page.As<RoutableAspect>());
var slugsLikeThis = _pageService.Get(PageStatus.Published).Where(
p => p.Slug.StartsWith(page.Slug, StringComparison.OrdinalIgnoreCase) &&
p.Id != page.Id).Select(p => p.Slug);
//todo: (heskew) need better messages
if (slugsLikeThis.Count() > 0) {
//todo: (heskew) need better messages
var originalSlug = page.Slug;
page.Slug = _routableService.GenerateUniqueSlug(page.Slug, slugsLikeThis);
if (originalSlug != page.Slug)
_orchardServices.Notifier.Warning(T("A different page is already published with this same slug ({0}) so a unique slug ({1}) was generated for this page.", originalSlug, page.Slug));
}
}
}
}

View File

@@ -82,6 +82,7 @@ namespace Orchard.Setup.Controllers {
"Orchard.Themes",
"Orchard.MultiTenancy",
"Orchard.Pages",
"Orchard.Blogs",
"Orchard.Comments"};
var setupContext = new SetupContext {

View File

@@ -1,6 +1,6 @@
using System;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using Orchard.Localization;
using System.Security.Principal;
using System.Web.Mvc;
using System.Web.Security;
@@ -26,9 +26,11 @@ namespace Orchard.Users.Controllers {
_membershipService = membershipService;
_userService = userService;
Logger = NullLogger.Instance;
T = NullLocalizer.Instance;
}
public ILogger Logger { get; set; }
public Localizer T { get; set; }
public ActionResult AccessDenied() {
var returnUrl = Request.QueryString["ReturnUrl"];
@@ -55,8 +57,8 @@ namespace Orchard.Users.Controllers {
[HttpPost]
[SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings",
Justification = "Needs to take same parameter type as Controller.Redirect()")]
public ActionResult LogOn(string userName, string password, bool rememberMe) {
var user = ValidateLogOn(userName, password);
public ActionResult LogOn(string userNameOrEmail, string password, bool rememberMe) {
var user = ValidateLogOn(userNameOrEmail, password);
if (!ModelState.IsValid) {
return View("LogOn", new LogOnViewModel {Title = "Log On"});
}
@@ -98,7 +100,7 @@ namespace Orchard.Users.Controllers {
return Redirect("~/");
}
else {
ModelState.AddModelError("_FORM", ErrorCodeToString(/*createStatus*/MembershipCreateStatus.ProviderError));
ModelState.AddModelError("_FORM", T(ErrorCodeToString(/*createStatus*/MembershipCreateStatus.ProviderError)));
}
}
@@ -133,12 +135,12 @@ namespace Orchard.Users.Controllers {
}
else {
ModelState.AddModelError("_FORM",
"The current password is incorrect or the new password is invalid.");
T("The current password is incorrect or the new password is invalid."));
return ChangePassword();
}
}
catch {
ModelState.AddModelError("_FORM", "The current password is incorrect or the new password is invalid.");
ModelState.AddModelError("_FORM", T("The current password is incorrect or the new password is invalid."));
return ChangePassword();
}
}
@@ -157,32 +159,29 @@ namespace Orchard.Users.Controllers {
private bool ValidateChangePassword(string currentPassword, string newPassword, string confirmPassword) {
if (String.IsNullOrEmpty(currentPassword)) {
ModelState.AddModelError("currentPassword", "You must specify a current password.");
ModelState.AddModelError("currentPassword", T("You must specify a current password."));
}
if (newPassword == null || newPassword.Length < MinPasswordLength) {
ModelState.AddModelError("newPassword",
String.Format(CultureInfo.CurrentCulture,
"You must specify a new password of {0} or more characters.",
MinPasswordLength));
ModelState.AddModelError("newPassword", T("You must specify a new password of {0} or more characters.", MinPasswordLength));
}
if (!String.Equals(newPassword, confirmPassword, StringComparison.Ordinal)) {
ModelState.AddModelError("_FORM", "The new password and confirmation password do not match.");
ModelState.AddModelError("_FORM", T("The new password and confirmation password do not match."));
}
return ModelState.IsValid;
}
private IUser ValidateLogOn(string userName, string password) {
if (String.IsNullOrEmpty(userName)) {
ModelState.AddModelError("username", "You must specify a username.");
private IUser ValidateLogOn(string userNameOrEmail, string password) {
if (String.IsNullOrEmpty(userNameOrEmail)) {
ModelState.AddModelError("userNameOrEmail", T("You must specify a username or e-mail."));
}
if (String.IsNullOrEmpty(password)) {
ModelState.AddModelError("password", "You must specify a password.");
ModelState.AddModelError("password", T("You must specify a password."));
}
var user = _membershipService.ValidateUser(userName, password);
var user = _membershipService.ValidateUser(userNameOrEmail, password);
if (user == null) {
ModelState.AddModelError("_FORM", "The username or password provided is incorrect.");
ModelState.AddModelError("_FORM", T("The username or e-mail or password provided is incorrect."));
}
return user;
@@ -190,23 +189,20 @@ namespace Orchard.Users.Controllers {
private bool ValidateRegistration(string userName, string email, string password, string confirmPassword) {
if (String.IsNullOrEmpty(userName)) {
ModelState.AddModelError("username", "You must specify a username.");
ModelState.AddModelError("username", T("You must specify a username."));
}
if (String.IsNullOrEmpty(email)) {
ModelState.AddModelError("email", "You must specify an email address.");
ModelState.AddModelError("email", T("You must specify an email address."));
}
string userUnicityMessage = _userService.VerifyUserUnicity(userName, email);
if (userUnicityMessage != null) {
ModelState.AddModelError("userExists", userUnicityMessage);
ModelState.AddModelError("userExists", T(userUnicityMessage));
}
if (password == null || password.Length < MinPasswordLength) {
ModelState.AddModelError("password",
String.Format(CultureInfo.CurrentCulture,
"You must specify a password of {0} or more characters.",
MinPasswordLength));
ModelState.AddModelError("password", T("You must specify a password of {0} or more characters.", MinPasswordLength));
}
if (!String.Equals(password, confirmPassword, StringComparison.Ordinal)) {
ModelState.AddModelError("_FORM", "The new password and confirmation password do not match.");
ModelState.AddModelError("_FORM", T("The new password and confirmation password do not match."));
}
return ModelState.IsValid;
}

View File

@@ -1,7 +1,7 @@
using System.Linq;
using System.Web.Mvc;
using Orchard.Localization;
using Orchard.ContentManagement;
using Orchard.Localization;
using Orchard.Security;
using Orchard.UI.Notify;
using Orchard.Users.Drivers;
@@ -147,6 +147,7 @@ namespace Orchard.Users.Controllers {
bool IUpdateModel.TryUpdateModel<TModel>(TModel model, string prefix, string[] includeProperties, string[] excludeProperties) {
return TryUpdateModel(model, prefix, includeProperties, excludeProperties);
}
public void AddModelError(string key, LocalizedString errorMessage) {
ModelState.AddModelError(key, errorMessage.ToString());
}

View File

@@ -44,6 +44,9 @@ namespace Orchard.Users.Services {
}
public IUser GetUser(string username) {
if(username == null) {
throw new ArgumentNullException("username");
}
var userRecord = _userRepository.Get(x => x.NormalizedUserName == username.ToLower());
if (userRecord == null) {
return null;
@@ -51,8 +54,10 @@ namespace Orchard.Users.Services {
return _contentManager.Get<IUser>(userRecord.Id);
}
public IUser ValidateUser(string username, string password) {
var userRecord = _userRepository.Get(x => x.NormalizedUserName == username.ToLower());
public IUser ValidateUser(string userNameOrEmail, string password) {
var userRecord = _userRepository.Get(x => x.NormalizedUserName == userNameOrEmail.ToLower());
if(userRecord == null)
userRecord = _userRepository.Get(x => x.Email == userNameOrEmail.ToLower());
if (userRecord == null || ValidatePassword(userRecord, password) == false)
return null;

View File

@@ -8,9 +8,9 @@ using (Html.BeginFormAntiForgeryPost(Url.Action("LogOn", new {ReturnUrl = Reques
<fieldset>
<legend><%=_Encoded("Account Information")%></legend>
<div>
<label for="username"><%=_Encoded("Username:")%></label>
<%= Html.TextBox("username")%>
<%= Html.ValidationMessage("username")%>
<label for="username"><%=_Encoded("Username or Email:")%></label>
<%= Html.TextBox("userNameOrEmail")%>
<%= Html.ValidationMessage("userNameOrEmail")%>
</div>
<div>
<label for="password"><%=_Encoded("Password:")%></label>