分布式调度框架。
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1350 lines
47 KiB

/*
* 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.api.service.impl;
import static org.apache.dolphinscheduler.api.constants.ApiFuncIdentificationConstant.USER_MANAGER;
import org.apache.dolphinscheduler.api.dto.resources.ResourceComponent;
import org.apache.dolphinscheduler.api.enums.Status;
import org.apache.dolphinscheduler.api.exceptions.ServiceException;
import org.apache.dolphinscheduler.api.service.MetricsCleanUpService;
import org.apache.dolphinscheduler.api.service.SessionService;
import org.apache.dolphinscheduler.api.service.UsersService;
import org.apache.dolphinscheduler.api.utils.CheckUtils;
import org.apache.dolphinscheduler.api.utils.PageInfo;
import org.apache.dolphinscheduler.api.utils.Result;
import org.apache.dolphinscheduler.common.constants.Constants;
import org.apache.dolphinscheduler.common.enums.AuthorizationType;
import org.apache.dolphinscheduler.common.enums.Flag;
import org.apache.dolphinscheduler.common.enums.UserType;
import org.apache.dolphinscheduler.common.utils.EncryptionUtils;
import org.apache.dolphinscheduler.dao.entity.AlertGroup;
import org.apache.dolphinscheduler.dao.entity.DatasourceUser;
import org.apache.dolphinscheduler.dao.entity.K8sNamespaceUser;
import org.apache.dolphinscheduler.dao.entity.Project;
import org.apache.dolphinscheduler.dao.entity.ProjectUser;
import org.apache.dolphinscheduler.dao.entity.Tenant;
import org.apache.dolphinscheduler.dao.entity.UDFUser;
import org.apache.dolphinscheduler.dao.entity.User;
import org.apache.dolphinscheduler.dao.mapper.AccessTokenMapper;
import org.apache.dolphinscheduler.dao.mapper.AlertGroupMapper;
import org.apache.dolphinscheduler.dao.mapper.DataSourceUserMapper;
import org.apache.dolphinscheduler.dao.mapper.K8sNamespaceUserMapper;
import org.apache.dolphinscheduler.dao.mapper.ProjectMapper;
import org.apache.dolphinscheduler.dao.mapper.ProjectUserMapper;
import org.apache.dolphinscheduler.dao.mapper.TenantMapper;
import org.apache.dolphinscheduler.dao.mapper.UDFUserMapper;
import org.apache.dolphinscheduler.dao.mapper.UserMapper;
import org.apache.dolphinscheduler.plugin.storage.api.StorageOperate;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import java.io.IOException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.TimeZone;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
/**
* users service impl
*/
@Service
@Slf4j
public class UsersServiceImpl extends BaseServiceImpl implements UsersService {
@Autowired
private AccessTokenMapper accessTokenMapper;
@Autowired
private UserMapper userMapper;
@Autowired
private TenantMapper tenantMapper;
@Autowired
private ProjectUserMapper projectUserMapper;
@Autowired
private DataSourceUserMapper datasourceUserMapper;
@Autowired
private UDFUserMapper udfUserMapper;
@Autowired
private AlertGroupMapper alertGroupMapper;
@Autowired
private ProjectMapper projectMapper;
@Autowired(required = false)
private StorageOperate storageOperate;
@Autowired
private K8sNamespaceUserMapper k8sNamespaceUserMapper;
@Autowired
private MetricsCleanUpService metricsCleanUpService;
@Autowired
private SessionService sessionService;
/**
* create user, only system admin have permission
*
* @param loginUser login user
* @param userName user name
* @param userPassword user password
* @param email email
* @param tenantId tenant id
* @param phone phone
* @param queue queue
* @return create result code
* @throws Exception exception
*/
@Override
@Transactional(rollbackFor = Exception.class)
public Map<String, Object> createUser(User loginUser,
String userName,
String userPassword,
String email,
int tenantId,
String phone,
String queue,
int state) throws Exception {
Map<String, Object> result = new HashMap<>();
// check all user params
String msg = this.checkUserParams(userName, userPassword, email, phone);
if (resourcePermissionCheckService.functionDisabled()) {
putMsg(result, Status.FUNCTION_DISABLED, msg);
return result;
}
if (!isAdmin(loginUser)) {
putMsg(result, Status.USER_NO_OPERATION_PERM);
return result;
}
if (!StringUtils.isEmpty(msg)) {
putMsg(result, Status.REQUEST_PARAMS_NOT_VALID_ERROR, msg);
return result;
}
if (!checkTenantExists(tenantId)) {
log.warn("Tenant does not exist, tenantId:{}.", tenantId);
putMsg(result, Status.TENANT_NOT_EXIST);
return result;
}
User user = createUser(userName, userPassword, email, tenantId, phone, queue, state);
Tenant tenant = tenantMapper.queryById(tenantId);
storageOperate.createTenantDirIfNotExists(tenant.getTenantCode());
log.info("User is created and id is {}.", user.getId());
result.put(Constants.DATA_LIST, user);
putMsg(result, Status.SUCCESS);
return result;
}
@Override
@Transactional
public User createUser(String userName,
String userPassword,
String email,
int tenantId,
String phone,
String queue,
int state) {
User user = new User();
Date now = new Date();
user.setUserName(userName);
user.setUserPassword(EncryptionUtils.getMd5(userPassword));
user.setEmail(email);
user.setTenantId(tenantId);
user.setPhone(phone);
user.setState(state);
// create general users, administrator users are currently built-in
user.setUserType(UserType.GENERAL_USER);
user.setCreateTime(now);
user.setUpdateTime(now);
if (StringUtils.isEmpty(queue)) {
queue = "";
}
user.setQueue(queue);
// save user
userMapper.insert(user);
return user;
}
/***
* create User for ldap、Casdoor SSO and OAuth2.0 login
*/
@Override
@Transactional
public User createUser(UserType userType, String userId, String email) {
User user = new User();
Date now = new Date();
user.setUserName(userId);
user.setEmail(email);
// create general users, administrator users are currently built-in
user.setUserType(userType);
user.setCreateTime(now);
user.setUpdateTime(now);
user.setTenantId(-1);
user.setQueue("");
user.setState(Flag.YES.getCode());
// save user
userMapper.insert(user);
return user;
}
/**
* get user by user name
*
* @param userName user name
* @return exist user or null
*/
@Override
public User getUserByUserName(String userName) {
return userMapper.queryByUserNameAccurately(userName);
}
/**
* query user by id
*
* @param id id
* @return user info
*/
@Override
public User queryUser(int id) {
return userMapper.selectById(id);
}
@Override
public List<User> queryUser(List<Integer> ids) {
if (CollectionUtils.isEmpty(ids)) {
return new ArrayList<>();
}
return userMapper.selectByIds(ids);
}
/**
* query user
*
* @param name name
* @return user info
*/
@Override
public User queryUser(String name) {
return userMapper.queryByUserNameAccurately(name);
}
/**
* query user
*
* @param name name
* @param password password
* @return user info
*/
@Override
public User queryUser(String name, String password) {
String md5 = EncryptionUtils.getMd5(password);
return userMapper.queryUserByNamePassword(name, md5);
}
/**
* get user id by user name
*
* @param name user name
* @return if name empty 0, user not exists -1, user exist user id
*/
@Override
public int getUserIdByName(String name) {
// executor name query
int executorId = 0;
if (StringUtils.isNotEmpty(name)) {
User executor = queryUser(name);
if (null != executor) {
executorId = executor.getId();
} else {
executorId = -1;
}
}
return executorId;
}
/**
* query user list
*
* @param loginUser login user
* @param pageNo page number
* @param searchVal search value
* @param pageSize page size
* @return user list page
*/
@Override
public Result<Object> queryUserList(User loginUser, String searchVal, Integer pageNo, Integer pageSize) {
Result<Object> result = new Result<>();
if (resourcePermissionCheckService.functionDisabled()) {
putMsg(result, Status.FUNCTION_DISABLED);
return result;
}
if (!isAdmin(loginUser)) {
log.warn("User does not have permission for this feature, userId:{}, userName:{}.", loginUser.getId(),
loginUser.getUserName());
putMsg(result, Status.USER_NO_OPERATION_PERM);
return result;
}
Page<User> page = new Page<>(pageNo, pageSize);
IPage<User> scheduleList = userMapper.queryUserPaging(page, searchVal);
PageInfo<User> pageInfo = new PageInfo<>(pageNo, pageSize);
pageInfo.setTotal((int) scheduleList.getTotal());
pageInfo.setTotalList(scheduleList.getRecords());
result.setData(pageInfo);
putMsg(result, Status.SUCCESS);
return result;
}
@Override
@Transactional
public User updateUser(User loginUser,
Integer userId,
String userName,
String userPassword,
String email,
Integer tenantId,
String phone,
String queue,
int state,
String timeZone) {
if (resourcePermissionCheckService.functionDisabled()) {
throw new ServiceException(Status.FUNCTION_DISABLED);
}
if (!canOperator(loginUser, userId)) {
throw new ServiceException(Status.USER_NO_OPERATION_PERM);
}
User user = userMapper.selectById(userId);
if (user == null) {
throw new ServiceException(Status.USER_NOT_EXIST, userId);
}
// non-admin should not modify tenantId and queue
if (!isAdmin(loginUser)) {
if (tenantId != null && user.getTenantId() != tenantId) {
throw new ServiceException(Status.USER_NO_OPERATION_PERM);
}
if (StringUtils.isNotEmpty(queue) && !StringUtils.equals(queue, user.getQueue())) {
throw new ServiceException(Status.USER_NO_OPERATION_PERM);
}
}
if (StringUtils.isNotEmpty(userName)) {
if (!CheckUtils.checkUserName(userName)) {
throw new ServiceException(Status.REQUEST_PARAMS_NOT_VALID_ERROR, userName);
}
// todo: use the db unique index
User tempUser = userMapper.queryByUserNameAccurately(userName);
if (tempUser != null && !userId.equals(tempUser.getId())) {
throw new ServiceException(Status.USER_NAME_EXIST);
}
user.setUserName(userName);
}
if (StringUtils.isNotEmpty(userPassword)) {
if (!CheckUtils.checkPasswordLength(userPassword)) {
throw new ServiceException(Status.USER_PASSWORD_LENGTH_ERROR);
}
user.setUserPassword(EncryptionUtils.getMd5(userPassword));
sessionService.expireSession(user.getId());
}
if (StringUtils.isNotEmpty(email)) {
if (!CheckUtils.checkEmail(email)) {
throw new ServiceException(Status.REQUEST_PARAMS_NOT_VALID_ERROR, email);
}
user.setEmail(email);
}
if (StringUtils.isNotEmpty(phone) && !CheckUtils.checkPhone(phone)) {
throw new ServiceException(Status.REQUEST_PARAMS_NOT_VALID_ERROR, phone);
}
if (state == 0 && user.getState() != state && Objects.equals(loginUser.getId(), user.getId())) {
throw new ServiceException(Status.NOT_ALLOW_TO_DISABLE_OWN_ACCOUNT);
}
if (StringUtils.isNotEmpty(timeZone)) {
if (!CheckUtils.checkTimeZone(timeZone)) {
throw new ServiceException(Status.TIME_ZONE_ILLEGAL, timeZone);
}
user.setTimeZone(timeZone);
}
user.setPhone(phone);
user.setQueue(queue);
user.setState(state);
user.setUpdateTime(new Date());
user.setTenantId(tenantId);
// updateProcessInstance user
if (userMapper.updateById(user) <= 0) {
throw new ServiceException(Status.UPDATE_USER_ERROR);
}
return user;
}
/**
* delete user
*
* @param loginUser login user
* @param id user id
* @return delete result code
* @throws Exception exception when operate hdfs
*/
@Override
@Transactional
public Map<String, Object> deleteUserById(User loginUser, int id) throws IOException {
Map<String, Object> result = new HashMap<>();
if (resourcePermissionCheckService.functionDisabled()) {
putMsg(result, Status.FUNCTION_DISABLED);
return result;
}
// only admin can operate
if (!isAdmin(loginUser)) {
log.warn("User does not have permission for this feature, userId:{}, userName:{}.", loginUser.getId(),
loginUser.getUserName());
putMsg(result, Status.USER_NO_OPERATION_PERM, id);
return result;
}
// check exist
User tempUser = userMapper.selectById(id);
if (tempUser == null) {
log.error("User does not exist, userId:{}.", id);
putMsg(result, Status.USER_NOT_EXIST, id);
return result;
}
// check if is a project owner
List<Project> projects = projectMapper.queryProjectCreatedByUser(id);
if (CollectionUtils.isNotEmpty(projects)) {
String projectNames = projects.stream().map(Project::getName).collect(Collectors.joining(","));
putMsg(result, Status.TRANSFORM_PROJECT_OWNERSHIP, projectNames);
log.warn("Please transfer the project ownership before deleting the user, userId:{}, projects:{}.", id,
projectNames);
return result;
}
// delete user
userMapper.queryTenantCodeByUserId(id);
accessTokenMapper.deleteAccessTokenByUserId(id);
sessionService.expireSession(id);
if (userMapper.deleteById(id) > 0) {
metricsCleanUpService.cleanUpApiResponseTimeMetricsByUserId(id);
log.info("User is deleted and id is :{}.", id);
putMsg(result, Status.SUCCESS);
return result;
} else {
log.error("User delete error, userId:{}.", id);
putMsg(result, Status.DELETE_USER_BY_ID_ERROR);
return result;
}
}
/**
* revoke the project permission for specified user by id
* @param loginUser Login user
* @param userId User id
* @param projectIds project id array
* @return
*/
@Override
@Transactional(rollbackFor = RuntimeException.class)
public Map<String, Object> revokeProjectById(User loginUser, int userId, String projectIds) {
Map<String, Object> result = new HashMap<>();
result.put(Constants.STATUS, false);
if (resourcePermissionCheckService.functionDisabled()) {
putMsg(result, Status.FUNCTION_DISABLED);
return result;
}
// 1. only admin can operate
if (this.check(result, !this.isAdmin(loginUser), Status.USER_NO_OPERATION_PERM)) {
return result;
}
// 2. check if user is existed
User user = this.userMapper.selectById(userId);
if (user == null) {
this.putMsg(result, Status.USER_NOT_EXIST, userId);
return result;
}
Arrays.stream(projectIds.split(",")).distinct().forEach(projectId -> {
// 3. check if project is existed
Project project = this.projectMapper.queryDetailById(Integer.parseInt(projectId));
if (project == null) {
this.putMsg(result, Status.PROJECT_NOT_FOUND, Integer.parseInt(projectId));
} else {
// 4. delete the relationship between project and user
this.projectUserMapper.deleteProjectRelation(project.getId(), user.getId());
}
});
this.putMsg(result, Status.SUCCESS);
return result;
}
/**
* grant project with read permission
*
* @param loginUser login user
* @param userId user id
* @param projectIds project id array
* @return grant result code
*/
@Override
@Transactional(rollbackFor = RuntimeException.class)
public Map<String, Object> grantProjectWithReadPerm(User loginUser, int userId, String projectIds) {
Map<String, Object> result = new HashMap<>();
result.put(Constants.STATUS, false);
if (resourcePermissionCheckService.functionDisabled()) {
putMsg(result, Status.FUNCTION_DISABLED);
return result;
}
if (!isAdmin(loginUser)) {
putMsg(result, Status.NO_CURRENT_OPERATING_PERMISSION);
return result;
}
// check exist
User tempUser = userMapper.selectById(userId);
if (tempUser == null) {
putMsg(result, Status.USER_NOT_EXIST, userId);
return result;
}
if (check(result, StringUtils.isEmpty(projectIds), Status.SUCCESS)) {
return result;
}
Arrays.stream(projectIds.split(Constants.COMMA)).distinct().forEach(projectId -> {
ProjectUser projectUserOld = projectUserMapper.queryProjectRelation(Integer.parseInt(projectId), userId);
if (projectUserOld != null) {
projectUserMapper.deleteProjectRelation(Integer.parseInt(projectId), userId);
}
Date now = new Date();
ProjectUser projectUser = new ProjectUser();
projectUser.setUserId(userId);
projectUser.setProjectId(Integer.parseInt(projectId));
projectUser.setPerm(Constants.READ_PERMISSION);
projectUser.setCreateTime(now);
projectUser.setUpdateTime(now);
projectUserMapper.insert(projectUser);
});
putMsg(result, Status.SUCCESS);
return result;
}
/**
* grant project
*
* @param loginUser login user
* @param userId user id
* @param projectIds project id array
* @return grant result code
*/
@Override
@Transactional
public Map<String, Object> grantProject(User loginUser, int userId, String projectIds) {
Map<String, Object> result = new HashMap<>();
result.put(Constants.STATUS, false);
if (resourcePermissionCheckService.functionDisabled()) {
putMsg(result, Status.FUNCTION_DISABLED);
return result;
}
// check exist
User tempUser = userMapper.selectById(userId);
if (tempUser == null) {
log.error("User does not exist, userId:{}.", userId);
putMsg(result, Status.USER_NOT_EXIST, userId);
return result;
}
if (!isAdmin(loginUser)) {
putMsg(result, Status.NO_CURRENT_OPERATING_PERMISSION);
return result;
}
if (check(result, StringUtils.isEmpty(projectIds), Status.SUCCESS)) {
log.warn("Parameter projectIds is empty.");
return result;
}
Arrays.stream(projectIds.split(",")).distinct().forEach(projectId -> {
ProjectUser projectUserOld = projectUserMapper.queryProjectRelation(Integer.parseInt(projectId), userId);
if (projectUserOld != null) {
projectUserMapper.deleteProjectRelation(Integer.parseInt(projectId), userId);
}
Date now = new Date();
ProjectUser projectUser = new ProjectUser();
projectUser.setUserId(userId);
projectUser.setProjectId(Integer.parseInt(projectId));
projectUser.setPerm(Constants.AUTHORIZE_WRITABLE_PERM);
projectUser.setCreateTime(now);
projectUser.setUpdateTime(now);
projectUserMapper.insert(projectUser);
});
putMsg(result, Status.SUCCESS);
return result;
}
/**
* grant project by code
*
* @param loginUser login user
* @param userId user id
* @param projectCode project code
* @return grant result code
*/
@Override
public Map<String, Object> grantProjectByCode(final User loginUser, final int userId, final long projectCode) {
Map<String, Object> result = new HashMap<>();
result.put(Constants.STATUS, false);
if (resourcePermissionCheckService.functionDisabled()) {
putMsg(result, Status.FUNCTION_DISABLED);
return result;
}
// 1. check if user is existed
User tempUser = this.userMapper.selectById(userId);
if (tempUser == null) {
log.error("User does not exist, userId:{}.", userId);
this.putMsg(result, Status.USER_NOT_EXIST, userId);
return result;
}
// 2. check if project is existed
Project project = this.projectMapper.queryByCode(projectCode);
if (project == null) {
log.error("Project does not exist, projectCode:{}.", projectCode);
this.putMsg(result, Status.PROJECT_NOT_FOUND, projectCode);
return result;
}
// 3. only project owner can operate
if (!this.canOperator(loginUser, project.getUserId())) {
log.warn("User does not have permission for project, userId:{}, userName:{}, projectCode:{}.",
loginUser.getId(), loginUser.getUserName(), projectCode);
this.putMsg(result, Status.USER_NO_OPERATION_PERM);
return result;
}
// 4. maintain the relationship between project and user if not exists
ProjectUser projectUser = projectUserMapper.queryProjectRelation(project.getId(), userId);
if (projectUser == null) {
Date today = new Date();
projectUser = new ProjectUser();
projectUser.setUserId(userId);
projectUser.setProjectId(project.getId());
projectUser.setPerm(Constants.AUTHORIZE_WRITABLE_PERM);
projectUser.setCreateTime(today);
projectUser.setUpdateTime(today);
this.projectUserMapper.insert(projectUser);
}
log.info("User is granted permission for projects, userId:{}, projectCode:{}.", userId, projectCode);
this.putMsg(result, Status.SUCCESS);
return result;
}
/**
* revoke the project permission for specified user.
*
* @param loginUser Login user
* @param userId User id
* @param projectCode Project Code
* @return
*/
@Override
public Map<String, Object> revokeProject(User loginUser, int userId, long projectCode) {
Map<String, Object> result = new HashMap<>();
result.put(Constants.STATUS, false);
if (resourcePermissionCheckService.functionDisabled()) {
putMsg(result, Status.FUNCTION_DISABLED);
return result;
}
// 1. only admin can operate
if (this.check(result, !this.isAdmin(loginUser), Status.USER_NO_OPERATION_PERM)) {
log.warn("Only admin can revoke the project permission.");
return result;
}
// 2. check if user is existed
User user = this.userMapper.selectById(userId);
if (user == null) {
log.error("User does not exist, userId:{}.", userId);
this.putMsg(result, Status.USER_NOT_EXIST, userId);
return result;
}
// 3. check if project is existed
Project project = this.projectMapper.queryByCode(projectCode);
if (project == null) {
log.error("Project does not exist, projectCode:{}.", projectCode);
this.putMsg(result, Status.PROJECT_NOT_FOUND, projectCode);
return result;
}
// 4. delete th relationship between project and user
this.projectUserMapper.deleteProjectRelation(project.getId(), user.getId());
log.info("User is revoked permission for projects, userId:{}, projectCode:{}.", userId, projectCode);
this.putMsg(result, Status.SUCCESS);
return result;
}
/**
* grant udf function
*
* @param loginUser login user
* @param userId user id
* @param udfIds udf id array
* @return grant result code
*/
@Override
@Transactional
public Map<String, Object> grantUDFFunction(User loginUser, int userId, String udfIds) {
Map<String, Object> result = new HashMap<>();
if (resourcePermissionCheckService.functionDisabled()) {
putMsg(result, Status.FUNCTION_DISABLED);
return result;
}
User user = userMapper.selectById(userId);
if (user == null) {
log.error("User does not exist, userId:{}.", userId);
putMsg(result, Status.USER_NOT_EXIST, userId);
return result;
}
if (!isAdmin(loginUser)) {
putMsg(result, Status.NO_CURRENT_OPERATING_PERMISSION);
return result;
}
udfUserMapper.deleteByUserId(userId);
if (check(result, StringUtils.isEmpty(udfIds), Status.SUCCESS)) {
log.warn("Parameter udfIds is empty.");
return result;
}
String[] resourcesIdArr = udfIds.split(",");
for (String udfId : resourcesIdArr) {
Date now = new Date();
UDFUser udfUser = new UDFUser();
udfUser.setUserId(userId);
udfUser.setUdfId(Integer.parseInt(udfId));
udfUser.setPerm(Constants.AUTHORIZE_WRITABLE_PERM);
udfUser.setCreateTime(now);
udfUser.setUpdateTime(now);
udfUserMapper.insert(udfUser);
}
log.info("User is granted permission for UDF, userName:{}.", user.getUserName());
putMsg(result, Status.SUCCESS);
return result;
}
/**
* grant namespace
*
* @param loginUser login user
* @param userId user id
* @param namespaceIds namespace id array
* @return grant result code
*/
@Override
@Transactional
public Map<String, Object> grantNamespaces(User loginUser, int userId, String namespaceIds) {
Map<String, Object> result = new HashMap<>();
result.put(Constants.STATUS, false);
if (resourcePermissionCheckService.functionDisabled()) {
putMsg(result, Status.FUNCTION_DISABLED);
return result;
}
// only admin can operate
if (this.check(result, !this.isAdmin(loginUser), Status.USER_NO_OPERATION_PERM)) {
log.warn("Only admin can grant namespaces.");
return result;
}
// check exist
User tempUser = userMapper.selectById(userId);
if (tempUser == null) {
log.error("User does not exist, userId:{}.", userId);
putMsg(result, Status.USER_NOT_EXIST, userId);
return result;
}
k8sNamespaceUserMapper.deleteNamespaceRelation(0, userId);
if (StringUtils.isNotEmpty(namespaceIds)) {
String[] namespaceIdArr = namespaceIds.split(",");
for (String namespaceId : namespaceIdArr) {
Date now = new Date();
K8sNamespaceUser namespaceUser = new K8sNamespaceUser();
namespaceUser.setUserId(userId);
namespaceUser.setNamespaceId(Integer.parseInt(namespaceId));
namespaceUser.setPerm(7);
namespaceUser.setCreateTime(now);
namespaceUser.setUpdateTime(now);
k8sNamespaceUserMapper.insert(namespaceUser);
}
}
log.info("User is granted permission for namespace, userId:{}.", tempUser.getId());
putMsg(result, Status.SUCCESS);
return result;
}
/**
* grant datasource
*
* @param loginUser login user
* @param userId user id
* @param datasourceIds data source id array
* @return grant result code
*/
@Override
@Transactional
public Map<String, Object> grantDataSource(User loginUser, int userId, String datasourceIds) {
Map<String, Object> result = new HashMap<>();
result.put(Constants.STATUS, false);
if (resourcePermissionCheckService.functionDisabled()) {
putMsg(result, Status.FUNCTION_DISABLED);
return result;
}
User user = userMapper.selectById(userId);
if (user == null) {
putMsg(result, Status.USER_NOT_EXIST, userId);
return result;
}
datasourceUserMapper.deleteByUserId(userId);
if (check(result, StringUtils.isEmpty(datasourceIds), Status.SUCCESS)) {
return result;
}
String[] datasourceIdArr = datasourceIds.split(",");
for (String datasourceId : datasourceIdArr) {
Date now = new Date();
DatasourceUser datasourceUser = new DatasourceUser();
datasourceUser.setUserId(userId);
datasourceUser.setDatasourceId(Integer.parseInt(datasourceId));
datasourceUser.setPerm(Constants.AUTHORIZE_WRITABLE_PERM);
datasourceUser.setCreateTime(now);
datasourceUser.setUpdateTime(now);
datasourceUserMapper.insert(datasourceUser);
}
putMsg(result, Status.SUCCESS);
return result;
}
/**
* query user info
*
* @param loginUser login user
* @return user info
*/
@Override
public Map<String, Object> getUserInfo(User loginUser) {
Map<String, Object> result = new HashMap<>();
if (resourcePermissionCheckService.functionDisabled()) {
putMsg(result, Status.FUNCTION_DISABLED);
return result;
}
User user = null;
if (loginUser.getUserType() == UserType.ADMIN_USER) {
user = loginUser;
} else {
user = userMapper.queryDetailsById(loginUser.getId());
List<AlertGroup> alertGroups = alertGroupMapper.queryByUserId(loginUser.getId());
StringBuilder sb = new StringBuilder();
if (alertGroups != null && !alertGroups.isEmpty()) {
for (int i = 0; i < alertGroups.size() - 1; i++) {
sb.append(alertGroups.get(i).getGroupName()).append(",");
}
sb.append(alertGroups.get(alertGroups.size() - 1));
user.setAlertGroup(sb.toString());
}
}
Tenant tenant = tenantMapper.selectById(user.getTenantId());
if (tenant != null) {
user.setTenantCode(tenant.getTenantCode());
}
// add system default timezone if not user timezone
if (StringUtils.isEmpty(user.getTimeZone())) {
user.setTimeZone(TimeZone.getDefault().toZoneId().getId());
}
// remove password
user.setUserPassword(null);
result.put(Constants.DATA_LIST, user);
putMsg(result, Status.SUCCESS);
return result;
}
/**
* query user list
*
* @param loginUser login user
* @return user list
*/
@Override
public Map<String, Object> queryAllGeneralUsers(User loginUser) {
Map<String, Object> result = new HashMap<>();
if (resourcePermissionCheckService.functionDisabled()) {
putMsg(result, Status.FUNCTION_DISABLED);
return result;
}
// only admin can operate
if (check(result, !isAdmin(loginUser), Status.USER_NO_OPERATION_PERM)) {
log.warn("Only admin can query all general users.");
return result;
}
List<User> userList = userMapper.queryAllGeneralUser();
result.put(Constants.DATA_LIST, userList);
putMsg(result, Status.SUCCESS);
return result;
}
/**
* query user list
*
* @param loginUser login user
* @return user list
*/
@Override
public Map<String, Object> queryUserList(User loginUser) {
Map<String, Object> result = new HashMap<>();
// only admin can operate
if (!canOperatorPermissions(loginUser, null, AuthorizationType.ACCESS_TOKEN, USER_MANAGER)) {
putMsg(result, Status.USER_NO_OPERATION_PERM);
return result;
}
List<User> userList = userMapper.queryEnabledUsers();
result.put(Constants.DATA_LIST, userList);
putMsg(result, Status.SUCCESS);
return result;
}
/**
* verify user name exists
*
* @param userName user name
* @return true if user name not exists, otherwise return false
*/
@Override
public Result<Object> verifyUserName(String userName) {
Result<Object> result = new Result<>();
User user = userMapper.queryByUserNameAccurately(userName);
if (user != null) {
putMsg(result, Status.USER_NAME_EXIST);
} else {
putMsg(result, Status.SUCCESS);
}
return result;
}
/**
* unauthorized user
*
* @param loginUser login user
* @param alertgroupId alert group id
* @return unauthorize result code
*/
@Override
public Map<String, Object> unauthorizedUser(User loginUser, Integer alertgroupId) {
Map<String, Object> result = new HashMap<>();
if (resourcePermissionCheckService.functionDisabled()) {
putMsg(result, Status.FUNCTION_DISABLED);
return result;
}
// only admin can operate
if (check(result, !isAdmin(loginUser), Status.USER_NO_OPERATION_PERM)) {
log.warn("Only admin can deauthorize user.");
return result;
}
List<User> userList = userMapper.selectList(null);
List<User> resultUsers = new ArrayList<>();
Set<User> userSet = null;
if (userList != null && !userList.isEmpty()) {
userSet = new HashSet<>(userList);
List<User> authedUserList = userMapper.queryUserListByAlertGroupId(alertgroupId);
Set<User> authedUserSet = null;
if (authedUserList != null && !authedUserList.isEmpty()) {
authedUserSet = new HashSet<>(authedUserList);
userSet.removeAll(authedUserSet);
}
resultUsers = new ArrayList<>(userSet);
}
result.put(Constants.DATA_LIST, resultUsers);
putMsg(result, Status.SUCCESS);
return result;
}
/**
* authorized user
*
* @param loginUser login user
* @param alertGroupId alert group id
* @return authorized result code
*/
@Override
public Map<String, Object> authorizedUser(User loginUser, Integer alertGroupId) {
Map<String, Object> result = new HashMap<>();
if (resourcePermissionCheckService.functionDisabled()) {
putMsg(result, Status.FUNCTION_DISABLED);
return result;
}
// only admin can operate
if (check(result, !isAdmin(loginUser), Status.USER_NO_OPERATION_PERM)) {
log.warn("Only admin can authorize user.");
return result;
}
List<User> userList = userMapper.queryUserListByAlertGroupId(alertGroupId);
result.put(Constants.DATA_LIST, userList);
putMsg(result, Status.SUCCESS);
return result;
}
/**
* @param tenantId tenant id
* @return true if tenant exists, otherwise return false
*/
private boolean checkTenantExists(int tenantId) {
return tenantMapper.queryById(tenantId) != null;
}
/**
* @return if check failed return the field, otherwise return null
*/
private String checkUserParams(String userName, String password, String email, String phone) {
String msg = null;
if (!CheckUtils.checkUserName(userName)) {
log.warn("Parameter userName check failed.");
msg = userName;
} else if (!CheckUtils.checkPassword(password)) {
log.warn("Parameter password check failed.");
msg = password;
} else if (!CheckUtils.checkEmail(email)) {
log.warn("Parameter email check failed.");
msg = email;
} else if (!CheckUtils.checkPhone(phone)) {
log.warn("Parameter phone check failed.");
msg = phone;
}
return msg;
}
/**
* copy resource files
* xxx unchecked
*
* @param resourceComponent resource component
* @param srcBasePath src base path
* @param dstBasePath dst base path
* @throws IOException io exception
*/
private void copyResourceFiles(String oldTenantCode, String newTenantCode, ResourceComponent resourceComponent,
String srcBasePath, String dstBasePath) {
List<ResourceComponent> components = resourceComponent.getChildren();
try {
if (CollectionUtils.isNotEmpty(components)) {
for (ResourceComponent component : components) {
// verify whether exist
if (!storageOperate.exists(
String.format(Constants.FORMAT_S_S, srcBasePath, component.getFullName()))) {
log.error("Resource file: {} does not exist, copy error.", component.getFullName());
throw new ServiceException(Status.RESOURCE_NOT_EXIST);
}
if (!component.isDirctory()) {
// copy it to dst
storageOperate.copy(String.format(Constants.FORMAT_S_S, srcBasePath, component.getFullName()),
String.format(Constants.FORMAT_S_S, dstBasePath, component.getFullName()), false, true);
continue;
}
if (CollectionUtils.isEmpty(component.getChildren())) {
// if not exist,need create it
if (!storageOperate
.exists(String.format(Constants.FORMAT_S_S, dstBasePath, component.getFullName()))) {
storageOperate.mkdir(newTenantCode,
String.format(Constants.FORMAT_S_S, dstBasePath, component.getFullName()));
}
} else {
copyResourceFiles(oldTenantCode, newTenantCode, component, srcBasePath, dstBasePath);
}
}
}
} catch (IOException e) {
log.error("copy the resources failed,the error message is {}", e.getMessage());
}
}
/**
* registry user, default state is 0, default tenant_id is 1, no phone, no queue
*
* @param userName user name
* @param userPassword user password
* @param repeatPassword repeat password
* @param email email
* @return registry result code
* @throws Exception exception
*/
@Override
@Transactional
public Map<String, Object> registerUser(String userName, String userPassword, String repeatPassword, String email) {
Map<String, Object> result = new HashMap<>();
// check user params
String msg = this.checkUserParams(userName, userPassword, email, "");
if (resourcePermissionCheckService.functionDisabled()) {
putMsg(result, Status.FUNCTION_DISABLED);
return result;
}
if (!StringUtils.isEmpty(msg)) {
putMsg(result, Status.REQUEST_PARAMS_NOT_VALID_ERROR, msg);
return result;
}
if (!userPassword.equals(repeatPassword)) {
putMsg(result, Status.REQUEST_PARAMS_NOT_VALID_ERROR, "two passwords are not same");
return result;
}
User user = createUser(userName, userPassword, email, -1, "", "", Flag.NO.ordinal());
putMsg(result, Status.SUCCESS);
result.put(Constants.DATA_LIST, user);
return result;
}
/**
* activate user, only system admin have permission, change user state code 0 to 1
*
* @param loginUser login user
* @param userName user name
* @return create result code
*/
@Override
public Map<String, Object> activateUser(User loginUser, String userName) {
Map<String, Object> result = new HashMap<>();
result.put(Constants.STATUS, false);
if (resourcePermissionCheckService.functionDisabled()) {
putMsg(result, Status.FUNCTION_DISABLED);
return result;
}
if (!isAdmin(loginUser)) {
putMsg(result, Status.USER_NO_OPERATION_PERM);
return result;
}
if (!CheckUtils.checkUserName(userName)) {
putMsg(result, Status.REQUEST_PARAMS_NOT_VALID_ERROR, userName);
return result;
}
User user = userMapper.queryByUserNameAccurately(userName);
if (user == null) {
putMsg(result, Status.USER_NOT_EXIST, userName);
return result;
}
if (user.getState() != Flag.NO.ordinal()) {
putMsg(result, Status.REQUEST_PARAMS_NOT_VALID_ERROR, userName);
return result;
}
user.setState(Flag.YES.ordinal());
Date now = new Date();
user.setUpdateTime(now);
userMapper.updateById(user);
User responseUser = userMapper.queryByUserNameAccurately(userName);
putMsg(result, Status.SUCCESS);
result.put(Constants.DATA_LIST, responseUser);
return result;
}
/**
* activate user, only system admin have permission, change users state code 0 to 1
*
* @param loginUser login user
* @param userNames user name
* @return create result code
*/
@Override
public Map<String, Object> batchActivateUser(User loginUser, List<String> userNames) {
Map<String, Object> result = new HashMap<>();
if (resourcePermissionCheckService.functionDisabled()) {
putMsg(result, Status.FUNCTION_DISABLED);
return result;
}
if (!isAdmin(loginUser)) {
putMsg(result, Status.USER_NO_OPERATION_PERM);
return result;
}
int totalSuccess = 0;
List<String> successUserNames = new ArrayList<>();
Map<String, Object> successRes = new HashMap<>();
int totalFailed = 0;
List<Map<String, String>> failedInfo = new ArrayList<>();
Map<String, Object> failedRes = new HashMap<>();
for (String userName : userNames) {
Map<String, Object> tmpResult = activateUser(loginUser, userName);
if (tmpResult.get(Constants.STATUS) != Status.SUCCESS) {
totalFailed++;
Map<String, String> failedBody = new HashMap<>();
failedBody.put("userName", userName);
Status status = (Status) tmpResult.get(Constants.STATUS);
String errorMessage = MessageFormat.format(status.getMsg(), userName);
failedBody.put("msg", errorMessage);
failedInfo.add(failedBody);
} else {
totalSuccess++;
successUserNames.add(userName);
}
}
successRes.put("sum", totalSuccess);
successRes.put("userName", successUserNames);
failedRes.put("sum", totalFailed);
failedRes.put("info", failedInfo);
Map<String, Object> res = new HashMap<>();
res.put("success", successRes);
res.put("failed", failedRes);
putMsg(result, Status.SUCCESS);
result.put(Constants.DATA_LIST, res);
return result;
}
/**
* Make sure user with given name exists, and create the user if not exists
* <p>
* ONLY for python gateway server, and should not use this in web ui function
*
* @param userName user name
* @param userPassword user password
* @param email user email
* @param phone user phone
* @param tenantCode tenant code
* @param queue queue
* @param state state
* @return create result code
*/
@Override
@Transactional
public User createUserIfNotExists(String userName,
String userPassword,
String email,
String phone,
String tenantCode,
String queue,
int state) {
User user = userMapper.queryByUserNameAccurately(userName);
if (Objects.isNull(user)) {
Tenant tenant = tenantMapper.queryByTenantCode(tenantCode);
user = createUser(userName, userPassword, email, tenant.getId(), phone, queue, state);
return user;
}
updateUser(user, user.getId(), userName, userPassword, email, user.getTenantId(), phone, queue, state, null);
user = userMapper.queryDetailsById(user.getId());
return user;
}
}