From 75c5d729704b5720f6d1871a979aab19ba70dee5 Mon Sep 17 00:00:00 2001 From: maliming Date: Thu, 28 Dec 2023 10:31:52 +0800 Subject: [PATCH] Add `GetUserNameFromEmailAsync` to `IdentityUserManager`. --- .../Pages/Account/AccountPageModel.cs | 19 ------- .../Pages/Account/Register.cshtml.cs | 4 +- .../Volo/Abp/Identity/IdentityUserManager.cs | 53 +++++++++++++++++++ .../Abp/Identity/IdentityUserManager_Tests.cs | 29 ++++++++++ 4 files changed, 84 insertions(+), 21 deletions(-) diff --git a/modules/account/src/Volo.Abp.Account.Web/Pages/Account/AccountPageModel.cs b/modules/account/src/Volo.Abp.Account.Web/Pages/Account/AccountPageModel.cs index f229253c4ab..ebd556f8e2f 100644 --- a/modules/account/src/Volo.Abp.Account.Web/Pages/Account/AccountPageModel.cs +++ b/modules/account/src/Volo.Abp.Account.Web/Pages/Account/AccountPageModel.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; using Microsoft.AspNetCore.Identity; using Microsoft.Extensions.Options; using Volo.Abp.Account.Localization; @@ -55,22 +54,4 @@ protected virtual string GetLocalizeExceptionMessage(Exception exception) return exception.Message; } - - protected virtual async Task GetUserNameFromEmail(string email) - { - var userName = email.Split('@')[0]; - var existUser = await UserManager.FindByNameAsync(userName); - while (existUser != null) - { - var randomUserName = userName + RandomHelper.GetRandom(1000, 9999); - existUser = await UserManager.FindByNameAsync(randomUserName); - if (existUser == null) - { - userName = randomUserName; - break; - } - } - - return userName; - } } diff --git a/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Register.cshtml.cs b/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Register.cshtml.cs index 9e0a2c191ba..c481715a16e 100644 --- a/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Register.cshtml.cs +++ b/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Register.cshtml.cs @@ -102,7 +102,7 @@ protected virtual async Task TrySetEmailAsync() return; } - var userName = await GetUserNameFromEmail(emailClaim.Value); + var userName = await UserManager.GetUserNameFromEmailAsync(emailClaim.Value); Input = new PostInput { UserName = userName, EmailAddress = emailClaim.Value }; } } @@ -128,7 +128,7 @@ public virtual async Task OnPostAsync() } if (Input.UserName.IsNullOrWhiteSpace()) { - Input.UserName = await GetUserNameFromEmail(Input.EmailAddress); + Input.UserName = await UserManager.GetUserNameFromEmailAsync(Input.EmailAddress); } await RegisterExternalUserAsync(externalLoginInfo, Input.UserName, Input.EmailAddress); } diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUserManager.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUserManager.cs index fce656cc09f..3e116aaed95 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUserManager.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUserManager.cs @@ -436,4 +436,57 @@ public virtual Task GetRandomUserNameAsync(int length) return Task.FromResult(randomUserName); } + + public virtual async Task GetUserNameFromEmailAsync(string email) + { + var userName = email.Split('@')[0]; + if (!Options.User.AllowedUserNameCharacters.IsNullOrWhiteSpace() && !userName.All(Options.User.AllowedUserNameCharacters.Contains)) + { + // The user name contains not allowed characters. We will use the email address as user name. + return email; + } + + if (await ValidateUserNameAsync(userName)) + { + return userName; + } + + const int maxTryCount = 10; + var tryCount = 0; + + if (Options.User.AllowedUserNameCharacters.IsNullOrWhiteSpace() || "0123456789".All(Options.User.AllowedUserNameCharacters.Contains)) + { + var randomUserName = userName; + var isUserNameValid = await ValidateUserNameAsync(randomUserName); + while (tryCount < maxTryCount) + { + randomUserName = userName + RandomHelper.GetRandom(1000, 9999); + isUserNameValid = await ValidateUserNameAsync(randomUserName); + if (isUserNameValid) + { + return randomUserName; + } + tryCount++; + } + if (isUserNameValid) + { + return randomUserName; + } + } + + tryCount = 0; + while (tryCount < maxTryCount) + { + var randomUserName = userName + await GetRandomUserNameAsync(4); + var isUserNameValid = await ValidateUserNameAsync(randomUserName); + if (isUserNameValid) + { + return randomUserName; + } + tryCount++; + } + + // We could not find a valid user name so we are returning the email address. + return email; + } } diff --git a/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/IdentityUserManager_Tests.cs b/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/IdentityUserManager_Tests.cs index f5b648516e3..c90a84e0e04 100644 --- a/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/IdentityUserManager_Tests.cs +++ b/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/IdentityUserManager_Tests.cs @@ -5,6 +5,7 @@ using System.Text.RegularExpressions; using System.Threading.Tasks; using Microsoft.AspNetCore.Identity; +using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Options; @@ -422,6 +423,34 @@ public async Task GetRandomUserNameAsync() username.All(c => "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._@+".Contains(c)).ShouldBeTrue(); } + [Fact] + public async Task GetUserNameFromEmailAsync() + { + _identityUserManager.Options.User.AllowedUserNameCharacters = "abcdefghijklmnopqrstuvwxyz0123456789"; + var username = await _identityUserManager.GetUserNameFromEmailAsync("admin@abp.io"); + username.Length.ShouldBe(9); //admin and random 4 numbers + username.ShouldContain("admin"); + Regex.IsMatch(username, @"\d{4}$").ShouldBeTrue(); + + _identityUserManager.Options.User.AllowedUserNameCharacters = "abcdefghijklmnopqrstuvwxyz"; + username = await _identityUserManager.GetUserNameFromEmailAsync("admin@abp.io"); + username.Length.ShouldBe(9); //admin and random 4 characters + username.ShouldContain("admin"); + Regex.IsMatch(username, @"[a-z]{4}$").ShouldBeTrue(); + + _identityUserManager.Options.User.AllowedUserNameCharacters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + username = await _identityUserManager.GetUserNameFromEmailAsync("ADMIN@abp.io"); + username.Length.ShouldBe(9); //admin and random 4 characters + username.ShouldContain("ADMIN"); + Regex.IsMatch(username, @"[A-Z]{4}$").ShouldBeTrue(); + + _identityUserManager.Options.User.AllowedUserNameCharacters = null!; + username = await _identityUserManager.GetUserNameFromEmailAsync("admin@abp.io"); + username.Length.ShouldBe(9); //admin and random 4 numbers + username.ShouldContain("admin"); + Regex.IsMatch(username, @"[0-9]{4}$").ShouldBeTrue(); + } + private async Task CreateRandomDefaultRoleAsync() { await _identityRoleRepository.InsertAsync(