Skip to content
Open
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ public Result<Boolean> connectDataSource(@Parameter(hidden = true) @RequestAttri
*
* @param loginUser login user
* @param id data source id
* @return connect result code
* @return A Result wrapping {@code true} if the connection is successful; otherwise, throws an exception.
*/
@Operation(summary = "connectionTest", description = "CONNECT_DATA_SOURCE_TEST_NOTES")
@Parameters({
Expand All @@ -236,7 +236,7 @@ public Result<Boolean> connectDataSource(@Parameter(hidden = true) @RequestAttri
@ApiException(CONNECTION_TEST_FAILURE)
public Result<Boolean> connectionTest(@Parameter(hidden = true) @RequestAttribute(value = Constants.SESSION_USER) User loginUser,
@PathVariable("id") int id) {
dataSourceService.connectionTest(id);
dataSourceService.connectionTest(loginUser, id);
return Result.success(true);
}

Expand Down Expand Up @@ -337,6 +337,14 @@ public Result<Object> getKerberosStartupState(@Parameter(hidden = true) @Request
return success(Status.SUCCESS.getMsg(), CommonUtils.getKerberosStartupState());
}

/**
* Retrieves the list of tables within a specific database of a data source.
*
* @param loginUser the current logged-in user (injected from session)
* @param datasourceId the unique identifier of the data source
* @param database the name of the database to query
* @return a list of table names/options accessible to the user
*/
@Operation(summary = "tables", description = "GET_DATASOURCE_TABLES_NOTES")
@Parameters({
@Parameter(name = "datasourceId", description = "DATA_SOURCE_ID", required = true, schema = @Schema(implementation = int.class, example = "1")),
Expand All @@ -345,37 +353,56 @@ public Result<Object> getKerberosStartupState(@Parameter(hidden = true) @Request
@GetMapping(value = "/tables")
@ResponseStatus(HttpStatus.OK)
@ApiException(GET_DATASOURCE_TABLES_ERROR)
public Result<Object> getTables(@RequestParam("datasourceId") Integer datasourceId,
@RequestParam(value = "database") String database) {
List<ParamsOptions> options = dataSourceService.getTables(datasourceId, database);
public Result<Object> getTables(@Parameter(hidden = true) @RequestAttribute(value = Constants.SESSION_USER) User loginUser,
@RequestParam("datasourceId") Integer datasourceId,
@RequestParam("database") String database) {
List<ParamsOptions> options = dataSourceService.getTables(loginUser, datasourceId, database);
return Result.success(options);
}

/**
* Retrieves the column details (schema) for a specific table.
*
* @param loginUser the current logged-in user (injected from session)
* @param datasourceId the unique identifier of the data source
* @param database the name of the database containing the table
* @param tableName the name of the table to query columns for
* @return a list of column definitions (name, type, etc.) for the specified table
*/
@Operation(summary = "tableColumns", description = "GET_DATASOURCE_TABLE_COLUMNS_NOTES")
@Parameters({
@Parameter(name = "datasourceId", description = "DATA_SOURCE_ID", required = true, schema = @Schema(implementation = int.class, example = "1")),
@Parameter(name = "tableName", description = "TABLE_NAME", required = true, schema = @Schema(implementation = String.class, example = "test")),
@Parameter(name = "database", description = "DATABASE", required = true, schema = @Schema(implementation = String.class, example = "test"))
@Parameter(name = "database", description = "DATABASE", required = true, schema = @Schema(implementation = String.class, example = "test")),
@Parameter(name = "tableName", description = "TABLE_NAME", required = true, schema = @Schema(implementation = String.class, example = "test"))
})
@GetMapping(value = "/tableColumns")
@ResponseStatus(HttpStatus.OK)
@ApiException(GET_DATASOURCE_TABLE_COLUMNS_ERROR)
public Result<Object> getTableColumns(@RequestParam("datasourceId") Integer datasourceId,
@RequestParam("tableName") String tableName,
@RequestParam(value = "database") String database) {
List<ParamsOptions> options = dataSourceService.getTableColumns(datasourceId, database, tableName);
public Result<Object> getTableColumns(@Parameter(hidden = true) @RequestAttribute(value = Constants.SESSION_USER) User loginUser,
@RequestParam("datasourceId") Integer datasourceId,
@RequestParam("database") String database,
@RequestParam("tableName") String tableName) {
List<ParamsOptions> options = dataSourceService.getTableColumns(loginUser, datasourceId, database, tableName);
return Result.success(options);
}

/**
* Retrieves the list of databases available in a specific data source.
*
* @param loginUser the current logged-in user (injected from session)
* @param datasourceId the unique identifier of the data source
* @return a list of database names/options accessible to the user
*/
@Operation(summary = "databases", description = "GET_DATASOURCE_DATABASE_NOTES")
@Parameters({
@Parameter(name = "datasourceId", description = "DATA_SOURCE_ID", required = true, schema = @Schema(implementation = int.class, example = "1"))
})
@GetMapping(value = "/databases")
@ResponseStatus(HttpStatus.OK)
@ApiException(GET_DATASOURCE_DATABASES_ERROR)
public Result<Object> getDatabases(@RequestParam("datasourceId") Integer datasourceId) {
List<ParamsOptions> options = dataSourceService.getDatabases(datasourceId);
public Result<Object> getDatabases(@Parameter(hidden = true) @RequestAttribute(value = Constants.SESSION_USER) User loginUser,
@RequestParam("datasourceId") Integer datasourceId) {
List<ParamsOptions> options = dataSourceService.getDatabases(loginUser, datasourceId);
return Result.success(options);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

package org.apache.dolphinscheduler.api.service;

import org.apache.dolphinscheduler.api.exceptions.ServiceException;
import org.apache.dolphinscheduler.api.utils.PageInfo;
import org.apache.dolphinscheduler.dao.entity.DataSource;
import org.apache.dolphinscheduler.dao.entity.User;
Expand Down Expand Up @@ -96,12 +97,13 @@ public interface DataSourceService {
void checkConnection(DbType type, ConnectionParam parameter);

/**
* test connection
* Tests the connectivity of a specific data source.
*
* @param id datasource id
* @return connect result code
* @param loginUser the current logged-in user (required for permission check)
* @param id the unique identifier of the data source to test
* @throws ServiceException if the resource doesn't exist, permission is denied, or connection fails
*/
void connectionTest(int id);
void connectionTest(User loginUser, int id);

/**
* delete datasource
Expand Down Expand Up @@ -131,26 +133,36 @@ public interface DataSourceService {
List<DataSource> authedDatasource(User loginUser, Integer userId);

/**
* get tables
* @param datasourceId
* @param database
* @return
* Retrieves the list of tables from a specific database within a data source.
*
* @param loginUser the current logged-in user (required for permission check)
* @param datasourceId the unique identifier of the data source
* @param database the specific database/schema name to query (nullable for some DB types like SQLite)
* @return a list of {@link ParamsOptions} containing table names and optional metadata (e.g., comments)
* @throws ServiceException if permission denied, resource not found, or connection fails
*/
List<ParamsOptions> getTables(Integer datasourceId, String database);
List<ParamsOptions> getTables(User loginUser, Integer datasourceId, String database);

/**
* get table columns
* @param datasourceId
* @param database
* @param tableName
* @return
* Retrieves the list of columns for a specific table in a data source.
*
* @param loginUser current logged-in user
* @param datasourceId ID of the data source
* @param database database/schema name
* @param tableName table name to query
* @return list of {@link ParamsOptions} representing column names and types
* @throws ServiceException if permission denied, resource not found, or connection fails
*/
List<ParamsOptions> getTableColumns(Integer datasourceId, String database, String tableName);
List<ParamsOptions> getTableColumns(User loginUser, Integer datasourceId, String database, String tableName);

/**
* get databases
* @param datasourceId
* @return
* Retrieves the list of databases (or schemas) available in a specific data source.
*
* @param loginUser current logged-in user
* @param datasourceId ID of the data source
* @return list of {@link ParamsOptions} representing database/schema names
* @throws ServiceException if permission denied, resource not found, or connection fails
*/
List<ParamsOptions> getDatabases(Integer datasourceId);
List<ParamsOptions> getDatabases(User loginUser, Integer datasourceId);

}
Original file line number Diff line number Diff line change
Expand Up @@ -330,18 +330,19 @@ public void checkConnection(DbType type, ConnectionParam connectionParam) {
throw new ServiceException(Status.CONNECTION_TEST_FAILURE);
}

/**
* test connection
*
* @param id datasource id
* @return connect result code
*/
@Override
public void connectionTest(int id) {
public void connectionTest(User loginUser, int id) {
DataSource dataSource = dataSourceMapper.selectById(id);

if (dataSource == null) {
throw new ServiceException(Status.RESOURCE_NOT_EXIST);
}

if (!canOperatorPermissions(loginUser, new Object[]{id}, AuthorizationType.DATASOURCE,
ApiFuncIdentificationConstant.DATASOURCE)) {
throw new ServiceException(Status.USER_NO_OPERATION_PERM);
}

checkConnection(dataSource.getType(),
DataSourceUtils.buildConnectionParams(dataSource.getType(), dataSource.getConnectionParams()));
}
Expand Down Expand Up @@ -417,9 +418,18 @@ public List<DataSource> authedDatasource(User loginUser, Integer userId) {
}

@Override
public List<ParamsOptions> getTables(Integer datasourceId, String database) {
public List<ParamsOptions> getTables(User loginUser, Integer datasourceId, String database) {
DataSource dataSource = dataSourceMapper.selectById(datasourceId);

if (dataSource == null) {
throw new ServiceException(Status.QUERY_DATASOURCE_ERROR);
}

if (!canOperatorPermissions(loginUser, new Object[]{datasourceId}, AuthorizationType.DATASOURCE,
ApiFuncIdentificationConstant.DATASOURCE)) {
throw new ServiceException(Status.USER_NO_OPERATION_PERM);
}

List<String> tableList;
BaseConnectionParam connectionParam =
(BaseConnectionParam) DataSourceUtils.buildConnectionParams(
Expand Down Expand Up @@ -477,8 +487,19 @@ public List<ParamsOptions> getTables(Integer datasourceId, String database) {
}

@Override
public List<ParamsOptions> getTableColumns(Integer datasourceId, String database, String tableName) {
public List<ParamsOptions> getTableColumns(User loginUser, Integer datasourceId, String database,
String tableName) {
DataSource dataSource = dataSourceMapper.selectById(datasourceId);

if (dataSource == null) {
throw new ServiceException(Status.QUERY_DATASOURCE_ERROR);
}

if (!canOperatorPermissions(loginUser, new Object[]{datasourceId}, AuthorizationType.DATASOURCE,
ApiFuncIdentificationConstant.DATASOURCE)) {

Check warning

Code scanning / CodeQL

Potential database resource leak Warning

This Statement is not always closed on method exit.
throw new ServiceException(Status.USER_NO_OPERATION_PERM);
}

Check warning

Code scanning / CodeQL

Potential database resource leak Warning

This Statement is not always closed on method exit.

BaseConnectionParam connectionParam =
(BaseConnectionParam) DataSourceUtils.buildConnectionParams(
dataSource.getType(),
Expand Down Expand Up @@ -523,14 +544,19 @@ public List<ParamsOptions> getTableColumns(Integer datasourceId, String database
}

@Override
public List<ParamsOptions> getDatabases(Integer datasourceId) {
public List<ParamsOptions> getDatabases(User loginUser, Integer datasourceId) {

DataSource dataSource = dataSourceMapper.selectById(datasourceId);

if (dataSource == null) {
throw new ServiceException(Status.QUERY_DATASOURCE_ERROR);
}

if (!canOperatorPermissions(loginUser, new Object[]{datasourceId}, AuthorizationType.DATASOURCE,
ApiFuncIdentificationConstant.DATASOURCE)) {
throw new ServiceException(Status.USER_NO_OPERATION_PERM);
}

List<String> tableList;
BaseConnectionParam connectionParam =
(BaseConnectionParam) DataSourceUtils.buildConnectionParams(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,9 @@ DELETE_DATA_SOURCE_NOTES=delete data source
VERIFY_DATA_SOURCE_NOTES=verify data source
UNAUTHORIZED_DATA_SOURCE_NOTES=unauthorized data source
AUTHORIZED_DATA_SOURCE_NOTES=authorized data source
GET_DATASOURCE_DATABASE_NOTES=get datasource databases
GET_DATASOURCE_TABLES_NOTES=get datasource tables
GET_DATASOURCE_TABLE_COLUMNS_NOTES=get datasource table columns
DELETE_SCHEDULE_NOTES=delete schedule by id
QUERY_ALERT_GROUP_LIST_PAGING_NOTES=query alert group list paging
QUERY_AUTHORIZED_AND_USER_CREATED_PROJECT_NOTES= query authorized and user created project
Expand All @@ -234,8 +237,6 @@ QUERY_WORKFLOW_DEFINITION_VERSIONS_NOTES=query workflow definition versions
SWITCH_WORKFLOW_DEFINITION_VERSION_NOTES=switch workflow definition version
VERSION=version
STATE=state
GET_DATASOURCE_TABLES_NOTES=get datasource table
GET_DATASOURCE_TABLE_COLUMNS_NOTES=get datasource table columns
TABLE_NAME=table name
AUDIT_LOG_TAG=audit log related operation
TASK_DEFINITION_TAG=task definition related operation
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,9 @@ DELETE_DATA_SOURCE_NOTES=delete data source
VERIFY_DATA_SOURCE_NOTES=verify data source
UNAUTHORIZED_DATA_SOURCE_NOTES=unauthorized data source
AUTHORIZED_DATA_SOURCE_NOTES=authorized data source
GET_DATASOURCE_DATABASE_NOTES=get datasource databases
GET_DATASOURCE_TABLES_NOTES=get datasource tables
GET_DATASOURCE_TABLE_COLUMNS_NOTES=get datasource table columns
DELETE_SCHEDULE_NOTES=delete schedule by id
QUERY_ALERT_GROUP_LIST_PAGING_NOTES=query alert group list paging
QUERY_AUTHORIZED_AND_USER_CREATED_PROJECT_NOTES=query authorized and user created project
Expand All @@ -267,8 +270,6 @@ QUERY_WORKFLOW_DEFINITION_VERSIONS_NOTES=query process definition versions
SWITCH_WORKFLOW_DEFINITION_VERSION_NOTES=switch process definition version
VERSION=version
TASK_GROUP_QUEUE_PRIORITY=task group queue priority
GET_DATASOURCE_TABLES_NOTES=get datasource table
GET_DATASOURCE_TABLE_COLUMNS_NOTES=get datasource table columns
TABLE_NAME=table name
QUERY_AUDIT_LOG=query audit log
AUDIT_LOG_TAG=audit log related operation
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,9 @@ DELETE_DATA_SOURCE_NOTES=\u5220\u9664\u6570\u636E\u6E90
VERIFY_DATA_SOURCE_NOTES=\u9A8C\u8BC1\u6570\u636E\u6E90
UNAUTHORIZED_DATA_SOURCE_NOTES=\u672A\u6388\u6743\u7684\u6570\u636E\u6E90
AUTHORIZED_DATA_SOURCE_NOTES=\u6388\u6743\u7684\u6570\u636E\u6E90
GET_DATASOURCE_DATABASE_NOTES=\u83B7\u53D6\u6570\u636E\u6E90\u5E93\u5217\u8868
GET_DATASOURCE_TABLES_NOTES=\u83B7\u53D6\u6570\u636E\u6E90\u8868\u5217\u8868
GET_DATASOURCE_TABLE_COLUMNS_NOTES=\u83B7\u53D6\u6570\u636E\u6E90\u8868\u5217\u540D
DELETE_SCHEDULE_NOTES=\u6839\u636E\u5B9A\u65F6id\u5220\u9664\u5B9A\u65F6\u6570\u636E
QUERY_ALERT_GROUP_LIST_PAGING_NOTES=\u5206\u9875\u67E5\u8BE2\u544A\u8B66\u7EC4\u5217\u8868
QUERY_AUTHORIZED_AND_USER_CREATED_PROJECT_NOTES=\u67E5\u8BE2\u6388\u6743\u548C\u7528\u6237\u521B\u5EFA\u7684\u9879\u76EE
Expand All @@ -266,8 +269,6 @@ QUERY_WORKFLOW_DEFINITION_VERSIONS_NOTES=\u67E5\u8BE2\u6D41\u7A0B\u5386\u53F2\u7
SWITCH_WORKFLOW_DEFINITION_VERSION_NOTES=\u5207\u6362\u6D41\u7A0B\u7248\u672C
VERSION=\u7248\u672C\u53F7
TASK_GROUP_QUEUE_PRIORITY=\u4EFB\u52A1\u961F\u5217\u4F18\u5148\u7EA7
GET_DATASOURCE_TABLES_NOTES=\u83B7\u53D6\u6570\u636E\u6E90\u8868\u5217\u8868
GET_DATASOURCE_TABLE_COLUMNS_NOTES=\u83B7\u53D6\u6570\u636E\u6E90\u8868\u5217\u540D
TABLE_NAME=\u8868\u540D
QUERY_AUDIT_LOG=\u67E5\u8BE2\u5BA1\u8BA1\u65E5\u5FD7
AUDIT_LOG_TAG=\u5BA1\u8BA1\u65E5\u5FD7\u6267\u884C\u76F8\u5173\u64CD\u4F5C
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -268,9 +268,11 @@ public void testQueryDataSourceListPaging() {

@Test
public void testConnectionTest() {
User loginUser = getAdminUser();
int dataSourceId = -1;
when(dataSourceMapper.selectById(dataSourceId)).thenReturn(null);
assertThrowsServiceException(Status.RESOURCE_NOT_EXIST, () -> dataSourceService.connectionTest(dataSourceId));
assertThrowsServiceException(Status.RESOURCE_NOT_EXIST,
() -> dataSourceService.connectionTest(loginUser, dataSourceId));

try (
MockedStatic<DataSourceUtils> ignored =
Expand All @@ -281,11 +283,12 @@ public void testConnectionTest() {

when(DataSourceUtils.getDatasourceProcessor(Mockito.any())).thenReturn(dataSourceProcessor);
when(dataSourceProcessor.checkDataSourceConnectivity(Mockito.any())).thenReturn(true);
assertDoesNotThrow(() -> dataSourceService.connectionTest(dataSource.getId()));
passResourcePermissionCheckService();
assertDoesNotThrow(() -> dataSourceService.connectionTest(loginUser, dataSource.getId()));

when(dataSourceProcessor.checkDataSourceConnectivity(Mockito.any())).thenReturn(false);
assertThrowsServiceException(Status.CONNECTION_TEST_FAILURE,
() -> dataSourceService.connectionTest(dataSource.getId()));
() -> dataSourceService.connectionTest(loginUser, dataSource.getId()));
}

}
Expand Down Expand Up @@ -605,13 +608,15 @@ public void testCheckConnection() throws Exception {

@Test
public void testGetDatabases() throws SQLException {
User loginUser = getAdminUser();

DataSource dataSource = getOracleDataSource();
int datasourceId = 1;
dataSource.setId(datasourceId);
when(dataSourceMapper.selectById(datasourceId)).thenReturn(null);

try {
dataSourceService.getDatabases(datasourceId);
dataSourceService.getDatabases(loginUser, datasourceId);
} catch (Exception e) {
Assertions.assertTrue(e.getMessage().contains(Status.QUERY_DATASOURCE_ERROR.getMsg()));
}
Expand All @@ -623,9 +628,10 @@ public void testGetDatabases() throws SQLException {
dataSourceUtils.when(() -> DataSourceUtils.getConnection(Mockito.any(), Mockito.any())).thenReturn(connection);
dataSourceUtils.when(() -> DataSourceUtils.buildConnectionParams(Mockito.any(), Mockito.any()))
.thenReturn(connectionParam);
passResourcePermissionCheckService();

try {
dataSourceService.getDatabases(datasourceId);
dataSourceService.getDatabases(loginUser, datasourceId);
} catch (Exception e) {
Assertions.assertTrue(e.getMessage().contains(Status.GET_DATASOURCE_TABLES_ERROR.getMsg()));
}
Expand All @@ -634,7 +640,7 @@ public void testGetDatabases() throws SQLException {
.thenReturn(null);

try {
dataSourceService.getDatabases(datasourceId);
dataSourceService.getDatabases(loginUser, datasourceId);
} catch (Exception e) {
Assertions.assertTrue(e.getMessage().contains(Status.DATASOURCE_CONNECT_FAILED.getMsg()));
}
Expand Down
Loading