Skip to content
Permalink
Browse files
Add more functionalities to user.js
Added functions for getting, inserting and deleting user data.
Expanded user table to accommodate for newly-added data columns(email,
location, date registered).

Future considerations:
Add a table for rating artiles which would be linked to the user table.
Add functions to retrieve specifically email addresses from users to
enable sending emails to users.
  • Loading branch information
jeea2 committed Nov 27, 2019
1 parent f49dd0f commit ad28ea98423cb358232be6f0db089625587018d6
Show file tree
Hide file tree
Showing 2 changed files with 320 additions and 84 deletions.
@@ -2,63 +2,184 @@
'use strict'

const bcrypt = require('bcrypt-promise')
const fs = require('fs-extra')
const mime = require('mime-types')
const sqlite = require('sqlite-async')
const saltRounds = 10

module.exports = class User {
/**
* Class representing the details of the user.
* */
class User {

/**
* Constructor for User table
* @constructor
* @param {} [dbName=':memory:'] database for the website
*/
constructor(dbName = ':memory:') {
return (async() => {
this.db = await sqlite.open(dbName)
// we need this table to store the user accounts
const sql = 'CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY AUTOINCREMENT, user TEXT, pass TEXT);'
const sql = `CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user TEXT,
password TEXT,
email TEXT,
location TEXT,
profileImg TEXT,
profileTxt TEXT,
registeredDate TEXT);`
await this.db.run(sql)
return this
})()
}

async register(user, pass) {
/**
* Register user with suitable username and password.
* @param {string} user - username
* @param {string} password
* @return {Promise<true>} registration confirmation
*/
async register(user, password) {
try {
if(user.length === 0) throw new Error('missing username')
if(pass.length === 0) throw new Error('missing password')
let sql = `SELECT COUNT(id) as records FROM users WHERE user="${user}";`
if(password.length === 0) throw new Error('missing password')
let sql = `SELECT COUNT(id) as records FROM users WHERE user='${user}';`
const data = await this.db.get(sql)
if(data.records !== 0) throw new Error(`username "${user}" already in use`)
pass = await bcrypt.hash(pass, saltRounds)
sql = `INSERT INTO users(user, pass) VALUES("${user}", "${pass}")`
password = await bcrypt.hash(password, saltRounds)
const currentDate = Date.now().toString()
sql = `INSERT INTO users(user, password, registeredDate) VALUES('${user}', '${password}', ${currentDate})`
await this.db.run(sql)
return true
} catch(err) {
throw err
}
}

async uploadPicture(path, mimeType, bodyUser) {
/**
* Login user with existing username and password.
* @param {string} username
* @param {string} password
* @return {Promise<true>} login confirmation
*/
async login(username, password) {
try {
let sql = `SELECT count(id) AS count FROM users WHERE user='${username}';`
const records = await this.db.get(sql)
if(!records.count) throw new Error(`username "${username}" not found`)
sql = `SELECT password FROM users WHERE user = '${username}';`
const record = await this.db.get(sql)
const valid = await bcrypt.compare(password, record.password)
if(valid === false) throw new Error(`invalid password for user "${username}"`)
return true
} catch(err) {
throw err
}
}

/**
* Check email syntax.
* @param {string} email
* @returns {Promise<true>} confirmation for proper email syntax
*/
async checkEmail(email) {
try{
const extension = mime.extension(mimeType)
const acceptedExtension = ['jpg', 'png', 'webp', 'tif', 'gif', 'svg']
if(acceptedExtension.includes(extension) === false) throw new Error('file type is not suitable for upload')
await fs.copy(path, `public/avatars/${bodyUser}.${extension}`)
if(email.length === 0) throw new Error('missing email')
if(/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email) === false) throw new Error('email is invalid')
else return true
} catch(err) {
throw err
}
}

async login(username, password) {
try {
let sql = `SELECT count(id) AS count FROM users WHERE user="${username}";`
const records = await this.db.get(sql)
if(!records.count) throw new Error(`username "${username}" not found`)
sql = `SELECT pass FROM users WHERE user = "${username}";`
const record = await this.db.get(sql)
const valid = await bcrypt.compare(password, record.pass)
if(valid === false) throw new Error(`invalid password for account "${username}"`)
/**
* Add user email.
* @param {string} user
* @param {string} email
* @returns {Promise<true>} confirmation for adding user email
*/
async addEmail(user, email) {
try{
if(user.length === 0) throw new Error('missing username')
await this.checkEmail(email)
let sql = `SELECT COUNT(id) as records FROM users WHERE user='${user}';`
const data = await this.db.get(sql)
if(data.records === 0) throw new Error('username does not exist')
sql = `UPDATE users SET email = ('${email}') WHERE user = '${user}';`
await this.db.run(sql)
return true
} catch(err) {
throw err
}
}

/**
* Add user location.
* @param {string} user
* @param {string} location
* @returns {Promise<true>} confirmation for adding user location
*/
async addLocation(user, location) {
try{
if(user.length === 0) throw new Error('missing username')
if(location.length === 0) throw new Error('missing location')
let sql = `SELECT COUNT(id) as records FROM users WHERE user='${user}';`
const data = await this.db.get(sql)
if(data.records === 0) throw new Error('username does not exist')
sql = `UPDATE users SET location = '${location}' WHERE user = '${user}';`
await this.db.run(sql)
return true
} catch(err) {
throw err
}
}

/**
* Get all data of a selected user
* @param {string} username
* @returns {Promise<userData>}
*/
async getUser(username) {
try{
if(username.length === 0) throw new Error('username is missing')
let sql = `SELECT COUNT(id) as records FROM users WHERE user = '${username}'`
let data = await this.db.get(sql)
if(data.records === 0) throw new Error('username does not exist')
sql = `SELECT * FROM users WHERE user = '${username}'`
data = await this.db.get(sql)
return data
} catch(err) {
throw err
}
}

/**
* Get all data of all users
* @returns {Promise<userData[]>} array of data objects of all existing user
*/
async getAll() {
const sql = 'SELECT * FROM users;'
const data = await this.db.all(sql)
return data
}

/**
* Delete a user.
* @param {integer} key
* @returns {Promise<true>} confirmation for deleting user
*/
async delete(key) {
try{
if(key === undefined) throw new Error('missing id')
let sql = `SELECT COUNT(id) as records FROM users WHERE id=${key};`
const data = await this.db.get(sql)
if(data.records === 0) throw new Error(`user with id ${key} does not exist`)
sql = `DELETE FROM users WHERE id = ${key};`
await this.db.run(sql)
return true
} catch(err) {
throw err
}
}
}

module.exports = User

0 comments on commit ad28ea9

Please sign in to comment.