Skip to content

Commit edbc245

Browse files
author
CodeBuddy Attribution Bot
committed
fix(attribution): queryPermissions 工具查询存储权限返回 resources.empty,未返回当前 aclTag 导致 AI 编造默认值 (issue_mojw1xd2_gaiuiu)
1 parent 6eaebcb commit edbc245

1 file changed

Lines changed: 38 additions & 14 deletions

File tree

mcp/src/tools/permissions.ts

Lines changed: 38 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -342,14 +342,14 @@ export function registerPermissionTools(server: ExtendedMcpServer) {
342342
{
343343
title: "查询权限与用户配置",
344344
description:
345-
"权限域统一只读入口。支持查询资源权限、角色列表/详情、应用用户列表/详情。",
345+
"权限域统一只读入口。支持查询资源权限、角色列表/详情、应用用户列表/详情。查询存储权限时(resourceType=\"storage\"),如果不提供 resourceId/resourceIds,会自动发现当前环境的存储 Bucket 并返回其权限(aclTag),无需先查 Bucket 名称。",
346346
inputSchema: {
347347
action: z.enum(QUERY_PERMISSION_ACTIONS),
348348
resourceType: z
349349
.enum(["noSqlDatabase", "sqlDatabase", "function", "storage"])
350350
.optional(),
351-
resourceId: z.string().optional(),
352-
resourceIds: z.array(z.string()).optional(),
351+
resourceId: z.string().optional().describe("资源标识。当 resourceType=\"storage\" 时可不提供,将自动使用默认 Bucket。"),
352+
resourceIds: z.array(z.string()).optional().describe("资源标识列表。当 resourceType=\"storage\" 时可不提供,将自动发现所有 Bucket。"),
353353
roleId: z.string().optional(),
354354
roleIdentity: z.string().optional(),
355355
roleName: z.string().optional(),
@@ -395,29 +395,42 @@ export function registerPermissionTools(server: ExtendedMcpServer) {
395395

396396
switch (action) {
397397
case "getResourcePermission": {
398-
if (!resourceType || !resourceId) {
399-
throw new Error("action=getResourcePermission 时必须提供 resourceType 和 resourceId");
398+
if (!resourceType) {
399+
throw new Error("action=getResourcePermission 时必须提供 resourceType");
400+
}
401+
// Auto-discover default storage bucket when resourceId is not provided for storage type
402+
let resolvedResourceId = resourceId;
403+
if (resourceType === "storage" && !resolvedResourceId) {
404+
const envInfo = await cloudbase.env.getEnvInfo();
405+
const defaultBucket = (envInfo?.EnvInfo?.Storages ?? [])
406+
.map((item: { Bucket?: string }) => item?.Bucket)
407+
.find((bucket: string | undefined): bucket is string => Boolean(bucket));
408+
if (defaultBucket) {
409+
resolvedResourceId = defaultBucket;
410+
} else {
411+
throw new Error("当前环境没有存储 Bucket,无法查询存储权限");
412+
}
400413
}
401-
if (resourceType === "storage") {
402-
await ensureStorageBucketsExist(cloudbase, [resourceId]);
414+
if (resourceType === "storage" && resolvedResourceId) {
415+
await ensureStorageBucketsExist(cloudbase, [resolvedResourceId]);
403416
}
404417
const result = await cloudbase.permission.describeResourcePermission({
405418
resourceType: mapResourceType(resourceType),
406-
resources: [resourceId],
419+
resources: [resolvedResourceId],
407420
});
408421
logCloudBaseResult(server.logger, result);
409422
const permissions = result.Data.PermissionList ?? [];
410423
const matchedPermission =
411-
permissions.find((item) => item.Resource === resourceId) ?? permissions[0];
424+
permissions.find((item) => item.Resource === resolvedResourceId) ?? permissions[0];
412425
const securityRule =
413426
matchedPermission?.SecurityRule;
414-
const hints = buildPermissionHints(securityRule, resourceId);
427+
const hints = buildPermissionHints(securityRule, resolvedResourceId);
415428
return buildEnvelope(
416429
{
417430
action,
418431
envId,
419432
resourceType,
420-
resourceId,
433+
resourceId: resolvedResourceId,
421434
aclTag: matchedPermission?.Permission,
422435
permissions,
423436
hints,
@@ -430,12 +443,23 @@ export function registerPermissionTools(server: ExtendedMcpServer) {
430443
if (!resourceType) {
431444
throw new Error("action=listResourcePermissions 时必须提供 resourceType");
432445
}
433-
if (resourceType === "storage" && resourceIds?.length) {
434-
await ensureStorageBucketsExist(cloudbase, resourceIds);
446+
// Auto-discover storage bucket names when resourceIds is not provided for storage type
447+
let resolvedResourceIds = resourceIds;
448+
if (resourceType === "storage" && !resolvedResourceIds?.length) {
449+
const envInfo = await cloudbase.env.getEnvInfo();
450+
const bucketNames = (envInfo?.EnvInfo?.Storages ?? [])
451+
.map((item: { Bucket?: string }) => item?.Bucket)
452+
.filter((bucket: string | undefined): bucket is string => Boolean(bucket));
453+
if (bucketNames.length > 0) {
454+
resolvedResourceIds = bucketNames;
455+
}
456+
}
457+
if (resourceType === "storage" && resolvedResourceIds?.length) {
458+
await ensureStorageBucketsExist(cloudbase, resolvedResourceIds);
435459
}
436460
const result = await cloudbase.permission.describeResourcePermission({
437461
resourceType: mapResourceType(resourceType),
438-
resources: resourceIds,
462+
resources: resolvedResourceIds,
439463
});
440464
logCloudBaseResult(server.logger, result);
441465
const permissions = result.Data.PermissionList ?? [];

0 commit comments

Comments
 (0)