Skip to content

Commit

Permalink
支持可插拔数据驱动配置
Browse files Browse the repository at this point in the history
1. 支持可插拔数据驱动配置
2. 修改登录验证状态码403
3. 修改组织邀请成员UI
  • Loading branch information
RichardShan committed Aug 23, 2018
1 parent 84edec4 commit bbf99e5
Show file tree
Hide file tree
Showing 28 changed files with 500 additions and 244 deletions.
1 change: 1 addition & 0 deletions assembly/src/main/assembly/assembly.xml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
<outputDirectory>config</outputDirectory>
<includes>
<include>application.yml.example</include>
<include>datasource_driver.yml.example</include>
<include>logback.xml</include>
</includes>
</fileSet>
Expand Down
1 change: 1 addition & 0 deletions assembly/src/main/assembly/release.xml
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
</directory>
<outputDirectory>config</outputDirectory>
<includes>
<include>datasource_driver.yml.example</include>
<include>application.yml.example</include>
<include>logback.xml</include>
</includes>
Expand Down
54 changes: 54 additions & 0 deletions config/datasource_driver.yml.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
## <<
## Davinci
## ==
## Copyright (C) 2016 - 2018 EDP
## ==
## Licensed 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.
## >>

## This file is used to add jdbc datasources that are not supported by the Davinci,
## ignore this file if your datasource is already supported,
## the jdbc datasources Davinci support by default are:
## mysql: com.mysql.jdbc.Driver
## oracle: oracle.jdbc.driver.OracleDriver
## sqlserver: com.microsoft.sqlserver.jdbc.SQLServerDriver
## h2: org.h2.Driver
## phoenix: org.apache.phoenix.jdbc.PhoenixDriver
## mongodb: mongodb.jdbc.MongoDriver
## elasticSearch: nl.anchormen.sql4es.jdbc.ESDriver
## presto: com.facebook.presto.jdbc.PrestoDriver
## moonbox: moonbox.jdbc.MbDriver
## cassandra: com.github.adejanovski.cassandra.jdbc.CassandraDriver
## clickhouse: ru.yandex.clickhouse.ClickHouseDriver
## kylin: org.apache.kylin.jdbc.Driver
## vertica: com.vertica.jdbc.Driver
## hana: com.sap.db.jdbc.Driver
## impala: com.cloudera.impala.jdbc41.Driver
## this means that if your datasource is in the above list, you don't need to use this method,
## unless you know what you are doing.

## How to use:
## 1. configure your own datasource like examples below,
## 2. add the corresponding dependency file (jar) in lib package,
## 3. restart your Davinci server

## If you have problems during use, please contact us.


# mysql:
# name: mysql
# desc: mysql
# driver: com.mysql.jdbc.Driver

# oracle:
# name: oracle
# desc: oracle
# driver: oracle.jdbc.driver.OracleDriver
1 change: 1 addition & 0 deletions server/src/main/java/edp/SwaggerConfiguration.java
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ public Docket createRestApi() {
responseMessageList.add(new ResponseMessageBuilder().code(HttpCodeEnum.OK.getCode()).message(HttpCodeEnum.OK.getMessage()).build());
responseMessageList.add(new ResponseMessageBuilder().code(HttpCodeEnum.FAIL.getCode()).message(HttpCodeEnum.FAIL.getMessage()).build());
responseMessageList.add(new ResponseMessageBuilder().code(HttpCodeEnum.UNAUTHORIZED.getCode()).message(HttpCodeEnum.UNAUTHORIZED.getMessage()).build());
responseMessageList.add(new ResponseMessageBuilder().code(HttpCodeEnum.FORBIDDEN.getCode()).message(HttpCodeEnum.FORBIDDEN.getMessage()).build());
responseMessageList.add(new ResponseMessageBuilder().code(HttpCodeEnum.SERVER_ERROR.getCode()).message(HttpCodeEnum.SERVER_ERROR.getMessage()).build());


Expand Down
22 changes: 19 additions & 3 deletions server/src/main/java/edp/core/common/jdbc/JdbcDataSource.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,11 @@
package edp.core.common.jdbc;

import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.util.StringUtils;
import edp.core.enums.DataTypeEnum;
import edp.core.exception.SourceException;
import edp.core.model.DataSourceDriver;
import edp.core.utils.DataSourceDriverLoadUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
Expand Down Expand Up @@ -63,22 +66,35 @@ public class JdbcDataSource extends DruidDataSource {
@Value("${spring.datasource.test-on-return}")
private boolean testOnReturn;


@Value("${custom-datasource-driver-path}")
private String dataSourceYamlPath;

private static volatile Map<String, Object> map = new HashMap<>();

public synchronized DruidDataSource getDataSource(String jdbcUrl, String username, String password) throws SourceException {
String url = jdbcUrl.toLowerCase();
if (!map.containsKey(username + "@" + url) || null == map.get(username + "@" + url)) {
DataTypeEnum dataTypeEnum = DataTypeEnum.urlOf(jdbcUrl);
if (null == dataTypeEnum) {
throw new SourceException("Not supported data type: jdbcUrl=" + jdbcUrl);

DataSourceDriver dataSourceDriver = null;
try {
dataSourceDriver = DataSourceDriverLoadUtils.loadFromYaml(dataSourceYamlPath,jdbcUrl);
} catch (Exception e) {
throw new SourceException(e.getMessage());
}

DruidDataSource instance = new JdbcDataSource();
if (null == dataTypeEnum && null == dataSourceDriver) {
throw new SourceException("Not supported data type: jdbcUrl=" + jdbcUrl);
}

instance.setDriverClassName(StringUtils.isEmpty(dataTypeEnum.getDriver()) ? dataSourceDriver.getDriver().trim() : dataTypeEnum.getDriver());

instance.setUrl(url);
instance.setUsername(url.indexOf(DataTypeEnum.ELASTICSEARCH.getFeature()) > -1 ? null : username);
instance.setPassword((url.indexOf(DataTypeEnum.PRESTO.getFeature()) > -1 || url.indexOf(DataTypeEnum.ELASTICSEARCH.getFeature()) > -1) ?
null : password);
instance.setDriverClassName(dataTypeEnum.getDriver());
instance.setInitialSize(initialSize);
instance.setMinIdle(minIdle);
instance.setMaxActive(maxActive);
Expand Down
10 changes: 8 additions & 2 deletions server/src/main/java/edp/core/enums/DataTypeEnum.java
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,13 @@ public enum DataTypeEnum {

CLICKHOUSE("clickhouse", "clickhouse", "ru.yandex.clickhouse.ClickHouseDriver"),

KYLIN("kylin", "kylin", "org.apache.kylin.jdbc.Driver");
KYLIN("kylin", "kylin", "org.apache.kylin.jdbc.Driver"),

VERTICA("vertica", "vertica", "com.vertica.jdbc.Driver"),

HANA("sap", "sap hana", "com.sap.db.jdbc.Driver"),

IMPALA("impala", "impala", "com.cloudera.impala.jdbc41.Driver");


private String feature;
Expand All @@ -62,7 +68,7 @@ public enum DataTypeEnum {
public static DataTypeEnum urlOf(String jdbcUrl) throws SourceException {
String url = jdbcUrl.toLowerCase();
for (DataTypeEnum dataTypeEnum : values()) {
if (url.toLowerCase().indexOf(dataTypeEnum.feature) > -1) {
if (url.indexOf(dataTypeEnum.feature) > -1) {
try {
Class<?> aClass = Class.forName(dataTypeEnum.getDriver());
if (null == aClass) {
Expand Down
1 change: 1 addition & 0 deletions server/src/main/java/edp/core/enums/HttpCodeEnum.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ public enum HttpCodeEnum {
OK(200, "OK"),
FAIL(400, "Bad Request"),
UNAUTHORIZED(401, "Unauthorized"),
FORBIDDEN(403, "Forbidden"),
NOT_FOUND(404, "Not Found"),
SERVER_ERROR(500, "Internal Server Error");

Expand Down
28 changes: 28 additions & 0 deletions server/src/main/java/edp/core/model/DataSourceDriver.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* <<
* Davinci
* ==
* Copyright (C) 2016 - 2018 EDP
* ==
* Licensed 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 edp.core.model;

import lombok.Data;

@Data
public class DataSourceDriver {
private String name;
private String desc;
private String driver;
}
117 changes: 117 additions & 0 deletions server/src/main/java/edp/core/utils/DataSourceDriverLoadUtils.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
/*
* <<
* Davinci
* ==
* Copyright (C) 2016 - 2018 EDP
* ==
* Licensed 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 edp.core.utils;

import com.alibaba.druid.util.StringUtils;
import edp.core.model.DataSourceDriver;
import org.yaml.snakeyaml.Yaml;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.util.Map;

public class DataSourceDriverLoadUtils {


/**
* 根据url 加载yaml中的数据源驱动
*
* @param url
* @return
* @throws Exception
*/
public static DataSourceDriver loadFromYaml(String yamlPath, String url) throws Exception {
if (StringUtils.isEmpty(url)) {
return null;
}
Map<String, DataSourceDriver> sourceDriverMap = loadAllFromYaml(yamlPath);
if (null == sourceDriverMap || sourceDriverMap.size() < 1) {
return null;
}

for (String key : sourceDriverMap.keySet()) {
DataSourceDriver dataSourceDriver = sourceDriverMap.get(key);
if (StringUtils.isEmpty(dataSourceDriver.getName()) || StringUtils.isEmpty(dataSourceDriver.getDriver())) {
continue;
}
if ("null".equals(dataSourceDriver.getName().trim().toLowerCase())) {
continue;
}
if ("null".equals(dataSourceDriver.getDriver().trim().toLowerCase())) {
continue;
}

if (StringUtils.isEmpty(dataSourceDriver.getDesc())) {
dataSourceDriver.setDesc(dataSourceDriver.getName());
}
if ("null".equals(dataSourceDriver.getDesc().trim().toLowerCase())) {
dataSourceDriver.setDesc(dataSourceDriver.getName());
}

if (url.toLowerCase().indexOf(dataSourceDriver.getName().trim().toLowerCase()) > -1) {
try {
Class<?> aClass = Class.forName(dataSourceDriver.getDriver());
if (null == aClass) {
throw new Exception("Unable to get driver instance for jdbcUrl: " + url);
}
} catch (ClassNotFoundException e) {
throw new Exception("Unable to get driver instance: " + url);
}
return dataSourceDriver;
}
}
return null;
}

private static Map<String, DataSourceDriver> loadAllFromYaml(String yamlPath) {
if (StringUtils.isEmpty(yamlPath)) {
return null;
}
File yamlFile = new File(yamlPath);
if (!yamlFile.exists()) {
return null;
}
if (!yamlFile.isFile()) {
return null;
}
if (!yamlFile.canRead()) {
return null;
}

FileReader fileReader = null;
try {
fileReader = new FileReader(yamlFile);
} catch (FileNotFoundException e) {
return null;
}
if (null == fileReader) {
return null;
}

Yaml yaml = new Yaml();
Object load = yaml.load(new BufferedReader(fileReader));
Map<String, DataSourceDriver> dataTypeMap = null;
if (null != load) {
dataTypeMap = (Map<String, DataSourceDriver>) load;
}
return dataTypeMap;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -340,56 +340,56 @@ public ResponseEntity inviteMember(@PathVariable("orgId") Long orgId,
}


/**
* 成员确认邀请
*
* @param request
* @return
*/
@ApiOperation(value = "member confirm invite")
@AuthIgnore
@PostMapping("/confirminvite/{token}")
public ResponseEntity confirmInvite(@PathVariable("token") String token,
HttpServletRequest request) {
if (StringUtils.isEmpty(token)) {
ResultMap resultMap = new ResultMap(tokenUtils).failAndRefreshToken(request).message("The invitation confirm token can not be empty");
return ResponseEntity.status(resultMap.getCode()).body(resultMap);
}
try {
ResultMap resultMap = organizationService.confirmInviteNoLogin(token);
return ResponseEntity.status(resultMap.getCode()).body(resultMap);
} catch (Exception e) {
e.printStackTrace();
return ResponseEntity.badRequest().body(HttpCodeEnum.SERVER_ERROR.getMessage());
}
}


// /**
// * 成员确认邀请
// *
// * @param user
// * @param request
// * @return
// */
// @ApiOperation(value = "member confirm invite")
// @AuthIgnore
// @PostMapping("/confirminvite/{token}")
// public ResponseEntity confirmInvite(@PathVariable("token") String token,
// @ApiIgnore @CurrentUser User user,
// HttpServletRequest request) {
// if (StringUtils.isEmpty(token)) {
// ResultMap resultMap = new ResultMap(tokenUtils).failAndRefreshToken(request).message("The invitation confirm token can not be empty");
// return ResponseEntity.status(resultMap.getCode()).body(resultMap);
// }
// try {
// ResultMap resultMap = organizationService.confirmInvite(token, user, request);
// ResultMap resultMap = organizationService.confirmInviteNoLogin(token);
// return ResponseEntity.status(resultMap.getCode()).body(resultMap);
// } catch (Exception e) {
// e.printStackTrace();
// return ResponseEntity.badRequest().body(HttpCodeEnum.SERVER_ERROR.getMessage());
// }
// }


/**
* 成员确认邀请
*
* @param user
* @param request
* @return
*/
@ApiOperation(value = "member confirm invite")
@PostMapping("/confirminvite/{token}")
public ResponseEntity confirmInvite(@PathVariable("token") String token,
@ApiIgnore @CurrentUser User user,
HttpServletRequest request) {
if (StringUtils.isEmpty(token)) {
ResultMap resultMap = new ResultMap(tokenUtils).failAndRefreshToken(request).message("The invitation confirm token can not be empty");
return ResponseEntity.status(resultMap.getCode()).body(resultMap);
}
try {
ResultMap resultMap = organizationService.confirmInvite(token, user, request);
return ResponseEntity.status(resultMap.getCode()).body(resultMap);
} catch (Exception e) {
e.printStackTrace();
return ResponseEntity.badRequest().body(HttpCodeEnum.SERVER_ERROR.getMessage());
}
}

/**
* 删除组织成员
*
Expand Down
Loading

0 comments on commit bbf99e5

Please sign in to comment.