mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-10-15 19:54:57 +08:00
Registration and last login date are now tracked for users, fixes #1296
This commit is contained in:
@@ -155,6 +155,7 @@ namespace Orchard.Users.Controllers {
|
||||
}
|
||||
|
||||
_authenticationService.SignIn(user, false /* createPersistentCookie */);
|
||||
_userEventHandler.LoggedIn(user);
|
||||
return this.RedirectLocal(returnUrl);
|
||||
}
|
||||
|
||||
|
@@ -87,6 +87,12 @@ namespace Orchard.Users.Controllers {
|
||||
case UsersOrder.Email:
|
||||
users = users.OrderBy(u => u.Email);
|
||||
break;
|
||||
case UsersOrder.CreatedUtc:
|
||||
users = users.OrderBy(u => u.CreatedUtc);
|
||||
break;
|
||||
case UsersOrder.LastLoginUtc:
|
||||
users = users.OrderBy(u => u.LastLoginUtc);
|
||||
break;
|
||||
}
|
||||
|
||||
var results = users
|
||||
|
@@ -0,0 +1,42 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.Security;
|
||||
using Orchard.Services;
|
||||
using Orchard.Users.Models;
|
||||
|
||||
namespace Orchard.Users.Events {
|
||||
public class LoginUserEventHandler : IUserEventHandler {
|
||||
private readonly IClock _clock;
|
||||
|
||||
public LoginUserEventHandler(IClock clock) {
|
||||
_clock = clock;
|
||||
}
|
||||
|
||||
public void Creating(UserContext context) { }
|
||||
|
||||
public void Created(UserContext context) { }
|
||||
|
||||
public void LoggedIn(IUser user) {
|
||||
user.As<UserPart>().LastLoginUtc = _clock.UtcNow;
|
||||
}
|
||||
|
||||
public void LoggedOut(IUser user) { }
|
||||
|
||||
public void AccessDenied(IUser user) { }
|
||||
|
||||
public void ChangedPassword(IUser user) { }
|
||||
|
||||
public void SentChallengeEmail(IUser user) { }
|
||||
|
||||
public void ConfirmedEmail(IUser user) { }
|
||||
|
||||
public void Approved(IUser user) { }
|
||||
|
||||
public void LoggingIn(string userNameOrEmail, string password) { }
|
||||
|
||||
public void LogInFailed(string userNameOrEmail, string password) { }
|
||||
}
|
||||
}
|
@@ -1,6 +1,7 @@
|
||||
using Orchard.ContentManagement.MetaData;
|
||||
using Orchard.Data.Migration;
|
||||
using System;
|
||||
using Orchard.ContentManagement.MetaData;
|
||||
using Orchard.Core.Contents.Extensions;
|
||||
using Orchard.Data.Migration;
|
||||
|
||||
namespace Orchard.Users {
|
||||
public class UsersDataMigration : DataMigrationImpl {
|
||||
@@ -19,9 +20,13 @@ namespace Orchard.Users {
|
||||
.Column<string>("RegistrationStatus", c => c.WithDefault("Approved"))
|
||||
.Column<string>("EmailStatus", c => c.WithDefault("Approved"))
|
||||
.Column<string>("EmailChallengeToken")
|
||||
.Column<DateTime>("CreatedUtc")
|
||||
.Column<DateTime>("LastLoginUtc")
|
||||
);
|
||||
|
||||
return 1;
|
||||
ContentDefinitionManager.AlterTypeDefinition("User", cfg => cfg.Creatable(false));
|
||||
|
||||
return 3;
|
||||
}
|
||||
|
||||
public int UpdateFrom1() {
|
||||
@@ -29,5 +34,15 @@ namespace Orchard.Users {
|
||||
|
||||
return 2;
|
||||
}
|
||||
|
||||
public int UpdateFrom2() {
|
||||
SchemaBuilder.AlterTable("UserPartRecord",
|
||||
table => {
|
||||
table.AddColumn<DateTime>("CreatedUtc");
|
||||
table.AddColumn<DateTime>("LastLoginUtc");
|
||||
});
|
||||
|
||||
return 3;
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,13 +1,14 @@
|
||||
using System.Web.Security;
|
||||
using System;
|
||||
using System.Web.Security;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.Security;
|
||||
|
||||
namespace Orchard.Users.Models {
|
||||
public sealed class UserPart : ContentPart<UserPartRecord>, IUser {
|
||||
public const string EmailPattern =
|
||||
public const string EmailPattern =
|
||||
@"^(?![\.@])(""([^""\r\\]|\\[""\r\\])*""|([-a-z0-9!#$%&'*+/=?^_`{|}~]|(?<!\.)\.)*)(?<!\.)"
|
||||
+ @"@([a-z0-9][\w-]*\.)+[a-z]{2,}$";
|
||||
|
||||
|
||||
public const int MaxUserNameLength = 255;
|
||||
public const int MaxEmailLength = 255;
|
||||
|
||||
@@ -60,5 +61,15 @@ namespace Orchard.Users.Models {
|
||||
get { return Retrieve(x => x.EmailStatus); }
|
||||
set { Store(x => x.EmailStatus, value); }
|
||||
}
|
||||
|
||||
public DateTime? CreatedUtc {
|
||||
get { return Retrieve(x => x.CreatedUtc); }
|
||||
set { Store(x => x.CreatedUtc, value); }
|
||||
}
|
||||
|
||||
public DateTime? LastLoginUtc {
|
||||
get { return Retrieve(x => x.LastLoginUtc); }
|
||||
set { Store(x => x.LastLoginUtc, value); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,3 +1,4 @@
|
||||
using System;
|
||||
using System.Web.Security;
|
||||
using Orchard.ContentManagement.Records;
|
||||
|
||||
@@ -15,5 +16,7 @@ namespace Orchard.Users.Models {
|
||||
public virtual UserStatus RegistrationStatus { get; set; }
|
||||
public virtual UserStatus EmailStatus { get; set; }
|
||||
public virtual string EmailChallengeToken { get; set; }
|
||||
public virtual DateTime? CreatedUtc { get; set; }
|
||||
public virtual DateTime? LastLoginUtc { get; set; }
|
||||
}
|
||||
}
|
@@ -28,6 +28,7 @@ namespace Orchard.Users.Services {
|
||||
private readonly IShapeFactory _shapeFactory;
|
||||
private readonly IShapeDisplay _shapeDisplay;
|
||||
private readonly IAppConfigurationAccessor _appConfigurationAccessor;
|
||||
private readonly IClock _clock;
|
||||
|
||||
public MembershipService(
|
||||
IOrchardServices orchardServices,
|
||||
@@ -45,6 +46,7 @@ namespace Orchard.Users.Services {
|
||||
_shapeFactory = shapeFactory;
|
||||
_shapeDisplay = shapeDisplay;
|
||||
_appConfigurationAccessor = appConfigurationAccessor;
|
||||
_clock = clock;
|
||||
Logger = NullLogger.Instance;
|
||||
T = NullLocalizer.Instance;
|
||||
}
|
||||
@@ -69,6 +71,7 @@ namespace Orchard.Users.Services {
|
||||
user.Email = createUserParams.Email;
|
||||
user.NormalizedUserName = createUserParams.Username.ToLowerInvariant();
|
||||
user.HashAlgorithm = PBKDF2;
|
||||
user.CreatedUtc = _clock.UtcNow;
|
||||
SetPassword(user, createUserParams.Password);
|
||||
|
||||
if ( registrationSettings != null ) {
|
||||
|
@@ -23,7 +23,9 @@ namespace Orchard.Users.ViewModels {
|
||||
|
||||
public enum UsersOrder {
|
||||
Name,
|
||||
Email
|
||||
Email,
|
||||
CreatedUtc,
|
||||
LastLoginUtc
|
||||
}
|
||||
|
||||
public enum UsersFilter {
|
||||
|
@@ -1,7 +1,10 @@
|
||||
@model Orchard.Users.ViewModels.UsersIndexViewModel
|
||||
@using Orchard.Core.Shapes;
|
||||
@using Orchard.Users.Models;
|
||||
@using Orchard.Users.ViewModels;
|
||||
|
||||
|
||||
|
||||
@{
|
||||
var userIndex = 0;
|
||||
|
||||
@@ -36,6 +39,8 @@
|
||||
<select id="sortResults" name="@Html.NameOf(m => m.Options.Order)">
|
||||
@Html.SelectOption(Model.Options.Order, UsersOrder.Name, T("Name").ToString())
|
||||
@Html.SelectOption(Model.Options.Order, UsersOrder.Email, T("Email").ToString())
|
||||
@Html.SelectOption(Model.Options.Order, UsersOrder.CreatedUtc, T("Creation Time").ToString())
|
||||
@Html.SelectOption(Model.Options.Order, UsersOrder.LastLoginUtc, T("Last Login Time").ToString())
|
||||
</select>
|
||||
|
||||
<button type="submit" name="submit.Filter" value="@T("Filter")">@T("Filter")</button>
|
||||
@@ -48,6 +53,8 @@
|
||||
<th scope="col">@T("Name")</th>
|
||||
<th scope="col">@T("Email")</th>
|
||||
<th scope="col">@T("Actions")</th>
|
||||
<th scope="col">@T("Creation Time")</th>
|
||||
<th scope="col">@T("Last Login Time")</th>
|
||||
</tr>
|
||||
</thead>
|
||||
@foreach (var entry in Model.Users) {
|
||||
@@ -79,6 +86,12 @@
|
||||
@Html.ActionLink(T("Send challenge E-mail").ToString(), "SendChallengeEmail", new { entry.User.Id }, new { itemprop = "UnsafeUrl" })
|
||||
}
|
||||
</td>
|
||||
<td>
|
||||
@Display(New.DateTimeRelative(dateTimeUtc: entry.User.CreatedUtc))
|
||||
</td>
|
||||
<td>
|
||||
@Display(New.DateTimeRelative(dateTimeUtc: entry.User.LastLoginUtc))
|
||||
</td>
|
||||
</tr>
|
||||
userIndex++;
|
||||
}
|
||||
|
Reference in New Issue
Block a user