132 lines
4.0 KiB
Lua
132 lines
4.0 KiB
Lua
-- Prevent running in monitor mode
|
|
if not TX_SERVER_MODE then return end
|
|
|
|
if TX_LUACOMHOST == "invalid" or TX_LUACOMTOKEN == "invalid" then
|
|
txPrint('^1API Host or Pipe Token ConVars not found. Do not start this resource if not using txAdmin.')
|
|
return
|
|
end
|
|
if TX_LUACOMTOKEN == "removed" then
|
|
txPrint('^1Please do not restart the monitor resource.')
|
|
return
|
|
end
|
|
|
|
|
|
-- =============================================
|
|
-- Lua Admin Manager
|
|
-- =============================================
|
|
|
|
-- Variables & Consts
|
|
local failedAuths = {}
|
|
local attemptCooldown = 15000
|
|
|
|
|
|
-- Handle auth failures
|
|
local function handleAuthFail(src, reason)
|
|
local srcString = tostring(src)
|
|
TX_ADMINS[srcString] = nil
|
|
failedAuths[srcString] = GetGameTimer()
|
|
reason = reason or "unknown"
|
|
debugPrint("Auth rejected #"..srcString.." ("..reason..")")
|
|
TriggerClientEvent('txcl:setAdmin', src, false, false, reason)
|
|
TriggerEvent('txAdmin:events:adminAuth', {
|
|
netid = src,
|
|
isAdmin = false,
|
|
})
|
|
end
|
|
|
|
-- Handle menu auth requests
|
|
RegisterNetEvent('txsv:checkIfAdmin', function()
|
|
local src = source
|
|
local srcString = tostring(source)
|
|
debugPrint('Handling authentication request from player #'..srcString)
|
|
|
|
-- Rate Limiter
|
|
if type(failedAuths[srcString]) == 'number' and failedAuths[srcString] + attemptCooldown > GetGameTimer() then
|
|
return handleAuthFail(source, "too many auth attempts")
|
|
end
|
|
|
|
-- Prepping http request
|
|
local url = "http://"..TX_LUACOMHOST.."/auth/self"
|
|
local headers = {
|
|
['Content-Type'] = 'application/json',
|
|
['X-TxAdmin-Token'] = TX_LUACOMTOKEN,
|
|
['X-TxAdmin-Identifiers'] = table.concat(GetPlayerIdentifiers(src), ',')
|
|
}
|
|
|
|
-- Making http request
|
|
PerformHttpRequest(url, function(httpCode, data, resultHeaders)
|
|
-- Validating response
|
|
local resp = json.decode(data)
|
|
if not resp then
|
|
return handleAuthFail(src, "invalid response")
|
|
end
|
|
if resp.logout ~= nil and resp.logout then
|
|
return handleAuthFail(src, resp.reason or 'unknown reject reason')
|
|
end
|
|
if type(resp.name) ~= "string" then
|
|
return handleAuthFail(src, "invalid response")
|
|
end
|
|
if type(resp.permissions) ~= 'table' then
|
|
resp.permissions = {}
|
|
end
|
|
|
|
-- Setting up admin
|
|
local adminTag = "[#"..src.."] "..resp.name
|
|
debugPrint(("^2Authenticated admin ^5%s^2 with permissions: %s"):format(
|
|
src,
|
|
adminTag,
|
|
json.encode(resp.permissions)
|
|
))
|
|
TX_ADMINS[srcString] = {
|
|
tag = adminTag,
|
|
username = resp.name,
|
|
perms = resp.permissions,
|
|
bucket = 0
|
|
}
|
|
sendInitialPlayerlist(src)
|
|
TriggerClientEvent('txcl:setAdmin', src, resp.name, resp.permissions)
|
|
TriggerEvent('txAdmin:events:adminAuth', {
|
|
netid = src,
|
|
isAdmin = true,
|
|
username = resp.name,
|
|
})
|
|
end, 'GET', '', headers)
|
|
end)
|
|
|
|
|
|
-- Remove admin from table when disconnected
|
|
AddEventHandler('playerDropped', function()
|
|
TX_ADMINS[tostring(source)] = nil
|
|
end)
|
|
|
|
|
|
-- Handle updated admin list
|
|
AddEventHandler('txAdmin:events:adminsUpdated', function(onlineAdminIDs)
|
|
debugPrint('^3Admins list updated. Online admins: ' .. json.encode(onlineAdminIDs))
|
|
|
|
-- Collect old and new admin IDs as key to prevent duplicate
|
|
local refreshAdminIds = {}
|
|
for id, _ in pairs(TX_ADMINS) do
|
|
refreshAdminIds[id] = true
|
|
end
|
|
for _, id in pairs(onlineAdminIDs) do
|
|
refreshAdminIds[tostring(id)] = true
|
|
end
|
|
debugPrint('^3Forcing clients to re-auth')
|
|
|
|
-- Resetting all admin permissions and rate limiter
|
|
TX_ADMINS = {}
|
|
failedAuths = {}
|
|
|
|
-- Informing clients that they need to reauth
|
|
for id, _ in pairs(refreshAdminIds) do
|
|
TriggerClientEvent('txcl:reAuth', tonumber(id))
|
|
end
|
|
|
|
-- Broadcasting the invalidation of all admins
|
|
TriggerEvent('txAdmin:events:adminAuth', {
|
|
netid = -1,
|
|
isAdmin = false,
|
|
})
|
|
end)
|