diff --git a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/controller/ProjectController.java b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/controller/ProjectController.java index bdd7d6d7ea..6583081ab4 100644 --- a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/controller/ProjectController.java +++ b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/controller/ProjectController.java @@ -112,7 +112,8 @@ public class ProjectController extends BaseController { @ApiImplicitParams({ @ApiImplicitParam(name = "projectId", value = "PROJECT_ID", dataType = "Int", example = "100"), @ApiImplicitParam(name = "projectName", value = "PROJECT_NAME", dataType = "String"), - @ApiImplicitParam(name = "description", value = "PROJECT_DESC", dataType = "String") + @ApiImplicitParam(name = "description", value = "PROJECT_DESC", dataType = "String"), + @ApiImplicitParam(name = "userName", value = "USER_NAME", dataType = "String"), }) @PostMapping(value = "/update") @ResponseStatus(HttpStatus.OK) @@ -120,9 +121,9 @@ public class ProjectController extends BaseController { public Result updateProject(@ApiIgnore @RequestAttribute(value = Constants.SESSION_USER) User loginUser, @RequestParam("projectId") Integer projectId, @RequestParam("projectName") String projectName, - @RequestParam(value = "description", required = false) String description) { - logger.info("login user {} , updateProcessInstance project name: {}, desc: {}", loginUser.getUserName(), projectName, description); - Map result = projectService.update(loginUser, projectId, projectName, description); + @RequestParam(value = "description", required = false) String description, + @RequestParam(value = "userName") String userName) { + Map result = projectService.update(loginUser, projectId, projectName, description, userName); return returnDataList(result); } diff --git a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/enums/Status.java b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/enums/Status.java index 461a2d8f11..e538e65414 100644 --- a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/enums/Status.java +++ b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/enums/Status.java @@ -210,6 +210,7 @@ public enum Status { DELETE_WORKER_GROUP_FORBIDDEN_IN_DOCKER(10176, "delete worker group forbidden in docker ", "删除worker分组在docker中禁止"), WORKER_ADDRESS_INVALID(10177, "worker address {0} invalid", "worker地址[{0}]无效"), QUERY_WORKER_ADDRESS_LIST_FAIL(10178, "query worker address list fail ", "查询worker地址列表失败"), + TRANSFORM_PROJECT_OWNERSHIP(10179, "Please transform project ownership [{0}]", "请先转移项目所有权[{0}]"), UDF_FUNCTION_NOT_EXIST(20001, "UDF function not found", "UDF函数不存在"), UDF_FUNCTION_EXISTS(20002, "UDF function already exists", "UDF函数已存在"), diff --git a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/ProjectService.java b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/ProjectService.java index 205393f527..08b77a9448 100644 --- a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/ProjectService.java +++ b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/ProjectService.java @@ -84,9 +84,10 @@ public interface ProjectService { * @param projectId project id * @param projectName project name * @param desc description + * @param userName project owner * @return update result code */ - Map update(User loginUser, Integer projectId, String projectName, String desc); + Map update(User loginUser, Integer projectId, String projectName, String desc, String userName); /** * query unauthorized project diff --git a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/ProjectServiceImpl.java b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/ProjectServiceImpl.java index dcc2374a3a..2e8752fe0a 100644 --- a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/ProjectServiceImpl.java +++ b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/ProjectServiceImpl.java @@ -31,6 +31,7 @@ import org.apache.dolphinscheduler.dao.entity.User; import org.apache.dolphinscheduler.dao.mapper.ProcessDefinitionMapper; import org.apache.dolphinscheduler.dao.mapper.ProjectMapper; import org.apache.dolphinscheduler.dao.mapper.ProjectUserMapper; +import org.apache.dolphinscheduler.dao.mapper.UserMapper; import java.util.ArrayList; import java.util.Date; @@ -40,6 +41,8 @@ import java.util.List; import java.util.Map; import java.util.Set; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -61,6 +64,11 @@ public class ProjectServiceImpl extends BaseServiceImpl implements ProjectServic @Autowired private ProcessDefinitionMapper processDefinitionMapper; + @Autowired + private UserMapper userMapper; + + private Logger logger = LoggerFactory.getLogger(ProjectServiceImpl.class); + /** * create project * @@ -255,10 +263,11 @@ public class ProjectServiceImpl extends BaseServiceImpl implements ProjectServic * @param projectId project id * @param projectName project name * @param desc description + * @param userName project owner * @return update result code */ @Override - public Map update(User loginUser, Integer projectId, String projectName, String desc) { + public Map update(User loginUser, Integer projectId, String projectName, String desc, String userName) { Map result = new HashMap<>(); Map descCheck = checkDesc(desc); @@ -276,10 +285,15 @@ public class ProjectServiceImpl extends BaseServiceImpl implements ProjectServic putMsg(result, Status.PROJECT_ALREADY_EXISTS, projectName); return result; } + User user = userMapper.queryByUserNameAccurately(userName); + if (user == null) { + putMsg(result, Status.USER_NOT_EXIST, userName); + return result; + } project.setName(projectName); project.setDescription(desc); project.setUpdateTime(new Date()); - + project.setUserId(user.getId()); int update = projectMapper.updateById(project); if (update > 0) { putMsg(result, Status.SUCCESS); diff --git a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/UsersServiceImpl.java b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/UsersServiceImpl.java index bd329a4325..460b7b4fc9 100644 --- a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/UsersServiceImpl.java +++ b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/UsersServiceImpl.java @@ -36,6 +36,7 @@ import org.apache.dolphinscheduler.common.utils.PropertyUtils; import org.apache.dolphinscheduler.common.utils.StringUtils; import org.apache.dolphinscheduler.dao.entity.AlertGroup; import org.apache.dolphinscheduler.dao.entity.DatasourceUser; +import org.apache.dolphinscheduler.dao.entity.Project; import org.apache.dolphinscheduler.dao.entity.ProjectUser; import org.apache.dolphinscheduler.dao.entity.Resource; import org.apache.dolphinscheduler.dao.entity.ResourcesUser; @@ -45,6 +46,7 @@ import org.apache.dolphinscheduler.dao.entity.User; import org.apache.dolphinscheduler.dao.mapper.AlertGroupMapper; import org.apache.dolphinscheduler.dao.mapper.DataSourceUserMapper; import org.apache.dolphinscheduler.dao.mapper.ProcessDefinitionMapper; +import org.apache.dolphinscheduler.dao.mapper.ProjectMapper; import org.apache.dolphinscheduler.dao.mapper.ProjectUserMapper; import org.apache.dolphinscheduler.dao.mapper.ResourceMapper; import org.apache.dolphinscheduler.dao.mapper.ResourceUserMapper; @@ -108,6 +110,9 @@ public class UsersServiceImpl extends BaseServiceImpl implements UsersService { @Autowired private ProcessDefinitionMapper processDefinitionMapper; + @Autowired + private ProjectMapper projectMapper; + /** * create user, only system admin have permission @@ -490,6 +495,13 @@ public class UsersServiceImpl extends BaseServiceImpl implements UsersService { putMsg(result, Status.USER_NOT_EXIST, id); return result; } + // check if is a project owner + List projects = projectMapper.queryProjectCreatedByUser(id); + if (CollectionUtils.isNotEmpty(projects)) { + String projectNames = projects.stream().map(Project::getName).collect(Collectors.joining(",")); + putMsg(result, Status.TRANSFORM_PROJECT_OWNERSHIP, projectNames); + return result; + } // delete user User user = userMapper.queryTenantCodeByUserId(id); diff --git a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/controller/ProjectControllerTest.java b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/controller/ProjectControllerTest.java index 7a4a51a9b6..f86d898546 100644 --- a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/controller/ProjectControllerTest.java +++ b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/controller/ProjectControllerTest.java @@ -87,6 +87,7 @@ public class ProjectControllerTest extends AbstractControllerTest { paramsMap.add("projectId", projectId); paramsMap.add("projectName","project_test_update"); paramsMap.add("desc","the test project update"); + paramsMap.add("userName", "the project owner"); MvcResult mvcResult = mockMvc.perform(post("/projects/update") .header(SESSION_ID, sessionId) @@ -96,7 +97,7 @@ public class ProjectControllerTest extends AbstractControllerTest { .andReturn(); Result result = JSONUtils.parseObject(mvcResult.getResponse().getContentAsString(), Result.class); - Assert.assertEquals(Status.SUCCESS.getCode(),result.getCode().intValue()); + Assert.assertEquals(Status.USER_NOT_EXIST.getCode(),result.getCode().intValue()); logger.info("update project return result:{}", mvcResult.getResponse().getContentAsString()); } diff --git a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/ProjectServiceTest.java b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/ProjectServiceTest.java index ebb6026f63..773cba458e 100644 --- a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/ProjectServiceTest.java +++ b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/ProjectServiceTest.java @@ -30,6 +30,7 @@ import org.apache.dolphinscheduler.dao.entity.User; import org.apache.dolphinscheduler.dao.mapper.ProcessDefinitionMapper; import org.apache.dolphinscheduler.dao.mapper.ProjectMapper; import org.apache.dolphinscheduler.dao.mapper.ProjectUserMapper; +import org.apache.dolphinscheduler.dao.mapper.UserMapper; import java.util.ArrayList; import java.util.Collections; @@ -70,6 +71,9 @@ public class ProjectServiceTest { @Mock private ProcessDefinitionMapper processDefinitionMapper; + @Mock + private UserMapper userMapper; + private String projectName = "ProjectServiceTest"; private String userName = "ProjectServiceTest"; @@ -240,19 +244,24 @@ public class ProjectServiceTest { Mockito.when(projectMapper.queryByName(projectName)).thenReturn(project); Mockito.when(projectMapper.selectById(1)).thenReturn(getProject()); // PROJECT_NOT_FOUNT - Map result = projectService.update(loginUser, 12, projectName, "desc"); + Map result = projectService.update(loginUser, 12, projectName, "desc", "testUser"); logger.info(result.toString()); Assert.assertEquals(Status.PROJECT_NOT_FOUNT, result.get(Constants.STATUS)); //PROJECT_ALREADY_EXISTS - result = projectService.update(loginUser, 1, projectName, "desc"); + result = projectService.update(loginUser, 1, projectName, "desc", "testUser"); logger.info(result.toString()); Assert.assertEquals(Status.PROJECT_ALREADY_EXISTS, result.get(Constants.STATUS)); + Mockito.when(userMapper.queryByUserNameAccurately(Mockito.any())).thenReturn(null); + result = projectService.update(loginUser, 1, "test", "desc", "testuser"); + Assert.assertEquals(Status.USER_NOT_EXIST, result.get(Constants.STATUS)); + //success + Mockito.when(userMapper.queryByUserNameAccurately(Mockito.any())).thenReturn(new User()); project.setUserId(1); Mockito.when(projectMapper.updateById(Mockito.any(Project.class))).thenReturn(1); - result = projectService.update(loginUser, 1, "test", "desc"); + result = projectService.update(loginUser, 1, "test", "desc", "testUser"); logger.info(result.toString()); Assert.assertEquals(Status.SUCCESS, result.get(Constants.STATUS)); diff --git a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/UsersServiceTest.java b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/UsersServiceTest.java index d8bcdb8070..8ae16b8639 100644 --- a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/UsersServiceTest.java +++ b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/UsersServiceTest.java @@ -31,11 +31,13 @@ import org.apache.dolphinscheduler.common.enums.UserType; import org.apache.dolphinscheduler.common.utils.CollectionUtils; import org.apache.dolphinscheduler.common.utils.EncryptionUtils; import org.apache.dolphinscheduler.dao.entity.AlertGroup; +import org.apache.dolphinscheduler.dao.entity.Project; import org.apache.dolphinscheduler.dao.entity.Resource; import org.apache.dolphinscheduler.dao.entity.Tenant; import org.apache.dolphinscheduler.dao.entity.User; import org.apache.dolphinscheduler.dao.mapper.AlertGroupMapper; import org.apache.dolphinscheduler.dao.mapper.DataSourceUserMapper; +import org.apache.dolphinscheduler.dao.mapper.ProjectMapper; import org.apache.dolphinscheduler.dao.mapper.ProjectUserMapper; import org.apache.dolphinscheduler.dao.mapper.ResourceMapper; import org.apache.dolphinscheduler.dao.mapper.ResourceUserMapper; @@ -61,6 +63,7 @@ import org.slf4j.LoggerFactory; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.google.common.collect.Lists; /** * users service test @@ -97,6 +100,9 @@ public class UsersServiceTest { @Mock private UDFUserMapper udfUserMapper; + @Mock + private ProjectMapper projectMapper; + private String queueName = "UsersServiceTestQueue"; @Before @@ -292,7 +298,13 @@ public class UsersServiceTest { logger.info(result.toString()); Assert.assertEquals(Status.USER_NOT_EXIST, result.get(Constants.STATUS)); + // user is project owner + Mockito.when(projectMapper.queryProjectCreatedByUser(1)).thenReturn(Lists.newArrayList(new Project())); + result = usersService.deleteUserById(loginUser, 1); + Assert.assertEquals(Status.TRANSFORM_PROJECT_OWNERSHIP, result.get(Constants.STATUS)); + //success + Mockito.when(projectMapper.queryProjectCreatedByUser(1)).thenReturn(null); result = usersService.deleteUserById(loginUser, 1); logger.info(result.toString()); Assert.assertEquals(Status.SUCCESS, result.get(Constants.STATUS)); @@ -301,7 +313,6 @@ public class UsersServiceTest { Assert.assertTrue(false); } - } @Test diff --git a/dolphinscheduler-ui/src/js/conf/home/pages/projects/pages/list/_source/createProject.vue b/dolphinscheduler-ui/src/js/conf/home/pages/projects/pages/list/_source/createProject.vue index 8e9c5afa32..064c1e7f01 100644 --- a/dolphinscheduler-ui/src/js/conf/home/pages/projects/pages/list/_source/createProject.vue +++ b/dolphinscheduler-ui/src/js/conf/home/pages/projects/pages/list/_source/createProject.vue @@ -31,6 +31,18 @@ + + + +