using Api.SeaHavenIndustries.DTOs; using Api.SeaHavenIndustries.Helper; using Api.SeaHavenIndustries.Models; using Data.SeaHavenIndustries; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using PasswordGenerator; using SendGrid.Helpers.Mail; using System.Security.Claims; using System.Security.Cryptography; namespace Api.SeaHavenIndustries.Controllers { [Authorize] [ApiController] [Route("api/User")] public class UserController : Controller { private readonly UserManager _userManager; private readonly ApplicationDbContext _db; private readonly SendMessage _sendemail; public UserController(UserManager userManager, ApplicationDbContext db, SendMessage sendemail) { _userManager = userManager; _db = db; _sendemail = sendemail; } [Route("")] [HttpGet] public async Task GetUsers() { _db.ChangeTracker.Clear(); var allUsers = _db.Users.Select(s => new UserRoleViewModel { RoleName = s.PhoneNumber, Email = s.Email, Name = s.FirstName, Date = s.CreatedDate != null ? s.CreatedDate.Value.Date.ToString("MMM dd yyyy") : "", Status = s.UniqueName, Id = s.Id }).AsQueryable(); return Ok(allUsers); } [HttpPost] [Route("AddUser")] public async Task AddUser(User_DTO user) { var model = new ApplicationUser { UserName = user.Email, FirstName = user.Name, Email = user.Email, }; try { _db.ChangeTracker.Clear(); var exist = _db.Set().Find(model.Id); if (exist == null) { model.EmailConfirmed = true; model.UserName = model.Email; model.CreatedDate = DateTime.Now; model.UniqueName = "Active"; model.PhoneNumber = user.Role; var pwd = new Password(8).IncludeLowercase().IncludeUppercase().IncludeSpecial().IncludeNumeric(); var password = pwd.Next(); var result = await _userManager.CreateAsync(model, password); if (result.Succeeded) { await _userManager.AddToRoleAsync(model, user.Role ?? ""); } else { return BadRequest(new Response { Status = "Error", Message = result.Errors.FirstOrDefault()?.Description ?? "error" }); } var request = HttpContext?.Request; //var domain = $"{request?.Scheme}://{request?.Host}"; var domain = "http://shoc-ui-app.s3-website-us-east-1.amazonaws.com/#"; string subject = "Login Information"; string greeting = $"Dear {model.FirstName},\n\n"; string loginLink = $"Click here to login:Login\n"; string passwordInfo = $"Your password is: {password}\n\n"; string body = $"{greeting}\n\n{loginLink}\n\n{passwordInfo}"; await _sendemail.SendEMail(model?.Email ?? "", subject, body); } else { var exist1 = await _userManager.Users.FirstOrDefaultAsync(w => w.Id == model.Id); if (exist1 == null) return BadRequest(new Response { Status = "Error", Message = "User not found" }); var existingRole = await _userManager.GetRolesAsync(exist1); // Remove from roles if any exist if (existingRole != null && existingRole.Any() && existingRole.FirstOrDefault() != exist1.PhoneNumber) { await _userManager.RemoveFromRolesAsync(exist1, existingRole); } // Update user details exist1.FirstName = model.FirstName; exist1.LastName = model.LastName; exist1.Contact = model.Contact; exist1.PhoneNumber = model.PhoneNumber; // Optionally, detach the entity if you're about to attach it again _db.Entry(exist1).State = EntityState.Detached; // Add to role after setting properties await _userManager.AddToRoleAsync(exist1, user.Role ?? ""); var result = await _userManager.UpdateAsync(exist1); //await _context.SaveChangesAsync(); } return Ok(new DataResponse { Message = "Updated Successfully", Status = "200" }); } catch (Exception ex) { return BadRequest(new Response { Status = "Error", Message = ex.Message }); } } [HttpPut] [Route("EditUser")] public async Task EditUser(EditUser_DTO user) { try { var exist = _db.Users.Where(w => w.Id == user.Id).FirstOrDefault(); if (exist == null) return BadRequest(new Response { Status = "Error", Message = "User not found" }); exist.FirstName = user.Name; exist.EmailConfirmed = true; exist.UserName = user.Email; exist.Email = user.Email; exist.NormalizedEmail = user.Email.ToUpper(); exist.NormalizedUserName = user.Email.ToUpper(); exist.CreatedDate = DateTime.Now; exist.UniqueName = "Active"; exist.PhoneNumber = user.Role; var existingRole = await _userManager.GetRolesAsync(exist); if (existingRole != null && existingRole.Any()) { await _userManager.RemoveFromRolesAsync(exist, existingRole); } await _userManager.AddToRoleAsync(exist, user.Role ?? ""); await _db.SaveChangesAsync(); return Ok(new DataResponse { Message = "Updated Successfully", Status = "200" }); } catch (Exception ex) { return BadRequest(new Response { Status = "Error", Message = ex.Message }); } } public class DeleteUserRequest { public string Id { get; set; } } [HttpDelete] [Route("DeleteUser")] public async Task DeleteUser(EditUser_DTO req) { string id = req.Id; try { var data = await _db.Users.Where(w => w.Id == id).FirstOrDefaultAsync(); if (data != null) { var existworkorder = _db.workOrders.Where(w => w.AssignTo.Contains(data.Id)).ToList(); foreach (var workorder in existworkorder) { var existdata = _db.workOrders.Where(w => w.Id == workorder.Id).FirstOrDefault(); existdata.AssignTo = null; } var existworkordercomments = _db.Comments.Where(w => w.UserId.Contains(data.Id)).ToList(); foreach (var workorderc in existworkordercomments) { var existdatacomm = _db.Comments.Where(w => w.Id == workorderc.Id).FirstOrDefault(); existdatacomm.UserId = null; } var existtemplate = _db.Templates.Where(w => w.AssignTo.Contains(data.Id)).ToList(); foreach (var workordert in existtemplate) { var existdattem = _db.Templates.Where(w => w.Id == workordert.Id).FirstOrDefault(); existdattem.AssignTo = null; } var existtempexistuserrolelate = _db.UserRoles.Where(w => w.UserId.Contains(data.Id)).ToList(); if (existtempexistuserrolelate.Count() > 0) { _db.UserRoles.RemoveRange(existtempexistuserrolelate); } _db.Users.Remove(data); } else { return BadRequest(new Response { Status = "Error", Message = "ID not matched!" }); } await _db.SaveChangesAsync(); return Ok(new DataResponse { Message = "Updated Successfully", Status = "200" }); } catch (Exception ex) { return BadRequest(new Response { Status = "Error", Message = ex.Message }); } } [HttpPost] [Route("DeleteCurrentUser")] public async Task DeleteCurrentUser() { try { var userid = User.FindFirstValue(ClaimTypes.NameIdentifier) ?? ""; var exist = _db.Users.Where(w => w.Id == userid).FirstOrDefault(); if(exist != null) { exist.IsDeleted = true; } await _db.SaveChangesAsync(); return Ok(new DataResponse { Message = "Updated Successfully", Status = "200" }); } catch (Exception ex) { return BadRequest(new Response { Status = "Error", Message = ex.Message }); } } [HttpGet] [Route("UserProfile")] public async Task UserProfile() { var userid = User.FindFirstValue(ClaimTypes.NameIdentifier) ?? ""; var data = await _db.Users.Where(w => w.Id == userid).Select(s => new { s.Id, Name = s.FirstName, addeddate = s.CreatedDate, s.Email, s.Contact }).ToListAsync(); return Ok(data); } public static string GenerateRandomPassword(int length = 8) { const string validChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890!@#$%^&*()_-+=<>?"; const string capitalLetters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; const string digits = "1234567890"; const string symbols = "!@#$%^&*()_-+=<>?"; using (var rng = RandomNumberGenerator.Create()) { var passwordChars = new char[length]; // Ensure at least one capital letter passwordChars[0] = capitalLetters[GetNextNonNegativeIndex(rng, capitalLetters.Length)]; // Ensure at least one digit passwordChars[1] = digits[GetNextNonNegativeIndex(rng, digits.Length)]; // Ensure at least one symbol passwordChars[2] = symbols[GetNextNonNegativeIndex(rng, symbols.Length)]; // Fill the rest of the password with random characters for (int i = 3; i < length; i++) { passwordChars[i] = validChars[GetNextNonNegativeIndex(rng, validChars.Length)]; } // Shuffle the password characters, excluding the initial characters Random random = new Random(); for (int i = length - 1; i > 2; i--) { int j = random.Next(2, i + 1); (passwordChars[i], passwordChars[j]) = (passwordChars[j], passwordChars[i]); } return new string(passwordChars); } } private static int GetNextNonNegativeIndex(RandomNumberGenerator rng, int maxValue) { byte[] randomBytes = new byte[4]; rng.GetBytes(randomBytes); int nextIndex = BitConverter.ToInt32(randomBytes, 0) % maxValue; return (nextIndex + maxValue) % maxValue; // Ensure the index is non-negative } } }