Skip to content

Commit 99c2aaf

Browse files
AndyButlandCopilot
andauthored
Members: Forward port of fix for member lockout issue #16988 from PR #17007 for 16 (#20441)
* Port PR #17007 * Update src/Umbraco.Infrastructure/Security/IdentityMapDefinition.cs Co-authored-by: Copilot <[email protected]> --------- Co-authored-by: Copilot <[email protected]>
1 parent a4c373d commit 99c2aaf

File tree

1 file changed

+36
-6
lines changed

1 file changed

+36
-6
lines changed

src/Umbraco.Infrastructure/Security/IdentityMapDefinition.cs

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)