fix(services): improve validation PUT /users/current
This commit is contained in:
parent
32ac15c831
commit
2405b4951b
@ -1,15 +1,15 @@
|
|||||||
FROM node:16.13.1 AS dependencies
|
FROM node:16.13.2 AS dependencies
|
||||||
WORKDIR /usr/src/app
|
WORKDIR /usr/src/app
|
||||||
COPY ./package*.json ./
|
COPY ./package*.json ./
|
||||||
RUN npm install
|
RUN npm install
|
||||||
|
|
||||||
FROM node:16.13.1 AS builder
|
FROM node:16.13.2 AS builder
|
||||||
WORKDIR /usr/src/app
|
WORKDIR /usr/src/app
|
||||||
COPY --from=dependencies /usr/src/app/node_modules ./node_modules
|
COPY --from=dependencies /usr/src/app/node_modules ./node_modules
|
||||||
COPY ./ ./
|
COPY ./ ./
|
||||||
RUN npm run prisma:generate && npm run build
|
RUN npm run prisma:generate && npm run build
|
||||||
|
|
||||||
FROM node:16.13.1 AS runner
|
FROM node:16.13.2 AS runner
|
||||||
WORKDIR /usr/src/app
|
WORKDIR /usr/src/app
|
||||||
ENV NODE_ENV=production
|
ENV NODE_ENV=production
|
||||||
COPY --from=builder /usr/src/app/node_modules ./node_modules
|
COPY --from=builder /usr/src/app/node_modules ./node_modules
|
||||||
|
2370
package-lock.json
generated
2370
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
32
package.json
32
package.json
@ -31,17 +31,17 @@
|
|||||||
"postinstall": "husky install"
|
"postinstall": "husky install"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@prisma/client": "3.8.0",
|
"@prisma/client": "3.8.1",
|
||||||
"@sinclair/typebox": "0.23.2",
|
"@sinclair/typebox": "0.23.2",
|
||||||
"@thream/socketio-jwt": "2.1.1",
|
"@thream/socketio-jwt": "2.1.1",
|
||||||
"axios": "0.24.0",
|
"axios": "0.25.0",
|
||||||
"bcryptjs": "2.4.3",
|
"bcryptjs": "2.4.3",
|
||||||
"dotenv": "11.0.0",
|
"dotenv": "14.2.0",
|
||||||
"ejs": "3.1.6",
|
"ejs": "3.1.6",
|
||||||
"fastify": "3.25.3",
|
"fastify": "3.27.0",
|
||||||
"fastify-cors": "6.0.2",
|
"fastify-cors": "6.0.2",
|
||||||
"fastify-helmet": "6.0.0",
|
"fastify-helmet": "7.0.1",
|
||||||
"fastify-multipart": "5.2.1",
|
"fastify-multipart": "5.3.0",
|
||||||
"fastify-plugin": "3.0.0",
|
"fastify-plugin": "3.0.0",
|
||||||
"fastify-rate-limit": "5.7.0",
|
"fastify-rate-limit": "5.7.0",
|
||||||
"fastify-sensible": "3.1.2",
|
"fastify-sensible": "3.1.2",
|
||||||
@ -56,20 +56,20 @@
|
|||||||
"socket.io": "4.4.1"
|
"socket.io": "4.4.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@commitlint/cli": "16.0.2",
|
"@commitlint/cli": "16.1.0",
|
||||||
"@commitlint/config-conventional": "16.0.0",
|
"@commitlint/config-conventional": "16.0.0",
|
||||||
"@saithodev/semantic-release-backmerge": "2.1.0",
|
"@saithodev/semantic-release-backmerge": "2.1.0",
|
||||||
"@swc/cli": "0.1.55",
|
"@swc/cli": "0.1.55",
|
||||||
"@swc/core": "1.2.129",
|
"@swc/core": "1.2.133",
|
||||||
"@swc/jest": "0.2.17",
|
"@swc/jest": "0.2.17",
|
||||||
"@types/bcryptjs": "2.4.2",
|
"@types/bcryptjs": "2.4.2",
|
||||||
"@types/busboy": "1.3.0",
|
"@types/busboy": "1.3.0",
|
||||||
"@types/ejs": "3.1.0",
|
"@types/ejs": "3.1.0",
|
||||||
"@types/http-errors": "1.8.1",
|
"@types/http-errors": "1.8.2",
|
||||||
"@types/jest": "27.4.0",
|
"@types/jest": "27.4.0",
|
||||||
"@types/jsonwebtoken": "8.5.7",
|
"@types/jsonwebtoken": "8.5.8",
|
||||||
"@types/ms": "0.7.31",
|
"@types/ms": "0.7.31",
|
||||||
"@types/node": "17.0.8",
|
"@types/node": "17.0.10",
|
||||||
"@types/nodemailer": "6.4.4",
|
"@types/nodemailer": "6.4.4",
|
||||||
"@typescript-eslint/eslint-plugin": "4.33.0",
|
"@typescript-eslint/eslint-plugin": "4.33.0",
|
||||||
"concurrently": "7.0.0",
|
"concurrently": "7.0.0",
|
||||||
@ -82,19 +82,19 @@
|
|||||||
"eslint-plugin-node": "11.1.0",
|
"eslint-plugin-node": "11.1.0",
|
||||||
"eslint-plugin-prettier": "4.0.0",
|
"eslint-plugin-prettier": "4.0.0",
|
||||||
"eslint-plugin-promise": "5.1.1",
|
"eslint-plugin-promise": "5.1.1",
|
||||||
"eslint-plugin-unicorn": "40.0.0",
|
"eslint-plugin-unicorn": "40.1.0",
|
||||||
"husky": "7.0.4",
|
"husky": "7.0.4",
|
||||||
"jest": "27.4.7",
|
"jest": "27.4.7",
|
||||||
"jest-mock-extended": "2.0.4",
|
"jest-mock-extended": "2.0.4",
|
||||||
"jest-ts-webcompat-resolver": "1.0.0",
|
"jest-ts-webcompat-resolver": "1.0.0",
|
||||||
"lint-staged": "12.1.7",
|
"lint-staged": "12.2.2",
|
||||||
"markdownlint-cli": "0.30.0",
|
"markdownlint-cli": "0.30.0",
|
||||||
"nodemon": "2.0.15",
|
"nodemon": "2.0.15",
|
||||||
"plop": "3.0.5",
|
"plop": "3.0.5",
|
||||||
"prettier": "2.5.1",
|
"prettier": "2.5.1",
|
||||||
"prisma": "3.8.0",
|
"prisma": "3.8.1",
|
||||||
"rimraf": "3.0.2",
|
"rimraf": "3.0.2",
|
||||||
"semantic-release": "18.0.1",
|
"semantic-release": "19.0.2",
|
||||||
"typescript": "4.5.4"
|
"typescript": "4.5.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,10 +8,10 @@ export const themes = [Type.Literal('light'), Type.Literal('dark')]
|
|||||||
|
|
||||||
export const userSettingsSchema = {
|
export const userSettingsSchema = {
|
||||||
id,
|
id,
|
||||||
language: Type.Union(languages, { default: 'en' }),
|
language: Type.Union(languages),
|
||||||
theme: Type.Union(themes, { default: 'dark' }),
|
theme: Type.Union(themes),
|
||||||
isPublicEmail: Type.Boolean({ default: false }),
|
isPublicEmail: Type.Boolean(),
|
||||||
isPublicGuilds: Type.Boolean({ default: false }),
|
isPublicGuilds: Type.Boolean(),
|
||||||
createdAt: date.createdAt,
|
createdAt: date.createdAt,
|
||||||
updatedAt: date.updatedAt,
|
updatedAt: date.updatedAt,
|
||||||
userId: id
|
userId: id
|
||||||
|
@ -82,7 +82,7 @@ describe('PUT /users/current', () => {
|
|||||||
expect(response.statusCode).toEqual(400)
|
expect(response.statusCode).toEqual(400)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('suceeds with valid website url', async () => {
|
it('succeeds with valid website url', async () => {
|
||||||
const newWebsite = 'https://somerandomwebsite.com'
|
const newWebsite = 'https://somerandomwebsite.com'
|
||||||
const { accessToken, user } = await authenticateUserTest()
|
const { accessToken, user } = await authenticateUserTest()
|
||||||
prismaMock.user.update.mockResolvedValue({
|
prismaMock.user.update.mockResolvedValue({
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import { randomUUID } from 'node:crypto'
|
import { randomUUID } from 'node:crypto'
|
||||||
|
|
||||||
import { Static, Type } from '@sinclair/typebox'
|
import { Static, Type } from '@sinclair/typebox'
|
||||||
import { FastifyPluginAsync, FastifySchema } from 'fastify'
|
import { FastifyPluginAsync, FastifySchema } from 'fastify'
|
||||||
|
|
||||||
@ -14,10 +13,10 @@ import { parseStringNullish } from '../../../tools/utils/parseStringNullish.js'
|
|||||||
|
|
||||||
const bodyPutServiceSchema = Type.Object({
|
const bodyPutServiceSchema = Type.Object({
|
||||||
name: Type.Optional(userSchema.name),
|
name: Type.Optional(userSchema.name),
|
||||||
email: Type.Optional(userSchema.email),
|
email: Type.Optional(Type.Union([userSchema.email, Type.Null()])),
|
||||||
status: Type.Optional(userSchema.status),
|
status: Type.Optional(Type.Union([userSchema.status, Type.Null()])),
|
||||||
biography: Type.Optional(userSchema.biography),
|
biography: Type.Optional(Type.Union([userSchema.biography, Type.Null()])),
|
||||||
website: Type.Optional(userSchema.website)
|
website: Type.Optional(Type.Union([userSchema.website, Type.Null()]))
|
||||||
})
|
})
|
||||||
|
|
||||||
type BodyPutServiceSchemaType = Static<typeof bodyPutServiceSchema>
|
type BodyPutServiceSchemaType = Static<typeof bodyPutServiceSchema>
|
||||||
@ -89,7 +88,12 @@ export const putCurrentUser: FastifyPluginAsync = async (fastify) => {
|
|||||||
if (request.user.current.password != null) {
|
if (request.user.current.password != null) {
|
||||||
strategies.push('local')
|
strategies.push('local')
|
||||||
}
|
}
|
||||||
if (email != null) {
|
if (email === null && strategies.includes('local')) {
|
||||||
|
throw fastify.httpErrors.badRequest(
|
||||||
|
'You must have an email to sign in.'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if (email != null && email !== request.user.current.email) {
|
||||||
await prisma.refreshToken.deleteMany({
|
await prisma.refreshToken.deleteMany({
|
||||||
where: {
|
where: {
|
||||||
userId: request.user.current.id
|
userId: request.user.current.id
|
||||||
|
@ -1,21 +1,25 @@
|
|||||||
/**
|
/**
|
||||||
* Parse a nullish string:
|
* Parse a nullish string:
|
||||||
|
* - if `string === undefined`, it returns `defaultString`
|
||||||
|
* - if `string === null`, it returns `null`
|
||||||
* - if `string.length === 0`, it returns `null`
|
* - if `string.length === 0`, it returns `null`
|
||||||
* - if `string == null`, it returns `defaultString`
|
* - else, it returns `string`
|
||||||
* - if `string.length > 0`, it returns `string`
|
|
||||||
* @param defaultString
|
* @param defaultString
|
||||||
* @param string
|
* @param string
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export const parseStringNullish = (
|
export const parseStringNullish = (
|
||||||
defaultString: string | null,
|
defaultString: string | null,
|
||||||
string?: string
|
string?: string | null
|
||||||
): string | null => {
|
): string | null => {
|
||||||
if (string != null) {
|
if (string === undefined) {
|
||||||
if (string.length > 0) {
|
return defaultString
|
||||||
return string
|
|
||||||
}
|
}
|
||||||
|
if (string === null) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
return defaultString
|
if (string.length === 0) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
return string
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user