import crypto from 'node:crypto'; import { initializeDefaultSpace } from './mindspace.mjs'; export async function createIntegrationUser(pool, label = 'plaza') { const id = crypto.randomUUID(); const suffix = id.slice(0, 8); const username = `${label}_${suffix}`; const now = Date.now(); await pool.query( `INSERT INTO h5_users (id, username, slug, email, display_name, salt, password_hash, role, workspace_root, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, 'user', ?, ?, ?)`, [ id, username, username, `${username}@plaza.test`, `Plaza ${label}`, 'testsalt', 'testhash', `/tmp/${username}`, now, now, ], ); await initializeDefaultSpace(pool, id); return { id, username, slug: username }; } export async function createOnlinePublication(pool, userId, title = 'Plaza Integration Post') { const now = Date.now(); const publicationId = crypto.randomUUID(); const pageId = crypto.randomUUID(); const pageVersionId = crypto.randomUUID(); const contentAssetId = crypto.randomUUID(); const assetVersionId = crypto.randomUUID(); const scanId = crypto.randomUUID(); const [[space]] = await pool.query( `SELECT id FROM h5_user_spaces WHERE user_id = ? LIMIT 1`, [userId], ); const [[category]] = await pool.query( `SELECT id FROM h5_space_categories WHERE user_id = ? AND category_code = 'draft' LIMIT 1`, [userId], ); if (!space?.id || !category?.id) { throw new Error('integration fixture: user space/category missing'); } await pool.query( `INSERT INTO h5_assets (id, user_id, space_id, category_id, asset_type, mime_type, original_filename, display_name, current_version_id, size_bytes, checksum, visibility, status, source_type, created_at, updated_at) VALUES (?, ?, ?, ?, 'content', 'text/markdown', 'page.md', ?, ?, 128, ?, 'private', 'ready', 'upload', ?, ?)`, [ contentAssetId, userId, space.id, category.id, title, assetVersionId, 'abc123', now, now, ], ); await pool.query( `INSERT INTO h5_asset_versions (id, asset_id, version_no, storage_key, size_bytes, checksum, mime_type, created_by, created_at) VALUES (?, ?, 1, ?, 128, ?, 'text/markdown', ?, ?)`, [assetVersionId, contentAssetId, `users/${userId}/assets/${contentAssetId}/v1`, 'abc123', userId, now], ); await pool.query( `INSERT INTO h5_page_records (id, user_id, space_id, category_id, title, summary, page_type, template_id, status, visibility, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, 'article', 'editorial', 'published', 'public', ?, ?)`, [pageId, userId, space.id, category.id, title, 'integration summary', now, now], ); await pool.query( `INSERT INTO h5_security_scans (id, user_id, target_type, target_id, scanner_version, status, risk_level, findings_count, started_at, completed_at) VALUES (?, ?, 'page_version', ?, 'test', 'passed', 'none', 0, ?, ?)`, [scanId, userId, pageVersionId, now, now], ); await pool.query( `INSERT INTO h5_page_versions (id, page_id, version_no, content_asset_id, created_by, immutable, created_at) VALUES (?, ?, 1, ?, ?, 1, ?)`, [pageVersionId, pageId, contentAssetId, userId, now], ); await pool.query( `UPDATE h5_page_records SET current_version_id = ?, updated_at = ? WHERE id = ?`, [pageVersionId, now, pageId], ); await pool.query( `INSERT INTO h5_publish_records (id, user_id, page_id, page_version_id, url_slug, public_url, access_mode, published_at, status, view_count, security_scan_id, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, 'public', ?, 'online', 0, ?, ?, ?)`, [ publicationId, userId, pageId, pageVersionId, `plaza-${publicationId.slice(0, 8)}`, `/u/test/pages/plaza-${publicationId.slice(0, 8)}`, now, scanId, now, now, ], ); return { publicationId, pageId }; } export async function getPlazaCategoryId(pool, slug = 'work-report') { const [[row]] = await pool.query( `SELECT id FROM plaza_categories WHERE slug = ? AND is_active = 1 LIMIT 1`, [slug], ); return row?.id ?? null; } export async function setOpsRole(pool, userId, role = 'reviewer') { await pool.query(`UPDATE h5_users SET ops_role = ?, updated_at = ? WHERE id = ?`, [ role, Date.now(), userId, ]); }