feat(backend): Express + Socket.IO API with PostgreSQL
- Auth: register/login/me with bcrypt (12 rounds) and JWT bearer tokens - Workspaces: CRUD, role-based members (owner/admin/member/viewer), invite by email - Pages: nested hierarchy, TipTap JSON+HTML content, archive, search, comments - Realtime: Socket.IO rooms per page with JWT handshake, live edits, presence, typing - DB schema with triggers (owner membership, updated_at) and migrate script - Helmet, CORS allow-list, rate limiting, /api/health with DB check - Dockerfile (migrate-on-boot) for compose/production
This commit is contained in:
@@ -0,0 +1,18 @@
|
||||
import { Router } from 'express';
|
||||
import { query } from '../config/db.js';
|
||||
import { requireAuth } from '../middleware/auth.js';
|
||||
|
||||
const router = Router();
|
||||
router.use(requireAuth);
|
||||
|
||||
// GET /api/users/search?email= — find user by email (for invites)
|
||||
router.get('/search', async (req, res) => {
|
||||
const { email = '' } = req.query;
|
||||
if (!email) return res.status(400).json({ error: 'email required' });
|
||||
const { rows } = await query('SELECT id, email, name FROM users WHERE email = $1', [
|
||||
String(email).toLowerCase(),
|
||||
]);
|
||||
return res.json({ user: rows[0] || null });
|
||||
});
|
||||
|
||||
export default router;
|
||||
Reference in New Issue
Block a user