From e39fe891400d10ecd665015c4595ad20628b6145 Mon Sep 17 00:00:00 2001 From: Kasey FItton Date: Thu, 11 Jul 2024 18:53:27 +0100 Subject: [PATCH 1/4] feat(server): SQL error handling --- locale/en.lua | 1 + server/events.lua | 22 ++++++++++++++++++++++ server/functions.lua | 27 +++++++++++++++++++++++++++ 3 files changed, 50 insertions(+) diff --git a/locale/en.lua b/locale/en.lua index a03be6c..8037338 100644 --- a/locale/en.lua +++ b/locale/en.lua @@ -17,6 +17,7 @@ local Translations = { no_permission = 'You don\'t have permissions for this..', no_waypoint = 'No Waypoint Set.', tp_error = 'Error While Teleporting.', + ban_table_not_found = '[QBCORE] - Unable to find the bans table in the database. Please ensure you have imported the SQL file correctly.', connecting_database_error = '[QBCORE] - A database error occurred while connecting to the server. (Is the SQL server on?)', connecting_database_timeout = '[QBCORE] - Connection to database timed out. (Is the SQL server on?)', }, diff --git a/server/events.lua b/server/events.lua index 49ec40f..0c7f168 100644 --- a/server/events.lua +++ b/server/events.lua @@ -20,6 +20,20 @@ end) -- Player Connecting +local databaseConnected = false +local bansTableExists = false +MySQL.Ready(function() + databaseConnected = true + + local DatabaseInfo = QBCore.Functions.GetDatabaseInfo() + if not DatabaseInfo or not DatabaseInfo.exists then return end + + local result = MySQL.query.await('SELECT * FROM information_schema.tables WHERE table_schema = "%s" AND table_name = "bans";', {DatabaseInfo.database}) + if result and result[1] then + bansTableExists = true + end +end) + local function onPlayerConnecting(name, _, deferrals) local src = source deferrals.defer() @@ -28,6 +42,10 @@ local function onPlayerConnecting(name, _, deferrals) return deferrals.done(QBCore.Config.Server.ClosedReason) end + if not databaseConnected then + return deferrals.done(Lang:t('error.connecting_database_error')) + end + if QBCore.Config.Server.Whitelist then Wait(0) deferrals.update(string.format(Lang:t('info.checking_whitelisted'), name)) @@ -49,6 +67,10 @@ local function onPlayerConnecting(name, _, deferrals) Wait(0) deferrals.update(string.format(Lang:t('info.checking_ban'), name)) + if not bansTableExists then + return deferrals.done(Lang:t('error.ban_table_not_found')) + end + local success, isBanned, reason = pcall(QBCore.Functions.IsPlayerBanned, src) if not success then return deferrals.done(Lang:t('error.connecting_database_error')) end if isBanned then return deferrals.done(reason) end diff --git a/server/functions.lua b/server/functions.lua index 3f7689d..ec46217 100644 --- a/server/functions.lua +++ b/server/functions.lua @@ -623,6 +623,33 @@ function QBCore.Functions.IsPlayerBanned(source) return false end +function QBCore.Functions.GetDatabaseInfo() + local details = { + exists = false, + database = "", + } + local connectionString = GetConvar("mysql_connection_string", "") + + if connectionString == "" then + return details + elseif connectionString:find("mysql://") then + connectionString = connectionString:sub(9, -1) + details.database = connectionString:sub(connectionString:find("/") + 1, -1):gsub("[%?]+[%w%p]*$", "") + details.exists = true + else + connectionString = { string.strsplit(";", connectionString) } + + for i = 1, #connectionString do + local v = connectionString[i] + if v:match("database") then + details.database = v:sub(10, #v) + details.exists = true + break + end + end + end +end + ---Check for duplicate license ---@param license any ---@return boolean From be3bbb8abf3f5c0bd321e6f974659ab4d95e4557 Mon Sep 17 00:00:00 2001 From: Kasey FItton Date: Fri, 12 Jul 2024 00:24:17 +0100 Subject: [PATCH 2/4] fix(server/events): error handle MySQL.ready --- server/events.lua | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/server/events.lua b/server/events.lua index 0c7f168..34f27b9 100644 --- a/server/events.lua +++ b/server/events.lua @@ -19,20 +19,21 @@ AddEventHandler('playerDropped', function(reason) end) -- Player Connecting - -local databaseConnected = false -local bansTableExists = false -MySQL.Ready(function() - databaseConnected = true - - local DatabaseInfo = QBCore.Functions.GetDatabaseInfo() - if not DatabaseInfo or not DatabaseInfo.exists then return end +local readyFunction = MySQL.ready +local databaseConnected, bansTableExists = readyFunction == nil, readyFunction == nil +if readyFunction ~= nil then + MySQL.ready(function() + databaseConnected = true - local result = MySQL.query.await('SELECT * FROM information_schema.tables WHERE table_schema = "%s" AND table_name = "bans";', {DatabaseInfo.database}) - if result and result[1] then - bansTableExists = true - end -end) + local DatabaseInfo = QBCore.Functions.GetDatabaseInfo() + if not DatabaseInfo or not DatabaseInfo.exists then return end + + local result = MySQL.query.await('SELECT * FROM information_schema.tables WHERE table_schema = "%s" AND table_name = "bans";', {DatabaseInfo.database}) + if result and result[1] then + bansTableExists = true + end + end) +end local function onPlayerConnecting(name, _, deferrals) local src = source From 1a5d0fe1b58aec729f5f2d1372e8c73a5eb442b0 Mon Sep 17 00:00:00 2001 From: Kasey FItton Date: Fri, 12 Jul 2024 00:27:33 +0100 Subject: [PATCH 3/4] tweak(locale/en): better SQL error messaging --- locale/en.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/locale/en.lua b/locale/en.lua index 8037338..2c17a26 100644 --- a/locale/en.lua +++ b/locale/en.lua @@ -18,8 +18,8 @@ local Translations = { no_waypoint = 'No Waypoint Set.', tp_error = 'Error While Teleporting.', ban_table_not_found = '[QBCORE] - Unable to find the bans table in the database. Please ensure you have imported the SQL file correctly.', - connecting_database_error = '[QBCORE] - A database error occurred while connecting to the server. (Is the SQL server on?)', - connecting_database_timeout = '[QBCORE] - Connection to database timed out. (Is the SQL server on?)', + connecting_database_error = '[QBCORE] - An error occurred while connecting to the database. Ensure that the SQL server is running and that the details in the server.cfg file are correct.', + connecting_database_timeout = '[QBCORE] - The database connection has timed out. Ensure that the SQL server is running and that the details in the server.cfg file are correct.', }, success = { server_opened = 'The server has been opened', From e1aa208b6174bbb3b1b82a50af7a14e9f868c5d1 Mon Sep 17 00:00:00 2001 From: Kasey FItton Date: Fri, 12 Jul 2024 01:06:48 +0100 Subject: [PATCH 4/4] fix(server/functions): return database details correctly --- server/events.lua | 4 ++-- server/functions.lua | 5 ++++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/server/events.lua b/server/events.lua index 34f27b9..793271e 100644 --- a/server/events.lua +++ b/server/events.lua @@ -27,8 +27,8 @@ if readyFunction ~= nil then local DatabaseInfo = QBCore.Functions.GetDatabaseInfo() if not DatabaseInfo or not DatabaseInfo.exists then return end - - local result = MySQL.query.await('SELECT * FROM information_schema.tables WHERE table_schema = "%s" AND table_name = "bans";', {DatabaseInfo.database}) + + local result = MySQL.query.await('SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCEMA = ? AND TABLE_NAME = "bans";', {DatabaseInfo.database}) if result and result[1] then bansTableExists = true end diff --git a/server/functions.lua b/server/functions.lua index ec46217..c4ae93b 100644 --- a/server/functions.lua +++ b/server/functions.lua @@ -623,6 +623,8 @@ function QBCore.Functions.IsPlayerBanned(source) return false end +-- Retrieves information about the database connection. +--- @return table; A table containing the database information. function QBCore.Functions.GetDatabaseInfo() local details = { exists = false, @@ -636,6 +638,7 @@ function QBCore.Functions.GetDatabaseInfo() connectionString = connectionString:sub(9, -1) details.database = connectionString:sub(connectionString:find("/") + 1, -1):gsub("[%?]+[%w%p]*$", "") details.exists = true + return details else connectionString = { string.strsplit(";", connectionString) } @@ -644,7 +647,7 @@ function QBCore.Functions.GetDatabaseInfo() if v:match("database") then details.database = v:sub(10, #v) details.exists = true - break + return details end end end