api: draft for upload avatars
Pedro Lucas Porcellis porcellis@eletrotupi.com · 5 months ago
aa9f316078c22a3cd681d3cef4743472fe1d1dad Browse filesParents
c74790eChanged 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;