diff --git a/qqq-backend-module-filesystem/src/main/java/com/kingsrook/qqq/backend/module/filesystem/sftp/actions/SFTPTestConnectionAction.java b/qqq-backend-module-filesystem/src/main/java/com/kingsrook/qqq/backend/module/filesystem/sftp/actions/SFTPTestConnectionAction.java new file mode 100644 index 00000000..53b93ccf --- /dev/null +++ b/qqq-backend-module-filesystem/src/main/java/com/kingsrook/qqq/backend/module/filesystem/sftp/actions/SFTPTestConnectionAction.java @@ -0,0 +1,404 @@ +/* + * QQQ - Low-code Application Framework for Engineers. + * Copyright (C) 2021-2025. Kingsrook, LLC + * 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States + * contact@kingsrook.com + * https://github.com/Kingsrook/ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package com.kingsrook.qqq.backend.module.filesystem.sftp.actions; + + +import com.kingsrook.qqq.backend.core.utils.StringUtils; +import org.apache.sshd.sftp.client.SftpClient; + + +/******************************************************************************* + ** action for testing credentials for an SFTP backend connection + *******************************************************************************/ +public class SFTPTestConnectionAction extends AbstractSFTPAction +{ + + /*************************************************************************** + ** + ***************************************************************************/ + public SFTPTestConnectionTestOutput testConnection(SFTPTestConnectionTestInput input) + { + try(SftpClient sftpClient = super.makeConnection(input.getUsername(), input.getHostName(), input.getPort(), input.getPassword())) + { + SFTPTestConnectionTestOutput output = new SFTPTestConnectionTestOutput().withIsConnectionSuccess(true); + + if(StringUtils.hasContent(input.basePath)) + { + try + { + Iterable dirEntries = sftpClient.readDir(input.basePath); + + ///////////////////////////////////////////////////////////////////////// + // it seems like only the .iterator call throws if bad directory here. // + ///////////////////////////////////////////////////////////////////////// + dirEntries.iterator(); + output.setIsListBasePathSuccess(true); + } + catch(Exception e) + { + output.setIsListBasePathSuccess(false); + output.setListBasePathErrorMessage(e.getMessage()); + } + } + + return output; + } + catch(Exception e) + { + return new SFTPTestConnectionTestOutput().withIsConnectionSuccess(false).withConnectionErrorMessage(e.getMessage()); + } + } + + + + /*************************************************************************** + ** + ***************************************************************************/ + public static class SFTPTestConnectionTestInput + { + private String username; + private String hostName; + private Integer port; + private String password; + private String basePath; + + + + /******************************************************************************* + ** Getter for username + ** + *******************************************************************************/ + public String getUsername() + { + return username; + } + + + + /******************************************************************************* + ** Setter for username + ** + *******************************************************************************/ + public void setUsername(String username) + { + this.username = username; + } + + + + /******************************************************************************* + ** Fluent setter for username + ** + *******************************************************************************/ + public SFTPTestConnectionTestInput withUsername(String username) + { + this.username = username; + return (this); + } + + + + /******************************************************************************* + ** Getter for hostName + ** + *******************************************************************************/ + public String getHostName() + { + return hostName; + } + + + + /******************************************************************************* + ** Setter for hostName + ** + *******************************************************************************/ + public void setHostName(String hostName) + { + this.hostName = hostName; + } + + + + /******************************************************************************* + ** Fluent setter for hostName + ** + *******************************************************************************/ + public SFTPTestConnectionTestInput withHostName(String hostName) + { + this.hostName = hostName; + return (this); + } + + + + /******************************************************************************* + ** Getter for port + ** + *******************************************************************************/ + public Integer getPort() + { + return port; + } + + + + /******************************************************************************* + ** Setter for port + ** + *******************************************************************************/ + public void setPort(Integer port) + { + this.port = port; + } + + + + /******************************************************************************* + ** Fluent setter for port + ** + *******************************************************************************/ + public SFTPTestConnectionTestInput withPort(Integer port) + { + this.port = port; + return (this); + } + + + + /******************************************************************************* + ** Getter for password + ** + *******************************************************************************/ + public String getPassword() + { + return password; + } + + + + /******************************************************************************* + ** Setter for password + ** + *******************************************************************************/ + public void setPassword(String password) + { + this.password = password; + } + + + + /******************************************************************************* + ** Fluent setter for password + ** + *******************************************************************************/ + public SFTPTestConnectionTestInput withPassword(String password) + { + this.password = password; + return (this); + } + + + + /******************************************************************************* + ** Getter for basePath + ** + *******************************************************************************/ + public String getBasePath() + { + return basePath; + } + + + + /******************************************************************************* + ** Setter for basePath + ** + *******************************************************************************/ + public void setBasePath(String basePath) + { + this.basePath = basePath; + } + + + + /******************************************************************************* + ** Fluent setter for basePath + ** + *******************************************************************************/ + public SFTPTestConnectionTestInput withBasePath(String basePath) + { + this.basePath = basePath; + return (this); + } + + } + + + + /*************************************************************************** + ** + ***************************************************************************/ + public static class SFTPTestConnectionTestOutput + { + private Boolean isConnectionSuccess; + private String connectionErrorMessage; + + private Boolean isListBasePathSuccess; + private String listBasePathErrorMessage; + + + + /******************************************************************************* + ** Getter for isSuccess + ** + *******************************************************************************/ + public Boolean getIsConnectionSuccess() + { + return isConnectionSuccess; + } + + + + /******************************************************************************* + ** Setter for isSuccess + ** + *******************************************************************************/ + public void setIsConnectionSuccess(Boolean isSuccess) + { + this.isConnectionSuccess = isSuccess; + } + + + + /******************************************************************************* + ** Fluent setter for isSuccess + ** + *******************************************************************************/ + public SFTPTestConnectionTestOutput withIsConnectionSuccess(Boolean isSuccess) + { + this.isConnectionSuccess = isSuccess; + return (this); + } + + + + /******************************************************************************* + ** Getter for connectionErrorMessage + ** + *******************************************************************************/ + public String getConnectionErrorMessage() + { + return connectionErrorMessage; + } + + + + /******************************************************************************* + ** Setter for connectionErrorMessage + ** + *******************************************************************************/ + public void setConnectionErrorMessage(String connectionErrorMessage) + { + this.connectionErrorMessage = connectionErrorMessage; + } + + + + /******************************************************************************* + ** Fluent setter for connectionErrorMessage + ** + *******************************************************************************/ + public SFTPTestConnectionTestOutput withConnectionErrorMessage(String connectionErrorMessage) + { + this.connectionErrorMessage = connectionErrorMessage; + return (this); + } + + + + /******************************************************************************* + ** Getter for listBasePathErrorMessage + *******************************************************************************/ + public String getListBasePathErrorMessage() + { + return (this.listBasePathErrorMessage); + } + + + + /******************************************************************************* + ** Setter for listBasePathErrorMessage + *******************************************************************************/ + public void setListBasePathErrorMessage(String listBasePathErrorMessage) + { + this.listBasePathErrorMessage = listBasePathErrorMessage; + } + + + + /******************************************************************************* + ** Fluent setter for listBasePathErrorMessage + *******************************************************************************/ + public SFTPTestConnectionTestOutput withListBasePathErrorMessage(String listBasePathErrorMessage) + { + this.listBasePathErrorMessage = listBasePathErrorMessage; + return (this); + } + + + + /******************************************************************************* + ** Getter for isListBasePathSuccess + ** + *******************************************************************************/ + public Boolean getIsListBasePathSuccess() + { + return isListBasePathSuccess; + } + + + + /******************************************************************************* + ** Setter for isListBasePathSuccess + ** + *******************************************************************************/ + public void setIsListBasePathSuccess(Boolean isListBasePathSuccess) + { + this.isListBasePathSuccess = isListBasePathSuccess; + } + + + + /******************************************************************************* + ** Fluent setter for isListBasePathSuccess + ** + *******************************************************************************/ + public SFTPTestConnectionTestOutput withIsListBasePathSuccess(Boolean isListBasePathSuccess) + { + this.isListBasePathSuccess = isListBasePathSuccess; + return (this); + } + + } + +} diff --git a/qqq-backend-module-filesystem/src/test/java/com/kingsrook/qqq/backend/module/filesystem/sftp/actions/SFTPTestConnectionActionTest.java b/qqq-backend-module-filesystem/src/test/java/com/kingsrook/qqq/backend/module/filesystem/sftp/actions/SFTPTestConnectionActionTest.java new file mode 100644 index 00000000..b1439cbf --- /dev/null +++ b/qqq-backend-module-filesystem/src/test/java/com/kingsrook/qqq/backend/module/filesystem/sftp/actions/SFTPTestConnectionActionTest.java @@ -0,0 +1,178 @@ +/* + * QQQ - Low-code Application Framework for Engineers. + * Copyright (C) 2021-2025. Kingsrook, LLC + * 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States + * contact@kingsrook.com + * https://github.com/Kingsrook/ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package com.kingsrook.qqq.backend.module.filesystem.sftp.actions; + + +import com.kingsrook.qqq.backend.module.filesystem.sftp.BaseSFTPTest; +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + + +/******************************************************************************* + ** Unit test for SFTPTestConnectionAction + *******************************************************************************/ +class SFTPTestConnectionActionTest extends BaseSFTPTest +{ + + /******************************************************************************* + ** + *******************************************************************************/ + @Test + void testSuccessWithoutPath() + { + SFTPTestConnectionAction.SFTPTestConnectionTestInput input = new SFTPTestConnectionAction.SFTPTestConnectionTestInput() + .withUsername(BaseSFTPTest.USERNAME) + .withPassword(BaseSFTPTest.PASSWORD) + .withPort(BaseSFTPTest.getCurrentPort()) + .withHostName(BaseSFTPTest.HOST_NAME); + SFTPTestConnectionAction.SFTPTestConnectionTestOutput output = new SFTPTestConnectionAction().testConnection(input); + assertTrue(output.getIsConnectionSuccess()); + assertNull(output.getConnectionErrorMessage()); + assertNull(output.getIsListBasePathSuccess()); + assertNull(output.getListBasePathErrorMessage()); + } + + + + /******************************************************************************* + ** + *******************************************************************************/ + @Test + void testSuccessWithPath() + { + SFTPTestConnectionAction.SFTPTestConnectionTestInput input = new SFTPTestConnectionAction.SFTPTestConnectionTestInput() + .withUsername(BaseSFTPTest.USERNAME) + .withPassword(BaseSFTPTest.PASSWORD) + .withPort(BaseSFTPTest.getCurrentPort()) + .withHostName(BaseSFTPTest.HOST_NAME) + .withBasePath(BaseSFTPTest.BACKEND_FOLDER); + SFTPTestConnectionAction.SFTPTestConnectionTestOutput output = new SFTPTestConnectionAction().testConnection(input); + assertTrue(output.getIsConnectionSuccess()); + assertNull(output.getConnectionErrorMessage()); + assertTrue(output.getIsListBasePathSuccess()); + assertNull(output.getListBasePathErrorMessage()); + } + + + + /******************************************************************************* + ** + *******************************************************************************/ + @Test + void testSuccessfulConnectFailedPath() + { + SFTPTestConnectionAction.SFTPTestConnectionTestInput input = new SFTPTestConnectionAction.SFTPTestConnectionTestInput() + .withUsername(BaseSFTPTest.USERNAME) + .withPassword(BaseSFTPTest.PASSWORD) + .withPort(BaseSFTPTest.getCurrentPort()) + .withHostName(BaseSFTPTest.HOST_NAME) + .withBasePath("no-such-path"); + SFTPTestConnectionAction.SFTPTestConnectionTestOutput output = new SFTPTestConnectionAction().testConnection(input); + assertTrue(output.getIsConnectionSuccess()); + assertNull(output.getConnectionErrorMessage()); + assertFalse(output.getIsListBasePathSuccess()); + assertNotNull(output.getListBasePathErrorMessage()); + } + + + + /******************************************************************************* + ** + *******************************************************************************/ + @Test + void testBadUsername() + { + SFTPTestConnectionAction.SFTPTestConnectionTestInput input = new SFTPTestConnectionAction.SFTPTestConnectionTestInput() + .withUsername("not-" + BaseSFTPTest.USERNAME) + .withPassword(BaseSFTPTest.PASSWORD) + .withPort(BaseSFTPTest.getCurrentPort()) + .withHostName(BaseSFTPTest.HOST_NAME); + SFTPTestConnectionAction.SFTPTestConnectionTestOutput output = new SFTPTestConnectionAction().testConnection(input); + assertFalse(output.getIsConnectionSuccess()); + assertNotNull(output.getConnectionErrorMessage()); + assertNull(output.getIsListBasePathSuccess()); + assertNull(output.getListBasePathErrorMessage()); + } + + + + /******************************************************************************* + ** + *******************************************************************************/ + @Test + void testBadPassword() + { + SFTPTestConnectionAction.SFTPTestConnectionTestInput input = new SFTPTestConnectionAction.SFTPTestConnectionTestInput() + .withUsername(BaseSFTPTest.USERNAME) + .withPassword("not-" + BaseSFTPTest.PASSWORD) + .withPort(BaseSFTPTest.getCurrentPort()) + .withHostName(BaseSFTPTest.HOST_NAME); + SFTPTestConnectionAction.SFTPTestConnectionTestOutput output = new SFTPTestConnectionAction().testConnection(input); + assertFalse(output.getIsConnectionSuccess()); + assertNotNull(output.getConnectionErrorMessage()); + assertNull(output.getIsListBasePathSuccess()); + assertNull(output.getListBasePathErrorMessage()); + } + + + + /******************************************************************************* + ** + *******************************************************************************/ + @Test + void testBadHostname() + { + SFTPTestConnectionAction.SFTPTestConnectionTestInput input = new SFTPTestConnectionAction.SFTPTestConnectionTestInput() + .withUsername(BaseSFTPTest.USERNAME) + .withPassword(BaseSFTPTest.PASSWORD) + .withPort(BaseSFTPTest.getCurrentPort()) + .withHostName("not-" + BaseSFTPTest.HOST_NAME); + SFTPTestConnectionAction.SFTPTestConnectionTestOutput output = new SFTPTestConnectionAction().testConnection(input); + assertFalse(output.getIsConnectionSuccess()); + assertNotNull(output.getConnectionErrorMessage()); + assertNull(output.getIsListBasePathSuccess()); + assertNull(output.getListBasePathErrorMessage()); + } + + + /******************************************************************************* + ** + *******************************************************************************/ + @Test + void testBadPort() + { + SFTPTestConnectionAction.SFTPTestConnectionTestInput input = new SFTPTestConnectionAction.SFTPTestConnectionTestInput() + .withUsername(BaseSFTPTest.USERNAME) + .withPassword(BaseSFTPTest.PASSWORD) + .withPort(10 * BaseSFTPTest.getCurrentPort()) + .withHostName(BaseSFTPTest.HOST_NAME); + SFTPTestConnectionAction.SFTPTestConnectionTestOutput output = new SFTPTestConnectionAction().testConnection(input); + assertFalse(output.getIsConnectionSuccess()); + assertNotNull(output.getConnectionErrorMessage()); + assertNull(output.getIsListBasePathSuccess()); + assertNull(output.getListBasePathErrorMessage()); + } + +} \ No newline at end of file