const express = require('express'); const router = express.Router(); const db = require('../db'); // Middleware to check for permissions (simplified for now) // In a real app, you'd check if req.user has the permission // Middleware to check for permissions const checkPermission = (requiredPerm) => { return async (req, res, next) => { const userId = req.headers['x-user-id']; if (!userId) { return res.status(401).json({ error: 'Unauthorized: No User ID' }); } try { // Fetch all roles for user and aggregate permissions const result = await db.query(` SELECT r.permissions FROM user_roles ur JOIN roles r ON ur.role_id = r.id WHERE ur.user_id = $1 `, [userId]); let hasPermission = false; // Check if ANY of the user's roles has the permission for (const row of result.rows) { const perms = row.permissions || {}; // If Manage Roles is true, or if checking for something else and they have it if (perms[requiredPerm] === true) { hasPermission = true; break; } // Implicit Admin/Owner check: if they have 'manage_roles' and we are checking something lower? // For "Owner" role, we seeded it with specific true values. // But let's check for 'administrator' equivalent if we had it. // For now, implicit check: if we need 'manage_roles', look for it. } if (!hasPermission) { return res.status(403).json({ error: `Forbidden: Missing ${requiredPerm}` }); } next(); } catch (err) { console.error('Permission check failed:', err); return res.status(500).json({ error: 'Internal Server Error' }); } }; }; // GET /api/roles/permissions - Get current user's permissions router.get('/permissions', async (req, res) => { const userId = req.headers['x-user-id']; if (!userId) return res.json({}); // No perms if no ID try { const result = await db.query(` SELECT r.permissions FROM user_roles ur JOIN roles r ON ur.role_id = r.id WHERE ur.user_id = $1 `, [userId]); const finalPerms = { manage_channels: false, manage_roles: false, create_invite: false, embed_links: false, attach_files: false }; for (const row of result.rows) { const p = row.permissions || {}; if (p.manage_channels) finalPerms.manage_channels = true; if (p.manage_roles) finalPerms.manage_roles = true; if (p.create_invite) finalPerms.create_invite = true; if (p.embed_links) finalPerms.embed_links = true; if (p.attach_files) finalPerms.attach_files = true; } res.json(finalPerms); } catch (err) { console.error(err); res.status(500).json({ error: 'Server error' }); } }); // GET /api/roles - List all roles router.get('/', async (req, res) => { try { const result = await db.query('SELECT * FROM roles ORDER BY position DESC, id ASC'); res.json(result.rows); } catch (err) { console.error(err); res.status(500).json({ error: 'Server error' }); } }); // POST /api/roles - Create new role router.post('/', checkPermission('manage_roles'), async (req, res) => { const { name, color, permissions, position, is_hoist } = req.body; try { const result = await db.query( 'INSERT INTO roles (name, color, permissions, position, is_hoist) VALUES ($1, $2, $3, $4, $5) RETURNING *', [name || 'new role', color || '#99aab5', permissions || {}, position || 0, is_hoist || false] ); res.json(result.rows[0]); } catch (err) { console.error(err); res.status(500).json({ error: 'Server error' }); } }); // PUT /api/roles/:id - Update role router.put('/:id', checkPermission('manage_roles'), async (req, res) => { const { id } = req.params; const { name, color, permissions, position, is_hoist } = req.body; // Dynamic update query const fields = []; const values = []; let idx = 1; if (name !== undefined) { fields.push(`name = $${idx++}`); values.push(name); } if (color !== undefined) { fields.push(`color = $${idx++}`); values.push(color); } if (permissions !== undefined) { fields.push(`permissions = $${idx++}`); values.push(permissions); } if (position !== undefined) { fields.push(`position = $${idx++}`); values.push(position); } if (is_hoist !== undefined) { fields.push(`is_hoist = $${idx++}`); values.push(is_hoist); } if (fields.length === 0) return res.json({ success: true }); // Nothing to update values.push(id); const query = `UPDATE roles SET ${fields.join(', ')} WHERE id = $${idx} RETURNING *`; try { const result = await db.query(query, values); if (result.rows.length === 0) return res.status(404).json({ error: 'Role not found' }); res.json(result.rows[0]); } catch (err) { console.error(err); res.status(500).json({ error: 'Server error' }); } }); // DELETE /api/roles/:id - Delete role router.delete('/:id', checkPermission('manage_roles'), async (req, res) => { const { id } = req.params; try { // user_roles cascade handled by DB const result = await db.query('DELETE FROM roles WHERE id = $1 RETURNING *', [id]); if (result.rows.length === 0) return res.status(404).json({ error: 'Role not found' }); res.json({ success: true, deletedId: id }); } catch (err) { console.error(err); res.status(500).json({ error: 'Server error' }); } }); // GET /api/roles/members - List members with roles // (This is effectively GET /api/users but enriched with roles) router.get('/members', async (req, res) => { try { const result = await db.query(` SELECT u.id, u.username, u.public_identity_key, json_agg(r.*) FILTER (WHERE r.id IS NOT NULL) as roles FROM users u LEFT JOIN user_roles ur ON u.id = ur.user_id LEFT JOIN roles r ON ur.role_id = r.id GROUP BY u.id `); res.json(result.rows); } catch (err) { console.error(err); res.status(500).json({ error: 'Server error' }); } }); // POST /api/roles/:id/assign - Assign role to user router.post('/:id/assign', checkPermission('manage_roles'), async (req, res) => { const { id } = req.params; // role id const { userId } = req.body; try { await db.query( 'INSERT INTO user_roles (user_id, role_id) VALUES ($1, $2) ON CONFLICT DO NOTHING', [userId, id] ); res.json({ success: true }); } catch (err) { console.error(err); res.status(500).json({ error: 'Server error' }); } }); // POST /api/roles/:id/remove - Remove role from user router.post('/:id/remove', checkPermission('manage_roles'), async (req, res) => { const { id } = req.params; // role id const { userId } = req.body; try { await db.query( 'DELETE FROM user_roles WHERE user_id = $1 AND role_id = $2', [userId, id] ); res.json({ success: true }); } catch (err) { console.error(err); res.status(500).json({ error: 'Server error' }); } }); module.exports = router;