using System.Security.Claims; using Brizco.Domain.CommandQueries.Queries; using Brizco.Domain.Entities.Complex; using Brizco.Domain.Mappers; using Mapster; namespace Brizco.Core.EntityServices; public class UserService : IUserService { private readonly ICurrentUserService _currentUserService; private readonly UserManager _userManager; private readonly RoleManager _roleManager; private readonly ISender _sender; private readonly IRepositoryWrapper _repositoryWrapper; private readonly IJwtService _jwtService; public UserService(ICurrentUserService currentUserService, UserManager userManager, RoleManager roleManager, ISender sender, IRepositoryWrapper repositoryWrapper, IJwtService jwtService) { _currentUserService = currentUserService; _userManager = userManager; _roleManager = roleManager; _sender = sender; _repositoryWrapper = repositoryWrapper; _jwtService = jwtService; } public async Task GetUserProfileAsync(CancellationToken cancellationToken) { if (!Guid.TryParse(_currentUserService.UserId, out var userId)) throw new AppException("Wrong Token", ApiResultStatusCode.UnAuthorized); var user = await _userManager.FindByIdAsync(userId.ToString()); if (user == null) throw new AppException("User NotFound", ApiResultStatusCode.NotFound); var response = new ProfileResponseDto(); var userSDto = user.AdaptToSDto(); var complexUsers = await GetUserRolesAsync(cancellationToken); response.User = userSDto; if (user.SelectedComplexUserRoleId != Guid.Empty) { var complexUserRole = complexUsers.FirstOrDefault(cu => cu.Id == user.SelectedComplexUserRoleId); userSDto.SelectedComplexName = complexUserRole!.ComplexName; userSDto.SelectedRoleName = complexUserRole!.RoleName; response.User.SelectedRoleId = complexUserRole!.Id; var role = await _roleManager.FindByIdAsync(complexUserRole.RoleId.ToString()); if (role != null) { var roleClaims = await _roleManager.GetClaimsAsync(role); response.Permissions = roleClaims.Where(c => c.Type == "Permission").Select(c => c.Value).ToList(); } } else { var complexUserRole = complexUsers.FirstOrDefault(); if (complexUserRole != null) { user.SelectedComplexUserRoleId = complexUserRole.Id; await _userManager.UpdateAsync(user); userSDto.SelectedComplexName = complexUserRole!.ComplexName; userSDto.SelectedRoleName = complexUserRole!.RoleName; response.User.SelectedRoleId = complexUserRole!.Id; var role = await _roleManager.FindByIdAsync(complexUserRole.RoleId.ToString()); if (role != null) { var roleClaims = await _roleManager.GetClaimsAsync(role); response.Permissions = roleClaims.Where(c => c.Type == "Permission").Select(c => c.Value).ToList(); } } } response.Roles = complexUsers; return response; } public async Task> ChangeUserRoleAsync(Guid roleId, CancellationToken cancellationToken) { if (!Guid.TryParse(_currentUserService.UserId, out var userId)) throw new AppException("Wrong Token", ApiResultStatusCode.UnAuthorized); AccessToken jwt; var complexUserRole = await _repositoryWrapper.SetRepository() .TableNoTracking .Where(c => c.Id == roleId) .Select(ComplexUserRoleMapper.ProjectToSDto) .FirstOrDefaultAsync(cancellationToken); if (complexUserRole == null) throw new AppException("Role not found", ApiResultStatusCode.NotFound); var complexUser = await _repositoryWrapper.SetRepository() .TableNoTracking .Where(mcu => mcu.Id == complexUserRole.ComplexUserId) .Select(ComplexUserMapper.ProjectToSDto) .FirstOrDefaultAsync(cancellationToken); var user = await _userManager.FindByIdAsync(userId.ToString()); if (user == null) throw new AppException("User not found", ApiResultStatusCode.NotFound); if (complexUser?.UserId != user.Id) throw new AppException("User role is wrong", ApiResultStatusCode.BadRequest); user.SelectedComplexUserRoleId = complexUserRole.Id; await _userManager.UpdateAsync(user); jwt = (await _jwtService.Generate(user, complexUser.ComplexId, complexUserRole.RoleId)).Adapt>(); jwt.User.SelectedComplexName = complexUser.ComplexName; jwt.User.SelectedRoleName = complexUserRole.RoleName; jwt.User.SelectedRoleId = complexUserRole.Id; jwt.Roles = await GetUserRolesAsync(cancellationToken); return jwt; } public async Task> GetUserRolesAsync(CancellationToken cancellationToken) { if (!Guid.TryParse(_currentUserService.UserId, out var userId)) throw new AppException("Wrong Token", ApiResultStatusCode.UnAuthorized); var user = await _userManager.FindByIdAsync(userId.ToString()); if (user == null) throw new AppException("User NotFound", ApiResultStatusCode.NotFound); var response = new List(); var complexUsers = await _repositoryWrapper.SetRepository() .TableNoTracking .Where(mcu => mcu.UserId == user.Id) .Select(ComplexUserMapper.ProjectToSDto) .ToListAsync(cancellationToken); if (complexUsers.Count == 0) return response; foreach (var complexUser in complexUsers) { var complexUserRoles = await _repositoryWrapper.SetRepository() .TableNoTracking .Where(c => c.ComplexUserId == complexUser.Id) .Select(ComplexUserRoleMapper.ProjectToSDto) .ToListAsync(cancellationToken); foreach (var userRole in complexUserRoles) { userRole.ComplexName = complexUser.ComplexName; response.Add(userRole); } } return response; } public async Task> GetUserRolesAsync(Guid userId,CancellationToken cancellationToken) { var user = await _userManager.FindByIdAsync(userId.ToString()); if (user == null) throw new AppException("User NotFound", ApiResultStatusCode.NotFound); var response = new List(); var complexUsers = await _repositoryWrapper.SetRepository() .TableNoTracking .Where(mcu => mcu.UserId == user.Id) .Select(ComplexUserMapper.ProjectToSDto) .ToListAsync(cancellationToken); if (complexUsers.Count == 0) return response; foreach (var complexUser in complexUsers) { var complexUserRoles = await _repositoryWrapper.SetRepository() .TableNoTracking .Where(c => c.ComplexUserId == complexUser.Id) .Select(ComplexUserRoleMapper.ProjectToSDto) .ToListAsync(cancellationToken); foreach (var userRole in complexUserRoles) { userRole.ComplexName = complexUser.ComplexName; response.Add(userRole); } } return response; } public async Task> GetUsersAsync(int page = 0, CancellationToken cancellationToken = default) { if (_currentUserService.ComplexId.IsNullOrEmpty()) throw new AppException("Wrong authorize token , ComplexId needed"); if (!Guid.TryParse(_currentUserService.ComplexId, out Guid complexId)) throw new AppException("Wrong authorize token , ComplexId needed"); var complexUsers = await _sender.Send(new GetComplexUsersQuery(complexId.ToString(), page), cancellationToken); return complexUsers; } public async Task GetUserAsync(Guid userId) { var user = await _userManager.FindByIdAsync(userId.ToString()); if (user == null) throw new AppException("User not found", ApiResultStatusCode.NotFound); var dto = user.AdaptToSDto(); var roles = await _userManager.GetRolesAsync(user); foreach (var roleName in roles) { var role = await _roleManager.FindByNameAsync(roleName); if (role != null) dto.RoleIds.Add(role.Id); } return dto; } public async Task CreateUserAsync(string phoneNumber) { var user = new ApplicationUser { UserName = phoneNumber, PhoneNumber = phoneNumber, SignUpStatus = SignUpStatus.StartSignOn }; var result = await _userManager.CreateAsync(user); if (!result.Succeeded) throw new AppException(string.Join('|', result.Errors)); return user; } public async Task CreateUserAsync(UserActionRequestDto request, CancellationToken cancellationToken) { if (_currentUserService.ComplexId.IsNullOrEmpty()) throw new AppException("Wrong authorize token , ComplexId needed"); if (!Guid.TryParse(_currentUserService.ComplexId, out Guid complexId)) throw new AppException("Wrong authorize token , ComplexId needed"); var user = await _userManager.FindByNameAsync(request.PhoneNumber); if (user == null) { user = new ApplicationUser { UserName = request.PhoneNumber, PhoneNumber = request.PhoneNumber, FirstName = request.FirstName, LastName = request.LastName, NationalId = request.NationalId, BirthDate = DateTimeExtensions.UnixTimeStampToDateTime(request.BirthDateTimeStamp), Gender = request.Gender, SignUpStatus = SignUpStatus.SignUpCompleted, PhoneNumberConfirmed = true }; if (!request.Password.IsNullOrEmpty()) { var result = await _userManager.CreateAsync(user, request.Password); if (!result.Succeeded) throw new AppException(string.Join('|', result.Errors.Select(e => e.Description))); } else { var result = await _userManager.CreateAsync(user); if (!result.Succeeded) throw new AppException(string.Join('|', result.Errors.Select(e => e.Description))); } } await _sender.Send(new CreateComplexUserCommand(complexId, user.Id, request.RoleIds), cancellationToken); return user; } public async Task EditUserAsync(UserActionRequestDto request, CancellationToken cancellationToken) { if (_currentUserService.ComplexId.IsNullOrEmpty()) throw new AppException("Wrong authorize token , ComplexId needed"); if (!Guid.TryParse(_currentUserService.ComplexId, out Guid complexId)) throw new AppException("Wrong authorize token , ComplexId needed"); if (request.UserId == Guid.Empty) throw new AppException("Wrong authorize token , UserId needed"); var user = await _userManager.FindByIdAsync(request.UserId.ToString()); if (user == null) throw new AppException("User not found", ApiResultStatusCode.NotFound); user.LastName = request.LastName; user.FirstName = request.FirstName; user.UserName = request.PhoneNumber; user.PhoneNumber = request.PhoneNumber; user.FirstName = request.FirstName; user.LastName = request.LastName; user.NationalId = request.NationalId; user.BirthDate = DateTimeExtensions.UnixTimeStampToDateTime(request.BirthDateTimeStamp); user.Gender = request.Gender; var result = await _userManager.UpdateAsync(user); if (!result.Succeeded) throw new AppException(string.Join('|', result.Errors.Select(e => e.Description))); if (!request.Password.IsNullOrEmpty()) { if (await _userManager.HasPasswordAsync(user)) await _userManager.RemovePasswordAsync(user); var addPassResult = await _userManager.AddPasswordAsync(user, request.Password); if (!addPassResult.Succeeded) throw new AppException(string.Join('|', addPassResult.Errors.Select(e => e.Description))); } await _sender.Send(new UpdateComplexUserCommand(user.Id, complexId, request.RoleIds), cancellationToken); return true; } public async Task EditUserProfileAsync(UserActionRequestDto request, CancellationToken cancellationToken) { if (_currentUserService.UserId == null) throw new AppException("Wrong authorize token , UserId needed"); var user = await _userManager.FindByIdAsync(_currentUserService.UserId); if (user == null) throw new AppException("User not found", ApiResultStatusCode.NotFound); user.LastName = request.LastName; user.FirstName = request.FirstName; user.UserName = request.PhoneNumber; user.PhoneNumber = request.PhoneNumber; user.FirstName = request.FirstName; user.LastName = request.LastName; user.NationalId = request.NationalId; user.BirthDate = DateTimeExtensions.UnixTimeStampToDateTime(request.BirthDateTimeStamp); user.Gender = request.Gender; var result = await _userManager.UpdateAsync(user); if (!result.Succeeded) throw new AppException(string.Join('|', result.Errors.Select(e => e.Description))); if (!request.Password.IsNullOrEmpty()) { if (await _userManager.HasPasswordAsync(user)) await _userManager.RemovePasswordAsync(user); var addPassResult = await _userManager.AddPasswordAsync(user, request.Password); if (!addPassResult.Succeeded) throw new AppException(string.Join('|', addPassResult.Errors.Select(e => e.Description))); } return true; } public async Task RemoveUserAsync(Guid userId, CancellationToken cancellationToken) { if (_currentUserService.ComplexId.IsNullOrEmpty()) throw new AppException("Wrong authorize token , ComplexId needed"); if (!Guid.TryParse(_currentUserService.ComplexId, out Guid complexId)) throw new AppException("Wrong authorize token , ComplexId needed"); var user = await _userManager.FindByIdAsync(userId.ToString()); if (user == null) throw new AppException("User not found", ApiResultStatusCode.NotFound); var roles = await _userManager.GetRolesAsync(user); await _userManager.RemoveFromRolesAsync(user, roles); await _sender.Send(new DeleteComplexUserCommand(userId, complexId), cancellationToken); var removeResult = await _userManager.DeleteAsync(user); if (!removeResult.Succeeded) throw new AppException(string.Join('|', removeResult.Errors.Select(e => e.Description))); return true; } public async Task RemoveUserFromComplexAsync(Guid userId, CancellationToken cancellationToken) { if (_currentUserService.ComplexId.IsNullOrEmpty()) throw new AppException("Wrong authorize token , ComplexId needed"); if (!Guid.TryParse(_currentUserService.ComplexId, out Guid complexId)) throw new AppException("Wrong authorize token , ComplexId needed"); var user = await _userManager.FindByIdAsync(userId.ToString()); if (user == null) throw new AppException("User not found", ApiResultStatusCode.NotFound); await _sender.Send(new DeleteComplexUserCommand(userId, complexId), cancellationToken); return true; } public async Task> GetRolesAsync(int page = 0, CancellationToken cancellationToken = default) { if (_currentUserService.ComplexId.IsNullOrEmpty()) throw new AppException("Wrong authorize token , ComplexId needed"); if (!Guid.TryParse(_currentUserService.ComplexId, out Guid complexId)) throw new AppException("Wrong authorize token , ComplexId needed"); var roles = await _roleManager.Roles .Where(r => r.ComplexId == complexId) .Skip(page * 15) .Take(15) .ToListAsync(cancellationToken); return roles; } public async Task GetRoleAsync(Guid roleId) { var role = (await _roleManager.FindByIdAsync(roleId.ToString())); if (role == null) throw new AppException("نقش پیدا نشد", ApiResultStatusCode.NotFound); var roleDto = role.Adapt(); roleDto.RoleId = roleId; roleDto.Permissions = (await _roleManager.GetClaimsAsync(role)) .Where(c => c.Type == CustomClaimType.Permission) .Select(c => c.Value) .ToList(); return roleDto; } public async Task CreateRoleAsync(RoleActionRequestDto request) { if (_currentUserService.ComplexId.IsNullOrEmpty()) throw new AppException("Wrong authorize token , ComplexId needed"); if (!Guid.TryParse(_currentUserService.ComplexId, out Guid complexId)) throw new AppException("Wrong authorize token , ComplexId wrong"); if (request.EnglishName.IsNullOrEmpty()) throw new AppException("لطفا نام انگلیسی را وارد کنید"); var applicationRole = new ApplicationRole { ComplexId = complexId, EnglishName = request.EnglishName, PersianName = request.PersianName, Description = request.Description, Name = $"{request.EnglishName}_{complexId.ToString()}" }; var createRoleResult = await _roleManager.CreateAsync(applicationRole); if (!createRoleResult.Succeeded) throw new AppException(string.Join('|', createRoleResult.Errors)); foreach (var claim in request.Permissions) await _roleManager.AddClaimAsync(applicationRole, new Claim(CustomClaimType.Permission, claim)); return applicationRole; } public async Task EditRoleAsync(RoleActionRequestDto request) { if (_currentUserService.ComplexId.IsNullOrEmpty()) throw new AppException("Wrong authorize token , ComplexId needed"); if (!Guid.TryParse(_currentUserService.ComplexId, out Guid complexId)) throw new AppException("Wrong authorize token , ComplexId wrong"); if (request.EnglishName.IsNullOrEmpty()) throw new AppException("لطفا نام انگلیسی را وارد کنید"); var applicationRole = await _roleManager.FindByIdAsync(request.RoleId.ToString()); if (applicationRole == null) throw new AppException("نقش پیدا نشد"); applicationRole.ComplexId = complexId; applicationRole.EnglishName = request.EnglishName; applicationRole.PersianName = request.PersianName; applicationRole.Description = request.Description; applicationRole.Name = $"{request.EnglishName}_{complexId.ToString()}"; var createRoleResult = await _roleManager.UpdateAsync(applicationRole); if (!createRoleResult.Succeeded) throw new AppException(string.Join('|', createRoleResult.Errors)); var roleClaims = (await _roleManager.GetClaimsAsync(applicationRole)).Where(c => c.Type == CustomClaimType.Permission).ToList(); foreach (var roleClaim in roleClaims.ToList()) { if (request.Permissions.Contains(roleClaim.Value)) { roleClaims.Remove(roleClaim); request.Permissions.Remove(roleClaim.Value); } } foreach (var claim in request.Permissions) await _roleManager.AddClaimAsync(applicationRole, new Claim(CustomClaimType.Permission, claim)); foreach (var claim in roleClaims) await _roleManager.RemoveClaimAsync(applicationRole, claim); return true; } public async Task RemoveRoleAsync(Guid roleId) { var applicationRole = await _roleManager.FindByIdAsync(roleId.ToString()); if (applicationRole == null) throw new AppException("User not found", ApiResultStatusCode.NotFound); var claims = await _roleManager.GetClaimsAsync(applicationRole); foreach (var claim in claims) await _roleManager.RemoveClaimAsync(applicationRole, claim); var users = await _userManager.GetUsersInRoleAsync(applicationRole.Name); foreach (var user in users) await _userManager.RemoveFromRoleAsync(user, applicationRole.Name); var complexRoles = await _repositoryWrapper.SetRepository() .TableNoTracking .Where(r => r.RoleId == applicationRole.Id) .ToListAsync(); foreach (var complexRole in complexRoles) { _repositoryWrapper.SetRepository() .HardDelete(complexRole); await _repositoryWrapper.SaveChangesAsync(default); } var removeResult = await _roleManager.DeleteAsync(applicationRole); if (!removeResult.Succeeded) throw new AppException(string.Join('|', removeResult.Errors.Select(e => e.Description))); return true; } public List GetPermissions() { return ApplicationClaims.AllClaimDtos; } }