Skip to content

Commit 495ce2c

Browse files
committed
fix(feishu): enforce perm tool account gates
1 parent 865e4db commit 495ce2c

2 files changed

Lines changed: 47 additions & 6 deletions

File tree

extensions/feishu/src/perm.ts

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,15 @@
22
import type * as Lark from "@larksuiteoapi/node-sdk";
33
import type { OpenClawPluginApi } from "../runtime-api.js";
44
import { listEnabledFeishuAccounts } from "./accounts.js";
5+
import { createFeishuClient } from "./client.js";
56
import { FeishuPermSchema, type FeishuPermParams } from "./perm-schema.js";
6-
import { createFeishuToolClient, resolveAnyEnabledFeishuToolsConfig } from "./tool-account.js";
7+
import { resolveAnyEnabledFeishuToolsConfig, resolveFeishuToolAccount } from "./tool-account.js";
78
import {
89
jsonToolResult,
910
toolExecutionErrorResult,
1011
unknownToolActionResult,
1112
} from "./tool-result.js";
13+
import { resolveToolsConfig } from "./tools-config.js";
1214

1315
type ListTokenType =
1416
| "doc"
@@ -130,6 +132,17 @@ export function registerFeishuPermTools(api: OpenClawPluginApi) {
130132

131133
type FeishuPermExecuteParams = FeishuPermParams & { accountId?: string };
132134

135+
const createPermClient = (
136+
params: FeishuPermExecuteParams | undefined,
137+
defaultAccountId?: string,
138+
) => {
139+
const account = resolveFeishuToolAccount({ api, executeParams: params, defaultAccountId });
140+
if (!resolveToolsConfig(account.config.tools).perm) {
141+
throw new Error(`Feishu Perm tools are disabled for account "${account.accountId}"`);
142+
}
143+
return createFeishuClient(account);
144+
};
145+
133146
api.registerTool(
134147
(ctx) => {
135148
const defaultAccountId = ctx.agentAccountId;
@@ -141,11 +154,7 @@ export function registerFeishuPermTools(api: OpenClawPluginApi) {
141154
async execute(_toolCallId, params) {
142155
const p = params as FeishuPermExecuteParams;
143156
try {
144-
const client = createFeishuToolClient({
145-
api,
146-
executeParams: p,
147-
defaultAccountId,
148-
});
157+
const client = createPermClient(p, defaultAccountId);
149158
switch (p.action) {
150159
case "list":
151160
return jsonToolResult(await listMembers(client, p.token, p.type));

extensions/feishu/src/tool-account-routing.test.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,38 @@ describe("feishu tool account routing", () => {
205205
expect(lastClientAppId()).toBe("app-b");
206206
});
207207

208+
test("perm tool rejects a disabled contextual account when another account enables it", async () => {
209+
const { api, resolveTool } = createToolFactoryHarness(
210+
createConfig({
211+
toolsA: { perm: false },
212+
toolsB: { perm: true },
213+
}),
214+
);
215+
registerFeishuPermTools(api);
216+
217+
const tool = resolveTool("feishu_perm", { agentAccountId: "a" });
218+
const result = await tool.execute("call", { action: "unknown_action" });
219+
220+
expect(createFeishuClientMock).not.toHaveBeenCalled();
221+
expect(result.details.error).toBe('Feishu Perm tools are disabled for account "a"');
222+
});
223+
224+
test("perm tool rejects an explicit disabled account override", async () => {
225+
const { api, resolveTool } = createToolFactoryHarness(
226+
createConfig({
227+
toolsA: { perm: false },
228+
toolsB: { perm: true },
229+
}),
230+
);
231+
registerFeishuPermTools(api);
232+
233+
const tool = resolveTool("feishu_perm", { agentAccountId: "b" });
234+
const result = await tool.execute("call", { action: "unknown_action", accountId: "a" });
235+
236+
expect(createFeishuClientMock).not.toHaveBeenCalled();
237+
expect(result.details.error).toBe('Feishu Perm tools are disabled for account "a"');
238+
});
239+
208240
test("bitable tool registers when only second account enables it and routes to agentAccountId", async () => {
209241
const { api, resolveTool } = createToolFactoryHarness(
210242
createConfig({

0 commit comments

Comments
 (0)