eletrotupi / tcc/ api/src/controllers/users.ts258151993396b0b11c8543ebb8fad1053d759bc3
3.9 KB | 166 lines Raw
1
import { Request, Response, NextFunction } from 'express';
2
import {
3
  generateToken
4
} from '@app/services/auth.service';
5

6
import { getQueue, MailJobName } from '@app/lib/queue';
7

8
import {
9
  CreateUserSchema,
10
  UpdateUserSchema
11
} from '@app/schemas';
12

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

20
import {
21
  storeActivationCode
22
} from '@app/services/auth.service';
23

24
import {
25
  AuthenticatedRequest
26
} from '@app/middleware/auth';
27

28
import { prisma } from '@app/lib/prisma';
29
import s3 from '@app/lib/s3';
30
import { DeleteObjectCommand } from '@aws-sdk/client-s3';
31
import crypto from 'crypto';
32
import { addMinutes } from 'date-fns';
33

34
// XXX: I've regreted already
35
interface SingleFileRequest extends AuthenticatedRequest {
36
  file?: any;
37
}
38

39
export const UsersController = {
40
  create: async (req: Request, res: Response, next: NextFunction) => {
41
    try {
42
      const parsed = CreateUserSchema.safeParse(req.body.user);
43

44
      if (!parsed.success) {
45
        return res.status(422).json({
46
          errors: parsed.error!.issues
47
        })
48
      }
49

50
      const user = await createUser(parsed.data);
51
      const jwtToken = generateToken(user.id, user.email);
52

53
      const code = [...Array(6)].map(() => crypto.randomInt(9))
54
        .join("");
55

56
      const expiresAt = addMinutes(new Date(), 5);
57
      await storeActivationCode(user.id, code, expiresAt);
58

59
      const mailQueue = getQueue('mail');
60
      const job = await mailQueue.add(MailJobName.WelcomeEmail, {
61
        userId: user.id,
62
        code: code
63
      });
64

65
      res.status(201).json({
66
        token: jwtToken
67
      });
68
    } catch (err) {
69
      next(err);
70
    }
71
  },
72

73
  update: async (req: Request, res: Response, next: NextFunction) => {
74
    try {
75
      const { id } = req.params;
76

77
      const parsed = UpdateUserSchema.safeParse(req.body.user);
78
      if (!parsed.success) {
79
        return res.status(400).json({
80
          errors: parsed.error!.issues
81
        });
82
      }
83

84
      const user = await findUserById(Number(id));
85

86
      if (!user) {
87
        return res.status(404).json({
88
          error: "Usuário não encontrado"
89
        });
90
      }
91

92
      const updated = await updateUser(parsed.data);
93

94
      // TODO: Drop encrypted password & token here
95
      return res.status(200).json({
96
        user: updated
97
      });
98
    } catch (err) {
99
      next(err);
100
    }
101
  },
102

103
  updateAvatar: async (req: SingleFileRequest, res: Response, next: NextFunction) => {
104
    try {
105
      if (!req.file) {
106
        return res.status(400).json({ error: 'No file uploaded' });
107
      }
108

109
      const currentUser = await findUserById(Number(req.userId));
110
      if (currentUser?.avatarKey) {
111
        await s3.send(
112
          new DeleteObjectCommand({
113
            Bucket: process.env.S3_BUCKET!, Key: currentUser?.avatarKey!
114
          })
115
        );
116
      }
117

118
      const user = await prisma.user.update({
119
        where: {
120
          id: currentUser?.id
121
        }, data: {
122
          avatarURL: req.file.location,
123
          avatarKey: req.file.key
124
        }
125
      });
126

127
      res.json({
128
        message: 'File uploaded successfully',
129
        fileLocation: req.file.location,
130
        key: req.file.key,
131
        filename: req.file.originalname,
132
        size: req.file.size,
133
        user: user
134
      });
135
    } catch (err) {
136
      next(err);
137
    }
138
  },
139

140
  removeAvatar: async (req: AuthenticatedRequest, res: Response, next: NextFunction) => {
141
    const currentUser = await findUserById(Number(req.userId));
142

143
    if (currentUser && currentUser?.avatarKey == null) {
144
      return res.json({ user: currentUser })
145
    }
146

147
    await s3.send(
148
      new DeleteObjectCommand({
149
        Bucket: process.env.S3_BUCKET!, Key: currentUser?.avatarKey!
150
      })
151
    );
152

153
    const user = await prisma.user.update({
154
      where: {
155
        id: req.userId
156
      }, data: {
157
        avatarURL: null,
158
        avatarKey: null
159
      }
160
    });
161

162
    return res.json({
163
      user
164
    })
165
  }
166
}