Files
iistwin/server/routes/form-offline.routes.ts
Ильяс Султанов 26419f395f security(errors): 5xx без утечки err.message клиенту
Шаг 0.7 плана production-готовности:
- глобальный error handler: нейтральный текст + код инцидента, детали в лог
- route-уровень: зачистка err.message/String(err) в 5xx по 12 файлам,
  оригинальные ошибки логируются с контекстом
2026-09-07 20:42:39 +03:00

69 lines
2.8 KiB
TypeScript

import { Router } from "express";
import { z } from "zod";
import { storage } from "../storage";
import { authenticateToken, requireFormAdminOrPermission, type AuthenticatedRequest } from "../middleware/auth.middleware";
import { tenantIsolation } from "../middleware/tenant.middleware";
const router = Router();
const offlineCacheSchema = z.object({
enabled: z.boolean(),
maxTasks: z.number().int().min(1).max(5000).optional(),
strategy: z.enum(['recent', 'assigned', 'all']).optional(),
includeFields: z.array(z.string()).optional(),
});
/**
* GET /api/forms/:id/offline-cache
* Получить настройки офлайн-кэша формы.
*/
router.get('/api/forms/:id/offline-cache', authenticateToken, tenantIsolation, async (req: AuthenticatedRequest, res) => {
try {
const id = parseInt(req.params.id);
if (isNaN(id)) return res.status(400).json({ error: 'Неверный ID формы' });
const config = await storage.getOfflineCacheConfig(id, req.organizationId!);
res.json({ success: true, offlineCache: config });
} catch (err: any) {
console.error('[FORM-OFFLINE] get error:', err);
res.status(500).json({ error: 'Ошибка получения настроек офлайн-кэша' });
}
});
/**
* PUT /api/forms/:id/offline-cache
* Установить настройки офлайн-кэша формы.
*/
router.put('/api/forms/:id/offline-cache', authenticateToken, tenantIsolation, requireFormAdminOrPermission('forms.manage'), async (req: AuthenticatedRequest, res) => {
try {
const id = parseInt(req.params.id);
if (isNaN(id)) return res.status(400).json({ error: 'Неверный ID формы' });
const config = offlineCacheSchema.parse(req.body);
const form = await storage.updateFormOfflineCache(id, req.organizationId!, config);
res.json({ success: true, offlineCache: form.offlineCache });
} catch (err: any) {
console.error('[FORM-OFFLINE] put error:', err);
res.status(500).json({ error: 'Ошибка обновления настроек офлайн-кэша' });
}
});
/**
* DELETE /api/forms/:id/offline-cache
* Отключить офлайн-кэш формы.
*/
router.delete('/api/forms/:id/offline-cache', authenticateToken, tenantIsolation, requireFormAdminOrPermission('forms.manage'), async (req: AuthenticatedRequest, res) => {
try {
const id = parseInt(req.params.id);
if (isNaN(id)) return res.status(400).json({ error: 'Неверный ID формы' });
await storage.updateFormOfflineCache(id, req.organizationId!, null);
res.json({ success: true });
} catch (err: any) {
console.error('[FORM-OFFLINE] delete error:', err);
res.status(500).json({ error: 'Ошибка отключения офлайн-кэша' });
}
});
export default router;