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
+330
View File
@@ -0,0 +1,330 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
# User-specific files
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
# Visual Studio 2015/2017 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# Visual Studio 2017 auto generated files
Generated\ Files/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUNIT
*.VisualState.xml
TestResult.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# Benchmark Results
BenchmarkDotNet.Artifacts/
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
**/Properties/launchSettings.json
# StyleCop
StyleCopReport.xml
# Files built by Visual Studio
*_i.c
*_p.c
*_i.h
*.ilk
*.meta
*.obj
*.iobj
*.pch
*.pdb
*.ipdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# Visual Studio Trace Files
*.e2e
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# JustCode is a .NET coding add-in
.JustCode
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Including strong name files can present a security risk
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
#*.snk
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
ServiceFabricBackup/
*.rptproj.bak
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
*.rptproj.rsuser
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# JetBrains Rider
.idea/
*.sln.iml
# CodeRush
.cr/
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Tabs Studio
*.tss
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs
# OpenCover UI analysis results
OpenCover/
# Azure Stream Analytics local run output
ASALocalRun/
# MSBuild Binary and Structured Log
*.binlog
# NVidia Nsight GPU debugger configuration file
*.nvuser
# MFractors (Xamarin productivity tool) working folder
.mfractor/
@@ -0,0 +1,132 @@
using System;
using System.IO;
using LCU.Api.Internal.FileOperations.Services.FileActionServices;
using LCU.Library.Internal.FileOperationsModels.Models;
using LCU.Library.Internal.LCUServiceFactory.Configurations;
using Org.BouncyCastle.Bcpg;
using Org.BouncyCastle.Bcpg.OpenPgp;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Crypto.Prng;
using Org.BouncyCastle.Security;
namespace LCU.API.Internal.FileOperations.IntegrationTests
{
class FileDataEncryptionTests
{
private const string TestPassword = "password";
private const string PrivateKeyFile = "TestPrivateKey";
private const string PublicKeyFile = "TestPublicKey";
private const string TestFile = "TestTextFile.txt";
private const string TestFileContents = "This text will be saved to a temporary test file for encryption/comparison to resulting files from this integration test";
private const string TestEncryptedFile = "TestTextFile.pgp";
private const string TestDecryptedFile = "TestTextFile-Decrypted";
private readonly string _basePath;
private readonly EncryptFileDataService _encryptFileDataService;
private readonly DecryptFileDataService _decryptFileDataService;
private readonly ServicesFactoryConfiguration _servicesFactoryConfiguration;
FileDataEncryptionTests()
{
_encryptFileDataService = new EncryptFileDataService(_servicesFactoryConfiguration);
_decryptFileDataService = new DecryptFileDataService(_servicesFactoryConfiguration);
_basePath = Path.Combine(Directory.GetCurrentDirectory(), "TempFileFolder");
Directory.CreateDirectory(_basePath);
GenerateTestKeys("[email protected]", TestPassword, Path.Combine(_basePath, PrivateKeyFile), Path.Combine(_basePath, PublicKeyFile));
File.WriteAllText(Path.Combine(_basePath, TestFile), TestFileContents);
}
static void Main()
{
var fileDataEncryptionTests = new FileDataEncryptionTests();
var encryptFileDataRequest = new EncryptFileDataRequest
{
SourcePath = fileDataEncryptionTests._basePath,
SourceFile = TestFile,
KeySourcePath = fileDataEncryptionTests._basePath,
KeySourceFile = PublicKeyFile,
DestinationPath = fileDataEncryptionTests._basePath
};
var decryptFileDataRequest = new DecryptFileDataRequest
{
SourcePath = fileDataEncryptionTests._basePath,
SourceFile = TestEncryptedFile,
KeySourcePath = fileDataEncryptionTests._basePath,
KeySourceFile = PrivateKeyFile,
DestinationPath = fileDataEncryptionTests._basePath,
DestinationFile = TestDecryptedFile,
PassPhrase = TestPassword
};
var encryptResult = fileDataEncryptionTests._encryptFileDataService.PerformRequest(encryptFileDataRequest);
var decryptResult = fileDataEncryptionTests._decryptFileDataService.PerformRequest(decryptFileDataRequest);
Console.WriteLine($"Encrypted Request Is Valid: {encryptResult.IsSuccessful}");
Console.WriteLine($"Decrypted Request Is Valid: {decryptResult.IsSuccessful}");
var encryptedFileContents = File.ReadAllText(Path.Combine(fileDataEncryptionTests._basePath, TestEncryptedFile));
var decryptedFileContents = File.ReadAllText(Path.Combine(fileDataEncryptionTests._basePath, TestDecryptedFile));
Console.WriteLine($"Test File Contents: {TestFileContents}");
Console.WriteLine($"Encrypted File Contents: {encryptedFileContents}");
Console.WriteLine($"Decrypted File Contents: {decryptedFileContents}");
Console.WriteLine("Complete");
}
private static void GenerateTestKeys(string identity, string passPhrase, string secretKeyOutputPath, string publicKeyOutputPath)
{
var keyPairGenerator = new RsaKeyPairGenerator();
keyPairGenerator.Init(new KeyGenerationParameters(new SecureRandom(new CryptoApiRandomGenerator()), 1024));
var keyPair = keyPairGenerator.GenerateKeyPair();
using var secretOut = new FileInfo(secretKeyOutputPath).OpenWrite();
using var publicOut = new FileInfo(publicKeyOutputPath).OpenWrite();
ExportGeneratedKeyPair(secretOut, publicOut, keyPair.Public, keyPair.Private, identity, passPhrase.ToCharArray(), true);
}
private static void ExportGeneratedKeyPair(
Stream secretOut,
Stream publicOut,
AsymmetricKeyParameter publicKey,
AsymmetricKeyParameter privateKey,
string identity,
char[] passPhrase,
bool armor)
{
if (armor)
{
secretOut = new ArmoredOutputStream(secretOut);
}
var pgpSecretKey = new PgpSecretKey
(
PgpSignature.DefaultCertification,
PublicKeyAlgorithmTag.RsaGeneral,
publicKey,
privateKey,
DateTime.Now,
identity,
SymmetricKeyAlgorithmTag.Cast5,
passPhrase,
null,
null,
new SecureRandom()
);
pgpSecretKey.Encode(secretOut);
secretOut.Close();
if (armor)
{
publicOut = new ArmoredOutputStream(publicOut);
}
var pgpPublicKey = pgpSecretKey.PublicKey;
pgpPublicKey.Encode(publicOut);
publicOut.Close();
}
}
}
@@ -0,0 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Portable.BouncyCastle" Version="1.9.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\LCU.Library.Internal.FileOperationsModels\LCU.Library.Internal.FileOperationsModels.csproj" />
<ProjectReference Include="..\LCU.Api.Internal.FileOperations\LCU.Api.Internal.FileOperations.csproj" />
</ItemGroup>
</Project>
@@ -0,0 +1,46 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.9.34723.18
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LCU.Api.Internal.FileOperations", "LCU.Api.Internal.FileOperations\LCU.Api.Internal.FileOperations.csproj", "{1C92A326-91A3-4904-B3EF-B766E10E7191}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LCU.Api.Internal.FileOperationsTests", "LCU.Api.Internal.FileOperationsTests\LCU.Api.Internal.FileOperationsTests.csproj", "{98503299-44F3-410A-B61F-36BC1706F132}"
ProjectSection(ProjectDependencies) = postProject
{1C92A326-91A3-4904-B3EF-B766E10E7191} = {1C92A326-91A3-4904-B3EF-B766E10E7191}
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LCU.Library.Internal.FileOperationsModels", "LCU.Library.Internal.FileOperationsModels\LCU.Library.Internal.FileOperationsModels.csproj", "{0D3255ED-449B-4F11-861B-5C9479520ED5}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LCU.API.Internal.FileOperations.IntegrationTests", "LCU.API.Internal.FileOperations.IntegrationTests\LCU.API.Internal.FileOperations.IntegrationTests.csproj", "{6D9C8EE6-5A6A-47F8-8DB0-DB757B154176}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{1C92A326-91A3-4904-B3EF-B766E10E7191}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1C92A326-91A3-4904-B3EF-B766E10E7191}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1C92A326-91A3-4904-B3EF-B766E10E7191}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1C92A326-91A3-4904-B3EF-B766E10E7191}.Release|Any CPU.Build.0 = Release|Any CPU
{98503299-44F3-410A-B61F-36BC1706F132}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{98503299-44F3-410A-B61F-36BC1706F132}.Debug|Any CPU.Build.0 = Debug|Any CPU
{98503299-44F3-410A-B61F-36BC1706F132}.Release|Any CPU.ActiveCfg = Release|Any CPU
{98503299-44F3-410A-B61F-36BC1706F132}.Release|Any CPU.Build.0 = Release|Any CPU
{0D3255ED-449B-4F11-861B-5C9479520ED5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0D3255ED-449B-4F11-861B-5C9479520ED5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0D3255ED-449B-4F11-861B-5C9479520ED5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0D3255ED-449B-4F11-861B-5C9479520ED5}.Release|Any CPU.Build.0 = Release|Any CPU
{6D9C8EE6-5A6A-47F8-8DB0-DB757B154176}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6D9C8EE6-5A6A-47F8-8DB0-DB757B154176}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6D9C8EE6-5A6A-47F8-8DB0-DB757B154176}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6D9C8EE6-5A6A-47F8-8DB0-DB757B154176}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {56A51B7E-A90A-4BFF-85D1-19ECB769AF6A}
EndGlobalSection
EndGlobal
@@ -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": []
}
@@ -0,0 +1,243 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Moq;
using Xunit;
using LCU.Api.Internal.FileOperations.Controllers;
using LCU.Api.Internal.FileOperations.Services;
using LCU.Api.Internal.FileOperations.Services.FileActionServices;
using LCU.Library.Internal.FileOperationsModels.Models;
using LCU.Library.Internal.Exceptions;
namespace LCU.Api.Internal.FileOperationsTests.Controllers;
public class DirectFileOperationsControllerTest
{
private readonly DirectFileOperationsController _controller;
private readonly Mock<IDirectFileOperationsService> _mockDirectFileOperationsService;
private readonly Mock<IActionService<MoveFileRequest>> _mockMoveFileService;
private readonly Mock<IActionService<WriteFileRequest>> _mockWriteFileService;
private readonly Mock<IActionService<CreateDirectoryRequest>> _mockCreateDirectoryService;
private readonly Mock<IActionService<UnzipFileRequest>> _mockUnzipFileService;
private readonly Mock<IActionService<ZipDirectoryRequest>> _mockZipDirectoryService;
private readonly Mock<IActionService<DeleteDirectoryRequest>> _mockDeleteDirectoryService;
private readonly Mock<IActionService<DeleteFileRequest>> _mockDeleteFileService;
private readonly Mock<IActionService<AppendFileRequest>> _mockAppendFileService;
public DirectFileOperationsControllerTest()
{
_mockDirectFileOperationsService = new Mock<IDirectFileOperationsService>();
_mockMoveFileService = new Mock<IActionService<MoveFileRequest>>();
_mockWriteFileService = new Mock<IActionService<WriteFileRequest>>();
_mockCreateDirectoryService = new Mock<IActionService<CreateDirectoryRequest>>();
_mockUnzipFileService = new Mock<IActionService<UnzipFileRequest>>();
_mockZipDirectoryService = new Mock<IActionService<ZipDirectoryRequest>>();
_mockDeleteDirectoryService = new Mock<IActionService<DeleteDirectoryRequest>>();
_mockDeleteFileService = new Mock<IActionService<DeleteFileRequest>>();
_mockAppendFileService = new Mock<IActionService<AppendFileRequest>>();
_controller = new DirectFileOperationsController(_mockDirectFileOperationsService.Object,
_mockMoveFileService.Object,
_mockWriteFileService.Object,
_mockCreateDirectoryService.Object,
_mockUnzipFileService.Object,
_mockZipDirectoryService.Object,
_mockDeleteDirectoryService.Object,
_mockDeleteFileService.Object,
_mockAppendFileService.Object);
}
[Fact]
public async Task MoveFilePost_OK()
{
// arrange
var request = new MoveFileRequest()
{
SourcePath = "",
SourceFile = "",
DestinationPath = ""
};
var validRequestResponse = new RequestResponse() { MessageStack = new List<string>(), IsSuccessful = true };
_mockMoveFileService.Setup(service => service.PreQueueValidation(It.IsAny<MoveFileRequest>())).Returns(validRequestResponse);
_mockDirectFileOperationsService.Setup(service =>
service.HandleDirectFileOperationsRequest(It.IsAny<MoveFileRequest>(), FileOperationType.Move))
.ReturnsAsync(validRequestResponse)
.Verifiable();
// act
var result = await _controller.MoveFile(request);
Assert.NotNull(result);
var okResult = result as OkObjectResult;
// assert
Assert.NotNull(okResult);
Assert.Equal(200, okResult.StatusCode);
_mockMoveFileService.Verify(service =>
service.PreQueueValidation(It.IsAny<MoveFileRequest>()), Times.Once);
_mockDirectFileOperationsService.Verify(service =>
service.HandleDirectFileOperationsRequest(It.IsAny<MoveFileRequest>(), FileOperationType.Move), Times.Once);
}
[Fact]
public async Task MoveFilePost_InvalidRequest()
{
// arrange
var request = new MoveFileRequest() { };
var validRequestResponse = new RequestResponse() { MessageStack = new List<string>() { "Invalid" }, IsSuccessful = false };
_mockMoveFileService.Setup(service => service.PreQueueValidation(It.IsAny<MoveFileRequest>())).Returns(validRequestResponse);
// act
var result = await _controller.MoveFile(request);
Assert.NotNull(result);
var badRequest = result as BadRequestObjectResult;
Assert.Equal(400, badRequest.StatusCode);
Assert.Equal($"Request is invalid. Response: {String.Join("\n ", validRequestResponse.MessageStack.ToArray())}", badRequest.Value);
_mockMoveFileService.Verify(service =>
service.PreQueueValidation(It.IsAny<MoveFileRequest>()), Times.Once);
_mockDirectFileOperationsService.Verify(service =>
service.HandleDirectFileOperationsRequest(It.IsAny<MoveFileRequest>(), FileOperationType.Move), Times.Never);
}
[Fact]
public async Task MoveFile_Failure_UnexpectedException()
{
var request = new MoveFileRequest()
{
SourcePath = "",
SourceFile = "",
DestinationPath = ""
};
var validRequestResponse = new RequestResponse() { MessageStack = new List<string>(), IsSuccessful = true };
_mockMoveFileService.Setup(service => service.PreQueueValidation(It.IsAny<MoveFileRequest>())).Returns(validRequestResponse).Verifiable();
_mockDirectFileOperationsService.Setup(service =>
service.HandleDirectFileOperationsRequest(It.IsAny<MoveFileRequest>(), FileOperationType.Move))
.ThrowsAsync(new Exception("Thrown From Unit Test"))
.Verifiable();
var result = await _controller.MoveFile(request);
Assert.NotNull(result);
var statusResult = result as StatusCodeResult;
Assert.NotNull(statusResult);
Assert.Equal(500, statusResult!.StatusCode);
_mockMoveFileService.Verify(service =>
service.PreQueueValidation(It.IsAny<MoveFileRequest>()), Times.Once);
_mockDirectFileOperationsService.Verify(service =>
service.HandleDirectFileOperationsRequest(It.IsAny<MoveFileRequest>(), FileOperationType.Move), Times.Once);
}
[Fact]
public async Task MoveFile_Failure_ServiceException()
{
var request = new MoveFileRequest()
{
SourcePath = "",
SourceFile = "",
DestinationPath = ""
};
var validRequestResponse = new RequestResponse() { MessageStack = new List<string>(), IsSuccessful = true };
_mockMoveFileService.Setup(service => service.PreQueueValidation(It.IsAny<MoveFileRequest>())).Returns(validRequestResponse).Verifiable();
_mockDirectFileOperationsService.Setup(service =>
service.HandleDirectFileOperationsRequest(It.IsAny<MoveFileRequest>(), FileOperationType.Move))
.ThrowsAsync(new ServiceException("Thrown From Unit Test"))
.Verifiable();
var result = await _controller.MoveFile(request);
Assert.NotNull(result);
var statusResult = result as ObjectResult;
Assert.NotNull(statusResult);
Assert.Equal(500, statusResult!.StatusCode);
_mockMoveFileService.Verify(service =>
service.PreQueueValidation(It.IsAny<MoveFileRequest>()), Times.Once);
_mockDirectFileOperationsService.Verify(service =>
service.HandleDirectFileOperationsRequest(It.IsAny<MoveFileRequest>(), FileOperationType.Move), Times.Once);
}
[Fact]
public async Task AppendFilePost_Ok()
{
var request = new AppendFileRequest()
{
FileData = "Text to write",
DestinationPath = "SomePath",
Extension = ".txt",
FileName = "FileName"
};
var validRequestResponse = new RequestResponse() { MessageStack = new List<string>(), IsSuccessful = true };
_mockAppendFileService.Setup(service => service.PreQueueValidation(It.IsAny<AppendFileRequest>())).Returns(validRequestResponse);
_mockDirectFileOperationsService.Setup(service =>
service.HandleDirectFileOperationsRequest(It.IsAny<AppendFileRequest>(), FileOperationType.AppendFile))
.ReturnsAsync(validRequestResponse)
.Verifiable();
// act
var result = await _controller.AppendFile(request);
Assert.NotNull(result);
var okResult = result as OkObjectResult;
// assert
Assert.NotNull(okResult);
Assert.Equal(200, okResult.StatusCode);
_mockAppendFileService.Verify(service =>
service.PreQueueValidation(It.IsAny<AppendFileRequest>()), Times.Once);
_mockDirectFileOperationsService.Verify(service =>
service.HandleDirectFileOperationsRequest(It.IsAny<AppendFileRequest>(), FileOperationType.AppendFile), Times.Once);
}
[Fact]
public async Task AppendFilePost_InvalidRequest()
{
// arrange
var request = new AppendFileRequest() { };
var validRequestResponse = new RequestResponse() { MessageStack = new List<string>() { "Invalid" }, IsSuccessful = false };
_mockAppendFileService.Setup(service => service.PreQueueValidation(It.IsAny<AppendFileRequest>())).Returns(validRequestResponse);
// act
var result = await _controller.AppendFile(request);
Assert.NotNull(result);
var badRequest = result as BadRequestObjectResult;
Assert.Equal(400, badRequest.StatusCode);
Assert.Equal($"Request is invalid. Response: {String.Join("\n ", validRequestResponse.MessageStack.ToArray())}", badRequest.Value);
_mockAppendFileService.Verify(service =>
service.PreQueueValidation(It.IsAny<AppendFileRequest>()), Times.Once);
_mockDirectFileOperationsService.Verify(service =>
service.HandleDirectFileOperationsRequest(It.IsAny<AppendFileRequest>(), FileOperationType.AppendFile), Times.Never);
}
[Fact]
public async Task AppendFile_Failure_ServiceException()
{
var request = new AppendFileRequest()
{
FileData = "Text to write",
DestinationPath = "SomePath",
Extension = ".txt",
FileName = "FileName"
};
var validRequestResponse = new RequestResponse() { MessageStack = new List<string>(), IsSuccessful = true };
_mockAppendFileService.Setup(service => service.PreQueueValidation(It.IsAny<AppendFileRequest>())).Returns(validRequestResponse).Verifiable();
_mockDirectFileOperationsService.Setup(service =>
service.HandleDirectFileOperationsRequest(It.IsAny<AppendFileRequest>(), FileOperationType.AppendFile))
.ThrowsAsync(new ServiceException("Thrown From Unit Test"))
.Verifiable();
var result = await _controller.AppendFile(request);
Assert.NotNull(result);
var statusResult = result as ObjectResult;
Assert.NotNull(statusResult);
Assert.Equal(500, statusResult!.StatusCode);
_mockAppendFileService.Verify(service =>
service.PreQueueValidation(It.IsAny<AppendFileRequest>()), Times.Once);
_mockDirectFileOperationsService.Verify(service =>
service.HandleDirectFileOperationsRequest(It.IsAny<AppendFileRequest>(), FileOperationType.AppendFile), Times.Once);
}
}
@@ -0,0 +1,302 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Moq;
using Xunit;
using LCU.Api.Internal.FileOperations.Controllers;
using LCU.Api.Internal.FileOperations.Services;
using LCU.Api.Internal.FileOperations.Services.FileActionServices;
using LCU.Library.Internal.FileOperationsModels.Models;
using LCU.Api.Internal.FileOperations.Services.QueueServices;
namespace LCU.Api.Internal.FileOperationsTests.Controllers;
public class FileOperationsControllerTest
{
private readonly FileOperationsController _controller;
private readonly Mock<IQueueFileOperationsService> _mockFileOperationsService;
private readonly Mock<IActionService<MoveFileRequest>> _mockMoveFileService;
private readonly Mock<IActionService<CopyFileRequest>> _mockCopyFileService;
private readonly Mock<IActionService<ModifyFileRequest>> _mockModifyFileService;
private readonly Mock<IActionService<DeleteFileRequest>> _mockDeleteFileService;
private readonly Mock<IActionService<RenameFileRequest>> _mockRenameFileService;
private readonly Mock<IActionService<ZipDirectoryRequest>> _mockZipDirectoryService;
private readonly Mock<IActionService<UnzipFileRequest>> _mockUnzipFileService;
private readonly Mock<IActionService<UnzipPasswordProtectedFileRequest>> _mockUnzipPasswordProtectedFileService;
private readonly Mock<IActionService<CreateDirectoryRequest>> _mockCreateDirectoryService;
private readonly Mock<IActionService<RenameDirectoryRequest>> _mockRenameDirectoryService;
private readonly Mock<IActionService<BulkOperationRequest<MoveFileRequest>>> _mockBulkMoveFileService;
private readonly Mock<IActionService<EncryptFileDataRequest>> _mockEncryptFileDataService;
private readonly Mock<IActionService<DecryptFileDataRequest>> _mockDecryptFileDataService;
private readonly Mock<IActionService<WriteFileRequest>> _mockWriteFileDataService;
private readonly Mock<IActionService<DeleteDirectoryRequest>> _mockDeleteDirectoryService;
private readonly Mock<IActionService<DeleteEmptyDirectoryRequest>> _mockDeleteEmptyDirectoriesService;
private readonly Mock<IDirectFileService> _mockDirectFileService;
public FileOperationsControllerTest()
{
_mockFileOperationsService = new Mock<IQueueFileOperationsService>();
_mockMoveFileService = new Mock<IActionService<MoveFileRequest>>();
_mockCopyFileService = new Mock<IActionService<CopyFileRequest>>();
_mockModifyFileService = new Mock<IActionService<ModifyFileRequest>>();
_mockDeleteFileService = new Mock<IActionService<DeleteFileRequest>>();
_mockRenameFileService = new Mock<IActionService<RenameFileRequest>>();
_mockZipDirectoryService = new Mock<IActionService<ZipDirectoryRequest>>();
_mockUnzipFileService = new Mock<IActionService<UnzipFileRequest>>();
_mockUnzipPasswordProtectedFileService = new Mock<IActionService<UnzipPasswordProtectedFileRequest>>();
_mockCreateDirectoryService = new Mock<IActionService<CreateDirectoryRequest>>();
_mockRenameDirectoryService = new Mock<IActionService<RenameDirectoryRequest>>();
_mockBulkMoveFileService = new Mock<IActionService<BulkOperationRequest<MoveFileRequest>>>();
_mockEncryptFileDataService = new Mock<IActionService<EncryptFileDataRequest>>();
_mockDecryptFileDataService = new Mock<IActionService<DecryptFileDataRequest>>();
_mockWriteFileDataService = new Mock<IActionService<WriteFileRequest>>();
_mockDeleteDirectoryService = new Mock<IActionService<DeleteDirectoryRequest>>();
_mockDeleteEmptyDirectoriesService = new Mock<IActionService<DeleteEmptyDirectoryRequest>>();
_mockDirectFileService = new Mock<IDirectFileService>();
_controller = new FileOperationsController(
_mockFileOperationsService.Object,
_mockMoveFileService.Object,
_mockCopyFileService.Object,
_mockModifyFileService.Object,
_mockDeleteFileService.Object,
_mockRenameFileService.Object,
_mockZipDirectoryService.Object,
_mockUnzipFileService.Object,
_mockUnzipPasswordProtectedFileService.Object,
_mockCreateDirectoryService.Object,
_mockRenameDirectoryService.Object,
_mockBulkMoveFileService.Object,
_mockEncryptFileDataService.Object,
_mockDecryptFileDataService.Object,
_mockWriteFileDataService.Object,
_mockDeleteDirectoryService.Object,
_mockDeleteEmptyDirectoriesService.Object,
_mockDirectFileService.Object);
}
[Fact]
public void GetFile_OK()
{
var bytes = new byte[1];
_mockDirectFileService.Setup(service => service.GetFileBytes(It.IsAny<string>())).Returns(bytes);
// act
var result = _controller.GetFile("\\\\fakeit\\file.csv");
Assert.NotNull(result);
var okResult = result as FileContentResult;
// assert
Assert.NotNull(okResult);
_mockDirectFileService.Verify(service => service.GetFileBytes(It.IsAny<string>()), Times.Once);
}
[Fact]
public void GetFile_BadRequest_Pre()
{
var bytes = new byte[1];
_mockDirectFileService.Setup(service => service.GetFileBytes(It.IsAny<string>())).Returns(bytes);
// act
var result = _controller.GetFile(" ");
Assert.NotNull(result);
var badResult = result as BadRequestObjectResult;
// assert
Assert.NotNull(badResult);
Assert.Equal(400, badResult.StatusCode);
_mockDirectFileService.Verify(service => service.GetFileBytes(It.IsAny<string>()), Times.Never);
}
[Fact]
public void GetFile_BadRequest_Post()
{
_mockDirectFileService.Setup(service => service.GetFileBytes(It.IsAny<string>()))
.Throws<ArgumentException>();
// act
var result = _controller.GetFile("\\\\fakeit\\file.csv");
Assert.NotNull(result);
var badResult = result as BadRequestObjectResult;
// assert
Assert.NotNull(badResult);
Assert.Equal(400, badResult.StatusCode);
_mockDirectFileService.Verify(service => service.GetFileBytes(It.IsAny<string>()), Times.Once);
}
// Post tests
[Fact]
public async Task MoveFilePost_OK()
{
// arrange
var request = new MoveFileRequest()
{
SourcePath = "",
SourceFile = "",
DestinationPath = ""
};
var validRequestResponse = new RequestResponse() { MessageStack = new List<string>(), IsSuccessful = true };
_mockMoveFileService.Setup(service => service.PreQueueValidation(It.IsAny<MoveFileRequest>())).Returns(validRequestResponse);
// act
var result = await _controller.MoveFile(request);
Assert.NotNull(result);
var okResult = result as OkResult;
// assert
Assert.NotNull(okResult);
Assert.Equal(200, okResult.StatusCode);
}
// Post tests
[Fact]
public async Task MoveFilePost_InvalidRequest()
{
// arrange
var request = new MoveFileRequest() { };
var validRequestResponse = new RequestResponse() { MessageStack = new List<string>() { "Invalid" }, IsSuccessful = false };
_mockMoveFileService.Setup(service => service.PreQueueValidation(It.IsAny<MoveFileRequest>())).Returns(validRequestResponse);
// act
var result = await _controller.MoveFile(request);
Assert.NotNull(result);
var badRequest = result as BadRequestObjectResult;
Assert.Equal(400, badRequest.StatusCode);
Assert.Equal($"Request is invalid. Response: {String.Join("\n ", validRequestResponse.MessageStack.ToArray())}", badRequest.Value);
}
// Post tests
[Fact]
public async Task CopyFilePost_OK()
{
// arrange
var request = new CopyFileRequest()
{
SourcePath = "",
SourceFile = "",
DestinationPath = ""
};
var validRequestResponse = new RequestResponse() { MessageStack = new List<string>(), IsSuccessful = true };
_mockCopyFileService.Setup(service => service.PreQueueValidation(It.IsAny<CopyFileRequest>())).Returns(validRequestResponse);
// act
var result = await _controller.CopyFile(request);
Assert.NotNull(result);
var okResult = result as OkResult;
// assert
Assert.NotNull(okResult);
Assert.Equal(200, okResult.StatusCode);
}
// Post tests
[Fact]
public async Task CopyFilePost_InvalidRequest()
{
// arrange
var request = new CopyFileRequest() { };
var validRequestResponse = new RequestResponse() { MessageStack = new List<string>() { "Invalid" }, IsSuccessful = false };
_mockCopyFileService.Setup(service => service.PreQueueValidation(It.IsAny<CopyFileRequest>())).Returns(validRequestResponse);
// act
var result = await _controller.CopyFile(request);
Assert.NotNull(result);
var badRequest = result as BadRequestObjectResult;
Assert.Equal(400, badRequest.StatusCode);
Assert.Equal($"Request is invalid. Response: {String.Join("\n ", validRequestResponse.MessageStack.ToArray())}", badRequest.Value);
}
// Post tests
[Fact]
public async Task UnzipPasswordProtectedFilePost_OK()
{
// arrange
var request = new UnzipPasswordProtectedFileRequest()
{
SourceDirectory = "",
PasswordProtectedZipFileName = "",
Password = "",
DestinationPath = ""
};
var validRequestResponse = new RequestResponse() { MessageStack = new List<string>(), IsSuccessful = true };
_mockUnzipPasswordProtectedFileService.Setup(service => service.PreQueueValidation(It.IsAny<UnzipPasswordProtectedFileRequest>())).Returns(validRequestResponse);
// act
var result = await _controller.UnzipPasswordProtectedFile(request);
// assert
Assert.NotNull(result);
Assert.Equal(200, (result as OkResult).StatusCode);
}
// Post tests
[Fact]
public async Task UnzipPasswordProtectedFilePost_InvalidRequest()
{
// arrange
var request = new UnzipPasswordProtectedFileRequest() { };
var validRequestResponse = new RequestResponse() { MessageStack = new List<string>() { "Invalid" }, IsSuccessful = false };
_mockUnzipPasswordProtectedFileService.Setup(service => service.PreQueueValidation(It.IsAny<UnzipPasswordProtectedFileRequest>())).Returns(validRequestResponse);
// act
var result = await _controller.UnzipPasswordProtectedFile(request);
Assert.NotNull(result);
var badRequest = result as BadRequestObjectResult;
Assert.Equal(400, badRequest.StatusCode);
Assert.Equal($"Request is invalid. Response: {String.Join("\n ", validRequestResponse.MessageStack.ToArray())}", badRequest.Value);
}
// Post tests
[Fact]
public async Task HandleRequestResponsePost_CopyFileRequest_OK()
{
// arrange
var request = new CopyFileRequest()
{
SourcePath = "",
SourceFile = "",
DestinationPath = ""
};
var validRequestResponse = new RequestResponse() { MessageStack = new List<string>(), IsSuccessful = true };
_mockCopyFileService.Setup(service => service.PreQueueValidation(It.IsAny<CopyFileRequest>())).Returns(validRequestResponse);
// act
var result = await _controller.HandleRequestResponse<CopyFileRequest>(request, FileOperationType.Copy, _mockCopyFileService.Object);
Assert.NotNull(result);
var okResult = result as OkResult;
// assert
Assert.NotNull(okResult);
Assert.Equal(200, okResult.StatusCode);
}
// Post tests
[Fact]
public async Task HandleRequestResponsePost_CreateDirectoryRequest_OK()
{
// arrange
var request = new CreateDirectoryRequest()
{
DirectoryName = "",
DirectoryPath = ""
};
var validRequestResponse = new RequestResponse() { MessageStack = new List<string>(), IsSuccessful = true };
_mockCreateDirectoryService.Setup(service => service.PreQueueValidation(It.IsAny<CreateDirectoryRequest>())).Returns(validRequestResponse);
// act
var result = await _controller.HandleRequestResponse<CreateDirectoryRequest>(request, FileOperationType.CreateDirectory,
_mockCreateDirectoryService.Object);
Assert.NotNull(result);
var okResult = result as OkResult;
// assert
Assert.NotNull(okResult);
Assert.Equal(200, okResult.StatusCode);
}
}
@@ -0,0 +1,81 @@
using System;
using Microsoft.AspNetCore.Mvc;
using Moq;
using Xunit;
using LCU.Library.Internal.Exceptions;
using LCU.Api.Internal.FileOperations.Controllers;
using LCU.Library.Internal.FileOperationsModels.Models;
using System.Threading.Tasks;
using LCU.Api.Internal.FileOperations.Services.QueueServices;
namespace LCU.Api.Internal.FileOperationsTests.Controllers
{
public class IndexFileControllerTest
{
private IndexFileController _controller;
private Mock<IQueueFileOperationsService> _mockQueueFileOperationsService;
public IndexFileControllerTest()
{
_mockQueueFileOperationsService = new Mock<IQueueFileOperationsService>();
_controller = new IndexFileController(_mockQueueFileOperationsService.Object);
}
[Fact]
public async Task BatchPdfParser_OK()
{
var request = new ExtractIndexFileDataRequest()
{
IndexFilePath = "\\test\test",
IndexFileName = "Test.csv"
};
_mockQueueFileOperationsService.Setup(service => service.QueueFileOperations(It.IsAny<ExtractIndexFileDataRequest>(), It.IsAny<FileOperationType>())).Verifiable();
var result = await _controller.QueueExtractIndexFileData(request);
Assert.NotNull(result);
var acceptedResult = result as AcceptedResult;
Assert.NotNull(acceptedResult);
Assert.Equal(202, acceptedResult!.StatusCode);
_mockQueueFileOperationsService.Verify();
}
[Fact]
public async Task ExtractIndexFileDataRequest_ServiceException_InternalServerError()
{
var request = new ExtractIndexFileDataRequest()
{
IndexFilePath = "\\test\test",
IndexFileName = "Test.csv"
};
_mockQueueFileOperationsService.Setup(service => service.QueueFileOperations(It.IsAny<ExtractIndexFileDataRequest>(), It.IsAny<FileOperationType>()))
.Throws(new ServiceException("Thrown From Unit Test")).Verifiable();
var result = await _controller.QueueExtractIndexFileData(request);
Assert.NotNull(result);
var statusResult = result as ObjectResult;
Assert.NotNull(statusResult);
Assert.Equal(500, statusResult!.StatusCode);
_mockQueueFileOperationsService.Verify();
}
[Fact]
public async Task ExtractIndexFileDataRequest_UnexpectedException_InternalServerError()
{
var request = new ExtractIndexFileDataRequest()
{
IndexFilePath = "\\test\test",
IndexFileName = "Test.csv"
};
_mockQueueFileOperationsService.Setup(service => service.QueueFileOperations(It.IsAny<ExtractIndexFileDataRequest>(), It.IsAny<FileOperationType>()))
.Throws(new Exception("Thrown From Unit Test")).Verifiable();
var result = await _controller.QueueExtractIndexFileData(request);
Assert.NotNull(result);
var statusResult = result as StatusCodeResult;
Assert.NotNull(statusResult);
Assert.Equal(500, statusResult!.StatusCode);
_mockQueueFileOperationsService.Verify();
}
}
}
@@ -0,0 +1,330 @@
using System;
using Microsoft.AspNetCore.Mvc;
using Moq;
using Xunit;
using LCU.Library.Internal.Exceptions;
using LCU.Api.Internal.FileOperations.Controllers;
using LCU.Api.Internal.FileOperations.Services;
using LCU.Library.Internal.FileOperationsModels.Models;
using System.Threading.Tasks;
using System.Collections.Generic;
using LCU.Library.Internal.FileOperationsModels.Models.HtmlToPdfModels;
using LCU.Api.Internal.FileOperations.Services.QueueServices;
using LCU.Api.Internal.FileOperations.Services.PdfServices;
namespace LCU.Api.Internal.FileOperationsTests.Controllers
{
public class PdfControllerTest
{
private PdfController _pdfController;
private Mock<IQueueFileOperationsService> _mockQueueFileOperationsService;
private Mock<IPdfParserService> _mockPdfParserService;
private Mock<IBatchPdfParserService> _mockBatchPdfParserService;
private Mock<IDirectFileService> _mockDirectFileService;
private Mock<IHtmlToPdfService> _mockHtmlToPdfService;
public PdfControllerTest()
{
_mockQueueFileOperationsService = new Mock<IQueueFileOperationsService>();
_mockPdfParserService = new Mock<IPdfParserService>();
_mockBatchPdfParserService = new Mock<IBatchPdfParserService>();
_mockDirectFileService = new Mock<IDirectFileService>();
_mockHtmlToPdfService = new Mock<IHtmlToPdfService>();
_pdfController = new PdfController(_mockQueueFileOperationsService.Object,
_mockPdfParserService.Object,
_mockBatchPdfParserService.Object,
_mockDirectFileService.Object,
_mockHtmlToPdfService.Object);
}
[Fact]
public async Task BatchPdfParser_OK()
{
var batchPdfParserRequest = new BatchParsePdfRequest()
{
RootPath = "\\test\test",
PdfName = "Test.pdf",
BatchPdfs = new List<BatchPdf>()
{
new BatchPdf
{
PageStart = 1,
PageStop = 2
}
}
};
var requestResponse = new RequestResponse
{
IsSuccessful = true
};
_mockBatchPdfParserService.Setup(service => service.IsRequestValid(batchPdfParserRequest, It.IsAny<RequestResponse>()))
.Returns(requestResponse).Verifiable();
_mockQueueFileOperationsService.Setup(service => service.QueueFileOperations(It.IsAny<BatchParsePdfRequest>(), It.IsAny<FileOperationType>())).Verifiable();
var result = await _pdfController.QueueBatchPdfParser(batchPdfParserRequest);
Assert.NotNull(result);
var acceptedResult = result as AcceptedResult;
Assert.NotNull(acceptedResult);
Assert.Equal(202, acceptedResult!.StatusCode);
_mockBatchPdfParserService.Verify();
_mockQueueFileOperationsService.Verify();
}
[Fact]
public async Task BatchParsePdfRequest_ServiceException_InternalServerError()
{
var batchPdfParserRequest = new BatchParsePdfRequest()
{
RootPath = "\\test\test",
PdfName = "Test.pdf",
BatchPdfs = new List<BatchPdf>()
{
new BatchPdf
{
PageStart = 1,
PageStop = 2
}
}
};
var requestResponse = new RequestResponse
{
IsSuccessful = true
};
_mockBatchPdfParserService.Setup(service => service.IsRequestValid(batchPdfParserRequest, It.IsAny<RequestResponse>()))
.Returns(requestResponse).Verifiable();
_mockQueueFileOperationsService.Setup(service => service.QueueFileOperations(It.IsAny<BatchParsePdfRequest>(), It.IsAny<FileOperationType>()))
.Throws(new ServiceException("Thrown From Unit Test")).Verifiable();
var result = await _pdfController.QueueBatchPdfParser(batchPdfParserRequest);
Assert.NotNull(result);
var statusResult = result as ObjectResult;
Assert.NotNull(statusResult);
Assert.Equal(500, statusResult!.StatusCode);
_mockBatchPdfParserService.Verify();
_mockQueueFileOperationsService.Verify();
}
[Fact]
public async Task BatchParsePdfRequest_UnexpectedException_InternalServerError()
{
var batchPdfParserRequest = new BatchParsePdfRequest()
{
RootPath = "\\test\test",
PdfName = "Test.pdf",
BatchPdfs = new List<BatchPdf>()
{
new BatchPdf
{
PageStart = 1,
PageStop = 2
}
}
};
var requestResponse = new RequestResponse
{
IsSuccessful = true
};
_mockBatchPdfParserService.Setup(service => service.IsRequestValid(batchPdfParserRequest, It.IsAny<RequestResponse>()))
.Returns(requestResponse).Verifiable();
_mockQueueFileOperationsService.Setup(service => service.QueueFileOperations(It.IsAny<BatchParsePdfRequest>(), It.IsAny<FileOperationType>()))
.Throws(new Exception("Thrown From Unit Test")).Verifiable();
var result = await _pdfController.QueueBatchPdfParser(batchPdfParserRequest);
Assert.NotNull(result);
var statusResult = result as StatusCodeResult;
Assert.NotNull(statusResult);
Assert.Equal(500, statusResult!.StatusCode);
_mockBatchPdfParserService.Verify();
_mockQueueFileOperationsService.Verify();
}
[Fact]
public void ParsePdf_OK()
{
var parsePdfRequest = new ParsePdfRequest()
{
RootPath = "\\test\test",
PdfName = "Test.pdf",
PageStart = 1,
PageStop = 2
};
var newPdfResponse = "test.pdf";
_mockPdfParserService.Setup(service => service.ParsePdf(parsePdfRequest)).Returns(newPdfResponse).Verifiable();
var result = _pdfController.ParsePdf(parsePdfRequest);
Assert.NotNull(result);
var okResult = result as OkObjectResult;
Assert.NotNull(okResult);
Assert.Equal(200, okResult!.StatusCode);
_mockPdfParserService.Verify();
}
[Fact]
public void ParsePdf_ServiceException_InternalServerError()
{
var parsePdfRequest = new ParsePdfRequest()
{
RootPath = "\\test\test",
PdfName = "Test.pdf",
PageStart = 1,
PageStop = 2
};
_mockPdfParserService.Setup(service => service.ParsePdf(parsePdfRequest))
.Throws(new ServiceException("Thrown From Unit Test")).Verifiable();
var result = _pdfController.ParsePdf(parsePdfRequest);
Assert.NotNull(result);
var statusResult = result as ObjectResult;
Assert.NotNull(statusResult);
Assert.Equal(500, statusResult!.StatusCode);
_mockPdfParserService.Verify();
}
[Fact]
public void ParsePdf_UnexpectedException_InternalServerError()
{
var parsePdfRequest = new ParsePdfRequest()
{
RootPath = "\\test\test",
PdfName = "Test.pdf",
PageStart = 1,
PageStop = 2
};
_mockPdfParserService.Setup(service => service.ParsePdf(parsePdfRequest))
.Throws(new Exception("Thrown From Unit Test")).Verifiable();
var result = _pdfController.ParsePdf(parsePdfRequest);
Assert.NotNull(result);
var statusResult = result as StatusCodeResult;
Assert.NotNull(statusResult);
Assert.Equal(500, statusResult!.StatusCode);
_mockPdfParserService.Verify();
}
[Fact]
public void GetPdfConent_OK()
{
var pdfPath = "\\\\Test\\PdfPath\\test.pdf";
var btyes = new byte[23122321];
_mockDirectFileService.Setup(service => service.GetFileBytes(pdfPath)).Returns(btyes).Verifiable();
var result = _pdfController.GetPdfContent(pdfPath);
var okResult = result as FileContentResult;
Assert.NotNull(okResult);
_mockDirectFileService.Verify();
}
[Fact]
public void GetPdfConent_UnexpectedException_InternalServerError()
{
var pdfPath = "\\\\Test\\PdfPath\\test.pdf";
_mockDirectFileService.Setup(service => service.GetFileBytes(pdfPath))
.Throws(new Exception("Thrown From Unit Test")).Verifiable();
var result = _pdfController.GetPdfContent(pdfPath);
Assert.NotNull(result);
var statusResult = result as StatusCodeResult;
Assert.NotNull(statusResult);
Assert.Equal(500, statusResult!.StatusCode);
_mockPdfParserService.Verify();
}
[Fact]
public void GetPdfConent_ArgumentException_InternalServerError()
{
var pdfPath = "\\\\Test\\PdfPath\\test.pdf";
_mockDirectFileService.Setup(service => service.GetFileBytes(pdfPath))
.Throws(new ArgumentException("Thrown From Unit Test")).Verifiable();
var result = _pdfController.GetPdfContent(pdfPath);
Assert.NotNull(result);
var statusResult = result as BadRequestObjectResult;
Assert.NotNull(statusResult);
Assert.Equal(400, statusResult!.StatusCode);
_mockPdfParserService.Verify();
}
[Fact]
public void ConvertHtmlToPdf_OK()
{
var htmlToPdfRequest = new HtmlToPdfRequest()
{
HtmlTemplateFilePath = "\\Test",
BodyTagValues = new List<TagValue>
{
new TagValue
{
Tag = "Test Tag",
Value = "Test Value"
}
}
};
var btyes = new byte[23122321];
_mockHtmlToPdfService.Setup(service => service.ConvertHtmlToPdf(htmlToPdfRequest)).Returns(btyes).Verifiable();
var result = _pdfController.ConvertHtmlToPdf(htmlToPdfRequest);
var okResult = result as FileContentResult;
Assert.NotNull(okResult);
_mockDirectFileService.Verify();
}
[Fact]
public void ConvertHtmlToPdf_ServiceExceptionException_InternalServerError()
{
var htmlToPdfRequest = new HtmlToPdfRequest()
{
HtmlTemplateFilePath = "\\Test",
BodyTagValues = new List<TagValue>
{
new TagValue
{
Tag = "Test Tag",
Value = "Test Value"
}
}
};
_mockHtmlToPdfService.Setup(service => service.ConvertHtmlToPdf(htmlToPdfRequest))
.Throws(new ServiceException("Thrown From Unit Test")).Verifiable();
var result = _pdfController.ConvertHtmlToPdf(htmlToPdfRequest);
Assert.NotNull(result);
var statusResult = result as ObjectResult;
Assert.NotNull(statusResult);
Assert.Equal(500, statusResult!.StatusCode);
_mockPdfParserService.Verify();
}
[Fact]
public void GetConvertHtmlToPdf_UnexpectedExceptionException_InternalServerError()
{
var htmlToPdfRequest = new HtmlToPdfRequest()
{
HtmlTemplateFilePath = "\\Test",
BodyTagValues = new List<TagValue>
{
new TagValue
{
Tag = "Test Tag",
Value = "Test Value"
}
}
};
_mockHtmlToPdfService.Setup(service => service.ConvertHtmlToPdf(htmlToPdfRequest))
.Throws(new Exception("Thrown From Unit Test")).Verifiable();
var result = _pdfController.ConvertHtmlToPdf(htmlToPdfRequest);
Assert.NotNull(result);
var statusResult = result as StatusCodeResult;
Assert.NotNull(statusResult);
Assert.Equal(500, statusResult!.StatusCode);
_mockPdfParserService.Verify();
}
}
}
@@ -0,0 +1,21 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0" />
<PackageReference Include="Moq" Version="4.13.0" />
<PackageReference Include="NUnit" Version="3.13.3" />
<PackageReference Include="xunit" Version="2.4.0" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\LCU.Api.Internal.FileOperations\LCU.Api.Internal.FileOperations.csproj" />
</ItemGroup>
</Project>
@@ -0,0 +1,79 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Moq;
using Xunit;
using LCU.Api.Internal.FileOperations.Services;
using LCU.Library.Internal.FileOperationsModels.Models;
namespace LCU.Api.Internal.FileOperationsTests.Services;
public class DirectFileOperationsServiceTest
{
private readonly DirectFileOperationsService _directFileOperationsService;
private Mock<IFileOperationsService> _mockFileOperationsService;
public DirectFileOperationsServiceTest()
{
_mockFileOperationsService = new Mock<IFileOperationsService>();
_directFileOperationsService = new DirectFileOperationsService(_mockFileOperationsService.Object);
}
[Fact]
public async Task HandleDirectFileOperationsRequest_Return_IsSuccessful_True()
{
var validRequestResponse = new RequestResponse() { MessageStack = new List<string>(), IsSuccessful = true };
_mockFileOperationsService.Setup(service => service.PerformFileOperation(It.IsAny<QueueRequest>())).Returns(validRequestResponse);
var request = new MoveFileRequest()
{
SourcePath = "",
SourceFile = "",
DestinationPath = ""
};
// act
var result = await _directFileOperationsService.HandleDirectFileOperationsRequest(request, FileOperationType.Move);
Assert.NotNull(result);
Assert.True(validRequestResponse.IsSuccessful);
_mockFileOperationsService.Verify(service => service.PerformFileOperation(It.IsAny<QueueRequest>()), Times.Once);
}
[Fact]
public async Task HandleDirectFileOperationsRequest_Return_IsSuccessful_False()
{
var validRequestResponse = new RequestResponse() { MessageStack = new List<string> { "test" }, IsSuccessful = false };
_mockFileOperationsService.Setup(service => service.PerformFileOperation(It.IsAny<QueueRequest>())).Returns(validRequestResponse);
var request = new MoveFileRequest()
{
SourcePath = "",
SourceFile = "",
DestinationPath = ""
};
// act
var result = await _directFileOperationsService.HandleDirectFileOperationsRequest(request, FileOperationType.Move);
Assert.NotNull(result);
Assert.False(result.IsSuccessful);
Assert.Single(result.MessageStack);
_mockFileOperationsService.Verify(service => service.PerformFileOperation(It.IsAny<QueueRequest>()), Times.Once);
}
[Fact]
public void HandleDirectFileOperationsRequest_PerformFileOperation_ThrowsException()
{
var validRequestResponse = new RequestResponse() { MessageStack = new List<string>(), IsSuccessful = true };
_mockFileOperationsService.Setup(service => service.PerformFileOperation(It.IsAny<QueueRequest>())).Throws(new Exception("Test"));
var request = new MoveFileRequest()
{
SourcePath = "",
SourceFile = "",
DestinationPath = ""
};
// act
Assert.ThrowsAsync<ArgumentNullException>(async () => await _directFileOperationsService.HandleDirectFileOperationsRequest(request, FileOperationType.Move));
_mockFileOperationsService.Verify(service => service.PerformFileOperation(It.IsAny<QueueRequest>()), Times.Once);
}
}
@@ -0,0 +1,27 @@
using LCU.Api.Internal.FileOperations.Services;
using System;
using Xunit;
namespace LCU.Api.Internal.FileOperationsTests.Services
{
public class DirectFileServiceTest
{
private readonly DirectFileService _directFileService;
public DirectFileServiceTest()
{
_directFileService = new DirectFileService();
}
[Fact]
public void Sir_Throws_A_Lot()
{
Assert.Throws<ArgumentException>(
() => { _directFileService.GetFileBytes(" "); });
Assert.Throws<ArgumentException>(
() => { _directFileService.GetFileBytes("C:\\secret.txt"); });
Assert.Throws<ArgumentException>(
() => { _directFileService.GetFileBytes("asdf"); });
}
}
}
@@ -0,0 +1,126 @@
using Moq;
using Xunit;
using LCU.Api.Internal.FileOperations.Services;
using LCU.Api.Internal.FileOperations.Services.FileActionServices;
using LCU.Library.Internal.FileOperationsModels.Models;
using LCU.Api.Internal.FileOperations.Configurations;
using LCU.Api.Internal.FileOperations.Services.QueueServices;
using LCU.Library.Internal.LCUServiceFactory.Services;
using System;
namespace LCU.Api.Internal.FileOperationsTests.Services;
public class FileOperationsServiceTest
{
private readonly FileOperationsService _fileOperationsService;
private readonly Mock<ILcuServiceFactory<IFileActionService>> _mockServiceFactory;
private Mock<IQueueFileOperationsService> _mockQueueFileOperationsService;
public FileOperationsServiceTest()
{
var apiConfiguration = new ApiConfiguration()
{
AttemptsLimit = 2
};
_mockQueueFileOperationsService = new Mock<IQueueFileOperationsService>();
_mockServiceFactory = new Mock<ILcuServiceFactory<IFileActionService>>();
_fileOperationsService = new FileOperationsService(
_mockQueueFileOperationsService.Object,
apiConfiguration,
_mockServiceFactory.Object);
;
}
[Fact]
public void Basic_Construct_Test()
{
Assert.NotNull(_fileOperationsService);
}
[Fact]
public void ShouldPerformFileOperationsAgain_AttempsLessThenLimit_True()
{
var request = new QueueRequest()
{
Attempts = 0
};
var requestResponse = new RequestResponse()
{
IsSuccessful = false
};
var result = _fileOperationsService.ShouldPerformFileOperationsAgain(request, requestResponse);
Assert.True(result);
}
[Fact]
public void ShouldPerformFileOperationsAgain_AttempsGreaterThenLimit_False()
{
var request = new QueueRequest()
{
Attempts = 3
};
var requestResponse = new RequestResponse()
{
IsSuccessful = false
};
var result = _fileOperationsService.ShouldPerformFileOperationsAgain(request, requestResponse);
Assert.False(result);
}
[Fact]
public void PerformFileOperation_IsSuccessful()
{
QueueRequest request = null;
var result = _fileOperationsService.PerformFileOperation(request);
Assert.NotNull(result);
Assert.Single(result.MessageStack);
Assert.True(result.IsSuccessful);
}
[Fact]
public void PerformFileOperation_NullRequest_IsSuccessful()
{
var request = new QueueRequest()
{
Attempts = 3,
FileOperationType = FileOperationType.Move
};
var response = new RequestResponse();
var mockedFileActionService = new Mock<IFileActionService>();
_mockServiceFactory.Setup(x => x.GetService(request.FileOperationType)).Returns(mockedFileActionService.Object);
mockedFileActionService.Setup(x => x.ExecuteAction(request)).Returns(response);
var result = _fileOperationsService.PerformFileOperation(request);
Assert.NotNull(result);
Assert.Empty(result.MessageStack);
Assert.True(result.IsSuccessful);
}
[Fact]
public void PerformFileOperation_ServiceFactoryException_IsNotSuccessful()
{
var request = new QueueRequest()
{
Attempts = 3,
FileOperationType = FileOperationType.Move
};
var response = new RequestResponse();
var mockedFileActionService = new Mock<IFileActionService>();
_mockServiceFactory.Setup(x => x.GetService(request.FileOperationType)).Throws(new Exception("Failure"));
var result = _fileOperationsService.PerformFileOperation(request);
Assert.NotNull(result);
Assert.Single(result.MessageStack);
Assert.False(result.IsSuccessful);
}
}
@@ -0,0 +1,128 @@
using System.Linq;
using Xunit;
using LCU.Library.Internal.FileOperationsModels.Models;
using LCU.Api.Internal.FileOperations.Validations;
namespace LCU.Api.Internal.FileOperationsTests.Services.Validations;
public class FileValidationTest
{
[Fact]
public void IsSourceEmpty_SourceEmpty_ReturnIsValid_False()
{
// arrange
var sourcePath = "";
var responseRequest = new RequestResponse();
// act
responseRequest = FileValidation.ValidateSourceNotEmpty(sourcePath, responseRequest);
// assert
Assert.False(responseRequest.IsSuccessful);
Assert.Equal("Source is empty and is required.", responseRequest.MessageStack.FirstOrDefault());
}
[Fact]
public void IsSourceEmpty_SourceNotEmpty_ReturnIsValid_True()
{
// arrange
var sourcePath = "TESTSource";
var responseRequest = new RequestResponse();
// act
responseRequest = FileValidation.ValidateSourceNotEmpty(sourcePath, responseRequest);
// assert
Assert.True(responseRequest.IsSuccessful);
Assert.Empty(responseRequest.MessageStack);
}
[Fact]
public void IsDestinationEmpty_DestinationEmpty_ReturnIsValid_False()
{
// arrange
var sourcePath = "";
var responseRequest = new RequestResponse();
// act
responseRequest = FileValidation.ValidateDestinationNotEmpty(sourcePath, responseRequest);
// assert
Assert.False(responseRequest.IsSuccessful);
Assert.Equal("Destination is empty and is required.", responseRequest.MessageStack.FirstOrDefault());
}
[Fact]
public void IsDestinationEmpty_DestinationNotEmpty_ReturnIsValid_True()
{
// arrange
var destinationPath = "TESTDestination";
var responseRequest = new RequestResponse();
// act
responseRequest = FileValidation.ValidateDestinationNotEmpty(destinationPath, responseRequest);
// assert
Assert.True(responseRequest.IsSuccessful);
Assert.Empty(responseRequest.MessageStack);
}
[Fact]
public void IsFilenameEmpty_FilenameEmpty_ReturnIsValid_False()
{
// arrange
var filename = "";
var responseRequest = new RequestResponse();
// act
responseRequest = FileValidation.ValidateFilenameNotEmpty(filename, responseRequest);
// assert
Assert.False(responseRequest.IsSuccessful);
Assert.Equal("Filename is empty and is required.", responseRequest.MessageStack.FirstOrDefault());
}
[Fact]
public void IsFilenameEmpty_FilenameNotEmpty_ReturnIsValid_True()
{
// arrange
var filename = "TESTFilename";
var responseRequest = new RequestResponse();
// act
responseRequest = FileValidation.ValidateDestinationNotEmpty(filename, responseRequest);
// assert
Assert.True(responseRequest.IsSuccessful);
Assert.Empty(responseRequest.MessageStack);
}
[Fact]
public void IsFilenameValid_FilenameNotValid_ReturnIsValid_False()
{
// arrange
var filename = "/**";
var responseRequest = new RequestResponse();
// act
responseRequest = FileValidation.ValidateFilename(filename, responseRequest);
// assert
Assert.False(responseRequest.IsSuccessful);
Assert.Equal("File name is invalid.", responseRequest.MessageStack.FirstOrDefault());
}
[Fact]
public void IsFilenameValid_FilenameValid_ReturnIsValid_True()
{
// arrange
var filename = "TESTFilename";
var responseRequest = new RequestResponse();
// act
responseRequest = FileValidation.ValidateFilename(filename, responseRequest);
// assert
Assert.True(responseRequest.IsSuccessful);
Assert.Empty(responseRequest.MessageStack);
}
}
@@ -0,0 +1,144 @@
using LCU.Library.Internal.FileOperationsModels.Models.NameSettings;
using LCU.Library.Internal.FileOperationsModels.Shared;
using System;
using System.Collections.Generic;
using Xunit;
namespace LCU.Api.Internal.FileOperationsTests.Shared
{
public class DynamicNameBuilderTest
{
public DynamicNameBuilderTest()
{
}
[Fact]
public void EmptyFileNameSettings_Return_FileName()
{
// arrange
var name = "testfile.txt";
var settings = new DynamicNameSetting();
// act
var result = DynamicNameBuilder.BuildDynamicName(name, settings);
// assert
Assert.Equal(name, result);
}
[Fact]
public void NullFileNameSettings_Return_FileName()
{
// arrange
var name = "testfile.txt";
DynamicNameSetting settings = null;
// act
var result = DynamicNameBuilder.BuildDynamicName(name, settings);
// assert
Assert.Equal(name, result);
}
[Fact]
public void Return_FileName_dd_MM()
{
// arrange
var name = "testfile_{TestDate}.txt";
var settings = new DynamicNameSetting();
var dateFormatSetting = new DateFormatSetting();
dateFormatSetting.Tag = "{TestDate}";
dateFormatSetting.DateFormat = "dd_MM";
settings.DateFormatSettings = new List<DateFormatSetting>();
settings.DateFormatSettings.Add(dateFormatSetting);
// act
var result = DynamicNameBuilder.BuildDynamicName(name, settings);
// assert
Assert.Equal($"testfile_{DateTime.Now:dd_MM}.txt", result);
}
[Fact]
public void Minus_One_Day_Return_FileName_dd_MM()
{
// arrange
var name = "testfile_{TestDate}.txt";
var settings = new DynamicNameSetting();
settings.DaysFromToday = -1;
var dateFormatSetting = new DateFormatSetting();
dateFormatSetting.Tag = "{TestDate}";
dateFormatSetting.DateFormat = "dd_MM";
settings.DateFormatSettings = new List<DateFormatSetting>();
settings.DateFormatSettings.Add(dateFormatSetting);
// act
var result = DynamicNameBuilder.BuildDynamicName(name, settings);
// assert
Assert.Equal($"testfile_{DateTime.Now.AddDays(-1):dd_MM}.txt", result);
}
[Fact]
public void Multiple_Formats_sepratedby_dashs_Return_FileName_dd_MM_yyyy()
{
// arrange
var name = "testfile_{TestDate}-{TestDate2}-{TestDate3}.txt";
var settings = new DynamicNameSetting();
settings.DateFormatSettings = new List<DateFormatSetting>();
var dateFormatSetting1 = new DateFormatSetting();
dateFormatSetting1.Tag = "{TestDate}";
dateFormatSetting1.DateFormat = "dd";
settings.DateFormatSettings.Add(dateFormatSetting1);
var dateFormatSetting2 = new DateFormatSetting();
dateFormatSetting2.Tag = "{TestDate2}";
dateFormatSetting2.DateFormat = "MM";
settings.DateFormatSettings.Add(dateFormatSetting2);
var dateFormatSetting3 = new DateFormatSetting();
dateFormatSetting3.Tag = "{TestDate3}";
dateFormatSetting3.DateFormat = "yyyy";
settings.DateFormatSettings.Add(dateFormatSetting3);
// act
var result = DynamicNameBuilder.BuildDynamicName(name, settings);
// assert
Assert.Equal($"testfile_{DateTime.Now:dd}-{DateTime.Now:MM}-{DateTime.Now:yyyy}.txt", result);
}
[Fact]
public void Multiple_Formats_nosepration_Return_FileName_ddMMyyyy()
{
// arrange
var fileName = "testfile_{TestDate}{TestDate2}{TestDate3}.txt";
var settings = new DynamicNameSetting();
settings.DateFormatSettings = new List<DateFormatSetting>();
var dateFormatSetting1 = new DateFormatSetting();
dateFormatSetting1.Tag = "{TestDate}";
dateFormatSetting1.DateFormat = "dd";
settings.DateFormatSettings.Add(dateFormatSetting1);
var dateFormatSetting2 = new DateFormatSetting();
dateFormatSetting2.Tag = "{TestDate2}";
dateFormatSetting2.DateFormat = "MM";
settings.DateFormatSettings.Add(dateFormatSetting2);
var dateFormatSetting3 = new DateFormatSetting();
dateFormatSetting3.Tag = "{TestDate3}";
dateFormatSetting3.DateFormat = "yyyy";
settings.DateFormatSettings.Add(dateFormatSetting3);
// act
var result = DynamicNameBuilder.BuildDynamicName(fileName, settings);
// assert
Assert.Equal($"testfile_{DateTime.Now:dd}{DateTime.Now:MM}{DateTime.Now:yyyy}.txt", result);
}
}
}
@@ -0,0 +1,90 @@
using LCU.Library.Internal.FileOperationsModels.Models.NameSettings;
using LCU.Library.Internal.FileOperationsModels.Shared;
using System.Collections.Generic;
using Xunit;
namespace LCU.Api.Internal.FileOperationsTests.Shared
{
public class RegexNameHandlerTest
{
[Fact]
public void BuildFileList_NoRegex_Return_SingleFileName()
{
// arrange
var name = "testfile.txt";
var path = "\\TEST";
var settings = new DynamicNameSetting();
// act
var result = RegexNameHandler.BuildFileList(path, name, settings);
// assert
Assert.Single(result);
}
[Fact]
public void BuildRegexName_Return_FileName_OneRegex_Replaced()
{
// arrange
var name = "testfile_{Regex01}.txt";
var settings = new DynamicNameSetting();
settings.RegexSettings = new List<RegexSetting>();
var regexTest = new RegexSetting()
{
Tag = "{Regex01}",
Regex = "\\d*"
};
settings.RegexSettings.Add(regexTest);
// act
var result = RegexNameHandler.BuildRegexName(name, settings);
// assert
Assert.Equal("testfile_\\d*.txt", result.ToString());
}
[Fact]
public void BuildRegexName_Return_FileName_TwoRegex_Replaced()
{
// arrange
var name = "testfile_{Regex01}_Test_{Regex02}.txt";
var settings = new DynamicNameSetting();
settings.RegexSettings = new List<RegexSetting>();
var regexTest1 = new RegexSetting()
{
Tag = "{Regex01}",
Regex = "\\d*"
};
settings.RegexSettings.Add(regexTest1);
var regexTest2 = new RegexSetting()
{
Tag = "{Regex02}",
Regex = "\\w*"
};
settings.RegexSettings.Add(regexTest2);
// act
var result = RegexNameHandler.BuildRegexName(name, settings);
// assert
Assert.Equal("testfile_\\d*_Test_\\w*.txt", result.ToString());
}
[Fact]
public void ReplaceTagWithRegex_Return_FileName_OneRegex_Replaced()
{
// arrange
var name = "testfile_{Regex01}.txt";
var tag = "{Regex01}";
var regex = "\\d*";
// act
var result = RegexNameHandler.ReplaceTagWithRegex(name, tag, regex);
// assert
Assert.Equal("testfile_\\d*.txt", result);
}
}
}
@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- additional settings used during the dotnet test execution step in the azure dev ops pipeline -->
<RunSettings>
<DataCollectionRunSettings>
<DataCollectors>
<DataCollector friendlyName="Code Coverage" uri="datacollector://Microsoft/CodeCoverage/2.0" assemblyQualifiedName="Microsoft.VisualStudio.Coverage.DynamicCoverageDataCollector, Microsoft.VisualStudio.TraceCollector, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<Configuration>
<CodeCoverage>
<CompanyNames>
<Exclude>
<CompanyName>.*microsoft.*</CompanyName>
</Exclude>
</CompanyNames>
</CodeCoverage>
</Configuration>
</DataCollector>
</DataCollectors>
</DataCollectionRunSettings>
</RunSettings>
@@ -0,0 +1,71 @@
using System.Collections.Generic;
namespace LCU.Library.Internal.FileOperationsModels.Constants;
public static class IndexEvaluationRequestVariablesConsts
{
public static readonly List<string> IndexEvaluationRequestVariablesConstValues = new()
{
InputFieldZero,
InputFieldOne,
InputFieldTwo,
InputFieldThree,
InputFieldFour,
InputFieldFive,
InputFieldSix,
InputFieldSeven,
InputFieldEight,
InputFieldNine,
InputFieldTen,
InputFieldEleven,
InputFieldTwelve,
InputFieldThirteen,
InputFieldFourteen,
InputFieldFifteen,
InputFieldSixteen,
InputFieldSeventeen,
InputFieldEighteen,
InputFieldNineteen,
InputFieldTwenty,
InputFieldTwentyOne,
InputFieldTwentyTwo,
InputFieldTwentyThree,
InputFieldTwentyFour,
InputFieldTwentyFive,
InputFieldTwentySix,
InputFieldTwentySeven,
InputFieldTwentyEight,
InputFieldTwentyNine
};
public const string InputFieldZero = "InputFieldZero";
public const string InputFieldOne = "InputFieldOne";
public const string InputFieldTwo = "InputFieldTwo";
public const string InputFieldThree = "InputFieldThree";
public const string InputFieldFour = "InputFieldFour";
public const string InputFieldFive = "InputFieldFive";
public const string InputFieldSix = "InputFieldSix";
public const string InputFieldSeven = "InputFieldSeven";
public const string InputFieldEight = "InputFieldEight";
public const string InputFieldNine = "InputFieldNine";
public const string InputFieldTen = "InputFieldTen";
public const string InputFieldEleven = "InputFieldEleven";
public const string InputFieldTwelve = "InputFieldTwelve";
public const string InputFieldThirteen = "InputFieldThirteen";
public const string InputFieldFourteen = "InputFieldFourteen";
public const string InputFieldFifteen = "InputFieldFifteen";
public const string InputFieldSixteen = "InputFieldSixteen";
public const string InputFieldSeventeen = "InputFieldSeventeen";
public const string InputFieldEighteen = "InputFieldEighteen";
public const string InputFieldNineteen = "InputFieldNineteen";
public const string InputFieldTwenty = "InputFieldTwenty";
public const string InputFieldTwentyOne = "InputFieldTwentyOne";
public const string InputFieldTwentyTwo = "InputFieldTwentyTwo";
public const string InputFieldTwentyThree = "InputFieldTwentyThree";
public const string InputFieldTwentyFour = "InputFieldTwentyFour";
public const string InputFieldTwentyFive = "InputFieldTwentyFive";
public const string InputFieldTwentySix = "InputFieldTwentySix";
public const string InputFieldTwentySeven = "InputFieldTwentySeven";
public const string InputFieldTwentyEight = "InputFieldTwentyEight";
public const string InputFieldTwentyNine = "InputFieldTwentyNine";
}
@@ -0,0 +1,12 @@
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
namespace LCU.Library.Internal.FileOperationsModels.Enums;
public enum Delimiters
{
[Display(Name = ",")]
Comma,
[Display(Name = "|")]
Pipe
}
@@ -0,0 +1,17 @@
using System.ComponentModel.DataAnnotations;
namespace LCU.Library.Internal.FileOperationsModels.Enums;
public enum FileSizeTypes
{
[Display(Name = "bytes")]
Byte = 0,
[Display(Name = "KB")]
Kilobyte = 1,
[Display(Name = "MB")]
Megabyte = 2,
[Display(Name = "GB")]
Gigabyte = 3,
[Display(Name = "TB")]
Terabyte = 4
}
@@ -0,0 +1,16 @@
using System.ComponentModel.DataAnnotations;
namespace LCU.Library.Internal.FileOperationsModels.Enums;
public enum OperatorTypes
{
[Display(Name = "=")]
Equals = 0,
[Display(Name = ">")]
GreaterThan = 1,
[Display(Name = "=>")]
GreaterThanEquals = 2,
[Display(Name = "<")]
LessThan = 3,
[Display(Name = "<=")]
LessThanEquals = 4
}
@@ -0,0 +1,119 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0; netstandard2.1; net6.0; net8.0</TargetFrameworks>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<LangVersion>latest</LangVersion>
<Version>4.1.5</Version>
<Description>
2.0.0 - Addition of ReturnResponse and QueueReturnResponse from the LCU.Library.Internal.ApiResponse
2.1.0 - Upgrade of ApiResponse and QueueLib Version
2.2.0 - Addition of ZipDirectoryRequest
3.0.0 - Creation of FileNameSettings and adding it to copy, delete, move, and rename models.
3.1.0 - Added CreateDirectory and RenameDirectory request.
3.2.0 - Addition of the RegexSettings for the Copy, Delete, and Move file operation.
3.3.0 - Added NameSettings for RenameFile NewFileName field.
3.4.0 - Fix to check for no Regex settings. Addition of NoFilesExist validation.
3.6.0 - New BulkOperationsRequest
3.7.0 - MoveFileRequest and CopyFileRequest now use FileRequest. Added generic method to BuildListOfRequest
3.7.1 - Added DynamicfileListRequest model.
3.8.0 - Upgrade of ApiResponse and QueueLib.
3.9.0 - New UnzipFile functionality.
3.10.0 - Dynamic Zip and Unzip Functionality.
3.11.0 - Add File Data Encryption/Decryption Actions.
3.12.0 - Add SucceedOnError to Copy/Rename/Move/Delete File
3.13.0 - Additions to RequestResponse, Added netstandard2.1 and net6.0, fix for regex directory name builder, and changed validation to return RequestResponse
3.14.0 - Upgrade ApiResponse Models Library
3.15.0 - Upgrade ApiResponse to use newest models version. With queueName obsolete.
3.16.0 - Add Modify File Model.
3.17.0 - Addition of ParsePdfRequest and moving FileRequestValidation to Obsolete as it should not be used by outside apis.
3.18.0 - New UnzipPasswordProtectedFile functionality.
3.19.0 - Add DynamicDate Source/Destination paths for Unzip and UnzipPasswordProtected. Added BuildDynamicDirectoryList functionality.
3.20.0 - Add UseZipFileNameAsFinalDestination Property to the UnzipFileRequest model
3.21.0 - Add BatchParsePdfRequest
3.22.0 - Add WriteFileRequest
3.23.0 - Add DeleteDirectoryRequest
3.24.0 - Alter ModifyFile to change extensions
3.25.0 - Add ValidateFileRequest
3.26.0 - Removed SucceedOnError field from ValidateFileRequest
3.27.0 - Added values to UnzipFileRequest model to handle flattening file structure
3.28.0 - Added ExcelModels
3.29.0 - ExcelModels modifications for the use of OpenXml enhancment
3.30.0 - Added MaxAmountOfFiles field to ModifyFileRequest
3.30.1 - Added HtmlToPdfModels
3.30.2 - Add AppendFile
3.30.3 - Add ExtractIndexFileData
3.30.4 - Edit IndexEvaluationRequest
3.30.5 - Upgrade NuGets
3.30.6 - Change ExcelDataRequest.FilePath to ExcelDataRequest.FileContent
3.31.0 - Upgrade to dotnet8
4.0.0 - Updated project name
4.1.1 - Added DeleteEmptyDirectoryRequest
4.1.2 - Added ValidateFizeSizeInRangeRequest and FileSiseRequest
4.1.3 - Update FileSourceRequest
4.1.4 - Update ValidateFileRequest to add CheckFileCount Property and added new enum OperatorTypes
4.1.5 - QueueRequest update to add ReturnResponse
</Description>
<PackageReleaseNotes>
2.0.0 - Addition of ReturnResponse and QueueReturnResponse from the LCU.Library.Internal.ApiResponse
2.1.0 - Upgrade of ApiResponse and QueueLib Version
2.2.0 - Addition of ZipDirectoryRequest
3.0.0 - Creation of FileNameSettings and adding it to copy, delete, move, and rename models.
3.1.0 - Added CreateDirectory and RenameDirectory request.
3.2.0 - Addition of the RegexSettings for the Copy, Delete, and Move file operation.
3.3.0 - Added NameSettings for RenameFile NewFileName field.
3.4.0 - Fix to check for no Regex settings. Addition of NoFilesExist validation.
3.6.0 - New BulkOperationsRequest
3.7.0 - MoveFileRequest and CopyFileRequest now use FileRequest. Added generic method to BuildListOfRequest
3.7.1 - Added DynamicfileListRequest model.
3.8.0 - Upgrade of ApiResponse and QueueLib.
3.9.0 - New UnzipFile functionality.
3.10.0 - Dynamic Zip and Unzip Functionality.
3.11.0 - Add File Data Encryption/Decryption Actions.
3.12.0 - Add SucceedOnError to Copy/Rename/Move/Delete File
3.13.0 - Additions to RequestResponse, Added netstandard2.1 and net6.0, fix for regex directory name builder, and changed validation to return RequestResponse
3.14.0 - Upgrade ApiResponse Models Library
3.15.0 - Upgrade ApiResponse to use newest models version. With queueName obsolete.
3.16.0 - Add Modify File Model.
3.17.0 - Addition of ParsePdfRequest and moving FileRequestValidation to Obsolete as it should not be used by outside apis.
3.18.0 - New UnzipPasswordProtectedFile functionality.
3.19.0 - Add DynamicDate Source/Destination paths for Unzip and UnzipPasswordProtected. Added BuildDynamicDirectoryList functionality.
3.20.0 - Add UseZipFileNameAsFinalDestination Property to the UnzipFileRequest model
3.21.0 - Add BatchParsePdfRequest
3.22.0 - Add WriteFileRequest
3.23.0 - Add DeleteDirectoryRequest
3.24.0 - Alter ModifyFile to change extensions
3.25.0 - Add ValidateFileRequest
3.26.0 - Removed SucceedOnError field from ValidateFileRequest
3.27.0 - Added values to UnzipFileRequest model to handle flattening file structure
3.28.0 - Added ExcelModels
3.29.0 - ExcelModels modifications for the use of OpenXml enhancment
3.30.0 - Added MaxAmountOfFiles field to ModifyFileRequest
3.30.1 - Added HtmlToPdfModels
3.30.2 - Add AppendFile
3.30.3 - Add ExtractIndexFileData
3.30.4 - Edit IndexEvaluationRequest
3.30.5 - Upgrade NuGets
3.30.6 - Change ExcelDataRequest.FilePath to ExcelDataRequest.FileContent
3.31.0 - Upgrade to dotnet8
4.0.0 - Updated project name
4.1.1 - Added DeleteEmptyDirectoryRequest
4.1.2 - Added ValidateFizeSizeInRangeRequest and FileSiseRequest
4.1.3 - Update FileSourceRequest
4.1.4 - Update ValidateFileRequest to add CheckFileCount Property and added new enum OperatorTypes
4.1.5 - QueueRequest update to add ReturnResponse
</PackageReleaseNotes>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="LCU.Library.Internal.ApiResponse.Models" Version="3.3.0" />
<PackageReference Include="LCU.Library.Internal.LcuEvaluationModels" Version="2.0.0" />
<PackageReference Include="LCU.Library.Internal.LcuMassTransit" Version="1.0.0" />
<PackageReference Include="LCU.Library.Internal.LcuMassTransitModels" Version="1.0.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="Serilog" Version="2.10.0" />
<PackageReference Include="SharpZipLib" Version="1.3.3" />
<PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" />
</ItemGroup>
</Project>
@@ -0,0 +1,40 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.ComponentModel.DataAnnotations;
using System.Text;
using LCU.Library.Internal.ApiResponse.Models;
namespace LCU.Library.Internal.FileOperationsModels.Models
{
public class AppendFileRequest : ReturnResponse
{
[Required(ErrorMessage = "Destination path is required.")]
public string DestinationPath { get; set; }
[Required(ErrorMessage = "FileName is required.")]
public string FileName { get; set; }
[Required(ErrorMessage = "Extension is required.")]
public string Extension { get; set; }
[Required(ErrorMessage = "FileData is required.")]
public string FileData { get; set; }
[NotMapped]
public string FullFilePath
{
get
{
return DestinationPath.EndsWith("\\") ? $"{DestinationPath}{FileNameWithExtension}" : $"{DestinationPath}\\{FileNameWithExtension}";
}
}
[NotMapped]
public string FileNameWithExtension
{
get
{
return Extension.StartsWith(".") ? $"{FileName}{Extension}" : $"{FileName}.{Extension}";
}
}
}
}
@@ -0,0 +1,64 @@
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using LCU.Library.Internal.ApiResponse.Models;
namespace LCU.Library.Internal.FileOperationsModels.Models
{
public class BatchParsePdfRequest : ReturnResponse
{
private string rootPath;
[Required(AllowEmptyStrings = false)]
public string RootPath
{
get
{
return rootPath;
}
set
{
rootPath = string.IsNullOrWhiteSpace(value) || value.EndsWith("\\") ? value : $"{value}\\";
}
}
[Required(AllowEmptyStrings = false)]
public string PdfName { get; set; }
public List<BatchPdf> BatchPdfs { get; set; }
[NotMapped]
public string FullPdfPath
{
get
{
return RootPath + PdfName;
}
}
}
public class BatchPdf
{
private string parsedPdfname;
[Required]
[Range(1, int.MaxValue, ErrorMessage = "PageStart must be larger then 0.")]
public int PageStart { get; set; }
[Required]
[Range(1, int.MaxValue, ErrorMessage = "PageStop must be larger then 0.")]
public int PageStop { get; set; }
public string ParsedPdfname
{
get
{
return parsedPdfname;
}
set
{
parsedPdfname = value.ToLower().EndsWith(".pdf") || string.IsNullOrWhiteSpace(value) ? value : $"{value}.pdf";
}
}
}
}
@@ -0,0 +1,10 @@
using System.Collections.Generic;
using LCU.Library.Internal.ApiResponse.Models;
namespace LCU.Library.Internal.FileOperationsModels.Models
{
public class BulkOperationRequest<TRequest> : ReturnResponse
{
public List<TRequest> OperationRequests { get; set; }
}
}
@@ -0,0 +1,7 @@
namespace LCU.Library.Internal.FileOperationsModels.Models
{
public class CopyFileRequest : FileRequest
{
}
}
@@ -0,0 +1,38 @@
using LCU.Library.Internal.ApiResponse.Models;
using LCU.Library.Internal.FileOperationsModels.Models.NameSettings;
using LCU.Library.Internal.FileOperationsModels.Shared;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace LCU.Library.Internal.FileOperationsModels.Models
{
public class CreateDirectoryRequest : ReturnResponse
{
[Required(ErrorMessage = "Directory name is required.")]
public string DirectoryName { get; set; }
[Required(ErrorMessage = "Directory path is required")]
public string DirectoryPath { get; set; }
public DynamicNameSetting NameSetting { get; set; }
[NotMapped]
public string FinalDirectoryName
{
get
{
return DynamicNameBuilder.BuildDynamicName(DirectoryName, NameSetting);
}
}
[NotMapped]
public string DirectoryDestination
{
get
{
var finalDestinationPath = DirectoryPath.EndsWith("\\") ? DirectoryPath : $"{DirectoryPath}\\";
return $"{finalDestinationPath}{FinalDirectoryName}";
}
}
}
}
@@ -0,0 +1,72 @@
using LCU.Library.Internal.ApiResponse.Models;
using LCU.Library.Internal.FileOperationsModels.Models.NameSettings;
using LCU.Library.Internal.FileOperationsModels.Shared;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.IO;
namespace LCU.Library.Internal.FileOperationsModels.Models
{
public class DecryptFileDataRequest : ReturnResponse
{
[Required(ErrorMessage = "Source path is required")]
public string SourcePath { get; set; }
[Required(ErrorMessage = "Source file is required")]
public string SourceFile { get; set; }
[Required(ErrorMessage = "Key source path is required")]
public string KeySourcePath { get; set; }
[Required(ErrorMessage = "Key source file is required")]
public string KeySourceFile { get; set; }
[Required(ErrorMessage = "PassPhrase is required")]
public string PassPhrase { get; set; }
[Required(ErrorMessage = "Destination path is required.")]
public string DestinationPath { get; set; }
public string DestinationFile { get; set; }
public bool Overwrite { get; set; }
public DynamicNameSetting FileNameSetting { get; set; }
[NotMapped] public string FinalSourceFile => DynamicNameBuilder.BuildDynamicName(SourceFile, FileNameSetting);
[NotMapped]
public string Source
{
get
{
var finalSourcePath = SourcePath.EndsWith("\\") ? SourcePath : $"{SourcePath}\\";
finalSourcePath = Path.Combine(finalSourcePath, FinalSourceFile);
return finalSourcePath;
}
}
[NotMapped]
public string Destination
{
get
{
var finalDestinationPath = DestinationPath.EndsWith("\\") ? DestinationPath : $"{DestinationPath}\\";
var finalDestinationFileName = string.IsNullOrWhiteSpace(DestinationFile) ? SourceFile : DestinationFile;
finalDestinationPath = Path.Combine(finalDestinationPath, Path.GetFileNameWithoutExtension(finalDestinationFileName));
return finalDestinationPath;
}
}
[NotMapped]
public string KeySource
{
get
{
var finalKeyPath = KeySourcePath.EndsWith("\\") ? KeySourcePath : $"{KeySourcePath}\\";
finalKeyPath = Path.Combine(finalKeyPath, KeySourceFile);
return finalKeyPath;
}
}
}
}
@@ -0,0 +1,42 @@
using LCU.Library.Internal.ApiResponse.Models;
using LCU.Library.Internal.FileOperationsModels.Models.NameSettings;
using LCU.Library.Internal.FileOperationsModels.Shared;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace LCU.Library.Internal.FileOperationsModels.Models
{
public class DeleteDirectoryRequest : ReturnResponse
{
[Required(ErrorMessage = "Directory name is required.")]
public string DirectoryName { get; set; }
[Required(ErrorMessage = "Directory path is required")]
public string DirectoryRootPath { get; set; }
[Range(0, 25, ErrorMessage = "MaxAmountOfDirectories must be between {1} and {2}.")]
public int MaxAmountOfDirectories { get; set; } = 0;
public bool Recursive { get; set; }
public DynamicNameSetting DirectoryNameSettings { get; set; }
[NotMapped]
public string FinalDirectoryName
{
get
{
return DynamicNameBuilder.BuildDynamicName(DirectoryName, DirectoryNameSettings);
}
}
[NotMapped]
public string FinalDirectoryPath
{
get
{
return $"{DirectoryRootPath}\\{FinalDirectoryName}";
}
}
}
}
@@ -0,0 +1,37 @@
using System.ComponentModel.DataAnnotations.Schema;
using System.ComponentModel.DataAnnotations;
using LCU.Library.Internal.FileOperationsModels.Models.NameSettings;
using LCU.Library.Internal.FileOperationsModels.Shared;
using LCU.Library.Internal.ApiResponse.Models;
namespace LCU.Library.Internal.FileOperationsModels.Models
{
public class DeleteEmptyDirectoryRequest : ReturnResponse
{
[Required(ErrorMessage = "Sub directory path is required.")]
public string SubDirectoryPath { get; set; }
[Required(ErrorMessage = "Dynamic directory name is required")]
public string DynamicDirectoryName { get; set; }
public DynamicNameSetting DirectoryNameSettings { get; set; }
[NotMapped]
public string FinalDirectoryName
{
get
{
return DynamicNameBuilder.BuildDynamicName(DynamicDirectoryName, DirectoryNameSettings);
}
}
[NotMapped]
public string FinalDirectoryPath
{
get
{
return SubDirectoryPath.EndsWith("\\") ? $"{SubDirectoryPath}{FinalDirectoryName}" : $"{SubDirectoryPath}\\{FinalDirectoryName}";
}
}
}
}
@@ -0,0 +1,39 @@
using LCU.Library.Internal.ApiResponse.Models;
using LCU.Library.Internal.FileOperationsModels.Models.NameSettings;
using LCU.Library.Internal.FileOperationsModels.Shared;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace LCU.Library.Internal.FileOperationsModels.Models
{
public class DeleteFileRequest : ReturnResponse
{
[Required(ErrorMessage = "Source path is required")]
public string SourcePath { get; set; }
[Required(ErrorMessage = "Source file is required")]
public string SourceFile { get; set; }
public DynamicNameSetting FileNameSetting { get; set; }
public bool SucceedOnError { get; set; }
[NotMapped]
public string FinalSourceFile
{
get
{
return DynamicNameBuilder.BuildDynamicName(SourceFile, FileNameSetting);
}
}
[NotMapped]
public string Source
{
get
{
var finalSourcePath = SourcePath.EndsWith("\\") ? SourcePath : $"{SourcePath}\\";
return finalSourcePath + FinalSourceFile;
}
}
}
}
@@ -0,0 +1,14 @@
using LCU.Library.Internal.FileOperationsModels.Models.NameSettings;
using System.ComponentModel.DataAnnotations;
namespace LCU.Library.Internal.FileOperationsModels.Models
{
public class DynamicDirectoryListRequest
{
[Required(ErrorMessage = "Path is required")]
public string Path { get; set; }
[Required(ErrorMessage = "Dynamic Directory Name is required")]
public string DynamicDirectoryName { get; set; }
public DynamicNameSetting DynamicFileSettings { get; set; }
}
}
@@ -0,0 +1,11 @@
using LCU.Library.Internal.FileOperationsModels.Models.NameSettings;
namespace LCU.Library.Internal.FileOperationsModels.Models
{
public class DynamicFileListRequest
{
public string Path { get; set; }
public string Filename { get; set; }
public DynamicNameSetting DynamicFileSettings { get; set; }
}
}

Some files were not shown because too many files have changed in this diff Show More