From 87407fe6040b87e4b9aa679ab86033d8b5928af2 Mon Sep 17 00:00:00 2001 From: Azure Date: Sun, 6 Sep 2026 23:52:25 +0200 Subject: [PATCH] Add DDL-based DB init and bootstrap Add bootstrap entrypoint and migrate DB schema setup to SQL files. Introduces bootstrap.js, many data/ddl/*.sql files, and a new runDDL() in modules/database.js (exports pool and runDDL). Remove legacy modules/databaseGlobals.js. Update repositories and code to use database.pool.query calls. Bump package version and set main to bootstrap.js. Clean up server.js to remove inline DB/cert init (now handled by bootstrap). Overall: refactor DB initialization to run ordered SQL DDL files and centralize startup logic. --- bootstrap.js | 20 + data/ddl/01_players.sql | 8 + data/ddl/02_players_properties.sql | 7 + data/ddl/03_client_sessions.sql | 6 + data/ddl/04_legacy_client_sessions.sql | 5 + data/ddl/05_uiid_to_name_history.sql | 8 + data/ddl/06_log_new_user_name.sql | 9 + data/ddl/07_log_user_name_change.sql | 11 + data/ddl/08_blocked_servers.sql | 5 + data/ddl/09_players_privileges.sql | 8 + data/ddl/10_players_preferences.sql | 5 + data/ddl/11_ban_reasons.sql | 4 + data/ddl/12_bans.sql | 11 + data/ddl/13_auto_init_player_settings.sql | 9 + data/ddl/13_players_blockslist.sql | 7 + data/ddl/14_usernames_rules.sql | 5 + data/ddl/15_textures.sql | 8 + data/ddl/16_players_skins.sql | 12 + data/ddl/17_players_capes.sql | 11 + data/ddl/18_init_defaults_skin.sql | 3 + .../ddl/19_drop_uniques_textures_triggers.sql | 2 + .../20_auto_assign_random_default_skin.sql | 23 ++ data/ddl/21_players_certificates.sql | 9 + data/ddl/22_player_profile_actions.sql | 7 + data/ddl/23_server_sessions.sql | 8 + data/ddl/24_event_scheduler.sql | 1 + data/ddl/25_clean_expired_certificates.sql | 4 + data/ddl/26_api_administrators.sql | 6 + ...27_api_administrators_permissions_list.sql | 5 + .../ddl/28_api_administrators_permissions.sql | 7 + data/ddl/29_oauth2_links_attempts.sql | 6 + modules/database.js | 83 +++- modules/databaseGlobals.js | 387 ------------------ package.json | 4 +- repositories/adminRepository.js | 18 +- repositories/authRepository.js | 20 +- repositories/oauth2Repository.js | 8 +- repositories/sessionsRepository.js | 18 +- repositories/userRepository.js | 106 ++--- server.js | 6 - 40 files changed, 405 insertions(+), 485 deletions(-) create mode 100644 bootstrap.js create mode 100644 data/ddl/01_players.sql create mode 100644 data/ddl/02_players_properties.sql create mode 100644 data/ddl/03_client_sessions.sql create mode 100644 data/ddl/04_legacy_client_sessions.sql create mode 100644 data/ddl/05_uiid_to_name_history.sql create mode 100644 data/ddl/06_log_new_user_name.sql create mode 100644 data/ddl/07_log_user_name_change.sql create mode 100644 data/ddl/08_blocked_servers.sql create mode 100644 data/ddl/09_players_privileges.sql create mode 100644 data/ddl/10_players_preferences.sql create mode 100644 data/ddl/11_ban_reasons.sql create mode 100644 data/ddl/12_bans.sql create mode 100644 data/ddl/13_auto_init_player_settings.sql create mode 100644 data/ddl/13_players_blockslist.sql create mode 100644 data/ddl/14_usernames_rules.sql create mode 100644 data/ddl/15_textures.sql create mode 100644 data/ddl/16_players_skins.sql create mode 100644 data/ddl/17_players_capes.sql create mode 100644 data/ddl/18_init_defaults_skin.sql create mode 100644 data/ddl/19_drop_uniques_textures_triggers.sql create mode 100644 data/ddl/20_auto_assign_random_default_skin.sql create mode 100644 data/ddl/21_players_certificates.sql create mode 100644 data/ddl/22_player_profile_actions.sql create mode 100644 data/ddl/23_server_sessions.sql create mode 100644 data/ddl/24_event_scheduler.sql create mode 100644 data/ddl/25_clean_expired_certificates.sql create mode 100644 data/ddl/26_api_administrators.sql create mode 100644 data/ddl/27_api_administrators_permissions_list.sql create mode 100644 data/ddl/28_api_administrators_permissions.sql create mode 100644 data/ddl/29_oauth2_links_attempts.sql delete mode 100644 modules/databaseGlobals.js diff --git a/bootstrap.js b/bootstrap.js new file mode 100644 index 0000000..fad20f1 --- /dev/null +++ b/bootstrap.js @@ -0,0 +1,20 @@ +const certificates = require("./modules/certificatesManager") +const database = require("./modules/database") +const logger = require("./modules/logger") + +async function boot() { + try { + await database.runDDL() + certificates.setupKeys() + require("./server") + } catch (error) { + if (error?.fatal) { + logger.error("Fatal error while booting:", ["STARTUP", "cyan"]) + logger.error(error?.stack || error?.toString(), ["STARTUP", "cyan"]) + process.exit(1) + } + return + } +} + +boot() \ No newline at end of file diff --git a/data/ddl/01_players.sql b/data/ddl/01_players.sql new file mode 100644 index 0000000..7d9c40a --- /dev/null +++ b/data/ddl/01_players.sql @@ -0,0 +1,8 @@ +CREATE TABLE IF NOT EXISTS players ( + email VARCHAR(255) NULL UNIQUE, + username VARCHAR(16) NOT NULL UNIQUE, + password TEXT NOT NULL, + uuid VARCHAR(36) NOT NULL UNIQUE PRIMARY KEY, + nameChangeAllowed TINYINT(1) DEFAULT 1, + createdAt DATETIME DEFAULT CURRENT_TIMESTAMP +) \ No newline at end of file diff --git a/data/ddl/02_players_properties.sql b/data/ddl/02_players_properties.sql new file mode 100644 index 0000000..a60cbf6 --- /dev/null +++ b/data/ddl/02_players_properties.sql @@ -0,0 +1,7 @@ +CREATE TABLE IF NOT EXISTS playersProperties ( + name VARCHAR(256) NOT NULL, + value VARCHAR(512) NOT NULL, + uuid VARCHAR(36) NOT NULL, + UNIQUE KEY uniqueProperty (uuid, name), + FOREIGN KEY (uuid) REFERENCES players(uuid) ON DELETE CASCADE +) \ No newline at end of file diff --git a/data/ddl/03_client_sessions.sql b/data/ddl/03_client_sessions.sql new file mode 100644 index 0000000..8718048 --- /dev/null +++ b/data/ddl/03_client_sessions.sql @@ -0,0 +1,6 @@ +CREATE TABLE IF NOT EXISTS clientSessions ( + accessToken TEXT NOT NULL, + clientToken VARCHAR(36) NOT NULL, + uuid VARCHAR(36) NOT NULL, + FOREIGN KEY (uuid) REFERENCES players(uuid) +) \ No newline at end of file diff --git a/data/ddl/04_legacy_client_sessions.sql b/data/ddl/04_legacy_client_sessions.sql new file mode 100644 index 0000000..ab08355 --- /dev/null +++ b/data/ddl/04_legacy_client_sessions.sql @@ -0,0 +1,5 @@ +CREATE TABLE IF NOT EXISTS legacyClientSessions ( + sessionId VARCHAR(36) NOT NULL, + uuid VARCHAR(36) NOT NULL, + FOREIGN KEY (uuid) REFERENCES players(uuid) ON DELETE CASCADE +) \ No newline at end of file diff --git a/data/ddl/05_uiid_to_name_history.sql b/data/ddl/05_uiid_to_name_history.sql new file mode 100644 index 0000000..f9907ce --- /dev/null +++ b/data/ddl/05_uiid_to_name_history.sql @@ -0,0 +1,8 @@ +CREATE TABLE IF NOT EXISTS uuidToNameHistory ( + uuid VARCHAR(36) NOT NULL, + username VARCHAR(255) NOT NULL, + changedAt DATETIME NULL, + FOREIGN KEY (uuid) REFERENCES players(uuid) ON DELETE CASCADE +); + +CREATE INDEX IF NOT EXISTS idx_uuidToNameHistory_uuid ON uuidToNameHistory (uuid); \ No newline at end of file diff --git a/data/ddl/06_log_new_user_name.sql b/data/ddl/06_log_new_user_name.sql new file mode 100644 index 0000000..8d5c795 --- /dev/null +++ b/data/ddl/06_log_new_user_name.sql @@ -0,0 +1,9 @@ +DROP TRIGGER IF EXISTS log_new_user_name; + +CREATE TRIGGER log_new_user_name +AFTER INSERT ON players +FOR EACH ROW +BEGIN + INSERT INTO uuidToNameHistory (uuid, username, changedAt) + VALUES (NEW.uuid, NEW.username, NULL); +END; \ No newline at end of file diff --git a/data/ddl/07_log_user_name_change.sql b/data/ddl/07_log_user_name_change.sql new file mode 100644 index 0000000..e826049 --- /dev/null +++ b/data/ddl/07_log_user_name_change.sql @@ -0,0 +1,11 @@ +DROP TRIGGER IF EXISTS log_user_name_change; + +CREATE TRIGGER log_user_name_change +AFTER UPDATE ON players +FOR EACH ROW +BEGIN + IF OLD.username != NEW.username THEN + INSERT INTO uuidToNameHistory (uuid, username, changedAt) + VALUES (NEW.uuid, NEW.username, CURRENT_TIMESTAMP); + END IF; +END; \ No newline at end of file diff --git a/data/ddl/08_blocked_servers.sql b/data/ddl/08_blocked_servers.sql new file mode 100644 index 0000000..5838ef6 --- /dev/null +++ b/data/ddl/08_blocked_servers.sql @@ -0,0 +1,5 @@ +CREATE TABLE IF NOT EXISTS blockedServers ( + hashedIp VARCHAR(40) NOT NULL PRIMARY KEY, + banner VARCHAR(256) DEFAULT 'CONSOLE', + reason VARCHAR(512) NULL +) \ No newline at end of file diff --git a/data/ddl/09_players_privileges.sql b/data/ddl/09_players_privileges.sql new file mode 100644 index 0000000..a672274 --- /dev/null +++ b/data/ddl/09_players_privileges.sql @@ -0,0 +1,8 @@ +CREATE TABLE IF NOT EXISTS playersPrivileges ( + uuid VARCHAR(36) PRIMARY KEY, + onlineChat TINYINT(1) DEFAULT 1, + multiplayerServer TINYINT(1) DEFAULT 1, + multiplayerRealms TINYINT(1) DEFAULT 1, + telemetry TINYINT(1) DEFAULT 1, + FOREIGN KEY (uuid) REFERENCES players(uuid) ON DELETE CASCADE +) \ No newline at end of file diff --git a/data/ddl/10_players_preferences.sql b/data/ddl/10_players_preferences.sql new file mode 100644 index 0000000..df61bcc --- /dev/null +++ b/data/ddl/10_players_preferences.sql @@ -0,0 +1,5 @@ +CREATE TABLE IF NOT EXISTS playersPreferences ( + uuid VARCHAR(36) PRIMARY KEY, + profanityFilter TINYINT(1) DEFAULT 0, + FOREIGN KEY (uuid) REFERENCES players(uuid) ON DELETE CASCADE +) \ No newline at end of file diff --git a/data/ddl/11_ban_reasons.sql b/data/ddl/11_ban_reasons.sql new file mode 100644 index 0000000..cbc3ee4 --- /dev/null +++ b/data/ddl/11_ban_reasons.sql @@ -0,0 +1,4 @@ +CREATE TABLE IF NOT EXISTS banReasons ( + id INTEGER PRIMARY KEY AUTO_INCREMENT, + reasonKey VARCHAR(512) UNIQUE NOT NULL +) \ No newline at end of file diff --git a/data/ddl/12_bans.sql b/data/ddl/12_bans.sql new file mode 100644 index 0000000..d27392c --- /dev/null +++ b/data/ddl/12_bans.sql @@ -0,0 +1,11 @@ +CREATE TABLE IF NOT EXISTS bans ( + banId VARCHAR(512) PRIMARY KEY NOT NULL, + uuid VARCHAR(36) NOT NULL, + expires BIGINT DEFAULT NULL, + reason INTEGER NOT NULL, + reasonMessage VARCHAR(1024) DEFAULT NULL, + FOREIGN KEY(reason) REFERENCES banReasons(id), + FOREIGN KEY (uuid) REFERENCES players(uuid) ON DELETE CASCADE +); + +CREATE INDEX IF NOT EXISTS idx_bans_uuid ON bans (uuid) \ No newline at end of file diff --git a/data/ddl/13_auto_init_player_settings.sql b/data/ddl/13_auto_init_player_settings.sql new file mode 100644 index 0000000..a5c6359 --- /dev/null +++ b/data/ddl/13_auto_init_player_settings.sql @@ -0,0 +1,9 @@ +DROP TRIGGER IF EXISTS auto_init_player_settings; + +CREATE TRIGGER auto_init_player_settings +AFTER INSERT ON players +FOR EACH ROW +BEGIN + INSERT INTO playersPrivileges (uuid) VALUES (NEW.uuid); + INSERT INTO playersPreferences (uuid) VALUES (NEW.uuid); +END; \ No newline at end of file diff --git a/data/ddl/13_players_blockslist.sql b/data/ddl/13_players_blockslist.sql new file mode 100644 index 0000000..b10a3a7 --- /dev/null +++ b/data/ddl/13_players_blockslist.sql @@ -0,0 +1,7 @@ +CREATE TABLE IF NOT EXISTS playersBlockslist ( + blockerUuid VARCHAR(36) NOT NULL, + blockedUuid VARCHAR(36) NOT NULL, + PRIMARY KEY (blockerUuid, blockedUuid), + FOREIGN KEY (blockerUuid) REFERENCES players(uuid) ON DELETE CASCADE, + FOREIGN KEY (blockedUuid) REFERENCES players(uuid) ON DELETE CASCADE +) \ No newline at end of file diff --git a/data/ddl/14_usernames_rules.sql b/data/ddl/14_usernames_rules.sql new file mode 100644 index 0000000..119b6c6 --- /dev/null +++ b/data/ddl/14_usernames_rules.sql @@ -0,0 +1,5 @@ +CREATE TABLE IF NOT EXISTS usernameRules ( + id INTEGER PRIMARY KEY AUTO_INCREMENT, + rule VARCHAR(255) NOT NULL, + type INTEGER DEFAULT 0 +) \ No newline at end of file diff --git a/data/ddl/15_textures.sql b/data/ddl/15_textures.sql new file mode 100644 index 0000000..99774d6 --- /dev/null +++ b/data/ddl/15_textures.sql @@ -0,0 +1,8 @@ +CREATE TABLE IF NOT EXISTS textures ( + uuid VARCHAR(36) NOT NULL UNIQUE, + hash VARCHAR(64) PRIMARY KEY NOT NULL, + type VARCHAR(10) NOT NULL, + url VARCHAR(2048) NOT NULL, + alias VARCHAR(64) NULL, + createdAt DATETIME DEFAULT CURRENT_TIMESTAMP +) \ No newline at end of file diff --git a/data/ddl/16_players_skins.sql b/data/ddl/16_players_skins.sql new file mode 100644 index 0000000..6dce9c1 --- /dev/null +++ b/data/ddl/16_players_skins.sql @@ -0,0 +1,12 @@ +CREATE TABLE IF NOT EXISTS playersSkins ( + playerUuid VARCHAR(36) NOT NULL, + assetHash VARCHAR(64) NOT NULL, + variant VARCHAR(10) DEFAULT "CLASSIC", + isSelected TINYINT(1) DEFAULT 0, + createdAt DATETIME DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (playerUuid, assetHash), + FOREIGN KEY (playerUuid) REFERENCES players(uuid) ON DELETE CASCADE, + FOREIGN KEY (assetHash) REFERENCES textures(hash) +); + +CREATE INDEX IF NOT EXISTS idx_active_skin ON playersSkins (playerUuid, isSelected); \ No newline at end of file diff --git a/data/ddl/17_players_capes.sql b/data/ddl/17_players_capes.sql new file mode 100644 index 0000000..1dd1e30 --- /dev/null +++ b/data/ddl/17_players_capes.sql @@ -0,0 +1,11 @@ +CREATE TABLE IF NOT EXISTS playersCapes ( + playerUuid VARCHAR(36) NOT NULL, + assetHash VARCHAR(64) NOT NULL, + isSelected TINYINT(1) DEFAULT 0, + createdAt DATETIME DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (playerUuid, assetHash), + FOREIGN KEY (playerUuid) REFERENCES players(uuid) ON DELETE CASCADE, + FOREIGN KEY (assetHash) REFERENCES textures(hash) ON DELETE CASCADE +); + +CREATE INDEX IF NOT EXISTS idx_active_cape ON playersCapes (playerUuid, assetHash) \ No newline at end of file diff --git a/data/ddl/18_init_defaults_skin.sql b/data/ddl/18_init_defaults_skin.sql new file mode 100644 index 0000000..fbbfd37 --- /dev/null +++ b/data/ddl/18_init_defaults_skin.sql @@ -0,0 +1,3 @@ +INSERT IGNORE INTO textures (hash, type, url, uuid) VALUES +('df8ed96c557d441a63e7b6a4a911ab84fa453b42fc2ae6b01c3e1b02e138168c', 'SKIN', '/texture/alex.png', UUID()), +('4c7b0468044bfecacc43d00a3a69335a834b73937688292c20d3988cae58248d', 'SKIN', '/texture/steve.png', UUID()); \ No newline at end of file diff --git a/data/ddl/19_drop_uniques_textures_triggers.sql b/data/ddl/19_drop_uniques_textures_triggers.sql new file mode 100644 index 0000000..9c64351 --- /dev/null +++ b/data/ddl/19_drop_uniques_textures_triggers.sql @@ -0,0 +1,2 @@ +DROP TRIGGER IF EXISTS unique_active_skin; +DROP TRIGGER IF EXISTS unique_active_cape; \ No newline at end of file diff --git a/data/ddl/20_auto_assign_random_default_skin.sql b/data/ddl/20_auto_assign_random_default_skin.sql new file mode 100644 index 0000000..8e2751e --- /dev/null +++ b/data/ddl/20_auto_assign_random_default_skin.sql @@ -0,0 +1,23 @@ +DROP TRIGGER IF EXISTS auto_assign_random_default_skin; + +CREATE TRIGGER auto_assign_random_default_skin +AFTER INSERT ON players +FOR EACH ROW +BEGIN + INSERT INTO playersSkins (playerUuid, assetHash, variant, isSelected) + SELECT + NEW.uuid, + hash, + CASE + WHEN hash = '4c7b0468044bfecacc43d00a3a69335a834b73937688292c20d3988cae58248d' THEN 'CLASSIC' + ELSE 'SLIM' + END, + 1 + FROM textures + WHERE hash IN ( + '4c7b0468044bfecacc43d00a3a69335a834b73937688292c20d3988cae58248d', + 'df8ed96c557d441a63e7b6a4a911ab84fa453b42fc2ae6b01c3e1b02e138168c' + ) + ORDER BY RAND() + LIMIT 1; +END; \ No newline at end of file diff --git a/data/ddl/21_players_certificates.sql b/data/ddl/21_players_certificates.sql new file mode 100644 index 0000000..a81ded3 --- /dev/null +++ b/data/ddl/21_players_certificates.sql @@ -0,0 +1,9 @@ +CREATE TABLE IF NOT EXISTS playerCertificates ( + uuid VARCHAR(36) PRIMARY KEY, + privateKey TEXT NOT NULL, + publicKey TEXT NOT NULL, + publicKeySignatureV2 TEXT NOT NULL, + expiresAt DATETIME NOT NULL, + refreshedAfter DATETIME NOT NULL, + FOREIGN KEY (uuid) REFERENCES players(uuid) ON DELETE CASCADE +) \ No newline at end of file diff --git a/data/ddl/22_player_profile_actions.sql b/data/ddl/22_player_profile_actions.sql new file mode 100644 index 0000000..c24770a --- /dev/null +++ b/data/ddl/22_player_profile_actions.sql @@ -0,0 +1,7 @@ +CREATE TABLE IF NOT EXISTS playerProfileActions ( + uuid VARCHAR(36) NOT NULL, + action VARCHAR(64) NOT NULL, + createdAt DATETIME DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (uuid, action), + FOREIGN KEY (uuid) REFERENCES players(uuid) ON DELETE CASCADE +) \ No newline at end of file diff --git a/data/ddl/23_server_sessions.sql b/data/ddl/23_server_sessions.sql new file mode 100644 index 0000000..a31eae2 --- /dev/null +++ b/data/ddl/23_server_sessions.sql @@ -0,0 +1,8 @@ +CREATE TABLE IF NOT EXISTS serverSessions ( + uuid VARCHAR(36) PRIMARY KEY, + accessToken TEXT NOT NULL, + serverId VARCHAR(255) NOT NULL, + ip VARCHAR(45) NULL, + createdAt DATETIME DEFAULT CURRENT_TIMESTAMP, + FOREIGN KEY (uuid) REFERENCES players(uuid) ON DELETE CASCADE +) \ No newline at end of file diff --git a/data/ddl/24_event_scheduler.sql b/data/ddl/24_event_scheduler.sql new file mode 100644 index 0000000..07748c2 --- /dev/null +++ b/data/ddl/24_event_scheduler.sql @@ -0,0 +1 @@ +SET GLOBAL event_scheduler = ON; \ No newline at end of file diff --git a/data/ddl/25_clean_expired_certificates.sql b/data/ddl/25_clean_expired_certificates.sql new file mode 100644 index 0000000..22c8739 --- /dev/null +++ b/data/ddl/25_clean_expired_certificates.sql @@ -0,0 +1,4 @@ +CREATE EVENT IF NOT EXISTS clean_expired_certificates +ON SCHEDULE EVERY 1 HOUR +DO +DELETE FROM playerCertificates WHERE expiresAt < NOW(); \ No newline at end of file diff --git a/data/ddl/26_api_administrators.sql b/data/ddl/26_api_administrators.sql new file mode 100644 index 0000000..4109b10 --- /dev/null +++ b/data/ddl/26_api_administrators.sql @@ -0,0 +1,6 @@ +CREATE TABLE IF NOT EXISTS apiAdministrators ( + id INTEGER PRIMARY KEY AUTO_INCREMENT, + username VARCHAR(255) UNIQUE NOT NULL, + password TEXT NOT NULL, + createdAt DATETIME DEFAULT CURRENT_TIMESTAMP +) \ No newline at end of file diff --git a/data/ddl/27_api_administrators_permissions_list.sql b/data/ddl/27_api_administrators_permissions_list.sql new file mode 100644 index 0000000..e9ff99f --- /dev/null +++ b/data/ddl/27_api_administrators_permissions_list.sql @@ -0,0 +1,5 @@ +CREATE TABLE IF NOT EXISTS apiAdministratorsPermissionsList ( + permissionKey VARCHAR(64) PRIMARY KEY +); + +INSERT IGNORE INTO apiAdministratorsPermissionsList(permissionKey) VALUES ("RESET_PLAYER_SKIN"), ("GRANT_PLAYER_CAPE"), ("REMOVE_PLAYER_CAPE"), ("CHANGE_PLAYER_USERNAME"), ("CHANGE_PLAYER_PASSWORD"), ("UPLOAD_CAPE"), ("DELETE_CAPES"), ("PLAYER_BAN"), ("PLAYER_BAN_HISTORY"), ("PLAYER_BAN_STATUS"), ("PLAYER_ACTIONS_LIST"), ("PLAYER_UNBAN"), ("REGISTER_USER") \ No newline at end of file diff --git a/data/ddl/28_api_administrators_permissions.sql b/data/ddl/28_api_administrators_permissions.sql new file mode 100644 index 0000000..83af7f8 --- /dev/null +++ b/data/ddl/28_api_administrators_permissions.sql @@ -0,0 +1,7 @@ +CREATE TABLE IF NOT EXISTS apiAdministratorsPermissions ( + administratorId INTEGER NOT NULL, + permissionKey VARCHAR(64) NOT NULL, + PRIMARY KEY (administratorId, permissionKey), + FOREIGN KEY (administratorId) REFERENCES apiAdministrators(id) ON DELETE CASCADE, + FOREIGN KEY (permissionkey) REFERENCES apiAdministratorsPermissionsList(permissionKey) ON DELETE CASCADE +) \ No newline at end of file diff --git a/data/ddl/29_oauth2_links_attempts.sql b/data/ddl/29_oauth2_links_attempts.sql new file mode 100644 index 0000000..6a27334 --- /dev/null +++ b/data/ddl/29_oauth2_links_attempts.sql @@ -0,0 +1,6 @@ +CREATE TABLE IF NOT EXISTS oaauth2LinkAttempts ( + OAuth2LinkId VARCHAR(255) NOT NULL, + playerUuid VARCHAR(255) NOT NULL, + createdAt DATETIME DEFAULT CURRENT_TIMESTAMP, + FOREIGN KEY (playerUuid) REFERENCES players(uuid) ON DELETE CASCADE +) \ No newline at end of file diff --git a/modules/database.js b/modules/database.js index 463f5b2..b02d233 100644 --- a/modules/database.js +++ b/modules/database.js @@ -1,16 +1,89 @@ const mariadb = require("mariadb") +const logger = require("./logger") +const fs = require("fs/promises") +const path = require("path") -const pool = mariadb.createPool({ - host: process.env.DATABASE_HOST, - user: process.env.DATABASE_USER, +const dbConfig = { + host: process.env.DATABASE_HOST, + user: process.env.DATABASE_USER, password: process.env.DATABASE_PASSWORD, database: process.env.DATABASE_NAME, - connectionLimit: process.env.DATABASE_CONNECTION_LIMIT || 10, acquireTimeout: 20000, connectTimeout: 20000, bigIntAsNumber: true, insertIdAsNumber: true, decimalAsNumber: true +} + +const pool = mariadb.createPool({ + ...dbConfig, + connectionLimit: Number(process.env.DATABASE_CONNECTION_LIMIT) || 10 }) -module.exports = pool \ No newline at end of file +async function runDDL() { + let rootConn + let ddlConn + + try { + rootConn = await mariadb.createConnection({ + host: dbConfig.host, + user: dbConfig.user, + password: dbConfig.password, + connectTimeout: dbConfig.connectTimeout + }) + + await rootConn.query( + `CREATE DATABASE IF NOT EXISTS \`${dbConfig.database}\` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;` + ) + logger.log(`Base de données '${dbConfig.database}' vérifiée.`, ["MariaDB", "yellow"]) + await rootConn.end() + rootConn = null + + ddlConn = await mariadb.createConnection({ + ...dbConfig, + multipleStatements: true + }) + + logger.log("Checking and synchronising the schema...", ["MariaDB", "yellow"]) + + const ddlDir = path.join(process.cwd(), "data", "ddl") + const files = await fs.readdir(ddlDir) + + const sqlFiles = files + .filter(file => file.endsWith(".sql")) + .sort() + + for (const file of sqlFiles) { + const filePath = path.join(ddlDir, file) + const sql = await fs.readFile(filePath, "utf-8") + + if (sql.trim()) { + logger.log(`Execution of ${file.bold || file}`, ["DDL", "yellow"]) + await ddlConn.query(sql) + } + } + + logger.log("MariaDB database successfully initialised!", ["MariaDB", "yellow"]) + } catch (error) { + if (error?.fatal) { + logger.error("Critical error during DB initialisation: " + error.message, ["MariaDB", "yellow"]) + logger.error(error) + throw error + } else { + logger.warn("Minimal error during DB initialisation: " + error.message, ["MariaDB", "yellow"]) + } + + } finally { + if (rootConn) { + await rootConn.end() + } + if (ddlConn) { + await ddlConn.end() + } + } +} + +module.exports = { + pool, + runDDL +} \ No newline at end of file diff --git a/modules/databaseGlobals.js b/modules/databaseGlobals.js deleted file mode 100644 index 08a56a2..0000000 --- a/modules/databaseGlobals.js +++ /dev/null @@ -1,387 +0,0 @@ -const path = require("node:path") -const mariadb = require("mariadb") -const logger = require("./logger") -const crypto = require("node:crypto") - -const rootConfig = { - host: process.env.DATABASE_HOST, - user: process.env.DATABASE_USER, - password: process.env.DATABASE_PASSWORD, - connectionLimit: 1, - connectTimeout: 20000 -} - -async function setupDatabase() { - let conn - - try { - conn = await mariadb.createConnection(rootConfig) - await conn.query(`CREATE DATABASE IF NOT EXISTS \`${process.env.DATABASE_NAME}\` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;`) - logger.log(`Base de données '${process.env.DB_NAME}' vérifiée.`, ["MariaDB", "yellow"]) - await conn.end() - - conn = await mariadb.createConnection({ - ...rootConfig, - database: process.env.DB_NAME, - multipleStatements: true - }) - logger.log("Checking and synchronising the schema...", ["MariaDB", "yellow"]) - await conn.query(`USE \`${process.env.DATABASE_NAME}\``) - - await conn.query(` - CREATE TABLE IF NOT EXISTS players ( - email VARCHAR(255) NULL UNIQUE, - username VARCHAR(16) NOT NULL UNIQUE, - password TEXT NOT NULL, - uuid VARCHAR(36) NOT NULL UNIQUE PRIMARY KEY, - nameChangeAllowed TINYINT(1) DEFAULT 1, - createdAt DATETIME DEFAULT CURRENT_TIMESTAMP - ) - `) - logger.log(`${"players".bold} table ready`, ["MariaDB", "yellow"]) - - await conn.query(` - CREATE TABLE IF NOT EXISTS playersProperties ( - name VARCHAR(256) NOT NULL, - value VARCHAR(512) NOT NULL, - uuid VARCHAR(36) NOT NULL, - UNIQUE KEY uniqueProperty (uuid, name), - FOREIGN KEY (uuid) REFERENCES players(uuid) ON DELETE CASCADE - ) - `) - logger.log(`${"playersProperties".bold} table ready`, ["MariaDB", "yellow"]) - - await conn.query(` - CREATE TABLE IF NOT EXISTS clientSessions ( - accessToken TEXT NOT NULL, - clientToken VARCHAR(36) NOT NULL, - uuid VARCHAR(36) NOT NULL, - FOREIGN KEY (uuid) REFERENCES players(uuid) - ) - `) - logger.log(`${"clientSessions".bold} table ready`, ["MariaDB", "yellow"]) - - await conn.query(` - CREATE TABLE IF NOT EXISTS legacyClientSessions ( - sessionId VARCHAR(36) NOT NULL, - uuid VARCHAR(36) NOT NULL, - FOREIGN KEY (uuid) REFERENCES players(uuid) ON DELETE CASCADE - ) - `) - logger.log(`${"legacyClientSessions".bold} table ready`, ["MariaDB", "yellow"]) - - await conn.query(` - CREATE TABLE IF NOT EXISTS uuidToNameHistory ( - uuid VARCHAR(36) NOT NULL, - username VARCHAR(255) NOT NULL, - changedAt DATETIME NULL, - FOREIGN KEY (uuid) REFERENCES players(uuid) ON DELETE CASCADE - ) - `) - logger.log(`${"uuidToNameHistory".bold} table ready`, ["MariaDB", "yellow"]) - - await conn.query(`CREATE INDEX IF NOT EXISTS idx_uuidToNameHistory_uuid ON uuidToNameHistory (uuid)`) - logger.log(`${"idx_uuidToNameHistory_uuid".bold} index ready`, ["MariaDB", "yellow"]) - - await conn.query(`DROP TRIGGER IF EXISTS log_new_user_name`) - await conn.query(` - CREATE TRIGGER log_new_user_name - AFTER INSERT ON players - FOR EACH ROW - BEGIN - INSERT INTO uuidToNameHistory (uuid, username, changedAt) - VALUES (NEW.uuid, NEW.username, NULL); - END; - `) - logger.log(`${"log_new_user_name".bold} trigger ready`, ["MariaDB", "yellow"]) - - await conn.query(`DROP TRIGGER IF EXISTS log_user_name_change`) - await conn.query(` - CREATE TRIGGER log_user_name_change - AFTER UPDATE ON players - FOR EACH ROW - BEGIN - IF OLD.username != NEW.username THEN - INSERT INTO uuidToNameHistory (uuid, username, changedAt) - VALUES (NEW.uuid, NEW.username, CURRENT_TIMESTAMP); - END IF; - END; - `) - logger.log(`${"log_user_name_change".bold} trigger ready`, ["MariaDB", "yellow"]) - - await conn.query(` - CREATE TABLE IF NOT EXISTS blockedServers ( - hashedIp VARCHAR(40) NOT NULL PRIMARY KEY, - banner VARCHAR(256) DEFAULT 'CONSOLE', - reason VARCHAR(512) NULL - ) - `) - logger.log(`${"blockedServers".bold} table ready`, ["MariaDB", "yellow"]) - - await conn.query(` - CREATE TABLE IF NOT EXISTS playersPrivileges ( - uuid VARCHAR(36) PRIMARY KEY, - onlineChat TINYINT(1) DEFAULT 1, - multiplayerServer TINYINT(1) DEFAULT 1, - multiplayerRealms TINYINT(1) DEFAULT 1, - telemetry TINYINT(1) DEFAULT 1, - FOREIGN KEY (uuid) REFERENCES players(uuid) ON DELETE CASCADE - ) - `) - logger.log(`${"playersPrivileges".bold} table ready`, ["MariaDB", "yellow"]) - - await conn.query(` - CREATE TABLE IF NOT EXISTS playersPreferences ( - uuid VARCHAR(36) PRIMARY KEY, - profanityFilter TINYINT(1) DEFAULT 0, - FOREIGN KEY (uuid) REFERENCES players(uuid) ON DELETE CASCADE - ) - `) - logger.log(`${"playersPreferences".bold} table ready`, ["MariaDB", "yellow"]) - - await conn.query(` - CREATE TABLE IF NOT EXISTS banReasons ( - id INTEGER PRIMARY KEY AUTO_INCREMENT, - reasonKey VARCHAR(512) UNIQUE NOT NULL - ) - `) - logger.log(`${"banReasons".bold} table ready`, ["MariaDB", "yellow"]) - - await conn.query(` - CREATE TABLE IF NOT EXISTS bans ( - banId VARCHAR(512) PRIMARY KEY NOT NULL, - uuid VARCHAR(36) NOT NULL, - expires BIGINT DEFAULT NULL, - reason INTEGER NOT NULL, - reasonMessage VARCHAR(1024) DEFAULT NULL, - FOREIGN KEY(reason) REFERENCES banReasons(id), - FOREIGN KEY (uuid) REFERENCES players(uuid) ON DELETE CASCADE - ) - `) - logger.log(`${"bans".bold} table ready`, ["MariaDB", "yellow"]) - await conn.query(`CREATE INDEX IF NOT EXISTS idx_bans_uuid ON bans (uuid)`) - logger.log(`${"idx_bans_uuid".bold} index ready`, ["MariaDB", "yellow"]) - - await conn.query(`DROP TRIGGER IF EXISTS auto_init_player_settings`) - await conn.query(` - CREATE TRIGGER auto_init_player_settings - AFTER INSERT ON players - FOR EACH ROW - BEGIN - INSERT INTO playersPrivileges (uuid) VALUES (NEW.uuid); - INSERT INTO playersPreferences (uuid) VALUES (NEW.uuid); - END; - `) - logger.log(`${"auto_init_player_settings".bold} trigger ready`, ["MariaDB", "yellow"]) - - await conn.query(` - CREATE TABLE IF NOT EXISTS playersBlockslist ( - blockerUuid VARCHAR(36) NOT NULL, - blockedUuid VARCHAR(36) NOT NULL, - PRIMARY KEY (blockerUuid, blockedUuid), - FOREIGN KEY (blockerUuid) REFERENCES players(uuid) ON DELETE CASCADE, - FOREIGN KEY (blockedUuid) REFERENCES players(uuid) ON DELETE CASCADE - ) - `) - logger.log(`${"playersBlockslist".bold} table ready`, ["MariaDB", "yellow"]) - - await conn.query(` - CREATE TABLE IF NOT EXISTS usernameRules ( - id INTEGER PRIMARY KEY AUTO_INCREMENT, - rule VARCHAR(255) NOT NULL, - type INTEGER DEFAULT 0 - ) - `) - logger.log(`${"usernameRules".bold} table ready`, ["MariaDB", "yellow"]) - - await conn.query(` - CREATE TABLE IF NOT EXISTS textures ( - uuid VARCHAR(36) NOT NULL UNIQUE, - hash VARCHAR(64) PRIMARY KEY NOT NULL, - type VARCHAR(10) NOT NULL, - url VARCHAR(2048) NOT NULL, - alias VARCHAR(64) NULL, - createdAt DATETIME DEFAULT CURRENT_TIMESTAMP - ) - `) - logger.log(`${"textures".bold} table ready`, ["MariaDB", "yellow"]) - - await conn.query(` - CREATE TABLE IF NOT EXISTS playersSkins ( - playerUuid VARCHAR(36) NOT NULL, - assetHash VARCHAR(64) NOT NULL, - variant VARCHAR(10) DEFAULT "CLASSIC", - isSelected TINYINT(1) DEFAULT 0, - createdAt DATETIME DEFAULT CURRENT_TIMESTAMP, - PRIMARY KEY (playerUuid, assetHash), - FOREIGN KEY (playerUuid) REFERENCES players(uuid) ON DELETE CASCADE, - FOREIGN KEY (assetHash) REFERENCES textures(hash) - ) - `) - logger.log(`${"playersSkins".bold} table ready`, ["MariaDB", "yellow"]) - await conn.query(`CREATE INDEX IF NOT EXISTS idx_active_skin ON playersSkins (playerUuid, isSelected)`) - logger.log(`${"idx_active_skin".bold} index ready`, ["MariaDB", "yellow"]) - - await conn.query(` - CREATE TABLE IF NOT EXISTS playersCapes ( - playerUuid VARCHAR(36) NOT NULL, - assetHash VARCHAR(64) NOT NULL, - isSelected TINYINT(1) DEFAULT 0, - createdAt DATETIME DEFAULT CURRENT_TIMESTAMP, - PRIMARY KEY (playerUuid, assetHash), - FOREIGN KEY (playerUuid) REFERENCES players(uuid) ON DELETE CASCADE, - FOREIGN KEY (assetHash) REFERENCES textures(hash) ON DELETE CASCADE - ) - `) - logger.log(`${"playersCapes".bold} table ready`, ["MariaDB", "yellow"]) - await conn.query(`CREATE INDEX IF NOT EXISTS idx_active_cape ON playersCapes (playerUuid, assetHash)`) - logger.log(`${"idx_active_cape".bold} index ready`, ["MariaDB", "yellow"]) - - await conn.query(`INSERT IGNORE INTO textures (hash, type, url, uuid) VALUES ('df8ed96c557d441a63e7b6a4a911ab84fa453b42fc2ae6b01c3e1b02e138168c', 'SKIN', '/texture/alex.png', '${crypto.randomUUID()}')`) - await conn.query(`INSERT IGNORE INTO textures (hash, type, url, uuid) VALUES ('4c7b0468044bfecacc43d00a3a69335a834b73937688292c20d3988cae58248d', 'SKIN', '/texture/steve.png', '${crypto.randomUUID()}')`) - logger.log(`defaults skins (steve, alex) ready`, ["MariaDB", "yellow"]) - - await conn.query(`DROP TRIGGER IF EXISTS unique_active_skin`) - - await conn.query(`DROP TRIGGER IF EXISTS unique_active_cape`) - - await conn.query(`DROP TRIGGER IF EXISTS auto_assign_random_default_skin`) - await conn.query(` - CREATE TRIGGER auto_assign_random_default_skin - AFTER INSERT ON players - FOR EACH ROW - BEGIN - INSERT INTO playersSkins (playerUuid, assetHash, variant, isSelected) - SELECT - NEW.uuid, - hash, - CASE - WHEN hash = '4c7b0468044bfecacc43d00a3a69335a834b73937688292c20d3988cae58248d' THEN 'CLASSIC' - ELSE 'SLIM' - END, - 1 - FROM textures - WHERE hash IN ( - '4c7b0468044bfecacc43d00a3a69335a834b73937688292c20d3988cae58248d', - 'df8ed96c557d441a63e7b6a4a911ab84fa453b42fc2ae6b01c3e1b02e138168c' - ) - ORDER BY RAND() - LIMIT 1; - END; - `) - logger.log(`${"auto_assign_random_default_skin".bold} trigger ready`, ["MariaDB", "yellow"]) - - await conn.query(` - CREATE TABLE IF NOT EXISTS playerCertificates ( - uuid VARCHAR(36) PRIMARY KEY, - privateKey TEXT NOT NULL, - publicKey TEXT NOT NULL, - publicKeySignatureV2 TEXT NOT NULL, - expiresAt DATETIME NOT NULL, - refreshedAfter DATETIME NOT NULL, - FOREIGN KEY (uuid) REFERENCES players(uuid) ON DELETE CASCADE - ) - `) - logger.log(`${"playerCertificates".bold} table ready`, ["MariaDB", "yellow"]) - - await conn.query(` - CREATE TABLE IF NOT EXISTS playerProfileActions ( - uuid VARCHAR(36) NOT NULL, - action VARCHAR(64) NOT NULL, - createdAt DATETIME DEFAULT CURRENT_TIMESTAMP, - PRIMARY KEY (uuid, action), - FOREIGN KEY (uuid) REFERENCES players(uuid) ON DELETE CASCADE - ) - `) - logger.log(`${"playerProfileActions".bold} table ready`, ["MariaDB", "yellow"]) - - await conn.query(` - CREATE TABLE IF NOT EXISTS serverSessions ( - uuid VARCHAR(36) PRIMARY KEY, - accessToken TEXT NOT NULL, - serverId VARCHAR(255) NOT NULL, - ip VARCHAR(45) NULL, - createdAt DATETIME DEFAULT CURRENT_TIMESTAMP, - FOREIGN KEY (uuid) REFERENCES players(uuid) ON DELETE CASCADE - ) - `) - logger.log(`${"serverSessions".bold} table ready`, ["MariaDB", "yellow"]) - - try { - await conn.query(`SET GLOBAL event_scheduler = ON;`) - logger.log("MySQL Event Scheduler enabled.", ["MySQL", "yellow"]) - - await conn.query(` - CREATE EVENT IF NOT EXISTS clean_expired_certificates - ON SCHEDULE EVERY 1 HOUR - DO - DELETE FROM playerCertificates WHERE expiresAt < NOW(); - `) - logger.log(`${"clean_expired_certificates".bold} event ready`, ["MySQL", "yellow"]) - } catch (e) { - logger.log("Warning: Could not enable Event Scheduler (permission issue?). Skipping event creation.", ["MySQL", "red"]) - } - - await conn.query(` - CREATE EVENT IF NOT EXISTS clean_expired_certificates - ON SCHEDULE EVERY 1 HOUR - DO - DELETE FROM playerCertificates WHERE expiresAt < NOW(); - `) - logger.log(`${"clean_expired_certificates".bold} event ready`, ["MariaDB", "yellow"]) - - await conn.query(` - CREATE TABLE IF NOT EXISTS apiAdministrators ( - id INTEGER PRIMARY KEY AUTO_INCREMENT, - username VARCHAR(255) UNIQUE NOT NULL, - password TEXT NOT NULL, - createdAt DATETIME DEFAULT CURRENT_TIMESTAMP - ) - `) - logger.log(`${"apiAdministrators".bold} table ready`, ["MariaDB", "yellow"]) - - await conn.query(` - CREATE TABLE IF NOT EXISTS apiAdministratorsPermissionsList ( - permissionKey VARCHAR(64) PRIMARY KEY - ) - `) - logger.log(`${"apiAdministratorsPermissionsList".bold} table ready`, ["MariaDB", "yellow"]) - - await conn.query(`INSERT IGNORE INTO apiAdministratorsPermissionsList(permissionKey) VALUES ("RESET_PLAYER_SKIN"), ("GRANT_PLAYER_CAPE"), ("REMOVE_PLAYER_CAPE"), ("CHANGE_PLAYER_USERNAME"), ("CHANGE_PLAYER_PASSWORD"), ("UPLOAD_CAPE"), ("DELETE_CAPES"), ("PLAYER_BAN"), ("PLAYER_BAN_HISTORY"), ("PLAYER_BAN_STATUS"), ("PLAYER_ACTIONS_LIST"), ("PLAYER_UNBAN"), ("REGISTER_USER")`) - logger.log(`${"apiAdministratorsPermissionsList".bold} permissions ready`, ["MariaDB", "yellow"]) - - await conn.query(` - CREATE TABLE IF NOT EXISTS apiAdministratorsPermissions ( - administratorId INTEGER NOT NULL, - permissionKey VARCHAR(64) NOT NULL, - PRIMARY KEY (administratorId, permissionKey), - FOREIGN KEY (administratorId) REFERENCES apiAdministrators(id) ON DELETE CASCADE, - FOREIGN KEY (permissionkey) REFERENCES apiAdministratorsPermissionsList(permissionKey) ON DELETE CASCADE - ) - `) - logger.log(`${"apiAdministratorsPermissions".bold} table ready`, ["MariaDB", "yellow"]) - - await conn.query(` - CREATE TABLE IF NOT EXISTS oaauth2LinkAttempts ( - OAuth2LinkId VARCHAR(255) NOT NULL, - playerUuid VARCHAR(255) NOT NULL, - createdAt DATETIME DEFAULT CURRENT_TIMESTAMP, - FOREIGN KEY (playerUuid) REFERENCES players(uuid) ON DELETE CASCADE - ) - `) - logger.log(`${"oaauth2LinkAttempts".bold} table ready`, ["MariaDB", "yellow"]) - - logger.log("MariaDB database successfully initialised!", ["MariaDB", "yellow"]) - - } catch (err) { - logger.error("Critical error during DB initialisation: " + err.message, ["MariaDB", "yellow"]) - console.error(err) - process.exit(1) - } finally { - if (conn) conn.end() - } -} - -module.exports = { - setupDatabase -} \ No newline at end of file diff --git a/package.json b/package.json index 2ffc696..30c6af9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "yggdrasil", - "version": "0.0.1-alpha", + "version": "0.0.5-alpha", "description": "", "repository": { "type": "git", @@ -13,7 +13,7 @@ "email": "gilleslazure04@gmail.com" }, "type": "commonjs", - "main": "server.js", + "main": "bootstrap.js", "scripts": { "start:dev": "nodemon .", "start": "node .", diff --git a/repositories/adminRepository.js b/repositories/adminRepository.js index dd3286c..f032c6d 100644 --- a/repositories/adminRepository.js +++ b/repositories/adminRepository.js @@ -5,7 +5,7 @@ const { DefaultError } = require("../errors/errors") async function getAdminById(id) { try { const sql = "SELECT id, username, createdAt FROM apiAdministrators WHERE id = ?" - const rows = await database.query(sql, [id]) + const rows = await database.pool.query(sql, [id]) return rows[0] || null } catch (error) { return utils.handleDBError(error) @@ -15,7 +15,7 @@ async function getAdminById(id) { async function createAdmin(username, hashedPassword) { try { const sql = "INSERT INTO apiAdministrators (username, password) VALUES (?, ?)" - const result = await database.query(sql, [username, hashedPassword]) + const result = await database.pool.query(sql, [username, hashedPassword]) if (result.affectedRows > 0) { return { code: 200, id: result.insertId, username } @@ -37,7 +37,7 @@ async function hasPermission(adminId, permissionKey) { FROM apiAdministratorsPermissions WHERE administratorId = ? AND permissionKey = ? ` - const rows = await database.query(sql, [adminId, permissionKey]) + const rows = await database.pool.query(sql, [adminId, permissionKey]) return rows[0].count === 1 } catch (error) { return utils.handleDBError(error) @@ -47,7 +47,7 @@ async function hasPermission(adminId, permissionKey) { async function assignPermission(adminId, permissionKey) { try { const sql = "INSERT INTO apiAdministratorsPermissions (administratorId, permissionKey) VALUES (?, ?)" - const result = await database.query(sql, [adminId, permissionKey]) + const result = await database.pool.query(sql, [adminId, permissionKey]) return result.affectedRows > 0 } catch (error) { @@ -59,7 +59,7 @@ async function assignPermission(adminId, permissionKey) { async function revokePermission(adminId, permissionKey) { try { const sql = "DELETE FROM apiAdministratorsPermissions WHERE administratorId = ? AND permissionKey = ?" - const result = await database.query(sql, [adminId, permissionKey]) + const result = await database.pool.query(sql, [adminId, permissionKey]) return result.affectedRows > 0 } catch (error) { @@ -74,7 +74,7 @@ async function getAdminPermissions(adminId) { FROM apiAdministratorsPermissions WHERE administratorId = ? ` - const rows = await database.query(sql, [adminId]) + const rows = await database.pool.query(sql, [adminId]) return rows.map(r => r.permissionKey) } catch (error) { return utils.handleDBError(error) @@ -84,7 +84,7 @@ async function getAdminPermissions(adminId) { async function updateAdminPassword(adminId, newHashedPassword) { try { const sql = "UPDATE apiAdministrators SET password = ? WHERE id = ?" - const result = await database.query(sql, [newHashedPassword, adminId]) + const result = await database.pool.query(sql, [newHashedPassword, adminId]) if (result.affectedRows > 0) { return { @@ -102,7 +102,7 @@ async function updateAdminPassword(adminId, newHashedPassword) { async function getAdminByUsername(username) { try { const sql = "SELECT id, username, password, createdAt FROM apiAdministrators WHERE username = ?" - const rows = await database.query(sql, [username]) + const rows = await database.pool.query(sql, [username]) return rows[0] || null } catch (error) { @@ -114,7 +114,7 @@ async function addPlayerAction(playerUuid, actionCode) { try { const cleanUuid = playerUuid.replace(/-/g, "") const sql = "INSERT IGNORE INTO playerProfileActions (uuid, action) VALUES (?, ?)" - const result = await database.query(sql, [cleanUuid, actionCode]) + const result = await database.pool.query(sql, [cleanUuid, actionCode]) return { code: 200, diff --git a/repositories/authRepository.js b/repositories/authRepository.js index b276d7f..bbd9a26 100644 --- a/repositories/authRepository.js +++ b/repositories/authRepository.js @@ -6,7 +6,7 @@ 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 rows = await database.pool.query(sql, [identifier, identifier, identifier]) const user = rows[0] if (!user) { throw new DefaultError(404, "User not found") @@ -28,7 +28,7 @@ async function register(email, username, password) { 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]) + const result = await database.pool.query(sql, [email, username, hashedPassword, uuid]) if (result.affectedRows > 0) { return { code: 200, email, username, uuid } } else { @@ -42,7 +42,7 @@ async function register(email, username, password) { 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]) + const result = await database.pool.query(sql, [accessToken, clientToken, uuid]) if (result.affectedRows > 0) { return { code: 204, accessToken, clientToken } @@ -57,7 +57,7 @@ async function insertClientSession(accessToken, clientToken, uuid) { async function getPlayerProperties(uuid) { try { const sql = `SELECT * FROM playersProperties WHERE uuid = ?` - const properties = await database.query(sql, [uuid]) + const properties = await database.pool.query(sql, [uuid]) if (properties.length === 0) { throw new DefaultError(404, "Properties not found for this user.", "InternalServerError") @@ -71,7 +71,7 @@ async function getPlayerProperties(uuid) { async function getClientSession(accessToken, clientToken) { try { const sql = `SELECT * FROM clientSessions WHERE accessToken = ? AND clientToken = ?` - const rows = await database.query(sql, [accessToken, clientToken]) + const rows = await database.pool.query(sql, [accessToken, clientToken]) const session = rows[0] if (session) { @@ -90,7 +90,7 @@ async function getClientSession(accessToken, clientToken) { async function validateClientSession(accessToken, clientToken) { try { const sql = `SELECT * FROM clientSessions WHERE accessToken = ? AND clientToken = ?` - const rows = await database.query(sql, [accessToken, clientToken]) + const rows = await database.pool.query(sql, [accessToken, clientToken]) const session = rows[0] if (session) { @@ -109,7 +109,7 @@ async function validateClientSession(accessToken, clientToken) { async function validateClientSessionWithoutClientToken(accessToken) { try { const sql = `SELECT * FROM clientSessions WHERE accessToken = ?` - const rows = await database.query(sql, [accessToken]) + const rows = await database.pool.query(sql, [accessToken]) const session = rows[0] if (session) { @@ -128,7 +128,7 @@ async function validateClientSessionWithoutClientToken(accessToken) { async function invalidateClientSession(accessToken, clientToken) { try { const sql = `DELETE FROM clientSessions WHERE accessToken = ? AND clientToken = ?` - const result = await database.query(sql, [accessToken, clientToken]) + const result = await database.pool.query(sql, [accessToken, clientToken]) if (result.affectedRows > 0) { return { @@ -146,7 +146,7 @@ async function invalidateClientSession(accessToken, clientToken) { async function revokeAccessTokens(uuid) { try { const sql = `DELETE FROM clientSessions WHERE uuid = ?` - const result = await database.query(sql, [uuid]) + const result = await database.pool.query(sql, [uuid]) if (result.affectedRows > 0) { return { @@ -163,7 +163,7 @@ async function revokeAccessTokens(uuid) { async function getUsernamesRules() { try { - const rows = await database.query("SELECT rule, type FROM usernameRules") + const rows = await database.pool.query("SELECT rule, type FROM usernameRules") return rows.map(row => { if (row.type === 1) { return { type: "regex", pattern: new RegExp(row.rule, "i") } diff --git a/repositories/oauth2Repository.js b/repositories/oauth2Repository.js index 12b6658..15a7d2c 100644 --- a/repositories/oauth2Repository.js +++ b/repositories/oauth2Repository.js @@ -8,7 +8,7 @@ async function createLinkAttempt(OAuth2LinkId, playerUuid) { VALUES (?, ?) ON DUPLICATE KEY UPDATE playerUuid = VALUES(playerUuid), createdAt = NOW() ` - const result = await database.query(sql, [OAuth2LinkId, playerUuid]) + const result = await database.pool.query(sql, [OAuth2LinkId, playerUuid]) return result.affectedRows > 0 } catch (error) { return utils.handleDBError(error) @@ -18,14 +18,14 @@ async function createLinkAttempt(OAuth2LinkId, playerUuid) { async function popLinkAttempt(OAuth2LinkId) { try { const selectSql = "SELECT playerUuid FROM oaauth2LinkAttempts WHERE OAuth2LinkId = ?" - const rows = await database.query(selectSql, [OAuth2LinkId]) + const rows = await database.pool.query(selectSql, [OAuth2LinkId]) if (rows.length === 0) return null const playerUuid = rows[0].playerUuid const deleteSql = "DELETE FROM oaauth2LinkAttempts WHERE OAuth2LinkId = ?" - await database.query(deleteSql, [OAuth2LinkId]) + await database.pool.query(deleteSql, [OAuth2LinkId]) return playerUuid } catch (error) { @@ -36,7 +36,7 @@ async function popLinkAttempt(OAuth2LinkId) { async function unlinkProviderAccount(provider, playerUuid) { try { const sql = `DELETE FROM playersProperties WHERE name = '${provider}Id' AND uuid = ?` - const result = await database.query(sql, [playerUuid]) + const result = await database.pool.query(sql, [playerUuid]) return result.affectedRows > 0 } catch (error) { diff --git a/repositories/sessionsRepository.js b/repositories/sessionsRepository.js index 6aecc75..0ef5970 100644 --- a/repositories/sessionsRepository.js +++ b/repositories/sessionsRepository.js @@ -4,10 +4,10 @@ const { DefaultError } = require("../errors/errors") async function insertLegacyClientSessions(sessionId, uuid) { try { - await database.query(`DELETE FROM legacyClientSessions WHERE uuid = ?`, [uuid]) + await database.pool.query(`DELETE FROM legacyClientSessions WHERE uuid = ?`, [uuid]) const sql = `INSERT INTO legacyClientSessions (sessionId, uuid) VALUES (?, ?)` - const result = await database.query(sql, [sessionId, uuid]) + const result = await database.pool.query(sql, [sessionId, uuid]) if (result.affectedRows > 0) { return { code: 200, sessionId, uuid } @@ -22,7 +22,7 @@ async function insertLegacyClientSessions(sessionId, uuid) { async function validateLegacyClientSession(sessionId, uuid) { try { const sql = `SELECT * FROM legacyClientSessions WHERE sessionId = ? AND uuid = ?` - const rows = await database.query(sql, [sessionId, uuid]) + const rows = await database.pool.query(sql, [sessionId, uuid]) const session = rows[0] if (session) { @@ -44,7 +44,7 @@ async function validateLegacyClientSession(sessionId, uuid) { async function getBlockedServers() { try { const sql = `SELECT * FROM blockedServers` - const blockedServers = await database.query(sql) + const blockedServers = await database.pool.query(sql) return { code: 200, @@ -63,7 +63,7 @@ async function getActiveSkin(uuid) { JOIN textures t ON ps.assetHash = t.hash WHERE ps.playerUuid = ? AND ps.isSelected = 1 ` - const rows = await database.query(sql, [uuid]) + const rows = await database.pool.query(sql, [uuid]) const skin = rows[0] if (!skin) { throw new DefaultError(404, "Not found", "Not found") @@ -82,7 +82,7 @@ async function getActiveCape(uuid) { JOIN textures t ON pc.assetHash = t.hash WHERE pc.playerUuid = ? AND pc.isSelected = 1 ` - const rows = await database.query(sql, [uuid]) + const rows = await database.pool.query(sql, [uuid]) const cape = rows[0] if (!cape) { throw new DefaultError(404, "Not found", "Not found") @@ -97,7 +97,7 @@ 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 rows = await database.pool.query(sql, [cleanUuid]) const actions = rows.map(row => row.action) @@ -118,7 +118,7 @@ async function saveServerSession(uuid, accessToken, serverId, ip) { ip = VALUES(ip), createdAt = CURRENT_TIMESTAMP ` - const result = await database.query(sql, [uuid, accessToken, serverId, ip]) + const result = await database.pool.query(sql, [uuid, accessToken, serverId, ip]) return { code: 200, success: result.affectedRows > 0 } } catch (error) { @@ -134,7 +134,7 @@ async function getServerSession(uuid, serverId) { WHERE uuid = ? AND serverId = ? AND createdAt > (NOW() - INTERVAL 30 SECOND) ` - const rows = await database.query(sql, [uuid, serverId]) + const rows = await database.pool.query(sql, [uuid, serverId]) const session = rows[0] if (!session) { diff --git a/repositories/userRepository.js b/repositories/userRepository.js index 1d6a194..8e6e75c 100644 --- a/repositories/userRepository.js +++ b/repositories/userRepository.js @@ -11,7 +11,7 @@ async function getSkins(uuid) { JOIN textures t ON ps.assetHash = t.hash WHERE ps.playerUuid = ? ` - const rows = await database.query(sql, [uuid]) + const rows = await database.pool.query(sql, [uuid]) return rows } catch (error) { return utils.handleDBError(error) @@ -26,7 +26,7 @@ async function getCapes(uuid) { JOIN textures t ON pc.assetHash = t.hash WHERE pc.playerUuid = ? ` - const rows = await database.query(sql, [uuid]) + const rows = await database.pool.query(sql, [uuid]) return rows } catch (error) { return utils.handleDBError(error) @@ -40,7 +40,7 @@ async function addPropertyToPlayer(key, value, uuid) { VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE value = VALUES(value) ` - const result = await database.query(sql, [key, value, uuid]) + const result = await database.pool.query(sql, [key, value, uuid]) if (result.affectedRows > 0) { return { code: 200, key, value, uuid } @@ -55,7 +55,7 @@ async function addPropertyToPlayer(key, value, uuid) { async function deletePropertyToPlayer(key, uuid) { try { const sql = `DELETE FROM playersProperties WHERE name = ? AND uuid = ?` - const result = await database.query(sql, [key, uuid]) + const result = await database.pool.query(sql, [key, uuid]) if (result.affectedRows > 0) { return { code: 200, key, uuid } @@ -70,7 +70,7 @@ async function deletePropertyToPlayer(key, uuid) { 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]) + const result = await database.pool.query(sql, [value, key, uuid]) if (result.affectedRows > 0) { return { code: 200, key, value, uuid } } else { @@ -84,7 +84,7 @@ async function updatePropertyToPlayer(key, value, uuid) { async function getPlayerProperties(uuid) { try { const sql = `SELECT * FROM playersProperties WHERE uuid = ?` - const rows = await database.query(sql, [uuid]) + const rows = await database.pool.query(sql, [uuid]) if (rows.length === 0) { throw new DefaultError(404, "Properties not found for this user") } @@ -100,7 +100,7 @@ async function getPlayerProperties(uuid) { async function getPlayerProperty(key, uuid) { try { const sql = `SELECT * FROM playersProperties WHERE name = ? AND uuid = ?` - const rows = await database.query(sql, [key, uuid]) + const rows = await database.pool.query(sql, [key, uuid]) const property = rows[0] if (!property) { throw new DefaultError(404, "Property not found for this user/key combination") @@ -114,7 +114,7 @@ async function getPlayerProperty(key, uuid) { async function getPlayerPropertyByValue(key, value) { try { const sql = `SELECT * FROM playersProperties WHERE name = ? AND value = ?` - const rows = await database.query(sql, [key, value]) + const rows = await database.pool.query(sql, [key, value]) const property = rows[0] if (!property) { @@ -140,8 +140,8 @@ async function getPlayerSettingsSchema() { preferences: {} } try { - const privilegesRows = await database.query("DESCRIBE playersPrivileges") - const preferencesRows = await database.query("DESCRIBE playersPreferences") + const privilegesRows = await database.pool.query("DESCRIBE playersPrivileges") + const preferencesRows = await database.pool.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 @@ -160,7 +160,7 @@ async function updatePlayerPreferences(uuid, updates) { 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) + const result = await database.pool.query(sql, values) if (result.affectedRows > 0) { return { code: 200, @@ -177,7 +177,7 @@ async function updatePlayerPreferences(uuid, updates) { async function getPlayerPreferences(uuid) { try { const sql = `SELECT profanityFilter FROM playersPreferences WHERE uuid = ?` - const rows = await database.query(sql, [uuid]) + const rows = await database.pool.query(sql, [uuid]) const data = rows[0] if (data) { @@ -201,7 +201,7 @@ async function getPlayerPrivileges(uuid) { FROM playersPrivileges WHERE uuid = ? ` - const rows = await database.query(sql, [uuid]) + const rows = await database.pool.query(sql, [uuid]) const data = rows[0] if (data) { return { @@ -227,7 +227,7 @@ async function updatePlayerPrivileges(uuid, updates) { 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) + const result = await database.pool.query(sql, values) if (result.affectedRows > 0) { return { code: 200, @@ -248,11 +248,11 @@ async function banUser(uuid, { reasonKey, reasonMessage, expires = null }) { } let reasonId - const reasonRows = await database.query("SELECT id FROM banReasons WHERE reasonKey = ?", [reasonKey]) + const reasonRows = await database.pool.query("SELECT id FROM banReasons WHERE reasonKey = ?", [reasonKey]) if (reasonRows.length > 0) { reasonId = reasonRows[0].id } else { - const insertReason = await database.query("INSERT INTO banReasons (reasonKey) VALUES (?)", [reasonKey]) + const insertReason = await database.pool.query("INSERT INTO banReasons (reasonKey) VALUES (?)", [reasonKey]) reasonId = insertReason.insertId } @@ -261,7 +261,7 @@ async function banUser(uuid, { reasonKey, reasonMessage, expires = null }) { INSERT INTO bans (banId, uuid, reason, reasonMessage, expires) VALUES (?, ?, ?, ?, ?) ` - const result = await database.query(insertSql, [banId, uuid, reasonId, reasonMessage || "Banned by operator", expires]) + const result = await database.pool.query(insertSql, [banId, uuid, reasonId, reasonMessage || "Banned by operator", expires]) if (result.affectedRows > 0) { return { @@ -288,7 +288,7 @@ async function unbanUser(uuid) { throw new DefaultError(400, "Missing uuid.") } const sql = "DELETE FROM bans WHERE uuid = ?" - const result = await database.query(sql, [uuid]) + const result = await database.pool.query(sql, [uuid]) if (result.affectedRows > 0) { return { code: 200, @@ -317,7 +317,7 @@ async function getPlayerBans(uuid) { WHERE b.uuid = ? ORDER BY b.expires ASC ` - const rows = await database.query(sql, [uuid]) + const rows = await database.pool.query(sql, [uuid]) if (rows.length > 0) { return { code: 200, bans: rows } @@ -332,7 +332,7 @@ async function getPlayerBans(uuid) { async function changeUsername(uuid, newName) { try { const sql = "UPDATE players SET username = ? WHERE uuid = ?" - const result = await database.query(sql, [newName, uuid]) + const result = await database.pool.query(sql, [newName, uuid]) if (result.affectedRows > 0) { return { code: 200, message: "Username changed successfully" } } else { @@ -353,7 +353,7 @@ async function createTexture(uuid, hash, type, url, alias) { INSERT INTO textures (uuid, hash, type, url, alias) VALUES (?, ?, ?, ?, ?) ` - await database.query(sql, [uuid, hash, type, url, alias]) + await database.pool.query(sql, [uuid, hash, type, url, alias]) return true } catch (error) { if (error.code === 'ER_DUP_ENTRY') { @@ -367,7 +367,7 @@ async function createTexture(uuid, hash, type, url, alias) { async function getTextureByUuid(textureUuid) { try { const sql = "SELECT hash FROM textures WHERE uuid = ?" - const rows = await database.query(sql, [textureUuid]) + const rows = await database.pool.query(sql, [textureUuid]) return rows[0] || null } catch (error) { return utils.handleDBError(error) @@ -377,7 +377,7 @@ async function getTextureByUuid(textureUuid) { async function getTextureByHash(hash) { try { const sql = "SELECT uuid FROM textures WHERE hash = ?" - const rows = await database.query(sql, [hash]) + const rows = await database.pool.query(sql, [hash]) return rows[0] } catch (error) { return utils.handleDBError(error) @@ -390,13 +390,13 @@ async function resetSkin(uuid, hash, variant) { INSERT IGNORE INTO playersSkins (playerUuid, assetHash, variant, isSelected) VALUES (?, ?, ?, 0) ` - await database.query(insertSql, [uuid, hash, variant]) + await database.pool.query(insertSql, [uuid, hash, variant]) const updateSql = ` UPDATE playersSkins SET isSelected = (assetHash = ?) WHERE playerUuid = ? ` - await database.query(updateSql, [hash, uuid]) + await database.pool.query(updateSql, [hash, uuid]) return { code: 200 } } catch (error) { return utils.handleDBError(error) @@ -406,7 +406,7 @@ async function resetSkin(uuid, hash, variant) { async function hideCape(uuid) { try { const sql = "UPDATE playersCapes SET isSelected = 0 WHERE playerUuid = ?" - await database.query(sql, [uuid]) + await database.pool.query(sql, [uuid]) return { code: 200 } } catch (error) { return utils.handleDBError(error) @@ -415,12 +415,12 @@ async function hideCape(uuid) { async function showCape(uuid, hash) { try { - await database.query( + await database.pool.query( "UPDATE playersCapes SET isSelected = 0 WHERE playerUuid = ?", [uuid] ) - const result = await database.query( + const result = await database.pool.query( "UPDATE playersCapes SET isSelected = 1 WHERE playerUuid = ? AND assetHash = ?", [uuid, hash] ) @@ -436,7 +436,7 @@ async function showCape(uuid, hash) { async function checkCapeOwnership(uuid, hash) { try { const sql = "SELECT 1 FROM playersCapes WHERE playerUuid = ? AND assetHash = ?" - const rows = await database.query(sql, [uuid, hash]) + const rows = await database.pool.query(sql, [uuid, hash]) return rows.length > 0 } catch (error) { return utils.handleDBError(error) @@ -446,7 +446,7 @@ async function checkCapeOwnership(uuid, hash) { async function getPlayerMeta(uuid) { try { const sql = `SELECT createdAt, nameChangeAllowed FROM players WHERE uuid = ?` - const rows = await database.query(sql, [uuid]) + const rows = await database.pool.query(sql, [uuid]) return rows[0] } catch (error) { return utils.handleDBError(error) @@ -462,7 +462,7 @@ async function getLastNameChange(uuid) { ORDER BY changedAt DESC LIMIT 1 ` - const rows = await database.query(sql, [uuid]) + const rows = await database.pool.query(sql, [uuid]) return rows[0] } catch (error) { return utils.handleDBError(error) @@ -472,7 +472,7 @@ async function getLastNameChange(uuid) { async function getPlayerCertificate(uuid) { try { const sql = "SELECT * FROM playerCertificates WHERE uuid = ?" - const rows = await database.query(sql, [uuid]) + const rows = await database.pool.query(sql, [uuid]) return rows[0] } catch (error) { return utils.handleDBError(error) @@ -486,7 +486,7 @@ async function savePlayerCertificate(uuid, privateKey, publicKey, signatureV2, e (uuid, privateKey, publicKey, publicKeySignatureV2, expiresAt, refreshedAfter) VALUES (?, ?, ?, ?, ?, ?) ` - const result = await database.query(sql, [uuid, privateKey, publicKey, signatureV2, expiresAt, refreshedAfter]) + const result = await database.pool.query(sql, [uuid, privateKey, publicKey, signatureV2, expiresAt, refreshedAfter]) return result.affectedRows > 0 } catch (error) { return utils.handleDBError(error) @@ -496,7 +496,7 @@ async function savePlayerCertificate(uuid, privateKey, publicKey, signatureV2, e async function deleteExpiredCertificates(isoDate) { try { const sql = "DELETE FROM playerCertificates WHERE expiresAt < ?" - const result = await database.query(sql, [isoDate]) + const result = await database.pool.query(sql, [isoDate]) return result.affectedRows } catch (error) { return utils.handleDBError(error) @@ -507,7 +507,7 @@ 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]) + const result = await database.pool.query(sql, [cleanUuid, actionCode]) return result.affectedRows > 0 } catch (error) { return utils.handleDBError(error) @@ -518,7 +518,7 @@ 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]) + const result = await database.pool.query(sql, [cleanUuid, actionCode]) return result.affectedRows } catch (error) { return utils.handleDBError(error) @@ -529,7 +529,7 @@ 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]) + const rows = await database.pool.query(sql, [cleanUuid]) return rows.map(r => r.action) } catch (error) { return utils.handleDBError(error) @@ -540,7 +540,7 @@ async function clearAllPlayerActions(uuid) { try { const cleanUuid = uuid.replace(/-/g, "") const sql = "DELETE FROM playerProfileActions WHERE uuid = ?" - const result = await database.query(sql, [cleanUuid]) + const result = await database.pool.query(sql, [cleanUuid]) return result.affectedRows } catch (error) { return utils.handleDBError(error) @@ -550,7 +550,7 @@ async function clearAllPlayerActions(uuid) { async function blockPlayer(blockerUuid, blockedUuid) { try { const sql = `INSERT IGNORE INTO playersBlockslist (blockerUuid, blockedUuid) VALUES (?, ?)` - const result = await database.query(sql, [blockerUuid, blockedUuid]) + const result = await database.pool.query(sql, [blockerUuid, blockedUuid]) return result.affectedRows > 0 } catch (error) { return utils.handleDBError(error) @@ -560,7 +560,7 @@ async function blockPlayer(blockerUuid, blockedUuid) { async function unblockPlayer(blockerUuid, blockedUuid) { try { const sql = `DELETE FROM playersBlockslist WHERE blockerUuid = ? AND blockedUuid = ?` - const result = await database.query(sql, [blockerUuid, blockedUuid]) + const result = await database.pool.query(sql, [blockerUuid, blockedUuid]) return result.affectedRows > 0 } catch (error) { return utils.handleDBError(error) @@ -570,7 +570,7 @@ async function unblockPlayer(blockerUuid, blockedUuid) { async function getBlockedUuids(blockerUuid) { try { const sql = `SELECT blockedUuid FROM playersBlockslist WHERE blockerUuid = ?` - const rows = await database.query(sql, [blockerUuid]) + const rows = await database.pool.query(sql, [blockerUuid]) return rows.map(r => r.blockedUuid) } catch (error) { return utils.handleDBError(error) @@ -580,7 +580,7 @@ async function getBlockedUuids(blockerUuid) { 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]) + const rows = await database.pool.query(sql, [blockerUuid, targetUuid]) return rows.length > 0 } catch (error) { return utils.handleDBError(error) @@ -595,7 +595,7 @@ async function getUsersByNames(usernames) { const placeholders = uniqueNames.map(() => "?").join(", ") const sql = `SELECT uuid, username FROM players WHERE username IN (${placeholders})` - const rows = await database.query(sql, uniqueNames) + const rows = await database.pool.query(sql, uniqueNames) return rows } catch (error) { return utils.handleDBError(error) @@ -605,7 +605,7 @@ async function getUsersByNames(usernames) { async function getUuidAndUsername(username) { try { const sql = "SELECT uuid, username FROM players WHERE username = ?" - const rows = await database.query(sql, [username]) + const rows = await database.pool.query(sql, [username]) return rows[0] || null } catch (error) { @@ -616,7 +616,7 @@ async function getUuidAndUsername(username) { async function getProfileByUsername(username) { try { const sql = "SELECT uuid, username FROM players WHERE username = ?" - const rows = await database.query(sql, [username]) + const rows = await database.pool.query(sql, [username]) return rows[0] || null } catch (error) { return utils.handleDBError(error) @@ -633,7 +633,7 @@ async function getProfileByHistory(username, isoDate) { ORDER BY changedAt DESC LIMIT 1 ` - const rows = await database.query(sql, [username, isoDate]) + const rows = await database.pool.query(sql, [username, isoDate]) return rows[0] || null } catch (error) { return utils.handleDBError(error) @@ -648,7 +648,7 @@ async function getNameHistory(uuid) { WHERE uuid = ? ORDER BY changedAt ASC ` - const rows = await database.query(sql, [uuid]) + const rows = await database.pool.query(sql, [uuid]) return rows } catch (error) { return utils.handleDBError(error) @@ -658,14 +658,14 @@ async function getNameHistory(uuid) { async function setSkin(uuid, hash, variant) { try { const resetSql = `UPDATE playersSkins SET isSelected = 0 WHERE playerUuid = ?` - await database.query(resetSql, [uuid]) + await database.pool.query(resetSql, [uuid]) const upsertSql = ` INSERT INTO playersSkins (playerUuid, assetHash, variant, isSelected) VALUES (?, ?, ?, 1) ON DUPLICATE KEY UPDATE isSelected = 1, variant = VALUES(variant) ` - await database.query(upsertSql, [uuid, hash, variant.toUpperCase()]) + await database.pool.query(upsertSql, [uuid, hash, variant.toUpperCase()]) return true } catch (error) { @@ -676,7 +676,7 @@ async function setSkin(uuid, hash, variant) { async function updatePassword(uuid, hashedPassword) { try { const sql = "UPDATE players SET password = ? WHERE uuid = ?" - const result = await database.query(sql, [hashedPassword, uuid]) + const result = await database.pool.query(sql, [hashedPassword, uuid]) if (result.affectedRows > 0) { return { code: 200, message: "Password updated successfully" } @@ -694,7 +694,7 @@ async function addCapeToPlayer(uuid, hash) { INSERT INTO playersCapes (playerUuid, assetHash, isSelected) VALUES (?, ?, 0) ` - const result = await database.query(sql, [uuid, hash]) + const result = await database.pool.query(sql, [uuid, hash]) if (result.affectedRows > 0) { return { code: 200, message: "Cape granted to the player." } @@ -711,7 +711,7 @@ async function addCapeToPlayer(uuid, hash) { async function removeCapeFromPlayer(uuid, hash) { try { const sql = "DELETE FROM playersCapes WHERE playerUuid = ? AND assetHash = ?" - const result = await database.query(sql, [uuid, hash]) + const result = await database.pool.query(sql, [uuid, hash]) if (result.affectedRows > 0) { return { code: 200, message: "Cape removed from player." } @@ -726,7 +726,7 @@ async function removeCapeFromPlayer(uuid, hash) { async function deleteTexture(hash) { try { const sql = "DELETE FROM textures WHERE hash = ?" - const result = await database.query(sql, [hash]) + const result = await database.pool.query(sql, [hash]) return result.affectedRows > 0 } catch (error) { return utils.handleDBError(error) diff --git a/server.js b/server.js index 9fd49be..81af59d 100644 --- a/server.js +++ b/server.js @@ -3,22 +3,16 @@ const hpp = require("hpp") const app = express() const cors = require("cors") const path = require("node:path") -const utils = require("./modules/utils") const logger = require("./modules/logger") const helmet = require("helmet") const loader = require("./modules/loader") -const DefaultError = require("./errors/DefaultError") const path2regex = require("path-to-regexp") -const databaseGlobals = require("./modules/databaseGlobals") -const certificates = require("./modules/certificatesManager") const { ValidationError } = require("./errors/errors") const routes = loader.getRecursiveFiles(path.join(__dirname, "routes")) const schemas = loader.getRecursiveFiles(path.join(__dirname, "schemas")) const schemaRegistry = {} -databaseGlobals.setupDatabase() -certificates.setupKeys() app.use(hpp()) app.use(helmet({