@@ -95,7 +95,7 @@ private void Map(IUser source, BackOfficeIdentityUser target)
9595 target . IsApproved = source . IsApproved ;
9696 target . SecurityStamp = source . SecurityStamp ;
9797 DateTime ? lockedOutUntil = source . LastLockoutDate ? . AddMinutes ( _securitySettings . UserDefaultLockoutTimeInMinutes ) ;
98- target . LockoutEnd = source . IsLockedOut ? ( lockedOutUntil ?? DateTime . MaxValue ) . ToUniversalTime ( ) : null ;
98+ target . LockoutEnd = source . IsLockedOut ? lockedOutUntil ?? DateTime . MaxValue : null ;
9999 target . Kind = source . Kind ;
100100 }
101101
@@ -114,16 +114,46 @@ private void Map(IMember source, MemberIdentityUser target)
114114 target . IsApproved = source . IsApproved ;
115115 target . SecurityStamp = source . SecurityStamp ;
116116 DateTime ? lockedOutUntil = source . LastLockoutDate ? . AddMinutes ( _securitySettings . MemberDefaultLockoutTimeInMinutes ) ;
117- target . LockoutEnd = source . IsLockedOut ? ( lockedOutUntil ?? DateTime . MaxValue ) . ToUniversalTime ( ) : null ;
117+ target . LockoutEnd = GetLockoutEnd ( source ) ;
118+ target . LastLockoutDateUtc = GetLastLockoutDateUtc ( source ) ;
119+ target . CreatedDateUtc = EnsureUtcWithServerTime ( source . CreateDate ) ;
118120 target . Comments = source . Comments ;
119- target . LastLockoutDateUtc = source . LastLockoutDate == DateTime . MinValue
120- ? null
121- : source . LastLockoutDate ? . ToUniversalTime ( ) ;
122- target . CreatedDateUtc = source . CreateDate . ToUniversalTime ( ) ;
123121 target . Key = source . Key ;
124122 target . MemberTypeAlias = source . ContentTypeAlias ;
125123 target . TwoFactorEnabled = _twoFactorLoginService . IsTwoFactorEnabledAsync ( source . Key ) . GetAwaiter ( ) . GetResult ( ) ;
126124
127125 // NB: same comments re AutoMapper as per BackOfficeUser
128126 }
127+
128+ private DateTimeOffset ? GetLockoutEnd ( IMember source )
129+ {
130+ if ( source . IsLockedOut is false )
131+ {
132+ return null ;
133+ }
134+
135+ DateTime ? lockedOutUntil = source . LastLockoutDate ? . AddMinutes ( _securitySettings . MemberDefaultLockoutTimeInMinutes ) ;
136+ if ( lockedOutUntil . HasValue is false )
137+ {
138+ return DateTime . MaxValue ;
139+ }
140+
141+ return EnsureUtcWithServerTime ( lockedOutUntil . Value ) ;
142+ }
143+
144+ private static DateTime ? GetLastLockoutDateUtc ( IMember source )
145+ {
146+ if ( source . LastLockoutDate is null || source . LastLockoutDate == DateTime . MinValue )
147+ {
148+ return null ;
149+ }
150+
151+ return EnsureUtcWithServerTime ( source . LastLockoutDate . Value ) ;
152+ }
153+
154+ private static DateTime EnsureUtcWithServerTime ( DateTime date ) =>
155+
156+ // We have a server time value here, but the Kind is UTC, so we can't use .ToUniversalTime() to convert to the UTC
157+ // value that the LockoutEnd property expects. We need to create a DateTimeOffset with the correct offset.
158+ DateTime . SpecifyKind ( date , DateTimeKind . Local ) . ToUniversalTime ( ) ;
129159}
0 commit comments