using Brizco.Domain.Entities.Complexes; using Brizco.Domain.Entities.Users; namespace Brizco.Core.EntityServices; public class UserService( ICurrentUserService currentUserService, UserManager userManager, RoleManager roleManager, ISender sender, IRepositoryWrapper repositoryWrapper, IJwtService jwtService) : IUserService { 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); if (user.SignUpStatus < SignUpStatus.ComplexCreated) throw new UnauthorizedAccessException("SignUp is not completed"); 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); if (!Guid.TryParse(currentUserService.ComplexId, out var complexId)) throw new AppException("Wrong Token", ApiResultStatusCode.UnAuthorized); AccessToken jwt; var complexUser = await repositoryWrapper.SetRepository() .TableNoTracking .Where(mcu => mcu.UserId == userId && mcu.ComplexId == complexId) .Select(ComplexUserMapper.ProjectToSDto) .FirstOrDefaultAsync(cancellationToken); if (complexUser == null) throw new AppException("User role is wrong", ApiResultStatusCode.BadRequest); 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 user = await userManager.FindByIdAsync(userId.ToString()); if (user == null) throw new AppException("User not found", ApiResultStatusCode.NotFound); 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(); if (currentUserService.ComplexId == null || !Guid.TryParse(currentUserService.ComplexId, out Guid complexId)) { 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); } } else { var complexUser = await repositoryWrapper.SetRepository().TableNoTracking .FirstOrDefaultAsync(c => c.UserId == userId && c.ComplexId == complexId); if (complexUser == null) throw new AppException("ComplexUser not found", ApiResultStatusCode.NotFound); var complexUserRoles = await repositoryWrapper.SetRepository() .TableNoTracking .Where(cur => cur.ComplexUserId == complexUser.Id) .ToListAsync(); foreach (var userRole in complexUserRoles) { dto.RoleIds.Add(userRole.RoleId); } } 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; } }