eletrotupi / tcc/ commit / aa9f316

api: draft for upload avatars

Pedro Lucas Porcellis porcellis@eletrotupi.com · 5 months ago aa9f316078c22a3cd681d3cef4743472fe1d1dad Browse files
Parents c74790e
Changed files
4
Additions
+62
Deletions
-2
api/src/controllers/users.ts
1 1
import { Request, Response, NextFunction } from 'express';
2 2
import {
3 3
  generateToken
4 4
} from '@app/services/auth.service';
5 5

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

19 +
// XXX: I've regreted already
20 +
interface SingleFileRequest extends Request {
21 +
  file?: any;
22 +
}
23 +

19 24
export const UsersController = {
20 25
  create: async (req: Request, res: Response, next: NextFunction) => {
21 26
    try {
22 27
      const parsed = CreateUserSchema.safeParse(req.body.user);
23 28

43 48

44 49
  update: async (req: Request, res: Response, next: NextFunction) => {
45 50
    try {
46 51
      const { id } = req.params;
47 52

48 -
      const parsed = UpdateUserSchema.safeParse(req.body);
53 +
      const parsed = UpdateUserSchema.safeParse(req.body.user);
49 54
      if (!parsed.success) {
50 55
        return res.status(400).json({
51 56
          errors: parsed.error!.issues
52 57
        });
53 58
      }
67 72
        user: updated
68 73
      });
69 74
    } catch (err) {
70 75
      next(err);
71 76
    }
77 +
  },
78 +

79 +
  updateAvatar: async (req: SingleFileRequest, res: Response, next: NextFunction) => {
80 +
    try {
81 +
      if (!req.file) {
82 +
        return res.status(400).json({ error: 'No file uploaded' });
83 +
      }
84 +

85 +
      res.json({
86 +
        message: 'File uploaded successfully',
87 +
        fileLocation: req.file.location,
88 +
        filename: req.file.originalname,
89 +
        size: req.file.size
90 +
      });
91 +
    } catch (err) {
92 +
      next(err);
93 +
    }
72 94
  }
73 -
};
95 +
}
/dev/null → api/src/lib/s3.ts
1 +
import { S3Client } from '@aws-sdk/client-s3';
2 +

3 +
const s3 = new S3Client({
4 +
  region: process.env.S3_REGION,
5 +
  endpoint: `https://${process.env.S3_URL}`,
6 +
  credentials: {
7 +
    accessKeyId: process.env.S3_ACCESS_KEY!,
8 +
    secretAccessKey: process.env.S3_ACCESS_SECRET!
9 +
  }
10 +
});
11 +

12 +
export default s3;
api/src/routes/users.ts
1 1
import { Router } from "express";
2 2
import { UsersController } from '@app/controllers/users'
3 +
import multer from '@app/services/avatar';
3 4

4 5
const router = Router();
5 6

6 7
router.post('/', UsersController.create);
7 8
router.put('/:id', UsersController.update);
9 +
router.post('/:id/avatar', multer.single('avatar'), UsersController.updateAvatar);
8 10

9 11
export default router;
/dev/null → api/src/services/avatar.ts
1 +
import s3 from '@app/lib/s3';
2 +
import multerBase from 'multer';
3 +
import multerS3 from 'multer-s3';
4 +
import path from 'path';
5 +
import crypto from 'crypto';
6 +

7 +
const avatarMulter = multerBase({
8 +
  storage: multerS3({
9 +
    s3,
10 +
    acl: "public-read",
11 +
    bucket: process.env.S3_BUCKET!,
12 +
    metadata: function (req, file, cb) {
13 +
      cb(null, { fieldName: file.fieldname });
14 +
    },
15 +
    key: function (req, file, cb) {
16 +
      const ext = path.extname(file.originalname).slice(1);
17 +
      const uuid = crypto.randomUUID();
18 +

19 +
      cb(null, `avatars/${uuid}.${ext}`)
20 +
    }
21 +
  })
22 +
})
23 +

24 +
export default avatarMulter;