File size: 2,689 Bytes
4a2c34e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
import { Router } from 'express';
import jwt from 'jsonwebtoken';
import { config } from '../../config';
import { redisClient } from '../../server';

const router = Router();

function signTokens(user: { id: string; email: string; orgId: string; role: string }) {
  const accessToken = jwt.sign(user, config.JWT_SECRET, { expiresIn: config.JWT_ACCESS_EXPIRY });
  const refreshToken = jwt.sign({ id: user.id }, config.JWT_REFRESH_SECRET, { expiresIn: config.JWT_REFRESH_EXPIRY });
  return { accessToken, refreshToken };
}

router.post('/register', async (req, res) => {
  const { email, name, password, orgName } = req.body;
  // TODO: hash password, create org + user in DB
  const user = { id: 'uuid-' + Date.now(), email, orgId: 'org-' + Date.now(), role: 'admin' };
  const tokens = signTokens(user);
  await redisClient.set(`refresh:${user.id}`, tokens.refreshToken, { EX: 7 * 24 * 60 * 60 });
  res.json({ data: { user, accessToken: tokens.accessToken }, meta: { refreshToken: tokens.refreshToken } });
});

router.post('/login', async (req, res) => {
  const { email, password } = req.body;
  // TODO: verify password against DB
  const user = { id: 'uuid-mock', email, orgId: 'org-mock', role: 'admin' };
  const tokens = signTokens(user);
  await redisClient.set(`refresh:${user.id}`, tokens.refreshToken, { EX: 7 * 24 * 60 * 60 });
  res.json({ data: { user, accessToken: tokens.accessToken }, meta: { refreshToken: tokens.refreshToken } });
});

router.post('/refresh', async (req, res) => {
  const { refreshToken } = req.body;
  try {
    const payload = jwt.verify(refreshToken, config.JWT_REFRESH_SECRET) as any;
    const stored = await redisClient.get(`refresh:${payload.id}`);
    if (!stored || stored !== refreshToken) throw new Error('Invalid refresh token');
    // TODO: fetch user from DB
    const user = { id: payload.id, email: 'mock@example.com', orgId: 'org-mock', role: 'admin' };
    const tokens = signTokens(user);
    await redisClient.set(`refresh:${user.id}`, tokens.refreshToken, { EX: 7 * 24 * 60 * 60 });
    res.json({ data: { accessToken: tokens.accessToken }, meta: { refreshToken: tokens.refreshToken } });
  } catch {
    res.status(401).json({ error: { message: 'Invalid refresh token', code: 'UNAUTHORIZED' } });
  }
});

router.post('/logout', async (req, res) => {
  const authHeader = req.headers.authorization;
  if (authHeader?.startsWith('Bearer ')) {
    try {
      const token = authHeader.slice(7);
      const payload = jwt.verify(token, config.JWT_SECRET) as any;
      await redisClient.del(`refresh:${payload.id}`);
    } catch { /* ignore */ }
  }
  res.json({ data: { success: true } });
});

export { router as authRouter };