This is an automated email from the ASF dual-hosted git repository. arshad pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/seatunnel-web.git
The following commit(s) were added to refs/heads/main by this push: new 0e8c3b60 [Feature] Add APIs to get resource names. (#286) 0e8c3b60 is described below commit 0e8c3b606a9d3187a6624d7ff35639eed565a2f3 Author: Mohammad Arshad <ars...@apache.org> AuthorDate: Fri Apr 11 15:37:42 2025 +0530 [Feature] Add APIs to get resource names. (#286) --- .../controller/ResourceNameProviderController.java | 82 ++++++ .../seatunnel/app/dal/dao/IDatasourceDao.java | 2 + .../seatunnel/app/dal/dao/IJobDefinitionDao.java | 2 + .../org/apache/seatunnel/app/dal/dao/IUserDao.java | 2 + .../seatunnel/app/dal/dao/IVirtualTableDao.java | 2 + .../seatunnel/app/dal/dao/IWorkspaceDao.java | 2 + .../app/dal/dao/impl/DatasourceDaoImpl.java | 13 + .../app/dal/dao/impl/JobDefinitionDaoImpl.java | 14 + .../seatunnel/app/dal/dao/impl/UserDaoImpl.java | 5 + .../app/dal/dao/impl/VirtualTableDaoImpl.java | 14 + .../app/dal/dao/impl/WorkspaceDaoImpl.java | 5 + .../seatunnel/app/dal/mapper/WorkspaceMapper.java | 4 - .../seatunnel/app/service/IDatasourceService.java | 2 + .../app/service/IJobDefinitionService.java | 2 + .../apache/seatunnel/app/service/IUserService.java | 4 + .../app/service/IVirtualTableService.java | 2 + .../seatunnel/app/service/WorkspaceService.java | 2 + .../app/service/impl/DatasourceServiceImpl.java | 9 + .../app/service/impl/JobDefinitionServiceImpl.java | 9 + .../app/service/impl/UserServiceImpl.java | 5 + .../app/service/impl/VirtualTableServiceImpl.java | 7 + .../app/service/impl/WorkspaceServiceImpl.java | 5 + .../apache/seatunnel/app/dal/mapper/UserMapper.xml | 5 + .../ResourceNameProviderControllerWrapper.java | 70 +++++ .../test/ResourceNameProviderControllerTest.java | 294 +++++++++++++++++++++ 25 files changed, 559 insertions(+), 4 deletions(-) diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/controller/ResourceNameProviderController.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/controller/ResourceNameProviderController.java new file mode 100644 index 00000000..bd26130b --- /dev/null +++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/controller/ResourceNameProviderController.java @@ -0,0 +1,82 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.seatunnel.app.controller; + +import org.apache.seatunnel.app.common.Result; +import org.apache.seatunnel.app.service.IDatasourceService; +import org.apache.seatunnel.app.service.IJobDefinitionService; +import org.apache.seatunnel.app.service.IUserService; +import org.apache.seatunnel.app.service.IVirtualTableService; +import org.apache.seatunnel.app.service.WorkspaceService; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +@RestController +@RequestMapping("/seatunnel/api/v1/resources") +public class ResourceNameProviderController { + + @Autowired private WorkspaceService workspaceService; + + @Autowired private IDatasourceService datasourceService; + + @Autowired private IJobDefinitionService jobDefinitionService; + + @Autowired private IVirtualTableService virtualTableService; + + @Autowired private IUserService userService; + + @GetMapping("/workspace") + public Result<List<String>> getWorkspaces( + @RequestParam(value = "searchName", required = false) String searchName) { + return Result.success(workspaceService.getWorkspaceNames(searchName)); + } + + @GetMapping("/datasource") + public Result<List<String>> getDatasources( + @RequestParam(value = "workspaceName", required = false) String workspaceName, + @RequestParam(value = "searchName", required = false) String searchName) { + return Result.success(datasourceService.getDatasourceNames(workspaceName, searchName)); + } + + @GetMapping("/job_definition") + public Result<List<String>> getJobDefinitions( + @RequestParam(value = "workspaceName", required = false) String workspaceName, + @RequestParam(value = "searchName", required = false) String searchName) { + return Result.success( + jobDefinitionService.getJobDefinitionNames(workspaceName, searchName)); + } + + @GetMapping("/virtual_table") + public Result<List<String>> getVirtualTables( + @RequestParam(value = "workspaceName", required = false) String workspaceName, + @RequestParam(value = "searchName", required = false) String searchName) { + return Result.success( + virtualTableService.getVirtualTableNamesWithinWorkspace(workspaceName, searchName)); + } + + @GetMapping("/user") + public Result<List<String>> getUserNames( + @RequestParam(value = "searchName", required = false) String searchName) { + return Result.success(userService.getUserNames(searchName)); + } +} diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/dao/IDatasourceDao.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/dao/IDatasourceDao.java index 206f63f2..58091da9 100644 --- a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/dao/IDatasourceDao.java +++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/dao/IDatasourceDao.java @@ -57,4 +57,6 @@ public interface IDatasourceDao { List<Datasource> selectByIds(List<Long> ids); List<Datasource> selectDatasourceByUserId(int userId); + + List<String> getDatasourceNames(Long workspaceId, String searchName); } diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/dao/IJobDefinitionDao.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/dao/IJobDefinitionDao.java index 8ff36100..1701b157 100644 --- a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/dao/IJobDefinitionDao.java +++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/dao/IJobDefinitionDao.java @@ -41,4 +41,6 @@ public interface IJobDefinitionDao { JobDefinition getJobByName(@NonNull String name); void delete(long id); + + List<String> getJobDefinitionNames(Long workspaceIdOrCurrent, String searchName); } diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/dao/IUserDao.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/dao/IUserDao.java index a8dafe7b..1cd4fd49 100644 --- a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/dao/IUserDao.java +++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/dao/IUserDao.java @@ -59,4 +59,6 @@ public interface IUserDao { * @return */ List<User> queryEnabledUsers(); + + List<String> getUserNames(String searchName); } diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/dao/IVirtualTableDao.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/dao/IVirtualTableDao.java index 9c4225d2..4f0b1b4e 100644 --- a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/dao/IVirtualTableDao.java +++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/dao/IVirtualTableDao.java @@ -48,4 +48,6 @@ public interface IVirtualTableDao { List<String> getVirtualDatabaseNames(Long datasourceId); boolean checkHasVirtualTable(Long datasourceId); + + List<String> getDatasourceNames(Long workspaceId, String searchName); } diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/dao/IWorkspaceDao.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/dao/IWorkspaceDao.java index 5458ea36..76dd9468 100644 --- a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/dao/IWorkspaceDao.java +++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/dao/IWorkspaceDao.java @@ -33,4 +33,6 @@ public interface IWorkspaceDao { boolean deleteWorkspaceById(Long id); List<Workspace> selectAllWorkspaces(); + + List<String> getWorkspaceNames(String searchName); } diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/dao/impl/DatasourceDaoImpl.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/dao/impl/DatasourceDaoImpl.java index e6c4180c..3b27c807 100644 --- a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/dao/impl/DatasourceDaoImpl.java +++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/dao/impl/DatasourceDaoImpl.java @@ -30,6 +30,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import javax.annotation.Resource; import java.util.List; +import java.util.stream.Collectors; import static org.apache.seatunnel.app.utils.ServletUtils.getCurrentWorkspaceId; @@ -174,4 +175,16 @@ public class DatasourceDaoImpl implements IDatasourceDao { .eq("create_user_id", userId) .eq("workspace_id", getCurrentWorkspaceId())); } + + @Override + public List<String> getDatasourceNames(Long workspaceId, String searchName) { + QueryWrapper<Datasource> queryWrapper = new QueryWrapper<>(); + queryWrapper.eq("workspace_id", workspaceId); + if (searchName != null) { + queryWrapper.like("datasource_name", "%" + searchName + "%"); + } + return datasourceMapper.selectList(queryWrapper).stream() + .map(Datasource::getDatasourceName) + .collect(Collectors.toList()); + } } diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/dao/impl/JobDefinitionDaoImpl.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/dao/impl/JobDefinitionDaoImpl.java index cad87acf..076934da 100644 --- a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/dao/impl/JobDefinitionDaoImpl.java +++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/dao/impl/JobDefinitionDaoImpl.java @@ -27,6 +27,7 @@ import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Repository; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; @@ -35,6 +36,7 @@ import lombok.NonNull; import javax.annotation.Resource; import java.util.List; +import java.util.stream.Collectors; import static org.apache.seatunnel.app.utils.ServletUtils.getCurrentWorkspaceId; @@ -107,4 +109,16 @@ public class JobDefinitionDaoImpl implements IJobDefinitionDao { .eq(JobDefinition::getId, id) .eq(JobDefinition::getWorkspaceId, getCurrentWorkspaceId())); } + + @Override + public List<String> getJobDefinitionNames(Long workspaceId, String searchName) { + LambdaQueryWrapper<JobDefinition> query = Wrappers.<JobDefinition>lambdaQuery(); + query.eq(JobDefinition::getWorkspaceId, workspaceId); + if (StringUtils.isNotEmpty(searchName)) { + query.like(JobDefinition::getName, "%" + searchName + "%"); + } + return jobMapper.selectList(query).stream() + .map(JobDefinition::getName) + .collect(Collectors.toList()); + } } diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/dao/impl/UserDaoImpl.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/dao/impl/UserDaoImpl.java index 9ed4a45b..2c666214 100644 --- a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/dao/impl/UserDaoImpl.java +++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/dao/impl/UserDaoImpl.java @@ -147,4 +147,9 @@ public class UserDaoImpl implements IUserDao { public List<User> queryEnabledUsers() { return userMapper.queryEnabledUsers(); } + + @Override + public List<String> getUserNames(String searchName) { + return userMapper.queryUserNames(searchName); + } } diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/dao/impl/VirtualTableDaoImpl.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/dao/impl/VirtualTableDaoImpl.java index 80ba3105..0c9ede19 100644 --- a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/dao/impl/VirtualTableDaoImpl.java +++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/dao/impl/VirtualTableDaoImpl.java @@ -26,8 +26,10 @@ import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Repository; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import lombok.extern.slf4j.Slf4j; @@ -159,4 +161,16 @@ public class VirtualTableDaoImpl implements IVirtualTableDao { .eq("workspace_id", getCurrentWorkspaceId())) > 0; } + + @Override + public List<String> getDatasourceNames(Long workspaceId, String searchName) { + LambdaQueryWrapper<VirtualTable> query = Wrappers.<VirtualTable>lambdaQuery(); + query.eq(VirtualTable::getWorkspaceId, workspaceId); + if (StringUtils.isNotEmpty(searchName)) { + query.like(VirtualTable::getVirtualDatabaseName, "%" + searchName + "%"); + } + return virtualTableMapper.selectList(query).stream() + .map(VirtualTable::getVirtualDatabaseName) + .collect(Collectors.toList()); + } } diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/dao/impl/WorkspaceDaoImpl.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/dao/impl/WorkspaceDaoImpl.java index 26c21da8..83afe0cf 100644 --- a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/dao/impl/WorkspaceDaoImpl.java +++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/dao/impl/WorkspaceDaoImpl.java @@ -62,4 +62,9 @@ public class WorkspaceDaoImpl implements IWorkspaceDao { public List<Workspace> selectAllWorkspaces() { return workspaceMapper.selectList(new QueryWrapper<>()); } + + @Override + public List<String> getWorkspaceNames(String searchName) { + return workspaceMapper.getWorkspaceNames(searchName); + } } diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/mapper/WorkspaceMapper.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/mapper/WorkspaceMapper.java index 552f166a..af138653 100644 --- a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/mapper/WorkspaceMapper.java +++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/mapper/WorkspaceMapper.java @@ -19,14 +19,10 @@ package org.apache.seatunnel.app.dal.mapper; import org.apache.seatunnel.app.dal.entity.Workspace; -import org.apache.ibatis.annotations.Param; - import com.baomidou.mybatisplus.core.mapper.BaseMapper; import java.util.List; public interface WorkspaceMapper extends BaseMapper<Workspace> { - List<Workspace> getWorkspaceByName(@Param("workspaceName") String workspaceName); - List<String> getWorkspaceNames(String searchName); } diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/IDatasourceService.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/IDatasourceService.java index afac531e..3359936a 100644 --- a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/IDatasourceService.java +++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/IDatasourceService.java @@ -247,4 +247,6 @@ public interface IDatasourceService { String datasourceName, String databaseName, String filterName, Integer size) { return new ArrayList<>(); } + + List<String> getDatasourceNames(String workspaceName, String searchName); } diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/IJobDefinitionService.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/IJobDefinitionService.java index 416b210b..ddc8e730 100644 --- a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/IJobDefinitionService.java +++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/IJobDefinitionService.java @@ -47,4 +47,6 @@ public interface IJobDefinitionService { boolean getUsedByDataSourceIdAndVirtualTable(long datasourceId, String tableName); void deleteJob(long id); + + List<String> getJobDefinitionNames(String workspaceName, String searchName); } diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/IUserService.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/IUserService.java index 1b84559a..4ce130ef 100644 --- a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/IUserService.java +++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/IUserService.java @@ -25,6 +25,8 @@ import org.apache.seatunnel.app.domain.response.PageInfo; import org.apache.seatunnel.app.domain.response.user.AddUserRes; import org.apache.seatunnel.app.domain.response.user.UserSimpleInfoRes; +import java.util.List; + public interface IUserService { AddUserRes add(AddUserReq addReq); @@ -40,4 +42,6 @@ public interface IUserService { void disable(int id); UserSimpleInfoRes login(UserLoginReq req, String authType); + + List<String> getUserNames(String searchName); } diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/IVirtualTableService.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/IVirtualTableService.java index 87c8b999..0c46d11a 100644 --- a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/IVirtualTableService.java +++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/IVirtualTableService.java @@ -50,4 +50,6 @@ public interface IVirtualTableService { List<String> getVirtualTableNames(String databaseName, String datasourceId); List<String> getVirtualDatabaseNames(String datasourceId); + + List<String> getVirtualTableNamesWithinWorkspace(String workspaceName, String searchName); } diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/WorkspaceService.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/WorkspaceService.java index b8f5b385..8ac94283 100644 --- a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/WorkspaceService.java +++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/WorkspaceService.java @@ -38,4 +38,6 @@ public interface WorkspaceService { Workspace getDefaultWorkspace(); Long getWorkspaceIdOrCurrent(String workspaceName); + + List<String> getWorkspaceNames(String searchName); } diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/impl/DatasourceServiceImpl.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/impl/DatasourceServiceImpl.java index a55bcded..6ea3a956 100644 --- a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/impl/DatasourceServiceImpl.java +++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/impl/DatasourceServiceImpl.java @@ -35,6 +35,7 @@ import org.apache.seatunnel.app.security.UserContextHolder; import org.apache.seatunnel.app.service.IDatasourceService; import org.apache.seatunnel.app.service.IJobDefinitionService; import org.apache.seatunnel.app.service.ITableSchemaService; +import org.apache.seatunnel.app.service.WorkspaceService; import org.apache.seatunnel.app.thirdparty.datasource.DataSourceClientFactory; import org.apache.seatunnel.app.thirdparty.framework.SeaTunnelOptionRuleWrapper; import org.apache.seatunnel.app.utils.ConfigShadeUtil; @@ -99,6 +100,8 @@ public class DatasourceServiceImpl extends SeatunnelBaseServiceImpl @Autowired private ConfigShadeUtil configShadeUtil; + @Resource private WorkspaceService workspaceService; + @Override public String createDatasource( String datasourceName, @@ -607,6 +610,12 @@ public class DatasourceServiceImpl extends SeatunnelBaseServiceImpl this.applicationContext = applicationContext; } + @Override + public List<String> getDatasourceNames(String workspaceName, String searchName) { + return datasourceDao.getDatasourceNames( + workspaceService.getWorkspaceIdOrCurrent(workspaceName), searchName); + } + private void permCheck(String resourceName, AccessType accessType) { permissionCheck( resourceName, diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/impl/JobDefinitionServiceImpl.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/impl/JobDefinitionServiceImpl.java index 915193a0..734434ff 100644 --- a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/impl/JobDefinitionServiceImpl.java +++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/impl/JobDefinitionServiceImpl.java @@ -31,6 +31,7 @@ import org.apache.seatunnel.app.domain.response.PageInfo; import org.apache.seatunnel.app.domain.response.job.JobDefinitionRes; import org.apache.seatunnel.app.security.UserContextHolder; import org.apache.seatunnel.app.service.IJobDefinitionService; +import org.apache.seatunnel.app.service.WorkspaceService; import org.apache.seatunnel.app.utils.ServletUtils; import org.apache.seatunnel.common.access.AccessType; import org.apache.seatunnel.common.access.ResourceType; @@ -72,6 +73,8 @@ public class JobDefinitionServiceImpl extends SeatunnelBaseServiceImpl @Resource(name = "jobVersionDaoImpl") private IJobVersionDao jobVersionDao; + @Resource private WorkspaceService workspaceService; + @Override @Transactional public long createJob(JobReq jobReq) throws CodeGenerateUtils.CodeGenerateException { @@ -206,6 +209,12 @@ public class JobDefinitionServiceImpl extends SeatunnelBaseServiceImpl jobDefinitionDao.delete(id); } + @Override + public List<String> getJobDefinitionNames(String workspaceName, String searchName) { + return jobDefinitionDao.getJobDefinitionNames( + workspaceService.getWorkspaceIdOrCurrent(workspaceName), searchName); + } + private void permCheck(String resourceName, AccessType accessType) { permissionCheck( resourceName, ResourceType.JOB, accessType, UserContextHolder.getAccessInfo()); diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/impl/UserServiceImpl.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/impl/UserServiceImpl.java index 2a47e299..f6377600 100644 --- a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/impl/UserServiceImpl.java +++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/impl/UserServiceImpl.java @@ -245,6 +245,11 @@ public class UserServiceImpl extends SeatunnelBaseServiceImpl implements IUserSe return info; } + @Override + public List<String> getUserNames(String searchName) { + return userDaoImpl.getUserNames(searchName); + } + private void permCheck(String resourceName, AccessType accessType) { permissionCheck( resourceName, ResourceType.USER, accessType, UserContextHolder.getAccessInfo()); diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/impl/VirtualTableServiceImpl.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/impl/VirtualTableServiceImpl.java index 12e4ee41..9cc341e6 100644 --- a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/impl/VirtualTableServiceImpl.java +++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/impl/VirtualTableServiceImpl.java @@ -331,4 +331,11 @@ public class VirtualTableServiceImpl extends SeatunnelBaseServiceImpl Long datasourceIdLong = Long.valueOf(datasourceId); return virtualTableDao.getVirtualDatabaseNames(datasourceIdLong); } + + @Override + public List<String> getVirtualTableNamesWithinWorkspace( + String workspaceName, String searchName) { + return virtualTableDao.getDatasourceNames( + workspaceService.getWorkspaceIdOrCurrent(workspaceName), searchName); + } } diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/impl/WorkspaceServiceImpl.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/impl/WorkspaceServiceImpl.java index 9406aada..d209736d 100644 --- a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/impl/WorkspaceServiceImpl.java +++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/impl/WorkspaceServiceImpl.java @@ -164,4 +164,9 @@ public class WorkspaceServiceImpl extends SeatunnelBaseServiceImpl implements Wo AccessType.READ, UserContextHolder.getAccessInfo()); } + + @Override + public List<String> getWorkspaceNames(String searchName) { + return workspaceDao.getWorkspaceNames(searchName); + } } diff --git a/seatunnel-server/seatunnel-app/src/main/resources/org/apache/seatunnel/app/dal/mapper/UserMapper.xml b/seatunnel-server/seatunnel-app/src/main/resources/org/apache/seatunnel/app/dal/mapper/UserMapper.xml index 049aec32..27e3efee 100644 --- a/seatunnel-server/seatunnel-app/src/main/resources/org/apache/seatunnel/app/dal/mapper/UserMapper.xml +++ b/seatunnel-server/seatunnel-app/src/main/resources/org/apache/seatunnel/app/dal/mapper/UserMapper.xml @@ -104,4 +104,9 @@ from `user` where status = 0 </select> + <select id="queryUserNames" resultType="java.lang.String"> + select username + from `user` + where #{searchName} IS NULL OR username LIKE concat('%', #{searchName}, '%') + </select> </mapper> diff --git a/seatunnel-web-it/src/test/java/org/apache/seatunnel/app/controller/ResourceNameProviderControllerWrapper.java b/seatunnel-web-it/src/test/java/org/apache/seatunnel/app/controller/ResourceNameProviderControllerWrapper.java new file mode 100644 index 00000000..b0c2be3d --- /dev/null +++ b/seatunnel-web-it/src/test/java/org/apache/seatunnel/app/controller/ResourceNameProviderControllerWrapper.java @@ -0,0 +1,70 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.seatunnel.app.controller; + +import org.apache.seatunnel.app.common.Result; +import org.apache.seatunnel.app.common.SeatunnelWebTestingBase; +import org.apache.seatunnel.app.utils.JSONTestUtils; + +import com.fasterxml.jackson.core.type.TypeReference; + +import java.util.List; + +public class ResourceNameProviderControllerWrapper extends SeatunnelWebTestingBase { + + private String buildUrl(String baseUrl, String workspaceName, String searchName) { + StringBuilder url = new StringBuilder(baseUrl); + if (workspaceName != null || searchName != null) { + url.append("?"); + if (workspaceName != null) { + url.append("workspaceName=").append(workspaceName); + } + if (searchName != null) { + if (workspaceName != null) { + url.append("&"); + } + url.append("searchName=").append(searchName); + } + } + return url.toString(); + } + + public Result<List<String>> getWorkspaces(String searchName) { + String url = buildUrl("resources/workspace", null, searchName); + String response = sendRequest(urlWithParam(url)); + return JSONTestUtils.parseObject(response, new TypeReference<Result<List<String>>>() {}); + } + + public Result<List<String>> getDatasources(String workspaceName, String searchName) { + String url = buildUrl("resources/datasource", workspaceName, searchName); + String response = sendRequest(urlWithParam(url)); + return JSONTestUtils.parseObject(response, new TypeReference<Result<List<String>>>() {}); + } + + public Result<List<String>> getJobDefinitions(String workspaceName, String searchName) { + String url = buildUrl("resources/job_definition", workspaceName, searchName); + String response = sendRequest(urlWithParam(url)); + return JSONTestUtils.parseObject(response, new TypeReference<Result<List<String>>>() {}); + } + + public Result<List<String>> getUserNames(String searchName) { + String url = buildUrl("resources/user", null, searchName); + String response = sendRequest(urlWithParam(url)); + return JSONTestUtils.parseObject(response, new TypeReference<Result<List<String>>>() {}); + } +} diff --git a/seatunnel-web-it/src/test/java/org/apache/seatunnel/app/test/ResourceNameProviderControllerTest.java b/seatunnel-web-it/src/test/java/org/apache/seatunnel/app/test/ResourceNameProviderControllerTest.java new file mode 100644 index 00000000..4049ecc7 --- /dev/null +++ b/seatunnel-web-it/src/test/java/org/apache/seatunnel/app/test/ResourceNameProviderControllerTest.java @@ -0,0 +1,294 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.seatunnel.app.test; + +import org.apache.seatunnel.app.common.Result; +import org.apache.seatunnel.app.common.SeaTunnelWebCluster; +import org.apache.seatunnel.app.controller.JobDefinitionControllerWrapper; +import org.apache.seatunnel.app.controller.ResourceNameProviderControllerWrapper; +import org.apache.seatunnel.app.controller.SeatunnelDatasourceControllerWrapper; +import org.apache.seatunnel.app.controller.UserControllerWrapper; +import org.apache.seatunnel.app.controller.WorkspaceControllerWrapper; +import org.apache.seatunnel.app.domain.request.user.UserLoginReq; +import org.apache.seatunnel.app.domain.response.user.AddUserRes; +import org.apache.seatunnel.server.common.SeatunnelErrorEnum; + +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class ResourceNameProviderControllerTest { + private static final SeaTunnelWebCluster seaTunnelWebCluster = new SeaTunnelWebCluster(); + private static ResourceNameProviderControllerWrapper resourceWrapper; + private static WorkspaceControllerWrapper workspaceControllerWrapper; + private static UserControllerWrapper userControllerWrapper; + private static SeatunnelDatasourceControllerWrapper datasourceControllerWrapper; + private static JobDefinitionControllerWrapper jobDefinitionControllerWrapper; + private static final String uniqueId = "_" + System.currentTimeMillis(); + + @BeforeAll + public static void setUp() { + seaTunnelWebCluster.start(); + resourceWrapper = new ResourceNameProviderControllerWrapper(); + workspaceControllerWrapper = new WorkspaceControllerWrapper(); + userControllerWrapper = new UserControllerWrapper(); + datasourceControllerWrapper = new SeatunnelDatasourceControllerWrapper(); + jobDefinitionControllerWrapper = new JobDefinitionControllerWrapper(); + } + + @Test + public void testGetWorkspaces() { + String prefix = System.currentTimeMillis() + "_"; + String postfix = "_" + System.currentTimeMillis(); + String workspaceName = prefix + "workspace" + uniqueId + "_name" + postfix; + createWorkspace(workspaceName); + + // search with infix + Result<List<String>> result = resourceWrapper.getWorkspaces(uniqueId); + assertTrue(result.isSuccess()); + assertTrue(result.getData().contains(workspaceName)); + // search with prefix + result = resourceWrapper.getWorkspaces(prefix); + assertTrue(result.isSuccess()); + assertTrue(result.getData().contains(workspaceName)); + + // search with postfix + result = resourceWrapper.getWorkspaces(postfix); + assertTrue(result.isSuccess()); + assertTrue(result.getData().contains(workspaceName)); + + // search with null + result = resourceWrapper.getWorkspaces(null); + assertTrue(result.isSuccess()); + assertTrue(result.getData().contains(workspaceName)); + } + + @Test + public void testGetUserNames() { + String prefix = System.currentTimeMillis() + "_"; + String postfix = "_" + System.currentTimeMillis(); + String userName = prefix + "user" + uniqueId + "_name" + postfix; + String password = "password"; + String workspaceName = "workspace_user" + uniqueId; + createWorkspaceAndUser(workspaceName, userName, password); + + // search with infix + Result<List<String>> result = resourceWrapper.getUserNames(uniqueId); + assertTrue(result.isSuccess()); + assertTrue(result.getData().contains(userName)); + + // search with prefix + result = resourceWrapper.getUserNames(prefix); + assertTrue(result.isSuccess()); + assertTrue(result.getData().contains(userName)); + + // search with postfix + result = resourceWrapper.getUserNames(postfix); + assertTrue(result.isSuccess()); + assertTrue(result.getData().contains(userName)); + + // search with null + result = resourceWrapper.getUserNames(null); + assertTrue(result.isSuccess()); + assertTrue(result.getData().contains(userName)); + } + + @Test + public void testGetDatasource() { + String prefix = System.currentTimeMillis() + "_"; + String postfix = "_" + System.currentTimeMillis(); + String user1 = "user_get_datasource_11" + uniqueId; + String user2 = "user_get_datasource_12" + uniqueId; + String pass = "somePassword"; + String workspace1 = "workspace_get_datasource_11" + uniqueId; + String workspace2 = "workspace_get_datasource_12" + uniqueId; + + createWorkspaceAndUser(workspace1, user1, pass); + createWorkspaceAndUser(workspace2, user2, pass); + + userControllerWrapper.loginAndSetCurrentUser(new UserLoginReq(user1, pass, workspace1)); + String datasourceName1 = prefix + "ds-1" + uniqueId + "_get" + postfix; + datasourceControllerWrapper.createFakeSourceDatasource(datasourceName1); + + // search with infix + Result<List<String>> result = resourceWrapper.getDatasources(workspace1, uniqueId); + assertTrue(result.isSuccess()); + assertEquals(1, result.getData().size()); + assertTrue(result.getData().contains(datasourceName1)); + + // search with prefix + result = resourceWrapper.getDatasources(workspace1, prefix); + assertTrue(result.isSuccess()); + assertEquals(1, result.getData().size()); + assertTrue(result.getData().contains(datasourceName1)); + + // search with postfix + result = resourceWrapper.getDatasources(workspace1, postfix); + assertTrue(result.isSuccess()); + assertEquals(1, result.getData().size()); + assertTrue(result.getData().contains(datasourceName1)); + + // search without searchName + result = resourceWrapper.getDatasources(workspace1, null); + assertTrue(result.isSuccess()); + assertEquals(1, result.getData().size()); + assertTrue(result.getData().contains(datasourceName1)); + + // search without workspaceName + result = resourceWrapper.getDatasources(null, null); + assertTrue(result.isSuccess()); + assertEquals(1, result.getData().size()); + assertTrue(result.getData().contains(datasourceName1)); + + // logout and login with another user with another namespace + userControllerWrapper.logout(); + String datasourceName2 = prefix + "ds-2" + uniqueId + "_get" + postfix; + userControllerWrapper.loginAndSetCurrentUser(new UserLoginReq(user2, pass, workspace2)); + datasourceControllerWrapper.createFakeSourceDatasource(datasourceName2); + + // Admin user will automatically log in when API is invoked + userControllerWrapper.logout(); + result = resourceWrapper.getDatasources(workspace1, uniqueId); + assertTrue(result.isSuccess()); + assertEquals(1, result.getData().size()); + assertTrue(result.getData().contains(datasourceName1)); + + result = resourceWrapper.getDatasources(workspace2, uniqueId); + assertTrue(result.isSuccess()); + assertEquals(1, result.getData().size()); + assertTrue(result.getData().contains(datasourceName2)); + + // search without workspaceName + result = resourceWrapper.getDatasources(null, uniqueId); + assertTrue(result.isSuccess()); + // if workspace is not passed, default workspace will be used and have not added any + // datasource to default workspace + assertEquals(0, result.getData().size()); + + result = resourceWrapper.getDatasources("non_existing_workspace", uniqueId); + assertFalse(result.isSuccess()); + assertEquals(SeatunnelErrorEnum.RESOURCE_NOT_FOUND.getCode(), result.getCode()); + assertEquals("Workspace with name non_existing_workspace not found.", result.getMsg()); + } + + @Test + public void testGetJobDefinitions() { + String prefix = System.currentTimeMillis() + "_"; + String postfix = "_" + System.currentTimeMillis(); + String user1 = "user_get_job_11" + uniqueId; + String user2 = "user_get_job_12" + uniqueId; + String pass = "somePassword"; + String workspace1 = "workspace_get_job_11" + uniqueId; + String workspace2 = "workspace_get_job_12" + uniqueId; + + createWorkspaceAndUser(workspace1, user1, pass); + createWorkspaceAndUser(workspace2, user2, pass); + + userControllerWrapper.loginAndSetCurrentUser(new UserLoginReq(user1, pass, workspace1)); + String jobName1 = prefix + "job1" + uniqueId + "_get" + postfix; + jobDefinitionControllerWrapper.createJobDefinition(jobName1); + + // search with infix + Result<List<String>> result = resourceWrapper.getJobDefinitions(workspace1, uniqueId); + assertTrue(result.isSuccess()); + assertEquals(1, result.getData().size()); + assertTrue(result.getData().contains(jobName1)); + + // search with prefix + result = resourceWrapper.getJobDefinitions(workspace1, prefix); + assertTrue(result.isSuccess()); + assertEquals(1, result.getData().size()); + assertTrue(result.getData().contains(jobName1)); + + // search with postfix + result = resourceWrapper.getJobDefinitions(workspace1, postfix); + assertTrue(result.isSuccess()); + assertEquals(1, result.getData().size()); + assertTrue(result.getData().contains(jobName1)); + + // search without searchName + result = resourceWrapper.getJobDefinitions(workspace1, null); + assertTrue(result.isSuccess()); + assertEquals(1, result.getData().size()); + assertTrue(result.getData().contains(jobName1)); + + // search without workspaceName + result = resourceWrapper.getJobDefinitions(null, null); + assertTrue(result.isSuccess()); + assertEquals(1, result.getData().size()); + assertTrue(result.getData().contains(jobName1)); + + // logout and login with another user with another namespace + userControllerWrapper.logout(); + String jobName2 = prefix + "job2" + uniqueId + "_get" + postfix; + userControllerWrapper.loginAndSetCurrentUser(new UserLoginReq(user2, pass, workspace2)); + jobDefinitionControllerWrapper.createJobDefinition(jobName2); + + // Admin user will automatically log in when API is invoked + userControllerWrapper.logout(); + result = resourceWrapper.getJobDefinitions(workspace1, uniqueId); + assertTrue(result.isSuccess()); + assertEquals(1, result.getData().size()); + assertTrue(result.getData().contains(jobName1)); + + result = resourceWrapper.getJobDefinitions(workspace2, uniqueId); + assertTrue(result.isSuccess()); + assertEquals(1, result.getData().size()); + assertTrue(result.getData().contains(jobName2)); + + // search without workspaceName + result = resourceWrapper.getJobDefinitions(null, uniqueId); + assertTrue(result.isSuccess()); + // if workspace is not passed, default workspace will be used and have not added any job to + // default workspace + assertEquals(0, result.getData().size()); + + result = resourceWrapper.getJobDefinitions("non_existing_workspace", uniqueId); + assertFalse(result.isSuccess()); + assertEquals(SeatunnelErrorEnum.RESOURCE_NOT_FOUND.getCode(), result.getCode()); + assertEquals("Workspace with name non_existing_workspace not found.", result.getMsg()); + } + + private void createWorkspace(String workspaceName) { + Result<Long> result = workspaceControllerWrapper.createWorkspace(workspaceName); + assertTrue(result.isSuccess()); + assertTrue(result.getData() > 0); + } + + private void createWorkspaceAndUser(String workspaceName, String username, String password) { + workspaceControllerWrapper.createWorkspaceAndVerify(workspaceName); + Result<AddUserRes> result = userControllerWrapper.addUser(username, password); + assertTrue(result.isSuccess()); + } + + @AfterEach + public void cleanup() { + userControllerWrapper.logout(); + } + + @AfterAll + public static void tearDown() { + seaTunnelWebCluster.stop(); + } +}