From c4221d946348442eb8d6ce0441aae305345fc13f Mon Sep 17 00:00:00 2001 From: adjoly Date: Thu, 23 Oct 2025 15:22:47 +0200 Subject: [PATCH] =?UTF-8?q?=E3=80=8C=F0=9F=94=A8=E3=80=8D=20fix(avatar):?= =?UTF-8?q?=20fix=20this=20shit?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 1 - pnpm-lock.yaml | 24 ------------------ pnpm-workspace.yaml | 1 + src/api/user/default.js | 9 +++++-- src/api/user/pAvatar.js | 55 ++++++++++++++++++++++------------------- src/utils/authDB.js | 1 - 6 files changed, 37 insertions(+), 54 deletions(-) diff --git a/package.json b/package.json index 32cd1ca..797d338 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,6 @@ "@fastify/cookie": "^11.0.2", "@fastify/env": "^5.0.2", "@fastify/jwt": "^9.1.0", - "@fastify/multipart": "^9.2.1", "axios": "^1.10.0", "base32.js": "^0.1.0", "bcrypt": "^6.0.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c40ec77..41a1bb9 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -20,9 +20,6 @@ importers: '@fastify/jwt': specifier: ^9.1.0 version: 9.1.0 - '@fastify/multipart': - specifier: ^9.2.1 - version: 9.2.1 axios: specifier: ^1.10.0 version: 1.10.0 @@ -261,18 +258,12 @@ packages: '@fastify/ajv-compiler@4.0.2': resolution: {integrity: sha512-Rkiu/8wIjpsf46Rr+Fitd3HRP+VsxUFDDeag0hs9L0ksfnwx2g7SPQQTFL0E8Qv+rfXzQOxBJnjUB9ITUDjfWQ==} - '@fastify/busboy@3.2.0': - resolution: {integrity: sha512-m9FVDXU3GT2ITSe0UaMA5rU3QkfC/UXtCU8y0gSN/GugTqtVldOBWIB5V6V3sbmenVZUIpU6f+mPEO2+m5iTaA==} - '@fastify/cookie@11.0.2': resolution: {integrity: sha512-GWdwdGlgJxyvNv+QcKiGNevSspMQXncjMZ1J8IvuDQk0jvkzgWWZFNC2En3s+nHndZBGV8IbLwOI/sxCZw/mzA==} '@fastify/deepmerge@2.0.2': resolution: {integrity: sha512-3wuLdX5iiiYeZWP6bQrjqhrcvBIf0NHbQH1Ur1WbHvoiuTYUEItgygea3zs8aHpiitn0lOB8gX20u1qO+FDm7Q==} - '@fastify/deepmerge@3.1.0': - resolution: {integrity: sha512-lCVONBQINyNhM6LLezB6+2afusgEYR4G8xenMsfe+AT+iZ7Ca6upM5Ha8UkZuYSnuMw3GWl/BiPXnLMi/gSxuQ==} - '@fastify/env@5.0.2': resolution: {integrity: sha512-4m/jHS3s/G/DBJVODob9sxGUei/Ij8JFbA2PYqBfoihTm+Qqae2xD9xhez68UFZu1d4SNJPIb6uAOwbNvRYw+A==} @@ -291,9 +282,6 @@ packages: '@fastify/merge-json-schemas@0.2.1': resolution: {integrity: sha512-OA3KGBCy6KtIvLf8DINC5880o5iBlDX4SxzLQS8HorJAbqluzLRn80UXU0bxZn7UOFhFgpRJDasfwn9nG4FG4A==} - '@fastify/multipart@9.2.1': - resolution: {integrity: sha512-U4221XDMfzCUtfzsyV1/PkR4MNgKI0158vUUyn/oF2Tl6RxMc+N7XYLr5fZXQiEC+Fmw5zFaTjxsTGTgtDtK+g==} - '@fastify/proxy-addr@5.0.0': resolution: {integrity: sha512-37qVVA1qZ5sgH7KpHkkC4z9SK6StIsIcOmpjvMPXNb3vx2GQxhZocogVYbr2PbbeLCQxYIPDok307xEvRZOzGA==} @@ -1910,8 +1898,6 @@ snapshots: ajv-formats: 3.0.1(ajv@8.17.1) fast-uri: 3.0.6 - '@fastify/busboy@3.2.0': {} - '@fastify/cookie@11.0.2': dependencies: cookie: 1.0.2 @@ -1919,8 +1905,6 @@ snapshots: '@fastify/deepmerge@2.0.2': {} - '@fastify/deepmerge@3.1.0': {} - '@fastify/env@5.0.2': dependencies: env-schema: 6.0.1 @@ -1946,14 +1930,6 @@ snapshots: dependencies: dequal: 2.0.3 - '@fastify/multipart@9.2.1': - dependencies: - '@fastify/busboy': 3.2.0 - '@fastify/deepmerge': 3.1.0 - '@fastify/error': 4.2.0 - fastify-plugin: 5.0.1 - secure-json-parse: 4.0.0 - '@fastify/proxy-addr@5.0.0': dependencies: '@fastify/forwarded': 3.0.0 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index a8eee40..8a8cca4 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -5,3 +5,4 @@ ignoredBuiltDependencies: onlyBuiltDependencies: - better-sqlite3 + - sharp diff --git a/src/api/user/default.js b/src/api/user/default.js index a2bb2aa..79b5786 100644 --- a/src/api/user/default.js +++ b/src/api/user/default.js @@ -1,7 +1,6 @@ import fastifyJWT from '@fastify/jwt'; import fastifyCookie from '@fastify/cookie'; import Database from 'better-sqlite3'; -import multipart from '@fastify/multipart'; import { gUsers } from './gUsers.js'; import { gUser } from './gUser.js'; @@ -151,7 +150,13 @@ export default async function(fastify, options) { }, }); fastify.register(fastifyCookie); - fastify.register(multipart, { limits: { fileSize: 2 * 1024 * 1024 + 1 } }); + + fastify.addContentTypeParser( + ['image/jpeg', 'image/png', 'image/gif', 'image/webp'], + { parseAs: 'buffer' }, + async (request, payload) => payload + ); + fastify.decorate('authenticate', async function(request, reply) { try { diff --git a/src/api/user/pAvatar.js b/src/api/user/pAvatar.js index 5b9f3a9..a567589 100644 --- a/src/api/user/pAvatar.js +++ b/src/api/user/pAvatar.js @@ -1,37 +1,40 @@ import sharp from 'sharp'; +/** + * @param {import('fastify').FastifyRequest} request + * @param {import('fastify').FastifyReply} reply + * @param {import('fastify').FastifyInstance} fastify + */ export async function pAvatar(request, reply, fastify, getUserInfo, setAvatarId, postImage) { try { const userId = request.params.userId; if (!getUserInfo.get(userId)) { - return reply.cose(404).send({ error: "User does not exist" }); + return reply.code(404).send({ error: "User does not exist" }); } - const parts = request.parts(); - for await (const part of parts) { - if (part.file) { - let size = 0; - const chunks = []; - for await (const chunk of part.file) { - size += chunk.length; - chunks.push(chunk); - } - if (size === 5 * 1024 * 1024 + 1) { - return reply.code(400).send({ error: "File too large" }); - } - const buffer = Buffer.concat(chunks); - if (!part.filename || part.filename.trim() === '') { - return reply.code(400).send({ error: "Missing filename" }); - } - if (!part.mimetype || part.mimetype.trim() === '') { - return reply.code(400).send({ error: "Missing mimetype" }); - } - const webpBuffer = await sharp(buffer).toFormat('webp').toBuffer(); - const imageId = postImage.run(part.filename, part.mimetype, webpBuffer); - setAvatarId.run(imageId.lastInsertRowid, userId); - return reply.code(200).send({ msg: "Avatar uploaded successfully" }); - } + + // Read the raw body as a Buffer + const buffer = request.body; + + if (!buffer) { + return reply.code(400).send({ error: "No file uploaded" }); } - return reply.code(400).send({ error: "No avatar uploaded" }); + + // Check file size (5MB limit) + if (buffer.length > 5 * 1024 * 1024) { + return reply.code(400).send({ error: "File too large" }); + } + + // Convert to WebP + const webpBuffer = await sharp(buffer).toFormat('webp').toBuffer(); + + // Save the image and update the user's avatar + const mimeType = request.headers['content-type']; + const fileName = `avatar_${userId}.webp`; + const imageId = postImage.run(fileName, mimeType, webpBuffer); + + setAvatarId.run(imageId.lastInsertRowid, userId); + + return reply.code(200).send({ msg: "Avatar uploaded successfully" }); } catch (err) { fastify.log.error(err); return reply.code(500).send({ error: "Internal server error" }); diff --git a/src/utils/authDB.js b/src/utils/authDB.js index 4aee3c1..69d1bde 100644 --- a/src/utils/authDB.js +++ b/src/utils/authDB.js @@ -87,7 +87,6 @@ function rmUser(user) { stmt.run(user); } - const authDB = { prepareDB, checkUser,