const express = require('express'); const router = express.Router(); const db = require('../db'); router.get('/', async (req, res) => { try { const result = await db.query("SELECT * FROM channels WHERE type != 'dm' ORDER BY name ASC"); res.json(result.rows); } catch (err) { console.error(err); res.status(500).json({ error: 'Server error' }); } }); // Create New Channel router.post('/create', async (req, res) => { console.log('Creates Channel Body:', req.body); const { name, type } = req.body; if (!name) return res.status(400).json({ error: 'Channel name required' }); try { const result = await db.query( 'INSERT INTO channels (name, type) VALUES ($1, $2) RETURNING *', [name, type || 'text'] ); const newChannel = result.rows[0]; // DO NOT emit 'new_channel' here. Wait until keys are uploaded. res.json({ id: newChannel.id }); } catch (err) { console.error('Error creating channel:', err); if (err.code === '23505') { res.status(400).json({ error: 'Channel already exists' }); } else { res.status(500).json({ error: 'Server error' }); } } }); // Notify Channel Creation (Called AFTER keys are uploaded) router.post('/:id/notify', async (req, res) => { const { id } = req.params; try { const result = await db.query('SELECT * FROM channels WHERE id = $1', [id]); if (result.rows.length === 0) return res.status(404).json({ error: 'Channel not found' }); const channel = result.rows[0]; if (req.io) req.io.emit('new_channel', channel); // Emit NOW res.json({ success: true }); } catch (err) { console.error(err); res.status(500).json({ error: 'Server error' }); } }); // Upload Channel Keys (for self or others) // Upload Channel Keys (for self or others) - Supports Batch router.post('/keys', async (req, res) => { // Check if body is array const keysToUpload = Array.isArray(req.body) ? req.body : [req.body]; if (keysToUpload.length === 0) return res.json({ success: true }); try { await db.query('BEGIN'); for (const keyData of keysToUpload) { const { channelId, userId, encryptedKeyBundle, keyVersion } = keyData; if (!channelId || !userId || !encryptedKeyBundle) { continue; } await db.query( `INSERT INTO channel_keys (channel_id, user_id, encrypted_key_bundle, key_version) VALUES ($1, $2, $3, $4) ON CONFLICT (channel_id, user_id) DO UPDATE SET encrypted_key_bundle = EXCLUDED.encrypted_key_bundle, key_version = EXCLUDED.key_version`, [channelId, userId, encryptedKeyBundle, keyVersion || 1] ); } await db.query('COMMIT'); res.json({ success: true, count: keysToUpload.length }); } catch (err) { await db.query('ROLLBACK'); console.error('Error uploading channel keys:', err); res.status(500).json({ error: 'Server error' }); } }); // Get User's Channel Keys router.get('/keys/:userId', async (req, res) => { const { userId } = req.params; try { const result = await db.query( 'SELECT channel_id, encrypted_key_bundle, key_version FROM channel_keys WHERE user_id = $1', [userId] ); res.json(result.rows); } catch (err) { console.error('Error fetching channel keys:', err); res.status(500).json({ error: 'Server error' }); } }); // Update Channel Name router.put('/:id', async (req, res) => { const { id } = req.params; const { name } = req.body; if (!name) return res.status(400).json({ error: 'Name required' }); try { const result = await db.query( 'UPDATE channels SET name = $1 WHERE id = $2 RETURNING *', [name, id] ); if (result.rows.length === 0) return res.status(404).json({ error: 'Channel not found' }); const updatedChannel = result.rows[0]; if (req.io) req.io.emit('channel_renamed', updatedChannel); res.json(updatedChannel); } catch (err) { console.error(err); res.status(500).json({ error: 'Server error' }); } }); // Delete Channel router.delete('/:id', async (req, res) => { const { id } = req.params; try { await db.query('BEGIN'); // Manual Cascade (since we didn't set FK CASCADE in schema for these yet) await db.query('DELETE FROM messages WHERE channel_id = $1', [id]); await db.query('DELETE FROM channel_keys WHERE channel_id = $1', [id]); const result = await db.query('DELETE FROM channels WHERE id = $1 RETURNING *', [id]); if (result.rows.length === 0) { await db.query('ROLLBACK'); return res.status(404).json({ error: 'Channel not found' }); } await db.query('COMMIT'); if (req.io) req.io.emit('channel_deleted', id); res.json({ success: true, deletedId: id }); } catch (err) { await db.query('ROLLBACK'); console.error(err); res.status(500).json({ error: 'Server error' }); } }); module.exports = router;