import sqlite3 from 'sqlite3' import bcrypt from 'bcryptjs' import ErrorType from '../error/types.error.js' import serverConfig from '../configuration/server.config.js' sqlite3.verbose() const tableName = 'Users' class User { constructor(options = {}) { if (!options.username || !options.password) { throw new Error('User has to have a username, a password') } this.username = options.username this.password_ = options.password } static findAll() { return new Promise((resolve, reject) => { const db = openDB() db.serialize(() => { db.all(`SELECT * FROM ${tableName}`, (err, users) => { if (err) reject(new Error(ErrorType.TECHNICAL_UNKNOWN)) else { const array = []; for (const user of users) { array.push(createUserFromDB(user)) } resolve(array); } }) closeDB(db) }) }) } static findByName(username) { return new Promise((resolve, reject) => { const db = openDB(); db.serialize(() => { db.get(`SELECT * FROM ${tableName} WHERE username = '${username}'`, (err, user) => { if (err) reject(new Error(ErrorType.TECHNICAL_UNKNOWN)) else { if (user) resolve(createUserFromDB(user)) else resolve(null) } }) }) closeDB(db) }) } static delete(username) { return new Promise((resolve, reject) => { const db = openDB(); db.serialize(() => { db.run(`DELETE FROM ${tableName} WHERE username = '${username}'`, (err, user) => { if (err) reject(new Error(ErrorType.TECHNICAL_UNKNOWN)) else resolve(user) }) }) closeDB(db) }) } async insert() { this.password_ = await hashPassword(this.password); await this.write_(); } async update() { if (this.isModifiedPassword_) { this.password_ = await hashPassword(this.password); } await this.write_(); } write_() { return new Promise((resolve, reject) => { const values = `'${this.username}', '${this.password}'`; const db = openDB(); db.serialize(() => { db.run(`INSERT OR REPLACE INTO ${tableName} (username, password) VALUES (${values})`, err => { if (err) reject(new Error(ErrorType.TECHNICAL_UNKNOWN)) else resolve() }) }) closeDB(db) }) } comparePassword(candidatePassword) { return bcrypt.compare(candidatePassword, this.password); } toJson() { return { username: this.username } } get password() { return this.password_ } set password(newPassword) { this.password_ = newPassword this.isModifiedPassword_ = true this.activated = true } } export default User function openDB() { const env = process.env.NODE_ENV || 'development' return new sqlite3.Database(serverConfig.database[env].path, err => { if (err) throw new Error(err) }) } function closeDB(db) { db.close(err => { if (err) throw new Error(err) }) } function createUserFromDB(dbUser) { return new User({ username: dbUser.username, password: dbUser.password }) } async function hashPassword(password) { const salt = await bcrypt.genSalt(10) return bcrypt.hash(password, salt) }