namespace NetinaShop.Core.EntityServices; public class UserService : IUserService { private readonly ICurrentUserService _currentUserService; private readonly UserManager _userManager; private readonly RoleManager _roleManager; private readonly IExternalFilesService _externalFilesService; private readonly IRepositoryWrapper _repositoryWrapper; public UserService(ICurrentUserService currentUserService, UserManager userManager, RoleManager roleManager, IExternalFilesService externalFilesService, IRepositoryWrapper repositoryWrapper) { _currentUserService = currentUserService; _userManager = userManager; _roleManager = roleManager; _externalFilesService = externalFilesService; _repositoryWrapper = repositoryWrapper; } 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(); response.User = new ApplicationUserSDto(); var userRoles = await _userManager.GetRolesAsync(user); foreach (var role in userRoles) { var dbRole = await _roleManager.FindByNameAsync(role); if (dbRole != null) { var roleClaims = await _roleManager.GetClaimsAsync(dbRole); response.Permissions.AddRange(roleClaims.Where(c => c.Type == "Permission").Select(c => c.Value).ToList()); } } response.Roles = userRoles.ToList(); return response; } public async Task> GetUsersAsync(int page = 0, string? phoneNumber = null, CancellationToken cancellationToken = default) { List users; if (phoneNumber == null || phoneNumber.IsNullOrEmpty()) users = await _userManager.Users .Where(u => u.UserName != "09214802813") .Skip(page * 15).Take(15) .Select(ApplicationUserMapper.ProjectToSDto) .ToListAsync(cancellationToken); else users = await _userManager.Users .Where(a => a.PhoneNumber == phoneNumber && a.UserName != "09214802813") .Skip(page * 15).Take(15) .Select(ApplicationUserMapper.ProjectToSDto) .ToListAsync(cancellationToken); foreach (var user in users) { var roles = await _userManager.GetRolesAsync(user.AdaptToApplicationUser()); foreach (var roleName in roles) { var role = await _roleManager.FindByNameAsync(roleName); if (role != null) user.RoleName += role.PersianName + " "; } } var returnUser = users.Where(r => r.FullName.Trim() != "همه کاره سیستم").ToList(); return returnUser; } public async Task GetUserAsync(Guid userId, CancellationToken cancellationToken = default) { 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, CancellationToken cancellationToken = default) { 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) { 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))); } if (request.RoleIds.Count > 0) { foreach (var roleId in request.RoleIds) { var role = await _roleManager.FindByIdAsync(roleId.ToString()); if (role is { Name: not null }) await _userManager.AddToRoleAsync(user, role.Name); } } var customer = await _repositoryWrapper.SetRepository() .TableNoTracking .FirstOrDefaultAsync(c => c.UserId == user.Id, cancellationToken); if (customer != null) { _repositoryWrapper.SetRepository() .Add(new Customer { UserId = user.Id }); await _repositoryWrapper.SaveChangesAsync(default); } _repositoryWrapper.SetRepository() .Add(new Manager { UserId = user.Id }); await _repositoryWrapper.SaveChangesAsync(default); } return user; } public async Task EditUserAsync(UserActionRequestDto request, CancellationToken cancellationToken) { 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))); } if (request.RoleIds.Count > 0) { var userRoles = await _userManager.GetRolesAsync(user); await _userManager.RemoveFromRolesAsync(user, userRoles); foreach (var roleId in request.RoleIds) { var role = await _roleManager.FindByIdAsync(roleId.ToString()); if (role is { Name: not null }) { await _userManager.AddToRoleAsync(user, role.Name); } } } 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) { 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); var removeResult = await _userManager.DeleteAsync(user); if (!removeResult.Succeeded) throw new AppException(string.Join('|', removeResult.Errors.Select(e => e.Description))); var customer = await _repositoryWrapper.SetRepository() .TableNoTracking .FirstOrDefaultAsync(c => c.UserId == userId, cancellationToken); if (customer != null) { _repositoryWrapper.SetRepository() .Delete(customer); await _repositoryWrapper.SaveChangesAsync(default); } var manager = await _repositoryWrapper.SetRepository() .TableNoTracking .FirstOrDefaultAsync(c => c.UserId == userId, cancellationToken); if (manager != null) { _repositoryWrapper.SetRepository() .Delete(manager); await _repositoryWrapper.SaveChangesAsync(default); } return true; } public async Task GetAdminChangeLogAsync(CancellationToken cancellationToken = default) { 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 manager = await _repositoryWrapper.SetRepository() .TableNoTracking .FirstOrDefaultAsync(m => m.UserId == userId, cancellationToken); var currentVersion = await _externalFilesService.GetAdminChangeLogAsync(cancellationToken); if (manager != null) { if (!(manager.LatestVersionUsed < currentVersion.VersionNumber)) return currentVersion; currentVersion.IsNewVersion = true; manager.LatestVersionUsed = currentVersion.VersionNumber; _repositoryWrapper.SetRepository() .Update(manager); await _repositoryWrapper.SaveChangesAsync(cancellationToken); } return currentVersion; } public async Task> GetRolesAsync(int page = 0, CancellationToken cancellationToken = default) { var roles = await _roleManager.Roles .Where(r => r.Name != "RootAdmin") .Skip(page * 15) .Take(15) .ToListAsync(cancellationToken); return roles; } public async Task> GetRolesAsync(int? page, string? roleName, CancellationToken cancellationToken = default) { IQueryable roles; if (roleName != null) roles = _roleManager.Roles.Where(r => r.Name != "RootAdmin" && r.Name != "Customer" && r.PersianName.Trim().ToLower().Contains(roleName)); else roles = _roleManager.Roles.Where(r => r.Name != "RootAdmin" && r.Name != "Customer"); if (page != null) roles = roles.Skip(page.Value * 15).Take(15); else roles = roles; return await roles.ToListAsync(cancellationToken); } public async Task GetRoleAsync(Guid roleId, CancellationToken cancellationToken = default) { 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, CancellationToken cancellationToken = default) { if (request.EnglishName.IsNullOrEmpty()) throw new AppException("لطفا نام انگلیسی را وارد کنید"); var applicationRole = new ApplicationRole { EnglishName = request.EnglishName, PersianName = request.PersianName, Description = request.Description, Name = $"{request.EnglishName}" }; 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, CancellationToken cancellationToken = default) { if (request.EnglishName.IsNullOrEmpty()) throw new AppException("لطفا نام انگلیسی را وارد کنید"); var applicationRole = await _roleManager.FindByIdAsync(request.RoleId.ToString()); if (applicationRole == null) throw new AppException("نقش پیدا نشد"); applicationRole.EnglishName = request.EnglishName; applicationRole.PersianName = request.PersianName; applicationRole.Description = request.Description; applicationRole.Name = $"{request.EnglishName}"; 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()) { var removeResult = await _roleManager.RemoveClaimAsync(applicationRole, roleClaim); if (!removeResult.Succeeded) throw new AppException(string.Join(" | ", removeResult.Errors.Select(e => e.Description))); } foreach (var claim in request.Permissions) { var addResult = await _roleManager.AddClaimAsync(applicationRole, new Claim(CustomClaimType.Permission, claim)); if (!addResult.Succeeded) throw new AppException(string.Join(" | ", addResult.Errors.Select(e => e.Description))); } return true; } public async Task RemoveRoleAsync(Guid roleId, CancellationToken cancellationToken = default) { 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 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; } }