From ca312c7fcdec0ea1d0fe39c96088c2e8d026ec17 Mon Sep 17 00:00:00 2001 From: fit2cloud-chenyw Date: Tue, 27 Jun 2023 11:01:59 +0800 Subject: [PATCH 1/7] =?UTF-8?q?perf(sql=E7=99=BD=E5=90=8D=E5=8D=95):=20sql?= =?UTF-8?q?=E6=B3=A8=E5=85=A5=E6=A3=80=E6=B5=8B=E7=99=BD=E5=90=8D=E5=8D=95?= =?UTF-8?q?=E7=94=B1=E5=A4=96=E9=83=A8=E9=85=8D=E7=BD=AE=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E8=A6=86=E7=9B=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../XssAndSqlHttpServletRequestWrapper.java | 48 ++++++++++--------- .../src/main/resources/application.properties | 2 +- 2 files changed, 26 insertions(+), 24 deletions(-) diff --git a/backend/src/main/java/io/dataease/commons/wrapper/XssAndSqlHttpServletRequestWrapper.java b/backend/src/main/java/io/dataease/commons/wrapper/XssAndSqlHttpServletRequestWrapper.java index 672f89d46a..0686f48b8f 100644 --- a/backend/src/main/java/io/dataease/commons/wrapper/XssAndSqlHttpServletRequestWrapper.java +++ b/backend/src/main/java/io/dataease/commons/wrapper/XssAndSqlHttpServletRequestWrapper.java @@ -1,18 +1,6 @@ package io.dataease.commons.wrapper; -import java.io.BufferedReader; -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.InputStreamReader; -import java.util.*; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import javax.servlet.ReadListener; -import javax.servlet.ServletInputStream; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletRequestWrapper; - import com.google.gson.Gson; import io.dataease.commons.holder.ThreadLocalContextHolder; import io.dataease.commons.utils.CommonBeanFactory; @@ -21,16 +9,30 @@ import org.apache.commons.lang3.StringUtils; import org.springframework.core.env.Environment; import org.springframework.util.StreamUtils; +import javax.servlet.ReadListener; +import javax.servlet.ServletInputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletRequestWrapper; +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + public class XssAndSqlHttpServletRequestWrapper extends HttpServletRequestWrapper { private static Gson gson = new Gson(); + private static final String defaultWhiteList = "/dataset/table/sqlPreview,/dataset/table/update,/dataset/field/multFieldValues,/dataset/field/linkMultFieldValues"; + HttpServletRequest orgRequest = null; private Map parameterMap; private final byte[] body; //用于保存读取body中数据 - public XssAndSqlHttpServletRequestWrapper(HttpServletRequest request) throws IOException{ + public XssAndSqlHttpServletRequestWrapper(HttpServletRequest request) throws IOException { super(request); orgRequest = request; parameterMap = request.getParameterMap(); @@ -38,6 +40,7 @@ public class XssAndSqlHttpServletRequestWrapper extends HttpServletRequestWrappe } // 重写几个HttpServletRequestWrapper中的方法 + /** * 获取所有参数名 * @@ -159,7 +162,6 @@ public class XssAndSqlHttpServletRequestWrapper extends HttpServletRequestWrappe } /** - * * 防止xss跨脚本攻击(替换,根据实际情况调整) */ @@ -208,9 +210,9 @@ public class XssAndSqlHttpServletRequestWrapper extends HttpServletRequestWrappe return value; } - public static boolean checkSqlInjection(Object obj){ + public static boolean checkSqlInjection(Object obj) { HttpServletRequest request = ServletUtils.request(); - String url = request.getRequestURI().toString(); + String url = request.getRequestURI(); if (null == obj) return false; if (StringUtils.isEmpty(obj.toString())) return false; @@ -219,14 +221,14 @@ public class XssAndSqlHttpServletRequestWrapper extends HttpServletRequestWrappe if (StringUtils.isEmpty(orders)) return false; - String whiteLists = CommonBeanFactory.getBean(Environment.class).getProperty("dataease.sqlinjection.whitelists", String.class, null); + String whiteLists = CommonBeanFactory.getBean(Environment.class).getProperty("dataease.sqlinjection.whitelists", String.class, defaultWhiteList); if (StringUtils.isNotEmpty(whiteLists)) { // 命中白名单 无需检测sql注入 if (Arrays.stream(whiteLists.split(",")).anyMatch(item -> url.indexOf(item) != -1)) return false; } - Pattern pattern= Pattern.compile("(.*\\=.*\\-\\-.*)|(.*(\\+).*)|(.*\\w+(%|\\$|#|&)\\w+.*)|(.*\\|\\|.*)|(.*\\s+(and|or)\\s+.*)" + + Pattern pattern = Pattern.compile("(.*\\=.*\\-\\-.*)|(.*(\\+).*)|(.*\\w+(%|\\$|#|&)\\w+.*)|(.*\\|\\|.*)|(.*\\s+(and|or)\\s+.*)" + "|(.*\\b(select|update|union|and|or|delete|insert|trancate|char|into|substr|ascii|declare|exec|count|master|into|drop|execute|sleep|extractvalue|updatexml|substring|database|concat|rand|gtid_subset)\\b.*)"); - Matcher matcher=pattern.matcher(orders.toLowerCase()); + Matcher matcher = pattern.matcher(orders.toLowerCase()); return matcher.find(); } @@ -236,7 +238,7 @@ public class XssAndSqlHttpServletRequestWrapper extends HttpServletRequestWrappe if (value != null) { boolean b = checkSqlInjection(value); - if(b) { + if (b) { ThreadLocalContextHolder.setData("包含SQL注入的参数,请检查参数!"); return true; } @@ -320,7 +322,7 @@ public class XssAndSqlHttpServletRequestWrapper extends HttpServletRequestWrappe return true; } } else if ((submitValues instanceof String[])) { - for (String submitValue : (String[])submitValues){ + for (String submitValue : (String[]) submitValues) { if (checkXSSAndSql(submitValue)) { return true; } @@ -332,7 +334,7 @@ public class XssAndSqlHttpServletRequestWrapper extends HttpServletRequestWrappe private static String orders(String json) { if (StringUtils.isEmpty(json)) return null; - try{ + try { Map map = new Gson().fromJson(json, Map.class); Object orders = map.get("orders"); @@ -345,7 +347,7 @@ public class XssAndSqlHttpServletRequestWrapper extends HttpServletRequestWrappe return sort.toString(); } return null; - }catch (Exception e) { + } catch (Exception e) { return null; } diff --git a/backend/src/main/resources/application.properties b/backend/src/main/resources/application.properties index e2095991b5..fb50ef16d8 100644 --- a/backend/src/main/resources/application.properties +++ b/backend/src/main/resources/application.properties @@ -68,7 +68,7 @@ spring.cache.ehcache.config=classpath:/ehcache/ehcache.xml pagehelper.PageRowBounds=true #excel\u7B49\u7528\u6237\u4E0A\u4F20\u6587\u4EF6\u8DEF\u5F84 upload.file.path=/opt/dataease/data/kettle/ -dataease.sqlinjection.whitelists=/dataset/table/sqlPreview,/dataset/table/update,/dataset/field/multFieldValues,/dataset/field/linkMultFieldValues +#dataease.sqlinjection.whitelists=/dataset/table/sqlPreview,/dataset/table/update,/dataset/field/multFieldValues,/dataset/field/linkMultFieldValues #\u5F00\u542F\u538B\u7F29 \u63D0\u9AD8\u54CD\u5E94\u901F\u5EA6 \u51CF\u5C11\u5E26\u5BBD\u538B\u529B server.compression.enabled=true server.compression.mime-types=application/javascript,text/css,application/json,application/xml,text/html,text/xml,text/plain From 0285fbe4c156f31f1b96aa510adb48b1d5e8ad63 Mon Sep 17 00:00:00 2001 From: xuwei-fit2cloud Date: Wed, 28 Jun 2023 09:43:49 +0800 Subject: [PATCH 2/7] =?UTF-8?q?chore:=20=E5=8D=87=E7=BA=A7=E7=89=88?= =?UTF-8?q?=E6=9C=AC=E5=8F=B7=E8=87=B31.18.9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/main/resources/db/migration/V56__1.18.9.sql | 4 ++++ frontend/package.json | 2 +- mobile/package.json | 2 +- pom.xml | 2 +- 4 files changed, 7 insertions(+), 3 deletions(-) create mode 100644 backend/src/main/resources/db/migration/V56__1.18.9.sql diff --git a/backend/src/main/resources/db/migration/V56__1.18.9.sql b/backend/src/main/resources/db/migration/V56__1.18.9.sql new file mode 100644 index 0000000000..3d6018d62f --- /dev/null +++ b/backend/src/main/resources/db/migration/V56__1.18.9.sql @@ -0,0 +1,4 @@ +UPDATE `my_plugin` +SET `version` = '1.18.9' +where `plugin_id` > 0 + and `version` = '1.18.8'; diff --git a/frontend/package.json b/frontend/package.json index a7449158f9..ba27c63f0d 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,6 +1,6 @@ { "name": "dataease", - "version": "1.18.8", + "version": "1.18.9", "description": "dataease front", "private": true, "scripts": { diff --git a/mobile/package.json b/mobile/package.json index 7988373a45..41def72170 100644 --- a/mobile/package.json +++ b/mobile/package.json @@ -1,6 +1,6 @@ { "name": "dataease-mobile", - "version": "1.18.8", + "version": "1.18.9", "private": true, "scripts": { "serve": "npm run dev:h5", diff --git a/pom.xml b/pom.xml index f370ded74d..4bc424337f 100644 --- a/pom.xml +++ b/pom.xml @@ -16,7 +16,7 @@ - 1.18.8 + 1.18.9 dataease From e72555785d8ea31ca9c9855f8ecd22e78f24f64b Mon Sep 17 00:00:00 2001 From: wisonic-s Date: Wed, 28 Jun 2023 18:21:33 +0800 Subject: [PATCH 3/7] =?UTF-8?q?fix(=E8=A7=86=E5=9B=BE-Excel=E5=AF=BC?= =?UTF-8?q?=E5=87=BA):=20=E4=BF=AE=E5=A4=8D=E5=AF=BC=E5=87=BA=E6=8C=89?= =?UTF-8?q?=E9=92=AE=E5=8F=8A=E9=A2=84=E8=A7=88=E7=95=8C=E9=9D=A2=E5=AF=BC?= =?UTF-8?q?=E5=87=BA=E5=BC=82=E5=B8=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../canvas/components/editor/ComponentWrapper.vue | 13 +++++++++---- .../components/canvas/components/editor/EditBar.vue | 2 +- frontend/src/components/canvas/utils/utils.js | 3 +++ frontend/src/icons/svg/file-excel.svg | 1 + 4 files changed, 14 insertions(+), 5 deletions(-) create mode 100644 frontend/src/icons/svg/file-excel.svg diff --git a/frontend/src/components/canvas/components/editor/ComponentWrapper.vue b/frontend/src/components/canvas/components/editor/ComponentWrapper.vue index 7f444018a5..b6111656ef 100644 --- a/frontend/src/components/canvas/components/editor/ComponentWrapper.vue +++ b/frontend/src/components/canvas/components/editor/ComponentWrapper.vue @@ -151,13 +151,18 @@ export default { data() { return { previewVisible: false, - chart: null, seriesIdMap: { id: '' } } }, computed: { + chart() { + if (this.config.propValue?.viewId) { + return JSON.parse(this.panelViewDetailsInfo[this.config.propValue.viewId]) + } + return null + }, componentCanvasId() { if (this.config.type === 'view') { return 'user-view-' + this.config.propValue.viewId @@ -216,7 +221,8 @@ export default { 'mobileLayoutStatus', 'curComponent', 'previewCanvasScale', - 'componentGap' + 'componentGap', + 'panelViewDetailsInfo' ]) }, mounted() { @@ -286,8 +292,7 @@ export default { } } else { return { - ... - getStyle(style, ['top', 'left', 'width', 'height', 'rotate']), + ...getStyle(style, ['top', 'left', 'width', 'height', 'rotate']), position: 'relative' } } diff --git a/frontend/src/components/canvas/components/editor/EditBar.vue b/frontend/src/components/canvas/components/editor/EditBar.vue index eddb002f73..a185a38f08 100644 --- a/frontend/src/components/canvas/components/editor/EditBar.vue +++ b/frontend/src/components/canvas/components/editor/EditBar.vue @@ -294,7 +294,7 @@ export default { return this.curComponent.type === 'view' && this.terminal === 'pc' && this.curComponent.propValue.innerType && this.curComponent.propValue.innerType !== 'richTextView' }, exportExcelShow() { - return this.detailsShow && hasDataPermission('export', this.$store.state.panel.panelInfo.privileges) + return this.detailsShow && hasDataPermission('export', this.$store.state.panel.panelInfo.privileges) && this.chart }, enlargeShow() { return this.curComponent.type === 'view' && this.curComponent.propValue.innerType && this.curComponent.propValue.innerType !== 'richTextView' && !this.curComponent.propValue.innerType.includes('table') diff --git a/frontend/src/components/canvas/utils/utils.js b/frontend/src/components/canvas/utils/utils.js index 84157b5295..bd262fc4d1 100644 --- a/frontend/src/components/canvas/utils/utils.js +++ b/frontend/src/components/canvas/utils/utils.js @@ -429,6 +429,9 @@ export function getCacheTree(treeName) { } export function exportExcelDownload(chart, snapshot, width, height, loadingWrapper, callBack) { + if (!chart.data?.data?.length) { + return + } const fields = JSON.parse(JSON.stringify(chart.data.fields)) const tableRow = JSON.parse(JSON.stringify(chart.data.tableRow)) const excelHeader = fields.map(item => item.name) diff --git a/frontend/src/icons/svg/file-excel.svg b/frontend/src/icons/svg/file-excel.svg new file mode 100644 index 0000000000..253306726f --- /dev/null +++ b/frontend/src/icons/svg/file-excel.svg @@ -0,0 +1 @@ + From ae7e3825bde3fb1799d9ab7e35ce7f9a90e8034f Mon Sep 17 00:00:00 2001 From: junjun Date: Thu, 29 Jun 2023 10:24:17 +0800 Subject: [PATCH 4/7] =?UTF-8?q?fix(=E8=A7=86=E5=9B=BE):=20=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=E8=BE=85=E5=8A=A9=E7=BA=BF=E5=8A=A8=E6=80=81=E5=80=BC?= =?UTF-8?q?=E6=8A=A5=E9=94=99=20#5534?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dataease/service/chart/ChartViewService.java | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/backend/src/main/java/io/dataease/service/chart/ChartViewService.java b/backend/src/main/java/io/dataease/service/chart/ChartViewService.java index 6077bbe9eb..1b7384fd61 100644 --- a/backend/src/main/java/io/dataease/service/chart/ChartViewService.java +++ b/backend/src/main/java/io/dataease/service/chart/ChartViewService.java @@ -33,6 +33,7 @@ import io.dataease.plugins.common.base.mapper.ChartViewMapper; import io.dataease.plugins.common.base.mapper.DatasetTableFieldMapper; import io.dataease.plugins.common.base.mapper.PanelViewMapper; import io.dataease.plugins.common.constants.DatasetType; +import io.dataease.plugins.common.constants.DatasourceTypes; import io.dataease.plugins.common.constants.datasource.SQLConstants; import io.dataease.plugins.common.dto.chart.ChartCustomFilterItemDTO; import io.dataease.plugins.common.dto.chart.ChartFieldCompareDTO; @@ -611,7 +612,7 @@ public class ChartViewService { xAxis.addAll(xAxisExt); } List yAxis = gson.fromJson(view.getYAxis(), tokenType); - if (StringUtils.equalsAnyIgnoreCase(view.getType(), "chart-mix","bidirectional-bar")) { + if (StringUtils.equalsAnyIgnoreCase(view.getType(), "chart-mix", "bidirectional-bar")) { List yAxisExt = gson.fromJson(view.getYAxisExt(), tokenType); yAxis.addAll(yAxisExt); } @@ -1126,7 +1127,7 @@ public class ChartViewService { datasourceRequest.setTotalPageFlag(false); data = datasourceProvider.getData(datasourceRequest); if (CollectionUtils.isNotEmpty(assistFields)) { - datasourceAssistRequest.setQuery(assistSQL(datasourceRequest.getQuery(), assistFields)); + datasourceAssistRequest.setQuery(assistSQL(datasourceRequest.getQuery(), assistFields, ds)); logger.info(datasourceAssistRequest.getQuery()); assistData = datasourceProvider.getData(datasourceAssistRequest); } @@ -1158,7 +1159,7 @@ public class ChartViewService { } } if (CollectionUtils.isNotEmpty(assistFields)) { - datasourceAssistRequest.setQuery(assistSQL(datasourceRequest.getQuery(), assistFields)); + datasourceAssistRequest.setQuery(assistSQL(datasourceRequest.getQuery(), assistFields, ds)); logger.info(datasourceAssistRequest.getQuery()); assistData = datasourceProvider.getData(datasourceAssistRequest); } @@ -1405,14 +1406,15 @@ public class ChartViewService { return res; } - public String assistSQL(String sql, List assistFields) { + public String assistSQL(String sql, List assistFields, Datasource ds) { + DatasourceTypes datasourceType = DatasourceTypes.valueOf(ds.getType()); StringBuilder stringBuilder = new StringBuilder(); for (int i = 0; i < assistFields.size(); i++) { ChartViewFieldDTO dto = assistFields.get(i); if (i == (assistFields.size() - 1)) { - stringBuilder.append(dto.getSummary() + "(" + dto.getOriginName() + ")"); + stringBuilder.append(dto.getSummary() + "(" + datasourceType.getKeywordPrefix() + dto.getOriginName() + datasourceType.getKeywordSuffix() + ")"); } else { - stringBuilder.append(dto.getSummary() + "(" + dto.getOriginName() + "),"); + stringBuilder.append(dto.getSummary() + "(" + datasourceType.getKeywordPrefix() + dto.getOriginName() + datasourceType.getKeywordSuffix() + "),"); } } return "SELECT " + stringBuilder + " FROM (" + sql + ") tmp"; From 7440fe4330afb52a703223fe7f09021c6949e7fa Mon Sep 17 00:00:00 2001 From: fit2cloud-chenyw Date: Fri, 30 Jun 2023 12:13:56 +0800 Subject: [PATCH 5/7] =?UTF-8?q?perf(=E8=A7=86=E5=9B=BE):=20=E5=9C=B0?= =?UTF-8?q?=E5=9B=BE=E6=8F=90=E7=A4=BA=E5=A2=9E=E5=8A=A0=E9=9A=90=E8=97=8F?= =?UTF-8?q?=E7=A9=BA=E5=80=BC=E8=AE=BE=E7=BD=AE#5562?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/lang/en.js | 2 ++ frontend/src/lang/tw.js | 2 ++ frontend/src/lang/zh.js | 2 ++ frontend/src/views/chart/chart/map/map.js | 6 +++++- frontend/src/views/chart/chart/util.js | 1 + .../chart/components/shapeAttr/TooltipSelector.vue | 10 ++++++++++ 6 files changed, 22 insertions(+), 1 deletion(-) diff --git a/frontend/src/lang/en.js b/frontend/src/lang/en.js index e78404581a..633c74808d 100644 --- a/frontend/src/lang/en.js +++ b/frontend/src/lang/en.js @@ -935,6 +935,8 @@ export default { password_input_error: 'Original password input error' }, chart: { + empty_hide: 'hiden empty', + hide: 'hide', chart_refresh_tips: 'View refresh setting takes precedence over panel refresh setting', '1-trend': 'trend', '2-state': 'State', diff --git a/frontend/src/lang/tw.js b/frontend/src/lang/tw.js index 9c09e989fa..05355e1942 100644 --- a/frontend/src/lang/tw.js +++ b/frontend/src/lang/tw.js @@ -934,6 +934,8 @@ export default { password_input_error: '原始密碼輸入錯誤' }, chart: { + empty_hide: '隱藏空值', + hide: '隱藏', chart_refresh_tips: '視圖刷新設置優先於儀表板刷新設置', '1-trend': '趨勢', '2-state': '狀態', diff --git a/frontend/src/lang/zh.js b/frontend/src/lang/zh.js index fc55889561..7bb7c43200 100644 --- a/frontend/src/lang/zh.js +++ b/frontend/src/lang/zh.js @@ -933,6 +933,8 @@ export default { password_input_error: '原始密码输入错误' }, chart: { + empty_hide: '隐藏空值', + hide: '隐藏', chart_refresh_tips: '视图刷新设置优先于仪表板刷新设置', '1-trend': '趋势', '2-state': '状态', diff --git a/frontend/src/views/chart/chart/map/map.js b/frontend/src/views/chart/chart/map/map.js index 1d534f9a9e..5433ca8441 100644 --- a/frontend/src/views/chart/chart/map/map.js +++ b/frontend/src/views/chart/chart/map/map.js @@ -72,9 +72,13 @@ export function baseMapOption(chart_option, geoJson, chart, themeStyle, curAreaC const reg = new RegExp('\n', 'g') const text = tooltip.formatter.replace(reg, '
') tooltip.formatter = params => { + const val = params.value + if (tooltip.emptyHide && (val === null || typeof val === 'undefined' || isNaN(val))) { + return '' + } const a = params.seriesName const b = params.name - const c = params.value ?? '' + const c = (val === null || typeof val === 'undefined' || isNaN(val)) ? '' : val return text.replace(new RegExp('{a}', 'g'), a).replace(new RegExp('{b}', 'g'), b).replace(new RegExp('{c}', 'g'), c) } chart_option.tooltip = tooltip diff --git a/frontend/src/views/chart/chart/util.js b/frontend/src/views/chart/chart/util.js index 52ad0e780b..2d06070bdd 100644 --- a/frontend/src/views/chart/chart/util.js +++ b/frontend/src/views/chart/chart/util.js @@ -3323,6 +3323,7 @@ export const TYPE_CONFIGS = [ ], 'tooltip-selector': [ 'show', + 'emptyHide', 'textStyle', 'formatter' ], diff --git a/frontend/src/views/chart/components/shapeAttr/TooltipSelector.vue b/frontend/src/views/chart/components/shapeAttr/TooltipSelector.vue index 618d32e305..b04e740df2 100644 --- a/frontend/src/views/chart/components/shapeAttr/TooltipSelector.vue +++ b/frontend/src/views/chart/components/shapeAttr/TooltipSelector.vue @@ -18,6 +18,16 @@ >{{ $t('chart.show') }}
+ + {{ $t('chart.hide') }} + Date: Fri, 30 Jun 2023 16:59:06 +0800 Subject: [PATCH 6/7] =?UTF-8?q?fix:=20=E6=8B=BC=E5=86=99=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/lang/en.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/lang/en.js b/frontend/src/lang/en.js index 633c74808d..bf2ffbffa2 100644 --- a/frontend/src/lang/en.js +++ b/frontend/src/lang/en.js @@ -935,7 +935,7 @@ export default { password_input_error: 'Original password input error' }, chart: { - empty_hide: 'hiden empty', + empty_hide: 'hide empty', hide: 'hide', chart_refresh_tips: 'View refresh setting takes precedence over panel refresh setting', '1-trend': 'trend', From bc7d072e6a1ef5abe9521e8207839bd5cbb58157 Mon Sep 17 00:00:00 2001 From: fit2cloud-chenyw Date: Mon, 3 Jul 2023 10:17:39 +0800 Subject: [PATCH 7/7] =?UTF-8?q?fix(=E6=8F=92=E4=BB=B6=E7=AE=A1=E7=90=86):?= =?UTF-8?q?=20=E6=8F=92=E4=BB=B6=E6=96=87=E4=BB=B6=E4=B8=8A=E4=BC=A0?= =?UTF-8?q?=E6=BC=8F=E6=B4=9E#5559?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/io/dataease/commons/utils/DeFileUtils.java | 13 +++++++++++++ .../controller/sys/SysPluginController.java | 7 +++++-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/backend/src/main/java/io/dataease/commons/utils/DeFileUtils.java b/backend/src/main/java/io/dataease/commons/utils/DeFileUtils.java index 6adc42e9be..2dcee5fa41 100644 --- a/backend/src/main/java/io/dataease/commons/utils/DeFileUtils.java +++ b/backend/src/main/java/io/dataease/commons/utils/DeFileUtils.java @@ -1,5 +1,7 @@ package io.dataease.commons.utils; +import io.dataease.commons.exception.DEException; +import org.apache.commons.lang3.StringUtils; import org.springframework.web.multipart.MultipartFile; import java.io.*; @@ -41,6 +43,17 @@ public class DeFileUtils { if (dir.exists()) return ; dir.mkdirs(); } + + public static void validateFile(MultipartFile file) { + String name = getFileNameNoEx(file.getOriginalFilename()); + if (StringUtils.contains(name, "./")) { + DEException.throwException("file path invalid"); + } + String suffix = getExtensionName(file.getOriginalFilename()); + if (!StringUtils.equalsIgnoreCase(suffix, "zip")) { + DEException.throwException("please upload valid zip file"); + } + } /** * 将文件名解析成文件的上传路径 */ diff --git a/backend/src/main/java/io/dataease/controller/sys/SysPluginController.java b/backend/src/main/java/io/dataease/controller/sys/SysPluginController.java index 7f3b3e669f..d8e32122c4 100644 --- a/backend/src/main/java/io/dataease/controller/sys/SysPluginController.java +++ b/backend/src/main/java/io/dataease/controller/sys/SysPluginController.java @@ -3,10 +3,11 @@ package io.dataease.controller.sys; import com.github.pagehelper.Page; import com.github.pagehelper.PageHelper; import io.dataease.auth.annotation.SqlInjectValidator; -import io.dataease.plugins.common.base.domain.MyPlugin; +import io.dataease.commons.utils.DeFileUtils; import io.dataease.commons.utils.PageUtils; import io.dataease.commons.utils.Pager; import io.dataease.controller.sys.base.BaseGridRequest; +import io.dataease.plugins.common.base.domain.MyPlugin; import io.dataease.service.sys.PluginService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; @@ -41,6 +42,7 @@ public class SysPluginController { @PostMapping("upload") @RequiresPermissions("plugin:upload") public Map localUpload(@RequestParam("file") MultipartFile file) throws Exception { + DeFileUtils.validateFile(file); return pluginService.localInstall(file); } @@ -54,7 +56,8 @@ public class SysPluginController { @ApiOperation("更新插件") @PostMapping("/update/{pluginId}") @RequiresPermissions("plugin:upload") - public Map update(@PathVariable("pluginId") Long pluginId, @RequestParam("file") MultipartFile file) throws Exception{ + public Map update(@PathVariable("pluginId") Long pluginId, @RequestParam("file") MultipartFile file) throws Exception { + DeFileUtils.validateFile(file); if (pluginService.uninstall(pluginId)) { return pluginService.localInstall(file); }