From ec4756d888b0f199192caf97a7a73c81cd71d39e Mon Sep 17 00:00:00 2001 From: "ashutosh.nehete" Date: Fri, 29 Aug 2025 17:17:38 +0530 Subject: [PATCH] Added the API to get document attachment details --- .../DocumentAttachmentDetailsVM.cs | 25 ++++++ .../Controllers/DocumentController.cs | 78 ++++++++++++++++--- .../MappingProfiles/MappingProfile.cs | 4 +- 3 files changed, 94 insertions(+), 13 deletions(-) create mode 100644 Marco.Pms.Model/ViewModels/DocumentManager/DocumentAttachmentDetailsVM.cs diff --git a/Marco.Pms.Model/ViewModels/DocumentManager/DocumentAttachmentDetailsVM.cs b/Marco.Pms.Model/ViewModels/DocumentManager/DocumentAttachmentDetailsVM.cs new file mode 100644 index 0000000..26d3e78 --- /dev/null +++ b/Marco.Pms.Model/ViewModels/DocumentManager/DocumentAttachmentDetailsVM.cs @@ -0,0 +1,25 @@ +using Marco.Pms.Model.ViewModels.Activities; + +namespace Marco.Pms.Model.ViewModels.DocumentManager +{ + public class DocumentAttachmentDetailsVM + { + public Guid Id { get; set; } + public string? Name { get; set; } + public string? DocumentId { get; set; } + public string? Description { get; set; } + public int Version { get; set; } + public bool IsCurrentVersion { get; set; } + public Guid ParentAttachmentId { get; set; } + public DateTime UploadedAt { get; set; } + public BasicEmployeeVM? UploadedBy { get; set; } + public DateTime? UpdatedAt { get; set; } + public BasicEmployeeVM? UpdatedBy { get; set; } + public DateTime? VerifiedAt { get; set; } + public bool? IsVerified { get; set; } + public BasicEmployeeVM? VerifiedBy { get; set; } + public Guid EntityId { get; set; } + public DocumentTypeVM? DocumentType { get; set; } + public bool IsActive { get; set; } = true; + } +} diff --git a/Marco.Pms.Services/Controllers/DocumentController.cs b/Marco.Pms.Services/Controllers/DocumentController.cs index 1a6b6ef..c0e5091 100644 --- a/Marco.Pms.Services/Controllers/DocumentController.cs +++ b/Marco.Pms.Services/Controllers/DocumentController.cs @@ -221,20 +221,66 @@ namespace Marco.Pms.Services.Controllers } } - // GET api//5 - [HttpGet("{id}")] - public async Task GetDetails(int id) + [HttpGet("get/details/{id}")] + public async Task GetDetailsAsync(Guid id) { + _logger.LogInfo("Starting GetDetails API for AttachmentId: {AttachmentId}", id); + + // Create a new DbContext instance to fetch data await using var _context = await _dbContextFactory.CreateDbContextAsync(); + + // Create a new scoped service provider to resolve scoped dependencies using var scope = _serviceScope.CreateScope(); + // Resolve the permission service from the scoped service provider + var _permission = scope.ServiceProvider.GetRequiredService(); + + // Get the currently logged-in employee var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync(); - //if (versionMapping.ChildAttachment != null && versionMapping.ChildAttachment.Document != null) - //{ - // var s3Service = scope.ServiceProvider.GetRequiredService(); - // documentVM.PreSignedUrl = s3Service.GeneratePreSignedUrl(versionMapping.ChildAttachment.Document.S3Key); - //} - return Ok(ApiResponse.SuccessResponse(new { }, "Filters for documents fetched successfully", 200)); + + _logger.LogDebug("Logged in employee id: {EmployeeId}", loggedInEmployee.Id); + + // Fetch the AttachmentVersionMapping with all necessary related data loaded eagerly + var versionMapping = await _context.AttachmentVersionMappings + .Include(av => av.ChildAttachment) + .ThenInclude(da => da!.UploadedBy) + .ThenInclude(e => e!.JobRole) + .Include(av => av.ChildAttachment) + .ThenInclude(da => da!.UpdatedBy) + .ThenInclude(e => e!.JobRole) + .Include(av => av.ChildAttachment) + .ThenInclude(da => da!.VerifiedBy) + .ThenInclude(e => e!.JobRole) + .Include(av => av.ChildAttachment) + .ThenInclude(da => da!.DocumentType) + .FirstOrDefaultAsync(av => av.ChildAttachmentId == id && av.TenantId == tenantId); + + // If no mapping found, return 404 + if (versionMapping == null || versionMapping.ChildAttachment == null) + { + _logger.LogWarning("AttachmentVersionMapping not found for AttachmentId: {AttachmentId}, TenantId: {TenantId}", + id, tenantId); + return NotFound(ApiResponse.ErrorResponse("Document Attachment not found", "Document Attachment not found in database", 404)); + } + + // Check if the logged in employee has permission to view the document OR is the owner of the attachment entity + var hasViewPermission = await _permission.HasPermission(PermissionsMaster.ViewDocument, loggedInEmployee.Id); + if (!hasViewPermission && loggedInEmployee.Id != versionMapping.ChildAttachment.EntityId) + { + _logger.LogWarning("Access Denied for Employee {EmployeeId} on EntityId {EntityId}", + loggedInEmployee.Id, versionMapping.ChildAttachment.EntityId); + return StatusCode(403, ApiResponse.ErrorResponse("Access Denied.", "You do not have permission to view documents", 403)); + } + + // Map the domain entity to the view model + var documentAttachmentVM = _mapper.Map(versionMapping.ChildAttachment); + documentAttachmentVM.Version = versionMapping.Version; + documentAttachmentVM.ParentAttachmentId = versionMapping.ParentAttachmentId; + + _logger.LogInfo("Document details fetched successfully for AttachmentId: {AttachmentId}", id); + + // Return success response with document details + return Ok(ApiResponse.SuccessResponse(documentAttachmentVM, "Document details fetched successfully", 200)); } [HttpGet("get/filter/{entityTypeId}")] @@ -333,6 +379,9 @@ namespace Marco.Pms.Services.Controllers // Create a new DbContext instance asynchronously await using var _context = await _dbContextFactory.CreateDbContextAsync(); + using var scope = _serviceScope.CreateScope(); + + var _permission = scope.ServiceProvider.GetRequiredService(); try { @@ -353,6 +402,16 @@ namespace Marco.Pms.Services.Controllers .Where(av => av.ParentAttachmentId == parentAttachmentId && av.TenantId == tenantId) .ToListAsync(); + var entityId = versionMappings.Select(av => av.ChildAttachment?.EntityId).FirstOrDefault(); + + // Check global permission + var hasViewPermission = await _permission.HasPermission(PermissionsMaster.ViewDocument, loggedInEmployee.Id); + if (!hasViewPermission && loggedInEmployee.Id != entityId) + { + _logger.LogWarning("Access Denied for Employee {EmployeeId} on EntityId {EntityId}", loggedInEmployee.Id, entityId ?? Guid.Empty); + return StatusCode(403, ApiResponse.ErrorResponse("Access Denied.", "You do not have permission to view documents", 403)); + } + _logger.LogInfo("Found {Count} versions for ParentAttachmentId: {ParentAttachmentId}", versionMappings.Count, parentAttachmentId); // Map the retrieved child attachments to view models with version info @@ -415,7 +474,6 @@ namespace Marco.Pms.Services.Controllers // Return the pre-signed URL with a success response } - /// /// Uploads a document attachment for an Employee or Project. /// Validates permissions, document type, entity existence, tags, and uploads to S3. diff --git a/Marco.Pms.Services/MappingProfiles/MappingProfile.cs b/Marco.Pms.Services/MappingProfiles/MappingProfile.cs index ea49414..8549bcf 100644 --- a/Marco.Pms.Services/MappingProfiles/MappingProfile.cs +++ b/Marco.Pms.Services/MappingProfiles/MappingProfile.cs @@ -311,13 +311,11 @@ namespace Marco.Pms.Services.MappingProfiles CreateMap(); CreateMap(); CreateMap(); - CreateMap(); + CreateMap(); CreateMap(); - CreateMap(); CreateMap(); - CreateMap(); #endregion -- 2.43.0