diff --git a/AsbCloudApp/Repositories/IUserRepository.cs b/AsbCloudApp/Repositories/IUserRepository.cs
index 02b713fe..4f6b0fac 100644
--- a/AsbCloudApp/Repositories/IUserRepository.cs
+++ b/AsbCloudApp/Repositories/IUserRepository.cs
@@ -1,41 +1,35 @@
using AsbCloudApp.Data;
-using System;
+using AsbCloudApp.Services;
using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading;
-using System.Threading.Tasks;
namespace AsbCloudApp.Repositories
{
///
/// Репозиторий пользователей
///
- public interface IUserRepository
+ public interface IUserRepository : ICrudService
{
///
- /// Добавление пользователя
- ///
- ///
- ///
- ///
- Task InsertAsync(UserExtendedDto dto, CancellationToken token);
-
- ///
- /// Обновление ролей пользователя
+ /// Получить список всех прав пользователя (включая наследование групп)
///
///
- ///
- ///
///
- Task UpdateRolesCacheForUserAsync(int idUser, IEnumerable newRoles, CancellationToken token);
+ IEnumerable GetNestedPermissions(int idUser);
///
- /// Получить пользователя по логину
+ /// Получить список ролей пользователя (включая наследование)
///
- ///
- ///
+ ///
+ ///
///
- Task GetUserByLoginAsync(string login, CancellationToken token);
+ IEnumerable GetRolesByIdUser(int idUser, int nestedLevel = 0);
+
+ ///
+ /// определяет есть ли у пользователя указанное разрешение
+ ///
+ ///
+ ///
+ ///
+ public bool HasPermission(int idUser, string permissionName);
}
}
diff --git a/AsbCloudApp/Services/IUserService.cs b/AsbCloudApp/Services/IUserService.cs
deleted file mode 100644
index 5eb9ab70..00000000
--- a/AsbCloudApp/Services/IUserService.cs
+++ /dev/null
@@ -1,40 +0,0 @@
-using AsbCloudApp.Data;
-using AsbCloudApp.Repositories;
-using System.Collections.Generic;
-
-namespace AsbCloudApp.Services
-{
- ///
- /// Сервис пользователей
- ///
- public interface IUserService : ICrudService
- {
- ///
- /// Сервис ролей
- ///
- IUserRoleRepository RoleService { get; }
-
- ///
- /// Получить список всех прав пользователя (включая наследование групп)
- ///
- ///
- ///
- IEnumerable GetNestedPermissions(int idUser);
-
- ///
- /// Получить список ролей пользователя (включая наследование)
- ///
- ///
- ///
- ///
- IEnumerable GetRolesByIdUser(int idUser, int nestedLevel = 0);
-
- ///
- /// определяет есть ли у пользователя указанное разрешение
- ///
- ///
- ///
- ///
- public bool HasPermission(int idUser, string permissionName);
- }
-}
diff --git a/AsbCloudInfrastructure/DependencyInjection.cs b/AsbCloudInfrastructure/DependencyInjection.cs
index cc6c279a..a9e521ca 100644
--- a/AsbCloudInfrastructure/DependencyInjection.cs
+++ b/AsbCloudInfrastructure/DependencyInjection.cs
@@ -120,7 +120,6 @@ namespace AsbCloudInfrastructure
services.AddTransient();
services.AddTransient();
services.AddTransient();
- services.AddTransient();
services.AddTransient();
services.AddTransient();
services.AddTransient();
@@ -163,6 +162,7 @@ namespace AsbCloudInfrastructure
services.AddTransient();
services.AddTransient();
services.AddTransient();
+ services.AddTransient();
// Subsystem service
services.AddTransient, CrudCacheServiceBase>();
services.AddTransient();
diff --git a/AsbCloudInfrastructure/Repository/UserRepository.cs b/AsbCloudInfrastructure/Repository/UserRepository.cs
index 83c058f9..1ba7f006 100644
--- a/AsbCloudInfrastructure/Repository/UserRepository.cs
+++ b/AsbCloudInfrastructure/Repository/UserRepository.cs
@@ -1,9 +1,13 @@
using AsbCloudApp.Data;
+using AsbCloudApp.Exceptions;
using AsbCloudApp.Repositories;
+using AsbCloudApp.Services;
+using AsbCloudDb;
using AsbCloudDb.Model;
using AsbCloudInfrastructure.EfCache;
using Mapster;
using Microsoft.EntityFrameworkCore;
+using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
@@ -14,8 +18,11 @@ namespace AsbCloudInfrastructure.Repository
#nullable enable
public class UserRepository : IUserRepository
{
- private readonly IAsbCloudDbContext db;
- private static readonly System.TimeSpan cacheObsolescence = System.TimeSpan.FromMinutes(15);
+ private readonly IAsbCloudDbContext dbContext;
+ private readonly IUserRoleRepository userRoleRepository;
+ private const string userCacheTag = "User";
+ private const string relationUserUserRoleCacheTag = "RelationUserUserRole";
+ private static readonly TimeSpan cacheObsolence = TimeSpan.FromMinutes(15);
private static readonly TypeAdapterConfig userTypeAdapterConfig = TypeAdapterConfig
.NewConfig()
.Ignore(dst => dst.Company,
@@ -24,75 +31,209 @@ namespace AsbCloudInfrastructure.Repository
dst => dst.RelationUsersUserRoles)
.Config;
- public UserRepository(IAsbCloudDbContext db) {
- this.db = db;
+ public UserRepository(IAsbCloudDbContext dbContext, IUserRoleRepository userRoleRepository) {
+ this.dbContext = dbContext;
+ this.userRoleRepository = userRoleRepository;
}
- public async Task InsertAsync(UserExtendedDto dto, CancellationToken token)
+ public async Task InsertAsync(UserExtendedDto dto, CancellationToken token = default)
{
dto.Id = default;
- var updatedEntity = await db.Users.AddAsync(Convert(dto), token).ConfigureAwait(false);
- return Convert(updatedEntity.Entity);
+ var entity = Convert(dto);
+ await AssertLoginIsBusyAsync(dto.Login, token);
+ var userRoles = await userRoleRepository.GetByNamesAsync(dto.RoleNames, token).ConfigureAwait(false);
+ var updatedEntity = await dbContext.Users.AddAsync(entity, token).ConfigureAwait(false);
+ if (userRoles?.Any() == true)
+ await UpdateRolesCacheForUserAsync(updatedEntity.Entity.Id, userRoles, token);
+
+ await dbContext.SaveChangesAsync(token);
+ DropCacheUsers();
+ return updatedEntity?.Entity?.Id ?? 0;
}
- public async Task UpdateRolesCacheForUserAsync(int idUser, IEnumerable newRoles, CancellationToken token)
+ public Task InsertRangeAsync(IEnumerable newItems, CancellationToken token = default)
{
- var entity = await db.RelationUserUserRoles.FirstOrDefaultAsync(x => x.IdUser == idUser, token).ConfigureAwait(false);
- if (entity is not null)
- {
- db.RelationUserUserRoles.Remove(entity);
- if (newRoles?.Any() == true)
- await db.RelationUserUserRoles.AddRangeAsync(newRoles.Select(role => new RelationUserUserRole
- {
- IdUser = idUser,
- IdUserRole = role.Id
- }), token).ConfigureAwait(false);
- }
+ throw new NotImplementedException();
}
- public async Task GetUserByLoginAsync(string login, CancellationToken token)
+ public async Task> GetAllAsync(CancellationToken token = default)
{
- var entities = await db.Users.FromCacheAsync("Users", cacheObsolescence, token).ConfigureAwait(false);
- var entity = entities.FirstOrDefault(x => x.Login.ToLower() == login.ToLower());
- if (entity is not null)
- return Convert(entity);
- return null;
- }
-
- public async Task?> GetAllAsync(CancellationToken token = default)
- {
- var entities = await db.Users.FromCacheAsync("Users", cacheObsolescence, token).ConfigureAwait(false);
- if (entities is null)
- return null;
+ var entities = await GetCacheUserAsync(token);
+
var dtos = entities.Select(Convert).ToList();
- //for (var i = 0; i < dtos.Count; i++)
- // dtos[i].RoleNames = GetRolesNamesByIdUser(dtos[i].Id, token);
+ for (var i = 0; i < dtos.Count; i++)
+ dtos[i].RoleNames = GetRolesNamesByIdUser(dtos[i].Id);
return dtos;
}
- //private async Task> GetRolesNamesByIdUser(int idUser, CancellationToken token)
- //=> await GetRolesByIdUser(idUser, token)
- // ?.Select(r => r.Caption)
- // .Distinct();
+ public UserExtendedDto? GetOrDefault(int id)
+ {
+ var entity = GetCacheUser().FirstOrDefault(u => u.Id == id);
+ if (entity is null)
+ return null;
+ var dto = Convert(entity);
+ dto.RoleNames = GetRolesNamesByIdUser(dto.Id);
+ return dto;
+ }
- //public async Task> GetRolesByIdUser(int idUser, CancellationToken token, int nestedLevel = 0)
- //{
- // var allRoles = await db.RelationUserUserRoles.FromCacheAsync("RelationUserUserRoles", cacheObsolescence, token).ConfigureAwait(false);
- // var roles = allRoles.Where(r => r.IdUser == idUser);
- // if (roles?.Any() != true)
- // return null;
- // return roles.SelectMany(r => RoleService.GetNestedById(r.IdUserRole, nestedLevel));
- //}
+ public async Task GetOrDefaultAsync(int id, CancellationToken token = default)
+ {
+ var entity = (await GetCacheUserAsync(token)).FirstOrDefault(u => u.Id == id);
+ if (entity is null)
+ return null;
+ var dto = Convert(entity);
+ dto.RoleNames = GetRolesNamesByIdUser(dto.Id);
+ return dto;
+ }
- private User Convert(UserExtendedDto dto)
+ public async Task UpdateAsync(UserExtendedDto dto, CancellationToken token = default)
+ {
+ if (dto.Id <= 1)
+ throw new ArgumentInvalidException($"Invalid id {dto.Id}. You can't edit this user.", nameof(dto));
+
+ var oldUser = (await GetCacheUserAsync(token)).FirstOrDefault(u => u.Id == dto.Id);
+ if (oldUser is null)
+ return 0;
+
+ if (oldUser.Login != dto.Login)
+ await AssertLoginIsBusyAsync(dto.Login, token);
+
+ var userRoles = await userRoleRepository.GetByNamesAsync(dto.RoleNames, token).ConfigureAwait(false);
+
+ if (userRoles is not null)
+ await UpdateRolesCacheForUserAsync(dto.Id, userRoles, token);
+
+ var entity = Convert(dto);
+
+ var result = dbContext.Users.Upsert(entity);
+ await dbContext.SaveChangesAsync(token);
+ DropCacheUsers();
+ return result?.Entity?.Id ?? 0;
+ }
+
+ public async Task DeleteAsync(int id, CancellationToken token = default)
+ {
+ var entity = (await GetCacheUserAsync(token)).FirstOrDefault(u => u.Id == id);
+ if (entity is null)
+ return 0;
+
+ var result = dbContext.Users.Remove(entity);
+ await dbContext.SaveChangesAsync(token);
+ DropCacheUsers();
+ return result?.Entity?.Id ?? 0;
+ }
+
+ public async Task DeleteAsync(IEnumerable ids, CancellationToken token = default)
+ {
+ var entities = (await GetCacheUserAsync(token)).Where(r => ids.Contains(r.Id));
+ if (entities is null)
+ return 0;
+
+ var count = entities.Count();
+ dbContext.Users.RemoveRange(entities);
+ await dbContext.SaveChangesAsync(token);
+ DropCacheUsers();
+ return count;
+ }
+
+ public IEnumerable? GetRolesByIdUser(int idUser, int nestedLevel = 0)
+ {
+ var roles = GetCachRelationUserUserRoleCacheTag().Where(r => r.IdUser == idUser);
+ if (roles is null)
+ return null;
+
+ return roles.SelectMany(r => userRoleRepository.GetNestedById(r.IdUserRole, nestedLevel));
+ }
+
+ public IEnumerable? GetNestedPermissions(int idUser)
+ {
+ var roles = GetRolesByIdUser(idUser, 7);
+ if (roles is null)
+ return null;
+ var permissions = roles
+ .Where(r => r.Permissions is not null)
+ .SelectMany(r => r.Permissions);
+
+ return permissions;
+ }
+
+ public bool HasPermission(int idUser, string permissionName)
+ {
+ if (idUser == 1)
+ return true;
+
+ var relationsToRoles = GetCachRelationUserUserRoleCacheTag().Where(r => r.IdUser == idUser);
+ if (relationsToRoles is null)
+ return false;
+
+ return userRoleRepository.HasPermission(relationsToRoles.Select(r => r.IdUserRole),
+ permissionName);
+ }
+
+ private IEnumerable? GetRolesNamesByIdUser(int idUser)
+ => GetRolesByIdUser(idUser)
+ ?.Select(r => r.Caption)
+ .Distinct();
+
+ private async Task AssertLoginIsBusyAsync(string login, CancellationToken token = default)
+ {
+ var existingUser = (await GetCacheUserAsync(token))
+ .FirstOrDefault(u => u.Login.ToLower() == login.ToLower());
+ if (existingUser is not null)
+ throw new ArgumentInvalidException($"Login {login} is busy by {existingUser.MakeDisplayName()}, id{existingUser.Id}", nameof(login));
+ }
+
+ private Task> GetCacheUserAsync(CancellationToken token)
+ => dbContext.Users
+ .Include(r => r.Company)
+ .Include(r => r.RelationUsersUserRoles)
+ .FromCacheAsync(userCacheTag, cacheObsolence, token);
+ private IEnumerable GetCacheUser()
+ => dbContext.Users
+ .Include(r => r.Company)
+ .Include(r => r.RelationUsersUserRoles)
+ .FromCache(userCacheTag, cacheObsolence);
+ private void DropCacheUsers()
+ => dbContext.Users.DropCache(userCacheTag);
+
+ private Task> GetCacheRelationUserUserRoleAsync(CancellationToken token)
+ => dbContext.RelationUserUserRoles
+ .Include(r => r.UserRole)
+ .Include(r => r.User)
+ .FromCacheAsync(relationUserUserRoleCacheTag, cacheObsolence, token);
+ private IEnumerable GetCachRelationUserUserRoleCacheTag()
+ => dbContext.RelationUserUserRoles
+ .Include(r => r.UserRole)
+ .Include(r => r.User)
+ .FromCache(relationUserUserRoleCacheTag, cacheObsolence);
+ private void DropCacheRelationUserUserRoleCacheTag()
+ => dbContext.RelationUserUserRoles.DropCache(relationUserUserRoleCacheTag);
+
+ private async Task UpdateRolesCacheForUserAsync(int idUser, IEnumerable newRoles, CancellationToken token)
+ {
+ var relations = (await GetCacheRelationUserUserRoleAsync(token)).Where(r => r.IdUser == idUser);
+ dbContext.RelationUserUserRoles.RemoveRange(relations);
+
+ if (newRoles?.Any() == true)
+ await dbContext.RelationUserUserRoles.AddRangeAsync(newRoles.Select(role => new RelationUserUserRole
+ {
+ IdUser = idUser,
+ IdUserRole = role.Id
+ }), token).ConfigureAwait(false);
+
+ await dbContext.SaveChangesAsync(token);
+ DropCacheRelationUserUserRoleCacheTag();
+ }
+
+ protected virtual User Convert(UserExtendedDto dto)
{
var entity = dto.Adapt(userTypeAdapterConfig);
if (string.IsNullOrEmpty(entity.PasswordHash))
- entity.PasswordHash = db.Users.FirstOrDefault(u => u.Id == dto.Id)?.PasswordHash;
+ entity.PasswordHash = dbContext.Users.FirstOrDefault(u => u.Id == dto.Id)?.PasswordHash;
return entity;
}
- private UserExtendedDto Convert(User entity)
+ protected virtual UserExtendedDto Convert(User entity)
{
var dto = entity.Adapt();
return dto;
diff --git a/AsbCloudInfrastructure/Repository/UserRoleRepository.cs b/AsbCloudInfrastructure/Repository/UserRoleRepository.cs
index 89d6150e..596ecfca 100644
--- a/AsbCloudInfrastructure/Repository/UserRoleRepository.cs
+++ b/AsbCloudInfrastructure/Repository/UserRoleRepository.cs
@@ -38,7 +38,8 @@ namespace AsbCloudInfrastructure.Repository
await UpdatePermissionsAsync(dto, token);
await UpdateIncludedRolesAsync(dto, token);
- dbContext.UserRoles.DropCache();
+ await dbContext.SaveChangesAsync(token);
+ DropCacheUserRole();
return updatedEntity?.Entity?.Id ?? 0;
}
@@ -98,6 +99,7 @@ namespace AsbCloudInfrastructure.Repository
await UpdateIncludedRolesAsync(dto, token);
var result = dbContext.UserRoles.Upsert(entity);
+ await dbContext.SaveChangesAsync(token);
DropCacheUserRole();
return result?.Entity?.Id ?? 0;
}
diff --git a/AsbCloudInfrastructure/Services/AuthService.cs b/AsbCloudInfrastructure/Services/AuthService.cs
index bf81ed4b..385a4a1a 100644
--- a/AsbCloudInfrastructure/Services/AuthService.cs
+++ b/AsbCloudInfrastructure/Services/AuthService.cs
@@ -1,4 +1,5 @@
using AsbCloudApp.Data;
+using AsbCloudApp.Repositories;
using AsbCloudApp.Services;
using AsbCloudDb.Model;
using Mapster;
@@ -21,7 +22,7 @@ namespace AsbCloudInfrastructure.Services
public class AuthService : IAuthService
{
private readonly IAsbCloudDbContext db;
- private readonly IUserService userService;
+ private readonly IUserRepository userRepository;
public const string issuer = "a";
public const string audience = "a";
@@ -36,10 +37,10 @@ namespace AsbCloudInfrastructure.Services
private readonly HashAlgorithm hashAlgorithm;
private readonly Random rnd;
- public AuthService(IAsbCloudDbContext db, IUserService userService)
+ public AuthService(IAsbCloudDbContext db, IUserRepository userRepository)
{
this.db = db;
- this.userService = userService;
+ this.userRepository = userRepository;
hashAlgorithm = SHA384.Create();
rnd = new Random((int)(DateTime.Now.Ticks % 2147480161));
}
@@ -165,12 +166,12 @@ namespace AsbCloudInfrastructure.Services
if (identity is null || user.IdState == 0)
return null;
- var userDto = await userService.GetOrDefaultAsync(user.Id, token);
+ var userDto = await userRepository.GetOrDefaultAsync(user.Id, token);
if (userDto is null)
return null;
var dto = userDto.Adapt();
- dto.Permissions = userService.GetNestedPermissions(userDto.Id);
+ dto.Permissions = userRepository.GetNestedPermissions(userDto.Id);
dto.Token = MakeToken(identity.Claims);
return dto;
}
@@ -209,7 +210,7 @@ namespace AsbCloudInfrastructure.Services
new (ClaimsIdentity.DefaultNameClaimType, user.Login),
new (claimNameIdCompany, user.IdCompany?.ToString()!),
};
- var roles = userService.GetRolesByIdUser(user.Id);
+ var roles = userRepository.GetRolesByIdUser(user.Id);
if (roles is not null)
foreach (var role in roles)
claims.Add(new Claim(ClaimsIdentity.DefaultRoleClaimType, role.Caption));
diff --git a/AsbCloudInfrastructure/Services/DrillingProgram/DrillingProgramService.cs b/AsbCloudInfrastructure/Services/DrillingProgram/DrillingProgramService.cs
index e926a886..b1a6d0c6 100644
--- a/AsbCloudInfrastructure/Services/DrillingProgram/DrillingProgramService.cs
+++ b/AsbCloudInfrastructure/Services/DrillingProgram/DrillingProgramService.cs
@@ -1,5 +1,6 @@
using AsbCloudApp.Data;
using AsbCloudApp.Exceptions;
+using AsbCloudApp.Repositories;
using AsbCloudApp.Services;
using AsbCloudDb.Model;
using AsbCloudInfrastructure.Repository;
@@ -21,7 +22,7 @@ namespace AsbCloudInfrastructure.Services.DrillingProgram
private readonly IAsbCloudDbContext context;
private readonly FileService fileService;
- private readonly IUserService userService;
+ private readonly IUserRepository userRepository;
private readonly IWellService wellService;
private readonly IConfiguration configuration;
private readonly IBackgroundWorkerService backgroundWorker;
@@ -51,7 +52,7 @@ namespace AsbCloudInfrastructure.Services.DrillingProgram
public DrillingProgramService(
IAsbCloudDbContext context,
FileService fileService,
- IUserService userService,
+ IUserRepository userRepository,
IWellService wellService,
IConfiguration configuration,
IBackgroundWorkerService backgroundWorker,
@@ -59,7 +60,7 @@ namespace AsbCloudInfrastructure.Services.DrillingProgram
{
this.context = context;
this.fileService = fileService;
- this.userService = userService;
+ this.userRepository = userRepository;
this.wellService = wellService;
this.configuration = configuration;
this.backgroundWorker = backgroundWorker;
@@ -127,7 +128,7 @@ namespace AsbCloudInfrastructure.Services.DrillingProgram
Parts = parts,
Program = files.FirstOrDefault(f => f.IdCategory == idFileCategoryDrillingProgram)
.Adapt(),
- PermissionToEdit = userService.HasPermission(idUser, "DrillingProgram.edit"),
+ PermissionToEdit = userRepository.HasPermission(idUser, "DrillingProgram.edit"),
};
if (parts.Any())
@@ -226,7 +227,7 @@ namespace AsbCloudInfrastructure.Services.DrillingProgram
public async Task AddUserAsync(int idWell, int idFileCategory, int idUser, int idUserRole, CancellationToken token = default)
{
- var user = await userService.GetOrDefaultAsync(idUser, token);
+ var user = await userRepository.GetOrDefaultAsync(idUser, token);
if (user is null)
throw new ArgumentInvalidException($"User id == {idUser} does not exist", nameof(idUser));
diff --git a/AsbCloudInfrastructure/Services/UserService.cs b/AsbCloudInfrastructure/Services/UserService.cs
deleted file mode 100644
index 09e284ae..00000000
--- a/AsbCloudInfrastructure/Services/UserService.cs
+++ /dev/null
@@ -1,198 +0,0 @@
-using AsbCloudApp.Data;
-using AsbCloudApp.Exceptions;
-using AsbCloudApp.Repositories;
-using AsbCloudApp.Services;
-using AsbCloudDb.Model;
-using AsbCloudInfrastructure.Services.Cache;
-using Mapster;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading;
-using System.Threading.Tasks;
-
-namespace AsbCloudInfrastructure.Services
-{
- public class UserService : IUserService
- {
- private readonly CacheTable cacheUsers;
- private readonly CacheTable cacheRelationUserToRoles;
- public ISet Includes { get; } = new SortedSet();
- public IUserRoleRepository RoleService { get; }
-
- private static readonly TypeAdapterConfig userTypeAdapterConfig = TypeAdapterConfig
- .NewConfig()
- .Ignore(dst => dst.Company,
- dst => dst.FileMarks,
- dst => dst.Files,
- dst => dst.RelationUsersUserRoles)
- .Config;
-
- public UserService(IAsbCloudDbContext context, CacheDb cacheDb, IUserRoleRepository roleService)
- {
- var db = (AsbCloudDbContext)context;
- cacheUsers = cacheDb.GetCachedTable(
- db,
- new[] {
- nameof(User.RelationUsersUserRoles),
- nameof(User.Company),
- });
- cacheRelationUserToRoles = cacheDb.GetCachedTable(
- db,
- new[] {
- nameof(RelationUserUserRole.User),
- nameof(RelationUserUserRole.UserRole),
- });
- RoleService = roleService;
- }
-
- public async Task InsertAsync(UserExtendedDto dto, CancellationToken token = default)
- {
- dto.Id = default;
- var entity = Convert(dto);
- await AssertLoginIsBusyAsync(dto.Login, token);
- var userRoles = await RoleService.GetByNamesAsync(dto.RoleNames, token).ConfigureAwait(false);
- var updatedEntity = await cacheUsers.InsertAsync(entity, token).ConfigureAwait(false);
- if (userRoles?.Any() == true)
- await UpdateRolesCacheForUserAsync(updatedEntity.Id, userRoles, token);
- return updatedEntity?.Id ?? 0;
- }
-
- private async Task AssertLoginIsBusyAsync(string login, CancellationToken token = default)
- {
- var existingUser = await cacheUsers.FirstOrDefaultAsync(u => u.Login.ToLower() == login.ToLower(), token);
- if (existingUser is not null)
- throw new ArgumentInvalidException($"Login {login} is busy by {existingUser.MakeDisplayName()}, id{existingUser.Id}", nameof(login));
- }
-
- public Task InsertRangeAsync(IEnumerable newItems, CancellationToken token = default)
- {
- throw new NotImplementedException();
- }
-
- public async Task> GetAllAsync(CancellationToken token = default)
- {
- var entities = (await cacheUsers.WhereAsync(token).ConfigureAwait(false))
- .ToList();
- if (entities.Count == 0)
- return null;
- var dtos = entities.Select(Convert).ToList();
- for (var i = 0; i < dtos.Count; i++)
- dtos[i].RoleNames = GetRolesNamesByIdUser(dtos[i].Id);
- return dtos;
- }
-
- public UserExtendedDto GetOrDefault(int id)
- {
- var entity = cacheUsers.FirstOrDefault(u => u.Id == id);
- var dto = Convert(entity);
- dto.RoleNames = GetRolesNamesByIdUser(dto.Id);
- return dto;
- }
-
- public async Task GetOrDefaultAsync(int id, CancellationToken token = default)
- {
- var entity = await cacheUsers.FirstOrDefaultAsync(u => u.Id == id, token).ConfigureAwait(false);
- var dto = Convert(entity);
- dto.RoleNames = GetRolesNamesByIdUser(dto.Id);
- return dto;
- }
-
- public async Task UpdateAsync(UserExtendedDto dto, CancellationToken token = default)
- {
- if (dto.Id <= 1)
- throw new ArgumentInvalidException($"Invalid id {dto.Id}. You can't edit this user.", nameof(dto));
-
- var oldUser = await cacheUsers.FirstOrDefaultAsync(u => u.Id == dto.Id, token);
- if (oldUser.Login != dto.Login)
- await AssertLoginIsBusyAsync(dto.Login, token);
-
- var userRoles = await RoleService.GetByNamesAsync(dto.RoleNames, token).ConfigureAwait(false);
- await UpdateRolesCacheForUserAsync(dto.Id, userRoles, token);
-
- var entity = Convert(dto);
-
- var result = await cacheUsers.UpsertAsync(entity, token)
- .ConfigureAwait(false);
- return result;
- }
-
- public Task DeleteAsync(int id, CancellationToken token = default)
- {
- if (id <= 1)
- return Task.FromResult(0);
- return cacheUsers.RemoveAsync(r => r.Id == id, token);
- }
-
- public Task DeleteAsync(IEnumerable ids, CancellationToken token = default)
- {
- var filteredIds = ids.Where(i => i > 1).ToList();
- return cacheUsers.RemoveAsync(r => filteredIds.Contains(r.Id), token);
- }
-
- private IEnumerable GetRolesNamesByIdUser(int idUser)
- => GetRolesByIdUser(idUser)
- ?.Select(r => r.Caption)
- .Distinct();
-
- public IEnumerable GetRolesByIdUser(int idUser, int nestedLevel = 0)
- {
- var roles = cacheRelationUserToRoles.Where(r => r.IdUser == idUser);
- if (roles?.Any() != true)
- return null;
- return roles.SelectMany(r => RoleService.GetNestedById(r.IdUserRole, nestedLevel));
- }
-
- public IEnumerable GetNestedPermissions(int idUser)
- {
- var roles = GetRolesByIdUser(idUser, 7);
- if (roles?.Any() != true)
- return null;
- var permissions = roles
- .Where(r => r.Permissions is not null)
- .SelectMany(r => r.Permissions);
-
- return permissions;
- }
-
- private async Task UpdateRolesCacheForUserAsync(int idUser, IEnumerable newRoles, CancellationToken token)
- {
- await cacheRelationUserToRoles.RemoveAsync(r => r.IdUser == idUser, 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 HasPermission(int idUser, string permissionName)
- {
- if (idUser == 1)
- return true;
-
- var relationsToRoles = cacheRelationUserToRoles.Where(r => r.IdUser == idUser);
- if (relationsToRoles is null)
- return false;
-
- return RoleService.HasPermission(relationsToRoles.Select(r => r.IdUserRole),
- permissionName);
- }
-
- protected virtual User Convert(UserExtendedDto dto)
- {
- var entity = dto.Adapt(userTypeAdapterConfig);
- if (string.IsNullOrEmpty(entity.PasswordHash))
- entity.PasswordHash = cacheUsers.FirstOrDefault(u => u.Id == dto.Id)?.PasswordHash;
- return entity;
- }
-
- protected virtual UserExtendedDto Convert(User entity)
- {
- var dto = entity.Adapt();
- return dto;
- }
- }
-}
diff --git a/AsbCloudInfrastructure/Services/WellFinalDocumentsService.cs b/AsbCloudInfrastructure/Services/WellFinalDocumentsService.cs
index 4d44f38c..c82b9f7a 100644
--- a/AsbCloudInfrastructure/Services/WellFinalDocumentsService.cs
+++ b/AsbCloudInfrastructure/Services/WellFinalDocumentsService.cs
@@ -1,5 +1,6 @@
using AsbCloudApp.Data;
using AsbCloudApp.Exceptions;
+using AsbCloudApp.Repositories;
using AsbCloudApp.Requests;
using AsbCloudApp.Services;
using AsbCloudDb.Model;
@@ -24,7 +25,7 @@ namespace AsbCloudInfrastructure.Services
{
private readonly IAsbCloudDbContext context;
private readonly FileService fileService;
- private readonly IUserService userService;
+ private readonly IUserRepository userRepository;
private readonly IWellService wellService;
private readonly IConfiguration configuration;
private readonly IEmailService emailService;
@@ -34,7 +35,7 @@ namespace AsbCloudInfrastructure.Services
public WellFinalDocumentsService(IAsbCloudDbContext context,
FileService fileService,
- IUserService userService,
+ IUserRepository userRepository,
IWellService wellService,
IConfiguration configuration,
IEmailService emailService,
@@ -42,7 +43,7 @@ namespace AsbCloudInfrastructure.Services
{
this.context = context;
this.fileService = fileService;
- this.userService = userService;
+ this.userRepository = userRepository;
this.wellService = wellService;
this.configuration = configuration;
this.emailService = emailService;
@@ -120,7 +121,7 @@ namespace AsbCloudInfrastructure.Services
var result = new WellCaseDto
{
IdWell = idWell,
- PermissionToSetPubliher = userService.HasPermission(idUser, "WellFinalDocument.editPublisher"),
+ PermissionToSetPubliher = userRepository.HasPermission(idUser, "WellFinalDocument.editPublisher"),
WellFinalDocuments = docs,
};
return result;
@@ -133,7 +134,7 @@ namespace AsbCloudInfrastructure.Services
.ToListAsync(token)
.ConfigureAwait(false);
- var allUsers = await userService.GetAllAsync(token)
+ var allUsers = await userRepository.GetAllAsync(token)
.ConfigureAwait(false);
return allUsers.Where(x => {
@@ -181,7 +182,7 @@ namespace AsbCloudInfrastructure.Services
{
foreach (var item in dtos)
{
- var user = await userService.GetOrDefaultAsync(item.IdUser, token);
+ var user = await userRepository.GetOrDefaultAsync(item.IdUser, token);
if (user?.Email is not null)
{
var category = await fileCategoryService.GetOrDefaultAsync(item.IdCategory, token);
diff --git a/AsbCloudWebApi.Tests/ServicesTests/DrillingProgramServiceTest.cs b/AsbCloudWebApi.Tests/ServicesTests/DrillingProgramServiceTest.cs
index a1e275b9..2c829eb4 100644
--- a/AsbCloudWebApi.Tests/ServicesTests/DrillingProgramServiceTest.cs
+++ b/AsbCloudWebApi.Tests/ServicesTests/DrillingProgramServiceTest.cs
@@ -1,4 +1,5 @@
using AsbCloudApp.Data;
+using AsbCloudApp.Repositories;
using AsbCloudApp.Services;
using AsbCloudDb.Model;
using AsbCloudInfrastructure.Repository;
@@ -79,7 +80,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests
};
private readonly Mock fileServiceMock;
- private readonly Mock userServiceMock;
+ private readonly Mock userRepositoryMock;
private readonly Mock wellServiceMock;
private readonly Mock configurationMock;
private readonly Mock backgroundWorkerMock;
@@ -98,7 +99,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests
db.SaveChanges();
fileServiceMock = new Mock();
- userServiceMock = new Mock();
+ userRepositoryMock = new Mock();
wellServiceMock = new Mock();
configurationMock = new Mock();
backgroundWorkerMock = new Mock();
@@ -110,7 +111,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests
var service = new DrillingProgramService(
db,
fileServiceMock.Object,
- userServiceMock.Object,
+ userRepositoryMock.Object,
wellServiceMock.Object,
configurationMock.Object,
backgroundWorkerMock.Object,
@@ -127,7 +128,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests
var service = new DrillingProgramService(
db,
fileServiceMock.Object,
- userServiceMock.Object,
+ userRepositoryMock.Object,
wellServiceMock.Object,
configurationMock.Object,
backgroundWorkerMock.Object,
@@ -146,7 +147,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests
var service = new DrillingProgramService(
db,
fileServiceMock.Object,
- userServiceMock.Object,
+ userRepositoryMock.Object,
wellServiceMock.Object,
configurationMock.Object,
backgroundWorkerMock.Object,
@@ -163,13 +164,13 @@ namespace AsbCloudWebApi.Tests.ServicesTests
db.DrillingProgramParts.Add(new DrillingProgramPart { IdFileCategory = 1001, IdWell = idWell });
db.SaveChanges();
- userServiceMock.Setup((s) => s.GetOrDefaultAsync(It.IsAny(), It.IsAny()))
+ userRepositoryMock.Setup((s) => s.GetOrDefaultAsync(It.IsAny(), It.IsAny()))
.Returns(Task.FromResult(publisher1.Adapt()));
var service = new DrillingProgramService(
db,
fileServiceMock.Object,
- userServiceMock.Object,
+ userRepositoryMock.Object,
wellServiceMock.Object,
configurationMock.Object,
backgroundWorkerMock.Object,
@@ -198,13 +199,13 @@ namespace AsbCloudWebApi.Tests.ServicesTests
IdUserRole = idUserRole
});
db.SaveChanges();
- userServiceMock.Setup((s) => s.GetOrDefaultAsync(It.IsAny(), It.IsAny()))
+ userRepositoryMock.Setup((s) => s.GetOrDefaultAsync(It.IsAny(), It.IsAny()))
.Returns(Task.FromResult(publisher1.Adapt()));
var service = new DrillingProgramService(
db,
fileServiceMock.Object,
- userServiceMock.Object,
+ userRepositoryMock.Object,
wellServiceMock.Object,
configurationMock.Object,
backgroundWorkerMock.Object,
@@ -230,7 +231,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests
var service = new DrillingProgramService(
db,
fileServiceMock.Object,
- userServiceMock.Object,
+ userRepositoryMock.Object,
wellServiceMock.Object,
configurationMock.Object,
backgroundWorkerMock.Object,
@@ -261,7 +262,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests
var service = new DrillingProgramService(
db,
fileServiceMock.Object,
- userServiceMock.Object,
+ userRepositoryMock.Object,
wellServiceMock.Object,
configurationMock.Object,
backgroundWorkerMock.Object,
@@ -299,7 +300,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests
var service = new DrillingProgramService(
db,
fileServiceMock.Object,
- userServiceMock.Object,
+ userRepositoryMock.Object,
wellServiceMock.Object,
configurationMock.Object,
backgroundWorkerMock.Object,
@@ -326,7 +327,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests
var service = new DrillingProgramService(
db,
fileServiceMock.Object,
- userServiceMock.Object,
+ userRepositoryMock.Object,
wellServiceMock.Object,
configurationMock.Object,
backgroundWorkerMock.Object,
@@ -353,7 +354,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests
var service = new DrillingProgramService(
db,
fileServiceMock.Object,
- userServiceMock.Object,
+ userRepositoryMock.Object,
wellServiceMock.Object,
configurationMock.Object,
backgroundWorkerMock.Object,
@@ -383,7 +384,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests
var service = new DrillingProgramService(
db,
fileServiceMock.Object,
- userServiceMock.Object,
+ userRepositoryMock.Object,
wellServiceMock.Object,
configurationMock.Object,
backgroundWorkerMock.Object,
diff --git a/AsbCloudWebApi.Tests/ServicesTests/UserServiceTest.cs b/AsbCloudWebApi.Tests/ServicesTests/UserServiceTest.cs
deleted file mode 100644
index bd47b853..00000000
--- a/AsbCloudWebApi.Tests/ServicesTests/UserServiceTest.cs
+++ /dev/null
@@ -1,76 +0,0 @@
-using AsbCloudApp.Data;
-using AsbCloudApp.Repositories;
-using AsbCloudApp.Services;
-using AsbCloudDb.Model;
-using AsbCloudInfrastructure.Services;
-using AsbCloudInfrastructure.Services.Cache;
-using Moq;
-using System;
-using System.Linq;
-using System.Threading;
-using System.Threading.Tasks;
-using Xunit;
-
-namespace AsbCloudWebApi.Tests.ServicesTests
-{
- public class UserServiceTest
- {
- private readonly AsbCloudDbContext context;
- private readonly CacheDb cacheDb;
- private readonly Mock roleRepository;
-
- public UserServiceTest()
- {
- context = TestHelpter.MakeTestContext();
- cacheDb = new CacheDb();
- roleRepository = new Mock();
-
- context.Users.RemoveRange(context.Users.Where(u => u.Id > 1));
- context.SaveChanges();
- }
-
- ~UserServiceTest()
- {
- context.Users.RemoveRange(context.Users.Where(u => u.Id > 1));
- context.SaveChanges();
- }
-
- [Fact]
- public async Task InsertAsync_returns_id()
- {
- var service = new UserService(context, cacheDb, roleRepository.Object);
- var dto = new UserExtendedDto
- {
- Id = 0,
- IdCompany = 1,
- Email = "test@test.test",
- Login = "test",
- Name = "test",
- Company = new CompanyDto { Caption = "test", Id = 1 },
- Patronymic = "test",
- Phone = "test",
- Position = "test",
- Surname = "test",
-
- };
- var id = await service.InsertAsync(dto, CancellationToken.None);
-
- Assert.NotEqual(0, id);
- }
-
- [Fact]
- public async Task InsertAsync_busy_login_throws_exceprion()
- {
- var service = new UserService(context, cacheDb, roleRepository.Object);
- var dto = new UserExtendedDto
- {
- Id = 5,
- Email = "test@test.test",
- Login = "test clone"
- };
-
- await service.InsertAsync(dto, CancellationToken.None);
- await Assert.ThrowsAsync(() => service.InsertAsync(dto, CancellationToken.None));
- }
- }
-}
diff --git a/AsbCloudWebApi.Tests/ServicesTests/WellFinalDocumentsServiceTest.cs b/AsbCloudWebApi.Tests/ServicesTests/WellFinalDocumentsServiceTest.cs
index 1718b92d..eb0d0a89 100644
--- a/AsbCloudWebApi.Tests/ServicesTests/WellFinalDocumentsServiceTest.cs
+++ b/AsbCloudWebApi.Tests/ServicesTests/WellFinalDocumentsServiceTest.cs
@@ -10,6 +10,8 @@ using Xunit;
using System.IO;
using System.Collections.Generic;
using System.Linq;
+using AsbCloudApp.Repositories;
+using AsbCloudInfrastructure.Repository;
namespace AsbCloudWebApi.Tests.ServicesTests
{
@@ -18,7 +20,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests
private readonly AsbCloudDbContext context;
private WellFinalDocumentsService service;
private readonly Mock fileServiceMock;
- private readonly Mock userServiceMock;
+ private readonly Mock userRepositoryMock;
private readonly Mock wellServiceMock;
private readonly Mock configurationMock;
private readonly Mock emailServiceMock;
@@ -45,8 +47,8 @@ namespace AsbCloudWebApi.Tests.ServicesTests
context.SaveChanges();
fileServiceMock = new Mock();
- userServiceMock = new Mock();
- userServiceMock.Setup(x => x.GetAllAsync(CancellationToken.None)).Returns(Task.Run(() => users.Select(x => (UserExtendedDto)x)));
+ userRepositoryMock = new Mock();
+ userRepositoryMock.Setup(x => x.GetAllAsync(CancellationToken.None)).Returns(Task.Run(() => users.Select(x => (UserExtendedDto)x)));
wellServiceMock = new Mock();
configurationMock = new Mock();
@@ -56,7 +58,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests
service = new WellFinalDocumentsService(
context: context,
fileService: fileServiceMock.Object,
- userService: userServiceMock.Object,
+ userRepository: userRepositoryMock.Object,
wellService: wellServiceMock.Object,
configuration: configurationMock.Object,
emailService: emailServiceMock.Object,
diff --git a/AsbCloudWebApi/Controllers/AdminUserController.cs b/AsbCloudWebApi/Controllers/AdminUserController.cs
index e515d370..0ce262d0 100644
--- a/AsbCloudWebApi/Controllers/AdminUserController.cs
+++ b/AsbCloudWebApi/Controllers/AdminUserController.cs
@@ -1,5 +1,7 @@
using AsbCloudApp.Data;
+using AsbCloudApp.Repositories;
using AsbCloudApp.Services;
+using AsbCloudInfrastructure.Repository;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
@@ -13,7 +15,7 @@ namespace AsbCloudWebApi.Controllers
[Authorize]
public class AdminUserController : CrudController>
{
- public AdminUserController(IUserService service)
+ public AdminUserController(IUserRepository service)
: base(service)
{ }
diff --git a/AsbCloudWebApi/Controllers/AuthController.cs b/AsbCloudWebApi/Controllers/AuthController.cs
index aeec1f81..b2702f81 100644
--- a/AsbCloudWebApi/Controllers/AuthController.cs
+++ b/AsbCloudWebApi/Controllers/AuthController.cs
@@ -1,5 +1,7 @@
using AsbCloudApp.Data;
+using AsbCloudApp.Repositories;
using AsbCloudApp.Services;
+using AsbCloudInfrastructure.Repository;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Swashbuckle.AspNetCore.Annotations;
@@ -16,12 +18,12 @@ namespace AsbCloudWebApi.Controllers
public class AuthController : ControllerBase
{
private readonly IAuthService authService;
- private readonly IUserService userService;
+ private readonly IUserRepository userRepository;
- public AuthController(IAuthService authService, IUserService userService)
+ public AuthController(IAuthService authService, IUserRepository userRepository)
{
this.authService = authService;
- this.userService = userService;
+ this.userRepository = userRepository;
}
///
@@ -97,7 +99,7 @@ namespace AsbCloudWebApi.Controllers
if (editorUserId is null)
return Forbid();
- if (!((editorUserId == idUser) || userService.HasPermission((int)editorUserId, "Auth.edit")))
+ if (!((editorUserId == idUser) || userRepository.HasPermission((int)editorUserId, "Auth.edit")))
return Forbid();
var code = authService.ChangePassword(idUser, newPassword);
diff --git a/AsbCloudWebApi/Controllers/FileController.cs b/AsbCloudWebApi/Controllers/FileController.cs
index d4dfad33..1340c55a 100644
--- a/AsbCloudWebApi/Controllers/FileController.cs
+++ b/AsbCloudWebApi/Controllers/FileController.cs
@@ -8,6 +8,8 @@ using System.IO;
using System.Threading;
using System.Threading.Tasks;
using AsbCloudDb.Model;
+using AsbCloudInfrastructure.Repository;
+using AsbCloudApp.Repositories;
namespace AsbCloudWebApi.Controllers
{
@@ -42,7 +44,7 @@ namespace AsbCloudWebApi.Controllers
[Permission]
[ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)]
public async Task SaveFilesAsync(int idWell, int idCategory,
- [FromForm] IFormFileCollection files, [FromServices] IUserService userService, CancellationToken token = default)
+ [FromForm] IFormFileCollection files, [FromServices] IUserRepository userRepository, CancellationToken token = default)
{
int? idCompany = User.GetCompanyId();
int? idUser = User.GetUserId();
@@ -54,7 +56,7 @@ namespace AsbCloudWebApi.Controllers
idWell, token).ConfigureAwait(false))
return Forbid();
- if (!userService.HasPermission((int)idUser, $"File.edit{idCategory}"))
+ if (!userRepository.HasPermission((int)idUser, $"File.edit{idCategory}"))
return Forbid();
foreach (var file in files)
@@ -140,7 +142,7 @@ namespace AsbCloudWebApi.Controllers
[Permission]
[ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)]
public async Task DeleteAsync(int idWell, int idFile,
- [FromServices] IUserService userService,
+ [FromServices] IUserRepository userRepository,
CancellationToken token = default)
{
int? idUser = User.GetUserId();
@@ -156,7 +158,7 @@ namespace AsbCloudWebApi.Controllers
if (fileInfo is null)
return NotFound(idFile);
- if (!userService.HasPermission((int)idUser, $"File.edit{fileInfo?.IdCategory}"))
+ if (!userRepository.HasPermission((int)idUser, $"File.edit{fileInfo?.IdCategory}"))
return Forbid();
var result = await fileService.MarkAsDeletedAsync(idFile, token);
diff --git a/AsbCloudWebApi/Middlewares/PermissionsMiddlware.cs b/AsbCloudWebApi/Middlewares/PermissionsMiddlware.cs
index 5373cf64..4f05c7d2 100644
--- a/AsbCloudWebApi/Middlewares/PermissionsMiddlware.cs
+++ b/AsbCloudWebApi/Middlewares/PermissionsMiddlware.cs
@@ -1,4 +1,5 @@
-using AsbCloudApp.Services;
+using AsbCloudApp.Repositories;
+using AsbCloudApp.Services;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
@@ -69,7 +70,7 @@ namespace AsbCloudWebApi.Middlewares
PermissionAttribute.Registered.Add(permissionName);
}
- var userService = context.RequestServices.GetRequiredService();
+ var userService = context.RequestServices.GetRequiredService();
isAuthorized = userService.HasPermission((int)idUser, permissionName);
}