/** * Кто видит тест: автор цепочки и пользователи с назначением (target user = clinic user id). */ import { isTestAuthor } from '../config/devAuthor.js'; import { query } from '../db/db.js'; /** * @param {string} userId * @param {string} testId * @returns {Promise<{ ok: boolean, isAuthor: boolean, notFound: boolean }>} */ export async function userHasTestAccess(userId, testId) { const { rows } = await query( `SELECT t.created_by FROM tests t WHERE t.id = $1`, [testId] ); if (!rows.length) { return { ok: false, isAuthor: false, notFound: true }; } if (isTestAuthor(rows[0].created_by, userId)) { return { ok: true, isAuthor: true, notFound: false }; } const { rows: ar } = await query( `SELECT 1 FROM test_assignments ta INNER JOIN test_versions tv_a ON tv_a.id = ta.test_version_id INNER JOIN test_assignment_targets tat ON tat.assignment_id = ta.id WHERE tv_a.test_id = $1 AND tat.target_type = 'user' AND tat.target_id = $2 LIMIT 1`, [testId, userId] ); return { ok: ar.length > 0, isAuthor: false, notFound: false }; } /** * Список тестов в каталоге: только `is_active` цепочка + (автор OR назначен). */ export async function queryTestsVisibleToUser(userId) { return query( `SELECT DISTINCT t.id, t.title, t.description, t.is_active AS chain_active, t.created_at, t.updated_at, tv.id AS active_version_id, tv.version, t.created_by, u.full_name AS author_full_name FROM tests t INNER JOIN test_versions tv ON tv.test_id = t.id AND tv.is_active = true INNER JOIN users u ON u.id = t.created_by WHERE t.is_active = true AND ( t.created_by = $1 OR EXISTS ( SELECT 1 FROM test_assignments ta INNER JOIN test_versions tv2 ON tv2.id = ta.test_version_id INNER JOIN test_assignment_targets tat ON tat.assignment_id = ta.id WHERE tv2.test_id = t.id AND tat.target_type = 'user' AND tat.target_id = $1 ) ) ORDER BY t.updated_at DESC NULLS LAST, t.created_at DESC`, [userId] ); }