Merge branch 'bug/datasource-api-validations' into 'release'
Postgres plugin load connection details from rich data structure instead of the URL See merge request theappsmith/internal-tools-server!259
This commit is contained in:
commit
d25b4acfd3
|
|
@ -1,38 +1,39 @@
|
||||||
package com.external.plugins;
|
package com.external.plugins;
|
||||||
|
|
||||||
import com.appsmith.external.models.ActionConfiguration;
|
import com.appsmith.external.models.*;
|
||||||
import com.appsmith.external.models.ActionExecutionResult;
|
import com.appsmith.external.pluginExceptions.AppsmithPluginError;
|
||||||
import com.appsmith.external.models.DatasourceConfiguration;
|
import com.appsmith.external.pluginExceptions.AppsmithPluginException;
|
||||||
import com.appsmith.external.plugins.BasePlugin;
|
import com.appsmith.external.plugins.BasePlugin;
|
||||||
import com.appsmith.external.plugins.PluginExecutor;
|
import com.appsmith.external.plugins.PluginExecutor;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import lombok.NonNull;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.commons.lang.ObjectUtils;
|
||||||
import org.pf4j.Extension;
|
import org.pf4j.Extension;
|
||||||
import org.pf4j.PluginException;
|
import org.pf4j.PluginException;
|
||||||
import org.pf4j.PluginWrapper;
|
import org.pf4j.PluginWrapper;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.CollectionUtils;
|
||||||
import reactor.core.publisher.Mono;
|
import reactor.core.publisher.Mono;
|
||||||
|
|
||||||
import java.sql.Connection;
|
import java.sql.Connection;
|
||||||
import java.sql.DriverManager;
|
import java.sql.*;
|
||||||
import java.sql.ResultSet;
|
import java.util.*;
|
||||||
import java.sql.ResultSetMetaData;
|
|
||||||
import java.sql.SQLException;
|
import static com.appsmith.external.models.Connection.Mode.ReadOnly;
|
||||||
import java.sql.Statement;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class PostgresPlugin extends BasePlugin {
|
public class PostgresPlugin extends BasePlugin {
|
||||||
|
|
||||||
private static ObjectMapper objectMapper;
|
private static ObjectMapper objectMapper = new ObjectMapper();
|
||||||
|
|
||||||
static String JDBC_DRIVER = "org.postgresql.Driver";
|
static final String JDBC_DRIVER = "org.postgresql.Driver";
|
||||||
|
|
||||||
|
private static final String USER = "user";
|
||||||
|
private static final String PASSWORD = "password";
|
||||||
|
private static final String SSL = "ssl";
|
||||||
|
|
||||||
public PostgresPlugin(PluginWrapper wrapper) {
|
public PostgresPlugin(PluginWrapper wrapper) {
|
||||||
super(wrapper);
|
super(wrapper);
|
||||||
this.objectMapper = new ObjectMapper();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -47,58 +48,95 @@ public class PostgresPlugin extends BasePlugin {
|
||||||
public static class PostgresPluginExecutor implements PluginExecutor {
|
public static class PostgresPluginExecutor implements PluginExecutor {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Mono<Object> execute(Object connection,
|
public Mono<Object> execute(@NonNull Object connection,
|
||||||
DatasourceConfiguration datasourceConfiguration,
|
DatasourceConfiguration datasourceConfiguration,
|
||||||
ActionConfiguration actionConfiguration) {
|
ActionConfiguration actionConfiguration) {
|
||||||
|
|
||||||
Connection conn = (Connection) connection;
|
Connection conn = (Connection) connection;
|
||||||
Assert.notNull(conn);
|
|
||||||
|
|
||||||
ArrayList list = new ArrayList(50);
|
Map<String, Object> queryJson = actionConfiguration.getQuery();
|
||||||
|
String query = (String) queryJson.get("cmd");
|
||||||
|
|
||||||
|
if (query == null) {
|
||||||
|
return pluginErrorMono("Missing required parameter: Query.");
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Map<String, Object>> rowsList = new ArrayList<>(50);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Statement statement = conn.createStatement();
|
Statement statement = conn.createStatement();
|
||||||
Map<String, Object> queryJson = actionConfiguration.getQuery();
|
|
||||||
String query = (String) queryJson.get("cmd");
|
|
||||||
ResultSet resultSet = statement.executeQuery(query);
|
ResultSet resultSet = statement.executeQuery(query);
|
||||||
ResultSetMetaData metaData = resultSet.getMetaData();
|
ResultSetMetaData metaData = resultSet.getMetaData();
|
||||||
Integer colCount = metaData.getColumnCount();
|
int colCount = metaData.getColumnCount();
|
||||||
while (resultSet.next()) {
|
while (resultSet.next()) {
|
||||||
HashMap row = new HashMap(colCount);
|
Map<String, Object> row = new HashMap<>(colCount);
|
||||||
for (int i = 1; i <= colCount; i++) {
|
for (int i = 1; i <= colCount; i++) {
|
||||||
row.put(metaData.getColumnName(i), resultSet.getObject(i));
|
row.put(metaData.getColumnName(i), resultSet.getObject(i));
|
||||||
}
|
}
|
||||||
list.add(row);
|
rowsList.add(row);
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
log.error("", e);
|
return pluginErrorMono(e);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ActionExecutionResult result = new ActionExecutionResult();
|
ActionExecutionResult result = new ActionExecutionResult();
|
||||||
result.setBody(objectMapper.valueToTree(list));
|
result.setBody(objectMapper.valueToTree(rowsList));
|
||||||
result.setShouldCacheResponse(true);
|
result.setShouldCacheResponse(true);
|
||||||
System.out.println("In the PostgresPlugin, got action execution result: " + result.toString());
|
System.out.println("In the PostgresPlugin, got action execution result: " + result.toString());
|
||||||
return Mono.just(result);
|
return Mono.just(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Mono<Object> pluginErrorMono(Object... args) {
|
||||||
|
return Mono.error(new AppsmithPluginException(AppsmithPluginError.PLUGIN_ERROR, args));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object datasourceCreate(DatasourceConfiguration datasourceConfiguration) {
|
public Object datasourceCreate(DatasourceConfiguration datasourceConfiguration) {
|
||||||
Connection conn = null;
|
|
||||||
try {
|
try {
|
||||||
// Load the class into JVM
|
|
||||||
Class.forName(JDBC_DRIVER);
|
Class.forName(JDBC_DRIVER);
|
||||||
|
|
||||||
// Create the connection
|
|
||||||
conn = DriverManager.getConnection(datasourceConfiguration.getUrl(),
|
|
||||||
datasourceConfiguration.getAuthentication().getUsername(),
|
|
||||||
datasourceConfiguration.getAuthentication().getPassword());
|
|
||||||
return conn;
|
|
||||||
} catch (ClassNotFoundException e) {
|
} catch (ClassNotFoundException e) {
|
||||||
log.error("", e);
|
return pluginErrorMono("Error loading Postgres JDBC Driver class.");
|
||||||
} catch (SQLException e) {
|
}
|
||||||
log.error("", e);
|
|
||||||
|
String url;
|
||||||
|
AuthenticationDTO authentication = datasourceConfiguration.getAuthentication();
|
||||||
|
|
||||||
|
Properties properties = new Properties();
|
||||||
|
properties.putAll(Map.of(
|
||||||
|
USER, authentication.getUsername(),
|
||||||
|
PASSWORD, authentication.getPassword(),
|
||||||
|
// TODO: Set SSL connection parameters.
|
||||||
|
SSL, datasourceConfiguration.getConnection().getSsl() != null
|
||||||
|
));
|
||||||
|
|
||||||
|
if (CollectionUtils.isEmpty(datasourceConfiguration.getEndpoints())) {
|
||||||
|
url = datasourceConfiguration.getUrl();
|
||||||
|
|
||||||
|
} else {
|
||||||
|
StringBuilder urlBuilder = new StringBuilder("jdbc:postgresql://");
|
||||||
|
for (Endpoint endpoint : datasourceConfiguration.getEndpoints()) {
|
||||||
|
urlBuilder
|
||||||
|
.append(endpoint.getHost())
|
||||||
|
.append(':')
|
||||||
|
.append(ObjectUtils.defaultIfNull(endpoint.getPort(), 5432L))
|
||||||
|
.append('/')
|
||||||
|
.append(authentication.getDatabaseName());
|
||||||
|
}
|
||||||
|
url = urlBuilder.toString();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
Connection connection = DriverManager.getConnection(url, properties);
|
||||||
|
connection.setReadOnly(ReadOnly.equals(datasourceConfiguration.getConnection().getMode()));
|
||||||
|
return connection;
|
||||||
|
|
||||||
|
} catch (SQLException e) {
|
||||||
|
return pluginErrorMono("Error connecting to Postgres.");
|
||||||
|
|
||||||
}
|
}
|
||||||
// Connection wasn't created. Return null
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -109,17 +147,24 @@ public class PostgresPlugin extends BasePlugin {
|
||||||
conn.close();
|
conn.close();
|
||||||
}
|
}
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
log.error("", e);
|
log.error("Error closing Postgres Connection.", e);
|
||||||
try {
|
|
||||||
throw new PluginException(e);
|
|
||||||
} catch (PluginException ex) {
|
|
||||||
ex.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("RedundantIfStatement")
|
||||||
@Override
|
@Override
|
||||||
public Boolean isDatasourceValid(DatasourceConfiguration datasourceConfiguration) {
|
public Boolean isDatasourceValid(@NonNull DatasourceConfiguration datasourceConfiguration) {
|
||||||
|
|
||||||
|
if (CollectionUtils.isEmpty(datasourceConfiguration.getEndpoints())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (datasourceConfiguration.getAuthentication() == null
|
||||||
|
|| datasourceConfiguration.getAuthentication().getUsername() == null
|
||||||
|
|| datasourceConfiguration.getAuthentication().getPassword() == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user