Yggdrasil/repositories/authRepository.js
azures04 71627c7041 Centralize and standardize database error handling
Introduced a new handleDBError utility in modules/utils.js to centralize database error logging and throwing. Refactored all repositories to use this utility, replacing repetitive error handling and logger calls with a single function call for improved maintainability and consistency.
2026-01-18 18:04:10 +01:00

189 lines
6.0 KiB
JavaScript

const bcrypt = require("bcryptjs")
const database = require("../modules/database")
const { DefaultError } = require("../errors/errors")
async function getUser(identifier, requirePassword = false) {
try {
const sql = `SELECT * FROM players WHERE uuid = ? OR email = ? OR username = ?`
const rows = await database.query(sql, [identifier, identifier, identifier])
const user = rows[0]
if (!user) {
throw new DefaultError(404, "User not found")
}
delete user.email
if (!requirePassword) {
delete user.password
}
return { code: 200, user }
} catch (error) {
return utils.handleDBError(error)
}
}
async function register(email, username, password) {
try {
const sql = `INSERT INTO players (email, username, password, uuid) VALUES (?, ?, ?, ?)`
const uuid = crypto.randomUUID()
const hashedPassword = await bcrypt.hash(password, 10)
const result = await database.query(sql, [email, username, hashedPassword, uuid])
if (result.affectedRows > 0) {
return { code: 200, email, username, uuid }
} else {
throw new DefaultError(500, "Please contact an administrator.", "InternalServerError")
}
} catch (error) {
return utils.handleDBError(error)
}
}
async function insertClientSession(accessToken, clientToken, uuid) {
try {
const sql = `INSERT INTO clientSessions (accessToken, clientToken, uuid) VALUES (?, ?, ?)`
const result = await database.query(sql, [accessToken, clientToken, uuid])
if (result.affectedRows > 0) {
return { code: 204, accessToken, clientToken }
} else {
throw new DefaultError(500, "Please contact an administrator.", "InternalServerError")
}
} catch (error) {
return utils.handleDBError(error)
}
}
async function getPlayerProperties(uuid) {
try {
const sql = `SELECT * FROM playersProperties WHERE uuid = ?`
const properties = await database.query(sql, [uuid])
if (properties.length === 0) {
throw new DefaultError(404, "Properties not found for this user.", "InternalServerError")
}
return { code: 200, properties: properties.map(property => { return { name: property.name, value: property.value } }) }
} catch (error) {
return utils.handleDBError(error)
}
}
async function getClientSession(accessToken, clientToken) {
try {
const sql = `SELECT * FROM clientSessions WHERE accessToken = ? AND clientToken = ?`
const rows = await database.query(sql, [accessToken, clientToken])
const session = rows[0]
if (session) {
return {
code: 200,
session: session
}
} else {
throw new DefaultError(404, "Client session not found")
}
} catch (error) {
return utils.handleDBError(error)
}
}
async function validateClientSession(accessToken, clientToken) {
try {
const sql = `SELECT * FROM clientSessions WHERE accessToken = ? AND clientToken = ?`
const rows = await database.query(sql, [accessToken, clientToken])
const session = rows[0]
if (session) {
return {
code: 200,
message: "Client session valid."
}
} else {
throw new DefaultError(404, "Client session not found for this accessToken/clientToken combination.")
}
} catch (error) {
return utils.handleDBError(error)
}
}
async function validateClientSessionWithoutClientToken(accessToken) {
try {
const sql = `SELECT * FROM clientSessions WHERE accessToken = ?`
const rows = await database.query(sql, [accessToken])
const session = rows[0]
if (session) {
return {
code: 200,
message: "Client session valid."
}
} else {
throw new DefaultError(404, "Client session not found for this accessToken.")
}
} catch (error) {
return utils.handleDBError(error)
}
}
async function invalidateClientSession(accessToken, clientToken) {
try {
const sql = `DELETE FROM clientSessions WHERE accessToken = ? AND clientToken = ?`
const result = await database.query(sql, [accessToken, clientToken])
if (result.affectedRows > 0) {
return {
code: 200,
message: "Client session successfully invalidated."
}
} else {
throw new DefaultError(404, "Client session not found for this accessToken/clientToken combination.")
}
} catch (error) {
return utils.handleDBError(error)
}
}
async function revokeAccessTokens(uuid) {
try {
const sql = `DELETE FROM clientSessions WHERE uuid = ?`
const result = await database.query(sql, [uuid])
if (result.affectedRows > 0) {
return {
code: 200,
message: "Access tokens successfully revoked."
}
} else {
throw new DefaultError(404, "No access token found for this user.")
}
} catch (error) {
return utils.handleDBError(error)
}
}
async function getUsernamesRules() {
try {
const rows = await database.query("SELECT rule, type FROM usernameRules")
return rows.map(row => {
if (row.type === 1) {
return { type: "regex", pattern: new RegExp(row.rule, "i") }
} else {
return { type: "literal", value: row.rule.toLowerCase() }
}
})
} catch (err) {
throw err
}
}
module.exports = {
getUser,
register,
getClientSession,
getUsernamesRules,
revokeAccessTokens,
insertClientSession,
getPlayerProperties,
validateClientSession,
invalidateClientSession,
validateClientSessionWithoutClientToken
}