feat: error message support i18n (#271)
* feat: error message support i18n * fix: ut failed
This commit is contained in:
parent
afc7b18330
commit
421ebc8005
|
@ -5,8 +5,10 @@ import com.databasir.common.JsonData;
|
|||
import com.databasir.common.SystemException;
|
||||
import com.databasir.common.exception.Forbidden;
|
||||
import com.databasir.common.exception.InvalidTokenException;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.TypeMismatchException;
|
||||
import org.springframework.context.MessageSource;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
|
@ -30,15 +32,19 @@ import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExcep
|
|||
import javax.validation.ConstraintViolation;
|
||||
import javax.validation.ConstraintViolationException;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
|
||||
@RestControllerAdvice
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
public class DatabasirExceptionAdvice extends ResponseEntityExceptionHandler {
|
||||
|
||||
private final MessageSource messageSource;
|
||||
|
||||
@ExceptionHandler({ConstraintViolationException.class})
|
||||
public ResponseEntity<Object> handleConstraintViolationException(
|
||||
ConstraintViolationException constraintViolationException, WebRequest request) {
|
||||
ConstraintViolationException constraintViolationException, WebRequest request) {
|
||||
|
||||
String errorMsg = "";
|
||||
String path = getPath(request);
|
||||
|
@ -46,17 +52,20 @@ public class DatabasirExceptionAdvice extends ResponseEntityExceptionHandler {
|
|||
for (ConstraintViolation<?> item : violations) {
|
||||
errorMsg = item.getMessage();
|
||||
log.warn("ConstraintViolationException, request: {}, exception: {}, invalid value: {}",
|
||||
path, errorMsg, item.getInvalidValue());
|
||||
path, errorMsg, item.getInvalidValue());
|
||||
break;
|
||||
}
|
||||
return handleNon200Response(errorMsg, HttpStatus.BAD_REQUEST, path);
|
||||
}
|
||||
|
||||
@ExceptionHandler({InvalidTokenException.class})
|
||||
protected ResponseEntity<Object> handleInvalidTokenException(InvalidTokenException ex, WebRequest request) {
|
||||
protected ResponseEntity<Object> handleInvalidTokenException(InvalidTokenException ex,
|
||||
WebRequest request,
|
||||
Locale locale) {
|
||||
String path = getPath(request);
|
||||
log.warn("handle InvalidTokenException " + path + ", " + ex);
|
||||
JsonData<Object> data = JsonData.error(ex.getErrCode(), ex.getErrMessage());
|
||||
String msg = messageSource.getMessage(ex.getErrCode(), ex.getArgs(), locale);
|
||||
JsonData<Object> data = JsonData.error(ex.getErrCode(), msg);
|
||||
return handleNon200Response(ex.getMessage(), HttpStatus.UNAUTHORIZED, path, data);
|
||||
}
|
||||
|
||||
|
@ -82,17 +91,21 @@ public class DatabasirExceptionAdvice extends ResponseEntityExceptionHandler {
|
|||
}
|
||||
|
||||
@ExceptionHandler(value = DatabasirException.class)
|
||||
public ResponseEntity<Object> handleBusinessException(
|
||||
DatabasirException databasirException, WebRequest request) {
|
||||
public ResponseEntity<Object> handleBusinessException(DatabasirException databasirException,
|
||||
WebRequest request,
|
||||
Locale locale) {
|
||||
|
||||
String path = getPath(request);
|
||||
JsonData<Void> body = JsonData.error(databasirException.getErrCode(), databasirException.getErrMessage());
|
||||
String msg = messageSource.getMessage(databasirException.getErrCode(), databasirException.getArgs(), locale);
|
||||
JsonData<Void> body = JsonData.error(databasirException.getErrCode(), msg);
|
||||
if (databasirException.getCause() == null) {
|
||||
log.warn("BusinessException, request: {}, exception: {}", path, databasirException.getErrMessage());
|
||||
log.warn("BusinessException, request: {}, exception: {}", path, msg);
|
||||
} else {
|
||||
log.warn("BusinessException, request: " + path, databasirException);
|
||||
}
|
||||
return ResponseEntity.ok().body(body);
|
||||
return ResponseEntity.ok()
|
||||
.header("X-Error-Code", databasirException.getErrCode())
|
||||
.body(body);
|
||||
}
|
||||
|
||||
@ExceptionHandler({SystemException.class})
|
||||
|
@ -101,7 +114,7 @@ public class DatabasirExceptionAdvice extends ResponseEntityExceptionHandler {
|
|||
String path = getPath(request);
|
||||
if (systemException.getCause() != null) {
|
||||
log.error("SystemException, request: " + path
|
||||
+ ", exception: " + systemException.getMessage() + ", caused by:", systemException.getCause());
|
||||
+ ", exception: " + systemException.getMessage() + ", caused by:", systemException.getCause());
|
||||
} else {
|
||||
log.error("SystemException, request: " + path + ", exception: " + systemException.getMessage());
|
||||
}
|
||||
|
@ -119,7 +132,7 @@ public class DatabasirExceptionAdvice extends ResponseEntityExceptionHandler {
|
|||
|
||||
@Override
|
||||
public ResponseEntity<Object> handleBindException(
|
||||
BindException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
|
||||
BindException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
|
||||
|
||||
String errorMsg = buildMessages(ex.getBindingResult());
|
||||
log.warn("BindException, request: {}, exception: {}", getPath(request), errorMsg);
|
||||
|
@ -128,7 +141,7 @@ public class DatabasirExceptionAdvice extends ResponseEntityExceptionHandler {
|
|||
|
||||
@Override
|
||||
public ResponseEntity<Object> handleMethodArgumentNotValid(
|
||||
MethodArgumentNotValidException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
|
||||
MethodArgumentNotValidException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
|
||||
|
||||
String errorMsg = buildMessages(ex.getBindingResult());
|
||||
log.warn("MethodArgumentNotValidException, request: {}, exception: {}", getPath(request), errorMsg);
|
||||
|
@ -137,7 +150,7 @@ public class DatabasirExceptionAdvice extends ResponseEntityExceptionHandler {
|
|||
|
||||
@Override
|
||||
public ResponseEntity<Object> handleTypeMismatch(
|
||||
TypeMismatchException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
|
||||
TypeMismatchException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
|
||||
|
||||
log.warn("TypeMismatchException, request: {}, exception: {}", getPath(request), ex.getMessage());
|
||||
return handleOverriddenException(ex, headers, status, request, ex.getMessage());
|
||||
|
@ -145,16 +158,16 @@ public class DatabasirExceptionAdvice extends ResponseEntityExceptionHandler {
|
|||
|
||||
@Override
|
||||
public ResponseEntity<Object> handleMissingServletRequestParameter(
|
||||
MissingServletRequestParameterException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
|
||||
MissingServletRequestParameterException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
|
||||
|
||||
log.warn("MissingServletRequestParameterException, request: {}, exception: {}",
|
||||
getPath(request), ex.getMessage());
|
||||
getPath(request), ex.getMessage());
|
||||
return handleOverriddenException(ex, headers, status, request, ex.getMessage());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseEntity<Object> handleMissingServletRequestPart(
|
||||
MissingServletRequestPartException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
|
||||
MissingServletRequestPartException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
|
||||
|
||||
log.warn("MissingServletRequestPartException, request: {}, exception: {}", getPath(request), ex.getMessage());
|
||||
return handleOverriddenException(ex, headers, status, request, ex.getMessage());
|
||||
|
@ -162,7 +175,7 @@ public class DatabasirExceptionAdvice extends ResponseEntityExceptionHandler {
|
|||
|
||||
@Override
|
||||
public ResponseEntity<Object> handleHttpMessageNotReadable(
|
||||
HttpMessageNotReadableException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
|
||||
HttpMessageNotReadableException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
|
||||
|
||||
String errorMsg = ex.getMostSpecificCause().getMessage();
|
||||
|
||||
|
@ -172,7 +185,7 @@ public class DatabasirExceptionAdvice extends ResponseEntityExceptionHandler {
|
|||
|
||||
@Override
|
||||
public ResponseEntity<Object> handleServletRequestBindingException(
|
||||
ServletRequestBindingException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
|
||||
ServletRequestBindingException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
|
||||
|
||||
log.warn("ServletRequestBindingException, request: {}, exception: {}", getPath(request), ex.getMessage());
|
||||
return handleOverriddenException(ex, headers, status, request, ex.getMessage());
|
||||
|
@ -180,7 +193,7 @@ public class DatabasirExceptionAdvice extends ResponseEntityExceptionHandler {
|
|||
|
||||
@Override
|
||||
public ResponseEntity<Object> handleHttpRequestMethodNotSupported(
|
||||
HttpRequestMethodNotSupportedException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
|
||||
HttpRequestMethodNotSupportedException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
|
||||
|
||||
String errorMsg = ex.getMessage();
|
||||
log.warn("HttpRequestMethodNotSupportedException, request: {}, exception: {}", getPath(request), errorMsg);
|
||||
|
@ -222,7 +235,7 @@ public class DatabasirExceptionAdvice extends ResponseEntityExceptionHandler {
|
|||
}
|
||||
|
||||
private ResponseEntity<Object> handleOverriddenException(
|
||||
Exception ex, HttpHeaders headers, HttpStatus status, WebRequest request, String errorMsg) {
|
||||
Exception ex, HttpHeaders headers, HttpStatus status, WebRequest request, String errorMsg) {
|
||||
return handleExceptionInternal(ex, null, headers, status, request);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
package com.databasir.api.config.i18n;
|
||||
|
||||
import org.springframework.context.MessageSource;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.support.ResourceBundleMessageSource;
|
||||
import org.springframework.web.servlet.LocaleResolver;
|
||||
import org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
@Configuration
|
||||
public class I18nConfig {
|
||||
|
||||
@Bean
|
||||
public LocaleResolver localeResolver() {
|
||||
AcceptHeaderLocaleResolver localeResolver = new AcceptHeaderLocaleResolver();
|
||||
localeResolver.setDefaultLocale(Locale.CHINA);
|
||||
return localeResolver;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public MessageSource messageSource() {
|
||||
ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
|
||||
messageSource.setDefaultEncoding("UTF-8");
|
||||
messageSource.addBasenames("i18n.messages");
|
||||
return messageSource;
|
||||
}
|
||||
}
|
|
@ -5,14 +5,17 @@ import com.databasir.core.domain.DomainErrors;
|
|||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.context.MessageSource;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.web.AuthenticationEntryPoint;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.servlet.LocaleResolver;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Locale;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
|
@ -21,16 +24,22 @@ public class DatabasirAuthenticationEntryPoint implements AuthenticationEntryPoi
|
|||
|
||||
private final ObjectMapper objectMapper;
|
||||
|
||||
private final MessageSource messageSource;
|
||||
|
||||
private final LocaleResolver localeResolver;
|
||||
|
||||
@Override
|
||||
public void commence(javax.servlet.http.HttpServletRequest request,
|
||||
javax.servlet.http.HttpServletResponse response,
|
||||
AuthenticationException authException) throws IOException, ServletException {
|
||||
log.warn("验证未通过. 提示信息 - {} - {} - {}", request.getRequestURI(),
|
||||
authException.getClass().getName(),
|
||||
authException.getMessage());
|
||||
authException.getClass().getName(),
|
||||
authException.getMessage());
|
||||
|
||||
Locale locale = localeResolver.resolveLocale(request);
|
||||
DomainErrors err = DomainErrors.INVALID_ACCESS_TOKEN;
|
||||
JsonData<Void> data = JsonData.error(err.getErrCode(), err.getErrMessage());
|
||||
String msg = messageSource.getMessage(err.getErrCode(), err.exception().getArgs(), locale);
|
||||
JsonData<Void> data = JsonData.error(err.getErrCode(), msg);
|
||||
String jsonString = objectMapper.writeValueAsString(data);
|
||||
response.setStatus(HttpStatus.UNAUTHORIZED.value());
|
||||
response.getOutputStream().write(jsonString.getBytes(StandardCharsets.UTF_8));
|
||||
|
|
|
@ -6,6 +6,7 @@ import com.databasir.core.domain.log.service.OperationLogService;
|
|||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.context.MessageSource;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.security.authentication.BadCredentialsException;
|
||||
|
@ -13,12 +14,14 @@ import org.springframework.security.authentication.DisabledException;
|
|||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.servlet.LocaleResolver;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Locale;
|
||||
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
|
@ -29,6 +32,10 @@ public class DatabasirAuthenticationFailureHandler implements AuthenticationFail
|
|||
|
||||
private final OperationLogService operationLogService;
|
||||
|
||||
private final MessageSource messageSource;
|
||||
|
||||
private final LocaleResolver localeResolver;
|
||||
|
||||
@Override
|
||||
public void onAuthenticationFailure(HttpServletRequest request,
|
||||
HttpServletResponse response,
|
||||
|
@ -50,7 +57,9 @@ public class DatabasirAuthenticationFailureHandler implements AuthenticationFail
|
|||
response.getOutputStream().write(jsonString.getBytes(StandardCharsets.UTF_8));
|
||||
} else if (exception instanceof DatabasirAuthenticationException) {
|
||||
DatabasirAuthenticationException bizException = (DatabasirAuthenticationException) exception;
|
||||
JsonData<Void> data = JsonData.error(bizException.getErrCode(), bizException.getErrMessage());
|
||||
Locale locale = localeResolver.resolveLocale(request);
|
||||
String msg = messageSource.getMessage(bizException.getErrCode(), bizException.getArgs(), locale);
|
||||
JsonData<Void> data = JsonData.error(bizException.getErrCode(), msg);
|
||||
saveLoginFailedLog(username, data.getErrMessage());
|
||||
String jsonString = objectMapper.writeValueAsString(data);
|
||||
response.setStatus(HttpStatus.OK.value());
|
||||
|
|
|
@ -27,7 +27,7 @@ public class CronExpressionValidator {
|
|||
try {
|
||||
new CronExpression(cron);
|
||||
} catch (ParseException pe) {
|
||||
throw DomainErrors.INVALID_CRON_EXPRESSION.exception("错误的 CRON 表达式:" + pe.getMessage(), pe);
|
||||
throw DomainErrors.INVALID_CRON_EXPRESSION.exception(pe);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,23 +2,23 @@ package com.databasir.api.validator;
|
|||
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import static com.databasir.core.domain.DomainErrors.INVALID_DATABASE_TYPE_URL_PATTERN;
|
||||
import static com.databasir.core.domain.DomainErrors.*;
|
||||
|
||||
@Component
|
||||
public class DatabaseTypeValidator {
|
||||
|
||||
public void isValidUrlPattern(String urlPattern) {
|
||||
if (urlPattern == null) {
|
||||
throw INVALID_DATABASE_TYPE_URL_PATTERN.exception("url pattern 不能为空");
|
||||
throw INVALID_DATABASE_TYPE_URL_PATTERN.exception();
|
||||
}
|
||||
if (!urlPattern.contains("{{jdbc.protocol}}")) {
|
||||
throw INVALID_DATABASE_TYPE_URL_PATTERN.exception("必须包含变量{{jdbc.protocol}}");
|
||||
throw MISS_JDBC_PROTOCOL.exception();
|
||||
}
|
||||
if (!urlPattern.contains("{{db.url}}")) {
|
||||
throw INVALID_DATABASE_TYPE_URL_PATTERN.exception("必须包含变量{{db.url}}不能为空");
|
||||
throw MISS_DB_URL.exception();
|
||||
}
|
||||
if (!urlPattern.contains("{{db.schema}}") && !urlPattern.contains("{{db.name}}")) {
|
||||
throw INVALID_DATABASE_TYPE_URL_PATTERN.exception("{{db.schema}} 和 {{db.name}} 至少设置一个");
|
||||
throw MISS_DB_SCHEMA.exception();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
# token
|
||||
X_0001=token expired
|
||||
X_0002=token invalid
|
||||
X_0004=access token invalid
|
||||
error.refresh-token.expired=token expired
|
||||
error.refresh-token.invalid=token invalid
|
||||
error.access-token.invalid=token invalid
|
||||
# common
|
||||
error.network.timeout=network timeout, please try later
|
||||
error.parameter.required=miss required parameter,{0}
|
||||
# database
|
||||
error.database.metadata.get-failed=get database info failed
|
||||
error.database.connect-failed=connect to database faeild
|
||||
error.database.type.not-supported=not support database type, please check project configuration
|
||||
error.database.type.name-duplicate=database type name duplicate
|
||||
error.database.type.must-not-modify-default-type=forbidden operation
|
||||
error.database.driver.download-failed=download driver failed
|
||||
error.database.driver.class-not-found=driver class not found
|
||||
error.database.driver.upload-failed=upload driver failed
|
||||
error.database.driver.url-or-path-invalid=driver url or path invalid
|
||||
error.database.driver.load-failed=load driver failed
|
||||
error.database.url-pattern.invalid=invalid url pattern
|
||||
error.database.url-patter.miss-db-url=must include {{db.url}} variable
|
||||
error.database.url-patter.miss-protocol=must include {{jdbc.protocol}} variable
|
||||
error.database.url-patter.miss-db-schema=must include {{db.schema}} or {{db.name}}
|
||||
# document
|
||||
error.document.version-invalid=invalid document version
|
||||
error.document.version-duplicate=document version duplicate
|
||||
error.document.table.not-found=table not found
|
||||
# user
|
||||
error.user.password.must-not-be-blank=password must not be blank
|
||||
error.user.password.not-match=password not match
|
||||
error.user.password.invalid=password not right
|
||||
error.user.username-or-email-duplicate=username or email duplicate
|
||||
error.user.role.duplicate=role duplicate
|
||||
error.user.role.must-not-update-self=forbidden operation
|
||||
error.user.must-not-enable-self=forbidden operation
|
||||
error.user.must-not-delete-self=forbidden operation
|
||||
# project
|
||||
error.project.not-found=project not found
|
||||
error.project.name-duplicate=duplicate project name
|
||||
error.project.cron-invalid=invalid cron expression
|
||||
# login-app
|
||||
error.login.app.registration-id-duplicate=duplicate registration ID
|
||||
error.login.app.registration-id-not-found=not found registration ID
|
||||
error.login.app.miss-redirect-uri=miss parameter: redirect_uri
|
||||
# mock script
|
||||
error.script.mock.is-blank=mock script must not be blank
|
||||
error.script.mock.dependent-column-name-required=miss required reference
|
||||
error.script.mock.dependent-must-not-ref-self=should not ref to self
|
||||
error.script.mock.dependent-circle-reference=circle reference
|
||||
error.script.mock.expression-invalid=invalid expression
|
|
@ -0,0 +1,52 @@
|
|||
# token
|
||||
X_0001=token 过期
|
||||
X_0002=tokena 无效
|
||||
X_0004=access token 无效
|
||||
error.refresh-token.expired=token expired
|
||||
error.refresh-token.invalid=token invalid
|
||||
error.access-token.invalid=token invalid
|
||||
# common
|
||||
error.network.timeout=网络不稳定,请稍后重试
|
||||
error.parameter.required=缺少必要的参数:{0}
|
||||
# database
|
||||
error.database.metadata.get-failed=数据库信息获取失败
|
||||
error.database.connect-failed=数据库连接失败
|
||||
error.database.type.not-supported=不支持得数据库类型,请检查配置
|
||||
error.database.type.name-duplicate=数据库类型名称重复
|
||||
error.database.type.must-not-modify-default-type=禁止删除系统默认得数据库类型
|
||||
error.database.driver.download-failed=驱动下载失败
|
||||
error.database.driver.class-not-found=驱动类加载失败,请检查是否为合法的 JDBC 驱动
|
||||
error.database.driver.upload-failed=驱动上传失败
|
||||
error.database.driver.url-or-path-invalid=请手动上传或指定驱动下载 URL
|
||||
error.database.driver.load-failed=驱动加载失败
|
||||
error.database.url-pattern.invalid=不合法得 url 表达式
|
||||
error.database.url-patter.miss-db-url=非法的 url 表达式: 缺少 {{db.url}}
|
||||
error.database.url-patter.miss-protocol=非法的 url 表达式: 缺少 {{jdbc.protocol}}
|
||||
error.database.url-patter.miss-db-schema=非法的 url 表达式: {{db.schema}} 和 {{db.name}} 至少指定一个
|
||||
# document
|
||||
error.document.version-invalid=文档版本不合法
|
||||
error.document.version-duplicate=文档版本重复
|
||||
error.document.table.not-found=找不到表信息
|
||||
# user
|
||||
error.user.password.must-not-be-blank=密码不能为空
|
||||
error.user.password.not-match=密码不匹配
|
||||
error.user.password.invalid=密码错误
|
||||
error.user.username-or-email-duplicate=用户名或邮箱重复
|
||||
error.user.role.duplicate=角色重复
|
||||
error.user.role.must-not-update-self=禁止的操作
|
||||
error.user.must-not-enable-self=禁止的操作
|
||||
error.user.must-not-delete-self=禁止的操作
|
||||
# project
|
||||
error.project.not-found=项目不存在
|
||||
error.project.name-duplicate=项目名称重复
|
||||
error.project.cron-invalid=非法的 cron 表达式
|
||||
# login-app
|
||||
error.login.app.registration-id-duplicate=registration ID 重复
|
||||
error.login.app.registration-id-not-found=registration ID 不存在
|
||||
error.login.app.miss-redirect-uri=缺少 redirect_uri
|
||||
# mock script
|
||||
error.script.mock.is-blank=表达式不能为空
|
||||
error.script.mock.dependent-column-name-required=请指定列
|
||||
error.script.mock.dependent-must-not-ref-self=禁止引用自身
|
||||
error.script.mock.dependent-circle-reference=检测到循环依赖
|
||||
error.script.mock.expression-invalid=非法的表达式
|
|
@ -4,5 +4,4 @@ public interface DatabasirErrors {
|
|||
|
||||
String getErrCode();
|
||||
|
||||
String getErrMessage();
|
||||
}
|
||||
|
|
|
@ -13,27 +13,15 @@ public class DatabasirException extends RuntimeException {
|
|||
private String errCode;
|
||||
|
||||
@Getter
|
||||
private String errMessage;
|
||||
private Object[] args = new Object[0];
|
||||
|
||||
/**
|
||||
* @param errorCodeMessage 错误信息
|
||||
*/
|
||||
public DatabasirException(DatabasirErrors errorCodeMessage) {
|
||||
super(errorCodeMessage.getErrMessage());
|
||||
super(errorCodeMessage.getErrCode());
|
||||
this.errorCodeMessage = errorCodeMessage;
|
||||
this.errCode = errorCodeMessage.getErrCode();
|
||||
this.errMessage = errorCodeMessage.getErrMessage();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param errorCodeMessage 错误信息
|
||||
* @param overrideMessage 覆盖 message
|
||||
*/
|
||||
public DatabasirException(DatabasirErrors errorCodeMessage, String overrideMessage) {
|
||||
super(overrideMessage);
|
||||
this.errorCodeMessage = errorCodeMessage;
|
||||
this.errCode = errorCodeMessage.getErrCode();
|
||||
this.errMessage = overrideMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -41,16 +29,21 @@ public class DatabasirException extends RuntimeException {
|
|||
* @param cause root cause
|
||||
*/
|
||||
public DatabasirException(DatabasirErrors errorCodeMessage, Throwable cause) {
|
||||
super(errorCodeMessage.getErrMessage(), cause);
|
||||
super(errorCodeMessage.getErrCode(), cause);
|
||||
this.errorCodeMessage = errorCodeMessage;
|
||||
this.errCode = errorCodeMessage.getErrCode();
|
||||
this.errMessage = errorCodeMessage.getErrMessage();
|
||||
}
|
||||
|
||||
public DatabasirException(DatabasirErrors errorCodeMessage, Object... args) {
|
||||
super(errorCodeMessage.getErrCode());
|
||||
this.errorCodeMessage = errorCodeMessage;
|
||||
this.errCode = errorCodeMessage.getErrCode();
|
||||
this.args = args;
|
||||
}
|
||||
|
||||
public DatabasirException(DatabasirErrors errorCodeMessage, String overrideMessage, Throwable cause) {
|
||||
super(overrideMessage, cause);
|
||||
this.errorCodeMessage = errorCodeMessage;
|
||||
this.errCode = errorCodeMessage.getErrCode();
|
||||
this.errMessage = overrideMessage;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,16 +9,8 @@ public class InvalidTokenException extends DatabasirException {
|
|||
super(errorCodeMessage);
|
||||
}
|
||||
|
||||
public InvalidTokenException(DatabasirErrors errorCodeMessage, String overrideMessage) {
|
||||
super(errorCodeMessage, overrideMessage);
|
||||
}
|
||||
|
||||
public InvalidTokenException(DatabasirErrors errorCodeMessage, Throwable cause) {
|
||||
super(errorCodeMessage, cause);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getErrCode() + ": " + getErrMessage();
|
||||
return "InvalidTokenException:" + getErrCode();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,53 +8,58 @@ import lombok.RequiredArgsConstructor;
|
|||
@RequiredArgsConstructor
|
||||
@Getter
|
||||
public enum DomainErrors implements DatabasirErrors {
|
||||
REFRESH_TOKEN_EXPIRED("X_0001", "refresh token expired"),
|
||||
INVALID_REFRESH_TOKEN_OPERATION("X_0002", "invalid refresh token operation"),
|
||||
NETWORK_ERROR("X_0003", "网络似乎不稳定,请稍后再试"),
|
||||
INVALID_ACCESS_TOKEN("X_0004", "无效的 access token"),
|
||||
REFRESH_TOKEN_EXPIRED("X_0001"),
|
||||
INVALID_REFRESH_TOKEN_OPERATION("X_0002"),
|
||||
NETWORK_ERROR("error.network.timeout"),
|
||||
INVALID_ACCESS_TOKEN("X_0004"),
|
||||
MISS_REQUIRED_PARAMETERS("error.parameter.required"),
|
||||
|
||||
NOT_SUPPORT_DATABASE_TYPE("A_10000", "不支持的数据库类型, 请检查项目配置"),
|
||||
PROJECT_NOT_FOUND("A_10001", "项目不存在"),
|
||||
DATABASE_META_NOT_FOUND("A_10002", "获取数据库信息失败"),
|
||||
CONNECT_DATABASE_FAILED("A_10003", "连接数据库失败,请检查连接配置"),
|
||||
GROUP_OWNER_MUST_NOT_BE_EMPTY("A_10004", "请至少指定一个分组组长"),
|
||||
PASSWORD_MUST_NOT_BE_BLANK("A_10005", "密码不能为空"),
|
||||
USERNAME_OR_EMAIL_DUPLICATE("A_10006", "用户名或邮箱已存在"),
|
||||
USER_ROLE_DUPLICATE("A_10007", "用户角色已存在"),
|
||||
PROJECT_NAME_DUPLICATE("A_10008", "项目名称已被占用"),
|
||||
CANNOT_UPDATE_SELF_ROLE("A_10009", "无法对自己执行角色变更的操作"),
|
||||
UPDATE_PASSWORD_CONFIRM_FAILED("A_10010", "两次密码输入不一致"),
|
||||
ORIGIN_PASSWORD_NOT_CORRECT("A_10011", "原密码不正确"),
|
||||
INVALID_CRON_EXPRESSION("A_10012", "不合法的 cron 表达式"),
|
||||
REGISTRATION_ID_DUPLICATE("A_10013", "应用注册 ID 不能重复"),
|
||||
REGISTRATION_ID_NOT_FOUND("A_10014", "应用 ID 不存在"),
|
||||
MISS_REQUIRED_PARAMETERS("A_10015", "缺少必填参数"),
|
||||
DATABASE_TYPE_NAME_DUPLICATE("A_10016", "数据库类型名已存在"),
|
||||
MUST_NOT_MODIFY_SYSTEM_DEFAULT_DATABASE_TYPE("A_10017", "禁止修改系统默认数据库类型"),
|
||||
DOWNLOAD_DRIVER_ERROR("A_10018", "驱动下载失败"),
|
||||
INVALID_DATABASE_TYPE_URL_PATTERN("A_10019", "不合法的 url pattern"),
|
||||
DOCUMENT_VERSION_IS_INVALID("A_10020", "文档版本不合法"),
|
||||
CANNOT_UPDATE_SELF_ENABLED_STATUS("A_10021", "无法对自己执行启用禁用操作"),
|
||||
MOCK_DATA_SCRIPT_MUST_NOT_BE_BLANK("A_10022", "脚本内容不能为空"),
|
||||
TABLE_META_NOT_FOUND("A_10023", "不存在的数据库表"),
|
||||
DEPENDENT_COLUMN_NAME_MUST_NOT_BE_BLANK("A_10024", "必须指定依赖的字段"),
|
||||
DEPENDENT_REF_MUST_NOT_BE_BLANK("A_10025", "请选择关联表和字段"),
|
||||
MUST_NOT_REF_SELF("A_10026", "不能引用自身"),
|
||||
CIRCLE_REFERENCE("A_10027", "检查到循环引用"),
|
||||
DUPLICATE_COLUMN("A_10028", "重复的列"),
|
||||
INVALID_MOCK_DATA_SCRIPT("A_10029", "不合法的表达式"),
|
||||
CANNOT_DELETE_SELF("A_10030", "无法对自己执行删除账号操作"),
|
||||
DRIVER_CLASS_NOT_FOUND("A_10031", "获取驱动类名失败"),
|
||||
DATABASE_DOCUMENT_DUPLICATE_KEY("A_10032", "文档版本重复"),
|
||||
UPLOAD_DRIVER_FILE_ERROR("A_10033", "上传失败,请检查后重新上传"),
|
||||
DRIVER_URL_AND_PATH_MUST_NOT_BE_ALL_BLANK("A_10034", "请填写下载驱动的地址或手动上传驱动文件"),
|
||||
LOAD_DRIVER_FAILED("A_10045", "驱动加载失败,请检查后重试")
|
||||
DATABASE_META_NOT_FOUND("error.database.metadata.get-failed"),
|
||||
DATABASE_CONNECT_FAILED("error.database.connect-failed"),
|
||||
DATABASE_TYPE_NOT_SUPPORT("error.database.type.not-supported"),
|
||||
DATABASE_TYPE_NAME_DUPLICATE("error.database.type.name-duplicate"),
|
||||
DATABASE_MUST_NOT_MODIFY_SYSTEM_DEFAULT_TYPE("error.database.type.must-not-modify-default-type"),
|
||||
|
||||
DRIVER_UPLOAD_FAILED("error.database.driver.upload-failed"),
|
||||
DRIVER_URL_AND_PATH_MUST_NOT_BE_ALL_BLANK("error.database.driver.url-or-path-invalid"),
|
||||
DRIVER_LOAD_FAILED("error.database.driver.load-failed"),
|
||||
DRIVER_CLASS_NOT_FOUND("error.database.driver.class-not-found"),
|
||||
DRIVER_DOWNLOAD_FAILED("error.database.driver.download-failed"),
|
||||
INVALID_DATABASE_TYPE_URL_PATTERN("error.database.url-pattern.invalid"),
|
||||
MISS_DB_URL("error.database.url-patter.miss-db-url"),
|
||||
MISS_JDBC_PROTOCOL("error.database.url-patter.miss-protocol"),
|
||||
MISS_DB_SCHEMA("error.database.url-patter.miss-db-schema"),
|
||||
|
||||
PASSWORD_MUST_NOT_BE_BLANK("error.user.password.must-not-be-blank"),
|
||||
USERNAME_OR_EMAIL_DUPLICATE("error.user.username-or-email-duplicate"),
|
||||
USER_ROLE_DUPLICATE("error.user.role.duplicate"),
|
||||
UPDATE_PASSWORD_CONFIRM_FAILED("error.user.password.not-match"),
|
||||
CANNOT_DELETE_SELF("error.user.must-not-delete-self"),
|
||||
ORIGIN_PASSWORD_NOT_CORRECT("error.user.password.invalid"),
|
||||
CANNOT_UPDATE_SELF_ROLE("error.user.role.must-not-update-self"),
|
||||
CANNOT_UPDATE_SELF_ENABLED_STATUS("error.user.role.must-not-update-self"),
|
||||
|
||||
PROJECT_NOT_FOUND("error.project.not-found"),
|
||||
PROJECT_NAME_DUPLICATE("error.project.name-duplicate"),
|
||||
INVALID_CRON_EXPRESSION("error.project.cron-invalid"),
|
||||
|
||||
REGISTRATION_ID_DUPLICATE("error.login.app.registration-id-duplicate"),
|
||||
REGISTRATION_ID_NOT_FOUND("error.login.app.registration-id-not-found"),
|
||||
MISS_REDIRECT_URI("error.login.app.miss-redirect-uri"),
|
||||
|
||||
DOCUMENT_VERSION_IS_INVALID("error.document.version-invalid"),
|
||||
DATABASE_DOCUMENT_DUPLICATE_KEY("error.document.version-duplicate"),
|
||||
TABLE_META_NOT_FOUND("error.document.table.not-found"),
|
||||
|
||||
INVALID_MOCK_DATA_SCRIPT("error.script.mock.expression-invalid"),
|
||||
MOCK_DATA_SCRIPT_MUST_NOT_BE_BLANK("error.script.mock.is-blank"),
|
||||
DEPENDENT_COLUMN_NAME_MUST_NOT_BE_BLANK("error.script.mock.dependent-column-name-required"),
|
||||
MUST_NOT_REF_SELF("error.script.mock.dependent-must-not-ref-self"),
|
||||
CIRCLE_REFERENCE("error.script.mock.dependent-circle-reference"),
|
||||
;
|
||||
|
||||
private final String errCode;
|
||||
|
||||
private final String errMessage;
|
||||
|
||||
public DatabasirException exception() {
|
||||
return new DatabasirException(this);
|
||||
}
|
||||
|
@ -63,11 +68,7 @@ public enum DomainErrors implements DatabasirErrors {
|
|||
return new DatabasirException(this, origin);
|
||||
}
|
||||
|
||||
public DatabasirException exception(String message, Throwable origin) {
|
||||
return new DatabasirException(this, message, origin);
|
||||
}
|
||||
|
||||
public DatabasirException exception(String s) {
|
||||
return exception(s, null);
|
||||
return new DatabasirException(this, s);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,15 +10,16 @@ public class DatabasirAuthenticationException extends AuthenticationException {
|
|||
private final DatabasirException databasirException;
|
||||
|
||||
public DatabasirAuthenticationException(DatabasirException databasirException) {
|
||||
super(databasirException.getErrMessage(), databasirException);
|
||||
super(databasirException.getErrCode(), databasirException);
|
||||
this.databasirException = databasirException;
|
||||
}
|
||||
|
||||
public String getErrMessage() {
|
||||
return databasirException.getErrMessage();
|
||||
}
|
||||
|
||||
public String getErrCode() {
|
||||
return databasirException.getErrCode();
|
||||
}
|
||||
|
||||
public Object[] getArgs() {
|
||||
return databasirException.getArgs();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ public class GitlabOpenAuthHandler implements OpenAuthHandler {
|
|||
List<OauthAppProperty> properties,
|
||||
Map<String, String[]> params) {
|
||||
if (!params.containsKey("redirect_uri")) {
|
||||
throw DomainErrors.MISS_REQUIRED_PARAMETERS.exception("缺少参数 redirect_uri", null);
|
||||
throw DomainErrors.MISS_REDIRECT_URI.exception();
|
||||
}
|
||||
|
||||
String authUrl = CommonProperties.INSTANCE.getAuthHost(properties);
|
||||
|
@ -40,15 +40,15 @@ public class GitlabOpenAuthHandler implements OpenAuthHandler {
|
|||
String authorizeUrl = authUrl + "/oauth/authorize";
|
||||
String redirectUri = params.get("redirect_uri")[0];
|
||||
UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(authorizeUrl)
|
||||
.queryParam("client_id", clientId)
|
||||
.queryParam("redirect_uri", redirectUri)
|
||||
.queryParam("state", redirectUri)
|
||||
.queryParam("response_type", "code")
|
||||
.queryParam("scope", "read_user");
|
||||
.queryParam("client_id", clientId)
|
||||
.queryParam("redirect_uri", redirectUri)
|
||||
.queryParam("state", redirectUri)
|
||||
.queryParam("response_type", "code")
|
||||
.queryParam("scope", "read_user");
|
||||
return builder
|
||||
.encode()
|
||||
.build()
|
||||
.toUriString();
|
||||
.encode()
|
||||
.build()
|
||||
.toUriString();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -56,7 +56,7 @@ public class GitlabOpenAuthHandler implements OpenAuthHandler {
|
|||
List<OauthAppProperty> properties,
|
||||
Map<String, String[]> requestParams) {
|
||||
if (!requestParams.containsKey("redirect_uri")) {
|
||||
throw DomainErrors.MISS_REQUIRED_PARAMETERS.exception("缺少参数 redirect_uri", null);
|
||||
throw DomainErrors.MISS_REDIRECT_URI.exception();
|
||||
}
|
||||
|
||||
String url = CommonProperties.INSTANCE.getAuthHost(properties);
|
||||
|
@ -66,7 +66,7 @@ public class GitlabOpenAuthHandler implements OpenAuthHandler {
|
|||
String clientId = CommonProperties.INSTANCE.get(properties, GitlabProperties.CLIENT_ID);
|
||||
String secret = CommonProperties.INSTANCE.get(properties, GitlabProperties.CLIENT_SECRET);
|
||||
JsonNode accessTokenData =
|
||||
gitlabRemoteService.getAccessToken(url, code, clientId, secret, redirectUri);
|
||||
gitlabRemoteService.getAccessToken(url, code, clientId, secret, redirectUri);
|
||||
if (accessTokenData == null) {
|
||||
throw new DatabasirAuthenticationException(DomainErrors.NETWORK_ERROR.exception());
|
||||
}
|
||||
|
|
|
@ -36,13 +36,13 @@ public class WeWorkOpenAuthHandler implements OpenAuthHandler {
|
|||
String authUrl = INSTANCE.getAuthHost(properties);
|
||||
String authorizeUrl = authUrl + "/wwopen/sso/qrConnect";
|
||||
UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(authorizeUrl)
|
||||
.queryParam("appid", INSTANCE.get(properties, WeWorkProperties.APP_ID))
|
||||
.queryParam("agentid", INSTANCE.get(properties, WeWorkProperties.AGENT_ID))
|
||||
.queryParam("redirect_uri", INSTANCE.get(properties, WeWorkProperties.REDIRECT_URL));
|
||||
.queryParam("appid", INSTANCE.get(properties, WeWorkProperties.APP_ID))
|
||||
.queryParam("agentid", INSTANCE.get(properties, WeWorkProperties.AGENT_ID))
|
||||
.queryParam("redirect_uri", INSTANCE.get(properties, WeWorkProperties.REDIRECT_URL));
|
||||
String url = builder
|
||||
.encode()
|
||||
.build()
|
||||
.toUriString();
|
||||
.encode()
|
||||
.build()
|
||||
.toUriString();
|
||||
return url;
|
||||
}
|
||||
|
||||
|
@ -51,7 +51,7 @@ public class WeWorkOpenAuthHandler implements OpenAuthHandler {
|
|||
List<OauthAppProperty> properties,
|
||||
Map<String, String[]> requestParams) {
|
||||
if (!requestParams.containsKey("redirect_uri")) {
|
||||
throw DomainErrors.MISS_REQUIRED_PARAMETERS.exception("缺少参数 redirect_uri", null);
|
||||
throw DomainErrors.MISS_REDIRECT_URI.exception();
|
||||
}
|
||||
String code = requestParams.get("code")[0];
|
||||
|
||||
|
|
|
@ -23,47 +23,43 @@ public class OauthPropertiesValidator {
|
|||
|
||||
public void validate(OAuthAppCreateRequest request, List<OAuthAppPlatformResponse> platforms) {
|
||||
Map<String, OauthAppPropertyData> propertyMapByName = request.getProperties()
|
||||
.stream()
|
||||
.collect(Collectors.toMap(OauthAppPropertyData::getName, i -> i));
|
||||
.stream()
|
||||
.collect(Collectors.toMap(OauthAppPropertyData::getName, i -> i));
|
||||
platforms.stream()
|
||||
.filter(platform -> platform.getAuthAppType() == request.getAppType())
|
||||
.forEach(platform -> {
|
||||
List<OAuthAppPlatformProperty> properties = platform.getProperties();
|
||||
properties.forEach(property -> {
|
||||
if (Objects.equals(true, property.getRequired())) {
|
||||
if (!propertyMapByName.containsKey(property.getName())) {
|
||||
throw DomainErrors.MISS_REQUIRED_PARAMETERS.exception(
|
||||
property.getLabel() + " 不能为空");
|
||||
}
|
||||
if (StringUtils.isBlank(propertyMapByName.get(property.getName()).getValue())) {
|
||||
throw DomainErrors.MISS_REQUIRED_PARAMETERS.exception(
|
||||
property.getLabel() + " 不能为空");
|
||||
}
|
||||
.filter(platform -> platform.getAuthAppType() == request.getAppType())
|
||||
.forEach(platform -> {
|
||||
List<OAuthAppPlatformProperty> properties = platform.getProperties();
|
||||
properties.forEach(property -> {
|
||||
if (Objects.equals(true, property.getRequired())) {
|
||||
if (!propertyMapByName.containsKey(property.getName())) {
|
||||
throw DomainErrors.MISS_REQUIRED_PARAMETERS.exception(property.getLabel());
|
||||
}
|
||||
});
|
||||
if (StringUtils.isBlank(propertyMapByName.get(property.getName()).getValue())) {
|
||||
throw DomainErrors.MISS_REQUIRED_PARAMETERS.exception(property.getLabel());
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public void validate(OAuthAppUpdateRequest request, List<OAuthAppPlatformResponse> platforms) {
|
||||
Map<String, OauthAppPropertyData> propertyMapByName = request.getProperties()
|
||||
.stream()
|
||||
.collect(Collectors.toMap(OauthAppPropertyData::getName, i -> i));
|
||||
.stream()
|
||||
.collect(Collectors.toMap(OauthAppPropertyData::getName, i -> i));
|
||||
platforms.stream()
|
||||
.filter(platform -> platform.getAuthAppType() == request.getAppType())
|
||||
.forEach(platform -> {
|
||||
List<OAuthAppPlatformProperty> properties = platform.getProperties();
|
||||
properties.forEach(property -> {
|
||||
if (Objects.equals(true, property.getRequired())) {
|
||||
if (!propertyMapByName.containsKey(property.getName())) {
|
||||
throw DomainErrors.MISS_REQUIRED_PARAMETERS.exception(
|
||||
property.getLabel() + " 不能为空");
|
||||
}
|
||||
if (StringUtils.isBlank(propertyMapByName.get(property.getName()).getValue())) {
|
||||
throw DomainErrors.MISS_REQUIRED_PARAMETERS.exception(
|
||||
property.getLabel() + " 不能为空");
|
||||
}
|
||||
.filter(platform -> platform.getAuthAppType() == request.getAppType())
|
||||
.forEach(platform -> {
|
||||
List<OAuthAppPlatformProperty> properties = platform.getProperties();
|
||||
properties.forEach(property -> {
|
||||
if (Objects.equals(true, property.getRequired())) {
|
||||
if (!propertyMapByName.containsKey(property.getName())) {
|
||||
throw DomainErrors.MISS_REQUIRED_PARAMETERS.exception(property.getLabel());
|
||||
}
|
||||
});
|
||||
if (StringUtils.isBlank(propertyMapByName.get(property.getName()).getValue())) {
|
||||
throw DomainErrors.MISS_REQUIRED_PARAMETERS.exception(property.getLabel());
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -114,7 +114,7 @@ public class DatabaseTypeService {
|
|||
public void deleteById(Integer id) {
|
||||
databaseTypeDao.selectOptionalById(id).ifPresent(data -> {
|
||||
if (DatabaseTypes.has(data.getDatabaseType())) {
|
||||
throw DomainErrors.MUST_NOT_MODIFY_SYSTEM_DEFAULT_DATABASE_TYPE.exception();
|
||||
throw DomainErrors.DATABASE_MUST_NOT_MODIFY_SYSTEM_DEFAULT_TYPE.exception();
|
||||
}
|
||||
databaseTypeDao.deleteById(id);
|
||||
driverResources.deleteByDatabaseType(data.getDatabaseType());
|
||||
|
@ -172,7 +172,7 @@ public class DatabaseTypeService {
|
|||
return path;
|
||||
} catch (IOException e) {
|
||||
log.error("upload driver file error", e);
|
||||
throw DomainErrors.UPLOAD_DRIVER_FILE_ERROR.exception();
|
||||
throw DomainErrors.DRIVER_UPLOAD_FAILED.exception();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import com.databasir.core.meta.data.*;
|
|||
import com.databasir.dao.tables.pojos.*;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.Mapping;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
@ -16,6 +17,8 @@ import java.util.stream.Collectors;
|
|||
@Mapper(componentModel = "spring", uses = JsonConverter.class)
|
||||
public interface DatabaseMetaConverter {
|
||||
|
||||
public static final DatabaseMetaConverter converter = Mappers.getMapper(DatabaseMetaConverter.class);
|
||||
|
||||
default DatabaseMeta of(DatabaseDocument database,
|
||||
List<TableDocument> tables,
|
||||
List<TableColumnDocument> columns,
|
||||
|
|
|
@ -112,7 +112,7 @@ public class DocumentSyncService {
|
|||
databasirConfig.setIgnoreTableColumnNameRegex(jsonConverter.fromJson(rule.getIgnoreColumnNameRegexArray()));
|
||||
try {
|
||||
if (jdbcConnection == null) {
|
||||
throw DomainErrors.CONNECT_DATABASE_FAILED.exception();
|
||||
throw DomainErrors.DATABASE_CONNECT_FAILED.exception();
|
||||
}
|
||||
DatabaseMeta databaseMeta = Databasir.of(databasirConfig)
|
||||
.get(jdbcConnection, dataSource.getDatabaseName(), dataSource.getSchemaName())
|
||||
|
|
|
@ -42,9 +42,9 @@ public class MockDataValidator {
|
|||
|
||||
public TableDocument validAndGetTableDocument(Integer databaseDocId, Integer tableId) {
|
||||
Optional<TableDocument> tableOption =
|
||||
tableDocumentDao.selectByDatabaseDocumentIdAndId(databaseDocId, tableId);
|
||||
tableDocumentDao.selectByDatabaseDocumentIdAndId(databaseDocId, tableId);
|
||||
if (tableOption.isEmpty()) {
|
||||
throw DomainErrors.DATABASE_META_NOT_FOUND.exception("表数据不存在");
|
||||
throw DomainErrors.DATABASE_META_NOT_FOUND.exception();
|
||||
}
|
||||
return tableOption.get();
|
||||
}
|
||||
|
|
|
@ -59,7 +59,7 @@ public class SystemService {
|
|||
|
||||
if (idOpt.isPresent()) {
|
||||
if (!StringUtils.hasText(request.getPassword())) {
|
||||
throw DomainErrors.CONNECT_DATABASE_FAILED.exception();
|
||||
throw DomainErrors.DATABASE_CONNECT_FAILED.exception();
|
||||
}
|
||||
sysMailDao.updateById(sysMail);
|
||||
} else {
|
||||
|
|
|
@ -45,14 +45,14 @@ public class CustomDatabaseConnectionFactory implements DatabaseConnectionFactor
|
|||
URLClassLoader loader = null;
|
||||
try {
|
||||
loader = new URLClassLoader(
|
||||
new URL[]{
|
||||
driverFile.toURI().toURL()
|
||||
},
|
||||
this.getClass().getClassLoader()
|
||||
new URL[]{
|
||||
driverFile.toURI().toURL()
|
||||
},
|
||||
this.getClass().getClassLoader()
|
||||
);
|
||||
} catch (MalformedURLException e) {
|
||||
log.error("load driver error " + context, e);
|
||||
throw DomainErrors.CONNECT_DATABASE_FAILED.exception(e.getMessage());
|
||||
throw DomainErrors.DATABASE_CONNECT_FAILED.exception(e.getMessage());
|
||||
}
|
||||
// retrieve the driver class
|
||||
Class<?> clazz = null;
|
||||
|
@ -62,13 +62,13 @@ public class CustomDatabaseConnectionFactory implements DatabaseConnectionFactor
|
|||
driver = (Driver) clazz.getConstructor().newInstance();
|
||||
} catch (ClassNotFoundException e) {
|
||||
log.error("init driver error", e);
|
||||
throw DomainErrors.CONNECT_DATABASE_FAILED.exception("驱动初始化异常, 请检查驱动类名:" + e.getMessage());
|
||||
throw DomainErrors.DRIVER_CLASS_NOT_FOUND.exception(e);
|
||||
} catch (InvocationTargetException
|
||||
| InstantiationException
|
||||
| IllegalAccessException
|
||||
| NoSuchMethodException e) {
|
||||
log.error("init driver error", e);
|
||||
throw DomainErrors.CONNECT_DATABASE_FAILED.exception("驱动初始化异常:" + e.getMessage());
|
||||
throw DomainErrors.DATABASE_CONNECT_FAILED.exception(e);
|
||||
}
|
||||
|
||||
Properties info = new Properties();
|
||||
|
@ -79,9 +79,9 @@ public class CustomDatabaseConnectionFactory implements DatabaseConnectionFactor
|
|||
}
|
||||
String urlPattern = type.getUrlPattern();
|
||||
String jdbcUrl = urlPattern.replace("{{jdbc.protocol}}", type.getJdbcProtocol())
|
||||
.replace("{{db.url}}", context.getUrl())
|
||||
.replace("{{db.name}}", context.getDatabaseName())
|
||||
.replace("{{db.schema}}", context.getSchemaName());
|
||||
.replace("{{db.url}}", context.getUrl())
|
||||
.replace("{{db.name}}", context.getDatabaseName())
|
||||
.replace("{{db.schema}}", context.getSchemaName());
|
||||
return driver.connect(jdbcUrl, info);
|
||||
}
|
||||
|
||||
|
@ -96,6 +96,6 @@ public class CustomDatabaseConnectionFactory implements DatabaseConnectionFactor
|
|||
return Paths.get(targetFile).toFile();
|
||||
}
|
||||
String databaseType = type.getDatabaseType();
|
||||
throw DomainErrors.DOWNLOAD_DRIVER_ERROR.exception("驱动加载失败, database=" + databaseType);
|
||||
throw DomainErrors.DRIVER_DOWNLOAD_FAILED.exception("驱动加载失败, database=" + databaseType);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,21 +33,21 @@ public class DatabaseConnectionService {
|
|||
dataSourceProperties.forEach(prop -> info.put(prop.getKey(), prop.getValue()));
|
||||
try {
|
||||
DatabaseConnectionFactory.Context context = DatabaseConnectionFactory.Context.builder()
|
||||
.username(username)
|
||||
.password(password)
|
||||
.url(url)
|
||||
.databaseName(dataSource.getDatabaseName())
|
||||
.schemaName(dataSource.getSchemaName())
|
||||
.properties(info)
|
||||
.databaseType(dataSource.getDatabaseType())
|
||||
.build();
|
||||
.username(username)
|
||||
.password(password)
|
||||
.url(url)
|
||||
.databaseName(dataSource.getDatabaseName())
|
||||
.schemaName(dataSource.getSchemaName())
|
||||
.properties(info)
|
||||
.databaseType(dataSource.getDatabaseType())
|
||||
.build();
|
||||
return factories.stream()
|
||||
.filter(factory -> factory.support(dataSource.getDatabaseType()))
|
||||
.findFirst()
|
||||
.orElseThrow(DomainErrors.NOT_SUPPORT_DATABASE_TYPE::exception)
|
||||
.getConnection(context);
|
||||
.filter(factory -> factory.support(dataSource.getDatabaseType()))
|
||||
.findFirst()
|
||||
.orElseThrow(DomainErrors.DATABASE_TYPE_NOT_SUPPORT::exception)
|
||||
.getConnection(context);
|
||||
} catch (SQLException e) {
|
||||
throw DomainErrors.CONNECT_DATABASE_FAILED.exception(e.getMessage(), e);
|
||||
throw DomainErrors.DATABASE_CONNECT_FAILED.exception(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -60,21 +60,21 @@ public class DatabaseConnectionService {
|
|||
Properties properties) {
|
||||
try {
|
||||
DatabaseConnectionFactory.Context context = DatabaseConnectionFactory.Context.builder()
|
||||
.username(username)
|
||||
.password(password)
|
||||
.url(url)
|
||||
.databaseName(databaseName)
|
||||
.schemaName(schemaName)
|
||||
.properties(properties)
|
||||
.databaseType(databaseType)
|
||||
.build();
|
||||
.username(username)
|
||||
.password(password)
|
||||
.url(url)
|
||||
.databaseName(databaseName)
|
||||
.schemaName(schemaName)
|
||||
.properties(properties)
|
||||
.databaseType(databaseType)
|
||||
.build();
|
||||
factories.stream()
|
||||
.filter(factory -> factory.support(databaseType))
|
||||
.findFirst()
|
||||
.orElseThrow(DomainErrors.NOT_SUPPORT_DATABASE_TYPE::exception)
|
||||
.getConnection(context);
|
||||
.filter(factory -> factory.support(databaseType))
|
||||
.findFirst()
|
||||
.orElseThrow(DomainErrors.DATABASE_TYPE_NOT_SUPPORT::exception)
|
||||
.getConnection(context);
|
||||
} catch (SQLException e) {
|
||||
throw DomainErrors.CONNECT_DATABASE_FAILED.exception(e.getMessage(), e);
|
||||
throw DomainErrors.DATABASE_CONNECT_FAILED.exception(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@ public class DriverResources {
|
|||
if (driverFile.exists()) {
|
||||
return new DriverResult(localPath, driverFile);
|
||||
} else {
|
||||
throw DomainErrors.LOAD_DRIVER_FAILED.exception();
|
||||
throw DomainErrors.DRIVER_LOAD_FAILED.exception();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -49,7 +49,7 @@ public class DriverResources {
|
|||
dirPath = Files.createTempDirectory("databasir-drivers");
|
||||
} catch (IOException e) {
|
||||
log.error("load driver error cause create temp dir failed", e);
|
||||
throw DomainErrors.DOWNLOAD_DRIVER_ERROR.exception();
|
||||
throw DomainErrors.DRIVER_DOWNLOAD_FAILED.exception();
|
||||
}
|
||||
File file = download(remoteUrl, dirPath.toString());
|
||||
return new DriverResult(file.getAbsolutePath(), file);
|
||||
|
@ -61,7 +61,7 @@ public class DriverResources {
|
|||
Files.createDirectories(parentDirPath);
|
||||
} catch (IOException e) {
|
||||
log.error("create directory for driver failed", e);
|
||||
throw DomainErrors.DOWNLOAD_DRIVER_ERROR.exception(e);
|
||||
throw DomainErrors.DRIVER_DOWNLOAD_FAILED.exception(e);
|
||||
}
|
||||
|
||||
// download
|
||||
|
@ -90,7 +90,7 @@ public class DriverResources {
|
|||
return targetFile;
|
||||
} else {
|
||||
log.error("{} download error from {}: {} ", parentDir, driverFileUrl, response);
|
||||
throw DomainErrors.DOWNLOAD_DRIVER_ERROR.exception("驱动下载失败:"
|
||||
throw DomainErrors.DRIVER_DOWNLOAD_FAILED.exception("驱动下载失败:"
|
||||
+ response.getStatusCode()
|
||||
+ ", "
|
||||
+ response.getStatusText());
|
||||
|
@ -99,7 +99,7 @@ public class DriverResources {
|
|||
} catch (RestClientException e) {
|
||||
String msg = String.format("download driver from %s to %s failed", driverFileUrl, parentDir);
|
||||
log.error(msg, e);
|
||||
throw DomainErrors.DOWNLOAD_DRIVER_ERROR.exception(msg);
|
||||
throw DomainErrors.DRIVER_DOWNLOAD_FAILED.exception(msg);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -183,7 +183,7 @@ public class DriverResources {
|
|||
);
|
||||
} catch (MalformedURLException e) {
|
||||
log.error("load driver jar error ", e);
|
||||
throw DomainErrors.DOWNLOAD_DRIVER_ERROR.exception(e.getMessage());
|
||||
throw DomainErrors.DRIVER_DOWNLOAD_FAILED.exception(e.getMessage());
|
||||
}
|
||||
|
||||
try {
|
||||
|
@ -211,7 +211,7 @@ public class DriverResources {
|
|||
return targetFile;
|
||||
} catch (IOException e) {
|
||||
log.error("copy driver file error", e);
|
||||
throw DomainErrors.DOWNLOAD_DRIVER_ERROR.exception(e.getMessage());
|
||||
throw DomainErrors.DRIVER_DOWNLOAD_FAILED.exception(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -43,7 +43,6 @@ class LoginServiceTest extends BaseTest {
|
|||
DatabasirException err = Assertions.assertThrows(DatabasirException.class,
|
||||
() -> loginService.refreshAccessTokens(request));
|
||||
Assertions.assertEquals(DomainErrors.INVALID_REFRESH_TOKEN_OPERATION.getErrCode(), err.getErrCode());
|
||||
Assertions.assertEquals("invalid user", err.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -54,7 +53,6 @@ class LoginServiceTest extends BaseTest {
|
|||
DatabasirException err = Assertions.assertThrows(DatabasirException.class,
|
||||
() -> loginService.refreshAccessTokens(request));
|
||||
Assertions.assertEquals(DomainErrors.INVALID_REFRESH_TOKEN_OPERATION.getErrCode(), err.getErrCode());
|
||||
Assertions.assertEquals("invalid user status", err.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
Loading…
Reference in New Issue