diff --git a/Tsi1.Api/Tsi1.Api/Controllers/UserController.cs b/Tsi1.Api/Tsi1.Api/Controllers/UserController.cs index c6b148c41c290f63ce81b14e072056554918cfc5..ac1b1b8b0df52c850b35dd1c4c1c15e5a6153b4f 100644 --- a/Tsi1.Api/Tsi1.Api/Controllers/UserController.cs +++ b/Tsi1.Api/Tsi1.Api/Controllers/UserController.cs @@ -113,67 +113,177 @@ namespace Tsi1.Api.Controllers } } - [Authorize(Roles = UserTypes.FacultyAdmin)] + [Authorize(Roles = UserTypes.FacultyAdmin + ", " + UserTypes.UdelarAdmin)] [HttpPost("Register")] - public async Task<IActionResult> Register(UserRegisterDto dto) + public async Task<IActionResult> Register(UserRegisterDto dto, [FromQuery] int? tenantId = null) { - var tenantId = int.Parse(HttpContext.User.Claims.FirstOrDefault(x => x.Type == "TenantId").Value); + var myUserType = HttpContext.User.Claims.FirstOrDefault(x => x.Type == ClaimTypes.Role).Value; + + if (myUserType == UserTypes.UdelarAdmin && tenantId == null) + { + return BadRequest(string.Format(ErrorMessages.TenantDoesNotExist, tenantId)); + } + + if (myUserType == UserTypes.FacultyAdmin) + { + tenantId = int.Parse(HttpContext.User.Claims.FirstOrDefault(x => x.Type == "TenantId").Value); + } var userTypeResult = await _userTypeService.GetById(dto.UserTypeId); + if (userTypeResult.HasError) + { + return BadRequest(userTypeResult.Message); + } + + var userType = userTypeResult.Data; + + if (myUserType == UserTypes.UdelarAdmin && + (userType.Name == UserTypes.Student || + userType.Name == UserTypes.Professor)) + { + return BadRequest(string.Format(ErrorMessages.InvalidUserType, userType.Name)); + } + + if (myUserType == UserTypes.FacultyAdmin && + (userType.Name == UserTypes.UdelarAdmin || + userType.Name == UserTypes.FacultyAdmin)) + { + return BadRequest(string.Format(ErrorMessages.InvalidUserType, userType.Name)); + } + + var userServiceResult = await _userService.Create(dto, userType.Name, (int) tenantId); + + if (userServiceResult.HasError) + { + BadRequest(userServiceResult.Message); + } + + return Ok(); + } + + [Authorize(Roles = UserTypes.FacultyAdmin + ", " + UserTypes.UdelarAdmin)] + [HttpPut("Modify/{userId}")] + public async Task<IActionResult> Modify(UserModifyDto dto, int userId) + { + var myUserType = HttpContext.User.Claims.FirstOrDefault(x => x.Type == ClaimTypes.Role).Value; + + var userTypeResult = await _userService.GetUserType(userId); + if (userTypeResult.HasError) { return BadRequest(userTypeResult.Message); } + if (myUserType == UserTypes.FacultyAdmin) + { + var tenantId = int.Parse(HttpContext.User.Claims.FirstOrDefault(x => x.Type == "TenantId").Value); + + var userTenant = await _userService.GetTenant(userId); + + if (userTenant.HasError) + { + return BadRequest(userTenant.Message); + } + + if (userTenant.Data != tenantId) + { + return BadRequest("No se puede modificar un usuario de otra facultad"); + } + } + var userType = userTypeResult.Data; - if (userType.Name == UserTypes.UdelarAdmin || - userType.Name == UserTypes.FacultyAdmin) + if (myUserType == UserTypes.UdelarAdmin && + (userType.Name == UserTypes.Student || + userType.Name == UserTypes.Professor)) + { + return BadRequest(string.Format(ErrorMessages.InvalidUserType, userType.Name)); + } + + if (myUserType == UserTypes.FacultyAdmin && + (userType.Name == UserTypes.UdelarAdmin || + userType.Name == UserTypes.FacultyAdmin)) { return BadRequest(string.Format(ErrorMessages.InvalidUserType, userType.Name)); } - var userServiceResult = await _userService.Create(dto, userType.Name, tenantId); + var userServiceResult = await _userService.Modify(dto, userType.Name, userId); if (userServiceResult.HasError) { return BadRequest(userServiceResult.Message); } + if (userServiceResult.Data == false) + { + return NotFound(userServiceResult.Message); + } + return Ok(); } - [Authorize(Roles = UserTypes.UdelarAdmin)] - [HttpPost("RegisterAdmin/{tenantId}")] - public async Task<IActionResult> RegisterAdmin(UserRegisterDto dto, int tenantId) + [Authorize(Roles = UserTypes.FacultyAdmin + ", " + UserTypes.UdelarAdmin)] + [HttpDelete("Delete/{userId}")] + public async Task<IActionResult> Delete(int userId) { - var userTypeResult = await _userTypeService.GetById(dto.UserTypeId); + var myUserType = HttpContext.User.Claims.FirstOrDefault(x => x.Type == ClaimTypes.Role).Value; + + if (myUserType == UserTypes.FacultyAdmin) + { + var tenantId = int.Parse(HttpContext.User.Claims.FirstOrDefault(x => x.Type == "TenantId").Value); + + var userTenant = await _userService.GetTenant(userId); + + if (userTenant.HasError) + { + return BadRequest(userTenant.Message); + } + + if (userTenant.Data != tenantId) + { + return BadRequest("No se puede borrar un usuario de otra facultad"); + } + } + + var userTypeResult = await _userService.GetUserType(userId); if (userTypeResult.HasError) { - BadRequest(userTypeResult.Message); + return BadRequest(userTypeResult.Message); } var userType = userTypeResult.Data; - if (userType.Name == UserTypes.Student || - userType.Name == UserTypes.Professor) + if (myUserType == UserTypes.UdelarAdmin && + (userType.Name == UserTypes.Student || + userType.Name == UserTypes.Professor)) + { + return BadRequest(string.Format(ErrorMessages.InvalidUserType, userType.Name)); + } + + if (myUserType == UserTypes.FacultyAdmin && + (userType.Name == UserTypes.UdelarAdmin || + userType.Name == UserTypes.FacultyAdmin)) { return BadRequest(string.Format(ErrorMessages.InvalidUserType, userType.Name)); } - var userServiceResult = await _userService.Create(dto, userType.Name, tenantId); + var userServiceResult = await _userService.Delete(userId); if (userServiceResult.HasError) { - BadRequest(userServiceResult.Message); + return BadRequest(userServiceResult.Message); + } + + if (userServiceResult.Data == false) + { + return NotFound(userServiceResult.Message); } return Ok(); } - [Authorize(Roles = UserTypes.Student + ", " + UserTypes.Professor + ", " + UserTypes.FacultyAdmin)] [HttpGet("GetAll")] public async Task<IActionResult> GetAll() diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Dtos/UserModifyDto.cs b/Tsi1.Api/Tsi1.BusinessLayer/Dtos/UserModifyDto.cs new file mode 100644 index 0000000000000000000000000000000000000000..c3e9894b71f0a081a566e718800561479a75b076 --- /dev/null +++ b/Tsi1.Api/Tsi1.BusinessLayer/Dtos/UserModifyDto.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Text; + +namespace Tsi1.BusinessLayer.Dtos +{ + public class UserModifyDto + { + [Required] + public string Username { get; set; } + + [Required] + public string Password { get; set; } + + [Required] + public string FirstName { get; set; } + + [Required] + public string LastName { get; set; } + + [Required] + public string Email { get; set; } + + [Required] + public string IdentityCard { get; set; } + + public int Age { get; set; } + } +} diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Helpers/ErrorMessages.cs b/Tsi1.Api/Tsi1.BusinessLayer/Helpers/ErrorMessages.cs index 74cab9f3d512fe48200a738d343fef433d46f8ff..e00a5824fae33c3235b76f2b3b27de5ea6e962ce 100644 --- a/Tsi1.Api/Tsi1.BusinessLayer/Helpers/ErrorMessages.cs +++ b/Tsi1.Api/Tsi1.BusinessLayer/Helpers/ErrorMessages.cs @@ -16,6 +16,7 @@ namespace Tsi1.BusinessLayer.Helpers public const string ProfessorCourseAlreadyExists = "El profesor '{0}' ya es docente del curso '{1}'"; public const string ProfessorCourseDoesNotExists = "El profesor '{0}' no es docente del curso '{1}'"; public const string InvalidUsername = "El nombre de usuario debe ser de la forma: 'usuario@facultad'"; + public const string DuplicateUsername = "Ya existe un usuario con username '{0}'"; public const string ForumDoesNotExist = "El foro con id '{0}' no existe"; diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Helpers/MappingProfile.cs b/Tsi1.Api/Tsi1.BusinessLayer/Helpers/MappingProfile.cs index 5e2ad7595a04cfa2d63482f4ef931a10d21c1962..f23738a577da9427cd53b0c75d945b93d3dee4b1 100644 --- a/Tsi1.Api/Tsi1.BusinessLayer/Helpers/MappingProfile.cs +++ b/Tsi1.Api/Tsi1.BusinessLayer/Helpers/MappingProfile.cs @@ -22,6 +22,7 @@ namespace Tsi1.BusinessLayer.Helpers CreateMap<Message, MessageCreateDto>(); CreateMap<User, UserPreviewDto>(); CreateMap<User, UserRegisterDto>(); + CreateMap<User, UserModifyDto>(); CreateMap<Student, StudentPreviewDto>(); CreateMap<Professor, ProfessorPreviewDto>(); CreateMap<Course, CourseCreateDto>(); @@ -40,6 +41,7 @@ namespace Tsi1.BusinessLayer.Helpers CreateMap<MessageCreateDto, Message>(); CreateMap<UserPreviewDto, User>(); CreateMap<UserRegisterDto, User>(); + CreateMap<UserModifyDto, User>(); CreateMap<StudentPreviewDto, Student>(); CreateMap<ProfessorPreviewDto, Professor>(); CreateMap<CourseCreateDto, Course>().ForMember(x => x.TenantId, opt => opt.Ignore()); diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Interfaces/IUserService.cs b/Tsi1.Api/Tsi1.BusinessLayer/Interfaces/IUserService.cs index cc1a12076c6cf6467484ac7fecdb336dee221980..54550814463757e24870ae34bb6b51a68217ce11 100644 --- a/Tsi1.Api/Tsi1.BusinessLayer/Interfaces/IUserService.cs +++ b/Tsi1.Api/Tsi1.BusinessLayer/Interfaces/IUserService.cs @@ -21,5 +21,13 @@ namespace Tsi1.BusinessLayer.Interfaces Task<ServiceResult<User>> GetByUsername(string username, int tenantId); Task<ServiceResult<bool>> UpdatePassword(int userId, string password); + + Task<ServiceResult<bool>> Modify(UserModifyDto dto, string type, int userId); + + Task<ServiceResult<int>> GetTenant(int userId); + + Task<ServiceResult<bool>> Delete(int userId); + + Task<ServiceResult<UserTypeDto>> GetUserType(int userId); } } diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Services/UserService.cs b/Tsi1.Api/Tsi1.BusinessLayer/Services/UserService.cs index a32af3a601986d0160ff4fec651a6b9510a62e62..3a54107291fd41bd09bd26976997cfe64e3788e7 100644 --- a/Tsi1.Api/Tsi1.BusinessLayer/Services/UserService.cs +++ b/Tsi1.Api/Tsi1.BusinessLayer/Services/UserService.cs @@ -57,6 +57,7 @@ namespace Tsi1.BusinessLayer.Services var result = new ServiceResult<User>(); var user = _mapper.Map<User>(dto); + user.TenantId = tenantId; if (type == UserTypes.Student) @@ -85,6 +86,55 @@ namespace Tsi1.BusinessLayer.Services return result; } + public async Task<ServiceResult<bool>> Modify(UserModifyDto dto, string type, int userId) + { + var result = new ServiceResult<bool>(); + + var user = await _context.Users + .Include(x => x.Student) + .Include(x => x.Professor) + .FirstOrDefaultAsync(x => x.Id == userId); + + if (user == null) + { + result.Message = string.Format(ErrorMessages.UserDoesNotExist, userId); + return result; + } + + if (dto.Username != user.Username) + { + var existingUser = await _context.Users + .FirstOrDefaultAsync(x => x.Username == dto.Username + && x.TenantId == user.TenantId); + + if (existingUser != null) + { + result.HasError = true; + result.Message = string.Format(ErrorMessages.DuplicateUsername, dto.Username); + return result; + } + } + + _mapper.Map(dto, user); + + if (type == UserTypes.Student) + { + user.Student.IdentityCard = dto.IdentityCard; + user.Student.Age = dto.Age; + } + + if (type == UserTypes.Professor) + { + user.Professor.IdentityCard = dto.IdentityCard; + } + + await _context.SaveChangesAsync(); + + result.Data = true; + + return result; + } + public async Task<ServiceResult<List<UserPreviewDto>>> GetAll(int tenantId) { var result = new ServiceResult<List<UserPreviewDto>>(); @@ -194,5 +244,63 @@ namespace Tsi1.BusinessLayer.Services return result; } + + public async Task<ServiceResult<int>> GetTenant(int userId) + { + var result = new ServiceResult<int>(); + + var user = await _context.Users.FirstOrDefaultAsync(x => x.Id == userId); + + if (user == null) + { + result.HasError = true; + result.Message = string.Format(ErrorMessages.UserDoesNotExist, userId); + return result; + } + + result.Data = user.TenantId; + + return result; + } + + public async Task<ServiceResult<bool>> Delete(int userId) + { + var result = new ServiceResult<bool>(); + + var user = await _context.Users.FirstOrDefaultAsync(x => x.Id == userId); + + if (user == null) + { + result.Message = string.Format(ErrorMessages.UserDoesNotExist, userId); + return result; + } + + _context.Users.Remove(user); + + await _context.SaveChangesAsync(); + + result.Data = true; + + return result; + } + + public async Task<ServiceResult<UserTypeDto>> GetUserType(int userId) + { + var result = new ServiceResult<UserTypeDto>(); + + var user = await _context.Users + .Include(x => x.UserType) + .FirstOrDefaultAsync(x => x.Id == userId); + + if (user == null) + { + result.HasError = true; + result.Message = string.Format(ErrorMessages.UserDoesNotExist, userId); + } + + result.Data = _mapper.Map<UserTypeDto>(user.UserType); + + return result; + } } } diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Services/UserTypeService.cs b/Tsi1.Api/Tsi1.BusinessLayer/Services/UserTypeService.cs index e11f550b6dd13589a7379b8579efa715632b989b..be8f6786758d37071c7db5025954e0e9fa1c6673 100644 --- a/Tsi1.Api/Tsi1.BusinessLayer/Services/UserTypeService.cs +++ b/Tsi1.Api/Tsi1.BusinessLayer/Services/UserTypeService.cs @@ -67,6 +67,5 @@ namespace Tsi1.BusinessLayer.Services return result; } - } }