mirror of https://github.com/halo-dev/halo
refactor: exception prompts during plugin installation (#3993)
#### What type of PR is this? /kind improvement /area core /milestone 2.6.x #### What this PR does / why we need it: 优化插件安装失败的提示信息 插件安装和升级时由于包格式不正确改为如下提示(Localization) <img width="449" alt="image" src="https://github.com/halo-dev/halo/assets/38999863/37da0d42-88fa-40c5-a2b9-b8e2698a5930"> how to test it? 使用下面的插件安装和升级会提示 plugin.yaml 缺失 [failed-plugins.zip](https://github.com/halo-dev/halo/files/11560921/failed-plugins.zip) see #3843 for more details #### Which issue(s) this PR fixes: Fixes #3843 #### Does this PR introduce a user-facing change? ```release-note 优化插件安装失败的提示信息 ```pull/4005/head
parent
710261b035
commit
c8cc9f2710
|
@ -28,6 +28,7 @@ import run.halo.app.extension.MetadataUtil;
|
|||
import run.halo.app.extension.ReactiveExtensionClient;
|
||||
import run.halo.app.infra.SystemVersionSupplier;
|
||||
import run.halo.app.infra.exception.PluginAlreadyExistsException;
|
||||
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;
|
||||
|
@ -70,49 +71,47 @@ public class PluginServiceImpl implements PluginService {
|
|||
|
||||
@Override
|
||||
public Mono<Plugin> install(Path path) {
|
||||
return Mono.defer(() -> {
|
||||
final var pluginFinder = new YamlPluginFinder();
|
||||
final var pluginInPath = pluginFinder.find(path);
|
||||
// validate the plugin version
|
||||
satisfiesRequiresVersion(pluginInPath);
|
||||
return findPluginManifest(path)
|
||||
.flatMap(pluginInPath -> {
|
||||
// validate the plugin version
|
||||
satisfiesRequiresVersion(pluginInPath);
|
||||
|
||||
return client.fetch(Plugin.class, pluginInPath.getMetadata().getName())
|
||||
.flatMap(oldPlugin -> Mono.<Plugin>error(
|
||||
new PluginAlreadyExistsException(oldPlugin.getMetadata().getName())))
|
||||
.switchIfEmpty(Mono.defer(
|
||||
() -> copyToPluginHome(pluginInPath)
|
||||
.map(pluginFinder::find)
|
||||
.doOnNext(p -> {
|
||||
// Disable auto enable after installation
|
||||
p.getSpec().setEnabled(false);
|
||||
})
|
||||
.flatMap(client::create)));
|
||||
|
||||
});
|
||||
return client.fetch(Plugin.class, pluginInPath.getMetadata().getName())
|
||||
.flatMap(oldPlugin -> Mono.<Plugin>error(
|
||||
new PluginAlreadyExistsException(oldPlugin.getMetadata().getName())))
|
||||
.switchIfEmpty(Mono.defer(
|
||||
() -> copyToPluginHome(pluginInPath)
|
||||
.flatMap(this::findPluginManifest)
|
||||
.doOnNext(p -> {
|
||||
// Disable auto enable after installation
|
||||
p.getSpec().setEnabled(false);
|
||||
})
|
||||
.flatMap(client::create))
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<Plugin> upgrade(String name, Path path) {
|
||||
return Mono.defer(() -> {
|
||||
// pre-check the plugin in the path
|
||||
final var pluginFinder = new YamlPluginFinder();
|
||||
final var pluginInPath = pluginFinder.find(path);
|
||||
Validate.notNull(pluginInPath.statusNonNull().getLoadLocation());
|
||||
satisfiesRequiresVersion(pluginInPath);
|
||||
if (!Objects.equals(name, pluginInPath.getMetadata().getName())) {
|
||||
return Mono.error(new ServerWebInputException(
|
||||
"The provided plugin " + pluginInPath.getMetadata().getName()
|
||||
+ " didn't match the given plugin " + name));
|
||||
}
|
||||
return findPluginManifest(path)
|
||||
.flatMap(pluginInPath -> {
|
||||
// pre-check the plugin in the path
|
||||
Validate.notNull(pluginInPath.statusNonNull().getLoadLocation());
|
||||
satisfiesRequiresVersion(pluginInPath);
|
||||
if (!Objects.equals(name, pluginInPath.getMetadata().getName())) {
|
||||
return Mono.error(new ServerWebInputException(
|
||||
"The provided plugin " + pluginInPath.getMetadata().getName()
|
||||
+ " didn't match the given plugin " + name));
|
||||
}
|
||||
|
||||
// check if the plugin exists
|
||||
return client.fetch(Plugin.class, name)
|
||||
.switchIfEmpty(Mono.error(() -> new ServerWebInputException(
|
||||
"The given plugin with name " + name + " was not found.")))
|
||||
// copy plugin into plugin home
|
||||
.flatMap(prevPlugin -> copyToPluginHome(pluginInPath))
|
||||
.flatMap(pluginPath -> updateReloadAnno(name, pluginPath));
|
||||
});
|
||||
// check if the plugin exists
|
||||
return client.fetch(Plugin.class, name)
|
||||
.switchIfEmpty(Mono.error(() -> new ServerWebInputException(
|
||||
"The given plugin with name " + name + " was not found.")))
|
||||
// copy plugin into plugin home
|
||||
.flatMap(prevPlugin -> copyToPluginHome(pluginInPath))
|
||||
.flatMap(pluginPath -> updateReloadAnno(name, pluginPath));
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -125,6 +124,17 @@ public class PluginServiceImpl implements PluginService {
|
|||
return updateReloadAnno(name, pluginWrapper.getPluginPath());
|
||||
}
|
||||
|
||||
Mono<Plugin> findPluginManifest(Path path) {
|
||||
return Mono.fromSupplier(
|
||||
() -> {
|
||||
final var pluginFinder = new YamlPluginFinder();
|
||||
return pluginFinder.find(path);
|
||||
})
|
||||
.onErrorMap(e -> new PluginInstallationException("Failed to parse the plugin manifest",
|
||||
"problemDetail.plugin.missingManifest", null)
|
||||
);
|
||||
}
|
||||
|
||||
private Mono<Plugin> updateReloadAnno(String name, Path pluginPath) {
|
||||
return client.get(Plugin.class, name)
|
||||
.flatMap(plugin -> {
|
||||
|
|
|
@ -75,8 +75,9 @@ public class YamlPluginFinder {
|
|||
}
|
||||
|
||||
protected Plugin readPluginDescriptor(Path pluginPath) {
|
||||
Path propertiesPath = getManifestPath(pluginPath, propertiesFileName);
|
||||
Path propertiesPath = null;
|
||||
try {
|
||||
propertiesPath = getManifestPath(pluginPath, propertiesFileName);
|
||||
if (propertiesPath == null) {
|
||||
throw new PluginRuntimeException("Cannot find the plugin manifest path");
|
||||
}
|
||||
|
|
|
@ -45,3 +45,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.missingManifest=Missing plugin manifest file "plugin.yaml" or manifest file does not conform to the specification.
|
||||
|
|
|
@ -14,6 +14,7 @@ problemDetail.user.signUpFailed.disallowed=系统不允许注册新用户。
|
|||
problemDetail.user.duplicateName=用户名 {0} 已存在,请更换用户名后重试。
|
||||
|
||||
problemDetail.plugin.version.unsatisfied.requires=插件要求一个最小的系统版本为 {0}, 但当前版本为 {1}。
|
||||
problemDetail.plugin.missingManifest=缺少 plugin.yaml 配置文件或配置文件不符合规范。
|
||||
|
||||
problemDetail.theme.version.unsatisfied.requires=主题要求一个最小的系统版本为 {0}, 但当前版本为 {1}。
|
||||
problemDetail.theme.install.missingManifest=缺少 theme.yaml 配置文件或配置文件不符合规范。
|
Loading…
Reference in New Issue