eletrotupi / tcc/ api/src/controllers/auth.ts3c4663c2d8ca263914cc1fcc6547f043c1aef311
3.8 KB | 151 lines Raw
1
import { Request, Response, NextFunction } from 'express';
2
import {
3
  login,
4
  generateToken,
5
  requestPasswordReset,
6
  resetPassword,
7
  activateUser
8
} from '@app/services/auth.service';
9

10
import {
11
  verifyToken
12
} from '@app/lib/jwt';
13

14
import {
15
  findUserByEmail,
16
  findUserById,
17
} from '@app/services/user.service'
18

19
import {
20
  LoginSchema,
21
  PasswordResetSchema,
22
  PasswordResetRequestSchema,
23
  ActivateUserSchema
24
} from '@app/schemas';
25

26
export const AuthController = {
27
  login: async (req: Request, res: Response, next: NextFunction) => {
28
    try {
29
      const parsed = LoginSchema.safeParse(req.body);
30

31
      if (!parsed.success) {
32
        return res.status(400).json({
33
          errors: parsed.error!.issues
34
        });
35
      }
36

37
      const { user, token } = await login(parsed.data);
38

39
      return res.json({
40
        token,
41
        user
42
      });
43
    } catch (err: any) {
44
      if (err.message === 'Invalid credentials') {
45
        return res.status(401).json({ error: 'Invalid credentials' });
46
      }
47
      next(err);
48
    }
49
  },
50

51
  forgotPassword: async (req: Request, res: Response, next: NextFunction) => {
52
    try {
53

54
      const parsed = PasswordResetRequestSchema.safeParse(req.body);
55

56
      if (!parsed.success) {
57
        return res.status(400).json({
58
          errors: parsed.error!.issues
59
        });
60
      }
61

62
      const result = await requestPasswordReset(parsed.data);
63
      return res.status(200).json(result)
64
    } catch (err) {
65
      next(err);
66
    }
67
  },
68

69
  resetPassword: async (req: Request, res: Response, next: NextFunction) => {
70
    try {
71
      const parsed = PasswordResetSchema.safeParse(req.body);
72

73
      if (!parsed.success) {
74
        return res.status(400).json({
75
          errors: parsed.error!.issues
76
        });
77
      }
78

79
      const result = await resetPassword(parsed.data);
80
      return res.status(200).json(result);
81
    } catch (err: any) {
82
      if (err.message.includes('token')) {
83
        return res.status(400).json({ error: err.message });
84
      }
85
      next(err);
86
    }
87
  },
88

89
  verify: async (req: Request, res: Response, next: NextFunction) => {
90
    try {
91
      const authHeader = req.headers.authorization;
92

93
      if (!authHeader || !authHeader.startsWith('Bearer ')) {
94
        return res.status(401).json({ error: 'No token provided' });
95
      }
96

97
      const token = authHeader.substring(7);
98
      const payload = verifyToken(token);
99
      const user = await findUserByEmail(payload.email);
100

101
      if (!user) {
102
        // XXX: Investigate which actual cases this would happen
103
        // But the possible reason is that a token is living inside
104
        // the user's phone, but somehow he was banned/deleted
105
        return res.status(404).json({
106
          errors: "User does not exist anymore"
107
        });
108
      }
109

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

129
  activate: async (req: Request, res: Response, next: NextFunction) => {
130
    try {
131
      const parsed = ActivateUserSchema.safeParse(req.body);
132

133
      if (!parsed.success) {
134
        return res.status(400).json({
135
          errors: parsed.error!.issues
136
        });
137
      }
138

139
      const user = await findUserById(parsed.data.userId);
140

141
      if (!user) {
142
        return res.status(403).json({ error: "Usuario não encontrado" })
143
      }
144

145
      const result = await activateUser(user, parsed.data);
146
      return res.status(200).json(result);
147
    } catch (err: any) {
148
      next(err);
149
    }
150
  }
151
};