diff --git a/Marco.Pms.Model/Mapper/EmployeeMapper.cs b/Marco.Pms.Model/Mapper/EmployeeMapper.cs index b82bccc..8e5b507 100644 --- a/Marco.Pms.Model/Mapper/EmployeeMapper.cs +++ b/Marco.Pms.Model/Mapper/EmployeeMapper.cs @@ -35,7 +35,7 @@ namespace Marco.Pms.Model.Mapper PhoneNumber = model.PhoneNumber, Photo = base64String, IsActive = model.IsActive, - IsRootUser = model.ApplicationUser!.IsRootUser!.Value, + IsRootUser = model.ApplicationUser?.IsRootUser ?? false, IsSystem = model.IsSystem, JoiningDate = model.JoiningDate, TenantId = model.TenantId diff --git a/Marco.Pms.Services/Controllers/AppMenuController.cs b/Marco.Pms.Services/Controllers/AppMenuController.cs index 7d856a3..8c4fd01 100644 --- a/Marco.Pms.Services/Controllers/AppMenuController.cs +++ b/Marco.Pms.Services/Controllers/AppMenuController.cs @@ -290,71 +290,136 @@ namespace Marco.Pms.Services.Controllers } } + /// + /// Adds a new sub-menu item to an existing menu item inside a sidebar menu section. + /// Only accessible by root users or within the super tenant. + /// + /// The ID of the sidebar menu section. + /// The ID of the parent menu item. + /// The details of the new sub-menu item. + /// HTTP response with the result of the add operation. [HttpPost("add/sidebar/menus/{sectionId}/items/{itemId}/subitems")] public async Task AddSubMenuItem(Guid sectionId, Guid itemId, [FromBody] CreateSubMenuItemDto newSubItem) { + // Step 1: Fetch logged-in user var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync(); var isRootUser = loggedInEmployee.ApplicationUser?.IsRootUser ?? false; + + // Step 2: Authorization check if (!isRootUser && tenantId != superTenantId) { - _logger.LogWarning("Access Denied while adding sub menu item"); - return StatusCode(403, ApiResponse.ErrorResponse("access denied", "User haven't permission", 403)); + _logger.LogWarning("Access denied: User {UserId} attempted to add sub-menu item in Section {SectionId}, MenuItem {ItemId}, Tenant {TenantId}", + loggedInEmployee.Id, sectionId, itemId, tenantId); + + return StatusCode(403, ApiResponse.ErrorResponse("Access Denied", "User does not have permission.", 403)); + } + + // Step 3: Validate input + if (sectionId == Guid.Empty || itemId == Guid.Empty || newSubItem == null) + { + _logger.LogWarning("Invalid AddSubMenuItem request. Tenant: {TenantId}, SectionId: {SectionId}, ItemId: {ItemId}, UserId: {UserId}", + tenantId, sectionId, itemId, loggedInEmployee.Id); + + return BadRequest(ApiResponse.ErrorResponse("Invalid section ID, item ID, or sub-menu item payload.", 400)); } - if (sectionId == Guid.Empty || itemId == Guid.Empty) - return BadRequest(ApiResponse.ErrorResponse("Invalid input", 400)); try { - var subMenuItem = _mapper.Map(newSubItem); + // Step 4: Map DTO to entity + var subMenuItemEntity = _mapper.Map(newSubItem); - var result = await _sideBarMenuHelper.AddSubMenuItemAsync(sectionId, itemId, subMenuItem); + // Step 5: Perform add operation + var result = await _sideBarMenuHelper.AddSubMenuItemAsync(sectionId, itemId, subMenuItemEntity); if (result == null) { - return NotFound(ApiResponse.ErrorResponse("Menu item not found", 404)); + _logger.LogWarning("Parent menu item not found. Failed to add sub-menu item. Tenant: {TenantId}, SectionId: {SectionId}, ItemId: {ItemId}, UserId: {UserId}", + tenantId, sectionId, itemId, loggedInEmployee.Id); + return NotFound(ApiResponse.ErrorResponse("Parent menu item not found.", 404)); } - _logger.LogInfo("Added SubMenuItem in Section: {SectionId}, MenuItem: {ItemId}"); - return Ok(ApiResponse.SuccessResponse(result, "Submenu item added successfully")); + // Step 6: Success logging + _logger.LogInfo("Sub-menu item added successfully. Tenant: {TenantId}, SectionId: {SectionId}, ParentItemId: {ItemId}, SubItemId: {SubItemId}, UserId: {UserId}", + tenantId, sectionId, itemId, result.Id, loggedInEmployee.Id); + + return Ok(ApiResponse.SuccessResponse(result, "Sub-menu item added successfully.")); } catch (Exception ex) { - _logger.LogError(ex, "Failed to add submenu item"); - return StatusCode(500, ApiResponse.ErrorResponse("Server error", ex, 500)); + // Step 7: Handle unexpected errors + _logger.LogError(ex, "Error occurred while adding sub-menu item. Tenant: {TenantId}, SectionId: {SectionId}, ItemId: {ItemId}, UserId: {UserId}, Payload: {@NewSubItem}", + tenantId, sectionId, itemId, loggedInEmployee.Id, newSubItem); + + return StatusCode(500, ApiResponse.ErrorResponse("Server Error", "An unexpected error occurred while adding the sub-menu item.", 500)); } } + /// + /// Updates an existing sub-menu item inside a sidebar menu section. + /// Only accessible by root users or within the super tenant. + /// + /// The ID of the sidebar menu section. + /// The ID of the parent menu item. + /// The ID of the sub-menu item to update. + /// The updated sub-menu item details. + /// HTTP response with the result of the update operation. [HttpPut("edit/sidebar/{sectionId}/items/{itemId}/subitems/{subItemId}")] public async Task UpdateSubmenuItem(Guid sectionId, Guid itemId, Guid subItemId, [FromBody] UpdateSubMenuItemDto updatedSubMenuItem) { + // Step 1: Fetch logged-in user var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync(); var isRootUser = loggedInEmployee.ApplicationUser?.IsRootUser ?? false; + + // Step 2: Authorization check if (!isRootUser && tenantId != superTenantId) { - _logger.LogWarning("Access Denied while updating sub menu item"); - return StatusCode(403, ApiResponse.ErrorResponse("access denied", "User haven't permission", 403)); + _logger.LogWarning("Access denied: User {UserId} attempted to update sub-menu {SubItemId} under MenuItem {ItemId} in Section {SectionId}, Tenant {TenantId}", + loggedInEmployee.Id, subItemId, itemId, sectionId, tenantId); + + return StatusCode(403, ApiResponse.ErrorResponse("Access Denied", "User does not have permission.", 403)); + } + + // Step 3: Input validation + if (sectionId == Guid.Empty || itemId == Guid.Empty || subItemId == Guid.Empty || updatedSubMenuItem == null || updatedSubMenuItem.Id != subItemId) + { + _logger.LogWarning("Invalid UpdateSubMenuItem request. Tenant: {TenantId}, SectionId: {SectionId}, ItemId: {ItemId}, SubItemId: {SubItemId}, UserId: {UserId}", + tenantId, sectionId, itemId, subItemId, loggedInEmployee.Id); + + return BadRequest(ApiResponse.ErrorResponse("Invalid section ID, menu item ID, sub-item ID, or payload mismatch.", 400)); } - if (sectionId == Guid.Empty || itemId == Guid.Empty || subItemId == Guid.Empty || updatedSubMenuItem.Id != subItemId) - return BadRequest(ApiResponse.ErrorResponse("Invalid input", 400)); try { - var SubMenuItem = _mapper.Map(updatedSubMenuItem); - SubMenuItem = await _sideBarMenuHelper.UpdateSubmenuItemAsync(sectionId, itemId, subItemId, SubMenuItem); + // Step 4: Map DTO to entity + var subMenuEntity = _mapper.Map(updatedSubMenuItem); - if (SubMenuItem == null) - return NotFound(ApiResponse.ErrorResponse("Submenu item not found", 404)); + // Step 5: Perform update operation + var result = await _sideBarMenuHelper.UpdateSubmenuItemAsync(sectionId, itemId, subItemId, subMenuEntity); - _logger.LogInfo("SidBar Section{SectionId} MenuItem {itemId} SubMenuItem {subItemId} Updated"); - return Ok(ApiResponse.SuccessResponse(SubMenuItem, "Submenu item updated successfully")); + if (result == null) + { + _logger.LogWarning("Sub-menu item not found or update failed. Tenant: {TenantId}, SectionId: {SectionId}, ItemId: {ItemId}, SubItemId: {SubItemId}, UserId: {UserId}", + tenantId, sectionId, itemId, subItemId, loggedInEmployee.Id); + + return NotFound(ApiResponse.ErrorResponse("Sub-menu item not found.", 404)); + } + + // Step 6: Log success + _logger.LogInfo("Sub-menu item updated successfully. Tenant: {TenantId}, SectionId: {SectionId}, MenuItemId: {ItemId}, SubItemId: {SubItemId}, UserId: {UserId}", + tenantId, sectionId, itemId, subItemId, loggedInEmployee.Id); + + return Ok(ApiResponse.SuccessResponse(result, "Sub-menu item updated successfully.")); } catch (Exception ex) { - _logger.LogError(ex, "Error Occurred while Updating Sub-MenuItem"); - return StatusCode(500, ApiResponse.ErrorResponse("Server Error", ex, 500)); + // Step 7: Handle unexpected errors + _logger.LogError(ex, "Error occurred while updating sub-menu item. Tenant: {TenantId}, SectionId: {SectionId}, MenuItemId: {ItemId}, SubItemId: {SubItemId}, UserId: {UserId}, Payload: {@UpdatedSubMenuItem}", + tenantId, sectionId, itemId, subItemId, loggedInEmployee.Id, updatedSubMenuItem); + + return StatusCode(500, ApiResponse.ErrorResponse("Server Error", "An unexpected error occurred while updating the sub-menu item.", 500)); } }