diff --git a/src/services/index.ts b/src/services/index.ts new file mode 100644 index 0000000..b5091d2 --- /dev/null +++ b/src/services/index.ts @@ -0,0 +1,2 @@ +export * from './jwt.service'; +export * from './mysql.service' \ No newline at end of file diff --git a/src/services/mysql.service.ts b/src/services/mysql.service.ts new file mode 100644 index 0000000..1f5de52 --- /dev/null +++ b/src/services/mysql.service.ts @@ -0,0 +1,234 @@ +import mysql, {type Connection, type ConnectionOptions} from 'mysql2'; +import {Logger} from "tslog"; +// biome-ignore lint/style/useImportType: +import DbUserData from "@interfaces/UserData"; + + +const access: ConnectionOptions = { + host: `${process.env["MYSQL_HOST"]}`, + port: Number.parseInt(`${process.env["MYSQL_PORT"]}`), + user: `${process.env["MYSQL_USER"]}`, + database: `${process.env["MYSQL_USER"]}`, + password: `${process.env["MYSQL_PASS"]}` +}; + + +class MySqlHandler { + private readonly handlerName: string; + private Logger: Logger + private Connection: Connection; + + constructor(handlerName?: string) { + this.handlerName = handlerName || 'Unknown'; + this.Logger = new Logger({ name: `DB>> ${this.handlerName}` }); + this.Connection = mysql.createConnection(access); + this.Connection.connect((err) => { + if (err) { + this.Logger.error(`Error connecting to MySQL: ${err}`); + throw new Error() + } + this.Logger.info(`Connected to MySQL database (${access.database})`); + }); + } + closeConnection() { + this.Connection.end(); + }; + + query(queryString: string) { + return new Promise((resolve, reject) => { + this.Connection.query(queryString, (err, results) => { + if (err) { + this.Logger.error(`Error executing query: ${err}`); + reject(err); + } else { + resolve(results); + } + }); + }); + } + + execute(queryString: string, values: Array): Promise { + return new Promise((resolve, reject) => { + this.Connection.execute(queryString, values, (err: mysql.QueryError | null, results: mysql.QueryResult) => { + if (err) { + this.Logger.error(`Error executing query: ${err}`); + reject(err); + } else { + resolve(results); + } + }); + }); + } + + /** + * Unprepare a previously prepared SQL query. + * + * @param {string} queryString + * - The SQL query string to unprepare. + * @return {Promise} + * - A promise that resolves if the unprepare operation is successful, + * or rejects with an error if there was an error unpreparing the query. + */ + unprepare(queryString: string): Promise { + return new Promise((resolve, reject) => { + try { + resolve(this.Connection.unprepare(queryString)); + } catch (err) { + reject(err) + } + }); + } +} + +const MySqlService = { + Handler : MySqlHandler, + User: { + insert(handler: MySqlHandler, userData: DbUserData) { + return new Promise((resolve, reject) => { + const _now = new Date() + const _sql = "INSERT INTO `users`(`username`, `displayName`, `firstName`, `lastName`, `email`, `passwordHash`, `isAdmin`, `isDisabled`, `dob`, `gdpr`, `iat`, `uat`) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" + const _values = [ + userData.username, + userData.displayName, + userData.firstName, + userData.lastName, + userData.email, + userData.passwordHash, + userData.isAdmin, + userData.isDisabled, + userData.dob, + userData.gdpr, + _now, + _now + ] + try { + resolve(handler.execute(_sql, _values)) + } catch (err: unknown) { + reject(err as Error); + } + }) + }, + + update(handler: MySqlHandler, userData: DbUserData) { + return new Promise((resolve, reject) => { + + //@ts-ignore + const _t = ` + ${userData.username ? "`username` = ?," : null} + ${userData.displayName ? "`displayName` = ?," : null} + ${userData.firstName ? "`firstName` = ?," : null}` + + + + + const __sql = "UPDATE `users` SET `lastName` = ?, `email` = ?, `passwordHash` = ?, `isAdmin` = ?, `isDisabled` = ?, `dob` = ?, `gdpr` = ? WHERE `id` = ?"; + const __values = [ + userData.username, + userData.displayName, + userData.firstName, + userData.lastName, + userData.email, + userData.passwordHash, + userData.isAdmin, + userData.isDisabled, + userData.dob, + userData.gdpr + ]; + try { + resolve(handler.execute(__sql, __values)); + } catch (err: unknown) { + reject(err as Error); + } + }); + }, + + getById(handler: MySqlHandler, userId: string): Promise { + return new Promise((resolve, reject) => { + const _sql = "SELECT * FROM `users` WHERE `id` = ?"; + const _values = [userId]; + try { + resolve(handler.execute(_sql, _values) as unknown as DbUserData); + } catch (err: unknown) { + reject(err as Error); + } + }); + }, + + getAll(handler: MySqlHandler): Promise> { + return new Promise((resolve, reject) => { + const _sql = "SELECT * FROM `users`"; + try { + return resolve(handler.query(_sql) as unknown as Array); + } catch (err: unknown) { + return reject(); + } + }); + }, + + getByUsername(handler: MySqlHandler, username: string) { + return new Promise((resolve, reject) => { + const _sql = "SELECT * FROM `users` WHERE `username` = ?"; + const _values = [username]; + try { + resolve(handler.execute(_sql, _values)); + } catch (err: unknown) { + reject(err as Error); + } + }); + }, + + getByEmail(handler: MySqlHandler, email: string) { + return new Promise((resolve, reject) => { + const _sql = "SELECT * FROM `users` WHERE `email` = ?"; + const _values = [email]; + try { + resolve(handler.execute(_sql, _values)); + } catch (err: unknown) { + reject(err as Error); + } + }); + }, + + getByDisplayName(handler: MySqlHandler, displayName: string) { + return new Promise((resolve, reject) => { + const _sql = "SELECT * FROM `users` WHERE `displayName` = ?"; + const _values = [displayName]; + try { + resolve(handler.execute(_sql, _values)); + } catch (err: unknown) { + reject(err as Error); + } + }); + }, + + getAdminStateForId(handler: MySqlHandler, userId: string) : Promise { + return new Promise((resolve, reject) => { + const _sql = "SELECT `isAdmin` FROM `users` WHERE `id` = ?"; + const _values = [userId]; + try { + const isAdmin = handler.execute(_sql, _values) + isAdmin.then((result) => { + if (result !== true) return resolve(false); + return resolve(true) + }); + } catch (err: unknown) { + reject(err as Error); + } + }); + }, + + delete(handler: MySqlHandler, userId: string) { + return new Promise((resolve, reject) => { + const _sql = "DELETE FROM `users` WHERE `id` = ?"; + const _values = [userId]; + try { + resolve(handler.execute(_sql, _values)); + } catch (err: unknown) { + reject(err as Error); + } + }); + } + }, +} + +export default MySqlService \ No newline at end of file