import { storage } from '../storage'; import type { AuthenticatedRequest } from '../middleware/auth.middleware'; import { isFormAllowedByScopes } from './api-key'; // Актор изменений для REST-хендлеров, поддерживающих API-ключ: // JWT — текущий пользователь; ключ бота — бот (changedBy=null); ключ без бота — label ключа. export interface RestActor { changedBy: number | null; changedByName: string; botId: number | null; source: 'api' | null; // 'api' при авторизации по ключу (идёт в metadata аудит-записей) } export async function resolveRestActor(req: AuthenticatedRequest, organizationId: number): Promise { if (!req.apiKey) { const name = req.user ? (`${req.user.firstName || ''} ${req.user.middleName || ''} ${req.user.lastName || ''}`.trim() || req.user.email) : 'API'; return { changedBy: req.user?.id ?? null, changedByName: name, botId: null, source: null }; } const bot = req.apiKey.botId ? await storage.getBot(req.apiKey.botId, organizationId).catch(() => null) : null; return { changedBy: bot ? null : req.apiKey.createdBy, changedByName: bot?.name ?? `Ключ «${req.apiKey.label}»`, botId: bot?.id ?? null, source: 'api', }; } // Проверки авторизации по API-ключу для write-endpoint'а (изменение данных формы/задачи). // Возвращает текст ошибки для 403 или null, если доступ разрешён. // Для JWT-запросов всегда null (их проверки — в хендлерах, как раньше). export function checkApiKeyWriteAccess(req: AuthenticatedRequest, formId: number): string | null { if (!req.apiKey) return null; if (req.apiKey.scopes.mode === 'read') { return 'API-ключ в режиме read не может изменять данные'; } if (!isFormAllowedByScopes(req.apiKey.scopes, formId)) { return 'Доступ к этой форме запрещён правами API-ключа'; } return null; }