Yggdrasil/repositories/authRepository.js
azures04 4975f7e191 Add static registration page and static file serving
Added a new registration HTML page under data/static/register.html and introduced a static file serving route in routes/static.js. Minor adjustments were made to authRepository.js and userRepository.js to update module imports. This enables serving static assets and provides a registration UI.
2026-01-19 02:47:55 +01:00

190 lines
6.0 KiB
JavaScript

const bcrypt = require("bcryptjs")
const database = require("../modules/database")
const utils = require("../modules/utils")
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
}