🌊 TeamFlow — Modern Trello alternative with email integration

- Full-stack: React 18 + Express + SQLite
- Drag-and-drop kanban boards with @hello-pangea/dnd
- Google App Password email integration (SMTP + IMAP)
- Inbound email: create cards by sending emails
- Reply-to-card: email replies become comments
- Admin/user management with role-based access
- Setup wizard: email config → admin creation
- Checklists, time tracking, priorities, labels, due dates
- Real-time notifications with activity feed
- Beautiful HTML email templates
This commit is contained in:
admin
2026-04-03 15:11:27 +00:00
Unverified
commit 460f83aef8
40 changed files with 8512 additions and 0 deletions

34
server/middleware/auth.js Normal file
View File

@@ -0,0 +1,34 @@
import jwt from 'jsonwebtoken';
import db from '../db.js';
const JWT_SECRET = process.env.JWT_SECRET || 'teamflow-secret-change-in-production';
export function generateToken(user) {
return jwt.sign(
{ id: user.id, email: user.email, role: user.role },
JWT_SECRET,
{ expiresIn: '7d' }
);
}
export function authMiddleware(req, res, next) {
const header = req.headers.authorization;
if (!header || !header.startsWith('Bearer ')) {
return res.status(401).json({ error: 'No token provided' });
}
try {
const token = header.split(' ')[1];
const payload = jwt.verify(token, JWT_SECRET);
const user = db.prepare('SELECT id, email, name, avatar_color, role, is_active FROM users WHERE id = ?').get(payload.id);
if (!user || !user.is_active) return res.status(401).json({ error: 'Invalid token' });
req.user = user;
next();
} catch {
return res.status(401).json({ error: 'Invalid token' });
}
}
export function adminOnly(req, res, next) {
if (req.user.role !== 'admin') return res.status(403).json({ error: 'Admin access required' });
next();
}