From adb9b58f8e064effb0fa32642ed52631380b89ac Mon Sep 17 00:00:00 2001 From: AffectedArc07 <25063394+AffectedArc07@users.noreply.github.com> Date: Sat, 16 Jan 2021 21:38:45 +0000 Subject: [PATCH] Updates some admin stuff (#15297) * Fixes camera view * Unique CID tracking notes * Ban tracking * Note round IDs * Karma viewing * Minor tweak * Manual ban job bans * More tweaks * Farie tweaks * Connection result field * Orange watchlist names * Autopopulate tickbox --- SQL/paradise_schema.sql | 5 + SQL/paradise_schema_prefixed.sql | 5 + SQL/updates/19-20.sql | 14 +++ code/__DEFINES/admin.dm | 16 +++ code/__DEFINES/misc.dm | 2 +- code/__HELPERS/unsorted.dm | 11 ++ code/controllers/configuration.dm | 5 + code/defines/procs/admin.dm | 2 + code/modules/admin/IsBanned.dm | 13 ++- code/modules/admin/admin.dm | 1 + code/modules/admin/banjob.dm | 13 +++ code/modules/admin/cookielog.dm | 113 +++++++++++++++++++++ code/modules/admin/db_ban/functions.dm | 19 ++-- code/modules/admin/sql_notes.dm | 30 ++++-- code/modules/admin/topic.dm | 133 +++++++++++++++++++++++-- code/modules/admin/verbs/mapping.dm | 19 ++-- code/modules/admin/watchlist.dm | 6 ++ code/modules/client/client_defines.dm | 3 + code/modules/client/client_procs.dm | 92 +++++++++++++++-- config/example/config.txt | 3 + config/example/dbconfig.txt | 2 +- goon/code/datums/browserOutput.dm | 1 + paradise.dme | 1 + tools/ci/dbconfig.txt | 2 +- 24 files changed, 462 insertions(+), 49 deletions(-) create mode 100644 SQL/updates/19-20.sql create mode 100644 code/modules/admin/cookielog.dm diff --git a/SQL/paradise_schema.sql b/SQL/paradise_schema.sql index 7da1473b4c3..dab229a8051 100644 --- a/SQL/paradise_schema.sql +++ b/SQL/paradise_schema.sql @@ -195,6 +195,7 @@ DROP TABLE IF EXISTS `ban`; CREATE TABLE `ban` ( `id` int(11) NOT NULL AUTO_INCREMENT, `bantime` datetime NOT NULL, + `ban_round_id` INT(11) NULL DEFAULT NULL, `serverip` varchar(32) COLLATE utf8mb4_unicode_ci NOT NULL, `bantype` varchar(32) COLLATE utf8mb4_unicode_ci NOT NULL, `reason` mediumtext COLLATE utf8mb4_unicode_ci NOT NULL, @@ -213,6 +214,7 @@ CREATE TABLE `ban` ( `edits` mediumtext COLLATE utf8mb4_unicode_ci DEFAULT NULL, `unbanned` tinyint(1) DEFAULT NULL, `unbanned_datetime` datetime DEFAULT NULL, + `unbanned_round_id` INT(11) NULL DEFAULT NULL, `unbanned_ckey` varchar(32) COLLATE utf8mb4_unicode_ci DEFAULT NULL, `unbanned_computerid` varchar(32) COLLATE utf8mb4_unicode_ci DEFAULT NULL, `unbanned_ip` varchar(32) COLLATE utf8mb4_unicode_ci DEFAULT NULL, @@ -433,11 +435,13 @@ CREATE TABLE `notes` ( `ckey` varchar(32) NOT NULL, `notetext` text NOT NULL, `timestamp` datetime NOT NULL, + `round_id` INT(11) NULL DEFAULT NULL, `adminckey` varchar(32) NOT NULL, `last_editor` varchar(32), `edits` text, `server` varchar(50) NOT NULL, `crew_playtime` mediumint(8) UNSIGNED DEFAULT '0', + `automated` TINYINT(3) UNSIGNED NULL DEFAULT '0', PRIMARY KEY (`id`), KEY `ckey` (`ckey`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; @@ -527,6 +531,7 @@ CREATE TABLE `connection_log` ( `ckey` varchar(32) NOT NULL, `ip` varchar(32) NOT NULL, `computerid` varchar(32) NOT NULL, + `result` ENUM('ESTABLISHED','DROPPED - IPINTEL','DROPPED - BANNED','DROPPED - INVALID') NOT NULL DEFAULT 'ESTABLISHED' COLLATE 'utf8mb4_general_ci', PRIMARY KEY (`id`), KEY `ckey` (`ckey`), KEY `ip` (`ip`), diff --git a/SQL/paradise_schema_prefixed.sql b/SQL/paradise_schema_prefixed.sql index 4f6898eeee7..a58d6250f65 100644 --- a/SQL/paradise_schema_prefixed.sql +++ b/SQL/paradise_schema_prefixed.sql @@ -194,6 +194,7 @@ DROP TABLE IF EXISTS `SS13_ban`; CREATE TABLE `SS13_ban` ( `id` int(11) NOT NULL AUTO_INCREMENT, `bantime` datetime NOT NULL, + `ban_round_id` INT(11) NULL DEFAULT NULL, `serverip` varchar(32) COLLATE utf8mb4_unicode_ci NOT NULL, `bantype` varchar(32) COLLATE utf8mb4_unicode_ci NOT NULL, `reason` mediumtext COLLATE utf8mb4_unicode_ci NOT NULL, @@ -212,6 +213,7 @@ CREATE TABLE `SS13_ban` ( `edits` mediumtext COLLATE utf8mb4_unicode_ci DEFAULT NULL, `unbanned` tinyint(1) DEFAULT NULL, `unbanned_datetime` datetime DEFAULT NULL, + `unbanned_round_id` INT(11) NULL DEFAULT NULL, `unbanned_ckey` varchar(32) COLLATE utf8mb4_unicode_ci DEFAULT NULL, `unbanned_computerid` varchar(32) COLLATE utf8mb4_unicode_ci DEFAULT NULL, `unbanned_ip` varchar(32) COLLATE utf8mb4_unicode_ci DEFAULT NULL, @@ -432,11 +434,13 @@ CREATE TABLE `SS13_notes` ( `ckey` varchar(32) NOT NULL, `notetext` text NOT NULL, `timestamp` datetime NOT NULL, + `round_id` INT(11) NULL DEFAULT NULL, `adminckey` varchar(32) NOT NULL, `last_editor` varchar(32), `edits` text, `server` varchar(50) NOT NULL, `crew_playtime` mediumint(8) UNSIGNED DEFAULT '0', + `automated` TINYINT(3) UNSIGNED NULL DEFAULT '0', PRIMARY KEY (`id`), KEY `ckey` (`ckey`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; @@ -524,6 +528,7 @@ CREATE TABLE `SS13_connection_log` ( `ckey` varchar(32) NOT NULL, `ip` varchar(32) NOT NULL, `computerid` varchar(32) NOT NULL, + `result` ENUM('ESTABLISHED','DROPPED - IPINTEL','DROPPED - BANNED','DROPPED - INVALID') NOT NULL DEFAULT 'ESTABLISHED' COLLATE 'utf8mb4_general_ci', PRIMARY KEY (`id`), KEY `ckey` (`ckey`), KEY `ip` (`ip`), diff --git a/SQL/updates/19-20.sql b/SQL/updates/19-20.sql new file mode 100644 index 00000000000..16eac5e7b68 --- /dev/null +++ b/SQL/updates/19-20.sql @@ -0,0 +1,14 @@ +# Updating DB from 19-20, -AffectedArc07 +# Tracks round IDs in notes and bans, as well as other admin tweaks + +# Add new columns to ban +ALTER TABLE `ban` ADD COLUMN `ban_round_id` INT NULL DEFAULT NULL AFTER `bantime`; +ALTER TABLE `ban` ADD COLUMN `unbanned_round_id` INT NULL DEFAULT NULL AFTER `unbanned_datetime`; + + +# Add new columns to notes +ALTER TABLE `notes` ADD COLUMN `round_id` INT NULL DEFAULT NULL AFTER `timestamp`; +ALTER TABLE `notes` ADD COLUMN `automated` TINYINT UNSIGNED NULL DEFAULT '0' AFTER `crew_playtime`; + +# Add new column to connection_log +ALTER TABLE `connection_log` ADD COLUMN `result` ENUM('ESTABLISHED','DROPPED - IPINTEL', 'DROPPED - BANNED', 'DROPPED - INVALID') NOT NULL DEFAULT 'ESTABLISHED' AFTER `computerid`; diff --git a/code/__DEFINES/admin.dm b/code/__DEFINES/admin.dm index 95494fb88cf..99fa1c50e0a 100644 --- a/code/__DEFINES/admin.dm +++ b/code/__DEFINES/admin.dm @@ -72,3 +72,19 @@ #define MAX_KEYPRESS_AUTOKICK 50 ///Length of held key rolling buffer #define HELD_KEY_BUFFER_LENGTH 15 + +/// Note text for suppressed CID warning +#define CIDWARNING_SUPPRESSED_NOTETEXT "CID COUNT WARNING DISABLED - Delete this note to re-enable" + +/// Note "ckey" for CID info tracking. Do not EVER update this. +#define CIDTRACKING_PSUEDO_CKEY "ALICE-CIDTRACKING" + +// Connection types. These match enums in the SQL DB. Dont change them +/// Client was let into the server +#define CONNECTION_TYPE_ESTABLISHED "ESTABLISHED" +/// Client was disallowed due to IPIntel +#define CONNECTION_TYPE_DROPPED_IPINTEL "DROPPED - IPINTEL" +/// Client was disallowed due to being banned +#define CONNECTION_TYPE_DROPPED_BANNED "DROPPED - BANNED" +/// Client was disallowed due to invalid data +#define CONNECTION_TYPE_DROPPED_INVALID "DROPPED - INVALID" diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm index 82550c5113a..c37a1943046 100644 --- a/code/__DEFINES/misc.dm +++ b/code/__DEFINES/misc.dm @@ -363,7 +363,7 @@ #define INVESTIGATE_BOMB "bombs" // The SQL version required by this version of the code -#define SQL_VERSION 19 +#define SQL_VERSION 20 // Vending machine stuff #define CAT_NORMAL 1 diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm index 4a2cbf8ce4f..33582212c1f 100644 --- a/code/__HELPERS/unsorted.dm +++ b/code/__HELPERS/unsorted.dm @@ -2052,3 +2052,14 @@ GLOBAL_DATUM_INIT(dview_mob, /mob/dview, new) return TRUE return contains(location.loc) + +/proc/log_connection(ckey, ip, cid, connection_type) + ASSERT(connection_type in list(CONNECTION_TYPE_ESTABLISHED, CONNECTION_TYPE_DROPPED_IPINTEL, CONNECTION_TYPE_DROPPED_BANNED, CONNECTION_TYPE_DROPPED_INVALID)) + var/datum/db_query/query_accesslog = SSdbcore.NewQuery("INSERT INTO `[format_table_name("connection_log")]`(`datetime`, `ckey`, `ip`, `computerid`, `result`) VALUES(Now(), :ckey, :ip, :cid, :result)", list( + "ckey" = ckey, + "ip" = "[ip ? ip : ""]", // This is important. NULL is not the same as "", and if you directly open the `.dmb` file, you get a NULL IP. + "cid" = cid, + "result" = connection_type + )) + query_accesslog.warn_execute() + qdel(query_accesslog) diff --git a/code/controllers/configuration.dm b/code/controllers/configuration.dm index c80fe0f7804..6640882facc 100644 --- a/code/controllers/configuration.dm +++ b/code/controllers/configuration.dm @@ -274,6 +274,9 @@ /// Limit of how many SQL threads can run at once var/rust_sql_thread_limit = 50 + /// Max amount of CIDs that one ckey can have attached to them before they trip a warning + var/max_client_cid_history = 3 + /datum/configuration/New() for(var/T in subtypesof(/datum/game_mode)) var/datum/game_mode/M = T @@ -765,6 +768,8 @@ // End discord stuff if("centcom_ban_db_url") centcom_ban_db_url = value + if("max_client_cid_history") + max_client_cid_history = text2num(value) else log_config("Unknown setting in configuration: '[name]'") diff --git a/code/defines/procs/admin.dm b/code/defines/procs/admin.dm index fa5556b4e40..dea540791be 100644 --- a/code/defines/procs/admin.dm +++ b/code/defines/procs/admin.dm @@ -48,6 +48,8 @@ if(include_link && C) . += "" . += key + if(C && C.watchlisted) + . += "(W)" if(include_link) if(C) . += "" diff --git a/code/modules/admin/IsBanned.dm b/code/modules/admin/IsBanned.dm index 44da9f04d58..e160ee3838d 100644 --- a/code/modules/admin/IsBanned.dm +++ b/code/modules/admin/IsBanned.dm @@ -3,6 +3,8 @@ if(!key || !address || !computer_id) log_adminwarn("Failed Login (invalid data): [key] [address]-[computer_id]") + // The nested ternaries are needed here + INVOKE_ASYNC(GLOBAL_PROC, .proc/log_connection, (ckey(key) || ""), (address || ""), (computer_id || ""), CONNECTION_TYPE_DROPPED_INVALID) 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(type == "world") @@ -10,6 +12,7 @@ if(text2num(computer_id) == 2147483647) //this cid causes stickybans to go haywire log_adminwarn("Failed Login (invalid cid): [key] [address]-[computer_id]") + INVOKE_ASYNC(GLOBAL_PROC, .proc/log_connection, ckey(key), address, computer_id, CONNECTION_TYPE_DROPPED_INVALID) 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 @@ -28,6 +31,7 @@ if(!GLOB.guests_allowed && IsGuestKey(key)) log_adminwarn("Failed Login: [key] [computer_id] [address] - Guests not allowed") // message_admins("Failed Login: [key] - Guests not allowed") + INVOKE_ASYNC(GLOBAL_PROC, .proc/log_connection, ckey(key), address, computer_id, CONNECTION_TYPE_DROPPED_BANNED) return list("reason"="guest", "desc"="\nReason: Guests not allowed. Please sign in with a BYOND account.") //check if the IP address is a known proxy/vpn, and the user is not whitelisted @@ -36,6 +40,7 @@ var/mistakemessage = "" if(config.banappeals) mistakemessage = "\nIf you have to use one, request whitelisting at: [config.banappeals]" + INVOKE_ASYNC(GLOBAL_PROC, .proc/log_connection, ckey(key), address, computer_id, CONNECTION_TYPE_DROPPED_IPINTEL) return list("reason"="using proxy or vpn", "desc"="\nReason: Proxies/VPNs are not allowed here. [mistakemessage]") @@ -72,7 +77,7 @@ sql_query_params["cid"] = computer_id var/datum/db_query/query = SSdbcore.NewQuery({" - SELECT ckey, ip, computerid, a_ckey, reason, expiration_time, duration, bantime, bantype FROM [format_table_name("ban")] + SELECT ckey, ip, computerid, a_ckey, reason, expiration_time, duration, bantime, bantype, ban_round_id FROM [format_table_name("ban")] WHERE (ckey=:ckeytext [ipquery] [cidquery]) AND (bantype = 'PERMABAN' OR bantype = 'ADMIN_PERMABAN' OR ((bantype = 'TEMPBAN' OR bantype = 'ADMIN_TEMPBAN') AND expiration_time > Now())) AND isnull(unbanned)"}, sql_query_params) @@ -91,6 +96,7 @@ var/duration = query.item[7] var/bantime = query.item[8] var/bantype = query.item[9] + var/ban_round_id = query.item[10] if(bantype == "ADMIN_PERMABAN" || bantype == "ADMIN_TEMPBAN") //admin bans MUST match on ckey to prevent cid-spoofing attacks // as well as dynamic ip abuse @@ -114,11 +120,12 @@ appealmessage = " You may appeal it at [config.banappeals]." expires = " This ban does not expire automatically and must be appealed.[appealmessage]" - var/desc = "\nReason: You, or another user of this computer or connection ([pckey]) is banned from playing here. The ban reason is:\n[reason]\nThis ban was applied by [ackey] on [bantime].[expires]" + var/desc = "\nReason: You, or another user of this computer or connection ([pckey]) is banned from playing here. The ban reason is:\n[reason]\nThis ban was applied by [ackey] on [bantime][ban_round_id ? " (Round [ban_round_id])" : ""].[expires]" . = list("reason"="[bantype]", "desc"="[desc]") log_adminwarn("Failed Login: [key] [computer_id] [address] - Banned [.["reason"]]") + INVOKE_ASYNC(GLOBAL_PROC, .proc/log_connection, ckey(key), address, computer_id, CONNECTION_TYPE_DROPPED_BANNED) qdel(query) return . qdel(query) @@ -135,5 +142,5 @@ return null else log_adminwarn("Failed Login: [key] [computer_id] [address] - Banned [.["message"]]") - + INVOKE_ASYNC(GLOBAL_PROC, .proc/log_connection, ckey(key), address, computer_id, CONNECTION_TYPE_DROPPED_BANNED) return . diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm index 1d63a00874f..64ad4bf7c4a 100644 --- a/code/modules/admin/admin.dm +++ b/code/modules/admin/admin.dm @@ -126,6 +126,7 @@ GLOBAL_VAR_INIT(nologevent, 0) body += "Jobban | " body += "Appearance Ban | " body += "Notes | " + body += "View Karma | " if(config.forum_playerinfo_url) body += "WebInfo | " if(M.client) diff --git a/code/modules/admin/banjob.dm b/code/modules/admin/banjob.dm index 22d2a825ac6..7ff26de5992 100644 --- a/code/modules/admin/banjob.dm +++ b/code/modules/admin/banjob.dm @@ -42,6 +42,19 @@ GLOBAL_DATUM_INIT(jobban_regex, /regex, regex("(\[\\S]+) - (\[^#]+\[^# ])(?: ## else return 0 +/proc/jobban_isbanned_ckey(ckey, rank) + if(!ckey || !rank) + return null + + if(config.guest_jobban && guest_jobbans(rank)) + if(IsGuestKey(ckey)) + return "Guest Job-ban" + + if(GLOB.jobban_assoclist[ckey]) + return GLOB.jobban_assoclist[ckey][rank] + + return null + /proc/jobban_loadbanfile() if(config.ban_legacy_system) var/savefile/S=new("data/job_full.ban") diff --git a/code/modules/admin/cookielog.dm b/code/modules/admin/cookielog.dm new file mode 100644 index 00000000000..a2de0c126fe --- /dev/null +++ b/code/modules/admin/cookielog.dm @@ -0,0 +1,113 @@ +////////////////////////////////////////////////////////////////////////////////////// +// This file houses all the code for cookie datum serialization and deserialization +// +// If you are going to modify ANYTHING in here, please test it THOROUGHLY +// The serialization and deserialization here is so complicated that you WILL break something here +// PLEASE test things properly if you modify this file. -aa07 +// +////////////////////////////////////////////////////////////////////////////////////// + +// Everything in this file is intentionally NOT autodocumented. PLEASE keep it that way. +// All these defines are integral to the workings and mesh together with the database. +// DO NOT EDIT THESE UNDER ANY CIRCUMSTANCES EVER +#define COOKIERECORD_FIRST_INFRACTION "First cookie match: " +#define COOKIERECORD_LAST_INFRACTION "Last cookie match: " +#define COOKIERECORD_TOTAL_INFRACTIONS "Total cookie matches: " +#define COOKIERECORD_MATCHED_CKEYS "Matched ckeys: " +#define COOKIERECORD_MATCHED_IPS "Matched IPs: " +#define COOKIERECORD_MATCHED_CIDS "Matched CIDS: " +#define COOKIERECORD_PSUEDO_CKEY "ALICE-COOKIE_RECORD" + +/datum/cookie_record + var/cookie_holder_ckey + var/first_infraction_date + var/last_infraction_date + var/infraction_count + var/list/matched_ckeys = list() + var/list/matched_ips = list() + var/list/matched_cids = list() + +// Some of these params can be null, others CAN NOT +/datum/cookie_record/New(holder_ckey, matched_ckey, matched_ip, matched_cid) + // Right off the bat + cookie_holder_ckey = holder_ckey + + var/has_note = FALSE + var/raw_text = "" + // Now lets see if we have a note logging the infraction in the past + var/datum/db_query/check_existing_note = SSdbcore.NewQuery("SELECT notetext FROM [format_table_name("notes")] WHERE ckey=:ckey AND adminckey=:ackey", list( + "ckey" = cookie_holder_ckey, + "ackey" = COOKIERECORD_PSUEDO_CKEY + )) + if(!check_existing_note.warn_execute()) + qdel(check_existing_note) + return + if(check_existing_note.NextRow()) + has_note = TRUE + raw_text = check_existing_note.item[1] + qdel(check_existing_note) + + if(has_note) + deserialize_and_load(raw_text) + infraction_count++ + else + // Sane defaults + first_infraction_date = SQLtime() + infraction_count = 1 + + last_infraction_date = SQLtime() + matched_ckeys |= matched_ckey + matched_ips |= matched_ip + matched_cids |= matched_cid + + serialize_and_save(has_note) + +/* + Expected output below. These are parsed from raw_text by splitting by
+ [1] COOKIERECORD_FIRST_INFRACTION + [2] COOKIERECORD_LAST_INFRACTION + [3] COOKIERECORD_TOTAL_INFRACTIONS + [4] COOKIERECORD_MATCHED_CKEYS + [5] COOKIERECORD_MATCHED_IPS + [6] COOKIERECORD_MATCHED_CIDS +*/ + +/datum/cookie_record/proc/deserialize_and_load(raw_text) + var/list/lines = splittext(raw_text, "
") + // Text + first_infraction_date = splittext(lines[1], COOKIERECORD_FIRST_INFRACTION)[2] + last_infraction_date = splittext(lines[2], COOKIERECORD_LAST_INFRACTION)[2] + // Number + infraction_count = text2num(splittext(lines[3], COOKIERECORD_TOTAL_INFRACTIONS)[2]) // Make sure its a number + // Lists + matched_ckeys = splittext(splittext(lines[4], COOKIERECORD_MATCHED_CKEYS)[2], ",") + matched_ips = splittext(splittext(lines[5], COOKIERECORD_MATCHED_IPS)[2], ",") + matched_cids = splittext(splittext(lines[6], COOKIERECORD_MATCHED_CIDS)[2], ",") + +/datum/cookie_record/proc/serialize_and_save(has_note) + var/serialized_text + var/list/serialized_list = list() + serialized_list.len = 6 // Make it 6 off the bat + + serialized_list[1] = "[COOKIERECORD_FIRST_INFRACTION][first_infraction_date]" + serialized_list[2] = "[COOKIERECORD_LAST_INFRACTION][last_infraction_date]" + serialized_list[3] = "[COOKIERECORD_TOTAL_INFRACTIONS][infraction_count]" + serialized_list[4] = "[COOKIERECORD_MATCHED_CKEYS][matched_ckeys.Join(",")]" + serialized_list[5] = "[COOKIERECORD_MATCHED_IPS][matched_ips.Join(",")]" + serialized_list[6] = "[COOKIERECORD_MATCHED_CIDS][matched_cids.Join(",")]" + + serialized_text = serialized_list.Join("
") + + if(has_note) // They have a note. Update. + var/datum/db_query/update_existing_note = SSdbcore.NewQuery("UPDATE [format_table_name("notes")] SET notetext=:nt, timestamp=NOW(), round_id=:rid WHERE ckey=:ckey AND adminckey=:ackey", list( + "nt" = serialized_text, + "rid" = GLOB.round_id, + "ckey" = cookie_holder_ckey, + "ackey" = COOKIERECORD_PSUEDO_CKEY + )) + if(!update_existing_note.warn_execute()) + qdel(update_existing_note) + return + qdel(update_existing_note) + else // They dont have a note. Insert. + add_note(cookie_holder_ckey, serialized_text, adminckey = COOKIERECORD_PSUEDO_CKEY, logged = FALSE, checkrights = FALSE, automated = TRUE) diff --git a/code/modules/admin/db_ban/functions.dm b/code/modules/admin/db_ban/functions.dm index 126e584e864..105c6bd6778 100644 --- a/code/modules/admin/db_ban/functions.dm +++ b/code/modules/admin/db_ban/functions.dm @@ -146,8 +146,8 @@ qdel(adm_query) var/datum/db_query/query_insert = SSdbcore.NewQuery({" - INSERT INTO [format_table_name("ban")] (`id`,`bantime`,`serverip`,`bantype`,`reason`,`job`,`duration`,`rounds`,`expiration_time`,`ckey`,`computerid`,`ip`,`a_ckey`,`a_computerid`,`a_ip`,`who`,`adminwho`,`edits`,`unbanned`,`unbanned_datetime`,`unbanned_ckey`,`unbanned_computerid`,`unbanned_ip`) - VALUES (null, Now(), :serverip, :bantype_str, :reason, :job, :duration, :rounds, Now() + INTERVAL :duration MINUTE, :ckey, :computerid, :ip, :a_ckey, :a_computerid, :a_ip, :who, :adminwho, '', null, null, null, null, null) + INSERT INTO [format_table_name("ban")] (`id`,`bantime`,`serverip`,`bantype`,`reason`,`job`,`duration`,`rounds`,`expiration_time`,`ckey`,`computerid`,`ip`,`a_ckey`,`a_computerid`,`a_ip`,`who`,`adminwho`,`edits`,`unbanned`,`unbanned_datetime`,`unbanned_ckey`,`unbanned_computerid`,`unbanned_ip`,`ban_round_id`,`unbanned_round_id`) + VALUES (null, Now(), :serverip, :bantype_str, :reason, :job, :duration, :rounds, Now() + INTERVAL :duration MINUTE, :ckey, :computerid, :ip, :a_ckey, :a_computerid, :a_ip, :who, :adminwho, '', null, null, null, null, null, :roundid, null) "}, list( // Get ready for parameters "serverip" = serverip, @@ -163,7 +163,8 @@ "a_computerid" = a_computerid, "a_ip" = a_ip, "who" = who, - "adminwho" = adminwho + "adminwho" = adminwho, + "roundid" = GLOB.round_id )) if(!query_insert.warn_execute()) qdel(query_insert) @@ -399,10 +400,11 @@ var/unban_computerid = src.owner:computer_id var/unban_ip = src.owner:address - var/datum/db_query/query_update = SSdbcore.NewQuery("UPDATE [format_table_name("ban")] SET unbanned = 1, unbanned_datetime = Now(), unbanned_ckey=:unban_ckey, unbanned_computerid=:unban_computerid, unbanned_ip=:unban_ip WHERE id=:id", list( + var/datum/db_query/query_update = SSdbcore.NewQuery("UPDATE [format_table_name("ban")] SET unbanned = 1, unbanned_datetime = Now(), unbanned_ckey=:unban_ckey, unbanned_computerid=:unban_computerid, unbanned_ip=:unban_ip, unbanned_round_id=:roundid WHERE id=:id", list( "unban_ckey" = unban_ckey, "unban_computerid" = unban_computerid, "unban_ip" = unban_ip, + "roundid" = GLOB.round_id, "id" = id )) if(!query_update.warn_execute()) @@ -477,6 +479,7 @@ output += "" output += "" output += "Reason:

" + output += " Auto populate CID & IP for online players
" output += "" output += "" @@ -582,7 +585,7 @@ var/datum/db_query/select_query = SSdbcore.NewQuery({" - SELECT id, bantime, bantype, reason, job, duration, expiration_time, ckey, a_ckey, unbanned, unbanned_ckey, unbanned_datetime, edits, ip, computerid + SELECT id, bantime, bantype, reason, job, duration, expiration_time, ckey, a_ckey, unbanned, unbanned_ckey, unbanned_datetime, edits, ip, computerid, ban_round_id, unbanned_round_id FROM [format_table_name("ban")] WHERE 1 [playersearch] [adminsearch] [ipsearch] [cidsearch] [bantypesearch] ORDER BY bantime DESC LIMIT 100"}, sql_params) if(!select_query.warn_execute()) @@ -605,6 +608,8 @@ var/edits = select_query.item[13] var/ip = select_query.item[14] var/cid = select_query.item[15] + var/ban_round_id = select_query.item[16] + var/unban_round_id = select_query.item[17] var/lcolor = blcolor var/dcolor = bdcolor @@ -632,7 +637,7 @@ output += "" output += "[typedesc]" output += "[ckey]" - output += "[bantime]" + output += "[bantime][ban_round_id ? " (Round [ban_round_id])" : ""]" output += "[ackey]" output += "[(unbanned) ? "" : "Unban"]" output += "" @@ -652,7 +657,7 @@ output += "" if(unbanned) output += "" - output += "UNBANNED by admin [unbanckey] on [unbantime]" + output += "UNBANNED by admin [unbanckey] on [unbantime][unban_round_id ? " (Round [unban_round_id])" : ""]" output += "" output += "" output += " " diff --git a/code/modules/admin/sql_notes.dm b/code/modules/admin/sql_notes.dm index 0a9db55cdf2..70fa439861a 100644 --- a/code/modules/admin/sql_notes.dm +++ b/code/modules/admin/sql_notes.dm @@ -1,5 +1,5 @@ // Do not attemtp to remove the blank string from the server arg. It will break DB saving. -/proc/add_note(target_ckey, notetext, timestamp, adminckey, logged = 1, server = "", checkrights = 1) +/proc/add_note(target_ckey, notetext, timestamp, adminckey, logged = 1, server = "", checkrights = 1, show_after = TRUE, automated = FALSE) if(checkrights && !check_rights(R_ADMIN|R_MOD)) return if(!SSdbcore.IsConnected()) @@ -57,15 +57,20 @@ if(config && config.server_name) server = config.server_name + // Force cast this to 1/0 incase someone tries to feed bad data + automated = !!automated + var/datum/db_query/query_noteadd = SSdbcore.NewQuery({" - INSERT INTO [format_table_name("notes")] (ckey, timestamp, notetext, adminckey, server, crew_playtime) - VALUES (:targetckey, NOW(), :notetext, :adminkey, :server, :crewnum) + INSERT INTO [format_table_name("notes")] (ckey, timestamp, notetext, adminckey, server, crew_playtime, round_id, automated) + VALUES (:targetckey, NOW(), :notetext, :adminkey, :server, :crewnum, :roundid, :automated) "}, list( "targetckey" = target_ckey, "notetext" = notetext, "adminkey" = adminckey, "server" = server, - "crewnum" = crew_number + "crewnum" = crew_number, + "roundid" = GLOB.round_id, + "automated" = automated )) if(!query_noteadd.warn_execute()) qdel(query_noteadd) @@ -74,7 +79,8 @@ if(logged) log_admin("[usr ? key_name(usr) : adminckey] has added a note to [target_ckey]: [notetext]") message_admins("[usr ? key_name_admin(usr) : adminckey] has added a note to [target_ckey]:
[notetext]") - show_note(target_ckey) + if(show_after) + show_note(target_ckey) /proc/remove_note(note_id) if(!check_rights(R_ADMIN|R_MOD)) @@ -124,7 +130,7 @@ return note_id = text2num(note_id) var/target_ckey - var/datum/db_query/query_find_note_edit = SSdbcore.NewQuery("SELECT ckey, notetext, adminckey FROM [format_table_name("notes")] WHERE id=:note_id", list( + var/datum/db_query/query_find_note_edit = SSdbcore.NewQuery("SELECT ckey, notetext, adminckey, automated FROM [format_table_name("notes")] WHERE id=:note_id", list( "note_id" = note_id )) if(!query_find_note_edit.warn_execute()) @@ -134,6 +140,10 @@ target_ckey = query_find_note_edit.item[1] var/old_note = query_find_note_edit.item[2] var/adminckey = query_find_note_edit.item[3] + var/automated = query_find_note_edit.item[4] + if(automated) + to_chat(usr, "That note is generated automatically. You can't edit it.") + return var/new_note = input("Input new note", "New Note", "[old_note]") as message|null if(!new_note) return @@ -171,7 +181,7 @@ if(target_ckey) var/target_sql_ckey = ckey(target_ckey) var/datum/db_query/query_get_notes = SSdbcore.NewQuery({" - SELECT id, timestamp, notetext, adminckey, last_editor, server, crew_playtime + SELECT id, timestamp, notetext, adminckey, last_editor, server, crew_playtime, round_id, automated FROM [format_table_name("notes")] WHERE ckey=:targetkey ORDER BY timestamp"}, list( "targetkey" = target_sql_ckey )) @@ -190,14 +200,16 @@ var/last_editor = query_get_notes.item[5] var/server = query_get_notes.item[6] var/mins = text2num(query_get_notes.item[7]) - output += "[timestamp] | [server] | [adminckey]" + var/round_id = text2num(query_get_notes.item[8]) + var/automated = text2num(query_get_notes.item[9]) // 0/1 bool stored in table + output += "[timestamp][round_id ? " (Round [round_id])" : ""] | [server] | [adminckey]" if(mins) var/playstring = get_exp_format(mins) output += " | [playstring] as Crew" output += "" if(!linkless) - output += " \[Remove Note\] \[Edit Note\]" + output += " \[Remove Note\] [automated ? "\[Automated Note\]" : "\[Edit Note\]"]" if(last_editor) output += " Last edit by [last_editor] (Click here to see edit log)" output += "
[notetext]
" diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm index fb21ec0380b..cfcc216187d 100644 --- a/code/modules/admin/topic.dm +++ b/code/modules/admin/topic.dm @@ -108,6 +108,10 @@ var/banjob = href_list["dbbanaddjob"] var/banreason = href_list["dbbanreason"] + var/job_ban = FALSE + var/multi_job = FALSE + var/list/jobs_to_ban = list() + banckey = ckey(banckey) switch(bantype) @@ -127,10 +131,12 @@ to_chat(usr, "Not enough parameters (Requires ckey, reason and job)") return banduration = null + job_ban = TRUE if(BANTYPE_JOB_TEMP) if(!banckey || !banreason || !banjob || !banduration) to_chat(usr, "Not enough parameters (Requires ckey, reason and job)") return + job_ban = TRUE if(BANTYPE_APPEARANCE) if(!banckey || !banreason) to_chat(usr, "Not enough parameters (Requires ckey and reason)") @@ -151,11 +157,11 @@ var/mob/playermob - for(var/mob/M in GLOB.player_list) - if(M.ckey == banckey) - playermob = M - break - + if("autopopulate" in href_list) + for(var/mob/M in GLOB.player_list) + if(M.ckey == banckey) + playermob = M + break banreason = "(MANUAL BAN) "+banreason @@ -167,7 +173,68 @@ else message_admins("Ban process: A mob matching [playermob.ckey] was found at location [playermob.x], [playermob.y], [playermob.z]. Custom IP and computer id fields replaced with the IP and computer id from the located mob") - DB_ban_record(bantype, playermob, banduration, banreason, banjob, null, banckey, banip, bancid ) + if(job_ban) + if(banjob in list("commanddept","securitydept","engineeringdept","medicaldept","sciencedept","supportdept","nonhumandept")) + multi_job = TRUE + switch(banjob) + if("commanddept") + for(var/jobPos in GLOB.command_positions) + if(!jobPos) continue + var/datum/job/temp = SSjobs.GetJob(jobPos) + if(!temp) continue + jobs_to_ban += temp.title + if("securitydept") + for(var/jobPos in GLOB.security_positions) + if(!jobPos) continue + var/datum/job/temp = SSjobs.GetJob(jobPos) + if(!temp) continue + jobs_to_ban += temp.title + if("engineeringdept") + for(var/jobPos in GLOB.engineering_positions) + if(!jobPos) continue + var/datum/job/temp = SSjobs.GetJob(jobPos) + if(!temp) continue + jobs_to_ban += temp.title + if("medicaldept") + for(var/jobPos in GLOB.medical_positions) + if(!jobPos) continue + var/datum/job/temp = SSjobs.GetJob(jobPos) + if(!temp) continue + jobs_to_ban += temp.title + if("sciencedept") + for(var/jobPos in GLOB.science_positions) + if(!jobPos) continue + var/datum/job/temp = SSjobs.GetJob(jobPos) + if(!temp) continue + jobs_to_ban += temp.title + if("supportdept") + for(var/jobPos in GLOB.support_positions) + if(!jobPos) continue + var/datum/job/temp = SSjobs.GetJob(jobPos) + if(!temp) continue + jobs_to_ban += temp.title + if("nonhumandept") + jobs_to_ban += "pAI" + for(var/jobPos in GLOB.nonhuman_positions) + if(!jobPos) continue + var/datum/job/temp = SSjobs.GetJob(jobPos) + if(!temp) continue + jobs_to_ban += temp.title + + // If the job ban is for multiple jobs in one group (IE: Command), iterate through jobs and ban each individually + if(multi_job) + //Create a list of unbanned jobs within joblist + var/list/notbannedlist = list() + for(var/job in jobs_to_ban) + if(!jobban_isbanned_ckey(banckey, job)) + notbannedlist += job + + for(var/job in notbannedlist) + DB_ban_record(bantype, playermob, banduration, banreason, job, null, banckey, banip, bancid) + + // Otherwise, do it normally + else + DB_ban_record(bantype, playermob, banduration, banreason, banjob, null, banckey, banip, bancid) else if(href_list["editrights"]) @@ -3423,7 +3490,61 @@ log_sql("[usr.key] | [response]") else if(answer == "no") log_sql("[usr.key] | Reported no server hang. Please investigate") + else if(href_list["suppresscidwarning"]) + if(!check_rights(R_ADMIN)) + return + add_note(href_list["suppresscidwarning"], CIDWARNING_SUPPRESSED_NOTETEXT, show_after = FALSE) + else if(href_list["viewkarma"]) + if(!check_rights(R_ADMIN)) + return + var/target_ckey = href_list["viewkarma"] + + var/total_karma = 0 + var/spent_karma = 0 + var/unlocked_jobs = "" + var/unlocked_species = "" + // Get their totals + var/datum/db_query/query_get_totals = SSdbcore.NewQuery("SELECT karma, karmaspent FROM [format_table_name("karmatotals")] WHERE byondkey=:ckey", list( + "ckey" = target_ckey + )) + if(!query_get_totals.warn_execute()) + qdel(query_get_totals) + return + // Even if there aint a row, we can still assume the defaults of 0 above + if(query_get_totals.NextRow()) + total_karma = query_get_totals.item[1] + spent_karma = query_get_totals.item[2] + + qdel(query_get_totals) + + // Now get their unlocks + var/datum/db_query/query_get_unlocks = SSdbcore.NewQuery("SELECT job, species FROM [format_table_name("whitelist")] WHERE ckey=:ckey", list( + "ckey" = target_ckey + )) + if(!query_get_unlocks.warn_execute()) + qdel(query_get_unlocks) + return + if(query_get_unlocks.NextRow()) + unlocked_jobs = query_get_unlocks.item[1] + unlocked_species = query_get_unlocks.item[2] + + qdel(query_get_unlocks) + + // Pack it into a dat + var/dat = {" + + "} + + var/datum/browser/popup = new(usr, "view_karma", "Karma stats for [target_ckey]", 600, 300) + popup.set_content(dat) + popup.open(FALSE) /client/proc/create_eventmob_for(var/mob/living/carbon/human/H, var/killthem = 0) if(!check_rights(R_EVENT)) diff --git a/code/modules/admin/verbs/mapping.dm b/code/modules/admin/verbs/mapping.dm index ce31c674cf5..43b806b86f5 100644 --- a/code/modules/admin/verbs/mapping.dm +++ b/code/modules/admin/verbs/mapping.dm @@ -22,15 +22,6 @@ GLOBAL_VAR_INIT(camera_range_display_status, 0) GLOBAL_VAR_INIT(intercom_range_display_status, 0) -/obj/effect/debugging/camera_range - icon = 'icons/480x480.dmi' - icon_state = "25percent" - -/obj/effect/debugging/camera_range/New() - . = ..() - src.pixel_x = -224 - src.pixel_y = -224 - /obj/effect/debugging/mapfix_marker name = "map fix marker" icon = 'icons/mob/screen_gen.dmi' @@ -56,12 +47,16 @@ GLOBAL_VAR_INIT(intercom_range_display_status, 0) else GLOB.camera_range_display_status = 1 - for(var/obj/effect/debugging/camera_range/C in world) - qdel(C) + for(var/obj/effect/debugging/marker/M in world) + qdel(M) if(GLOB.camera_range_display_status) for(var/obj/machinery/camera/C in GLOB.cameranet.cameras) - new/obj/effect/debugging/camera_range(C.loc) + for(var/turf/T in orange(7, C)) + var/obj/effect/debugging/marker/F = new/obj/effect/debugging/marker(T) + if(!(F in view(7, C.loc))) + qdel(F) + SSblackbox.record_feedback("tally", "admin_verb", 1, "Camera Range Display") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! /client/proc/sec_camera_report() diff --git a/code/modules/admin/watchlist.dm b/code/modules/admin/watchlist.dm index 7387b0a5215..df6a56933f4 100644 --- a/code/modules/admin/watchlist.dm +++ b/code/modules/admin/watchlist.dm @@ -41,6 +41,9 @@ return log_admin("[key_name(usr)] has added [target_ckey] to the watchlist - Reason: [reason]") message_admins("[key_name_admin(usr)] has added [target_ckey] to the watchlist - Reason: [reason]", 1) + if(GLOB.directory[target_ckey]) + var/client/C = GLOB.directory[target_ckey] + C.watchlisted = TRUE // Mark them ingame now if(browse) watchlist_show(target_ckey) @@ -56,6 +59,9 @@ qdel(query_watchdel) log_admin("[key_name(usr)] has removed [target_ckey] from the watchlist") message_admins("[key_name_admin(usr)] has removed [target_ckey] from the watchlist", 1) + if(GLOB.directory[target_ckey]) + var/client/C = GLOB.directory[target_ckey] + C.watchlisted = FALSE // Mark them ingame now if(browse) watchlist_show() diff --git a/code/modules/client/client_defines.dm b/code/modules/client/client_defines.dm index 11c8307cfe1..ca30cf25d5a 100644 --- a/code/modules/client/client_defines.dm +++ b/code/modules/client/client_defines.dm @@ -109,6 +109,9 @@ /// Has the client accepted the TOS about data collection and other stuff var/tos_consent = FALSE + /// Is the client watchlisted + var/watchlisted = FALSE + /client/vv_edit_var(var_name, var_value) switch(var_name) // I know we will never be in a world where admins are editing client vars to let people bypass TOS diff --git a/code/modules/client/client_procs.dm b/code/modules/client/client_procs.dm index 261f1986ff0..0c2aa04569e 100644 --- a/code/modules/client/client_procs.dm +++ b/code/modules/client/client_procs.dm @@ -390,6 +390,8 @@ GLOB.panic_bunker_enabled = FALSE message_admins("Panic bunker has been automatically disabled due to playercount dropping below [threshold]") + INVOKE_ASYNC(src, .proc/cid_count_check) + /client/proc/is_connecting_from_localhost() var/localhost_addresses = list("127.0.0.1", "::1") // Adresses if(!isnull(address) && (address in localhost_addresses)) @@ -524,6 +526,7 @@ if(watchreason) message_admins("Notice: [key_name_admin(src)] is on the watchlist and has just connected - Reason: [watchreason]") SSdiscord.send2discord_simple_noadmins("**\[Watchlist]** [key_name(src)] is on the watchlist and has just connected - Reason: [watchreason]") + watchlisted = TRUE //Just the standard check to see if it's actually a number @@ -576,15 +579,7 @@ INVOKE_ASYNC(src, /client/.proc/get_byond_account_date, TRUE) // Async to avoid other procs in the client chain being delayed by a web request // Log player connections to DB - var/datum/db_query/query_accesslog = SSdbcore.NewQuery("INSERT INTO `[format_table_name("connection_log")]`(`datetime`,`ckey`,`ip`,`computerid`) VALUES(Now(), :ckey, :ip, :cid)", list( - "ckey" = ckey, - "ip" = "[address ? address : ""]", // This is important. NULL is not the same as "", and if you directly open the `.dmb` file, you get a NULL IP. - "cid" = computer_id - )) - // We do nothing with output here, or anything else after, so we dont need to if() wrap it - // If you ever extend this proc below this point, please wrap these with an if() in the same way its done above - query_accesslog.warn_execute() - qdel(query_accesslog) + INVOKE_ASYNC(GLOBAL_PROC, .proc/log_connection, ckey, address, computer_id, CONNECTION_TYPE_ESTABLISHED) /client/proc/check_ip_intel() set waitfor = 0 //we sleep when getting the intel, no need to hold up the client connection while we sleep @@ -1139,6 +1134,85 @@ // If we are here, they have not accepted, and need to read it return FALSE +/** + * Checks if the client has more than a configured amount of CIDs tied to them in the past + */ +/client/proc/cid_count_check() + // If the config is 0, disable this + if(config.max_client_cid_history == 0) + return + + // If we have no DB, dont even bother + if(!SSdbcore.IsConnected()) + return + + // Now query how many cids they have + var/datum/db_query/query_cidcheck = SSdbcore.NewQuery("SELECT COUNT(DISTINCT computerID) FROM connection_log WHERE ckey=:ckey", list( + "ckey" = ckey + )) + if(!query_cidcheck.warn_execute()) + qdel(query_cidcheck) + return + + var/cidcount = 0 + if(query_cidcheck.NextRow()) + cidcount = query_cidcheck.item[1] + qdel(query_cidcheck) + + if(cidcount > config.max_client_cid_history) + // Check their notes for CID tracking in the past + var/has_note = FALSE + var/note_text = "" + var/datum/db_query/query_find_track_note = SSdbcore.NewQuery("SELECT notetext FROM [format_table_name("notes")] WHERE ckey=:ckey AND adminckey=:ackey", list( + "ckey" = ckey, + "ackey" = CIDTRACKING_PSUEDO_CKEY + )) + if(!query_find_track_note.warn_execute()) + qdel(query_find_track_note) + return + if(query_find_track_note.NextRow()) + note_text = query_find_track_note.item[1] // Grab existing note text + has_note = TRUE + qdel(query_find_track_note) + + + if(has_note) // They have a note. Update it. + var/new_text = "Connected on the date of this note with unique CID #[cidcount]" + // Only update the note if the text is different. Otherwise it bumps the timestamp when it shouldnt + if(note_text != new_text) + var/datum/db_query/query_update_track_note = SSdbcore.NewQuery("UPDATE [format_table_name("notes")] SET notetext=:notetext, timestamp=NOW(), round_id=:rid WHERE ckey=:ckey AND adminckey=:ackey", list( + "notetext" = new_text, + "ckey" = ckey, + "ackey" = CIDTRACKING_PSUEDO_CKEY, + "rid" = GLOB.round_id + )) + if(!query_update_track_note.warn_execute()) + qdel(query_update_track_note) + return + qdel(query_update_track_note) + + else // They dont have a note. Make one. + // NOT logged because its automatic and will spam logs otherwise + // Also right checking must be disabled because its a psuedockey, not a real one + add_note(ckey, "Connected on the date of this note with unique CID #[cidcount]", adminckey = CIDTRACKING_PSUEDO_CKEY, logged = FALSE, checkrights = FALSE, automated = TRUE) + + var/show_warning = TRUE + // Check if they have a note that matches the warning suppressor + var/datum/db_query/query_find_note = SSdbcore.NewQuery("SELECT id FROM [format_table_name("notes")] WHERE ckey=:ckey AND notetext=:notetext", list( + "ckey" = ckey, + "notetext" = CIDWARNING_SUPPRESSED_NOTETEXT + )) + if(!query_find_note.warn_execute()) + qdel(query_find_note) + return + if(query_find_note.NextRow()) + show_warning = FALSE + qdel(query_find_note) + + if(show_warning) + message_admins("[ckey] has just connected and has a history of [cidcount] different CIDs. (WebInfo) (Suppress Warning)") + + #undef LIMITER_SIZE #undef CURRENT_SECOND #undef SECOND_COUNT diff --git a/config/example/config.txt b/config/example/config.txt index 699e416053e..9698d7f90ab 100644 --- a/config/example/config.txt +++ b/config/example/config.txt @@ -471,3 +471,6 @@ BYOND_ACCOUNT_AGE_THRESHOLD 7 ## THE TRAILING SLASH ON THE END IS IMPORTANT SINCE IT JUST APPENDS THE CKEY TO THE END IN RAW ## Add a hash before the line below to disable the system CENTCOM_BAN_DB_URL https://centcom.melonmesa.com/ban/search/ + +## Max amount of CIDs that one ckey can have attached to them before they trip a warning. Set to 0 to disable. +MAX_CLIENT_CID_HISTORY 2 diff --git a/config/example/dbconfig.txt b/config/example/dbconfig.txt index aa41b95392b..6ed16cac5f1 100644 --- a/config/example/dbconfig.txt +++ b/config/example/dbconfig.txt @@ -9,7 +9,7 @@ ## This value must be set to the version of the paradise schema in use. ## If this value does not match, the SQL database will not be loaded and an error will be generated. ## Roundstart will be delayed. -DB_VERSION 19 +DB_VERSION 20 ## Server the MySQL database can be found at. # Examples: localhost, 200.135.5.43, www.mysqldb.com, etc. diff --git a/goon/code/datums/browserOutput.dm b/goon/code/datums/browserOutput.dm index c89d9f8496a..fcc53672a43 100644 --- a/goon/code/datums/browserOutput.dm +++ b/goon/code/datums/browserOutput.dm @@ -194,6 +194,7 @@ var/list/chatResources = list( if (found.len > 0) message_admins("[key_name(src.owner)] has a cookie from a banned account! (Matched: [found["ckey"]], [found["ip"]], [found["compid"]])") log_admin("[key_name(src.owner)] has a cookie from a banned account! (Matched: [found["ckey"]], [found["ip"]], [found["compid"]])") + new /datum/cookie_record(owner, found["ckey"], found["ip"], found["compid"]) cookieSent = 1 diff --git a/paradise.dme b/paradise.dme index 5c9729e83ec..7d4a10a0129 100644 --- a/paradise.dme +++ b/paradise.dme @@ -1199,6 +1199,7 @@ #include "code\modules\admin\banappearance.dm" #include "code\modules\admin\banjob.dm" #include "code\modules\admin\centcom_ban_db.dm" +#include "code\modules\admin\cookielog.dm" #include "code\modules\admin\create_mob.dm" #include "code\modules\admin\create_object.dm" #include "code\modules\admin\create_turf.dm" diff --git a/tools/ci/dbconfig.txt b/tools/ci/dbconfig.txt index cde89586820..d97fffaf812 100644 --- a/tools/ci/dbconfig.txt +++ b/tools/ci/dbconfig.txt @@ -2,7 +2,7 @@ # Dont use it ingame # Remember to update this when you increase the SQL version! -aa SQL_ENABLED -DB_VERSION 19 +DB_VERSION 20 ADDRESS 127.0.0.1 PORT 3306 FEEDBACK_DATABASE feedback