Fixes issue with email confirmation date, adds invite date, adds user state counts

This commit is contained in:
Shannon
2017-06-15 16:47:51 +02:00
parent 0f89b1dea7
commit 021e083b75
13 changed files with 109 additions and 14 deletions
@@ -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
}
}
+4
View File
@@ -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)
@@ -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
+17
View File
@@ -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 = "");
+10 -1
View File
@@ -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);
}
+26 -5
View File
@@ -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; }
}
}
}