Права доступа API-ключей: скоупы read/write/full и выборочный доступ к формам и справочникам
- organization_api_keys.scopes (jsonb, NULL = полный доступ для legacy-ключей) - MCP: фильтрация инструментов по режиму и проверка formIds в handler'ах - PATCH /api/mcp-keys/:id, валидация скоупов в server/utils/api-key.ts - UI Settings: диалог создания/редактирования ключа с режимом и мультивыбором форм/справочников
This commit is contained in:
@@ -2557,6 +2557,14 @@ export type WebPushSubscription = typeof webPushSubscriptions.$inferSelect;
|
||||
// Organization API Keys (for MCP server access)
|
||||
// =====================
|
||||
|
||||
// Скоупы прав доступа API-ключа.
|
||||
// NULL в БД = полный доступ (legacy-ключи, созданные до введения скоупов).
|
||||
export type ApiKeyScopes = {
|
||||
mode: 'read' | 'write' | 'full'; // read = только чтение; write = чтение + создание; full = всё
|
||||
formIds: number[] | null; // null = все формы
|
||||
tableIds: number[] | null; // null = все справочники
|
||||
};
|
||||
|
||||
export const organizationApiKeys = pgTable("organization_api_keys", {
|
||||
id: serial("id").primaryKey(),
|
||||
organizationId: integer("organization_id").notNull().references(() => organizations.id, { onDelete: "cascade" }),
|
||||
@@ -2568,6 +2576,7 @@ export const organizationApiKeys = pgTable("organization_api_keys", {
|
||||
lastUsedAt: timestamp("last_used_at"),
|
||||
isActive: boolean("is_active").notNull().default(true),
|
||||
isLegacy: boolean("is_legacy").notNull().default(false),
|
||||
scopes: jsonb("scopes").$type<ApiKeyScopes>(),
|
||||
}, (table) => ({
|
||||
orgIndex: index("api_keys_org_idx").on(table.organizationId),
|
||||
hashIndex: index("api_keys_hash_idx").on(table.keyHash),
|
||||
|
||||
Reference in New Issue
Block a user