using AutoMapper; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using ZeroFramework.IdentityServer.API.Constants; using ZeroFramework.IdentityServer.API.Extensions; using ZeroFramework.IdentityServer.API.IdentityStores; using ZeroFramework.IdentityServer.API.Models.Generics; using ZeroFramework.IdentityServer.API.Models.Users; using ZeroFramework.IdentityServer.API.Tenants; namespace ZeroFramework.IdentityServer.API.Controllers { [Route("api/[controller]")] [ApiController] [Authorize(AuthorizeConstants.TenantOwnerPolicyName, AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)] public class UsersController(UserManager userManager, IMapper mapper, ICurrentTenant currentTenant) : ControllerBase { private readonly UserManager _userManager = userManager; private readonly IMapper _mapper = mapper; private readonly ICurrentTenant _currentTenant = currentTenant; // GET: api/Users [HttpGet] public async Task>> GetUsers(string keyword, [ModelBinder(typeof(SortingModelBinder))] IEnumerable? sorter, int pageNumber = 1, int pageSize = PagingConstants.DefaultPageSize) { IQueryable userQuery = _userManager.Users; if (!string.IsNullOrWhiteSpace(keyword)) { userQuery = _userManager.Users.Where(u => u.UserName!.Contains(keyword) || u.PhoneNumber!.Contains(keyword) || (u.DisplayName != null && u.DisplayName.Contains(keyword))); } int totalCount = await userQuery.CountAsync(); userQuery = sorter != null && sorter.Any() ? userQuery.ApplySorting(sorter) : userQuery.OrderByDescending(e => e.CreationTime); userQuery = userQuery.ApplyPaging(pageNumber, pageSize); List list = _mapper.Map>(await userQuery.ToListAsync()); return new PagedResponseModel(list, totalCount); } // GET: api/Users/5 [HttpGet("{id}")] public async Task> GetUser(int id) { ApplicationUser? user = await _userManager.FindByIdAsync(id.ToString()); if (user is null) { return NotFound(); } return _mapper.Map(user); } // POST: api/Users [HttpPost] public async Task> PostUser(UserCreateRequestModel userModel) { ApplicationUser user = _mapper.Map(userModel); user.TenantUserName = user.UserName; user.UserName = _currentTenant.Name is null ? user.TenantUserName : $"{user.TenantUserName}@{_currentTenant.Name}"; IdentityResult identityResult = await _userManager.CreateAsync(user, userModel.Password); if (!identityResult.Succeeded) { identityResult.Errors.ToList().ForEach(e => ModelState.AddModelError(string.Empty, e.Description)); return ValidationProblem(ModelState); } var token = await _userManager.GenerateChangePhoneNumberTokenAsync(user, user.PhoneNumber!); identityResult = await _userManager.ChangePhoneNumberAsync(user, user.PhoneNumber!, token); if (!identityResult.Succeeded) { identityResult.Errors.ToList().ForEach(e => ModelState.AddModelError(string.Empty, e.Description)); return ValidationProblem(ModelState); } var model = _mapper.Map(user); return CreatedAtAction("GetUser", new { id = user.Id }, model); } // PUT: api/Users/5 [HttpPut("{id}")] public async Task PutUser(int id, UserUpdateRequestModel userModel) { ApplicationUser? user = await _userManager.FindByIdAsync(id.ToString()); if (user is null) { return NotFound(); } _mapper.Map(userModel, user); user.TenantUserName = user.UserName; user.UserName = _currentTenant.Name is null ? user.TenantUserName : $"{user.TenantUserName}@{_currentTenant.Name}"; user.PasswordHash = _userManager.PasswordHasher.HashPassword(user, userModel.Password); IdentityResult identityResult = await _userManager.UpdateAsync(user); if (!identityResult.Succeeded) { identityResult.Errors.ToList().ForEach(e => ModelState.AddModelError(string.Empty, e.Description)); return ValidationProblem(ModelState); } return NoContent(); } // DELETE: api/Users/5 [HttpDelete("{id}")] public async Task DeleteUser(int id) { ApplicationUser? user = await _userManager.FindByIdAsync(id.ToString()); if (user is null) { return NotFound(); } await _userManager.DeleteAsync(user); return NoContent(); } } }