import { Router } from 'express'; import bcrypt from 'bcryptjs'; import db from '../db.js'; import { authMiddleware, adminOnly, generateToken } from '../middleware/auth.js'; import { sendMail, buildCardNotificationHtml, buildCardUrl } from '../email/transporter.js'; const router = Router(); router.use(authMiddleware); router.get('/', (req, res) => { if (req.user.role !== 'admin') return res.status(403).json({ error: 'Admin only' }); const users = db.prepare('SELECT id, email, name, avatar_color, role, is_active, created_at FROM users ORDER BY created_at').all(); res.json(users); }); router.post('/', adminOnly, async (req, res) => { const { email, name, password, role } = req.body; if (!email || !name || !password) return res.status(400).json({ error: 'All fields required' }); if (password.length < 6) return res.status(400).json({ error: 'Password must be at least 6 characters' }); const existing = db.prepare('SELECT id FROM users WHERE email = ?').get(email); if (existing) return res.status(400).json({ error: 'Email already exists' }); const hash = await bcrypt.hash(password, 12); const colors = ['#ef4444','#f97316','#eab308','#22c55e','#14b8a6','#3b82f6','#6366f1','#a855f7','#ec4899']; const color = colors[Math.floor(Math.random() * colors.length)]; const result = db.prepare('INSERT INTO users (email, name, password, role, avatar_color) VALUES (?, ?, ?, ?, ?)') .run(email, name, hash, role || 'member', color); const user = db.prepare('SELECT id, email, name, avatar_color, role FROM users WHERE id = ?').get(result.lastInsertRowid); try { await sendMail({ to: email, subject: 'Welcome to TeamFlow! 🚀', html: `

Welcome to TeamFlow, ${name}!

Your account has been created. Log in to get started.

Email: ${email}

Password: (set by your admin)

Go to TeamFlow
`, }); } catch {} res.json(user); }); router.put('/:id', adminOnly, (req, res) => { const { name, role, is_active } = req.body; const user = db.prepare('SELECT id FROM users WHERE id = ?').get(req.params.id); if (!user) return res.status(404).json({ error: 'User not found' }); if (user.id === req.user.id) return res.status(400).json({ error: 'Cannot modify yourself' }); if (name !== undefined) db.prepare('UPDATE users SET name = ? WHERE id = ?').run(name, user.id); if (role !== undefined) db.prepare('UPDATE users SET role = ? WHERE id = ?').run(role, user.id); if (is_active !== undefined) db.prepare('UPDATE users SET is_active = ? WHERE id = ?').run(is_active ? 1 : 0, user.id); const updated = db.prepare('SELECT id, email, name, avatar_color, role, is_active FROM users WHERE id = ?').get(user.id); res.json(updated); }); router.put('/:id/reset-password', adminOnly, async (req, res) => { const { password } = req.body; if (!password || password.length < 6) return res.status(400).json({ error: 'Password must be at least 6 characters' }); const user = db.prepare('SELECT id, email, name FROM users WHERE id = ?').get(req.params.id); if (!user) return res.status(404).json({ error: 'User not found' }); const hash = await bcrypt.hash(password, 12); db.prepare('UPDATE users SET password = ? WHERE id = ?').run(hash, user.id); res.json({ success: true }); }); router.get('/board/:boardId', (req, res) => { const members = db.prepare(` SELECT u.id, u.email, u.name, u.avatar_color, u.role, bm.role as board_role FROM board_members bm JOIN users u ON u.id = bm.user_id WHERE bm.board_id = ? `).all(req.params.boardId); res.json(members); }); export default router;