mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2026-02-09 09:16:41 +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 */);
|
_authenticationService.SignIn(user, false /* createPersistentCookie */);
|
||||||
|
_userEventHandler.LoggedIn(user);
|
||||||
return this.RedirectLocal(returnUrl);
|
return this.RedirectLocal(returnUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -87,6 +87,12 @@ namespace Orchard.Users.Controllers {
|
|||||||
case UsersOrder.Email:
|
case UsersOrder.Email:
|
||||||
users = users.OrderBy(u => u.Email);
|
users = users.OrderBy(u => u.Email);
|
||||||
break;
|
break;
|
||||||
|
case UsersOrder.CreatedUtc:
|
||||||
|
users = users.OrderBy(u => u.CreatedUtc);
|
||||||
|
break;
|
||||||
|
case UsersOrder.LastLoginUtc:
|
||||||
|
users = users.OrderBy(u => u.LastLoginUtc);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
var results = users
|
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 System;
|
||||||
using Orchard.Data.Migration;
|
using Orchard.ContentManagement.MetaData;
|
||||||
using Orchard.Core.Contents.Extensions;
|
using Orchard.Core.Contents.Extensions;
|
||||||
|
using Orchard.Data.Migration;
|
||||||
|
|
||||||
namespace Orchard.Users {
|
namespace Orchard.Users {
|
||||||
public class UsersDataMigration : DataMigrationImpl {
|
public class UsersDataMigration : DataMigrationImpl {
|
||||||
@@ -19,9 +20,13 @@ namespace Orchard.Users {
|
|||||||
.Column<string>("RegistrationStatus", c => c.WithDefault("Approved"))
|
.Column<string>("RegistrationStatus", c => c.WithDefault("Approved"))
|
||||||
.Column<string>("EmailStatus", c => c.WithDefault("Approved"))
|
.Column<string>("EmailStatus", c => c.WithDefault("Approved"))
|
||||||
.Column<string>("EmailChallengeToken")
|
.Column<string>("EmailChallengeToken")
|
||||||
|
.Column<DateTime>("CreatedUtc")
|
||||||
|
.Column<DateTime>("LastLoginUtc")
|
||||||
);
|
);
|
||||||
|
|
||||||
return 1;
|
ContentDefinitionManager.AlterTypeDefinition("User", cfg => cfg.Creatable(false));
|
||||||
|
|
||||||
|
return 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int UpdateFrom1() {
|
public int UpdateFrom1() {
|
||||||
@@ -29,5 +34,15 @@ namespace Orchard.Users {
|
|||||||
|
|
||||||
return 2;
|
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.ContentManagement;
|
||||||
using Orchard.Security;
|
using Orchard.Security;
|
||||||
|
|
||||||
namespace Orchard.Users.Models {
|
namespace Orchard.Users.Models {
|
||||||
public sealed class UserPart : ContentPart<UserPartRecord>, IUser {
|
public sealed class UserPart : ContentPart<UserPartRecord>, IUser {
|
||||||
public const string EmailPattern =
|
public const string EmailPattern =
|
||||||
@"^(?![\.@])(""([^""\r\\]|\\[""\r\\])*""|([-a-z0-9!#$%&'*+/=?^_`{|}~]|(?<!\.)\.)*)(?<!\.)"
|
@"^(?![\.@])(""([^""\r\\]|\\[""\r\\])*""|([-a-z0-9!#$%&'*+/=?^_`{|}~]|(?<!\.)\.)*)(?<!\.)"
|
||||||
+ @"@([a-z0-9][\w-]*\.)+[a-z]{2,}$";
|
+ @"@([a-z0-9][\w-]*\.)+[a-z]{2,}$";
|
||||||
|
|
||||||
public const int MaxUserNameLength = 255;
|
public const int MaxUserNameLength = 255;
|
||||||
public const int MaxEmailLength = 255;
|
public const int MaxEmailLength = 255;
|
||||||
|
|
||||||
@@ -60,5 +61,15 @@ namespace Orchard.Users.Models {
|
|||||||
get { return Retrieve(x => x.EmailStatus); }
|
get { return Retrieve(x => x.EmailStatus); }
|
||||||
set { Store(x => x.EmailStatus, value); }
|
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 System.Web.Security;
|
||||||
using Orchard.ContentManagement.Records;
|
using Orchard.ContentManagement.Records;
|
||||||
|
|
||||||
@@ -15,5 +16,7 @@ namespace Orchard.Users.Models {
|
|||||||
public virtual UserStatus RegistrationStatus { get; set; }
|
public virtual UserStatus RegistrationStatus { get; set; }
|
||||||
public virtual UserStatus EmailStatus { get; set; }
|
public virtual UserStatus EmailStatus { get; set; }
|
||||||
public virtual string EmailChallengeToken { 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 IShapeFactory _shapeFactory;
|
||||||
private readonly IShapeDisplay _shapeDisplay;
|
private readonly IShapeDisplay _shapeDisplay;
|
||||||
private readonly IAppConfigurationAccessor _appConfigurationAccessor;
|
private readonly IAppConfigurationAccessor _appConfigurationAccessor;
|
||||||
|
private readonly IClock _clock;
|
||||||
|
|
||||||
public MembershipService(
|
public MembershipService(
|
||||||
IOrchardServices orchardServices,
|
IOrchardServices orchardServices,
|
||||||
@@ -45,6 +46,7 @@ namespace Orchard.Users.Services {
|
|||||||
_shapeFactory = shapeFactory;
|
_shapeFactory = shapeFactory;
|
||||||
_shapeDisplay = shapeDisplay;
|
_shapeDisplay = shapeDisplay;
|
||||||
_appConfigurationAccessor = appConfigurationAccessor;
|
_appConfigurationAccessor = appConfigurationAccessor;
|
||||||
|
_clock = clock;
|
||||||
Logger = NullLogger.Instance;
|
Logger = NullLogger.Instance;
|
||||||
T = NullLocalizer.Instance;
|
T = NullLocalizer.Instance;
|
||||||
}
|
}
|
||||||
@@ -69,6 +71,7 @@ namespace Orchard.Users.Services {
|
|||||||
user.Email = createUserParams.Email;
|
user.Email = createUserParams.Email;
|
||||||
user.NormalizedUserName = createUserParams.Username.ToLowerInvariant();
|
user.NormalizedUserName = createUserParams.Username.ToLowerInvariant();
|
||||||
user.HashAlgorithm = PBKDF2;
|
user.HashAlgorithm = PBKDF2;
|
||||||
|
user.CreatedUtc = _clock.UtcNow;
|
||||||
SetPassword(user, createUserParams.Password);
|
SetPassword(user, createUserParams.Password);
|
||||||
|
|
||||||
if ( registrationSettings != null ) {
|
if ( registrationSettings != null ) {
|
||||||
|
|||||||
@@ -23,7 +23,9 @@ namespace Orchard.Users.ViewModels {
|
|||||||
|
|
||||||
public enum UsersOrder {
|
public enum UsersOrder {
|
||||||
Name,
|
Name,
|
||||||
Email
|
Email,
|
||||||
|
CreatedUtc,
|
||||||
|
LastLoginUtc
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum UsersFilter {
|
public enum UsersFilter {
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
@model Orchard.Users.ViewModels.UsersIndexViewModel
|
@model Orchard.Users.ViewModels.UsersIndexViewModel
|
||||||
|
@using Orchard.Core.Shapes;
|
||||||
@using Orchard.Users.Models;
|
@using Orchard.Users.Models;
|
||||||
@using Orchard.Users.ViewModels;
|
@using Orchard.Users.ViewModels;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@{
|
@{
|
||||||
var userIndex = 0;
|
var userIndex = 0;
|
||||||
|
|
||||||
@@ -36,6 +39,8 @@
|
|||||||
<select id="sortResults" name="@Html.NameOf(m => m.Options.Order)">
|
<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.Name, T("Name").ToString())
|
||||||
@Html.SelectOption(Model.Options.Order, UsersOrder.Email, T("Email").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>
|
</select>
|
||||||
|
|
||||||
<button type="submit" name="submit.Filter" value="@T("Filter")">@T("Filter")</button>
|
<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("Name")</th>
|
||||||
<th scope="col">@T("Email")</th>
|
<th scope="col">@T("Email")</th>
|
||||||
<th scope="col">@T("Actions")</th>
|
<th scope="col">@T("Actions")</th>
|
||||||
|
<th scope="col">@T("Creation Time")</th>
|
||||||
|
<th scope="col">@T("Last Login Time")</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
@foreach (var entry in Model.Users) {
|
@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" })
|
@Html.ActionLink(T("Send challenge E-mail").ToString(), "SendChallengeEmail", new { entry.User.Id }, new { itemprop = "UnsafeUrl" })
|
||||||
}
|
}
|
||||||
</td>
|
</td>
|
||||||
|
<td>
|
||||||
|
@Display(New.DateTimeRelative(dateTimeUtc: entry.User.CreatedUtc))
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
@Display(New.DateTimeRelative(dateTimeUtc: entry.User.LastLoginUtc))
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
userIndex++;
|
userIndex++;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user