eletrotupi / tcc/ api/src/controllers/auth.tsbdc1f3aa45bfff5472ae567a15ca20cc76ec3370
3.3 KB | 124 lines Raw
1
import { Request, Response, NextFunction } from 'express';
2
import {
3
  authenticateUser,
4
  generateToken,
5
  initiatePasswordReset,
6
  resetPassword
7
} from '@app/models/user';
8
import {
9
  validateRequiredFields
10
} from '@app/utils/validators';
11
import { verifyToken } from '@app/lib/jwt';
12

13
export const AuthController = {
14
  login: async (req: Request, res: Response, next: NextFunction) => {
15
    try {
16
      const { email, password } = req.body;
17

18
      const requiredValidation = validateRequiredFields(req.body, [
19
        'email', 'password'
20
      ]);
21

22
      if (!requiredValidation.valid) {
23
        return res.status(400).json({
24
          error: 'Missing required fields',
25
          missing: requiredValidation.missing
26
        });
27
      }
28

29
      const user = await authenticateUser(email, password);
30
      const jwtToken = generateToken(user.id, user.email);
31

32
      res.json({
33
        token: jwtToken,
34
        user: {
35
          id: user.id,
36
          email: user.email,
37
          firstName: user.firstName,
38
          lastName: user.lastName
39
        }
40
      });
41
    } catch (err: any) {
42
      if (err.message === 'Invalid credentials') {
43
        return res.status(401).json({ error: 'Invalid credentials' });
44
      }
45
      next(err);
46
    }
47
  },
48

49
  forgotPassword: async (req: Request, res: Response, next: NextFunction) => {
50
    try {
51
      const { email } = req.body;
52

53
      const requiredValidation = validateRequiredFields(req.body, ['email']);
54

55
      if (!requiredValidation.valid) {
56
        return res.status(400).json({
57
          error: 'Email is required',
58
          missing: requiredValidation.missing
59
        });
60
      }
61

62
      const result = await initiatePasswordReset(email);
63

64
      // In production, don't send token in response
65
      // Instead, send email with reset link
66
      res.json({
67
        message: 'Password reset instructions sent to your email',
68
        ...(!process.env.NODE_ENV || process.env.NODE_ENV === 'development' ? { token: result.token } : {})
69
      });
70
    } catch (err) {
71
      next(err);
72
    }
73
  },
74

75
  resetPassword: async (req: Request, res: Response, next: NextFunction) => {
76
    try {
77
      const { token, password } = req.body;
78

79
      const requiredValidation = validateRequiredFields(req.body, [
80
        'token', 'password'
81
      ]);
82

83
      if (!requiredValidation.valid) {
84
        return res.status(400).json({
85
          error: 'Missing required fields',
86
          missing: requiredValidation.missing
87
        });
88
      }
89

90
      await resetPassword(token, password);
91

92
      res.json({ message: 'Password successfully reset' });
93
    } catch (err: any) {
94
      if (err.message.includes('token')) {
95
        return res.status(400).json({ error: err.message });
96
      }
97
      next(err);
98
    }
99
  },
100

101
  verify: async (req: Request, res: Response, next: NextFunction) => {
102
    try {
103
      const authHeader = req.headers.authorization;
104

105
      if (!authHeader || !authHeader.startsWith('Bearer ')) {
106
        return res.status(401).json({ error: 'No token provided' });
107
      }
108

109
      const token = authHeader.substring(7);
110
      const payload = verifyToken(token);
111

112
      res.json({
113
        valid: true,
114
        userId: payload.userId,
115
        email: payload.email
116
      });
117
    } catch (err: any) {
118
      if (err.name === 'JsonWebTokenError' || err.name === 'TokenExpiredError') {
119
        return res.status(401).json({ error: 'Invalid or expired token' });
120
      }
121
      next(err);
122
    }
123
  }
124
};