break60 4 years ago
parent
commit
0f2684c00b
  1. 2
      dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/security/AuthenticationType.java
  2. 5
      dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/security/Authenticator.java
  3. 9
      dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/security/SecurityConfig.java
  4. 35
      dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/security/impl/AbstractAuthenticator.java
  5. 45
      dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/security/impl/ldap/LdapAuthenticator.java
  6. 133
      dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/security/impl/ldap/LdapService.java
  7. 34
      dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/security/impl/pwd/PasswordAuthenticator.java
  8. 166
      dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/UsersService.java
  9. 14
      dolphinscheduler-api/src/main/resources/application-api.properties
  10. 45
      dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/security/SecurityConfigLDAPTest.java
  11. 4
      dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/security/SecurityConfigPasswordTest.java
  12. 142
      dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/security/impl/ldap/LdapAuthenticatorTest.java
  13. 81
      dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/security/impl/ldap/LdapServiceTest.java
  14. 24
      dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/security/impl/pwd/PasswordAuthenticatorTest.java
  15. 156
      dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/UsersServiceTest.java
  16. 2
      dolphinscheduler-dao/src/main/resources/org/apache/dolphinscheduler/dao/mapper/AccessTokenMapper.xml
  17. 99
      dolphinscheduler-dao/src/main/resources/org/apache/dolphinscheduler/dao/mapper/UdfFuncMapper.xml
  18. 30
      dolphinscheduler-server/src/main/java/org/apache/dolphinscheduler/server/utils/ArgsUtils.java
  19. 5
      dolphinscheduler-server/src/main/java/org/apache/dolphinscheduler/server/utils/FlinkArgsUtils.java
  20. 6
      dolphinscheduler-server/src/main/java/org/apache/dolphinscheduler/server/utils/LogUtils.java
  21. 14
      dolphinscheduler-server/src/main/java/org/apache/dolphinscheduler/server/utils/ProcessUtils.java
  22. 13
      dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/formModel/tasks/flink.vue
  23. 2
      dolphinscheduler-ui/src/js/module/i18n/locale/en_US.js
  24. 2
      dolphinscheduler-ui/src/js/module/i18n/locale/zh_CN.js
  25. 6
      pom.xml

2
dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/security/AuthenticationType.java

@ -14,6 +14,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.apache.dolphinscheduler.api.security; package org.apache.dolphinscheduler.api.security;
import com.baomidou.mybatisplus.annotation.EnumValue; import com.baomidou.mybatisplus.annotation.EnumValue;
@ -24,6 +25,7 @@ import com.baomidou.mybatisplus.annotation.EnumValue;
public enum AuthenticationType { public enum AuthenticationType {
PASSWORD(0, "verify via user name and password"), PASSWORD(0, "verify via user name and password"),
LDAP(1, "verify via LDAP server"),
; ;
AuthenticationType(int code, String desc) { AuthenticationType(int code, String desc) {

5
dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/security/Authenticator.java

@ -14,13 +14,16 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.apache.dolphinscheduler.api.security; package org.apache.dolphinscheduler.api.security;
import org.apache.dolphinscheduler.api.utils.Result; import org.apache.dolphinscheduler.api.utils.Result;
import org.apache.dolphinscheduler.dao.entity.User; import org.apache.dolphinscheduler.dao.entity.User;
import javax.servlet.http.HttpServletRequest;
import java.util.Map; import java.util.Map;
import javax.servlet.http.HttpServletRequest;
public interface Authenticator { public interface Authenticator {
/** /**
* Verifying legality via username and password * Verifying legality via username and password

9
dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/security/SecurityConfig.java

@ -14,9 +14,13 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.apache.dolphinscheduler.api.security; package org.apache.dolphinscheduler.api.security;
import org.apache.commons.lang.StringUtils; import org.apache.dolphinscheduler.api.security.impl.ldap.LdapAuthenticator;
import org.apache.dolphinscheduler.api.security.impl.pwd.PasswordAuthenticator;
import org.apache.dolphinscheduler.common.utils.StringUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@ -58,6 +62,9 @@ public class SecurityConfig {
case PASSWORD: case PASSWORD:
authenticator = new PasswordAuthenticator(); authenticator = new PasswordAuthenticator();
break; break;
case LDAP:
authenticator = new LdapAuthenticator();
break;
default: default:
throw new IllegalStateException("Unexpected value: " + authenticationType); throw new IllegalStateException("Unexpected value: " + authenticationType);
} }

35
dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/security/PasswordAuthenticator.java → dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/security/impl/AbstractAuthenticator.java

@ -14,9 +14,11 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.apache.dolphinscheduler.api.security;
package org.apache.dolphinscheduler.api.security.impl;
import org.apache.dolphinscheduler.api.enums.Status; import org.apache.dolphinscheduler.api.enums.Status;
import org.apache.dolphinscheduler.api.security.Authenticator;
import org.apache.dolphinscheduler.api.service.SessionService; import org.apache.dolphinscheduler.api.service.SessionService;
import org.apache.dolphinscheduler.api.service.UsersService; import org.apache.dolphinscheduler.api.service.UsersService;
import org.apache.dolphinscheduler.api.utils.Result; import org.apache.dolphinscheduler.api.utils.Result;
@ -24,26 +26,38 @@ import org.apache.dolphinscheduler.common.Constants;
import org.apache.dolphinscheduler.common.enums.Flag; import org.apache.dolphinscheduler.common.enums.Flag;
import org.apache.dolphinscheduler.dao.entity.Session; import org.apache.dolphinscheduler.dao.entity.Session;
import org.apache.dolphinscheduler.dao.entity.User; import org.apache.dolphinscheduler.dao.entity.User;
import java.util.Collections;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import javax.servlet.http.HttpServletRequest;
import java.util.Collections;
import java.util.Map;
public class PasswordAuthenticator implements Authenticator { public abstract class AbstractAuthenticator implements Authenticator {
private static final Logger logger = LoggerFactory.getLogger(PasswordAuthenticator.class); private static final Logger logger = LoggerFactory.getLogger(AbstractAuthenticator.class);
@Autowired @Autowired
private UsersService userService; private UsersService userService;
@Autowired @Autowired
private SessionService sessionService; private SessionService sessionService;
/**
* user login and return user in db
*
* @param userId user identity field
* @param password user login password
* @param extra extra user login field
* @return user object in databse
*/
public abstract User login(String userId, String password, String extra);
@Override @Override
public Result<Map<String, String>> authenticate(String username, String password, String extra) { public Result<Map<String, String>> authenticate(String userId, String password, String extra) {
Result<Map<String, String>> result = new Result<>(); Result<Map<String, String>> result = new Result<>();
// verify username and password User user = login(userId, password, extra);
User user = userService.queryUser(username, password);
if (user == null) { if (user == null) {
result.setCode(Status.USER_NAME_PASSWD_ERROR.getCode()); result.setCode(Status.USER_NAME_PASSWD_ERROR.getCode());
result.setMsg(Status.USER_NAME_PASSWD_ERROR.getMsg()); result.setMsg(Status.USER_NAME_PASSWD_ERROR.getMsg());
@ -64,7 +78,7 @@ public class PasswordAuthenticator implements Authenticator {
result.setMsg(Status.LOGIN_SESSION_FAILED.getMsg()); result.setMsg(Status.LOGIN_SESSION_FAILED.getMsg());
return result; return result;
} }
logger.info("sessionId : {}" , sessionId); logger.info("sessionId : {}", sessionId);
result.setData(Collections.singletonMap(Constants.SESSION_ID, sessionId)); result.setData(Collections.singletonMap(Constants.SESSION_ID, sessionId));
result.setCode(Status.SUCCESS.getCode()); result.setCode(Status.SUCCESS.getCode());
result.setMsg(Status.LOGIN_SUCCESS.getMsg()); result.setMsg(Status.LOGIN_SUCCESS.getMsg());
@ -81,4 +95,5 @@ public class PasswordAuthenticator implements Authenticator {
//get user object from session //get user object from session
return userService.queryUser(session.getUserId()); return userService.queryUser(session.getUserId());
} }
} }

45
dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/security/impl/ldap/LdapAuthenticator.java

@ -0,0 +1,45 @@
/*
* 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.security.impl.ldap;
import org.apache.dolphinscheduler.api.security.impl.AbstractAuthenticator;
import org.apache.dolphinscheduler.api.service.UsersService;
import org.apache.dolphinscheduler.dao.entity.User;
import org.springframework.beans.factory.annotation.Autowired;
public class LdapAuthenticator extends AbstractAuthenticator {
@Autowired
private UsersService usersService;
@Autowired
LdapService ldapService;
@Override
public User login(String userId, String password, String extra) {
User user = null;
String ldapEmail = ldapService.ldapLogin(userId, password);
if (ldapEmail != null) {
//check if user exist
user = usersService.getUserByUserName(userId);
if (user == null) {
user = usersService.createUser(ldapService.getUserType(userId), userId, ldapEmail);
}
}
return user;
}
}

133
dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/security/impl/ldap/LdapService.java

@ -0,0 +1,133 @@
/*
* 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.security.impl.ldap;
import org.apache.dolphinscheduler.common.enums.UserType;
import java.util.Properties;
import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.InitialDirContext;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import javax.naming.ldap.InitialLdapContext;
import javax.naming.ldap.LdapContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
@Component
@Configuration
public class LdapService {
private static final Logger logger = LoggerFactory.getLogger(LdapService.class);
@Value("${security.authentication.ldap.user.admin:null}")
private String adminUserId;
@Value("${ldap.urls:null}")
private String ldapUrls;
@Value("${ldap.base.dn:null}")
private String ldapBaseDn;
@Value("${ldap.username:null}")
private String ldapSecurityPrincipal;
@Value("${ldap.password:null}")
private String ldapPrincipalPassword;
@Value("${ldap.user.identity.attribute:null}")
private String ldapUserIdentifyingAttribute;
@Value("${ldap.user.email.attribute:null}")
private String ldapEmailAttribute;
/***
* get user type by configured admin userId
* @param userId login userId
* @return user type
*/
public UserType getUserType(String userId) {
return adminUserId.equalsIgnoreCase(userId) ? UserType.ADMIN_USER : UserType.GENERAL_USER;
}
/**
* login by userId and return user email
*
* @param userId user identity id
* @param userPwd user login password
* @return user email
*/
public String ldapLogin(String userId, String userPwd) {
Properties searchEnv = getManagerLdapEnv();
try {
//Connect to the LDAP server and Authenticate with a service user of whom we know the DN and credentials
LdapContext ctx = new InitialLdapContext(searchEnv, null);
SearchControls sc = new SearchControls();
sc.setReturningAttributes(new String[]{ldapEmailAttribute});
sc.setSearchScope(SearchControls.SUBTREE_SCOPE);
String searchFilter = String.format("(%s=%s)", ldapUserIdentifyingAttribute, userId);
//Search for the user you want to authenticate, search him with some attribute
NamingEnumeration<SearchResult> results = ctx.search(ldapBaseDn, searchFilter, sc);
if (results.hasMore()) {
// get the users DN (distinguishedName) from the result
SearchResult result = results.next();
NamingEnumeration attrs = result.getAttributes().getAll();
while (attrs.hasMore()) {
//Open another connection to the LDAP server with the found DN and the password
searchEnv.put(Context.SECURITY_PRINCIPAL, result.getNameInNamespace());
searchEnv.put(Context.SECURITY_CREDENTIALS, userPwd);
try {
new InitialDirContext(searchEnv);
} catch (Exception e) {
logger.warn("invalid ldap credentials or ldap search error", e);
return null;
}
Attribute attr = (Attribute) attrs.next();
if (attr.getID().equals(ldapEmailAttribute)) {
return (String) attr.get();
}
}
}
} catch (NamingException e) {
logger.error("ldap search error", e);
return null;
}
return null;
}
/***
* get ldap env fot ldap server search
* @return Properties
*/
Properties getManagerLdapEnv() {
Properties env = new Properties();
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, ldapSecurityPrincipal);
env.put(Context.SECURITY_CREDENTIALS, ldapPrincipalPassword);
env.put(Context.PROVIDER_URL, ldapUrls);
return env;
}
}

34
dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/security/impl/pwd/PasswordAuthenticator.java

@ -0,0 +1,34 @@
/*
* 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.security.impl.pwd;
import org.apache.dolphinscheduler.api.security.impl.AbstractAuthenticator;
import org.apache.dolphinscheduler.api.service.UsersService;
import org.apache.dolphinscheduler.dao.entity.User;
import org.springframework.beans.factory.annotation.Autowired;
public class PasswordAuthenticator extends AbstractAuthenticator {
@Autowired
private UsersService userService;
@Override
public User login(String userId, String password, String extra) {
return userService.queryUser(userId, password);
}
}

166
dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/UsersService.java

@ -14,10 +14,9 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.apache.dolphinscheduler.api.service; package org.apache.dolphinscheduler.api.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.dolphinscheduler.api.dto.resources.ResourceComponent; import org.apache.dolphinscheduler.api.dto.resources.ResourceComponent;
import org.apache.dolphinscheduler.api.dto.resources.visitor.ResourceTreeVisitor; import org.apache.dolphinscheduler.api.dto.resources.visitor.ResourceTreeVisitor;
import org.apache.dolphinscheduler.api.enums.Status; import org.apache.dolphinscheduler.api.enums.Status;
@ -29,20 +28,49 @@ import org.apache.dolphinscheduler.common.Constants;
import org.apache.dolphinscheduler.common.enums.Flag; import org.apache.dolphinscheduler.common.enums.Flag;
import org.apache.dolphinscheduler.common.enums.ResourceType; import org.apache.dolphinscheduler.common.enums.ResourceType;
import org.apache.dolphinscheduler.common.enums.UserType; import org.apache.dolphinscheduler.common.enums.UserType;
import org.apache.dolphinscheduler.common.utils.*; import org.apache.dolphinscheduler.common.utils.CollectionUtils;
import org.apache.dolphinscheduler.dao.entity.*; import org.apache.dolphinscheduler.common.utils.EncryptionUtils;
import org.apache.dolphinscheduler.dao.mapper.*; import org.apache.dolphinscheduler.common.utils.HadoopUtils;
import org.apache.dolphinscheduler.common.utils.PropertyUtils;
import org.apache.dolphinscheduler.common.utils.StringUtils;
import org.apache.dolphinscheduler.dao.entity.AlertGroup;
import org.apache.dolphinscheduler.dao.entity.DatasourceUser;
import org.apache.dolphinscheduler.dao.entity.ProjectUser;
import org.apache.dolphinscheduler.dao.entity.Resource;
import org.apache.dolphinscheduler.dao.entity.ResourcesUser;
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.AlertGroupMapper;
import org.apache.dolphinscheduler.dao.mapper.DataSourceUserMapper;
import org.apache.dolphinscheduler.dao.mapper.ProcessDefinitionMapper;
import org.apache.dolphinscheduler.dao.mapper.ProjectUserMapper;
import org.apache.dolphinscheduler.dao.mapper.ResourceMapper;
import org.apache.dolphinscheduler.dao.mapper.ResourceUserMapper;
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.dao.utils.ResourceProcessDefinitionUtils; import org.apache.dolphinscheduler.dao.utils.ResourceProcessDefinitionUtils;
import java.io.IOException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import java.io.IOException; import com.baomidou.mybatisplus.core.metadata.IPage;
import java.text.MessageFormat; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import java.util.*;
import java.util.stream.Collectors;
/** /**
* user service * user service
@ -109,7 +137,7 @@ public class UsersService extends BaseService {
String msg = this.checkUserParams(userName, userPassword, email, phone); String msg = this.checkUserParams(userName, userPassword, email, phone);
if (!StringUtils.isEmpty(msg)) { if (!StringUtils.isEmpty(msg)) {
putMsg(result, Status.REQUEST_PARAMS_NOT_VALID_ERROR,msg); putMsg(result, Status.REQUEST_PARAMS_NOT_VALID_ERROR, msg);
return result; return result;
} }
if (!isAdmin(loginUser)) { if (!isAdmin(loginUser)) {
@ -126,12 +154,12 @@ public class UsersService extends BaseService {
Tenant tenant = tenantMapper.queryById(tenantId); Tenant tenant = tenantMapper.queryById(tenantId);
// resource upload startup // resource upload startup
if (PropertyUtils.getResUploadStartupState()){ if (PropertyUtils.getResUploadStartupState()) {
// if tenant not exists // if tenant not exists
if (!HadoopUtils.getInstance().exists(HadoopUtils.getHdfsTenantDir(tenant.getTenantCode()))){ if (!HadoopUtils.getInstance().exists(HadoopUtils.getHdfsTenantDir(tenant.getTenantCode()))) {
createTenantDirIfNotExists(tenant.getTenantCode()); createTenantDirIfNotExists(tenant.getTenantCode());
} }
String userPath = HadoopUtils.getHdfsUserDir(tenant.getTenantCode(),user.getId()); String userPath = HadoopUtils.getHdfsUserDir(tenant.getTenantCode(), user.getId());
HadoopUtils.getInstance().mkdir(userPath); HadoopUtils.getInstance().mkdir(userPath);
} }
@ -161,7 +189,7 @@ public class UsersService extends BaseService {
user.setUserType(UserType.GENERAL_USER); user.setUserType(UserType.GENERAL_USER);
user.setCreateTime(now); user.setCreateTime(now);
user.setUpdateTime(now); user.setUpdateTime(now);
if (StringUtils.isEmpty(queue)){ if (StringUtils.isEmpty(queue)) {
queue = ""; queue = "";
} }
user.setQueue(queue); user.setQueue(queue);
@ -171,8 +199,40 @@ public class UsersService extends BaseService {
return user; return user;
} }
/***
* create User for ldap login
*/
@Transactional(rollbackFor = Exception.class)
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.setQueue("");
// save user
userMapper.insert(user);
return user;
}
/**
* get user by user name
*
* @param userName user name
* @return exist user or null
*/
public User getUserByUserName(String userName) {
return userMapper.queryByUserNameAccurately(userName);
}
/** /**
* query user by id * query user by id
*
* @param id id * @param id id
* @return user info * @return user info
*/ */
@ -182,6 +242,7 @@ public class UsersService extends BaseService {
/** /**
* query user * query user
*
* @param name name * @param name name
* @return user info * @return user info
*/ */
@ -203,6 +264,7 @@ public class UsersService extends BaseService {
/** /**
* get user id by user name * get user id by user name
*
* @param name user name * @param name user name
* @return if name empty 0, user not exists -1, user exist user id * @return if name empty 0, user not exists -1, user exist user id
*/ */
@ -242,7 +304,7 @@ public class UsersService extends BaseService {
IPage<User> scheduleList = userMapper.queryUserPaging(page, searchVal); IPage<User> scheduleList = userMapper.queryUserPaging(page, searchVal);
PageInfo<User> pageInfo = new PageInfo<>(pageNo, pageSize); PageInfo<User> pageInfo = new PageInfo<>(pageNo, pageSize);
pageInfo.setTotalCount((int)scheduleList.getTotal()); pageInfo.setTotalCount((int) scheduleList.getTotal());
pageInfo.setLists(scheduleList.getRecords()); pageInfo.setLists(scheduleList.getRecords());
result.put(Constants.DATA_LIST, pageInfo); result.put(Constants.DATA_LIST, pageInfo);
putMsg(result, Status.SUCCESS); putMsg(result, Status.SUCCESS);
@ -286,8 +348,8 @@ public class UsersService extends BaseService {
} }
if (StringUtils.isNotEmpty(userName)) { if (StringUtils.isNotEmpty(userName)) {
if (!CheckUtils.checkUserName(userName)){ if (!CheckUtils.checkUserName(userName)) {
putMsg(result, Status.REQUEST_PARAMS_NOT_VALID_ERROR,userName); putMsg(result, Status.REQUEST_PARAMS_NOT_VALID_ERROR, userName);
return result; return result;
} }
@ -300,23 +362,23 @@ public class UsersService extends BaseService {
} }
if (StringUtils.isNotEmpty(userPassword)) { if (StringUtils.isNotEmpty(userPassword)) {
if (!CheckUtils.checkPassword(userPassword)){ if (!CheckUtils.checkPassword(userPassword)) {
putMsg(result, Status.REQUEST_PARAMS_NOT_VALID_ERROR,userPassword); putMsg(result, Status.REQUEST_PARAMS_NOT_VALID_ERROR, userPassword);
return result; return result;
} }
user.setUserPassword(EncryptionUtils.getMd5(userPassword)); user.setUserPassword(EncryptionUtils.getMd5(userPassword));
} }
if (StringUtils.isNotEmpty(email)) { if (StringUtils.isNotEmpty(email)) {
if (!CheckUtils.checkEmail(email)){ if (!CheckUtils.checkEmail(email)) {
putMsg(result, Status.REQUEST_PARAMS_NOT_VALID_ERROR,email); putMsg(result, Status.REQUEST_PARAMS_NOT_VALID_ERROR, email);
return result; return result;
} }
user.setEmail(email); user.setEmail(email);
} }
if (StringUtils.isNotEmpty(phone) && !CheckUtils.checkPhone(phone)) { if (StringUtils.isNotEmpty(phone) && !CheckUtils.checkPhone(phone)) {
putMsg(result, Status.REQUEST_PARAMS_NOT_VALID_ERROR,phone); putMsg(result, Status.REQUEST_PARAMS_NOT_VALID_ERROR, phone);
return result; return result;
} }
user.setPhone(phone); user.setPhone(phone);
@ -332,13 +394,13 @@ public class UsersService extends BaseService {
Tenant newTenant = tenantMapper.queryById(tenantId); Tenant newTenant = tenantMapper.queryById(tenantId);
if (newTenant != null) { if (newTenant != null) {
// if hdfs startup // if hdfs startup
if (PropertyUtils.getResUploadStartupState() && oldTenant != null){ if (PropertyUtils.getResUploadStartupState() && oldTenant != null) {
String newTenantCode = newTenant.getTenantCode(); String newTenantCode = newTenant.getTenantCode();
String oldResourcePath = HadoopUtils.getHdfsResDir(oldTenant.getTenantCode()); String oldResourcePath = HadoopUtils.getHdfsResDir(oldTenant.getTenantCode());
String oldUdfsPath = HadoopUtils.getHdfsUdfDir(oldTenant.getTenantCode()); String oldUdfsPath = HadoopUtils.getHdfsUdfDir(oldTenant.getTenantCode());
// if old tenant dir exists // if old tenant dir exists
if (HadoopUtils.getInstance().exists(oldResourcePath)){ if (HadoopUtils.getInstance().exists(oldResourcePath)) {
String newResourcePath = HadoopUtils.getHdfsResDir(newTenantCode); String newResourcePath = HadoopUtils.getHdfsResDir(newTenantCode);
String newUdfsPath = HadoopUtils.getHdfsUdfDir(newTenantCode); String newUdfsPath = HadoopUtils.getHdfsUdfDir(newTenantCode);
@ -361,18 +423,18 @@ public class UsersService extends BaseService {
} }
//Delete the user from the old tenant directory //Delete the user from the old tenant directory
String oldUserPath = HadoopUtils.getHdfsUserDir(oldTenant.getTenantCode(),userId); String oldUserPath = HadoopUtils.getHdfsUserDir(oldTenant.getTenantCode(), userId);
HadoopUtils.getInstance().delete(oldUserPath, true); HadoopUtils.getInstance().delete(oldUserPath, true);
}else { } else {
// if old tenant dir not exists , create // if old tenant dir not exists , create
createTenantDirIfNotExists(oldTenant.getTenantCode()); createTenantDirIfNotExists(oldTenant.getTenantCode());
} }
if (HadoopUtils.getInstance().exists(HadoopUtils.getHdfsTenantDir(newTenant.getTenantCode()))){ if (HadoopUtils.getInstance().exists(HadoopUtils.getHdfsTenantDir(newTenant.getTenantCode()))) {
//create user in the new tenant directory //create user in the new tenant directory
String newUserPath = HadoopUtils.getHdfsUserDir(newTenant.getTenantCode(),user.getId()); String newUserPath = HadoopUtils.getHdfsUserDir(newTenant.getTenantCode(), user.getId());
HadoopUtils.getInstance().mkdir(newUserPath); HadoopUtils.getInstance().mkdir(newUserPath);
}else { } else {
// if new tenant dir not exists , create // if new tenant dir not exists , create
createTenantDirIfNotExists(newTenant.getTenantCode()); createTenantDirIfNotExists(newTenant.getTenantCode());
} }
@ -414,7 +476,7 @@ public class UsersService extends BaseService {
if (user != null) { if (user != null) {
if (PropertyUtils.getResUploadStartupState()) { if (PropertyUtils.getResUploadStartupState()) {
String userPath = HadoopUtils.getHdfsUserDir(user.getTenantCode(),id); String userPath = HadoopUtils.getHdfsUserDir(user.getTenantCode(), id);
if (HadoopUtils.getInstance().exists(userPath)) { if (HadoopUtils.getInstance().exists(userPath)) {
HadoopUtils.getInstance().delete(userPath, true); HadoopUtils.getInstance().delete(userPath, true);
} }
@ -493,7 +555,7 @@ public class UsersService extends BaseService {
return result; return result;
} }
User user = userMapper.selectById(userId); User user = userMapper.selectById(userId);
if(user == null){ if (user == null) {
putMsg(result, Status.USER_NOT_EXIST, userId); putMsg(result, Status.USER_NOT_EXIST, userId);
return result; return result;
} }
@ -504,7 +566,7 @@ public class UsersService extends BaseService {
// need authorize resource id set // need authorize resource id set
for (String resourceFullId : resourceFullIdArr) { for (String resourceFullId : resourceFullIdArr) {
String[] resourceIdArr = resourceFullId.split("-"); String[] resourceIdArr = resourceFullId.split("-");
for (int i=0;i<=resourceIdArr.length-1;i++) { for (int i = 0; i <= resourceIdArr.length - 1; i++) {
int resourceIdValue = Integer.parseInt(resourceIdArr[i]); int resourceIdValue = Integer.parseInt(resourceIdArr[i]);
needAuthorizeResIds.add(resourceIdValue); needAuthorizeResIds.add(resourceIdValue);
} }
@ -531,7 +593,7 @@ public class UsersService extends BaseService {
if (CollectionUtils.isNotEmpty(resourceIdSet)) { if (CollectionUtils.isNotEmpty(resourceIdSet)) {
logger.error("can't be deleted,because it is used of process definition"); logger.error("can't be deleted,because it is used of process definition");
for (Integer resId : resourceIdSet) { for (Integer resId : resourceIdSet) {
logger.error("resource id:{} is used of process definition {}",resId,resourceProcessMap.get(resId)); logger.error("resource id:{} is used of process definition {}", resId, resourceProcessMap.get(resId));
} }
putMsg(result, Status.RESOURCE_IS_USED); putMsg(result, Status.RESOURCE_IS_USED);
return result; return result;
@ -558,7 +620,7 @@ public class UsersService extends BaseService {
resourcesUser.setResourcesId(resourceIdValue); resourcesUser.setResourcesId(resourceIdValue);
if (resource.isDirectory()) { if (resource.isDirectory()) {
resourcesUser.setPerm(Constants.AUTHORIZE_READABLE_PERM); resourcesUser.setPerm(Constants.AUTHORIZE_READABLE_PERM);
}else{ } else {
resourcesUser.setPerm(Constants.AUTHORIZE_WRITABLE_PERM); resourcesUser.setPerm(Constants.AUTHORIZE_WRITABLE_PERM);
} }
@ -591,7 +653,7 @@ public class UsersService extends BaseService {
return result; return result;
} }
User user = userMapper.selectById(userId); User user = userMapper.selectById(userId);
if(user == null){ if (user == null) {
putMsg(result, Status.USER_NOT_EXIST, userId); putMsg(result, Status.USER_NOT_EXIST, userId);
return result; return result;
} }
@ -639,7 +701,7 @@ public class UsersService extends BaseService {
return result; return result;
} }
User user = userMapper.selectById(userId); User user = userMapper.selectById(userId);
if(user == null){ if (user == null) {
putMsg(result, Status.USER_NOT_EXIST, userId); putMsg(result, Status.USER_NOT_EXIST, userId);
return result; return result;
} }
@ -738,7 +800,7 @@ public class UsersService extends BaseService {
return result; return result;
} }
List<User> userList = userMapper.selectList(null ); List<User> userList = userMapper.selectList(null);
result.put(Constants.DATA_LIST, userList); result.put(Constants.DATA_LIST, userList);
putMsg(result, Status.SUCCESS); putMsg(result, Status.SUCCESS);
@ -782,7 +844,7 @@ public class UsersService extends BaseService {
return result; return result;
} }
List<User> userList = userMapper.selectList(null ); List<User> userList = userMapper.selectList(null);
List<User> resultUsers = new ArrayList<>(); List<User> resultUsers = new ArrayList<>();
Set<User> userSet = null; Set<User> userSet = null;
if (userList != null && userList.size() > 0) { if (userList != null && userList.size() > 0) {
@ -833,11 +895,6 @@ public class UsersService extends BaseService {
} }
/** /**
*
* @param userName
* @param password
* @param email
* @param phone
* @return if check failed return the field, otherwise return null * @return if check failed return the field, otherwise return null
*/ */
private String checkUserParams(String userName, String password, String email, String phone) { private String checkUserParams(String userName, String password, String email, String phone) {
@ -862,6 +919,7 @@ public class UsersService extends BaseService {
/** /**
* copy resource files * copy resource files
*
* @param resourceComponent resource component * @param resourceComponent resource component
* @param srcBasePath src base path * @param srcBasePath src base path
* @param dstBasePath dst base path * @param dstBasePath dst base path
@ -871,26 +929,26 @@ public class UsersService extends BaseService {
List<ResourceComponent> components = resourceComponent.getChildren(); List<ResourceComponent> components = resourceComponent.getChildren();
if (CollectionUtils.isNotEmpty(components)) { if (CollectionUtils.isNotEmpty(components)) {
for (ResourceComponent component:components) { for (ResourceComponent component : components) {
// verify whether exist // verify whether exist
if (!HadoopUtils.getInstance().exists(String.format("%s/%s",srcBasePath,component.getFullName()))){ if (!HadoopUtils.getInstance().exists(String.format("%s/%s", srcBasePath, component.getFullName()))) {
logger.error("resource file: {} not exist,copy error",component.getFullName()); logger.error("resource file: {} not exist,copy error", component.getFullName());
throw new ServiceException(Status.RESOURCE_NOT_EXIST); throw new ServiceException(Status.RESOURCE_NOT_EXIST);
} }
if (!component.isDirctory()) { if (!component.isDirctory()) {
// copy it to dst // copy it to dst
HadoopUtils.getInstance().copy(String.format("%s/%s",srcBasePath,component.getFullName()),String.format("%s/%s",dstBasePath,component.getFullName()),false,true); HadoopUtils.getInstance().copy(String.format("%s/%s", srcBasePath, component.getFullName()), String.format("%s/%s", dstBasePath, component.getFullName()), false, true);
continue; continue;
} }
if(CollectionUtils.isEmpty(component.getChildren())) { if (CollectionUtils.isEmpty(component.getChildren())) {
// if not exist,need create it // if not exist,need create it
if (!HadoopUtils.getInstance().exists(String.format("%s/%s",dstBasePath,component.getFullName()))) { if (!HadoopUtils.getInstance().exists(String.format("%s/%s", dstBasePath, component.getFullName()))) {
HadoopUtils.getInstance().mkdir(String.format("%s/%s",dstBasePath,component.getFullName())); HadoopUtils.getInstance().mkdir(String.format("%s/%s", dstBasePath, component.getFullName()));
} }
}else{ } else {
copyResourceFiles(component,srcBasePath,dstBasePath); copyResourceFiles(component, srcBasePath, dstBasePath);
} }
} }
} }
@ -914,7 +972,7 @@ public class UsersService extends BaseService {
String msg = this.checkUserParams(userName, userPassword, email, ""); String msg = this.checkUserParams(userName, userPassword, email, "");
if (!StringUtils.isEmpty(msg)) { if (!StringUtils.isEmpty(msg)) {
putMsg(result, Status.REQUEST_PARAMS_NOT_VALID_ERROR,msg); putMsg(result, Status.REQUEST_PARAMS_NOT_VALID_ERROR, msg);
return result; return result;
} }
@ -944,7 +1002,7 @@ public class UsersService extends BaseService {
return result; return result;
} }
if (!CheckUtils.checkUserName(userName)){ if (!CheckUtils.checkUserName(userName)) {
putMsg(result, Status.REQUEST_PARAMS_NOT_VALID_ERROR, userName); putMsg(result, Status.REQUEST_PARAMS_NOT_VALID_ERROR, userName);
return result; return result;
} }

14
dolphinscheduler-api/src/main/resources/application-api.properties

@ -45,6 +45,18 @@ spring.messages.basename=i18n/messages
# Authentication types (supported types: PASSWORD) # Authentication types (supported types: PASSWORD)
security.authentication.type=PASSWORD security.authentication.type=PASSWORD
#============================================================================
# LDAP Config
# mock ldap server from https://www.forumsys.com/tutorials/integration-how-to/ldap/online-ldap-test-server/
#============================================================================
# admin userId
#security.authentication.ldap.user.admin=read-only-admin
# ldap server config
#ldap.urls=ldap://ldap.forumsys.com:389/
#ldap.base.dn=dc=example,dc=com
#ldap.username=cn=read-only-admin,dc=example,dc=com
#ldap.password=password
#ldap.user.identity.attribute=uid
#ldap.user.email.attribute=mail

45
dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/security/SecurityConfigLDAPTest.java

@ -0,0 +1,45 @@
/*
* 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.security;
import org.apache.dolphinscheduler.api.ApiApplicationServer;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest(classes = ApiApplicationServer.class)
@TestPropertySource(properties = {
"security.authentication.type=LDAP",
})
public class SecurityConfigLDAPTest {
@Autowired
private SecurityConfig securityConfig;
@Test
public void testAuthenticator() {
Authenticator authenticator = securityConfig.authenticator();
Assert.assertNotNull(authenticator);
}
}

4
dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/security/SecurityConfigTest.java → dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/security/SecurityConfigPasswordTest.java

@ -14,9 +14,11 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.apache.dolphinscheduler.api.security; package org.apache.dolphinscheduler.api.security;
import org.apache.dolphinscheduler.api.ApiApplicationServer; import org.apache.dolphinscheduler.api.ApiApplicationServer;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
@ -30,7 +32,7 @@ import org.springframework.test.context.junit4.SpringRunner;
@TestPropertySource(properties = { @TestPropertySource(properties = {
"security.authentication.type=PASSWORD", "security.authentication.type=PASSWORD",
}) })
public class SecurityConfigTest { public class SecurityConfigPasswordTest {
@Autowired @Autowired
private SecurityConfig securityConfig; private SecurityConfig securityConfig;

142
dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/security/impl/ldap/LdapAuthenticatorTest.java

@ -0,0 +1,142 @@
/*
* 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.security.impl.ldap;
import static org.mockito.Mockito.when;
import org.apache.dolphinscheduler.api.ApiApplicationServer;
import org.apache.dolphinscheduler.api.enums.Status;
import org.apache.dolphinscheduler.api.service.SessionService;
import org.apache.dolphinscheduler.api.service.UsersService;
import org.apache.dolphinscheduler.api.utils.Result;
import org.apache.dolphinscheduler.common.enums.Flag;
import org.apache.dolphinscheduler.common.enums.UserType;
import org.apache.dolphinscheduler.dao.entity.Session;
import org.apache.dolphinscheduler.dao.entity.User;
import java.util.Date;
import java.util.UUID;
import javax.servlet.http.HttpServletRequest;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest(classes = ApiApplicationServer.class)
@TestPropertySource(
properties = {
"security.authentication.type=LDAP",
"security.authentication.ldap.user.admin=read-only-admin",
"ldap.urls=ldap://ldap.forumsys.com:389/",
"ldap.base.dn=dc=example,dc=com",
"ldap.username=cn=read-only-admin,dc=example,dc=com",
"ldap.password=password",
"ldap.user.identity.attribute=uid",
"ldap.user.email.attribute=mail",
})
public class LdapAuthenticatorTest {
private static Logger logger = LoggerFactory.getLogger(LdapAuthenticatorTest.class);
@Autowired
protected AutowireCapableBeanFactory beanFactory;
@MockBean
private LdapService ldapService;
@MockBean
private SessionService sessionService;
@MockBean
private UsersService usersService;
private LdapAuthenticator ldapAuthenticator;
//test param
private User mockUser;
private Session mockSession;
private String ldapUid = "test";
private String ldapUserPwd = "password";
private String ldapEmail = "test@example.com";
private String ip = "127.0.0.1";
private UserType userType = UserType.GENERAL_USER;
@Before
public void setUp() {
ldapAuthenticator = new LdapAuthenticator();
beanFactory.autowireBean(ldapAuthenticator);
mockUser = new User();
mockUser.setId(1);
mockUser.setUserName(ldapUid);
mockUser.setEmail(ldapEmail);
mockUser.setUserType(userType);
mockUser.setState(Flag.YES.getCode());
mockSession = new Session();
mockSession.setId(UUID.randomUUID().toString());
mockSession.setIp(ip);
mockSession.setUserId(1);
mockSession.setLastLoginTime(new Date());
}
@Test
public void testAuthenticate() {
when(usersService.createUser(userType, ldapUid, ldapEmail)).thenReturn(mockUser);
when(usersService.getUserByUserName(ldapUid)).thenReturn(mockUser);
when(sessionService.createSession(mockUser, ip)).thenReturn(mockSession.getId());
when(ldapService.ldapLogin(ldapUid, ldapUserPwd)).thenReturn(ldapEmail);
Result result = ldapAuthenticator.authenticate(ldapUid, ldapUserPwd, ip);
Assert.assertEquals(Status.SUCCESS.getCode(), (int) result.getCode());
logger.info(result.toString());
when(sessionService.createSession(mockUser, ip)).thenReturn(null);
result = ldapAuthenticator.authenticate(ldapUid, ldapUserPwd, ip);
Assert.assertEquals(Status.LOGIN_SESSION_FAILED.getCode(), (int) result.getCode());
when(sessionService.createSession(mockUser, ip)).thenReturn(mockSession.getId());
when(usersService.getUserByUserName(ldapUid)).thenReturn(null);
result = ldapAuthenticator.authenticate(ldapUid, ldapUserPwd, ip);
Assert.assertEquals(Status.USER_NAME_PASSWD_ERROR.getCode(), (int) result.getCode());
}
@Test
public void testGetAuthUser() {
HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
when(usersService.queryUser(mockUser.getId())).thenReturn(mockUser);
when(sessionService.getSession(request)).thenReturn(mockSession);
User user = ldapAuthenticator.getAuthUser(request);
Assert.assertNotNull(user);
when(sessionService.getSession(request)).thenReturn(null);
user = ldapAuthenticator.getAuthUser(request);
Assert.assertNull(user);
}
}

81
dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/security/impl/ldap/LdapServiceTest.java

@ -0,0 +1,81 @@
/*
* 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.security.impl.ldap;
import org.apache.dolphinscheduler.api.ApiApplicationServer;
import org.apache.dolphinscheduler.common.enums.UserType;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest(classes = ApiApplicationServer.class)
@TestPropertySource(
properties = {
"security.authentication.type=LDAP",
"security.authentication.ldap.user.admin=read-only-admin",
"ldap.urls=ldap://ldap.forumsys.com:389/",
"ldap.base.dn=dc=example,dc=com",
"ldap.username=cn=read-only-admin,dc=example,dc=com",
"ldap.password=password",
"ldap.user.identity.attribute=uid",
"ldap.user.email.attribute=mail",
})
public class LdapServiceTest {
@Autowired
protected AutowireCapableBeanFactory beanFactory;
private LdapService ldapService;
@Before
public void setUp() {
ldapService = new LdapService();
beanFactory.autowireBean(ldapService);
}
@Test
public void getUserType() {
UserType userType = ldapService.getUserType("read-only-admin");
Assert.assertEquals(UserType.ADMIN_USER, userType);
}
@Test
public void ldapLogin() {
String email = ldapService.ldapLogin("tesla", "password");
Assert.assertEquals("tesla@ldap.forumsys.com", email);
String email2 = ldapService.ldapLogin("tesla", "error password");
Assert.assertNull(email2);
}
@Test
public void ldapLoginError() {
String email = ldapService.ldapLogin("tesla", "password");
Assert.assertEquals("tesla@ldap.forumsys.com", email);
String email2 = ldapService.ldapLogin("tesla", "error password");
Assert.assertNull(email2);
}
}

24
dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/security/PasswordAuthenticatorTest.java → dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/security/impl/pwd/PasswordAuthenticatorTest.java

@ -14,7 +14,10 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.apache.dolphinscheduler.api.security;
package org.apache.dolphinscheduler.api.security.impl.pwd;
import static org.mockito.Mockito.when;
import org.apache.dolphinscheduler.api.ApiApplicationServer; import org.apache.dolphinscheduler.api.ApiApplicationServer;
import org.apache.dolphinscheduler.api.enums.Status; import org.apache.dolphinscheduler.api.enums.Status;
@ -23,12 +26,17 @@ import org.apache.dolphinscheduler.api.service.UsersService;
import org.apache.dolphinscheduler.api.utils.Result; import org.apache.dolphinscheduler.api.utils.Result;
import org.apache.dolphinscheduler.dao.entity.Session; import org.apache.dolphinscheduler.dao.entity.Session;
import org.apache.dolphinscheduler.dao.entity.User; import org.apache.dolphinscheduler.dao.entity.User;
import java.util.Date;
import java.util.UUID;
import javax.servlet.http.HttpServletRequest;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.mockito.Mockito; import org.mockito.Mockito;
import static org.mockito.Mockito.*;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@ -36,9 +44,6 @@ import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.context.junit4.SpringRunner;
import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.UUID;
@RunWith(SpringRunner.class) @RunWith(SpringRunner.class)
@SpringBootTest(classes = ApiApplicationServer.class) @SpringBootTest(classes = ApiApplicationServer.class)
@ -58,7 +63,7 @@ public class PasswordAuthenticatorTest {
private Session mockSession; private Session mockSession;
@Before @Before
public void setUp() throws Exception { public void setUp() {
authenticator = new PasswordAuthenticator(); authenticator = new PasswordAuthenticator();
beanFactory.autowireBean(authenticator); beanFactory.autowireBean(authenticator);
@ -76,6 +81,13 @@ public class PasswordAuthenticatorTest {
mockSession.setLastLoginTime(new Date()); mockSession.setLastLoginTime(new Date());
} }
@Test
public void testLogin() {
when(usersService.queryUser("test", "test")).thenReturn(mockUser);
User login = authenticator.login("test", "test", "127.0.0.1");
Assert.assertNotNull(login);
}
@Test @Test
public void testAuthenticate() { public void testAuthenticate() {
when(usersService.queryUser("test", "test")).thenReturn(mockUser); when(usersService.queryUser("test", "test")).thenReturn(mockUser);

156
dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/UsersServiceTest.java

@ -14,10 +14,13 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.apache.dolphinscheduler.api.service; package org.apache.dolphinscheduler.api.service;
import com.baomidou.mybatisplus.core.metadata.IPage; import static org.mockito.ArgumentMatchers.any;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.when;
import org.apache.dolphinscheduler.api.enums.Status; import org.apache.dolphinscheduler.api.enums.Status;
import org.apache.dolphinscheduler.api.utils.PageInfo; import org.apache.dolphinscheduler.api.utils.PageInfo;
import org.apache.dolphinscheduler.api.utils.Result; import org.apache.dolphinscheduler.api.utils.Result;
@ -29,7 +32,19 @@ import org.apache.dolphinscheduler.common.utils.EncryptionUtils;
import org.apache.dolphinscheduler.dao.entity.Resource; import org.apache.dolphinscheduler.dao.entity.Resource;
import org.apache.dolphinscheduler.dao.entity.Tenant; import org.apache.dolphinscheduler.dao.entity.Tenant;
import org.apache.dolphinscheduler.dao.entity.User; import org.apache.dolphinscheduler.dao.entity.User;
import org.apache.dolphinscheduler.dao.mapper.*; import org.apache.dolphinscheduler.dao.mapper.AlertGroupMapper;
import org.apache.dolphinscheduler.dao.mapper.DataSourceUserMapper;
import org.apache.dolphinscheduler.dao.mapper.ProjectUserMapper;
import org.apache.dolphinscheduler.dao.mapper.ResourceMapper;
import org.apache.dolphinscheduler.dao.mapper.ResourceUserMapper;
import org.apache.dolphinscheduler.dao.mapper.TenantMapper;
import org.apache.dolphinscheduler.dao.mapper.UDFUserMapper;
import org.apache.dolphinscheduler.dao.mapper.UserMapper;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.junit.After; import org.junit.After;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Before; import org.junit.Before;
@ -42,13 +57,8 @@ import org.mockito.junit.MockitoJUnitRunner;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import static org.mockito.ArgumentMatchers.any; import com.baomidou.mybatisplus.core.metadata.IPage;
import static org.mockito.ArgumentMatchers.eq; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import static org.mockito.Mockito.when;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@RunWith(MockitoJUnitRunner.class) @RunWith(MockitoJUnitRunner.class)
public class UsersServiceTest { public class UsersServiceTest {
@ -73,30 +83,34 @@ public class UsersServiceTest {
@Mock @Mock
private ResourceMapper resourceMapper; private ResourceMapper resourceMapper;
private String queueName ="UsersServiceTestQueue"; private String queueName = "UsersServiceTestQueue";
@Before @Before
public void before(){ public void before() {
} }
@After @After
public void after(){ public void after() {
} }
@Test @Test
public void testCreateUser(){ public void testCreateUserForLdap() {
String userName = "user1";
String email = "user1@ldap.com";
User user = usersService.createUser(UserType.ADMIN_USER, userName, email);
Assert.assertNotNull(user);
}
@Test
public void testCreateUser() {
User user = new User(); User user = new User();
user.setUserType(UserType.ADMIN_USER); user.setUserType(UserType.ADMIN_USER);
String userName = "userTest0001~"; String userName = "userTest0001~";
String userPassword = "userTest"; String userPassword = "userTest";
String email = "123@qq.com"; String email = "123@qq.com";
int tenantId = Integer.MAX_VALUE; int tenantId = Integer.MAX_VALUE;
String phone= "13456432345"; String phone = "13456432345";
int state = 1; int state = 1;
try { try {
//userName error //userName error
@ -119,7 +133,7 @@ public class UsersServiceTest {
Assert.assertEquals(Status.REQUEST_PARAMS_NOT_VALID_ERROR, result.get(Constants.STATUS)); Assert.assertEquals(Status.REQUEST_PARAMS_NOT_VALID_ERROR, result.get(Constants.STATUS));
email = "122222@qq.com"; email = "122222@qq.com";
phone ="2233"; phone = "2233";
//phone error //phone error
result = usersService.createUser(user, userName, userPassword, email, tenantId, phone, queueName, state); result = usersService.createUser(user, userName, userPassword, email, tenantId, phone, queueName, state);
logger.info(result.toString()); logger.info(result.toString());
@ -137,20 +151,19 @@ public class UsersServiceTest {
Assert.assertEquals(Status.SUCCESS, result.get(Constants.STATUS)); Assert.assertEquals(Status.SUCCESS, result.get(Constants.STATUS));
} catch (Exception e) { } catch (Exception e) {
logger.error(Status.CREATE_USER_ERROR.getMsg(),e); logger.error(Status.CREATE_USER_ERROR.getMsg(), e);
Assert.assertTrue(false); Assert.assertTrue(false);
} }
} }
@Test @Test
public void testQueryUser(){ public void testQueryUser() {
String userName = "userTest0001"; String userName = "userTest0001";
String userPassword = "userTest0001"; String userPassword = "userTest0001";
when(userMapper.queryUserByNamePassword(userName,EncryptionUtils.getMd5(userPassword))).thenReturn(getGeneralUser()); when(userMapper.queryUserByNamePassword(userName, EncryptionUtils.getMd5(userPassword))).thenReturn(getGeneralUser());
User queryUser = usersService.queryUser(userName, userPassword); User queryUser = usersService.queryUser(userName, userPassword);
logger.info(queryUser.toString()); logger.info(queryUser.toString());
Assert.assertTrue(queryUser!=null); Assert.assertTrue(queryUser != null);
} }
@Test @Test
@ -176,11 +189,8 @@ public class UsersServiceTest {
} }
@Test @Test
public void testQueryUserList(){ public void testQueryUserList() {
User user = new User(); User user = new User();
//no operate //no operate
@ -190,37 +200,34 @@ public class UsersServiceTest {
//success //success
user.setUserType(UserType.ADMIN_USER); user.setUserType(UserType.ADMIN_USER);
when(userMapper.selectList(null )).thenReturn(getUserList()); when(userMapper.selectList(null)).thenReturn(getUserList());
result = usersService.queryUserList(user); result = usersService.queryUserList(user);
List<User> userList = (List<User>) result.get(Constants.DATA_LIST); List<User> userList = (List<User>) result.get(Constants.DATA_LIST);
Assert.assertTrue(userList.size()>0); Assert.assertTrue(userList.size() > 0);
} }
@Test @Test
public void testQueryUserListPage(){ public void testQueryUserListPage() {
User user = new User(); User user = new User();
IPage<User> page = new Page<>(1,10); IPage<User> page = new Page<>(1, 10);
page.setRecords(getUserList()); page.setRecords(getUserList());
when(userMapper.queryUserPaging(any(Page.class), eq("userTest"))).thenReturn(page); when(userMapper.queryUserPaging(any(Page.class), eq("userTest"))).thenReturn(page);
//no operate //no operate
Map<String, Object> result = usersService.queryUserList(user,"userTest",1,10); Map<String, Object> result = usersService.queryUserList(user, "userTest", 1, 10);
logger.info(result.toString()); logger.info(result.toString());
Assert.assertEquals(Status.USER_NO_OPERATION_PERM, result.get(Constants.STATUS)); Assert.assertEquals(Status.USER_NO_OPERATION_PERM, result.get(Constants.STATUS));
//success //success
user.setUserType(UserType.ADMIN_USER); user.setUserType(UserType.ADMIN_USER);
result = usersService.queryUserList(user,"userTest",1,10); result = usersService.queryUserList(user, "userTest", 1, 10);
Assert.assertEquals(Status.SUCCESS, result.get(Constants.STATUS)); Assert.assertEquals(Status.SUCCESS, result.get(Constants.STATUS));
PageInfo<User> pageInfo = (PageInfo<User>) result.get(Constants.DATA_LIST); PageInfo<User> pageInfo = (PageInfo<User>) result.get(Constants.DATA_LIST);
Assert.assertTrue(pageInfo.getLists().size()>0); Assert.assertTrue(pageInfo.getLists().size() > 0);
} }
@Test @Test
public void testUpdateUser(){ public void testUpdateUser() {
String userName = "userTest0001"; String userName = "userTest0001";
String userPassword = "userTest0001"; String userPassword = "userTest0001";
try { try {
@ -235,36 +242,35 @@ public class UsersServiceTest {
logger.info(result.toString()); logger.info(result.toString());
Assert.assertEquals(Status.SUCCESS, result.get(Constants.STATUS)); Assert.assertEquals(Status.SUCCESS, result.get(Constants.STATUS));
} catch (Exception e) { } catch (Exception e) {
logger.error("update user error",e); logger.error("update user error", e);
Assert.assertTrue(false); Assert.assertTrue(false);
} }
} }
@Test @Test
public void testDeleteUserById(){ public void testDeleteUserById() {
User loginUser = new User(); User loginUser = new User();
try { try {
when(userMapper.queryTenantCodeByUserId(1)).thenReturn(getUser()); when(userMapper.queryTenantCodeByUserId(1)).thenReturn(getUser());
when(userMapper.selectById(1)).thenReturn(getUser()); when(userMapper.selectById(1)).thenReturn(getUser());
//no operate //no operate
Map<String, Object> result = usersService.deleteUserById(loginUser,3); Map<String, Object> result = usersService.deleteUserById(loginUser, 3);
logger.info(result.toString()); logger.info(result.toString());
Assert.assertEquals(Status.USER_NO_OPERATION_PERM, result.get(Constants.STATUS)); Assert.assertEquals(Status.USER_NO_OPERATION_PERM, result.get(Constants.STATUS));
// user not exist // user not exist
loginUser.setUserType(UserType.ADMIN_USER); loginUser.setUserType(UserType.ADMIN_USER);
result = usersService.deleteUserById(loginUser,3); result = usersService.deleteUserById(loginUser, 3);
logger.info(result.toString()); logger.info(result.toString());
Assert.assertEquals(Status.USER_NOT_EXIST, result.get(Constants.STATUS)); Assert.assertEquals(Status.USER_NOT_EXIST, result.get(Constants.STATUS));
//success //success
result = usersService.deleteUserById(loginUser,1); result = usersService.deleteUserById(loginUser, 1);
logger.info(result.toString()); logger.info(result.toString());
Assert.assertEquals(Status.SUCCESS, result.get(Constants.STATUS)); Assert.assertEquals(Status.SUCCESS, result.get(Constants.STATUS));
} catch (Exception e) { } catch (Exception e) {
logger.error("delete user error",e); logger.error("delete user error", e);
Assert.assertTrue(false); Assert.assertTrue(false);
} }
@ -272,11 +278,10 @@ public class UsersServiceTest {
} }
@Test @Test
public void testGrantProject(){ public void testGrantProject() {
when(userMapper.selectById(1)).thenReturn(getUser()); when(userMapper.selectById(1)).thenReturn(getUser());
User loginUser = new User(); User loginUser = new User();
String projectIds= "100000,120000"; String projectIds = "100000,120000";
Map<String, Object> result = usersService.grantProject(loginUser, 1, projectIds); Map<String, Object> result = usersService.grantProject(loginUser, 1, projectIds);
logger.info(result.toString()); logger.info(result.toString());
Assert.assertEquals(Status.USER_NO_OPERATION_PERM, result.get(Constants.STATUS)); Assert.assertEquals(Status.USER_NO_OPERATION_PERM, result.get(Constants.STATUS));
@ -292,8 +297,7 @@ public class UsersServiceTest {
} }
@Test @Test
public void testGrantResources(){ public void testGrantResources() {
String resourceIds = "100000,120000"; String resourceIds = "100000,120000";
when(userMapper.selectById(1)).thenReturn(getUser()); when(userMapper.selectById(1)).thenReturn(getUser());
User loginUser = new User(); User loginUser = new User();
@ -317,8 +321,7 @@ public class UsersServiceTest {
@Test @Test
public void testGrantUDFFunction(){ public void testGrantUDFFunction() {
String udfIds = "100000,120000"; String udfIds = "100000,120000";
when(userMapper.selectById(1)).thenReturn(getUser()); when(userMapper.selectById(1)).thenReturn(getUser());
User loginUser = new User(); User loginUser = new User();
@ -337,8 +340,7 @@ public class UsersServiceTest {
} }
@Test @Test
public void testGrantDataSource(){ public void testGrantDataSource() {
String datasourceIds = "100000,120000"; String datasourceIds = "100000,120000";
when(userMapper.selectById(1)).thenReturn(getUser()); when(userMapper.selectById(1)).thenReturn(getUser());
User loginUser = new User(); User loginUser = new User();
@ -365,8 +367,7 @@ public class UsersServiceTest {
} }
@Test @Test
public void getUserInfo(){ public void getUserInfo() {
User loginUser = new User(); User loginUser = new User();
loginUser.setUserName("admin"); loginUser.setUserName("admin");
loginUser.setUserType(UserType.ADMIN_USER); loginUser.setUserType(UserType.ADMIN_USER);
@ -376,7 +377,7 @@ public class UsersServiceTest {
Assert.assertEquals(Status.SUCCESS, result.get(Constants.STATUS)); Assert.assertEquals(Status.SUCCESS, result.get(Constants.STATUS));
User tempUser = (User) result.get(Constants.DATA_LIST); User tempUser = (User) result.get(Constants.DATA_LIST);
//check userName //check userName
Assert.assertEquals("admin",tempUser.getUserName()); Assert.assertEquals("admin", tempUser.getUserName());
//get general user //get general user
loginUser.setUserType(null); loginUser.setUserType(null);
@ -387,13 +388,12 @@ public class UsersServiceTest {
Assert.assertEquals(Status.SUCCESS, result.get(Constants.STATUS)); Assert.assertEquals(Status.SUCCESS, result.get(Constants.STATUS));
tempUser = (User) result.get(Constants.DATA_LIST); tempUser = (User) result.get(Constants.DATA_LIST);
//check userName //check userName
Assert.assertEquals("userTest0001",tempUser.getUserName()); Assert.assertEquals("userTest0001", tempUser.getUserName());
} }
@Test @Test
public void testQueryAllGeneralUsers(){ public void testQueryAllGeneralUsers() {
User loginUser = new User(); User loginUser = new User();
//no operate //no operate
Map<String, Object> result = usersService.queryAllGeneralUsers(loginUser); Map<String, Object> result = usersService.queryAllGeneralUsers(loginUser);
@ -410,8 +410,7 @@ public class UsersServiceTest {
} }
@Test @Test
public void testVerifyUserName(){ public void testVerifyUserName() {
//not exist user //not exist user
Result result = usersService.verifyUserName("admin89899"); Result result = usersService.verifyUserName("admin89899");
logger.info(result.toString()); logger.info(result.toString());
@ -424,11 +423,10 @@ public class UsersServiceTest {
} }
@Test @Test
public void testUnauthorizedUser(){ public void testUnauthorizedUser() {
User loginUser = new User(); User loginUser = new User();
when(userMapper.selectList(null )).thenReturn(getUserList()); when(userMapper.selectList(null)).thenReturn(getUserList());
when( userMapper.queryUserListByAlertGroupId(2)).thenReturn(getUserList()); when(userMapper.queryUserListByAlertGroupId(2)).thenReturn(getUserList());
//no operate //no operate
Map<String, Object> result = usersService.unauthorizedUser(loginUser, 2); Map<String, Object> result = usersService.unauthorizedUser(loginUser, 2);
logger.info(result.toString()); logger.info(result.toString());
@ -442,8 +440,7 @@ public class UsersServiceTest {
@Test @Test
public void testAuthorizedUser(){ public void testAuthorizedUser() {
User loginUser = new User(); User loginUser = new User();
when(userMapper.queryUserListByAlertGroupId(2)).thenReturn(getUserList()); when(userMapper.queryUserListByAlertGroupId(2)).thenReturn(getUserList());
//no operate //no operate
@ -571,10 +568,8 @@ public class UsersServiceTest {
/** /**
* get disabled user * get disabled user
* @return
*/ */
private User getDisabledUser() { private User getDisabledUser() {
User user = new User(); User user = new User();
user.setUserType(UserType.GENERAL_USER); user.setUserType(UserType.GENERAL_USER);
user.setUserName("userTest0001"); user.setUserName("userTest0001");
@ -586,10 +581,8 @@ public class UsersServiceTest {
/** /**
* get user * get user
* @return
*/ */
private User getGeneralUser(){ private User getGeneralUser() {
User user = new User(); User user = new User();
user.setUserType(UserType.GENERAL_USER); user.setUserType(UserType.GENERAL_USER);
user.setUserName("userTest0001"); user.setUserName("userTest0001");
@ -597,8 +590,7 @@ public class UsersServiceTest {
return user; return user;
} }
private List<User> getUserList() {
private List<User> getUserList(){
List<User> userList = new ArrayList<>(); List<User> userList = new ArrayList<>();
userList.add(getGeneralUser()); userList.add(getGeneralUser());
return userList; return userList;
@ -607,8 +599,7 @@ public class UsersServiceTest {
/** /**
* get user * get user
*/ */
private User getUser(){ private User getUser() {
User user = new User(); User user = new User();
user.setUserType(UserType.ADMIN_USER); user.setUserType(UserType.ADMIN_USER);
user.setUserName("userTest0001"); user.setUserName("userTest0001");
@ -619,9 +610,10 @@ public class UsersServiceTest {
/** /**
* get tenant * get tenant
*
* @return tenant * @return tenant
*/ */
private Tenant getTenant(){ private Tenant getTenant() {
Tenant tenant = new Tenant(); Tenant tenant = new Tenant();
tenant.setId(1); tenant.setId(1);
return tenant; return tenant;
@ -629,10 +621,10 @@ public class UsersServiceTest {
/** /**
* get resource * get resource
*
* @return resource * @return resource
*/ */
private Resource getResource(){ private Resource getResource() {
Resource resource = new Resource(); Resource resource = new Resource();
resource.setPid(-1); resource.setPid(-1);
resource.setUserId(1); resource.setUserId(1);

2
dolphinscheduler-dao/src/main/resources/org/apache/dolphinscheduler/dao/mapper/AccessTokenMapper.xml

@ -19,7 +19,7 @@
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" > <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="org.apache.dolphinscheduler.dao.mapper.AccessTokenMapper"> <mapper namespace="org.apache.dolphinscheduler.dao.mapper.AccessTokenMapper">
<select id="selectAccessTokenPage" resultType="org.apache.dolphinscheduler.dao.entity.AccessToken"> <select id="selectAccessTokenPage" resultType="org.apache.dolphinscheduler.dao.entity.AccessToken">
select t.id, t.user_id, t.token, t.expire_time, t.create_time, t.update_time select t.id, t.user_id, t.token, t.expire_time, t.create_time, t.update_time, u.user_name
from t_ds_access_token t from t_ds_access_token t
left join t_ds_user u on t.user_id = u.id left join t_ds_user u on t.user_id = u.id
where 1 = 1 where 1 = 1

99
dolphinscheduler-dao/src/main/resources/org/apache/dolphinscheduler/dao/mapper/UdfFuncMapper.xml

@ -18,82 +18,97 @@
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" > <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="org.apache.dolphinscheduler.dao.mapper.UdfFuncMapper"> <mapper namespace="org.apache.dolphinscheduler.dao.mapper.UdfFuncMapper">
<sql id="baseSql">
${alias}.id, ${alias}.user_id, ${alias}.func_name, ${alias}.class_name, ${alias}.type, ${alias}.arg_types,
${alias}.database, ${alias}.description, ${alias}.resource_id, ${alias}.resource_name, ${alias}.create_time, ${alias}.update_time
</sql>
<select id="selectUdfById" resultType="org.apache.dolphinscheduler.dao.entity.UdfFunc"> <select id="selectUdfById" resultType="org.apache.dolphinscheduler.dao.entity.UdfFunc">
select select
id, user_id, func_name, class_name, type, arg_types, <include refid="baseSql">
database, description, resource_id, resource_name, create_time, update_time <property name="alias" value="udf"/>
from t_ds_udfs </include>
from t_ds_udfs udf
where id = #{id} where id = #{id}
</select> </select>
<select id="queryUdfByIdStr" resultType="org.apache.dolphinscheduler.dao.entity.UdfFunc"> <select id="queryUdfByIdStr" resultType="org.apache.dolphinscheduler.dao.entity.UdfFunc">
select select
id, user_id, func_name, class_name, type, arg_types, <include refid="baseSql">
database, description, resource_id, resource_name, create_time, update_time <property name="alias" value="udf"/>
from t_ds_udfs </include>
from t_ds_udfs udf
where 1 = 1 where 1 = 1
<if test="ids != null and ids != ''"> <if test="ids != null and ids != ''">
and id in and udf.id in
<foreach collection="ids" item="i" open="(" close=")" separator=","> <foreach collection="ids" item="i" open="(" close=")" separator=",">
#{i} #{i}
</foreach> </foreach>
</if> </if>
<if test="funcNames != null and funcNames != ''"> <if test="funcNames != null and funcNames != ''">
and func_name = #{funcNames} and udf.func_name = #{funcNames}
</if> </if>
order by id asc order by udf.id asc
</select> </select>
<select id="queryUdfFuncPaging" resultType="org.apache.dolphinscheduler.dao.entity.UdfFunc"> <select id="queryUdfFuncPaging" resultType="org.apache.dolphinscheduler.dao.entity.UdfFunc">
select id, user_id, func_name, class_name, type, arg_types, database, description, resource_id, resource_name, create_time, update_time select
from t_ds_udfs <include refid="baseSql">
<property name="alias" value="udf"/>
</include>
from t_ds_udfs udf
where 1=1 where 1=1
<if test="searchVal!= null and searchVal != ''"> <if test="searchVal!= null and searchVal != ''">
and func_name like concat('%', #{searchVal}, '%') and udf.func_name like concat('%', #{searchVal}, '%')
</if> </if>
<if test="userId != 0"> <if test="userId != 0">
and id in ( and udf.id in (
select udf_id from t_ds_relation_udfs_user where user_id=#{userId} select udf_id from t_ds_relation_udfs_user where user_id=#{userId}
union select id as udf_id from t_ds_udfs where user_id=#{userId}) union select id as udf_id from t_ds_udfs where user_id=#{userId})
</if> </if>
order by create_time desc order by udf.create_time desc
</select> </select>
<select id="getUdfFuncByType" resultType="org.apache.dolphinscheduler.dao.entity.UdfFunc"> <select id="getUdfFuncByType" resultType="org.apache.dolphinscheduler.dao.entity.UdfFunc">
select select
id, user_id, func_name, class_name, type, arg_types, <include refid="baseSql">
database, description, resource_id, resource_name, create_time, update_time <property name="alias" value="udf"/>
from t_ds_udfs </include>
where type=#{type} from t_ds_udfs udf
where udf.type=#{type}
<if test="userId != 0"> <if test="userId != 0">
and id in ( and udf.id in (
select udf_id from t_ds_relation_udfs_user where user_id=#{userId} select udf_id from t_ds_relation_udfs_user where user_id=#{userId}
union select id as udf_id from t_ds_udfs where user_id=#{userId}) union select id as udf_id from t_ds_udfs where user_id=#{userId})
</if> </if>
</select> </select>
<select id="queryUdfFuncExceptUserId" resultType="org.apache.dolphinscheduler.dao.entity.UdfFunc"> <select id="queryUdfFuncExceptUserId" resultType="org.apache.dolphinscheduler.dao.entity.UdfFunc">
select select
id, user_id, func_name, class_name, type, arg_types, <include refid="baseSql">
database, description, resource_id, resource_name, create_time, update_time <property name="alias" value="udf"/>
from t_ds_udfs </include>
where user_id <![CDATA[ <> ]]> #{userId} from t_ds_udfs udf
where udf.user_id <![CDATA[ <> ]]> #{userId}
</select> </select>
<select id="queryAuthedUdfFunc" resultType="org.apache.dolphinscheduler.dao.entity.UdfFunc"> <select id="queryAuthedUdfFunc" resultType="org.apache.dolphinscheduler.dao.entity.UdfFunc">
SELECT SELECT
u.id, u.user_id, u.func_name, u.class_name, u.type, u.arg_types, <include refid="baseSql">
u.database, u.description, u.resource_id, u.resource_name, u.create_time, u.update_time <property name="alias" value="udf"/>
from t_ds_udfs u,t_ds_relation_udfs_user rel </include>
WHERE u.id = rel.udf_id from t_ds_udfs udf,t_ds_relation_udfs_user rel
WHERE udf.id = rel.udf_id
AND rel.user_id = #{userId} AND rel.user_id = #{userId}
</select> </select>
<select id="listAuthorizedUdfFunc" resultType="org.apache.dolphinscheduler.dao.entity.UdfFunc"> <select id="listAuthorizedUdfFunc" resultType="org.apache.dolphinscheduler.dao.entity.UdfFunc">
select select
u.id, u.user_id, u.func_name, u.class_name, u.type, u.arg_types, <include refid="baseSql">
u.database, u.description, u.resource_id, u.resource_name, u.create_time, u.update_time <property name="alias" value="udf"/>
from t_ds_udfs u </include>
from t_ds_udfs udf
where where
id in (select udf_id from t_ds_relation_udfs_user where user_id=#{userId} udf.id in (select udf_id from t_ds_relation_udfs_user where user_id=#{userId}
union select id as udf_id from t_ds_udfs where user_id=#{userId}) union select id as udf_id from t_ds_udfs where user_id=#{userId})
<if test="udfIds != null and udfIds != ''"> <if test="udfIds != null and udfIds != ''">
and id in and udf.id in
<foreach collection="udfIds" item="i" open="(" close=")" separator=","> <foreach collection="udfIds" item="i" open="(" close=")" separator=",">
#{i} #{i}
</foreach> </foreach>
@ -101,12 +116,13 @@
</select> </select>
<select id="listUdfByResourceId" resultType="org.apache.dolphinscheduler.dao.entity.UdfFunc"> <select id="listUdfByResourceId" resultType="org.apache.dolphinscheduler.dao.entity.UdfFunc">
select select
u.id, u.user_id, u.func_name, u.class_name, u.type, u.arg_types, <include refid="baseSql">
u.database, u.description, u.resource_id, u.resource_name, u.create_time, u.update_time <property name="alias" value="udf"/>
from t_ds_udfs u </include>
from t_ds_udfs udf
where 1=1 where 1=1
<if test="resourceIds != null and resourceIds != ''"> <if test="resourceIds != null and resourceIds != ''">
and resource_id in and udf.resource_id in
<foreach collection="resourceIds" item="i" open="(" close=")" separator=","> <foreach collection="resourceIds" item="i" open="(" close=")" separator=",">
#{i} #{i}
</foreach> </foreach>
@ -114,14 +130,15 @@
</select> </select>
<select id="listAuthorizedUdfByResourceId" resultType="org.apache.dolphinscheduler.dao.entity.UdfFunc"> <select id="listAuthorizedUdfByResourceId" resultType="org.apache.dolphinscheduler.dao.entity.UdfFunc">
select select
u.id, u.user_id, u.func_name, u.class_name, u.type, u.arg_types, <include refid="baseSql">
u.database, u.description, u.resource_id, u.resource_name, u.create_time, u.update_time <property name="alias" value="udf"/>
from t_ds_udfs u </include>
from t_ds_udfs udf
where where
id in (select udf_id from t_ds_relation_udfs_user where user_id=#{userId} udf.id in (select udf_id from t_ds_relation_udfs_user where user_id=#{userId}
union select id as udf_id from t_ds_udfs where user_id=#{userId}) union select id as udf_id from t_ds_udfs where user_id=#{userId})
<if test="resourceIds != null and resourceIds != ''"> <if test="resourceIds != null and resourceIds != ''">
and resource_id in and udf.resource_id in
<foreach collection="resourceIds" item="i" open="(" close=")" separator=","> <foreach collection="resourceIds" item="i" open="(" close=")" separator=",">
#{i} #{i}
</foreach> </foreach>

30
dolphinscheduler-server/src/main/java/org/apache/dolphinscheduler/server/utils/ArgsUtils.java

@ -0,0 +1,30 @@
/*
* 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.server.utils;
public class ArgsUtils {
private ArgsUtils() throws IllegalStateException {
throw new IllegalStateException("Utility class");
}
public static String escape(String arg) {
return arg.replace(" ", "\\ ").replace("\"", "\\\"").replace("'", "\\'");
}
}

5
dolphinscheduler-server/src/main/java/org/apache/dolphinscheduler/server/utils/FlinkArgsUtils.java

@ -14,8 +14,8 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.apache.dolphinscheduler.server.utils;
package org.apache.dolphinscheduler.server.utils;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.apache.dolphinscheduler.common.Constants; import org.apache.dolphinscheduler.common.Constants;
@ -26,7 +26,6 @@ import org.apache.dolphinscheduler.common.task.flink.FlinkParameters;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
/** /**
* flink args utils * flink args utils
*/ */
@ -62,7 +61,7 @@ public class FlinkArgsUtils {
String appName = param.getAppName(); String appName = param.getAppName();
if (StringUtils.isNotEmpty(appName)) { //-ynm if (StringUtils.isNotEmpty(appName)) { //-ynm
args.add(Constants.FLINK_APP_NAME); args.add(Constants.FLINK_APP_NAME);
args.add(appName); args.add(ArgsUtils.escape(appName));
} }
// judge flink version,from flink1.10,the parameter -yn removed // judge flink version,from flink1.10,the parameter -yn removed

6
dolphinscheduler-server/src/main/java/org/apache/dolphinscheduler/server/utils/LogUtils.java

@ -25,8 +25,6 @@ import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.Optional; import java.util.Optional;
import javax.transaction.NotSupportedException;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import ch.qos.logback.classic.sift.SiftingAppender; import ch.qos.logback.classic.sift.SiftingAppender;
@ -35,8 +33,8 @@ import ch.qos.logback.core.spi.AppenderAttachable;
public class LogUtils { public class LogUtils {
private LogUtils() throws NotSupportedException { private LogUtils() throws IllegalStateException {
throw new NotSupportedException(); throw new IllegalStateException("Utility class");
} }
/** /**

14
dolphinscheduler-server/src/main/java/org/apache/dolphinscheduler/server/utils/ProcessUtils.java

@ -30,9 +30,6 @@ import org.apache.dolphinscheduler.remote.utils.Host;
import org.apache.dolphinscheduler.server.entity.TaskExecutionContext; import org.apache.dolphinscheduler.server.entity.TaskExecutionContext;
import org.apache.dolphinscheduler.service.log.LogClientService; import org.apache.dolphinscheduler.service.log.LogClientService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File; import java.io.File;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.ArrayList; import java.util.ArrayList;
@ -40,21 +37,28 @@ import java.util.List;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/** /**
* mainly used to get the start command line of a process. * mainly used to get the start command line of a process.
*/ */
public class ProcessUtils { public class ProcessUtils {
/** /**
* logger. * logger
*/ */
private static final Logger logger = LoggerFactory.getLogger(ProcessUtils.class); private static final Logger logger = LoggerFactory.getLogger(ProcessUtils.class);
/** /**
* Initialization regularization, solve the problem of pre-compilation performance, * Initialization regularization, solve the problem of pre-compilation performance,
* avoid the thread safety problem of multi-thread operation. * avoid the thread safety problem of multi-thread operation
*/ */
private static final Pattern MACPATTERN = Pattern.compile("-[+|-]-\\s(\\d+)"); private static final Pattern MACPATTERN = Pattern.compile("-[+|-]-\\s(\\d+)");
/**
* Expression of PID recognition in Windows scene
*/
private static final Pattern WINDOWSATTERN = Pattern.compile("(\\d+)"); private static final Pattern WINDOWSATTERN = Pattern.compile("(\\d+)");
private static final String LOCAL_PROCESS_EXEC = "jdk.lang.Process.allowAmbiguousCommands"; private static final String LOCAL_PROCESS_EXEC = "jdk.lang.Process.allowAmbiguousCommands";

13
dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/formModel/tasks/flink.vue

@ -89,7 +89,7 @@
type="input" type="input"
size="small" size="small"
v-model="appName" v-model="appName"
:placeholder="$t('Please enter the job name of Flink')" :placeholder="$t('Please enter the job name of Flink(optional)')"
style="width: 200px;"> style="width: 200px;">
</el-input> </el-input>
</span> </span>
@ -303,11 +303,6 @@
return false return false
} }
if (!this.appName) {
this.$message.warning(`${i18n.$t('Please enter the job name of Flink')}`)
return false
}
if (!this.jobManagerMemory) { if (!this.jobManagerMemory) {
this.$message.warning(`${i18n.$t('Please enter jobManager memory')}`) this.$message.warning(`${i18n.$t('Please enter jobManager memory')}`)
return false return false
@ -353,9 +348,9 @@
flinkVersion: this.flinkVersion, flinkVersion: this.flinkVersion,
slot: this.slot, slot: this.slot,
taskManager: this.taskManager, taskManager: this.taskManager,
appName: this.appName,
jobManagerMemory: this.jobManagerMemory, jobManagerMemory: this.jobManagerMemory,
taskManagerMemory: this.taskManagerMemory, taskManagerMemory: this.taskManagerMemory,
appName: this.appName,
mainArgs: this.mainArgs, mainArgs: this.mainArgs,
others: this.others, others: this.others,
programType: this.programType programType: this.programType
@ -489,9 +484,9 @@
localParams: this.localParams, localParams: this.localParams,
slot: this.slot, slot: this.slot,
taskManager: this.taskManager, taskManager: this.taskManager,
appName: this.appName,
jobManagerMemory: this.jobManagerMemory, jobManagerMemory: this.jobManagerMemory,
taskManagerMemory: this.taskManagerMemory, taskManagerMemory: this.taskManagerMemory,
appName: this.appName,
mainArgs: this.mainArgs, mainArgs: this.mainArgs,
others: this.others, others: this.others,
programType: this.programType programType: this.programType
@ -522,7 +517,7 @@
this.taskManager = o.params.taskManager || '2' this.taskManager = o.params.taskManager || '2'
this.jobManagerMemory = o.params.jobManagerMemory || '1G' this.jobManagerMemory = o.params.jobManagerMemory || '1G'
this.taskManagerMemory = o.params.taskManagerMemory || '2G' this.taskManagerMemory = o.params.taskManagerMemory || '2G'
this.appName = o.params.appName || ''
this.mainArgs = o.params.mainArgs || '' this.mainArgs = o.params.mainArgs || ''
this.others = o.params.others this.others = o.params.others
this.programType = o.params.programType || 'SCALA' this.programType = o.params.programType || 'SCALA'

2
dolphinscheduler-ui/src/js/module/i18n/locale/en_US.js

@ -108,7 +108,7 @@ export default {
'Driver memory use': 'Driver memory use', 'Driver memory use': 'Driver memory use',
'Please enter driver memory use': 'Please enter driver memory use', 'Please enter driver memory use': 'Please enter driver memory use',
'Number of Executors': 'Number of Executors', 'Number of Executors': 'Number of Executors',
'Please enter the job name of Flink': 'Please enter the job name of Flink', 'Please enter the job name of Flink(optional)': 'Please enter the job name of Flink(optional)',
'Please enter the number of Executor': 'Please enter the number of Executor', 'Please enter the number of Executor': 'Please enter the number of Executor',
'Executor memory': 'Executor memory', 'Executor memory': 'Executor memory',
'Please enter the Executor memory': 'Please enter the Executor memory', 'Please enter the Executor memory': 'Please enter the Executor memory',

2
dolphinscheduler-ui/src/js/module/i18n/locale/zh_CN.js

@ -106,7 +106,7 @@ export default {
'Driver memory use': 'Driver内存数', 'Driver memory use': 'Driver内存数',
'Please enter driver memory use': '请输入Driver内存数', 'Please enter driver memory use': '请输入Driver内存数',
'Number of Executors': 'Executor数量', 'Number of Executors': 'Executor数量',
'Please enter the job name of Flink': '请输入Flink任务名称', 'Please enter the job name of Flink(optional)': '请输入Flink任务名称(选填)',
'Please enter the number of Executor': '请输入Executor数量', 'Please enter the number of Executor': '请输入Executor数量',
'Executor memory': 'Executor内存数', 'Executor memory': 'Executor内存数',
'Please enter the Executor memory': '请输入Executor内存数', 'Please enter the Executor memory': '请输入Executor内存数',

6
pom.xml

@ -725,8 +725,10 @@
<include>**/api/exceptions/ApiExceptionHandlerTest.java</include> <include>**/api/exceptions/ApiExceptionHandlerTest.java</include>
<include>**/api/exceptions/ServiceExceptionTest.java</include> <include>**/api/exceptions/ServiceExceptionTest.java</include>
<include>**/api/interceptor/LoginHandlerInterceptorTest.java</include> <include>**/api/interceptor/LoginHandlerInterceptorTest.java</include>
<include>**/api/security/PasswordAuthenticatorTest.java</include> <include>**/api/security/impl/pwd/PasswordAuthenticatorTest.java</include>
<include>**/api/security/SecurityConfigTest.java</include> <include>**/api/security/impl/ldap/LdapAuthenticatorTest.java</include>
<include>**/api/security/SecurityConfigLDAPTest.java</include>
<include>**/api/security/SecurityConfigPasswordTest.java</include>
<include>**/api/service/AccessTokenServiceTest.java</include> <include>**/api/service/AccessTokenServiceTest.java</include>
<include>**/api/service/AlertGroupServiceTest.java</include> <include>**/api/service/AlertGroupServiceTest.java</include>
<include>**/api/service/BaseDAGServiceTest.java</include> <include>**/api/service/BaseDAGServiceTest.java</include>

Loading…
Cancel
Save