#8 Core service refctoring (auth)

This commit is contained in:
serge-rider
2020-05-04 20:54:24 +03:00
parent c8d10e187d
commit c03af05bc2
5 changed files with 220 additions and 198 deletions
@@ -18,35 +18,29 @@ package io.cloudbeaver.model.session;
import io.cloudbeaver.DBWSecurityController;
import io.cloudbeaver.DBWebException;
import io.cloudbeaver.WebServiceUtils;
import io.cloudbeaver.model.WebAsyncTaskInfo;
import io.cloudbeaver.model.WebConnectionInfo;
import io.cloudbeaver.model.WebServerMessage;
import io.cloudbeaver.model.user.WebUser;
import io.cloudbeaver.server.CBApplication;
import io.cloudbeaver.server.CBPlatform;
import io.cloudbeaver.server.CBConstants;
import io.cloudbeaver.model.*;
import io.cloudbeaver.server.CBPlatform;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.jkiss.code.NotNull;
import org.jkiss.code.Nullable;
import org.jkiss.dbeaver.DBException;
import org.jkiss.dbeaver.Log;
import org.jkiss.dbeaver.model.DBPDataSourceContainer;
import org.jkiss.dbeaver.model.app.DBPDataSourceRegistry;
import org.jkiss.dbeaver.model.app.DBPPlatform;
import org.jkiss.dbeaver.model.app.DBPProject;
import org.jkiss.dbeaver.model.connection.DBPConnectionConfiguration;
import org.jkiss.dbeaver.model.connection.DBPDriver;
import org.jkiss.dbeaver.model.exec.DBCException;
import org.jkiss.dbeaver.model.meta.Association;
import org.jkiss.dbeaver.model.meta.Property;
import org.jkiss.dbeaver.model.navigator.*;
import org.jkiss.dbeaver.model.navigator.DBNModel;
import org.jkiss.dbeaver.model.navigator.DBNProject;
import org.jkiss.dbeaver.model.navigator.DBNProjectDatabases;
import org.jkiss.dbeaver.model.runtime.*;
import org.jkiss.dbeaver.registry.DataSourceDescriptor;
import org.jkiss.dbeaver.registry.DataSourceNavigatorSettings;
import org.jkiss.dbeaver.runtime.DBWorkbench;
import org.jkiss.dbeaver.runtime.jobs.ConnectionTestJob;
import org.jkiss.dbeaver.runtime.jobs.DisconnectJob;
import org.jkiss.dbeaver.utils.RuntimeUtils;
import org.jkiss.utils.CommonUtils;
import javax.servlet.http.HttpSession;
@@ -241,149 +235,6 @@ public class WebSession {
}
}
public WebConnectionInfo openConnectionFromTemplate(WebConnectionConfig config) throws DBWebException {
String dataSourceId = config.getDataSourceId();
if (CommonUtils.isEmpty(dataSourceId)) {
throw new DBWebException("Only preconfigured data sources are supported yet");
}
DBPDataSourceRegistry templateRegistry = WebServiceUtils.getDataSourceRegistry();
DBPDataSourceContainer dataSourceTemplate = templateRegistry.getDataSource(dataSourceId);
if (dataSourceTemplate == null) {
throw new DBWebException("Datasource '" + dataSourceId + "' not found");
}
DBPDataSourceRegistry sessionRegistry = databases.getDataSourceRegistry();
DBPDataSourceContainer newDataSource = sessionRegistry.createDataSource(dataSourceTemplate);
newDataSource.setSavePassword(true);
((DataSourceDescriptor)newDataSource).setTemporary(true);
DBPConnectionConfiguration cfg = newDataSource.getConnectionConfiguration();
cfg.setUserName(config.getUserName());
cfg.setUserPassword(config.getUserPassword());
if (!CommonUtils.isEmpty(config.getName())) {
newDataSource.setName(config.getName());
}
if (!CommonUtils.isEmpty(config.getDescription())) {
newDataSource.setDescription(config.getDescription());
}
try {
newDataSource.connect(getProgressMonitor(), true, false);
} catch (DBException e) {
throw new DBWebException("Error connecting to database", e);
}
sessionRegistry.addDataSource(newDataSource);
WebConnectionInfo connectionInfo = new WebConnectionInfo(this, newDataSource);
synchronized (connections) {
connections.add(connectionInfo);
}
return connectionInfo;
}
public WebConnectionInfo createConnection(WebConnectionConfig config) throws DBWebException {
DBPDataSourceRegistry sessionRegistry = databases.getDataSourceRegistry();
DBPDataSourceContainer newDataSource = makeConnectionInstance(config, sessionRegistry);
if (CommonUtils.isEmpty(newDataSource.getName())) {
newDataSource.setName(CommonUtils.notNull(config.getName(), "NewConnection"));
}
((DataSourceDescriptor)newDataSource).setTemporary(true);
sessionRegistry.addDataSource(newDataSource);
WebConnectionInfo connectionInfo = new WebConnectionInfo(this, newDataSource);
synchronized (connections) {
connections.add(connectionInfo);
}
return connectionInfo;
}
public WebConnectionInfo testConnection(WebConnectionConfig config) throws DBWebException {
DBPDataSourceRegistry sessionRegistry = databases.getDataSourceRegistry();
DBPDataSourceContainer newDataSource = makeConnectionInstance(config, sessionRegistry);
try {
ConnectionTestJob ct = new ConnectionTestJob(newDataSource, param -> {});
ct.run(getProgressMonitor());
if (ct.getConnectError() != null) {
throw new DBWebException("Connection failed", ct.getConnectError());
}
WebConnectionInfo connectionInfo = new WebConnectionInfo(this, newDataSource);
connectionInfo.setConnectError(ct.getConnectError());
connectionInfo.setServerVersion(ct.getServerVersion());
connectionInfo.setClientVersion(ct.getClientVersion());
connectionInfo.setConnectTime(RuntimeUtils.formatExecutionTime(ct.getConnectTime()));
return connectionInfo;
} catch (DBException e) {
throw new DBWebException("Error connecting to database", e);
}
}
@NotNull
private DBPDataSourceContainer makeConnectionInstance(WebConnectionConfig config, DBPDataSourceRegistry sessionRegistry) throws DBWebException {
String driverId = config.getDriverId();
if (CommonUtils.isEmpty(driverId)) {
throw new DBWebException("Driver not specified");
}
DBPDriver driver = WebServiceUtils.getDriverById(driverId);
DBPConnectionConfiguration dsConfig = new DBPConnectionConfiguration();
DBPDataSourceContainer newDataSource = sessionRegistry.createDataSource(driver, dsConfig);
newDataSource.setSavePassword(true);
if (!CommonUtils.isEmpty(config.getUrl())) {
dsConfig.setUrl(config.getUrl());
} else {
dsConfig.setHostName(config.getHost());
dsConfig.setHostPort(config.getPort());
dsConfig.setDatabaseName(config.getDatabaseName());
dsConfig.setServerName(config.getServerName());
dsConfig.setUrl(driver.getDataSourceProvider().getConnectionURL(driver, dsConfig));
}
if (config.getProperties() != null) {
for (Map.Entry<String, Object> pe : config.getProperties().entrySet()) {
dsConfig.setProperty(pe.getKey(), CommonUtils.toString(pe.getValue()));
}
}
dsConfig.setUserName(config.getUserName());
dsConfig.setUserPassword(config.getUserPassword());
newDataSource.setName(config.getName());
newDataSource.setDescription(config.getDescription());
// Set default navigator settings
DataSourceNavigatorSettings navSettings = new DataSourceNavigatorSettings(newDataSource.getNavigatorSettings());
navSettings.setShowSystemObjects(false);
((DataSourceDescriptor)newDataSource).setNavigatorSettings(navSettings);
return newDataSource;
}
public boolean closeConnection(String connectionID) throws DBWebException {
WebConnectionInfo connectionInfo = getWebConnectionInfo(connectionID);
boolean disconnected = false;
if (connectionInfo.isConnected()) {
try {
connectionInfo.getDataSourceContainer().disconnect(getProgressMonitor());
disconnected = true;
} catch (DBException e) {
log.error("Error closing connection", e);
}
// Disconnect in async mode?
//new DisconnectJob(connectionInfo.getDataSource()).schedule();
}
databases.getDataSourceRegistry().removeDataSource(connectionInfo.getDataSourceContainer());
synchronized (connections) {
connections.remove(connectionInfo);
}
return disconnected;
}
@NotNull
public WebConnectionInfo getWebConnectionInfo(String connectionID) throws DBWebException {
WebConnectionInfo connectionInfo = null;
@@ -401,6 +252,19 @@ public class WebSession {
return connectionInfo;
}
public void addConnection(WebConnectionInfo connectionInfo) {
synchronized (connections) {
connections.add(connectionInfo);
}
}
public void removeConnection(WebConnectionInfo connectionInfo) {
synchronized (connections) {
connections.remove(connectionInfo);
}
}
void close() {
try {
// Clear attributes
@@ -17,8 +17,6 @@
package io.cloudbeaver.model.session;
import io.cloudbeaver.DBWebException;
import io.cloudbeaver.model.WebConnectionConfig;
import io.cloudbeaver.model.WebConnectionInfo;
import io.cloudbeaver.server.CBPlatform;
import org.jkiss.code.NotNull;
import org.jkiss.dbeaver.Log;
@@ -118,22 +116,6 @@ public class WebSessionManager {
}
}
public WebConnectionInfo openConnection(HttpServletRequest servletRequest, Map<String, Object> config) throws DBWebException {
return getWebSession(servletRequest).openConnectionFromTemplate(new WebConnectionConfig(config));
}
public WebConnectionInfo createConnection(HttpServletRequest servletRequest, Map<String, Object> config) throws DBWebException {
return getWebSession(servletRequest).createConnection(new WebConnectionConfig(config));
}
public WebConnectionInfo testConnection(HttpServletRequest servletRequest, Map<String, Object> config) throws DBWebException {
return getWebSession(servletRequest).testConnection(new WebConnectionConfig(config));
}
public boolean closeConnection(HttpServletRequest servletRequest, String connectionId) throws DBWebException {
return getWebSession(servletRequest).closeConnection(connectionId);
}
public void expireIdleSessions() {
long maxSessionIdleTime = DBWorkbench.getPlatform(CBPlatform.class).getApplication().getMaxSessionIdleTime();
@@ -154,4 +136,5 @@ public class WebSessionManager {
session.close();
}
}
}
@@ -19,10 +19,7 @@ package io.cloudbeaver.service.core;
import io.cloudbeaver.DBWService;
import io.cloudbeaver.DBWebException;
import io.cloudbeaver.WebAction;
import io.cloudbeaver.model.WebDataSourceConfig;
import io.cloudbeaver.model.WebDatabaseDriverConfig;
import io.cloudbeaver.model.WebServerConfig;
import io.cloudbeaver.model.WebServerMessage;
import io.cloudbeaver.model.*;
import io.cloudbeaver.model.session.WebSession;
import org.jkiss.dbeaver.model.exec.DBCException;
@@ -65,5 +62,30 @@ public interface DBWServiceCore extends DBWService {
@WebAction
boolean touchSession(HttpServletRequest request) throws DBWebException;
boolean changeSessionLanguage(WebSession webSession, String locale);
@WebAction
boolean changeSessionLanguage(WebSession webSession, String locale) throws DBWebException;
///////////////////////////////////////////
// Connections
@WebAction
WebConnectionInfo openConnection(WebSession webSession, WebConnectionConfig connectionConfig) throws DBWebException;
@WebAction
WebConnectionInfo createConnection(WebSession webSession, WebConnectionConfig connectionConfig) throws DBWebException;
@WebAction
WebConnectionInfo testConnection(WebSession webSession, WebConnectionConfig connectionConfig) throws DBWebException;
@WebAction
boolean closeConnection(WebSession webSession, String connectionId) throws DBWebException;
///////////////////////////////////////////
// Async tasks
@WebAction
WebAsyncTaskInfo getAsyncTaskStatus(WebSession webSession, String taskId) throws DBWebException;
@WebAction
boolean cancelAsyncTask(WebSession webSession, String taskId) throws DBWebException;
}
@@ -17,11 +17,11 @@
package io.cloudbeaver.service.core;
import graphql.TypeResolutionEnvironment;
import graphql.schema.DataFetchingEnvironment;
import graphql.schema.idl.TypeRuntimeWiring;
import io.cloudbeaver.DBWebException;
import io.cloudbeaver.model.WebServerConfig;
import io.cloudbeaver.model.WebConnectionConfig;
import io.cloudbeaver.model.session.WebSessionManager;
import io.cloudbeaver.server.CBApplication;
import io.cloudbeaver.server.CBPlatform;
import io.cloudbeaver.server.graphql.GraphQLEndpoint;
import io.cloudbeaver.service.DBWBindingContext;
@@ -62,23 +62,21 @@ public class WebServiceBindingCore extends WebServiceBindingBase<DBWServiceCore>
.dataFetcher("touchSession", env -> getService(env).touchSession(GraphQLEndpoint.getServletRequest(env)))
.dataFetcher("changeSessionLanguage", env -> getService(env).changeSessionLanguage(getWebSession(env), env.getArgument("locale")))
.dataFetcher("openConnection", env -> sessionManager.openConnection(GraphQLEndpoint.getServletRequest(env), env.getArgument("config")))
.dataFetcher("createConnection", env -> sessionManager.createConnection(GraphQLEndpoint.getServletRequest(env), env.getArgument("config")))
.dataFetcher("testConnection", env -> sessionManager.testConnection(GraphQLEndpoint.getServletRequest(env), env.getArgument("config")))
.dataFetcher("closeConnection", env -> sessionManager.closeConnection(GraphQLEndpoint.getServletRequest(env), env.getArgument("id")))
.dataFetcher("openConnection", env -> getService(env).openConnection(getWebSession(env), getConnectionConfig(env)))
.dataFetcher("createConnection", env -> getService(env).createConnection(getWebSession(env), getConnectionConfig(env)))
.dataFetcher("testConnection", env -> getService(env).testConnection(getWebSession(env), getConnectionConfig(env)))
.dataFetcher("closeConnection", env -> getService(env).closeConnection(getWebSession(env), env.getArgument("id")))
.dataFetcher("asyncTaskStatus", env ->
sessionManager.getWebSession(GraphQLEndpoint.getServletRequest(env)).asyncTaskStatus(
env.getArgument("id"))
)
.dataFetcher("asyncTaskCancel", env ->
sessionManager.getWebSession(GraphQLEndpoint.getServletRequest(env)).asyncTaskCancel(
env.getArgument("id"))
)
.dataFetcher("asyncTaskStatus", env -> getService(env).getAsyncTaskStatus(getWebSession(env), env.getArgument("id")))
.dataFetcher("asyncTaskCancel", env -> getService(env).cancelAsyncTask(getWebSession(env), env.getArgument("id")))
;
model.getRuntimeWiring().type(TypeRuntimeWiring.newTypeWiring("AsyncTaskResult").typeResolver(TypeResolutionEnvironment::getObject)
);
}
private WebConnectionConfig getConnectionConfig(DataFetchingEnvironment env) {
return new WebConnectionConfig(env.getArgument("config"));
}
}
@@ -19,24 +19,29 @@ package io.cloudbeaver.service.core.impl;
import io.cloudbeaver.DBWebException;
import io.cloudbeaver.WebServiceUtils;
import io.cloudbeaver.model.WebDataSourceConfig;
import io.cloudbeaver.model.WebDatabaseDriverConfig;
import io.cloudbeaver.model.WebServerConfig;
import io.cloudbeaver.model.WebServerMessage;
import io.cloudbeaver.model.*;
import io.cloudbeaver.model.session.WebSession;
import io.cloudbeaver.server.CBApplication;
import io.cloudbeaver.server.CBPlatform;
import io.cloudbeaver.server.graphql.GraphQLEndpoint;
import io.cloudbeaver.service.core.DBWServiceCore;
import org.jkiss.code.NotNull;
import org.jkiss.dbeaver.DBException;
import org.jkiss.dbeaver.Log;
import org.jkiss.dbeaver.model.DBPDataSourceContainer;
import org.jkiss.dbeaver.model.app.DBPDataSourceRegistry;
import org.jkiss.dbeaver.model.connection.DBPConnectionConfiguration;
import org.jkiss.dbeaver.model.connection.DBPDriver;
import org.jkiss.dbeaver.model.exec.DBCException;
import org.jkiss.dbeaver.registry.DataSourceDescriptor;
import org.jkiss.dbeaver.registry.DataSourceNavigatorSettings;
import org.jkiss.dbeaver.runtime.jobs.ConnectionTestJob;
import org.jkiss.dbeaver.utils.RuntimeUtils;
import org.jkiss.utils.CommonUtils;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* Web service implementation
@@ -118,4 +123,154 @@ public class WebServiceCore implements DBWServiceCore {
return true;
}
@Override
public WebConnectionInfo openConnection(WebSession webSession, WebConnectionConfig config) throws DBWebException {
String dataSourceId = config.getDataSourceId();
if (CommonUtils.isEmpty(dataSourceId)) {
throw new DBWebException("Only preconfigured data sources are supported yet");
}
DBPDataSourceRegistry templateRegistry = WebServiceUtils.getDataSourceRegistry();
DBPDataSourceContainer dataSourceTemplate = templateRegistry.getDataSource(dataSourceId);
if (dataSourceTemplate == null) {
throw new DBWebException("Datasource '" + dataSourceId + "' not found");
}
DBPDataSourceRegistry sessionRegistry = webSession.getDatabases().getDataSourceRegistry();
DBPDataSourceContainer newDataSource = sessionRegistry.createDataSource(dataSourceTemplate);
newDataSource.setSavePassword(true);
((DataSourceDescriptor)newDataSource).setTemporary(true);
DBPConnectionConfiguration cfg = newDataSource.getConnectionConfiguration();
cfg.setUserName(config.getUserName());
cfg.setUserPassword(config.getUserPassword());
if (!CommonUtils.isEmpty(config.getName())) {
newDataSource.setName(config.getName());
}
if (!CommonUtils.isEmpty(config.getDescription())) {
newDataSource.setDescription(config.getDescription());
}
try {
newDataSource.connect(webSession.getProgressMonitor(), true, false);
} catch (DBException e) {
throw new DBWebException("Error connecting to database", e);
}
sessionRegistry.addDataSource(newDataSource);
WebConnectionInfo connectionInfo = new WebConnectionInfo(webSession, newDataSource);
webSession.addConnection(connectionInfo);
return connectionInfo;
}
@Override
public WebConnectionInfo createConnection(WebSession webSession, WebConnectionConfig connectionConfig) throws DBWebException {
DBPDataSourceRegistry sessionRegistry = webSession.getDatabases().getDataSourceRegistry();
DBPDataSourceContainer newDataSource = makeConnectionInstance(connectionConfig, sessionRegistry);
if (CommonUtils.isEmpty(newDataSource.getName())) {
newDataSource.setName(CommonUtils.notNull(connectionConfig.getName(), "NewConnection"));
}
((DataSourceDescriptor)newDataSource).setTemporary(true);
sessionRegistry.addDataSource(newDataSource);
WebConnectionInfo connectionInfo = new WebConnectionInfo(webSession, newDataSource);
webSession.addConnection(connectionInfo);
return connectionInfo;
}
@Override
public WebConnectionInfo testConnection(WebSession webSession, WebConnectionConfig connectionConfig) throws DBWebException {
DBPDataSourceRegistry sessionRegistry = webSession.getDatabases().getDataSourceRegistry();
DBPDataSourceContainer newDataSource = makeConnectionInstance(connectionConfig, sessionRegistry);
try {
ConnectionTestJob ct = new ConnectionTestJob(newDataSource, param -> {});
ct.run(webSession.getProgressMonitor());
if (ct.getConnectError() != null) {
throw new DBWebException("Connection failed", ct.getConnectError());
}
WebConnectionInfo connectionInfo = new WebConnectionInfo(webSession, newDataSource);
connectionInfo.setConnectError(ct.getConnectError());
connectionInfo.setServerVersion(ct.getServerVersion());
connectionInfo.setClientVersion(ct.getClientVersion());
connectionInfo.setConnectTime(RuntimeUtils.formatExecutionTime(ct.getConnectTime()));
return connectionInfo;
} catch (DBException e) {
throw new DBWebException("Error connecting to database", e);
}
}
@Override
public boolean closeConnection(WebSession webSession, String connectionId) throws DBWebException {
WebConnectionInfo connectionInfo = webSession.getWebConnectionInfo(connectionId);
boolean disconnected = false;
if (connectionInfo.isConnected()) {
try {
connectionInfo.getDataSourceContainer().disconnect(webSession.getProgressMonitor());
disconnected = true;
} catch (DBException e) {
log.error("Error closing connection", e);
}
// Disconnect in async mode?
//new DisconnectJob(connectionInfo.getDataSource()).schedule();
}
webSession.getDatabases().getDataSourceRegistry().removeDataSource(connectionInfo.getDataSourceContainer());
webSession.removeConnection(connectionInfo);
return disconnected;
}
@NotNull
private DBPDataSourceContainer makeConnectionInstance(WebConnectionConfig config, DBPDataSourceRegistry sessionRegistry) throws DBWebException {
String driverId = config.getDriverId();
if (CommonUtils.isEmpty(driverId)) {
throw new DBWebException("Driver not specified");
}
DBPDriver driver = WebServiceUtils.getDriverById(driverId);
DBPConnectionConfiguration dsConfig = new DBPConnectionConfiguration();
DBPDataSourceContainer newDataSource = sessionRegistry.createDataSource(driver, dsConfig);
newDataSource.setSavePassword(true);
if (!CommonUtils.isEmpty(config.getUrl())) {
dsConfig.setUrl(config.getUrl());
} else {
dsConfig.setHostName(config.getHost());
dsConfig.setHostPort(config.getPort());
dsConfig.setDatabaseName(config.getDatabaseName());
dsConfig.setServerName(config.getServerName());
dsConfig.setUrl(driver.getDataSourceProvider().getConnectionURL(driver, dsConfig));
}
if (config.getProperties() != null) {
for (Map.Entry<String, Object> pe : config.getProperties().entrySet()) {
dsConfig.setProperty(pe.getKey(), CommonUtils.toString(pe.getValue()));
}
}
dsConfig.setUserName(config.getUserName());
dsConfig.setUserPassword(config.getUserPassword());
newDataSource.setName(config.getName());
newDataSource.setDescription(config.getDescription());
// Set default navigator settings
DataSourceNavigatorSettings navSettings = new DataSourceNavigatorSettings(newDataSource.getNavigatorSettings());
navSettings.setShowSystemObjects(false);
((DataSourceDescriptor)newDataSource).setNavigatorSettings(navSettings);
return newDataSource;
}
@Override
public WebAsyncTaskInfo getAsyncTaskStatus(WebSession webSession, String taskId) throws DBWebException {
return webSession.asyncTaskStatus(taskId);
}
@Override
public boolean cancelAsyncTask(WebSession webSession, String taskId) throws DBWebException {
return webSession.asyncTaskCancel(taskId);
}
}