const express = require('express'); const router = express.Router(); const { getDb } = require('../models/db'); const { authMiddleware, adminMiddleware } = require('../middleware/auth'); // Get all groups for current user router.get('/', authMiddleware, (req, res) => { const db = getDb(); const userId = req.user.id; // Public groups (all users are members) const publicGroups = db.prepare(` SELECT g.*, (SELECT COUNT(*) FROM messages m WHERE m.group_id = g.id AND m.is_deleted = 0) as message_count, (SELECT m.content FROM messages m WHERE m.group_id = g.id AND m.is_deleted = 0 ORDER BY m.created_at DESC LIMIT 1) as last_message, (SELECT m.created_at FROM messages m WHERE m.group_id = g.id AND m.is_deleted = 0 ORDER BY m.created_at DESC LIMIT 1) as last_message_at FROM groups g WHERE g.type = 'public' ORDER BY g.is_default DESC, g.name ASC `).all(); // Private groups (user is a member) const privateGroups = db.prepare(` SELECT g.*, u.name as owner_name, (SELECT COUNT(*) FROM messages m WHERE m.group_id = g.id AND m.is_deleted = 0) as message_count, (SELECT m.content FROM messages m WHERE m.group_id = g.id AND m.is_deleted = 0 ORDER BY m.created_at DESC LIMIT 1) as last_message, (SELECT m.created_at FROM messages m WHERE m.group_id = g.id AND m.is_deleted = 0 ORDER BY m.created_at DESC LIMIT 1) as last_message_at FROM groups g JOIN group_members gm ON g.id = gm.group_id AND gm.user_id = ? LEFT JOIN users u ON g.owner_id = u.id WHERE g.type = 'private' ORDER BY last_message_at DESC NULLS LAST `).all(userId); res.json({ publicGroups, privateGroups }); }); // Create group router.post('/', authMiddleware, (req, res) => { const { name, type, memberIds, isReadonly } = req.body; const db = getDb(); if (type === 'public' && req.user.role !== 'admin') { return res.status(403).json({ error: 'Only admins can create public groups' }); } const result = db.prepare(` INSERT INTO groups (name, type, owner_id, is_readonly) VALUES (?, ?, ?, ?) `).run(name, type || 'private', req.user.id, isReadonly ? 1 : 0); const groupId = result.lastInsertRowid; if (type === 'public') { // Add all users to public group const allUsers = db.prepare("SELECT id FROM users WHERE status = 'active'").all(); const insert = db.prepare('INSERT OR IGNORE INTO group_members (group_id, user_id) VALUES (?, ?)'); for (const u of allUsers) insert.run(groupId, u.id); } else { // Add creator db.prepare('INSERT OR IGNORE INTO group_members (group_id, user_id) VALUES (?, ?)').run(groupId, req.user.id); // Add other members if (memberIds && memberIds.length > 0) { const insert = db.prepare('INSERT OR IGNORE INTO group_members (group_id, user_id) VALUES (?, ?)'); for (const uid of memberIds) insert.run(groupId, uid); } } const group = db.prepare('SELECT * FROM groups WHERE id = ?').get(groupId); res.json({ group }); }); // Rename group router.patch('/:id/rename', authMiddleware, (req, res) => { const { name } = req.body; const db = getDb(); const group = db.prepare('SELECT * FROM groups WHERE id = ?').get(req.params.id); if (!group) return res.status(404).json({ error: 'Group not found' }); if (group.is_default) return res.status(403).json({ error: 'Cannot rename default group' }); if (group.type === 'public' && req.user.role !== 'admin') return res.status(403).json({ error: 'Only admins can rename public groups' }); if (group.type === 'private' && group.owner_id !== req.user.id && req.user.role !== 'admin') { return res.status(403).json({ error: 'Only owner can rename private group' }); } db.prepare("UPDATE groups SET name = ?, updated_at = datetime('now') WHERE id = ?").run(name, group.id); res.json({ success: true }); }); // Get group members router.get('/:id/members', authMiddleware, (req, res) => { const db = getDb(); const members = db.prepare(` SELECT u.id, u.name, u.display_name, u.avatar, u.role, u.status FROM group_members gm JOIN users u ON gm.user_id = u.id WHERE gm.group_id = ? ORDER BY u.name ASC `).all(req.params.id); res.json({ members }); }); // Add member to private group router.post('/:id/members', authMiddleware, (req, res) => { const { userId } = req.body; const db = getDb(); const group = db.prepare('SELECT * FROM groups WHERE id = ?').get(req.params.id); if (!group) return res.status(404).json({ error: 'Group not found' }); if (group.type !== 'private') return res.status(400).json({ error: 'Cannot manually add members to public groups' }); if (group.owner_id !== req.user.id && req.user.role !== 'admin') { return res.status(403).json({ error: 'Only owner can add members' }); } db.prepare('INSERT OR IGNORE INTO group_members (group_id, user_id) VALUES (?, ?)').run(group.id, userId); res.json({ success: true }); }); // Remove a member from a private group (owner or admin only) router.delete('/:id/members/:userId', authMiddleware, (req, res) => { const db = getDb(); const group = db.prepare('SELECT * FROM groups WHERE id = ?').get(req.params.id); if (!group) return res.status(404).json({ error: 'Group not found' }); if (group.type !== 'private') return res.status(400).json({ error: 'Cannot remove members from public groups' }); if (group.owner_id !== req.user.id && req.user.role !== 'admin') { return res.status(403).json({ error: 'Only owner or admin can remove members' }); } const targetId = parseInt(req.params.userId); if (targetId === group.owner_id) { return res.status(400).json({ error: 'Cannot remove the group owner' }); } db.prepare('DELETE FROM group_members WHERE group_id = ? AND user_id = ?').run(group.id, targetId); res.json({ success: true }); }); // Leave private group router.delete('/:id/leave', authMiddleware, (req, res) => { const db = getDb(); const group = db.prepare('SELECT * FROM groups WHERE id = ?').get(req.params.id); if (!group) return res.status(404).json({ error: 'Group not found' }); if (group.type === 'public') return res.status(400).json({ error: 'Cannot leave public groups' }); db.prepare('DELETE FROM group_members WHERE group_id = ? AND user_id = ?').run(group.id, req.user.id); res.json({ success: true }); }); // Admin take ownership of private group router.post('/:id/take-ownership', authMiddleware, adminMiddleware, (req, res) => { const db = getDb(); db.prepare("UPDATE groups SET owner_id = ?, updated_at = datetime('now') WHERE id = ?").run(req.user.id, req.params.id); db.prepare('INSERT OR IGNORE INTO group_members (group_id, user_id) VALUES (?, ?)').run(req.params.id, req.user.id); res.json({ success: true }); }); // Delete group (admin or private group owner) router.delete('/:id', authMiddleware, (req, res) => { const db = getDb(); const group = db.prepare('SELECT * FROM groups WHERE id = ?').get(req.params.id); if (!group) return res.status(404).json({ error: 'Group not found' }); if (group.is_default) return res.status(403).json({ error: 'Cannot delete default group' }); if (group.type === 'public' && req.user.role !== 'admin') return res.status(403).json({ error: 'Only admins can delete public groups' }); if (group.type === 'private' && group.owner_id !== req.user.id && req.user.role !== 'admin') { return res.status(403).json({ error: 'Only owner or admin can delete private groups' }); } db.prepare('DELETE FROM groups WHERE id = ?').run(group.id); res.json({ success: true }); }); module.exports = router;