From 65a6b580ab27d13a7755a25a8b895dce77a451fb Mon Sep 17 00:00:00 2001 From: ouyangyewei Date: Mon, 13 Dec 2021 17:56:06 +0800 Subject: [PATCH] [Cherry-pick-2.0.2][Feature][Dolphinscheduler-api] cherry-pick from dev to 2.0.2 (#7373) * [Feature-7110][dolphinscheduler-api] support grant project by code * [Feature-7180][dolphinscheduler-api] Revoke project permission for specified user * [Feature-7191][dolphinscheduler-api] support query authorized user list by project code * [Feature-7301][dolphinscheduler-api] Support query access token for specified user Co-authored-by: ouyangyewei --- .../api/controller/AccessTokenController.java | 22 +++++ .../api/controller/ProjectController.java | 22 +++++ .../api/controller/UsersController.java | 49 +++++++++++ .../dolphinscheduler/api/enums/Status.java | 4 +- .../api/service/AccessTokenService.java | 9 ++ .../api/service/ProjectService.java | 9 ++ .../api/service/UsersService.java | 19 +++++ .../service/impl/AccessTokenServiceImpl.java | 25 ++++++ .../api/service/impl/ProjectServiceImpl.java | 25 ++++++ .../api/service/impl/UsersServiceImpl.java | 84 +++++++++++++++++++ .../main/resources/i18n/messages.properties | 5 ++ .../resources/i18n/messages_en_US.properties | 5 ++ .../resources/i18n/messages_zh_CN.properties | 5 ++ .../controller/AccessTokenControllerTest.java | 13 +++ .../api/controller/ProjectControllerTest.java | 10 +++ .../api/controller/UsersControllerTest.java | 37 ++++++++ .../api/service/AccessTokenServiceTest.java | 21 +++++ .../api/service/ProjectServiceTest.java | 54 ++++++++++++ .../api/service/UsersServiceTest.java | 84 +++++++++++++++++++ .../dao/mapper/AccessTokenMapper.java | 10 +++ .../dao/mapper/UserMapper.java | 7 ++ .../dao/mapper/AccessTokenMapper.xml | 7 ++ .../dao/mapper/UserMapper.xml | 8 ++ 23 files changed, 533 insertions(+), 1 deletion(-) diff --git a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/controller/AccessTokenController.java b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/controller/AccessTokenController.java index 01bb22d9ae..a841bd6be4 100644 --- a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/controller/AccessTokenController.java +++ b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/controller/AccessTokenController.java @@ -17,6 +17,7 @@ package org.apache.dolphinscheduler.api.controller; +import static org.apache.dolphinscheduler.api.enums.Status.QUERY_ACCESSTOKEN_BY_USER_ERROR; import static org.apache.dolphinscheduler.api.enums.Status.CREATE_ACCESS_TOKEN_ERROR; import static org.apache.dolphinscheduler.api.enums.Status.DELETE_ACCESS_TOKEN_ERROR; import static org.apache.dolphinscheduler.api.enums.Status.GENERATE_TOKEN_ERROR; @@ -140,6 +141,27 @@ public class AccessTokenController extends BaseController { return result; } + /** + * query access token for specified user + * + * @param loginUser login user + * @param userId user id + * @return token list for specified user + */ + @ApiOperation(value = "queryAccessTokenByUser", notes = "QUERY_ACCESS_TOKEN_BY_USER_NOTES") + @ApiImplicitParams({ + @ApiImplicitParam(name = "userId", value = "USER_ID", dataType = "Int") + }) + @GetMapping(value = "/user/{userId}") + @ResponseStatus(HttpStatus.OK) + @ApiException(QUERY_ACCESSTOKEN_BY_USER_ERROR) + @AccessLogAnnotation(ignoreRequestArgs = "loginUser") + public Result queryAccessTokenByUser(@ApiIgnore @RequestAttribute(value = Constants.SESSION_USER) User loginUser, + @PathVariable("userId") Integer userId) { + Map result = this.accessTokenService.queryAccessTokenByUser(loginUser, userId); + return this.returnDataList(result); + } + /** * delete access token by id * 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 1dfb7e5df8..22e582204d 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 @@ -17,6 +17,7 @@ package org.apache.dolphinscheduler.api.controller; +import static org.apache.dolphinscheduler.api.enums.Status.QUERY_AUTHORIZED_USER; import static org.apache.dolphinscheduler.api.enums.Status.CREATE_PROJECT_ERROR; import static org.apache.dolphinscheduler.api.enums.Status.DELETE_PROJECT_ERROR; import static org.apache.dolphinscheduler.api.enums.Status.LOGIN_USER_QUERY_PROJECT_LIST_PAGING_ERROR; @@ -237,6 +238,27 @@ public class ProjectController extends BaseController { return returnDataList(result); } + /** + * query authorized user + * + * @param loginUser login user + * @param projectCode project code + * @return users who have permission for the specified project + */ + @ApiOperation(value = "queryAuthorizedUser", notes = "QUERY_AUTHORIZED_USER_NOTES") + @ApiImplicitParams({ + @ApiImplicitParam(name = "projectCode", value = "PROJECT_CODE", dataType = "Long", example = "100") + }) + @GetMapping(value = "/authed-user") + @ResponseStatus(HttpStatus.OK) + @ApiException(QUERY_AUTHORIZED_USER) + @AccessLogAnnotation(ignoreRequestArgs = "loginUser") + public Result queryAuthorizedUser(@ApiIgnore @RequestAttribute(value = Constants.SESSION_USER) User loginUser, + @RequestParam("projectCode") Long projectCode) { + Map result = this.projectService.queryAuthorizedUser(loginUser, projectCode); + return this.returnDataList(result); + } + /** * query authorized and user created project * diff --git a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/controller/UsersController.java b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/controller/UsersController.java index 11de0389ad..a79e5f709a 100644 --- a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/controller/UsersController.java +++ b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/controller/UsersController.java @@ -17,6 +17,7 @@ package org.apache.dolphinscheduler.api.controller; +import static org.apache.dolphinscheduler.api.enums.Status.REVOKE_PROJECT_ERROR; import static org.apache.dolphinscheduler.api.enums.Status.AUTHORIZED_USER_ERROR; import static org.apache.dolphinscheduler.api.enums.Status.CREATE_USER_ERROR; import static org.apache.dolphinscheduler.api.enums.Status.DELETE_USER_BY_ID_ERROR; @@ -234,6 +235,54 @@ public class UsersController extends BaseController { return returnDataList(result); } + /** + * grant project by code + * + * @param loginUser login user + * @param userId user id + * @param projectCode project code + * @return grant result code + */ + @ApiOperation(value = "grantProjectByCode", notes = "GRANT_PROJECT_BY_CODE_NOTES") + @ApiImplicitParams({ + @ApiImplicitParam(name = "userId", value = "USER_ID", required = true, dataType = "Int", example = "100"), + @ApiImplicitParam(name = "projectCode", value = "PROJECT_CODE", required = true, type = "Long") + }) + @PostMapping(value = "/grant-project-by-code") + @ResponseStatus(HttpStatus.OK) + @ApiException(GRANT_PROJECT_ERROR) + @AccessLogAnnotation + public Result grantProjectByCode(@ApiIgnore @RequestAttribute(value = Constants.SESSION_USER) User loginUser, + @RequestParam(value = "userId") int userId, + @RequestParam(value = "projectCode") long projectCode) { + Map result = this.usersService.grantProjectByCode(loginUser, userId, projectCode); + return this.returnDataList(result); + } + + /** + * revoke project + * + * @param loginUser login user + * @param userId user id + * @param projectCode project code + * @return revoke result code + */ + @ApiOperation(value = "revokeProject", notes = "REVOKE_PROJECT_NOTES") + @ApiImplicitParams({ + @ApiImplicitParam(name = "userId", value = "USER_ID", required = true, dataType = "Int", example = "100"), + @ApiImplicitParam(name = "projectCode", value = "PROJECT_CODE", required = true, type = "Long", example = "100") + }) + @PostMapping(value = "/revoke-project") + @ResponseStatus(HttpStatus.OK) + @ApiException(REVOKE_PROJECT_ERROR) + @AccessLogAnnotation + public Result revokeProject(@ApiIgnore @RequestAttribute(value = Constants.SESSION_USER) User loginUser, + @RequestParam(value = "userId") int userId, + @RequestParam(value = "projectCode") long projectCode) { + Map result = this.usersService.revokeProject(loginUser, userId, projectCode); + return returnDataList(result); + } + /** * grant resource * 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 7276404df6..c4243f0e9e 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 @@ -212,7 +212,8 @@ public enum Status { TRANSFORM_PROJECT_OWNERSHIP(10179, "Please transform project ownership [{0}]", "请先转移项目所有权[{0}]"), QUERY_ALERT_GROUP_ERROR(10180, "query alert group error", "查询告警组错误"), CURRENT_LOGIN_USER_TENANT_NOT_EXIST(10181, "the tenant of the currently login user is not specified", "未指定当前登录用户的租户"), - + REVOKE_PROJECT_ERROR(10182, "revoke project error", "撤销项目授权错误"), + QUERY_AUTHORIZED_USER(10183, "query authorized user error", "查询拥有项目权限的用户错误"), UDF_FUNCTION_NOT_EXIST(20001, "UDF function not found", "UDF函数不存在"), UDF_FUNCTION_EXISTS(20002, "UDF function already exists", "UDF函数已存在"), @@ -304,6 +305,7 @@ public enum Status { UPDATE_ACCESS_TOKEN_ERROR(70013, "update access token error", "更新访问token错误"), DELETE_ACCESS_TOKEN_ERROR(70014, "delete access token error", "删除访问token错误"), ACCESS_TOKEN_NOT_EXIST(70015, "access token not exist", "访问token不存在"), + QUERY_ACCESSTOKEN_BY_USER_ERROR(70016, "query access token by user error", "查询访问指定用户的token错误"), COMMAND_STATE_COUNT_ERROR(80001, "task instance state count error", "查询各状态任务实例数错误"), diff --git a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/AccessTokenService.java b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/AccessTokenService.java index fc4ed78d46..b3e14eeee4 100644 --- a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/AccessTokenService.java +++ b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/AccessTokenService.java @@ -38,6 +38,15 @@ public interface AccessTokenService { */ Result queryAccessTokenList(User loginUser, String searchVal, Integer pageNo, Integer pageSize); + /** + * query access token for specified user + * + * @param loginUser login user + * @param userId user id + * @return token list for specified user + */ + Map queryAccessTokenByUser(User loginUser, Integer userId); + /** * create token * 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 dffa866ac8..1300834442 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 @@ -110,6 +110,15 @@ public interface ProjectService { */ Map queryAuthorizedProject(User loginUser, Integer userId); + /** + * query authorized user + * + * @param loginUser login user + * @param projectCode project code + * @return users who have permission for the specified project + */ + Map queryAuthorizedUser(User loginUser, Long projectCode); + /** * query authorized project * diff --git a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/UsersService.java b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/UsersService.java index a5c004b964..485702a0e8 100644 --- a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/UsersService.java +++ b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/UsersService.java @@ -153,6 +153,25 @@ public interface UsersService { Map grantProject(User loginUser, int userId, String projectIds); + /** + * grant project by code + * + * @param loginUser login user + * @param userId user id + * @param projectCode project code + * @return grant result code + */ + Map grantProjectByCode(User loginUser, int userId, long projectCode); + + /** + * revoke the project permission for specified user. + * @param loginUser Login user + * @param userId User id + * @param projectCode Project Code + * @return + */ + Map revokeProject(User loginUser, int userId, long projectCode); + /** * grant resource * diff --git a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/AccessTokenServiceImpl.java b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/AccessTokenServiceImpl.java index 39048469be..f5e434a163 100644 --- a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/AccessTokenServiceImpl.java +++ b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/AccessTokenServiceImpl.java @@ -31,6 +31,7 @@ import org.apache.dolphinscheduler.dao.mapper.AccessTokenMapper; import java.util.Date; import java.util.HashMap; +import java.util.List; import java.util.Map; import org.slf4j.Logger; @@ -78,6 +79,30 @@ public class AccessTokenServiceImpl extends BaseServiceImpl implements AccessTok return result; } + /** + * query access token for specified user + * + * @param loginUser login user + * @param userId user id + * @return token list for specified user + */ + @Override + public Map queryAccessTokenByUser(User loginUser, Integer userId) { + Map result = new HashMap<>(); + result.put(Constants.STATUS, false); + + // only admin can operate + if (isNotAdmin(loginUser, result)) { + return result; + } + + // query access token for specified user + List accessTokenList = this.accessTokenMapper.queryAccessTokenByUser(userId); + result.put(Constants.DATA_LIST, accessTokenList); + this.putMsg(result, Status.SUCCESS); + return result; + } + /** * create token * 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 a02458a06d..3bb222b752 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 @@ -389,6 +389,31 @@ public class ProjectServiceImpl extends BaseServiceImpl implements ProjectServic return result; } + /** + * query authorized user + * + * @param loginUser login user + * @param projectCode project code + * @return users who have permission for the specified project + */ + @Override + public Map queryAuthorizedUser(User loginUser, Long projectCode) { + Map result = new HashMap<>(); + + // 1. check read permission + Project project = this.projectMapper.queryByCode(projectCode); + boolean hasProjectAndPerm = this.hasProjectAndPerm(loginUser, project, result); + if (!hasProjectAndPerm) { + return result; + } + + // 2. query authorized user list + List users = this.userMapper.queryAuthedUserListByProjectId(project.getId()); + result.put(Constants.DATA_LIST, users); + this.putMsg(result, Status.SUCCESS); + return result; + } + /** * query authorized project * 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 e07516ac0e..ab7a24433e 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 @@ -579,6 +579,90 @@ public class UsersServiceImpl extends BaseServiceImpl implements UsersService { return result; } + /** + * grant project by code + * + * @param loginUser login user + * @param userId user id + * @param projectCode project code + * @return grant result code + */ + @Override + public Map grantProjectByCode(final User loginUser, final int userId, final long projectCode) { + Map result = new HashMap<>(); + result.put(Constants.STATUS, false); + + // 1. check if user is existed + User tempUser = this.userMapper.selectById(userId); + if (tempUser == null) { + this.putMsg(result, Status.USER_NOT_EXIST, userId); + return result; + } + + // 2. check if project is existed + Project project = this.projectMapper.queryByCode(projectCode); + if (project == null) { + this.putMsg(result, Status.PROJECT_NOT_FOUNT, projectCode); + return result; + } + + // 3. only project owner can operate + if (!this.hasPerm(loginUser, project.getUserId())) { + this.putMsg(result, Status.USER_NO_OPERATION_PERM); + return result; + } + + // 4. maintain the relationship between project and user + final Date today = new Date(); + ProjectUser projectUser = new ProjectUser(); + projectUser.setUserId(userId); + projectUser.setProjectId(project.getId()); + projectUser.setPerm(7); + projectUser.setCreateTime(today); + projectUser.setUpdateTime(today); + this.projectUserMapper.insert(projectUser); + + this.putMsg(result, Status.SUCCESS); + return result; + } + + /** + * revoke the project permission for specified user. + * @param loginUser Login user + * @param userId User id + * @param projectCode Project Code + * @return + */ + @Override + public Map revokeProject(User loginUser, int userId, long projectCode) { + Map result = new HashMap<>(); + result.put(Constants.STATUS, false); + + // 1. only admin can operate + if (this.check(result, !this.isAdmin(loginUser), Status.USER_NO_OPERATION_PERM)) { + return result; + } + + // 2. check if user is existed + User user = this.userMapper.selectById(userId); + if (user == null) { + this.putMsg(result, Status.USER_NOT_EXIST, userId); + return result; + } + + // 3. check if project is existed + Project project = this.projectMapper.queryByCode(projectCode); + if (project == null) { + this.putMsg(result, Status.PROJECT_NOT_FOUNT, projectCode); + return result; + } + + // 4. delete the relationship between project and user + this.projectUserMapper.deleteProjectRelation(project.getId(), user.getId()); + this.putMsg(result, Status.SUCCESS); + return result; + } + /** * grant resource * diff --git a/dolphinscheduler-api/src/main/resources/i18n/messages.properties b/dolphinscheduler-api/src/main/resources/i18n/messages.properties index 62d3615664..b5b127be54 100644 --- a/dolphinscheduler-api/src/main/resources/i18n/messages.properties +++ b/dolphinscheduler-api/src/main/resources/i18n/messages.properties @@ -140,10 +140,12 @@ DELETE_PROJECT_BY_ID_NOTES=delete project by id QUERY_UNAUTHORIZED_PROJECT_NOTES=query unauthorized project QUERY_ALL_PROJECT_LIST_NOTES=query all project list QUERY_AUTHORIZED_PROJECT_NOTES=query authorized project +QUERY_AUTHORIZED_USER_NOTES=query authorized user TASK_RECORD_TAG=task record related operation QUERY_TASK_RECORD_LIST_PAGING_NOTES=query task record list paging CREATE_TOKEN_NOTES=create token ,note: please login first QUERY_ACCESS_TOKEN_LIST_NOTES=query access token list paging +QUERY_ACCESS_TOKEN_BY_USER_NOTES=query access token for specified user SCHEDULE=schedule WARNING_TYPE=warning type(sending strategy) WARNING_GROUP_ID=warning group id @@ -221,6 +223,9 @@ UPDATE_USER_NOTES=update user DELETE_USER_BY_ID_NOTES=delete user by id GRANT_PROJECT_NOTES=GRANT PROJECT PROJECT_IDS=project ids(string format, multiple projects separated by ",") +GRANT_PROJECT_BY_CODE_NOTES=GRANT PROJECT BY CODE +REVOKE_PROJECT_NOTES=REVOKE PROJECT FOR USER +PROJECT_CODE=project codes GRANT_RESOURCE_NOTES=grant resource file RESOURCE_IDS=resource ids(string format, multiple resources separated by ",") GET_USER_INFO_NOTES=get user info diff --git a/dolphinscheduler-api/src/main/resources/i18n/messages_en_US.properties b/dolphinscheduler-api/src/main/resources/i18n/messages_en_US.properties index db705be6ab..3fa384e494 100644 --- a/dolphinscheduler-api/src/main/resources/i18n/messages_en_US.properties +++ b/dolphinscheduler-api/src/main/resources/i18n/messages_en_US.properties @@ -156,10 +156,12 @@ QUERY_ALL_PROJECT_LIST_NOTES=query all project list DELETE_PROJECT_BY_ID_NOTES=delete project by id QUERY_UNAUTHORIZED_PROJECT_NOTES=query unauthorized project QUERY_AUTHORIZED_PROJECT_NOTES=query authorized project +QUERY_AUTHORIZED_USER_NOTES=query authorized user TASK_RECORD_TAG=task record related operation QUERY_TASK_RECORD_LIST_PAGING_NOTES=query task record list paging CREATE_TOKEN_NOTES=create token ,note: please login first QUERY_ACCESS_TOKEN_LIST_NOTES=query access token list paging +QUERY_ACCESS_TOKEN_BY_USER_NOTES=query access token for specified user SCHEDULE=schedule WARNING_TYPE=warning type(sending strategy) WARNING_GROUP_ID=warning group id @@ -268,6 +270,9 @@ UPDATE_QUEUE_NOTES=update queue DELETE_USER_BY_ID_NOTES=delete user by id GRANT_PROJECT_NOTES=GRANT PROJECT PROJECT_IDS=project ids(string format, multiple projects separated by ",") +GRANT_PROJECT_BY_CODE_NOTES=GRANT PROJECT BY CODE +REVOKE_PROJECT_NOTES=REVOKE PROJECT FOR USER +PROJECT_CODE=project codes GRANT_RESOURCE_NOTES=grant resource file RESOURCE_IDS=resource ids(string format, multiple resources separated by ",") GET_USER_INFO_NOTES=get user info diff --git a/dolphinscheduler-api/src/main/resources/i18n/messages_zh_CN.properties b/dolphinscheduler-api/src/main/resources/i18n/messages_zh_CN.properties index ec88f74fb5..e18cdf3395 100644 --- a/dolphinscheduler-api/src/main/resources/i18n/messages_zh_CN.properties +++ b/dolphinscheduler-api/src/main/resources/i18n/messages_zh_CN.properties @@ -145,10 +145,12 @@ QUERY_ALL_PROJECT_LIST_NOTES=查询所有项目 DELETE_PROJECT_BY_ID_NOTES=通过ID删除项目 QUERY_UNAUTHORIZED_PROJECT_NOTES=查询未授权的项目 QUERY_AUTHORIZED_PROJECT_NOTES=查询授权项目 +QUERY_AUTHORIZED_USER_NOTES=查询拥有项目授权的用户 TASK_RECORD_TAG=任务记录相关操作 QUERY_TASK_RECORD_LIST_PAGING_NOTES=分页查询任务记录列表 CREATE_TOKEN_NOTES=创建token,注意需要先登录 QUERY_ACCESS_TOKEN_LIST_NOTES=分页查询access token列表 +QUERY_ACCESS_TOKEN_BY_USER_NOTES=查询指定用户的access token SCHEDULE=定时 WARNING_TYPE=发送策略 WARNING_GROUP_ID=发送组ID @@ -256,6 +258,9 @@ UPDATE_QUEUE_NOTES=更新队列 DELETE_USER_BY_ID_NOTES=删除用户通过ID GRANT_PROJECT_NOTES=授权项目 PROJECT_IDS=项目IDS(字符串格式,多个项目以","分割) +GRANT_PROJECT_BY_CODE_NOTES=授权项目 +REVOKE_PROJECT_NOTES=撤销用户的项目权限 +PROJECT_CODE=项目Code GRANT_RESOURCE_NOTES=授权资源文件 RESOURCE_IDS=资源ID列表(字符串格式,多个资源ID以","分割) GET_USER_INFO_NOTES=获取用户信息 diff --git a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/controller/AccessTokenControllerTest.java b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/controller/AccessTokenControllerTest.java index a13d773abf..0a9d7a3a5e 100644 --- a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/controller/AccessTokenControllerTest.java +++ b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/controller/AccessTokenControllerTest.java @@ -109,6 +109,19 @@ public class AccessTokenControllerTest extends AbstractControllerTest { logger.info(mvcResult.getResponse().getContentAsString()); } + @Test + public void testQueryAccessTokenByUser() throws Exception { + MvcResult mvcResult = this.mockMvc + .perform(get("/access-tokens/user/1") + .header("sessionId", this.sessionId)) + .andExpect(status().isOk()) + .andExpect(content().contentType(MediaType.APPLICATION_JSON)) + .andReturn(); + Result result = JSONUtils.parseObject(mvcResult.getResponse().getContentAsString(), Result.class); + Assert.assertEquals(Status.SUCCESS.getCode(), result.getCode().intValue()); + logger.info(mvcResult.getResponse().getContentAsString()); + } + @Test public void testDelAccessTokenById() throws Exception { MultiValueMap paramsMap = new LinkedMultiValueMap<>(); 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 0bce72d9f9..118484c4c9 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 @@ -125,6 +125,16 @@ public class ProjectControllerTest { Assert.assertEquals(Status.SUCCESS.getCode(), response.getCode().intValue()); } + @Test + public void testQueryAuthorizedUser() { + Map result = new HashMap<>(); + this.putMsg(result, Status.SUCCESS); + + Mockito.when(this.projectService.queryAuthorizedUser(this.user, 3682329499136L)).thenReturn(result); + Result response = this.projectController.queryAuthorizedUser(this.user, 3682329499136L); + Assert.assertEquals(Status.SUCCESS.getCode(), response.getCode().intValue()); + } + @Test public void testQueryAllProjectList() { Map result = new HashMap<>(); diff --git a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/controller/UsersControllerTest.java b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/controller/UsersControllerTest.java index fb4b0cee4a..248cfea2a9 100644 --- a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/controller/UsersControllerTest.java +++ b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/controller/UsersControllerTest.java @@ -108,6 +108,43 @@ public class UsersControllerTest extends AbstractControllerTest { logger.info(mvcResult.getResponse().getContentAsString()); } + @Test + public void testGrantProjectByCode() throws Exception { + MultiValueMap paramsMap = new LinkedMultiValueMap<>(); + paramsMap.add("userId", "32"); + paramsMap.add("projectCode", "3682329499136"); + + MvcResult mvcResult = this.mockMvc + .perform(post("/users/grant-project-by-code") + .header(SESSION_ID, this.sessionId) + .params(paramsMap)) + .andExpect(status().isOk()) + .andExpect(content().contentType(MediaType.APPLICATION_JSON)) + .andReturn(); + + Result result = JSONUtils.parseObject(mvcResult.getResponse().getContentAsString(), Result.class); + Assert.assertEquals(Status.USER_NOT_EXIST.getCode(), result.getCode().intValue()); + logger.info(mvcResult.getResponse().getContentAsString()); + } + + @Test + public void testRevokeProject() throws Exception { + MultiValueMap paramsMap = new LinkedMultiValueMap<>(); + paramsMap.add("userId", "32"); + paramsMap.add("projectCode", "3682329499136"); + + MvcResult mvcResult = this.mockMvc.perform(post("/users/revoke-project") + .header(SESSION_ID, this.sessionId) + .params(paramsMap)) + .andExpect(status().isOk()) + .andExpect(content().contentType(MediaType.APPLICATION_JSON)) + .andReturn(); + + Result result = JSONUtils.parseObject(mvcResult.getResponse().getContentAsString(), Result.class); + Assert.assertEquals(Status.USER_NOT_EXIST.getCode(), result.getCode().intValue()); + logger.info(mvcResult.getResponse().getContentAsString()); + } + @Test public void testGrantResource() throws Exception { MultiValueMap paramsMap = new LinkedMultiValueMap<>(); diff --git a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/AccessTokenServiceTest.java b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/AccessTokenServiceTest.java index 3b8ef6b792..8f8554f97e 100644 --- a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/AccessTokenServiceTest.java +++ b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/AccessTokenServiceTest.java @@ -38,11 +38,13 @@ import java.util.Date; import java.util.List; import java.util.Map; +import org.assertj.core.util.Lists; import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.InjectMocks; import org.mockito.Mock; +import org.mockito.Mockito; import org.mockito.junit.MockitoJUnitRunner; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -79,6 +81,25 @@ public class AccessTokenServiceTest { Assert.assertTrue(pageInfo.getTotal() > 0); } + @Test + public void testQueryAccessTokenByUser() { + List accessTokenList = Lists.newArrayList(this.getEntity()); + Mockito.when(this.accessTokenMapper.queryAccessTokenByUser(1)).thenReturn(accessTokenList); + + // USER_NO_OPERATION_PERM + User user = this.getLoginUser(); + user.setUserType(UserType.GENERAL_USER); + Map result = this.accessTokenService.queryAccessTokenByUser(user, 1); + logger.info(result.toString()); + Assert.assertEquals(Status.USER_NO_OPERATION_PERM, result.get(Constants.STATUS)); + + // SUCCESS + user.setUserType(UserType.ADMIN_USER); + result = this.accessTokenService.queryAccessTokenByUser(user, 1); + logger.info(result.toString()); + Assert.assertEquals(Status.SUCCESS, result.get(Constants.STATUS)); + } + @Test public void testCreateToken() { 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 6f516b750f..de782df087 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 @@ -276,6 +276,38 @@ public class ProjectServiceTest { Assert.assertTrue(CollectionUtils.isNotEmpty(projects)); } + @Test + public void testQueryAuthorizedUser() { + final User loginUser = this.getLoginUser(); + + // Failure 1: PROJECT_NOT_FOUND + Map result = this.projectService.queryAuthorizedUser(loginUser, 3682329499136L); + logger.info("FAILURE 1: {}", result.toString()); + Assert.assertEquals(Status.PROJECT_NOT_FOUNT, result.get(Constants.STATUS)); + + // Failure 2: USER_NO_OPERATION_PROJECT_PERM + loginUser.setId(100); + Mockito.when(this.projectMapper.queryByCode(Mockito.anyLong())).thenReturn(this.getProject()); + result = this.projectService.queryAuthorizedUser(loginUser, 3682329499136L); + logger.info("FAILURE 2: {}", result.toString()); + Assert.assertEquals(Status.USER_NO_OPERATION_PROJECT_PERM, result.get(Constants.STATUS)); + + // SUCCESS + loginUser.setUserType(UserType.ADMIN_USER); + Mockito.when(this.userMapper.queryAuthedUserListByProjectId(1)).thenReturn(this.getUserList()); + result = this.projectService.queryAuthorizedUser(loginUser, 3682329499136L); + logger.info("SUCCESS 1: {}", result.toString()); + List users = (List) result.get(Constants.DATA_LIST); + Assert.assertTrue(CollectionUtils.isNotEmpty(users)); + + loginUser.setId(1); + loginUser.setUserType(UserType.GENERAL_USER); + result = this.projectService.queryAuthorizedUser(loginUser, 3682329499136L); + logger.info("SUCCESS 2: {}", result.toString()); + users = (List) result.get(Constants.DATA_LIST); + Assert.assertTrue(CollectionUtils.isNotEmpty(users)); + } + @Test public void testQueryCreatedProject() { @@ -365,6 +397,28 @@ public class ProjectServiceTest { return loginUser; } + /** + * Get general user + * @return + */ + private User getGeneralUser() { + User user = new User(); + user.setUserType(UserType.GENERAL_USER); + user.setUserName("userTest0001"); + user.setUserPassword("userTest0001"); + return user; + } + + /** + * Get user list + * @return + */ + private List getUserList() { + List userList = new ArrayList<>(); + userList.add(this.getGeneralUser()); + return userList; + } + /** * get project user */ 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 e586db8cbf..85daa7eae8 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 @@ -338,6 +338,74 @@ public class UsersServiceTest { Assert.assertEquals(Status.SUCCESS, result.get(Constants.STATUS)); } + @Test + public void testGrantProjectByCode() { + // Mock Project, User + final long projectCode = 1L; + final int projectCreator = 1; + final int authorizer = 100; + Mockito.when(this.userMapper.selectById(authorizer)).thenReturn(this.getUser()); + Mockito.when(this.userMapper.selectById(projectCreator)).thenReturn(this.getUser()); + Mockito.when(this.projectMapper.queryByCode(projectCode)).thenReturn(this.getProject()); + + // ERROR: USER_NOT_EXIST + User loginUser = new User(); + Map result = this.usersService.grantProjectByCode(loginUser, 999, projectCode); + logger.info(result.toString()); + Assert.assertEquals(Status.USER_NOT_EXIST, result.get(Constants.STATUS)); + + // ERROR: PROJECT_NOT_FOUNT + result = this.usersService.grantProjectByCode(loginUser, authorizer, 999); + logger.info(result.toString()); + Assert.assertEquals(Status.PROJECT_NOT_FOUNT, result.get(Constants.STATUS)); + + // ERROR: USER_NO_OPERATION_PERM + loginUser.setId(999); + loginUser.setUserType(UserType.GENERAL_USER); + result = this.usersService.grantProjectByCode(loginUser, authorizer, projectCode); + logger.info(result.toString()); + Assert.assertEquals(Status.USER_NO_OPERATION_PERM, result.get(Constants.STATUS)); + + // SUCCESS: USER IS PROJECT OWNER + loginUser.setId(projectCreator); + loginUser.setUserType(UserType.GENERAL_USER); + result = this.usersService.grantProjectByCode(loginUser, authorizer, projectCode); + logger.info(result.toString()); + Assert.assertEquals(Status.SUCCESS, result.get(Constants.STATUS)); + + // SUCCESS: USER IS ADMINISTRATOR + loginUser.setId(999); + loginUser.setUserType(UserType.ADMIN_USER); + result = this.usersService.grantProjectByCode(loginUser, authorizer, projectCode); + logger.info(result.toString()); + Assert.assertEquals(Status.SUCCESS, result.get(Constants.STATUS)); + } + + @Test + public void testRevokeProject() { + Mockito.when(this.userMapper.selectById(1)).thenReturn(this.getUser()); + + final long projectCode = 3682329499136L; + + // user no permission + User loginUser = new User(); + Map result = this.usersService.revokeProject(loginUser, 1, projectCode); + logger.info(result.toString()); + Assert.assertEquals(Status.USER_NO_OPERATION_PERM, result.get(Constants.STATUS)); + + // user not exist + loginUser.setUserType(UserType.ADMIN_USER); + result = this.usersService.revokeProject(loginUser, 2, projectCode); + logger.info(result.toString()); + Assert.assertEquals(Status.USER_NOT_EXIST, result.get(Constants.STATUS)); + + // success + Mockito.when(this.projectMapper.queryByCode(Mockito.anyLong())).thenReturn(new Project()); + result = this.usersService.revokeProject(loginUser, 1, projectCode); + logger.info(result.toString()); + Assert.assertEquals(Status.SUCCESS, result.get(Constants.STATUS)); + } + @Test public void testGrantResources() { String resourceIds = "100000,120000"; @@ -618,6 +686,22 @@ public class UsersServiceTest { return user; } + /** + * Get project + * @return + */ + private Project getProject() { + Project project = new Project(); + project.setId(1); + project.setCode(1L); + project.setUserId(1); + project.setName("PJ-001"); + project.setPerm(7); + project.setDefCount(0); + project.setInstRunningCount(0); + return project; + } + /** * get user */ diff --git a/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/mapper/AccessTokenMapper.java b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/mapper/AccessTokenMapper.java index 472ba35e3b..3c73a56bbf 100644 --- a/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/mapper/AccessTokenMapper.java +++ b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/mapper/AccessTokenMapper.java @@ -25,6 +25,8 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import java.util.List; + /** * accesstoken mapper interface */ @@ -44,6 +46,14 @@ public interface AccessTokenMapper extends BaseMapper { @Param("userId") int userId ); + /** + * Query access token for specified user + * + * @param userId userId + * @return access token for specified user + */ + List queryAccessTokenByUser(@Param("userId") int userId); + /** * delete by userId * diff --git a/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/mapper/UserMapper.java b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/mapper/UserMapper.java index 4418363dc2..9fcb488395 100644 --- a/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/mapper/UserMapper.java +++ b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/mapper/UserMapper.java @@ -124,4 +124,11 @@ public interface UserMapper extends BaseMapper { * @return user list */ List selectByIds(@Param("ids") List ids); + + /** + * query authed user list by projectId + * @param projectId projectId + * @return user list + */ + List queryAuthedUserListByProjectId(@Param("projectId") int projectId); } diff --git a/dolphinscheduler-dao/src/main/resources/org/apache/dolphinscheduler/dao/mapper/AccessTokenMapper.xml b/dolphinscheduler-dao/src/main/resources/org/apache/dolphinscheduler/dao/mapper/AccessTokenMapper.xml index 35312fb88a..f8c8ad4ba2 100644 --- a/dolphinscheduler-dao/src/main/resources/org/apache/dolphinscheduler/dao/mapper/AccessTokenMapper.xml +++ b/dolphinscheduler-dao/src/main/resources/org/apache/dolphinscheduler/dao/mapper/AccessTokenMapper.xml @@ -31,6 +31,13 @@ order by t.update_time desc + + + delete from t_ds_access_token where user_id = #{userId} diff --git a/dolphinscheduler-dao/src/main/resources/org/apache/dolphinscheduler/dao/mapper/UserMapper.xml b/dolphinscheduler-dao/src/main/resources/org/apache/dolphinscheduler/dao/mapper/UserMapper.xml index dec6a51937..570e395ffb 100644 --- a/dolphinscheduler-dao/src/main/resources/org/apache/dolphinscheduler/dao/mapper/UserMapper.xml +++ b/dolphinscheduler-dao/src/main/resources/org/apache/dolphinscheduler/dao/mapper/UserMapper.xml @@ -123,4 +123,12 @@ #{id} +