mirror of
https://gitcode.com/JianFeeeee/HomeAgent.git
synced 2026-09-23 18:38:11 +00:00
feat: 设备鉴权迁移至客户端 + 插件卸载保护
安全修复(客户端鉴权): - remotedevice 服务端移除授权状态存储(authorized map/SetAuthorized/handleDeviceAuth) - DeviceMeta.Authorized 改为设备 hello 自报,服务端仅透传展示 - device_ctl_* 工具移除服务端授权检查,无条件转发,设备端自行决定是否执行 - 共享设备桥库 Bridge 新增本地 authorized 状态,未授权收到 cmd 直接拒绝 - waiter: --device-authorized / device_authorized 配置控制本地授权 - GUI: 授权存 gui-prefs 本地文件;设备页仅本机可切换开关 - webui /device/auth 旧路径返回 410 Gone - 根因:agent 可经 config_set 篡改服务端授权配置自行授权设备 插件管理强化: - 内置插件禁止卸载(IsBuiltinPlugin + 409),外部插件卸载即时生效 - 卸载不存在插件返回 404;移除误导性 reload_required 提示 - webui 插件路由:名称白名单校验防路径穿越、保留字路径保护
This commit is contained in:
@ -4667,10 +4667,21 @@ background:
|
||||
return;
|
||||
}
|
||||
try {
|
||||
var r = await api("/plugins", {
|
||||
var raw = await api("/plugins", {
|
||||
method: "POST",
|
||||
body: JSON.stringify({ url: url }),
|
||||
raw: true,
|
||||
});
|
||||
var ct = raw.headers.get("content-type") || "";
|
||||
var r = ct.includes("json") ? await raw.json() : await raw.text();
|
||||
if (!raw.ok || (r && r.error)) {
|
||||
toast(
|
||||
__("安装失败: ", "Install failed: ") +
|
||||
((r && (r.error || r.details)) || "HTTP " + raw.status),
|
||||
true,
|
||||
);
|
||||
return;
|
||||
}
|
||||
toast(
|
||||
__("安装结果: ", "Install result: ") +
|
||||
(r.status || JSON.stringify(r)),
|
||||
@ -4683,7 +4694,7 @@ background:
|
||||
),
|
||||
false,
|
||||
);
|
||||
loadInstalledPlugins();
|
||||
await loadInstalledPlugins();
|
||||
renderPlugins();
|
||||
} catch (e) {
|
||||
toast(__("安装失败: ", "Install failed: ") + e.message, true);
|
||||
@ -4732,7 +4743,10 @@ background:
|
||||
renderPlugins();
|
||||
}
|
||||
|
||||
var removingPlugins = {};
|
||||
|
||||
async function removePlugin(name) {
|
||||
if (removingPlugins[name]) return; // 防重复点击
|
||||
if (
|
||||
!confirm(
|
||||
__("确定卸载插件", "Are you sure to unload plugin") +
|
||||
@ -4742,23 +4756,39 @@ background:
|
||||
)
|
||||
)
|
||||
return;
|
||||
removingPlugins[name] = true;
|
||||
try {
|
||||
var r = await api("/plugins/" + encodeURIComponent(name), {
|
||||
method: "DELETE",
|
||||
});
|
||||
toast(__("已卸载: ", "Unloaded: ") + (r.status || r.name));
|
||||
if (r.action === "reload_required")
|
||||
toast(
|
||||
__(
|
||||
"已卸载,请点击「重载插件」生效",
|
||||
'Unloaded, click "Reload Plugins" to apply',
|
||||
),
|
||||
false,
|
||||
);
|
||||
loadInstalledPlugins();
|
||||
var raw = await api(
|
||||
"/plugins/" + encodeURIComponent(name),
|
||||
{ method: "DELETE", raw: true },
|
||||
);
|
||||
var ct = raw.headers.get("content-type") || "";
|
||||
var body = ct.includes("json")
|
||||
? await raw.json()
|
||||
: await raw.text();
|
||||
if (!raw.ok) {
|
||||
var em =
|
||||
(body && (body.error || body.details)) ||
|
||||
("HTTP " + raw.status);
|
||||
toast(__("卸载失败: ", "Unload failed: ") + em, true);
|
||||
// 内置插件或路径错误时刷新一次列表保持状态一致
|
||||
loadInstalledPlugins();
|
||||
renderPlugins();
|
||||
return;
|
||||
}
|
||||
toast(__("已卸载: ", "Unloaded: ") + (body.name || body.status || name));
|
||||
await loadInstalledPlugins();
|
||||
// 同步内核插件/禁用列表,确保列表与工具立即消失
|
||||
try {
|
||||
state.kernel = await api("/kernel");
|
||||
var s = await api("/settings");
|
||||
state.disabledPlugins = s.disabled_plugins || [];
|
||||
} catch (e2) {}
|
||||
renderPlugins();
|
||||
} catch (e) {
|
||||
toast(__("卸载失败: ", "Unload failed: ") + e.message, true);
|
||||
} finally {
|
||||
delete removingPlugins[name];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user