Skip to content

Commit 7af9675

Browse files
committed
fix(http-code): return 406 for invalid file extensions
1 parent 47300e0 commit 7af9675

File tree

8 files changed

+42
-43
lines changed

8 files changed

+42
-43
lines changed

app/app.ts

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import type { NextFunction, Request, Response } from 'express'
33
import express from 'express'
44
import { PrismaClient } from '@prisma/client'
55
import cors from 'cors'
6+
import { HttpError } from 'http-errors'
67
import logger from 'morgan'
78
import swaggerUi from 'swagger-ui-express'
89

@@ -17,15 +18,10 @@ import {
1718
userRouter
1819
} from './routes/api'
1920

20-
export type ResponseError = Error & {
21-
status?: number
22-
code?: number | string
23-
}
21+
export const prisma = new PrismaClient()
2422

2523
const app = express()
2624

27-
export const prisma = new PrismaClient()
28-
2925
app.listen(Number(process.env.PORT) || 5432, () => {
3026
console.log(`Server started on port ${process.env.PORT || 5432}`)
3127
})
@@ -50,7 +46,7 @@ app.use((_, res) => {
5046
res.status(404).json({ message: 'Not found' })
5147
})
5248

53-
app.use((err: ResponseError, _: Request, res: Response, __: NextFunction) => {
49+
app.use((err: HttpError, _: Request, res: Response, __: NextFunction) => {
5450
const { status = 500, message = 'Server error' } = err
5551
res.status(status).json({ statusCode: status, message })
5652
})

app/middlewares/authenticate.ts

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import type { NextFunction, Request, Response } from 'express'
22

33
import { prisma } from 'app'
4-
import createHttpError from 'http-errors'
5-
import jwt from 'jsonwebtoken'
4+
import { Unauthorized } from 'http-errors'
5+
import { verify } from 'jsonwebtoken'
66

77
export const authenticate = async (
88
req: Request,
@@ -12,28 +12,24 @@ export const authenticate = async (
1212
const { authorization = '' } = req.headers
1313
const [bearer, token] = authorization.split(' ')
1414

15-
if (bearer !== 'Bearer') {
16-
return next(createHttpError(401))
17-
}
15+
if (bearer !== 'Bearer') return next(Unauthorized())
1816

1917
try {
20-
const { id, sid } = jwt.verify(token, process.env.ACCESS_JWT_SECRET!) as {
18+
const { id, sid } = verify(token, process.env.ACCESS_JWT_SECRET!) as {
2119
id: string
2220
sid: string
2321
}
2422

2523
const user = await prisma.user.findFirst({ where: { id } })
2624
const session = await prisma.session.findFirst({ where: { id: sid } })
2725

28-
if (!user || !session) {
29-
return next(createHttpError(401))
30-
}
26+
if (!user || !session) return next(Unauthorized())
3127

3228
req.user = user
3329
req.session = session.id
3430

3531
next()
3632
} catch {
37-
return next(createHttpError(401))
33+
return next(Unauthorized())
3834
}
3935
}

app/middlewares/index.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,2 @@
11
export * from './authenticate'
2-
export * from './multer'
32
export * from './validateRequest'

app/routes/api/board.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -61,15 +61,15 @@ boardRouter.put(
6161
'/:boardId',
6262
validateRequest({ body: EditBoardSchema, params: BoardParamsSchema }),
6363
async ({ body, params, user }, res, next) => {
64-
const updatedBoard = await prisma.board.update({
64+
const updatedBoard = await prisma.board.updateMany({
6565
where: { id: params.boardId, userId: user.id },
6666
data: {
6767
...body,
6868
background: body.background && boardImages[body.background]
6969
}
7070
})
7171

72-
if (!updatedBoard) return next(NotFound('Board not found'))
72+
if (!updatedBoard.count) return next(NotFound('Board not found'))
7373

7474
res.json(updatedBoard)
7575
}
@@ -79,11 +79,11 @@ boardRouter.delete(
7979
'/:boardId',
8080
validateRequest({ params: BoardParamsSchema }),
8181
async ({ params, user }, res, next) => {
82-
const deletedBoard = await prisma.board.delete({
82+
const deletedBoard = await prisma.board.deleteMany({
8383
where: { id: params.boardId, userId: user.id }
8484
})
8585

86-
if (!deletedBoard) return next(NotFound('Board not found'))
86+
if (!deletedBoard.count) return next(NotFound('Board not found'))
8787

8888
res.status(204).send()
8989
}

app/routes/api/card.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,12 @@ cardRouter.put(
4242
'/:cardId',
4343
validateRequest({ body: EditCardSchema, params: CardParamsSchema }),
4444
async ({ params, body }, res, next) => {
45-
const updatedCard = await prisma.card.update({
45+
const updatedCard = await prisma.card.updateMany({
4646
where: { id: params.cardId },
4747
data: body
4848
})
4949

50-
if (!updatedCard) return next(NotFound('Card not found'))
50+
if (!updatedCard.count) return next(NotFound('Card not found'))
5151

5252
res.json(updatedCard)
5353
}
@@ -83,11 +83,11 @@ cardRouter.delete(
8383
'/:cardId',
8484
validateRequest({ params: CardParamsSchema }),
8585
async ({ params }, res, next) => {
86-
const deletedCard = await prisma.card.delete({
86+
const deletedCard = await prisma.card.deleteMany({
8787
where: { id: params.cardId }
8888
})
8989

90-
if (!deletedCard) return next(NotFound('Card not found'))
90+
if (!deletedCard.count) return next(NotFound('Card not found'))
9191

9292
res.status(204).send()
9393
}

app/routes/api/column.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,12 +45,12 @@ columnRouter.put(
4545
'/:columnId',
4646
validateRequest({ body: EditColumnSchema, params: ColumnParamsSchema }),
4747
async ({ params, body }, res, next) => {
48-
const updatedColumn = await prisma.column.update({
48+
const updatedColumn = await prisma.column.updateMany({
4949
where: { id: params.columnId },
5050
data: body
5151
})
5252

53-
if (!updatedColumn) return next(NotFound('Column not found'))
53+
if (!updatedColumn.count) return next(NotFound('Column not found'))
5454

5555
res.json(updatedColumn)
5656
}
@@ -86,11 +86,11 @@ columnRouter.delete(
8686
'/:columnId',
8787
validateRequest({ params: ColumnParamsSchema }),
8888
async ({ params }, res, next) => {
89-
const deletedColumn = await prisma.column.delete({
89+
const deletedColumn = await prisma.column.deleteMany({
9090
where: { id: params.columnId }
9191
})
9292

93-
if (!deletedColumn) return next(NotFound('Column not found'))
93+
if (!deletedColumn.count) return next(NotFound('Column not found'))
9494

9595
res.status(204).send()
9696
}

app/routes/api/user.ts

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,11 @@ import { hash } from 'bcrypt'
55
import cloudinary from 'config/cloudinary.config'
66
import { transport } from 'config/nodemailer.config'
77
import defaultAvatars from 'data/default-avatars.json'
8-
import { BadRequest, Conflict, InternalServerError } from 'http-errors'
8+
import { Conflict, InternalServerError, NotAcceptable } from 'http-errors'
9+
import { Options } from 'nodemailer/lib/mailer'
910

10-
import { authenticate, upload, validateRequest } from 'middlewares'
11+
import { authenticate, validateRequest } from 'middlewares'
12+
import { upload } from 'middlewares/multer'
1113

1214
import { EditUserSchema, NeedHelpSchema, ThemeSchema } from 'schemas/user'
1315

@@ -50,7 +52,7 @@ userRouter.put(
5052
const ext = file.mimetype.split('/').pop()
5153

5254
if (!extArr.includes(ext!)) {
53-
return next(BadRequest('File must have .jpeg or .png extension'))
55+
return next(NotAcceptable('File must have .jpeg or .png extension'))
5456
}
5557

5658
try {
@@ -86,7 +88,7 @@ userRouter.post(
8688
'/help',
8789
validateRequest({ body: NeedHelpSchema }),
8890
async (req, res, next) => {
89-
const emailBody = {
91+
const emailBody: Options = {
9092
from: process.env.EMAIL_USER,
9193
to: process.env.EMAIL_RECEIVER,
9294
subject: 'Need help',
@@ -110,12 +112,7 @@ userRouter.put(
110112
'/theme',
111113
validateRequest({ body: ThemeSchema }),
112114
async (req, res) => {
113-
const user = await prisma.user.findFirst({
114-
where: { id: req.user.id },
115-
omit: { password: true }
116-
})
117-
118-
const updateData = !user?.avatarPublicId
115+
const updateData = !req.user.avatarPublicId
119116
? {
120117
...req.body,
121118
avatar: defaultAvatars[req.body.theme],
@@ -125,7 +122,8 @@ userRouter.put(
125122

126123
const editedUser = await prisma.user.update({
127124
where: { id: req.user.id },
128-
data: updateData
125+
data: updateData,
126+
omit: { password: true }
129127
})
130128

131129
res.json(editedUser)

swagger.json

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -233,15 +233,15 @@
233233
"requestBody": {
234234
"required": true,
235235
"content": {
236+
"application/json": { "example": { "password": "123456789" } },
236237
"multipart/form-data": {
237238
"schema": {
238239
"type": "object",
239240
"properties": {
240241
"avatar": { "type": "string", "format": "binary" }
241242
}
242243
}
243-
},
244-
"application/json": { "example": { "password": "123456789" } }
244+
}
245245
}
246246
},
247247
"responses": {
@@ -259,6 +259,16 @@
259259
}
260260
}
261261
},
262+
"406": {
263+
"content": {
264+
"application/json": {
265+
"example": {
266+
"statusCode": 406,
267+
"message": "File must have .jpeg or .png extension"
268+
}
269+
}
270+
}
271+
},
262272
"401": { "$ref": "#/components/responses/Unauthorized" },
263273
"409": { "$ref": "#/components/responses/Conflict" }
264274
}

0 commit comments

Comments
 (0)