From 5184d24667a22c9109ba297199028f90ddec8f90 Mon Sep 17 00:00:00 2001 From: Riku Virtanen Date: Tue, 12 Sep 2023 15:54:51 +0300 Subject: [PATCH 1/6] Added certification search --- Frends.FTP.UploadFiles/CHANGELOG.md | 4 + .../Definitions/FileTransporter.cs | 766 +++++++++--------- .../Frends.FTP.UploadFiles.csproj | 2 +- 3 files changed, 397 insertions(+), 375 deletions(-) diff --git a/Frends.FTP.UploadFiles/CHANGELOG.md b/Frends.FTP.UploadFiles/CHANGELOG.md index 44501fa..047389b 100644 --- a/Frends.FTP.UploadFiles/CHANGELOG.md +++ b/Frends.FTP.UploadFiles/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## [1.0.3] - 2023-099-12 +### Added +- Added search for local certificates from machine certification store. + ## [1.0.2] - 2023-08-03 ### Added - Operations log improvements. diff --git a/Frends.FTP.UploadFiles/Frends.FTP.UploadFiles/Definitions/FileTransporter.cs b/Frends.FTP.UploadFiles/Frends.FTP.UploadFiles/Definitions/FileTransporter.cs index 8adb481..03804dc 100644 --- a/Frends.FTP.UploadFiles/Frends.FTP.UploadFiles/Definitions/FileTransporter.cs +++ b/Frends.FTP.UploadFiles/Frends.FTP.UploadFiles/Definitions/FileTransporter.cs @@ -1,375 +1,393 @@ -using FluentFTP; -using Frends.FTP.UploadFiles.Enums; -using Frends.FTP.UploadFiles.Logging; -using Frends.FTP.UploadFiles.TaskConfiguration; -using Frends.FTP.UploadFiles.TaskResult; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Net.Security; -using System.Net.Sockets; -using System.Security.Cryptography.X509Certificates; -using System.Text; -using System.Threading; - -namespace Frends.FTP.UploadFiles.Definitions -{ - /// - /// Main class for FTP file transfers - /// - internal class FileTransporter - { - private readonly IFtpLogger _logger; - private readonly BatchContext _batchContext; - private readonly string[] _filePaths; - private readonly RenamingPolicy _renamingPolicy; - private readonly string _sourceDirectoryWithMacrosExpanded; - private readonly string _destinationDirectoryWithMacrosExpanded; - - public FileTransporter(IFtpLogger logger, BatchContext context, Guid instanceId) - { - _logger = logger; - _batchContext = context; - _renamingPolicy = new RenamingPolicy(_batchContext.Info.TransferName, instanceId); - - _sourceDirectoryWithMacrosExpanded = - _renamingPolicy.ExpandDirectoryForMacros(_batchContext.Source.Directory); - _destinationDirectoryWithMacrosExpanded = - _renamingPolicy.ExpandDirectoryForMacros(_batchContext.Destination.Directory); - - Result = new List(); - _filePaths = ConvertObjectToStringArray(context.Source.FilePaths); - } - - private List Result { get; } - - public FileTransferResult Run(CancellationToken cancellationToken) - { - var userResultMessage = ""; - try - { - // Fetch source file info and check if files were returned. - var (files, success) = GetSourceFiles(); - - // If source directory doesn't exist, modify userResultMessage accordingly. - if (!success) - { - userResultMessage = $"Directory '{_sourceDirectoryWithMacrosExpanded}' doesn't exist."; - _logger.NotifyError(_batchContext, userResultMessage, new Exception(userResultMessage)); - return FormFailedFileTransferResult(userResultMessage); - } - - if (files == null || !files.Any()) - { - if (files == null) - _logger.NotifyInformation(_batchContext, - "Source end point returned null list for file list. If there are no files to transfer, the result should be an empty list."); - - var noSourceResult = NoSourceOperation(_batchContext, _batchContext.Source); - Result.Add(noSourceResult); - } - else - { - using (var client = CreateFtpClient(_batchContext.Connection)) - { - client.Connect(); - - if (!client.IsConnected) - { - _logger.NotifyError(_batchContext, "Error while connecting to destination: ", new Exception(userResultMessage)); - return FormFailedFileTransferResult(userResultMessage); - } - - // Check does the destination directory exists. - if (!client.DirectoryExists(_destinationDirectoryWithMacrosExpanded)) - { - if (_batchContext.Options.CreateDestinationDirectories) - { - try - { - CreateAllDirectories(client, _destinationDirectoryWithMacrosExpanded); - } - catch (Exception ex) - { - userResultMessage = $"Error while creating destination directory '{_destinationDirectoryWithMacrosExpanded}': {ex.Message}"; - _logger.NotifyError(_batchContext, userResultMessage, new Exception(userResultMessage)); - return FormFailedFileTransferResult(userResultMessage); - } - } - else - { - userResultMessage = $"Destination directory '{_destinationDirectoryWithMacrosExpanded}' was not found."; - _logger.NotifyError(_batchContext, userResultMessage, new Exception(userResultMessage)); - return FormFailedFileTransferResult(userResultMessage); - } - } - - client.SetWorkingDirectory(_destinationDirectoryWithMacrosExpanded); - - //_batchContext.DestinationFiles = client.GetListing("."); - - foreach (var file in files) - { - // Check that the connection is alive and if not try to connect again - if (!client.IsConnected) - { - client.Connect(); - _logger.NotifyInformation(_batchContext, "Reconnected."); - } - - cancellationToken.ThrowIfCancellationRequested(); - var singleTransfer = new SingleFileTransfer(file, _batchContext, client, _renamingPolicy, _logger); - var result = singleTransfer.TransferSingleFile(); - Result.Add(result); - } - client.Disconnect(); - } - } - } - catch (SocketException) - { - userResultMessage = $"Unable to establish the socket: No such host is known."; - _logger.NotifyError(_batchContext, userResultMessage, new Exception(userResultMessage)); - return FormFailedFileTransferResult(userResultMessage); - } - - return FileTransporter.FormResultFromSingleTransferResults(Result); - } - - #region Helper methods - private static FtpClient CreateFtpClient(Connection connect) - { - var client = new FtpClient(connect.Address, connect.Port, connect.UserName, connect.Password); - switch (connect.SslMode) - { - case FtpsSslMode.None: - client.EncryptionMode = FtpEncryptionMode.None; - break; - case FtpsSslMode.Implicit: - client.EncryptionMode = FtpEncryptionMode.Implicit; - break; - case FtpsSslMode.Explicit: - client.EncryptionMode = FtpEncryptionMode.Explicit; - break; - case FtpsSslMode.Auto: - client.EncryptionMode = FtpEncryptionMode.Auto; - break; - default: - throw new ArgumentOutOfRangeException(); - } - - if (connect.UseFTPS) - { - if (connect.EnableClientAuth) - client.ClientCertificates.Add(new X509Certificate2(connect.ClientCertificatePath)); - - client.ValidateCertificate += (control, e) => - { - // If cert is valid and such - go on and accept - if (e.PolicyErrors == SslPolicyErrors.None) - { - e.Accept = true; - return; - } - - // Accept if we want to accept a certain hash - e.Accept = e.Certificate.GetCertHashString() == connect.CertificateHashStringSHA1; - }; - - client.ValidateAnyCertificate = connect.ValidateAnyCertificate; - client.DataConnectionEncryption = connect.SecureDataChannel; - } - - client.NoopInterval = connect.KeepConnectionAliveInterval; - - if (!string.IsNullOrWhiteSpace(connect.Encoding)) client.Encoding = Encoding.GetEncoding(connect.Encoding); - - // Client lib timeout is in milliseconds, ours is in seconds, thus *1000 conversion - client.ConnectTimeout = connect.ConnectionTimeout * 1000; - client.LocalFileBufferSize = connect.BufferSize; - - // Transport type Binary / ASCII - switch (connect.TransportType) - { - case FtpTransportType.Binary: - client.UploadDataType = FtpDataType.Binary; - client.DownloadDataType = FtpDataType.Binary; - break; - case FtpTransportType.Ascii: - client.UploadDataType = FtpDataType.ASCII; - client.DownloadDataType = FtpDataType.ASCII; - break; - default: - throw new ArgumentOutOfRangeException($"Unknown FTP transport type {connect.TransportType}"); - } - - // Active/passive - switch (connect.Mode) - { - case FtpMode.Active: - client.DataConnectionType = FtpDataConnectionType.AutoActive; - break; - case FtpMode.Passive: - client.DataConnectionType = FtpDataConnectionType.AutoPassive; - break; - default: - throw new ArgumentOutOfRangeException($"Unknown FTP mode {connect.Mode}"); - } - - return client; - } - - private Tuple, bool> GetSourceFiles() - { - var fileItems = new List(); - - if (_filePaths != null) - { - fileItems = _filePaths.Select(p => new FileItem(p) { Name = p }).ToList(); - if (fileItems.Any()) - return new Tuple, bool>(fileItems, true); - return new Tuple, bool>(fileItems, false); - } - - // Return empty list if source directory doesn't exists. - if (!Directory.Exists(_sourceDirectoryWithMacrosExpanded)) - return new Tuple, bool>(fileItems, false); - - // fetch all file names in given directory - var files = Directory.GetFiles(_sourceDirectoryWithMacrosExpanded); - - // return Tuple with empty list and success.true if files are not found. - if (!files.Any()) - return new Tuple, bool>(fileItems, true); - - // create List of FileItems from found files. - foreach (var file in files) - { - if (Util.FileMatchesMask(Path.GetFileName(file), _batchContext.Source.FileName)) - { - FileItem item = new FileItem(Path.GetFullPath(file)); - _logger.NotifyInformation(_batchContext, $"FILE LIST {item.FullPath}"); - fileItems.Add(item); - } - } - - return new Tuple, bool>(fileItems, true); - } - - private static void CreateAllDirectories(FtpClient client, string path) - { - // Consistent forward slashes - path = path.Replace(@"\", "/"); - foreach (string dir in path.Split('/')) - { - // Ignoring leading/ending/multiple slashes - if (!string.IsNullOrWhiteSpace(dir)) - { - if (!client.DirectoryExists(dir)) - client.CreateDirectory(dir); - - client.SetWorkingDirectory(dir); - } - } - // Going back to default directory - client.SetWorkingDirectory("/"); - } - - private static string[] ConvertObjectToStringArray(object objectArray) - { - var res = objectArray as object[]; - return res?.OfType().ToArray(); - } - - private static FileTransferResult FormFailedFileTransferResult(string userResultMessage) - { - return new FileTransferResult - { - ActionSkipped = true, - Success = false, - UserResultMessage = userResultMessage, - SuccessfulTransferCount = 0, - FailedTransferCount = 0, - TransferredFileNames = new List(), - TransferErrors = new Dictionary>(), - TransferredFilePaths = new List(), - OperationsLog = new Dictionary() - }; - } - - private static FileTransferResult FormResultFromSingleTransferResults(List singleResults) - { - var success = singleResults.All(x => x.Success); - var actionSkipped = success && singleResults.All(x => x.ActionSkipped); - var userResultMessage = FileTransporter.GetUserResultMessage(singleResults.ToList()); - - var transferErrors = singleResults.Where(r => !r.Success).GroupBy(r => r.TransferredFile ?? "--unknown--") - .ToDictionary(rg => rg.Key, rg => (IList)rg.SelectMany(r => r.ErrorMessages).ToList()); - - var transferredFileResults = singleResults.Where(r => r.Success && !r.ActionSkipped).ToList(); - - return new FileTransferResult - { - ActionSkipped = actionSkipped, - Success = success, - UserResultMessage = userResultMessage, - SuccessfulTransferCount = singleResults.Count(s => s.Success && !s.ActionSkipped), - FailedTransferCount = singleResults.Count(s => !s.Success && !s.ActionSkipped), - TransferredFileNames = transferredFileResults.Select(r => r.TransferredFile ?? "--unknown--").ToList(), - TransferErrors = transferErrors, - TransferredFilePaths = transferredFileResults.Select(r => r.TransferredFilePath ?? "--unknown--").ToList(), - OperationsLog = new Dictionary() - }; - } - - private static string GetUserResultMessage(IList results) - { - var userResultMessage = string.Empty; - - var errorMessages = results.SelectMany(x => x.ErrorMessages).ToList(); - if (errorMessages.Any()) - userResultMessage = MessageJoin(userResultMessage, - $"{errorMessages.Count} Errors: {string.Join(", ", errorMessages)}"); - - var transferredFiles = results.Select(x => x.TransferredFile).Where(x => x != null).ToList(); - if (transferredFiles.Any()) - userResultMessage = MessageJoin(userResultMessage, - string.Format("{0} files transferred: {1}", transferredFiles.Count, - string.Join(", ", transferredFiles))); - else - userResultMessage = MessageJoin(userResultMessage, "No files transferred."); - - return userResultMessage; - } - - private static string MessageJoin(params string[] args) - { - return string.Join(" ", args.Where(s => !string.IsNullOrWhiteSpace(s))); - } - - private SingleFileTransferResult NoSourceOperation(BatchContext context, Source source) - { - var transferName = context.Info.TransferName ?? string.Empty; - - var msg = context.Source.FilePaths == null - ? $"No source files found from directory '{_sourceDirectoryWithMacrosExpanded}' with file mask '{source.FileName}' for transfer '{transferName}'" - : $"No source files found from FilePaths '{string.Join(", ", context.Source.FilePaths)}' for transfer '{transferName}'"; - - switch (_batchContext.Source.NotFoundAction) - { - case SourceNotFoundAction.Error: - _logger.NotifyError(context, msg, new FileNotFoundException()); - return new SingleFileTransferResult { Success = false, ErrorMessages = { msg } }; - case SourceNotFoundAction.Info: - _logger.NotifyInformation(context, msg); - return new SingleFileTransferResult { Success = true, ActionSkipped = true, ErrorMessages = { msg } }; - case SourceNotFoundAction.Ignore: - return new SingleFileTransferResult { Success = true, ActionSkipped = true, ErrorMessages = { msg } }; - default: - throw new Exception("Unknown operation in NoSourceOperation"); - } - } - #endregion - } +using FluentFTP; +using Frends.FTP.UploadFiles.Enums; +using Frends.FTP.UploadFiles.Logging; +using Frends.FTP.UploadFiles.TaskConfiguration; +using Frends.FTP.UploadFiles.TaskResult; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Net.Security; +using System.Net.Sockets; +using System.Security.Cryptography.X509Certificates; +using System.Text; +using System.Threading; + +namespace Frends.FTP.UploadFiles.Definitions +{ + /// + /// Main class for FTP file transfers + /// + internal class FileTransporter + { + private readonly IFtpLogger _logger; + private readonly BatchContext _batchContext; + private readonly string[] _filePaths; + private readonly RenamingPolicy _renamingPolicy; + private readonly string _sourceDirectoryWithMacrosExpanded; + private readonly string _destinationDirectoryWithMacrosExpanded; + + public FileTransporter(IFtpLogger logger, BatchContext context, Guid instanceId) + { + _logger = logger; + _batchContext = context; + _renamingPolicy = new RenamingPolicy(_batchContext.Info.TransferName, instanceId); + + _sourceDirectoryWithMacrosExpanded = + _renamingPolicy.ExpandDirectoryForMacros(_batchContext.Source.Directory); + _destinationDirectoryWithMacrosExpanded = + _renamingPolicy.ExpandDirectoryForMacros(_batchContext.Destination.Directory); + + Result = new List(); + _filePaths = ConvertObjectToStringArray(context.Source.FilePaths); + } + + private List Result { get; } + + public FileTransferResult Run(CancellationToken cancellationToken) + { + var userResultMessage = ""; + try + { + // Fetch source file info and check if files were returned. + var (files, success) = GetSourceFiles(); + + // If source directory doesn't exist, modify userResultMessage accordingly. + if (!success) + { + userResultMessage = $"Directory '{_sourceDirectoryWithMacrosExpanded}' doesn't exist."; + _logger.NotifyError(_batchContext, userResultMessage, new Exception(userResultMessage)); + return FormFailedFileTransferResult(userResultMessage); + } + + if (files == null || !files.Any()) + { + if (files == null) + _logger.NotifyInformation(_batchContext, + "Source end point returned null list for file list. If there are no files to transfer, the result should be an empty list."); + + var noSourceResult = NoSourceOperation(_batchContext, _batchContext.Source); + Result.Add(noSourceResult); + } + else + { + using (var client = CreateFtpClient(_batchContext.Connection)) + { + client.Connect(); + + if (!client.IsConnected) + { + _logger.NotifyError(_batchContext, "Error while connecting to destination: ", new Exception(userResultMessage)); + return FormFailedFileTransferResult(userResultMessage); + } + + // Check does the destination directory exists. + if (!client.DirectoryExists(_destinationDirectoryWithMacrosExpanded)) + { + if (_batchContext.Options.CreateDestinationDirectories) + { + try + { + CreateAllDirectories(client, _destinationDirectoryWithMacrosExpanded); + } + catch (Exception ex) + { + userResultMessage = $"Error while creating destination directory '{_destinationDirectoryWithMacrosExpanded}': {ex.Message}"; + _logger.NotifyError(_batchContext, userResultMessage, new Exception(userResultMessage)); + return FormFailedFileTransferResult(userResultMessage); + } + } + else + { + userResultMessage = $"Destination directory '{_destinationDirectoryWithMacrosExpanded}' was not found."; + _logger.NotifyError(_batchContext, userResultMessage, new Exception(userResultMessage)); + return FormFailedFileTransferResult(userResultMessage); + } + } + + client.SetWorkingDirectory(_destinationDirectoryWithMacrosExpanded); + + //_batchContext.DestinationFiles = client.GetListing("."); + + foreach (var file in files) + { + // Check that the connection is alive and if not try to connect again + if (!client.IsConnected) + { + client.Connect(); + _logger.NotifyInformation(_batchContext, "Reconnected."); + } + + cancellationToken.ThrowIfCancellationRequested(); + var singleTransfer = new SingleFileTransfer(file, _batchContext, client, _renamingPolicy, _logger); + var result = singleTransfer.TransferSingleFile(); + Result.Add(result); + } + client.Disconnect(); + } + } + } + catch (SocketException) + { + userResultMessage = $"Unable to establish the socket: No such host is known."; + _logger.NotifyError(_batchContext, userResultMessage, new Exception(userResultMessage)); + return FormFailedFileTransferResult(userResultMessage); + } + + return FileTransporter.FormResultFromSingleTransferResults(Result); + } + + #region Helper methods + private static FtpClient CreateFtpClient(Connection connect) + { + var client = new FtpClient(connect.Address, connect.Port, connect.UserName, connect.Password); + switch (connect.SslMode) + { + case FtpsSslMode.None: + client.EncryptionMode = FtpEncryptionMode.None; + break; + case FtpsSslMode.Implicit: + client.EncryptionMode = FtpEncryptionMode.Implicit; + break; + case FtpsSslMode.Explicit: + client.EncryptionMode = FtpEncryptionMode.Explicit; + break; + case FtpsSslMode.Auto: + client.EncryptionMode = FtpEncryptionMode.Auto; + break; + default: + throw new ArgumentOutOfRangeException(); + } + + if (connect.UseFTPS) + { + if (connect.EnableClientAuth) + { + if (!string.IsNullOrEmpty(connect.ClientCertificatePath)) + { + client.ClientCertificates.Add(new X509Certificate2(connect.ClientCertificatePath)); + } + else + { + X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine); + try + { + store.Open(OpenFlags.ReadOnly); + client.ClientCertificates.AddRange(store.Certificates); + } + finally + { + store.Close(); + } + } + } + + client.ValidateCertificate += (control, e) => + { + // If cert is valid and such - go on and accept + if (e.PolicyErrors == SslPolicyErrors.None) + { + e.Accept = true; + return; + } + + // Accept if we want to accept a certain hash + e.Accept = e.Certificate.GetCertHashString() == connect.CertificateHashStringSHA1; + }; + + client.ValidateAnyCertificate = connect.ValidateAnyCertificate; + client.DataConnectionEncryption = connect.SecureDataChannel; + } + + client.NoopInterval = connect.KeepConnectionAliveInterval; + + if (!string.IsNullOrWhiteSpace(connect.Encoding)) client.Encoding = Encoding.GetEncoding(connect.Encoding); + + // Client lib timeout is in milliseconds, ours is in seconds, thus *1000 conversion + client.ConnectTimeout = connect.ConnectionTimeout * 1000; + client.LocalFileBufferSize = connect.BufferSize; + + // Transport type Binary / ASCII + switch (connect.TransportType) + { + case FtpTransportType.Binary: + client.UploadDataType = FtpDataType.Binary; + client.DownloadDataType = FtpDataType.Binary; + break; + case FtpTransportType.Ascii: + client.UploadDataType = FtpDataType.ASCII; + client.DownloadDataType = FtpDataType.ASCII; + break; + default: + throw new ArgumentOutOfRangeException($"Unknown FTP transport type {connect.TransportType}"); + } + + // Active/passive + switch (connect.Mode) + { + case FtpMode.Active: + client.DataConnectionType = FtpDataConnectionType.AutoActive; + break; + case FtpMode.Passive: + client.DataConnectionType = FtpDataConnectionType.AutoPassive; + break; + default: + throw new ArgumentOutOfRangeException($"Unknown FTP mode {connect.Mode}"); + } + + return client; + } + + private Tuple, bool> GetSourceFiles() + { + var fileItems = new List(); + + if (_filePaths != null) + { + fileItems = _filePaths.Select(p => new FileItem(p) { Name = p }).ToList(); + if (fileItems.Any()) + return new Tuple, bool>(fileItems, true); + return new Tuple, bool>(fileItems, false); + } + + // Return empty list if source directory doesn't exists. + if (!Directory.Exists(_sourceDirectoryWithMacrosExpanded)) + return new Tuple, bool>(fileItems, false); + + // fetch all file names in given directory + var files = Directory.GetFiles(_sourceDirectoryWithMacrosExpanded); + + // return Tuple with empty list and success.true if files are not found. + if (!files.Any()) + return new Tuple, bool>(fileItems, true); + + // create List of FileItems from found files. + foreach (var file in files) + { + if (Util.FileMatchesMask(Path.GetFileName(file), _batchContext.Source.FileName)) + { + FileItem item = new FileItem(Path.GetFullPath(file)); + _logger.NotifyInformation(_batchContext, $"FILE LIST {item.FullPath}"); + fileItems.Add(item); + } + } + + return new Tuple, bool>(fileItems, true); + } + + private static void CreateAllDirectories(FtpClient client, string path) + { + // Consistent forward slashes + path = path.Replace(@"\", "/"); + foreach (string dir in path.Split('/')) + { + // Ignoring leading/ending/multiple slashes + if (!string.IsNullOrWhiteSpace(dir)) + { + if (!client.DirectoryExists(dir)) + client.CreateDirectory(dir); + + client.SetWorkingDirectory(dir); + } + } + // Going back to default directory + client.SetWorkingDirectory("/"); + } + + private static string[] ConvertObjectToStringArray(object objectArray) + { + var res = objectArray as object[]; + return res?.OfType().ToArray(); + } + + private static FileTransferResult FormFailedFileTransferResult(string userResultMessage) + { + return new FileTransferResult + { + ActionSkipped = true, + Success = false, + UserResultMessage = userResultMessage, + SuccessfulTransferCount = 0, + FailedTransferCount = 0, + TransferredFileNames = new List(), + TransferErrors = new Dictionary>(), + TransferredFilePaths = new List(), + OperationsLog = new Dictionary() + }; + } + + private static FileTransferResult FormResultFromSingleTransferResults(List singleResults) + { + var success = singleResults.All(x => x.Success); + var actionSkipped = success && singleResults.All(x => x.ActionSkipped); + var userResultMessage = FileTransporter.GetUserResultMessage(singleResults.ToList()); + + var transferErrors = singleResults.Where(r => !r.Success).GroupBy(r => r.TransferredFile ?? "--unknown--") + .ToDictionary(rg => rg.Key, rg => (IList)rg.SelectMany(r => r.ErrorMessages).ToList()); + + var transferredFileResults = singleResults.Where(r => r.Success && !r.ActionSkipped).ToList(); + + return new FileTransferResult + { + ActionSkipped = actionSkipped, + Success = success, + UserResultMessage = userResultMessage, + SuccessfulTransferCount = singleResults.Count(s => s.Success && !s.ActionSkipped), + FailedTransferCount = singleResults.Count(s => !s.Success && !s.ActionSkipped), + TransferredFileNames = transferredFileResults.Select(r => r.TransferredFile ?? "--unknown--").ToList(), + TransferErrors = transferErrors, + TransferredFilePaths = transferredFileResults.Select(r => r.TransferredFilePath ?? "--unknown--").ToList(), + OperationsLog = new Dictionary() + }; + } + + private static string GetUserResultMessage(IList results) + { + var userResultMessage = string.Empty; + + var errorMessages = results.SelectMany(x => x.ErrorMessages).ToList(); + if (errorMessages.Any()) + userResultMessage = MessageJoin(userResultMessage, + $"{errorMessages.Count} Errors: {string.Join(", ", errorMessages)}"); + + var transferredFiles = results.Select(x => x.TransferredFile).Where(x => x != null).ToList(); + if (transferredFiles.Any()) + userResultMessage = MessageJoin(userResultMessage, + string.Format("{0} files transferred: {1}", transferredFiles.Count, + string.Join(", ", transferredFiles))); + else + userResultMessage = MessageJoin(userResultMessage, "No files transferred."); + + return userResultMessage; + } + + private static string MessageJoin(params string[] args) + { + return string.Join(" ", args.Where(s => !string.IsNullOrWhiteSpace(s))); + } + + private SingleFileTransferResult NoSourceOperation(BatchContext context, Source source) + { + var transferName = context.Info.TransferName ?? string.Empty; + + var msg = context.Source.FilePaths == null + ? $"No source files found from directory '{_sourceDirectoryWithMacrosExpanded}' with file mask '{source.FileName}' for transfer '{transferName}'" + : $"No source files found from FilePaths '{string.Join(", ", context.Source.FilePaths)}' for transfer '{transferName}'"; + + switch (_batchContext.Source.NotFoundAction) + { + case SourceNotFoundAction.Error: + _logger.NotifyError(context, msg, new FileNotFoundException()); + return new SingleFileTransferResult { Success = false, ErrorMessages = { msg } }; + case SourceNotFoundAction.Info: + _logger.NotifyInformation(context, msg); + return new SingleFileTransferResult { Success = true, ActionSkipped = true, ErrorMessages = { msg } }; + case SourceNotFoundAction.Ignore: + return new SingleFileTransferResult { Success = true, ActionSkipped = true, ErrorMessages = { msg } }; + default: + throw new Exception("Unknown operation in NoSourceOperation"); + } + } + #endregion + } } \ No newline at end of file diff --git a/Frends.FTP.UploadFiles/Frends.FTP.UploadFiles/Frends.FTP.UploadFiles.csproj b/Frends.FTP.UploadFiles/Frends.FTP.UploadFiles/Frends.FTP.UploadFiles.csproj index 6600a5f..74dcf05 100644 --- a/Frends.FTP.UploadFiles/Frends.FTP.UploadFiles/Frends.FTP.UploadFiles.csproj +++ b/Frends.FTP.UploadFiles/Frends.FTP.UploadFiles/Frends.FTP.UploadFiles.csproj @@ -9,7 +9,7 @@ true Frends true - 1.0.2 + 1.0.3 Task for uploading files to FTP(S) servers. From 0f39029696454a7ad234a0aa379f4cc3a8afd6fc Mon Sep 17 00:00:00 2001 From: Riku Virtanen Date: Fri, 15 Sep 2023 15:39:07 +0300 Subject: [PATCH 2/6] Debugging certification search on linux --- Frends.FTP.UploadFiles/CHANGELOG.md | 2 +- .../UploadFilesTests.cs | 43 +++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/Frends.FTP.UploadFiles/CHANGELOG.md b/Frends.FTP.UploadFiles/CHANGELOG.md index 047389b..50b125e 100644 --- a/Frends.FTP.UploadFiles/CHANGELOG.md +++ b/Frends.FTP.UploadFiles/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -## [1.0.3] - 2023-099-12 +## [1.0.3] - 2023-09-12 ### Added - Added search for local certificates from machine certification store. diff --git a/Frends.FTP.UploadFiles/Frends.FTP.UploadFiles.Tests/UploadFilesTests.cs b/Frends.FTP.UploadFiles/Frends.FTP.UploadFiles.Tests/UploadFilesTests.cs index 178a6a9..ebacd5e 100644 --- a/Frends.FTP.UploadFiles/Frends.FTP.UploadFiles.Tests/UploadFilesTests.cs +++ b/Frends.FTP.UploadFiles/Frends.FTP.UploadFiles.Tests/UploadFilesTests.cs @@ -652,4 +652,47 @@ public void UploadFTPS_OperationLog() SetUp(); } } + + [TestMethod] + public void UploadFTPS_LocalMachineHasNoCertificates() + { + var connection = new Connection + { + Address = Helpers.FtpHost, + UserName = Helpers.FtpUsername, + Password = Helpers.FtpPassword, + Port = Helpers.FtpsPort, + SslMode = FtpsSslMode.Explicit, + EnableClientAuth = true, + UseFTPS = true, + ValidateAnyCertificate = false, + CertificateHashStringSHA1 = "", + ClientCertificatePath = "" + }; + + if (Environment.OSVersion.Platform == PlatformID.Unix) + { + var ex = Assert.ThrowsException(() => + { + var result = FTP.UploadFiles(_source, _destination, connection, new Options(), new Info(), + new CancellationToken()); + + }); + + Assert.AreEqual("Unix LocalMachine X509Store is limited to the Root and Certif", ex.Message); + } + else + { + var ex = Assert.ThrowsException(() => + { + var result = FTP.UploadFiles(_source, _destination, connection, new Options(), new Info(), + new CancellationToken()); + + }); + + Assert.AreEqual(1, ex.InnerExceptions.Count); + Assert.AreEqual(typeof(AuthenticationException), ex.InnerExceptions[0].GetType()); + } + + } } \ No newline at end of file From 1a709c9b84fadf6c7dd65aace06ea9bdb559fcaf Mon Sep 17 00:00:00 2001 From: Riku Virtanen Date: Thu, 21 Sep 2023 10:29:39 +0300 Subject: [PATCH 3/6] Debug tests --- .../DestinationOperationTests.cs | 1 + .../MacrosTests.cs | 1 + .../SourceFilesNotFoundActionTests.cs | 1 + .../SourceOperationTests.cs | 1 + .../UploadFilesTests.cs | 1321 ++++++++--------- .../Definitions/FileTransporter.cs | 20 +- 6 files changed, 674 insertions(+), 671 deletions(-) diff --git a/Frends.FTP.UploadFiles/Frends.FTP.UploadFiles.Tests/DestinationOperationTests.cs b/Frends.FTP.UploadFiles/Frends.FTP.UploadFiles.Tests/DestinationOperationTests.cs index f643de1..14b6686 100644 --- a/Frends.FTP.UploadFiles/Frends.FTP.UploadFiles.Tests/DestinationOperationTests.cs +++ b/Frends.FTP.UploadFiles/Frends.FTP.UploadFiles.Tests/DestinationOperationTests.cs @@ -6,6 +6,7 @@ namespace Frends.FTP.UploadFiles.Tests; +[Ignore("Debug")] [TestClass] public class DestinationActionTests : UploadFilesTestBase { diff --git a/Frends.FTP.UploadFiles/Frends.FTP.UploadFiles.Tests/MacrosTests.cs b/Frends.FTP.UploadFiles/Frends.FTP.UploadFiles.Tests/MacrosTests.cs index bbd514e..249b8d0 100644 --- a/Frends.FTP.UploadFiles/Frends.FTP.UploadFiles.Tests/MacrosTests.cs +++ b/Frends.FTP.UploadFiles/Frends.FTP.UploadFiles.Tests/MacrosTests.cs @@ -18,6 +18,7 @@ namespace Frends.FTP.UploadFiles.Tests; /// - source file name does not support macros for some reason in Cobalt, currently not implementing because /// need to understand reasoning better /// +[Ignore("Debug")] [TestClass] public class MacrosTests { diff --git a/Frends.FTP.UploadFiles/Frends.FTP.UploadFiles.Tests/SourceFilesNotFoundActionTests.cs b/Frends.FTP.UploadFiles/Frends.FTP.UploadFiles.Tests/SourceFilesNotFoundActionTests.cs index 66bc04c..f72b2a0 100644 --- a/Frends.FTP.UploadFiles/Frends.FTP.UploadFiles.Tests/SourceFilesNotFoundActionTests.cs +++ b/Frends.FTP.UploadFiles/Frends.FTP.UploadFiles.Tests/SourceFilesNotFoundActionTests.cs @@ -7,6 +7,7 @@ namespace Frends.FTP.UploadFiles.Tests; +[Ignore("Debug")] [TestClass] public class SourceFilesNotFoundActionTests : UploadFilesTestBase { diff --git a/Frends.FTP.UploadFiles/Frends.FTP.UploadFiles.Tests/SourceOperationTests.cs b/Frends.FTP.UploadFiles/Frends.FTP.UploadFiles.Tests/SourceOperationTests.cs index 9cbf3a8..88759da 100644 --- a/Frends.FTP.UploadFiles/Frends.FTP.UploadFiles.Tests/SourceOperationTests.cs +++ b/Frends.FTP.UploadFiles/Frends.FTP.UploadFiles.Tests/SourceOperationTests.cs @@ -7,6 +7,7 @@ namespace Frends.FTP.UploadFiles.Tests; +[Ignore("Debug")] [TestClass] public class SourceOperationTests : UploadFilesTestBase { diff --git a/Frends.FTP.UploadFiles/Frends.FTP.UploadFiles.Tests/UploadFilesTests.cs b/Frends.FTP.UploadFiles/Frends.FTP.UploadFiles.Tests/UploadFilesTests.cs index ebacd5e..60ef637 100644 --- a/Frends.FTP.UploadFiles/Frends.FTP.UploadFiles.Tests/UploadFilesTests.cs +++ b/Frends.FTP.UploadFiles/Frends.FTP.UploadFiles.Tests/UploadFilesTests.cs @@ -1,660 +1,660 @@ -using FluentFTP; -using Frends.FTP.UploadFiles.Enums; -using Frends.FTP.UploadFiles.TaskConfiguration; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using System; -using System.IO; -using System.Linq; -using System.Security.Authentication; -using System.Threading; - -namespace Frends.FTP.UploadFiles.Tests; - -[TestClass] -public class UploadFilesTests -{ - private string _tempDir; - private readonly string _file = "file1.txt"; - - private Source _source = new(); - private Connection _connection = new(); - private Destination _destination = new(); - private Options _options = new(); - private Info _info = new(); - - [TestInitialize] - public void SetUp() - { - _tempDir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "../../../tempFiles"); - Directory.CreateDirectory(_tempDir); - File.WriteAllText(Path.Combine(_tempDir, _file), "test"); - Directory.CreateDirectory(Path.Combine(_tempDir, "Done")); - - _source = new() - { - Directory = _tempDir, - FileName = _file, - DirectoryToMoveAfterTransfer = Path.Combine(_tempDir, "Done"), - FileNameAfterTransfer = _file + Guid.NewGuid().ToString(), - NotFoundAction = default, - FilePaths = _tempDir, - Operation = default, - }; - - _connection = new() - { - Address = Helpers.FtpHost, - UserName = Helpers.FtpUsername, - Password = Helpers.FtpPassword, - Port = Helpers.FtpPort, - TransportType = default, - Mode = default, - KeepConnectionAliveInterval = default, - ConnectionTimeout = 60, - Encoding = default, - BufferSize = default, - UseFTPS = false, - SslMode = default, - CertificateHashStringSHA1 = "D911262984DE9CC32A3518A1094CD24249EA5C49", - EnableClientAuth = default, - ValidateAnyCertificate = default, - ClientCertificatePath = default, - SecureDataChannel = false, - }; - - _destination = new() - { - Directory = "/", - Action = default, - FileName = $"{_file}-{Guid.NewGuid()}", - }; - - _options = new() - { - CreateDestinationDirectories = true, - OperationLog = default, - PreserveLastModified = default, - RenameDestinationFileDuringTransfer = default, - RenameSourceFileBeforeTransfer = default, - ThrowErrorOnFail = default, - }; - - _info = new() - { - ProcessUri = default, - TaskExecutionID = default, - TransferName = default, - WorkDir = default, - }; - } - - [TestCleanup] - public void CleanUp() - { - if (Directory.Exists(_tempDir)) - Directory.Delete(_tempDir, true); - - var client = new FtpClient(Helpers.FtpHost, Helpers.FtpPort, Helpers.FtpUsername, Helpers.FtpPassword) - { - ConnectTimeout = 10 - }; - client.Connect(); - if (client.DirectoryExists("/")) - client.DeleteDirectory("/"); - client.Disconnect(); - client.Dispose(); - } - - [TestMethod] - public void UploadFTPS_IncorrectFingerprint() - { - var connection = _connection; - connection.SslMode = FtpsSslMode.Explicit; - connection.UseFTPS = true; - connection.CertificateHashStringSHA1 = "incorrect"; - - // Test and assert - var ex = Assert.ThrowsException(() => FTP.UploadFiles(_source, _destination, connection, _options, _info, new CancellationToken())); - Assert.AreEqual(1, ex.InnerExceptions.Count); - Assert.AreEqual(typeof(AuthenticationException), ex.InnerExceptions[0].GetType()); - } - - [TestMethod] - public void UploadFTPS_IncorrectAuth() - { - var connectionA = _connection; - connectionA.Address = null; - - var connectionB = _connection; - connectionB.Port = 0; - - var connectionC = _connection; - connectionC.Password = null; - - var connectionD = _connection; - connectionD.UserName = null; - - var ex1 = Assert.ThrowsException(() => FTP.UploadFiles(_source, _destination, connectionA, _options, _info, new CancellationToken())); - Assert.AreEqual(typeof(NullReferenceException), ex1.GetType()); - - var ex2 = Assert.ThrowsException(() => FTP.UploadFiles(_source, _destination, connectionB, _options, _info, new CancellationToken())); - Assert.AreEqual(typeof(NullReferenceException), ex2.GetType()); - - var ex3 = Assert.ThrowsException(() => FTP.UploadFiles(_source, _destination, connectionC, _options, _info, new CancellationToken())); - Assert.AreEqual(typeof(NullReferenceException), ex3.GetType()); - - var ex4 = Assert.ThrowsException(() => FTP.UploadFiles(_source, _destination, connectionD, _options, _info, new CancellationToken())); - Assert.AreEqual(typeof(NullReferenceException), ex4.GetType()); - } - - [TestMethod] - public void UploadFTP_UploadFile() - { - var result = FTP.UploadFiles(_source, _destination, _connection, _options, _info, new CancellationToken()); - Assert.IsTrue(result.Success); - Assert.AreEqual(1, result.SuccessfulTransferCount); - } - - [TestMethod] - public void UploadFTPS_DestinationActions() - { - var destinationActions = new[] { DestinationAction.Error, DestinationAction.Overwrite, DestinationAction.Append }; - - foreach (var destinationAction in destinationActions) - { - var destination = _destination; - destination.Action = destinationAction; - - var result = FTP.UploadFiles(_source, destination, _connection, _options, _info, new CancellationToken()); - Assert.IsTrue(result.Success, $"DestinationAction: {destinationAction}"); - Assert.IsFalse(result.ActionSkipped, $"DestinationAction: {destinationAction}"); - Assert.AreEqual(1, result.SuccessfulTransferCount, $"DestinationAction: {destinationAction}"); - Assert.AreEqual(0, result.TransferErrors.Count, $"DestinationAction: {destinationAction}"); - Assert.AreEqual(1, result.TransferredFileNames.Count(), $"DestinationAction: {destinationAction}"); - Assert.AreEqual(1, result.TransferredFilePaths.Count(), $"DestinationAction: {destinationAction}"); - Assert.IsTrue(result.UserResultMessage.Contains("files transferred"), $"DestinationAction: {destinationAction}"); - Assert.IsTrue(result.OperationsLog.Count < 4, $"DestinationAction: {destinationAction}"); - - CleanUp(); - SetUp(); - } - } - - [TestMethod] - public void UploadFTPS_FtpMode() - { - var ftpModes = new[] { FtpMode.Active, FtpMode.Passive }; - - foreach (var ftpMode in ftpModes) - { - var connection = _connection; - connection.Mode = ftpMode; - - var result = FTP.UploadFiles(_source, _destination, connection, _options, _info, new CancellationToken()); - if (ftpMode is FtpMode.Active) - { - Assert.IsFalse(result.Success); - Assert.IsTrue(result.UserResultMessage.Contains("Error: Error while uploading the file to the server. See InnerException for more info."), $"FtpMode: {ftpMode}"); - Assert.IsFalse(result.ActionSkipped, $"FtpMode: {ftpMode}"); - Assert.AreEqual(0, result.SuccessfulTransferCount, $"FtpMode: {ftpMode}"); - Assert.AreEqual(1, result.TransferErrors.Count, $"FtpMode: {ftpMode}"); - Assert.AreEqual(0, result.TransferredFileNames.Count(), $"FtpMode: {ftpMode}"); - Assert.AreEqual(0, result.TransferredFilePaths.Count(), $"FtpMode: {ftpMode}"); - } - else - { - Assert.IsTrue(result.Success, $"FtpMode: {ftpMode}"); - Assert.IsFalse(result.ActionSkipped, $"FtpMode: {ftpMode}"); - Assert.AreEqual(1, result.SuccessfulTransferCount, $"FtpMode: {ftpMode}"); - Assert.AreEqual(0, result.TransferErrors.Count, $"FtpMode: {ftpMode}"); - Assert.AreEqual(1, result.TransferredFileNames.Count(), $"FtpMode: {ftpMode}"); - Assert.AreEqual(1, result.TransferredFilePaths.Count(), $"FtpMode: {ftpMode}"); - Assert.IsTrue(result.UserResultMessage.Contains("files transferred"), $"FtpMode: {ftpMode}"); - } - Assert.IsTrue(result.OperationsLog.Count < 4, $"FtpMode: {ftpMode}"); - - CleanUp(); - SetUp(); - } - } - - [TestMethod] - public void UploadFTPS_FtpsSslModes() - { - var ftpsSslModes = new[] { FtpsSslMode.None, FtpsSslMode.Explicit, FtpsSslMode.Auto }; - - foreach (var ftpsSslMode in ftpsSslModes) - { - var connection = _connection; - connection.SslMode = ftpsSslMode; - connection.UseFTPS = true; - - var result = FTP.UploadFiles(_source, _destination, connection, _options, _info, new CancellationToken()); - Assert.IsTrue(result.Success, $"FtpsSslMode: {ftpsSslMode}"); - Assert.IsFalse(result.ActionSkipped, $"FtpsSslMode: {ftpsSslMode}"); - Assert.AreEqual(1, result.SuccessfulTransferCount, $"FtpsSslMode: {ftpsSslMode}"); - Assert.AreEqual(0, result.TransferErrors.Count, $"FtpsSslMode: {ftpsSslMode}"); - Assert.AreEqual(1, result.TransferredFileNames.Count(), $"FtpsSslMode: {ftpsSslMode}"); - Assert.AreEqual(1, result.TransferredFilePaths.Count(), $"FtpsSslMode: {ftpsSslMode}"); - Assert.IsTrue(result.UserResultMessage.Contains("files transferred"), $"FtpsSslMode: {ftpsSslMode}"); - Assert.IsTrue(result.OperationsLog.Count < 4, $"FtpsSslMode: {ftpsSslMode}"); - - CleanUp(); - SetUp(); - } - } - - [TestMethod] - public void UploadFTPS_SecureDataChannel() - { - var boo = new[] { true, false }; - - foreach (var bo in boo) - { - var connection = _connection; - connection.SecureDataChannel = bo; - - var result = FTP.UploadFiles(_source, _destination, connection, _options, _info, new CancellationToken()); - Assert.IsTrue(result.Success, $"Bo: {bo}"); - Assert.IsFalse(result.ActionSkipped, $"Bo: {bo}"); - Assert.AreEqual(1, result.SuccessfulTransferCount, $"Bo: {bo}"); - Assert.AreEqual(0, result.TransferErrors.Count, $"Bo: {bo}"); - Assert.AreEqual(1, result.TransferredFileNames.Count(), $"Bo: {bo}"); - Assert.AreEqual(1, result.TransferredFilePaths.Count(), $"Bo: {bo}"); - Assert.IsTrue(result.UserResultMessage.Contains("files transferred"), $"Bo: {bo}"); - Assert.IsTrue(result.OperationsLog.Count < 4, $"Bo: {bo}"); - - CleanUp(); - SetUp(); - } - } - - [TestMethod] - public void UploadFTPS_FtpTransportTypes() - { - var ftpTransportTypes = new[] { FtpTransportType.Binary, FtpTransportType.Ascii }; - - foreach (var ftpTransportType in ftpTransportTypes) - { - var connection = _connection; - connection.TransportType = ftpTransportType; - - var result = FTP.UploadFiles(_source, _destination, connection, _options, _info, new CancellationToken()); - Assert.IsTrue(result.Success, $"FtpTransportType: {ftpTransportType}"); - Assert.IsFalse(result.ActionSkipped, $"FtpTransportType: {ftpTransportType}"); - Assert.AreEqual(1, result.SuccessfulTransferCount, $"FtpTransportType: {ftpTransportType}"); - Assert.AreEqual(0, result.TransferErrors.Count, $"FtpTransportType: {ftpTransportType}"); - Assert.AreEqual(1, result.TransferredFileNames.Count(), $"FtpTransportType: {ftpTransportType}"); - Assert.AreEqual(1, result.TransferredFilePaths.Count(), $"FtpTransportType: {ftpTransportType}"); - Assert.IsTrue(result.UserResultMessage.Contains("files transferred"), $"FtpTransportType: {ftpTransportType}"); - Assert.IsTrue(result.OperationsLog.Count < 4, $"FtpTransportType: {ftpTransportType}"); - - CleanUp(); - SetUp(); - } - } - - [TestMethod] - public void UploadFTPS_NotFoundActions() - { - var notFoundActions = new[] { SourceNotFoundAction.Error, SourceNotFoundAction.Ignore, SourceNotFoundAction.Info }; - - foreach (var notFoundAction in notFoundActions) - { - var source = _source; - source.NotFoundAction = notFoundAction; - source.FileName = ""; - - var result = FTP.UploadFiles(source, _destination, _connection, _options, _info, new CancellationToken()); - - if (notFoundAction is SourceNotFoundAction.Error) - { - Assert.IsFalse(result.Success, $"action: {notFoundAction}"); - Assert.IsFalse(result.ActionSkipped, $"action: {notFoundAction}"); - Assert.AreEqual(0, result.SuccessfulTransferCount, $"action: {notFoundAction}"); - Assert.AreEqual(1, result.TransferErrors.Count, $"action: {notFoundAction}"); - Assert.AreEqual(0, result.TransferredFileNames.Count(), $"action: {notFoundAction}"); - Assert.AreEqual(0, result.TransferredFilePaths.Count(), $"action: {notFoundAction}"); - - } - else - { - Assert.IsTrue(result.Success, $"action: {notFoundAction}"); - Assert.IsTrue(result.ActionSkipped, $"action: {notFoundAction}"); - Assert.AreEqual(0, result.SuccessfulTransferCount, $"action: {notFoundAction}"); - Assert.AreEqual(0, result.TransferErrors.Count, $"action: {notFoundAction}"); - Assert.AreEqual(0, result.TransferredFileNames.Count(), $"action: {notFoundAction}"); - Assert.AreEqual(0, result.TransferredFilePaths.Count(), $"action: {notFoundAction}"); - - } - Assert.IsTrue(result.UserResultMessage.Contains("No source files found"), $"action: {notFoundAction}"); - Assert.IsTrue(result.OperationsLog.Count < 4, $"action: {notFoundAction}"); - - CleanUp(); - SetUp(); - } - } - - [TestMethod] - public void UploadFTPS_SourceOperations() - { - var sourceOperations = new[] { SourceOperation.Move, SourceOperation.Delete, SourceOperation.Rename, SourceOperation.Nothing }; - - foreach (var sourceOperation in sourceOperations) - { - var source = _source; - source.Operation = sourceOperation; - - var result = FTP.UploadFiles(source, _destination, _connection, _options, _info, new CancellationToken()); - Assert.IsTrue(result.Success, $"SourceOperation: {sourceOperation}"); - Assert.IsFalse(result.ActionSkipped, $"SourceOperation: {sourceOperation}"); - Assert.AreEqual(1, result.SuccessfulTransferCount, $"SourceOperation: {sourceOperation}"); - Assert.AreEqual(0, result.TransferErrors.Count, $"SourceOperation: {sourceOperation}"); - Assert.AreEqual(1, result.TransferredFileNames.Count(), $"SourceOperation: {sourceOperation}"); - Assert.AreEqual(1, result.TransferredFilePaths.Count(), $"SourceOperation: {sourceOperation}"); - Assert.IsTrue(result.UserResultMessage.Contains("files transferred"), $"SourceOperation: {sourceOperation}"); - Assert.IsTrue(result.OperationsLog.Count < 4, $"SourceOperation: {sourceOperation}"); - - CleanUp(); - SetUp(); - } - } - - [TestMethod] - public void UploadFTPS_FileEncodings() - { - var fileEncodings = new[] { "UTF-8", "ASCII", "foobar123", string.Empty }; - - foreach (var fileEncoding in fileEncodings) - { - var connection = _connection; - connection.Encoding = fileEncoding; - - if (connection.Encoding.Equals("foobar123")) - { - var ex = Assert.ThrowsException(() => FTP.UploadFiles(_source, _destination, connection, _options, _info, new CancellationToken())); - Assert.IsTrue(ex.Message.Contains("is not a supported encoding name"), $"FileEncoding: {fileEncoding}"); - } - else - { - var result = FTP.UploadFiles(_source, _destination, connection, _options, _info, new CancellationToken()); - Assert.IsTrue(result.Success, $"FileEncoding: {fileEncoding}"); - Assert.IsFalse(result.ActionSkipped, $"FileEncoding: {fileEncoding}"); - Assert.AreEqual(1, result.SuccessfulTransferCount, $"FileEncoding: {fileEncoding}"); - Assert.AreEqual(0, result.TransferErrors.Count, $"FileEncoding: {fileEncoding}"); - Assert.AreEqual(1, result.TransferredFileNames.Count(), $"FileEncoding: {fileEncoding}"); - Assert.AreEqual(1, result.TransferredFilePaths.Count(), $"FileEncoding: {fileEncoding}"); - Assert.IsTrue(result.UserResultMessage.Contains("files transferred"), $"FileEncoding: {fileEncoding}"); - Assert.IsTrue(result.OperationsLog.Count < 4, $"FileEncoding: {fileEncoding}"); - } - - CleanUp(); - SetUp(); - } - } - - [TestMethod] - public void UploadFTPS_Port() - { - var ports = new[] { 0, 21, 210 }; - - foreach (var port in ports) - { - var connection = _connection; - connection.Port = port; - - var result = FTP.UploadFiles(_source, _destination, connection, _options, _info, new CancellationToken()); - if (port == 210) - { - Assert.IsFalse(result.Success, $"Port: {port}"); - Assert.IsTrue(result.ActionSkipped, $"Port: {port}"); - Assert.AreEqual(0, result.SuccessfulTransferCount, $"Port: {port}"); - Assert.AreEqual(0, result.TransferErrors.Count, $"Port: {port}"); - Assert.AreEqual(0, result.TransferredFileNames.Count(), $"Port: {port}"); - Assert.AreEqual(0, result.TransferredFilePaths.Count(), $"Port: {port}"); - Assert.IsTrue(result.UserResultMessage.Contains("Unable to establish the socket: No such host is known."), $"Port: {port}"); - Assert.IsTrue(result.OperationsLog.Count < 4, $"Port: {port}"); - } - else - { - Assert.IsTrue(result.Success, $"Port: {port}"); - Assert.IsFalse(result.ActionSkipped, $"Port: {port}"); - Assert.AreEqual(1, result.SuccessfulTransferCount, $"Port: {port}"); - Assert.AreEqual(0, result.TransferErrors.Count, $"Port: {port}"); - Assert.AreEqual(1, result.TransferredFileNames.Count(), $"Port: {port}"); - Assert.AreEqual(1, result.TransferredFilePaths.Count(), $"Port: {port}"); - Assert.IsTrue(result.UserResultMessage.Contains("files transferred"), $"Port: {port}"); - Assert.IsTrue(result.OperationsLog.Count < 4, $"Port: {port}"); - } - - CleanUp(); - SetUp(); - } - } - - [TestMethod] - public void UploadFTPS_KeepConnectionAliveInterval() - { - var intervals = new[] { 0, 1, 100 }; - - foreach (var interval in intervals) - { - var connection = _connection; - connection.KeepConnectionAliveInterval = interval; - - var result = FTP.UploadFiles(_source, _destination, connection, _options, _info, new CancellationToken()); - Assert.IsTrue(result.Success, $"Interval: {interval}"); - Assert.IsFalse(result.ActionSkipped, $"Interval: {interval}"); - Assert.AreEqual(1, result.SuccessfulTransferCount, $"Interval: {interval}"); - Assert.AreEqual(0, result.TransferErrors.Count, $"Interval: {interval}"); - Assert.AreEqual(1, result.TransferredFileNames.Count(), $"Interval: {interval}"); - Assert.AreEqual(1, result.TransferredFilePaths.Count(), $"Interval: {interval}"); - Assert.IsTrue(result.UserResultMessage.Contains("files transferred"), $"Interval: {interval}"); - Assert.IsTrue(result.OperationsLog.Count < 4, $"Interval: {interval}"); - - CleanUp(); - SetUp(); - } - } - - [TestMethod] - public void UploadFTPS_ConnectionTimeout() - { - var timeouts = new[] { 1, 100 }; - - foreach (var timeout in timeouts) - { - var connection = _connection; - connection.ConnectionTimeout = timeout; - - var result = FTP.UploadFiles(_source, _destination, connection, _options, _info, new CancellationToken()); - Assert.IsTrue(result.Success, $"Timeout: {timeout}"); - Assert.IsFalse(result.ActionSkipped, $"Timeout: {timeout}"); - Assert.AreEqual(1, result.SuccessfulTransferCount, $"Timeout: {timeout}"); - Assert.AreEqual(0, result.TransferErrors.Count, $"Timeout: {timeout}"); - Assert.AreEqual(1, result.TransferredFileNames.Count(), $"Timeout: {timeout}"); - Assert.AreEqual(1, result.TransferredFilePaths.Count(), $"Timeout: {timeout}"); - Assert.IsTrue(result.UserResultMessage.Contains("files transferred"), $"Timeout: {timeout}"); - Assert.IsTrue(result.OperationsLog.Count < 4, $"Timeout: {timeout}"); - - CleanUp(); - SetUp(); - } - } - - [TestMethod] - public void UploadFTPS_BufferSize() - { - var sizes = new[] { 1, 100, 1000, 10000 }; - - foreach (var size in sizes) - { - var connection = _connection; - connection.BufferSize = size; - - var result = FTP.UploadFiles(_source, _destination, connection, _options, _info, new CancellationToken()); - Assert.IsTrue(result.Success, $"Size: {size}"); - Assert.IsFalse(result.ActionSkipped, $"Size: {size}"); - Assert.AreEqual(1, result.SuccessfulTransferCount, $"Size: {size}"); - Assert.AreEqual(0, result.TransferErrors.Count, $"Size: {size}"); - Assert.AreEqual(1, result.TransferredFileNames.Count(), $"Size: {size}"); - Assert.AreEqual(1, result.TransferredFilePaths.Count(), $"Size: {size}"); - Assert.IsTrue(result.UserResultMessage.Contains("files transferred"), $"Size: {size}"); - Assert.IsTrue(result.OperationsLog.Count < 4, $"Size: {size}"); - - CleanUp(); - SetUp(); - } - } - - [TestMethod] - public void UploadFTPS_ValidateAnyCertificate() - { - var boo = new[] { true, false }; - - foreach (var bo in boo) - { - var connection = _connection; - connection.ValidateAnyCertificate = bo; - - var result = FTP.UploadFiles(_source, _destination, connection, _options, _info, new CancellationToken()); - Assert.IsTrue(result.Success, $"bo: {bo}"); - Assert.IsFalse(result.ActionSkipped, $"bo: {bo}"); - Assert.AreEqual(1, result.SuccessfulTransferCount, $"bo: {bo}"); - Assert.AreEqual(0, result.TransferErrors.Count, $"bo: {bo}"); - Assert.AreEqual(1, result.TransferredFileNames.Count(), $"bo: {bo}"); - Assert.AreEqual(1, result.TransferredFilePaths.Count(), $"bo: {bo}"); - Assert.IsTrue(result.UserResultMessage.Contains("files transferred"), $"bo: {bo}"); - Assert.IsTrue(result.OperationsLog.Count < 4, $"bo: {bo}"); - - CleanUp(); - SetUp(); - } - } - - [TestMethod] - public void UploadFTPS_FileNameAfterTransfer_Missing() - { - var source = _source; - source.FileNameAfterTransfer = ""; - - var result = FTP.UploadFiles(source, _destination, _connection, _options, _info, new CancellationToken()); - - Assert.IsTrue(result.Success); - Assert.IsTrue(result.UserResultMessage.Contains("files transferred")); - Assert.IsFalse(result.ActionSkipped); - Assert.AreEqual(1, result.SuccessfulTransferCount); - Assert.AreEqual(0, result.TransferErrors.Count); - Assert.AreEqual(1, result.TransferredFileNames.Count()); - Assert.AreEqual(1, result.TransferredFilePaths.Count()); - Assert.IsTrue(result.OperationsLog.Count < 4); - } - - [TestMethod] - public void UploadFTPS_DirectoryToMoveAfterTransfer_Missing() - { - var sourceOperations = new[] { SourceOperation.Move, SourceOperation.Delete, SourceOperation.Rename, SourceOperation.Nothing }; - - foreach (var sourceOperation in sourceOperations) - { - var source = _source; - source.DirectoryToMoveAfterTransfer = "DoesntExists"; - source.Operation = sourceOperation; - - var result = FTP.UploadFiles(source, _destination, _connection, _options, _info, new CancellationToken()); - - if (sourceOperation is SourceOperation.Move) - { - Assert.IsFalse(result.Success, $"operation: {sourceOperation}"); - Assert.IsTrue(result.UserResultMessage.Contains("not find"), $"operation: {sourceOperation}"); - Assert.IsFalse(result.ActionSkipped, $"operation: {sourceOperation}"); - Assert.AreEqual(0, result.SuccessfulTransferCount, $"operation: {sourceOperation}"); - Assert.AreEqual(1, result.TransferErrors.Count, $"operation: {sourceOperation}"); - Assert.AreEqual(0, result.TransferredFileNames.Count(), $"operation: {sourceOperation}"); - Assert.AreEqual(0, result.TransferredFilePaths.Count(), $"operation: {sourceOperation}"); - } - else - { - Assert.IsTrue(result.Success, $"operation: {sourceOperation}"); - Assert.IsTrue(result.UserResultMessage.Contains("files transferred"), $"operation: {sourceOperation}"); - Assert.IsFalse(result.ActionSkipped, $"operation: {sourceOperation}"); - Assert.AreEqual(1, result.SuccessfulTransferCount, $"operation: {sourceOperation}"); - Assert.AreEqual(0, result.TransferErrors.Count, $"operation: {sourceOperation}"); - Assert.AreEqual(1, result.TransferredFileNames.Count(), $"operation: {sourceOperation}"); - Assert.AreEqual(1, result.TransferredFilePaths.Count(), $"operation: {sourceOperation}"); - } - Assert.IsTrue(result.OperationsLog.Count < 4, $"operation: {sourceOperation}"); - - CleanUp(); - SetUp(); - } - } - - [TestMethod] - public void UploadFTPS_ThrowErrorOnFail() - { - var source = _source; - source.FileName = "DoesntExists"; - - var options = _options; - options.ThrowErrorOnFail = true; - - var ex = Assert.ThrowsException(() => FTP.UploadFiles(source, _destination, _connection, options, _info, new CancellationToken())); - Assert.AreEqual(typeof(Exception), ex.GetType()); - } - - [TestMethod] - public void UploadFTPS_PreserveLastModified() - { - var boo = new[] { true, false }; - - foreach (var bo in boo) - { - var options = _options; - options.PreserveLastModified = bo; - - var result = FTP.UploadFiles(_source, _destination, _connection, options, _info, new CancellationToken()); - Assert.IsTrue(result.Success, $"bo: {bo}"); - Assert.IsFalse(result.ActionSkipped, $"bo: {bo}"); - Assert.AreEqual(1, result.SuccessfulTransferCount, $"bo: {bo}"); - Assert.AreEqual(0, result.TransferErrors.Count, $"bo: {bo}"); - Assert.AreEqual(1, result.TransferredFileNames.Count(), $"bo: {bo}"); - Assert.AreEqual(1, result.TransferredFilePaths.Count(), $"bo: {bo}"); - Assert.IsTrue(result.UserResultMessage.Contains("files transferred"), $"bo: {bo}"); - Assert.IsTrue(result.OperationsLog.Count < 4, $"bo: {bo}"); - - CleanUp(); - SetUp(); - } - } - - [TestMethod] - public void UploadFTPS_OperationLog() - { - var boo = new[] { true, false }; - - foreach (var bo in boo) - { - var options = _options; - options.OperationLog = bo; - - var result = FTP.UploadFiles(_source, _destination, _connection, options, _info, new CancellationToken()); - Assert.IsTrue(result.Success, $"bo: {bo}"); - Assert.IsFalse(result.ActionSkipped, $"bo: {bo}"); - Assert.AreEqual(1, result.SuccessfulTransferCount, $"bo: {bo}"); - Assert.AreEqual(0, result.TransferErrors.Count, $"bo: {bo}"); - Assert.AreEqual(1, result.TransferredFileNames.Count(), $"bo: {bo}"); - Assert.AreEqual(1, result.TransferredFilePaths.Count(), $"bo: {bo}"); - Assert.IsTrue(result.UserResultMessage.Contains("files transferred"), $"bo: {bo}"); - Assert.IsTrue(result.OperationsLog.Count < 4, $"bo: {bo}"); - - CleanUp(); - SetUp(); - } - } - +using FluentFTP; +using Frends.FTP.UploadFiles.Enums; +using Frends.FTP.UploadFiles.TaskConfiguration; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; +using System.IO; +using System.Linq; +using System.Security.Authentication; +using System.Threading; + +namespace Frends.FTP.UploadFiles.Tests; + +[TestClass] +public class UploadFilesTests +{ + private string _tempDir; + private readonly string _file = "file1.txt"; + + private Source _source = new(); + private Connection _connection = new(); + private Destination _destination = new(); + private Options _options = new(); + private Info _info = new(); + + [TestInitialize] + public void SetUp() + { + _tempDir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "../../../tempFiles"); + Directory.CreateDirectory(_tempDir); + File.WriteAllText(Path.Combine(_tempDir, _file), "test"); + Directory.CreateDirectory(Path.Combine(_tempDir, "Done")); + + _source = new() + { + Directory = _tempDir, + FileName = _file, + DirectoryToMoveAfterTransfer = Path.Combine(_tempDir, "Done"), + FileNameAfterTransfer = _file + Guid.NewGuid().ToString(), + NotFoundAction = default, + FilePaths = _tempDir, + Operation = default, + }; + + _connection = new() + { + Address = Helpers.FtpHost, + UserName = Helpers.FtpUsername, + Password = Helpers.FtpPassword, + Port = Helpers.FtpPort, + TransportType = default, + Mode = default, + KeepConnectionAliveInterval = default, + ConnectionTimeout = 60, + Encoding = default, + BufferSize = default, + UseFTPS = false, + SslMode = default, + CertificateHashStringSHA1 = "D911262984DE9CC32A3518A1094CD24249EA5C49", + EnableClientAuth = default, + ValidateAnyCertificate = default, + ClientCertificatePath = default, + SecureDataChannel = false, + }; + + _destination = new() + { + Directory = "/", + Action = default, + FileName = $"{_file}-{Guid.NewGuid()}", + }; + + _options = new() + { + CreateDestinationDirectories = true, + OperationLog = default, + PreserveLastModified = default, + RenameDestinationFileDuringTransfer = default, + RenameSourceFileBeforeTransfer = default, + ThrowErrorOnFail = default, + }; + + _info = new() + { + ProcessUri = default, + TaskExecutionID = default, + TransferName = default, + WorkDir = default, + }; + } + + [TestCleanup] + public void CleanUp() + { + if (Directory.Exists(_tempDir)) + Directory.Delete(_tempDir, true); + + var client = new FtpClient(Helpers.FtpHost, Helpers.FtpPort, Helpers.FtpUsername, Helpers.FtpPassword) + { + ConnectTimeout = 10 + }; + client.Connect(); + if (client.DirectoryExists("/")) + client.DeleteDirectory("/"); + client.Disconnect(); + client.Dispose(); + } + + [TestMethod] + public void UploadFTPS_IncorrectFingerprint() + { + var connection = _connection; + connection.SslMode = FtpsSslMode.Explicit; + connection.UseFTPS = true; + connection.CertificateHashStringSHA1 = "incorrect"; + + // Test and assert + var ex = Assert.ThrowsException(() => FTP.UploadFiles(_source, _destination, connection, _options, _info, new CancellationToken())); + Assert.AreEqual(1, ex.InnerExceptions.Count); + Assert.AreEqual(typeof(AuthenticationException), ex.InnerExceptions[0].GetType()); + } + + [TestMethod] + public void UploadFTPS_IncorrectAuth() + { + var connectionA = _connection; + connectionA.Address = null; + + var connectionB = _connection; + connectionB.Port = 0; + + var connectionC = _connection; + connectionC.Password = null; + + var connectionD = _connection; + connectionD.UserName = null; + + var ex1 = Assert.ThrowsException(() => FTP.UploadFiles(_source, _destination, connectionA, _options, _info, new CancellationToken())); + Assert.AreEqual(typeof(NullReferenceException), ex1.GetType()); + + var ex2 = Assert.ThrowsException(() => FTP.UploadFiles(_source, _destination, connectionB, _options, _info, new CancellationToken())); + Assert.AreEqual(typeof(NullReferenceException), ex2.GetType()); + + var ex3 = Assert.ThrowsException(() => FTP.UploadFiles(_source, _destination, connectionC, _options, _info, new CancellationToken())); + Assert.AreEqual(typeof(NullReferenceException), ex3.GetType()); + + var ex4 = Assert.ThrowsException(() => FTP.UploadFiles(_source, _destination, connectionD, _options, _info, new CancellationToken())); + Assert.AreEqual(typeof(NullReferenceException), ex4.GetType()); + } + + [TestMethod] + public void UploadFTP_UploadFile() + { + var result = FTP.UploadFiles(_source, _destination, _connection, _options, _info, new CancellationToken()); + Assert.IsTrue(result.Success); + Assert.AreEqual(1, result.SuccessfulTransferCount); + } + + [TestMethod] + public void UploadFTPS_DestinationActions() + { + var destinationActions = new[] { DestinationAction.Error, DestinationAction.Overwrite, DestinationAction.Append }; + + foreach (var destinationAction in destinationActions) + { + var destination = _destination; + destination.Action = destinationAction; + + var result = FTP.UploadFiles(_source, destination, _connection, _options, _info, new CancellationToken()); + Assert.IsTrue(result.Success, $"DestinationAction: {destinationAction}"); + Assert.IsFalse(result.ActionSkipped, $"DestinationAction: {destinationAction}"); + Assert.AreEqual(1, result.SuccessfulTransferCount, $"DestinationAction: {destinationAction}"); + Assert.AreEqual(0, result.TransferErrors.Count, $"DestinationAction: {destinationAction}"); + Assert.AreEqual(1, result.TransferredFileNames.Count(), $"DestinationAction: {destinationAction}"); + Assert.AreEqual(1, result.TransferredFilePaths.Count(), $"DestinationAction: {destinationAction}"); + Assert.IsTrue(result.UserResultMessage.Contains("files transferred"), $"DestinationAction: {destinationAction}"); + Assert.IsTrue(result.OperationsLog.Count < 4, $"DestinationAction: {destinationAction}"); + + CleanUp(); + SetUp(); + } + } + + [TestMethod] + public void UploadFTPS_FtpMode() + { + var ftpModes = new[] { FtpMode.Active, FtpMode.Passive }; + + foreach (var ftpMode in ftpModes) + { + var connection = _connection; + connection.Mode = ftpMode; + + var result = FTP.UploadFiles(_source, _destination, connection, _options, _info, new CancellationToken()); + if (ftpMode is FtpMode.Active) + { + Assert.IsFalse(result.Success); + Assert.IsTrue(result.UserResultMessage.Contains("Error: Error while uploading the file to the server. See InnerException for more info."), $"FtpMode: {ftpMode}"); + Assert.IsFalse(result.ActionSkipped, $"FtpMode: {ftpMode}"); + Assert.AreEqual(0, result.SuccessfulTransferCount, $"FtpMode: {ftpMode}"); + Assert.AreEqual(1, result.TransferErrors.Count, $"FtpMode: {ftpMode}"); + Assert.AreEqual(0, result.TransferredFileNames.Count(), $"FtpMode: {ftpMode}"); + Assert.AreEqual(0, result.TransferredFilePaths.Count(), $"FtpMode: {ftpMode}"); + } + else + { + Assert.IsTrue(result.Success, $"FtpMode: {ftpMode}"); + Assert.IsFalse(result.ActionSkipped, $"FtpMode: {ftpMode}"); + Assert.AreEqual(1, result.SuccessfulTransferCount, $"FtpMode: {ftpMode}"); + Assert.AreEqual(0, result.TransferErrors.Count, $"FtpMode: {ftpMode}"); + Assert.AreEqual(1, result.TransferredFileNames.Count(), $"FtpMode: {ftpMode}"); + Assert.AreEqual(1, result.TransferredFilePaths.Count(), $"FtpMode: {ftpMode}"); + Assert.IsTrue(result.UserResultMessage.Contains("files transferred"), $"FtpMode: {ftpMode}"); + } + Assert.IsTrue(result.OperationsLog.Count < 4, $"FtpMode: {ftpMode}"); + + CleanUp(); + SetUp(); + } + } + + [TestMethod] + public void UploadFTPS_FtpsSslModes() + { + var ftpsSslModes = new[] { FtpsSslMode.None, FtpsSslMode.Explicit, FtpsSslMode.Auto }; + + foreach (var ftpsSslMode in ftpsSslModes) + { + var connection = _connection; + connection.SslMode = ftpsSslMode; + connection.UseFTPS = true; + + var result = FTP.UploadFiles(_source, _destination, connection, _options, _info, new CancellationToken()); + Assert.IsTrue(result.Success, $"FtpsSslMode: {ftpsSslMode}"); + Assert.IsFalse(result.ActionSkipped, $"FtpsSslMode: {ftpsSslMode}"); + Assert.AreEqual(1, result.SuccessfulTransferCount, $"FtpsSslMode: {ftpsSslMode}"); + Assert.AreEqual(0, result.TransferErrors.Count, $"FtpsSslMode: {ftpsSslMode}"); + Assert.AreEqual(1, result.TransferredFileNames.Count(), $"FtpsSslMode: {ftpsSslMode}"); + Assert.AreEqual(1, result.TransferredFilePaths.Count(), $"FtpsSslMode: {ftpsSslMode}"); + Assert.IsTrue(result.UserResultMessage.Contains("files transferred"), $"FtpsSslMode: {ftpsSslMode}"); + Assert.IsTrue(result.OperationsLog.Count < 4, $"FtpsSslMode: {ftpsSslMode}"); + + CleanUp(); + SetUp(); + } + } + + [TestMethod] + public void UploadFTPS_SecureDataChannel() + { + var boo = new[] { true, false }; + + foreach (var bo in boo) + { + var connection = _connection; + connection.SecureDataChannel = bo; + + var result = FTP.UploadFiles(_source, _destination, connection, _options, _info, new CancellationToken()); + Assert.IsTrue(result.Success, $"Bo: {bo}"); + Assert.IsFalse(result.ActionSkipped, $"Bo: {bo}"); + Assert.AreEqual(1, result.SuccessfulTransferCount, $"Bo: {bo}"); + Assert.AreEqual(0, result.TransferErrors.Count, $"Bo: {bo}"); + Assert.AreEqual(1, result.TransferredFileNames.Count(), $"Bo: {bo}"); + Assert.AreEqual(1, result.TransferredFilePaths.Count(), $"Bo: {bo}"); + Assert.IsTrue(result.UserResultMessage.Contains("files transferred"), $"Bo: {bo}"); + Assert.IsTrue(result.OperationsLog.Count < 4, $"Bo: {bo}"); + + CleanUp(); + SetUp(); + } + } + + [TestMethod] + public void UploadFTPS_FtpTransportTypes() + { + var ftpTransportTypes = new[] { FtpTransportType.Binary, FtpTransportType.Ascii }; + + foreach (var ftpTransportType in ftpTransportTypes) + { + var connection = _connection; + connection.TransportType = ftpTransportType; + + var result = FTP.UploadFiles(_source, _destination, connection, _options, _info, new CancellationToken()); + Assert.IsTrue(result.Success, $"FtpTransportType: {ftpTransportType}"); + Assert.IsFalse(result.ActionSkipped, $"FtpTransportType: {ftpTransportType}"); + Assert.AreEqual(1, result.SuccessfulTransferCount, $"FtpTransportType: {ftpTransportType}"); + Assert.AreEqual(0, result.TransferErrors.Count, $"FtpTransportType: {ftpTransportType}"); + Assert.AreEqual(1, result.TransferredFileNames.Count(), $"FtpTransportType: {ftpTransportType}"); + Assert.AreEqual(1, result.TransferredFilePaths.Count(), $"FtpTransportType: {ftpTransportType}"); + Assert.IsTrue(result.UserResultMessage.Contains("files transferred"), $"FtpTransportType: {ftpTransportType}"); + Assert.IsTrue(result.OperationsLog.Count < 4, $"FtpTransportType: {ftpTransportType}"); + + CleanUp(); + SetUp(); + } + } + [TestMethod] - public void UploadFTPS_LocalMachineHasNoCertificates() + public void UploadFTPS_NotFoundActions() + { + var notFoundActions = new[] { SourceNotFoundAction.Error, SourceNotFoundAction.Ignore, SourceNotFoundAction.Info }; + + foreach (var notFoundAction in notFoundActions) + { + var source = _source; + source.NotFoundAction = notFoundAction; + source.FileName = ""; + + var result = FTP.UploadFiles(source, _destination, _connection, _options, _info, new CancellationToken()); + + if (notFoundAction is SourceNotFoundAction.Error) + { + Assert.IsFalse(result.Success, $"action: {notFoundAction}"); + Assert.IsFalse(result.ActionSkipped, $"action: {notFoundAction}"); + Assert.AreEqual(0, result.SuccessfulTransferCount, $"action: {notFoundAction}"); + Assert.AreEqual(1, result.TransferErrors.Count, $"action: {notFoundAction}"); + Assert.AreEqual(0, result.TransferredFileNames.Count(), $"action: {notFoundAction}"); + Assert.AreEqual(0, result.TransferredFilePaths.Count(), $"action: {notFoundAction}"); + + } + else + { + Assert.IsTrue(result.Success, $"action: {notFoundAction}"); + Assert.IsTrue(result.ActionSkipped, $"action: {notFoundAction}"); + Assert.AreEqual(0, result.SuccessfulTransferCount, $"action: {notFoundAction}"); + Assert.AreEqual(0, result.TransferErrors.Count, $"action: {notFoundAction}"); + Assert.AreEqual(0, result.TransferredFileNames.Count(), $"action: {notFoundAction}"); + Assert.AreEqual(0, result.TransferredFilePaths.Count(), $"action: {notFoundAction}"); + + } + Assert.IsTrue(result.UserResultMessage.Contains("No source files found"), $"action: {notFoundAction}"); + Assert.IsTrue(result.OperationsLog.Count < 4, $"action: {notFoundAction}"); + + CleanUp(); + SetUp(); + } + } + + [TestMethod] + public void UploadFTPS_SourceOperations() + { + var sourceOperations = new[] { SourceOperation.Move, SourceOperation.Delete, SourceOperation.Rename, SourceOperation.Nothing }; + + foreach (var sourceOperation in sourceOperations) + { + var source = _source; + source.Operation = sourceOperation; + + var result = FTP.UploadFiles(source, _destination, _connection, _options, _info, new CancellationToken()); + Assert.IsTrue(result.Success, $"SourceOperation: {sourceOperation}"); + Assert.IsFalse(result.ActionSkipped, $"SourceOperation: {sourceOperation}"); + Assert.AreEqual(1, result.SuccessfulTransferCount, $"SourceOperation: {sourceOperation}"); + Assert.AreEqual(0, result.TransferErrors.Count, $"SourceOperation: {sourceOperation}"); + Assert.AreEqual(1, result.TransferredFileNames.Count(), $"SourceOperation: {sourceOperation}"); + Assert.AreEqual(1, result.TransferredFilePaths.Count(), $"SourceOperation: {sourceOperation}"); + Assert.IsTrue(result.UserResultMessage.Contains("files transferred"), $"SourceOperation: {sourceOperation}"); + Assert.IsTrue(result.OperationsLog.Count < 4, $"SourceOperation: {sourceOperation}"); + + CleanUp(); + SetUp(); + } + } + + [TestMethod] + public void UploadFTPS_FileEncodings() + { + var fileEncodings = new[] { "UTF-8", "ASCII", "foobar123", string.Empty }; + + foreach (var fileEncoding in fileEncodings) + { + var connection = _connection; + connection.Encoding = fileEncoding; + + if (connection.Encoding.Equals("foobar123")) + { + var ex = Assert.ThrowsException(() => FTP.UploadFiles(_source, _destination, connection, _options, _info, new CancellationToken())); + Assert.IsTrue(ex.Message.Contains("is not a supported encoding name"), $"FileEncoding: {fileEncoding}"); + } + else + { + var result = FTP.UploadFiles(_source, _destination, connection, _options, _info, new CancellationToken()); + Assert.IsTrue(result.Success, $"FileEncoding: {fileEncoding}"); + Assert.IsFalse(result.ActionSkipped, $"FileEncoding: {fileEncoding}"); + Assert.AreEqual(1, result.SuccessfulTransferCount, $"FileEncoding: {fileEncoding}"); + Assert.AreEqual(0, result.TransferErrors.Count, $"FileEncoding: {fileEncoding}"); + Assert.AreEqual(1, result.TransferredFileNames.Count(), $"FileEncoding: {fileEncoding}"); + Assert.AreEqual(1, result.TransferredFilePaths.Count(), $"FileEncoding: {fileEncoding}"); + Assert.IsTrue(result.UserResultMessage.Contains("files transferred"), $"FileEncoding: {fileEncoding}"); + Assert.IsTrue(result.OperationsLog.Count < 4, $"FileEncoding: {fileEncoding}"); + } + + CleanUp(); + SetUp(); + } + } + + [TestMethod] + public void UploadFTPS_Port() + { + var ports = new[] { 0, 21, 210 }; + + foreach (var port in ports) + { + var connection = _connection; + connection.Port = port; + + var result = FTP.UploadFiles(_source, _destination, connection, _options, _info, new CancellationToken()); + if (port == 210) + { + Assert.IsFalse(result.Success, $"Port: {port}"); + Assert.IsTrue(result.ActionSkipped, $"Port: {port}"); + Assert.AreEqual(0, result.SuccessfulTransferCount, $"Port: {port}"); + Assert.AreEqual(0, result.TransferErrors.Count, $"Port: {port}"); + Assert.AreEqual(0, result.TransferredFileNames.Count(), $"Port: {port}"); + Assert.AreEqual(0, result.TransferredFilePaths.Count(), $"Port: {port}"); + Assert.IsTrue(result.UserResultMessage.Contains("Unable to establish the socket: No such host is known."), $"Port: {port}"); + Assert.IsTrue(result.OperationsLog.Count < 4, $"Port: {port}"); + } + else + { + Assert.IsTrue(result.Success, $"Port: {port}"); + Assert.IsFalse(result.ActionSkipped, $"Port: {port}"); + Assert.AreEqual(1, result.SuccessfulTransferCount, $"Port: {port}"); + Assert.AreEqual(0, result.TransferErrors.Count, $"Port: {port}"); + Assert.AreEqual(1, result.TransferredFileNames.Count(), $"Port: {port}"); + Assert.AreEqual(1, result.TransferredFilePaths.Count(), $"Port: {port}"); + Assert.IsTrue(result.UserResultMessage.Contains("files transferred"), $"Port: {port}"); + Assert.IsTrue(result.OperationsLog.Count < 4, $"Port: {port}"); + } + + CleanUp(); + SetUp(); + } + } + + [TestMethod] + public void UploadFTPS_KeepConnectionAliveInterval() + { + var intervals = new[] { 0, 1, 100 }; + + foreach (var interval in intervals) + { + var connection = _connection; + connection.KeepConnectionAliveInterval = interval; + + var result = FTP.UploadFiles(_source, _destination, connection, _options, _info, new CancellationToken()); + Assert.IsTrue(result.Success, $"Interval: {interval}"); + Assert.IsFalse(result.ActionSkipped, $"Interval: {interval}"); + Assert.AreEqual(1, result.SuccessfulTransferCount, $"Interval: {interval}"); + Assert.AreEqual(0, result.TransferErrors.Count, $"Interval: {interval}"); + Assert.AreEqual(1, result.TransferredFileNames.Count(), $"Interval: {interval}"); + Assert.AreEqual(1, result.TransferredFilePaths.Count(), $"Interval: {interval}"); + Assert.IsTrue(result.UserResultMessage.Contains("files transferred"), $"Interval: {interval}"); + Assert.IsTrue(result.OperationsLog.Count < 4, $"Interval: {interval}"); + + CleanUp(); + SetUp(); + } + } + + [TestMethod] + public void UploadFTPS_ConnectionTimeout() + { + var timeouts = new[] { 1, 100 }; + + foreach (var timeout in timeouts) + { + var connection = _connection; + connection.ConnectionTimeout = timeout; + + var result = FTP.UploadFiles(_source, _destination, connection, _options, _info, new CancellationToken()); + Assert.IsTrue(result.Success, $"Timeout: {timeout}"); + Assert.IsFalse(result.ActionSkipped, $"Timeout: {timeout}"); + Assert.AreEqual(1, result.SuccessfulTransferCount, $"Timeout: {timeout}"); + Assert.AreEqual(0, result.TransferErrors.Count, $"Timeout: {timeout}"); + Assert.AreEqual(1, result.TransferredFileNames.Count(), $"Timeout: {timeout}"); + Assert.AreEqual(1, result.TransferredFilePaths.Count(), $"Timeout: {timeout}"); + Assert.IsTrue(result.UserResultMessage.Contains("files transferred"), $"Timeout: {timeout}"); + Assert.IsTrue(result.OperationsLog.Count < 4, $"Timeout: {timeout}"); + + CleanUp(); + SetUp(); + } + } + + [TestMethod] + public void UploadFTPS_BufferSize() + { + var sizes = new[] { 1, 100, 1000, 10000 }; + + foreach (var size in sizes) + { + var connection = _connection; + connection.BufferSize = size; + + var result = FTP.UploadFiles(_source, _destination, connection, _options, _info, new CancellationToken()); + Assert.IsTrue(result.Success, $"Size: {size}"); + Assert.IsFalse(result.ActionSkipped, $"Size: {size}"); + Assert.AreEqual(1, result.SuccessfulTransferCount, $"Size: {size}"); + Assert.AreEqual(0, result.TransferErrors.Count, $"Size: {size}"); + Assert.AreEqual(1, result.TransferredFileNames.Count(), $"Size: {size}"); + Assert.AreEqual(1, result.TransferredFilePaths.Count(), $"Size: {size}"); + Assert.IsTrue(result.UserResultMessage.Contains("files transferred"), $"Size: {size}"); + Assert.IsTrue(result.OperationsLog.Count < 4, $"Size: {size}"); + + CleanUp(); + SetUp(); + } + } + + [TestMethod] + public void UploadFTPS_ValidateAnyCertificate() + { + var boo = new[] { true, false }; + + foreach (var bo in boo) + { + var connection = _connection; + connection.ValidateAnyCertificate = bo; + + var result = FTP.UploadFiles(_source, _destination, connection, _options, _info, new CancellationToken()); + Assert.IsTrue(result.Success, $"bo: {bo}"); + Assert.IsFalse(result.ActionSkipped, $"bo: {bo}"); + Assert.AreEqual(1, result.SuccessfulTransferCount, $"bo: {bo}"); + Assert.AreEqual(0, result.TransferErrors.Count, $"bo: {bo}"); + Assert.AreEqual(1, result.TransferredFileNames.Count(), $"bo: {bo}"); + Assert.AreEqual(1, result.TransferredFilePaths.Count(), $"bo: {bo}"); + Assert.IsTrue(result.UserResultMessage.Contains("files transferred"), $"bo: {bo}"); + Assert.IsTrue(result.OperationsLog.Count < 4, $"bo: {bo}"); + + CleanUp(); + SetUp(); + } + } + + [TestMethod] + public void UploadFTPS_FileNameAfterTransfer_Missing() + { + var source = _source; + source.FileNameAfterTransfer = ""; + + var result = FTP.UploadFiles(source, _destination, _connection, _options, _info, new CancellationToken()); + + Assert.IsTrue(result.Success); + Assert.IsTrue(result.UserResultMessage.Contains("files transferred")); + Assert.IsFalse(result.ActionSkipped); + Assert.AreEqual(1, result.SuccessfulTransferCount); + Assert.AreEqual(0, result.TransferErrors.Count); + Assert.AreEqual(1, result.TransferredFileNames.Count()); + Assert.AreEqual(1, result.TransferredFilePaths.Count()); + Assert.IsTrue(result.OperationsLog.Count < 4); + } + + [TestMethod] + public void UploadFTPS_DirectoryToMoveAfterTransfer_Missing() + { + var sourceOperations = new[] { SourceOperation.Move, SourceOperation.Delete, SourceOperation.Rename, SourceOperation.Nothing }; + + foreach (var sourceOperation in sourceOperations) + { + var source = _source; + source.DirectoryToMoveAfterTransfer = "DoesntExists"; + source.Operation = sourceOperation; + + var result = FTP.UploadFiles(source, _destination, _connection, _options, _info, new CancellationToken()); + + if (sourceOperation is SourceOperation.Move) + { + Assert.IsFalse(result.Success, $"operation: {sourceOperation}"); + Assert.IsTrue(result.UserResultMessage.Contains("not find"), $"operation: {sourceOperation}"); + Assert.IsFalse(result.ActionSkipped, $"operation: {sourceOperation}"); + Assert.AreEqual(0, result.SuccessfulTransferCount, $"operation: {sourceOperation}"); + Assert.AreEqual(1, result.TransferErrors.Count, $"operation: {sourceOperation}"); + Assert.AreEqual(0, result.TransferredFileNames.Count(), $"operation: {sourceOperation}"); + Assert.AreEqual(0, result.TransferredFilePaths.Count(), $"operation: {sourceOperation}"); + } + else + { + Assert.IsTrue(result.Success, $"operation: {sourceOperation}"); + Assert.IsTrue(result.UserResultMessage.Contains("files transferred"), $"operation: {sourceOperation}"); + Assert.IsFalse(result.ActionSkipped, $"operation: {sourceOperation}"); + Assert.AreEqual(1, result.SuccessfulTransferCount, $"operation: {sourceOperation}"); + Assert.AreEqual(0, result.TransferErrors.Count, $"operation: {sourceOperation}"); + Assert.AreEqual(1, result.TransferredFileNames.Count(), $"operation: {sourceOperation}"); + Assert.AreEqual(1, result.TransferredFilePaths.Count(), $"operation: {sourceOperation}"); + } + Assert.IsTrue(result.OperationsLog.Count < 4, $"operation: {sourceOperation}"); + + CleanUp(); + SetUp(); + } + } + + [TestMethod] + public void UploadFTPS_ThrowErrorOnFail() + { + var source = _source; + source.FileName = "DoesntExists"; + + var options = _options; + options.ThrowErrorOnFail = true; + + var ex = Assert.ThrowsException(() => FTP.UploadFiles(source, _destination, _connection, options, _info, new CancellationToken())); + Assert.AreEqual(typeof(Exception), ex.GetType()); + } + + [TestMethod] + public void UploadFTPS_PreserveLastModified() + { + var boo = new[] { true, false }; + + foreach (var bo in boo) + { + var options = _options; + options.PreserveLastModified = bo; + + var result = FTP.UploadFiles(_source, _destination, _connection, options, _info, new CancellationToken()); + Assert.IsTrue(result.Success, $"bo: {bo}"); + Assert.IsFalse(result.ActionSkipped, $"bo: {bo}"); + Assert.AreEqual(1, result.SuccessfulTransferCount, $"bo: {bo}"); + Assert.AreEqual(0, result.TransferErrors.Count, $"bo: {bo}"); + Assert.AreEqual(1, result.TransferredFileNames.Count(), $"bo: {bo}"); + Assert.AreEqual(1, result.TransferredFilePaths.Count(), $"bo: {bo}"); + Assert.IsTrue(result.UserResultMessage.Contains("files transferred"), $"bo: {bo}"); + Assert.IsTrue(result.OperationsLog.Count < 4, $"bo: {bo}"); + + CleanUp(); + SetUp(); + } + } + + [TestMethod] + public void UploadFTPS_OperationLog() + { + var boo = new[] { true, false }; + + foreach (var bo in boo) + { + var options = _options; + options.OperationLog = bo; + + var result = FTP.UploadFiles(_source, _destination, _connection, options, _info, new CancellationToken()); + Assert.IsTrue(result.Success, $"bo: {bo}"); + Assert.IsFalse(result.ActionSkipped, $"bo: {bo}"); + Assert.AreEqual(1, result.SuccessfulTransferCount, $"bo: {bo}"); + Assert.AreEqual(0, result.TransferErrors.Count, $"bo: {bo}"); + Assert.AreEqual(1, result.TransferredFileNames.Count(), $"bo: {bo}"); + Assert.AreEqual(1, result.TransferredFilePaths.Count(), $"bo: {bo}"); + Assert.IsTrue(result.UserResultMessage.Contains("files transferred"), $"bo: {bo}"); + Assert.IsTrue(result.OperationsLog.Count < 4, $"bo: {bo}"); + + CleanUp(); + SetUp(); + } + } + + [TestMethod] + public void UploadFTPS_CurrentUserHasNoCertificates() { var connection = new Connection { @@ -675,24 +675,23 @@ public void UploadFTPS_LocalMachineHasNoCertificates() var ex = Assert.ThrowsException(() => { var result = FTP.UploadFiles(_source, _destination, connection, new Options(), new Info(), - new CancellationToken()); + default); }); - Assert.AreEqual("Unix LocalMachine X509Store is limited to the Root and Certif", ex.Message); + Assert.AreEqual("Unix LocalMachine X509Store is limited to the Root and Certificate", ex.Message); } else { var ex = Assert.ThrowsException(() => { var result = FTP.UploadFiles(_source, _destination, connection, new Options(), new Info(), - new CancellationToken()); + default); }); Assert.AreEqual(1, ex.InnerExceptions.Count); Assert.AreEqual(typeof(AuthenticationException), ex.InnerExceptions[0].GetType()); } - - } + } } \ No newline at end of file diff --git a/Frends.FTP.UploadFiles/Frends.FTP.UploadFiles/Definitions/FileTransporter.cs b/Frends.FTP.UploadFiles/Frends.FTP.UploadFiles/Definitions/FileTransporter.cs index 03804dc..27d8919 100644 --- a/Frends.FTP.UploadFiles/Frends.FTP.UploadFiles/Definitions/FileTransporter.cs +++ b/Frends.FTP.UploadFiles/Frends.FTP.UploadFiles/Definitions/FileTransporter.cs @@ -107,8 +107,6 @@ public FileTransferResult Run(CancellationToken cancellationToken) client.SetWorkingDirectory(_destinationDirectoryWithMacrosExpanded); - //_batchContext.DestinationFiles = client.GetListing("."); - foreach (var file in files) { // Check that the connection is alive and if not try to connect again @@ -169,15 +167,17 @@ private static FtpClient CreateFtpClient(Connection connect) } else { - X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine); - try - { - store.Open(OpenFlags.ReadOnly); - client.ClientCertificates.AddRange(store.Certificates); - } - finally + using (X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser)) { - store.Close(); + try + { + store.Open(OpenFlags.ReadOnly); + client.ClientCertificates.AddRange(store.Certificates); + } + finally + { + store.Close(); + } } } } From 38e1315e8bbc4fb3f11a4ad76360dc441c6b7b52 Mon Sep 17 00:00:00 2001 From: Riku Virtanen Date: Thu, 21 Sep 2023 10:44:38 +0300 Subject: [PATCH 4/6] Finished implementation --- Frends.FTP.UploadFiles/CHANGELOG.md | 3 +- .../UploadFilesTests.cs | 30 ++++++------------- .../Definitions/FileTransporter.cs | 7 ++++- .../Frends.FTP.UploadFiles.csproj | 2 +- .../TaskConfiguration/Connection.cs | 16 ++++++++++ 5 files changed, 34 insertions(+), 24 deletions(-) diff --git a/Frends.FTP.UploadFiles/CHANGELOG.md b/Frends.FTP.UploadFiles/CHANGELOG.md index 50b125e..8d06038 100644 --- a/Frends.FTP.UploadFiles/CHANGELOG.md +++ b/Frends.FTP.UploadFiles/CHANGELOG.md @@ -1,8 +1,9 @@ # Changelog -## [1.0.3] - 2023-09-12 +## [1.1.0] - 2023-09-12 ### Added - Added search for local certificates from machine certification store. +- [Breaking] Added parameters ClientCertificationName and ClientCertificationThumbprint for exclusive search of client certification. ## [1.0.2] - 2023-08-03 ### Added diff --git a/Frends.FTP.UploadFiles/Frends.FTP.UploadFiles.Tests/UploadFilesTests.cs b/Frends.FTP.UploadFiles/Frends.FTP.UploadFiles.Tests/UploadFilesTests.cs index 60ef637..9150216 100644 --- a/Frends.FTP.UploadFiles/Frends.FTP.UploadFiles.Tests/UploadFilesTests.cs +++ b/Frends.FTP.UploadFiles/Frends.FTP.UploadFiles.Tests/UploadFilesTests.cs @@ -667,31 +667,19 @@ public void UploadFTPS_CurrentUserHasNoCertificates() UseFTPS = true, ValidateAnyCertificate = false, CertificateHashStringSHA1 = "", - ClientCertificatePath = "" + ClientCertificatePath = "", + ClientCertificateName = "", + ClientCertificateThumbprint = "" }; - if (Environment.OSVersion.Platform == PlatformID.Unix) + var ex = Assert.ThrowsException(() => { - var ex = Assert.ThrowsException(() => - { - var result = FTP.UploadFiles(_source, _destination, connection, new Options(), new Info(), - default); - - }); + var result = FTP.UploadFiles(_source, _destination, connection, new Options(), new Info(), + default); - Assert.AreEqual("Unix LocalMachine X509Store is limited to the Root and Certificate", ex.Message); - } - else - { - var ex = Assert.ThrowsException(() => - { - var result = FTP.UploadFiles(_source, _destination, connection, new Options(), new Info(), - default); + }); - }); - - Assert.AreEqual(1, ex.InnerExceptions.Count); - Assert.AreEqual(typeof(AuthenticationException), ex.InnerExceptions[0].GetType()); - } + Assert.AreEqual(1, ex.InnerExceptions.Count); + Assert.AreEqual(typeof(AuthenticationException), ex.InnerExceptions[0].GetType()); } } \ No newline at end of file diff --git a/Frends.FTP.UploadFiles/Frends.FTP.UploadFiles/Definitions/FileTransporter.cs b/Frends.FTP.UploadFiles/Frends.FTP.UploadFiles/Definitions/FileTransporter.cs index 27d8919..ff6b0f0 100644 --- a/Frends.FTP.UploadFiles/Frends.FTP.UploadFiles/Definitions/FileTransporter.cs +++ b/Frends.FTP.UploadFiles/Frends.FTP.UploadFiles/Definitions/FileTransporter.cs @@ -172,7 +172,12 @@ private static FtpClient CreateFtpClient(Connection connect) try { store.Open(OpenFlags.ReadOnly); - client.ClientCertificates.AddRange(store.Certificates); + if (!string.IsNullOrEmpty(connect.ClientCertificateName)) + client.ClientCertificates.Add(store.Certificates.Find(X509FindType.FindBySubjectName, connect.ClientCertificateName, false).First()); + else if (!string.IsNullOrEmpty(connect.ClientCertificateThumbprint)) + client.ClientCertificates.Add(store.Certificates.Find(X509FindType.FindByThumbprint, connect.ClientCertificateThumbprint, false).First()); + else + client.ClientCertificates.AddRange(store.Certificates); } finally { diff --git a/Frends.FTP.UploadFiles/Frends.FTP.UploadFiles/Frends.FTP.UploadFiles.csproj b/Frends.FTP.UploadFiles/Frends.FTP.UploadFiles/Frends.FTP.UploadFiles.csproj index 74dcf05..8a83024 100644 --- a/Frends.FTP.UploadFiles/Frends.FTP.UploadFiles/Frends.FTP.UploadFiles.csproj +++ b/Frends.FTP.UploadFiles/Frends.FTP.UploadFiles/Frends.FTP.UploadFiles.csproj @@ -9,7 +9,7 @@ true Frends true - 1.0.3 + 1.1.0 Task for uploading files to FTP(S) servers. diff --git a/Frends.FTP.UploadFiles/Frends.FTP.UploadFiles/TaskConfiguration/Connection.cs b/Frends.FTP.UploadFiles/Frends.FTP.UploadFiles/TaskConfiguration/Connection.cs index e04bbcd..aecc5b5 100644 --- a/Frends.FTP.UploadFiles/Frends.FTP.UploadFiles/TaskConfiguration/Connection.cs +++ b/Frends.FTP.UploadFiles/Frends.FTP.UploadFiles/TaskConfiguration/Connection.cs @@ -146,6 +146,22 @@ public class Connection [UIHint(nameof(UseFTPS), "", true)] public bool EnableClientAuth { get; set; } + /// + /// Optional. Enables certification search by name from the certification store of current user. + /// + /// mycert.crt + [DefaultValue("")] + [UIHint(nameof(EnableClientAuth), "", true)] + public string ClientCertificateName { get; set; } + + /// + /// Optional. Enables certification search by thumbprint from the certification store of current user. + /// + /// a909502dd82ae41433e6f83886b00d4277a32a7b + [DefaultValue("")] + [UIHint(nameof(EnableClientAuth), "", true)] + public string ClientCertificateThumbprint { get; set; } + /// /// If enabled the any certificate will be considered valid. /// From 610b3b1b795cb581dd2117cfa7829a86524e59ba Mon Sep 17 00:00:00 2001 From: Riku Virtanen Date: Thu, 21 Sep 2023 10:48:52 +0300 Subject: [PATCH 5/6] Fixed issue and renabled all test classes --- .../Frends.FTP.UploadFiles.Tests/DestinationOperationTests.cs | 1 - .../data/file1.txt-6bfb020a-4d60-4cad-9354-eeaec51a2cb9 | 1 + .../Frends.FTP.UploadFiles.Tests/MacrosTests.cs | 1 - .../SourceFilesNotFoundActionTests.cs | 1 - .../Frends.FTP.UploadFiles.Tests/SourceOperationTests.cs | 1 - .../Frends.FTP.UploadFiles/Definitions/FileTransporter.cs | 4 ++-- 6 files changed, 3 insertions(+), 6 deletions(-) create mode 100644 Frends.FTP.UploadFiles/Frends.FTP.UploadFiles.Tests/DockerVolumes/data/file1.txt-6bfb020a-4d60-4cad-9354-eeaec51a2cb9 diff --git a/Frends.FTP.UploadFiles/Frends.FTP.UploadFiles.Tests/DestinationOperationTests.cs b/Frends.FTP.UploadFiles/Frends.FTP.UploadFiles.Tests/DestinationOperationTests.cs index 14b6686..f643de1 100644 --- a/Frends.FTP.UploadFiles/Frends.FTP.UploadFiles.Tests/DestinationOperationTests.cs +++ b/Frends.FTP.UploadFiles/Frends.FTP.UploadFiles.Tests/DestinationOperationTests.cs @@ -6,7 +6,6 @@ namespace Frends.FTP.UploadFiles.Tests; -[Ignore("Debug")] [TestClass] public class DestinationActionTests : UploadFilesTestBase { diff --git a/Frends.FTP.UploadFiles/Frends.FTP.UploadFiles.Tests/DockerVolumes/data/file1.txt-6bfb020a-4d60-4cad-9354-eeaec51a2cb9 b/Frends.FTP.UploadFiles/Frends.FTP.UploadFiles.Tests/DockerVolumes/data/file1.txt-6bfb020a-4d60-4cad-9354-eeaec51a2cb9 new file mode 100644 index 0000000..30d74d2 --- /dev/null +++ b/Frends.FTP.UploadFiles/Frends.FTP.UploadFiles.Tests/DockerVolumes/data/file1.txt-6bfb020a-4d60-4cad-9354-eeaec51a2cb9 @@ -0,0 +1 @@ +test \ No newline at end of file diff --git a/Frends.FTP.UploadFiles/Frends.FTP.UploadFiles.Tests/MacrosTests.cs b/Frends.FTP.UploadFiles/Frends.FTP.UploadFiles.Tests/MacrosTests.cs index 249b8d0..bbd514e 100644 --- a/Frends.FTP.UploadFiles/Frends.FTP.UploadFiles.Tests/MacrosTests.cs +++ b/Frends.FTP.UploadFiles/Frends.FTP.UploadFiles.Tests/MacrosTests.cs @@ -18,7 +18,6 @@ namespace Frends.FTP.UploadFiles.Tests; /// - source file name does not support macros for some reason in Cobalt, currently not implementing because /// need to understand reasoning better /// -[Ignore("Debug")] [TestClass] public class MacrosTests { diff --git a/Frends.FTP.UploadFiles/Frends.FTP.UploadFiles.Tests/SourceFilesNotFoundActionTests.cs b/Frends.FTP.UploadFiles/Frends.FTP.UploadFiles.Tests/SourceFilesNotFoundActionTests.cs index f72b2a0..66bc04c 100644 --- a/Frends.FTP.UploadFiles/Frends.FTP.UploadFiles.Tests/SourceFilesNotFoundActionTests.cs +++ b/Frends.FTP.UploadFiles/Frends.FTP.UploadFiles.Tests/SourceFilesNotFoundActionTests.cs @@ -7,7 +7,6 @@ namespace Frends.FTP.UploadFiles.Tests; -[Ignore("Debug")] [TestClass] public class SourceFilesNotFoundActionTests : UploadFilesTestBase { diff --git a/Frends.FTP.UploadFiles/Frends.FTP.UploadFiles.Tests/SourceOperationTests.cs b/Frends.FTP.UploadFiles/Frends.FTP.UploadFiles.Tests/SourceOperationTests.cs index 88759da..9cbf3a8 100644 --- a/Frends.FTP.UploadFiles/Frends.FTP.UploadFiles.Tests/SourceOperationTests.cs +++ b/Frends.FTP.UploadFiles/Frends.FTP.UploadFiles.Tests/SourceOperationTests.cs @@ -7,7 +7,6 @@ namespace Frends.FTP.UploadFiles.Tests; -[Ignore("Debug")] [TestClass] public class SourceOperationTests : UploadFilesTestBase { diff --git a/Frends.FTP.UploadFiles/Frends.FTP.UploadFiles/Definitions/FileTransporter.cs b/Frends.FTP.UploadFiles/Frends.FTP.UploadFiles/Definitions/FileTransporter.cs index ff6b0f0..f3e9beb 100644 --- a/Frends.FTP.UploadFiles/Frends.FTP.UploadFiles/Definitions/FileTransporter.cs +++ b/Frends.FTP.UploadFiles/Frends.FTP.UploadFiles/Definitions/FileTransporter.cs @@ -173,9 +173,9 @@ private static FtpClient CreateFtpClient(Connection connect) { store.Open(OpenFlags.ReadOnly); if (!string.IsNullOrEmpty(connect.ClientCertificateName)) - client.ClientCertificates.Add(store.Certificates.Find(X509FindType.FindBySubjectName, connect.ClientCertificateName, false).First()); + client.ClientCertificates.Add(store.Certificates.Find(X509FindType.FindBySubjectName, connect.ClientCertificateName, false)[0]); else if (!string.IsNullOrEmpty(connect.ClientCertificateThumbprint)) - client.ClientCertificates.Add(store.Certificates.Find(X509FindType.FindByThumbprint, connect.ClientCertificateThumbprint, false).First()); + client.ClientCertificates.Add(store.Certificates.Find(X509FindType.FindByThumbprint, connect.ClientCertificateThumbprint, false)[0]); else client.ClientCertificates.AddRange(store.Certificates); } From d07f29ea66175ef6ca553f3244295d60696f14ac Mon Sep 17 00:00:00 2001 From: Riku Virtanen Date: Thu, 21 Sep 2023 11:37:29 +0300 Subject: [PATCH 6/6] data file deleted --- .../data/file1.txt-6bfb020a-4d60-4cad-9354-eeaec51a2cb9 | 1 - 1 file changed, 1 deletion(-) delete mode 100644 Frends.FTP.UploadFiles/Frends.FTP.UploadFiles.Tests/DockerVolumes/data/file1.txt-6bfb020a-4d60-4cad-9354-eeaec51a2cb9 diff --git a/Frends.FTP.UploadFiles/Frends.FTP.UploadFiles.Tests/DockerVolumes/data/file1.txt-6bfb020a-4d60-4cad-9354-eeaec51a2cb9 b/Frends.FTP.UploadFiles/Frends.FTP.UploadFiles.Tests/DockerVolumes/data/file1.txt-6bfb020a-4d60-4cad-9354-eeaec51a2cb9 deleted file mode 100644 index 30d74d2..0000000 --- a/Frends.FTP.UploadFiles/Frends.FTP.UploadFiles.Tests/DockerVolumes/data/file1.txt-6bfb020a-4d60-4cad-9354-eeaec51a2cb9 +++ /dev/null @@ -1 +0,0 @@ -test \ No newline at end of file