fix: 插件上传增加版本验证

This commit is contained in:
fit2cloud-chenyw 2022-04-04 21:34:05 +08:00
parent f4d0988251
commit c716dee725
7 changed files with 113 additions and 15 deletions

View File

@ -35,5 +35,7 @@ public class MyPlugin implements Serializable {
private String icon;
private String require = "1.9.0";
private static final long serialVersionUID = 1L;
}

View File

@ -195,4 +195,16 @@ public class CodingUtil {
}
return shortBuffer.toString();
}
public static Integer string2Integer(String str) {
StringBuffer sb = new StringBuffer();
if (StringUtils.isBlank(str)) return null;
for (int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
if (Character.isDigit(c)) {
sb.append(c);
}
}
return sb.length() > 0 ? Integer.parseInt(sb.toString()) : null;
}
}

View File

@ -1,17 +1,22 @@
package io.dataease.service.sys;
import cn.hutool.core.io.FileUtil;
import com.google.gson.Gson;
import io.dataease.base.domain.MyPlugin;
import io.dataease.base.mapper.MyPluginMapper;
import io.dataease.base.mapper.ext.ExtSysPluginMapper;
import io.dataease.base.mapper.ext.query.GridExample;
import io.dataease.commons.constants.AuthConstants;
import io.dataease.commons.exception.DEException;
import io.dataease.commons.utils.CodingUtil;
import io.dataease.commons.utils.DeFileUtils;
import io.dataease.commons.utils.LogUtil;
import io.dataease.commons.utils.ZipUtils;
import io.dataease.controller.sys.base.BaseGridRequest;
import io.dataease.listener.util.CacheUtils;
import io.dataease.plugins.config.LoadjarUtil;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
@ -22,8 +27,10 @@ import javax.annotation.Resource;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Service
@ -43,6 +50,9 @@ public class PluginService {
@Autowired
private LoadjarUtil loadjarUtil;
@Value("${version}")
private String version;
public List<MyPlugin> query(BaseGridRequest request) {
GridExample gridExample = request.convertExample();
@ -66,7 +76,9 @@ public class PluginService {
DeFileUtils.deleteFile(pluginDir + "temp/");
DeFileUtils.deleteFile(folder);
// 需要删除文件
e.printStackTrace();
// e.printStackTrace();
LogUtil.error(e.getMessage(), e);
DEException.throwException(e);
}
//3.解析plugin.json 失败则 直接返回错误 删除文件
File folderFile = new File(folder);
@ -74,15 +86,31 @@ public class PluginService {
if (ArrayUtils.isEmpty(jsonFiles)) {
DeFileUtils.deleteFile(pluginDir + "temp/");
DeFileUtils.deleteFile(folder);
throw new RuntimeException("缺少插件描述文件");
String msg = "缺少插件描述文件【plugin.json】";
LogUtil.error(msg);
DEException.throwException(new RuntimeException(msg));
}
MyPlugin myPlugin = formatJsonFile(jsonFiles[0]);
if (!versionMatch(myPlugin.getRequire())) {
String msg = "当前插件要求系统版本最低为:" + myPlugin.getRequire();
LogUtil.error(msg);
DEException.throwException(new RuntimeException(msg));
}
//4.加载jar包 失败则 直接返回错误 删除文件
File[] jarFiles = folderFile.listFiles(this::isPluginJar);
if (ArrayUtils.isEmpty(jarFiles)) {
DeFileUtils.deleteFile(pluginDir + "temp/");
DeFileUtils.deleteFile(folder);
throw new RuntimeException("缺少插件jar文件");
String msg = "缺少插件jar文件";
LogUtil.error(msg);
DEException.throwException(new RuntimeException(msg));
}
if (pluginExist(myPlugin)) {
String msg = "插件【"+myPlugin.getName()+"】已存在,请先卸载";
LogUtil.error(msg);
DEException.throwException(new RuntimeException(msg));
}
String targetDir = null;
try {
@ -100,7 +128,8 @@ public class PluginService {
if (StringUtils.isNotEmpty(targetDir)) {
DeFileUtils.deleteFile(targetDir);
}
e.printStackTrace();
LogUtil.error(e.getMessage(), e);
DEException.throwException(e);
} finally {
DeFileUtils.deleteFile(pluginDir + "temp/");
DeFileUtils.deleteFile(folder);
@ -122,6 +151,19 @@ public class PluginService {
return dir;
}
/**
* 检测插件是否已存在
* @param myPlugin
* @return
*/
public boolean pluginExist(MyPlugin myPlugin) {
GridExample gridExample = new GridExample();
List<MyPlugin> plugins = extSysPluginMapper.query(gridExample);
return plugins.stream().anyMatch(plugin -> {
return StringUtils.equals(myPlugin.getName(), plugin.getName()) || StringUtils.equals(myPlugin.getModuleName(), plugin.getModuleName());
});
}
/**
* 卸载插件
*
@ -129,6 +171,13 @@ public class PluginService {
* @return
*/
public Boolean uninstall(Long pluginId) {
MyPlugin myPlugin = myPluginMapper.selectByPrimaryKey(pluginId);
if (ObjectUtils.isEmpty(myPlugin)) {
String msg = "当前插件不存在";
LogUtil.error(msg);
DEException.throwException(new RuntimeException(msg));
}
deleteJarFile(myPlugin);
CacheUtils.removeAll(AuthConstants.USER_CACHE_NAME);
CacheUtils.removeAll(AuthConstants.USER_ROLE_CACHE_NAME);
CacheUtils.removeAll(AuthConstants.USER_PERMISSION_CACHE_NAME);
@ -136,6 +185,15 @@ public class PluginService {
return true;
}
private void deleteJarFile(MyPlugin plugin) {
String version = plugin.getVersion();
String moduleName = plugin.getModuleName();
String fileName = moduleName + "-" + version + ".jar";
String path = pluginDir + plugin.getStore() + "/" + fileName;
File jarFile = new File(path);
FileUtil.del(jarFile);
}
/**
* 改变插件状态
*
@ -195,4 +253,16 @@ public class PluginService {
public Map<String, Object> remoteInstall(Map<String, Object> params) {
return null;
}
public boolean versionMatch(String pluginVersion) {
List<Integer> versionLists = Arrays.stream(version.split(".")).map(CodingUtil::string2Integer).collect(Collectors.toList());
List<Integer> requireVersionLists = Arrays.stream(pluginVersion.split(".")).map(CodingUtil::string2Integer).collect(Collectors.toList());
int maxSize = Math.max(versionLists.size(), requireVersionLists.size());
for (int i = 0; i < maxSize; i++) {
Integer currentV = versionLists.size() == i ? 0 : versionLists.get(i);
Integer requireV = requireVersionLists.size() == i ? 0 : requireVersionLists.get(i);
if (requireV > currentV) return false;
}
return false;
}
}

View File

@ -1645,7 +1645,9 @@ export default {
uninstall_cancel: 'Cancel uninstall plugin',
setting_background: 'BackGround',
setting_jump: 'Jump Setting',
select_view: 'Select View'
select_view: 'Select View',
un_install_success: 'Uninstall is successful and restart takes effect',
un_install_error: 'Uninstall failed, please contact the administrator'
},
display: {
logo: 'Head system logo',

View File

@ -1644,9 +1644,11 @@ export default {
creator: '作者',
install_time: '安裝時間',
release_time: '時間',
un_install: '卸載',
un_install: '卸載(重啟服務後生效)',
uninstall_confirm: '確定卸載該插件',
uninstall_cancel: '取消卸載插件'
uninstall_cancel: '取消卸載插件',
un_install_success: '卸載成功,重啟生效',
un_install_error: '卸載失敗,請聯系管理員'
},
display: {
logo: '頭部繫統logo',

View File

@ -1653,9 +1653,11 @@ export default {
creator: '作者',
install_time: '安装时间',
release_time: '时间',
un_install: '卸载',
un_install: '卸载(卸载并重启服务后生效)',
uninstall_confirm: '确定卸载该插件',
uninstall_cancel: '取消卸载插件'
uninstall_cancel: '取消卸载插件',
un_install_success: '卸载成功,重启生效',
un_install_error: '卸载失败,请联系管理员'
},
display: {
logo: '头部系统logo',

View File

@ -8,7 +8,6 @@
@search="search"
>
<template #toolbar>
<!-- <el-button @click="create">{{ $t('plugin.local_install') }}</el-button> -->
<el-upload
:action="baseUrl+'api/plugin/upload'"
@ -46,7 +45,7 @@
<span>{{ scope.row.installTime | timestampFormatDate }}</span>
</template>
</el-table-column>
<!-- <fu-table-operations :buttons="buttons" label="操作" fix /> -->
<fu-table-operations :buttons="buttons" :label="$t('commons.operating')" fix />
</complex-table>
</layout-content>
@ -72,6 +71,10 @@ export default {
// label: this.$t('commons.delete'), icon: 'el-icon-delete', type: 'danger', click: this.del,
// show: checkPermission(['user:del'])
// }
{
label: this.$t('plugin.un_install'), icon: 'el-icon-delete', type: 'danger', click: this.del,
disabled: this.btnDisabled
}
],
searchConfig: {
useQuickSearch: true,
@ -113,6 +116,8 @@ export default {
this.uploading = true
},
uploadFail(response, file, fileList) {
const msg = response && response.message || '安装失败'
this.$error(msg)
this.uploading = false
},
uploadSuccess(response, file, fileList) {
@ -121,20 +126,23 @@ export default {
},
del(row) {
this.$confirm(this.$t('user.delete_confirm'), '', {
this.$confirm(this.$t('plugin.uninstall_confirm'), '', {
confirmButtonText: this.$t('commons.confirm'),
cancelButtonText: this.$t('commons.cancel'),
type: 'warning'
}).then(() => {
uninstall(row.pluginId).then(res => {
this.search()
this.$success('卸载成功')
this.$success(this.$t('plugin.un_install_success'))
}).catch(() => {
this.$error('卸载失败')
this.$error(this.$t('plugin.un_install_error'))
})
}).catch(() => {
this.$info(this.$t('commons.delete_cancel'))
this.$info(this.$t('plugin.uninstall_cancel'))
})
},
btnDisabled(row) {
return row.pluginId < 4
}
}