blob: cef8478d887e50896a153170939ca99005ebbbaa [file] [log] [blame]
// 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.doris.stack.component;
import org.apache.doris.stack.dao.ClusterUserMembershipRepository;
import org.apache.doris.stack.entity.ClusterUserMembershipEntity;
import org.apache.doris.stack.exception.UserNoSelectClusterException;
import org.apache.doris.stack.model.request.user.UserGroupRole;
import org.apache.doris.stack.dao.ClusterInfoRepository;
import org.apache.doris.stack.dao.CoreUserRepository;
import org.apache.doris.stack.dao.PermissionsGroupMembershipRepository;
import org.apache.doris.stack.dao.PermissionsGroupRoleRepository;
import org.apache.doris.stack.entity.ClusterInfoEntity;
import org.apache.doris.stack.entity.CoreUserEntity;
import org.apache.doris.stack.entity.PermissionsGroupMembershipEntity;
import org.apache.doris.stack.entity.PermissionsGroupRoleEntity;
import org.apache.doris.stack.exception.NoPermissionException;
import org.apache.doris.stack.model.response.user.GroupMember;
import org.apache.doris.stack.service.BaseService;
import lombok.extern.slf4j.Slf4j;
import org.apache.doris.stack.util.CredsUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
/**
* @Description:The engine cluster management tool class is mainly responsible for
* verifying whether the user has the permission of cluster space
*/
@Component
@Slf4j
public class ClusterUserComponent extends BaseService {
@Autowired
private ClusterInfoRepository clusterInfoRepository;
@Autowired
private PermissionsGroupRoleRepository groupRoleRepository;
@Autowired
private PermissionsGroupMembershipRepository membershipRepository;
@Autowired
private CoreUserRepository userRepository;
@Autowired
private ClusterUserMembershipRepository clusterUserMembershipRepository;
/**
* Obtain the user's current space information.
* All API accesses in the space need to obtain the current space ID
* @param user
* @return
* @throws Exception
*/
public ClusterInfoEntity getUserCurrentCluster(CoreUserEntity user) throws Exception {
long clusterId = user.getClusterId();
if (clusterId < 1) {
log.error("The user do not have current cluster");
throw new UserNoSelectClusterException();
}
Optional<ClusterInfoEntity> clusterInfoEntityOp = clusterInfoRepository.findById((long) clusterId);
if (clusterInfoEntityOp.equals(Optional.empty())) {
log.error("The user current cluster {} has been deleted", clusterId);
throw new UserNoSelectClusterException();
}
ClusterInfoEntity clusterInfoEntity = clusterInfoEntityOp.get();
try {
clusterInfoEntity.setPasswd(CredsUtil.aesDecrypt(clusterInfoEntity.getPasswd()));
} catch (Exception e) {
log.warn("execute more than once select in one thread, the password was cached. msg {}", e.getMessage());
}
return clusterInfoEntity;
}
// add a user for all space which doesn't have default user
// public void addDefaultUserForSpace() throws Exception {
// log.debug("add default user");
// List<ClusterInfoEntity> clusterInfoEntities = clusterInfoRepository.findAll();
// for (ClusterInfoEntity clusterInfo : clusterInfoEntities) {
// int adminGroupUserId = clusterInfo.getAdminGroupId();
// int allUserGroupId = clusterInfo.getAllUserGroupId();
// long clusterId = clusterInfo.getId();
// if (membershipRepository.getByUserId(-1L * clusterId).size() < 2) {
//
// addDefaultUserForSpace(clusterId, adminGroupUserId, allUserGroupId);
// }
// }
// }
// public void addDefaultUserForSpace(long clusterId, int adminGroupUserId, int allUserGroupId) throws Exception {
// log.debug("add default user for space");
// // add into admin group
// PermissionsGroupMembershipEntity adminMembershipEntity = new PermissionsGroupMembershipEntity();
// adminMembershipEntity.setUserId(-clusterId);
// adminMembershipEntity.setGroupId(adminGroupUserId);
// membershipRepository.save(adminMembershipEntity);
// // add into all user group
// PermissionsGroupMembershipEntity allUserMembershipEntity = new PermissionsGroupMembershipEntity();
// allUserMembershipEntity.setUserId(-clusterId);
// allUserMembershipEntity.setGroupId(allUserGroupId);
// membershipRepository.save(allUserMembershipEntity);
// }
/**
* Judge whether the user is in the space
* @param userId
* @return
* @throws Exception
*/
public boolean checkUserBelongToCluster(int userId, long clusterId) throws Exception {
// built in user
if (userId == BuiltInUserComponent.BUILT_USER_ID) {
return true;
}
List<ClusterUserMembershipEntity> clusterUserMembershipEntities =
clusterUserMembershipRepository.getByUserIdAndClusterId(userId, clusterId);
if (clusterUserMembershipEntities.isEmpty()) {
log.error("The user {} is not a space {} user.", userId, clusterId);
throw new NoPermissionException();
}
return true;
}
/**
* Judge whether the user is in the space
* @param userId
* @return
* @throws Exception
*/
public boolean userBelongToCluster(int userId, long clusterId) {
List<ClusterUserMembershipEntity> clusterUserMembershipEntities =
clusterUserMembershipRepository.getByUserIdAndClusterId(userId, clusterId);
if (clusterUserMembershipEntities.isEmpty()) {
return false;
} else {
return true;
}
}
/**
* Determine whether the user is the administrator role of a space
* @param userId
* @param clusterInfo
* @return
*/
public boolean userIsClusterAdminRole(int userId, ClusterInfoEntity clusterInfo) {
int adminGroupRoleId = clusterInfo.getAdminGroupId();
List<PermissionsGroupMembershipEntity> membershipEntities =
membershipRepository.getByUserIdAndGroupId(userId, adminGroupRoleId);
if (membershipEntities == null || membershipEntities.isEmpty()) {
return false;
}
return true;
}
/**
* Add a normal user to the space
* @param userId
* @param clusterInfo
*/
public void addUserToCluster(int userId, ClusterInfoEntity clusterInfo) {
ClusterUserMembershipEntity membershipEntity =
new ClusterUserMembershipEntity(userId, clusterInfo.getId());
clusterUserMembershipRepository.save(membershipEntity);
addGroupUserMembership(userId, clusterInfo.getAllUserGroupId());
}
/**
* Add an administrator user to the space
* @param userId
* @param clusterInfo
*/
public void addAdminUserToCluster(int userId, ClusterInfoEntity clusterInfo) {
addUserToCluster(userId, clusterInfo);
addGroupUserMembership(userId, clusterInfo.getAdminGroupId());
}
/**
* Check whether the user is the administrator role user of the space
* Available to space level APIs
* @param user
* @return
* @throws Exception
*/
public long getUserCurrentClusterIdAndCheckAdmin(CoreUserEntity user) throws Exception {
ClusterInfoEntity cluster = getUserCurrentCluster(user);
long clusterId = cluster.getId();
if (!user.isSuperuser() && !user.getIsClusterAdmin()) {
log.error("The user {} not cluster {} space admin", user.getId(), clusterId);
throw new NoPermissionException();
}
return clusterId;
}
/**
* Check whether the user is the administrator role user of the space
* Available to space level APIs
* @param user
* @return
* @throws Exception
*/
public ClusterInfoEntity getUserCurrentClusterAndCheckAdmin(CoreUserEntity user) throws Exception {
ClusterInfoEntity cluster = getUserCurrentCluster(user);
if (!user.isSuperuser() && !user.getIsClusterAdmin()) {
log.error("The user {} not cluster {} space admin", user.getId(), cluster.getId());
throw new NoPermissionException();
}
return cluster;
}
/**
* Check whether the user has the operation permission of the administrator role of the space
* Space level API usage
* @param user
* @param clusterId
* @return
* @throws Exception
*/
public ClusterInfoEntity checkUserClusterAdminPermission(CoreUserEntity user, long clusterId) throws Exception {
// The super admin user has all space administrator permissions by default and can operate directly
if (user.isSuperuser()) {
return clusterInfoRepository.findById((long) clusterId).get();
} else {
int userId = user.getId();
ClusterInfoEntity clusterInfoEntity = clusterInfoRepository.findById((long) clusterId).get();
boolean isAdmin = userIsClusterAdminRole(userId, clusterInfoEntity);
if (!isAdmin) {
log.error("The user {} is not a space {} user.", userId, clusterId);
throw new NoPermissionException();
}
return clusterInfoEntity;
}
}
/**
* Check whether the user has the operation permission of the administrator role of the space
* APIs that can be accessed at both platform and space levels are used
* @param user
* @param clusterId
* @return
* @throws Exception
*/
public void checkUserSpuerAdminOrClusterAdmin(CoreUserEntity user, long clusterId) throws Exception {
// The super admin user has all space administrator permissions by default and can operate directly
if (user.isSuperuser()) {
return;
} else {
int userId = user.getId();
ClusterInfoEntity clusterInfoEntity = clusterInfoRepository.findById((long) clusterId).get();
boolean isAdmin = userIsClusterAdminRole(userId, clusterInfoEntity);
if (!isAdmin) {
log.error("The user {} is not a space {} user.", userId, clusterId);
throw new NoPermissionException();
}
return;
}
}
/**
* Initialize the correspondence between permission groups and users
*
* @param userId
* @param groupId
* @return
*/
public int addGroupUserMembership(int userId, int groupId) {
PermissionsGroupMembershipEntity amdinMembershipEntity =
new PermissionsGroupMembershipEntity(userId, groupId);
return membershipRepository.save(amdinMembershipEntity).getId();
}
/**
* Create a user group and return the user group ID
*
* @return
*/
public int addPermissionsGroup(String name, long clusterId, UserGroupRole role) {
// Create a user group and bind the relationship with the Doris cluster and user information.
PermissionsGroupRoleEntity groupRoleEntity =
new PermissionsGroupRoleEntity(name, role.name(), clusterId);
int groupId = groupRoleRepository.save(groupRoleEntity).getGroupId();
log.debug("create group {}.", groupId);
return groupId;
}
/**
* Create a user group and return the user group ID
*
* @return
*/
public int addPermissionsGroup(String name, long clusterId, UserGroupRole role, String dorisUserName,
String passwd) {
// Create a user group and bind the relationship with the Doris cluster and user information.
PermissionsGroupRoleEntity groupRoleEntity =
new PermissionsGroupRoleEntity(name, role.name(), clusterId, dorisUserName, passwd);
int groupId = groupRoleRepository.save(groupRoleEntity).getGroupId();
log.debug("create group {}.", groupId);
return groupId;
}
/**
* Save user group password information
* @Param
* @return
*/
public PermissionsGroupRoleEntity addPermissionsGroupWithPaloUser(String name, long clusterId,
UserGroupRole role, String password,
String userName) throws Exception {
// Create a user group and bind the relationship with the Doris cluster and user information.
password = CredsUtil.aesEncrypt(password);
PermissionsGroupRoleEntity groupRoleEntity =
new PermissionsGroupRoleEntity(name, role.name(), clusterId, userName, password);
int groupId = groupRoleRepository.save(groupRoleEntity).getGroupId();
log.debug("create group {}.", groupId);
return groupRoleEntity;
}
/**
* Get all members of a permission group
*
* @param groupId
* @return
*/
public List<GroupMember> getGroupMembers(int groupId) {
log.debug("get group {} all members.", groupId);
List<Integer> stopLdapUsers = userRepository.getByEmptyEntryUUID();
List<PermissionsGroupMembershipEntity> users = membershipRepository.getByGroupId(groupId);
List<GroupMember> members = new ArrayList<>();
for (PermissionsGroupMembershipEntity membershipEntity : users) {
// get user
if (membershipEntity.getUserId() < 0 || stopLdapUsers.contains(membershipEntity.getUserId())) {
continue;
}
CoreUserEntity userEntity = userRepository.findById(membershipEntity.getUserId()).get();
// construct Member
GroupMember member = new GroupMember();
member.setMembershipId(membershipEntity.getId());
member.setUserId(membershipEntity.getUserId());
member.setName(userEntity.getFirstName());
member.setEmail(userEntity.getEmail());
// add list
members.add(member);
}
return members;
}
// Encrypt the cluster unencrypted password
public void encryptClusterPassword() throws Exception {
log.debug("encrypt password for cluster");
List<ClusterInfoEntity> clusterInfoEntities = clusterInfoRepository.findAll();
log.debug("encrypt password for cluster, size is {}", clusterInfoEntities.size());
for (ClusterInfoEntity clusterInfo : clusterInfoEntities) {
if (clusterInfo.getPasswd() == null) {
log.debug("cluster password is null");
continue;
}
if (!clusterInfo.getPasswd().trim().equals("")) {
try {
CredsUtil.aesDecrypt(clusterInfo.getPasswd());
log.debug("password has been encrypted");
continue;
} catch (Exception e) {
log.debug("password has not been encrypted");
}
}
// Empty string is still empty after encryption
clusterInfo.setPasswd(CredsUtil.aesEncrypt(clusterInfo.getPasswd()));
clusterInfoRepository.save(clusterInfo);
}
}
}