api/users: fix auth hole on update users endpoint
Pedro Lucas Porcellis porcellis@eletrotupi.com · 29 days ago
7c9911031ecbe75f0d9d67f8fbaae4eece125df9 Browse filesParents
2ee3cb6Changed files
2
Additions
+24
Deletions
-7
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
31 31
import { prisma } from '@app/lib/prisma';
32 32
import s3 from '@app/lib/s3';
33 33
import { DeleteObjectCommand } from '@aws-sdk/client-s3';
34 34
import crypto from 'crypto';
35 35
import { addMinutes } from 'date-fns';
36 +
import { User } from '@prisma/client';
36 37
37 38
// XXX: I've regreted already
38 39
interface SingleFileRequest extends AuthenticatedRequest {
39 40
file?: any;
40 41
}
42 +
43 +
const withoutSecrets = (user: User) => {
44 +
const {
45 +
encryptedPassword,
46 +
passwordResetToken,
47 +
passwordResetExpires,
48 +
...safe
49 +
} = user;
50 +
51 +
return safe;
52 +
};
41 53
42 54
export const UsersController = {
43 55
create: async (req: Request, res: Response, next: NextFunction) => {
44 56
try {
45 57
const parsed = CreateUserSchema.safeParse(req.body.user);
69 81
} catch (err) {
70 82
next(err);
71 83
}
72 84
},
73 85
74 -
update: async (req: Request, res: Response, next: NextFunction) => {
86 +
update: async (req: AuthenticatedRequest, res: Response, next: NextFunction) => {
75 87
try {
76 -
const { id } = req.params;
88 +
const targetId = Number(req.params.id);
89 +
90 +
if (targetId !== req.userId) {
91 +
return res.status(403).json({
92 +
error: "Você só pode atualizar o próprio perfil"
93 +
});
94 +
}
77 95
78 96
const parsed = UpdateUserSchema.safeParse(req.body.user);
79 97
if (!parsed.success) {
80 98
return res.status(400).json(formatValidationError(parsed.error!));
81 99
}
82 100
83 -
const user = await findUserById(Number(id));
101 +
const user = await findUserById(targetId);
84 102
85 103
if (!user) {
86 104
return res.status(404).json({
87 105
error: "Usuário não encontrado"
88 106
});
89 107
}
90 108
91 -
const updated = await updateUser(parsed.data);
109 +
const updated = await updateUser({ ...parsed.data, id: targetId });
92 110
93 -
// TODO: Drop encrypted password & token here
94 111
return res.status(200).json({
95 -
user: updated
112 +
user: withoutSecrets(updated)
96 113
});
97 114
} catch (err) {
98 115
next(err);
99 116
}
100 117
},
208 225
return res.json({
209 226
user
210 227
})
211 228
}
212 229
}
api/src/routes/users.ts
1 1
import { Router } from "express";
2 2
import { UsersController } from '@app/controllers/users';
3 3
import multer from '@app/services/avatar';
4 4
import { requireAuth } from '@app/middleware/auth';
5 5
6 6
const router = Router();
7 7
8 8
router.post('/', UsersController.create);
9 9
router.get('/me', requireAuth, UsersController.me);
10 10
router.patch('/me', requireAuth, UsersController.updatePreferences);
11 -
router.put('/:id', UsersController.update);
11 +
router.put('/:id', requireAuth, UsersController.update);
12 12
router.post('/me/avatar', requireAuth, multer.single('avatar'), UsersController.updateAvatar);
13 13
router.delete('/me/avatar', requireAuth, UsersController.removeAvatar);
14 14
15 15
export default router;