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));