eletrotupi / tcc/ commit / c456c24

api: lint & dispatch push token to feed the app internal user data

Pedro Lucas Porcellis porcellis@eletrotupi.com 1 month ago c456c24bb910e567777c909b4b5f59a0cd0e4c85
Parents: 9e31441
1 file(s) changed
  • api/src/controllers/auth.ts +54 -48
api/src/controllers/auth.ts
1 -
import { Request, Response, NextFunction } from 'express';
2 -
import { AuthenticatedRequest } from '@app/middleware/auth';
1 +
import { Request, Response, NextFunction } from "express";
2 +
import { AuthenticatedRequest } from "@app/middleware/auth";
3 3

4 4
import {
5 5
  login,
6 6
  generateToken,
7 7
  requestPasswordReset,
8 8
  resetPassword,
9 9
  activateUser,
10 -
  storeActivationCode
11 -
} from '@app/services/auth.service';
10 +
  storeActivationCode,
11 +
} from "@app/services/auth.service";
12 12

13 -
import {
14 -
  verifyToken
15 -
} from '@app/lib/jwt';
13 +
import { verifyToken } from "@app/lib/jwt";
16 14

17 15
import {
18 16
  findUserByEmail,
19 17
  findUserById,
20 18
  findUserByActivationCode,
21 -
} from '@app/services/user.service'
19 +
} from "@app/services/user.service";
22 20

23 21
import {
24 22
  LoginSchema,
25 23
  PasswordResetSchema,
26 24
  PasswordResetRequestSchema,
27 -
  ActivateUserSchema
28 -
} from '@app/schemas';
25 +
  ActivateUserSchema,
26 +
} from "@app/schemas";
29 27

30 -
import { addMinutes } from 'date-fns';
31 -
import { getQueue, MailJobName } from '@app/lib/queue';
32 -
import crypto from 'crypto';
28 +
import { addMinutes } from "date-fns";
29 +
import { getQueue, MailJobName } from "@app/lib/queue";
30 +
import crypto from "crypto";
33 31

34 32
export const AuthController = {
35 33
  login: async (req: Request, res: Response, next: NextFunction) => {
36 34
    try {
37 35
      const parsed = LoginSchema.safeParse(req.body);
38 36

39 37
      if (!parsed.success) {
40 38
        return res.status(400).json({
41 -
          errors: parsed.error!.issues
39 +
          errors: parsed.error!.issues,
42 40
        });
43 41
      }
44 42

45 43
      const { user, token } = await login(parsed.data);
46 44

47 -
      if (!user.active && (new Date() > new Date(user.activationCodeExpiresAt!))) {
48 -
        const code = [...Array(6)].map(() => crypto.randomInt(9))
49 -
        .join("");
45 +
      if (
46 +
        !user.active &&
47 +
        new Date() > new Date(user.activationCodeExpiresAt!)
48 +
      ) {
49 +
        const code = [...Array(6)].map(() => crypto.randomInt(9)).join("");
50 50

51 51
        const expiresAt = addMinutes(new Date(), 5);
52 52
        await storeActivationCode(user.id, code, expiresAt);
53 53

54 -
        const mailQueue = getQueue('mail');
54 +
        const mailQueue = getQueue("mail");
55 55
        const job = await mailQueue.add(MailJobName.ActivateAccountEmail, {
56 56
          userId: user.id,
57 -
          code: code
57 +
          code: code,
58 58
        });
59 59
      }
60 60

61 61
      return res.json({
62 62
        token,
63 -
        user
63 +
        user,
64 64
      });
65 65
    } catch (err: any) {
66 -
      if (err.message === 'Invalid credentials') {
67 -
        return res.status(401).json({ error: 'Invalid credentials' });
66 +
      if (err.message === "Invalid credentials") {
67 +
        return res.status(401).json({ error: "Invalid credentials" });
68 68
      }
69 69
      next(err);
70 70
    }
71 71
  },
72 72

73 73
  forgotPassword: async (req: Request, res: Response, next: NextFunction) => {
74 74
    try {
75 -

76 75
      const parsed = PasswordResetRequestSchema.safeParse(req.body);
77 76

78 77
      if (!parsed.success) {
79 78
        return res.status(400).json({
80 -
          errors: parsed.error!.issues
79 +
          errors: parsed.error!.issues,
81 80
        });
82 81
      }
83 82

84 83
      const result = await requestPasswordReset(parsed.data);
85 -
      return res.status(200).json(result)
84 +
      return res.status(200).json(result);
86 85
    } catch (err) {
87 86
      next(err);
88 87
    }
89 88
  },
90 89

▸ 1 unchanged lines
92 91
    try {
93 92
      const parsed = PasswordResetSchema.safeParse(req.body);
94 93

95 94
      if (!parsed.success) {
96 95
        return res.status(400).json({
97 -
          errors: parsed.error!.issues
96 +
          errors: parsed.error!.issues,
98 97
        });
99 98
      }
100 99

101 100
      const result = await resetPassword(parsed.data);
102 101
      return res.status(200).json(result);
103 102
    } catch (err: any) {
104 -
      if (err.message.includes('token')) {
103 +
      if (err.message.includes("token")) {
105 104
        return res.status(400).json({ error: err.message });
106 105
      }
107 106
      next(err);
108 107
    }
109 108
  },
110 109

111 110
  verify: async (req: Request, res: Response, next: NextFunction) => {
112 111
    try {
113 112
      const authHeader = req.headers.authorization;
114 113

115 -
      if (!authHeader || !authHeader.startsWith('Bearer ')) {
116 -
        return res.status(401).json({ error: 'No token provided' });
114 +
      if (!authHeader || !authHeader.startsWith("Bearer ")) {
115 +
        return res.status(401).json({ error: "No token provided" });
117 116
      }
118 117

119 118
      const token = authHeader.substring(7);
120 119
      const payload = verifyToken(token);
121 120
      const user = await findUserByEmail(payload.email);
▸ 1 unchanged lines
123 122
      if (!user) {
124 123
        // XXX: Investigate which actual cases this would happen
125 124
        // But the possible reason is that a token is living inside
126 125
        // the user's phone, but somehow he was banned/deleted
127 126
        return res.status(404).json({
128 -
          errors: "User does not exist anymore"
127 +
          errors: "User does not exist anymore",
129 128
        });
130 129
      }
131 130

132 131
      res.json({
133 132
        valid: true,
▸ 4 unchanged lines
138 137
          email: user.email,
139 138
          lastName: user.lastName,
140 139
          updatedAt: user.updatedAt,
141 140
          active: user.active,
142 141
          avatarKey: user.avatarKey,
143 -
          avatarURL: user.avatarURL
144 -
        }
142 +
          avatarURL: user.avatarURL,
143 +
          pushToken: user.pushToken,
144 +
        },
145 145
      });
146 146
    } catch (err: any) {
147 -
      if (err.name === 'JsonWebTokenError' || err.name === 'TokenExpiredError') {
148 -
        return res.status(401).json({ error: 'Invalid or expired token' });
147 +
      if (
148 +
        err.name === "JsonWebTokenError" ||
149 +
        err.name === "TokenExpiredError"
150 +
      ) {
151 +
        return res.status(401).json({ error: "Invalid or expired token" });
149 152
      }
150 153
      next(err);
151 154
    }
152 155
  },
153 156

▸ 1 unchanged lines
155 158
    try {
156 159
      const parsed = ActivateUserSchema.safeParse(req.body);
157 160

158 161
      if (!parsed.success) {
159 162
        return res.status(400).json({
160 -
          errors: parsed.error!.issues
163 +
          errors: parsed.error!.issues,
161 164
        });
162 165
      }
163 166

164 167
      const user = await findUserByActivationCode(String(parsed.data.code));
165 168

166 169
      if (!user) {
167 170
        return res.status(422).json({
168 -
          error: "Código incorreto. Verifique o código e tente novamente"
169 -
        })
171 +
          error: "Código incorreto. Verifique o código e tente novamente",
172 +
        });
170 173
      }
171 174

172 175
      const result = await activateUser(user);
173 176

174 177
      return res.status(200).json({
175 -
        user: result
178 +
        user: result,
176 179
      });
177 180
    } catch (err: any) {
178 181
      next(err);
179 182
    }
180 183
  },
181 184

182 -
  resendActivationCode: async (req: AuthenticatedRequest, res: Response, next: NextFunction) => {
185 +
  resendActivationCode: async (
186 +
    req: AuthenticatedRequest,
187 +
    res: Response,
188 +
    next: NextFunction,
189 +
  ) => {
183 190
    try {
184 191
      const user = await findUserById(req.userId!);
185 192

186 193
      if (!user) {
187 194
        return res.status(400).json({
188 -
          errors: "Usuário não encontrado"
189 -
        })
195 +
          errors: "Usuário não encontrado",
196 +
        });
190 197
      }
191 198

192 -
      const code = [...Array(6)].map(() => crypto.randomInt(9))
193 -
      .join("");
199 +
      const code = [...Array(6)].map(() => crypto.randomInt(9)).join("");
194 200

195 201
      const expiresAt = addMinutes(new Date(), 5);
196 202
      await storeActivationCode(user.id, code, expiresAt);
197 203

198 -
      const mailQueue = getQueue('mail');
204 +
      const mailQueue = getQueue("mail");
199 205
      const job = await mailQueue.add(MailJobName.ActivateAccountEmail, {
200 206
        userId: user.id,
201 -
        code: code
207 +
        code: code,
202 208
      });
203 209

204 210
      res.json({
205 -
        user
206 -
      })
211 +
        user,
212 +
      });
207 213
    } catch (err: any) {
208 214
      next(err);
209 215
    }
210 -
  }
216 +
  },
211 217
};