minetest-verbana/data.lua

701 lines
28 KiB
Lua
Raw Normal View History

2019-07-07 17:59:32 -07:00
verbana.data = {}
local lib_asn = verbana.lib_asn
local lib_ip = verbana.lib_ip
2019-07-07 19:18:59 -07:00
local log = verbana.log
2019-06-04 23:39:56 -07:00
2019-06-11 15:37:57 -07:00
local sql = verbana.sql
local db = verbana.db
2019-06-04 23:39:56 -07:00
2019-06-25 22:16:29 -07:00
-- constants
2019-06-20 01:59:39 -07:00
verbana.data.player_status = {
unknown={name='unknown', id=1},
default={name='default', id=2},
unverified={name='unverified', id=3},
banned={name='banned', id=4},
tempbanned={name='tempbanned', id=5},
locked={name='locked', id=6},
whitelisted={name='whitelisted', id=7},
suspicious={name='suspicious', id=8},
2019-06-25 22:16:29 -07:00
kicked={name='kicked', id=9},
2019-06-11 15:37:57 -07:00
}
2019-06-20 01:59:39 -07:00
verbana.data.ip_status = {
default={name='default', id=1},
trusted={name='trusted', id=2},
suspicious={name='suspicious', id=3},
blocked={name='blocked', id=4},
tempblocked={name='tempblocked', id=5},
2019-06-11 15:37:57 -07:00
}
2019-06-20 01:59:39 -07:00
verbana.data.asn_status = {
default={name='default', id=1},
suspicious={name='suspicious', id=2},
blocked={name='blocked', id=3},
tempblocked={name='tempblocked', id=4},
2019-06-11 15:37:57 -07:00
}
verbana.data.verbana_player = '!verbana!'
verbana.data.verbana_player_id = 1
2019-06-25 22:16:29 -07:00
-- wrap sqllite API to make error reporting less messy
2019-06-15 20:52:08 -07:00
local function execute(code, description)
if db:exec(code) ~= sql.OK then
2019-07-07 19:18:59 -07:00
log('error', 'executing %s %q: %s', description, code, db:errmsg())
2019-06-04 23:39:56 -07:00
return false
end
return true
end
2019-06-15 20:52:08 -07:00
local function prepare(code, description)
local statement = db:prepare(code)
if not statement then
2019-07-07 19:18:59 -07:00
log('error', 'preparing %s %q: %s', description, code, db:errmsg())
2019-06-15 20:52:08 -07:00
return nil
end
return statement
end
2019-06-11 15:37:57 -07:00
2019-06-15 20:52:08 -07:00
local function bind(statement, description, ...)
if statement:bind_values(...) ~= sql.OK then
2019-07-07 19:18:59 -07:00
log('error', 'binding %s: %s %q', description, db:errmsg(), minetest.serialize({...}))
2019-06-15 20:52:08 -07:00
return false
2019-06-11 15:37:57 -07:00
end
2019-06-15 20:52:08 -07:00
return true
end
2019-06-04 23:39:56 -07:00
2019-06-15 20:52:08 -07:00
local function bind_and_step(statement, description, ...)
2019-06-20 01:59:39 -07:00
if not bind(statement, description, ...) then return false end
2019-06-15 20:52:08 -07:00
if statement:step() ~= sql.DONE then
2019-07-07 19:18:59 -07:00
log('error', 'stepping %s: %s %q', description, db:errmsg(), minetest.serialize({...}))
2019-06-15 20:52:08 -07:00
return false
end
statement:reset()
return true
end
2019-06-04 23:39:56 -07:00
2019-06-15 20:52:08 -07:00
local function finalize(statement, description)
if statement:finalize() ~= sql.OK then
2019-07-07 19:18:59 -07:00
log('error', 'finalizing %s: %s', description, db:errmsg())
2019-06-15 20:52:08 -07:00
return false
2019-06-11 15:37:57 -07:00
end
2019-06-15 20:52:08 -07:00
return true
end
2019-06-04 23:39:56 -07:00
2019-06-15 20:52:08 -07:00
local function execute_bind_one(code, description, ...)
2019-06-20 01:59:39 -07:00
local statement = prepare(code, description)
2019-06-15 20:52:08 -07:00
if not statement then return false end
if not bind_and_step(statement, description, ...) then return false end
if not finalize(statement, description) then return false end
return true
2019-06-11 15:37:57 -07:00
end
2019-06-04 23:39:56 -07:00
2019-06-15 20:52:08 -07:00
local function get_full_table(code, description, ...)
local statement = prepare(code, description)
if not statement then return nil end
2019-06-20 01:59:39 -07:00
if not bind(statement, description, ...) then return nil end
2019-06-15 20:52:08 -07:00
local rows = {}
for row in statement:rows() do
table.insert(rows, row)
2019-06-11 15:37:57 -07:00
end
2019-06-15 20:52:08 -07:00
if not finalize(statement, description) then return nil end
return rows
end
2019-06-04 23:39:56 -07:00
2019-06-20 01:59:39 -07:00
local function get_full_ntable(code, description, ...)
local statement = prepare(code, description)
if not statement then return nil end
if not bind(statement, description, ...) then return nil end
local rows = {}
for row in statement:nrows() do
table.insert(rows, row)
end
if not finalize(statement, description) then return nil end
return rows
end
2019-06-25 22:16:29 -07:00
local function sort_status_table(data)
local sortable = {}
for _, value in pairs(data) do table.insert(sortable, value) end
table.sort(sortable, function (a, b) return a.id < b.id end)
return sortable
end
local function init_status_table(table_name, data)
local status_sql = ('INSERT OR IGNORE INTO %s_status (id, name) VALUES (?, ?)'):format(table_name)
local status_statement = prepare(status_sql, ('initialize %s_status'):format(table_name))
if not status_statement then return false end
2019-07-07 19:18:59 -07:00
for _, status in ipairs(sort_status_table(data)) do
2019-06-25 22:16:29 -07:00
if not bind_and_step(status_statement, 'insert status', status.id, status.name) then
return false
end
end
if not finalize(status_statement, 'insert status') then
return false
end
return true
end
local function init_db()
local schema = verbana.util.load_file(verbana.modpath .. '/schema.sql')
if not schema then
error(('Could not find Verbana schema at %q'):format(verbana.modpath .. '/schema.sql'))
end
if db:exec(schema) ~= sql.OK then
error(('Verbana failed to initialize the database: %s'):format(db:error_message()))
end
if not init_status_table('player', verbana.data.player_status) then
error('error initializing player_status: see server log')
end
if not init_status_table('ip', verbana.data.ip_status) then
error('error initializing ip_status: see server log')
end
if not init_status_table('asn', verbana.data.asn_status) then
error('error initializing asn_status: see server log')
end
local verbana_player_sql = 'INSERT OR IGNORE INTO player (name) VALUES (?)'
if not execute_bind_one(verbana_player_sql, 'verbana player', verbana.data.verbana_player) then
error('error initializing verbana internal player: see server log')
end
end
init_db()
---- data API -----
2019-06-11 15:37:57 -07:00
function verbana.data.import_from_sban(filename)
2019-06-20 01:59:39 -07:00
-- apologies for the very long method
2019-06-15 20:52:08 -07:00
local start = os.clock()
if not execute('BEGIN TRANSACTION', 'sban import transaction') then
return false
end
2019-06-11 15:37:57 -07:00
local sban_db, _, errormsg = sql.open(filename, sql.OPEN_READONLY)
if not sban_db then
2019-07-07 19:18:59 -07:00
log('error', 'Error opening %s: %s', filename, errormsg)
2019-06-15 20:52:08 -07:00
return false
2019-06-11 15:37:57 -07:00
end
2019-06-15 20:52:08 -07:00
local function _error(message, ...)
if message then
2019-07-07 19:18:59 -07:00
log('error', message, ...)
end
2019-06-15 20:52:08 -07:00
execute('ROLLBACK', 'sban import rollback')
if sban_db:close() ~= sql.OK then
2019-07-07 19:18:59 -07:00
log('error', 'closing sban DB %s', sban_db:errmsg())
end
2019-06-15 20:52:08 -07:00
return false
end
2019-06-15 20:52:08 -07:00
-- IMPORT INTO VERBANA --
local insert_player_statement = prepare('INSERT OR IGNORE INTO player (name) VALUES (?)', 'insert player')
if not insert_player_statement then return _error() end
for name in sban_db:urows('SELECT DISTINCT name FROM playerdata') do
if not bind_and_step(insert_player_statement, 'insert player', name) then
return _error()
end
end
2019-06-15 20:52:08 -07:00
if not finalize(insert_player_statement, 'insert player') then return _error() end
-- GET VERBANA PLAYER IDS --
local player_id_by_name = {}
for id, name in db:urows('SELECT id, name FROM player') do
player_id_by_name[name] = id
end
2019-06-20 01:59:39 -07:00
-- ips, asns, associations, and logs --
2019-06-15 20:52:08 -07:00
local insert_ip_statement = prepare('INSERT OR IGNORE INTO ip (ip) VALUES (?)', 'insert IP')
if not insert_ip_statement then return _error() end
local insert_asn_statement = prepare('INSERT OR IGNORE INTO asn (asn) VALUES (?)', 'insert ASN')
if not insert_asn_statement then return _error() end
2019-06-25 22:16:29 -07:00
local insert_assoc_statement = prepare('INSERT OR IGNORE INTO assoc (player_id, ip, asn, first_seen, last_seen) VALUES (?, ?, ?, ?, ?)', 'insert assoc')
2019-06-15 20:52:08 -07:00
if not insert_assoc_statement then return _error() end
2019-06-20 01:59:39 -07:00
local insert_log_statement = prepare('INSERT OR IGNORE INTO connection_log (player_id, ip, asn, success, timestamp) VALUES (?, ?, ?, ?, ?)', 'insert connection log')
2019-06-15 20:52:08 -07:00
if not insert_log_statement then return _error() end
for name, ipstr, created, last_login in sban_db:urows('SELECT name, ip, created, last_login FROM playerdata') do
local player_id = player_id_by_name[name]
2019-07-07 17:59:32 -07:00
if not lib_ip.is_valid_ip(ipstr) then
2019-06-15 20:52:08 -07:00
return _error('%s is not a valid IPv4 address', ipstr)
end
2019-07-07 17:59:32 -07:00
local ipint = lib_ip.ipstr_to_ipint(ipstr)
local asn = lib_asn.lookup(ipint)
2019-06-15 20:52:08 -07:00
if not bind_and_step(insert_ip_statement, 'insert IP', ipint) then return _error() end
if not bind_and_step(insert_asn_statement, 'insert ASN', asn) then return _error() end
2019-06-25 22:16:29 -07:00
if not bind_and_step(insert_assoc_statement, 'insert assoc', player_id, ipint, asn, created, created) then return _error() end
2019-06-20 01:59:39 -07:00
if not bind_and_step(insert_log_statement, 'insert connection log', player_id, ipint, asn, true, created) then return _error() end
end
2019-06-15 20:52:08 -07:00
if not finalize(insert_ip_statement, 'insert IP') then return _error() end
if not finalize(insert_asn_statement, 'insert ASN') then return _error() end
if not finalize(insert_assoc_statement, 'insert assoc') then return _error() end
2019-06-20 01:59:39 -07:00
if not finalize(insert_log_statement, 'insert connection log') then return _error() end
2019-06-15 20:52:08 -07:00
-- player status --
2019-06-20 01:59:39 -07:00
local default_player_status_id = verbana.data.player_status.default.id
local banned_player_status_id = verbana.data.player_status.banned.id
local tempbanned_player_status_id = verbana.data.player_status.tempbanned.id
2019-06-15 20:52:08 -07:00
local insert_player_status_sql = [[
INSERT OR IGNORE
2019-06-15 20:52:08 -07:00
INTO player_status_log (executor_id, player_id, status_id, timestamp, reason, expires)
VALUES (?, ?, ?, ?, ?, ?)
]]
2019-06-15 20:52:08 -07:00
local insert_player_status_statement = prepare(insert_player_status_sql, 'insert player status')
if not insert_player_status_statement then return _error() end
local select_bans_sql = [[
SELECT name, source, created, reason, expires, u_source, u_reason, u_date
FROM bans
2019-06-15 20:52:08 -07:00
ORDER BY created
]]
for name, source, created, reason, expires, u_source, u_reason, u_date in sban_db:urows(select_bans_sql) do
local player_id = player_id_by_name[name]
local source_id = player_id_by_name[source]
local unban_source_id
if u_source and u_source == 'sban' then
unban_source_id = source_id
else
unban_source_id = player_id_by_name[u_source]
end
local status_id
2019-06-15 20:52:08 -07:00
if expires and type(expires) == 'number' then
status_id = tempbanned_player_status_id
else
status_id = banned_player_status_id
2019-06-15 20:52:08 -07:00
expires = nil
end
2019-06-15 20:52:08 -07:00
-- BAN
if not bind_and_step(insert_player_status_statement, 'insert player status (ban)', source_id, player_id, status_id, created, reason, expires) then return _error() end
-- UNBAN
if unban_source_id then
2019-06-15 20:52:08 -07:00
if not bind_and_step(insert_player_status_statement, 'insert player status (unban)', unban_source_id, player_id, default_player_status_id, u_date, u_reason, nil) then return _error() end
end
end
if not finalize(insert_player_status_statement, 'insert player status') then return _error() end
-- SET LAST ACTION --
2019-06-20 01:59:39 -07:00
local set_current_status_id_sql = [[
2019-06-15 20:52:08 -07:00
UPDATE player
2019-06-20 01:59:39 -07:00
SET current_status_id = (SELECT MAX(player_status_log.id)
2019-06-15 20:52:08 -07:00
FROM player_status_log
WHERE player_status_log.player_id == player.id);
]]
2019-06-20 01:59:39 -07:00
if not execute(set_current_status_id_sql, 'set last status') then return _error() end
2019-06-15 20:52:08 -07:00
-- CLEANUP --
if not execute('COMMIT') then
if sban_db:close() ~= sql.OK then
2019-07-07 19:18:59 -07:00
log('error', 'closing sban DB %s', sban_db:errmsg())
end
2019-06-15 20:52:08 -07:00
return false
end
2019-06-15 20:52:08 -07:00
if sban_db:close() ~= sql.OK then
2019-07-07 19:18:59 -07:00
log('error', 'closing sban DB %s', sban_db:errmsg())
2019-06-15 20:52:08 -07:00
return false
end
2019-07-07 19:18:59 -07:00
log('action', 'imported from SBAN in %s seconds', os.clock() - start)
2019-06-15 20:52:08 -07:00
return true
end -- verbana.data.import_from_sban
2019-06-04 23:39:56 -07:00
2019-07-07 17:59:32 -07:00
local player_id_cache = {}
2019-06-15 20:52:08 -07:00
function verbana.data.get_player_id(name, create_if_new)
2019-07-07 17:59:32 -07:00
local cached_id = player_id_cache[name]
if cached_id then return cached_id end
2019-06-15 20:52:08 -07:00
if create_if_new then
if not execute_bind_one('INSERT OR IGNORE INTO player (name) VALUES (?)', 'insert player', name) then return nil end
end
2019-06-20 01:59:39 -07:00
local table = get_full_table('SELECT id FROM player WHERE name = ? LIMIT 1', 'get player id', name)
2019-06-15 20:52:08 -07:00
if not (table and table[1]) then return nil end
2019-07-07 17:59:32 -07:00
player_id_cache[name] = table[1][1]
2019-06-15 20:52:08 -07:00
return table[1][1]
2019-06-11 15:37:57 -07:00
end
2019-07-07 17:59:32 -07:00
local player_status_cache = {}
2019-06-20 01:59:39 -07:00
function verbana.data.get_player_status(player_id, create_if_new)
2019-07-07 17:59:32 -07:00
local cached_status = player_status_cache[player_id]
if cached_status then return cached_status end
2019-06-20 01:59:39 -07:00
local code = [[
SELECT executor.id executor_id
, executor.name executor
, status.id status_id
, status.name name
, log.timestamp timestamp
, log.reason reason
, log.expires expires
FROM player
JOIN player_status_log log ON player.current_status_id == log.id
JOIN player_status status ON log.status_id == status.id
JOIN player executor ON log.executor_id == executor.id
WHERE player.id == ?
LIMIT 1
]]
local table = get_full_ntable(code, 'get player status', player_id)
if #table == 1 then
2019-07-07 17:59:32 -07:00
player_status_cache[player_id] = table[1]
2019-06-20 01:59:39 -07:00
return table[1]
elseif #table > 1 then
2019-07-07 19:18:59 -07:00
log('error', 'somehow got more than 1 result when getting current player status for %s', player_id)
2019-06-20 01:59:39 -07:00
return nil
elseif not create_if_new then
return nil
end
if not verbana.data.set_player_status(player_id, verbana.data.verbana_player_id, verbana.data.player_status.unknown.id, 'creating initial player status') then
2019-07-07 19:18:59 -07:00
log('error', 'failed to set initial player status')
2019-06-20 01:59:39 -07:00
return nil
end
return {
executor_id=verbana.data.verbana_player_id,
executor=verbana.data.verbana_player,
status_id=verbana.data.player_status.unknown.id,
name='unknown',
timestamp=os.clock()
}
end
2019-06-25 22:16:29 -07:00
function verbana.data.set_player_status(player_id, executor_id, status_id, reason, expires, no_update_current)
2019-07-07 17:59:32 -07:00
player_status_cache[player_id] = nil
2019-06-20 01:59:39 -07:00
local code = [[
INSERT INTO player_status_log (player_id, executor_id, status_id, reason, expires, timestamp)
VALUES (?, ?, ?, ?, ?, ?)
]]
2019-07-07 19:18:59 -07:00
if not execute_bind_one(code, 'set player status', player_id, executor_id, status_id, reason, expires, os.clock()) then return false end
2019-06-25 22:16:29 -07:00
if not no_update_current then
local last_id = db:last_insert_rowid()
local code = 'UPDATE player SET current_status_id = ? WHERE id = ?'
if not execute_bind_one(code, 'update player last status id', last_id, player_id) then return false end
end
2019-06-20 01:59:39 -07:00
return true
end
2019-07-07 17:59:32 -07:00
local ip_status_cache = {}
2019-06-20 01:59:39 -07:00
function verbana.data.get_ip_status(ipint, create_if_new)
2019-07-07 17:59:32 -07:00
local cached_status = ip_status_cache[ipint]
if cached_status then return cached_status end
2019-06-20 01:59:39 -07:00
local code = [[
SELECT executor.id executor_id
, executor.name executor
, status.id status_id
, status.name name
, log.timestamp timestamp
, log.reason reason
, log.expires expires
FROM ip
JOIN ip_status_log log ON ip.current_status_id == log.id
JOIN ip_status status ON log.status_id == status.id
JOIN player executor ON log.executor_id == executor.id
WHERE ip.ip == ?
LIMIT 1
]]
local table = get_full_ntable(code, 'get ip status', ipint)
if #table == 1 then
2019-07-07 17:59:32 -07:00
ip_status_cache[ipint] = table[1]
2019-06-20 01:59:39 -07:00
return table[1]
elseif #table > 1 then
2019-07-07 19:18:59 -07:00
log('error', 'somehow got more than 1 result when getting current ip status for %s', ipint)
2019-06-20 01:59:39 -07:00
return nil
elseif not create_if_new then
return nil
end
if not verbana.data.set_ip_status(ipint, verbana.data.verbana_player_id, verbana.data.ip_status.default.id, 'creating initial ip status') then
2019-07-07 19:18:59 -07:00
log('error', 'failed to set initial ip status')
2019-06-20 01:59:39 -07:00
return nil
end
return {
executor_id=verbana.data.verbana_player_id,
executor=verbana.data.verbana_player,
status_id=verbana.data.ip_status.default.id,
name='default',
timestamp=os.clock()
}
end
function verbana.data.set_ip_status(ipint, executor_id, status_id, reason, expires)
2019-07-07 17:59:32 -07:00
ip_status_cache[ipint] = nil
2019-06-20 01:59:39 -07:00
local code = [[
INSERT INTO ip_status_log (ip, executor_id, status_id, reason, expires, timestamp)
VALUES (?, ?, ?, ?, ?, ?)
]]
2019-07-07 19:18:59 -07:00
if not execute_bind_one(code, 'set ip status', ipint, executor_id, status_id, reason, expires, os.clock()) then return false end
2019-06-20 01:59:39 -07:00
local last_id = db:last_insert_rowid()
local code = 'UPDATE ip SET current_status_id = ? WHERE ip = ?'
if not execute_bind_one(code, 'update ip last status id', last_id, ipint) then return false end
return true
end
2019-07-07 17:59:32 -07:00
local asn_status_cache = {}
2019-06-20 01:59:39 -07:00
function verbana.data.get_asn_status(asn, create_if_new)
2019-07-07 17:59:32 -07:00
local cached_status = asn_status_cache[asn]
if cached_status then return cached_status end
2019-06-20 01:59:39 -07:00
local code = [[
SELECT executor.id executor_id
, executor.name executor
, status.id status_id
, status.name name
, log.timestamp timestamp
, log.reason reason
, log.expires expires
FROM asn
JOIN asn_status_log log ON asn.current_status_id == log.id
JOIN asn_status status ON log.status_id == status.id
JOIN player executor ON log.executor_id == executor.id
WHERE asn.asn == ?
LIMIT 1
]]
local table = get_full_ntable(code, 'get asn status', asn)
if #table == 1 then
2019-07-07 17:59:32 -07:00
asn_status_cache[asn] = table[1]
2019-06-20 01:59:39 -07:00
return table[1]
elseif #table > 1 then
2019-07-07 19:18:59 -07:00
log('error', 'somehow got more than 1 result when getting current asn status for %s', asn)
2019-06-20 01:59:39 -07:00
return nil
elseif not create_if_new then
return nil
end
if not verbana.data.set_asn_status(asn, verbana.data.verbana_player_id, verbana.data.asn_status.default.id, 'creating initial asn status') then
2019-07-07 19:18:59 -07:00
log('error', 'failed to set initial asn status')
2019-06-20 01:59:39 -07:00
return nil
end
return {
executor_id=verbana.data.verbana_player_id,
executor=verbana.data.verbana_player,
status_id=verbana.data.asn_status.default.id,
name='default',
timestamp=os.clock()
}
end
function verbana.data.set_asn_status(asn, executor_id, status_id, reason, expires)
2019-07-07 17:59:32 -07:00
asn_status_cache[asn] = nil
2019-06-20 01:59:39 -07:00
local code = [[
INSERT INTO asn_status_log (asn, executor_id, status_id, reason, expires, timestamp)
VALUES (?, ?, ?, ?, ?, ?)
]]
2019-07-07 19:18:59 -07:00
if not execute_bind_one(code, 'set asn status', asn, executor_id, status_id, reason, expires, os.clock()) then return false end
2019-06-20 01:59:39 -07:00
local last_id = db:last_insert_rowid()
local code = 'UPDATE asn SET current_status_id = ? WHERE asn = ?'
if not execute_bind_one(code, 'update asn last status id', last_id, asn) then return false end
return true
end
2019-06-20 01:59:39 -07:00
function verbana.data.log(player_id, ipint, asn, success)
local code = [[
INSERT INTO connection_log (player_id, ip, asn, success, timestamp)
VALUES (?, ?, ?, ?, ?)
]]
if not execute_bind_one(code, 'log connection', player_id, ipint, asn, success, os.clock()) then return false end
return true
end
2019-06-20 01:59:39 -07:00
function verbana.data.assoc(player_id, ipint, asn)
2019-06-25 22:16:29 -07:00
local insert_code = [[
INSERT OR IGNORE INTO assoc (player_id, ip, asn, first_seen, last_seen)
VALUES (?, ?, ?, ?, ?)
]]
if not execute_bind_one(insert_code, 'insert assoc', player_id, ipint, asn, os.clock(), os.clock()) then return false end
local update_code = [[
UPDATE assoc
SET last_seen = ?
WHERE player_id == ?
AND ip == ?
AND asn == ?
2019-06-20 01:59:39 -07:00
]]
2019-06-25 22:16:29 -07:00
if not execute_bind_one(insert_code, 'update assoc', os.clock(), player_id, ipint, asn) then return false end
2019-06-20 01:59:39 -07:00
return true
end
function verbana.data.has_asn_assoc(player_id, asn)
local code = 'SELECT 1 FROM assoc WHERE player_id = ? AND asn == ? LIMIT 1'
local table = get_full_table(code, 'find player asn assoc', player_id, asn)
return #table == 1
end
function verbana.data.has_ip_assoc(player_id, ipint)
local code = 'SELECT 1 FROM assoc WHERE player_id = ? AND ip == ? LIMIT 1'
local table = get_full_table(code, 'find player asn assoc', player_id, ipint)
return #table == 1
end
2019-06-25 22:16:29 -07:00
function verbana.data.get_player_status_log(player_id)
2019-06-20 01:59:39 -07:00
local code = [[
SELECT executor.name executor
, status.name status
, log.timestamp timestamp
, log.reason reason
, log.expires expires
FROM player_status_log log
JOIN player ON log.player_id == player.id
JOIN player executor ON log.executor_id == executor.id
JOIN player_status status ON log.status_id == status.id
2019-06-25 22:16:29 -07:00
WHERE player.id == ?
2019-06-20 01:59:39 -07:00
ORDER BY log.timestamp
]]
2019-06-25 22:16:29 -07:00
return get_full_ntable(code, 'player status log', player_id)
2019-06-20 01:59:39 -07:00
end
function verbana.data.get_ip_status_log(ipint)
local code = [[
SELECT executor.name executor
, status.name status
, log.timestamp timestamp
, log.reason reason
, log.expires expires
FROM ip_status_log log
JOIN player executor ON log.executor_id == executor.id
JOIN ip_status status ON log.status_id == status.id
WHERE log.ip == ?
ORDER BY log.timestamp
]]
return get_full_ntable(code, 'ip status log', ipint)
end
function verbana.data.get_asn_status_log(asn)
local code = [[
SELECT executor.name executor
, status.name status
, log.timestamp timestamp
, log.reason reason
, log.expires expires
FROM asn_status_log log
JOIN player executor ON log.executor_id == executor.id
JOIN asn_status status ON log.status_id == status.id
WHERE log.asn == ?
ORDER BY log.timestamp
]]
return get_full_ntable(code, 'asn status log', asn)
end
2019-06-25 22:16:29 -07:00
function verbana.data.get_player_connection_log(player_id, limit)
2019-06-20 01:59:39 -07:00
local code = [[
2019-06-25 22:16:29 -07:00
SELECT log.ip ipint
, log.asn asn
, log.success success
, log.timestamp timestamp
, ip_status.id ip_status_id
, ip_status.name ip_status_name
, asn_status.id asn_status_id
, asn_status.name asn_status_name
2019-06-20 01:59:39 -07:00
FROM connection_log log
JOIN player ON player.id == log.player_id
JOIN ip ON ip.ip == log.ip
LEFT JOIN ip_status_log ON ip.current_status_id == ip_status_log.id
2019-06-25 22:16:29 -07:00
LEFT JOIN ip_status ON ip_status_log.status_id == ip_status.id
2019-06-20 01:59:39 -07:00
JOIN asn ON asn.asn == log.asn
LEFT JOIN asn_status_log ON asn.current_status_id == asn_status_log.id
2019-06-25 22:16:29 -07:00
LEFT JOIN asn_status ON asn_status_log.status_id == asn_status.id
WHERE player.id == ?
2019-06-20 01:59:39 -07:00
ORDER BY timestamp DESC
LIMIT ?
2019-06-15 20:52:08 -07:00
]]
2019-06-20 01:59:39 -07:00
if not limit or type(limit) ~= 'number' or limit < 0 then
limit = 20
end
2019-06-25 22:16:29 -07:00
local t = get_full_ntable(code, 'player connection log', player_id, limit)
2019-06-20 01:59:39 -07:00
return verbana.util.table_reversed(t)
end
function verbana.data.get_ip_connection_log(ipint, limit)
local code = [[
SELECT player.name player_name
, player.id player_id
, log.asn asn
, log.success success
, log.timestamp timestamp
, player_status_log.status_id player_status_id
, asn_status_log.status_id asn_status_id
FROM connection_log log
JOIN player ON player.id == log.player_id
LEFT JOIN player_status_log ON player_status_log.id == player.current_status_id
JOIN asn ON asn.asn == log.asn
LEFT JOIN asn_status_log ON asn.current_status_id == asn_status_log.id
WHERE log.ip == ?
ORDER BY timestamp DESC
LIMIT ?
]]
if not limit or type(limit) ~= 'number' or limit < 0 then
limit = 20
end
local t = get_full_ntable(code, 'ip connection log', ipint, limit)
return verbana.util.table_reversed(t)
end
function verbana.data.get_asn_connection_log(asn, limit)
local code = [[
SELECT player.name player_name
, player.id player_id
2019-06-25 22:16:29 -07:00
, log.ip ipint
2019-06-20 01:59:39 -07:00
, log.success success
, log.timestamp timestamp
, player_status_log.status_id player_status_id
, ip.current_status_id ip_status_id
FROM connection_log log
JOIN player ON player.id == log.player_id
LEFT JOIN player_status_log ON player_status_log.id == player.current_status_id
JOIN ip ON ip.ip == log.ip
LEFT JOIN ip_status_log ON ip.current_status_id == ip_status_log.id
WHERE log.asn == ?
ORDER BY timestamp DESC
LIMIT ?
]]
if not limit or type(limit) ~= 'number' or limit < 0 then
limit = 20
end
local t = get_full_ntable(code, 'asn connection log', asn, limit)
return verbana.util.table_reversed(t)
end
2019-06-25 22:16:29 -07:00
function verbana.data.get_player_associations(player_id)
2019-06-20 01:59:39 -07:00
local code = [[
2019-06-25 22:16:29 -07:00
SELECT assoc.ip ipint
2019-06-20 01:59:39 -07:00
, assoc.asn asn
, ip_status_log.status_id ip_status_id
, asn_status_log.status_id asn_status_id
FROM assoc
JOIN player ON player.id == assoc.player_id
JOIN ip ON ip.ip == log.ip
LEFT JOIN ip_status_log ON ip.current_status_id == ip_status_log.id
JOIN asn ON asn.asn == log.asn
LEFT JOIN asn_status_log ON asn.current_status_id == asn_status_log.id
2019-06-25 22:16:29 -07:00
WHERE player.id == ?
2019-06-20 01:59:39 -07:00
ORDER BY assoc.asn, assoc.ip
]]
2019-06-25 22:16:29 -07:00
return get_full_ntable(code, 'player associations', player_id)
2019-06-20 01:59:39 -07:00
end
function verbana.data.get_ip_associations(ipint)
local code = [[
SELECT
DISTINCT player.name player_name
, player_status_log.status_id player_status_id
FROM assoc
JOIN player ON player.id == assoc.player_id
LEFT JOIN player_status_log ON player_status_log.id == player.current_status_id
WHERE assoc.ip == ?
ORDER BY LOWER(player.name)
]]
return get_full_ntable(code, 'ip associations', ipint)
end
function verbana.data.get_asn_associations(asn)
local code = [[
SELECT
DISTINCT player.name player_name
, player_status_log.status_id player_status_id
FROM assoc
JOIN player ON player.id == assoc.player_id
LEFT JOIN player_status_log ON player_status_log.id == player.current_status_id
WHERE assoc.asn == ?
ORDER BY LOWER(player.name)
]]
return get_full_ntable(code, 'asn associations', asn)
end
2019-06-25 22:16:29 -07:00
function verbana.data.get_player_cluster(player_id)
2019-06-20 01:59:39 -07:00
local code = [[
SELECT
DISTINCT other.name player_name
, player_status_log.status_id status_id
FROM player
JOIN assoc player_assoc ON player.id == player_assoc.player_id
JOIN assoc other_assoc ON player_assoc.ip == other_assoc.ip
AND player_assoc.player_id != other_assoc.player_id
JOIN player other ON other_assoc.player_id == other.id
LEFT JOIN player_status_log ON other.id == player_status_log.player_id
2019-06-25 22:16:29 -07:00
WHERE player.id == ?
2019-06-20 01:59:39 -07:00
ORDER BY other_name
]]
2019-06-25 22:16:29 -07:00
return get_full_ntable(code, 'player cluster', player_id)
2019-06-20 01:59:39 -07:00
end
function verbana.data.get_all_banned_players()
local code = [[
SELECT player.name player_name
, player_status_log.status_id player_status_id
, player_status_log.reason reason
, player_status_log.expires expires
FROM player
LEFT JOIN player_status_log ON player.id == player_status_log.player_id
2019-07-07 17:59:32 -07:00
WHERE player_status_log.status_id IN (?, ?, ?)
]]
return get_full_ntable(code, 'all banned',
verbana.data.player_status.banned,
verbana.data.player_status.tempbanned,
verbana.data.player_status.locked
)
2019-06-15 20:52:08 -07:00
end