Fixes issue with email confirmation date, adds invite date, adds user state counts
This commit is contained in:
@@ -15,6 +15,7 @@ namespace Umbraco.Core.Models.Identity
|
||||
config.CreateMap<IUser, BackOfficeIdentityUser>()
|
||||
.ForMember(user => user.LastLoginDateUtc, expression => expression.MapFrom(user => user.LastLoginDate.ToUniversalTime()))
|
||||
.ForMember(user => user.Email, expression => expression.MapFrom(user => user.Email))
|
||||
.ForMember(user => user.EmailConfirmed, expression => expression.MapFrom(user => user.EmailConfirmedDate.HasValue))
|
||||
.ForMember(user => user.Id, expression => expression.MapFrom(user => user.Id))
|
||||
.ForMember(user => user.LockoutEndDateUtc, expression => expression.MapFrom(user => user.IsLockedOut ? DateTime.MaxValue.ToUniversalTime() : (DateTime?)null))
|
||||
.ForMember(user => user.UserName, expression => expression.MapFrom(user => user.Username))
|
||||
|
||||
@@ -19,6 +19,7 @@ namespace Umbraco.Core.Models.Membership
|
||||
string Language { get; set; }
|
||||
|
||||
DateTime? EmailConfirmedDate { get; set; }
|
||||
DateTime? InvitedDate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the groups that user is part of
|
||||
|
||||
@@ -104,6 +104,7 @@ namespace Umbraco.Core.Models.Membership
|
||||
|
||||
private string _username;
|
||||
private DateTime? _emailConfirmedDate;
|
||||
private DateTime? _invitedDate;
|
||||
private string _email;
|
||||
private string _rawPasswordValue;
|
||||
private IEnumerable<string> _allowedSections;
|
||||
@@ -140,6 +141,7 @@ namespace Umbraco.Core.Models.Membership
|
||||
public readonly PropertyInfo IsApprovedSelector = ExpressionHelper.GetPropertyInfo<User, bool>(x => x.IsApproved);
|
||||
public readonly PropertyInfo LanguageSelector = ExpressionHelper.GetPropertyInfo<User, string>(x => x.Language);
|
||||
public readonly PropertyInfo EmailConfirmedDateSelector = ExpressionHelper.GetPropertyInfo<User, DateTime?>(x => x.EmailConfirmedDate);
|
||||
public readonly PropertyInfo InvitedDateSelector = ExpressionHelper.GetPropertyInfo<User, DateTime?>(x => x.InvitedDate);
|
||||
|
||||
public readonly PropertyInfo DefaultToLiveEditingSelector = ExpressionHelper.GetPropertyInfo<User, bool>(x => x.DefaultToLiveEditing);
|
||||
|
||||
@@ -168,6 +170,12 @@ namespace Umbraco.Core.Models.Membership
|
||||
set { SetPropertyValueAndDetectChanges(value, ref _emailConfirmedDate, Ps.Value.EmailConfirmedDateSelector); }
|
||||
}
|
||||
[DataMember]
|
||||
public DateTime? InvitedDate
|
||||
{
|
||||
get { return _invitedDate; }
|
||||
set { SetPropertyValueAndDetectChanges(value, ref _invitedDate, Ps.Value.InvitedDateSelector); }
|
||||
}
|
||||
[DataMember]
|
||||
public string Username
|
||||
{
|
||||
get { return _username; }
|
||||
|
||||
@@ -5,9 +5,10 @@
|
||||
/// </summary>
|
||||
public enum UserState
|
||||
{
|
||||
Active = 0,
|
||||
Disabled = 1,
|
||||
LockedOut = 2,
|
||||
Invited = 3
|
||||
All = 0,
|
||||
Active = 1,
|
||||
Disabled = 2,
|
||||
LockedOut = 3,
|
||||
Invited = 4
|
||||
}
|
||||
}
|
||||
@@ -74,6 +74,10 @@ namespace Umbraco.Core.Models.Rdbms
|
||||
[NullSetting(NullSetting = NullSettings.Null)]
|
||||
public DateTime? EmailConfirmedDate { get; set; }
|
||||
|
||||
[Column("invitedDate")]
|
||||
[NullSetting(NullSetting = NullSettings.Null)]
|
||||
public DateTime? InvitedDate { get; set; }
|
||||
|
||||
[Column("createDate")]
|
||||
[NullSetting(NullSetting = NullSettings.NotNull)]
|
||||
[Constraint(Default = SystemMethods.CurrentDateTime)]
|
||||
|
||||
@@ -34,6 +34,8 @@ namespace Umbraco.Core.Persistence.Factories
|
||||
user.CreateDate = dto.CreateDate;
|
||||
user.UpdateDate = dto.UpdateDate;
|
||||
user.Avatar = dto.Avatar;
|
||||
user.EmailConfirmedDate = dto.EmailConfirmedDate;
|
||||
user.InvitedDate = dto.InvitedDate;
|
||||
|
||||
//on initial construction we don't want to have dirty properties tracked
|
||||
// http://issues.umbraco.org/issue/U4-1946
|
||||
@@ -66,7 +68,8 @@ namespace Umbraco.Core.Persistence.Factories
|
||||
CreateDate = entity.CreateDate,
|
||||
UpdateDate = entity.UpdateDate,
|
||||
Avatar = entity.Avatar,
|
||||
EmailConfirmedDate = entity.EmailConfirmedDate
|
||||
EmailConfirmedDate = entity.EmailConfirmedDate,
|
||||
InvitedDate = entity.InvitedDate
|
||||
};
|
||||
|
||||
foreach (var startNodeId in entity.StartContentIds)
|
||||
|
||||
+3
@@ -25,6 +25,9 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenSevenZe
|
||||
|
||||
if (columns.Any(x => x.TableName.InvariantEquals("umbracoUser") && x.ColumnName.InvariantEquals("emailConfirmedDate")) == false)
|
||||
Create.Column("emailConfirmedDate").OnTable("umbracoUser").AsDateTime().Nullable();
|
||||
|
||||
if (columns.Any(x => x.TableName.InvariantEquals("umbracoUser") && x.ColumnName.InvariantEquals("invitedDate")) == false)
|
||||
Create.Column("invitedDate").OnTable("umbracoUser").AsDateTime().Nullable();
|
||||
}
|
||||
|
||||
public override void Down()
|
||||
|
||||
@@ -56,6 +56,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
IEnumerable<IUser> GetPagedResultsByQuery(IQuery<IUser> query, long pageIndex, int pageSize, out long totalRecords, Expression<Func<IUser, object>> orderBy, Direction orderDirection, string[] userGroups = null, UserState? userState = null, IQuery<IUser> filter = null);
|
||||
|
||||
IProfile GetProfile(string username);
|
||||
IProfile GetProfile(int id);
|
||||
IProfile GetProfile(int id);
|
||||
IDictionary<UserState, int> GetUserStates();
|
||||
}
|
||||
}
|
||||
@@ -75,7 +75,28 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
return null;
|
||||
|
||||
return new UserProfile(dto.Id, dto.UserName);
|
||||
}
|
||||
}
|
||||
|
||||
public IDictionary<UserState, int> GetUserStates()
|
||||
{
|
||||
var sql = @"SELECT
|
||||
(SELECT COUNT(id) FROM umbracoUser) AS CountOfAll,
|
||||
(SELECT COUNT(id) FROM umbracoUser WHERE userDisabled = 0 AND userNoConsole = 0 AND lastLoginDate IS NOT NULL) AS CountOfActive,
|
||||
(SELECT COUNT(id) FROM umbracoUser WHERE userDisabled = 1) AS CountOfDisabled,
|
||||
(SELECT COUNT(id) FROM umbracoUser WHERE userNoConsole = 1) AS CountOfLockedOut,
|
||||
(SELECT COUNT(id) FROM umbracoUser WHERE lastLoginDate IS NULL AND userDisabled = 1 AND invitedDate IS NOT NULL) AS CountOfInvited";
|
||||
|
||||
var result = Database.First<dynamic>(sql);
|
||||
|
||||
return new Dictionary<UserState, int>
|
||||
{
|
||||
{UserState.All, result.CountOfAll},
|
||||
{UserState.Active, result.CountOfActive},
|
||||
{UserState.Disabled, result.CountOfDisabled},
|
||||
{UserState.Invited, result.CountOfInvited},
|
||||
{UserState.LockedOut, result.CountOfLockedOut}
|
||||
};
|
||||
}
|
||||
|
||||
protected override IEnumerable<IUser> PerformGetAll(params int[] ids)
|
||||
{
|
||||
@@ -271,7 +292,8 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
{"createDate", "CreateDate"},
|
||||
{"updateDate", "UpdateDate"},
|
||||
{"avatar", "Avatar"},
|
||||
{"emailConfirmedDate", "EmailConfirmedDate"}
|
||||
{"emailConfirmedDate", "EmailConfirmedDate"},
|
||||
{"invitedDate", "InvitedDate"}
|
||||
};
|
||||
|
||||
//create list of properties that have changed
|
||||
|
||||
@@ -10,6 +10,23 @@ namespace Umbraco.Core.Services
|
||||
/// </summary>
|
||||
public interface IUserService : IMembershipUserService
|
||||
{
|
||||
/// <summary>
|
||||
/// This is basically facets of UserStates key = state, value = count
|
||||
/// </summary>
|
||||
IDictionary<UserState, int> GetUserStates();
|
||||
|
||||
/// <summary>
|
||||
/// Get paged users
|
||||
/// </summary>
|
||||
/// <param name="pageIndex"></param>
|
||||
/// <param name="pageSize"></param>
|
||||
/// <param name="totalRecords"></param>
|
||||
/// <param name="orderBy"></param>
|
||||
/// <param name="orderDirection"></param>
|
||||
/// <param name="userState"></param>
|
||||
/// <param name="userGroups"></param>
|
||||
/// <param name="filter"></param>
|
||||
/// <returns></returns>
|
||||
IEnumerable<IUser> GetAll(long pageIndex, int pageSize, out long totalRecords,
|
||||
string orderBy, Direction orderDirection,
|
||||
UserState? userState = null, string[] userGroups = null, string filter = "");
|
||||
|
||||
@@ -487,7 +487,16 @@ namespace Umbraco.Core.Services
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public IDictionary<UserState, int> GetUserStates()
|
||||
{
|
||||
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
|
||||
{
|
||||
var repository = RepositoryFactory.CreateUserRepository(uow);
|
||||
return repository.GetUserStates();
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<IUser> GetAll(long pageIndex, int pageSize, out long totalRecords, string orderBy, Direction orderDirection, UserState? userState = null, string[] userGroups = null, string filter = "")
|
||||
{
|
||||
|
||||
@@ -392,6 +392,10 @@ namespace Umbraco.Web.Editors
|
||||
|
||||
throw new HttpResponseException(Request.CreateValidationErrorResponse(ModelState));
|
||||
}
|
||||
|
||||
//They've successfully set their password, we can now update their user account to be approved
|
||||
Security.CurrentUser.IsApproved = true;
|
||||
Services.UserService.Save(Security.CurrentUser);
|
||||
|
||||
return Request.CreateResponse(HttpStatusCode.OK);
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Threading.Tasks;
|
||||
using System.Web;
|
||||
using System.Web.Http;
|
||||
@@ -196,7 +197,7 @@ namespace Umbraco.Web.Editors
|
||||
/// <param name="userGroups"></param>
|
||||
/// <param name="filter"></param>
|
||||
/// <returns></returns>
|
||||
public PagedResult<UserDisplay> GetPagedUsers(
|
||||
public PagedUserResult GetPagedUsers(
|
||||
int pageNumber = 1,
|
||||
int pageSize = 10,
|
||||
string orderBy = "username",
|
||||
@@ -210,13 +211,16 @@ namespace Umbraco.Web.Editors
|
||||
|
||||
if (total == 0)
|
||||
{
|
||||
return new PagedResult<UserDisplay>(0, 0, 0);
|
||||
return new PagedUserResult(0, 0, 0);
|
||||
}
|
||||
|
||||
return new PagedResult<UserDisplay>(total, pageNumber, pageSize)
|
||||
var paged = new PagedUserResult(total, pageNumber, pageSize)
|
||||
{
|
||||
Items = Mapper.Map<IEnumerable<UserDisplay>>(result)
|
||||
Items = Mapper.Map<IEnumerable<UserDisplay>>(result),
|
||||
UserStates = Services.UserService.GetUserStates()
|
||||
};
|
||||
|
||||
return paged;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -325,7 +329,10 @@ namespace Umbraco.Web.Editors
|
||||
//map the save info over onto the user
|
||||
user = Mapper.Map(userSave, user);
|
||||
|
||||
//Save the user first
|
||||
//ensure the invited date is set
|
||||
user.InvitedDate = DateTime.Now;
|
||||
|
||||
//Save the updated user
|
||||
Services.UserService.Save(user);
|
||||
var display = Mapper.Map<UserDisplay>(user);
|
||||
|
||||
@@ -490,5 +497,19 @@ namespace Umbraco.Web.Editors
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public class PagedUserResult : PagedResult<UserDisplay>
|
||||
{
|
||||
public PagedUserResult(long totalItems, long pageNumber, long pageSize) : base(totalItems, pageNumber, pageSize)
|
||||
{
|
||||
UserStates = new Dictionary<UserState, int>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is basically facets of UserStates key = state, value = count
|
||||
/// </summary>
|
||||
[DataMember(Name = "userStates")]
|
||||
public IDictionary<UserState, int> UserStates { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user