From 6452ec2dba35041a7bad8dab27dba3482c2d2bcc Mon Sep 17 00:00:00 2001 From: Lightemerald Date: Mon, 11 Mar 2024 12:19:19 +0100 Subject: [PATCH] Fixed API issues and added a test file --- .env.sample | 4 ++-- .gitignore | 2 +- bun.lockb | Bin 97275 -> 97275 bytes database.sql | 13 +++++++------ index.js | 2 +- modules/mailHandler.js | 26 ++++++++++++++------------ modules/permissionManager.js | 10 +++++----- modules/tokenManager.js | 4 +++- routes/users.js | 7 ++++--- test.js | 34 ++++++++++++++++++++++++++++++++++ 10 files changed, 71 insertions(+), 31 deletions(-) create mode 100644 test.js diff --git a/.env.sample b/.env.sample index fec9b30..8d2906f 100644 --- a/.env.sample +++ b/.env.sample @@ -1,8 +1,8 @@ PORT=3000 DOMAIN="http://localhost:3000" DATABASE_HOST="127.0.0.1" -DATABASE_NAME=hsp-gdh -DATABASE_USER=hsp-gdh +DATABASE_NAME=hsp_gdh +DATABASE_USER=hsp_gdh DATABASE_PASSWORD="" JWT_SECRET="" SMTP= diff --git a/.gitignore b/.gitignore index f0d9796..6769c0e 100644 --- a/.gitignore +++ b/.gitignore @@ -136,4 +136,4 @@ logs/ *.log # token -token/ \ No newline at end of file +tokens/ \ No newline at end of file diff --git a/bun.lockb b/bun.lockb index e0b6543d7c0f2209a3b4e64e5e11603a89727b62..6bed908634736a42adf59a9a11cdcabf6d3214bd 100755 GIT binary patch delta 1574 zcmezUo%Q#3)(vkH8RI6uOAKd>o9vbZBIkk0Z(!0d86>g{O#TCtVJRSybzqV$6~vAM zliR=~Um8dx4NUF>lVa&0kvuSY3{1*pfJDl`+y*B3 z3PB=iU~(Ur6e|LWK_ctGBwHJZ9S0`2fl0o0kVqPs+y^Gb zIzS?MVDcE4lwC`z@*&_kjOMJ`3_9F z%>;?e1C!stq~9!%$TBeb4@`#528pZ#lWcQ9>^LyF4NUUQ1&O4A$$el_Y#vA?4@@2d zlXCMxB4uFm9GFyF01~MKlh?qc-a?Q_8<@NYCe0RsMEbzwGcakl7$hg{O#TCtVJRSybzqV$6~vAM zliR=~Um8dx4NUF>lVa&0kvuSY3{1*pfJDl`+y*B3 z3PB=iU~(Ur6e|LWK_ctGBwHJZ9S0`2fl0o0kVqPs+y^Gb zIzS?MVDcE4lwC`z@*&_kjOMJ`3_9F z%>;?e1C!stq~9!%$TBeb4@`#528pZ#lWcQ9>^LyF4NUUQ1&O4A$$el_Y#vA?4@@2d zlXCMxB4uFm9GFyF01~MKlh?qc-a?Q_8<@NYCe0RsMEbzwGcakl7$h { // test // import { post } from './modules/fetcher'; -// post('http://127.0.0.1:1109/users/login', { 'usernameOrEmail':'foo', 'password':'bar' }).then(res => console.log(res)); +// post('http://127.0.0.1:1109/users/login', { 'usernameOrEmail':'foo', 'password':'bar' }).then(res => console.log(res)); \ No newline at end of file diff --git a/modules/mailHandler.js b/modules/mailHandler.js index 1ba5917..160455d 100644 --- a/modules/mailHandler.js +++ b/modules/mailHandler.js @@ -1,44 +1,45 @@ import nodemailer from 'nodemailer'; import { random } from './random'; +import { log } from './logManager'; const transporter = nodemailer.createTransport({ host: process.env.SMTP, port: 465, secure: true, auth: { - user: process.env.MAIL, - pass: process.env.MAIL_PASS, + user: `${process.env.MAIL}`, + pass: `${process.env.PASS}`, }, + tls: { rejectUnauthorized: false }, }); function sendMail(email, head, body) { try { - // setup email data const mailOptions = { - from: `"AirJet" <${process.env.MAIL}>`, + from: `"HSP-GDH" <${process.env.MAIL}>`, to: email, subject: head, text: body, }; - // send mail with defined transport object transporter.sendMail(mailOptions, (error, info) => { if (error) { - console.log(error); + log('Retrying connection to SMTP'); + if (sendMail(email, head, body)) return true; } else { - console.log('Email sent: ' + info.response); + log('Email sent: ' + info.response); + return true; } }); - return true; } catch (err) { return false; } } -function sendVerification(email, userId, type = 'register', code = null) { +async function sendVerification(email, userId, type = 'register', code = null) { try { - code ? code : random(100000, 999999); + code ? code : code = random(100000, 999999); let title, body; switch (type) { case 'email': @@ -56,8 +57,9 @@ function sendVerification(email, userId, type = 'register', code = null) { default: return false; } - if (sendMail(email, title, body)) return code; - return false; + await sendMail(email, title, body); + return code; + } catch (err) { return false; diff --git a/modules/permissionManager.js b/modules/permissionManager.js index 281ac37..649e4fe 100644 --- a/modules/permissionManager.js +++ b/modules/permissionManager.js @@ -18,7 +18,7 @@ export async function userExists(userId) { export async function isBanned(userId) { try { const [bannedUser] = await pool.execute('SELECT * FROM bans WHERE user_id = ? LIMIT 1', [userId]); - if (bannedUser.length > 0) return true; + if (bannedUser.length) return true; return false; } catch (err) { @@ -60,24 +60,24 @@ export async function checkIfUserEmailIsVerified(userId) { export async function checkUserExists(req, res, next) { const userId = req.userId; - if (!userExists(userId)) return await respondWithStatus(res, 404, 'User not found'); + if (!await userExists(userId)) return await respondWithStatus(res, 404, 'User not found'); next(); } export async function checkBanned(req, res, next) { const userId = req.userId; - if (isBanned(userId)) return await respondWithStatus(res, 403, 'User is banned'); + if (await isBanned(userId)) return await respondWithStatus(res, 403, 'User is banned'); next(); } export const checkPermissions = (permissionName, permissionType) => async (req, res, next) => { const userId = req.userId; - if (!verifyPermissions(userId, permissionName, permissionType)) return await respondWithStatus(res, 403, 'Missing permission'); + if (!await verifyPermissions(userId, permissionName, permissionType)) return await respondWithStatus(res, 403, 'Missing permission'); next(); }; export const checkEmailVerified = async (req, res, next) => { const userId = req.userId; - if (!checkIfUserEmailIsVerified(userId)) return await respondWithStatus(res, 403, 'Email not verified'); + if (!await checkIfUserEmailIsVerified(userId)) return await respondWithStatus(res, 403, 'Email not verified'); next(); }; \ No newline at end of file diff --git a/modules/tokenManager.js b/modules/tokenManager.js index 3581abb..4f1e24c 100644 --- a/modules/tokenManager.js +++ b/modules/tokenManager.js @@ -1,6 +1,7 @@ import jwt from 'jsonwebtoken'; import { Level } from 'level'; import { pool } from './databaseManager'; +import { error } from '../modules/logManager'; import { respondWithStatus } from './requestHandler'; const db = new Level('tokens', { valueEncoding: 'json' }); @@ -31,7 +32,8 @@ export async function verifyToken(req, res, next) { } next(); } - catch (error) { + catch (err) { + error(err); return await respondWithStatus(res, 401, 'Invalid user'); } } diff --git a/routes/users.js b/routes/users.js index 8a522f0..b7f863e 100644 --- a/routes/users.js +++ b/routes/users.js @@ -20,7 +20,7 @@ router.post('/register', requestLimiter, async (req, res) => { const [existingEmail] = await pool.execute('SELECT * FROM users WHERE email = ? LIMIT 1', [email]); if (existingEmail.length) return await respondWithStatus(res, 400, 'Email is already taken'); - if (!isPhoneNumber(phone)) return await respondWithStatus(res, 400, 'Invalid phone number'); + if (phone && !isPhoneNumber(phone)) return await respondWithStatus(res, 400, 'Invalid phone number'); const hashedPassword = await Bun.password.hash(password); @@ -63,7 +63,7 @@ router.post('/login', requestLimiter, async (req, res) => { const passwordMatch = await Bun.password.verify(password, user.password); if (!passwordMatch) return await respondWithStatus(res, 401, 'Incorrect password'); - if (isBanned(user.id)) return await respondWithStatus(res, 403, 'User is banned or an issue occured'); + if (await isBanned(user.id)) return await respondWithStatus(res, 403, 'User is banned or an issue occured'); const token = await generateToken(user.id, password); return await respondWithStatusJSON(res, 200, { message: 'Login successful', @@ -128,7 +128,7 @@ router.get('/email/request', verifyToken, checkBanned, async (req, res) => { if (!rows.length) return await respondWithStatus(res, 404, 'User not found'); const user = rows[0]; if (user.email_verified) return await respondWithStatus(res, 400, 'Email is already verified'); - const code = sendVerification(user.email, userId, 'email'); + const code = await sendVerification(user.email, userId, 'email'); pool.execute('INSERT INTO verification_codes (user_id, verification_code, type) VALUES (?, ?, ?)', [ userId, code, 'email' ]); return await respondWithStatus(res, 200, 'Successfully sent verification email'); } @@ -151,6 +151,7 @@ router.get('/email/verify', verifyToken, checkBanned, async (req, res) => { const [result] = await pool.execute('UPDATE users SET email_verified = ? WHERE id = ?', [ true, userId ]); if (result.affectedRows === 0) return await respondWithStatus(res, 500, 'Error updating user'); + await pool.execute('DELETE FROM verification_codes WHERE id = ?', [ rows[0].id ]); return await respondWithStatus(res, 200, 'Successfully verified user'); } diff --git a/test.js b/test.js new file mode 100644 index 0000000..315c055 --- /dev/null +++ b/test.js @@ -0,0 +1,34 @@ +import { get, post } from './modules/fetchManager'; + +let token = ''; + +async function main() { + let res = await post('http://127.0.0.1:1109/api/users/register', { + username: + 'emerald', + email: + 'light_emerald@aostia.com', + password: + 'test1234', + first_name: + 'Emerald', + last_name: + 'Light', + }); + console.log(res); + + res = await post('http://127.0.0.1:1109/api/users/login', { + usernameOrEmail: 'emerald', + password: 'test1234', + }); + console.log(res); + token = res.JSON.token; + + res = await get('http://127.0.0.1:1109/api/users/email/request', token); + console.log(res); + + res = await get('http://127.0.0.1:1109/api/users/email/verify?code=345708', token); + console.log(res); +} + +main(); \ No newline at end of file