You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@inlong.apache.org by he...@apache.org on 2022/04/20 11:06:49 UTC

[incubator-inlong] branch master updated: [INLONG-3673][Manager] Support permission access control according to user role (#3847)

This is an automated email from the ASF dual-hosted git repository.

healchow pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-inlong.git


The following commit(s) were added to refs/heads/master by this push:
     new e061dd3d0 [INLONG-3673][Manager] Support permission access control according to user role (#3847)
e061dd3d0 is described below

commit e061dd3d0777fa5064ca76dcd498d56edb241d9b
Author: wangheng <67...@qq.com>
AuthorDate: Wed Apr 20 19:06:45 2022 +0800

    [INLONG-3673][Manager] Support permission access control according to user role (#3847)
---
 .../inlong/manager/common/enums/UserTypeEnum.java  |  7 +++--
 .../common/pojo/group/InlongGroupPageRequest.java  |  3 ++
 .../user/UserRoleCode.java}                        | 32 +++------------------
 .../manager/service/core/impl/UserServiceImpl.java | 13 +++++----
 .../manager/web/auth/WebAuthorizingRealm.java      | 33 +++++++++++++++++-----
 .../web/config/ControllerExceptionHandler.java     | 22 +++++++++++----
 .../manager/web/controller/ClusterController.java  |  7 +++--
 .../web/controller/InlongGroupController.java      |  2 ++
 .../manager/web/controller/UserController.java     |  4 +++
 9 files changed, 71 insertions(+), 52 deletions(-)

diff --git a/inlong-manager/manager-common/src/main/java/org/apache/inlong/manager/common/enums/UserTypeEnum.java b/inlong-manager/manager-common/src/main/java/org/apache/inlong/manager/common/enums/UserTypeEnum.java
index a9d06dab0..25d2e2f6c 100644
--- a/inlong-manager/manager-common/src/main/java/org/apache/inlong/manager/common/enums/UserTypeEnum.java
+++ b/inlong-manager/manager-common/src/main/java/org/apache/inlong/manager/common/enums/UserTypeEnum.java
@@ -18,16 +18,17 @@
 package org.apache.inlong.manager.common.enums;
 
 import com.fasterxml.jackson.annotation.JsonValue;
-import java.util.Arrays;
 import lombok.Getter;
 
+import java.util.Arrays;
+
 /**
  * User type enum
  */
 public enum UserTypeEnum {
 
-    MANAGER(0), // has all privilege
-    OPERATOR(1), // No privilege to manage the system
+    Admin(0), // has all privilege
+    Operator(1), // No privilege to manage the system
     ;
 
     @Getter
diff --git a/inlong-manager/manager-common/src/main/java/org/apache/inlong/manager/common/pojo/group/InlongGroupPageRequest.java b/inlong-manager/manager-common/src/main/java/org/apache/inlong/manager/common/pojo/group/InlongGroupPageRequest.java
index 70c38620e..8eced0cd4 100644
--- a/inlong-manager/manager-common/src/main/java/org/apache/inlong/manager/common/pojo/group/InlongGroupPageRequest.java
+++ b/inlong-manager/manager-common/src/main/java/org/apache/inlong/manager/common/pojo/group/InlongGroupPageRequest.java
@@ -51,6 +51,9 @@ public class InlongGroupPageRequest extends PageRequest {
     @ApiModelProperty(value = "Current user", hidden = true)
     private String currentUser;
 
+    @ApiModelProperty(value = "Whether the current user is in the administrator role", hidden = true)
+    private Boolean isAdminRole;
+
     @ApiModelProperty(value = "If list streamSource for group", hidden = true)
     private boolean listSources = false;
 }
diff --git a/inlong-manager/manager-common/src/main/java/org/apache/inlong/manager/common/enums/UserTypeEnum.java b/inlong-manager/manager-common/src/main/java/org/apache/inlong/manager/common/pojo/user/UserRoleCode.java
similarity index 54%
copy from inlong-manager/manager-common/src/main/java/org/apache/inlong/manager/common/enums/UserTypeEnum.java
copy to inlong-manager/manager-common/src/main/java/org/apache/inlong/manager/common/pojo/user/UserRoleCode.java
index a9d06dab0..8262a7732 100644
--- a/inlong-manager/manager-common/src/main/java/org/apache/inlong/manager/common/enums/UserTypeEnum.java
+++ b/inlong-manager/manager-common/src/main/java/org/apache/inlong/manager/common/pojo/user/UserRoleCode.java
@@ -15,34 +15,10 @@
  * limitations under the License.
  */
 
-package org.apache.inlong.manager.common.enums;
+package org.apache.inlong.manager.common.pojo.user;
 
-import com.fasterxml.jackson.annotation.JsonValue;
-import java.util.Arrays;
-import lombok.Getter;
-
-/**
- * User type enum
- */
-public enum UserTypeEnum {
-
-    MANAGER(0), // has all privilege
-    OPERATOR(1), // No privilege to manage the system
-    ;
-
-    @Getter
-    @JsonValue
-    private final Integer code;
-
-    UserTypeEnum(Integer code) {
-        this.code = code;
-    }
-
-    public static UserTypeEnum parse(Integer value) {
-        return Arrays.stream(UserTypeEnum.class.getEnumConstants())
-                .filter(x -> x.getCode().equals(value))
-                .findAny()
-                .orElse(null);
-    }
+public class UserRoleCode {
 
+    public static final String ADMIN = "Admin";
+    public static final String OPERATOR = "Operator";
 }
diff --git a/inlong-manager/manager-service/src/main/java/org/apache/inlong/manager/service/core/impl/UserServiceImpl.java b/inlong-manager/manager-service/src/main/java/org/apache/inlong/manager/service/core/impl/UserServiceImpl.java
index 06d9f2c5f..2e201d9a9 100644
--- a/inlong-manager/manager-service/src/main/java/org/apache/inlong/manager/service/core/impl/UserServiceImpl.java
+++ b/inlong-manager/manager-service/src/main/java/org/apache/inlong/manager/service/core/impl/UserServiceImpl.java
@@ -17,13 +17,9 @@
 
 package org.apache.inlong.manager.service.core.impl;
 
-import static org.apache.inlong.manager.common.util.SmallTools.getOverDueDate;
-
 import com.github.pagehelper.Page;
 import com.github.pagehelper.PageHelper;
 import com.github.pagehelper.PageInfo;
-import java.util.Date;
-import java.util.List;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.inlong.manager.common.enums.UserTypeEnum;
 import org.apache.inlong.manager.common.pojo.user.PasswordChangeRequest;
@@ -42,6 +38,11 @@ import org.apache.inlong.manager.service.core.UserService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
+import java.util.Date;
+import java.util.List;
+
+import static org.apache.inlong.manager.common.util.SmallTools.getOverDueDate;
+
 /**
  * User service
  */
@@ -103,7 +104,7 @@ public class UserServiceImpl implements UserService {
 
         // Whether the current user is an administrator
         UserEntity currentUserEntity = getByName(currentUser);
-        Preconditions.checkTrue(currentUserEntity.getAccountType().equals(UserTypeEnum.MANAGER.getCode()),
+        Preconditions.checkTrue(currentUserEntity.getAccountType().equals(UserTypeEnum.Admin.getCode()),
                 "The current user is not a manager and does not have permission to update users");
 
         UserEntity entity = userMapper.selectByPrimaryKey(userInfo.getId());
@@ -141,7 +142,7 @@ public class UserServiceImpl implements UserService {
 
         // Whether the current user is an administrator
         UserEntity entity = getByName(currentUser);
-        Preconditions.checkTrue(entity.getAccountType().equals(UserTypeEnum.MANAGER.getCode()),
+        Preconditions.checkTrue(entity.getAccountType().equals(UserTypeEnum.Admin.getCode()),
                 "The current user is not a manager and does not have permission to delete users");
 
         userMapper.deleteByPrimaryKey(userId);
diff --git a/inlong-manager/manager-web/src/main/java/org/apache/inlong/manager/web/auth/WebAuthorizingRealm.java b/inlong-manager/manager-web/src/main/java/org/apache/inlong/manager/web/auth/WebAuthorizingRealm.java
index 7fd910bcb..d71c3f958 100644
--- a/inlong-manager/manager-web/src/main/java/org/apache/inlong/manager/web/auth/WebAuthorizingRealm.java
+++ b/inlong-manager/manager-web/src/main/java/org/apache/inlong/manager/web/auth/WebAuthorizingRealm.java
@@ -18,7 +18,7 @@
 package org.apache.inlong.manager.web.auth;
 
 import com.google.common.collect.Sets;
-import java.util.Date;
+import org.apache.inlong.manager.common.enums.UserTypeEnum;
 import org.apache.inlong.manager.common.pojo.user.UserDetail;
 import org.apache.inlong.manager.common.util.Preconditions;
 import org.apache.inlong.manager.dao.entity.UserEntity;
@@ -29,36 +29,55 @@ import org.apache.shiro.authc.AuthenticationToken;
 import org.apache.shiro.authc.SimpleAuthenticationInfo;
 import org.apache.shiro.authc.UsernamePasswordToken;
 import org.apache.shiro.authz.AuthorizationInfo;
+import org.apache.shiro.authz.SimpleAuthorizationInfo;
 import org.apache.shiro.realm.AuthorizingRealm;
 import org.apache.shiro.subject.PrincipalCollection;
 
+import java.util.Date;
+
 public class WebAuthorizingRealm extends AuthorizingRealm {
 
-    private UserService userService;
+    private final UserService userService;
 
     public WebAuthorizingRealm(UserService userService) {
         this.userService = userService;
     }
 
+    /**
+     * Login authentication
+     *
+     * @param authenticationToken
+     * @return
+     * @throws AuthenticationException
+     */
     @Override
     protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken)
             throws AuthenticationException {
         UsernamePasswordToken upToken = (UsernamePasswordToken) authenticationToken;
         String username = upToken.getUsername();
         UserEntity userEntity = userService.getByName(username);
-
         Preconditions.checkNotNull(userEntity, "User doesn't exist");
         Preconditions.checkTrue(userEntity.getDueDate().after(new Date()), "user has expired");
-
         UserDetail userDetail = new UserDetail();
         userDetail.setUserName(username);
-        userDetail.setRoles(Sets.newHashSet(userEntity.getAccountType().toString()));
-
+        userDetail.setRoles(Sets.newHashSet(userEntity.getAccountType() == 0
+                ? UserTypeEnum.Admin.name() : UserTypeEnum.Operator.name()));
         return new SimpleAuthenticationInfo(userDetail, userEntity.getPassword(), getName());
     }
 
+    /**
+     * URI access control
+     *
+     * @param principalCollection
+     * @return
+     */
     @Override
     protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
-        return null;
+        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
+        UserDetail userDetail = (UserDetail) getAvailablePrincipal(principalCollection);
+        if (userDetail != null) {
+            simpleAuthorizationInfo.setRoles(userDetail.getRoles());
+        }
+        return simpleAuthorizationInfo;
     }
 }
diff --git a/inlong-manager/manager-web/src/main/java/org/apache/inlong/manager/web/config/ControllerExceptionHandler.java b/inlong-manager/manager-web/src/main/java/org/apache/inlong/manager/web/config/ControllerExceptionHandler.java
index d58ca235a..457c1063b 100644
--- a/inlong-manager/manager-web/src/main/java/org/apache/inlong/manager/web/config/ControllerExceptionHandler.java
+++ b/inlong-manager/manager-web/src/main/java/org/apache/inlong/manager/web/config/ControllerExceptionHandler.java
@@ -17,17 +17,15 @@
 
 package org.apache.inlong.manager.web.config;
 
-import java.util.Set;
-import javax.servlet.http.HttpServletRequest;
-import javax.validation.ConstraintViolation;
-import javax.validation.ConstraintViolationException;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.inlong.manager.common.beans.Response;
 import org.apache.inlong.manager.common.exceptions.BusinessException;
+import org.apache.inlong.manager.common.exceptions.WorkflowException;
 import org.apache.inlong.manager.common.pojo.user.UserDetail;
 import org.apache.inlong.manager.common.util.LoginUserUtils;
-import org.apache.inlong.manager.common.exceptions.WorkflowException;
 import org.apache.shiro.authc.AuthenticationException;
+import org.apache.shiro.authz.AuthorizationException;
+import org.apache.shiro.authz.UnauthorizedException;
 import org.springframework.http.converter.HttpMessageConversionException;
 import org.springframework.validation.BindException;
 import org.springframework.web.bind.MethodArgumentNotValidException;
@@ -35,6 +33,11 @@ import org.springframework.web.bind.annotation.ControllerAdvice;
 import org.springframework.web.bind.annotation.ExceptionHandler;
 import org.springframework.web.bind.annotation.ResponseBody;
 
+import javax.servlet.http.HttpServletRequest;
+import javax.validation.ConstraintViolation;
+import javax.validation.ConstraintViolationException;
+import java.util.Set;
+
 @Slf4j
 @ControllerAdvice
 public class ControllerExceptionHandler {
@@ -117,6 +120,15 @@ public class ControllerExceptionHandler {
         return Response.fail("username or password is incorrect, or the account has expired");
     }
 
+    @ResponseBody
+    @ExceptionHandler(value = UnauthorizedException.class)
+    public Response<String> handleUnauthorizedException(HttpServletRequest request, AuthorizationException e) {
+        log.error("Failed to handle request on path:" + request.getRequestURI(), e);
+        UserDetail userDetail = LoginUserUtils.getLoginUserDetail();
+        return Response.fail("Current user [" + (userDetail != null ? userDetail.getUserName() : "")
+                + "] has no permission to access URL: " + request.getRequestURI());
+    }
+
     @ExceptionHandler(Exception.class)
     @ResponseBody
     public Response<String> handle(HttpServletRequest request, Exception e) {
diff --git a/inlong-manager/manager-web/src/main/java/org/apache/inlong/manager/web/controller/ClusterController.java b/inlong-manager/manager-web/src/main/java/org/apache/inlong/manager/web/controller/ClusterController.java
index d8ca4bf74..c0053267d 100644
--- a/inlong-manager/manager-web/src/main/java/org/apache/inlong/manager/web/controller/ClusterController.java
+++ b/inlong-manager/manager-web/src/main/java/org/apache/inlong/manager/web/controller/ClusterController.java
@@ -26,10 +26,11 @@ import org.apache.inlong.manager.common.enums.OperationType;
 import org.apache.inlong.manager.common.pojo.cluster.ClusterPageRequest;
 import org.apache.inlong.manager.common.pojo.cluster.ClusterRequest;
 import org.apache.inlong.manager.common.pojo.cluster.ClusterResponse;
+import org.apache.inlong.manager.common.pojo.user.UserRoleCode;
 import org.apache.inlong.manager.common.util.LoginUserUtils;
-import org.apache.inlong.manager.service.core.DataProxyClusterService;
 import org.apache.inlong.manager.service.core.ThirdPartyClusterService;
 import org.apache.inlong.manager.service.core.operationlog.OperationLog;
+import org.apache.shiro.authz.annotation.RequiresRoles;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.DeleteMapping;
 import org.springframework.web.bind.annotation.GetMapping;
@@ -50,12 +51,11 @@ public class ClusterController {
 
     @Autowired
     private ThirdPartyClusterService thirdPartyClusterService;
-    @Autowired
-    private DataProxyClusterService dataProxyClusterService;
 
     @PostMapping(value = "/save")
     @ApiOperation(value = "Save cluster info")
     @OperationLog(operation = OperationType.CREATE)
+    @RequiresRoles(value = UserRoleCode.ADMIN)
     public Response<Integer> save(@RequestBody ClusterRequest request) {
         String currentUser = LoginUserUtils.getLoginUserDetail().getUserName();
         return Response.success(thirdPartyClusterService.save(request, currentUser));
@@ -86,6 +86,7 @@ public class ClusterController {
     @ApiOperation(value = "Delete cluster info by id")
     @OperationLog(operation = OperationType.DELETE)
     @ApiImplicitParam(name = "id", value = "Cluster ID", dataTypeClass = Integer.class, required = true)
+    @RequiresRoles(value = UserRoleCode.ADMIN)
     public Response<Boolean> delete(@PathVariable Integer id) {
         return Response.success(thirdPartyClusterService.delete(id, LoginUserUtils.getLoginUserDetail().getUserName()));
     }
diff --git a/inlong-manager/manager-web/src/main/java/org/apache/inlong/manager/web/controller/InlongGroupController.java b/inlong-manager/manager-web/src/main/java/org/apache/inlong/manager/web/controller/InlongGroupController.java
index 3f2573f21..6205063ec 100644
--- a/inlong-manager/manager-web/src/main/java/org/apache/inlong/manager/web/controller/InlongGroupController.java
+++ b/inlong-manager/manager-web/src/main/java/org/apache/inlong/manager/web/controller/InlongGroupController.java
@@ -23,6 +23,7 @@ import io.swagger.annotations.ApiImplicitParam;
 import io.swagger.annotations.ApiOperation;
 import org.apache.inlong.manager.common.beans.Response;
 import org.apache.inlong.manager.common.enums.OperationType;
+import org.apache.inlong.manager.common.enums.UserTypeEnum;
 import org.apache.inlong.manager.common.pojo.group.InlongGroupCountResponse;
 import org.apache.inlong.manager.common.pojo.group.InlongGroupListResponse;
 import org.apache.inlong.manager.common.pojo.group.InlongGroupPageRequest;
@@ -73,6 +74,7 @@ public class InlongGroupController {
     @ApiOperation(value = "Get inlong group list by paginating")
     public Response<PageInfo<InlongGroupListResponse>> listByCondition(@RequestBody InlongGroupPageRequest request) {
         request.setCurrentUser(LoginUserUtils.getLoginUserDetail().getUserName());
+        request.setIsAdminRole(LoginUserUtils.getLoginUserDetail().getRoles().contains(UserTypeEnum.Admin.name()));
         return Response.success(groupService.listByCondition(request));
     }
 
diff --git a/inlong-manager/manager-web/src/main/java/org/apache/inlong/manager/web/controller/UserController.java b/inlong-manager/manager-web/src/main/java/org/apache/inlong/manager/web/controller/UserController.java
index cdbe11cad..748cb1bd5 100644
--- a/inlong-manager/manager-web/src/main/java/org/apache/inlong/manager/web/controller/UserController.java
+++ b/inlong-manager/manager-web/src/main/java/org/apache/inlong/manager/web/controller/UserController.java
@@ -26,8 +26,10 @@ import org.apache.inlong.manager.common.pojo.user.UserDetail;
 import org.apache.inlong.manager.common.pojo.user.UserDetailListVO;
 import org.apache.inlong.manager.common.pojo.user.UserDetailPageRequest;
 import org.apache.inlong.manager.common.pojo.user.UserInfo;
+import org.apache.inlong.manager.common.pojo.user.UserRoleCode;
 import org.apache.inlong.manager.common.util.LoginUserUtils;
 import org.apache.inlong.manager.service.core.UserService;
+import org.apache.shiro.authz.annotation.RequiresRoles;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.DeleteMapping;
 import org.springframework.web.bind.annotation.GetMapping;
@@ -57,6 +59,7 @@ public class UserController {
 
     @PostMapping("/register")
     @ApiOperation(value = "Register user")
+    @RequiresRoles(value = UserRoleCode.ADMIN)
     public Response<Boolean> register(@RequestBody UserInfo userInfo) {
         userInfo.checkValid();
         return Response.success(userService.create(userInfo));
@@ -89,6 +92,7 @@ public class UserController {
 
     @DeleteMapping("/delete")
     @ApiOperation(value = "Delete user by id")
+    @RequiresRoles(value = UserRoleCode.ADMIN)
     public Response<Boolean> delete(@RequestParam("id") Integer id) {
         String currentUser = LoginUserUtils.getLoginUserDetail().getUserName();
         return Response.success(userService.delete(id, currentUser));