Merge pull request #12066 from dataease/dev

merge Dev
This commit is contained in:
fit2cloudrd 2024-09-06 15:29:14 +08:00 committed by GitHub
commit ffb7146472
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
17 changed files with 169 additions and 37 deletions

View File

@ -1,9 +1,14 @@
package io.dataease.auth.config.cas;
import com.auth0.jwt.JWT;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import io.dataease.auth.service.impl.ShiroServiceImpl;
import io.dataease.commons.utils.CommonBeanFactory;
import io.dataease.commons.utils.LogUtil;
import io.dataease.commons.utils.ServletUtils;
import io.dataease.service.system.SystemParameterService;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.util.AntPathMatcher;
import org.jasig.cas.client.authentication.UrlPatternMatcherStrategy;
@ -38,9 +43,9 @@ public class CasStrategy implements UrlPatternMatcherStrategy {
s = s.substring(beginIndex + serverName.length());
}
if (StringUtils.equals("/", s)) {
if (fromLink(serverName)) return true;
return false;
return fromLink(serverName);
}
if (fromShot()) return true;
if (StringUtils.equals("/login", s)) return false;
if (StringUtils.startsWith(s, "/cas/callBack")) return false;
if (StringUtils.equals("/api/auth/deLogout", s)) return true;
@ -74,4 +79,17 @@ public class CasStrategy implements UrlPatternMatcherStrategy {
}
return false;
}
private Boolean fromShot() {
String token = ServletUtils.getToken();
if (StringUtils.isBlank(token)) return false;
try {
DecodedJWT jwt = JWT.decode(token);
Claim forShot = jwt.getClaim("forShot");
return ObjectUtils.isNotEmpty(forShot) && forShot.asBoolean();
} catch (Exception e) {
LogUtil.error(e.getMessage());
return false;
}
}
}

View File

@ -125,6 +125,18 @@ public class JWTUtils {
return IPUtils.get();
}
public static String signShotToken(TokenInfo tokenInfo, String secret) {
Long userId = tokenInfo.getUserId();
long expireTimeMillis = getExpireTime();
Date date = new Date(System.currentTimeMillis() + expireTimeMillis);
Algorithm algorithm = Algorithm.HMAC256(secret);
Builder builder = JWT.create()
.withClaim("username", tokenInfo.getUsername())
.withClaim("forShot", true)
.withClaim("userId", userId);
return builder.withExpiresAt(date).sign(algorithm);
}
public static String sign(TokenInfo tokenInfo, String secret, boolean writeOnline) {
Long userId = tokenInfo.getUserId();

View File

@ -435,9 +435,7 @@ public class EmailTaskHandler extends TaskHandler implements Job {
private String tokenByUser(SysUserEntity user) {
TokenInfo tokenInfo = TokenInfo.builder().userId(user.getUserId()).username(user.getUsername()).build();
String token = JWTUtils.sign(tokenInfo, user.getPassword(), false);
return token;
return JWTUtils.signShotToken(tokenInfo, user.getPassword());
}
private String panelUrl(String panelId) {
@ -445,4 +443,10 @@ public class EmailTaskHandler extends TaskHandler implements Job {
return domain + "/#/previewScreenShot/" + panelId + "/true";
}
public static void main(String[] args) {
TokenInfo tokenInfo = TokenInfo.builder().userId(1L).username("admin").build();
String contextPath = JWTUtils.signShotToken(tokenInfo, "ae8000252199d4f2aa00e3b99e6f9934");
System.out.println(contextPath);
}
}

View File

@ -1,10 +1,14 @@
package io.dataease.service.dataset.impl.direct;
import com.google.gson.Gson;
import io.dataease.auth.entity.SysUserEntity;
import io.dataease.auth.service.AuthUserService;
import io.dataease.commons.model.BaseTreeNode;
import io.dataease.commons.utils.AuthUtils;
import io.dataease.commons.utils.BeanUtils;
import io.dataease.commons.utils.LogUtil;
import io.dataease.commons.utils.TreeUtils;
import io.dataease.dto.dataset.DataSetTableDTO;
import io.dataease.dto.dataset.DataSetTableUnionDTO;
import io.dataease.plugins.common.dto.dataset.DataTableInfoDTO;
import io.dataease.dto.dataset.DeSortDTO;
@ -53,6 +57,8 @@ public class DirectFieldService implements DataSetFieldService {
private EngineService engineService;
@Resource
private PermissionsTreeService permissionsTreeService;
@Resource
private AuthUserService authUserService;
@Override
public List<Object> fieldValues(String fieldId, Long userId, Boolean userPermissions, Boolean rowAndColumnMgm) throws Exception {
@ -107,7 +113,13 @@ public class DirectFieldService implements DataSetFieldService {
DatasetTable datasetTable = dataSetTableService.get(field.getTableId());
if (ObjectUtils.isEmpty(datasetTable) || StringUtils.isEmpty(datasetTable.getName())) return null;
SysUserEntity userEntity = userId != null ? authUserService.getUserById(userId) : AuthUtils.getUser();
if (userEntity != null && !userEntity.getIsAdmin()) {
DataSetTableDTO withPermission = dataSetTableService.getWithPermission(datasetTable.getId(), userEntity.getUserId());
if (ObjectUtils.isEmpty(withPermission.getPrivileges()) || !withPermission.getPrivileges().contains("use")) {
DataEaseException.throwException(Translator.get("i18n_dataset_no_permission") + String.format(":table name [%s]", withPermission.getName()));
}
}
DatasetTableField datasetTableField = DatasetTableField.builder().tableId(field.getTableId()).checked(Boolean.TRUE).build();
List<DatasetTableField> fields = dataSetTableFieldsService.list(datasetTableField);

View File

@ -29,30 +29,39 @@
}
return (false)
}
const link = getQueryVariable('link')
const user = getQueryVariable('user')
const terminal = getQueryVariable('terminal')
const attachParams = getQueryVariable('attachParams')
const fromLink = getQueryVariable('fromLink')
const ticket = getQueryVariable('ticket')
const baseUrl = window.location.pathname.replace('link.html', '')
let url = baseUrl + "#/delink?link=" + encodeURIComponent(link)
if (terminal) {
url += '&terminal=' + terminal
const shot = getQueryVariable('shot')
if (shot) {
const panelId = getQueryVariable('panelId')
const baseUrl = window.location.pathname.replace('link.html', '')
const shoturl = baseUrl + "#/previewScreenShot/" + panelId + "/true"
window.location.href = shoturl
} else {
const link = getQueryVariable('link')
const user = getQueryVariable('user')
const terminal = getQueryVariable('terminal')
const attachParams = getQueryVariable('attachParams')
const fromLink = getQueryVariable('fromLink')
const ticket = getQueryVariable('ticket')
const baseUrl = window.location.pathname.replace('link.html', '')
let url = baseUrl + "#/delink?link=" + encodeURIComponent(link)
if (terminal) {
url += '&terminal=' + terminal
}
if (user) {
url += '&user=' + encodeURIComponent(user)
}
if (attachParams) {
url += '&attachParams=' + encodeURIComponent(attachParams)
}
if (fromLink) {
url += '&fromLink=' + fromLink
}
if (ticket) {
url += '&ticket=' + ticket
}
window.location.href = url
}
if (user) {
url += '&user=' + encodeURIComponent(user)
}
if (attachParams) {
url += '&attachParams=' + encodeURIComponent(attachParams)
}
if (fromLink) {
url += '&fromLink=' + fromLink
}
if (ticket) {
url += '&ticket=' + ticket
}
window.location.href = url
</script>
</html>

View File

@ -16,7 +16,7 @@
@back-to-top="backToTop"
/>
<link-opt-bar
v-if="canvasId==='canvas-main'"
v-if="linkOptBarShow"
ref="link-opt-bar"
:terminal="terminal"
:canvas-style-data="canvasStyleData"
@ -382,6 +382,9 @@ export default {
}
},
computed: {
linkOptBarShow() {
return this.canvasId==='canvas-main' && this.canvasStyleData.showPublicLinkButton
},
screenShotStatues() {
return this.exporting || this.screenShot || this.backScreenShot
},

View File

@ -94,6 +94,7 @@ export function panelDataPrepare(componentData, componentStyle, callback) {
componentStyle.refreshUnit = (componentStyle.refreshUnit || 'minute')
componentStyle.refreshViewEnable = (componentStyle.refreshViewEnable === undefined ? true : componentStyle.refreshViewEnable)
componentStyle.refreshBrowserEnable = (componentStyle.refreshBrowserEnable || false)
componentStyle.showPublicLinkButton = (componentStyle.showPublicLinkButton === undefined ? true : componentStyle.showPublicLinkButton)
componentStyle.refreshBrowserTime = (componentStyle.refreshBrowserTime || 5)
componentStyle.aidedDesign = (componentStyle.aidedDesign || deepCopy(AIDED_DESIGN))
componentStyle.pdfPageLine = (componentStyle.pdfPageLine || deepCopy(PAGE_LINE_DESIGN))

View File

@ -1615,6 +1615,9 @@ export default {
table_freeze: 'Table Freeze',
table_config: 'Table Config',
table_column_width_config: 'Column Width',
table_layout_mode: 'Layout Mode',
table_layout_grid: 'Grid',
table_layout_tree: 'Tree',
table_column_adapt: 'Adapt',
table_column_custom: 'Custom',
table_column_fixed: 'Fixed',
@ -2396,7 +2399,9 @@ export default {
theme_color_light: 'Light',
refresh_frequency: 'Refresh Frequency',
refresh_browser_frequency: 'Refresh Browser',
public_link_button_show: 'Show Public Link Button',
refresh_browser_tips: 'Only public links are effective',
public_link_button_tips: 'Only public links are effective',
card_color_matching: 'Card Color Matching',
table_color_matching: 'Table Color Matching',
background_color: 'Background Color',

View File

@ -1613,6 +1613,9 @@ export default {
column: '列',
table_config: '表格配置',
table_column_width_config: '列寬調整',
table_layout_mode: '展示形式',
table_layout_grid: '平鋪展示',
table_layout_tree: '樹形模式',
table_freeze: '表格凍結',
table_column_adapt: '自適應',
table_column_custom: '自定義',
@ -2389,7 +2392,9 @@ export default {
theme_color_light: '淺色',
refresh_frequency: '刷新頻率',
refresh_browser_frequency: '瀏覽器刷新',
public_link_button_show: '顯示公共鏈接操作按鈕',
refresh_browser_tips: '僅公共鏈接生效',
public_link_button_tips: '僅公共鏈接生效',
card_color_matching: '卡片配色',
table_color_matching: '表格配色',
background_color: '背景顏色',

View File

@ -1611,6 +1611,9 @@ export default {
table_freeze: '表格冻结',
table_config: '表格配置',
table_column_width_config: '列宽调整',
table_layout_mode: '展示形式',
table_layout_grid: '平铺展示',
table_layout_tree: '树形模式',
table_column_adapt: '自适应',
table_column_custom: '自定义',
table_column_fixed: '固定列宽',
@ -2390,7 +2393,9 @@ export default {
theme_color_light: '浅色',
refresh_frequency: '刷新频率',
refresh_browser_frequency: '浏览器刷新',
public_link_button_show: '显示公共链接操作按钮',
refresh_browser_tips: '仅公共链接生效',
public_link_button_tips: '仅公共链接生效',
card_color_matching: '卡片配色',
table_color_matching: '表格配色',
background_color: '背景颜色',

View File

@ -110,6 +110,7 @@ export const DEFAULT_SIZE = {
show: false
},
tableFieldWidth: [],
tableLayoutMode: 'grid',
gaugeMinType: 'fix', // fix or dynamic
gaugeMinField: {
id: '',

View File

@ -659,12 +659,14 @@ export function baseTablePivot(container, chart, action, headerAction, tableData
data: newData,
sortParams: sortParams
}
// options
const s2Options = {
width: containerDom.offsetWidth,
height: containerDom.offsetHeight,
style: getSize(chart),
style: {
hierarchyCollapse: true,
...getSize(chart)
},
totals: totalCfg,
conditions: getConditions(chart),
tooltip: {
@ -676,7 +678,8 @@ export function baseTablePivot(container, chart, action, headerAction, tableData
position: 'absolute',
padding: '4px 2px'
}
}
},
hierarchyType: customAttr.size.tableLayoutMode ?? 'grid'
}
// 开始渲染

View File

@ -178,7 +178,8 @@ export const TYPE_CONFIGS = [
'tableColumnMode',
'tableRowTooltip',
'tableColTooltip',
'tableCellTooltip'
'tableCellTooltip',
'tableLayoutMode'
],
'total-cfg': [
'row',

View File

@ -163,6 +163,22 @@
</el-form-item>
<!--radar-end-->
<!--table-begin-->
<el-form-item
v-if="showProperty('tableLayoutMode')"
:label="$t('chart.table_layout_mode')"
class="form-item"
>
<el-radio-group
v-model="sizeForm.tableLayoutMode"
class="column-radio"
@change="changeBarSizeCase('tableLayoutMode')"
>
<el-radio label="grid"><span>{{ $t('chart.table_layout_grid') }}</span></el-radio>
<el-radio label="tree">
<span>{{ $t('chart.table_layout_tree') }}</span>
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item
v-if="showProperty('tableItemFontSize')"
:label="$t('chart.table_item_fontsize')"
@ -1833,6 +1849,7 @@ export default {
this.sizeForm.tableColumnFreezeTail = this.sizeForm.tableColumnFreezeTail ?? DEFAULT_SIZE.tableColumnFreezeTail
this.sizeForm.tableRowFreezeHead = this.sizeForm.tableRowFreezeHead ?? DEFAULT_SIZE.tableRowFreezeHead
this.sizeForm.summaryLabel = this.sizeForm.summaryLabel ?? DEFAULT_SIZE.summaryLabel
this.sizeForm.tableLayoutMode = this.sizeForm.tableLayoutMode ?? DEFAULT_SIZE.tableLayoutMode
this.sizeForm.showIndex = this.sizeForm.showIndex ? this.sizeForm.showIndex : DEFAULT_SIZE.showIndex
this.sizeForm.showTableHeader = this.sizeForm.showTableHeader !== false

View File

@ -82,6 +82,7 @@ export const CANVAS_STYLE = {
refreshUnit: 'minute', // 仪表板刷新时间带外 默认 分钟
refreshTime: 5, // 仪表板刷新时间 默认5分钟
refreshBrowserEnable: false, // 开启视图刷新(默认关闭)
showPublicLinkButton: true, // 开启公共链接按钮(默认开启)
refreshBrowserTime: 5, // 仪表板刷新时间 默认5分钟(浏览器刷新仅保留分钟)
themeId: 'system_1', // 当前所选主题ID 默认系统主题1
chartInfo: PANEL_CHART_INFO

View File

@ -93,7 +93,7 @@
@change="themeChange"
>{{ $t('panel.refresh_browser_frequency') }}
</el-checkbox>
<span class="custom-item-text bl">
<span class="custom-item-text bl margin-left4">
<span>
<el-tooltip
class="item"
@ -126,11 +126,11 @@
</el-input>
</el-row>
</el-row>
<el-row class="margin-top20 margin-bottom20">
<el-row class="margin-top20">
<el-row class="custom-item-text-row">
<span class="custom-item-text bl">
{{ $t('panel.panel_view_result_show') }}
<span>
<span class="margin-left4">
<el-tooltip
class="item"
effect="dark"
@ -182,6 +182,36 @@
</el-row>
</el-row>
</el-row>
<el-row class="margin-top20 margin-bottom20">
<el-row class="custom-item-text-row">
<span class="custom-item-text el-input-refresh-browser-inner bl">
<el-checkbox
v-model="overallSettingForm.showPublicLinkButton"
class="el-input-refresh-browser"
@change="themeChange"
>{{ $t('panel.public_link_button_show') }}
</el-checkbox>
<span class="custom-item-text bl margin-left4">
<span>
<el-tooltip
class="item"
effect="dark"
placement="bottom"
>
<div slot="content">
{{ $t('panel.public_link_button_tips') }}
</div>
<i
class="el-icon-info"
style="cursor: pointer;"
/>
</el-tooltip>
</span>
</span>
</span>
</el-row>
</el-row>
</el-col>
</div>
</template>
@ -360,6 +390,10 @@ export default {
margin-left: 32px;
}
.margin-left4 {
margin-left: 4px;
}
.bl {
justify-content: flex-start;
display: flex;

View File

@ -12,6 +12,7 @@
<dataease.version>1.18.24</dataease.version>
<poi.version>4.1.1</poi.version>
<xmlbeans.version>3.1.0</xmlbeans.version>
<tomcat.version>9.0.64</tomcat.version>
</properties>
<name>dataease</name>