Initial project structure and core files
Add base project files including environment example, license, README, .gitignore, error classes, ESLint config, database modules, texture assets, repositories, routes, schemas, services, and server entry point. This establishes the foundational structure for a Yggdrasil-compatible REST API with modular error handling, database setup, and route organization.
This commit is contained in:
131
repositories/adminRepository.js
Normal file
131
repositories/adminRepository.js
Normal file
@@ -0,0 +1,131 @@
|
||||
const logger = require("../modules/logger")
|
||||
const database = require("../modules/database")
|
||||
const { DefaultError } = require("../errors/errors")
|
||||
|
||||
async function getAdminById(id) {
|
||||
try {
|
||||
const sql = "SELECT id, username, createdAt FROM api_administrators WHERE id = ?"
|
||||
const rows = await database.query(sql, [id])
|
||||
return rows[0] || null
|
||||
} catch (error) {
|
||||
logger.log("Internal Server Error".bold + " : " + error.toString(), ["MariaDB", "yellow"])
|
||||
throw new DefaultError(500, "Internal Server Error", "Database Error")
|
||||
}
|
||||
}
|
||||
|
||||
async function createAdmin(username, hashedPassword) {
|
||||
try {
|
||||
const sql = "INSERT INTO api_administrators (username, password) VALUES (?, ?)"
|
||||
const result = await database.query(sql, [username, hashedPassword])
|
||||
|
||||
if (result.affectedRows > 0) {
|
||||
return { code: 200, id: result.insertId, username }
|
||||
} else {
|
||||
throw new DefaultError(500, "Failed to create administrator.")
|
||||
}
|
||||
} catch (error) {
|
||||
if (error.code === "ER_DUP_ENTRY") {
|
||||
throw new DefaultError(409, "Administrator username already exists.")
|
||||
}
|
||||
logger.log("Internal Server Error".bold + " : " + error.toString(), ["MariaDB", "yellow"])
|
||||
throw new DefaultError(500, "Internal Server Error", "Database Error")
|
||||
}
|
||||
}
|
||||
|
||||
async function hasPermission(adminId, permissionKey) {
|
||||
try {
|
||||
const sql = `
|
||||
SELECT COUNT(*) as count
|
||||
FROM api_administrators_permissions
|
||||
WHERE administrator_id = ? AND permission_key = ?
|
||||
`
|
||||
const rows = await database.query(sql, [adminId, permissionKey])
|
||||
return rows[0].count === 1
|
||||
} catch (error) {
|
||||
logger.log("Internal Server Error".bold + " : " + error.toString(), ["MariaDB", "yellow"])
|
||||
throw new DefaultError(500, "Internal Server Error", "Database Error")
|
||||
}
|
||||
}
|
||||
|
||||
async function assignPermission(adminId, permissionKey) {
|
||||
try {
|
||||
const sql = "INSERT INTO api_administrators_permissions (administrator_id, permission_key) VALUES (?, ?)"
|
||||
const result = await database.query(sql, [adminId, permissionKey])
|
||||
|
||||
return result.affectedRows > 0
|
||||
} catch (error) {
|
||||
if (error.code === "ER_DUP_ENTRY") return true
|
||||
logger.log("Internal Server Error".bold + " : " + error.toString(), ["MariaDB", "yellow"])
|
||||
throw new DefaultError(500, "Internal Server Error", "Database Error")
|
||||
}
|
||||
}
|
||||
|
||||
async function revokePermission(adminId, permissionKey) {
|
||||
try {
|
||||
const sql = "DELETE FROM api_administrators_permissions WHERE administrator_id = ? AND permission_key = ?"
|
||||
const result = await database.query(sql, [adminId, permissionKey])
|
||||
|
||||
return result.affectedRows > 0
|
||||
} catch (error) {
|
||||
logger.log("Internal Server Error".bold + " : " + error.toString(), ["MariaDB", "yellow"])
|
||||
throw new DefaultError(500, "Internal Server Error", "Database Error")
|
||||
}
|
||||
}
|
||||
|
||||
async function getAdminPermissions(adminId) {
|
||||
try {
|
||||
const sql = `
|
||||
SELECT permission_key
|
||||
FROM api_administrators_permissions
|
||||
WHERE administrator_id = ?
|
||||
`
|
||||
const rows = await database.query(sql, [adminId])
|
||||
return rows.map(r => r.permission_key)
|
||||
} catch (error) {
|
||||
logger.log("Internal Server Error".bold + " : " + error.toString(), ["MariaDB", "yellow"])
|
||||
throw new DefaultError(500, "Internal Server Error", "Database Error")
|
||||
}
|
||||
}
|
||||
|
||||
async function updateAdminPassword(adminId, newHashedPassword) {
|
||||
try {
|
||||
const sql = "UPDATE api_administrators SET password = ? WHERE id = ?"
|
||||
const result = await database.query(sql, [newHashedPassword, adminId])
|
||||
|
||||
if (result.affectedRows > 0) {
|
||||
return {
|
||||
code: 200,
|
||||
message: "Password updated successfully."
|
||||
}
|
||||
} else {
|
||||
throw new DefaultError(404, "Administrator not found.")
|
||||
}
|
||||
} catch (error) {
|
||||
if (error instanceof DefaultError) throw error
|
||||
logger.log("Internal Server Error".bold + " : " + error.toString(), ["MariaDB", "yellow"])
|
||||
throw new DefaultError(500, "Internal Server Error", "Database Error")
|
||||
}
|
||||
}
|
||||
|
||||
async function getAdminByUsername(username) {
|
||||
try {
|
||||
const sql = "SELECT id, username, password, createdAt FROM api_administrators WHERE username = ?"
|
||||
const rows = await database.query(sql, [username])
|
||||
|
||||
return rows[0] || null
|
||||
} catch (error) {
|
||||
logger.log("Internal Server Error".bold + " : " + error.toString(), ["MariaDB", "yellow"])
|
||||
throw new DefaultError(500, "Internal Server Error", "Database Error")
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
createAdmin,
|
||||
getAdminById,
|
||||
hasPermission,
|
||||
assignPermission,
|
||||
revokePermission,
|
||||
getAdminByUsername,
|
||||
getAdminPermissions,
|
||||
updateAdminPassword
|
||||
}
|
||||
208
repositories/authRepository.js
Normal file
208
repositories/authRepository.js
Normal file
@@ -0,0 +1,208 @@
|
||||
const logger = require("../modules/logger")
|
||||
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) {
|
||||
if (error instanceof DefaultError) throw error
|
||||
logger.log("Internal Server Error".bold + " : " + error.toString(), ["MariaDB", "yellow"])
|
||||
throw new DefaultError(500, "Internal Server Error", "Please contact an administrator.")
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
if (error instanceof DefaultError) throw error
|
||||
|
||||
logger.log("Internal Server Error".bold + " : " + error.toString(), ["MariaDB", "yellow"])
|
||||
console.log(error)
|
||||
throw new DefaultError(500, "Please contact an administrator.", "InternalServerError")
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
logger.log("Internal Server Error".bold + " : " + error.toString(), ["MariaDB", "yellow"])
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
if (error instanceof DefaultError) throw error
|
||||
logger.log("Internal Server Error".bold + " : " + error.toString(), ["MariaDB", "yellow"])
|
||||
throw new DefaultError(500, "Please contact an administrator.", "InternalServerError")
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
if (error instanceof DefaultError) throw error
|
||||
logger.log("Internal Server Error".bold + " : " + error.toString(), ["MariaDB", "yellow"])
|
||||
throw new DefaultError(500, "Please contact an administrator.", "InternalServerError")
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
if (error instanceof DefaultError) throw error
|
||||
logger.log("Internal Server Error".bold + " : " + error.toString(), ["MariaDB", "yellow"])
|
||||
throw new DefaultError(500, "Please contact an administrator.", "InternalServerError")
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
if (error instanceof DefaultError) throw error
|
||||
logger.log("Internal Server Error".bold + " : " + error.toString(), ["MariaDB", "yellow"])
|
||||
throw new DefaultError(500, "Please contact an administrator.", "InternalServerError")
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
if (error instanceof DefaultError) throw error
|
||||
logger.log("Internal Server Error".bold + " : " + error.toString(), ["MariaDB", "yellow"])
|
||||
throw new DefaultError(500, "Please contact an administrator.", "InternalServerError")
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
if (error instanceof DefaultError) throw error
|
||||
logger.log("Internal Server Error".bold + " : " + error.toString(), ["MariaDB", "yellow"])
|
||||
throw new DefaultError(500, "Please contact an administrator.", "InternalServerError")
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
174
repositories/sessionsRepository.js
Normal file
174
repositories/sessionsRepository.js
Normal file
@@ -0,0 +1,174 @@
|
||||
const logger = require("../modules/logger")
|
||||
const database = require("../modules/database")
|
||||
const { DefaultError } = require("../errors/errors")
|
||||
|
||||
async function insertLegacyClientSessions(sessionId, uuid) {
|
||||
try {
|
||||
await database.query(`DELETE FROM legacyClientSessions WHERE uuid = ?`, [uuid])
|
||||
|
||||
const sql = `INSERT INTO legacyClientSessions (sessionId, uuid) VALUES (?, ?)`
|
||||
const result = await database.query(sql, [sessionId, uuid])
|
||||
|
||||
if (result.affectedRows > 0) {
|
||||
return { code: 200, sessionId, uuid }
|
||||
} else {
|
||||
throw new DefaultError(500, "Internal Server Error", "Unknown DB Error")
|
||||
}
|
||||
} catch (error) {
|
||||
if (error instanceof DefaultError) throw error
|
||||
logger.log("Internal Server Error".bold + " : " + error.toString(), ["MariaDB", "yellow"])
|
||||
throw new DefaultError(500, "Internal Server Error", "Please contact an administrator.")
|
||||
}
|
||||
}
|
||||
|
||||
async function validateLegacyClientSession(sessionId, uuid) {
|
||||
try {
|
||||
const sql = `SELECT * FROM legacyClientSessions WHERE sessionId = ? AND uuid = ?`
|
||||
const rows = await database.query(sql, [sessionId, uuid])
|
||||
|
||||
const session = rows[0]
|
||||
if (session) {
|
||||
return {
|
||||
code: 200,
|
||||
message: "Client session valid."
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
code: 404,
|
||||
message: "Client session not found for this accessToken/clientToken combination"
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
logger.log("Internal Server Error".bold + " : " + error.toString(), ["MariaDB", "yellow"])
|
||||
throw new DefaultError(500, "Internal Server Error", "Please contact an administrator.")
|
||||
}
|
||||
}
|
||||
|
||||
async function getBlockedServers() {
|
||||
try {
|
||||
const sql = `SELECT * FROM blockedServers`
|
||||
const blockedServers = await database.query(sql)
|
||||
|
||||
return {
|
||||
code: 200,
|
||||
blockedServers: blockedServers.map(bannedServer => ({ sha1: bannedServer.hashedIp }))
|
||||
}
|
||||
} catch (error) {
|
||||
logger.log("Internal Server Error".bold + " : " + error.toString(), ["MariaDB", "yellow"])
|
||||
throw new DefaultError(500, "Internal Server Error", "Please contact an administrator.")
|
||||
}
|
||||
}
|
||||
|
||||
async function getActiveSkin(uuid) {
|
||||
try {
|
||||
const sql = `
|
||||
SELECT t.url, ps.variant
|
||||
FROM playersSkins ps
|
||||
JOIN textures t ON ps.assetHash = t.hash
|
||||
WHERE ps.playerUuid = ? AND ps.isSelected = 1
|
||||
`
|
||||
const rows = await database.query(sql, [uuid])
|
||||
const skin = rows[0]
|
||||
if (!skin) {
|
||||
throw new DefaultError(404, "Not found", "Not found")
|
||||
}
|
||||
return { code: 200, data: skin || null }
|
||||
} catch (error) {
|
||||
if (error instanceof DefaultError) {
|
||||
throw error
|
||||
}
|
||||
logger.log("Internal Server Error".bold + " : " + error.toString(), ["MariaDB", "yellow"])
|
||||
throw new DefaultError(500, "Internal Server Error", "Please contact an administrator.")
|
||||
}
|
||||
}
|
||||
|
||||
async function getActiveCape(uuid) {
|
||||
try {
|
||||
const sql = `
|
||||
SELECT t.url
|
||||
FROM playersCapes pc
|
||||
JOIN textures t ON pc.assetHash = t.hash
|
||||
WHERE pc.playerUuid = ? AND pc.isSelected = 1
|
||||
`
|
||||
const rows = await database.query(sql, [uuid])
|
||||
const cape = rows[0]
|
||||
if (!cape) {
|
||||
throw new DefaultError(404, "Not found", "Not found")
|
||||
}
|
||||
return { code: 200, data: cape || null }
|
||||
} catch (error) {
|
||||
if (error instanceof DefaultError) {
|
||||
throw error
|
||||
}
|
||||
logger.log("Internal Server Error".bold + " : " + error.toString(), ["MariaDB", "yellow"])
|
||||
throw new DefaultError(500, "Internal Server Error", "Please contact an administrator.")
|
||||
}
|
||||
}
|
||||
|
||||
async function getProfileActionsList(uuid) {
|
||||
try {
|
||||
const cleanUuid = uuid.replace(/-/g, "")
|
||||
const sql = "SELECT action FROM playerProfileActions WHERE uuid = ?"
|
||||
const rows = await database.query(sql, [cleanUuid])
|
||||
|
||||
const actions = rows.map(row => row.action)
|
||||
|
||||
return { code: 200, data: actions }
|
||||
} catch (error) {
|
||||
logger.log("Internal Server Error".bold + " : " + error.toString(), ["MariaDB", "yellow"])
|
||||
throw new DefaultError(500, "Internal Server Error", "Please contact an administrator.")
|
||||
}
|
||||
}
|
||||
|
||||
async function saveServerSession(uuid, accessToken, serverId, ip) {
|
||||
try {
|
||||
const sql = `
|
||||
INSERT INTO serverSessions (uuid, accessToken, serverId, ip, createdAt)
|
||||
VALUES (?, ?, ?, ?, CURRENT_TIMESTAMP)
|
||||
ON DUPLICATE KEY UPDATE
|
||||
accessToken = VALUES(accessToken),
|
||||
serverId = VALUES(serverId),
|
||||
ip = VALUES(ip),
|
||||
createdAt = CURRENT_TIMESTAMP
|
||||
`
|
||||
const result = await database.query(sql, [uuid, accessToken, serverId, ip])
|
||||
|
||||
return { code: 200, success: result.affectedRows > 0 }
|
||||
} catch (error) {
|
||||
logger.log("Internal Server Error".bold + " : " + error.toString(), ["MariaDB", "yellow"])
|
||||
throw new DefaultError(500, "Internal Server Error", "Please contact an administrator.")
|
||||
}
|
||||
}
|
||||
|
||||
async function getServerSession(uuid, serverId) {
|
||||
try {
|
||||
const sql = `
|
||||
SELECT ip
|
||||
FROM serverSessions
|
||||
WHERE uuid = ? AND serverId = ?
|
||||
AND createdAt > (NOW() - INTERVAL 30 SECOND)
|
||||
`
|
||||
const rows = await database.query(sql, [uuid, serverId])
|
||||
const session = rows[0]
|
||||
|
||||
if (!session) {
|
||||
return { code: 404, valid: false }
|
||||
}
|
||||
|
||||
return { code: 200, valid: true, ip: session.ip }
|
||||
} catch (error) {
|
||||
logger.log("Internal Server Error".bold + " : " + error.toString(), ["MariaDB", "yellow"])
|
||||
throw new DefaultError(500, "Internal Server Error", "Please contact an administrator.")
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
insertLegacyClientSessions,
|
||||
validateLegacyClientSession,
|
||||
getBlockedServers,
|
||||
getActiveSkin,
|
||||
getActiveCape,
|
||||
getProfileActionsList,
|
||||
saveServerSession,
|
||||
getServerSession
|
||||
}
|
||||
774
repositories/userRepository.js
Normal file
774
repositories/userRepository.js
Normal file
@@ -0,0 +1,774 @@
|
||||
const crypto = require("node:crypto")
|
||||
const logger = require("../modules/logger")
|
||||
const database = require("../modules/database")
|
||||
const { DefaultError } = require("../errors/errors")
|
||||
|
||||
async function addPropertyToPlayer(key, value, uuid) {
|
||||
try {
|
||||
const sql = `
|
||||
INSERT INTO playersProperties (name, value, uuid)
|
||||
VALUES (?, ?, ?)
|
||||
ON DUPLICATE KEY UPDATE value = VALUES(value)
|
||||
`
|
||||
const result = await database.query(sql, [key, value, uuid])
|
||||
|
||||
if (result.affectedRows > 0) {
|
||||
return { code: 200, key, value, uuid }
|
||||
} else {
|
||||
throw new DefaultError(500, "Please contact an administrator.", "InternalServerError")
|
||||
}
|
||||
} catch (error) {
|
||||
logger.log("Internal Server Error".bold + " : " + error.toString(), ["MariaDB", "yellow"])
|
||||
throw new DefaultError(500, "Please contact an administrator.", "InternalServerError")
|
||||
}
|
||||
}
|
||||
|
||||
async function deletePropertyToPlayer(key, uuid) {
|
||||
try {
|
||||
const sql = `DELETE FROM playersProperties WHERE name = ? AND uuid = ?`
|
||||
const result = await database.query(sql, [key, uuid])
|
||||
|
||||
if (result.affectedRows > 0) {
|
||||
return { code: 200, key, uuid }
|
||||
} else {
|
||||
throw new DefaultError(500, "Property not found for this user/key combination.")
|
||||
}
|
||||
} catch (error) {
|
||||
if (error instanceof DefaultError) throw error
|
||||
logger.log("Internal Server Error".bold + " : " + error.toString(), ["MariaDB", "yellow"])
|
||||
throw new DefaultError(500, "Please contact an administrator.", "InternalServerError")
|
||||
}
|
||||
}
|
||||
|
||||
async function updatePropertyToPlayer(key, value, uuid) {
|
||||
try {
|
||||
const sql = `UPDATE playersProperties SET value = ? WHERE name = ? AND uuid = ?`
|
||||
const result = await database.query(sql, [value, key, uuid])
|
||||
if (result.affectedRows > 0) {
|
||||
return { code: 200, key, value, uuid }
|
||||
} else {
|
||||
throw new DefaultError(404, "Property not found for this user/key combination")
|
||||
}
|
||||
} catch (error) {
|
||||
if (error instanceof DefaultError) throw error
|
||||
logger.log("Internal Server Error".bold + " : " + error.toString(), ["MariaDB", "yellow"])
|
||||
throw new DefaultError(500, "Please contact an administrator.", "InternalServerError")
|
||||
}
|
||||
}
|
||||
|
||||
async function getPlayerProperties(uuid) {
|
||||
try {
|
||||
const sql = `SELECT * FROM playersProperties WHERE uuid = ?`
|
||||
const rows = await database.query(sql, [uuid])
|
||||
if (rows.length === 0) {
|
||||
throw new DefaultError(404, "Properties not found for this user")
|
||||
}
|
||||
return {
|
||||
code: 200,
|
||||
properties: rows.map(property => ({ name: property.name, value: property.value }))
|
||||
}
|
||||
} catch (error) {
|
||||
if (error instanceof DefaultError) throw error
|
||||
logger.log("Internal Server Error".bold + " : " + error.toString(), ["MariaDB", "yellow"])
|
||||
throw new DefaultError(500, "Please contact an administrator.", "InternalServerError")
|
||||
}
|
||||
}
|
||||
|
||||
async function getPlayerProperty(key, uuid) {
|
||||
try {
|
||||
const sql = `SELECT * FROM playersProperties WHERE name = ? AND uuid = ?`
|
||||
const rows = await database.query(sql, [key, uuid])
|
||||
const property = rows[0]
|
||||
if (!property) {
|
||||
throw new DefaultError(404, "Property not found for this user/key combination")
|
||||
}
|
||||
return { code: 200, property }
|
||||
} catch (error) {
|
||||
if (error instanceof DefaultError) throw error
|
||||
logger.log("Internal Server Error".bold + " : " + error.toString(), ["MariaDB", "yellow"])
|
||||
throw new DefaultError(500, "Please contact an administrator.", "InternalServerError")
|
||||
}
|
||||
}
|
||||
|
||||
async function getPlayerSettingsSchema() {
|
||||
const RAW_SCHEMA_CACHE = {
|
||||
privileges: {},
|
||||
preferences: {}
|
||||
}
|
||||
try {
|
||||
const privilegesRows = await database.query("DESCRIBE playersPrivileges")
|
||||
const preferencesRows = await database.query("DESCRIBE playersPreferences")
|
||||
RAW_SCHEMA_CACHE.privileges = privilegesRows.map(c => c.Field).filter(n => n !== "uuid")
|
||||
RAW_SCHEMA_CACHE.preferences = preferencesRows.map(c => c.Field).filter(n => n !== "uuid")
|
||||
return RAW_SCHEMA_CACHE
|
||||
} catch (err) {
|
||||
logger.log("Database Schema Error: " + err.toString(), ["MariaDB", "red"])
|
||||
throw new DefaultError(500, "Internal Server Error", "Database Schema Error")
|
||||
}
|
||||
}
|
||||
|
||||
async function updatePlayerPreferences(uuid, updates) {
|
||||
try {
|
||||
const keys = Object.keys(updates)
|
||||
if (keys.length === 0) {
|
||||
throw new DefaultError(400, "No fields provided for update.")
|
||||
}
|
||||
const setClause = keys.map(key => `\`${key}\` = ?`).join(', ')
|
||||
const sql = `UPDATE playersPreferences SET ${setClause} WHERE uuid = ?`
|
||||
const values = keys.map(key => updates[key])
|
||||
values.push(uuid)
|
||||
const result = await database.query(sql, values)
|
||||
if (result.affectedRows > 0) {
|
||||
return {
|
||||
code: 200,
|
||||
message: "Preferences updated successfully."
|
||||
}
|
||||
} else {
|
||||
throw new DefaultError(404, "Player preferences not found or no changes made.")
|
||||
}
|
||||
} catch (error) {
|
||||
if (error instanceof DefaultError) throw error
|
||||
logger.log("Internal Server Error".bold + " : " + error.toString(), ["MariaDB", "yellow"])
|
||||
throw new DefaultError(500, "Please contact an administrator.", "InternalServerError")
|
||||
}
|
||||
}
|
||||
|
||||
async function getPlayerPreferences(uuid) {
|
||||
try {
|
||||
const sql = `SELECT profanityFilter FROM playersPreferences WHERE uuid = ?`
|
||||
const rows = await database.query(sql, [uuid])
|
||||
const data = rows[0]
|
||||
|
||||
if (data) {
|
||||
return {
|
||||
code: 200,
|
||||
message: "Preferences retrieved successfully.",
|
||||
data: data
|
||||
}
|
||||
} else {
|
||||
throw new DefaultError(404, "Preferences not found for this UUID.")
|
||||
}
|
||||
} catch (error) {
|
||||
if (error instanceof DefaultError) throw error
|
||||
logger.log("Internal Server Error".bold + " : " + error.toString(), ["MariaDB", "yellow"])
|
||||
throw new DefaultError(500, "Please contact an administrator.", "InternalServerError")
|
||||
}
|
||||
}
|
||||
|
||||
async function getPlayerPrivileges(uuid) {
|
||||
try {
|
||||
const sql = `
|
||||
SELECT onlineChat, multiplayerServer, multiplayerRealms, telemetry
|
||||
FROM playersPrivileges
|
||||
WHERE uuid = ?
|
||||
`
|
||||
const rows = await database.query(sql, [uuid])
|
||||
const data = rows[0]
|
||||
if (data) {
|
||||
return {
|
||||
code: 200,
|
||||
message: "Privileges retrieved successfully.",
|
||||
data: data
|
||||
}
|
||||
} else {
|
||||
throw new DefaultError(404, "Privileges not found for this UUID.")
|
||||
}
|
||||
} catch (error) {
|
||||
if (error instanceof DefaultError) throw error
|
||||
logger.log("Internal Server Error".bold + " : " + error.toString(), ["MariaDB", "yellow"])
|
||||
throw new DefaultError(500, "Please contact an administrator.", "InternalServerError")
|
||||
}
|
||||
}
|
||||
|
||||
async function updatePlayerPrivileges(uuid, updates) {
|
||||
try {
|
||||
const keys = Object.keys(updates)
|
||||
if (keys.length === 0) {
|
||||
throw new DefaultError(404, "No fields provided for update.")
|
||||
}
|
||||
const setClause = keys.map(key => `\`${key}\` = ?`).join(', ')
|
||||
const sql = `UPDATE playersPrivileges SET ${setClause} WHERE uuid = ?`
|
||||
const values = keys.map(key => updates[key])
|
||||
values.push(uuid)
|
||||
const result = await database.query(sql, values)
|
||||
if (result.affectedRows > 0) {
|
||||
return {
|
||||
code: 200,
|
||||
message: "Privileges updated successfully."
|
||||
}
|
||||
} else {
|
||||
throw new DefaultError(404, "Player privileges not found or no changes made.")
|
||||
}
|
||||
} catch (error) {
|
||||
if (error instanceof DefaultError) throw error
|
||||
logger.log("Internal Server Error".bold + " : " + error.toString(), ["MariaDB", "yellow"])
|
||||
throw new DefaultError(500, "Please contact an administrator.", "InternalServerError")
|
||||
}
|
||||
}
|
||||
|
||||
async function banUser(uuid, { reasonKey, reasonMessage, expires = null }) {
|
||||
try {
|
||||
if (!uuid || !reasonKey) {
|
||||
throw new DefaultError(400, "Missing uuid or reasonKey.")
|
||||
}
|
||||
|
||||
let reasonId
|
||||
const reasonRows = await database.query("SELECT id FROM banReasons WHERE reason_key = ?", [reasonKey])
|
||||
if (reasonRows.length > 0) {
|
||||
reasonId = reasonRows[0].id
|
||||
} else {
|
||||
const insertReason = await database.query("INSERT INTO banReasons (reason_key) VALUES (?)", [reasonKey])
|
||||
reasonId = insertReason.insertId
|
||||
}
|
||||
|
||||
const banId = crypto.randomUUID()
|
||||
const insertSql = `
|
||||
INSERT INTO bans (banId, uuid, reason, reasonMessage, expires)
|
||||
VALUES (?, ?, ?, ?, ?)
|
||||
`
|
||||
const result = await database.query(insertSql, [banId, uuid, reasonId, reasonMessage || "Banned by operator", expires])
|
||||
|
||||
if (result.affectedRows > 0) {
|
||||
return {
|
||||
code: 200,
|
||||
message: "User successfully banned.",
|
||||
banId: banId
|
||||
}
|
||||
} else {
|
||||
throw new DefaultError(500, "Failed to ban user.")
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
if (error instanceof DefaultError) throw error
|
||||
if (error.code === "ER_NO_REFERENCED_ROW_2" || error.toString().includes("foreign key constraint")) {
|
||||
throw new DefaultError(404, "User not found (cannot ban a ghost).")
|
||||
}
|
||||
logger.log("Internal Server Error".bold + " : " + error.toString(), ["MariaDB", "yellow"])
|
||||
throw new DefaultError(500, "Internal Server Error", error.toString())
|
||||
}
|
||||
}
|
||||
|
||||
async function unbanUser(uuid) {
|
||||
try {
|
||||
if (!uuid) {
|
||||
throw new DefaultError(400, "Missing uuid.")
|
||||
}
|
||||
const sql = "DELETE FROM bans WHERE uuid = ?"
|
||||
const result = await database.query(sql, [uuid])
|
||||
if (result.affectedRows > 0) {
|
||||
return {
|
||||
code: 200,
|
||||
message: "User successfully unbanned.",
|
||||
count: result.affectedRows
|
||||
}
|
||||
} else {
|
||||
throw new DefaultError(404, "User was not banned.")
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
if (error instanceof DefaultError) throw error
|
||||
logger.log("Internal Server Error".bold + " : " + error.toString(), ["MariaDB", "yellow"])
|
||||
throw new DefaultError(500, "Please contact an administrator.", "InternalServerError")
|
||||
}
|
||||
}
|
||||
|
||||
async function getPlayerBans(uuid) {
|
||||
try {
|
||||
const sql = `
|
||||
SELECT
|
||||
b.banId,
|
||||
b.expires,
|
||||
b.reasonMessage,
|
||||
r.reason_key as reason
|
||||
FROM bans b
|
||||
JOIN banReasons r ON b.reason = r.id
|
||||
WHERE b.uuid = ?
|
||||
ORDER BY b.expires ASC
|
||||
`
|
||||
const rows = await database.query(sql, [uuid])
|
||||
|
||||
if (rows.length > 0) {
|
||||
return { code: 200, bans: rows }
|
||||
} else {
|
||||
return { code: 204 }
|
||||
}
|
||||
} catch (error) {
|
||||
if (error instanceof DefaultError) throw error
|
||||
logger.log("Internal Server Error".bold + " : " + error.toString(), ["MariaDB", "yellow"])
|
||||
throw new DefaultError(500, "Please contact an administrator.", "InternalServerError")
|
||||
}
|
||||
}
|
||||
|
||||
async function changeUsername(uuid, newName) {
|
||||
try {
|
||||
const sql = "UPDATE players SET username = ? WHERE uuid = ?"
|
||||
const result = await database.query(sql, [newName, uuid])
|
||||
if (result.affectedRows > 0) {
|
||||
return { code: 200, message: "Username changed successfully" }
|
||||
} else {
|
||||
throw new DefaultError(404, "User not found")
|
||||
}
|
||||
} catch (error) {
|
||||
if (error instanceof DefaultError) throw error
|
||||
if (error.code === "ER_DUP_ENTRY" || error.errno === 1062) {
|
||||
throw new DefaultError(409, "Username already taken", "ForbiddenOperationException")
|
||||
}
|
||||
logger.log("Internal Server Error".bold + " : " + error.toString(), ["MariaDB", "yellow"])
|
||||
throw new DefaultError(500, "Internal Server Error", error.toString())
|
||||
}
|
||||
}
|
||||
|
||||
async function createTexture(uuid, hash, type, url, alias) {
|
||||
try {
|
||||
const sql = `
|
||||
INSERT INTO textures (uuid, hash, type, url, alias)
|
||||
VALUES (?, ?, ?, ?, ?)
|
||||
`
|
||||
await database.query(sql, [uuid, hash, type, url, alias])
|
||||
return true
|
||||
} catch (error) {
|
||||
if (error.code === 'ER_DUP_ENTRY') {
|
||||
return false
|
||||
}
|
||||
logger.log("Database Error: " + error.toString(), ["MariaDB", "red"])
|
||||
throw new DefaultError(500, "Internal Server Error", "Database Error")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
async function getTextureByUuid(textureUuid) {
|
||||
try {
|
||||
const sql = "SELECT hash FROM textures WHERE uuid = ?"
|
||||
const rows = await database.query(sql, [textureUuid])
|
||||
return rows[0] || null
|
||||
} catch (error) {
|
||||
logger.log("Internal Server Error".bold + " : " + error.toString(), ["MariaDB", "yellow"])
|
||||
throw new DefaultError(500, "Internal Server Error", "Database Error")
|
||||
}
|
||||
}
|
||||
|
||||
async function getTextureByHash(hash) {
|
||||
try {
|
||||
const sql = "SELECT uuid FROM textures WHERE hash = ?"
|
||||
const rows = await database.query(sql, [hash])
|
||||
return rows[0]
|
||||
} catch (error) {
|
||||
logger.log("Database Error: " + error.toString(), ["MariaDB", "red"])
|
||||
throw new DefaultError(500, "Internal Server Error", "Database Error")
|
||||
}
|
||||
}
|
||||
|
||||
async function resetSkin(uuid, hash, variant) {
|
||||
try {
|
||||
const insertSql = `
|
||||
INSERT IGNORE INTO playersSkins (playerUuid, assetHash, variant, isSelected)
|
||||
VALUES (?, ?, ?, 0)
|
||||
`
|
||||
await database.query(insertSql, [uuid, hash, variant])
|
||||
const updateSql = `
|
||||
UPDATE playersSkins
|
||||
SET isSelected = (assetHash = ?)
|
||||
WHERE playerUuid = ?
|
||||
`
|
||||
await database.query(updateSql, [hash, uuid])
|
||||
return { code: 200 }
|
||||
} catch (error) {
|
||||
logger.log("Internal Server Error".bold + " : " + error.toString(), ["MariaDB", "yellow"])
|
||||
throw new DefaultError(500, "Internal Server Error", "Database Error")
|
||||
}
|
||||
}
|
||||
|
||||
async function hideCape(uuid) {
|
||||
try {
|
||||
const sql = "UPDATE playersCapes SET isSelected = 0 WHERE playerUuid = ?"
|
||||
await database.query(sql, [uuid])
|
||||
return { code: 200 }
|
||||
} catch (error) {
|
||||
logger.log("Internal Server Error".bold + " : " + error.toString(), ["MariaDB", "yellow"])
|
||||
throw new DefaultError(500, "Internal Server Error", "Database Error")
|
||||
}
|
||||
}
|
||||
|
||||
async function showCape(uuid, hash) {
|
||||
try {
|
||||
const sql = `
|
||||
UPDATE playersCapes
|
||||
SET isSelected = (assetHash = ?)
|
||||
WHERE playerUuid = ?
|
||||
`
|
||||
const result = await database.query(sql, [hash, uuid])
|
||||
return { code: 200, changed: result.affectedRows > 0 }
|
||||
} catch (error) {
|
||||
logger.log("Internal Server Error".bold + " : " + error.toString(), ["MariaDB", "yellow"])
|
||||
throw new DefaultError(500, "Internal Server Error", "Database Error")
|
||||
}
|
||||
}
|
||||
|
||||
async function checkCapeOwnership(uuid, hash) {
|
||||
try {
|
||||
const sql = "SELECT 1 FROM playersCapes WHERE playerUuid = ? AND assetHash = ?"
|
||||
const rows = await database.query(sql, [uuid, hash])
|
||||
return rows.length > 0
|
||||
} catch (error) {
|
||||
throw new DefaultError(500, "Internal Server Error", "Database Error")
|
||||
}
|
||||
}
|
||||
|
||||
async function getPlayerMeta(uuid) {
|
||||
try {
|
||||
const sql = `SELECT createdAt, nameChangeAllowed FROM players WHERE uuid = ?`
|
||||
const rows = await database.query(sql, [uuid])
|
||||
return rows[0]
|
||||
} catch (error) {
|
||||
logger.log("Database Error: " + error.toString(), ["MariaDB", "red"])
|
||||
throw new DefaultError(500, "Internal Server Error", "Database Error")
|
||||
}
|
||||
}
|
||||
|
||||
async function getLastNameChange(uuid) {
|
||||
try {
|
||||
const sql = `
|
||||
SELECT changedAt
|
||||
FROM uuidToNameHistory
|
||||
WHERE uuid = ? AND changedAt IS NOT NULL
|
||||
ORDER BY changedAt DESC
|
||||
LIMIT 1
|
||||
`
|
||||
const rows = await database.query(sql, [uuid])
|
||||
return rows[0]
|
||||
} catch (error) {
|
||||
logger.log("Database Error: " + error.toString(), ["MariaDB", "red"])
|
||||
throw new DefaultError(500, "Internal Server Error", "Database Error")
|
||||
}
|
||||
}
|
||||
|
||||
async function getPlayerCertificate(uuid) {
|
||||
try {
|
||||
const sql = "SELECT * FROM playerCertificates WHERE uuid = ?"
|
||||
const rows = await database.query(sql, [uuid])
|
||||
return rows[0]
|
||||
} catch (error) {
|
||||
logger.log("Database Error: " + error.toString(), ["MariaDB", "red"])
|
||||
throw new DefaultError(500, "Internal Server Error", "Database Error")
|
||||
}
|
||||
}
|
||||
|
||||
async function savePlayerCertificate(uuid, privateKey, publicKey, signatureV2, expiresAt, refreshedAfter) {
|
||||
try {
|
||||
const sql = `
|
||||
REPLACE INTO playerCertificates
|
||||
(uuid, privateKey, publicKey, publicKeySignatureV2, expiresAt, refreshedAfter)
|
||||
VALUES (?, ?, ?, ?, ?, ?)
|
||||
`
|
||||
const result = await database.query(sql, [uuid, privateKey, publicKey, signatureV2, expiresAt, refreshedAfter])
|
||||
return result.affectedRows > 0
|
||||
} catch (error) {
|
||||
logger.log("Database Error: " + error.toString(), ["MariaDB", "red"])
|
||||
throw new DefaultError(500, "Internal Server Error", "Database Error")
|
||||
}
|
||||
}
|
||||
|
||||
async function deleteExpiredCertificates(isoDate) {
|
||||
try {
|
||||
const sql = "DELETE FROM playerCertificates WHERE expiresAt < ?"
|
||||
const result = await database.query(sql, [isoDate])
|
||||
return result.affectedRows
|
||||
} catch (error) {
|
||||
logger.log("Database Error: " + error.toString(), ["MariaDB", "red"])
|
||||
throw new DefaultError(500, "Internal Server Error", "Database Error")
|
||||
}
|
||||
}
|
||||
|
||||
async function addProfileAction(uuid, actionCode) {
|
||||
try {
|
||||
const cleanUuid = uuid.replace(/-/g, "")
|
||||
const sql = "INSERT IGNORE INTO playerProfileActions (uuid, action) VALUES (?, ?)"
|
||||
const result = await database.query(sql, [cleanUuid, actionCode])
|
||||
return result.affectedRows > 0
|
||||
} catch (error) {
|
||||
logger.log("Database Error: " + error.toString(), ["MariaDB", "red"])
|
||||
throw new DefaultError(500, "Internal Server Error", "Database Error")
|
||||
}
|
||||
}
|
||||
|
||||
async function removeProfileAction(uuid, actionCode) {
|
||||
try {
|
||||
const cleanUuid = uuid.replace(/-/g, "")
|
||||
const sql = "DELETE FROM playerProfileActions WHERE uuid = ? AND action = ?"
|
||||
const result = await database.query(sql, [cleanUuid, actionCode])
|
||||
return result.affectedRows
|
||||
} catch (error) {
|
||||
logger.log("Database Error: " + error.toString(), ["MariaDB", "red"])
|
||||
throw new DefaultError(500, "Internal Server Error", "Database Error")
|
||||
}
|
||||
}
|
||||
|
||||
async function getPlayerActions(uuid) {
|
||||
try {
|
||||
const cleanUuid = uuid.replace(/-/g, "")
|
||||
const sql = "SELECT action FROM playerProfileActions WHERE uuid = ?"
|
||||
const rows = await database.query(sql, [cleanUuid])
|
||||
return rows.map(r => r.action)
|
||||
} catch (error) {
|
||||
logger.log("Database Error: " + error.toString(), ["MariaDB", "red"])
|
||||
throw new DefaultError(500, "Internal Server Error", "Database Error")
|
||||
}
|
||||
}
|
||||
|
||||
async function clearAllPlayerActions(uuid) {
|
||||
try {
|
||||
const cleanUuid = uuid.replace(/-/g, "")
|
||||
const sql = "DELETE FROM playerProfileActions WHERE uuid = ?"
|
||||
const result = await database.query(sql, [cleanUuid])
|
||||
return result.affectedRows
|
||||
} catch (error) {
|
||||
logger.log("Database Error: " + error.toString(), ["MariaDB", "red"])
|
||||
throw new DefaultError(500, "Internal Server Error", "Database Error")
|
||||
}
|
||||
}
|
||||
|
||||
async function blockPlayer(blockerUuid, blockedUuid) {
|
||||
try {
|
||||
const sql = `INSERT IGNORE INTO playersBlockslist (blockerUuid, blockedUuid) VALUES (?, ?)`
|
||||
const result = await database.query(sql, [blockerUuid, blockedUuid])
|
||||
return result.affectedRows > 0
|
||||
} catch (error) {
|
||||
logger.log("Database Error: " + error.toString(), ["MariaDB", "red"])
|
||||
throw new DefaultError(500, "Internal Server Error", "Database Error")
|
||||
}
|
||||
}
|
||||
|
||||
async function unblockPlayer(blockerUuid, blockedUuid) {
|
||||
try {
|
||||
const sql = `DELETE FROM playersBlockslist WHERE blockerUuid = ? AND blockedUuid = ?`
|
||||
const result = await database.query(sql, [blockerUuid, blockedUuid])
|
||||
return result.affectedRows > 0
|
||||
} catch (error) {
|
||||
logger.log("Database Error: " + error.toString(), ["MariaDB", "red"])
|
||||
throw new DefaultError(500, "Internal Server Error", "Database Error")
|
||||
}
|
||||
}
|
||||
|
||||
async function getBlockedUuids(blockerUuid) {
|
||||
try {
|
||||
const sql = `SELECT blockedUuid FROM playersBlockslist WHERE blockerUuid = ?`
|
||||
const rows = await database.query(sql, [blockerUuid])
|
||||
return rows.map(r => r.blockedUuid)
|
||||
} catch (error) {
|
||||
logger.log("Database Error: " + error.toString(), ["MariaDB", "red"])
|
||||
throw new DefaultError(500, "Internal Server Error", "Database Error")
|
||||
}
|
||||
}
|
||||
|
||||
async function isBlocked(blockerUuid, targetUuid) {
|
||||
try {
|
||||
const sql = `SELECT 1 FROM playersBlockslist WHERE blockerUuid = ? AND blockedUuid = ? LIMIT 1`
|
||||
const rows = await database.query(sql, [blockerUuid, targetUuid])
|
||||
return rows.length > 0
|
||||
} catch (error) {
|
||||
logger.log("Database Error: " + error.toString(), ["MariaDB", "red"])
|
||||
throw new DefaultError(500, "Internal Server Error", "Database Error")
|
||||
}
|
||||
}
|
||||
|
||||
async function getUsersByNames(usernames) {
|
||||
try {
|
||||
if (!usernames || usernames.length === 0) return []
|
||||
const uniqueNames = [...new Set(usernames)]
|
||||
|
||||
const placeholders = uniqueNames.map(() => "?").join(", ")
|
||||
const sql = `SELECT uuid, username FROM players WHERE username IN (${placeholders})`
|
||||
|
||||
const rows = await database.query(sql, uniqueNames)
|
||||
return rows
|
||||
} catch (error) {
|
||||
logger.log("Database Error: " + error.toString(), ["MariaDB", "red"])
|
||||
throw new DefaultError(500, "Internal Server Error", "Database Error")
|
||||
}
|
||||
}
|
||||
|
||||
async function getUuidAndUsername(username) {
|
||||
try {
|
||||
const sql = "SELECT uuid, username FROM players WHERE username = ?"
|
||||
const rows = await database.query(sql, [username])
|
||||
|
||||
return rows[0] || null
|
||||
} catch (error) {
|
||||
logger.log("Database Error: " + error.toString(), ["MariaDB", "red"])
|
||||
throw new DefaultError(500, "Internal Server Error", "Database Error")
|
||||
}
|
||||
}
|
||||
|
||||
async function getProfileByUsername(username) {
|
||||
try {
|
||||
const sql = "SELECT uuid, username FROM players WHERE username = ?"
|
||||
const rows = await database.query(sql, [username])
|
||||
return rows[0] || null
|
||||
} catch (error) {
|
||||
logger.log("Database Error: " + error.toString(), ["MariaDB", "red"])
|
||||
throw new DefaultError(500, "Internal Server Error", "Database Error")
|
||||
}
|
||||
}
|
||||
|
||||
async function getProfileByHistory(username, isoDate) {
|
||||
try {
|
||||
const sql = `
|
||||
SELECT uuid, username
|
||||
FROM uuidToNameHistory
|
||||
WHERE username = ?
|
||||
AND (changedAt <= ? OR changedAt IS NULL)
|
||||
ORDER BY changedAt DESC
|
||||
LIMIT 1
|
||||
`
|
||||
const rows = await database.query(sql, [username, isoDate])
|
||||
return rows[0] || null
|
||||
} catch (error) {
|
||||
logger.log("Database Error: " + error.toString(), ["MariaDB", "red"])
|
||||
throw new DefaultError(500, "Internal Server Error", "Database Error")
|
||||
}
|
||||
}
|
||||
|
||||
async function getNameHistory(uuid) {
|
||||
try {
|
||||
const sql = `
|
||||
SELECT username, changedAt
|
||||
FROM uuidToNameHistory
|
||||
WHERE uuid = ?
|
||||
ORDER BY changedAt ASC
|
||||
`
|
||||
const rows = await database.query(sql, [uuid])
|
||||
return rows
|
||||
} catch (error) {
|
||||
logger.log("Database Error: " + error.toString(), ["MariaDB", "red"])
|
||||
throw new DefaultError(500, "Internal Server Error", "Database Error")
|
||||
}
|
||||
}
|
||||
|
||||
async function setSkin(uuid, hash, variant) {
|
||||
const insertSql = `
|
||||
INSERT INTO playersSkins (playerUuid, assetHash, variant, isSelected)
|
||||
VALUES (?, ?, ?, 1)
|
||||
ON DUPLICATE KEY UPDATE isSelected = 1, variant = ?
|
||||
`
|
||||
await database.query(insertSql, [uuid, hash, variant, variant])
|
||||
const updateSql = `
|
||||
UPDATE playersSkins
|
||||
SET isSelected = 0
|
||||
WHERE playerUuid = ? AND assetHash != ?
|
||||
`
|
||||
await database.query(updateSql, [uuid, hash])
|
||||
return true
|
||||
}
|
||||
|
||||
async function updatePassword(uuid, hashedPassword) {
|
||||
try {
|
||||
const sql = "UPDATE players SET password = ? WHERE uuid = ?"
|
||||
const result = await database.query(sql, [hashedPassword, uuid])
|
||||
|
||||
if (result.affectedRows > 0) {
|
||||
return { code: 200, message: "Password updated successfully" }
|
||||
} else {
|
||||
throw new DefaultError(404, "User not found")
|
||||
}
|
||||
} catch (error) {
|
||||
if (error instanceof DefaultError) throw error
|
||||
logger.log("Internal Server Error".bold + " : " + error.toString(), ["MariaDB", "yellow"])
|
||||
throw new DefaultError(500, "Internal Server Error", "Database Error")
|
||||
}
|
||||
}
|
||||
|
||||
async function addCapeToPlayer(uuid, hash) {
|
||||
try {
|
||||
const sql = `
|
||||
INSERT INTO playersCapes (playerUuid, assetHash, isSelected)
|
||||
VALUES (?, ?, 0)
|
||||
`
|
||||
const result = await database.query(sql, [uuid, hash])
|
||||
|
||||
if (result.affectedRows > 0) {
|
||||
return { code: 200, message: "Cape accordée au joueur." }
|
||||
}
|
||||
throw new DefaultError(500, "Erreur lors de l'attribution de la cape.")
|
||||
} catch (error) {
|
||||
if (error.code === 'ER_DUP_ENTRY') {
|
||||
throw new DefaultError(409, "Le joueur possède déjà cette cape.")
|
||||
}
|
||||
logger.log("Internal Server Error".bold + " : " + error.toString(), ["MariaDB", "yellow"])
|
||||
throw new DefaultError(500, "Internal Server Error", "Database Error")
|
||||
}
|
||||
}
|
||||
|
||||
async function removeCapeFromPlayer(uuid, hash) {
|
||||
try {
|
||||
const sql = "DELETE FROM playersCapes WHERE playerUuid = ? AND assetHash = ?"
|
||||
const result = await database.query(sql, [uuid, hash])
|
||||
|
||||
if (result.affectedRows > 0) {
|
||||
return { code: 200, message: "Cape retirée du joueur." }
|
||||
} else {
|
||||
throw new DefaultError(404, "Le joueur ne possède pas cette cape.")
|
||||
}
|
||||
} catch (error) {
|
||||
if (error instanceof DefaultError) throw error
|
||||
logger.log("Internal Server Error".bold + " : " + error.toString(), ["MariaDB", "yellow"])
|
||||
throw new DefaultError(500, "Internal Server Error", "Database Error")
|
||||
}
|
||||
}
|
||||
|
||||
async function deleteTexture(hash) {
|
||||
try {
|
||||
const sql = "DELETE FROM textures WHERE hash = ?"
|
||||
const result = await database.query(sql, [hash])
|
||||
return result.affectedRows > 0
|
||||
} catch (error) {
|
||||
logger.log("Internal Server Error".bold + " : " + error.toString(), ["MariaDB", "yellow"])
|
||||
throw new DefaultError(500, "Internal Server Error", "Database Error")
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
setSkin,
|
||||
banUser,
|
||||
showCape,
|
||||
hideCape,
|
||||
resetSkin,
|
||||
isBlocked,
|
||||
unbanUser,
|
||||
blockPlayer,
|
||||
deleteTexture,
|
||||
createTexture,
|
||||
getPlayerBans,
|
||||
getPlayerMeta,
|
||||
unblockPlayer,
|
||||
changeUsername,
|
||||
getNameHistory,
|
||||
updatePassword,
|
||||
getBlockedUuids,
|
||||
getUsersByNames,
|
||||
addCapeToPlayer,
|
||||
getPlayerActions,
|
||||
getTextureByUuid,
|
||||
getTextureByHash,
|
||||
addProfileAction,
|
||||
getLastNameChange,
|
||||
getPlayerProperty,
|
||||
getUuidAndUsername,
|
||||
checkCapeOwnership,
|
||||
getProfileByHistory,
|
||||
getPlayerPrivileges,
|
||||
getPlayerProperties,
|
||||
removeProfileAction,
|
||||
addPropertyToPlayer,
|
||||
removeCapeFromPlayer,
|
||||
getProfileByUsername,
|
||||
getPlayerPreferences,
|
||||
getPlayerCertificate,
|
||||
clearAllPlayerActions,
|
||||
savePlayerCertificate,
|
||||
updatePlayerPrivileges,
|
||||
deletePropertyToPlayer,
|
||||
updatePropertyToPlayer,
|
||||
getPlayerSettingsSchema,
|
||||
updatePlayerPreferences,
|
||||
deleteExpiredCertificates,
|
||||
}
|
||||
Reference in New Issue
Block a user