EF UserStore FindByEmail will throw on dupes (#8220)

This commit is contained in:
Hao Kung 2019-03-08 11:39:26 -08:00 committed by GitHub
parent a53accfd75
commit f4c80ca99f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 44 additions and 2 deletions

View File

@ -502,7 +502,7 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore
{
cancellationToken.ThrowIfCancellationRequested();
ThrowIfDisposed();
return Users.FirstOrDefaultAsync(u => u.NormalizedEmail == normalizedEmail, cancellationToken);
return Users.SingleOrDefaultAsync(u => u.NormalizedEmail == normalizedEmail, cancellationToken);
}
/// <summary>

View File

@ -635,7 +635,7 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore
{
cancellationToken.ThrowIfCancellationRequested();
ThrowIfDisposed();
return Users.FirstOrDefaultAsync(u => u.NormalizedEmail == normalizedEmail, cancellationToken);
return Users.SingleOrDefaultAsync(u => u.NormalizedEmail == normalizedEmail, cancellationToken);
}
/// <summary>

View File

@ -1,6 +1,7 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder.Internal;
using Microsoft.AspNetCore.Identity.Test;
@ -65,5 +66,27 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test
IdentityResultAssert.IsSuccess(await userManager.CreateAsync(user, password));
IdentityResultAssert.IsSuccess(await userManager.DeleteAsync(user));
}
[ConditionalFact]
[FrameworkSkipCondition(RuntimeFrameworks.Mono)]
[OSSkipCondition(OperatingSystems.Linux)]
[OSSkipCondition(OperatingSystems.MacOSX)]
public async Task FindByEmailThrowsWithTwoUsersWithSameEmail()
{
var userStore = _builder.ApplicationServices.GetRequiredService<IUserStore<IdentityUser>>();
var manager = _builder.ApplicationServices.GetRequiredService<UserManager<IdentityUser>>();
Assert.NotNull(userStore);
Assert.NotNull(manager);
var userA = new IdentityUser(Guid.NewGuid().ToString());
userA.Email = "dupe@dupe.com";
const string password = "1qaz@WSX";
IdentityResultAssert.IsSuccess(await manager.CreateAsync(userA, password));
var userB = new IdentityUser(Guid.NewGuid().ToString());
userB.Email = "dupe@dupe.com";
IdentityResultAssert.IsSuccess(await manager.CreateAsync(userB, password));
await Assert.ThrowsAsync<InvalidOperationException>(async () => await manager.FindByEmailAsync("dupe@dupe.com"));
}
}
}

View File

@ -208,6 +208,23 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test
Assert.NotEqual(userA.PasswordHash, userB.PasswordHash);
}
[ConditionalFact]
[FrameworkSkipCondition(RuntimeFrameworks.Mono)]
[OSSkipCondition(OperatingSystems.Linux)]
[OSSkipCondition(OperatingSystems.MacOSX)]
public async Task FindByEmailThrowsWithTwoUsersWithSameEmail()
{
var manager = CreateManager();
var userA = new IdentityUser(Guid.NewGuid().ToString());
userA.Email = "dupe@dupe.com";
IdentityResultAssert.IsSuccess(await manager.CreateAsync(userA, "password"));
var userB = new IdentityUser(Guid.NewGuid().ToString());
userB.Email = "dupe@dupe.com";
IdentityResultAssert.IsSuccess(await manager.CreateAsync(userB, "password"));
await Assert.ThrowsAsync<InvalidOperationException>(async () => await manager.FindByEmailAsync("dupe@dupe.com"));
}
[ConditionalFact]
[FrameworkSkipCondition(RuntimeFrameworks.Mono)]
[OSSkipCondition(OperatingSystems.Linux)]

View File

@ -1393,6 +1393,8 @@ namespace Microsoft.AspNetCore.Identity
/// <summary>
/// Gets the user, if any, associated with the normalized value of the specified email address.
/// Note: Its recommended that identityOptions.User.RequireUniqueEmail be set to true when using this method, otherwise
/// the store may throw if there are users with duplicate emails.
/// </summary>
/// <param name="email">The email address to return the user for.</param>
/// <returns>