mirror of
https://github.com/matt-fidd/stratos.git
synced 2026-01-01 19:59:27 +00:00
181 lines
3.3 KiB
JavaScript
181 lines
3.3 KiB
JavaScript
'use strict';
|
|
|
|
const bcrypt = require('bcrypt');
|
|
const crypto = require('crypto');
|
|
|
|
const DatabaseConnectionPool = require('./DatabaseConnectionPool');
|
|
const PasswordReset = require('./PasswordReset');
|
|
|
|
class User {
|
|
id;
|
|
firstName;
|
|
otherNames;
|
|
lastName;
|
|
email;
|
|
#password;
|
|
type = null;
|
|
|
|
constructor(type, userId) {
|
|
type = type ?? false;
|
|
|
|
let types = [];
|
|
let knownType = false;
|
|
if (type) {
|
|
types.push(type);
|
|
knownType = true;
|
|
} else {
|
|
types = [ 'account', 'student', 'parent' ];
|
|
}
|
|
|
|
return (async () => {
|
|
for (const type of types) {
|
|
const sql = `
|
|
select
|
|
email,
|
|
firstName,
|
|
otherNames,
|
|
lastName,
|
|
password,
|
|
${type}Id as id
|
|
from ${type}
|
|
where
|
|
${type}Id = ?;
|
|
`;
|
|
|
|
const conn = await new DatabaseConnectionPool();
|
|
const res =
|
|
await conn.runQuery(sql, [ userId ]);
|
|
|
|
if (!res.length)
|
|
continue;
|
|
|
|
const record = res[0];
|
|
|
|
for (const [ k, v ] of Object.entries(record))
|
|
this[k] = v;
|
|
|
|
this.type = type;
|
|
|
|
if (knownType)
|
|
return this;
|
|
|
|
const className =
|
|
`${type.substring(0, 1).toUpperCase()}`
|
|
+ `${type.substring(1)}`;
|
|
|
|
return new (require(`./${className}`))(this.id);
|
|
}
|
|
})();
|
|
}
|
|
|
|
get fullName() {
|
|
let name = `${this.firstName} `;
|
|
|
|
if (this?.otherNames?.length > 0)
|
|
name += `${this.otherNames} `;
|
|
|
|
name += this.lastName;
|
|
|
|
return name;
|
|
}
|
|
|
|
async verifyPassword(password) {
|
|
return await bcrypt.compare(password, this.password);
|
|
}
|
|
|
|
async changePassword(password) {
|
|
const newPassword = await User.hashPassword(password);
|
|
|
|
const conn = await new DatabaseConnectionPool();
|
|
|
|
const sql = `
|
|
update ${this.type}
|
|
set password = ?
|
|
where ${this.type}Id = ?;
|
|
`;
|
|
|
|
await conn.runQuery(sql, [ newPassword, this.id ]);
|
|
}
|
|
|
|
generatePasswordReset() {
|
|
return PasswordReset.generatePasswordReset(this.id);
|
|
}
|
|
|
|
login(req) {
|
|
req.session.authenticated = true;
|
|
req.session.userId = this.id;
|
|
req.session.userType = this.type;
|
|
req.session.fullName = `${this.firstName} ${this.lastName}`;
|
|
}
|
|
|
|
static async hashPassword(password) {
|
|
return await bcrypt.hash(password, 10);
|
|
}
|
|
|
|
static async createUser(type, fname, oname, lname, email, password) {
|
|
const conn = await new DatabaseConnectionPool();
|
|
|
|
const uuid = crypto.randomUUID();
|
|
const hashedPassword = await User.hashPassword(password);
|
|
|
|
const sql = `
|
|
insert into ${type} (
|
|
${type}Id,
|
|
email,
|
|
firstName,
|
|
otherNames,
|
|
lastName,
|
|
password)
|
|
VALUES (?, ?, ?, ?, ?, ?);
|
|
`;
|
|
|
|
await conn.runQuery(sql, [
|
|
uuid,
|
|
email,
|
|
fname,
|
|
oname,
|
|
lname,
|
|
hashedPassword
|
|
]);
|
|
|
|
let res;
|
|
switch (type) {
|
|
case 'account':
|
|
res = new (require('./Account'))(uuid);
|
|
break;
|
|
default:
|
|
throw new Error(
|
|
`Cannot create user of type ${type}`);
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static async getUserByEmail(email) {
|
|
const conn = await new DatabaseConnectionPool();
|
|
const types = [ 'account', 'student', 'parent' ];
|
|
|
|
for (const type of types) {
|
|
const sql = `
|
|
select ${type}id as id
|
|
from ${type}
|
|
where email = ?;
|
|
`;
|
|
|
|
const id = (await conn.runQuery(sql, [
|
|
email
|
|
]))?.[0]?.['id'];
|
|
|
|
if (typeof id !== 'undefined') {
|
|
const className =
|
|
`${type.substring(0, 1).toUpperCase()}`
|
|
+ `${type.substring(1)}`;
|
|
return new (require(`./${className}`))(id);
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
module.exports = User;
|