You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dolphinscheduler.apache.org by le...@apache.org on 2022/05/29 08:14:22 UTC
[dolphinscheduler] branch dev updated: [Feature][Permission] Project management module authority control refactoring, authority abstract interface setting. (#10261)
This is an automated email from the ASF dual-hosted git repository.
leonbao pushed a commit to branch dev
in repository https://gitbox.apache.org/repos/asf/dolphinscheduler.git
The following commit(s) were added to refs/heads/dev by this push:
new 7ac8ea493c [Feature][Permission] Project management module authority control refactoring, authority abstract interface setting. (#10261)
7ac8ea493c is described below
commit 7ac8ea493cf6f458097c695baa500dd0c22b3bb8
Author: WangJPLeo <10...@users.noreply.github.com>
AuthorDate: Sun May 29 16:14:16 2022 +0800
[Feature][Permission] Project management module authority control refactoring, authority abstract interface setting. (#10261)
* Create process definition with task group and task group priority cannot be save into db
* [Feature][API] Permission control of project
* [Feature][API] Permission control of project
* [Feature][API] Permission control of project
* [Feature][API] Permission control of project
* [Feature][API] Permission control of project
* [Feature][API] Permission control of project
* [Feature][API] Permission control of project
* [Feature][API] Permission control of project
* [Feature][API] Permission control of project
* [Feature][API] Permission control of project
* [Feature][API] Permission control of project
* [Feature][API] Permission control of project
* [Feature][API] Permission control of project
* [Feature][API] Permission control of project
* [Feature][API] Permission control of project
* [Feature][API] Permission control of project
* The result of the assertion cannot be changed. The only difference is the judgment condition.
* test recovery.
* controller test fix.
* ProjectE2ETest fix.
* WebElement import.
* Prioritize problem solving.
* Judging the length of the set fix
Co-authored-by: houshitao <sh...@163.com>
Co-authored-by: hstdream <33...@users.noreply.github.com>
---
.../dolphinscheduler/api/service/BaseService.java | 11 ++
.../api/service/impl/BaseServiceImpl.java | 24 ++++
.../api/service/impl/ProjectServiceImpl.java | 54 +++++---
.../api/controller/DataAnalysisControllerTest.java | 26 +++-
.../api/service/ProjectServiceTest.java | 104 ++++++++------
.../common/enums/AuthorizationType.java | 29 +++-
.../dolphinscheduler/dao/mapper/ProjectMapper.java | 14 +-
.../dolphinscheduler/dao/mapper/ProjectMapper.xml | 21 ++-
.../dao/mapper/ProjectMapperTest.java | 17 ++-
.../dolphinscheduler/e2e/cases/ProjectE2ETest.java | 9 +-
.../permission/ResourcePermissionCheckService.java | 54 ++++++++
.../ResourcePermissionCheckServiceImpl.java | 149 +++++++++++++++++++++
.../ResourcePermissionCheckServiceTest.java | 125 +++++++++++++++++
13 files changed, 548 insertions(+), 89 deletions(-)
diff --git a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/BaseService.java b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/BaseService.java
index de35cd8ce6..fd3ae0c8bc 100644
--- a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/BaseService.java
+++ b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/BaseService.java
@@ -19,6 +19,8 @@ package org.apache.dolphinscheduler.api.service;
import org.apache.dolphinscheduler.api.enums.Status;
import org.apache.dolphinscheduler.api.utils.Result;
+import org.apache.dolphinscheduler.common.enums.AuthorizationType;
+import org.apache.dolphinscheduler.dao.entity.Project;
import org.apache.dolphinscheduler.dao.entity.User;
import java.util.Map;
@@ -83,6 +85,15 @@ public interface BaseService {
*/
boolean canOperator(User operateUser, int createUserId);
+ /**
+ * Verify that the operator has permissions
+ * @param user operate user
+ * @param ids Object[]
+ * @Param type authorizationType
+ * @return check result
+ */
+ boolean canOperatorPermissions(User user, Object[] ids, AuthorizationType type);
+
/**
* check and parse date parameters
*
diff --git a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/BaseServiceImpl.java b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/BaseServiceImpl.java
index b09c57554b..e45d51eb79 100644
--- a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/BaseServiceImpl.java
+++ b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/BaseServiceImpl.java
@@ -22,9 +22,15 @@ import org.apache.dolphinscheduler.api.enums.Status;
import org.apache.dolphinscheduler.api.service.BaseService;
import org.apache.dolphinscheduler.api.utils.Result;
import org.apache.dolphinscheduler.common.Constants;
+import org.apache.dolphinscheduler.common.enums.AuthorizationType;
import org.apache.dolphinscheduler.common.enums.UserType;
import org.apache.dolphinscheduler.common.utils.DateUtils;
+import org.apache.dolphinscheduler.dao.entity.Project;
import org.apache.dolphinscheduler.dao.entity.User;
+import org.apache.dolphinscheduler.service.permission.ResourcePermissionCheckService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
import java.io.IOException;
import java.text.MessageFormat;
@@ -37,6 +43,10 @@ import java.util.Objects;
* base service impl
*/
public class BaseServiceImpl implements BaseService {
+ private static final Logger logger = LoggerFactory.getLogger(ProjectServiceImpl.class);
+
+ @Autowired
+ private ResourcePermissionCheckService resourcePermissionCheckService;
/**
* check admin
@@ -145,6 +155,20 @@ public class BaseServiceImpl implements BaseService {
return operateUser.getId() == createUserId || isAdmin(operateUser);
}
+ /**
+ * Verify that the operator has permissions
+ * @param user operate user
+ * @param ids Object[]
+ * @param type AuthorizationType
+ * @return boolean
+ */
+ @Override
+ public boolean canOperatorPermissions(User user, Object[] ids,AuthorizationType type) {
+ boolean operationPermissionCheck = resourcePermissionCheckService.operationPermissionCheck(type, user.getId(), null, logger);
+ boolean resourcePermissionCheck = resourcePermissionCheckService.resourcePermissionCheck(type, ids, user.getUserType().equals(UserType.ADMIN_USER) ? 0 : user.getId(), logger);
+ return operationPermissionCheck || resourcePermissionCheck;
+ }
+
/**
* check and parse date parameters
*
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 e10a83f8e1..d24637134f 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
@@ -24,6 +24,7 @@ import org.apache.dolphinscheduler.api.service.ProjectService;
import org.apache.dolphinscheduler.api.utils.PageInfo;
import org.apache.dolphinscheduler.api.utils.Result;
import org.apache.dolphinscheduler.common.Constants;
+import org.apache.dolphinscheduler.common.enums.AuthorizationType;
import org.apache.dolphinscheduler.common.enums.UserType;
import org.apache.dolphinscheduler.common.utils.CodeGenerateUtils;
import org.apache.dolphinscheduler.common.utils.CodeGenerateUtils.CodeGenerateException;
@@ -35,10 +36,14 @@ 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 org.apache.dolphinscheduler.service.permission.ResourcePermissionCheckService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
@@ -54,6 +59,8 @@ import static org.apache.dolphinscheduler.api.utils.CheckUtils.checkDesc;
@Service
public class ProjectServiceImpl extends BaseServiceImpl implements ProjectService {
+ private static final Logger logger = LoggerFactory.getLogger(ProjectServiceImpl.class);
+
@Autowired
private ProjectMapper projectMapper;
@@ -66,6 +73,9 @@ public class ProjectServiceImpl extends BaseServiceImpl implements ProjectServic
@Autowired
private UserMapper userMapper;
+ @Autowired
+ private ResourcePermissionCheckService resourcePermissionCheckService;
+
/**
* create project
*
@@ -165,7 +175,7 @@ public class ProjectServiceImpl extends BaseServiceImpl implements ProjectServic
Map<String, Object> result = new HashMap<>();
if (project == null) {
putMsg(result, Status.PROJECT_NOT_EXIST);
- } else if (!checkReadPermission(loginUser, project)) {
+ } else if (!checkReadPermissions(loginUser, project.getId())) {
// check read permission
putMsg(result, Status.USER_NO_OPERATION_PROJECT_PERM, loginUser.getUserName(), projectCode);
} else {
@@ -179,7 +189,7 @@ public class ProjectServiceImpl extends BaseServiceImpl implements ProjectServic
boolean checkResult = false;
if (project == null) {
putMsg(result, Status.PROJECT_NOT_FOUND, "");
- } else if (!checkReadPermission(loginUser, project)) {
+ } else if (!checkReadPermissions(loginUser, project.getId())) {
putMsg(result, Status.USER_NO_OPERATION_PROJECT_PERM, loginUser.getUserName(), project.getCode());
} else {
checkResult = true;
@@ -192,7 +202,7 @@ public class ProjectServiceImpl extends BaseServiceImpl implements ProjectServic
boolean checkResult = false;
if (project == null) {
putMsg(result, Status.PROJECT_NOT_FOUND, "");
- } else if (!checkReadPermission(loginUser, project)) {
+ } else if (!checkReadPermissions(loginUser, project.getId())) {
putMsg(result, Status.USER_NO_OPERATION_PROJECT_PERM, loginUser.getUserName(), project.getName());
} else {
checkResult = true;
@@ -216,11 +226,11 @@ public class ProjectServiceImpl extends BaseServiceImpl implements ProjectServic
Page<Project> page = new Page<>(pageNo, pageSize);
- int userId = loginUser.getUserType() == UserType.ADMIN_USER ? 0 : loginUser.getId();
- IPage<Project> projectIPage = projectMapper.queryProjectListPaging(page, userId, searchVal);
+ Set<Integer> projectIds = resourcePermissionCheckService.userOwnedResourceIdsAcquisition(AuthorizationType.PROJECTS, loginUser.getId(), logger);
+ IPage<Project> projectIPage = projectMapper.queryProjectListPaging(page, new ArrayList<>(projectIds), searchVal);
List<Project> projectList = projectIPage.getRecords();
- if (userId != 0) {
+ if (loginUser.getUserType() != UserType.ADMIN_USER) {
for (Project project : projectList) {
project.setPerm(Constants.DEFAULT_ADMIN_PERMISSION);
}
@@ -248,7 +258,7 @@ public class ProjectServiceImpl extends BaseServiceImpl implements ProjectServic
return checkResult;
}
- if (!canOperator(loginUser, project.getUserId())) {
+ if (!canOperatorPermissions(loginUser, new Object[]{project.getId()}, AuthorizationType.PROJECTS)) {
putMsg(result, Status.USER_NO_OPERATION_PERM);
return result;
}
@@ -343,13 +353,9 @@ public class ProjectServiceImpl extends BaseServiceImpl implements ProjectServic
public Map<String, Object> queryUnauthorizedProject(User loginUser, Integer userId) {
Map<String, Object> result = new HashMap<>();
- List<Project> projectList;
- if (isAdmin(loginUser)) {
- // admin gets all projects except userId
- projectList = projectMapper.queryProjectExceptUserId(userId);
- } else {
- projectList = projectMapper.queryProjectCreatedByUser(loginUser.getId());
- }
+ Set<Integer> projectIds = resourcePermissionCheckService.userOwnedResourceIdsAcquisition(AuthorizationType.PROJECTS, loginUser.getId(), logger);
+ List<Project> projectList = projectMapper.listAuthorizedProjects(loginUser.getUserType().equals(UserType.ADMIN_USER) ? 0 : loginUser.getId(), new ArrayList<>(projectIds));
+
List<Project> resultList = new ArrayList<>();
Set<Project> projectSet;
if (projectList != null && !projectList.isEmpty()) {
@@ -453,12 +459,8 @@ public class ProjectServiceImpl extends BaseServiceImpl implements ProjectServic
public Map<String, Object> queryProjectCreatedAndAuthorizedByUser(User loginUser) {
Map<String, Object> result = new HashMap<>();
- List<Project> projects = null;
- if (loginUser.getUserType() == UserType.ADMIN_USER) {
- projects = projectMapper.selectList(null);
- } else {
- projects = projectMapper.queryProjectCreatedAndAuthorizedByUserId(loginUser.getId());
- }
+ Set<Integer> projectIds = resourcePermissionCheckService.userOwnedResourceIdsAcquisition(AuthorizationType.PROJECTS, loginUser.getId(), logger);
+ List<Project> projects = projectMapper.listAuthorizedProjects(loginUser.getUserType().equals(UserType.ADMIN_USER) ? 0 : loginUser.getId(), new ArrayList<>(projectIds));
result.put(Constants.DATA_LIST, projects);
putMsg(result, Status.SUCCESS);
@@ -478,6 +480,18 @@ public class ProjectServiceImpl extends BaseServiceImpl implements ProjectServic
return (permissionId & Constants.READ_PERMISSION) != 0;
}
+ /**
+ * check whether have read permission new
+ * @param user
+ * @param id
+ * @return true if the user have permission to see the project, otherwise return false
+ */
+ private boolean checkReadPermissions(User user, Integer id){
+ boolean operationPermissionCheck = resourcePermissionCheckService.operationPermissionCheck(AuthorizationType.PROJECTS, user.getId(), null, logger);
+ boolean resourcePermissionCheck = resourcePermissionCheckService.resourcePermissionCheck(AuthorizationType.PROJECTS, new Object[]{id}, user.getUserType().equals(UserType.ADMIN_USER) ? 0 : user.getId(), logger);
+ return operationPermissionCheck && resourcePermissionCheck;
+ }
+
/**
* query permission id
*
diff --git a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/controller/DataAnalysisControllerTest.java b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/controller/DataAnalysisControllerTest.java
index c806100ee4..636a1ec0a4 100644
--- a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/controller/DataAnalysisControllerTest.java
+++ b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/controller/DataAnalysisControllerTest.java
@@ -33,30 +33,41 @@ import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
+import java.util.Date;
+
/**
* data analysis controller test
*/
public class DataAnalysisControllerTest extends AbstractControllerTest {
private static final Logger logger = LoggerFactory.getLogger(DataAnalysisControllerTest.class);
- @MockBean(name = "projectMapper")
+ @Autowired
private ProjectMapper projectMapper;
+ private int createProject() {
+ Project project = new Project();
+ project.setCode(16L);
+ project.setName("ut project");
+ project.setUserId(1);
+ project.setCreateTime(new Date());
+ projectMapper.insert(project);
+ return project.getId();
+ }
+
@Test
public void testCountTaskState() throws Exception {
- PowerMockito.when(projectMapper.queryByCode(Mockito.anyLong())).thenReturn(getProject("test"));
+ int projectId = createProject();
MultiValueMap<String, String> paramsMap = new LinkedMultiValueMap<>();
paramsMap.add("startDate","2019-12-01 00:00:00");
paramsMap.add("endDate","2019-12-28 00:00:00");
paramsMap.add("projectCode","16");
-
MvcResult mvcResult = mockMvc.perform(get("/projects/analysis/task-state-count")
.header("sessionId", sessionId)
.params(paramsMap))
@@ -66,11 +77,13 @@ public class DataAnalysisControllerTest extends AbstractControllerTest {
Result result = JSONUtils.parseObject(mvcResult.getResponse().getContentAsString(), Result.class);
assertThat(result.getCode().intValue()).isEqualTo(Status.SUCCESS.getCode());
logger.info(mvcResult.getResponse().getContentAsString());
+
+ projectMapper.deleteById(projectId);
}
@Test
public void testCountProcessInstanceState() throws Exception {
- PowerMockito.when(projectMapper.queryByCode(Mockito.anyLong())).thenReturn(getProject("test"));
+ int projectId = createProject();
MultiValueMap<String, String> paramsMap = new LinkedMultiValueMap<>();
paramsMap.add("startDate","2019-12-01 00:00:00");
@@ -86,11 +99,12 @@ public class DataAnalysisControllerTest extends AbstractControllerTest {
Result result = JSONUtils.parseObject(mvcResult.getResponse().getContentAsString(), Result.class);
assertThat(result.getCode().intValue()).isEqualTo(Status.SUCCESS.getCode());
logger.info(mvcResult.getResponse().getContentAsString());
+
+ projectMapper.deleteById(projectId);
}
@Test
public void testCountDefinitionByUser() throws Exception {
- PowerMockito.when(projectMapper.queryByCode(Mockito.anyLong())).thenReturn(getProject("test"));
MultiValueMap<String, String> paramsMap = new LinkedMultiValueMap<>();
paramsMap.add("projectId","16");
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 2f83fcc78e..065b2c273b 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
@@ -19,9 +19,8 @@ package org.apache.dolphinscheduler.api.service;
import org.apache.dolphinscheduler.api.enums.Status;
import org.apache.dolphinscheduler.api.service.impl.ProjectServiceImpl;
-import org.apache.dolphinscheduler.api.utils.PageInfo;
-import org.apache.dolphinscheduler.api.utils.Result;
import org.apache.dolphinscheduler.common.Constants;
+import org.apache.dolphinscheduler.common.enums.AuthorizationType;
import org.apache.dolphinscheduler.common.enums.UserType;
import org.apache.dolphinscheduler.dao.entity.ProcessDefinition;
import org.apache.dolphinscheduler.dao.entity.Project;
@@ -34,12 +33,9 @@ import org.apache.dolphinscheduler.dao.mapper.UserMapper;
import org.apache.commons.collections.CollectionUtils;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
+import org.apache.dolphinscheduler.service.permission.ResourcePermissionCheckService;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -50,9 +46,6 @@ import org.mockito.junit.MockitoJUnitRunner;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-
/**
* project service test
**/
@@ -68,10 +61,11 @@ public class ProjectServiceTest {
private ProjectMapper projectMapper;
@Mock
- private ProjectUserMapper projectUserMapper;
+ private ProcessDefinitionMapper processDefinitionMapper;
@Mock
- private ProcessDefinitionMapper processDefinitionMapper;
+ private ResourcePermissionCheckService resourcePermissionCheckService;
+
@Mock
private UserMapper userMapper;
@@ -80,6 +74,8 @@ public class ProjectServiceTest {
private String userName = "ProjectServiceTest";
+ private static final Logger projectServiceLogger = LoggerFactory.getLogger(ProjectServiceImpl.class);
+
@Test
public void testCreateProject() {
@@ -106,8 +102,8 @@ public class ProjectServiceTest {
@Test
public void testCheckProjectAndAuth() {
+ // no admin user
long projectCode = 1L;
- Mockito.when(projectUserMapper.queryProjectRelation(1, 1)).thenReturn(getProjectUser());
User loginUser = getLoginUser();
Map<String, Object> result = projectService.checkProjectAndAuth(loginUser, null, projectCode);
@@ -118,17 +114,23 @@ public class ProjectServiceTest {
Project project = getProject();
//USER_NO_OPERATION_PROJECT_PERM
project.setUserId(2);
+ Mockito.when(resourcePermissionCheckService.operationPermissionCheck(AuthorizationType.PROJECTS, 1, null, projectServiceLogger)).thenReturn(true);
+ Mockito.when(resourcePermissionCheckService.resourcePermissionCheck(AuthorizationType.PROJECTS, new Object[]{1}, 1, projectServiceLogger)).thenReturn(false);
result = projectService.checkProjectAndAuth(loginUser, project, projectCode);
logger.info(result.toString());
Assert.assertEquals(Status.USER_NO_OPERATION_PROJECT_PERM, result.get(Constants.STATUS));
//success
project.setUserId(1);
+ Mockito.when(resourcePermissionCheckService.operationPermissionCheck(AuthorizationType.PROJECTS, 1, null, projectServiceLogger)).thenReturn(true);
+ Mockito.when(resourcePermissionCheckService.resourcePermissionCheck(AuthorizationType.PROJECTS, new Object[]{1}, 1, projectServiceLogger)).thenReturn(true);
result = projectService.checkProjectAndAuth(loginUser, project, projectCode);
logger.info(result.toString());
Assert.assertEquals(Status.SUCCESS, result.get(Constants.STATUS));
+ // admin user
Map<String, Object> result2 = new HashMap<>();
+ loginUser = geAdminUser();
result2 = projectService.checkProjectAndAuth(loginUser, null, projectCode);
Assert.assertEquals(Status.PROJECT_NOT_EXIST, result2.get(Constants.STATUS));
@@ -136,12 +138,18 @@ public class ProjectServiceTest {
Project project1 = getProject();
// USER_NO_OPERATION_PROJECT_PERM
project1.setUserId(2);
+ Mockito.when(resourcePermissionCheckService.operationPermissionCheck(AuthorizationType.PROJECTS, 11, null, projectServiceLogger)).thenReturn(true);
+ Mockito.when(resourcePermissionCheckService.resourcePermissionCheck(AuthorizationType.PROJECTS, new Object[]{1}, 0, projectServiceLogger)).thenReturn(true);
result2 = projectService.checkProjectAndAuth(loginUser, project1, projectCode);
- Assert.assertEquals(Status.USER_NO_OPERATION_PROJECT_PERM, result2.get(Constants.STATUS));
+ Assert.assertEquals(Status.SUCCESS, result2.get(Constants.STATUS));
//success
project1.setUserId(1);
- projectService.checkProjectAndAuth(loginUser, project1, projectCode);
+ Mockito.when(resourcePermissionCheckService.operationPermissionCheck(AuthorizationType.PROJECTS, 11, null, projectServiceLogger)).thenReturn(true);
+ Mockito.when(resourcePermissionCheckService.resourcePermissionCheck(AuthorizationType.PROJECTS, new Object[]{1}, 0, projectServiceLogger)).thenReturn(true);
+ result2 = projectService.checkProjectAndAuth(loginUser, project1, projectCode);
+ Assert.assertEquals(Status.SUCCESS, result2.get(Constants.STATUS));
+
}
@@ -155,6 +163,7 @@ public class ProjectServiceTest {
// not exist user
User tempUser = new User();
tempUser.setId(Integer.MAX_VALUE);
+ tempUser.setUserType(UserType.GENERAL_USER);
boolean checkResult = projectService.hasProjectAndPerm(tempUser, project, result);
logger.info(result.toString());
Assert.assertFalse(checkResult);
@@ -162,35 +171,13 @@ public class ProjectServiceTest {
//success
result = new HashMap<>();
project.setUserId(1);
+ Mockito.when(resourcePermissionCheckService.operationPermissionCheck(AuthorizationType.PROJECTS, 1, null, projectServiceLogger)).thenReturn(true);
+ Mockito.when(resourcePermissionCheckService.resourcePermissionCheck(AuthorizationType.PROJECTS, new Object[]{1}, 1, projectServiceLogger)).thenReturn(true);
checkResult = projectService.hasProjectAndPerm(loginUser, project, result);
logger.info(result.toString());
Assert.assertTrue(checkResult);
}
- @Test
- public void testQueryProjectListPaging() {
-
- IPage<Project> page = new Page<>(1, 10);
- page.setRecords(getList());
- page.setTotal(1L);
- Mockito.when(projectMapper.queryProjectListPaging(Mockito.any(Page.class), Mockito.eq(1), Mockito.eq(projectName))).thenReturn(page);
- User loginUser = getLoginUser();
-
- // project owner
- Result result = projectService.queryProjectListPaging(loginUser, 10, 1, projectName);
- logger.info(result.toString());
- PageInfo<Project> pageInfo = (PageInfo<Project>) result.getData();
- Assert.assertTrue(CollectionUtils.isNotEmpty(pageInfo.getTotalList()));
-
- //admin
- Mockito.when(projectMapper.queryProjectListPaging(Mockito.any(Page.class), Mockito.eq(0), Mockito.eq(projectName))).thenReturn(page);
- loginUser.setUserType(UserType.ADMIN_USER);
- result = projectService.queryProjectListPaging(loginUser, 10, 1, projectName);
- logger.info(result.toString());
- pageInfo = (PageInfo<Project>) result.getData();
- Assert.assertTrue(CollectionUtils.isNotEmpty(pageInfo.getTotalList()));
- }
-
@Test
public void testDeleteProject() {
User loginUser = getLoginUser();
@@ -199,12 +186,17 @@ public class ProjectServiceTest {
Map<String, Object> result = projectService.deleteProject(loginUser, 11L);
logger.info(result.toString());
Assert.assertEquals(Status.PROJECT_NOT_EXIST, result.get(Constants.STATUS));
+
loginUser.setId(2);
+ Mockito.when(resourcePermissionCheckService.operationPermissionCheck(AuthorizationType.PROJECTS, 2, null, projectServiceLogger)).thenReturn(true);
+ Mockito.when(resourcePermissionCheckService.resourcePermissionCheck(AuthorizationType.PROJECTS, new Object[]{1}, 2, projectServiceLogger)).thenReturn(false);
//USER_NO_OPERATION_PROJECT_PERM
result = projectService.deleteProject(loginUser, 1L);
logger.info(result.toString());
Assert.assertEquals(Status.USER_NO_OPERATION_PROJECT_PERM, result.get(Constants.STATUS));
+ Mockito.when(resourcePermissionCheckService.operationPermissionCheck(AuthorizationType.PROJECTS, 2, null, projectServiceLogger)).thenReturn(true);
+ Mockito.when(resourcePermissionCheckService.resourcePermissionCheck(AuthorizationType.PROJECTS, new Object[]{1}, 0, projectServiceLogger)).thenReturn(true);
//DELETE_PROJECT_ERROR_DEFINES_NOT_NULL
Mockito.when(processDefinitionMapper.queryAllDefinitionList(1L)).thenReturn(getProcessDefinitions());
loginUser.setUserType(UserType.ADMIN_USER);
@@ -213,6 +205,8 @@ public class ProjectServiceTest {
Assert.assertEquals(Status.DELETE_PROJECT_ERROR_DEFINES_NOT_NULL, result.get(Constants.STATUS));
//success
+ Mockito.when(resourcePermissionCheckService.operationPermissionCheck(AuthorizationType.PROJECTS, 2, null, projectServiceLogger)).thenReturn(true);
+ Mockito.when(resourcePermissionCheckService.resourcePermissionCheck(AuthorizationType.PROJECTS, new Object[]{1}, 0, projectServiceLogger)).thenReturn(true);
Mockito.when(projectMapper.deleteById(1)).thenReturn(1);
Mockito.when(processDefinitionMapper.queryAllDefinitionList(1L)).thenReturn(new ArrayList<>());
result = projectService.deleteProject(loginUser, 1L);
@@ -234,15 +228,21 @@ public class ProjectServiceTest {
Assert.assertEquals(Status.PROJECT_NOT_FOUND, result.get(Constants.STATUS));
//PROJECT_ALREADY_EXISTS
+ Mockito.when(resourcePermissionCheckService.operationPermissionCheck(AuthorizationType.PROJECTS, 1, null, projectServiceLogger)).thenReturn(true);
+ Mockito.when(resourcePermissionCheckService.resourcePermissionCheck(AuthorizationType.PROJECTS, new Object[]{1}, 1, projectServiceLogger)).thenReturn(true);
result = projectService.update(loginUser, 2L, projectName, "desc", userName);
logger.info(result.toString());
Assert.assertEquals(Status.PROJECT_ALREADY_EXISTS, result.get(Constants.STATUS));
+ Mockito.when(resourcePermissionCheckService.operationPermissionCheck(AuthorizationType.PROJECTS, 1, null, projectServiceLogger)).thenReturn(true);
+ Mockito.when(resourcePermissionCheckService.resourcePermissionCheck(AuthorizationType.PROJECTS, new Object[]{1}, 1, projectServiceLogger)).thenReturn(true);
Mockito.when(userMapper.queryByUserNameAccurately(Mockito.any())).thenReturn(null);
result = projectService.update(loginUser, 2L, "test", "desc", "testuser");
Assert.assertEquals(Status.USER_NOT_EXIST, result.get(Constants.STATUS));
//success
+ Mockito.when(resourcePermissionCheckService.operationPermissionCheck(AuthorizationType.PROJECTS, 1, null, projectServiceLogger)).thenReturn(true);
+ Mockito.when(resourcePermissionCheckService.resourcePermissionCheck(AuthorizationType.PROJECTS, new Object[]{1}, 1, projectServiceLogger)).thenReturn(true);
Mockito.when(userMapper.queryByUserNameAccurately(Mockito.any())).thenReturn(new User());
project.setUserId(1);
Mockito.when(projectMapper.updateById(Mockito.any(Project.class))).thenReturn(1);
@@ -284,6 +284,8 @@ public class ProjectServiceTest {
// Failure 2: USER_NO_OPERATION_PROJECT_PERM
loginUser.setId(100);
+ Mockito.when(resourcePermissionCheckService.operationPermissionCheck(AuthorizationType.PROJECTS, 100, null, projectServiceLogger)).thenReturn(true);
+ Mockito.when(resourcePermissionCheckService.resourcePermissionCheck(AuthorizationType.PROJECTS, new Object[]{1}, 100, projectServiceLogger)).thenReturn(false);
Mockito.when(this.projectMapper.queryByCode(Mockito.anyLong())).thenReturn(this.getProject());
result = this.projectService.queryAuthorizedUser(loginUser, 3682329499136L);
logger.info("FAILURE 2: {}", result.toString());
@@ -291,6 +293,8 @@ public class ProjectServiceTest {
// SUCCESS
loginUser.setUserType(UserType.ADMIN_USER);
+ Mockito.when(resourcePermissionCheckService.operationPermissionCheck(AuthorizationType.PROJECTS, 100, null, projectServiceLogger)).thenReturn(true);
+ Mockito.when(resourcePermissionCheckService.resourcePermissionCheck(AuthorizationType.PROJECTS, new Object[]{1}, 0, projectServiceLogger)).thenReturn(true);
Mockito.when(this.userMapper.queryAuthedUserListByProjectId(1)).thenReturn(this.getUserList());
result = this.projectService.queryAuthorizedUser(loginUser, 3682329499136L);
logger.info("SUCCESS 1: {}", result.toString());
@@ -299,6 +303,8 @@ public class ProjectServiceTest {
loginUser.setId(1);
loginUser.setUserType(UserType.GENERAL_USER);
+ Mockito.when(resourcePermissionCheckService.operationPermissionCheck(AuthorizationType.PROJECTS, 1, null, projectServiceLogger)).thenReturn(true);
+ Mockito.when(resourcePermissionCheckService.resourcePermissionCheck(AuthorizationType.PROJECTS, new Object[]{1}, 1, projectServiceLogger)).thenReturn(true);
result = this.projectService.queryAuthorizedUser(loginUser, 3682329499136L);
logger.info("SUCCESS 2: {}", result.toString());
users = (List<User>) result.get(Constants.DATA_LIST);
@@ -328,14 +334,15 @@ public class ProjectServiceTest {
User loginUser = getLoginUser();
// not admin user
- Mockito.when(projectMapper.queryProjectCreatedAndAuthorizedByUserId(1)).thenReturn(getList());
+ Set<Integer> projectIds = new HashSet<>();
+ Mockito.when(projectMapper.listAuthorizedProjects(1, new ArrayList<>(projectIds))).thenReturn(getList());
result = projectService.queryProjectCreatedAndAuthorizedByUser(loginUser);
List<Project> notAdminUserResult = (List<Project>) result.get(Constants.DATA_LIST);
Assert.assertTrue(CollectionUtils.isNotEmpty(notAdminUserResult));
//admin user
loginUser.setUserType(UserType.ADMIN_USER);
- Mockito.when(projectMapper.selectList(null)).thenReturn(getList());
+ Mockito.when(projectMapper.listAuthorizedProjects(0, new ArrayList<>(projectIds))).thenReturn(getList());
result = projectService.queryProjectCreatedAndAuthorizedByUser(loginUser);
List<Project> projects = (List<Project>) result.get(Constants.DATA_LIST);
@@ -358,11 +365,11 @@ public class ProjectServiceTest {
@Test
public void testQueryUnauthorizedProject() {
- Mockito.when(projectMapper.queryProjectExceptUserId(2)).thenReturn(getList());
- Mockito.when(projectMapper.queryProjectCreatedByUser(2)).thenReturn(getList());
- Mockito.when(projectMapper.queryAuthedProjectListByUserId(2)).thenReturn(getSingleList());
// test admin user
+ Set<Integer> projectIds = new HashSet<>();
+ Mockito.when(projectMapper.listAuthorizedProjects(0, new ArrayList<>(projectIds))).thenReturn(getList());
+
User loginUser = new User();
loginUser.setUserType(UserType.ADMIN_USER);
Map<String, Object> result = projectService.queryUnauthorizedProject(loginUser, 2);
@@ -371,6 +378,7 @@ public class ProjectServiceTest {
Assert.assertTrue(CollectionUtils.isNotEmpty(projects));
// test non-admin user
+ Mockito.when(projectMapper.listAuthorizedProjects(2, new ArrayList<>(projectIds))).thenReturn(getList());
loginUser.setId(2);
loginUser.setUserType(UserType.GENERAL_USER);
result = projectService.queryUnauthorizedProject(loginUser, 3);
@@ -420,6 +428,14 @@ public class ProjectServiceTest {
return loginUser;
}
+ private User geAdminUser() {
+ User loginUser = new User();
+ loginUser.setUserType(UserType.ADMIN_USER);
+ loginUser.setUserName(userName);
+ loginUser.setId(11);
+ return loginUser;
+ }
+
/**
* Get general user
* @return
diff --git a/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/enums/AuthorizationType.java b/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/enums/AuthorizationType.java
index 5d7934d069..6fa45ba724 100644
--- a/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/enums/AuthorizationType.java
+++ b/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/enums/AuthorizationType.java
@@ -25,17 +25,34 @@ import com.baomidou.mybatisplus.annotation.EnumValue;
public enum AuthorizationType {
/**
* 0 RESOURCE_FILE_ID;
- * 0 RESOURCE_FILE_NAME;
- * 1 UDF_FILE;
- * 1 DATASOURCE;
- * 2 UDF;
+ * 1 RESOURCE_FILE_NAME;
+ * 2 UDF_FILE;
+ * 3 DATASOURCE;
+ * 4 UDF;
+ * 5 PROJECTS;
+ * 6 WORKER_GROUP;
+ * 7 ALERT_GROUP;
+ * 8 ENVIRONMENT;
+ * 9 ACCESS_TOKEN;
+ * 10 QUEUE;
+ * 11 DATA_ANALYSIS;
+ * 12 K8S_NAMESPACE;
+ * 13 MONITOR;
*/
RESOURCE_FILE_ID(0, "resource file id"),
RESOURCE_FILE_NAME(1, "resource file name"),
UDF_FILE(2, "udf file"),
DATASOURCE(3, "data source"),
- UDF(4, "udf function");
-
+ UDF(4, "udf function"),
+ PROJECTS(5, "projects"),
+ WORKER_GROUP(6, "worker group"),
+ ALERT_GROUP(7, "alert group"),
+ ENVIRONMENT(8, "environment"),
+ ACCESS_TOKEN(9, "access token"),
+ QUEUE(10,"queue"),
+ DATA_ANALYSIS(11,"data analysis"),
+ K8S_NAMESPACE(12,"k8s namespace"),
+ MONITOR(13,"montitor");
AuthorizationType(int code, String descp) {
this.code = code;
this.descp = descp;
diff --git a/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/mapper/ProjectMapper.java b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/mapper/ProjectMapper.java
index f31fc11088..6bd4c4be5f 100644
--- a/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/mapper/ProjectMapper.java
+++ b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/mapper/ProjectMapper.java
@@ -71,12 +71,12 @@ public interface ProjectMapper extends BaseMapper<Project> {
/**
* project page
* @param page page
- * @param userId userId
+ * @param projectsIds projectsIds
* @param searchName searchName
* @return project Ipage
*/
IPage<Project> queryProjectListPaging(IPage<Project> page,
- @Param("userId") int userId,
+ @Param("projectsIds") List<Integer> projectsIds,
@Param("searchName") String searchName);
/**
@@ -127,4 +127,14 @@ public interface ProjectMapper extends BaseMapper<Project> {
* @return projectList
*/
List<Project> queryAllProject(@Param("userId") int userId);
+
+
+ /**
+ * list authorized Projects
+ * @param userId
+ * @param projectsIds
+ * @param <T>
+ * @return
+ */
+ List<Project> listAuthorizedProjects(@Param("userId") int userId, @Param("projectsIds")List<Integer> projectsIds);
}
diff --git a/dolphinscheduler-dao/src/main/resources/org/apache/dolphinscheduler/dao/mapper/ProjectMapper.xml b/dolphinscheduler-dao/src/main/resources/org/apache/dolphinscheduler/dao/mapper/ProjectMapper.xml
index 549afdfcb6..08282e3d0e 100644
--- a/dolphinscheduler-dao/src/main/resources/org/apache/dolphinscheduler/dao/mapper/ProjectMapper.xml
+++ b/dolphinscheduler-dao/src/main/resources/org/apache/dolphinscheduler/dao/mapper/ProjectMapper.xml
@@ -94,11 +94,11 @@
from t_ds_project p
left join t_ds_user u on u.id=p.user_id
where 1=1
- <if test="userId != 0">
- and p.id in
- (select project_id from t_ds_relation_project_user where user_id=#{userId}
- union select id as project_id from t_ds_project where user_id=#{userId}
- )
+ <if test="projectsIds != null and projectsIds.size() > 0">
+ and p.id in
+ <foreach item="id" index="index" collection="projectsIds" open="(" separator="," close=")">
+ #{id}
+ </foreach>
</if>
<if test="searchName!=null and searchName != ''">
AND (p.name LIKE concat('%', #{searchName}, '%')
@@ -169,4 +169,15 @@
and user_id = #{userId}
</if>
</select>
+
+ <select id="listAuthorizedProjects" resultType="org.apache.dolphinscheduler.dao.entity.Project">
+ select
+ <include refid="baseSql"/>
+ from t_ds_project dp
+ where 1=1
+ <if test="userId != 0">
+ and dp.id in (select project_id from t_ds_relation_project_user where user_id=#{userId}
+ union select id as project_id from t_ds_project where user_id=#{userId})
+ </if>
+ </select>
</mapper>
diff --git a/dolphinscheduler-dao/src/test/java/org/apache/dolphinscheduler/dao/mapper/ProjectMapperTest.java b/dolphinscheduler-dao/src/test/java/org/apache/dolphinscheduler/dao/mapper/ProjectMapperTest.java
index 7bf8ffb47d..93df32d048 100644
--- a/dolphinscheduler-dao/src/test/java/org/apache/dolphinscheduler/dao/mapper/ProjectMapperTest.java
+++ b/dolphinscheduler-dao/src/test/java/org/apache/dolphinscheduler/dao/mapper/ProjectMapperTest.java
@@ -21,6 +21,8 @@ import org.apache.dolphinscheduler.dao.BaseDaoTest;
import org.apache.dolphinscheduler.dao.entity.Project;
import org.apache.dolphinscheduler.dao.entity.User;
+import java.util.Arrays;
+import java.util.Collections;
import java.util.Date;
import java.util.List;
@@ -142,12 +144,12 @@ public class ProjectMapperTest extends BaseDaoTest {
Page<Project> page = new Page(1, 3);
IPage<Project> projectIPage = projectMapper.queryProjectListPaging(
page,
- project.getUserId(),
+ null,
null
);
IPage<Project> projectIPage1 = projectMapper.queryProjectListPaging(
page,
- project.getUserId(),
+ null,
project.getName()
);
Assert.assertEquals(projectIPage.getTotal(), 1);
@@ -192,4 +194,15 @@ public class ProjectMapperTest extends BaseDaoTest {
Assert.assertNotEquals(projects.size(), 0);
}
+
+ /**
+ * test query project permission
+ */
+ @Test
+ public void testListAuthorizedProjects(){
+ Project project = insertOne();
+ List<Project> projects = projectMapper.listAuthorizedProjects(1, Collections.singletonList(project.getId()));
+ Assert.assertEquals(projects.size(),0);
+ }
+
}
\ No newline at end of file
diff --git a/dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/java/org/apache/dolphinscheduler/e2e/cases/ProjectE2ETest.java b/dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/java/org/apache/dolphinscheduler/e2e/cases/ProjectE2ETest.java
index 85b5ba0cd9..2701ae3b64 100644
--- a/dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/java/org/apache/dolphinscheduler/e2e/cases/ProjectE2ETest.java
+++ b/dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/java/org/apache/dolphinscheduler/e2e/cases/ProjectE2ETest.java
@@ -29,6 +29,7 @@ import org.apache.dolphinscheduler.e2e.pages.project.ProjectPage;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
+import org.openqa.selenium.WebElement;
import org.openqa.selenium.remote.RemoteWebDriver;
@DolphinScheduler(composeFiles = "docker/basic/docker-compose.yaml")
@@ -40,8 +41,8 @@ class ProjectE2ETest {
@BeforeAll
public static void setup() {
new LoginPage(browser)
- .login("admin", "dolphinscheduler123")
- .goToNav(ProjectPage.class);
+ .login("admin", "dolphinscheduler123")
+ .goToNav(ProjectPage.class);
}
@Test
@@ -59,9 +60,9 @@ class ProjectE2ETest {
await().untilAsserted(() -> {
browser.navigate().refresh();
assertThat(
- page.projectList()
+ page.projectList()
).noneMatch(
- it -> it.getText().contains(project)
+ it -> it.getText().contains(project)
);
});
}
diff --git a/dolphinscheduler-service/src/main/java/org/apache/dolphinscheduler/service/permission/ResourcePermissionCheckService.java b/dolphinscheduler-service/src/main/java/org/apache/dolphinscheduler/service/permission/ResourcePermissionCheckService.java
new file mode 100644
index 0000000000..a1f9b10a90
--- /dev/null
+++ b/dolphinscheduler-service/src/main/java/org/apache/dolphinscheduler/service/permission/ResourcePermissionCheckService.java
@@ -0,0 +1,54 @@
+/*
+ * 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.dolphinscheduler.service.permission;
+
+import org.apache.dolphinscheduler.common.enums.AuthorizationType;
+import org.slf4j.Logger;
+
+import java.util.Set;
+
+public interface ResourcePermissionCheckService<T>{
+ /**
+ * resourcePermissionCheck
+ * @param authorizationType
+ * @param needChecks
+ * @param userId
+ * @param logger
+ * @return
+ */
+ boolean resourcePermissionCheck(AuthorizationType authorizationType, T[] needChecks, int userId, Logger logger);
+
+ /**
+ * userOwnedResourceIdsAcquisition
+ * @param authorizationType
+ * @param userId
+ * @param logger
+ * @param <T>
+ * @return
+ */
+ <T> Set<T> userOwnedResourceIdsAcquisition(AuthorizationType authorizationType, int userId, Logger logger);
+
+ /**
+ * operationpermissionCheck
+ * @param authorizationType
+ * @param userId
+ * @param sourceUrl
+ * @param logger
+ * @return
+ */
+ boolean operationPermissionCheck(AuthorizationType authorizationType, int userId, String sourceUrl, Logger logger);
+}
diff --git a/dolphinscheduler-service/src/main/java/org/apache/dolphinscheduler/service/permission/ResourcePermissionCheckServiceImpl.java b/dolphinscheduler-service/src/main/java/org/apache/dolphinscheduler/service/permission/ResourcePermissionCheckServiceImpl.java
new file mode 100644
index 0000000000..18ecd908b5
--- /dev/null
+++ b/dolphinscheduler-service/src/main/java/org/apache/dolphinscheduler/service/permission/ResourcePermissionCheckServiceImpl.java
@@ -0,0 +1,149 @@
+/*
+ * 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.
+ */
+/*
+ * 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.dolphinscheduler.service.permission;
+
+import org.apache.dolphinscheduler.common.enums.AuthorizationType;
+import org.apache.dolphinscheduler.common.enums.UserType;
+import org.apache.dolphinscheduler.dao.entity.*;
+import org.apache.dolphinscheduler.dao.mapper.*;
+import org.apache.dolphinscheduler.service.process.ProcessService;
+import org.slf4j.Logger;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.stereotype.Component;
+
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+
+import static java.util.stream.Collectors.toSet;
+
+@Component
+public class ResourcePermissionCheckServiceImpl implements ResourcePermissionCheckService<Object>, ApplicationContextAware {
+
+ @Autowired
+ private ProcessService processService;
+
+ public static final Map<AuthorizationType, ResourceAcquisitionAndPermissionCheck<?>> RESOURCE_LIST_MAP = new ConcurrentHashMap<>();
+
+ @Override
+ public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
+ for (ResourceAcquisitionAndPermissionCheck<?> authorizedResourceList : applicationContext.getBeansOfType(ResourceAcquisitionAndPermissionCheck.class).values()) {
+ List<AuthorizationType> authorizationTypes = authorizedResourceList.authorizationTypes();
+ authorizationTypes.forEach(auth -> RESOURCE_LIST_MAP.put(auth, authorizedResourceList));
+ }
+ }
+
+ @Override
+ public boolean resourcePermissionCheck(AuthorizationType authorizationType, Object[] needChecks, int userId, Logger logger) {
+ if (Objects.nonNull(needChecks) && needChecks.length > 0){
+ Set<Object> originResSet = new HashSet<>(Arrays.asList(needChecks));
+ Set<Object> ownResSets = RESOURCE_LIST_MAP.get(authorizationType).listAuthorizedResource(userId, logger);
+ originResSet.removeAll(ownResSets);
+ return originResSet.isEmpty();
+ }
+ return true;
+ }
+
+ @Override
+ public boolean operationPermissionCheck(AuthorizationType authorizationType, int userId, String sourceUrl, Logger logger) {
+ return RESOURCE_LIST_MAP.get(authorizationType).permissionCheck(userId, sourceUrl, logger);
+ }
+
+ @Override
+ public <T> Set<T> userOwnedResourceIdsAcquisition(AuthorizationType authorizationType, int userId, Logger logger) {
+ User user = processService.getUserById(userId);
+ if (user == null){
+ logger.error("user id {} doesn't exist", userId);
+ return Collections.emptySet();
+ }
+ return RESOURCE_LIST_MAP.get(authorizationType).listAuthorizedResource(user.getUserType().equals(UserType.ADMIN_USER) ? 0 : userId, logger);
+ }
+
+ @Component
+ public static class ProjectsResourceList implements ResourceAcquisitionAndPermissionCheck<Integer> {
+
+ private final ProjectMapper projectMapper;
+
+ @Autowired
+ private ProcessService processService;
+
+ public ProjectsResourceList(ProjectMapper projectMapper) {
+ this.projectMapper = projectMapper;
+ }
+
+ @Override
+ public List<AuthorizationType> authorizationTypes() {
+ return Collections.singletonList(AuthorizationType.PROJECTS);
+ }
+
+ @Override
+ public boolean permissionCheck(int userId, String url, Logger logger) {
+ // all users can create projects
+ return true;
+ }
+
+ @Override
+ public Set<Integer> listAuthorizedResource(int userId, Logger logger) {
+ return projectMapper.listAuthorizedProjects(userId, null).stream().map(Project::getId).collect(toSet());
+ }
+ }
+
+
+ interface ResourceAcquisitionAndPermissionCheck<T> {
+
+ /**
+ * authorization types
+ * @return
+ */
+ List<AuthorizationType> authorizationTypes();
+
+ /**
+ * get all resources under the user (no admin)
+ * @param userId
+ * @param <T>
+ * @return
+ */
+ <T> Set<T> listAuthorizedResource(int userId, Logger logger);
+
+ /**
+ * permission check
+ * @param userId
+ * @return
+ */
+ boolean permissionCheck(int userId, String url, Logger logger);
+
+ }
+}
diff --git a/dolphinscheduler-service/src/test/java/org/apache/dolphinscheduler/service/permission/ResourcePermissionCheckServiceTest.java b/dolphinscheduler-service/src/test/java/org/apache/dolphinscheduler/service/permission/ResourcePermissionCheckServiceTest.java
new file mode 100644
index 0000000000..93f5b63d83
--- /dev/null
+++ b/dolphinscheduler-service/src/test/java/org/apache/dolphinscheduler/service/permission/ResourcePermissionCheckServiceTest.java
@@ -0,0 +1,125 @@
+/*
+ * 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.dolphinscheduler.service.permission;
+
+
+import com.google.common.collect.Lists;
+import org.apache.dolphinscheduler.common.enums.AuthorizationType;
+import org.apache.dolphinscheduler.common.enums.UserType;
+import org.apache.dolphinscheduler.dao.entity.Project;
+import org.apache.dolphinscheduler.dao.entity.User;
+import org.apache.dolphinscheduler.dao.mapper.ProjectMapper;
+import org.apache.dolphinscheduler.service.process.ProcessService;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnitRunner;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.context.ApplicationContext;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * permission service test
+ */
+@RunWith(MockitoJUnitRunner.class)
+public class ResourcePermissionCheckServiceTest {
+
+ private static final Logger logger = LoggerFactory.getLogger(ResourcePermissionCheckServiceTest.class);
+
+ @Mock
+ private ProcessService processService;
+
+ @Mock
+ private ProjectMapper projectMapper;
+
+ @Mock
+ private ApplicationContext context;
+ @Mock
+ private ResourcePermissionCheckService<Object> resourcePermissionCheckService;
+
+ @InjectMocks
+ ResourcePermissionCheckServiceImpl resourcePermissionCheckServices;
+
+ protected static final Map<AuthorizationType, ResourcePermissionCheckServiceImpl.ResourceAcquisitionAndPermissionCheck<?>> RESOURCE_LIST_MAP = new ConcurrentHashMap<>();
+
+ @Test
+ public void testResourcePermissionCheck(){
+ User user = new User();
+ user.setId(1);
+ Object[] obj = new Object[]{1,2};
+ boolean result = this.resourcePermissionCheckService.resourcePermissionCheck(AuthorizationType.PROJECTS, obj, user.getId(), logger);
+ Assert.assertFalse(result);
+ }
+
+ @Test
+ public void testOperationPermissionCheck(){
+ User user = new User();
+ user.setId(1);
+ resourcePermissionCheckServices.setApplicationContext(context);
+ Assert.assertFalse(resourcePermissionCheckService.operationPermissionCheck(AuthorizationType.PROJECTS, user.getId(), null, logger));
+ String sourceUrl = "/tmp/";
+ Assert.assertFalse(resourcePermissionCheckService.operationPermissionCheck(AuthorizationType.PROJECTS, user.getId(), sourceUrl, logger));
+ }
+
+ @Test
+ public void testUserOwnedResourceIdsAcquisition(){
+ User user = new User();
+ user.setId(1);
+ //ADMIN
+ user.setUserType(UserType.ADMIN_USER);
+ Object[] obj = new Object[]{1,2};
+ List<Project> projectList = Lists.newArrayList(this.getEntity());
+ Set result = resourcePermissionCheckServices.userOwnedResourceIdsAcquisition(AuthorizationType.PROJECTS,
+ user.getId(),
+ logger);
+ Assert.assertNotNull(result);
+ }
+
+
+ @Test
+ public void testSetApplication(){
+ resourcePermissionCheckServices.setApplicationContext(context);
+ }
+ /**
+ * create entity
+ */
+ private Project getEntity() {
+ Project project = new Project();
+ project.setId(1);
+ project.setUserId(1);
+ project.setName("permissionsTest");
+ project.setUserName("permissionTest");
+ return project;
+ }
+
+ /**
+ * entity list
+ */
+ private List<Project> getList() {
+ List<Project> list = new ArrayList<>();
+ list.add(getEntity());
+ return list;
+ }
+}