From 470b0de70dcc6f2002cd9506a3eb251f3abde7b3 Mon Sep 17 00:00:00 2001 From: Ryan Wang Date: Tue, 26 Sep 2023 23:34:16 +0800 Subject: [PATCH 1/3] refactor: user detail page structure (#4664) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit #### What type of PR is this? /area console /kind improvement /milestone 2.10.x #### What this PR does / why we need it: 重构 Console 端用户详情页面的结构。 1. 提高代码可读性。 2. 使用问号参数来区分不同的选项卡。 3. 封装头像修改相关的代码为组件。 #### Special notes for your reviewer: 测试用户详情页面的所有功能是否正常。 #### Does this PR introduce a user-facing change? ```release-note 重构 Console 端用户详情页面的代码结构。 ``` --- .../src/modules/system/users/UserDetail.vue | 319 +++++++++------- .../system/users/components/UserAvatar.vue | 186 +++++++++ .../users/layouts/UserProfileLayout.vue | 355 ------------------ console/src/modules/system/users/module.ts | 14 +- .../src/modules/system/users/tabs/Detail.vue | 168 +++++++++ .../users/{ => tabs}/PersonalAccessTokens.vue | 4 +- 6 files changed, 533 insertions(+), 513 deletions(-) create mode 100644 console/src/modules/system/users/components/UserAvatar.vue delete mode 100644 console/src/modules/system/users/layouts/UserProfileLayout.vue create mode 100644 console/src/modules/system/users/tabs/Detail.vue rename console/src/modules/system/users/{ => tabs}/PersonalAccessTokens.vue (93%) diff --git a/console/src/modules/system/users/UserDetail.vue b/console/src/modules/system/users/UserDetail.vue index 73b4b62b461..33915d7df39 100644 --- a/console/src/modules/system/users/UserDetail.vue +++ b/console/src/modules/system/users/UserDetail.vue @@ -1,168 +1,199 @@ diff --git a/console/src/modules/system/users/components/UserAvatar.vue b/console/src/modules/system/users/components/UserAvatar.vue new file mode 100644 index 00000000000..137e737a243 --- /dev/null +++ b/console/src/modules/system/users/components/UserAvatar.vue @@ -0,0 +1,186 @@ + + + diff --git a/console/src/modules/system/users/layouts/UserProfileLayout.vue b/console/src/modules/system/users/layouts/UserProfileLayout.vue deleted file mode 100644 index eaeaf367cb0..00000000000 --- a/console/src/modules/system/users/layouts/UserProfileLayout.vue +++ /dev/null @@ -1,355 +0,0 @@ - - diff --git a/console/src/modules/system/users/module.ts b/console/src/modules/system/users/module.ts index f7f60e94d76..d437af010b4 100644 --- a/console/src/modules/system/users/module.ts +++ b/console/src/modules/system/users/module.ts @@ -1,11 +1,9 @@ import { definePlugin } from "@halo-dev/console-shared"; import BasicLayout from "@/layouts/BasicLayout.vue"; import BlankLayout from "@/layouts/BlankLayout.vue"; -import UserProfileLayout from "./layouts/UserProfileLayout.vue"; import UserStatsWidget from "./widgets/UserStatsWidget.vue"; import UserList from "./UserList.vue"; import UserDetail from "./UserDetail.vue"; -import PersonalAccessTokens from "./PersonalAccessTokens.vue"; import Login from "./Login.vue"; import { IconUserSettings } from "@halo-dev/components"; import { markRaw } from "vue"; @@ -61,25 +59,17 @@ export default definePlugin({ }, { path: ":name", - component: UserProfileLayout, + component: BasicLayout, name: "User", children: [ { - path: "detail", + path: "", name: "UserDetail", component: UserDetail, meta: { title: "core.user.detail.title", }, }, - { - path: "tokens", - name: "PersonalAccessTokens", - component: PersonalAccessTokens, - meta: { - title: "个人令牌", - }, - }, ], }, ], diff --git a/console/src/modules/system/users/tabs/Detail.vue b/console/src/modules/system/users/tabs/Detail.vue new file mode 100644 index 00000000000..73b4b62b461 --- /dev/null +++ b/console/src/modules/system/users/tabs/Detail.vue @@ -0,0 +1,168 @@ + + diff --git a/console/src/modules/system/users/PersonalAccessTokens.vue b/console/src/modules/system/users/tabs/PersonalAccessTokens.vue similarity index 93% rename from console/src/modules/system/users/PersonalAccessTokens.vue rename to console/src/modules/system/users/tabs/PersonalAccessTokens.vue index 55a32754707..9b9f24624af 100644 --- a/console/src/modules/system/users/PersonalAccessTokens.vue +++ b/console/src/modules/system/users/tabs/PersonalAccessTokens.vue @@ -10,9 +10,9 @@ import { ref } from "vue"; import { apiClient } from "@/utils/api-client"; import type { PersonalAccessToken } from "@halo-dev/api-client"; import { useQuery } from "@tanstack/vue-query"; -import PersonalAccessTokenCreationModal from "./components/PersonalAccessTokenCreationModal.vue"; +import PersonalAccessTokenCreationModal from "../components/PersonalAccessTokenCreationModal.vue"; import { nextTick } from "vue"; -import PersonalAccessTokenListItem from "./components/PersonalAccessTokenListItem.vue"; +import PersonalAccessTokenListItem from "../components/PersonalAccessTokenListItem.vue"; const { data: pats, From 1f0cfc18e39dbc22cb97a08f221b0f81f52875b9 Mon Sep 17 00:00:00 2001 From: guqing <38999863+guqing@users.noreply.github.com> Date: Wed, 27 Sep 2023 10:16:16 +0800 Subject: [PATCH 2/3] feat: support running plugins from JAR in development mode (#4589) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit #### What type of PR is this? /kind feature /milestone 2.10.x /area core #### What this PR does / why we need it: 支持在开发模式下通过 JAR 运行插件 *从此版本开始 BasePlugin 的子类建议使用 BasePlugin(PluginContext context) 构造函数,而不要使用之前的 BasePlugin(PluginWrapper wrapper) 构造函数。BasePlugin(PluginWrapper wrapper) 构造函数将计划在后续版本移除* ,当移除构造函数后不再将 PluginWrapper 暴露给插件使用,它只应该在 halo core 使用。 how to test it? 1. 测试开发模式下配置的 `halo.plugin.fixed-plugin-path` 插件是否正确运行 2. 测试开发模式下通过 JAR 包安装插件是否正确运行 3. 测试生产模式下是否能通过项目目录的方式运行插件,期望是生产模式不可以运行开发模式的插件 4. 测试开发模式和生产模式的插件卸载功能是否正确 #### Which issue(s) this PR fixes: Fixes #2908 #### Does this PR introduce a user-facing change? ```release-note 支持在开发模式下通过 JAR 运行插件 ``` --- .../java/run/halo/app/plugin/BasePlugin.java | 36 ++++++ .../run/halo/app/plugin/PluginContext.java | 27 +++++ .../reconciler/PluginReconciler.java | 23 +++- .../halo/app/plugin/BasePluginFactory.java | 8 +- .../halo/app/plugin/HaloPluginManager.java | 11 ++ .../halo/app/plugin/HaloPluginWrapper.java | 34 ++++++ .../plugin/PluginApplicationInitializer.java | 12 ++ .../app/plugin/PluginAutoConfiguration.java | 72 ++++++------ .../app/plugin/SpringExtensionFactory.java | 103 ++++++------------ .../reconciler/PluginReconcilerTest.java | 3 +- 10 files changed, 216 insertions(+), 113 deletions(-) create mode 100644 api/src/main/java/run/halo/app/plugin/PluginContext.java create mode 100644 application/src/main/java/run/halo/app/plugin/HaloPluginWrapper.java diff --git a/api/src/main/java/run/halo/app/plugin/BasePlugin.java b/api/src/main/java/run/halo/app/plugin/BasePlugin.java index f513514fec4..d010998c56c 100644 --- a/api/src/main/java/run/halo/app/plugin/BasePlugin.java +++ b/api/src/main/java/run/halo/app/plugin/BasePlugin.java @@ -3,6 +3,8 @@ import lombok.extern.slf4j.Slf4j; import org.pf4j.Plugin; import org.pf4j.PluginWrapper; +import org.springframework.lang.NonNull; +import org.springframework.util.Assert; /** * This class will be extended by all plugins and serve as the common class between a plugin and @@ -14,12 +16,46 @@ @Slf4j public class BasePlugin extends Plugin { + protected PluginContext context; + @Deprecated public BasePlugin(PluginWrapper wrapper) { super(wrapper); log.info("Initialized plugin {}", wrapper.getPluginId()); } + /** + * Constructor a plugin with the given plugin context. + * TODO Mark {@link PluginContext} as final to prevent modification. + * + * @param pluginContext plugin context must not be null. + */ + public BasePlugin(PluginContext pluginContext) { + this.context = pluginContext; + } + + /** + * use {@link #BasePlugin(PluginContext)} instead of. + * + * @deprecated since 2.10.0 + */ public BasePlugin() { } + + /** + * Compatible with old constructors, if the plugin is not use + * {@link #BasePlugin(PluginContext)} constructor then base plugin factory will use this + * method to set plugin context. + * + * @param context plugin context must not be null. + */ + final void setContext(PluginContext context) { + Assert.notNull(context, "Plugin context must not be null"); + this.context = context; + } + + @NonNull + public PluginContext getContext() { + return context; + } } diff --git a/api/src/main/java/run/halo/app/plugin/PluginContext.java b/api/src/main/java/run/halo/app/plugin/PluginContext.java new file mode 100644 index 00000000000..01bae2f9670 --- /dev/null +++ b/api/src/main/java/run/halo/app/plugin/PluginContext.java @@ -0,0 +1,27 @@ +package run.halo.app.plugin; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import org.pf4j.RuntimeMode; + +/** + *

This class will provide a context for the plugin, which will be used to store some + * information about the plugin.

+ *

An instance of this class is provided to plugins in their constructor.

+ *

It's safe for plugins to keep a reference to the instance for later use.

+ *

This class facilitates communication with application and plugin manager.

+ *

Pf4j recommends that you use a custom PluginContext instead of PluginWrapper.

+ * Use application custom PluginContext instead of PluginWrapper + * + * @author guqing + * @since 2.10.0 + */ +@Getter +@RequiredArgsConstructor +public class PluginContext { + private final String name; + + private final String version; + + private final RuntimeMode runtimeMode; +} diff --git a/application/src/main/java/run/halo/app/core/extension/reconciler/PluginReconciler.java b/application/src/main/java/run/halo/app/core/extension/reconciler/PluginReconciler.java index 92d0750bf7e..5361b08a8fc 100644 --- a/application/src/main/java/run/halo/app/core/extension/reconciler/PluginReconciler.java +++ b/application/src/main/java/run/halo/app/core/extension/reconciler/PluginReconciler.java @@ -60,6 +60,7 @@ import run.halo.app.infra.utils.PathUtils; import run.halo.app.infra.utils.YamlUnstructuredLoader; import run.halo.app.plugin.HaloPluginManager; +import run.halo.app.plugin.HaloPluginWrapper; import run.halo.app.plugin.PluginConst; import run.halo.app.plugin.PluginExtensionLoaderUtils; import run.halo.app.plugin.PluginStartingError; @@ -184,11 +185,12 @@ Optional lookupPluginSetting(String name, String settingName) { Assert.notNull(name, "Plugin name must not be null"); Assert.notNull(settingName, "Setting name must not be null"); PluginWrapper pluginWrapper = getPluginWrapper(name); + var runtimeMode = getRuntimeMode(name); var resourceLoader = new DefaultResourceLoader(pluginWrapper.getPluginClassLoader()); return PluginExtensionLoaderUtils.lookupExtensions(pluginWrapper.getPluginPath(), - pluginWrapper.getRuntimeMode()) + runtimeMode) .stream() .map(resourceLoader::getResource) .filter(Resource::exists) @@ -215,6 +217,7 @@ boolean waitForSettingCreation(Plugin plugin) { return false; } + var runtimeMode = getRuntimeMode(pluginName); Optional settingOption = lookupPluginSetting(pluginName, settingName) .map(setting -> { // This annotation is added to prevent it from being deleted when stopped. @@ -802,11 +805,19 @@ static String initialReverseProxyName(String pluginName) { } private boolean isDevelopmentMode(String name) { - PluginWrapper pluginWrapper = haloPluginManager.getPlugin(name); - RuntimeMode runtimeMode = haloPluginManager.getRuntimeMode(); - if (pluginWrapper != null) { - runtimeMode = pluginWrapper.getRuntimeMode(); + return RuntimeMode.DEVELOPMENT.equals(getRuntimeMode(name)); + } + + private RuntimeMode getRuntimeMode(String name) { + var pluginWrapper = haloPluginManager.getPlugin(name); + if (pluginWrapper == null) { + return haloPluginManager.getRuntimeMode(); + } + if (pluginWrapper instanceof HaloPluginWrapper haloPluginWrapper) { + return haloPluginWrapper.getRuntimeMode(); } - return RuntimeMode.DEVELOPMENT.equals(runtimeMode); + return Files.isDirectory(pluginWrapper.getPluginPath()) + ? RuntimeMode.DEVELOPMENT + : RuntimeMode.DEPLOYMENT; } } diff --git a/application/src/main/java/run/halo/app/plugin/BasePluginFactory.java b/application/src/main/java/run/halo/app/plugin/BasePluginFactory.java index c769ab8e291..211cdee0d7f 100644 --- a/application/src/main/java/run/halo/app/plugin/BasePluginFactory.java +++ b/application/src/main/java/run/halo/app/plugin/BasePluginFactory.java @@ -23,13 +23,17 @@ public Plugin create(PluginWrapper pluginWrapper) { return getPluginContext(pluginWrapper) .map(context -> { try { - return context.getBean(BasePlugin.class); + var basePlugin = context.getBean(BasePlugin.class); + var pluginContext = context.getBean(PluginContext.class); + basePlugin.setContext(pluginContext); + return basePlugin; } catch (NoSuchBeanDefinitionException e) { log.info( "No bean named 'basePlugin' found in the context create default instance"); DefaultListableBeanFactory beanFactory = context.getDefaultListableBeanFactory(); - BasePlugin pluginInstance = new BasePlugin(); + var pluginContext = beanFactory.getBean(PluginContext.class); + BasePlugin pluginInstance = new BasePlugin(pluginContext); beanFactory.registerSingleton(Plugin.class.getName(), pluginInstance); return pluginInstance; } diff --git a/application/src/main/java/run/halo/app/plugin/HaloPluginManager.java b/application/src/main/java/run/halo/app/plugin/HaloPluginManager.java index 7abcb1d5f4d..41a61a86e74 100644 --- a/application/src/main/java/run/halo/app/plugin/HaloPluginManager.java +++ b/application/src/main/java/run/halo/app/plugin/HaloPluginManager.java @@ -108,6 +108,17 @@ protected PluginDescriptorFinder createPluginDescriptorFinder() { return new YamlPluginDescriptorFinder(); } + @Override + protected PluginWrapper createPluginWrapper(PluginDescriptor pluginDescriptor, Path pluginPath, + ClassLoader pluginClassLoader) { + // create the plugin wrapper + log.debug("Creating wrapper for plugin '{}'", pluginPath); + HaloPluginWrapper pluginWrapper = + new HaloPluginWrapper(this, pluginDescriptor, pluginPath, pluginClassLoader); + pluginWrapper.setPluginFactory(getPluginFactory()); + return pluginWrapper; + } + @Override protected void firePluginStateEvent(PluginStateEvent event) { rootApplicationContext.publishEvent( diff --git a/application/src/main/java/run/halo/app/plugin/HaloPluginWrapper.java b/application/src/main/java/run/halo/app/plugin/HaloPluginWrapper.java new file mode 100644 index 00000000000..f784400ab4b --- /dev/null +++ b/application/src/main/java/run/halo/app/plugin/HaloPluginWrapper.java @@ -0,0 +1,34 @@ +package run.halo.app.plugin; + +import java.nio.file.Files; +import java.nio.file.Path; +import org.pf4j.PluginDescriptor; +import org.pf4j.PluginManager; +import org.pf4j.PluginWrapper; +import org.pf4j.RuntimeMode; + +/** + * A wrapper over plugin instance for Halo. + * + * @author guqing + * @since 2.10.0 + */ +public class HaloPluginWrapper extends PluginWrapper { + + private final RuntimeMode runtimeMode; + + /** + * Creates a new plugin wrapper to manage the specified plugin. + */ + public HaloPluginWrapper(PluginManager pluginManager, PluginDescriptor descriptor, + Path pluginPath, ClassLoader pluginClassLoader) { + super(pluginManager, descriptor, pluginPath, pluginClassLoader); + this.runtimeMode = Files.isDirectory(pluginPath) + ? RuntimeMode.DEVELOPMENT : RuntimeMode.DEPLOYMENT; + } + + @Override + public RuntimeMode getRuntimeMode() { + return runtimeMode; + } +} diff --git a/application/src/main/java/run/halo/app/plugin/PluginApplicationInitializer.java b/application/src/main/java/run/halo/app/plugin/PluginApplicationInitializer.java index d437b61981d..45c9d367f63 100644 --- a/application/src/main/java/run/halo/app/plugin/PluginApplicationInitializer.java +++ b/application/src/main/java/run/halo/app/plugin/PluginApplicationInitializer.java @@ -9,6 +9,7 @@ import java.util.Set; import java.util.stream.Stream; import lombok.extern.slf4j.Slf4j; +import org.pf4j.PluginRuntimeException; import org.pf4j.PluginWrapper; import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.boot.env.PropertySourceLoader; @@ -88,6 +89,8 @@ private PluginApplicationContext createPluginApplicationContext(String pluginId) AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory); stopWatch.stop(); + beanFactory.registerSingleton("pluginContext", createPluginContext(plugin)); + // TODO deprecated beanFactory.registerSingleton("pluginWrapper", haloPluginManager.getPlugin(pluginId)); populateSettingFetcher(pluginId, beanFactory); @@ -131,6 +134,15 @@ private void initApplicationContext(String pluginId) { stopWatch.getTotalTimeMillis(), stopWatch.prettyPrint()); } + PluginContext createPluginContext(PluginWrapper pluginWrapper) { + if (pluginWrapper instanceof HaloPluginWrapper haloPluginWrapper) { + return new PluginContext(haloPluginWrapper.getPluginId(), + pluginWrapper.getDescriptor().getVersion(), + haloPluginWrapper.getRuntimeMode()); + } + throw new PluginRuntimeException("PluginWrapper must be instance of HaloPluginWrapper"); + } + private void populateSettingFetcher(String pluginName, DefaultListableBeanFactory listableBeanFactory) { ReactiveExtensionClient extensionClient = diff --git a/application/src/main/java/run/halo/app/plugin/PluginAutoConfiguration.java b/application/src/main/java/run/halo/app/plugin/PluginAutoConfiguration.java index 40d4df246f7..bd740314381 100644 --- a/application/src/main/java/run/halo/app/plugin/PluginAutoConfiguration.java +++ b/application/src/main/java/run/halo/app/plugin/PluginAutoConfiguration.java @@ -5,6 +5,7 @@ import java.io.File; import java.io.IOException; import java.lang.reflect.Constructor; +import java.nio.file.Files; import java.nio.file.Path; import java.time.Instant; import lombok.extern.slf4j.Slf4j; @@ -109,33 +110,7 @@ protected PluginLoader createPluginLoader() { } } else { return new CompoundPluginLoader() - .add(new DevelopmentPluginLoader(this) { - - @Override - protected PluginClassLoader createPluginClassLoader(Path pluginPath, - PluginDescriptor pluginDescriptor) { - return new PluginClassLoader(pluginManager, pluginDescriptor, - getClass().getClassLoader(), ClassLoadingStrategy.APD); - } - - @Override - public ClassLoader loadPlugin(Path pluginPath, - PluginDescriptor pluginDescriptor) { - if (pluginProperties.getClassesDirectories() != null) { - for (String classesDirectory : - pluginProperties.getClassesDirectories()) { - pluginClasspath.addClassesDirectories(classesDirectory); - } - } - if (pluginProperties.getLibDirectories() != null) { - for (String libDirectory : - pluginProperties.getLibDirectories()) { - pluginClasspath.addJarsDirectories(libDirectory); - } - } - return super.loadPlugin(pluginPath, pluginDescriptor); - } - }, this::isDevelopment) + .add(createDevelopmentPluginLoader(this), this::isDevelopment) .add(new JarPluginLoader(this) { @Override public ClassLoader loadPlugin(Path pluginPath, @@ -145,9 +120,8 @@ public ClassLoader loadPlugin(Path pluginPath, getClass().getClassLoader(), ClassLoadingStrategy.APD); pluginClassLoader.addFile(pluginPath.toFile()); return pluginClassLoader; - } - }, this::isNotDevelopment); + }); } } @@ -167,9 +141,8 @@ protected PluginRepository createPluginRepository() { .setFixedPaths(pluginProperties.getFixedPluginPath()); return new CompoundPluginRepository() .add(developmentPluginRepository, this::isDevelopment) - .add(new JarPluginRepository(getPluginsRoots()), this::isNotDevelopment) - .add(new DefaultPluginRepository(getPluginsRoots()), - this::isNotDevelopment); + .add(new JarPluginRepository(getPluginsRoots())) + .add(new DefaultPluginRepository(getPluginsRoots())); } }; @@ -181,6 +154,41 @@ protected PluginRepository createPluginRepository() { return pluginManager; } + DevelopmentPluginLoader createDevelopmentPluginLoader(PluginManager pluginManager) { + return new DevelopmentPluginLoader(pluginManager) { + @Override + protected PluginClassLoader createPluginClassLoader(Path pluginPath, + PluginDescriptor pluginDescriptor) { + return new PluginClassLoader(pluginManager, pluginDescriptor, + getClass().getClassLoader(), ClassLoadingStrategy.APD); + } + + @Override + public ClassLoader loadPlugin(Path pluginPath, + PluginDescriptor pluginDescriptor) { + if (pluginProperties.getClassesDirectories() != null) { + for (String classesDirectory : + pluginProperties.getClassesDirectories()) { + pluginClasspath.addClassesDirectories(classesDirectory); + } + } + if (pluginProperties.getLibDirectories() != null) { + for (String libDirectory : + pluginProperties.getLibDirectories()) { + pluginClasspath.addJarsDirectories(libDirectory); + } + } + return super.loadPlugin(pluginPath, pluginDescriptor); + } + + @Override + public boolean isApplicable(Path pluginPath) { + return Files.exists(pluginPath) + && Files.isDirectory(pluginPath); + } + }; + } + String getSystemVersion() { return systemVersionSupplier.get().getNormalVersion(); } diff --git a/application/src/main/java/run/halo/app/plugin/SpringExtensionFactory.java b/application/src/main/java/run/halo/app/plugin/SpringExtensionFactory.java index 4bf0c5b22f3..6477f48115c 100644 --- a/application/src/main/java/run/halo/app/plugin/SpringExtensionFactory.java +++ b/application/src/main/java/run/halo/app/plugin/SpringExtensionFactory.java @@ -6,11 +6,12 @@ import java.util.Objects; import java.util.Optional; import java.util.stream.Stream; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.pf4j.Extension; import org.pf4j.ExtensionFactory; -import org.pf4j.Plugin; import org.pf4j.PluginManager; +import org.pf4j.PluginRuntimeException; import org.pf4j.PluginWrapper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.config.AutowireCapableBeanFactory; @@ -52,46 +53,18 @@ * @since 2.0.0 */ @Slf4j +@RequiredArgsConstructor public class SpringExtensionFactory implements ExtensionFactory { - public static final boolean AUTOWIRE_BY_DEFAULT = true; - /** * The plugin manager is used for retrieving a plugin from a given extension class and as a * fallback supplier of an application context. */ protected final PluginManager pluginManager; - /** - * Indicates if springs autowiring possibilities should be used. - */ - protected final boolean autowire; - - public SpringExtensionFactory(PluginManager pluginManager) { - this(pluginManager, AUTOWIRE_BY_DEFAULT); - } - - public SpringExtensionFactory(final PluginManager pluginManager, final boolean autowire) { - this.pluginManager = pluginManager; - this.autowire = autowire; - if (!autowire) { - log.warn( - "Autowiring is disabled although the only reason for existence of this special " - + "factory is" - + - " supporting spring and its application context."); - } - } - @Override @Nullable public T create(Class extensionClass) { - if (!this.autowire) { - log.warn("Create instance of '" + nameOf(extensionClass) - + "' without using springs possibilities as" - + " autowiring is disabled."); - return createWithoutSpring(extensionClass); - } Optional contextOptional = getPluginApplicationContextBy(extensionClass); if (contextOptional.isPresent()) { @@ -154,52 +127,38 @@ private Object[] nullParameters(final Constructor constructor) { protected Optional getPluginApplicationContextBy( final Class extensionClass) { - final Plugin plugin = Optional.ofNullable(this.pluginManager.whichPlugin(extensionClass)) + return Optional.ofNullable(this.pluginManager.whichPlugin(extensionClass)) .map(PluginWrapper::getPlugin) - .orElse(null); - - final PluginApplicationContext applicationContext; - - if (plugin instanceof BasePlugin) { - log.debug( - " Extension class ' " + nameOf(extensionClass) + "' belongs to halo-plugin '" - + nameOf(plugin) - + "' and will be autowired by using its application context."); - applicationContext = ExtensionContextRegistry.getInstance() - .getByPluginId(plugin.getWrapper().getPluginId()); - return Optional.of(applicationContext); - } else if (this.pluginManager instanceof HaloPluginManager && plugin != null) { - log.debug(" Extension class ' " + nameOf(extensionClass) - + "' belongs to a non halo-plugin (or main application)" - + " '" + nameOf(plugin) - + ", but the used Halo plugin-manager is a spring-plugin-manager. Therefore" - + " the extension class will be autowired by using the managers application " - + "contexts"); - String pluginId = plugin.getWrapper().getPluginId(); - applicationContext = ((HaloPluginManager) this.pluginManager) - .getPluginApplicationContext(pluginId); - } else { - log.warn(" No application contexts can be used for instantiating extension class '" - + nameOf(extensionClass) + "'." - + " This extension neither belongs to a halo-plugin (id: '" + nameOf(plugin) - + "') nor is the used" - + " plugin manager a spring-plugin-manager (used manager: '" - + nameOf(this.pluginManager.getClass()) + "')." - + " At perspective of PF4J this seems highly uncommon in combination with a factory" - + " which only reason for existence" - + " is using spring (and its application context) and should at least be reviewed. " - + "In fact no autowiring can be" - + " applied although autowire flag was set to 'true'. Instantiating will fallback " - + "to standard Java reflection."); - applicationContext = null; - } - - return Optional.ofNullable(applicationContext); + .map(plugin -> { + if (plugin instanceof BasePlugin basePlugin) { + return basePlugin; + } + throw new PluginRuntimeException( + "The plugin must be an instance of BasePlugin"); + }) + .map(plugin -> { + var pluginName = plugin.getContext().getName(); + if (this.pluginManager instanceof HaloPluginManager haloPluginManager) { + log.debug(" Extension class ' " + nameOf(extensionClass) + + "' belongs to a non halo-plugin (or main application)" + + " '" + nameOf(plugin) + + ", but the used Halo plugin-manager is a spring-plugin-manager. Therefore" + + " the extension class will be autowired by using the managers " + + "application " + + "contexts"); + return haloPluginManager.getPluginApplicationContext(pluginName); + } + log.debug( + " Extension class ' " + nameOf(extensionClass) + "' belongs to halo-plugin '" + + nameOf(plugin) + + "' and will be autowired by using its application context."); + return ExtensionContextRegistry.getInstance().getByPluginId(pluginName); + }); } - private String nameOf(final Plugin plugin) { + private String nameOf(final BasePlugin plugin) { return Objects.nonNull(plugin) - ? plugin.getWrapper().getPluginId() + ? plugin.getContext().getName() : "system"; } diff --git a/application/src/test/java/run/halo/app/core/extension/reconciler/PluginReconcilerTest.java b/application/src/test/java/run/halo/app/core/extension/reconciler/PluginReconcilerTest.java index 811e2c92713..a2e46134e51 100644 --- a/application/src/test/java/run/halo/app/core/extension/reconciler/PluginReconcilerTest.java +++ b/application/src/test/java/run/halo/app/core/extension/reconciler/PluginReconcilerTest.java @@ -50,6 +50,7 @@ import run.halo.app.infra.utils.FileUtils; import run.halo.app.infra.utils.JsonUtils; import run.halo.app.plugin.HaloPluginManager; +import run.halo.app.plugin.HaloPluginWrapper; import run.halo.app.plugin.PluginConst; import run.halo.app.plugin.PluginStartingError; @@ -69,7 +70,7 @@ class PluginReconcilerTest { ExtensionClient extensionClient; @Mock - PluginWrapper pluginWrapper; + HaloPluginWrapper pluginWrapper; @Mock ApplicationEventPublisher eventPublisher; From 9b310ca65e4fd75168761ab59f6a6e3beb0fb9db Mon Sep 17 00:00:00 2001 From: Ryan Wang Date: Wed, 27 Sep 2023 10:22:16 +0800 Subject: [PATCH 3/3] feat: add configration route for auth provider item (#4635) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit #### What type of PR is this? /area console /kind improvement /milestone 2.10.x #### What this PR does / why we need it: 为认证方式添加更直观的配置页面入口 image #### Which issue(s) this PR fixes: Fixes #4634 #### Does this PR introduce a user-facing change? ```release-note 为 Console 端认证方式管理添加更直观的配置页面入口 ``` --- .../components/AuthProviderListItem.vue | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/console/src/modules/system/auth-providers/components/AuthProviderListItem.vue b/console/src/modules/system/auth-providers/components/AuthProviderListItem.vue index 371d5172fb6..9b0cbf2217e 100644 --- a/console/src/modules/system/auth-providers/components/AuthProviderListItem.vue +++ b/console/src/modules/system/auth-providers/components/AuthProviderListItem.vue @@ -3,6 +3,7 @@ import { apiClient } from "@/utils/api-client"; import type { ListedAuthProvider } from "@halo-dev/api-client"; import { Dialog, + IconSettings, Toast, VAvatar, VEntity, @@ -93,6 +94,19 @@ const handleChangeStatus = async () => { + + +