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 , ... )
2019-06-12 22:28:21 -07:00
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 ( ) )
2019-06-12 22:28:21 -07:00
end
2019-06-15 20:52:08 -07:00
return false
2019-06-12 22:28:21 -07:00
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
2019-06-12 22:28:21 -07:00
end
2019-06-15 20:52:08 -07:00
if not finalize ( insert_player_statement , ' insert player ' ) then return _error ( ) end
2019-06-12 22:28:21 -07:00
-- 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
2019-06-12 22:28:21 -07:00
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 )
2019-06-12 22:28:21 -07:00
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
2019-06-12 22:28:21 -07:00
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 = [ [
2019-06-12 22:28:21 -07:00
INSERT OR IGNORE
2019-06-15 20:52:08 -07:00
INTO player_status_log ( executor_id , player_id , status_id , timestamp , reason , expires )
2019-06-12 22:28:21 -07:00
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
2019-06-12 22:28:21 -07:00
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
2019-06-12 22:28:21 -07:00
] ]
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
2019-06-12 22:28:21 -07:00
status_id = tempbanned_player_status_id
else
status_id = banned_player_status_id
2019-06-15 20:52:08 -07:00
expires = nil
2019-06-12 22:28:21 -07:00
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
2019-06-12 22:28:21 -07:00
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 ( ) )
2019-06-12 22:28:21 -07:00
end
2019-06-15 20:52:08 -07:00
return false
2019-06-12 22:28:21 -07:00
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
2019-06-12 22:28:21 -07:00
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-12 22:28:21 -07:00
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-06-09 18:08:00 -07:00
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-09 18:08:00 -07:00
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-09 18:08:00 -07:00
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-09 18:08:00 -07:00
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-09 18:08:00 -07:00
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