diff --git a/Marco.Pms.Model/Mapper/ApplicationRoleMapper.cs b/Marco.Pms.Model/Mapper/ApplicationRoleMapper.cs index 45228e2..86b96d8 100644 --- a/Marco.Pms.Model/Mapper/ApplicationRoleMapper.cs +++ b/Marco.Pms.Model/Mapper/ApplicationRoleMapper.cs @@ -13,6 +13,7 @@ namespace Marco.Pms.Model.Mapper { Id = model.Id, Role = model.Role, + IsSystem = model.IsSystem, Description = model.Description, //FeaturePermission = model.FeaturePermissions }; @@ -73,4 +74,4 @@ namespace Marco.Pms.Model.Mapper } } -} +} \ No newline at end of file diff --git a/Marco.Pms.Services/Controllers/ProjectController.cs b/Marco.Pms.Services/Controllers/ProjectController.cs index 1aa5096..a0fb7ff 100644 --- a/Marco.Pms.Services/Controllers/ProjectController.cs +++ b/Marco.Pms.Services/Controllers/ProjectController.cs @@ -493,6 +493,7 @@ namespace MarcoBMS.Services.Controllers { Guid tenantId = GetTenantId(); List workItems = new List { }; + string responseMessage = ""; if (workItemDot != null) { foreach (var item in workItemDot) @@ -504,12 +505,14 @@ namespace MarcoBMS.Services.Controllers //update _context.WorkItems.Update(workItem); await _context.SaveChangesAsync(); + responseMessage = "Task Added Successfully"; } else { //create _context.WorkItems.Add(workItem); await _context.SaveChangesAsync(); + responseMessage = "Task Updated Successfully"; } var result = new WorkItemVM { @@ -519,7 +522,7 @@ namespace MarcoBMS.Services.Controllers workItems.Add(result); } var activity = await _context.ActivityMasters.ToListAsync(); - return Ok(ApiResponse.SuccessResponse(workItems, "Data saved successfully.", 200)); + return Ok(ApiResponse.SuccessResponse(workItems, responseMessage, 200)); } return BadRequest(ApiResponse.ErrorResponse("Invalid details.", "Work Item Details are not valid.", 400)); @@ -569,6 +572,7 @@ namespace MarcoBMS.Services.Controllers { Guid tenantId = GetTenantId(); var responseData = new InfraVM { }; + string responseMessage = ""; if (infraDots != null) { foreach (var item in infraDots) @@ -585,6 +589,7 @@ namespace MarcoBMS.Services.Controllers _context.Buildings.Add(building); await _context.SaveChangesAsync(); responseData.building = building; + responseMessage = "Buliding Added Successfully"; } else { @@ -592,6 +597,7 @@ namespace MarcoBMS.Services.Controllers _context.Buildings.Update(building); await _context.SaveChangesAsync(); responseData.building = building; + responseMessage = "Buliding Updated Successfully"; } } @@ -606,6 +612,7 @@ namespace MarcoBMS.Services.Controllers _context.Floor.Add(floor); await _context.SaveChangesAsync(); responseData.floor = floor; + responseMessage = "Floor Added Successfully"; } else { @@ -613,6 +620,7 @@ namespace MarcoBMS.Services.Controllers _context.Floor.Update(floor); await _context.SaveChangesAsync(); responseData.floor = floor; + responseMessage = "Floor Updated Successfully"; } } if (item.WorkArea != null) @@ -626,6 +634,7 @@ namespace MarcoBMS.Services.Controllers _context.WorkAreas.Add(workArea); await _context.SaveChangesAsync(); responseData.workArea = workArea; + responseMessage = "Work Area Added Successfully"; } else { @@ -633,14 +642,15 @@ namespace MarcoBMS.Services.Controllers _context.WorkAreas.Update(workArea); await _context.SaveChangesAsync(); responseData.workArea = workArea; + responseMessage = "Work Area Updated Successfully"; } } } - return Ok(ApiResponse.SuccessResponse(responseData, "Data saved successfully.", 200)); + return Ok(ApiResponse.SuccessResponse(responseData, responseMessage, 200)); } return BadRequest(ApiResponse.ErrorResponse("Invalid details.", "Infra Details are not valid.", 400)); } } -} +} \ No newline at end of file diff --git a/Marco.Pms.Services/Controllers/RolesController.cs b/Marco.Pms.Services/Controllers/RolesController.cs index 80c49d3..651900b 100644 --- a/Marco.Pms.Services/Controllers/RolesController.cs +++ b/Marco.Pms.Services/Controllers/RolesController.cs @@ -1,6 +1,8 @@ using System.Data; using Marco.Pms.DataAccess.Data; +using Marco.Pms.Model.Dtos.Employees; using Marco.Pms.Model.Dtos.Roles; +using Marco.Pms.Model.Employees; using Marco.Pms.Model.Entitlements; using Marco.Pms.Model.Mapper; using Marco.Pms.Model.Roles; @@ -9,6 +11,7 @@ using Marco.Pms.Model.ViewModels; using Marco.Pms.Model.ViewModels.Master; using Marco.Pms.Model.ViewModels.Roles; using MarcoBMS.Services.Helpers; +using MarcoBMS.Services.Service; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; @@ -24,16 +27,16 @@ namespace MarcoBMS.Services.Controllers private readonly ApplicationDbContext _context; private readonly RolesHelper _rolesHelper; private readonly UserHelper _userHelper; - - private readonly UserManager _userManager; + private readonly ILoggingService _logger; - public RolesController(UserManager userManager, ApplicationDbContext context, RolesHelper rolesHelper, UserHelper userHelper) + public RolesController(UserManager userManager, ApplicationDbContext context, RolesHelper rolesHelper, UserHelper userHelper, ILoggingService logger) { _context = context; _userManager = userManager; _rolesHelper = rolesHelper; _userHelper = userHelper; + _logger = logger; } private Guid GetTenantId() @@ -102,7 +105,30 @@ namespace MarcoBMS.Services.Controllers return BadRequest(ApiResponse.ErrorResponse(ex.Message, ex, 400)); } } - + [HttpDelete("jobrole/{id}")] + public async Task DeleteJobRole(Guid id) + { + Guid tenantId = GetTenantId(); + var LoggedEmployee = await _userHelper.GetCurrentEmployeeAsync(); + var jobRole = await _context.JobRoles.FirstOrDefaultAsync(r => r.Id == id && r.TenantId == tenantId); + if (jobRole != null) + { + var employee = await _context.Employees.Where(e => e.JobRoleId == jobRole.Id).ToListAsync(); + if (employee.Any()) + { + _logger.LogWarning("Employee with ID {LoggedEmployeeId} tries to delete the job role with ID {JobRoleId} which is assigned to one or more employees", LoggedEmployee.Id, jobRole.Id); + return BadRequest(ApiResponse.ErrorResponse("Cannot delete the job role because it is assigned to one or more employees.", "Cannot delete the job role because it is assigned to one or more employees.", 400)); + } + _context.JobRoles.Remove(jobRole); + await _context.SaveChangesAsync(); + _logger.LogInfo("Employee with ID {LoggedEmployeeId} deleted the job role with ID {JobRoleId}", LoggedEmployee.Id, jobRole.Id); + } + else + { + _logger.LogWarning("Job role with ID {JobRoleId} not found in database", id); + } + return Ok(ApiResponse.SuccessResponse(new { }, "Job role deleted successfully", 200)); + } [HttpGet] public async Task GetAllRoles() @@ -140,6 +166,7 @@ namespace MarcoBMS.Services.Controllers { Id = item.Id, Role = item.Role, + IsSystem = item.IsSystem, Description = item.Description, FeaturePermission = [] }; @@ -228,17 +255,21 @@ namespace MarcoBMS.Services.Controllers try { Guid TenantId = GetTenantId(); - + var LoggedEmployee = await _userHelper.GetCurrentEmployeeAsync(); + var existingRole = await _context.ApplicationRoles.AsNoTracking().FirstOrDefaultAsync(r => r.Id == id); + if (existingRole != null && existingRole.IsSystem) + { + _logger.LogWarning("Employee with ID {LoggedEmployeeId} tries to update System-defined application roles {AppcationRoleId}", LoggedEmployee.Id, existingRole.Id); + return BadRequest(ApiResponse.ErrorResponse("System-defined roles cannot be updated", "System-defined roles cannot be updated", 400)); + } ApplicationRole role = updateRoleDto.ToApplicationRoleFromUpdateDto(TenantId); if (role.TenantId != TenantId) return Unauthorized(ApiResponse.ErrorResponse("You don't have any authority to update role", "You don't have any authority to update role", 401)); - - var projectModel = _context.ApplicationRoles.Update(role); - - if (projectModel == null) + if (existingRole != null) { - return NotFound(ApiResponse.ErrorResponse("Project not found", "Project not found", 404)); + _context.ApplicationRoles.Update(role); + await _context.SaveChangesAsync(); } bool modified = false; @@ -268,7 +299,13 @@ namespace MarcoBMS.Services.Controllers } catch (Exception ex) { - return BadRequest(ApiResponse.ErrorResponse(ex.Message, ex, 400)); + var response = new + { + message = ex.Message, + detail = ex.StackTrace, + statusCode = StatusCodes.Status500InternalServerError + }; + return BadRequest(ApiResponse.ErrorResponse(ex.Message, response, 400)); } } @@ -306,11 +343,101 @@ namespace MarcoBMS.Services.Controllers { Id = role.Id, Role = role.Role, + IsSystem = role.IsSystem, FeaturePermission = featurePermissions }; return Ok(ApiResponse.SuccessResponse(vm, "Roles Perimssions fetched successfully.", 200)); } + [HttpDelete("{id}")] + public async Task DeleteApplicationRole(Guid id) + { + Guid tenantId = GetTenantId(); + var LoggedEmployee = await _userHelper.GetCurrentEmployeeAsync(); + var role = await _context.ApplicationRoles.AsNoTracking().FirstOrDefaultAsync(r => r.Id == id && r.TenantId == tenantId); + if (role != null) + { + if (role.IsSystem) + { + _logger.LogInfo("Employee with ID {LoggedEmployeeId} tries to delete system-defined application role with ID {ApplicationRoleId}", LoggedEmployee.Id, role.Id); + return BadRequest(ApiResponse.ErrorResponse("This role cannot be deleted because it is system-defined.", "This role cannot be deleted because it is system-defined.", 400)); + } + var employeeRoleMapping = await _context.EmployeeRoleMappings.Where(erm => erm.RoleId == role.Id).ToListAsync(); + if (employeeRoleMapping.Count != 0) + { + _logger.LogInfo("Employee with ID {LoggedEmployeeId} tries to delete application role with ID {ApplicationRoleId} with is assigned to an employee", LoggedEmployee.Id, role.Id); + return BadRequest(ApiResponse.ErrorResponse("This role cannot be deleted because it is currently assigned to employees.", "This role cannot be deleted because it is currently assigned to employees.", 400)); + } + _context.ApplicationRoles.Remove(role); + var rolePermissionMapping = await _context.RolePermissionMappings.Where(r => r.ApplicationRoleId == role.Id).ToListAsync(); + if (rolePermissionMapping.Count != 0) + { + _context.RolePermissionMappings.RemoveRange(rolePermissionMapping); + _logger.LogInfo("All permissions assigned to the application role with ID {ApplicationRoleId} have been removed.", role.Id); + } + await _context.SaveChangesAsync(); + _logger.LogInfo("Employee with ID {LoggedEmployeeId} deleted application role with ID {ApplicationRoleId}", LoggedEmployee.Id, role.Id); + } + else + { + _logger.LogWarning("Application role with ID {ApplicationRoleId} not found in database", id); + } + return Ok(ApiResponse.SuccessResponse(new { }, "Application role is deleted successfully", 200)); + } + + + [HttpPost] + [Route("assign-roles")] + public async Task ManageRoles([FromBody] List employeeRoleDots) + { + if (!ModelState.IsValid) + { + var errors = ModelState.Values + .SelectMany(v => v.Errors) + .Select(e => e.ErrorMessage) + .ToList(); + return BadRequest(ApiResponse.ErrorResponse("Invalid data", errors, 400)); + } + var employeesIds = employeeRoleDots.Select(e => e.EmployeeId).Distinct().ToList(); + var LoggedEmployee = await _userHelper.GetCurrentEmployeeAsync(); + var employees = await _context.Employees.Where(e => employeesIds.Contains(e.Id)).ToListAsync(); + + Guid TenantId = GetTenantId(); + try + { + foreach (EmployeeRoleDot role in employeeRoleDots) + { + var employee = employees.Find(e => e.Id == role.EmployeeId && e.IsSystem); + if (employee != null) + { + _logger.LogWarning("Employee with ID {LoggedEmployeeId} tries to assign or remove the application role to System-defined employee with ID {EmployeeId}", LoggedEmployee.Id, employee.Id); + return BadRequest(ApiResponse.ErrorResponse("System-defined employee cannot have application roles assigned or removed.", "System-defined employee cannot have application roles assigned or removed.", 400)); + } + EmployeeRoleMapping mapping = role.ToEmployeeRoleMappingFromEmployeeRoleDot(TenantId); + + var existingItem = await _context.EmployeeRoleMappings.AsNoTracking().SingleOrDefaultAsync(c => c.Id == mapping.Id); + + if (existingItem == null) + { + if (role.IsEnabled == true) + { + _context.EmployeeRoleMappings.Add(mapping); + } + } + else if (role.IsEnabled == false) + { + _context.EmployeeRoleMappings.Remove(existingItem); + } + + } + await _context.SaveChangesAsync(); + } + catch (Exception ex) + { + return BadRequest(ApiResponse.ErrorResponse(ex.Message, ex, 400)); + } + return Ok(ApiResponse.SuccessResponse("success", "Roles modified.", 200)); + } } }