eletrotupi / tcc/ commit / 7c99110

api/users: fix auth hole on update users endpoint

Pedro Lucas Porcellis porcellis@eletrotupi.com · 29 days ago 7c9911031ecbe75f0d9d67f8fbaae4eece125df9 Browse files
Parents 2ee3cb6
Changed 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;