mirror of
https://github.com/yogstation13/Yogstation.git
synced 2025-02-26 09:04:50 +00:00
Database backed stickybans.
This commit is contained in:
committed by
yogstation13-bot
parent
b663d96166
commit
d8ab6375c0
@@ -1,15 +1,53 @@
|
||||
Any time you make a change to the schema files, remember to increment the database schema version. Generally increment the minor number, major should be reserved for significant changes to the schema. Both values go up to 255.
|
||||
|
||||
The latest database version is 4.7; The query to update the schema revision table is:
|
||||
The latest database version is 5.1; The query to update the schema revision table is:
|
||||
|
||||
INSERT INTO `schema_revision` (`major`, `minor`) VALUES (5, 0);
|
||||
INSERT INTO `schema_revision` (`major`, `minor`) VALUES (5, 1);
|
||||
or
|
||||
INSERT INTO `SS13_schema_revision` (`major`, `minor`) VALUES (5, 0);
|
||||
INSERT INTO `SS13_schema_revision` (`major`, `minor`) VALUES (5, 1);
|
||||
|
||||
In any query remember to add a prefix to the table names if you use one.
|
||||
|
||||
----------------------------------------------------
|
||||
|
||||
Version 5.1, 25 Feb 2018, by MrStonedOne
|
||||
Added four tables to enable storing of stickybans in the database since byond can lose them, and to enable disabling stickybans for a round without depending on a crash free round. Existing stickybans are automagically imported to the tables.
|
||||
|
||||
CREATE TABLE `stickyban` (
|
||||
`ckey` VARCHAR(32) NOT NULL,
|
||||
`reason` VARCHAR(2048) NOT NULL,
|
||||
`banning_admin` VARCHAR(32) NOT NULL,
|
||||
`datetime` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`ckey`)
|
||||
) ENGINE=InnoDB;
|
||||
|
||||
CREATE TABLE `stickyban_matched_ckey` (
|
||||
`stickyban` VARCHAR(32) NOT NULL,
|
||||
`matched_ckey` VARCHAR(32) NOT NULL,
|
||||
`first_matched` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
`last_matched` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
`exempt` TINYINT(1) NOT NULL DEFAULT '0',
|
||||
PRIMARY KEY (`stickyban`, `matched_ckey`)
|
||||
) ENGINE=InnoDB;
|
||||
|
||||
CREATE TABLE `stickyban_matched_ip` (
|
||||
`stickyban` VARCHAR(32) NOT NULL,
|
||||
`matched_ip` INT UNSIGNED NOT NULL,
|
||||
`first_matched` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
`last_matched` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`stickyban`, `matched_ip`)
|
||||
) ENGINE=InnoDB;
|
||||
|
||||
CREATE TABLE `stickyban_matched_cid` (
|
||||
`stickyban` VARCHAR(32) NOT NULL,
|
||||
`matched_cid` VARCHAR(32) NOT NULL,
|
||||
`first_matched` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
`last_matched` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`stickyban`, `matched_cid`)
|
||||
) ENGINE=InnoDB;
|
||||
|
||||
----------------------------------------------------
|
||||
|
||||
Version 5.0, 28 October 2018, by Jordie0608
|
||||
Modified ban table to remove the need for the `bantype` column, a python script is used to migrate data to this new format.
|
||||
|
||||
@@ -88,8 +126,7 @@ Added table `role_time_log` and triggers `role_timeTlogupdate`, `role_timeTlogin
|
||||
|
||||
CREATE TABLE `role_time_log` ( `id` BIGINT NOT NULL AUTO_INCREMENT , `ckey` VARCHAR(32) NOT NULL , `job` VARCHAR(128) NOT NULL , `delta` INT NOT NULL , `datetime` TIMESTAMP on update CURRENT_TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP , PRIMARY KEY (`id`), INDEX (`ckey`), INDEX (`job`), INDEX (`datetime`)) ENGINE = InnoDB;
|
||||
|
||||
DELIMITER
|
||||
$$
|
||||
DELIMITER $$
|
||||
CREATE TRIGGER `role_timeTlogupdate` AFTER UPDATE ON `role_time` FOR EACH ROW BEGIN INSERT into role_time_log (ckey, job, delta) VALUES (NEW.CKEY, NEW.job, NEW.minutes-OLD.minutes);
|
||||
END
|
||||
$$
|
||||
@@ -99,7 +136,7 @@ $$
|
||||
CREATE TRIGGER `role_timeTlogdelete` AFTER DELETE ON `role_time` FOR EACH ROW BEGIN INSERT into role_time_log (ckey, job, delta) VALUES (OLD.ckey, OLD.job, 0-OLD.minutes);
|
||||
END
|
||||
$$
|
||||
|
||||
DELIMITER ;
|
||||
----------------------------------------------------
|
||||
|
||||
Version 4.2, 17 April 2018, by Jordie0608
|
||||
|
||||
@@ -462,6 +462,57 @@ $$
|
||||
CREATE TRIGGER `role_timeTlogdelete` AFTER DELETE ON `role_time` FOR EACH ROW BEGIN INSERT into role_time_log (ckey, job, delta) VALUES (OLD.ckey, OLD.job, 0-OLD.minutes);
|
||||
END
|
||||
$$
|
||||
DELIMITER ;
|
||||
|
||||
--
|
||||
-- Table structure for table `stickyban`
|
||||
--
|
||||
DROP TABLE IF EXISTS `stickyban`;
|
||||
CREATE TABLE `stickyban` (
|
||||
`ckey` VARCHAR(32) NOT NULL,
|
||||
`reason` VARCHAR(2048) NOT NULL,
|
||||
`banning_admin` VARCHAR(32) NOT NULL,
|
||||
`datetime` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`ckey`)
|
||||
) ENGINE=InnoDB;
|
||||
|
||||
--
|
||||
-- Table structure for table `stickyban_matched_ckey`
|
||||
--
|
||||
DROP TABLE IF EXISTS `stickyban_matched_ckey`;
|
||||
CREATE TABLE `ss13_stickyban_matched_ckey` (
|
||||
`stickyban` VARCHAR(32) NOT NULL,
|
||||
`matched_ckey` VARCHAR(32) NOT NULL,
|
||||
`first_matched` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
`last_matched` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
`exempt` TINYINT(1) NOT NULL DEFAULT '0',
|
||||
PRIMARY KEY (`stickyban`, `matched_ckey`)
|
||||
) ENGINE=InnoDB;
|
||||
|
||||
--
|
||||
-- Table structure for table `ss13_stickyban_matched_ip`
|
||||
--
|
||||
DROP TABLE IF EXISTS `ss13_stickyban_matched_ip`;
|
||||
CREATE TABLE `ss13_stickyban_matched_ip` (
|
||||
`stickyban` VARCHAR(32) NOT NULL,
|
||||
`matched_ip` INT UNSIGNED NOT NULL,
|
||||
`first_matched` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
`last_matched` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`stickyban`, `matched_ip`)
|
||||
) ENGINE=InnoDB;
|
||||
|
||||
--
|
||||
-- Table structure for table `stickyban_matched_cid`
|
||||
--
|
||||
DROP TABLE IF EXISTS `stickyban_matched_cid`;
|
||||
CREATE TABLE `stickyban_matched_cid` (
|
||||
`stickyban` VARCHAR(32) NOT NULL,
|
||||
`matched_cid` VARCHAR(32) NOT NULL,
|
||||
`first_matched` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
`last_matched` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`stickyban`, `matched_cid`)
|
||||
) ENGINE=InnoDB;
|
||||
|
||||
|
||||
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
|
||||
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
|
||||
|
||||
@@ -462,6 +462,58 @@ $$
|
||||
CREATE TRIGGER `SS13_role_timeTlogdelete` AFTER DELETE ON `SS13_role_time` FOR EACH ROW BEGIN INSERT into SS13_role_time_log (ckey, job, delta) VALUES (OLD.ckey, OLD.job, 0-OLD.minutes);
|
||||
END
|
||||
$$
|
||||
DELIMITER ;
|
||||
|
||||
--
|
||||
-- Table structure for table `SS13_stickyban`
|
||||
--
|
||||
DROP TABLE IF EXISTS `SS13_stickyban`;
|
||||
CREATE TABLE `SS13_stickyban` (
|
||||
`ckey` VARCHAR(32) NOT NULL,
|
||||
`reason` VARCHAR(2048) NOT NULL,
|
||||
`banning_admin` VARCHAR(32) NOT NULL,
|
||||
`datetime` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`ckey`)
|
||||
) ENGINE=InnoDB;
|
||||
|
||||
--
|
||||
-- Table structure for table `SS13_stickyban_matched_ckey`
|
||||
--
|
||||
DROP TABLE IF EXISTS `SS13_stickyban_matched_ckey`;
|
||||
CREATE TABLE `SS13_stickyban_matched_ckey` (
|
||||
`stickyban` VARCHAR(32) NOT NULL,
|
||||
`matched_ckey` VARCHAR(32) NOT NULL,
|
||||
`first_matched` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
`last_matched` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
`exempt` TINYINT(1) NOT NULL DEFAULT '0',
|
||||
PRIMARY KEY (`stickyban`, `matched_ckey`)
|
||||
) ENGINE=InnoDB;
|
||||
|
||||
--
|
||||
-- Table structure for table `SS13_stickyban_matched_ip`
|
||||
--
|
||||
DROP TABLE IF EXISTS `SS13_stickyban_matched_ip`;
|
||||
CREATE TABLE `SS13_stickyban_matched_ip` (
|
||||
`stickyban` VARCHAR(32) NOT NULL,
|
||||
`matched_ip` INT UNSIGNED NOT NULL,
|
||||
`first_matched` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
`last_matched` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`stickyban`, `matched_ip`)
|
||||
) ENGINE=InnoDB;
|
||||
|
||||
--
|
||||
-- Table structure for table `SS13_stickyban_matched_cid`
|
||||
--
|
||||
DROP TABLE IF EXISTS `SS13_stickyban_matched_cid`;
|
||||
CREATE TABLE `SS13_stickyban_matched_cid` (
|
||||
`stickyban` VARCHAR(32) NOT NULL,
|
||||
`matched_cid` VARCHAR(32) NOT NULL,
|
||||
`first_matched` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
`last_matched` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`stickyban`, `matched_cid`)
|
||||
) ENGINE=InnoDB;
|
||||
|
||||
|
||||
|
||||
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
|
||||
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
|
||||
|
||||
@@ -81,3 +81,6 @@
|
||||
|
||||
#define SPAM_TRIGGER_WARNING 5 //Number of identical messages required before the spam-prevention will warn you to stfu
|
||||
#define SPAM_TRIGGER_AUTOMUTE 10 //Number of identical messages required before the spam-prevention will automute you
|
||||
|
||||
#define STICKYBAN_DB_CACHE_TIME 10 SECONDS
|
||||
#define STICKYBAN_ROGUE_CHECK_TIME 5
|
||||
@@ -1,7 +1,8 @@
|
||||
//Update this whenever the db schema changes
|
||||
//make sure you add an update to the schema_version stable in the db changelog
|
||||
#define DB_MAJOR_VERSION 5
|
||||
#define DB_MINOR_VERSION 0
|
||||
#define DB_MINOR_VERSION 1
|
||||
|
||||
|
||||
//Timing subsystem
|
||||
//Don't run if there is an identical unique timer active
|
||||
|
||||
@@ -177,6 +177,27 @@ SUBSYSTEM_DEF(dbcore)
|
||||
return FALSE
|
||||
return new /datum/DBQuery(sql_query, connection)
|
||||
|
||||
/datum/controller/subsystem/dbcore/proc/QuerySelect(list/querys, warn = FALSE, qdel = FALSE)
|
||||
if (!islist(querys))
|
||||
if (!istype(querys, /datum/DBQuery))
|
||||
CRASH("Invalid query passed to QuerySelect: [querys]")
|
||||
querys = list(querys)
|
||||
|
||||
for (var/thing in querys)
|
||||
var/datum/DBQuery/query = thing
|
||||
if (warn)
|
||||
INVOKE_ASYNC(query, /datum/DBQuery.proc/warn_execute)
|
||||
else
|
||||
INVOKE_ASYNC(query, /datum/DBQuery.proc/Execute)
|
||||
|
||||
for (var/thing in querys)
|
||||
var/datum/DBQuery/query = thing
|
||||
UNTIL(!query.in_progress)
|
||||
if (qdel)
|
||||
qdel(query)
|
||||
|
||||
|
||||
|
||||
/*
|
||||
Takes a list of rows (each row being an associated list of column => value) and inserts them via a single mass query.
|
||||
Rows missing columns present in other rows will resolve to SQL NULL
|
||||
|
||||
@@ -9,6 +9,9 @@ SUBSYSTEM_DEF(server_maint)
|
||||
runlevels = RUNLEVEL_LOBBY | RUNLEVELS_DEFAULT
|
||||
var/list/currentrun
|
||||
|
||||
/datum/controller/subsystem/server_maint/PreInit()
|
||||
world.hub_password = "" //quickly! before the hubbies see us.
|
||||
|
||||
/datum/controller/subsystem/server_maint/Initialize(timeofday)
|
||||
if (CONFIG_GET(flag/hub))
|
||||
world.update_hub_visibility(TRUE)
|
||||
|
||||
@@ -1,34 +1,207 @@
|
||||
SUBSYSTEM_DEF(stickyban)
|
||||
name = "Sticky Ban"
|
||||
name = "PRISM"
|
||||
init_order = INIT_ORDER_STICKY_BAN
|
||||
flags = SS_NO_FIRE
|
||||
|
||||
var/list/cache = list()
|
||||
var/list/dbcache = list()
|
||||
var/list/confirmed_exempt = list()
|
||||
var/dbcacheexpire = 0
|
||||
|
||||
|
||||
/datum/controller/subsystem/stickyban/Initialize(timeofday)
|
||||
var/list/bannedkeys = world.GetConfig("ban")
|
||||
var/list/bannedkeys = sticky_banned_ckeys()
|
||||
//sanitize the sticky ban list
|
||||
|
||||
//delete db bans that no longer exist in the database and add new legacy bans to the database
|
||||
if (SSdbcore.Connect() || length(SSstickyban.dbcache))
|
||||
for (var/oldban in (world.GetConfig("ban") - bannedkeys))
|
||||
var/ckey = ckey(oldban)
|
||||
if (ckey != oldban && (ckey in bannedkeys))
|
||||
continue
|
||||
|
||||
var/list/ban = params2list(world.GetConfig("ban", oldban))
|
||||
if (ban && !ban["fromdb"])
|
||||
if (!import_raw_stickyban_to_db(ckey, ban))
|
||||
log_world("Could not import stickyban on [oldban] into the database. Ignoring")
|
||||
continue
|
||||
dbcacheexpire = 0
|
||||
bannedkeys += ckey
|
||||
world.SetConfig("ban", oldban, null)
|
||||
|
||||
|
||||
for (var/bannedkey in bannedkeys)
|
||||
var/ckey = ckey(bannedkey)
|
||||
var/list/ban = stickyban2list(world.GetConfig("ban", bannedkey))
|
||||
var/list/ban = get_stickyban_from_ckey(bannedkey)
|
||||
|
||||
//byond stores sticky bans by key, that can end up confusing things
|
||||
//i also remove it here so that if any stickybans cause a runtime, they just stop existing
|
||||
//byond stores sticky bans by key, that's lame
|
||||
if (ckey != bannedkey)
|
||||
world.SetConfig("ban", bannedkey, null)
|
||||
|
||||
if (!ban["ckey"])
|
||||
ban["ckey"] = ckey
|
||||
|
||||
//storing these can break things and isn't needed for sticky ban tracking
|
||||
ban -= "IP"
|
||||
ban -= "computer_id"
|
||||
|
||||
ban["matches_this_round"] = list()
|
||||
ban["existing_user_matches_this_round"] = list()
|
||||
ban["admin_matches_this_round"] = list()
|
||||
cache[ckey] = ban
|
||||
ban["pending_matches_this_round"] = list()
|
||||
|
||||
for (var/bannedckey in cache)
|
||||
world.SetConfig("ban", bannedckey, list2stickyban(cache[bannedckey]))
|
||||
cache[ckey] = ban
|
||||
world.SetConfig("ban", ckey, list2stickyban(ban))
|
||||
|
||||
return ..()
|
||||
|
||||
/datum/controller/subsystem/stickyban/proc/Populatedbcache()
|
||||
var/newdbcache = list() //so if we runtime or the db connection dies we don't kill the existing cache
|
||||
|
||||
var/datum/DBQuery/query_stickybans = SSdbcore.NewQuery("SELECT ckey, reason, banning_admin, datetime FROM [format_table_name("stickyban")] ORDER BY ckey")
|
||||
var/datum/DBQuery/query_ckey_matches = SSdbcore.NewQuery("SELECT stickyban, matched_ckey, first_matched, last_matched, exempt FROM [format_table_name("stickyban_matched_ckey")] ORDER BY first_matched")
|
||||
var/datum/DBQuery/query_cid_matches = SSdbcore.NewQuery("SELECT stickyban, matched_cid, first_matched, last_matched FROM [format_table_name("stickyban_matched_cid")] ORDER BY first_matched")
|
||||
var/datum/DBQuery/query_ip_matches = SSdbcore.NewQuery("SELECT stickyban, INET_NTOA(matched_ip), first_matched, last_matched FROM [format_table_name("stickyban_matched_ip")] ORDER BY first_matched")
|
||||
|
||||
SSdbcore.QuerySelect(list(query_stickybans, query_ckey_matches, query_cid_matches, query_ip_matches))
|
||||
|
||||
if (query_stickybans.last_error)
|
||||
qdel(query_stickybans)
|
||||
qdel(query_ckey_matches)
|
||||
qdel(query_cid_matches)
|
||||
qdel(query_ip_matches)
|
||||
return
|
||||
|
||||
while (query_stickybans.NextRow())
|
||||
var/list/ban = list()
|
||||
|
||||
ban["ckey"] = query_stickybans.item[1]
|
||||
ban["message"] = query_stickybans.item[2]
|
||||
ban["reason"] = "(InGameBan)([query_stickybans.item[3]])"
|
||||
ban["admin"] = query_stickybans.item[3]
|
||||
ban["datetime"] = query_stickybans.item[4]
|
||||
ban["type"] = list("sticky")
|
||||
|
||||
newdbcache["[query_stickybans.item[1]]"] = ban
|
||||
|
||||
|
||||
if (!query_ckey_matches.last_error)
|
||||
while (query_ckey_matches.NextRow())
|
||||
var/list/match = list()
|
||||
|
||||
match["stickyban"] = query_ckey_matches.item[1]
|
||||
match["matched_ckey"] = query_ckey_matches.item[2]
|
||||
match["first_matched"] = query_ckey_matches.item[3]
|
||||
match["last_matched"] = query_ckey_matches.item[4]
|
||||
match["exempt"] = text2num(query_ckey_matches.item[5])
|
||||
|
||||
var/ban = newdbcache[query_ckey_matches.item[1]]
|
||||
if (!ban)
|
||||
continue
|
||||
var/keys = ban[text2num(query_ckey_matches.item[5]) ? "whitelist" : "keys"]
|
||||
if (!keys)
|
||||
keys = ban[text2num(query_ckey_matches.item[5]) ? "whitelist" : "keys"] = list()
|
||||
keys[query_ckey_matches.item[2]] = match
|
||||
|
||||
if (!query_cid_matches.last_error)
|
||||
while (query_cid_matches.NextRow())
|
||||
var/list/match = list()
|
||||
|
||||
match["stickyban"] = query_cid_matches.item[1]
|
||||
match["matched_cid"] = query_cid_matches.item[2]
|
||||
match["first_matched"] = query_cid_matches.item[3]
|
||||
match["last_matched"] = query_cid_matches.item[4]
|
||||
|
||||
var/ban = newdbcache[query_cid_matches.item[1]]
|
||||
if (!ban)
|
||||
continue
|
||||
var/computer_ids = ban["computer_id"]
|
||||
if (!computer_ids)
|
||||
computer_ids = ban["computer_id"] = list()
|
||||
computer_ids[query_cid_matches.item[2]] = match
|
||||
|
||||
|
||||
if (!query_ip_matches.last_error)
|
||||
while (query_ip_matches.NextRow())
|
||||
var/list/match = list()
|
||||
|
||||
match["stickyban"] = query_ip_matches.item[1]
|
||||
match["matched_ip"] = query_ip_matches.item[2]
|
||||
match["first_matched"] = query_ip_matches.item[3]
|
||||
match["last_matched"] = query_ip_matches.item[4]
|
||||
|
||||
var/ban = newdbcache[query_ip_matches.item[1]]
|
||||
if (!ban)
|
||||
continue
|
||||
var/IPs = ban["IP"]
|
||||
if (!IPs)
|
||||
IPs = ban["IP"] = list()
|
||||
IPs[query_ip_matches.item[2]] = match
|
||||
|
||||
dbcache = newdbcache
|
||||
dbcacheexpire = world.time+STICKYBAN_DB_CACHE_TIME
|
||||
|
||||
qdel(query_stickybans)
|
||||
qdel(query_ckey_matches)
|
||||
qdel(query_cid_matches)
|
||||
qdel(query_ip_matches)
|
||||
|
||||
|
||||
/datum/controller/subsystem/stickyban/proc/import_raw_stickyban_to_db(ckey, list/ban)
|
||||
. = FALSE
|
||||
if (!ban["admin"])
|
||||
ban["admin"] = "LEGACY"
|
||||
if (!ban["message"])
|
||||
ban["message"] = "Evasion"
|
||||
|
||||
var/datum/DBQuery/query_create_stickyban = SSdbcore.NewQuery("INSERT IGNORE INTO [format_table_name("stickyban")] (ckey, reason, banning_admin) VALUES ('[sanitizeSQL(ckey)]', '[sanitizeSQL(ban["message"])]', '[sanitizeSQL(ban["admin"])]')")
|
||||
if (!query_create_stickyban.warn_execute())
|
||||
qdel(query_create_stickyban)
|
||||
return
|
||||
qdel(query_create_stickyban)
|
||||
|
||||
var/list/sqlckeys = list()
|
||||
var/list/sqlcids = list()
|
||||
var/list/sqlips = list()
|
||||
|
||||
if (ban["keys"])
|
||||
var/list/keys = splittext(ban["keys"], ",")
|
||||
for (var/key in keys)
|
||||
var/list/sqlckey = list()
|
||||
sqlckey["stickyban"] = "'[sanitizeSQL(ckey)]'"
|
||||
sqlckey["matched_ckey"] = "'[sanitizeSQL(ckey(key))]'"
|
||||
sqlckey["exempt"] = FALSE
|
||||
sqlckeys[++sqlckeys.len] = sqlckey
|
||||
|
||||
if (ban["whitelist"])
|
||||
var/list/keys = splittext(ban["whitelist"], ",")
|
||||
for (var/key in keys)
|
||||
var/list/sqlckey = list()
|
||||
sqlckey["stickyban"] = "'[sanitizeSQL(ckey)]'"
|
||||
sqlckey["matched_ckey"] = "'[sanitizeSQL(ckey(key))]'"
|
||||
sqlckey["exempt"] = TRUE
|
||||
sqlckeys[++sqlckeys.len] = sqlckey
|
||||
|
||||
if (ban["computer_id"])
|
||||
var/list/cids = splittext(ban["computer_id"], ",")
|
||||
for (var/cid in cids)
|
||||
var/list/sqlcid = list()
|
||||
sqlcid["stickyban"] = "'[sanitizeSQL(ckey)]'"
|
||||
sqlcid["matched_cid"] = "'[sanitizeSQL(cid)]'"
|
||||
sqlcids[++sqlcids.len] = sqlcid
|
||||
|
||||
if (ban["IP"])
|
||||
var/list/ips = splittext(ban["IP"], ",")
|
||||
for (var/ip in ips)
|
||||
var/list/sqlip = list()
|
||||
sqlip["stickyban"] = "'[sanitizeSQL(ckey)]'"
|
||||
sqlip["matched_ip"] = "'[sanitizeSQL(ip)]'"
|
||||
sqlips[++sqlips.len] = sqlip
|
||||
|
||||
if (length(sqlckeys))
|
||||
SSdbcore.MassInsert(format_table_name("stickyban_matched_ckey"), sqlckeys, FALSE, TRUE)
|
||||
|
||||
if (length(sqlcids))
|
||||
SSdbcore.MassInsert(format_table_name("stickyban_matched_cid"), sqlcids, FALSE, TRUE)
|
||||
|
||||
if (length(sqlips))
|
||||
SSdbcore.MassInsert(format_table_name("stickyban_matched_ip"), sqlips, FALSE, TRUE)
|
||||
|
||||
|
||||
return TRUE
|
||||
|
||||
@@ -20,6 +20,8 @@ GLOBAL_VAR(restart_counter)
|
||||
|
||||
config.Load(params[OVERRIDE_CONFIG_DIRECTORY_PARAMETER])
|
||||
|
||||
load_admins()
|
||||
|
||||
//SetupLogs depends on the RoundID, so lets check
|
||||
//DB schema and set RoundID if we can
|
||||
SSdbcore.CheckSchemaVersion()
|
||||
@@ -30,9 +32,12 @@ GLOBAL_VAR(restart_counter)
|
||||
world.log = file("[GLOB.log_directory]/dd.log")
|
||||
#endif
|
||||
|
||||
<<<<<<< HEAD
|
||||
load_yogs_stuff() // yogs - Donators
|
||||
refresh_admin_files() //yogs - DB support
|
||||
load_admins()
|
||||
=======
|
||||
>>>>>>> c961d93003... Merge pull request #42899 from MrStonedOne/sqlstickybans
|
||||
LoadVerbs(/datum/verbs/menu)
|
||||
if(CONFIG_GET(flag/usewhitelist))
|
||||
load_whitelist()
|
||||
|
||||
@@ -2,30 +2,35 @@
|
||||
|
||||
//How many new ckey matches before we revert the stickyban to it's roundstart state
|
||||
//These are exclusive, so once it goes over one of these numbers, it reverts the ban
|
||||
#define STICKYBAN_MAX_MATCHES 20
|
||||
#define STICKYBAN_MAX_EXISTING_USER_MATCHES 5 //ie, users who were connected before the ban triggered
|
||||
#define STICKYBAN_MAX_ADMIN_MATCHES 2
|
||||
#define STICKYBAN_MAX_MATCHES 15
|
||||
#define STICKYBAN_MAX_EXISTING_USER_MATCHES 3 //ie, users who were connected before the ban triggered
|
||||
#define STICKYBAN_MAX_ADMIN_MATCHES 1
|
||||
|
||||
/world/IsBanned(key,address,computer_id,type,real_bans_only=FALSE)
|
||||
if (!key || !address || !computer_id)
|
||||
/world/IsBanned(key, address, computer_id, type, real_bans_only=FALSE)
|
||||
debug_world_log("isbanned(): '[args.Join("', '")]'")
|
||||
if (!key || (!real_bans_only && (!address || !computer_id)))
|
||||
if(real_bans_only)
|
||||
return FALSE
|
||||
log_access("Failed Login (invalid data): [key] [address]-[computer_id]")
|
||||
return list("reason"="invalid login data", "desc"="Error: Could not check ban status, Please try again. Error message: Your computer provided invalid or blank information to the server on connection (byond username, IP, and Computer ID.) Provided information for reference: Username:'[key]' IP:'[address]' Computer ID:'[computer_id]'. (If you continue to get this error, please restart byond or contact byond support.)")
|
||||
|
||||
if (text2num(computer_id) == 2147483647) //this cid causes stickybans to go haywire
|
||||
log_access("Failed Login (invalid cid): [key] [address]-[computer_id]")
|
||||
return list("reason"="invalid login data", "desc"="Error: Could not check ban status, Please try again. Error message: Your computer provided an invalid Computer ID.)")
|
||||
var/admin = 0
|
||||
var/admin = FALSE
|
||||
var/ckey = ckey(key)
|
||||
|
||||
//IsBanned can get re-called on a user in certain situations, this prevents that leading to repeated messages to admins.
|
||||
var/static/list/checkedckeys = list()
|
||||
//magic voodo to check for a key in a list while also adding that key to the list without having to do two associated lookups
|
||||
var/message = !checkedckeys[ckey]++
|
||||
|
||||
if(GLOB.admin_datums[ckey] || GLOB.deadmins[ckey])
|
||||
admin = 1
|
||||
admin = TRUE
|
||||
|
||||
//Whitelist
|
||||
if(CONFIG_GET(flag/usewhitelist))
|
||||
if(!check_whitelist(ckey))
|
||||
if (admin)
|
||||
log_admin("The admin [key] has been allowed to bypass the whitelist")
|
||||
if (message)
|
||||
message_admins("<span class='adminnotice'>The admin [key] has been allowed to bypass the whitelist</span>")
|
||||
addclientmessage(ckey,"<span class='adminnotice'>You have been allowed to bypass the whitelist</span>")
|
||||
else
|
||||
@@ -46,10 +51,12 @@
|
||||
if(!real_bans_only && extreme_popcap && living_player_count() >= extreme_popcap && !admin)
|
||||
log_access("Failed Login: [key] - Population cap reached")
|
||||
return list("reason"="popcap", "desc"= "\nReason: [CONFIG_GET(string/extreme_popcap_message)]")
|
||||
|
||||
if(CONFIG_GET(flag/sql_enabled))
|
||||
if(!SSdbcore.Connect())
|
||||
var/msg = "Ban database connection failure. Key [ckey] not checked"
|
||||
log_world(msg)
|
||||
if (message)
|
||||
message_admins(msg)
|
||||
else
|
||||
var/list/ban_details = is_banned_from_with_details(ckey, address, computer_id, "Server")
|
||||
@@ -58,10 +65,12 @@
|
||||
if(text2num(i["applies_to_admins"]))
|
||||
var/msg = "Admin [key] is admin banned, and has been disallowed access."
|
||||
log_admin(msg)
|
||||
if (message)
|
||||
message_admins(msg)
|
||||
else
|
||||
var/msg = "Admin [key] has been allowed to bypass a matching non-admin ban on [i["key"]] [i["ip"]]-[i["computerid"]]."
|
||||
log_admin(msg)
|
||||
if (message)
|
||||
message_admins(msg)
|
||||
addclientmessage(ckey,"<span class='adminnotice'>Admin [key] has been allowed to bypass a matching non-admin ban on [i["key"]] [i["ip"]]-[i["computerid"]].</span>")
|
||||
continue
|
||||
@@ -74,18 +83,24 @@
|
||||
[expires] If you wish to appeal this ban please use the keyword 'assistantgreytide' to register an account on the forums."} //yogs
|
||||
log_access("Failed Login: [key] [computer_id] [address] - Banned (#[i["id"]])")
|
||||
return list("reason"="Banned","desc"="[desc]")
|
||||
|
||||
var/list/ban = ..() //default pager ban stuff
|
||||
|
||||
if (ban)
|
||||
if (!admin)
|
||||
. = ban
|
||||
if (real_bans_only)
|
||||
return
|
||||
var/bannedckey = "ERROR"
|
||||
if (ban["ckey"])
|
||||
bannedckey = ban["ckey"]
|
||||
|
||||
var/newmatch = FALSE
|
||||
var/client/C = GLOB.directory[ckey]
|
||||
var/cachedban = SSstickyban.cache[bannedckey]
|
||||
|
||||
var/list/cachedban = SSstickyban.cache[bannedckey]
|
||||
//rogue ban in the process of being reverted.
|
||||
if (cachedban && cachedban["reverting"])
|
||||
if (cachedban && (cachedban["reverting"] || cachedban["timeout"]))
|
||||
world.SetConfig("ban", bannedckey, null)
|
||||
return null
|
||||
|
||||
if (cachedban && ckey != bannedckey)
|
||||
@@ -98,51 +113,80 @@
|
||||
|
||||
if (newmatch && cachedban)
|
||||
var/list/newmatches = cachedban["matches_this_round"]
|
||||
var/list/pendingmatches = cachedban["matches_this_round"]
|
||||
var/list/newmatches_connected = cachedban["existing_user_matches_this_round"]
|
||||
var/list/newmatches_admin = cachedban["admin_matches_this_round"]
|
||||
|
||||
newmatches[ckey] = ckey
|
||||
if (C)
|
||||
newmatches_connected[ckey] = ckey
|
||||
newmatches_connected = cachedban["existing_user_matches_this_round"]
|
||||
pendingmatches[ckey] = ckey
|
||||
sleep(STICKYBAN_ROGUE_CHECK_TIME)
|
||||
pendingmatches -= ckey
|
||||
if (admin)
|
||||
newmatches_admin[ckey] = ckey
|
||||
|
||||
if (cachedban["reverting"] || cachedban["timeout"])
|
||||
return null
|
||||
|
||||
newmatches[ckey] = ckey
|
||||
|
||||
|
||||
if (\
|
||||
newmatches.len > STICKYBAN_MAX_MATCHES || \
|
||||
newmatches.len+pendingmatches.len > STICKYBAN_MAX_MATCHES || \
|
||||
newmatches_connected.len > STICKYBAN_MAX_EXISTING_USER_MATCHES || \
|
||||
newmatches_admin.len > STICKYBAN_MAX_ADMIN_MATCHES \
|
||||
)
|
||||
if (cachedban["reverting"])
|
||||
return null
|
||||
|
||||
var/action
|
||||
if (ban["fromdb"])
|
||||
cachedban["timeout"] = TRUE
|
||||
action = "putting it on timeout for the remainder of the round"
|
||||
else
|
||||
cachedban["reverting"] = TRUE
|
||||
action = "reverting to its roundstart state"
|
||||
|
||||
world.SetConfig("ban", bannedckey, null)
|
||||
|
||||
log_game("Stickyban on [bannedckey] detected as rogue, reverting to its roundstart state")
|
||||
message_admins("Stickyban on [bannedckey] detected as rogue, reverting to its roundstart state")
|
||||
//we always report this
|
||||
log_game("Stickyban on [bannedckey] detected as rogue, [action]")
|
||||
message_admins("Stickyban on [bannedckey] detected as rogue, [action]")
|
||||
//do not convert to timer.
|
||||
spawn (5)
|
||||
world.SetConfig("ban", bannedckey, null)
|
||||
sleep(1)
|
||||
world.SetConfig("ban", bannedckey, null)
|
||||
if (!ban["fromdb"])
|
||||
cachedban = cachedban.Copy() //so old references to the list still see the ban as reverting
|
||||
cachedban["matches_this_round"] = list()
|
||||
cachedban["existing_user_matches_this_round"] = list()
|
||||
cachedban["admin_matches_this_round"] = list()
|
||||
cachedban -= "reverting"
|
||||
SSstickyban.cache[bannedckey] = cachedban
|
||||
world.SetConfig("ban", bannedckey, list2stickyban(cachedban))
|
||||
return null
|
||||
|
||||
if (ban["fromdb"])
|
||||
if(SSdbcore.Connect())
|
||||
INVOKE_ASYNC(SSdbcore, /datum/controller/subsystem/dbcore/proc.QuerySelect, list(
|
||||
SSdbcore.NewQuery("INSERT INTO [format_table_name("stickyban_matched_ckey")] (matched_ckey, stickyban) VALUES ('[sanitizeSQL(ckey)]', '[sanitizeSQL(bannedckey)]') ON DUPLICATE KEY UPDATE last_matched = now()"),
|
||||
SSdbcore.NewQuery("INSERT INTO [format_table_name("stickyban_matched_ip")] (matched_ip, stickyban) VALUES ( INET_ATON('[sanitizeSQL(address)]'), '[sanitizeSQL(bannedckey)]') ON DUPLICATE KEY UPDATE last_matched = now()"),
|
||||
SSdbcore.NewQuery("INSERT INTO [format_table_name("stickyban_matched_cid")] (matched_cid, stickyban) VALUES ('[sanitizeSQL(computer_id)]', '[sanitizeSQL(bannedckey)]') ON DUPLICATE KEY UPDATE last_matched = now()")
|
||||
), FALSE, TRUE)
|
||||
|
||||
|
||||
//byond will not trigger isbanned() for "global" host bans,
|
||||
//ie, ones where the "apply to this game only" checkbox is not checked (defaults to not checked)
|
||||
//So it's safe to let admins walk thru host/sticky bans here
|
||||
if (admin)
|
||||
log_admin("The admin [key] has been allowed to bypass a matching host/sticky ban on [bannedckey]")
|
||||
if (message)
|
||||
message_admins("<span class='adminnotice'>The admin [key] has been allowed to bypass a matching host/sticky ban on [bannedckey]</span>")
|
||||
addclientmessage(ckey,"<span class='adminnotice'>You have been allowed to bypass a matching host/sticky ban on [bannedckey]</span>")
|
||||
return null
|
||||
|
||||
if (C) //user is already connected!.
|
||||
to_chat(C, "You are about to get disconnected for matching a sticky ban after you connected. If this turns out to be the ban evasion detection system going haywire, we will automatically detect this and revert the matches. if you feel that this is the case, please wait EXACTLY 6 seconds then reconnect using file -> reconnect to see if the match was reversed.")
|
||||
to_chat(C, "You are about to get disconnected for matching a sticky ban after you connected. If this turns out to be the ban evasion detection system going haywire, we will automatically detect this and revert the matches. if you feel that this is the case, please wait EXACTLY 6 seconds then reconnect using file -> reconnect to see if the match was automatically reversed.")
|
||||
|
||||
var/desc = "\nReason:(StickyBan) You, or another user of this computer or connection ([bannedckey]) is banned from playing here. The ban reason is:\n[ban["message"]]\nThis ban was applied by [ban["admin"]]\nThis is a BanEvasion Detection System ban, if you think this ban is a mistake, please wait EXACTLY 6 seconds, then try again before filing an appeal. If you wish to appeal this ban please use the keyword 'assistantgreytide' to register an account on the forums.\n" //yogs
|
||||
. = list("reason" = "Stickyban", "desc" = desc)
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
if ("add")
|
||||
var/list/ban = list()
|
||||
var/ckey
|
||||
ban["admin"] = usr.key
|
||||
ban["admin"] = usr.ckey
|
||||
ban["type"] = list("sticky")
|
||||
ban["reason"] = "(InGameBan)([usr.key])" //this will be displayed in dd only
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
|
||||
if (get_stickyban_from_ckey(ckey))
|
||||
to_chat(usr, "<span class='adminnotice'>Error: Can not add a stickyban: User already has a current sticky ban</span>")
|
||||
return
|
||||
|
||||
if (data["reason"])
|
||||
ban["message"] = data["reason"]
|
||||
@@ -31,7 +32,19 @@
|
||||
return
|
||||
ban["message"] = "[reason]"
|
||||
|
||||
if(SSdbcore.Connect())
|
||||
var/datum/DBQuery/query_create_stickyban = SSdbcore.NewQuery("INSERT INTO [format_table_name("stickyban")] (ckey, reason, banning_admin) VALUES ('[sanitizeSQL(ckey)]', '[sanitizeSQL(ban["message"])]', '[sanitizeSQL(usr.ckey)]')")
|
||||
if (query_create_stickyban.warn_execute())
|
||||
ban["fromdb"] = TRUE
|
||||
qdel(query_create_stickyban)
|
||||
|
||||
world.SetConfig("ban",ckey,list2stickyban(ban))
|
||||
ban = stickyban2list(list2stickyban(ban))
|
||||
ban["matches_this_round"] = list()
|
||||
ban["existing_user_matches_this_round"] = list()
|
||||
ban["admin_matches_this_round"] = list()
|
||||
ban["pending_matches_this_round"] = list()
|
||||
SSstickyban.cache[ckey] = ban
|
||||
|
||||
log_admin_private("[key_name(usr)] has stickybanned [ckey].\nReason: [ban["message"]]")
|
||||
message_admins("<span class='adminnotice'>[key_name_admin(usr)] has stickybanned [ckey].\nReason: [ban["message"]]</span>")
|
||||
@@ -51,6 +64,16 @@
|
||||
to_chat(usr, "<span class='adminnotice'>Error: The ban disappeared.</span>")
|
||||
return
|
||||
world.SetConfig("ban",ckey, null)
|
||||
SSstickyban.cache -= ckey
|
||||
|
||||
if (SSdbcore.Connect())
|
||||
SSdbcore.QuerySelect(list(
|
||||
SSdbcore.NewQuery("DELETE FROM [format_table_name("stickyban")] WHERE ckey = '[sanitizeSQL(ckey)]'"),
|
||||
SSdbcore.NewQuery("DELETE FROM [format_table_name("stickyban_matched_ckey")] WHERE stickyban = '[sanitizeSQL(ckey)]'"),
|
||||
SSdbcore.NewQuery("DELETE FROM [format_table_name("stickyban_matched_cid")] WHERE stickyban = '[sanitizeSQL(ckey)]'"),
|
||||
SSdbcore.NewQuery("DELETE FROM [format_table_name("stickyban_matched_ip")] WHERE stickyban = '[sanitizeSQL(ckey)]'")
|
||||
), warn = TRUE, qdel = TRUE)
|
||||
|
||||
|
||||
log_admin_private("[key_name(usr)] removed [ckey]'s stickyban")
|
||||
message_admins("<span class='adminnotice'>[key_name_admin(usr)] removed [ckey]'s stickyban</span>")
|
||||
@@ -67,18 +90,12 @@
|
||||
to_chat(usr, "<span class='adminnotice'>Error: No sticky ban for [ckey] found!</span>")
|
||||
return
|
||||
|
||||
var/found = 0
|
||||
//we have to do it this way because byond keeps the case in its sticky ban matches WHY!!!
|
||||
for (var/key in ban["keys"])
|
||||
if (ckey(key) == alt)
|
||||
found = 1
|
||||
break
|
||||
|
||||
if (!found)
|
||||
var/key = LAZYACCESS(ban["keys"], alt)
|
||||
if (!key)
|
||||
to_chat(usr, "<span class='adminnotice'>Error: [alt] is not linked to [ckey]'s sticky ban!</span>")
|
||||
return
|
||||
|
||||
if (alert("Are you sure you want to disassociate [alt] from [ckey]'s sticky ban? \nNote: Nothing stops byond from re-linking them","Are you sure","Yes","No") == "No")
|
||||
if (alert("Are you sure you want to disassociate [alt] from [ckey]'s sticky ban? \nNote: Nothing stops byond from re-linking them, Use \[E] to exempt them","Are you sure","Yes","No") == "No")
|
||||
return
|
||||
|
||||
//we have to do this again incase something changes
|
||||
@@ -87,19 +104,22 @@
|
||||
to_chat(usr, "<span class='adminnotice'>Error: The ban disappeared.</span>")
|
||||
return
|
||||
|
||||
found = 0
|
||||
for (var/key in ban["keys"])
|
||||
if (ckey(key) == alt)
|
||||
ban["keys"] -= key
|
||||
found = 1
|
||||
break
|
||||
key = LAZYACCESS(ban["keys"], alt)
|
||||
|
||||
if (!found)
|
||||
if (!key)
|
||||
to_chat(usr, "<span class='adminnotice'>Error: [alt] link to [ckey]'s sticky ban disappeared.</span>")
|
||||
return
|
||||
|
||||
LAZYREMOVE(ban["keys"], alt)
|
||||
world.SetConfig("ban",ckey,list2stickyban(ban))
|
||||
|
||||
SSstickyban.cache[ckey] = ban
|
||||
|
||||
if (SSdbcore.Connect())
|
||||
var/datum/DBQuery/query_remove_stickyban_alt = SSdbcore.NewQuery("DELETE FROM [format_table_name("stickyban_matched_ckey")] WHERE stickyban = '[sanitizeSQL(ckey)]' AND matched_ckey = '[sanitizeSQL(alt)]'")
|
||||
query_remove_stickyban_alt.warn_execute()
|
||||
qdel(query_remove_stickyban_alt)
|
||||
|
||||
log_admin_private("[key_name(usr)] has disassociated [alt] from [ckey]'s sticky ban")
|
||||
message_admins("<span class='adminnotice'>[key_name_admin(usr)] has disassociated [alt] from [ckey]'s sticky ban</span>")
|
||||
|
||||
@@ -124,14 +144,171 @@
|
||||
|
||||
world.SetConfig("ban",ckey,list2stickyban(ban))
|
||||
|
||||
SSstickyban.cache[ckey] = ban
|
||||
|
||||
if (SSdbcore.Connect())
|
||||
var/datum/DBQuery/query_edit_stickyban = SSdbcore.NewQuery("UPDATE [format_table_name("stickyban")] SET reason = '[sanitizeSQL(reason)]' WHERE ckey = '[sanitizeSQL(ckey)]'")
|
||||
query_edit_stickyban.warn_execute()
|
||||
qdel(query_edit_stickyban)
|
||||
|
||||
log_admin_private("[key_name(usr)] has edited [ckey]'s sticky ban reason from [oldreason] to [reason]")
|
||||
message_admins("<span class='adminnotice'>[key_name_admin(usr)] has edited [ckey]'s sticky ban reason from [oldreason] to [reason]</span>")
|
||||
|
||||
if ("exempt")
|
||||
if (!data["ckey"])
|
||||
return
|
||||
var/ckey = data["ckey"]
|
||||
if (!data["alt"])
|
||||
return
|
||||
var/alt = ckey(data["alt"])
|
||||
var/ban = get_stickyban_from_ckey(ckey)
|
||||
if (!ban)
|
||||
to_chat(usr, "<span class='adminnotice'>Error: No sticky ban for [ckey] found!</span>")
|
||||
return
|
||||
|
||||
var/key = LAZYACCESS(ban["keys"], alt)
|
||||
if (!key)
|
||||
to_chat(usr, "<span class='adminnotice'>Error: [alt] is not linked to [ckey]'s sticky ban!</span>")
|
||||
return
|
||||
|
||||
if (alert("Are you sure you want to exempt [alt] from [ckey]'s sticky ban?","Are you sure","Yes","No") == "No")
|
||||
return
|
||||
|
||||
//we have to do this again incase something changes
|
||||
ban = get_stickyban_from_ckey(ckey)
|
||||
if (!ban)
|
||||
to_chat(usr, "<span class='adminnotice'>Error: The ban disappeared.</span>")
|
||||
return
|
||||
|
||||
key = LAZYACCESS(ban["keys"], alt)
|
||||
|
||||
if (!key)
|
||||
to_chat(usr, "<span class='adminnotice'>Error: [alt]'s link to [ckey]'s sticky ban disappeared.</span>")
|
||||
return
|
||||
LAZYREMOVE(ban["keys"], alt)
|
||||
key["exempt"] = TRUE
|
||||
LAZYSET(ban["whitelist"], alt, key)
|
||||
|
||||
world.SetConfig("ban",ckey,list2stickyban(ban))
|
||||
|
||||
SSstickyban.cache[ckey] = ban
|
||||
|
||||
if (SSdbcore.Connect())
|
||||
var/datum/DBQuery/query_exempt_stickyban_alt = SSdbcore.NewQuery("UPDATE [format_table_name("stickyban_matched_ckey")] SET exempt = 1 WHERE stickyban = '[sanitizeSQL(ckey)]' AND matched_ckey = '[sanitizeSQL(alt)]'")
|
||||
query_exempt_stickyban_alt.warn_execute()
|
||||
qdel(query_exempt_stickyban_alt)
|
||||
|
||||
log_admin_private("[key_name(usr)] has exempted [alt] from [ckey]'s sticky ban")
|
||||
message_admins("<span class='adminnotice'>[key_name_admin(usr)] has exempted [alt] from [ckey]'s sticky ban</span>")
|
||||
|
||||
if ("unexempt")
|
||||
if (!data["ckey"])
|
||||
return
|
||||
var/ckey = data["ckey"]
|
||||
if (!data["alt"])
|
||||
return
|
||||
var/alt = ckey(data["alt"])
|
||||
var/ban = get_stickyban_from_ckey(ckey)
|
||||
if (!ban)
|
||||
to_chat(usr, "<span class='adminnotice'>Error: No sticky ban for [ckey] found!</span>")
|
||||
return
|
||||
|
||||
var/key = LAZYACCESS(ban["whitelist"], alt)
|
||||
if (!key)
|
||||
to_chat(usr, "<span class='adminnotice'>Error: [alt] is not exempt from [ckey]'s sticky ban!</span>")
|
||||
return
|
||||
|
||||
if (alert("Are you sure you want to unexempt [alt] from [ckey]'s sticky ban?","Are you sure","Yes","No") == "No")
|
||||
return
|
||||
|
||||
//we have to do this again incase something changes
|
||||
ban = get_stickyban_from_ckey(ckey)
|
||||
if (!ban)
|
||||
to_chat(usr, "<span class='adminnotice'>Error: The ban disappeared.</span>")
|
||||
return
|
||||
|
||||
key = LAZYACCESS(ban["whitelist"], alt)
|
||||
if (!key)
|
||||
to_chat(usr, "<span class='adminnotice'>Error: [alt]'s exemption from [ckey]'s sticky ban disappeared.</span>")
|
||||
return
|
||||
|
||||
LAZYREMOVE(ban["whitelist"], alt)
|
||||
key["exempt"] = FALSE
|
||||
LAZYSET(ban["keys"], alt, key)
|
||||
|
||||
world.SetConfig("ban",ckey,list2stickyban(ban))
|
||||
|
||||
SSstickyban.cache[ckey] = ban
|
||||
|
||||
if (SSdbcore.Connect())
|
||||
var/datum/DBQuery/query_unexempt_stickyban_alt = SSdbcore.NewQuery("UPDATE [format_table_name("stickyban_matched_ckey")] SET exempt = 0 WHERE stickyban = '[sanitizeSQL(ckey)]' AND matched_ckey = '[sanitizeSQL(alt)]'")
|
||||
query_unexempt_stickyban_alt.warn_execute()
|
||||
qdel(query_unexempt_stickyban_alt)
|
||||
|
||||
log_admin_private("[key_name(usr)] has unexempted [alt] from [ckey]'s sticky ban")
|
||||
message_admins("<span class='adminnotice'>[key_name_admin(usr)] has unexempted [alt] from [ckey]'s sticky ban</span>")
|
||||
|
||||
if ("timeout")
|
||||
if (!data["ckey"])
|
||||
return
|
||||
if (!SSdbcore.Connect())
|
||||
to_chat(usr, "<span class='adminnotice'>No database connection!</span>")
|
||||
return
|
||||
|
||||
var/ckey = data["ckey"]
|
||||
|
||||
if (alert("Are you sure you want to put [ckey]'s stickyban on timeout until next round (or removed)?","Are you sure","Yes","No") == "No")
|
||||
return
|
||||
var/ban = get_stickyban_from_ckey(ckey)
|
||||
if (!ban)
|
||||
to_chat(usr, "<span class='adminnotice'>Error: No sticky ban for [ckey] found!</span>")
|
||||
return
|
||||
|
||||
ban["timeout"] = TRUE
|
||||
|
||||
world.SetConfig("ban", ckey, null)
|
||||
|
||||
var/cachedban = SSstickyban.cache[ckey]
|
||||
if (cachedban)
|
||||
cachedban["timeout"] = TRUE
|
||||
|
||||
log_admin_private("[key_name(usr)] has put [ckey]'s sticky ban on timeout.")
|
||||
message_admins("<span class='adminnotice'>[key_name_admin(usr)] has put [ckey]'s sticky ban on timeout.</span>")
|
||||
|
||||
if ("untimeout")
|
||||
if (!data["ckey"])
|
||||
return
|
||||
if (!SSdbcore.Connect())
|
||||
to_chat(usr, "<span class='adminnotice'>No database connection!</span>")
|
||||
return
|
||||
var/ckey = data["ckey"]
|
||||
|
||||
if (alert("Are you sure you want to lift the timeout on [ckey]'s stickyban?","Are you sure","Yes","No") == "No")
|
||||
return
|
||||
|
||||
var/ban = get_stickyban_from_ckey(ckey)
|
||||
var/cachedban = SSstickyban.cache[ckey]
|
||||
if (cachedban)
|
||||
cachedban["timeout"] = FALSE
|
||||
if (!ban)
|
||||
if (!cachedban)
|
||||
to_chat(usr, "<span class='adminnotice'>Error: No sticky ban for [ckey] found!</span>")
|
||||
return
|
||||
ban = cachedban
|
||||
|
||||
ban["timeout"] = FALSE
|
||||
|
||||
world.SetConfig("ban",ckey,list2stickyban(ban))
|
||||
|
||||
log_admin_private("[key_name(usr)] has taken [ckey]'s sticky ban off of timeout.")
|
||||
message_admins("<span class='adminnotice'>[key_name_admin(usr)] has taken [ckey]'s sticky ban off of timeout.</span>")
|
||||
|
||||
|
||||
if ("revert")
|
||||
if (!data["ckey"])
|
||||
return
|
||||
var/ckey = data["ckey"]
|
||||
if (alert("Are you sure you want to revert the sticky ban on [ckey] to its state at round start?","Are you sure","Yes","No") == "No")
|
||||
if (alert("Are you sure you want to revert the sticky ban on [ckey] to its state at round start (or last edit)?","Are you sure","Yes","No") == "No")
|
||||
return
|
||||
var/ban = get_stickyban_from_ckey(ckey)
|
||||
if (!ban)
|
||||
@@ -150,14 +327,22 @@
|
||||
world.SetConfig("ban",ckey,list2stickyban(cached_ban))
|
||||
|
||||
|
||||
/datum/admins/proc/stickyban_gethtml(ckey, ban)
|
||||
. = {"
|
||||
/datum/admins/proc/stickyban_gethtml(ckey)
|
||||
var/ban = get_stickyban_from_ckey(ckey)
|
||||
if (!ban)
|
||||
return
|
||||
var/timeout
|
||||
if (SSdbcore.Connect())
|
||||
timeout = "<a href='?_src_=holder;[HrefToken()];stickyban=[(ban["timeout"] ? "untimeout" : "timeout")]&ckey=[ckey]'>\[[(ban["timeout"] ? "untimeout" : "timeout" )]\]</a>"
|
||||
else
|
||||
timeout = "<a href='?_src_=holder;[HrefToken()];stickyban=revert&ckey=[ckey]'>\[revert\]</a>"
|
||||
. = list({"
|
||||
<a href='?_src_=holder;[HrefToken()];stickyban=remove&ckey=[ckey]'>\[-\]</a>
|
||||
<a href='?_src_=holder;[HrefToken()];stickyban=revert&ckey=[ckey]'>\[revert\]</a>
|
||||
[timeout]
|
||||
<b>[ckey]</b>
|
||||
<br />"
|
||||
[ban["message"]] <b><a href='?_src_=holder;[HrefToken()];stickyban=edit&ckey=[ckey]'>\[Edit\]</a></b><br />
|
||||
"}
|
||||
"})
|
||||
if (ban["admin"])
|
||||
. += "[ban["admin"]]<br />"
|
||||
else
|
||||
@@ -166,19 +351,24 @@
|
||||
for (var/key in ban["keys"])
|
||||
if (ckey(key) == ckey)
|
||||
continue
|
||||
. += "<li><a href='?_src_=holder;[HrefToken()];stickyban=remove_alt&ckey=[ckey]&alt=[ckey(key)]'>\[-\]</a>[key]</li>"
|
||||
. += "<li><a href='?_src_=holder;[HrefToken()];stickyban=remove_alt&ckey=[ckey]&alt=[ckey(key)]'>\[-\]</a>[key]<a href='?_src_=holder;[HrefToken()];stickyban=exempt&ckey=[ckey]&alt=[ckey(key)]'>\[E\]</a></li>"
|
||||
|
||||
for (var/key in ban["whitelist"])
|
||||
if (ckey(key) == ckey)
|
||||
continue
|
||||
. += "<li><a href='?_src_=holder;[HrefToken()];stickyban=remove_alt&ckey=[ckey]&alt=[ckey(key)]'>\[-\]</a>[key]<a href='?_src_=holder;[HrefToken()];stickyban=unexempt&ckey=[ckey]&alt=[ckey(key)]'>\[UE\]</a></li>"
|
||||
|
||||
. += "</ol>\n"
|
||||
|
||||
/datum/admins/proc/stickyban_show()
|
||||
if(!check_rights(R_BAN))
|
||||
return
|
||||
var/list/bans = sortList(world.GetConfig("ban"))
|
||||
var/banhtml = ""
|
||||
var/list/bans = sticky_banned_ckeys()
|
||||
var/list/banhtml = list()
|
||||
for(var/key in bans)
|
||||
var/ckey = ckey(key)
|
||||
var/ban = stickyban2list(world.GetConfig("ban",key))
|
||||
banhtml += "<br /><hr />\n"
|
||||
banhtml += stickyban_gethtml(ckey,ban)
|
||||
banhtml += stickyban_gethtml(ckey)
|
||||
|
||||
var/html = {"
|
||||
<head>
|
||||
@@ -186,22 +376,49 @@
|
||||
</head>
|
||||
<body>
|
||||
<h2>All Sticky Bans:</h2> <a href='?_src_=holder;[HrefToken()];stickyban=add'>\[+\]</a><br>
|
||||
[banhtml]
|
||||
[banhtml.Join("")]
|
||||
</body>
|
||||
"}
|
||||
usr << browse(html,"window=stickybans;size=700x400")
|
||||
|
||||
/proc/sticky_banned_ckeys()
|
||||
if (SSdbcore.Connect() || length(SSstickyban.dbcache))
|
||||
if (SSstickyban.dbcacheexpire < world.time)
|
||||
SSstickyban.Populatedbcache()
|
||||
if (SSstickyban.dbcacheexpire)
|
||||
return SSstickyban.dbcache.Copy()
|
||||
|
||||
return sortList(world.GetConfig("ban"))
|
||||
|
||||
|
||||
/proc/get_stickyban_from_ckey(var/ckey)
|
||||
. = list()
|
||||
if (!ckey)
|
||||
return null
|
||||
ckey = ckey(ckey)
|
||||
. = null
|
||||
for (var/key in world.GetConfig("ban"))
|
||||
if (ckey(key) == ckey)
|
||||
. = stickyban2list(world.GetConfig("ban",key))
|
||||
break
|
||||
if (SSdbcore.Connect() || length(SSstickyban.dbcache))
|
||||
if (SSstickyban.dbcacheexpire < world.time)
|
||||
SSstickyban.Populatedbcache()
|
||||
if (SSstickyban.dbcacheexpire)
|
||||
. = SSstickyban.dbcache[ckey]
|
||||
//reset the cache incase its a newer ban (but only if we didn't update the cache recently)
|
||||
if (!. && SSstickyban.dbcacheexpire != world.time+STICKYBAN_DB_CACHE_TIME)
|
||||
SSstickyban.dbcacheexpire = 1
|
||||
SSstickyban.Populatedbcache()
|
||||
. = SSstickyban.dbcache[ckey]
|
||||
if (.)
|
||||
var/list/cachedban = SSstickyban.cache["[ckey]"]
|
||||
if (cachedban)
|
||||
.["timeout"] = cachedban["timeout"]
|
||||
|
||||
/proc/stickyban2list(var/ban)
|
||||
.["fromdb"] = TRUE
|
||||
return
|
||||
|
||||
. = stickyban2list(world.GetConfig("ban", ckey)) || stickyban2list(world.GetConfig("ban", ckey(ckey))) || list()
|
||||
|
||||
if (!length(.))
|
||||
return null
|
||||
|
||||
/proc/stickyban2list(ban, strictdb = TRUE)
|
||||
if (!ban)
|
||||
return null
|
||||
. = params2list(ban)
|
||||
@@ -212,30 +429,40 @@
|
||||
var/ckey = ckey(key)
|
||||
ckeys[ckey] = ckey //to make searching faster.
|
||||
.["keys"] = ckeys
|
||||
if (.["whitelist"])
|
||||
var/keys = splittext(.["whitelist"], ",")
|
||||
var/ckeys = list()
|
||||
for (var/key in keys)
|
||||
var/ckey = ckey(key)
|
||||
ckeys[ckey] = ckey //to make searching faster.
|
||||
.["whitelist"] = ckeys
|
||||
.["type"] = splittext(.["type"], ",")
|
||||
.["IP"] = splittext(.["IP"], ",")
|
||||
.["computer_id"] = splittext(.["computer_id"], ",")
|
||||
. -= "fromdb"
|
||||
|
||||
|
||||
/proc/list2stickyban(var/list/ban)
|
||||
/proc/list2stickyban(list/ban)
|
||||
if (!ban || !islist(ban))
|
||||
return null
|
||||
. = ban.Copy()
|
||||
if (.["keys"])
|
||||
.["keys"] = jointext(.["keys"], ",")
|
||||
if (.["IP"])
|
||||
.["IP"] = jointext(.["IP"], ",")
|
||||
if (.["computer_id"])
|
||||
.["computer_id"] = jointext(.["computer_id"], ",")
|
||||
if (.["whitelist"])
|
||||
.["whitelist"] = jointext(.["whitelist"], ",")
|
||||
if (.["type"])
|
||||
.["type"] = jointext(.["type"], ",")
|
||||
|
||||
//internal tracking only, shouldn't be stored
|
||||
. -= "reverting"
|
||||
. -= "matches_this_round"
|
||||
. -= "existing_user_matches_this_round"
|
||||
. -= "admin_matches_this_round"
|
||||
. -= "matches_this_round"
|
||||
. -= "reverting"
|
||||
. -= "pending_matches_this_round"
|
||||
|
||||
//storing these can sometimes cause sticky bans to start matching everybody
|
||||
// and isn't even needed for sticky ban matching, as the hub tracks these separately
|
||||
. -= "IP"
|
||||
. -= "computer_id"
|
||||
|
||||
. = list2params(.)
|
||||
|
||||
|
||||
@@ -174,7 +174,7 @@ GLOBAL_DATUM_INIT(iconCache, /savefile, new("tmp/iconCache.sav")) //Cache of ico
|
||||
var/list/row = src.connectionHistory[i]
|
||||
if (!row || row.len < 3 || (!row["ckey"] || !row["compid"] || !row["ip"])) //Passed malformed history object
|
||||
return
|
||||
if (world.IsBanned(row["ckey"], row["compid"], row["ip"], real_bans_only=TRUE))
|
||||
if (world.IsBanned(row["ckey"], row["ip"], row["compid"], real_bans_only=TRUE))
|
||||
found = row
|
||||
break
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
area = /area/space
|
||||
view = "15x15"
|
||||
hub = "Exadv1.spacestation13"
|
||||
hub_password = "kMZy3U5jJHSiBQjr"
|
||||
name = "/tg/ Station 13"
|
||||
fps = 20
|
||||
#ifdef FIND_REF_NO_CHECK_TICK
|
||||
|
||||
Reference in New Issue
Block a user