Merge pull request #13255 from dataease/pr@dev-v2@fixds
Pr@dev v2@fixds
This commit is contained in:
commit
217da936cc
@ -128,17 +128,20 @@ public class ChartDataServer implements ChartDataApi {
|
|||||||
request.setHeader(dsHeader);
|
request.setHeader(dsHeader);
|
||||||
request.setExcelTypes(dsTypes);
|
request.setExcelTypes(dsTypes);
|
||||||
}
|
}
|
||||||
for (Object[] objects : tableRow) {
|
if (CollectionUtils.isNotEmpty(tableRow)) {
|
||||||
for (int i = 0; i < viewDTO.getXAxis().size(); i++) {
|
for (Object[] objects : tableRow) {
|
||||||
if (viewDTO.getXAxis().get(i).getDeType().equals(DeTypeConstants.DE_INT) || viewDTO.getXAxis().get(i).getDeType().equals(DeTypeConstants.DE_FLOAT)) {
|
for (int i = 0; i < viewDTO.getXAxis().size(); i++) {
|
||||||
try {
|
if (viewDTO.getXAxis().get(i).getDeType().equals(DeTypeConstants.DE_INT) || viewDTO.getXAxis().get(i).getDeType().equals(DeTypeConstants.DE_FLOAT)) {
|
||||||
objects[i] = valueFormatter(BigDecimal.valueOf(Double.valueOf(objects[i].toString())), viewDTO.getXAxis().get(i).getFormatterCfg());
|
try {
|
||||||
} catch (Exception ignore) {
|
objects[i] = valueFormatter(BigDecimal.valueOf(Double.valueOf(objects[i].toString())), viewDTO.getXAxis().get(i).getFormatterCfg());
|
||||||
|
} catch (Exception ignore) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
request.setDetails(tableRow);
|
request.setDetails(tableRow);
|
||||||
|
request.setData(chartViewInfo.getData());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -483,6 +483,23 @@ public class DatasourceServer implements DatasourceApi {
|
|||||||
return getDatasourceDTOById(datasourceId, true);
|
return getDatasourceDTOById(datasourceId, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DatasourceDTO getSimpleDs(Long datasourceId) throws DEException {
|
||||||
|
CoreDatasource datasource = datasourceMapper.selectById(datasourceId);
|
||||||
|
if (datasource == null) {
|
||||||
|
DEException.throwException("不存在的数据源!");
|
||||||
|
}
|
||||||
|
if (datasource.getType().equalsIgnoreCase("api")) {
|
||||||
|
datasource.setConfiguration("[]");
|
||||||
|
} else {
|
||||||
|
datasource.setConfiguration("");
|
||||||
|
}
|
||||||
|
datasource.setConfiguration("");
|
||||||
|
DatasourceDTO datasourceDTO = new DatasourceDTO();
|
||||||
|
BeanUtils.copyBean(datasourceDTO, datasource);
|
||||||
|
return datasourceDTO;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DatasourceDTO get(Long datasourceId) throws DEException {
|
public DatasourceDTO get(Long datasourceId) throws DEException {
|
||||||
return getDatasourceDTOById(datasourceId, false);
|
return getDatasourceDTOById(datasourceId, false);
|
||||||
@ -1132,8 +1149,12 @@ public class DatasourceServer implements DatasourceApi {
|
|||||||
params.add(apiDefinition);
|
params.add(apiDefinition);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
datasourceDTO.setApiConfigurationStr(new String(Base64.getEncoder().encode(Objects.requireNonNull(JsonUtil.toJSONString(apiDefinitionListWithStatus)).toString().getBytes())));
|
if(CollectionUtils.isNotEmpty(params)){
|
||||||
datasourceDTO.setParamsStr(new String(Base64.getEncoder().encode(Objects.requireNonNull(JsonUtil.toJSONString(params)).toString().getBytes())));
|
datasourceDTO.setParamsStr(RsaUtils.symmetricEncrypt(JsonUtil.toJSONString(params).toString()));
|
||||||
|
}
|
||||||
|
if(CollectionUtils.isNotEmpty(apiDefinitionListWithStatus)){
|
||||||
|
datasourceDTO.setApiConfigurationStr(RsaUtils.symmetricEncrypt(JsonUtil.toJSONString(apiDefinitionListWithStatus).toString()));
|
||||||
|
}
|
||||||
if (success == apiDefinitionList.size()) {
|
if (success == apiDefinitionList.size()) {
|
||||||
datasourceDTO.setStatus("Success");
|
datasourceDTO.setStatus("Success");
|
||||||
} else {
|
} else {
|
||||||
@ -1147,7 +1168,6 @@ public class DatasourceServer implements DatasourceApi {
|
|||||||
TaskDTO taskDTO = new TaskDTO();
|
TaskDTO taskDTO = new TaskDTO();
|
||||||
BeanUtils.copyBean(taskDTO, coreDatasourceTask);
|
BeanUtils.copyBean(taskDTO, coreDatasourceTask);
|
||||||
datasourceDTO.setSyncSetting(taskDTO);
|
datasourceDTO.setSyncSetting(taskDTO);
|
||||||
|
|
||||||
CoreDatasourceTask task = datasourceTaskServer.selectByDSId(datasourceDTO.getId());
|
CoreDatasourceTask task = datasourceTaskServer.selectByDSId(datasourceDTO.getId());
|
||||||
if (task != null) {
|
if (task != null) {
|
||||||
datasourceDTO.setLastSyncTime(task.getStartTime());
|
datasourceDTO.setLastSyncTime(task.getStartTime());
|
||||||
@ -1157,13 +1177,12 @@ public class DatasourceServer implements DatasourceApi {
|
|||||||
Provider provider = ProviderFactory.getProvider(datasourceDTO.getType());
|
Provider provider = ProviderFactory.getProvider(datasourceDTO.getType());
|
||||||
provider.hidePW(datasourceDTO);
|
provider.hidePW(datasourceDTO);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
if (datasourceDTO.getType().equalsIgnoreCase(DatasourceConfiguration.DatasourceType.Excel.toString())) {
|
if (datasourceDTO.getType().equalsIgnoreCase(DatasourceConfiguration.DatasourceType.Excel.toString())) {
|
||||||
datasourceDTO.setFileName(ExcelUtils.getFileName(datasource));
|
datasourceDTO.setFileName(ExcelUtils.getFileName(datasource));
|
||||||
datasourceDTO.setSize(ExcelUtils.getSize(datasource));
|
datasourceDTO.setSize(ExcelUtils.getSize(datasource));
|
||||||
}
|
}
|
||||||
datasourceDTO.setConfiguration(new String(Base64.getEncoder().encode(datasourceDTO.getConfiguration().getBytes())));
|
datasourceDTO.setConfiguration(RsaUtils.symmetricEncrypt(datasourceDTO.getConfiguration()));
|
||||||
datasourceDTO.setCreator(coreUserManage.getUserName(Long.valueOf(datasourceDTO.getCreateBy())));
|
datasourceDTO.setCreator(coreUserManage.getUserName(Long.valueOf(datasourceDTO.getCreateBy())));
|
||||||
return datasourceDTO;
|
return datasourceDTO;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,9 +5,12 @@ import io.dataease.datasource.dao.auto.entity.CoreDeEngine;
|
|||||||
import io.dataease.datasource.dao.auto.mapper.CoreDeEngineMapper;
|
import io.dataease.datasource.dao.auto.mapper.CoreDeEngineMapper;
|
||||||
import io.dataease.datasource.manage.EngineManage;
|
import io.dataease.datasource.manage.EngineManage;
|
||||||
import io.dataease.datasource.provider.CalciteProvider;
|
import io.dataease.datasource.provider.CalciteProvider;
|
||||||
|
import io.dataease.exception.DEException;
|
||||||
import io.dataease.extensions.datasource.dto.DatasourceDTO;
|
import io.dataease.extensions.datasource.dto.DatasourceDTO;
|
||||||
|
import io.dataease.utils.AuthUtils;
|
||||||
import io.dataease.utils.BeanUtils;
|
import io.dataease.utils.BeanUtils;
|
||||||
import io.dataease.utils.IDUtils;
|
import io.dataease.utils.IDUtils;
|
||||||
|
import io.dataease.utils.RsaUtils;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
@ -30,33 +33,44 @@ public class EngineServer implements EngineApi {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DatasourceDTO getEngine() {
|
public DatasourceDTO getEngine() {
|
||||||
|
if (!AuthUtils.getUser().getUserId().equals(1L)) {
|
||||||
|
DEException.throwException("非管理员,无权访问!");
|
||||||
|
}
|
||||||
DatasourceDTO datasourceDTO = new DatasourceDTO();
|
DatasourceDTO datasourceDTO = new DatasourceDTO();
|
||||||
List<CoreDeEngine> deEngines = deEngineMapper.selectList(null);
|
List<CoreDeEngine> deEngines = deEngineMapper.selectList(null);
|
||||||
if (CollectionUtils.isEmpty(deEngines)) {
|
if (CollectionUtils.isEmpty(deEngines)) {
|
||||||
return datasourceDTO;
|
return datasourceDTO;
|
||||||
}
|
}
|
||||||
return BeanUtils.copyBean(datasourceDTO, deEngines.get(0));
|
BeanUtils.copyBean(datasourceDTO, deEngines.get(0));
|
||||||
|
datasourceDTO.setConfiguration(RsaUtils.symmetricEncrypt(datasourceDTO.getConfiguration()));
|
||||||
|
return datasourceDTO;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void save(DatasourceDTO datasourceDTO) {
|
public void save(DatasourceDTO datasourceDTO) {
|
||||||
|
if (!AuthUtils.getUser().getUserId().equals(1L)) {
|
||||||
|
DEException.throwException("非管理员,无权访问!");
|
||||||
|
}
|
||||||
if (StringUtils.isNotEmpty(datasourceDTO.getConfiguration())) {
|
if (StringUtils.isNotEmpty(datasourceDTO.getConfiguration())) {
|
||||||
datasourceDTO.setConfiguration(new String(Base64.getDecoder().decode(datasourceDTO.getConfiguration())));
|
datasourceDTO.setConfiguration(new String(Base64.getDecoder().decode(datasourceDTO.getConfiguration())));
|
||||||
}
|
}
|
||||||
CoreDeEngine coreDeEngine = new CoreDeEngine();
|
CoreDeEngine coreDeEngine = new CoreDeEngine();
|
||||||
BeanUtils.copyBean(coreDeEngine, datasourceDTO);
|
BeanUtils.copyBean(coreDeEngine, datasourceDTO);
|
||||||
if(coreDeEngine.getId() == null){
|
if (coreDeEngine.getId() == null) {
|
||||||
coreDeEngine.setId(IDUtils.snowID());
|
coreDeEngine.setId(IDUtils.snowID());
|
||||||
datasourceDTO.setId(coreDeEngine.getId());
|
datasourceDTO.setId(coreDeEngine.getId());
|
||||||
deEngineMapper.insert(coreDeEngine);
|
deEngineMapper.insert(coreDeEngine);
|
||||||
}else {
|
} else {
|
||||||
deEngineMapper.updateById(coreDeEngine);
|
deEngineMapper.updateById(coreDeEngine);
|
||||||
}
|
}
|
||||||
calciteProvider.update(datasourceDTO);
|
calciteProvider.update(datasourceDTO);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void validate(DatasourceDTO datasourceDTO) throws Exception{
|
public void validate(DatasourceDTO datasourceDTO) throws Exception {
|
||||||
|
if (!AuthUtils.getUser().getUserId().equals(1L)) {
|
||||||
|
DEException.throwException("非管理员,无权访问!");
|
||||||
|
}
|
||||||
CoreDeEngine coreDeEngine = new CoreDeEngine();
|
CoreDeEngine coreDeEngine = new CoreDeEngine();
|
||||||
BeanUtils.copyBean(coreDeEngine, datasourceDTO);
|
BeanUtils.copyBean(coreDeEngine, datasourceDTO);
|
||||||
coreDeEngine.setConfiguration(new String(Base64.getDecoder().decode(coreDeEngine.getConfiguration())));
|
coreDeEngine.setConfiguration(new String(Base64.getDecoder().decode(coreDeEngine.getConfiguration())));
|
||||||
@ -65,6 +79,9 @@ public class EngineServer implements EngineApi {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void validateById(Long id) throws Exception {
|
public void validateById(Long id) throws Exception {
|
||||||
|
if (!AuthUtils.getUser().getUserId().equals(1L)) {
|
||||||
|
DEException.throwException("非管理员,无权访问!");
|
||||||
|
}
|
||||||
engineManage.validate(deEngineMapper.selectById(id));
|
engineManage.validate(deEngineMapper.selectById(id));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -655,16 +655,18 @@ public class ExportCenterManage implements BaseExportApi {
|
|||||||
cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
|
cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
|
||||||
|
|
||||||
if (CollectionUtils.isEmpty(request.getMultiInfo())) {
|
if (CollectionUtils.isEmpty(request.getMultiInfo())) {
|
||||||
List<Object[]> details = request.getDetails();
|
if(request.getViewInfo().getType().equalsIgnoreCase("chart-mix-dual-line")){
|
||||||
Integer[] excelTypes = request.getExcelTypes();
|
|
||||||
details.add(0, request.getHeader());
|
|
||||||
ViewDetailField[] detailFields = request.getDetailFields();
|
|
||||||
Object[] header = request.getHeader();
|
|
||||||
|
|
||||||
//明细sheet
|
}else {
|
||||||
Sheet detailsSheet = wb.createSheet("数据");
|
List<Object[]> details = request.getDetails();
|
||||||
|
Integer[] excelTypes = request.getExcelTypes();
|
||||||
|
details.add(0, request.getHeader());
|
||||||
|
ViewDetailField[] detailFields = request.getDetailFields();
|
||||||
|
Object[] header = request.getHeader();
|
||||||
|
Sheet detailsSheet = wb.createSheet("数据");
|
||||||
|
ChartDataServer.setExcelData(detailsSheet, cellStyle, header, details, detailFields, excelTypes);
|
||||||
|
}
|
||||||
|
|
||||||
ChartDataServer.setExcelData(detailsSheet, cellStyle, header, details, detailFields, excelTypes);
|
|
||||||
} else {
|
} else {
|
||||||
//多个sheet
|
//多个sheet
|
||||||
for (int i = 0; i < request.getMultiInfo().size(); i++) {
|
for (int i = 0; i < request.getMultiInfo().size(); i++) {
|
||||||
|
|||||||
@ -23,6 +23,13 @@ public class RestIndexController {
|
|||||||
return RsaUtils.publicKey();
|
return RsaUtils.publicKey();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GetMapping("/symmetricKey")
|
||||||
|
@ResponseBody
|
||||||
|
public String symmetricKey() {
|
||||||
|
return RsaUtils.generateSymmetricKey();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@GetMapping("/model")
|
@GetMapping("/model")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public boolean model() {
|
public boolean model() {
|
||||||
|
|||||||
@ -19,7 +19,7 @@ import java.util.List;
|
|||||||
@Component
|
@Component
|
||||||
public class LinkInterceptor implements HandlerInterceptor {
|
public class LinkInterceptor implements HandlerInterceptor {
|
||||||
|
|
||||||
private final static String whiteListText = "/user/ipInfo, /apisix/check, /datasetData/enumValue, /datasetData/enumValueObj, /datasetData/getFieldTree, /dekey, /share/validate, /sysParameter/queryOnlineMap, /chartData/innerExportDetails";
|
private final static String whiteListText = "/user/ipInfo, /apisix/check, /datasetData/enumValue, /datasetData/enumValueObj, /datasetData/getFieldTree, /dekey, /symmetricKey, /share/validate, /sysParameter/queryOnlineMap, /chartData/innerExportDetails";
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -155,6 +155,8 @@ export const getById = (id: number) => request.get({ url: '/datasource/get/' + i
|
|||||||
|
|
||||||
export const getHidePwById = (id: number) => request.get({ url: '/datasource/hidePw/' + id })
|
export const getHidePwById = (id: number) => request.get({ url: '/datasource/hidePw/' + id })
|
||||||
|
|
||||||
|
export const getSimpleDs = (id: number) => request.get({ url: '/datasource/getSimpleDs/' + id })
|
||||||
|
|
||||||
export const uploadFile = async (data): Promise<IResponse> => {
|
export const uploadFile = async (data): Promise<IResponse> => {
|
||||||
return request
|
return request
|
||||||
.post({
|
.post({
|
||||||
|
|||||||
@ -4,6 +4,8 @@ export const loginApi = data => request.post({ url: '/login/localLogin', data })
|
|||||||
|
|
||||||
export const queryDekey = () => request.get({ url: 'dekey' })
|
export const queryDekey = () => request.get({ url: 'dekey' })
|
||||||
|
|
||||||
|
export const querySymmetricKey = () => request.get({ url: 'symmetricKey' })
|
||||||
|
|
||||||
export const modelApi = () => request.get({ url: 'model' })
|
export const modelApi = () => request.get({ url: 'model' })
|
||||||
|
|
||||||
export const platformLoginApi = origin => request.post({ url: '/login/platformLogin/' + origin })
|
export const platformLoginApi = origin => request.post({ url: '/login/platformLogin/' + origin })
|
||||||
|
|||||||
@ -40,3 +40,15 @@ export const rsaEncryp = word => {
|
|||||||
crypt.setKey(pk)
|
crypt.setKey(pk)
|
||||||
return crypt.encrypt(word)
|
return crypt.encrypt(word)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const symmetricDecrypt = (data, keyStr) => {
|
||||||
|
const iv = CryptoJS.enc.Utf8.parse('0000000000000000')
|
||||||
|
const key = CryptoJS.enc.Base64.parse(keyStr)
|
||||||
|
const decodedCiphertext = CryptoJS.enc.Base64.parse(data)
|
||||||
|
const decrypted = CryptoJS.AES.decrypt({ ciphertext: decodedCiphertext }, key, {
|
||||||
|
iv: iv,
|
||||||
|
mode: CryptoJS.mode.CBC,
|
||||||
|
padding: CryptoJS.pad.Pkcs7
|
||||||
|
})
|
||||||
|
return decrypted.toString(CryptoJS.enc.Utf8)
|
||||||
|
}
|
||||||
|
|||||||
@ -10,6 +10,8 @@ import { cloneDeep } from 'lodash-es'
|
|||||||
import { getDeEngine } from '@/api/datasource'
|
import { getDeEngine } from '@/api/datasource'
|
||||||
import { CustomPassword } from '@/components/custom-password'
|
import { CustomPassword } from '@/components/custom-password'
|
||||||
import { Base64 } from 'js-base64'
|
import { Base64 } from 'js-base64'
|
||||||
|
import { querySymmetricKey } from '@/api/login'
|
||||||
|
import { symmetricDecrypt } from '@/utils/encryption'
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
const dialogVisible = ref(false)
|
const dialogVisible = ref(false)
|
||||||
const loadingInstance = ref(null)
|
const loadingInstance = ref(null)
|
||||||
@ -149,45 +151,47 @@ const defaultInfo = {
|
|||||||
}
|
}
|
||||||
const nodeInfo = reactive(cloneDeep(defaultInfo))
|
const nodeInfo = reactive(cloneDeep(defaultInfo))
|
||||||
const edit = () => {
|
const edit = () => {
|
||||||
getDeEngine()
|
querySymmetricKey().then(response => {
|
||||||
.then(res => {
|
getDeEngine()
|
||||||
let {
|
.then(res => {
|
||||||
name,
|
let {
|
||||||
createBy,
|
name,
|
||||||
id,
|
createBy,
|
||||||
createTime,
|
id,
|
||||||
creator,
|
createTime,
|
||||||
type,
|
creator,
|
||||||
pid,
|
type,
|
||||||
configuration,
|
pid,
|
||||||
syncSetting,
|
configuration,
|
||||||
fileName,
|
syncSetting,
|
||||||
size,
|
fileName,
|
||||||
description,
|
size,
|
||||||
lastSyncTime
|
description,
|
||||||
} = res.data
|
lastSyncTime
|
||||||
if (configuration) {
|
} = res.data
|
||||||
configuration = JSON.parse(configuration)
|
if (configuration) {
|
||||||
}
|
configuration = JSON.parse(symmetricDecrypt(configuration, response.data))
|
||||||
Object.assign(nodeInfo, {
|
}
|
||||||
name,
|
Object.assign(nodeInfo, {
|
||||||
pid,
|
name,
|
||||||
description,
|
pid,
|
||||||
fileName,
|
description,
|
||||||
size,
|
fileName,
|
||||||
createTime,
|
size,
|
||||||
creator,
|
createTime,
|
||||||
createBy,
|
creator,
|
||||||
id,
|
createBy,
|
||||||
type,
|
id,
|
||||||
configuration,
|
type,
|
||||||
syncSetting,
|
configuration,
|
||||||
lastSyncTime
|
syncSetting,
|
||||||
|
lastSyncTime
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
.finally(() => {
|
||||||
.finally(() => {
|
dialogVisible.value = true
|
||||||
dialogVisible.value = true
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
const basicForm = ref()
|
const basicForm = ref()
|
||||||
|
|
||||||
|
|||||||
@ -42,6 +42,8 @@ import InfoTemplate from '@/views/system/common/InfoTemplate.vue'
|
|||||||
import { dsTypes } from '@/views/visualized/data/datasource/form/option'
|
import { dsTypes } from '@/views/visualized/data/datasource/form/option'
|
||||||
import { getDeEngine } from '@/api/datasource'
|
import { getDeEngine } from '@/api/datasource'
|
||||||
import request from '@/config/axios'
|
import request from '@/config/axios'
|
||||||
|
import { querySymmetricKey } from '@/api/login'
|
||||||
|
import { symmetricDecrypt } from '@/utils/encryption'
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
const typeMap = dsTypes.reduce((pre, next) => {
|
const typeMap = dsTypes.reduce((pre, next) => {
|
||||||
pre[next.type] = next.name
|
pre[next.type] = next.name
|
||||||
@ -54,82 +56,82 @@ const infoTemplateTime = ref()
|
|||||||
const templateList = ref<SettingRecord[]>([])
|
const templateList = ref<SettingRecord[]>([])
|
||||||
const templateListTime = ref<SettingRecord[]>([])
|
const templateListTime = ref<SettingRecord[]>([])
|
||||||
const getEngine = () => {
|
const getEngine = () => {
|
||||||
getDeEngine().then(res => {
|
querySymmetricKey().then(response => {
|
||||||
let { id, type, configuration } = res.data
|
getDeEngine().then(res => {
|
||||||
if (configuration) {
|
let { id, type, configuration } = res.data
|
||||||
configuration = JSON.parse(configuration)
|
if (configuration) {
|
||||||
}
|
configuration = JSON.parse(symmetricDecrypt(configuration, response.data))
|
||||||
|
|
||||||
nodeInfoId = id
|
|
||||||
|
|
||||||
templateListTime.value = [
|
|
||||||
{
|
|
||||||
pkey: 'datasource.initial_pool_size',
|
|
||||||
pval: configuration?.initialPoolSize || 5,
|
|
||||||
type: '',
|
|
||||||
sort: 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
pkey: 'datasource.min_pool_size',
|
|
||||||
pval: configuration?.minPoolSize || 5,
|
|
||||||
type: '',
|
|
||||||
sort: 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
pkey: 'datasource.max_pool_size',
|
|
||||||
pval: configuration?.maxPoolSize || 5,
|
|
||||||
type: '',
|
|
||||||
sort: 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
pkey: 'datasource.query_timeout',
|
|
||||||
pval: `${configuration?.queryTimeout || 30}${t('common.second')}`,
|
|
||||||
type: '',
|
|
||||||
sort: 0
|
|
||||||
}
|
}
|
||||||
]
|
nodeInfoId = id
|
||||||
|
templateListTime.value = [
|
||||||
|
{
|
||||||
|
pkey: 'datasource.initial_pool_size',
|
||||||
|
pval: configuration?.initialPoolSize || 5,
|
||||||
|
type: '',
|
||||||
|
sort: 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pkey: 'datasource.min_pool_size',
|
||||||
|
pval: configuration?.minPoolSize || 5,
|
||||||
|
type: '',
|
||||||
|
sort: 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pkey: 'datasource.max_pool_size',
|
||||||
|
pval: configuration?.maxPoolSize || 5,
|
||||||
|
type: '',
|
||||||
|
sort: 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pkey: 'datasource.query_timeout',
|
||||||
|
pval: `${configuration?.queryTimeout || 30}${t('common.second')}`,
|
||||||
|
type: '',
|
||||||
|
sort: 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
templateList.value = [
|
templateList.value = [
|
||||||
{
|
{
|
||||||
pkey: t('system.engine_type'),
|
pkey: t('system.engine_type'),
|
||||||
pval: typeMap[type],
|
pval: typeMap[type],
|
||||||
type: '',
|
type: '',
|
||||||
sort: 0
|
sort: 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
pkey: 'datasource.host',
|
pkey: 'datasource.host',
|
||||||
pval: configuration?.host,
|
pval: configuration?.host,
|
||||||
type: '',
|
type: '',
|
||||||
sort: 0
|
sort: 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
pkey: 'datasource.port',
|
pkey: 'datasource.port',
|
||||||
pval: configuration?.port,
|
pval: configuration?.port,
|
||||||
type: '',
|
type: '',
|
||||||
sort: 0
|
sort: 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
pkey: 'datasource.data_base',
|
pkey: 'datasource.data_base',
|
||||||
pval: configuration?.dataBase,
|
pval: configuration?.dataBase,
|
||||||
type: '',
|
type: '',
|
||||||
sort: 0
|
sort: 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
pkey: 'datasource.user_name',
|
pkey: 'datasource.user_name',
|
||||||
pval: configuration?.username,
|
pval: configuration?.username,
|
||||||
type: '',
|
type: '',
|
||||||
sort: 0
|
sort: 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
pkey: 'datasource.extra_params',
|
pkey: 'datasource.extra_params',
|
||||||
pval: configuration?.extraParams,
|
pval: configuration?.extraParams,
|
||||||
type: '',
|
type: '',
|
||||||
sort: 0
|
sort: 0
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
infoTemplate.value.init()
|
infoTemplate.value.init()
|
||||||
infoTemplateTime.value.init()
|
infoTemplateTime.value.init()
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@ -42,7 +42,13 @@ import { HandleMore } from '@/components/handle-more'
|
|||||||
import { Icon } from '@/components/icon-custom'
|
import { Icon } from '@/components/icon-custom'
|
||||||
import { fieldType } from '@/utils/attr'
|
import { fieldType } from '@/utils/attr'
|
||||||
import { useEmitt } from '@/hooks/web/useEmitt'
|
import { useEmitt } from '@/hooks/web/useEmitt'
|
||||||
import { getHidePwById, listSyncRecord, uploadFile, perDeleteDatasource } from '@/api/datasource'
|
import {
|
||||||
|
getHidePwById,
|
||||||
|
listSyncRecord,
|
||||||
|
uploadFile,
|
||||||
|
perDeleteDatasource,
|
||||||
|
getSimpleDs
|
||||||
|
} from '@/api/datasource'
|
||||||
import CreatDsGroup from './form/CreatDsGroup.vue'
|
import CreatDsGroup from './form/CreatDsGroup.vue'
|
||||||
import type { Tree } from '../dataset/form/CreatDsGroup.vue'
|
import type { Tree } from '../dataset/form/CreatDsGroup.vue'
|
||||||
import { previewData, getById } from '@/api/datasource'
|
import { previewData, getById } from '@/api/datasource'
|
||||||
@ -81,6 +87,8 @@ import { useEmbedded } from '@/store/modules/embedded'
|
|||||||
import { XpackComponent } from '@/components/plugin'
|
import { XpackComponent } from '@/components/plugin'
|
||||||
import { iconFieldMap } from '@/components/icon-group/field-list'
|
import { iconFieldMap } from '@/components/icon-group/field-list'
|
||||||
import { iconDatasourceMap } from '@/components/icon-group/datasource-list'
|
import { iconDatasourceMap } from '@/components/icon-group/datasource-list'
|
||||||
|
import { querySymmetricKey } from '@/api/login'
|
||||||
|
import { symmetricDecrypt } from '@/utils/encryption'
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
const interactiveStore = interactiveStoreWithOut()
|
const interactiveStore = interactiveStoreWithOut()
|
||||||
interface Field {
|
interface Field {
|
||||||
@ -458,6 +466,7 @@ const saveDsFolder = (params, successCb, finallyCb, cmd) => {
|
|||||||
|
|
||||||
const dsLoading = ref(false)
|
const dsLoading = ref(false)
|
||||||
const mounted = ref(false)
|
const mounted = ref(false)
|
||||||
|
const symmetricKey = ref('')
|
||||||
|
|
||||||
const listDs = () => {
|
const listDs = () => {
|
||||||
rawDatasourceList.value = []
|
rawDatasourceList.value = []
|
||||||
@ -550,7 +559,11 @@ const handleNodeClick = data => {
|
|||||||
dsListTree.value.setCurrentKey(null)
|
dsListTree.value.setCurrentKey(null)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
return getHidePwById(data.id).then(res => {
|
let method = getHidePwById
|
||||||
|
if (data.weight < 7) {
|
||||||
|
method = getSimpleDs
|
||||||
|
}
|
||||||
|
return method(data.id).then(res => {
|
||||||
let {
|
let {
|
||||||
name,
|
name,
|
||||||
createBy,
|
createBy,
|
||||||
@ -570,13 +583,13 @@ const handleNodeClick = data => {
|
|||||||
enableDataFill
|
enableDataFill
|
||||||
} = res.data
|
} = res.data
|
||||||
if (configuration) {
|
if (configuration) {
|
||||||
configuration = JSON.parse(Base64.decode(configuration))
|
configuration = JSON.parse(symmetricDecrypt(configuration, symmetricKey.value))
|
||||||
}
|
|
||||||
if (apiConfigurationStr) {
|
|
||||||
apiConfigurationStr = JSON.parse(Base64.decode(apiConfigurationStr))
|
|
||||||
}
|
}
|
||||||
if (paramsStr) {
|
if (paramsStr) {
|
||||||
paramsStr = JSON.parse(Base64.decode(paramsStr))
|
paramsStr = JSON.parse(symmetricDecrypt(paramsStr, symmetricKey.value))
|
||||||
|
}
|
||||||
|
if (apiConfigurationStr) {
|
||||||
|
apiConfigurationStr = JSON.parse(symmetricDecrypt(apiConfigurationStr, symmetricKey.value))
|
||||||
}
|
}
|
||||||
Object.assign(nodeInfo, {
|
Object.assign(nodeInfo, {
|
||||||
name,
|
name,
|
||||||
@ -697,13 +710,13 @@ const editDatasource = (editType?: number) => {
|
|||||||
enableDataFill
|
enableDataFill
|
||||||
} = res.data
|
} = res.data
|
||||||
if (configuration) {
|
if (configuration) {
|
||||||
configuration = JSON.parse(Base64.decode(configuration))
|
configuration = JSON.parse(symmetricDecrypt(configuration, symmetricKey.value))
|
||||||
}
|
}
|
||||||
if (paramsStr) {
|
if (paramsStr) {
|
||||||
paramsStr = JSON.parse(Base64.decode(paramsStr))
|
paramsStr = JSON.parse(symmetricDecrypt(paramsStr, symmetricKey.value))
|
||||||
}
|
}
|
||||||
if (apiConfigurationStr) {
|
if (apiConfigurationStr) {
|
||||||
apiConfigurationStr = JSON.parse(Base64.decode(apiConfigurationStr))
|
apiConfigurationStr = JSON.parse(symmetricDecrypt(apiConfigurationStr, symmetricKey.value))
|
||||||
}
|
}
|
||||||
let datasource = reactive<Node>(cloneDeep(defaultInfo))
|
let datasource = reactive<Node>(cloneDeep(defaultInfo))
|
||||||
Object.assign(datasource, {
|
Object.assign(datasource, {
|
||||||
@ -762,13 +775,13 @@ const handleCopy = async data => {
|
|||||||
lastSyncTime
|
lastSyncTime
|
||||||
} = res.data
|
} = res.data
|
||||||
if (configuration) {
|
if (configuration) {
|
||||||
configuration = JSON.parse(Base64.decode(configuration))
|
configuration = JSON.parse(symmetricDecrypt(configuration, symmetricKey.value))
|
||||||
}
|
}
|
||||||
if (paramsStr) {
|
if (paramsStr) {
|
||||||
paramsStr = JSON.parse(Base64.decode(paramsStr))
|
paramsStr = JSON.parse(symmetricDecrypt(paramsStr, symmetricKey.value))
|
||||||
}
|
}
|
||||||
if (apiConfigurationStr) {
|
if (apiConfigurationStr) {
|
||||||
apiConfigurationStr = JSON.parse(Base64.decode(apiConfigurationStr))
|
apiConfigurationStr = JSON.parse(symmetricDecrypt(apiConfigurationStr, symmetricKey.value))
|
||||||
}
|
}
|
||||||
let datasource = reactive<Node>(cloneDeep(defaultInfo))
|
let datasource = reactive<Node>(cloneDeep(defaultInfo))
|
||||||
Object.assign(datasource, {
|
Object.assign(datasource, {
|
||||||
@ -901,6 +914,7 @@ const operation = (cmd: string, data: Tree, nodeType: string) => {
|
|||||||
const handleClick = (tabName: TabPaneName) => {
|
const handleClick = (tabName: TabPaneName) => {
|
||||||
switch (tabName) {
|
switch (tabName) {
|
||||||
case 'config':
|
case 'config':
|
||||||
|
tableData.value = []
|
||||||
listDatasourceTables({ datasourceId: nodeInfo.id }).then(res => {
|
listDatasourceTables({ datasourceId: nodeInfo.id }).then(res => {
|
||||||
tabList.value = res.data.map(ele => {
|
tabList.value = res.data.map(ele => {
|
||||||
const { name, tableName } = ele
|
const { name, tableName } = ele
|
||||||
@ -979,6 +993,9 @@ onMounted(() => {
|
|||||||
if (opt && opt === 'create') {
|
if (opt && opt === 'create') {
|
||||||
datasourceEditor.value.init(null, null)
|
datasourceEditor.value.init(null, null)
|
||||||
}
|
}
|
||||||
|
querySymmetricKey().then(res => {
|
||||||
|
symmetricKey.value = res.data
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
const sideTreeStatus = ref(true)
|
const sideTreeStatus = ref(true)
|
||||||
@ -1433,7 +1450,9 @@ const getMenuList = (val: boolean) => {
|
|||||||
}}</BaseInfoItem>
|
}}</BaseInfoItem>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
<template v-if="!['Excel', 'API', 'es'].includes(nodeInfo.type)">
|
<template
|
||||||
|
v-if="!['Excel', 'API', 'es'].includes(nodeInfo.type) && nodeInfo.weight >= 7"
|
||||||
|
>
|
||||||
<el-row :gutter="24" v-show="nodeInfo.configuration.urlType !== 'jdbcUrl'">
|
<el-row :gutter="24" v-show="nodeInfo.configuration.urlType !== 'jdbcUrl'">
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<BaseInfoItem :label="t('datasource.host')">{{
|
<BaseInfoItem :label="t('datasource.host')">{{
|
||||||
@ -1564,7 +1583,7 @@ const getMenuList = (val: boolean) => {
|
|||||||
</el-row>
|
</el-row>
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
<template v-if="['es'].includes(nodeInfo.type)">
|
<template v-if="['es'].includes(nodeInfo.type) && nodeInfo.weight >= 7">
|
||||||
<el-row :gutter="24">
|
<el-row :gutter="24">
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<BaseInfoItem :label="t('datasource.datasource_url')">{{
|
<BaseInfoItem :label="t('datasource.datasource_url')">{{
|
||||||
@ -1576,7 +1595,7 @@ const getMenuList = (val: boolean) => {
|
|||||||
</template>
|
</template>
|
||||||
</BaseInfoContent>
|
</BaseInfoContent>
|
||||||
<BaseInfoContent
|
<BaseInfoContent
|
||||||
v-if="nodeInfo.type === 'API'"
|
v-if="nodeInfo.type === 'API' && nodeInfo.weight >= 7"
|
||||||
v-slot="slotProps"
|
v-slot="slotProps"
|
||||||
:name="t('datasource.data_table')"
|
:name="t('datasource.data_table')"
|
||||||
>
|
>
|
||||||
@ -1633,7 +1652,7 @@ const getMenuList = (val: boolean) => {
|
|||||||
</el-button>
|
</el-button>
|
||||||
</BaseInfoContent>
|
</BaseInfoContent>
|
||||||
<BaseInfoContent
|
<BaseInfoContent
|
||||||
v-if="nodeInfo.type === 'API'"
|
v-if="nodeInfo.type === 'API' && nodeInfo.weight >= 7"
|
||||||
v-slot="slotProps"
|
v-slot="slotProps"
|
||||||
:name="t('dataset.update_setting')"
|
:name="t('dataset.update_setting')"
|
||||||
:time="(nodeInfo.lastSyncTime as string)"
|
:time="(nodeInfo.lastSyncTime as string)"
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import lombok.Data;
|
|||||||
|
|
||||||
import java.io.Serial;
|
import java.io.Serial;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Author wangjiahao
|
* @Author wangjiahao
|
||||||
@ -26,4 +27,6 @@ public class ChartExcelRequest extends ChartExcelRequestInner {
|
|||||||
|
|
||||||
private String downloadType;
|
private String downloadType;
|
||||||
|
|
||||||
|
private Map<String, Object> data;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -87,16 +87,21 @@ public interface DatasourceApi {
|
|||||||
@Operation(summary = "删除")
|
@Operation(summary = "删除")
|
||||||
void delete(@PathVariable("datasourceId") Long datasourceId) throws DEException;
|
void delete(@PathVariable("datasourceId") Long datasourceId) throws DEException;
|
||||||
|
|
||||||
@DePermit({"#p0+':read'"})
|
@DePermit({"#p0+':manage'"})
|
||||||
@GetMapping("/get/{datasourceId}")
|
@GetMapping("/get/{datasourceId}")
|
||||||
@Operation(summary = "数据源详情")
|
@Operation(summary = "数据源详情")
|
||||||
DatasourceDTO get(@PathVariable("datasourceId") Long datasourceId) throws DEException;
|
DatasourceDTO get(@PathVariable("datasourceId") Long datasourceId) throws DEException;
|
||||||
|
|
||||||
@DePermit({"#p0+':read'"})
|
@DePermit({"#p0+':manage'"})
|
||||||
@GetMapping("/hidePw/{datasourceId}")
|
@GetMapping("/hidePw/{datasourceId}")
|
||||||
@Operation(summary = "数据源详情")
|
@Operation(summary = "数据源详情")
|
||||||
DatasourceDTO hidePw(@PathVariable("datasourceId") Long datasourceId) throws DEException;
|
DatasourceDTO hidePw(@PathVariable("datasourceId") Long datasourceId) throws DEException;
|
||||||
|
|
||||||
|
@DePermit({"#p0+':read'"})
|
||||||
|
@GetMapping("/getSimpleDs/{datasourceId}")
|
||||||
|
@Operation(summary = "数据源详情")
|
||||||
|
DatasourceDTO getSimpleDs(@PathVariable("datasourceId") Long datasourceId) throws DEException;
|
||||||
|
|
||||||
|
|
||||||
@PostMapping("/getTableField")
|
@PostMapping("/getTableField")
|
||||||
@Operation(summary = "获取表字段")
|
@Operation(summary = "获取表字段")
|
||||||
|
|||||||
@ -8,9 +8,11 @@ import io.dataease.rsa.manage.RsaManage;
|
|||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
import org.apache.commons.lang3.ObjectUtils;
|
import org.apache.commons.lang3.ObjectUtils;
|
||||||
import org.apache.commons.lang3.RandomStringUtils;
|
import org.apache.commons.lang3.RandomStringUtils;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import javax.crypto.Cipher;
|
import javax.crypto.Cipher;
|
||||||
|
import javax.crypto.KeyGenerator;
|
||||||
import javax.crypto.SecretKey;
|
import javax.crypto.SecretKey;
|
||||||
import javax.crypto.spec.IvParameterSpec;
|
import javax.crypto.spec.IvParameterSpec;
|
||||||
import javax.crypto.spec.SecretKeySpec;
|
import javax.crypto.spec.SecretKeySpec;
|
||||||
@ -176,7 +178,7 @@ public class RsaUtils {
|
|||||||
return pk + separator + aesKey;
|
return pk + separator + aesKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final String IV_KEY = "0000000000000000";
|
public static final String IV_KEY = "0000000000000000";
|
||||||
|
|
||||||
private static String generateAesKey() {
|
private static String generateAesKey() {
|
||||||
return RandomStringUtils.randomAlphanumeric(16);
|
return RandomStringUtils.randomAlphanumeric(16);
|
||||||
@ -200,4 +202,53 @@ public class RsaUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static final String ALGORITHM = "AES";
|
||||||
|
public static String symmetricKey = null;
|
||||||
|
private static final int KEY_SIZE = 128;
|
||||||
|
|
||||||
|
|
||||||
|
public static String generateSymmetricKey() {
|
||||||
|
try {
|
||||||
|
if (StringUtils.isEmpty(symmetricKey)) {
|
||||||
|
KeyGenerator keyGenerator = KeyGenerator.getInstance(ALGORITHM);
|
||||||
|
keyGenerator.init(KEY_SIZE, new SecureRandom());
|
||||||
|
SecretKey secretKey = keyGenerator.generateKey();
|
||||||
|
symmetricKey = Base64.getEncoder().encodeToString(secretKey.getEncoded());
|
||||||
|
}
|
||||||
|
return symmetricKey;
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String symmetricEncrypt(String data) {
|
||||||
|
try {
|
||||||
|
byte[] iv = IV_KEY.getBytes(StandardCharsets.UTF_8);
|
||||||
|
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
|
||||||
|
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
|
||||||
|
SecretKeySpec secretKeySpec = new SecretKeySpec(Base64.getDecoder().decode(generateSymmetricKey()), ALGORITHM);
|
||||||
|
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
|
||||||
|
byte[] ciphertext = cipher.doFinal(data.getBytes("UTF-8"));
|
||||||
|
return Base64.getEncoder().encodeToString(ciphertext);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String symmetricDecrypt(String data) {
|
||||||
|
try {
|
||||||
|
byte[] iv = IV_KEY.getBytes(StandardCharsets.UTF_8);
|
||||||
|
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
|
||||||
|
SecretKeySpec secretKeySpec = new SecretKeySpec(Base64.getDecoder().decode(generateSymmetricKey()), ALGORITHM);
|
||||||
|
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
|
||||||
|
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec);
|
||||||
|
byte[] decodedCiphertext = Base64.getDecoder().decode(data);
|
||||||
|
byte[] decryptedText = cipher.doFinal(decodedCiphertext);
|
||||||
|
return new String(decryptedText, "UTF-8");
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -24,6 +24,7 @@ public class WhitelistUtils {
|
|||||||
"/login/localLogin",
|
"/login/localLogin",
|
||||||
"/apisix/check",
|
"/apisix/check",
|
||||||
"/dekey",
|
"/dekey",
|
||||||
|
"/symmetricKey",
|
||||||
"/index.html",
|
"/index.html",
|
||||||
"/model",
|
"/model",
|
||||||
"/xpackModel",
|
"/xpackModel",
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user