Skip to content

Commit a5769b6

Browse files
committed
Expose plugin pages at /plugin/:id/page/:path
Add a public route to serve plugin extension pages without auth and update related pieces accordingly. Backend: register GET /plugin/:pluginId/page/:pagePath to locate the plugin router, validate page and HTML file existence, and send the file (returns appropriate 4xx/5xx errors). Frontend: switch iframe and new-window URLs to the new unauthenticated route (remove webui_token usage). Builtin plugin: clarify page registration comment and add a log line for the extension page URL. Minor formatting whitespace tweaks in plugin manager type annotations.
1 parent d9297c1 commit a5769b6

5 files changed

Lines changed: 44 additions & 9 deletions

File tree

packages/napcat-onebot/network/plugin-manger.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ export class OB11PluginMangerAdapter extends IOB11NetworkAdapter<PluginConfig> i
216216
this.pluginRouters.set(entry.id, routerRegistry);
217217

218218
// 创建获取其他插件导出的方法
219-
const getPluginExports = <T = any>(pluginId: string): T | undefined => {
219+
const getPluginExports = <T = any> (pluginId: string): T | undefined => {
220220
const targetEntry = this.plugins.get(pluginId);
221221
if (!targetEntry || !targetEntry.loaded || targetEntry.runtime.status !== 'loaded') {
222222
return undefined;

packages/napcat-onebot/network/plugin/manager.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ export class OB11PluginManager extends IOB11NetworkAdapter<PluginConfig> impleme
195195
}
196196

197197
// 创建获取其他插件导出的方法
198-
const getPluginExports = <T = any>(pluginId: string): T | undefined => {
198+
const getPluginExports = <T = any> (pluginId: string): T | undefined => {
199199
const targetEntry = this.plugins.get(pluginId);
200200
if (!targetEntry || !targetEntry.loaded || targetEntry.runtime.status !== 'loaded') {
201201
return undefined;

packages/napcat-plugin-builtin/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ const plugin_init: PluginModule['plugin_init'] = async (ctx) => {
160160
});
161161
});
162162

163-
// 注册扩展页面
163+
// 注册扩展页面(无需鉴权,可通过 /plugin/{pluginId}/page/dashboard 访问)
164164
ctx.router.page({
165165
path: 'dashboard',
166166
title: '插件仪表盘',
@@ -171,6 +171,7 @@ const plugin_init: PluginModule['plugin_init'] = async (ctx) => {
171171

172172
logger.info('WebUI 路由已注册:');
173173
logger.info(' - API 路由: /api/Plugin/ext/' + ctx.pluginName + '/');
174+
logger.info(' - 扩展页面: /plugin/' + ctx.pluginName + '/page/dashboard');
174175
logger.info(' - 静态资源: /plugin/' + ctx.pluginName + '/files/static/');
175176
logger.info(' - 内存资源: /plugin/' + ctx.pluginName + '/mem/dynamic/');
176177
};

packages/napcat-webui-backend/index.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,42 @@ export async function InitWebUi (logger: ILogWrapper, pathWrapper: NapCatPathWra
332332
return res.status(404).json({ code: -1, message: 'Memory file not found' });
333333
});
334334

335+
// 插件页面路由(不需要鉴权)
336+
// 路径格式: /plugin/:pluginId/page/:pagePath
337+
app.get('/plugin/:pluginId/page/:pagePath', (req, res) => {
338+
const { pluginId, pagePath } = req.params;
339+
if (!pluginId) return res.status(400).json({ code: -1, message: 'Plugin ID is required' });
340+
341+
const ob11 = WebUiDataRuntime.getOneBotContext() as NapCatOneBot11Adapter | null;
342+
if (!ob11) return res.status(503).json({ code: -1, message: 'OneBot context not available' });
343+
344+
const pluginManager = ob11.networkManager.findSomeAdapter('plugin_manager') as OB11PluginMangerAdapter | undefined;
345+
if (!pluginManager) return res.status(503).json({ code: -1, message: 'Plugin manager not available' });
346+
347+
const routerRegistry = pluginManager.getPluginRouter(pluginId);
348+
if (!routerRegistry || !routerRegistry.hasPages()) {
349+
return res.status(404).json({ code: -1, message: `Plugin '${pluginId}' has no registered pages` });
350+
}
351+
352+
const pages = routerRegistry.getPages();
353+
const page = pages.find(p => p.path === '/' + pagePath || p.path === pagePath);
354+
if (!page) {
355+
return res.status(404).json({ code: -1, message: `Page '${pagePath}' not found in plugin '${pluginId}'` });
356+
}
357+
358+
const pluginPath = routerRegistry.getPluginPath();
359+
if (!pluginPath) {
360+
return res.status(500).json({ code: -1, message: 'Plugin path not available' });
361+
}
362+
363+
const htmlFilePath = join(pluginPath, page.htmlFile);
364+
if (!existsSync(htmlFilePath)) {
365+
return res.status(404).json({ code: -1, message: `HTML file not found: ${page.htmlFile}` });
366+
}
367+
368+
return res.sendFile(htmlFilePath);
369+
});
370+
335371
// 插件文件系统静态资源路由(不需要鉴权)
336372
// 路径格式: /plugin/:pluginId/files/*
337373
app.use('/plugin/:pluginId/files', (req, res, next) => {

packages/napcat-webui-frontend/src/pages/dashboard/extension.tsx

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -63,13 +63,12 @@ export default function ExtensionPage () {
6363
}, [extensionPages]);
6464

6565
// 获取当前选中页面的 iframe URL
66+
// 新路由格式不需要鉴权: /plugin/:pluginId/page/:pagePath
6667
const currentPageUrl = useMemo(() => {
6768
if (!selectedTab) return '';
6869
const [pluginId, ...pathParts] = selectedTab.split(':');
6970
const path = pathParts.join(':').replace(/^\//, '');
70-
// 获取认证 token
71-
const token = localStorage.getItem('token') || '';
72-
return `/api/Plugin/page/${pluginId}/${path}?webui_token=${token}`;
71+
return `/plugin/${pluginId}/page/${path}`;
7372
}, [selectedTab]);
7473

7574
useEffect(() => {
@@ -86,11 +85,10 @@ export default function ExtensionPage () {
8685
setIframeLoading(false);
8786
};
8887

89-
// 在新窗口打开页面
88+
// 在新窗口打开页面(新路由不需要鉴权)
9089
const openInNewWindow = (pluginId: string, path: string) => {
9190
const cleanPath = path.replace(/^\//, '');
92-
const token = localStorage.getItem('token') || '';
93-
const url = `/api/Plugin/page/${pluginId}/${cleanPath}?webui_token=${token}`;
91+
const url = `/plugin/${pluginId}/page/${cleanPath}`;
9492
window.open(url, '_blank');
9593
};
9694

0 commit comments

Comments
 (0)