hi
Can you try to override the ImportUsersFromFileAsync
method of IdentityUserAppService
to support batch import?
We will change it in the next version.
Thanks.
[Authorize(IdentityPermissions.Users.Import)]
public virtual async Task<ImportUsersFromFileOutput> ImportUsersFromFileAsync(ImportUsersFromFileInputWithStream input)
{
await IdentityOptions.SetAsync();
var stream = new MemoryStream();
await input.File.GetStream().CopyToAsync(stream);
var invalidUsers = new List<InvalidImportUsersFromFileDto>();
List<InvalidImportUsersFromFileDto> waitingImportUsers;
try
{
IConfiguration configuration = null;
if (input.FileType == ImportUsersFromFileType.Csv)
{
configuration = new CsvConfiguration { Seperator = ';' };
}
waitingImportUsers = (await stream.QueryAsync<InvalidImportUsersFromFileDto>(excelType: input.FileType == ImportUsersFromFileType.Excel ? ExcelType.XLSX : ExcelType.CSV, configuration: configuration)).ToList();
}
catch (Exception)
{
throw new BusinessException(IdentityProErrorCodes.InvalidImportFileFormat);
}
if (!waitingImportUsers.Any())
{
throw new BusinessException(IdentityProErrorCodes.NoUserFoundInFile);
}
var resultDto = new ImportUsersFromFileOutput
{
AllCount = waitingImportUsers.Count
};
const int batchSize = 3;
var totalUsers = waitingImportUsers.Count;
var batchCount = (int)Math.Ceiling((double)totalUsers / batchSize);
for (var batchIndex = 0; batchIndex < batchCount; batchIndex++)
{
var currentBatch = waitingImportUsers
.Skip(batchIndex * batchSize)
.Take(batchSize)
.ToList();
var (invalidBatchUsers, successBatchUsers) = await ImportUsersAsync(currentBatch);
invalidUsers.AddRange(invalidBatchUsers);
if (invalidBatchUsers.Any() && successBatchUsers.Any())
{
var (invalidBatchUsers2, successBatchUsers2) = await ImportUsersAsync(successBatchUsers);
if (invalidBatchUsers2.Any())
{
invalidUsers.AddRange(invalidBatchUsers2);
invalidUsers.AddRange(successBatchUsers2);
}
}
}
if (invalidUsers.Any())
{
var token = Guid.NewGuid().ToString("N");
await ImportInvalidUsersCache.SetAsync(
token,
new ImportInvalidUsersCacheItem
{
Token = token,
InvalidUsers = invalidUsers,
FileType = input.FileType
},
new DistributedCacheEntryOptions
{
AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(1)
});
resultDto.InvalidUsersDownloadToken = token;
}
resultDto.SucceededCount = resultDto.AllCount - invalidUsers.Count;
resultDto.FailedCount = invalidUsers.Count;
return resultDto;
}
protected virtual async Task<(List<InvalidImportUsersFromFileDto>, List<InvalidImportUsersFromFileDto>)> ImportUsersAsync(List<InvalidImportUsersFromFileDto> users)
{
var hasException = false;
var invalidUsers = new List<InvalidImportUsersFromFileDto>();
var successUsers = new List<InvalidImportUsersFromFileDto>();
using (var uow = UnitOfWorkManager.Begin(requiresNew: true, isTransactional: true))
{
foreach (var waitingImportUser in users)
{
try
{
var user = new IdentityUser(
GuidGenerator.Create(),
waitingImportUser.UserName,
waitingImportUser.EmailAddress,
CurrentTenant.Id
)
{
Surname = waitingImportUser.Surname,
Name = waitingImportUser.Name
};
if (!waitingImportUser.PhoneNumber.IsNullOrWhiteSpace())
{
user.SetPhoneNumber(waitingImportUser.PhoneNumber, false);
}
if (!waitingImportUser.Password.IsNullOrWhiteSpace())
{
(await UserManager.CreateAsync(user, waitingImportUser.Password)).CheckErrors();
}
else
{
(await UserManager.CreateAsync(user)).CheckErrors();
}
if (!waitingImportUser.AssignedRoleNames.IsNullOrWhiteSpace())
{
(await UserManager.SetRolesAsync(user,
waitingImportUser.AssignedRoleNames.Split(new[] { ",", ";" },
StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries))).CheckErrors();
}
if (!waitingImportUser.AssignedOrganizationUnitNames.IsNullOrWhiteSpace())
{
var ouNames = waitingImportUser.AssignedOrganizationUnitNames.Split(new[] { ",", ";" },
StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries).ToArray();
var ous = await OrganizationUnitRepository.GetListByDisplayNamesAsync(ouNames);
if (ous.Any())
{
await UserManager.SetOrganizationUnitsAsync(user, ous.Select(x => x.Id).ToArray());
}
}
successUsers.Add(waitingImportUser);
}
catch (Exception e)
{
hasException = true;
waitingImportUser.ErrorReason = e is UserFriendlyException ? e.Message : e.ToString();
invalidUsers.Add(waitingImportUser);
Logger.LogWarning(e, $"Import user failed: {waitingImportUser}");
}
}
await (hasException ? uow.RollbackAsync() : uow.CompleteAsync());
}
return (invalidUsers, successUsers);
}
hi
I will share a solution, Wait a sec.
Thanks.
hi
Can you share the authserver project logs?
https://abp.io/support/questions/8622/How-to-enable-Debug-logs-for-troubleshoot-problems
and the HTTP request and response of Angular.
https://abp.io/support/questions/8622/How-to-enable-Debug-logs-for-troubleshoot-problems#answer-3a1a1c4b-691e-3403-98b9-5f23fa024759
liming.ma@volosoft.com
Thanks
hi
How many policies of abpPolicyNames
and otherPolicyNames
?
Thanks.
: )
hi
What are the versions of NuGet packages? Please check it in all csproj
files.
The exception will be fixed >= 9.1.1.
Thanks.
Great
hi
You can use it in the next version. remove it now. ; )