This commit is contained in:
Zeeshaun
2026-04-27 10:50:07 -05:00
parent 8b528fa00b
commit b5edd55420
141 changed files with 9602 additions and 0 deletions
@@ -0,0 +1,13 @@
namespace LCU.Api.Internal.FileOperations.Configurations;
public class ApiConfiguration
{
public string AppName { get; set; }
public string SeqUrl { get; set; }
public string SeqApiKey { get; set; }
public int AttemptsLimit { get; set; }
public int MaxFileCheckAttempts { get; set; }
public string ChromePath { get; set; }
public string FileOperationsChromeProfileFolderPath { get; set; }
public string[] CorsAllowedOrigins { get; set; }
}
@@ -0,0 +1,43 @@
using System;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Serilog;
using MassTransit;
using LCU.Api.Internal.FileOperations.Services;
using LCU.Library.Internal.Exceptions;
using LCU.Api.Internal.MaidBotLib.Models;
using LCU.Library.Internal.FileOperationsModels.Models;
namespace LCU.Api.Internal.FileOperations.Consumers;
public class FileOperationsConsumer : IConsumer<QueueRequest>
{
private readonly IServiceScopeFactory _scopeFactory;
public FileOperationsConsumer(IServiceScopeFactory scopeFactory)
{
_scopeFactory = scopeFactory;
}
public async Task Consume(ConsumeContext<QueueRequest> context)
{
try
{
using var scope = _scopeFactory.CreateScope();
await Task.Run(async () => await scope.ServiceProvider.GetRequiredService<IFileOperationsService>().HandleFileOperationsRequest(context.Message));
}
catch (ServiceException)
{
//Masstransit handles the exception. https://masstransit-project.com/usage/exceptions.html#retry
throw;
}
catch (Exception exception)
{
Log.ForContext(Enum.GetName(typeof(PropertyEnum), PropertyEnum.Group),
Enum.GetName(typeof(GroupEnum), GroupEnum.ITDevelopment))
.Fatal(exception, $"Unexpected Failure in FileOperations Api");
//Masstransit handles the exception. https://masstransit-project.com/usage/exceptions.html#retry
throw;
}
}
}
@@ -0,0 +1,60 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using LCU.Api.Internal.FileOperations.Extensions;
using LCU.Api.Internal.FileOperations.Services.FileActionServices;
using LCU.Library.Internal.ApiResponse.Models;
using LCU.Library.Internal.Exceptions;
using LCU.Library.Internal.FileOperationsModels.Models;
using LCU.Library.Internal.FileOperationsModels.Models.Requests;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Serilog;
namespace LCU.Api.Internal.FileOperations.Controllers;
[ApiController]
[Route("api/[controller]")]
public class DirectFileInformationController : ControllerBase
{
private readonly IFileSizeService _fileSizeService;
public DirectFileInformationController(IFileSizeService fileSizeService)
{
_fileSizeService = fileSizeService;
}
[HttpPost("GetFileSize")]
[ProducesResponseType(200)]
[ProducesResponseType(typeof(List<string>), 400)]
[ProducesResponseType(500)]
public IActionResult GetFileSize([FromBody] FileSizeRequest request)
{
try
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState.GetErrorMessages());
}
var validateResponse = _fileSizeService.PreQueueValidation(request);
if (!validateResponse.IsSuccessful)
{
return BadRequest($"Request is invalid. Response: {string.Join("\n ", validateResponse.MessageStack.ToArray())}");
}
var response = _fileSizeService.GetFileSize(request);
return Ok(response);
}
catch (ServiceException exception)
{
return StatusCode(StatusCodes.Status500InternalServerError, exception.Message);
}
catch (Exception exception)
{
Log.Error(exception, "Unexpected Exception");
return StatusCode(StatusCodes.Status500InternalServerError);
}
}
}
@@ -0,0 +1,146 @@
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Serilog;
using LCU.Api.Internal.FileOperations.Services;
using LCU.Api.Internal.FileOperations.Services.FileActionServices;
using LCU.Library.Internal.FileOperationsModels.Models;
using LCU.Library.Internal.Exceptions;
using LCU.Library.Internal.ApiResponse.Models;
namespace LCU.Api.Internal.FileOperations.Controllers;
[ApiController]
[Route("api/[controller]")]
public class DirectFileOperationsController : ControllerBase
{
private readonly IDirectFileOperationsService _directFileOperationsService;
private readonly IActionService<MoveFileRequest> _moveFileService;
private readonly IActionService<WriteFileRequest> _writeFileService;
private readonly IActionService<CreateDirectoryRequest> _createDirectoryRequestService;
private readonly IActionService<UnzipFileRequest> _unzipFileRequestService;
private readonly IActionService<ZipDirectoryRequest> _zipDirectoryRequestService;
private readonly IActionService<DeleteDirectoryRequest> _deleteDirectoryRequestService;
private readonly IActionService<DeleteFileRequest> _deleteFileRequestService;
private readonly IActionService<AppendFileRequest> _appendFileService;
public DirectFileOperationsController(IDirectFileOperationsService directFileOperationsService,
IActionService<MoveFileRequest> moveFileService,
IActionService<WriteFileRequest> writeFileRequest,
IActionService<CreateDirectoryRequest> createDirectoryRequestService,
IActionService<UnzipFileRequest> unzipFileRequestService,
IActionService<ZipDirectoryRequest> zipDirectoryRequestService,
IActionService<DeleteDirectoryRequest> deleteDirectoryRequestService,
IActionService<DeleteFileRequest> deleteFileRequestService,
IActionService<AppendFileRequest> appendFileService)
{
_directFileOperationsService = directFileOperationsService;
_moveFileService = moveFileService;
_writeFileService = writeFileRequest;
_createDirectoryRequestService = createDirectoryRequestService;
_unzipFileRequestService = unzipFileRequestService;
_zipDirectoryRequestService = zipDirectoryRequestService;
_deleteDirectoryRequestService = deleteDirectoryRequestService;
_deleteFileRequestService = deleteFileRequestService;
_appendFileService = appendFileService;
}
[HttpPost("MoveFile")]
[ProducesResponseType(200)]
[ProducesResponseType(typeof(ReturnResponse), 400)]
[ProducesResponseType(500)]
public async Task<IActionResult> MoveFile([FromBody] MoveFileRequest request)
{
return await HandleRequestResponse(request, FileOperationType.Move, _moveFileService);
}
[HttpPost("WriteFile")]
[ProducesResponseType(200)]
[ProducesResponseType(typeof(ReturnResponse), 400)]
[ProducesResponseType(500)]
public async Task<IActionResult> WriteFile([FromBody] WriteFileRequest request)
{
return await HandleRequestResponse(request, FileOperationType.WriteFile, _writeFileService);
}
[HttpPost("CreateDirectory")]
[ProducesResponseType(200)]
[ProducesResponseType(typeof(ReturnResponse), 400)]
[ProducesResponseType(500)]
public async Task<IActionResult> CreateDirectory([FromBody] CreateDirectoryRequest request)
{
return await HandleRequestResponse(request, FileOperationType.CreateDirectory, _createDirectoryRequestService);
}
[HttpPost("UnzipFile")]
[ProducesResponseType(200)]
[ProducesResponseType(typeof(ReturnResponse), 400)]
[ProducesResponseType(500)]
public async Task<IActionResult> UnzipFile([FromBody] UnzipFileRequest request)
{
return await HandleRequestResponse(request, FileOperationType.UnzipFile, _unzipFileRequestService);
}
[HttpPost("ZipDirectory")]
[ProducesResponseType(200)]
[ProducesResponseType(typeof(ReturnResponse), 400)]
[ProducesResponseType(500)]
public async Task<IActionResult> ZipDirectory([FromBody] ZipDirectoryRequest request)
{
return await HandleRequestResponse(request, FileOperationType.ZipDirectory, _zipDirectoryRequestService);
}
[HttpPost("DeleteDirectory")]
[ProducesResponseType(200)]
[ProducesResponseType(typeof(ReturnResponse), 400)]
[ProducesResponseType(500)]
public async Task<IActionResult> DeleteDirectory([FromBody] DeleteDirectoryRequest request)
{
return await HandleRequestResponse(request, FileOperationType.DeleteDirectory, _deleteDirectoryRequestService);
}
[HttpPost("DeleteFile")]
[ProducesResponseType(200)]
[ProducesResponseType(typeof(ReturnResponse), 400)]
[ProducesResponseType(500)]
public async Task<IActionResult> DeleteFile([FromBody] DeleteFileRequest request)
{
return await HandleRequestResponse(request, FileOperationType.Delete, _deleteFileRequestService);
}
[HttpPost("AppendFile")]
[ProducesResponseType(200)]
[ProducesResponseType(typeof(ReturnResponse), 400)]
[ProducesResponseType(500)]
public async Task<IActionResult> AppendFile([FromBody] AppendFileRequest request)
{
return await HandleRequestResponse(request, FileOperationType.AppendFile, _appendFileService);
}
public async Task<IActionResult> HandleRequestResponse<TRequest>(TRequest originalRequest,
FileOperationType operationType,
IActionService<TRequest> service) where TRequest : ReturnResponse
{
try
{
var validateResponse = service.PreQueueValidation(originalRequest);
if (!validateResponse.IsSuccessful)
{
return BadRequest($"Request is invalid. Response: {String.Join("\n ", validateResponse.MessageStack.ToArray())}");
}
var result = await _directFileOperationsService.HandleDirectFileOperationsRequest(originalRequest, operationType);
return Ok(result);
}
catch (ServiceException serviceException)
{
return StatusCode(StatusCodes.Status500InternalServerError, serviceException.Message);
}
catch (Exception exception)
{
Log.Error(exception, "Unexpected Exception");
return StatusCode(StatusCodes.Status500InternalServerError);
}
}
}
@@ -0,0 +1,45 @@
using System;
using System.Linq;
using System.Collections.Generic;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Serilog;
using LCU.Library.Internal.FileOperationsModels.Models;
using LCU.Api.Internal.FileOperations.Services;
namespace LCU.Api.Internal.FileOperations.Controllers;
[ApiController]
[Route("[controller]")]
public class DynamicDirectoryController : ControllerBase
{
private readonly IDynamicDirectoryService _dynamicDirectoryService;
public DynamicDirectoryController(IDynamicDirectoryService dynamicDirectoryService)
{
_dynamicDirectoryService = dynamicDirectoryService;
}
[HttpPost("BuildDirectoryList")]
[ProducesResponseType(201)]
[ProducesResponseType(404)]
[ProducesResponseType(typeof(List<string>), 400)]
[ProducesResponseType(500)]
public IActionResult BuildDirectoryList([FromBody] DynamicDirectoryListRequest request)
{
try
{
var result = _dynamicDirectoryService.BuildDirectoryList(request);
if (result == null || !result.Any())
{
return NotFound();
}
return Ok(result);
}
catch (Exception ex)
{
Log.Error(ex, "Failure Build Dynamic Directory List");
return StatusCode(StatusCodes.Status500InternalServerError);
}
}
}
@@ -0,0 +1,59 @@
using System;
using System.Collections.Generic;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Serilog;
using LCU.Library.Internal.FileOperationsModels.Models;
using LCU.Library.Internal.FileOperationsModels.Shared;
namespace LCU.Api.Internal.FileOperations.Controllers
{
[ApiController]
[Route("[controller]")]
public class DynamicFileController : ControllerBase
{
/// <summary>Gets a list of files based on regex substitution.</summary>
/// <remarks>
/// Example:
/// POST /api/BuildDynamicFileList
/// {
/// "path": "\\\\172.16.13.17\\Reports\\",
/// "filename": "Action_IndirectVehicleLoanSales_date_time.csv",
/// "dynamicFileSettings": {
/// "regexSettings": [
/// {
/// "tag": "date",
/// "regex": "\\d+_\\d+_\\d+"
/// },
/// {
/// "tag": "time",
/// "regex": "\\d+"
/// }],
/// "daysFromToday": 0
/// }
/// }
/// </remarks>
/// <param name="dynamicFileListRequest"></param>
/// <returns></returns>
// POST api/BuildDynamicFileList
[HttpPost("BuildDynamicFileList")]
[ProducesResponseType(201)]
[ProducesResponseType(typeof(List<string>), 400)]
[ProducesResponseType(500)]
public IActionResult BuildDynamicFileList([FromBody] DynamicFileListRequest dynamicFileListRequest)
{
try
{
var fileNames = RegexNameHandler.BuildFileList(dynamicFileListRequest.Path,
dynamicFileListRequest.Filename,
dynamicFileListRequest.DynamicFileSettings);
return Ok(fileNames);
}
catch (Exception ex)
{
Log.Error(ex, "Failure Build Dynamic File List");
return StatusCode(StatusCodes.Status500InternalServerError);
}
}
}
}
@@ -0,0 +1,62 @@
using System;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Serilog;
using LCU.Library.Internal.Exceptions;
using LCU.Api.Internal.FileOperations.Services.ExcelServices;
using LCU.Library.Internal.FileOperationsModels.Models.ExcelModels.Requests;
using LCU.Library.Internal.FileOperationsModels.Models.ExcelModels.Responses;
using LCU.Api.Internal.FileOperations.Extensions;
namespace LCU.Api.Internal.FileOperations.Controllers;
[ApiController]
[Route("api/[controller]")]
public class ExcelController : ControllerBase
{
private readonly IExcelService _excelService;
public ExcelController(IExcelService excelService)
{
_excelService = excelService;
}
/// <remarks>
/// This endpoint is a direct file operations call to extract excel workbook data. The ExcelDataRequest contains
/// the file content in a base64 encoded string for an excel sheet and it will extract all data into a json object.
/// The request also has optional SheetRequests in which a SheetName and specific Rows and Columns can be selected.
///
/// Notes:
/// - FileContent is required.
/// - SheetRequests are optional.
/// - If SheetRequests are added the SheetName is required.
/// - The SheetRequest's Rows and Columns are optional.
/// </remarks>
/// <param name="request"></param>
/// <returns>ExcelDataResponse</returns>
[HttpPost("ExtractExcelWorkBookData")]
[ProducesResponseType(200)]
[ProducesResponseType(typeof(ExcelDataResponse), 400)]
[ProducesResponseType(500)]
public IActionResult ExtractExcelWorkBookData([FromBody] ExcelDataRequest request)
{
try
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState.GetErrorMessages());
}
var requestResponse = _excelService.ExtractExcelWorkBookData(request);
return Ok(requestResponse);
}
catch (ServiceException exception)
{
return StatusCode(StatusCodes.Status500InternalServerError, exception.Message);
}
catch (Exception exception)
{
Log.Error(exception, "Unexpected Exception");
return StatusCode(StatusCodes.Status500InternalServerError);
}
}
}
@@ -0,0 +1,292 @@
using System;
using System.Threading.Tasks;
using System.Collections.Generic;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Serilog;
using LCU.Library.Internal.FileOperationsModels.Models;
using LCU.Library.Internal.Exceptions;
using LCU.Library.Internal.ApiResponse.Models;
using LCU.Api.Internal.FileOperations.Services.QueueServices;
using LCU.Api.Internal.FileOperations.Extensions;
using LCU.Api.Internal.FileOperations.Services;
using LCU.Api.Internal.FileOperations.Services.FileActionServices;
namespace LCU.Api.Internal.FileOperations.Controllers;
[Route("api/[controller]")]
[ApiController]
public class FileOperationsController : ControllerBase
{
private readonly IQueueFileOperationsService _queueFileOperationsService;
private readonly IActionService<MoveFileRequest> _moveFileService;
private readonly IActionService<CopyFileRequest> _copyFileService;
private readonly IActionService<DeleteFileRequest> _deleteFileService;
private readonly IActionService<ModifyFileRequest> _modifyFileService;
private readonly IActionService<RenameFileRequest> _renameFileService;
private readonly IActionService<ZipDirectoryRequest> _zipDirectoryService;
private readonly IActionService<UnzipFileRequest> _unzipFileService;
private readonly IActionService<UnzipPasswordProtectedFileRequest> _unzipPasswordProtectedFileService;
private readonly IActionService<CreateDirectoryRequest> _createDirectoryService;
private readonly IActionService<RenameDirectoryRequest> _renameDirectoryService;
private readonly IActionService<BulkOperationRequest<MoveFileRequest>> _bulkMoveFileService;
private readonly IActionService<EncryptFileDataRequest> _encryptFileDataService;
private readonly IActionService<DecryptFileDataRequest> _decryptFileDataService;
private readonly IActionService<WriteFileRequest> _writeFileDataService;
private readonly IActionService<DeleteDirectoryRequest> _deleteDirectoryService;
private readonly IActionService<DeleteEmptyDirectoryRequest> _deleteEmptyDirectoryService;
private readonly IDirectFileService _directFileService;
public FileOperationsController(IQueueFileOperationsService fileOperationsService,
IActionService<MoveFileRequest> moveFileService,
IActionService<CopyFileRequest> copyFileService,
IActionService<ModifyFileRequest> modifyFileService,
IActionService<DeleteFileRequest> deleteFileService,
IActionService<RenameFileRequest> renameFileService,
IActionService<ZipDirectoryRequest> zipDirectoryService,
IActionService<UnzipFileRequest> unzipFileService,
IActionService<UnzipPasswordProtectedFileRequest> unzipPasswordProtectedFileService,
IActionService<CreateDirectoryRequest> createDirectoryService,
IActionService<RenameDirectoryRequest> renameDirectoryService,
IActionService<BulkOperationRequest<MoveFileRequest>> bulkMoveFileService,
IActionService<EncryptFileDataRequest> encryptFileDataService,
IActionService<DecryptFileDataRequest> decryptFileDataService,
IActionService<WriteFileRequest> writeFileDataService,
IActionService<DeleteDirectoryRequest> deleteDirectoryService,
IActionService<DeleteEmptyDirectoryRequest> deleteEmptyDirectoryService,
IDirectFileService directFileService)
{
_queueFileOperationsService = fileOperationsService;
_moveFileService = moveFileService;
_copyFileService = copyFileService;
_modifyFileService = modifyFileService;
_deleteFileService = deleteFileService;
_renameFileService = renameFileService;
_zipDirectoryService = zipDirectoryService;
_unzipFileService = unzipFileService;
_unzipPasswordProtectedFileService = unzipPasswordProtectedFileService;
_createDirectoryService = createDirectoryService;
_renameDirectoryService = renameDirectoryService;
_bulkMoveFileService = bulkMoveFileService;
_encryptFileDataService = encryptFileDataService;
_decryptFileDataService = decryptFileDataService;
_directFileService = directFileService;
_writeFileDataService = writeFileDataService;
_deleteDirectoryService = deleteDirectoryService;
_deleteEmptyDirectoryService = deleteEmptyDirectoryService;
}
// Get api/{file}
[HttpGet("{filename}")]
[ProducesResponseType(200)]
[ProducesResponseType(400)]
public IActionResult GetFile([FromRoute] string filename)
{
if (string.IsNullOrWhiteSpace(filename))
{
return BadRequest("filename is required");
}
try
{
var result = _directFileService.GetFileBytes(filename);
return new FileContentResult(result, "application/octet-stream");
}
catch (ArgumentException ae)
{
Log.Error(ae, $"Request for bad file path {filename}");
return BadRequest("File path not found");
}
catch (Exception ex)
{
Log.Error(ex, $"Unexpected error retrieving file path {filename}");
return StatusCode(StatusCodes.Status500InternalServerError);
}
}
// POST api/MoveFile
[HttpPost("MoveFile")]
[ProducesResponseType(201)]
[ProducesResponseType(typeof(List<string>), 400)]
[ProducesResponseType(500)]
public async Task<IActionResult> MoveFile([FromBody] MoveFileRequest request)
{
return await HandleRequestResponse(request, FileOperationType.Move, _moveFileService);
}
// POST api/CopyFile
[HttpPost("CopyFile")]
[ProducesResponseType(201)]
[ProducesResponseType(typeof(List<string>), 400)]
[ProducesResponseType(500)]
public async Task<IActionResult> CopyFile([FromBody] CopyFileRequest request)
{
return await HandleRequestResponse(request, FileOperationType.Copy, _copyFileService);
}
// POST api/ModifyFile
[HttpPost("ModifyFile")]
[ProducesResponseType(201)]
[ProducesResponseType(typeof(List<string>), 400)]
[ProducesResponseType(500)]
public async Task<IActionResult> ModifyFile([FromBody] ModifyFileRequest request)
{
return await HandleRequestResponse(request, FileOperationType.Modify, _modifyFileService);
}
// POST api/DeleteFile
[HttpPost("DeleteFile")]
[ProducesResponseType(201)]
[ProducesResponseType(typeof(List<string>), 400)]
[ProducesResponseType(500)]
public async Task<IActionResult> DeleteFile([FromBody] DeleteFileRequest request)
{
return await HandleRequestResponse(request, FileOperationType.Delete, _deleteFileService);
}
// POST api/RenameFile
[HttpPost("RenameFile")]
[ProducesResponseType(201)]
[ProducesResponseType(typeof(List<string>), 400)]
[ProducesResponseType(500)]
public async Task<IActionResult> RenameFile([FromBody] RenameFileRequest request)
{
return await HandleRequestResponse(request, FileOperationType.Rename, _renameFileService);
}
// POST api/ZipDirectory
[HttpPost("ZipDirectory")]
[ProducesResponseType(201)]
[ProducesResponseType(typeof(List<string>), 400)]
[ProducesResponseType(500)]
public async Task<IActionResult> ZipDirectory([FromBody] ZipDirectoryRequest request)
{
return await HandleRequestResponse(request, FileOperationType.ZipDirectory, _zipDirectoryService);
}
// POST api/UnzipFile
[HttpPost("UnzipFile")]
[ProducesResponseType(201)]
[ProducesResponseType(typeof(List<string>), 400)]
[ProducesResponseType(500)]
public async Task<IActionResult> UnzipFile([FromBody] UnzipFileRequest request)
{
return await HandleRequestResponse(request, FileOperationType.UnzipFile, _unzipFileService);
}
// POST api/UnzipPasswordProtectedFile
[HttpPost("UnzipPasswordProtectedFile")]
[ProducesResponseType(201)]
[ProducesResponseType(typeof(List<string>), 400)]
[ProducesResponseType(500)]
public async Task<IActionResult> UnzipPasswordProtectedFile([FromBody] UnzipPasswordProtectedFileRequest request)
{
return await HandleRequestResponse(request, FileOperationType.UnzipPasswordProtectedFile, _unzipPasswordProtectedFileService);
}
// POST api/CreateDirectory
[HttpPost("CreateDirectory")]
[ProducesResponseType(201)]
[ProducesResponseType(typeof(List<string>), 400)]
[ProducesResponseType(500)]
public async Task<IActionResult> CreateDirectory([FromBody] CreateDirectoryRequest request)
{
return await HandleRequestResponse(request, FileOperationType.CreateDirectory, _createDirectoryService);
}
// POST api/RenameDirectory
[HttpPost("RenameDirectory")]
[ProducesResponseType(201)]
[ProducesResponseType(typeof(List<string>), 400)]
[ProducesResponseType(500)]
public async Task<IActionResult> RenameDirectory([FromBody] RenameDirectoryRequest request)
{
return await HandleRequestResponse(request, FileOperationType.RenameDirectory, _renameDirectoryService);
}
// POST api/BulkMoveFile
[HttpPost("BulkMoveFile")]
[ProducesResponseType(201)]
[ProducesResponseType(typeof(List<string>), 400)]
[ProducesResponseType(500)]
public async Task<IActionResult> BulkMoveFile([FromBody] BulkOperationRequest<MoveFileRequest> request)
{
return await HandleRequestResponse(request, FileOperationType.BulkMoveFile, _bulkMoveFileService);
}
// POST api/EncryptFileData
[HttpPost("EncryptFileData")]
[ProducesResponseType(201)]
[ProducesResponseType(typeof(List<string>), 400)]
[ProducesResponseType(500)]
public async Task<IActionResult> EncryptFileData([FromBody] EncryptFileDataRequest request)
{
return await HandleRequestResponse(request, FileOperationType.EncryptFileData, _encryptFileDataService);
}
// POST api/DecryptFileData
[HttpPost("DecryptFileData")]
[ProducesResponseType(201)]
[ProducesResponseType(typeof(List<string>), 400)]
[ProducesResponseType(500)]
public async Task<IActionResult> DecryptFileData([FromBody] DecryptFileDataRequest request)
{
return await HandleRequestResponse(request, FileOperationType.DecryptFileData, _decryptFileDataService);
}
// POST api/WriteFileData
[HttpPost("WriteFileData")]
[ProducesResponseType(201)]
[ProducesResponseType(typeof(List<string>), 400)]
[ProducesResponseType(500)]
public async Task<IActionResult> WriteFileData([FromBody] WriteFileRequest request)
{
return await HandleRequestResponse(request, FileOperationType.WriteFile, _writeFileDataService);
}
[HttpPost("DeleteDirectory")]
[ProducesResponseType(201)]
[ProducesResponseType(typeof(List<string>), 400)]
[ProducesResponseType(500)]
public async Task<IActionResult> DeleteDirectory([FromBody] DeleteDirectoryRequest request)
{
return await HandleRequestResponse(request, FileOperationType.DeleteDirectory, _deleteDirectoryService);
}
[HttpPost("DeleteEmptyDirectory")]
[ProducesResponseType(201)]
[ProducesResponseType(typeof(List<string>), 400)]
[ProducesResponseType(500)]
public async Task<IActionResult> DeleteEmptyDirectory([FromBody] DeleteEmptyDirectoryRequest request)
{
return await HandleRequestResponse(request, FileOperationType.DeleteEmptyDirectory, _deleteEmptyDirectoryService);
}
public async Task<IActionResult> HandleRequestResponse<TRequest>(TRequest originalRequest, FileOperationType operationType, IActionService<TRequest> service) where TRequest : ReturnResponse
{
try
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState.GetErrorMessages());
}
var validateResponse = service.PreQueueValidation(originalRequest);
if (!validateResponse.IsSuccessful)
{
return BadRequest($"Request is invalid. Response: {String.Join("\n ", validateResponse.MessageStack.ToArray())}");
}
await _queueFileOperationsService.QueueFileOperations(originalRequest, operationType);
return Ok();
}
catch (ServiceException)
{
return StatusCode(StatusCodes.Status500InternalServerError);
}
catch (Exception exception)
{
Log.Error(exception, "Unexpected Exception");
return StatusCode(StatusCodes.Status500InternalServerError);
}
}
}
@@ -0,0 +1,141 @@
using System;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Serilog;
using LCU.Library.Internal.FileOperationsModels.Models;
using LCU.Api.Internal.FileOperations.Validations;
using LCU.Api.Internal.FileOperations.Services.FileActionServices;
using System.Collections.Generic;
using System.Threading.Tasks;
using LCU.Api.Internal.FileOperations.Extensions;
using LCU.Library.Internal.Exceptions;
using LCU.Api.Internal.FileOperations.Services.QueueServices;
using LCU.Library.Internal.FileOperationsModels.Models.Requests;
namespace LCU.Api.Internal.FileOperations.Controllers;
[ApiController]
[Route("[controller]")]
public class FileValidationController : ControllerBase
{
private readonly IQueueFileOperationsService _queueFileOperationsService;
private readonly IActionService<ValidateFileRequest> _validateFileService;
private readonly IActionService<ValidateFileSizeInRangeRequest> _validateFileSizeInRangeService;
public FileValidationController(IQueueFileOperationsService fileOperationsService,
IActionService<ValidateFileRequest> validateFileService,
IActionService<ValidateFileSizeInRangeRequest> validateFileSizeInRangeService
)
{
_queueFileOperationsService = fileOperationsService;
_validateFileService = validateFileService;
_validateFileSizeInRangeService = validateFileSizeInRangeService;
}
// POST ValidateFileExists
[HttpPost("ValidateFileExists")]
[ProducesResponseType(200)]
[ProducesResponseType(typeof(bool), 400)]
[ProducesResponseType(500)]
public IActionResult ValidateFileExists([FromBody] string sourceFilePath)
{
try
{
var requestResponse = new RequestResponse();
requestResponse = FileValidation.ValidateFileExists(sourceFilePath, requestResponse);
return Ok(requestResponse.IsSuccessful);
}
catch (Exception exception)
{
Log.Error(exception, "Unexpected Exception");
return StatusCode(StatusCodes.Status500InternalServerError);
}
}
// POST api/QueueValidateFile
[HttpPost("QueueValidateFile")]
[ProducesResponseType(201)]
[ProducesResponseType(typeof(List<string>), 400)]
[ProducesResponseType(500)]
public async Task<IActionResult> ValidateFile([FromBody] ValidateFileRequest request)
{
try
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState.GetErrorMessages());
}
var validateResponse = _validateFileService.PreQueueValidation(request);
if (!validateResponse.IsSuccessful)
{
return BadRequest($"Request is invalid. Response: {String.Join("\n ", validateResponse.MessageStack.ToArray())}");
}
await _queueFileOperationsService.QueueFileOperations(request, FileOperationType.Validate);
return Accepted();
}
catch (ServiceException)
{
return StatusCode(StatusCodes.Status500InternalServerError);
}
catch (Exception exception)
{
Log.Error(exception, "Unexpected Exception");
return StatusCode(StatusCodes.Status500InternalServerError);
}
}
[HttpPost("ValidatePdfPageExists/{path}/{pageNumber:int}")]
[ProducesResponseType(200)]
[ProducesResponseType(typeof(bool), 400)]
[ProducesResponseType(500)]
public IActionResult ValidatePdfPageExists(string path, int pageNumber)
{
try
{
var requestResponse = new RequestResponse();
requestResponse = PdfValidations.ValidatePdfPageExists(requestResponse, path, pageNumber);
return Ok(requestResponse);
}
catch (Exception exception)
{
Log.Error(exception, "Unexpected Exception");
return StatusCode(StatusCodes.Status500InternalServerError);
}
}
// POST api/QueueValidateFileSizeInRange
[HttpPost("QueueValidateFileSizeInRange")]
[ProducesResponseType(201)]
[ProducesResponseType(typeof(List<string>), 400)]
[ProducesResponseType(500)]
public async Task<IActionResult> ValidateFileSizeInRange([FromBody] ValidateFileSizeInRangeRequest request)
{
try
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState.GetErrorMessages());
}
var validateResponse = _validateFileSizeInRangeService.PreQueueValidation(request);
if (!validateResponse.IsSuccessful)
{
return BadRequest($"Request is invalid. Response: {string.Join("\n ", validateResponse.MessageStack.ToArray())}");
}
await _queueFileOperationsService.QueueFileOperations(request, FileOperationType.ValidateFileSizeInRange);
return Accepted();
}
catch (ServiceException)
{
return StatusCode(StatusCodes.Status500InternalServerError);
}
catch (Exception exception)
{
Log.Error(exception, "Unexpected Exception");
return StatusCode(StatusCodes.Status500InternalServerError);
}
}
}
@@ -0,0 +1,51 @@
using System;
using System.Threading.Tasks;
using LCU.Api.Internal.FileOperations.Extensions;
using LCU.Api.Internal.FileOperations.Services.QueueServices;
using LCU.Library.Internal.FileOperationsModels.Models;
using LCU.Library.Internal.ApiResponse.Models;
using LCU.Library.Internal.Exceptions;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Serilog;
namespace LCU.Api.Internal.FileOperations.Controllers;
[ApiController]
[Route("api/[controller]")]
public class IndexFileController : ControllerBase
{
private readonly IQueueFileOperationsService _queueFileOperationsService;
public IndexFileController(IQueueFileOperationsService queueFileOperationsService)
{
_queueFileOperationsService = queueFileOperationsService;
}
[HttpPost("QueueExtractIndexFileData")]
[ProducesResponseType(200)]
[ProducesResponseType(typeof(ReturnResponse), 400)]
[ProducesResponseType(500)]
public async Task<IActionResult> QueueExtractIndexFileData([FromBody] ExtractIndexFileDataRequest request)
{
try
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState.GetErrorMessages());
}
await _queueFileOperationsService.QueueFileOperations(request, FileOperationType.ExtractIndexFileData);
return Accepted();
}
catch (ServiceException exception)
{
return StatusCode(StatusCodes.Status500InternalServerError, exception.Message);
}
catch (Exception exception)
{
Log.Error(exception, "Unexpected Exception");
return StatusCode(StatusCodes.Status500InternalServerError);
}
}
}
@@ -0,0 +1,185 @@
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Serilog;
using LCU.Api.Internal.FileOperations.Services;
using LCU.Library.Internal.FileOperationsModels.Models;
using LCU.Library.Internal.Exceptions;
using LCU.Library.Internal.FileOperationsModels.Models.HtmlToPdfModels;
using LCU.Api.Internal.FileOperations.Extensions;
using LCU.Api.Internal.FileOperations.Services.QueueServices;
using LCU.Api.Internal.FileOperations.Services.PdfServices;
namespace LCU.Api.Internal.FileOperations.Controllers;
[ApiController]
[Route("api/[controller]")]
public class PdfController : ControllerBase
{
private readonly IQueueFileOperationsService _queueFileOperationsService;
private readonly IPdfParserService _pdfParserService;
private readonly IBatchPdfParserService _batchPdfParserService;
private readonly IDirectFileService _directFileService;
private readonly IHtmlToPdfService _htmlToPdfService;
public PdfController(IQueueFileOperationsService queueFileOperationsService,
IPdfParserService pdfParserService,
IBatchPdfParserService batchPdfParserService,
IDirectFileService directFileService,
IHtmlToPdfService htmlToPdfService)
{
_queueFileOperationsService = queueFileOperationsService;
_batchPdfParserService = batchPdfParserService;
_pdfParserService = pdfParserService;
_directFileService = directFileService;
_htmlToPdfService = htmlToPdfService;
}
[HttpPost("QueueBatchPdfParser")]
[ProducesResponseType(202)]
[ProducesResponseType(400)]
[ProducesResponseType(500)]
public async Task<IActionResult> QueueBatchPdfParser([FromBody] BatchParsePdfRequest request)
{
try
{
var requestResponse = _batchPdfParserService.IsRequestValid(request, new RequestResponse());
if (!requestResponse.IsSuccessful)
{
return BadRequest($"Request is invalid. Response: {String.Join("\n ", requestResponse.MessageStack.ToArray())}");
}
await _queueFileOperationsService.QueueFileOperations(request, FileOperationType.BatchPdfParser);
return Accepted();
}
catch (ServiceException exception)
{
return StatusCode(StatusCodes.Status500InternalServerError, exception.Message);
}
catch (Exception exception)
{
Log.Error(exception, "Unexpected Exception");
return StatusCode(StatusCodes.Status500InternalServerError);
}
}
/// <remarks>
/// This will parse a PDF from a starting page to and a stopping page, save new pdf to RootPath,
/// and returns the PDF name. The PDF name will be set to ParsedPdfname or the default "{pdfParserRequest.PdfName}.{pdfParserRequest.StartingPage}.pdf".
///
/// Notes:
/// - Page numbers range from 1-x.
/// - If PDF exists it will automatically overwrite.
/// - Original PDF can be open at the time of parsing.
/// </remarks>
/// <param name="pdfParserRequest"></param>
/// <returns></returns>
[HttpPost("ParsePdf")]
[ProducesResponseType(200)]
[ProducesResponseType(typeof(ParsePdfRequest), 400)]
[ProducesResponseType(500)]
public IActionResult ParsePdf([FromBody] ParsePdfRequest pdfParserRequest)
{
try
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState.GetErrorMessages());
}
var result = _pdfParserService.ParsePdf(pdfParserRequest);
return Ok(result);
}
catch (ServiceException exception)
{
return StatusCode(StatusCodes.Status500InternalServerError, exception.Message);
}
catch (Exception exception)
{
Log.Error(exception, "Unexpected Exception");
return StatusCode(StatusCodes.Status500InternalServerError);
}
}
[HttpGet("GetPdfContent/{pdfPath}")]
[ProducesResponseType(200)]
[ProducesResponseType(400)]
[ProducesResponseType(500)]
public IActionResult GetPdfContent([FromRoute] string pdfPath)
{
if (string.IsNullOrWhiteSpace(pdfPath))
{
return BadRequest("PDF Path is required");
}
try
{
var result = _directFileService.GetFileBytes(pdfPath);
return new FileContentResult(result, "application/pdf");
}
catch (ArgumentException ae)
{
Log.Error(ae, $"Request for bad PDF path {pdfPath}");
return BadRequest("PDF path not found");
}
catch (Exception ex)
{
Log.Error(ex, $"Unexpected error retrieving PDF path {pdfPath}");
return StatusCode(StatusCodes.Status500InternalServerError);
}
}
/// <remarks>
/// ConvertHmtlToPdf will take the HtmlToPdfRequest and generate a HTML file filling in the tags with the supplied data.
/// It will then utilize Chrome functionality to print a pdf and save it to a location. Finally converting to byte array and returning.
///
/// HtmlToPdfRequest:
/// - HtmlTemplateFilePath: (REQUIRED) File Path of the main html template that the HTML file will start to build.
/// - PdfName: (REQUIRED) What the PDF and HTML files will be called.
/// - KeepHtmlFile: (Defaults = False) Mostly for testing purposes. If set to true it will keep the generated HTML file.
/// - KeepPdfFile: (Defaults = False) Mostly for testing purposes. If set to true it will keep the generated PDF file
/// - HtmlSaveFilePath: (REQUIRED) Location that the generated HTML file will be temporarily (KeepHtmlFile = false) stored.
/// - PdfSaveFilePath: (REQUIRED) Location that the generated PDF file will be temporarily (KeepHtmlFile = false) stored.
/// - BodyTagValues: Tags that will be filled in with supplied values.
/// - TagValues:
/// - Tag: (REQUIRED) Name of the tag in the HTML. In HTML should be surrounded by {}. This tag does not need {}.
/// - Value: (REQUIRED) Value in which will replace the {TagName}.
/// - BodyValueCollections: List of ValueCollections that give us the ability to replace a tag that is associated with a HTML Template. The ValucollectionItems is
/// looped through to generate what will replace the tag. Common use case would be a list of items or a table of items.
/// - CollectionTag: (REQUIRED) Name of the tag in the HTML. In HTML should be surrounded by {}. This tag does not need {}.
/// - CollectionHtmlTemplateFilePath: (REQUIRED) File Path of the collections html template that the HTML file will start to build.
/// - ValueCollectionItems: List of ValueCollectionItems that can be looped through to help build out what the CollectionTag will be replaced with.
/// ValueCollection has a nested ValueCollectionItems, giving the ability to create infinite amount of nested collections within collections.
/// - TagValues: List of TagValues
/// - ValueCollections: List of ValueCollections
///
/// Notes:
/// - In HTML templates tags should be surrounded by braces {TagName}. The request does not need the braces {}.
/// - Any unused tags surrounded by braces will be removed at the end of the process.
/// - Can use \\\\zeus\DataIntegrationsQA\\PDFCreation\\ folder to store templates, generated HTML files, and generated PDF
/// - \\\\zeus\DataIntegrationsQA\\PDFCreation\\Html_Templates
/// - \\\\zeus\DataIntegrationsQA\\PDFCreation\\Html_Drop
/// - \\\\zeus\DataIntegrationsQA\\PDFCreation\\PDF_Drop
/// </remarks>
[HttpPost("ConvertHtmlToPdf")]
[ProducesResponseType(200)]
[ProducesResponseType(400)]
[ProducesResponseType(500)]
public IActionResult ConvertHtmlToPdf([FromBody] HtmlToPdfRequest htmlToPdfRequest)
{
try
{
var result = _htmlToPdfService.ConvertHtmlToPdf(htmlToPdfRequest);
return new FileContentResult(result, "application/pdf");
}
catch (ServiceException exception)
{
return StatusCode(StatusCodes.Status500InternalServerError, exception.Message);
}
catch (Exception exception)
{
Log.Error(exception, "Unexpected Exception");
return StatusCode(StatusCodes.Status500InternalServerError);
}
}
}
@@ -0,0 +1,39 @@
using System;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Http;
using Serilog;
using LCU.Library.Internal.Exceptions;
using LCU.Library.Internal.Status.Services;
namespace LCU.Api.Internal.FileOperations.Controllers;
[ApiController]
[Route("api/[controller]")]
public class StatusController : ControllerBase
{
private readonly IApiHealthCheckService _apiHealthCheckService;
public StatusController(IApiHealthCheckService apiHealthCheckService)
{
_apiHealthCheckService = apiHealthCheckService;
}
[HttpGet]
[ProducesResponseType(200)]
[ProducesResponseType(500)]
public IActionResult Get()
{
try
{
return Ok(_apiHealthCheckService.CheckApiHealthAndBuildEnvironmentView());
}
catch (ServiceException exception)
{
return StatusCode(StatusCodes.Status500InternalServerError, exception.Message);
}
catch (Exception exception)
{
Log.Error(exception, "Unexpected Exception");
return StatusCode(StatusCodes.Status500InternalServerError);
}
}
}
@@ -0,0 +1,16 @@
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Mvc.ModelBinding;
namespace LCU.Api.Internal.FileOperations.Extensions
{
public static class ModelStateMessages
{
public static List<string> GetErrorMessages(this ModelStateDictionary dictionary)
{
return dictionary.SelectMany(m => m.Value.Errors)
.Select(m => m.ErrorMessage)
.ToList();
}
}
}
@@ -0,0 +1,82 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel>
<Version>3.0.0</Version>
<Description>
2.0.0 - Adding the use of DynamicNameSettings
2.1.0 - Added CreateDirectory and RenameDirectory. Also the IActionService is taking over as the service interface for all the action services.
2.2.0 - Addition of the RegexSettings for the Copy, Delete, and Move file operation.
2.3.0 - Added NameSettings for RenameFile NewFileName field.
2.4.0 - Fix to add failure validation for no files available for Moveing, Copying, and Deleteing with regex.
2.5.0 - New BulkOperationsRequest and some service refactoring.
2.6.0 - New UnzipFile functionality.
2.7.0 - Dynamiz Zip and Unzip functionality
2.8.0 - Add File Data Encryption/Decryption Actions.
2.9.0 - Add SucceedOnError to Copy/Rename/Move/Delete File
2.10.0 - Upgrade ApiResponse, change to await async QueueReturnResponse.
2.11.0 - New UnzipPasswordProtectedFile functionality.
2.12.0 - Upgrade to dotnet8.
3.0.0 - Updated models project reference.
</Description>
<PackageReleaseNotes>
2.0.0 - Adding the use of DynamicNameSettings
2.1.0 - Added CreateDirectory and RenameDirectory. Also the IActionService is taking over as the service interface for all the action services.
2.2.0 - Addition of the RegexSettings for the Copy, Delete, and Move file operation.
2.3.0 - Added NameSettings for RenameFile NewFileName field.
2.4.0 - Fix to add failure validation for no files available for Moveing, Copying, and Deleteing with regex.
2.5.0 - New BulkOperationsRequest and some service refactoring.
2.6.0 - New UnzipFile functionality.
2.7.0 - Dynamiz Zip and Unzip functionality
2.8.0 - Add File Data Encryption/Decryption Actions.
2.9.0 - Add SucceedOnError to Copy/Rename/Move/Delete File
2.10.0 - Upgrade ApiResponse, change to await async QueueReturnResponse.
2.11.0 - New UnzipPasswordProtectedFile functionality.
2.12.0 - Upgrade to dotnet8.
3.0.0 - Updated models project reference.
</PackageReleaseNotes>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DocumentationFile>C:\dev\projects\LCU.API.Internal.FileOperations\LCU.Api.Internal.FileOperations\LCU.Api.Internal.FileOperations.xml</DocumentationFile>
<NoWarn>1701;1702;1591</NoWarn>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<DocumentationFile>C:\dev\projects\LCU.API.Internal.FileOperations\LCU.Api.Internal.FileOperations\LCU.Api.Internal.FileOperations.xml</DocumentationFile>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="CsvHelper" Version="32.0.3" />
<PackageReference Include="DocumentFormat.OpenXml" Version="2.20.0" />
<PackageReference Include="LCU.Api.Internal.MaidBotLib" Version="1.0.0" />
<PackageReference Include="LCU.Library.Internal.ApiResponse" Version="3.4.0" />
<PackageReference Include="LCU.Library.Internal.Configuration" Version="1.0.0" />
<PackageReference Include="LCU.Library.Internal.LcuEvaluation" Version="3.0.0" />
<PackageReference Include="LCU.Library.Internal.LcuMassTransit" Version="1.0.0" />
<PackageReference Include="LCU.Library.Internal.LcuMassTransitModels" Version="1.1.0" />
<PackageReference Include="LCU.Library.Internal.LCUServiceFactory" Version="2.0.0" />
<PackageReference Include="LCU.Library.Internal.Status" Version="1.2.0" />
<PackageReference Include="LCU.Library.Internal.StatusModels" Version="1.1.0" />
<PackageReference Include="LCU.Library.Internal.TypeExtentions" Version="1.1.1" />
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="2.2.3" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="PdfSharp" Version="1.50.5147" />
<PackageReference Include="Portable.BouncyCastle" Version="1.9.0" />
<PackageReference Include="Serilog" Version="2.10.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="3.1.1" />
<PackageReference Include="SharpZipLib" Version="1.3.3" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="5.6.3" />
<PackageReference Include="System.Text.Encoding.CodePages" Version="6.0.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\LCU.Library.Internal.FileOperationsModels\LCU.Library.Internal.FileOperationsModels.csproj" />
</ItemGroup>
<ItemGroup>
<Folder Include="Properties\" />
</ItemGroup>
</Project>
@@ -0,0 +1,42 @@
<?xml version="1.0"?>
<doc>
<assembly>
<name>LCU.Api.Internal.FileOperations</name>
</assembly>
<members>
<member name="M:LCU.Api.Internal.FileOperations.Controllers.DynamicFileController.BuildDynamicFileList(LCU.Library.Internal.FileOperationsModels.Models.DynamicFileListRequest)">
<summary>Gets a list of files based on regex substitution.</summary>
<remarks>
Example:
POST /api/BuildDynamicFileList
{
"path": "\\\\172.16.13.17\\Reports\\",
"filename": "Action_IndirectVehicleLoanSales_date_time.csv",
"dynamicFileSettings": {
"regexSettings": [
{
"tag": "date",
"regex": "\\d+_\\d+_\\d+"
},
{
"tag": "time",
"regex": "\\d+"
}],
"daysFromToday": 0
}
}
</remarks>
<param name="dynamicFileListRequest"></param>
<returns></returns>
</member>
<member name="M:LCU.Api.Internal.FileOperations.Services.FileActionServices.BulkOperationService`1.ExecuteAction(LCU.Api.Internal.FileOperations.Models.QueueRequest)">
<summary>
Bulk Operations was created to always try. This meaning that it should try to attempt
every operation action. This also means that it will alway try to also return response and
that it always returns true (Exeption being catastrophic exeption thrown).
</summary>
<param name="queueRequest"></param>
<returns></returns>
</member>
</members>
</doc>
@@ -0,0 +1,128 @@
using System.ComponentModel.DataAnnotations;
using CsvHelper.Configuration.Attributes;
using LCU.Library.Internal.LcuEvaluationModels.Requests;
namespace LCU.Api.Internal.FileOperations.Models;
public class IndexEvaluationRequest : EvaluationRequest
{
[Index(0)]
[Display(Name = "InputFieldZero")]
public string InputFieldZero { get; set; }
[Index(1)]
[Display(Name = "InputFieldOne")]
public string InputFieldOne { get; set; }
[Index(2)]
[Display(Name = "InputFieldTwo")]
public string InputFieldTwo { get; set; }
[Index(3)]
[Display(Name = "InputFieldThree")]
public string InputFieldThree { get; set; }
[Index(4)]
[Display(Name = "InputFieldFour")]
public string InputFieldFour { get; set; }
[Index(5)]
[Display(Name = "InputFieldFive")]
public string InputFieldFive { get; set; }
[Index(6)]
[Display(Name = "InputFieldSix")]
public string InputFieldSix { get; set; }
[Index(7)]
[Display(Name = "InputFieldSeven")]
public string InputFieldSeven { get; set; }
[Index(8)]
[Display(Name = "InputFieldEight")]
public string InputFieldEight { get; set; }
[Index(9)]
[Display(Name = "InputFieldNine")]
public string InputFieldNine { get; set; }
[Index(10)]
[Display(Name = "InputFieldTen")]
public string InputFieldTen { get; set; }
[Index(11)]
[Display(Name = "InputFieldEleven")]
public string InputFieldEleven { get; set; }
[Index(12)]
[Display(Name = "InputFieldTwelve")]
public string InputFieldTwelve { get; set; }
[Index(13)]
[Display(Name = "InputFieldThirteen")]
public string InputFieldThirteen { get; set; }
[Index(14)]
[Display(Name = "InputFieldFourteen")]
public string InputFieldFourteen { get; set; }
[Index(15)]
[Display(Name = "InputFieldFifteen")]
public string InputFieldFifteen { get; set; }
[Index(16)]
[Display(Name = "InputFieldSixteen")]
public string InputFieldSixteen { get; set; }
[Index(17)]
[Display(Name = "InputFieldSeventeen")]
public string InputFieldSeventeen { get; set; }
[Index(18)]
[Display(Name = "InputFieldEighteen")]
public string InputFieldEighteen { get; set; }
[Index(19)]
[Display(Name = "InputFieldNineteen")]
public string InputFieldNineteen { get; set; }
[Index(20)]
[Display(Name = "InputFieldTwenty")]
public string InputFieldTwenty { get; set; }
[Index(21)]
[Display(Name = "InputFieldTwentyOne")]
public string InputFieldTwentyOne { get; set; }
[Index(22)]
[Display(Name = "InputFieldTwentyTwo")]
public string InputFieldTwentyTwo { get; set; }
[Index(23)]
[Display(Name = "InputFieldTwentyThree")]
public string InputFieldTwentyThree { get; set; }
[Index(24)]
[Display(Name = "InputFieldTwentyFour")]
public string InputFieldTwentyFour { get; set; }
[Index(25)]
[Display(Name = "InputFieldTwentyFive")]
public string InputFieldTwentyFive { get; set; }
[Index(26)]
[Display(Name = "InputFieldTwentySix")]
public string InputFieldTwentySix { get; set; }
[Index(27)]
[Display(Name = "InputFieldTwentySeven")]
public string InputFieldTwentySeven { get; set; }
[Index(28)]
[Display(Name = "InputFieldTwentyEight")]
public string InputFieldTwentyEight { get; set; }
[Index(29)]
[Display(Name = "InputFieldTwentyNine")]
public string InputFieldTwentyNine { get; set; }
}
@@ -0,0 +1,227 @@
using System;
using System.IO;
using System.Reflection;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Serilog;
using MassTransit;
using LCU.Library.Internal.FileOperationsModels.Models;
using LCU.Library.Internal.LcuEvaluation;
using LCU.Library.Internal.LcuMassTransit;
using LCU.Library.Internal.LcuMassTransitModels;
using LCU.Library.Internal.Status;
using LCU.Library.Internal.Configuration;
using LCU.Library.Internal.FileOperationsModels.Models.Requests;
using LCU.Library.Internal.LCUServiceFactory;
using LCU.Library.Internal.LCUServiceFactory.Configurations;
using LCU.Library.Internal.Logging.Models;
using LCU.Library.Internal.Logging;
using LCU.Api.Internal.FileOperations.Configurations;
using LCU.Api.Internal.FileOperations.Consumers;
using LCU.Api.Internal.FileOperations.Services;
using LCU.Api.Internal.FileOperations.Services.ExcelServices;
using LCU.Api.Internal.FileOperations.Services.FileActionServices;
using LCU.Api.Internal.FileOperations.Services.PdfServices;
using LCU.Api.Internal.FileOperations.Services.QueueServices;
string MyAllowSpecificOrigins = "_myAllowSpecificOrigins";
var builder = BuildBuilder(args);
BuildServicesAndConfigurations(builder);
BuildAppAndRun(builder);
WebApplicationBuilder BuildBuilder(string[] args)
{
var builder = WebApplication.CreateBuilder(args);
builder.Host.UseSerilog();
return builder;
}
void BuildServicesAndConfigurations(WebApplicationBuilder builder)
{
var services = builder.Services;
var configuration = builder.Configuration;
//Configurations
var apiConfiguration = configuration.Bind<ApiConfiguration>(services, "Primary");
var servicesFactoryConfiguration = configuration.Bind<ServicesFactoryConfiguration>(services);
services.AddSingleton(apiConfiguration);
var loggerConfiguration = new LoggingConfiguration(apiConfiguration.AppName,
apiConfiguration.SeqApiKey,
apiConfiguration.SeqUrl);
var lcuLogging = new LcuLogging(loggerConfiguration);
lcuLogging.UseLcuLogging();
var connectionConfiguration = MassTransitConfigurationSetUp.AddConnectionConfiguration(ref services, configuration);
var receiveEndpointConfiguration = MassTransitConfigurationSetUp.GetReceiveEndpointConfiguration(configuration, "FileOperationsReceiveEndpoint");
services.AddSingleton(receiveEndpointConfiguration);
AddMassTransitServices(ref services, connectionConfiguration, receiveEndpointConfiguration);
//Services
services.AddLCUStatusServicesWithApiHealthCheck(configuration);
services.AddLcuEvaluationServices();
AddFileOperationServices(services);
AddFileActionServices(services);
AddServiceFactoryServices(services);
AddPdfServices(services);
AddExcelServices(services);
services.AddLCUServiceFactoryAndValidateServiceRegistration<IFileActionService>(servicesFactoryConfiguration);
services.AddControllers();
services.AddCors(options =>
{
options.AddPolicy(MyAllowSpecificOrigins,
builder =>
{
builder.WithOrigins(
apiConfiguration.CorsAllowedOrigins
).AllowAnyHeader().AllowAnyMethod();
});
});
// Register the Swagger generator, defining 1 or more Swagger documents
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new Microsoft.OpenApi.Models.OpenApiInfo { Title = "File Operations API", Version = "v1" });
// For this to work, I also had to check the generate xml box in build options.
var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.XML";
var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
c.IncludeXmlComments(xmlPath);
});
}
void BuildAppAndRun(WebApplicationBuilder builder)
{
var app = builder.Build();
app.UseSwagger();
// Enable middleware to serve swagger-ui (HTML, JS, CSS, etc.),
// specifying the Swagger JSON endpoint.
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/swagger/v1/swagger.json", "File Operations API");
});
if (app.Environment.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseAuthentication();
app.UseCors(MyAllowSpecificOrigins);
app.UseHttpsRedirection();
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
}
);
app.Run();
}
void AddFileOperationServices(IServiceCollection services)
{
services.AddScoped<IQueueFileOperationsService, QueueFileOperationsService>();
services.AddScoped<IFileOperationsService, FileOperationsService>();
services.AddScoped<IDirectFileOperationsService, DirectFileOperationsService>();
services.AddScoped<IDirectFileService, DirectFileService>();
services.AddScoped<IDynamicDirectoryService, DynamicDirectoryService>();
services.AddScoped<IFileSizeService, FileSizeService>();
}
void AddServiceFactoryServices(IServiceCollection services)
{
services.AddScoped<IFileActionService, MoveFileService>();
services.AddScoped<IFileActionService, CopyFileService>();
services.AddScoped<IFileActionService, DeleteFileService>();
services.AddScoped<IFileActionService, RenameFileService>();
services.AddScoped<IFileActionService, ZipDirectoryService>();
services.AddScoped<IFileActionService, CreateDirectoryService>();
services.AddScoped<IFileActionService, RenameDirectoryService>();
services.AddScoped<IFileActionService, BulkOperationService<MoveFileRequest>>();
services.AddScoped<IFileActionService, UnzipFileService>();
services.AddScoped<IFileActionService, EncryptFileDataService>();
services.AddScoped<IFileActionService, DecryptFileDataService>();
services.AddScoped<IFileActionService, ModifyFileService>();
services.AddScoped<IFileActionService, UnzipPasswordProtectedFileService>();
services.AddScoped<IFileActionService, BatchPdfParserService>();
services.AddScoped<IFileActionService, WriteFileService>();
services.AddScoped<IFileActionService, DeleteDirectoryService>();
services.AddScoped<IFileActionService, ValidateFileService>();
services.AddScoped<IFileActionService, AppendFileService>();
services.AddScoped<IFileActionService, ExtractIndexFileDataService>();
services.AddScoped<IFileActionService, DeleteEmptyDirectoryService>();
services.AddScoped<IFileActionService, ValidateFileSizeInRangeService>();
}
void AddFileActionServices(IServiceCollection services)
{
services.AddScoped<IActionService<MoveFileRequest>, MoveFileService>();
services.AddScoped<IActionService<ModifyFileRequest>, ModifyFileService>();
services.AddScoped<IActionService<CopyFileRequest>, CopyFileService>();
services.AddScoped<IActionService<DeleteFileRequest>, DeleteFileService>();
services.AddScoped<IActionService<RenameFileRequest>, RenameFileService>();
services.AddScoped<IActionService<ZipDirectoryRequest>, ZipDirectoryService>();
services.AddScoped<IActionService<UnzipFileRequest>, UnzipFileService>();
services.AddScoped<IActionService<UnzipPasswordProtectedFileRequest>, UnzipPasswordProtectedFileService>();
services.AddScoped<IActionService<ValidateFileRequest>, ValidateFileService>();
services.AddScoped<IActionService<CreateDirectoryRequest>, CreateDirectoryService>();
services.AddScoped<IActionService<RenameDirectoryRequest>, RenameDirectoryService>();
services.AddScoped<IActionService<BulkOperationRequest<MoveFileRequest>>, BulkOperationService<MoveFileRequest>>();
services.AddScoped<IActionService<EncryptFileDataRequest>, EncryptFileDataService>();
services.AddScoped<IActionService<DecryptFileDataRequest>, DecryptFileDataService>();
services.AddScoped<IActionService<WriteFileRequest>, WriteFileService>();
services.AddScoped<IActionService<DeleteDirectoryRequest>, DeleteDirectoryService>();
services.AddScoped<IActionService<AppendFileRequest>, AppendFileService>();
services.AddScoped<IActionService<ExtractIndexFileDataRequest>, ExtractIndexFileDataService>();
services.AddScoped<IActionService<DeleteEmptyDirectoryRequest>, DeleteEmptyDirectoryService>();
services.AddScoped<IActionService<ValidateFileSizeInRangeRequest>, ValidateFileSizeInRangeService>();
}
void AddPdfServices(IServiceCollection services)
{
services.AddScoped<IBatchPdfParserService, BatchPdfParserService>();
services.AddScoped<IPdfParserService, PdfParserService>();
services.AddScoped<IHtmlToPdfService, HtmlToPdfService>();
}
void AddExcelServices(IServiceCollection services)
{
services.AddScoped<IExcelService, ExcelService>();
}
void AddMassTransitServices(ref IServiceCollection services,
ConnectionConfiguration connectionConfiguration,
ReceiveEndpointConfiguration receiveEndpointConfiguration)
{
services.AddMassTransit(x =>
{
x.AddConsumer<FileOperationsConsumer>();
x.UsingRabbitMq((context, cfg) =>
{
cfg.Host(connectionConfiguration.HostUrl, "/", host =>
{
host.Username(connectionConfiguration.UserName);
host.Password(connectionConfiguration.Password);
});
cfg.ReceiveEndpoint(receiveEndpointConfiguration.ReceiveEndpoint, e =>
{
e.ConfigureConsumer<FileOperationsConsumer>(context);
e.SetQuorumQueue();
e.PrefetchCount = receiveEndpointConfiguration.PrefetchLimit;
});
});
});
services.AddMassTransitHostedService();
}
@@ -0,0 +1,213 @@
using Org.BouncyCastle.Bcpg;
using Org.BouncyCastle.Bcpg.OpenPgp;
using Org.BouncyCastle.Security;
using System;
using System.IO;
using System.Text;
using Org.BouncyCastle.Utilities.IO;
namespace LCU.Api.Internal.FileOperations.Services
{
public static class CryptoHelper
{
private static PgpPublicKey ReadPublicKey(Stream inputStream)
{
inputStream = PgpUtilities.GetDecoderStream(inputStream);
PgpPublicKeyRingBundle pgpPub = new PgpPublicKeyRingBundle(inputStream);
foreach (PgpPublicKeyRing keyRing in pgpPub.GetKeyRings())
{
foreach (PgpPublicKey key in keyRing.GetPublicKeys())
{
if (key.IsEncryptionKey)
{
return key;
}
}
}
throw new ArgumentException("Can't find encryption key in key ring.");
}
private static PgpPrivateKey FindSecretKey(PgpSecretKeyRingBundle pgpSec, long keyId, char[] pass)
{
PgpSecretKey pgpSecKey = pgpSec.GetSecretKey(keyId);
return pgpSecKey?.ExtractPrivateKey(pass);
}
public static void DecryptPgpFile(string inputFile, string outputFile, string keyFile, string passPhrase)
{
var encryptedFileData = File.ReadAllBytes(inputFile);
var secretKeyData = File.ReadAllBytes(keyFile);
var decryptedData = DecryptPgpData(encryptedFileData, secretKeyData, passPhrase);
File.WriteAllText(outputFile, decryptedData);
}
public static string DecryptPgpData(byte[] inputData, byte[] secretKeyData, string passPhrase)
{
Stream inputStream = new MemoryStream(inputData);
Stream secretKeyStream = new MemoryStream(secretKeyData);
string output;
PgpObjectFactory pgpFactory = new PgpObjectFactory(PgpUtilities.GetDecoderStream(inputStream));
// find secret key
PgpSecretKeyRingBundle pgpKeyRing = new PgpSecretKeyRingBundle(PgpUtilities.GetDecoderStream(secretKeyStream));
PgpObject pgp = null;
if (pgpFactory != null)
{
pgp = pgpFactory.NextPgpObject();
}
// the first object might be a PGP marker packet.
PgpEncryptedDataList encryptedData = null;
if (pgp is PgpEncryptedDataList)
{
encryptedData = (PgpEncryptedDataList)pgp;
}
else
{
encryptedData = (PgpEncryptedDataList)pgpFactory.NextPgpObject();
}
// decrypt
PgpPrivateKey privateKey = null;
PgpPublicKeyEncryptedData pubKeyData = null;
foreach (PgpPublicKeyEncryptedData pubKeyDataItem in encryptedData.GetEncryptedDataObjects())
{
privateKey = FindSecretKey(pgpKeyRing, pubKeyDataItem.KeyId, passPhrase.ToCharArray());
if (privateKey != null)
{
pubKeyData = pubKeyDataItem;
break;
}
}
if (privateKey == null)
{
throw new ArgumentException("Secret key for message not found.");
}
PgpObjectFactory plainFact = null;
using (Stream clear = pubKeyData.GetDataStream(privateKey))
{
plainFact = new PgpObjectFactory(clear);
}
PgpObject message = plainFact.NextPgpObject();
switch (message)
{
case PgpCompressedData data:
{
PgpCompressedData compressedData = data;
PgpObjectFactory pgpCompressedFactory = null;
using (Stream compDataIn = compressedData.GetDataStream())
{
pgpCompressedFactory = new PgpObjectFactory(compDataIn);
}
message = pgpCompressedFactory.NextPgpObject();
PgpLiteralData literalData = null;
if (message is PgpOnePassSignatureList)
{
message = pgpCompressedFactory.NextPgpObject();
}
literalData = (PgpLiteralData)message;
using (Stream unc = literalData.GetInputStream())
{
output = GetString(unc);
}
break;
}
case PgpLiteralData data:
{
PgpLiteralData literalData = data;
using (Stream unc = literalData.GetInputStream())
{
output = GetString(unc);
}
break;
}
case PgpOnePassSignatureList _:
throw new PgpException("Encrypted message contains a signed message - not literal data.");
default:
throw new PgpException("Message is not a simple encrypted file - type unknown.");
}
return output;
}
public static void EncryptPgpFile(string inputFile, string outputFile, string publicKeyFile, bool applyArmor, bool withIntegrityCheck)
{
using (Stream publicKeyStream = File.OpenRead(publicKeyFile))
{
PgpPublicKey pubKey = ReadPublicKey(publicKeyStream);
using (MemoryStream outputBytes = new MemoryStream())
{
PgpCompressedDataGenerator dataCompressor = new PgpCompressedDataGenerator(CompressionAlgorithmTag.Zip);
PgpUtilities.WriteFileToLiteralData(dataCompressor.Open(outputBytes), PgpLiteralData.Binary, new FileInfo(inputFile));
dataCompressor.Close();
PgpEncryptedDataGenerator dataGenerator =
new PgpEncryptedDataGenerator(SymmetricKeyAlgorithmTag.Cast5, withIntegrityCheck, new SecureRandom());
dataGenerator.AddMethod(pubKey);
byte[] dataBytes = outputBytes.ToArray();
using (Stream outputStream = File.Create(outputFile))
{
if (applyArmor)
{
using (ArmoredOutputStream armoredStream = new ArmoredOutputStream(outputStream))
{
WriteStream(dataGenerator.Open(armoredStream, dataBytes.Length), ref dataBytes);
}
}
else
{
WriteStream(dataGenerator.Open(outputStream, dataBytes.Length), ref dataBytes);
}
}
}
}
}
public static void WriteStream(Stream inputStream, ref byte[] dataBytes)
{
using (Stream outputStream = inputStream)
{
outputStream.Write(dataBytes, 0, dataBytes.Length);
}
}
public static string GetString(Stream inputStream)
{
string output;
using (StreamReader reader = new StreamReader(inputStream))
{
output = reader.ReadToEnd();
}
return output;
}
public static Stream GetStream(string stringData)
{
MemoryStream stream = new MemoryStream();
StreamWriter writer = new StreamWriter(stream);
writer.Write(stringData);
writer.Flush();
stream.Position = 0;
return stream;
}
}
}
@@ -0,0 +1,46 @@
using System;
using Newtonsoft.Json;
using Serilog;
using LCU.Library.Internal.FileOperationsModels.Models;
using LCU.Library.Internal.Exceptions;
using System.Threading.Tasks;
using LCU.Library.Internal.ApiResponse.Services;
using LCU.Library.Internal.ApiResponse.Models;
namespace LCU.Api.Internal.FileOperations.Services;
public class DirectFileOperationsService : IDirectFileOperationsService
{
private readonly IFileOperationsService _fileOperationsService;
public DirectFileOperationsService(IFileOperationsService fileOperationsService)
{
_fileOperationsService = fileOperationsService;
}
public async Task<RequestResponse> HandleDirectFileOperationsRequest<TRequest>(TRequest request,
FileOperationType fileOperationType)
where TRequest : ReturnResponse
{
try
{
var queueRequest = new QueueRequest
{
Request = JsonConvert.SerializeObject(request),
FileOperationType = fileOperationType,
Attempts = 0
};
var requestResponse = _fileOperationsService.PerformFileOperation(queueRequest);
await QueueReturnResponse.QueueResponse(request, requestResponse.IsSuccessful, requestResponse.MessageStack);
return requestResponse;
}
catch (Exception exception)
{
var message = "Failure to Handle Direct File Operations Request";
Log.Error(exception, message);
throw new ServiceException($"{message}, Exception Message: {exception.Message}");
}
}
}
@@ -0,0 +1,18 @@
using System;
using System.IO;
namespace LCU.Api.Internal.FileOperations.Services
{
public class DirectFileService : IDirectFileService
{
public byte[] GetFileBytes(string path)
{
if (!string.IsNullOrWhiteSpace(path) && File.Exists(path))
{
return File.ReadAllBytes(path);
}
throw new ArgumentException($"Path {path} must exist.");
}
}
}
@@ -0,0 +1,26 @@
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Serilog;
using LCU.Library.Internal.FileOperationsModels.Models;
using LCU.Library.Internal.FileOperationsModels.Shared;
using LCU.Library.Internal.Exceptions;
namespace LCU.Api.Internal.FileOperations.Services;
public class DynamicDirectoryService : IDynamicDirectoryService
{
public IEnumerable<string> BuildDirectoryList(DynamicDirectoryListRequest request)
{
try
{
var dynamicDirectoryNameWithDates = DynamicNameBuilder.BuildDynamicName(request.DynamicDirectoryName, request.DynamicFileSettings);
var directoryNameList = RegexNameHandler.BuildDirectoryList(request.Path, dynamicDirectoryNameWithDates, request.DynamicFileSettings);
return directoryNameList;
}
catch (Exception exception)
{
Log.Error(exception, $"Error while trying to build directory list. Request: {JsonConvert.SerializeObject(request)}");
throw new ServiceException(exception.Message);
}
}
}
@@ -0,0 +1,119 @@
using System;
using System.IO;
using System.Linq;
using Serilog;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Spreadsheet;
using LCU.Library.Internal.Exceptions;
using LCU.Library.Internal.FileOperationsModels.Models.ExcelModels.Responses;
using LCU.Library.Internal.FileOperationsModels.Models.ExcelModels.Requests;
namespace LCU.Api.Internal.FileOperations.Services.ExcelServices;
public class ExcelService : IExcelService
{
public ExcelDataResponse ExtractExcelWorkBookData(ExcelDataRequest excelDataRequest)
{
var excelDataResponse = new ExcelDataResponse();
try
{
var fileBytes = Convert.FromBase64String(excelDataRequest.FileContent);
using var memoryStream = new MemoryStream(fileBytes);
using SpreadsheetDocument spreadsheetDocument = SpreadsheetDocument.Open(memoryStream, false);
WorkbookPart workbookPart = spreadsheetDocument.WorkbookPart;
Workbook workbook = workbookPart.Workbook;
foreach (Sheet sheet in workbook.GetFirstChild<Sheets>().Elements<Sheet>())
{
SheetRequest sheetRequest = null;
if (excelDataRequest.SkipSheetForExtraction(sheet.Name, out sheetRequest))
{
continue;
}
var sheetResponse = new SheetResponse(sheet.Name);
var worksheetPart = (WorksheetPart)workbookPart.GetPartById(sheet.Id);
var sheetData = worksheetPart.Worksheet.Elements<SheetData>().FirstOrDefault();
if (sheetData == null)
{
Log.Information($"Sheet named {sheet.Name} does not have any sheet data.");
continue;
}
sheetResponse = ExtractRowData(sheetData, sheetRequest, sheetResponse);
excelDataResponse.WorkBook.SheetResponses.Add(sheetResponse);
}
return excelDataResponse;
}
catch (Exception exception)
{
var message = $"Failure during ExtractExcelWorkBookData. Exception Message: {exception.Message}";
Log.Error(message, exception);
throw new ServiceException(message);
}
}
private SheetResponse ExtractRowData(SheetData sheetData, SheetRequest sheetRequest, SheetResponse sheetResponse)
{
foreach (var row in sheetData.Elements<Row>())
{
if (!int.TryParse(row.RowIndex, out int rowIndex))
{
continue;
}
if (sheetRequest.SkipRowForExtraction(rowIndex))
{
continue;
}
sheetResponse = ExtractCellData(row, rowIndex, sheetRequest, sheetResponse);
}
return sheetResponse;
}
private SheetResponse ExtractCellData(Row row, int rowIndex, SheetRequest sheetRequest, SheetResponse sheetResponse)
{
foreach (var cell in row.Elements<Cell>())
{
var columnName = GetColumnName(cell.CellReference);
if (sheetRequest.SkipColumnForExtraction(columnName))
{
continue;
}
if(cell is null || cell.CellValue is null)
{
continue;
}
var cellResponse = new CellResponse()
{
Row = rowIndex,
ColumnName = columnName,
Value = cell.CellValue.InnerText,
Formula = cell.CellFormula is null ? string.Empty : cell.CellFormula.InnerText
};
sheetResponse.CellResponses.Add(cellResponse);
}
return sheetResponse;
}
private static string GetColumnName(string cellReference)
{
string columnName = "";
foreach (char character in cellReference)
{
if (!char.IsLetter(character))
{
break;
}
columnName += character;
}
return columnName;
}
}
@@ -0,0 +1,9 @@
using LCU.Library.Internal.FileOperationsModels.Models.ExcelModels.Requests;
using LCU.Library.Internal.FileOperationsModels.Models.ExcelModels.Responses;
namespace LCU.Api.Internal.FileOperations.Services.ExcelServices;
public interface IExcelService
{
ExcelDataResponse ExtractExcelWorkBookData(ExcelDataRequest excelDataRequest);
}
@@ -0,0 +1,72 @@
using LCU.Api.Internal.FileOperations.Validations;
using LCU.Library.Internal.FileOperationsModels.Models;
using LCU.Library.Internal.LCUServiceFactory.Configurations;
using Newtonsoft.Json;
using System;
using System.IO;
namespace LCU.Api.Internal.FileOperations.Services.FileActionServices
{
public class AppendFileService : FileActionService, IFileActionService, IActionService<AppendFileRequest>
{
public AppendFileService(ServicesFactoryConfiguration servicesFactoryConfiguration)
: base(servicesFactoryConfiguration)
{
}
public RequestResponse ExecuteAction(QueueRequest queueRequest)
{
var requestResponse = new RequestResponse();
try
{
var fileRequest = JsonConvert.DeserializeObject<AppendFileRequest>(queueRequest.Request);
requestResponse = PerformRequest(fileRequest);
requestResponse.ReturnResponse = fileRequest;
return requestResponse;
}
catch (Exception exception)
{
return RequestResponseHelper.ExceptionUpdateRequestResponse(requestResponse,
queueRequest.FileOperationType,
exception.Message);
}
}
public RequestResponse PerformRequest(AppendFileRequest request)
{
return OperationService.PerformOperation(request, IsRequestValid, AppendFile);
}
private void AppendFile(AppendFileRequest request)
{
try
{
File.AppendAllText(request.FullFilePath, request.FileData);
}
catch (Exception exception)
{
throw new Exception($"Exception thrown while trying to ExecuteRequestAction. " +
$"Request: {JsonConvert.SerializeObject(request)}" +
$"ExceptionMessage: {exception.Message}");
}
}
public RequestResponse PreQueueValidation(AppendFileRequest originalRequest)
{
var requestResponse = new RequestResponse();
requestResponse = IsRequestValid(originalRequest, requestResponse);
return requestResponse;
}
public RequestResponse IsRequestValid(AppendFileRequest originalRequest, RequestResponse requestResponse)
{
requestResponse = DirectoryValidation.ValidateDirectoryExists(originalRequest.DestinationPath, requestResponse);
return requestResponse;
}
}
}
@@ -0,0 +1,85 @@
using System;
using System.Linq;
using Newtonsoft.Json;
using LCU.Library.Internal.FileOperationsModels.Models;
using LCU.Library.Internal.LCUServiceFactory.Configurations;
namespace LCU.Api.Internal.FileOperations.Services.FileActionServices;
public class BulkOperationService<TRequest> : FileActionService, IFileActionService, IActionService<BulkOperationRequest<TRequest>>
{
private readonly IActionService<TRequest> _actionService;
public BulkOperationService(ServicesFactoryConfiguration servicesFactoryConfiguration, IActionService<TRequest> actionService)
: base(servicesFactoryConfiguration)
{
_actionService = actionService;
}
/// <summary>
/// Bulk Operations was created to always try. This meaning that it should try to attempt
/// every operation action. This also means that it will alway try to also return response and
/// that it always returns true (Exeption being catastrophic exeption thrown).
/// </summary>
/// <param name="queueRequest"></param>
/// <returns></returns>
public RequestResponse ExecuteAction(QueueRequest queueRequest)
{
var requestResponse = new RequestResponse();
try
{
var request = JsonConvert.DeserializeObject<BulkOperationRequest<TRequest>>(queueRequest.Request);
requestResponse = PerformRequest(request);
//Bulk Operations just tries so if it gets to this point its sucessful.
requestResponse.IsSuccessful = true;
requestResponse.ReturnResponse = request;
return requestResponse;
}
catch (Exception exception)
{
return RequestResponseHelper.ExceptionUpdateRequestResponse(requestResponse,
queueRequest.FileOperationType,
exception.Message);
}
}
public RequestResponse PerformRequest(BulkOperationRequest<TRequest> request)
{
return BulkOperation(request);
}
private RequestResponse BulkOperation(BulkOperationRequest<TRequest> request)
{
var finalRequestResponse = new RequestResponse();
foreach (var operationRequest in request.OperationRequests)
{
var requestResponse = _actionService.PerformRequest(operationRequest);
if (!requestResponse.IsSuccessful)
{
finalRequestResponse.IsSuccessful = requestResponse.IsSuccessful;
finalRequestResponse.MessageStack.AddRange(requestResponse.MessageStack);
}
}
return finalRequestResponse;
}
public RequestResponse PreQueueValidation(BulkOperationRequest<TRequest> originalRequest)
{
var requestResponse = new RequestResponse();
requestResponse = IsRequestValid(originalRequest, requestResponse);
return requestResponse;
}
public RequestResponse IsRequestValid(BulkOperationRequest<TRequest> request, RequestResponse requestResponse)
{
var anyOperationRequests = request.OperationRequests.Any();
if (!anyOperationRequests)
{
requestResponse.IsSuccessful = anyOperationRequests;
requestResponse.MessageStack.Add($"There are no bulk operation requests to perform.");
}
return requestResponse;
}
}
@@ -0,0 +1,104 @@
using System;
using System.IO;
using Newtonsoft.Json;
using LCU.Library.Internal.FileOperationsModels.Shared;
using LCU.Library.Internal.FileOperationsModels.Models;
using LCU.Library.Internal.LCUServiceFactory.Configurations;
using LCU.Api.Internal.FileOperations.Validations;
namespace LCU.Api.Internal.FileOperations.Services.FileActionServices;
public class CopyFileService : FileActionService, IFileActionService, IActionService<CopyFileRequest>
{
public CopyFileService(ServicesFactoryConfiguration servicesFactoryConfiguration)
: base(servicesFactoryConfiguration)
{
}
public RequestResponse ExecuteAction(QueueRequest queueRequest)
{
var requestResponse = new RequestResponse();
try
{
var fileRequest = JsonConvert.DeserializeObject<CopyFileRequest>(queueRequest.Request);
var requests = DynamicNameBuilder.BuildListOfRequest(fileRequest);
requestResponse = FileValidation.ValidateIfAnyRequest(requests, fileRequest.Source, fileRequest.SucceedOnError, requestResponse);
foreach (var request in requests)
{
var temporaryRequestResponse = PerformRequest(request);
if (!temporaryRequestResponse.IsSuccessful)
{
requestResponse.IsSuccessful = fileRequest.SucceedOnError;
if (fileRequest.SucceedOnError)
{
requestResponse.MessageStack.Add("Succeed On Error is set.");
}
requestResponse.MessageStack.AddRange(temporaryRequestResponse.MessageStack);
}
}
requestResponse.ReturnResponse = fileRequest;
return requestResponse;
}
catch (Exception exception)
{
return RequestResponseHelper.ExceptionUpdateRequestResponse(requestResponse,
queueRequest.FileOperationType,
exception.Message);
}
}
public RequestResponse PerformRequest(CopyFileRequest request)
{
return OperationService.PerformOperation(request, IsRequestValid, CopyFile);
}
private void CopyFile(CopyFileRequest request)
{
try
{
File.Copy(request.Source, request.Destination, request.Overwrite);
}
catch (Exception exception)
{
throw new Exception($"Exception thrown while trying to ExecuteRequestAction. " +
$"Request: {JsonConvert.SerializeObject(request)}" +
$"ExceptionMessage: {exception.Message}");
}
}
public RequestResponse PreQueueValidation(CopyFileRequest originalRequest)
{
var requestResponse = new RequestResponse();
var requestList = DynamicNameBuilder.BuildListOfRequest(originalRequest);
requestResponse = FileValidation.ValidateIfAnyRequest(requestList, originalRequest.SourcePath, originalRequest.SucceedOnError, requestResponse);
foreach (var request in requestList)
{
requestResponse = IsRequestValid(request, requestResponse);
}
return requestResponse;
}
public RequestResponse IsRequestValid(CopyFileRequest fileRequest, RequestResponse requestResponse)
{
if (fileRequest.SucceedOnError)
{
return requestResponse;
}
requestResponse = FileValidation.ValidateSourceNotEmpty(fileRequest.Source, requestResponse);
requestResponse = FileValidation.ValidateFileExists(fileRequest.Source, requestResponse);
requestResponse = FileValidation.ValidateDestinationNotEmpty(fileRequest.Destination, requestResponse);
requestResponse = FileValidation.ValidateDirectoryExists(fileRequest.DestinationPath, requestResponse);
if (!fileRequest.Overwrite)
{
requestResponse = FileValidation.ValidateFileNotExists(fileRequest.Destination, requestResponse);
}
return requestResponse;
}
}
@@ -0,0 +1,66 @@
using System;
using System.IO;
using Newtonsoft.Json;
using LCU.Library.Internal.FileOperationsModels.Models;
using LCU.Library.Internal.LCUServiceFactory.Configurations;
using LCU.Api.Internal.FileOperations.Validations;
namespace LCU.Api.Internal.FileOperations.Services.FileActionServices;
public class CreateDirectoryService : FileActionService, IFileActionService, IActionService<CreateDirectoryRequest>
{
public CreateDirectoryService(ServicesFactoryConfiguration servicesFactoryConfiguration)
: base(servicesFactoryConfiguration)
{
}
public RequestResponse ExecuteAction(QueueRequest queueRequest)
{
var requestResponse = new RequestResponse();
try
{
var directoryRequest = JsonConvert.DeserializeObject<CreateDirectoryRequest>(queueRequest.Request);
requestResponse = PerformRequest(directoryRequest);
requestResponse.ReturnResponse = directoryRequest;
return requestResponse;
}
catch (Exception exception)
{
return RequestResponseHelper.ExceptionUpdateRequestResponse(requestResponse,
queueRequest.FileOperationType,
exception.Message);
}
}
public RequestResponse PerformRequest(CreateDirectoryRequest request)
{
return OperationService.PerformOperation(request, IsRequestValid, CreateDirectory);
}
private void CreateDirectory(CreateDirectoryRequest request)
{
try
{
Directory.CreateDirectory(request.DirectoryDestination);
}
catch (Exception exception)
{
throw new Exception($"Exception thrown while trying to ExecuteRequestAction. " +
$"Request: {JsonConvert.SerializeObject(request)}" +
$"ExceptionMessage: {exception.Message}");
}
}
public RequestResponse PreQueueValidation(CreateDirectoryRequest originalRequest)
{
var requestResponse = new RequestResponse();
requestResponse = IsRequestValid(originalRequest, requestResponse);
return requestResponse;
}
public RequestResponse IsRequestValid(CreateDirectoryRequest request, RequestResponse requestResponse)
{
requestResponse = FileValidation.ValidateDirectoryExists(request.DirectoryPath, requestResponse);
requestResponse = FileValidation.ValidateDirectoryNotExists(request.DirectoryDestination, requestResponse);
return requestResponse;
}
}
@@ -0,0 +1,68 @@
using System;
using Newtonsoft.Json;
using LCU.Library.Internal.FileOperationsModels.Models;
using LCU.Library.Internal.LCUServiceFactory.Configurations;
using LCU.Api.Internal.FileOperations.Validations;
namespace LCU.Api.Internal.FileOperations.Services.FileActionServices;
public class DecryptFileDataService : FileActionService, IFileActionService, IActionService<DecryptFileDataRequest>
{
public DecryptFileDataService(ServicesFactoryConfiguration servicesFactoryConfiguration)
: base(servicesFactoryConfiguration)
{
}
public RequestResponse ExecuteAction(QueueRequest queueRequest)
{
var requestResponse = new RequestResponse();
try
{
var request = JsonConvert.DeserializeObject<DecryptFileDataRequest>(queueRequest.Request);
requestResponse = PerformRequest(request);
requestResponse.ReturnResponse = request;
return requestResponse;
}
catch (Exception exception)
{
return RequestResponseHelper.ExceptionUpdateRequestResponse(requestResponse,
queueRequest.FileOperationType,
exception.Message);
}
}
public RequestResponse PerformRequest(DecryptFileDataRequest request)
{
return OperationService.PerformOperation(request, IsRequestValid, ExecuteRequestAction);
}
private void ExecuteRequestAction(DecryptFileDataRequest request)
{
try
{
CryptoHelper.DecryptPgpFile(request.Source, request.Destination, request.KeySource, request.PassPhrase);
}
catch (Exception exception)
{
throw new Exception($"Exception thrown while trying to ExecuteRequestAction. " +
$"Request: {JsonConvert.SerializeObject(request)}" +
$"ExceptionMessage: {exception.Message}");
}
}
public RequestResponse PreQueueValidation(DecryptFileDataRequest originalRequest)
{
var requestResponse = new RequestResponse();
requestResponse = IsRequestValid(originalRequest, requestResponse);
return requestResponse;
}
public RequestResponse IsRequestValid(DecryptFileDataRequest fileRequest, RequestResponse requestResponse)
{
requestResponse = FileValidation.ValidateDirectoryExists(fileRequest.SourcePath, requestResponse);
requestResponse = FileValidation.ValidateDirectoryExists(fileRequest.DestinationPath, requestResponse);
requestResponse = FileValidation.ValidateDirectoryExists(fileRequest.KeySourcePath, requestResponse);
requestResponse = FileValidation.ValidateFileExists(fileRequest.Source, requestResponse);
requestResponse = FileValidation.ValidateFileExists(fileRequest.KeySource, requestResponse);
return requestResponse;
}
}
@@ -0,0 +1,123 @@
using System;
using System.IO;
using System.Collections.Generic;
using Newtonsoft.Json;
using LCU.Library.Internal.FileOperationsModels.Models;
using LCU.Library.Internal.FileOperationsModels.Shared;
using LCU.Api.Internal.FileOperations.Validations;
using LCU.Library.Internal.LCUServiceFactory.Configurations;
namespace LCU.Api.Internal.FileOperations.Services.FileActionServices;
public class DeleteDirectoryService : FileActionService, IFileActionService, IActionService<DeleteDirectoryRequest>
{
public DeleteDirectoryService(ServicesFactoryConfiguration servicesFactoryConfiguration)
: base(servicesFactoryConfiguration)
{
}
public RequestResponse ExecuteAction(QueueRequest queueRequest)
{
var requestResponse = new RequestResponse();
try
{
var directoryRequest = JsonConvert.DeserializeObject<DeleteDirectoryRequest>(queueRequest.Request);
var requests = BuildListOfRequest(directoryRequest);
requestResponse = DirectoryValidation.ValidateDirectoryRequestsWithinLimit(requests,
directoryRequest.MaxAmountOfDirectories,
requestResponse);
if (!requestResponse.IsSuccessful)
{
return requestResponse;
}
foreach (var request in requests)
{
var temporaryRequestResponse = PerformRequest(request);
if (!temporaryRequestResponse.IsSuccessful)
{
requestResponse.IsSuccessful = temporaryRequestResponse.IsSuccessful;
requestResponse.MessageStack.AddRange(temporaryRequestResponse.MessageStack);
}
}
requestResponse.ReturnResponse = directoryRequest;
return requestResponse;
}
catch (Exception exception)
{
return RequestResponseHelper.ExceptionUpdateRequestResponse(requestResponse,
queueRequest.FileOperationType,
exception.Message);
}
}
public RequestResponse PerformRequest(DeleteDirectoryRequest request)
{
return OperationService.PerformOperation(request, IsRequestValid, DeleteDirectory);
}
private void DeleteDirectory(DeleteDirectoryRequest request)
{
try
{
Directory.Delete(request.FinalDirectoryPath, request.Recursive);
}
catch (Exception exception)
{
throw new Exception($"Exception thrown while trying to ExecuteRequestAction. " +
$"Request: {JsonConvert.SerializeObject(request)}" +
$"ExceptionMessage: {exception.Message}");
}
}
public RequestResponse PreQueueValidation(DeleteDirectoryRequest originalRequest)
{
var requestResponse = new RequestResponse();
requestResponse = DirectoryValidation.ValidateDirectoryExists(originalRequest.DirectoryRootPath, requestResponse);
if (!requestResponse.IsSuccessful)
{
return requestResponse;
}
var requestList = BuildListOfRequest(originalRequest);
requestResponse = DirectoryValidation.ValidateDirectoryRequestsWithinLimit(requestList,
originalRequest.MaxAmountOfDirectories,
requestResponse);
if (!requestResponse.IsSuccessful)
{
return requestResponse;
}
foreach (var request in requestList)
{
requestResponse = IsRequestValid(request, requestResponse);
}
return requestResponse;
}
public List<DeleteDirectoryRequest> BuildListOfRequest(DeleteDirectoryRequest originalRequest)
{
var nameList = RegexNameHandler.BuildDirectoryList(originalRequest.DirectoryRootPath,
originalRequest.FinalDirectoryName,
originalRequest.DirectoryNameSettings);
var requests = new List<DeleteDirectoryRequest>();
foreach (var name in nameList)
{
var newRequest = Clone.DeepClone(originalRequest);
newRequest.DirectoryName = name;
requests.Add(newRequest);
}
return requests;
}
public RequestResponse IsRequestValid(DeleteDirectoryRequest request, RequestResponse requestResponse)
{
requestResponse = DirectoryValidation.ValidateDirectoryExists(request.FinalDirectoryPath, requestResponse);
return requestResponse;
}
}
@@ -0,0 +1,122 @@
using System;
using System.Collections.Generic;
using System.IO;
using LCU.Api.Internal.FileOperations.Validations;
using LCU.Library.Internal.FileOperationsModels.Models;
using LCU.Library.Internal.FileOperationsModels.Shared;
using LCU.Library.Internal.LCUServiceFactory.Configurations;
using Newtonsoft.Json;
namespace LCU.Api.Internal.FileOperations.Services.FileActionServices
{
public class DeleteEmptyDirectoryService : FileActionService, IFileActionService, IActionService<DeleteEmptyDirectoryRequest>
{
public DeleteEmptyDirectoryService(ServicesFactoryConfiguration servicesFactoryConfiguration)
: base(servicesFactoryConfiguration)
{
}
public RequestResponse ExecuteAction(QueueRequest queueRequest)
{
var requestResponse = new RequestResponse();
try
{
var directoryRequest = JsonConvert.DeserializeObject<DeleteEmptyDirectoryRequest>(queueRequest.Request);
var requests = BuildListOfRequest(directoryRequest);
foreach (var request in requests)
{
if (DirectoryValidation.ValidateDirectoryIsEmpty(request.FinalDirectoryPath, new RequestResponse()).IsSuccessful)
{
var temporaryRequestResponse = PerformRequest(request);
if (!temporaryRequestResponse.IsSuccessful)
{
requestResponse.IsSuccessful = temporaryRequestResponse.IsSuccessful;
requestResponse.MessageStack.AddRange(temporaryRequestResponse.MessageStack);
}
}
else
{
requestResponse.MessageStack.Add($"Directory {request.FinalDirectoryPath} is skipped as it is not empty and won't be deleted.");
}
}
requestResponse.ReturnResponse = directoryRequest;
return requestResponse;
}
catch (Exception exception)
{
return RequestResponseHelper.ExceptionUpdateRequestResponse(requestResponse,
queueRequest.FileOperationType,
exception.Message);
}
}
public RequestResponse PerformRequest(DeleteEmptyDirectoryRequest request)
{
return OperationService.PerformOperation(request, IsRequestValid, DeleteEmptyDirectory);
}
private void DeleteEmptyDirectory(DeleteEmptyDirectoryRequest request)
{
try
{
Directory.Delete(request.FinalDirectoryPath);
}
catch (Exception exception)
{
throw new Exception($"Exception thrown while trying to ExecuteRequestAction. " +
$"Request: {JsonConvert.SerializeObject(request)}" +
$"ExceptionMessage: {exception.Message}");
}
}
public RequestResponse PreQueueValidation(DeleteEmptyDirectoryRequest originalRequest)
{
var requestResponse = new RequestResponse();
requestResponse = DirectoryValidation.ValidateDirectoryExists(originalRequest.SubDirectoryPath, requestResponse);
if (!requestResponse.IsSuccessful)
{
return requestResponse;
}
var requestList = BuildListOfRequest(originalRequest);
foreach (var request in requestList)
{
requestResponse = IsRequestValid(request, requestResponse);
}
return requestResponse;
}
public RequestResponse IsRequestValid(DeleteEmptyDirectoryRequest request, RequestResponse requestResponse)
{
requestResponse = DirectoryValidation.ValidateDirectoryExists(request.FinalDirectoryPath, requestResponse);
return requestResponse;
}
private List<DeleteEmptyDirectoryRequest> BuildListOfRequest(DeleteEmptyDirectoryRequest originalRequest)
{
var nameList = RegexNameHandler.BuildDirectoryList(originalRequest.SubDirectoryPath,
originalRequest.FinalDirectoryName,
originalRequest.DirectoryNameSettings);
var requests = new List<DeleteEmptyDirectoryRequest>();
foreach (var name in nameList)
{
var newRequest = Clone.DeepClone(originalRequest);
newRequest.DynamicDirectoryName = name;
requests.Add(newRequest);
}
return requests;
}
}
}
@@ -0,0 +1,109 @@
using System;
using System.Collections.Generic;
using System.IO;
using Newtonsoft.Json;
using LCU.Library.Internal.FileOperationsModels.Models;
using LCU.Library.Internal.FileOperationsModels.Shared;
using LCU.Library.Internal.LCUServiceFactory.Configurations;
using LCU.Api.Internal.FileOperations.Validations;
namespace LCU.Api.Internal.FileOperations.Services.FileActionServices;
public class DeleteFileService : FileActionService, IFileActionService, IActionService<DeleteFileRequest>
{
public DeleteFileService(ServicesFactoryConfiguration servicesFactoryConfiguration)
: base(servicesFactoryConfiguration)
{
}
public RequestResponse ExecuteAction(QueueRequest queueRequest)
{
var requestResponse = new RequestResponse();
try
{
var fileRequest = JsonConvert.DeserializeObject<DeleteFileRequest>(queueRequest.Request);
var requests = BuildListOfRequest(fileRequest);
requestResponse = FileValidation.ValidateIfAnyRequest(requests, fileRequest.Source, requestResponse);
foreach (var request in requests)
{
var temporaryRequestResponse = PerformRequest(request);
if (!temporaryRequestResponse.IsSuccessful)
{
requestResponse.IsSuccessful = temporaryRequestResponse.IsSuccessful;
requestResponse.MessageStack.AddRange(temporaryRequestResponse.MessageStack);
}
}
requestResponse.ReturnResponse = fileRequest;
return requestResponse;
}
catch (Exception exception)
{
return RequestResponseHelper.ExceptionUpdateRequestResponse(requestResponse,
queueRequest.FileOperationType,
exception.Message);
}
}
public RequestResponse PerformRequest(DeleteFileRequest request)
{
return OperationService.PerformOperation(request, IsRequestValid, DeleteFile);
}
private void DeleteFile(DeleteFileRequest request)
{
try
{
File.Delete(request.Source);
}
catch (Exception exception)
{
throw new Exception($"Exception thrown while trying to ExecuteRequestAction. " +
$"Request: {JsonConvert.SerializeObject(request)}" +
$"ExceptionMessage: {exception.Message}");
}
}
public RequestResponse PreQueueValidation(DeleteFileRequest originalRequest)
{
var requestResponse = new RequestResponse();
var requestList = BuildListOfRequest(originalRequest);
requestResponse = FileValidation.ValidateIfAnyRequest(requestList, originalRequest.SourcePath, requestResponse);
foreach (var request in requestList)
{
requestResponse = IsRequestValid(request, requestResponse);
}
return requestResponse;
}
public List<DeleteFileRequest> BuildListOfRequest(DeleteFileRequest originalRequest)
{
var nameList = RegexNameHandler.BuildFileList(originalRequest.SourcePath,
originalRequest.FinalSourceFile,
originalRequest.FileNameSetting);
var requests = new List<DeleteFileRequest>();
foreach (var name in nameList)
{
var newRequest = Clone.DeepClone(originalRequest);
newRequest.SourceFile = name;
requests.Add(newRequest);
}
return requests;
}
public RequestResponse IsRequestValid(DeleteFileRequest fileRequest, RequestResponse requestResponse)
{
if (fileRequest.SucceedOnError)
{
return requestResponse;
}
requestResponse = FileValidation.ValidateSourceNotEmpty(fileRequest.Source, requestResponse);
requestResponse = FileValidation.ValidateFileExists(fileRequest.Source, requestResponse);
return requestResponse;
}
}
@@ -0,0 +1,68 @@
using System;
using Newtonsoft.Json;
using LCU.Library.Internal.FileOperationsModels.Models;
using LCU.Library.Internal.LCUServiceFactory.Configurations;
using LCU.Api.Internal.FileOperations.Validations;
namespace LCU.Api.Internal.FileOperations.Services.FileActionServices;
public class EncryptFileDataService : FileActionService, IFileActionService, IActionService<EncryptFileDataRequest>
{
public EncryptFileDataService(ServicesFactoryConfiguration servicesFactoryConfiguration)
: base(servicesFactoryConfiguration)
{
}
public RequestResponse ExecuteAction(QueueRequest queueRequest)
{
var requestResponse = new RequestResponse();
try
{
var request = JsonConvert.DeserializeObject<EncryptFileDataRequest>(queueRequest.Request);
requestResponse = PerformRequest(request);
requestResponse.ReturnResponse = request;
return requestResponse;
}
catch (Exception exception)
{
return RequestResponseHelper.ExceptionUpdateRequestResponse(requestResponse,
queueRequest.FileOperationType,
exception.Message);
}
}
public RequestResponse PerformRequest(EncryptFileDataRequest request)
{
return OperationService.PerformOperation(request, IsRequestValid, ExecuteRequestAction);
}
private void ExecuteRequestAction(EncryptFileDataRequest request)
{
try
{
CryptoHelper.EncryptPgpFile(request.Source, request.Destination, request.KeySource, true, true);
}
catch (Exception exception)
{
throw new Exception($"Exception thrown while trying to ExecuteRequestAction. " +
$"Request: {JsonConvert.SerializeObject(request)}" +
$"ExceptionMessage: {exception.Message}");
}
}
public RequestResponse PreQueueValidation(EncryptFileDataRequest originalRequest)
{
var requestResponse = new RequestResponse();
requestResponse = IsRequestValid(originalRequest, requestResponse);
return requestResponse;
}
public RequestResponse IsRequestValid(EncryptFileDataRequest fileRequest, RequestResponse requestResponse)
{
requestResponse = FileValidation.ValidateDirectoryExists(fileRequest.SourcePath, requestResponse);
requestResponse = FileValidation.ValidateDirectoryExists(fileRequest.DestinationPath, requestResponse);
requestResponse = FileValidation.ValidateDirectoryExists(fileRequest.KeySourcePath, requestResponse);
requestResponse = FileValidation.ValidateFileExists(fileRequest.Source, requestResponse);
requestResponse = FileValidation.ValidateFileExists(fileRequest.KeySource, requestResponse);
return requestResponse;
}
}
@@ -0,0 +1,262 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using CsvHelper;
using CsvHelper.Configuration;
using CsvHelper.Configuration.Attributes;
using LCU.Api.Internal.FileOperations.Validations;
using LCU.Api.Internal.FileOperations.Models;
using LCU.Library.Internal.FileOperationsModels.Models;
using LCU.Library.Internal.FileOperationsModels.Shared;
using LCU.Library.Internal.LcuEvaluation.Services.EvaluationServices;
using LCU.Library.Internal.LCUServiceFactory.Configurations;
using LCU.Library.Internal.TypeExtentions.EnumExtensions;
using Newtonsoft.Json;
using Serilog;
namespace LCU.Api.Internal.FileOperations.Services.FileActionServices;
public class ExtractIndexFileDataService : FileActionService, IFileActionService, IActionService<ExtractIndexFileDataRequest>
{
private readonly IRunRuleService _runRuleService;
private const string RegexMatch = "(\")(.*?)(\")";
public ExtractIndexFileDataService(IRunRuleService runRuleService, ServicesFactoryConfiguration servicesFactoryConfiguration)
: base(servicesFactoryConfiguration)
{
_runRuleService = runRuleService;
}
public RequestResponse ExecuteAction(QueueRequest queueRequest)
{
var requestResponse = new RequestResponse();
try
{
var request = JsonConvert.DeserializeObject<ExtractIndexFileDataRequest>(queueRequest.Request);
var requests = DynamicNameBuilder.BuildListOfRequest(request);
if (requests.Count > 1)
{
requestResponse.MessageStack.Add("More than one file was found.");
requestResponse.IsSuccessful = false;
}
else
{
requestResponse = PerformRequest(requests.FirstOrDefault());
}
requestResponse.ReturnResponse = requests.FirstOrDefault();
return requestResponse;
}
catch (Exception exception)
{
return RequestResponseHelper.ExceptionUpdateRequestResponse(requestResponse,
queueRequest.FileOperationType,
exception.Message);
}
}
public RequestResponse PerformRequest(ExtractIndexFileDataRequest request)
{
return OperationService.PerformOperation(request, IsRequestValid, ExtractIndexFileData);
}
public RequestResponse PreQueueValidation(ExtractIndexFileDataRequest originalRequest)
{
var requestResponse = new RequestResponse();
return requestResponse;
}
public RequestResponse IsRequestValid(ExtractIndexFileDataRequest request, RequestResponse requestResponse)
{
requestResponse = FileValidation.ValidateFileExists(request.FinalIndexFilePath, requestResponse);
requestResponse = DirectoryValidation.ValidateDirectoryExists(request.FinalDestinationPath, requestResponse);
return requestResponse;
}
private void ExtractIndexFileData(ExtractIndexFileDataRequest request)
{
try
{
var delimiter = request.DelimiterType.GetNameFromValue();
var fileLines = GetFileContents(request.FinalIndexFilePath);
if (fileLines is null || !fileLines.Any())
{
Log.Information($"No content was extracted from filepath: ({request.FinalIndexFilePath})");
return;
}
var recordsAreWrappedInQuotes = HasQuotes(fileLines);
var headers = request.IndexHasHeaders ? GetHeaders(fileLines, delimiter, recordsAreWrappedInQuotes) : new List<string>();
var columnMax = GetColumnCount(fileLines, delimiter, recordsAreWrappedInQuotes);
var fileContent = string.Join(Environment.NewLine, fileLines);
var indexEvaluationRequests = GetCsvRecords(fileContent,
delimiter,
request.IndexHasHeaders);
var evaluatedRequests = BuildAndRunRules(indexEvaluationRequests, request);
var passedList = FilterColumns(evaluatedRequests.Passed,
request.IndexesToExtract,
columnMax,
request.ExtractAllIndexes);
var failedList = FilterColumns(evaluatedRequests.Failed,
request.IndexesToExtract,
columnMax,
true);
if (passedList is null || !passedList.Any())
{
Log.Information("No results passed evaluations to write to destination file.");
return;
}
OutputResults(request, failedList, passedList, headers, recordsAreWrappedInQuotes);
}
catch (Exception exception)
{
throw new Exception(@$"Exception thrown while trying to ExecuteRequestAction.
ExceptionMessage: {exception.Message}
Request: {JsonConvert.SerializeObject(request)}");
}
}
private (List<IndexEvaluationRequest> Passed, List<IndexEvaluationRequest> Failed) BuildAndRunRules(List<IndexEvaluationRequest> indexEvaluationRequests, ExtractIndexFileDataRequest request)
{
if (request.EvaluationRule is null)
{
return (indexEvaluationRequests, new List<IndexEvaluationRequest>());
}
var passedRules = new List<IndexEvaluationRequest>();
var failedRules = new List<IndexEvaluationRequest>();
foreach (var indexEvaluationRequest in indexEvaluationRequests)
{
if (_runRuleService.BuildAndRunRule(new List<IndexEvaluationRequest> { indexEvaluationRequest }, request.EvaluationRule))
{
passedRules.Add(indexEvaluationRequest);
}
else
{
failedRules.Add(indexEvaluationRequest);
}
}
return (passedRules, failedRules);
}
private static List<string> GetFileContents(string filepath)
=> File.ReadAllLines(filepath).Where(line => !string.IsNullOrWhiteSpace(line)).ToList();
private static bool HasQuotes(List<string> content)
=> Regex.Split(content.First(), RegexMatch).Length > 1;
private static List<string> GetHeaders(List<string> content, string delimiter, bool recordsAreWrappedInQuotes)
=> recordsAreWrappedInQuotes ? Regex.Split(content.First(), RegexMatch).Where(x => !new List<string> { delimiter, "\"" }.Contains(x)
&& !string.IsNullOrWhiteSpace(x)).ToList()
: content.First().Split(delimiter).ToList();
private static int GetColumnCount(List<string> content, string delimiter, bool recordsAreWrappedInQuotes)
{
var line = content.First();
if (!recordsAreWrappedInQuotes)
{
return line.Split(delimiter).Length;
}
var filterList = new List<string> { string.Empty, "\"", delimiter };
return Regex.Split(line, RegexMatch).Where(x => !filterList.Contains(x)).ToList().Count;
}
private static List<IndexEvaluationRequest> GetCsvRecords(string fileContent, string delimiter, bool hasHeaders)
{
using var stringReader = new StringReader(fileContent);
var config = new CsvConfiguration(CultureInfo.InvariantCulture)
{
Delimiter = delimiter,
MissingFieldFound = null,
HasHeaderRecord = hasHeaders,
BadDataFound = null
};
using var csvReader = new CsvReader(stringReader, config);
return csvReader.GetRecords<IndexEvaluationRequest>().ToList();
}
private static List<List<string>> FilterColumns(List<IndexEvaluationRequest> records,
List<int> indexesToExtract,
int columnMax,
bool extractAllIndexes)
{
if (!extractAllIndexes && (indexesToExtract is null || !indexesToExtract.Any()))
{
throw new Exception("IndexesToExtract was empty");
}
var keepProperties = new List<string>();
var removeProperties = new List<string>();
var indexes = typeof(IndexEvaluationRequest).GetProperties().ToDictionary(
prop => ((IndexAttribute)prop.GetCustomAttributes(true).FirstOrDefault(attr => attr.GetType() == typeof(IndexAttribute)))?.Index ?? int.MaxValue,
prop => prop.Name);
var recordsDictionary = JsonConvert.DeserializeObject<List<Dictionary<string,string>>>(JsonConvert.SerializeObject(records));
keepProperties.AddRange(indexes.Where(index => extractAllIndexes ? index.Key < columnMax : indexesToExtract.Contains(index.Key))
.Select(x => x.Value).Distinct());
return recordsDictionary.Select(recordList =>
recordList.Where(record =>
(!keepProperties.Any() || keepProperties.Contains(record.Key))
&& !removeProperties.Contains(record.Key)
).Select(record => record.Value).ToList()
).ToList();
}
private static string TransformToOutputString(IEnumerable<List<string>> content, string delimiter, string wrapText)
=> string.Join(Environment.NewLine, content.Select(x => string.Join(delimiter, x.Select(y => $"{wrapText}{y}{wrapText}"))));
private static void OutputResults(ExtractIndexFileDataRequest request,
IEnumerable<List<string>> originalContent,
IEnumerable<List<string>> newContent,
List<string> headers,
bool recordIsWrappedInQuotes)
{
var delimiter = request.DelimiterType.GetNameFromValue();
var wrapText = recordIsWrappedInQuotes ? "\"" : string.Empty;
var destinationFileExists = File.Exists(request.FinalDestinationIndexFilePath);
if (request.IndexHasHeaders)
{
originalContent = originalContent.Prepend(headers);
if (!request.AppendToDestinationIndexFile || !destinationFileExists)
{
newContent = !request.ExtractAllIndexes && request.IndexesToExtract.Count > 0
? newContent.Prepend(headers.Where((_, i) => request.IndexesToExtract.Contains(i)).ToList())
: newContent.Prepend(headers);
}
}
var originalFile = TransformToOutputString(originalContent, delimiter, wrapText);
var newFile = TransformToOutputString(newContent, delimiter, wrapText);
if (request.AppendToDestinationIndexFile && destinationFileExists)
{
File.AppendAllText(request.FinalDestinationIndexFilePath, Environment.NewLine + newFile);
}
else
{
File.WriteAllText(request.FinalDestinationIndexFilePath, newFile);
}
File.WriteAllText(request.FinalIndexFilePath, originalFile);
}
}
@@ -0,0 +1,9 @@
using LCU.Library.Internal.LCUServiceFactory.Configurations;
using LCU.Library.Internal.LCUServiceFactory.Services;
namespace LCU.Api.Internal.FileOperations.Services.FileActionServices;
public abstract class FileActionService(ServicesFactoryConfiguration servicesFactoryConfiguration)
: LcuAbstractService(servicesFactoryConfiguration.GetServiceFactoryRegistrationByInterface<IFileActionService>())
{
}
@@ -0,0 +1,85 @@
using System;
using System.Collections.Generic;
using System.IO;
using LCU.Api.Internal.FileOperations.Validations;
using LCU.Library.Internal.FileOperationsModels.Enums;
using LCU.Library.Internal.FileOperationsModels.Models;
using LCU.Library.Internal.FileOperationsModels.Models.Requests;
using LCU.Library.Internal.FileOperationsModels.Models.Responses;
using LCU.Library.Internal.FileOperationsModels.Shared;
namespace LCU.Api.Internal.FileOperations.Services.FileActionServices;
public class FileSizeService : IFileSizeService
{
public List<FileSizeResponse> GetFileSize(FileSizeRequest fileSizeRequest)
{
var fileSizeResponses = new List<FileSizeResponse>();
try
{
var requests = DynamicNameBuilder.BuildListOfRequests(fileSizeRequest);
foreach (var request in requests)
{
var response = DetermineFileSize(request);
fileSizeResponses.Add(response);
}
return fileSizeResponses;
}
catch (Exception exception)
{
throw new Exception($"Failed to get file size. Exception: {exception.Message}");
}
}
public decimal ConvertFileSize(decimal fileSizeInBytes, FileSizeTypes returnFileSizeType)
=> returnFileSizeType switch
{
FileSizeTypes.Byte => fileSizeInBytes,
FileSizeTypes.Kilobyte => fileSizeInBytes/1024,
FileSizeTypes.Megabyte => fileSizeInBytes/1024/1024,
FileSizeTypes.Gigabyte => fileSizeInBytes/1024/1024/1024,
FileSizeTypes.Terabyte => fileSizeInBytes/1024/1024/1024/1024,
_ => throw new ArgumentOutOfRangeException(nameof(returnFileSizeType), $"Not expected FileSizeType value: {returnFileSizeType}"),
};
public RequestResponse PreQueueValidation(FileSizeRequest fileSizeRequest)
{
var requestResponse = new RequestResponse();
try
{
var requestList = DynamicNameBuilder.BuildListOfRequests(fileSizeRequest);
requestResponse = FileValidation.ValidateIfAnyRequest(requestList, fileSizeRequest.FileSourceRequest.SourcePath, requestResponse);
foreach (var request in requestList)
{
requestResponse = IsRequestValid(request, requestResponse);
}
return requestResponse;
}
catch (Exception exception)
{
requestResponse.IsSuccessful = false;
requestResponse.MessageStack.Add(exception.Message);
return requestResponse;
}
}
private static RequestResponse IsRequestValid(FileSizeRequest request, RequestResponse requestResponse)
{
return FileValidation.ValidateFileExists(request.FileSourceRequest.Source, requestResponse);
}
private FileSizeResponse DetermineFileSize(FileSizeRequest request)
{
var file = new FileInfo(request.FileSourceRequest.Source);
var length = Convert.ToDecimal(file.Length);
return new FileSizeResponse
{
FileName = file.Name,
FileSize = ConvertFileSize(length, request.FileSizeType),
FileSizeType = request.FileSizeType
};
}
}
@@ -0,0 +1,9 @@
using LCU.Library.Internal.FileOperationsModels.Models;
namespace LCU.Api.Internal.FileOperations.Services.FileActionServices;
public interface IActionService<TRequest>
{
RequestResponse PerformRequest(TRequest request);
RequestResponse PreQueueValidation(TRequest originalRequest);
RequestResponse IsRequestValid(TRequest request, RequestResponse requestResponse);
}
@@ -0,0 +1,10 @@
using LCU.Library.Internal.FileOperationsModels.Models;
using LCU.Library.Internal.LCUServiceFactory.Services;
namespace LCU.Api.Internal.FileOperations.Services.FileActionServices
{
public interface IFileActionService : ILcuService
{
RequestResponse ExecuteAction(QueueRequest queueRequest);
}
}
@@ -0,0 +1,14 @@
using System.Collections.Generic;
using LCU.Library.Internal.FileOperationsModels.Enums;
using LCU.Library.Internal.FileOperationsModels.Models;
using LCU.Library.Internal.FileOperationsModels.Models.Requests;
using LCU.Library.Internal.FileOperationsModels.Models.Responses;
namespace LCU.Api.Internal.FileOperations.Services.FileActionServices;
public interface IFileSizeService
{
public List<FileSizeResponse> GetFileSize(FileSizeRequest request);
public decimal ConvertFileSize(decimal fileSizeInBytes, FileSizeTypes returnFileSizeType);
public RequestResponse PreQueueValidation(FileSizeRequest originalRequest);
}
@@ -0,0 +1,99 @@
using Newtonsoft.Json;
using System;
using System.IO;
using LCU.Api.Internal.FileOperations.Validations;
using LCU.Library.Internal.FileOperationsModels.Models;
using LCU.Library.Internal.FileOperationsModels.Shared;
using LCU.Library.Internal.LCUServiceFactory.Configurations;
namespace LCU.Api.Internal.FileOperations.Services.FileActionServices;
public class ModifyFileService : FileActionService, IFileActionService, IActionService<ModifyFileRequest>
{
public ModifyFileService(ServicesFactoryConfiguration servicesFactoryConfiguration)
: base(servicesFactoryConfiguration)
{
}
public RequestResponse ExecuteAction(QueueRequest queueRequest)
{
var requestResponse = new RequestResponse();
try
{
var fileRequest = JsonConvert.DeserializeObject<ModifyFileRequest>(queueRequest.Request);
var requests = DynamicNameBuilder.BuildListOfRequest(fileRequest);
requestResponse = FileValidation.ValidateFileRequestsWithinLimit(requests, fileRequest.MaxAmountOfFiles, requestResponse);
foreach (var request in requests)
{
var temporaryRequestResponse = PerformRequest(request);
if (!temporaryRequestResponse.IsSuccessful)
{
requestResponse.IsSuccessful = fileRequest.SucceedOnError;
if (fileRequest.SucceedOnError)
{
requestResponse.MessageStack.Add("Succeed On Error is set.");
}
requestResponse.MessageStack.AddRange(temporaryRequestResponse.MessageStack);
}
}
requestResponse.ReturnResponse = fileRequest;
return requestResponse;
}
catch (Exception exception)
{
return RequestResponseHelper.ExceptionUpdateRequestResponse(requestResponse,
queueRequest.FileOperationType,
exception.Message);
}
}
public RequestResponse PerformRequest(ModifyFileRequest request)
{
return OperationService.PerformOperation(request, IsRequestValid, ModifyFile);
}
private void ModifyFile(ModifyFileRequest request)
{
try
{
File.Move(request.OriginalSource, request.FinalSource);
}
catch (Exception exception)
{
throw new Exception($"Exception thrown while trying to ExecuteRequestAction. " +
$"Request: {JsonConvert.SerializeObject(request)}" +
$"ExceptionMessage: {exception.Message}");
}
}
public RequestResponse PreQueueValidation(ModifyFileRequest originalRequest)
{
var requestResponse = new RequestResponse();
var requestList = DynamicNameBuilder.BuildListOfRequest(originalRequest);
requestResponse = FileValidation.ValidateFileRequestsWithinLimit(requestList, originalRequest.MaxAmountOfFiles, requestResponse);
foreach (var request in requestList)
{
requestResponse = IsRequestValid(request, requestResponse);
}
return requestResponse;
}
public RequestResponse IsRequestValid(ModifyFileRequest fileRequest, RequestResponse requestResponse)
{
if (fileRequest.SucceedOnError)
{
return requestResponse;
}
requestResponse = FileValidation.ValidateDirectoryExists(fileRequest.SourcePath, requestResponse);
requestResponse = FileValidation.ValidateFileExists(fileRequest.OriginalSource, requestResponse);
requestResponse = FileValidation.ValidateFileNotExists(fileRequest.FinalSource, requestResponse);
return requestResponse;
}
}
@@ -0,0 +1,105 @@
using System;
using System.IO;
using Newtonsoft.Json;
using LCU.Library.Internal.FileOperationsModels.Models;
using LCU.Library.Internal.FileOperationsModels.Shared;
using LCU.Library.Internal.LCUServiceFactory.Configurations;
using LCU.Api.Internal.FileOperations.Validations;
namespace LCU.Api.Internal.FileOperations.Services.FileActionServices;
public class MoveFileService : FileActionService, IFileActionService, IActionService<MoveFileRequest>
{
public MoveFileService(ServicesFactoryConfiguration servicesFactoryConfiguration)
: base(servicesFactoryConfiguration)
{
}
public RequestResponse ExecuteAction(QueueRequest queueRequest)
{
var requestResponse = new RequestResponse();
try
{
var fileRequest = JsonConvert.DeserializeObject<MoveFileRequest>(queueRequest.Request);
var requests = DynamicNameBuilder.BuildListOfRequest(fileRequest);
requestResponse = FileValidation.ValidateIfAnyRequest(requests, fileRequest.Source, fileRequest.SucceedOnError, requestResponse);
foreach (var request in requests)
{
var temporaryRequestResponse = PerformRequest(request);
if (!temporaryRequestResponse.IsSuccessful)
{
requestResponse.IsSuccessful = fileRequest.SucceedOnError;
if (fileRequest.SucceedOnError)
{
requestResponse.MessageStack.Add("Succeed On Error is set.");
}
requestResponse.MessageStack.AddRange(temporaryRequestResponse.MessageStack);
}
}
requestResponse.ReturnResponse = fileRequest;
return requestResponse;
}
catch (Exception exception)
{
return RequestResponseHelper.ExceptionUpdateRequestResponse(requestResponse,
queueRequest.FileOperationType,
exception.Message);
}
}
public RequestResponse PerformRequest(MoveFileRequest request)
{
return OperationService.PerformOperation(request, IsRequestValid, MoveFile);
}
private void MoveFile(MoveFileRequest request)
{
try
{
File.Move(request.Source, request.Destination, request.Overwrite);
}
catch (Exception exception)
{
throw new Exception($"Exception thrown while trying to ExecuteRequestAction. " +
$"Request: {JsonConvert.SerializeObject(request)}" +
$"ExceptionMessage: {exception.Message}");
}
}
public RequestResponse PreQueueValidation(MoveFileRequest originalRequest)
{
var requestResponse = new RequestResponse();
var requestList = DynamicNameBuilder.BuildListOfRequest(originalRequest);
requestResponse = FileValidation.ValidateIfAnyRequest(requestList, originalRequest.SourcePath, originalRequest.SucceedOnError, requestResponse);
foreach (var request in requestList)
{
requestResponse = IsRequestValid(request, requestResponse);
}
return requestResponse;
}
public RequestResponse IsRequestValid(MoveFileRequest fileRequest, RequestResponse requestResponse)
{
if (fileRequest.SucceedOnError)
{
return requestResponse;
}
requestResponse = FileValidation.ValidateSourceNotEmpty(fileRequest.Source, requestResponse);
requestResponse = FileValidation.ValidateFileExists(fileRequest.Source, requestResponse);
requestResponse = FileValidation.ValidateDestinationNotEmpty(fileRequest.Destination, requestResponse);
requestResponse = FileValidation.ValidateDirectoryExists(fileRequest.DestinationPath, requestResponse);
if (!fileRequest.Overwrite)
{
requestResponse = FileValidation.ValidateFileNotExists(fileRequest.Destination, requestResponse);
}
return requestResponse;
}
}
@@ -0,0 +1,30 @@
using System;
using LCU.Library.Internal.FileOperationsModels.Models;
namespace LCU.Api.Internal.FileOperations.Services.FileActionServices;
public static class OperationService
{
public static RequestResponse PerformOperation<T>(T request,
Func<T, RequestResponse, RequestResponse> validate,
Action<T> action)
{
var requestResponse = new RequestResponse();
try
{
requestResponse = validate(request, requestResponse);
if (requestResponse.IsSuccessful)
{
action(request);
}
return requestResponse;
}
catch (Exception exception)
{
requestResponse.IsSuccessful = false;
requestResponse.MessageStack.Add(exception.Message);
return requestResponse;
}
}
}
@@ -0,0 +1,67 @@
using System;
using System.IO;
using Newtonsoft.Json;
using LCU.Library.Internal.FileOperationsModels.Models;
using LCU.Library.Internal.LCUServiceFactory.Configurations;
using LCU.Api.Internal.FileOperations.Validations;
namespace LCU.Api.Internal.FileOperations.Services.FileActionServices;
public class RenameDirectoryService : FileActionService, IFileActionService, IActionService<RenameDirectoryRequest>
{
public RenameDirectoryService(ServicesFactoryConfiguration servicesFactoryConfiguration)
: base(servicesFactoryConfiguration)
{
}
public RequestResponse ExecuteAction(QueueRequest queueRequest)
{
var requestResponse = new RequestResponse();
try
{
var directoryRequest = JsonConvert.DeserializeObject<RenameDirectoryRequest>(queueRequest.Request);
requestResponse = PerformRequest(directoryRequest);
requestResponse.ReturnResponse = directoryRequest;
return requestResponse;
}
catch (Exception exception)
{
return RequestResponseHelper.ExceptionUpdateRequestResponse(requestResponse,
queueRequest.FileOperationType,
exception.Message);
}
}
public RequestResponse PerformRequest(RenameDirectoryRequest request)
{
return OperationService.PerformOperation(request, IsRequestValid, RenameDirectory);
}
private void RenameDirectory(RenameDirectoryRequest request)
{
try
{
Directory.Move(request.FinalSourceDirectoryPath, request.NewDirectoryDestination);
}
catch (Exception exception)
{
throw new Exception($"Exception thrown while trying to ExecuteRequestAction. " +
$"Request: {JsonConvert.SerializeObject(request)}" +
$"ExceptionMessage: {exception.Message}");
}
}
public RequestResponse PreQueueValidation(RenameDirectoryRequest originalRequest)
{
var requestResponse = new RequestResponse();
requestResponse = IsRequestValid(originalRequest, requestResponse);
return requestResponse;
}
public RequestResponse IsRequestValid(RenameDirectoryRequest request, RequestResponse requestResponse)
{
requestResponse = FileValidation.ValidateDirectoryExists(request.SourceDirectoryPath, requestResponse);
requestResponse = FileValidation.ValidateDirectoryExists(request.FinalSourceDirectoryPath, requestResponse);
requestResponse = FileValidation.ValidateDirectoryNotExists(request.NewDirectoryDestination, requestResponse);
return requestResponse;
}
}
@@ -0,0 +1,85 @@
using System;
using System.IO;
using Newtonsoft.Json;
using LCU.Library.Internal.FileOperationsModels.Models;
using LCU.Library.Internal.LCUServiceFactory.Configurations;
using LCU.Api.Internal.FileOperations.Validations;
namespace LCU.Api.Internal.FileOperations.Services.FileActionServices;
public class RenameFileService : FileActionService, IFileActionService, IActionService<RenameFileRequest>
{
public RenameFileService(ServicesFactoryConfiguration servicesFactoryConfiguration)
: base(servicesFactoryConfiguration)
{
}
public RequestResponse ExecuteAction(QueueRequest queueRequest)
{
var requestResponse = new RequestResponse();
try
{
var fileRequest = JsonConvert.DeserializeObject<RenameFileRequest>(queueRequest.Request);
requestResponse = PerformRequest(fileRequest);
if (!requestResponse.IsSuccessful)
{
requestResponse.IsSuccessful = fileRequest.SucceedOnError;
if (fileRequest.SucceedOnError)
{
requestResponse.MessageStack.Add("Succeed On Error is set.");
}
}
requestResponse.ReturnResponse = fileRequest;
return requestResponse;
}
catch (Exception exception)
{
return RequestResponseHelper.ExceptionUpdateRequestResponse(requestResponse,
queueRequest.FileOperationType,
exception.Message);
}
}
public RequestResponse PerformRequest(RenameFileRequest request)
{
return OperationService.PerformOperation(request, IsRequestValid, RenameFile);
}
private void RenameFile(RenameFileRequest request)
{
try
{
File.Move(request.Source, request.NewFilenamePath);
}
catch (Exception exception)
{
throw new Exception($"Exception thrown while trying to ExecuteRequestAction. " +
$"Request: {JsonConvert.SerializeObject(request)}" +
$"ExceptionMessage: {exception.Message}");
}
}
public RequestResponse PreQueueValidation(RenameFileRequest originalRequest)
{
var requestResponse = new RequestResponse();
requestResponse = IsRequestValid(originalRequest, requestResponse);
return requestResponse;
}
public RequestResponse IsRequestValid(RenameFileRequest fileRequest, RequestResponse requestResponse)
{
if (fileRequest.SucceedOnError)
{
return requestResponse;
}
requestResponse = FileValidation.ValidateSourceNotEmpty(fileRequest.Source, requestResponse);
requestResponse = FileValidation.ValidateFileExists(fileRequest.Source, requestResponse);
requestResponse = FileValidation.ValidateFilenameNotEmpty(fileRequest.FinalNewFileName, requestResponse);
requestResponse = FileValidation.ValidateFilename(fileRequest.FinalNewFileName, requestResponse);
requestResponse = FileValidation.ValidateFileNotExists(fileRequest.NewFilenamePath, requestResponse);
return requestResponse;
}
}
@@ -0,0 +1,152 @@
using System;
using System.Collections.Generic;
using System.IO.Compression;
using System.IO;
using Newtonsoft.Json;
using LCU.Library.Internal.FileOperationsModels.Models;
using LCU.Library.Internal.FileOperationsModels.Shared;
using LCU.Api.Internal.FileOperations.Validations;
using LCU.Library.Internal.LCUServiceFactory.Configurations;
namespace LCU.Api.Internal.FileOperations.Services.FileActionServices;
public class UnzipFileService : FileActionService, IFileActionService, IActionService<UnzipFileRequest>
{
public UnzipFileService(ServicesFactoryConfiguration servicesFactoryConfiguration)
: base(servicesFactoryConfiguration)
{
}
public RequestResponse ExecuteAction(QueueRequest queueRequest)
{
var requestResponse = new RequestResponse();
try
{
var unzipRequest = JsonConvert.DeserializeObject<UnzipFileRequest>(queueRequest.Request);
var requests = BuildFileList(unzipRequest);
requestResponse = FileValidation.ValidateIfAnyRequest(requests, unzipRequest.FormattedSourceDirectoryPath, requestResponse);
foreach (var request in requests)
{
var temporaryRequestResponse = PerformRequest(request);
if (!temporaryRequestResponse.IsSuccessful)
{
requestResponse.IsSuccessful = temporaryRequestResponse.IsSuccessful;
requestResponse.MessageStack.AddRange(temporaryRequestResponse.MessageStack);
}
}
requestResponse.ReturnResponse = unzipRequest;
return requestResponse;
}
catch (Exception exception)
{
return RequestResponseHelper.ExceptionUpdateRequestResponse(requestResponse,
queueRequest.FileOperationType,
exception.Message);
}
}
public RequestResponse PerformRequest(UnzipFileRequest request)
{
return OperationService.PerformOperation(request, IsRequestValid, UnzipFile);
}
private void UnzipFile(UnzipFileRequest request)
{
try
{
var destination = request.FormattedDestinationPath;
if (request.UseZipFileNameAsFinalDestination)
{
destination = Path.GetDirectoryName(request.DestinationPathZipFileNameWithoutZip);
if (destination.Length > 0)
{
Directory.CreateDirectory(destination);
}
}
ZipFile.ExtractToDirectory(request.SourceFilePath, destination);
if (request.IgnoreFileNameSubFolderAsDestination)
{
MoveFromChildFolder(destination, request);
}
}
catch (Exception exception)
{
throw new Exception($"Exception thrown while trying to ExecuteRequestAction. " +
$"Request: {JsonConvert.SerializeObject(request)}" +
$"ExceptionMessage: {exception.Message}");
}
}
private void MoveFromChildFolder(string destination, UnzipFileRequest request)
{
var recursionDepth = request.MaxFileDepth;
var currentDepth = 0;
var currentFilePath = destination;
RecursiveFolderSearch(destination, recursionDepth, currentFilePath,currentDepth);
}
public void RecursiveFolderSearch(string destination, int recursionDepth, string currentFilePath, int currentDepth)
{
if (currentDepth>recursionDepth)
{
return;
}
var folders = Directory.EnumerateDirectories(currentFilePath);
foreach (var folder in folders)
{
RecursiveFolderSearch(destination, recursionDepth, folder, currentDepth + 1);
var childFiles = Directory.EnumerateFiles(folder);
foreach (var file in childFiles)
{
var fileName = file[(file.LastIndexOf("\\") + 1)..];
File.Move(file, destination + "\\" + fileName);
}
Directory.Delete(folder);
}
}
public RequestResponse PreQueueValidation(UnzipFileRequest originalRequest)
{
var requestResponse = new RequestResponse();
var requestList = BuildFileList(originalRequest);
requestResponse = FileValidation.ValidateIfAnyRequest(requestList, originalRequest.FormattedSourceDirectoryPath, requestResponse);
foreach (var request in requestList)
{
requestResponse = IsRequestValid(request, requestResponse);
}
return requestResponse;
}
public List<UnzipFileRequest> BuildFileList(UnzipFileRequest originalRequest)
{
var nameList = RegexNameHandler.BuildFileList(originalRequest.FormattedSourceDirectoryPath,
originalRequest.FinalZipFileName,
originalRequest.FileNameSetting);
var requests = new List<UnzipFileRequest>();
foreach (var name in nameList)
{
var newRequest = Clone.DeepClone(originalRequest);
newRequest.ZipFileName = name;
requests.Add(newRequest);
}
return requests;
}
public RequestResponse IsRequestValid(UnzipFileRequest fileRequest, RequestResponse requestResponse)
{
requestResponse = DirectoryValidation.ValidateDirectoryExists(fileRequest.FormattedSourceDirectoryPath, requestResponse);
requestResponse = FileValidation.ValidateFileExists(fileRequest.SourceFilePath, requestResponse);
requestResponse = DirectoryValidation.ValidateDirectoryExists(fileRequest.FormattedDestinationPath, requestResponse);
return requestResponse;
}
}
@@ -0,0 +1,165 @@
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using ICSharpCode.SharpZipLib.Zip;
using ICSharpCode.SharpZipLib.Core;
using System.IO;
using LCU.Library.Internal.FileOperationsModels.Models;
using LCU.Library.Internal.FileOperationsModels.Shared;
using LCU.Api.Internal.FileOperations.Validations;
using LCU.Library.Internal.LCUServiceFactory.Configurations;
namespace LCU.Api.Internal.FileOperations.Services.FileActionServices;
public class UnzipPasswordProtectedFileService : FileActionService, IFileActionService, IActionService<UnzipPasswordProtectedFileRequest>
{
public UnzipPasswordProtectedFileService(ServicesFactoryConfiguration servicesFactoryConfiguration)
: base(servicesFactoryConfiguration)
{
}
public RequestResponse ExecuteAction(QueueRequest queueRequest)
{
var requestResponse = new RequestResponse();
try
{
var unzipPasswordProtectedFileRequest = JsonConvert.DeserializeObject<UnzipPasswordProtectedFileRequest>(queueRequest.Request);
var requests = BuildFileList(unzipPasswordProtectedFileRequest);
requestResponse = FileValidation.ValidateIfAnyRequest(requests, unzipPasswordProtectedFileRequest.FormattedSourceDirectoryPath, requestResponse);
foreach (var request in requests)
{
var temporaryRequestResponse = PerformRequest(request);
if (!temporaryRequestResponse.IsSuccessful)
{
requestResponse.IsSuccessful = temporaryRequestResponse.IsSuccessful;
requestResponse.MessageStack.AddRange(temporaryRequestResponse.MessageStack);
}
}
requestResponse.ReturnResponse = unzipPasswordProtectedFileRequest;
return requestResponse;
}
catch (Exception exception)
{
return RequestResponseHelper.ExceptionUpdateRequestResponse(requestResponse,
queueRequest.FileOperationType,
exception.Message);
}
}
public RequestResponse PerformRequest(UnzipPasswordProtectedFileRequest request)
{
return OperationService.PerformOperation(request, IsRequestValid, UnzipPasswordProtectedFile);
}
public void UnzipPasswordProtectedFile(UnzipPasswordProtectedFileRequest request)
{
ZipFile passwordProtectedZipFile = null;
try
{
var fileStream = File.OpenRead(request.SourceFilePath);
passwordProtectedZipFile = new ZipFile(fileStream)
{
Password = request.Password
};
foreach (ZipEntry zipEntry in passwordProtectedZipFile)
{
if (!zipEntry.IsFile)
{
// Ignore directories
continue;
}
var entryFileName = zipEntry.Name;
// to remove the folder from the entry:- entryFileName = Path.GetFileName(entryFileName);
// Optionally match entrynames against a selection list here to skip as desired.
// The unpacked length is available in the zipEntry.Size property.
// 4K is optimum
var buffer = new byte[4096];
var zipStream = passwordProtectedZipFile.GetInputStream(zipEntry);
// Manipulate the output filename here as desired.
var finalDestinationPath = request.FormattedDestinationPath;
if (request.UseZipFileNameAsFinalDestination)
{
var zipFilename = request.PasswordProtectedZipFileNameWithDate.ToUpper().EndsWith(".ZIP") ?
request.PasswordProtectedZipFileNameWithDate.ToUpper().Replace(".ZIP", "") :
request.PasswordProtectedZipFileNameWithDate;
finalDestinationPath = $"{finalDestinationPath}{zipFilename}\\";
}
var fullZipToPath = Path.Combine(finalDestinationPath, entryFileName);
var directoryName = Path.GetDirectoryName(fullZipToPath);
if (directoryName.Length > 0)
{
Directory.CreateDirectory(directoryName);
}
// Unzip file in buffered chunks. This is just as fast as unpacking to a buffer the full size
// of the file, but does not waste memory.
// The "using" will close the stream even if an exception occurs.
using (FileStream streamWriter = File.Create(fullZipToPath))
{
StreamUtils.Copy(zipStream, streamWriter, buffer);
}
}
}
catch (Exception exception)
{
throw new Exception($"Exception thrown while trying to ExecuteRequestAction. " +
$"Request: {JsonConvert.SerializeObject(request)}" +
$"ExceptionMessage: {exception.Message}");
}
finally
{
if (passwordProtectedZipFile != null)
{
passwordProtectedZipFile.IsStreamOwner = true; // Makes close also shut the underlying stream
passwordProtectedZipFile.Close(); // Ensure we release resources
}
}
}
public RequestResponse PreQueueValidation(UnzipPasswordProtectedFileRequest originalRequest)
{
var requestResponse = new RequestResponse();
var requestList = BuildFileList(originalRequest);
requestResponse = FileValidation.ValidateIfAnyRequest(requestList, originalRequest.FormattedSourceDirectoryPath, requestResponse);
foreach (var request in requestList)
{
requestResponse = IsRequestValid(request, requestResponse);
}
return requestResponse;
}
public List<UnzipPasswordProtectedFileRequest> BuildFileList(UnzipPasswordProtectedFileRequest originalRequest)
{
var nameList = RegexNameHandler.BuildFileList(originalRequest.FormattedSourceDirectoryPath,
originalRequest.FinalPasswordProtectedZipFileName,
originalRequest.FileNameSetting);
var requests = new List<UnzipPasswordProtectedFileRequest>();
foreach (var name in nameList)
{
var newRequest = Clone.DeepClone(originalRequest);
newRequest.PasswordProtectedZipFileName = name;
requests.Add(newRequest);
}
return requests;
}
public RequestResponse IsRequestValid(UnzipPasswordProtectedFileRequest fileRequest, RequestResponse requestResponse)
{
requestResponse = DirectoryValidation.ValidateDirectoryExists(fileRequest.FormattedSourceDirectoryPath, requestResponse);
requestResponse = FileValidation.ValidateFileExists(fileRequest.SourceFilePath, requestResponse);
requestResponse = DirectoryValidation.ValidateDirectoryExists(fileRequest.FormattedDestinationPath, requestResponse);
return requestResponse;
}
}
@@ -0,0 +1,108 @@
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using LCU.Library.Internal.LCUServiceFactory.Configurations;
using LCU.Library.Internal.FileOperationsModels.Models;
using LCU.Library.Internal.FileOperationsModels.Shared;
using LCU.Library.Internal.FileOperationsModels.Enums;
using LCU.Api.Internal.FileOperations.Validations;
using LCU.Library.Internal.FileOperationsModels.Models.Requests;
using Microsoft.OpenApi.Extensions;
namespace LCU.Api.Internal.FileOperations.Services.FileActionServices;
public class ValidateFileService : FileActionService, IFileActionService, IActionService<ValidateFileRequest>
{
public ValidateFileService(ServicesFactoryConfiguration servicesFactoryConfiguration)
: base(servicesFactoryConfiguration)
{
}
public RequestResponse ExecuteAction(QueueRequest queueRequest)
{
var requestResponse = new RequestResponse();
try
{
var fileRequest = JsonConvert.DeserializeObject<ValidateFileRequest>(queueRequest.Request);
var requests = DynamicNameBuilder.BuildListOfRequests(fileRequest);
if (fileRequest.FileDoesExist)
{
requestResponse = FileValidation.ValidateIfAnyRequest(requests, fileRequest.FileSourceRequest.Source, requestResponse);
}
if (fileRequest.CheckFileCount)
{
if (!ValidateFileCount(fileRequest, requests))
{
requestResponse.MessageStack.Add($"The file count condition returned false: {requests.Count} {fileRequest.OperatorType.GetDisplayName()} {fileRequest.FileCount} ");
requestResponse.IsSuccessful = false;
}
}
requestResponse = PerformRequests(requests, requestResponse);
requestResponse.ReturnResponse = fileRequest;
return requestResponse;
}
catch (Exception exception)
{
return RequestResponseHelper.ExceptionUpdateRequestResponse(requestResponse,
queueRequest.FileOperationType,
exception.Message);
}
}
public bool ValidateFileCount(ValidateFileRequest fileRequest, List<ValidateFileRequest> requests)
=> fileRequest.OperatorType switch
{
OperatorTypes.Equals => (requests.Count == fileRequest.FileCount),
OperatorTypes.GreaterThan => (requests.Count > fileRequest.FileCount),
OperatorTypes.GreaterThanEquals => (requests.Count >= fileRequest.FileCount ),
OperatorTypes.LessThan => (requests.Count < fileRequest.FileCount),
OperatorTypes.LessThanEquals => (requests.Count <= fileRequest.FileCount ),
_ => throw new ArgumentOutOfRangeException(nameof(fileRequest.OperatorType), $"Not expected OperatorType value: {fileRequest.OperatorType}"),
};
public RequestResponse PerformRequests(List<ValidateFileRequest> requests, RequestResponse requestResponse)
{
foreach (var request in requests)
{
var temporaryRequestResponse = PerformRequest(request);
if (!temporaryRequestResponse.IsSuccessful)
{
requestResponse.MessageStack.AddRange(temporaryRequestResponse.MessageStack);
requestResponse.IsSuccessful = false;
}
}
return requestResponse;
}
public RequestResponse PerformRequest(ValidateFileRequest request)
{
var requestResponse = new RequestResponse();
if (request.FileDoesExist)
{
return FileValidation.ValidateFileExists(request.FileSourceRequest.Source, requestResponse);
}
return FileValidation.ValidateFileNotExists(request.FileSourceRequest.Source, requestResponse);
}
public RequestResponse PreQueueValidation(ValidateFileRequest originalRequest)
{
var requestResponse = new RequestResponse();
requestResponse = IsRequestValid(originalRequest, requestResponse);
return requestResponse;
}
public RequestResponse IsRequestValid(ValidateFileRequest request, RequestResponse requestResponse)
{
requestResponse = FileValidation.ValidateSourceNotEmpty(request.FileSourceRequest.SourceFile, requestResponse);
requestResponse = FileValidation.ValidateFilenameNotEmpty(request.FileSourceRequest.SourceFile, requestResponse);
requestResponse = FileValidation.ValidateFilename(request.FileSourceRequest.SourceFile, requestResponse);
return requestResponse;
}
}
@@ -0,0 +1,111 @@
using System;
using System.IO;
using LCU.Api.Internal.FileOperations.Validations;
using LCU.Library.Internal.FileOperationsModels.Enums;
using LCU.Library.Internal.FileOperationsModels.Models;
using LCU.Library.Internal.FileOperationsModels.Models.Requests;
using LCU.Library.Internal.FileOperationsModels.Shared;
using LCU.Library.Internal.LCUServiceFactory.Configurations;
using Newtonsoft.Json;
namespace LCU.Api.Internal.FileOperations.Services.FileActionServices;
public class ValidateFileSizeInRangeService : FileActionService, IFileActionService, IActionService<ValidateFileSizeInRangeRequest>
{
private readonly IFileSizeService _fileSizeService;
public ValidateFileSizeInRangeService(IFileSizeService fileSizeService,
ServicesFactoryConfiguration servicesFactoryConfiguration)
: base(servicesFactoryConfiguration)
{
_fileSizeService = fileSizeService;
}
public RequestResponse ExecuteAction(QueueRequest queueRequest)
{
var requestResponse = new RequestResponse();
try
{
var fileRequest = JsonConvert.DeserializeObject<ValidateFileSizeInRangeRequest>(queueRequest.Request);
var requests = DynamicNameBuilder.BuildListOfRequests(fileRequest);
requestResponse = FileValidation.ValidateIfAnyRequest(requests, fileRequest.FileSourceRequest.Source, requestResponse);
foreach (var request in requests)
{
var temporaryRequestResponse = PerformRequest(request);
if (temporaryRequestResponse.IsSuccessful)
{
continue;
}
requestResponse.MessageStack.AddRange(temporaryRequestResponse.MessageStack);
requestResponse.IsSuccessful = false;
}
requestResponse.ReturnResponse = fileRequest;
return requestResponse;
}
catch (Exception exception)
{
return RequestResponseHelper.ExceptionUpdateRequestResponse(requestResponse,
queueRequest.FileOperationType,
exception.Message);
}
}
public RequestResponse PerformRequest(ValidateFileSizeInRangeRequest request)
{
var requestResponse = new RequestResponse();
return ValidateFileSizeInRange(request.FileSourceRequest.Source,
request.StartFileSizeRange,
request.EndFileSizeRange,
request.FileSizeType,
requestResponse);
}
public RequestResponse PreQueueValidation(ValidateFileSizeInRangeRequest originalRequest)
{
var requestResponse = new RequestResponse();
try
{
var requestList = DynamicNameBuilder.BuildListOfRequests(originalRequest);
requestResponse = FileValidation.ValidateIfAnyRequest(requestList, originalRequest.FileSourceRequest.SourcePath, requestResponse);
foreach (var request in requestList)
{
requestResponse = IsRequestValid(request, requestResponse);
}
return requestResponse;
}
catch (Exception exception)
{
requestResponse.IsSuccessful = false;
requestResponse.MessageStack.Add(exception.Message);
return requestResponse;
}
}
public RequestResponse IsRequestValid(ValidateFileSizeInRangeRequest request, RequestResponse requestResponse)
{
requestResponse = FileValidation.ValidateFileExists(request.FileSourceRequest.Source, requestResponse);
return requestResponse;
}
private RequestResponse ValidateFileSizeInRange(string path, decimal min, decimal max,
FileSizeTypes fileSizeType,
RequestResponse requestResponse)
{
decimal fileLengthInBytes = new FileInfo(path).Length;
var fileLength = _fileSizeService.ConvertFileSize(fileLengthInBytes, fileSizeType);
if (fileLength < min || fileLength > max)
{
requestResponse.IsSuccessful = false;
requestResponse.MessageStack.Add($"File size is not in range at path {path}");
}
return requestResponse;
}
}
@@ -0,0 +1,78 @@
using LCU.Api.Internal.FileOperations.Validations;
using LCU.Library.Internal.FileOperationsModels.Models;
using LCU.Library.Internal.LCUServiceFactory.Configurations;
using Newtonsoft.Json;
using System;
using System.IO;
namespace LCU.Api.Internal.FileOperations.Services.FileActionServices
{
public class WriteFileService : FileActionService, IFileActionService, IActionService<WriteFileRequest>
{
public WriteFileService(ServicesFactoryConfiguration servicesFactoryConfiguration)
: base(servicesFactoryConfiguration)
{
}
public RequestResponse ExecuteAction(QueueRequest queueRequest)
{
var requestResponse = new RequestResponse();
try
{
var fileRequest = JsonConvert.DeserializeObject<WriteFileRequest>(queueRequest.Request);
requestResponse = PerformRequest(fileRequest);
requestResponse.ReturnResponse = fileRequest;
return requestResponse;
}
catch (Exception exception)
{
return RequestResponseHelper.ExceptionUpdateRequestResponse(requestResponse,
queueRequest.FileOperationType,
exception.Message);
}
}
public RequestResponse PerformRequest(WriteFileRequest request)
{
return OperationService.PerformOperation(request, IsRequestValid, WriteFile);
}
private void WriteFile(WriteFileRequest request)
{
try
{
File.WriteAllText(request.FullFilePath, request.FileData);
}
catch (Exception exception)
{
throw new Exception($"Exception thrown while trying to ExecuteRequestAction. " +
$"Request: {JsonConvert.SerializeObject(request)}" +
$"ExceptionMessage: {exception.Message}");
}
}
public RequestResponse PreQueueValidation(WriteFileRequest originalRequest)
{
var requestResponse = new RequestResponse();
requestResponse = IsRequestValid(originalRequest, requestResponse);
return requestResponse;
}
public RequestResponse IsRequestValid(WriteFileRequest originalRequest, RequestResponse requestResponse)
{
requestResponse = FileValidation.ValidateDirectoryExists(originalRequest.DestinationPath, requestResponse);
if (!originalRequest.Overwrite)
{
requestResponse = FileValidation.ValidateFileNotExists(originalRequest.FullFilePath, requestResponse);
}
return requestResponse;
}
}
}
@@ -0,0 +1,110 @@
using System;
using System.Collections.Generic;
using System.IO.Compression;
using Newtonsoft.Json;
using LCU.Library.Internal.FileOperationsModels.Models;
using LCU.Library.Internal.FileOperationsModels.Shared;
using LCU.Api.Internal.FileOperations.Validations;
using LCU.Library.Internal.LCUServiceFactory.Configurations;
namespace LCU.Api.Internal.FileOperations.Services.FileActionServices;
public class ZipDirectoryService : FileActionService, IFileActionService, IActionService<ZipDirectoryRequest>
{
public ZipDirectoryService(ServicesFactoryConfiguration servicesFactoryConfiguration)
: base(servicesFactoryConfiguration)
{
}
public RequestResponse ExecuteAction(QueueRequest queueRequest)
{
var requestResponse = new RequestResponse();
try
{
var zipRequest = JsonConvert.DeserializeObject<ZipDirectoryRequest>(queueRequest.Request);
var requests = BuildDirectoryList(zipRequest);
requestResponse = FileValidation.ValidateIfAnyRequest(requests, zipRequest.SourceDirectory, requestResponse);
var result = requestResponse.IsSuccessful;
foreach (var request in requests)
{
var temporaryRequestResponse = PerformRequest(request);
if (!temporaryRequestResponse.IsSuccessful)
{
requestResponse.IsSuccessful = temporaryRequestResponse.IsSuccessful;
requestResponse.MessageStack.AddRange(temporaryRequestResponse.MessageStack);
}
}
requestResponse.ReturnResponse = zipRequest;
return requestResponse;
}
catch (Exception exception)
{
return RequestResponseHelper.ExceptionUpdateRequestResponse(requestResponse,
queueRequest.FileOperationType,
exception.Message);
}
}
public RequestResponse PerformRequest(ZipDirectoryRequest request)
{
return OperationService.PerformOperation(request, IsRequestValid, ZipDirectory);
}
private void ZipDirectory(ZipDirectoryRequest request)
{
try
{
ZipFile.CreateFromDirectory(request.SourceDirectory, request.ZipDestination);
}
catch (Exception exception)
{
throw new Exception($"Exception thrown while trying to ExecuteRequestAction. " +
$"Request: {JsonConvert.SerializeObject(request)}" +
$"ExceptionMessage: {exception.Message}");
}
}
public RequestResponse PreQueueValidation(ZipDirectoryRequest originalRequest)
{
var requestResponse = new RequestResponse();
var requestList = BuildDirectoryList(originalRequest);
requestResponse = FileValidation.ValidateIfAnyRequest(requestList, originalRequest.FormattedSourceDirectory, requestResponse);
foreach (var request in requestList)
{
requestResponse = IsRequestValid(request, requestResponse);
}
return requestResponse;
}
public List<ZipDirectoryRequest> BuildDirectoryList(ZipDirectoryRequest originalRequest)
{
var nameList = RegexNameHandler.BuildDirectoryList(originalRequest.SourceDirectory,
originalRequest.DynamicDirectoryName,
originalRequest.FileNameSetting);
var requests = new List<ZipDirectoryRequest>();
foreach (var name in nameList)
{
var newRequest = Clone.DeepClone(originalRequest);
newRequest.DirectoryName = name;
newRequest.SourceDirectory = String.IsNullOrWhiteSpace(newRequest.DirectoryName) ?
originalRequest.SourceDirectory :
$"{originalRequest.FormattedSourceDirectory}{newRequest.DirectoryName}";
requests.Add(newRequest);
}
return requests;
}
public RequestResponse IsRequestValid(ZipDirectoryRequest fileRequest, RequestResponse requestResponse)
{
requestResponse = DirectoryValidation.ValidateDirectoryExists(fileRequest.SourceDirectory, requestResponse);
requestResponse = DirectoryValidation.ValidateDirectoryExists(fileRequest.ZipPath, requestResponse);
requestResponse = FileValidation.ValidateFileNotExists(fileRequest.ZipDestination, requestResponse);
return requestResponse;
}
}
@@ -0,0 +1,87 @@
using System;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Serilog;
using LCU.Library.Internal.ApiResponse.Services;
using LCU.Library.Internal.Exceptions;
using LCU.Library.Internal.FileOperationsModels.Models;
using LCU.Library.Internal.LCUServiceFactory.Services;
using LCU.Api.Internal.FileOperations.Services.QueueServices;
using LCU.Api.Internal.FileOperations.Services.FileActionServices;
using LCU.Api.Internal.FileOperations.Configurations;
namespace LCU.Api.Internal.FileOperations.Services;
public class FileOperationsService : IFileOperationsService
{
private readonly IQueueFileOperationsService _queueFileOperationsService;
private readonly ApiConfiguration _apiConfiguration;
private readonly ILcuServiceFactory<IFileActionService> _lcuServiceFactory;
public FileOperationsService(IQueueFileOperationsService queueFileOperationsService,
ApiConfiguration apiConfiguration,
ILcuServiceFactory<IFileActionService> lcuServiceFactory)
{
_queueFileOperationsService = queueFileOperationsService;
_apiConfiguration = apiConfiguration;
_lcuServiceFactory = lcuServiceFactory;
}
public async Task HandleFileOperationsRequest(QueueRequest queueRequest)
{
var result = PerformFileOperation(queueRequest);
if (ShouldPerformFileOperationsAgain(queueRequest, result))
{
Log.Information($"Attempting to requeue file operations request. Request: {JsonConvert.SerializeObject(queueRequest)}");
queueRequest.Attempts++;
await _queueFileOperationsService.QueueFileOperationsRequest(queueRequest);
return;
}
await QueueReturnResponse.QueueResponse(queueRequest.ReturnResponse, result.IsSuccessful, result.MessageStack);
if (!result.IsSuccessful)
{
var errorMessage = String.Join("; ", result.MessageStack.ToArray());
throw new ServiceException($"File Operation Request was not successful. MessageStack:{errorMessage}");
}
}
public RequestResponse PerformFileOperation(QueueRequest queueRequest)
{
var requestResponse = new RequestResponse();
try
{
ArgumentNullException.ThrowIfNull(queueRequest);
var fileActionService = _lcuServiceFactory.GetService(queueRequest.FileOperationType);
return fileActionService.ExecuteAction(queueRequest);
}
catch (Exception exception)
{
var failureMessage = $"Failed to perform file operations.";
Log.Error(exception, failureMessage);
var fileOperationType = queueRequest?.FileOperationType;
if (fileOperationType == null)
{
requestResponse.MessageStack.Add($"{failureMessage}. FileOperationType is Null. " +
$"ExceptionMessage: {exception.Message}");
return requestResponse;
}
requestResponse = RequestResponseHelper.ExceptionUpdateRequestResponse(requestResponse, queueRequest.FileOperationType, exception.Message);
return requestResponse;
}
}
public bool ShouldPerformFileOperationsAgain(QueueRequest request, RequestResponse requestResponse)
{
return !requestResponse.IsSuccessful &&
request.Attempts != null &&
request.Attempts < _apiConfiguration.AttemptsLimit;
}
}
@@ -0,0 +1,11 @@
using System.Threading.Tasks;
using LCU.Library.Internal.FileOperationsModels.Models;
using LCU.Library.Internal.ApiResponse.Models;
namespace LCU.Api.Internal.FileOperations.Services;
public interface IDirectFileOperationsService
{
Task<RequestResponse> HandleDirectFileOperationsRequest<TRequest>(TRequest request,
FileOperationType fileOperationType) where TRequest : ReturnResponse;
}
@@ -0,0 +1,7 @@
namespace LCU.Api.Internal.FileOperations.Services
{
public interface IDirectFileService
{
byte[] GetFileBytes(string path);
}
}
@@ -0,0 +1,8 @@
using System.Collections.Generic;
using LCU.Library.Internal.FileOperationsModels.Models;
namespace LCU.Api.Internal.FileOperations.Services;
public interface IDynamicDirectoryService
{
public IEnumerable<string> BuildDirectoryList(DynamicDirectoryListRequest request);
}
@@ -0,0 +1,10 @@
using LCU.Library.Internal.FileOperationsModels.Models;
using System.Threading.Tasks;
namespace LCU.Api.Internal.FileOperations.Services;
public interface IFileOperationsService
{
RequestResponse PerformFileOperation(QueueRequest queueRequest);
Task HandleFileOperationsRequest(QueueRequest queueRequest);
}
@@ -0,0 +1,93 @@
using System;
using System.IO;
using System.Text;
using PdfSharp.Pdf;
using PdfSharp.Pdf.IO;
using Serilog;
using Newtonsoft.Json;
using LCU.Library.Internal.FileOperationsModels.Models;
using LCU.Api.Internal.FileOperations.Services.FileActionServices;
using LCU.Api.Internal.FileOperations.Validations;
using LCU.Library.Internal.LCUServiceFactory.Configurations;
namespace LCU.Api.Internal.FileOperations.Services.PdfServices;
public class BatchPdfParserService : FileActionService, IFileActionService, IBatchPdfParserService
{
public BatchPdfParserService(ServicesFactoryConfiguration servicesFactoryConfiguration)
: base(servicesFactoryConfiguration)
{
}
public RequestResponse ExecuteAction(QueueRequest queueRequest)
{
var requestResponse = new RequestResponse();
try
{
var request = JsonConvert.DeserializeObject<BatchParsePdfRequest>(queueRequest.Request);
requestResponse = PerformRequest(request);
requestResponse.ReturnResponse = request;
return requestResponse;
}
catch (Exception exception)
{
return RequestResponseHelper.ExceptionUpdateRequestResponse(requestResponse,
queueRequest.FileOperationType,
exception.Message);
}
}
public RequestResponse PerformRequest(BatchParsePdfRequest request)
{
return OperationService.PerformOperation(request, IsRequestValid, BatchParsePdfs);
}
public void BatchParsePdfs(BatchParsePdfRequest batchParsePdfRequest)
{
try
{
var inputDocument = PdfReader.Open(batchParsePdfRequest.FullPdfPath, PdfDocumentOpenMode.Import);
foreach(var batchPdf in batchParsePdfRequest.BatchPdfs)
{
ParseAndSavePdf(batchParsePdfRequest, batchPdf, inputDocument);
}
}
catch (Exception exception)
{
Log.Error(exception, $"Failure to Batch Parse Pdfs. ParsePdfRequest:{JsonConvert.SerializeObject(batchParsePdfRequest)}");
throw new Exception($"Failure to Batch Parse Pdfs. ExceptionMessage:{exception.Message}");
}
}
public void ParseAndSavePdf(BatchParsePdfRequest batchParsePdfRequest, BatchPdf batchPdf, PdfDocument inputDocument)
{
var outputDocument = AddPdfPagesToOutputDocument(batchPdf.PageStart, batchPdf.PageStop, inputDocument);
string name = Path.GetFileNameWithoutExtension(batchParsePdfRequest.PdfName);
var newPdfName = string.IsNullOrWhiteSpace(batchPdf.ParsedPdfname) ? $"{name}.{batchPdf.PageStart}.pdf" : batchPdf.ParsedPdfname;
var newPath = Path.Combine(batchParsePdfRequest.RootPath, newPdfName);
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
outputDocument.Save(newPath);
}
public PdfDocument AddPdfPagesToOutputDocument(int pageStart, int pageStop, PdfDocument inputDocument)
{
var startIndex = pageStart - 1;
var stopIndex = pageStop - 1;
var outputDocument = new PdfDocument();
for (int page = startIndex; page <= stopIndex; page++)
{
outputDocument.Version = inputDocument.Version;
outputDocument.Info.Title = inputDocument.Info.Title;
outputDocument.Info.Creator = inputDocument.Info.Creator;
outputDocument.AddPage(inputDocument.Pages[page]);
}
return outputDocument;
}
public RequestResponse IsRequestValid(BatchParsePdfRequest request, RequestResponse requestResponse)
{
requestResponse = DirectoryValidation.ValidateDirectoryExists(request.RootPath, requestResponse);
requestResponse = FileValidation.ValidateFileExists(request.FullPdfPath, requestResponse);
return requestResponse;
}
}
@@ -0,0 +1,193 @@
using System;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using Serilog;
using Newtonsoft.Json;
using LCU.Library.Internal.Exceptions;
using LCU.Library.Internal.FileOperationsModels.Models.HtmlToPdfModels;
using LCU.Api.Internal.FileOperations.Configurations;
using System.Threading;
namespace LCU.Api.Internal.FileOperations.Services.PdfServices;
public class HtmlToPdfService : IHtmlToPdfService
{
private readonly ApiConfiguration _apiConfiguration;
private readonly IDirectFileService _directFileService;
public HtmlToPdfService(ApiConfiguration apiConfiguration, IDirectFileService directFileService)
{
_apiConfiguration = apiConfiguration;
_directFileService = directFileService;
}
public byte[] ConvertHtmlToPdf(HtmlToPdfRequest htmlToPdfRequest)
{
try
{
var output = CreateHtmlOutput(htmlToPdfRequest);
var finalOutput = CleanUpUnusedTagsFromOutput(output);
File.WriteAllText($"{htmlToPdfRequest.FinalHtmlSaveFilePath}{htmlToPdfRequest.PdfName}.html", finalOutput);
var fileCreated = CreatePdfFromHtml(htmlToPdfRequest);
if (!fileCreated)
{
throw new ServiceException($"Pdf file was not created. HtmlToPdfRequest: {JsonConvert.SerializeObject(htmlToPdfRequest)}");
}
var pdfBytes = _directFileService.GetFileBytes(htmlToPdfRequest.FinalPdfSaveFilePathWithFile);
CleanUpHtmlAndPdfFiles(htmlToPdfRequest);
return pdfBytes;
}
catch (Exception exception)
{
var message = "Failure to Convert Html To Pdf.";
Log.Error(exception, $"{message} HtmlToPdfRequest:{JsonConvert.SerializeObject(htmlToPdfRequest)}");
throw new ServiceException($"{message}. ExceptionMessage:{exception.Message}");
}
}
public string CreateHtmlOutput(HtmlToPdfRequest htmlToPdfRequest)
{
var templateOutput = AddBodyValuesToTemplateOutput(htmlToPdfRequest);
templateOutput = BuildOutputFromCollectionValues(htmlToPdfRequest.BodyValueCollections, templateOutput);
return templateOutput;
}
public string AddBodyValuesToTemplateOutput(HtmlToPdfRequest htmlToPdfRequest)
{
var templateOutput = File.ReadAllText(htmlToPdfRequest.HtmlTemplateFilePath);
templateOutput = AddTagValuesToOutput(templateOutput, htmlToPdfRequest.BodyTagValues);
return templateOutput;
}
public string BuildOutputFromCollectionValues(List<ValueCollection> valueCollections, string output)
{
if (valueCollections == null || !valueCollections.Any())
{
return output;
}
foreach (var bodyValueCollection in valueCollections)
{
var rowTemplateOutput = File.ReadAllText(bodyValueCollection.CollectionHtmlTemplateFilePath);
var rowsBuilder = new StringBuilder();
rowsBuilder = AddCollectionItemsToStringBuilder(bodyValueCollection.ValueCollectionItems, rowTemplateOutput, rowsBuilder);
output = output.Replace($"{{{bodyValueCollection.CollectionTag}}}", rowsBuilder.ToString());
}
return output;
}
public string AddTagValuesToOutput(string output, List<TagValue> tagValues)
{
foreach (var tagValue in tagValues)
{
output = output.Replace($"{{{tagValue.Tag}}}", tagValue.Value);
}
return output;
}
public StringBuilder AddCollectionItemsToStringBuilder(List<ValueCollectionItem> valueCollectionItems, string output, StringBuilder builder)
{
foreach (var valueCollectionItem in valueCollectionItems)
{
var tempOutput = output;
tempOutput = AddTagValuesToOutput(tempOutput, valueCollectionItem.TagValues);
if (valueCollectionItem.ValueCollections != null && valueCollectionItem.ValueCollections.Any())
{
tempOutput = BuildItemValueCollectionsOutput(valueCollectionItem.ValueCollections, tempOutput);
}
builder.Append(tempOutput);
}
return builder;
}
public string BuildItemValueCollectionsOutput(List<ValueCollection> valueCollections, string templateOutput)
{
if (valueCollections == null)
{
return templateOutput;
}
templateOutput = BuildOutputFromCollectionValues(valueCollections, templateOutput);
return templateOutput;
}
public string CleanUpUnusedTagsFromOutput(string output)
{
var pattern = @"{[A-Za-z0-9]*}";
var finalOutput = Regex.Replace(output, pattern, string.Empty);
return finalOutput;
}
public void SaveHtmlToFilePath(HtmlToPdfRequest htmlToPdfRequest, string htmlOutput)
{
using (StreamWriter outputFile = new StreamWriter($"{htmlToPdfRequest.FinalHtmlSaveFilePath}{htmlToPdfRequest.PdfName}.html"))
{
outputFile.Write(htmlOutput);
}
}
public bool CreatePdfFromHtml(HtmlToPdfRequest htmlToPdfRequest)
{
try
{
var url = $"{htmlToPdfRequest.FinalHtmlSaveFilePath}{htmlToPdfRequest.PdfName}.html";
var output = Path.Combine(htmlToPdfRequest.FinalPdfSaveFilePath, $"{htmlToPdfRequest.PdfName}.pdf");
using (var process = new Process())
{
process.StartInfo.FileName = _apiConfiguration.ChromePath;
process.StartInfo.Arguments = $"--user-data-dir={_apiConfiguration.FileOperationsChromeProfileFolderPath} " +
$"--headless --disable-gpu --print-to-pdf={output} {url} --no-pdf-header-footer";
process.Start();
process.WaitForExit();
}
var attempts = 0;
var fileCreated = false;
while (!fileCreated)
{
fileCreated = File.Exists(htmlToPdfRequest.FinalPdfSaveFilePathWithFile);
attempts++;
if (attempts > _apiConfiguration.MaxFileCheckAttempts)
{
break;
}
Thread.Sleep(1000);
}
return fileCreated;
}
catch (Exception exception)
{
var message = $"Failure to Create Pdf From Html.";
Log.Error(exception, message);
throw new Exception($"{message}. Exception Message: {exception.Message}");
}
}
public void CleanUpHtmlAndPdfFiles(HtmlToPdfRequest htmlToPdfRequest)
{
if (!htmlToPdfRequest.KeepHtmlFile)
{
File.Delete(htmlToPdfRequest.FinalHtmlSaveFilePathWithFile);
}
if (!htmlToPdfRequest.KeepPdfFile)
{
File.Delete(htmlToPdfRequest.FinalPdfSaveFilePathWithFile);
}
}
}
@@ -0,0 +1,8 @@
using LCU.Library.Internal.FileOperationsModels.Models;
namespace LCU.Api.Internal.FileOperations.Services;
public interface IBatchPdfParserService
{
RequestResponse ExecuteAction(QueueRequest queueRequest);
RequestResponse IsRequestValid(BatchParsePdfRequest request, RequestResponse requestResponse);
}
@@ -0,0 +1,7 @@
using LCU.Library.Internal.FileOperationsModels.Models.HtmlToPdfModels;
namespace LCU.Api.Internal.FileOperations.Services.PdfServices;
public interface IHtmlToPdfService
{
byte[] ConvertHtmlToPdf(HtmlToPdfRequest htmlToPdfRequest);
}
@@ -0,0 +1,9 @@
using LCU.Library.Internal.FileOperationsModels.Models;
namespace LCU.Api.Internal.FileOperations.Services
{
public interface IPdfParserService
{
string ParsePdf(ParsePdfRequest parsePdfRequest);
}
}
@@ -0,0 +1,47 @@
using System;
using System.IO;
using System.Text;
using PdfSharp.Pdf;
using PdfSharp.Pdf.IO;
using Serilog;
using Newtonsoft.Json;
using LCU.Library.Internal.Exceptions;
using LCU.Library.Internal.FileOperationsModels.Models;
namespace LCU.Api.Internal.FileOperations.Services.PdfServices;
public class PdfParserService : IPdfParserService
{
public string ParsePdf(ParsePdfRequest parsePdfRequest)
{
try
{
var fullPath = Path.Combine(parsePdfRequest.RootPath, parsePdfRequest.PdfName);
var inputDocument = PdfReader.Open(fullPath, PdfDocumentOpenMode.Import);
var startIndex = parsePdfRequest.PageStart - 1;
var stopIndex = parsePdfRequest.PageStop - 1;
var outputDocument = new PdfDocument();
for (int page = startIndex; page <= stopIndex; page++)
{
outputDocument.Version = inputDocument.Version;
outputDocument.Info.Title = inputDocument.Info.Title;
outputDocument.Info.Creator = inputDocument.Info.Creator;
outputDocument.AddPage(inputDocument.Pages[page]);
}
string name = Path.GetFileNameWithoutExtension(parsePdfRequest.PdfName);
var newPdfName = string.IsNullOrWhiteSpace(parsePdfRequest.ParsedPdfname) ? $"{name}.{parsePdfRequest.PageStart}.pdf" : parsePdfRequest.ParsedPdfname;
var newPath = Path.Combine(parsePdfRequest.RootPath, newPdfName);
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
outputDocument.Save(newPath);
return newPdfName;
}
catch (Exception exception)
{
Log.Error(exception, $"Failure to Parse Pdf. ParsePdfRequest:{JsonConvert.SerializeObject(parsePdfRequest)}");
throw new ServiceException($"Failure to Parse Pdf. ExceptionMessage:{exception.Message}");
}
}
}
@@ -0,0 +1,10 @@
using LCU.Library.Internal.ApiResponse.Models;
using LCU.Library.Internal.FileOperationsModels.Models;
using System.Threading.Tasks;
namespace LCU.Api.Internal.FileOperations.Services.QueueServices;
public interface IQueueFileOperationsService
{
Task QueueFileOperations<TRequest>(TRequest originalRequest, FileOperationType operationType) where TRequest : ReturnResponse;
Task QueueFileOperationsRequest(QueueRequest queueRequest);
}
@@ -0,0 +1,65 @@
using System;
using System.Threading.Tasks;
using System.Threading;
using Newtonsoft.Json;
using Serilog;
using MassTransit;
using LCU.Library.Internal.LcuMassTransitModels;
using LCU.Library.Internal.Exceptions;
using LCU.Library.Internal.FileOperationsModels.Models;
using LCU.Library.Internal.ApiResponse.Models;
namespace LCU.Api.Internal.FileOperations.Services.QueueServices;
public class QueueFileOperationsService : IQueueFileOperationsService
{
private readonly ISendEndpoint _sendEndpoint;
private readonly ReceiveEndpointConfiguration _receiveEndpointConfiguration;
public QueueFileOperationsService(IBusControl busControl,
ReceiveEndpointConfiguration receiveEndpointConfiguration)
{
_receiveEndpointConfiguration = receiveEndpointConfiguration;
_sendEndpoint = busControl.GetSendEndpoint(_receiveEndpointConfiguration.ReceiveEndpointUri).Result;
}
public async Task QueueFileOperations<TRequest>(TRequest originalRequest, FileOperationType operationType) where TRequest : ReturnResponse
{
try
{
QueueRequest queueRequest = new QueueRequest()
{
ReturnResponse = originalRequest,
FileOperationType = operationType,
Request = JsonConvert.SerializeObject(originalRequest),
Attempts = 0,
QueueTimeStamp = DateTime.Now
};
await QueueFileOperationsRequest(queueRequest);
}
catch (Exception ex)
{
Log.Error(ex, $"Failed to Queue File Operations. FileOperationType: {operationType.ToString()}");
throw new ServiceException($"Failed to Queue File Operation Request. FileOperationType: {operationType.ToString()}");
}
}
public async Task QueueFileOperationsRequest(QueueRequest queueRequest)
{
try
{
var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(30));
await _sendEndpoint.Send(queueRequest, cancellationTokenSource.Token);
}
catch (TaskCanceledException exception)
{
Log.Error(exception, $"Failed to Queue File Operation Request. FileOperationType: {queueRequest.FileOperationType}");
throw new ServiceException(exception.Message);
}
catch (Exception exception)
{
Log.Error(exception, $"Failed to Queue File Operation Request. FileOperationType: {queueRequest.FileOperationType}");
throw new ServiceException($"Failed to Queue File Operation Request. FileOperationType: {queueRequest.FileOperationType}");
}
}
}
@@ -0,0 +1,16 @@
using LCU.Library.Internal.FileOperationsModels.Models;
namespace LCU.Api.Internal.FileOperations.Services;
public static class RequestResponseHelper
{
public static RequestResponse ExceptionUpdateRequestResponse(RequestResponse requestResponse,
FileOperationType fileOperationType,
string exception)
{
requestResponse.IsSuccessful = false;
requestResponse.MessageStack.Add($"Failure to execute file action. " +
$"FileOperationType: {fileOperationType}, " +
$"Exception: {exception} ");
return requestResponse;
}
}
@@ -0,0 +1,108 @@
using Serilog;
using System;
using System.IO;
using System.Collections.Generic;
using LCU.Library.Internal.FileOperationsModels.Models;
using System.Linq;
namespace LCU.Api.Internal.FileOperations.Validations;
public class DirectoryValidation
{
private const string DirectoryDoesNotExist = "Directory does not exist at path";
private const string DirectoryExist = "Directory exists at path";
private const string DirectoriesNotWithinRange = "Number of expected Directories are not within range.";
public static RequestResponse ValidateDirectoryExists(string path, RequestResponse requestResponse)
{
bool doesDirectoryExists = false;
try
{
doesDirectoryExists = Directory.Exists(path);
}
catch (Exception exception)
{
Log.Error(exception, $"{DirectoryDoesNotExist} {path}");
}
if (!doesDirectoryExists)
{
requestResponse.IsSuccessful = false;
requestResponse.MessageStack.Add($"{DirectoryDoesNotExist} {path}");
}
return requestResponse;
}
public static RequestResponse ValidateDirectoryNotExists(string path, RequestResponse requestResponse)
{
bool directoryExists = false;
try
{
directoryExists = !Directory.Exists(path);
}
catch (Exception exception)
{
Log.Error(exception, $"{DirectoryExist} {path}");
}
if (!directoryExists)
{
requestResponse.IsSuccessful = false;
requestResponse.MessageStack.Add($"{DirectoryExist} {path}");
}
return requestResponse;
}
public static RequestResponse ValidateDirectoryRequestsWithinLimit<TRequest>(List<TRequest> requests,
int maxAmountOfDirectories,
RequestResponse requestResponse)
{
bool countWithRange = false;
try
{
countWithRange = requests.Count >= 0 && requests.Count <= maxAmountOfDirectories;
}
catch (Exception exception)
{
var message = $"Unexpected issue while validate directory requests within limit.";
Log.Error(exception, $"Unexpected issue while validate directory requests within limit.");
requestResponse.MessageStack.Add($"{message} Exception Message: {exception.Message}");
}
if (!countWithRange)
{
requestResponse.IsSuccessful = countWithRange;
requestResponse.MessageStack.Add($"{DirectoriesNotWithinRange} Expected Range: 0-{maxAmountOfDirectories}, Actual Directories: {requests.Count} ");
}
return requestResponse;
}
public static RequestResponse ValidateDirectoryIsEmpty(string path, RequestResponse requestResponse)
{
bool directoryIsEmpty = false;
try
{
directoryIsEmpty = !Directory.EnumerateFileSystemEntries(path).Any();
}
catch (Exception exception)
{
var message = $"Unexpected issue while validate directory is empty.";
Log.Error(exception, message);
requestResponse.MessageStack.Add($"{message} Exception Message: {exception.Message}");
}
if(!directoryIsEmpty)
{
requestResponse.IsSuccessful = directoryIsEmpty;
requestResponse.MessageStack.Add($"{path} is not empty.");
}
return requestResponse;
}
}
@@ -0,0 +1,223 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Serilog;
using LCU.Library.Internal.FileOperationsModels.Models;
namespace LCU.Api.Internal.FileOperations.Validations;
public static class FileValidation
{
private const string DestinationField = "Destination";
private const string SourceField = "Source";
private const string FilenameField = "Filename";
private const string FieldEmptyResponse = " is empty and is required.";
private const string FileNameInvalid = "File name is invalid.";
private const string FileDoesNotExists = "File does not exist at path";
private const string FileExists = "File exists at path";
private const string FilesDoNotExists = "Files do not exist at path";
private const string FilesNotWithinRange = "Number of expected Files are not within range.";
private const string DirectoryDoesNotExists = "Directory does not exists at path";
private const string DirectoryExist = "Directory exists at path";
public static RequestResponse ValidateSourceNotEmpty(string source, RequestResponse requestResponse)
{
requestResponse = ValidateNotEmpty(source, SourceField, requestResponse);
return requestResponse;
}
public static RequestResponse ValidateDestinationNotEmpty(string destination, RequestResponse requestResponse)
{
requestResponse = ValidateNotEmpty(destination, DestinationField, requestResponse);
return requestResponse;
}
public static RequestResponse ValidateFilenameNotEmpty(string filename, RequestResponse requestResponse)
{
requestResponse = ValidateNotEmpty(filename, FilenameField, requestResponse);
return requestResponse;
}
private static RequestResponse ValidateNotEmpty(string field, string fieldName, RequestResponse requestResponse)
{
if (string.IsNullOrEmpty(field))
{
requestResponse.IsSuccessful = false;
requestResponse.MessageStack.Add($"{fieldName}{FieldEmptyResponse}");
}
return requestResponse;
}
public static RequestResponse ValidateFilename(string filename, RequestResponse requestResponse)
{
if (filename.IndexOfAny(Path.GetInvalidFileNameChars()) >= 0)
{
requestResponse.IsSuccessful = false;
requestResponse.MessageStack.Add(FileNameInvalid);
}
return requestResponse;
}
public static RequestResponse ValidateFileExists(string path, RequestResponse requestResponse)
{
bool doesFileExists = false;
try
{
doesFileExists = File.Exists(path);
}
catch (Exception exception)
{
Log.Error(exception, $"{FileDoesNotExists} {path}");
}
if (!doesFileExists)
{
requestResponse.IsSuccessful = false;
requestResponse.MessageStack.Add($"{FileDoesNotExists} {path}");
}
return requestResponse;
}
public static RequestResponse ValidateFileNotExists(string path, RequestResponse requestResponse)
{
bool doesFileExists = false;
try
{
doesFileExists = File.Exists(path);
}
catch (Exception exception)
{
Log.Error(exception, $"{FileExists} {path}");
}
if (doesFileExists)
{
requestResponse.IsSuccessful = false;
requestResponse.MessageStack.Add($"{FileExists} {path}");
}
return requestResponse;
}
public static RequestResponse ValidateIfAnyRequest<TRequest>(List<TRequest> requests, string path, RequestResponse requestResponse)
{
bool anyRequest = false;
try
{
anyRequest = requests.Any();
}
catch (Exception exception)
{
Log.Error(exception, $"{FilesDoNotExists} {path}");
}
if (!anyRequest)
{
requestResponse.IsSuccessful = false;
requestResponse.MessageStack.Add($"{FilesDoNotExists} {path}");
}
return requestResponse;
}
public static RequestResponse ValidateIfAnyRequest<TRequest>(List<TRequest> requests,
string path,
bool succeedOnError,
RequestResponse requestResponse)
{
bool anyRequest = false;
try
{
anyRequest = requests.Any();
}
catch (Exception exception)
{
Log.Error(exception, $"{FilesDoNotExists} {path}");
}
if (!anyRequest)
{
requestResponse.IsSuccessful = succeedOnError;
requestResponse.MessageStack.Add($"{FilesDoNotExists} {path}");
}
return requestResponse;
}
public static RequestResponse ValidateFileRequestsWithinLimit<TRequest>(List<TRequest> requests,
int maxAmountOfFiles,
RequestResponse requestResponse)
{
bool countWithRange = false;
try
{
if (maxAmountOfFiles == 0)
{
return requestResponse;
}
countWithRange = requests.Count >= 0 && requests.Count <= maxAmountOfFiles;
}
catch (Exception exception)
{
var message = $"Unexpected issue while validate file requests within limit.";
Log.Error(exception, $"Unexpected issue while validate file requests within limit.");
requestResponse.MessageStack.Add($"{message} Exception Message: {exception.Message}");
}
if (!countWithRange)
{
requestResponse.IsSuccessful = countWithRange;
requestResponse.MessageStack.Add($"{FilesNotWithinRange} Expected Range: 0-{maxAmountOfFiles}, Actual Files: {requests.Count} ");
}
return requestResponse;
}
public static RequestResponse ValidateDirectoryExists(string path, RequestResponse requestResponse)
{
bool doesDirectoryExists = false;
try
{
doesDirectoryExists = Directory.Exists(path);
}
catch (Exception exception)
{
Log.Error(exception, $"{DirectoryDoesNotExists} {path}");
}
if (!doesDirectoryExists)
{
requestResponse.IsSuccessful = false;
requestResponse.MessageStack.Add($"{DirectoryDoesNotExists} {path}");
}
return requestResponse;
}
public static RequestResponse ValidateDirectoryNotExists(string path, RequestResponse requestResponse)
{
bool directoryExists = false;
try
{
directoryExists = !Directory.Exists(path);
}
catch (Exception exception)
{
Log.Error(exception, $"{DirectoryExist} {path}");
}
if (!directoryExists)
{
requestResponse.IsSuccessful = false;
requestResponse.MessageStack.Add($"{DirectoryExist} {path}");
}
return requestResponse;
}
}
@@ -0,0 +1,38 @@
using System;
using PdfSharp.Pdf;
using PdfSharp.Pdf.IO;
using LCU.Library.Internal.FileOperationsModels.Models;
namespace LCU.Api.Internal.FileOperations.Validations;
public static class PdfValidations
{
private const string PdfPageDoesntExist = "PDF Page Doesn't Exist.";
private const string PdfPageCantBeLessThanOne = "PDF Page Can't Be Less Than 1.";
public static RequestResponse ValidatePdfPageExists(RequestResponse requestResponse, string pdfName, int pageNumber)
{
try
{
PdfDocument inputDocument = PdfReader.Open(pdfName, PdfDocumentOpenMode.Import);
if(pageNumber <= 0)
{
requestResponse.IsSuccessful = false;
requestResponse.MessageStack.Add(PdfPageCantBeLessThanOne);
}
if (pageNumber > inputDocument.PageCount)
{
requestResponse.IsSuccessful = false;
requestResponse.MessageStack.Add(PdfPageDoesntExist);
}
}
catch (Exception exception)
{
requestResponse.IsSuccessful = false;
requestResponse.MessageStack.Add(exception.Message);
}
return requestResponse;
}
}
@@ -0,0 +1,122 @@
{
"Primary": {
"AppName": "File Operations",
"SeqUrl": "http://localhost:80/",
"SeqApiKey": "hkgw5LWrT7b7hXi3C0RN",
"AttemptsLimit": 2,
//OR Depending on your machine "C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe"
"ChromePath": "C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe",
"FileOperationsChromeProfileFolderPath": "C:\\FileOperationsChromeProfile",
"MaxFileCheckAttempts": 60,
"CorsAllowedOrigins": [
"http://localhost:3000",
"https://localhost:5001",
"http://lcu-internal.com",
"https://lcu-internal.com"
]
},
"AllowedHosts": "*",
"ServicesFactoryConfiguration": {
"ServiceFactoryRegistrations": [
{
"ServiceInterfaceName": "IFileActionService",
"ServiceRegistrations": [
{
"ServiceName": "MoveFileService",
"ServiceId": "0"
},
{
"ServiceName": "CopyFileService",
"ServiceId": "1"
},
{
"ServiceName": "DeleteFileService",
"ServiceId": "2"
},
{
"ServiceName": "RenameFileService",
"ServiceId": "3"
},
{
"ServiceName": "ZipDirectoryService",
"ServiceId": "4"
},
{
"ServiceName": "CreateDirectoryService",
"ServiceId": "5"
},
{
"ServiceName": "RenameDirectoryService",
"ServiceId": "6"
},
{
"ServiceName": "BulkOperationService`1",
"ServiceId": "7"
},
{
"ServiceName": "UnzipFileService",
"ServiceId": "8"
},
{
"ServiceName": "EncryptFileDataService",
"ServiceId": "9"
},
{
"ServiceName": "DecryptFileDataService",
"ServiceId": "10"
},
{
"ServiceName": "ModifyFileService",
"ServiceId": "11"
},
{
"ServiceName": "UnzipPasswordProtectedFileService",
"ServiceId": "12"
},
{
"ServiceName": "BatchPdfParserService",
"ServiceId": "13"
},
{
"ServiceName": "WriteFileService",
"ServiceId": "14"
},
{
"ServiceName": "DeleteDirectoryService",
"ServiceId": "15"
},
{
"ServiceName": "ValidateFileService",
"ServiceId": "16"
},
{
"ServiceName": "AppendFileService",
"ServiceId": "17"
},
{
"ServiceName": "ExtractIndexFileDataService",
"ServiceId": "18"
},
{
"ServiceName": "DeleteEmptyDirectoryService",
"ServiceId": "19"
},
{
"ServiceName": "ValidateFileSizeInRangeService",
"ServiceId": "20"
}
]
}
]
},
"ConnectionConfiguration": {
"HostUrl": "localhost",
"UserName": "guest",
"Password": "guest"
},
"FileOperationsReceiveEndpoint": {
"ReceiveEndpoint": "LCU.FileOperations",
"ReceiveEndpointType": "exchange",
"PrefetchLimit": 1
}
}
@@ -0,0 +1,5 @@
{
"version": "1.0",
"defaultProvider": "cdnjs",
"libraries": []
}