From 4c5c1acaf551c66bee2efae0c3ae4abb18205140 Mon Sep 17 00:00:00 2001 From: Xodrium <118943715+malloc62@users.noreply.github.com> Date: Sun, 5 Feb 2023 09:50:49 -0500 Subject: [PATCH] fixed gitignore --- .gitignore | 2 +- src/lib/db/db.js | 253 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 254 insertions(+), 1 deletion(-) create mode 100644 src/lib/db/db.js diff --git a/.gitignore b/.gitignore index 4662f70..42e5a50 100644 --- a/.gitignore +++ b/.gitignore @@ -8,4 +8,4 @@ node_modules !.env.example vite.config.js.timestamp-* vite.config.ts.timestamp-* -db +/db diff --git a/src/lib/db/db.js b/src/lib/db/db.js new file mode 100644 index 0000000..1b5e87d --- /dev/null +++ b/src/lib/db/db.js @@ -0,0 +1,253 @@ +const rowCount = 5; + +import sqlite3 from 'sqlite3' +import { open } from 'sqlite' +import { hash, compare } from 'bcrypt' +import { calcVote, calcVoteUser, heckLength, checkRegex } from '../util.js'; + +const { + randomBytes +} = await import('node:crypto'); + +var db; +async function initDb() { + db = await open({ + filename: `${process.cwd()}/db/main.db`, + driver: sqlite3.Database + }); + + await db.run('CREATE TABLE IF NOT EXISTS auth (username CHAR(64), password CHAR(1024))'); + await db.run('CREATE TABLE IF NOT EXISTS token (username CHAR(64), token CHAR(1024))'); + await db.run('CREATE TABLE IF NOT EXISTS post (username CHAR(64), id CHAR(64), content CHAR(10240), upvotes INTEGER, downvotes INTEGER, rating REAL)'); + await db.run('CREATE TABLE IF NOT EXISTS vote (id CHAR(64), username CHAR(64), type INTEGER)'); + await db.run('CREATE TABLE IF NOT EXISTS user (username CHAR(64), followers INTEGER, following INTEGER, upvotes INTEGER, downvotes INTEGER, reputation REAL)'); +} + +var backend = {}; + +var updateUser = async ({user}) => { + let allPosts = await db.all('SELECT * from post WHERE username = ?', [ + user + ]); + + let upvotes = 0; + let downvotes = 0; + let reputation = 0; + + allPosts.forEach(post => { + upvotes += post.upvotes || 0; + downvotes += post.downvotes || 0; + }); + + await db.run('DELETE FROM user WHERE username = ?', [ + user + ]); + + await db.run('INSERT INTO user (username,followers,following,upvotes,downvotes,reputation) VALUES (?,?,?,?,?,?)', [ + user, + 0, + 0, + upvotes, + downvotes, + calcVoteUser(upvotes,downvotes) + ]); +} + +backend.register = async ({user, pass, pass2}) => { + var lengthCheck = false; + + lengthCheck = + checkLength(pass,'Password',4,1024) || + checkLength(user,'Username',1,64) || + checkRegex(user,'Username',/[^A-Za-z0-9\-\_]/g); + + if (lengthCheck) return lengthCheck; + + if (pass != pass2) return {'success': 'Passwords don\'t match.'}; + + if (!db) await initDb(); + + var existingAccounts = await db.all('SELECT username FROM auth WHERE username = ?',[ + user + ]); + + if (existingAccounts && existingAccounts.length > 0) + return { success: 'Account already exists.' }; + + var passHash = await hash(pass,10); + + await db.run('INSERT INTO auth (username, password) VALUES (?, ?)', [ + user, + passHash + ]) + + return { success: 'Successfully created account.', location: '/'}; +} + +backend.login = async ({user, pass, cookies}) => { + if (!db) await initDb(); + + var existingAccounts = await db.all('SELECT username, password FROM auth WHERE username = ?',[ + user + ]); + + if (!existingAccounts || existingAccounts.length < 1) + return { success: 'Account does not exist.' }; + + var passHash = await compare(pass,existingAccounts[0].password); + + if (!passHash) + return { success: 'Incorrect password.' }; + + var token = randomBytes(256).toString('hex'); + + await db.run('INSERT INTO token (username, token) VALUES (?, ?)', [ + user, + token + ]) + + if (token) { + cookies.set('token',token, { + maxAge: 60 * 60 * 24 * 7, + path: '/' + }); + }; + + return { success: 'Successfully logged into account.', data: token, location: '/'}; +} + +backend.postCreate = async ({cookies, content}) => { + if (!db) await initDb(); + + var lengthCheck = checkLength(content,'Post content',1,10240); + + if (lengthCheck) + return lengthCheck; + + var user = (await backend.token({cookies})).data; + + if (!user || !content || user == '') return {'success': 'Not authorized.' }; + + var id = randomBytes(10).toString('hex'); + + await db.run('INSERT INTO post (username, id, content, rating) VALUES (?, ?, ?, ?)', [ + user, + id, + content, + calcVote(0,0) + ]) + + return {'success': 'Your post has been broadcasted!' }; +} + +backend.postGet = async ({id}) => { + if (!db) await initDb(); + + var posts = await db.all('SELECT * from post WHERE id = ?', [ + id + ]) + + if (!posts || posts.length < 1) { + return {'success': 'Post does not exist.'} + } + + return {data: posts[0]}; +} + +backend.userGet = async ({user}) => { + if (!db) await initDb(); + + var posts = await db.all('SELECT * from user WHERE username = ?', [ + user + ]) + + if (!posts || posts.length < 1) { + return {'success': 'Post does not exist.'} + } + + return {data: posts[0]}; +} + +backend.postBulk = async ({page,user}) => { + if (!db) await initDb(); + + var posts; + + if (!user) { + posts = await db.all('SELECT * from post ORDER BY rating DESC LIMIT ?, ?', [ + page*rowCount, + rowCount + ]) + } else { + posts = await db.all('SELECT * from post WHERE username = ? ORDER BY rating DESC LIMIT ?, ?', [ + user, + page*rowCount, + rowCount + ]) + } + + return {data: posts}; +} + +backend.vote = async ({cookies, id, vote}) => { + if (!db) await initDb(); + + var user = (await backend.token({cookies})).data; + + if (!user || !id || user == '' || (vote != 'down' && vote != 'up')) return {success: 'fail' }; + + await db.run('DELETE FROM vote WHERE username = ? AND id = ?', [ + user, + id + ]); + + await db.run('INSERT INTO vote (id, username, type) VALUES (?,?,?)', [ + id, + user, + vote == 'up' ? 1 : 2 + ]); + + var votes = await db.all('SELECT type from vote WHERE id = ?', [ + id + ]) || []; + + var up = votes.filter(x => x.type == 1).length; + var down = votes.filter(x => x.type == 2).length; + + await db.run('UPDATE post SET upvotes = ?, downvotes = ?, rating = ? WHERE id = ?', [ + up, + down, + calcVote(up,down), + id + ]); + + var user = await db.all('SELECT * from post WHERE id = ?', [ + id + ]) || []; + + if (!user[0]) + return {success: 'fail' }; + + await updateUser({user: user[0].username}); + + return {data: {up,down}}; +} + +backend.token = async ({cookies}) => { + if (!db) await initDb(); + + var tokenIn = cookies.get('token'); + + var existingAccounts = await db.all('SELECT username from token WHERE token = ?',[ + tokenIn + ]); + + if (!existingAccounts || existingAccounts.length < 1) + return false; + + return {data: existingAccounts[0].username}; +} + +export { + backend +} \ No newline at end of file