mirror of https://github.com/halo-dev/halo
fix: plugin disappeared after plugin with same name reinstalled (#3198)
#### What type of PR is this? /kind bug /area core /milestone 2.2.x #### What this PR does / why we need it: 修复重复安装插件时 JAR 文件被删除的问题 需要注意的场景: prod 模式下,假如安装一个 sitemap 插件,版本为 1.0.0 ,而此时 plugins 目录已经存在同名文件 sitemap-1.0.0.jar 文件但 sitemap 的 plugin.yaml 没有被持久化过,则能正常安装,旧的 JAR 文件被覆盖。 see #3159 for more details #### Which issue(s) this PR fixes: Fixes #3159 #### Special notes for your reviewer: /cc @halo-dev/sig-halo #### Does this PR introduce a user-facing change? ```release-note 修复重复安装插件时 JAR 文件被删除的问题 ```pull/3209/head
parent
764b664fd8
commit
0fd023b8f6
|
@ -22,6 +22,7 @@ import java.io.IOException;
|
|||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
|
@ -61,6 +62,7 @@ import run.halo.app.extension.ConfigMap;
|
|||
import run.halo.app.extension.ReactiveExtensionClient;
|
||||
import run.halo.app.extension.router.IListRequest.QueryListRequest;
|
||||
import run.halo.app.infra.SystemVersionSupplier;
|
||||
import run.halo.app.infra.exception.PluginInstallationException;
|
||||
import run.halo.app.infra.exception.UnsatisfiedAttributeValueException;
|
||||
import run.halo.app.infra.utils.FileUtils;
|
||||
import run.halo.app.infra.utils.VersionUtils;
|
||||
|
@ -455,25 +457,25 @@ public class PluginEndpoint implements CustomEndpoint {
|
|||
// Disable auto enable during installation
|
||||
plugin.getSpec().setEnabled(false);
|
||||
return client.fetch(Plugin.class, plugin.getMetadata().getName())
|
||||
.switchIfEmpty(Mono.defer(() -> client.create(plugin)))
|
||||
.doOnNext(oldPlugin -> {
|
||||
String pluginName = oldPlugin.getMetadata().getName();
|
||||
throw new PluginInstallationException(
|
||||
"Plugin [" + pluginName + "] already installed",
|
||||
"problemDetail.plugin.install.alreadyInstalled",
|
||||
new Object[] {pluginName});
|
||||
})
|
||||
.then(client.create(plugin))
|
||||
.publishOn(Schedulers.boundedElastic())
|
||||
.map(created -> {
|
||||
.doOnNext(created -> {
|
||||
String fileName = created.generateFileName();
|
||||
var pluginRoot = Paths.get(pluginProperties.getPluginsRoot());
|
||||
createDirectoriesIfNotExists(pluginRoot);
|
||||
Path pluginFilePath = pluginRoot.resolve(fileName);
|
||||
if (Files.exists(pluginFilePath)) {
|
||||
throw new IllegalArgumentException(
|
||||
"Plugin already installed : " + pluginFilePath);
|
||||
}
|
||||
FileUtils.copy(tempJarFilePath, pluginFilePath);
|
||||
return created;
|
||||
// move the plugin jar file to the plugin root
|
||||
// replace the old plugin jar file if exists
|
||||
FileUtils.copy(tempJarFilePath, pluginFilePath,
|
||||
StandardCopyOption.REPLACE_EXISTING);
|
||||
})
|
||||
.onErrorResume(
|
||||
error -> client.fetch(Plugin.class, plugin.getMetadata().getName())
|
||||
.flatMap(client::delete)
|
||||
.then(Mono.error(error))
|
||||
)
|
||||
.doFinally(signalType -> {
|
||||
try {
|
||||
Files.deleteIfExists(tempJarFilePath);
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
package run.halo.app.infra.exception;
|
||||
|
||||
import jakarta.validation.constraints.Null;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.web.server.ServerWebInputException;
|
||||
|
||||
/**
|
||||
* {@link ServerWebInputException} subclass that indicates plugin installation failure.
|
||||
*
|
||||
* @author guqing
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public class PluginInstallationException extends ServerWebInputException {
|
||||
|
||||
public PluginInstallationException(String reason, @Nullable String messageDetailCode,
|
||||
@Null Object[] messageDetailArguments) {
|
||||
super(reason, null, null, messageDetailCode, messageDetailArguments);
|
||||
}
|
||||
}
|
|
@ -14,6 +14,7 @@ problemDetail.title.run.halo.app.infra.exception.AccessDeniedException=Access De
|
|||
problemDetail.title.reactor.core.Exceptions.RetryExhaustedException=Retry Exhausted
|
||||
problemDetail.title.run.halo.app.infra.exception.ThemeInstallationException=Theme Install Error
|
||||
problemDetail.title.run.halo.app.infra.exception.ThemeUpgradeException=Theme Upgrade Error
|
||||
problemDetail.title.run.halo.app.infra.exception.PluginInstallationException=Plugin Install Error
|
||||
|
||||
# Detail definitions
|
||||
problemDetail.org.springframework.web.server.UnsupportedMediaTypeStatusException=Content type {0} is not supported. Supported media types: {1}.
|
||||
|
@ -38,3 +39,4 @@ problemDetail.theme.version.unsatisfied.requires=The theme requires a minimum sy
|
|||
problemDetail.directoryTraversal=Directory traversal detected. Base path is {0}, but real path is {1}.
|
||||
|
||||
problemDetail.plugin.version.unsatisfied.requires=Plugin requires a minimum system version of {0}, but the current version is {1}.
|
||||
problemDetail.plugin.install.alreadyInstalled=Plugin {0} already installed.
|
|
@ -1,9 +1,11 @@
|
|||
problemDetail.title.org.springframework.web.server.ServerWebInputException=请求参数有误
|
||||
problemDetail.title.run.halo.app.infra.exception.UnsatisfiedAttributeValueException=请求参数属性值不满足要求
|
||||
problemDetail.title.run.halo.app.infra.exception.PluginInstallationException=插件安装失败
|
||||
problemDetail.title.run.halo.app.infra.exception.AttachmentAlreadyExistsException=附件已存在
|
||||
|
||||
problemDetail.run.halo.app.infra.exception.AttachmentAlreadyExistsException=文件 {0} 已存在,建议更名后重试。
|
||||
|
||||
problemDetail.plugin.version.unsatisfied.requires=插件要求一个最小的系统版本为 {0}, 但当前版本为 {1}。
|
||||
problemDetail.plugin.install.alreadyInstalled=插件 {0} 已经被安装。
|
||||
|
||||
problemDetail.theme.version.unsatisfied.requires=主题要求一个最小的系统版本为 {0}, 但当前版本为 {1}。
|
Loading…
Reference in New Issue