From dfacd04b4792ed7e130f4ba586d2840d00017b8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A4=D1=80=D0=BE=D0=BB=D0=BE=D0=B2?= Date: Thu, 23 Dec 2021 18:07:20 +0500 Subject: [PATCH] fix UserService --- AsbCloudApp/Services/IUserRoleService.cs | 1 + .../Services/UserRoleService.cs | 12 ++++ .../Services/UserService.cs | 57 +++++++++++-------- .../SimplifyExceptionsMiddleware.cs | 2 +- 4 files changed, 46 insertions(+), 26 deletions(-) diff --git a/AsbCloudApp/Services/IUserRoleService.cs b/AsbCloudApp/Services/IUserRoleService.cs index 85780812..d651c189 100644 --- a/AsbCloudApp/Services/IUserRoleService.cs +++ b/AsbCloudApp/Services/IUserRoleService.cs @@ -8,6 +8,7 @@ namespace AsbCloudApp.Services public interface IUserRoleService : ICrudService { Task GetByNameAsync(string name, CancellationToken token = default); + Task> GetByNamesAsync(IEnumerable names, CancellationToken token = default); List GetNestedById(int id, int counter = 10); bool HasPermission(IEnumerable rolesIds, string permissionName); } diff --git a/AsbCloudInfrastructure/Services/UserRoleService.cs b/AsbCloudInfrastructure/Services/UserRoleService.cs index 5e41ad83..c4946ed0 100644 --- a/AsbCloudInfrastructure/Services/UserRoleService.cs +++ b/AsbCloudInfrastructure/Services/UserRoleService.cs @@ -71,6 +71,18 @@ namespace AsbCloudInfrastructure.Services return dto; } + public async Task> GetByNamesAsync(IEnumerable names, CancellationToken token = default) + { + if (names?.Any() != true) + return null; + var entities = await cacheUserRoles.WhereAsync(r => names.Contains(r.Caption), token) + .ConfigureAwait(false); + if (entities?.Count() != names.Count()) + throw new ArgumentException("Invalid role names", nameof(names)); + var dtos = entities.Select(Convert); + return dtos; + } + public async Task UpdateAsync(int id, UserRoleDto dto, CancellationToken token = default) { if (dto.Id != id) diff --git a/AsbCloudInfrastructure/Services/UserService.cs b/AsbCloudInfrastructure/Services/UserService.cs index f716246a..c9c938b1 100644 --- a/AsbCloudInfrastructure/Services/UserService.cs +++ b/AsbCloudInfrastructure/Services/UserService.cs @@ -47,11 +47,21 @@ namespace AsbCloudInfrastructure.Services public async Task InsertAsync(UserExtendedDto dto, CancellationToken token = default) { var entity = Convert(dto); + await AssertLoginAsync(dto.Login, token); + var userRoles = await RoleService.GetByNamesAsync(dto.RoleNames, token).ConfigureAwait(false); var updatedEntity = await cacheUsers.InsertAsync(entity, token).ConfigureAwait(false); - await UpdateRolesCacheForUserAsync((int)updatedEntity.Id, dto.RoleNames, token); + if (userRoles?.Any() == true) + await UpdateRolesCacheForUserAsync(updatedEntity.Id, userRoles, token); return updatedEntity?.Id ?? 0; } + private async Task AssertLoginAsync(string login, CancellationToken token = default) + { + var existingUser = await cacheUsers.FirstOrDefaultAsync(u => u.Login.ToLower() == login.ToLower(), token); + if (existingUser is not null) + throw new ArgumentException($"Login {login} is busy by {existingUser.MakeDisplayName()}, id{existingUser.Id}", nameof(login)); + } + public Task InsertRangeAsync(IEnumerable newItems, CancellationToken token = default) { throw new NotImplementedException(); @@ -66,7 +76,6 @@ namespace AsbCloudInfrastructure.Services var dtos = entities.Select(Convert).ToList(); for (var i = 0; i < dtos.Count; i++) dtos[i].RoleNames = GetRolesNamesByIdUser(dtos[i].Id); - return dtos; } @@ -80,12 +89,21 @@ namespace AsbCloudInfrastructure.Services public async Task UpdateAsync(int id, UserExtendedDto dto, CancellationToken token = default) { + var oldUser = await cacheUsers.FirstOrDefaultAsync(u=>u.Id == id, token); + if(oldUser.Login != dto.Login) + await AssertLoginAsync(dto.Login, token); + + var userRoles = await RoleService.GetByNamesAsync(dto.RoleNames, token).ConfigureAwait(false); + await UpdateRolesCacheForUserAsync(id, userRoles, token); + var entity = Convert(dto); - await UpdateRolesCacheForUserAsync(id, dto.RoleNames, token); + if (dto.Id == 0) + entity.Id = id; + else if (dto.Id != id) + throw new ArgumentException($"Invalid userDto.id it mast be 0 or {id}", nameof(dto)); var result = await cacheUsers.UpsertAsync(entity, token) .ConfigureAwait(false); - return result; } @@ -120,27 +138,17 @@ namespace AsbCloudInfrastructure.Services return permissions; } - private async Task UpdateRolesCacheForUserAsync(int idUser, IEnumerable newRoleNames, CancellationToken token) + private async Task UpdateRolesCacheForUserAsync(int idUser, IEnumerable newRoles, CancellationToken token) { - if (newRoleNames?.Any() != true) - return; - - var relatrions = new List(newRoleNames.Count()); - foreach (var roleName in newRoleNames) - { - var role = await RoleService.GetByNameAsync(roleName, token) - .ConfigureAwait(false); - if (role != null) - relatrions.Add(new() - { - IdUser = idUser, - IdUserRole = role.Id, - }); - } await cacheRelationUserToRoles.RemoveAsync(r => r.IdUser == idUser, token) .ConfigureAwait(false); - await cacheRelationUserToRoles.InsertAsync(relatrions, token) - .ConfigureAwait(false); + + if (newRoles?.Any() == true) + await cacheRelationUserToRoles.InsertAsync(newRoles.Select(role => new RelationUserUserRole + { + IdUser = idUser, + IdUserRole = role.Id + }), token).ConfigureAwait(false); } public bool HasAnyRoleOf(int idUser, IEnumerable roleNames) @@ -177,10 +185,9 @@ namespace AsbCloudInfrastructure.Services protected virtual User Convert(UserExtendedDto dto) { - var entity = dto.Adapt(userTypeAdapterConfig); - var oldUser = new Lazy(() => cacheUsers.FirstOrDefault(u => u.Id == dto.Id)); + var entity = dto.Adapt(userTypeAdapterConfig); if (string.IsNullOrEmpty(entity.PasswordHash)) - entity.PasswordHash = oldUser.Value.PasswordHash; + entity.PasswordHash = cacheUsers.FirstOrDefault(u => u.Id == dto.Id)?.PasswordHash; return entity; } diff --git a/AsbCloudWebApi/Middlewares/SimplifyExceptionsMiddleware.cs b/AsbCloudWebApi/Middlewares/SimplifyExceptionsMiddleware.cs index 667f1946..293e67ec 100644 --- a/AsbCloudWebApi/Middlewares/SimplifyExceptionsMiddleware.cs +++ b/AsbCloudWebApi/Middlewares/SimplifyExceptionsMiddleware.cs @@ -42,7 +42,7 @@ namespace AsbCloudWebApi.Middlewares } } - private string MakeJsonBody(ArgumentException ex) + private static string MakeJsonBody(ArgumentException ex) { object error = new { name = ex.ParamName, errors = new string[] { ex.Message } }; var buffer = System.Text.Json.JsonSerializer.Serialize(error);