From 630f16c2127999b4f2f2b84a16038f2fd2db8450 Mon Sep 17 00:00:00 2001 From: adjoly Date: Mon, 30 Jun 2025 21:43:13 +0200 Subject: [PATCH] =?UTF-8?q?=E3=80=8C=E2=9C=A8=E3=80=8D=20feat:=20added=20/?= =?UTF-8?q?register?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 5 +-- pnpm-lock.yaml | 24 +++++++++++++ pnpm-workspace.yaml | 1 + src/api/auth/default.js | 76 ++++++++++++++++++++++++++++++++++++----- 4 files changed, 95 insertions(+), 11 deletions(-) diff --git a/package.json b/package.json index 5fdc3e4..cb61f23 100644 --- a/package.json +++ b/package.json @@ -3,6 +3,7 @@ "@fastify/env": "^5.0.2", "@fastify/jwt": "^9.1.0", "@tailwindcss/vite": "^4.1.11", + "bcrypt": "^6.0.0", "fastify": "^5.4.0", "fastify-cli": "^7.4.0", "tailwindcss": "^4.1.11", @@ -10,7 +11,7 @@ }, "type": "module", "devDependencies": { - "vite": "^6.3.5", - "pino-pretty": "^13.0.0" + "pino-pretty": "^13.0.0", + "vite": "^6.3.5" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c1073f7..6361bfb 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -17,6 +17,9 @@ importers: '@tailwindcss/vite': specifier: ^4.1.11 version: 4.1.11(vite@6.3.5(jiti@2.4.2)(lightningcss@1.30.1)) + bcrypt: + specifier: ^6.0.0 + version: 6.0.0 fastify: specifier: ^5.4.0 version: 5.4.0 @@ -462,6 +465,10 @@ packages: avvio@9.1.0: resolution: {integrity: sha512-fYASnYi600CsH/j9EQov7lECAniYiBFiiAtBNuZYLA2leLe9qOvZzqYHFjtIj6gD2VMoMLP14834LFWvr4IfDw==} + bcrypt@6.0.0: + resolution: {integrity: sha512-cU8v/EGSrnH+HnxV2z0J7/blxH8gq7Xh2JFT6Aroax7UohdmiJJlxApMxtKfuI7z68NvvVcmR78k2LbT6efhRg==} + engines: {node: '>= 18'} + bn.js@4.12.2: resolution: {integrity: sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw==} @@ -755,6 +762,14 @@ packages: engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true + node-addon-api@8.4.0: + resolution: {integrity: sha512-D9DI/gXHvVmjHS08SVch0Em8G5S1P+QWtU31appcKT/8wFSPRcdHadIFSAntdMMVM5zz+/DL+bL/gz3UDppqtg==} + engines: {node: ^18 || ^20 || >= 21} + + node-gyp-build@4.8.4: + resolution: {integrity: sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==} + hasBin: true + obliterator@2.0.5: resolution: {integrity: sha512-42CPE9AhahZRsMNslczq0ctAEtqk8Eka26QofnqC346BZdHDySk3LWka23LI7ULIw11NmltpiLagIq8gBozxTw==} @@ -1308,6 +1323,11 @@ snapshots: '@fastify/error': 4.2.0 fastq: 1.19.1 + bcrypt@6.0.0: + dependencies: + node-addon-api: 8.4.0 + node-gyp-build: 4.8.4 + bn.js@4.12.2: {} chalk@4.1.2: @@ -1611,6 +1631,10 @@ snapshots: nanoid@3.3.11: {} + node-addon-api@8.4.0: {} + + node-gyp-build@4.8.4: {} + obliterator@2.0.5: {} on-exit-leak-free@2.1.2: {} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 35fa89c..620547b 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -1,3 +1,4 @@ ignoredBuiltDependencies: - '@tailwindcss/oxide' + - bcrypt - esbuild diff --git a/src/api/auth/default.js b/src/api/auth/default.js index 6e6e0fc..3be430d 100644 --- a/src/api/auth/default.js +++ b/src/api/auth/default.js @@ -1,16 +1,53 @@ -import fastifyJWT from '@fastify/jwt' -import sqlite from 'node:sqlite' +import fastifyJWT from '@fastify/jwt'; +import sqlite from 'node:sqlite'; +import bcrypt from 'bcrypt'; const database = new sqlite.DatabaseSync(':memory:'); +const saltRounds = 10; /** - * @param {import('fastify').FastifyInstance} fastify - * @param {import('fastify').FastifyPluginOptions} options + * @description Can be used to prepare the database + */ +function prepareDB() { + database.exec(` + CREATE TABLE credentials ( + username TEXT PRIMARY KEY, + passwordHash TEXT + ) STRICT + `); +} + +prepareDB() + +const userCheck = database.prepare('SELECT EXISTS (SELECT 1 FROM credentials WHERE username = ?);'); +const userQuery = database.prepare('SELECT username, passwordHash FROM credentials WHERE username = ?;'); +const userAdd = database.prepare('INSERT INTO credentials (username, passwordHash) VALUES (?, ?)'); + +/** + * @description Can be used to check is a user exists in the database + * @param {string} name + * + * @returns {boolean} + */ +function checkUser(name) { + const result = userCheck.get(name); + const key = Object.keys(result)[0]; + + return result[key] === 1; +} + +function isValidString(value) { + return typeof value === 'string' && value.trim() !== ''; +} + +/** + * @param {import('fastify').FastifyInstance} fastify + * @param {import('fastify').FastifyPluginOptions} options */ export default async function(fastify, options) { fastify.register(fastifyJWT, { secret: '12345', cookie: { - cookieName: 'refreshToken', + cookieName: 'refreshToken' }, sign: { expiresIn: '100000m' @@ -26,14 +63,35 @@ export default async function(fastify, options) { }); fastify.post('/login', async (request, reply) => { - // const { username, password } = request.body; + /** @type {{ user: string, password: string }} */ + const { user, password } = request.body; }); fastify.post('/register', async (request, reply) => { - // const { username, password } = request.body; + try { + /** @type {{ username: string, password: string }} */ + const { username, password } = request.body; + + if (!isValidString(username) || !isValidString(password)) { + return reply.code(400).send({ error: 'Invalid username or password' }); + } else if (checkUser(username) === true) { + return reply.code(400).send({ error: "User already exist" }); + } else if (password.length <= 8) { + return reply.code(400).send({ error: "Password too short" }); + } else if (password.length > 64) { + return reply.code(400).send({ error: "Password too long" }); + } + + const hash = await bcrypt.hash(password, saltRounds); + userAdd.run(username, hash); + return reply.code(200).send({ msg: 'Register successfuly' }); + } catch (err) { + fastify.log.error(err); + return reply.code(500).send(); + } }); - fastify.get('/profile', { preHandler: [fastify.authenticate] }, async (request) => { - // return { user: request.user }; + fastify.get('/check', { preHandler: [fastify.authenticate] }, async (request) => { + return reply.code(200).send(); }); }