From 9e27ad46bcbfe70093cc03e5ba089f90ca028465 Mon Sep 17 00:00:00 2001 From: atermonera Date: Sat, 18 Mar 2023 18:20:15 -0800 Subject: [PATCH] Revert "Revert whitelist rev 3 (#9078)" This reverts commit b104a5e33a95983920426555e6bf8916652594d6. --- code/game/world.dm | 3 +- code/modules/admin/banjob.dm | 2 +- code/modules/admin/topic.dm | 8 +- .../preference_setup/general/03_body.dm | 2 +- code/modules/whitelist/admin.dm | 123 +++++++++++++++++ code/modules/whitelist/admin_ops.dm | 125 ------------------ code/modules/whitelist/legacy.dm | 65 --------- code/modules/whitelist/phony_paths.dm | 4 - code/modules/whitelist/whitelist.dm | 88 ++++++------ polaris.dme | 4 +- tools/whitelistupdate5000.py | 63 +++++++++ 11 files changed, 232 insertions(+), 255 deletions(-) create mode 100644 code/modules/whitelist/admin.dm delete mode 100644 code/modules/whitelist/admin_ops.dm delete mode 100644 code/modules/whitelist/legacy.dm delete mode 100644 code/modules/whitelist/phony_paths.dm create mode 100644 tools/whitelistupdate5000.py diff --git a/code/game/world.dm b/code/game/world.dm index 00c0f99a414..cec0ca1e633 100644 --- a/code/game/world.dm +++ b/code/game/world.dm @@ -21,9 +21,8 @@ callHook("startup") init_vchat() - //Emergency Fix load_mods() - //end-emergency fix + load_whitelist() src.update_status() diff --git a/code/modules/admin/banjob.dm b/code/modules/admin/banjob.dm index 6a010bf8bb0..f5e5fd9e873 100644 --- a/code/modules/admin/banjob.dm +++ b/code/modules/admin/banjob.dm @@ -23,7 +23,7 @@ var/global/jobban_keylist[0] //to store the keys & ranks if (guest_jobbans(rank)) if(config.guest_jobban && IsGuestKey(M.key)) return "Guest Job-ban" - if(config.usewhitelist && !M.client.is_whitelisted(rank)) // This outright doesn't work, but at least compiles. AFAIK we don't use this system at present. ~Ater + if(config.usewhitelist && !M.client.is_whitelisted(rank)) return "Whitelisted Job" return ckey_is_jobbanned(M.ckey, rank) diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm index cddf8eedb0e..68a6411b02e 100644 --- a/code/modules/admin/topic.dm +++ b/code/modules/admin/topic.dm @@ -1944,13 +1944,7 @@ var/client/C = locate(href_list["modify_whitelist"]) if(!istype(C)) return - var/entry = input(usr, "Please enter the path of the whitelist you wish to modify:", "Whitelist target", "") as text|null - if(!entry || !ispath(text2path(entry))) - return - if(href_list["set_value"] == "1") - C.add_whitelist(entry) - else if(href_list["set_value"] == "0") - C.remove_whitelist(entry) + usr.client.admin_modify_whitelist((href_list["set_value"] == "1"), ckey(C.ckey)) /mob/living/proc/can_centcom_reply() return 0 diff --git a/code/modules/client/preference_setup/general/03_body.dm b/code/modules/client/preference_setup/general/03_body.dm index 052641df84e..7e46dd84d2a 100644 --- a/code/modules/client/preference_setup/general/03_body.dm +++ b/code/modules/client/preference_setup/general/03_body.dm @@ -78,7 +78,7 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O // That last list is entirely arbitrary. Take complaints up with Kholdstare. if((istype(client) && check_rights(R_ADMIN | R_EVENT | R_FUN, 0, client)) || \ (LAZYLEN(instance.species_allowed) && species && (species in instance.species_allowed)) || \ - (config.genemod_whitelist && client.is_whitelisted(/whitelist/genemod) && LAZYLEN(instance.whitelist_allowed) && (species in instance.whitelist_allowed))) + (config.genemod_whitelist && client.is_whitelisted("Genemods") && LAZYLEN(instance.whitelist_allowed) && (species in instance.whitelist_allowed))) .[instance.name] = instance /datum/category_item/player_setup_item/general/body diff --git a/code/modules/whitelist/admin.dm b/code/modules/whitelist/admin.dm new file mode 100644 index 00000000000..3df85a8e3b9 --- /dev/null +++ b/code/modules/whitelist/admin.dm @@ -0,0 +1,123 @@ +// Rewrites the whitelists to disk +/proc/write_whitelist() + var/filename = "config/whitelists.json" + log_admin("Writing whitelists to disk at `[filename]`") + try + // Byond doesn't have a mechanism for in-place modification of a file, so we have to make a new one and then overwrite the old one. + // If this is interrupted, the .tmp file exists and can be loaded at the start of the next round. + // The in-game list represents the set of valid entries within the whitelist file, so we may as well remove invalid lines in the process. + text2file(json_encode(global.whitelists), filename + ".tmp") + if(fexists(filename) && !fdel(filename)) + error("Exception when overwriting whitelist file [filename]") + if(fcopy(filename + ".tmp", filename)) + if(!fdel(filename + ".tmp")) + error("Exception when deleting tmp whitelist file [filename].tmp") + catch(var/exception/E) + error("Exception when writing to whitelist file [filename]: [E]") + + +// Add the selected path to the player's whitelists, if it's valid. +/client/proc/add_whitelist(var/w_key) + if(istype(w_key, /datum)) + var/datum/D = w_key + w_key = D:name + if(!istext(w_key)) + return FALSE // Not set. + // If they're already whitelisted, do nothing (Also loads the whitelist) + if(is_whitelisted(w_key)) + return + + log_and_message_admins("[usr ? usr : "SYSTEM"] gave [w_key] whitelist to [src]", usr) + if(!islist(global.whitelists[ckey(ckey)])) + global.whitelists[ckey(ckey)] = list() + global.whitelists[ckey(ckey)] += w_key + write_whitelist() + +// Remove the selected path from the player's whitelists. +/client/proc/remove_whitelist(var/w_key) + if(istype(w_key, /datum)) + var/datum/D = w_key + w_key = D:name + if(!istext(w_key)) + return FALSE // Not set. + // If they're not whitelisted, do nothing (Also loads the whitelist) + if(!is_whitelisted(w_key)) + return + + log_and_message_admins("[usr ? usr : "SYSTEM"] removed [w_key] whitelist from [src]", usr) + global.whitelists[ckey] -= w_key + write_whitelist() + + +/client/proc/admin_add_whitelist() + set name = "Whitelist Add Player" + set category = "Admin" + set desc = "Give a whitelist to a target player" + admin_modify_whitelist(TRUE) + + +/client/proc/admin_del_whitelist() + set name = "Whitelist Remove Player" + set category = "Admin" + set desc = "Remove a whitelist from the target player" + admin_modify_whitelist(FALSE) + + +/client/proc/admin_modify_whitelist(var/set_value, var/key = null) + if(!check_rights(R_ADMIN|R_DEBUG)) + return + + // Get the person to whitelist. + if(!key) + key = input(src, "Please enter the CKEY of the player whose whitelist you wish to modify:", "Whitelist ckey", "") as text|null + if(!key || !length(key)) + return + + key = ckey(key) + + // Get the whitelist thing to modify. + var/entry = input(src, "Please enter the name of the whitelist you wish to modify:", "Whitelist target", "") as null|anything in global.whitelistable + if(!entry) + return + + if(set_value) + if(!islist(global.whitelists[key])) + global.whitelists[key] = list() + else + to_world("is a list: [global.whitelists[ckey(ckey)]]") + if(entry in global.whitelists[key]) + to_chat(src, SPAN_NOTICE("[key] is already whitelisted for [entry]!")) + return + global.whitelists[key] += entry + else + if(!islist(global.whitelists[key])) + to_chat(src, SPAN_NOTICE("[key] isn't whitelisted for anything!")) + return + global.whitelists[key] -= entry + + log_and_message_admins("[src] [set_value ? "gave [entry] whitelist to" : "removed [entry] whitelist from"] [key]", src) + + write_whitelist() + + +/client/vv_get_dropdown() + . = ..() + VV_DROPDOWN_OPTION(VV_HK_ADD_WHITELIST, "Add whitelist") + VV_DROPDOWN_OPTION(VV_HK_DEL_WHITELIST, "Remove whitelist") + + +/client/vv_do_topic(list/href_list) + . = ..() + IF_VV_OPTION(VV_HK_ADD_WHITELIST) + if(!check_rights(R_ADMIN|R_DEBUG)) + return + var/client/C = locate(href_list["target"]) + if(istype(C)) + usr.client.admin_modify_whitelist(TRUE, ckey(C.ckey)) + + IF_VV_OPTION(VV_HK_DEL_WHITELIST) + if(!check_rights(R_ADMIN|R_DEBUG)) + return + var/client/C = locate(href_list["target"]) + if(istype(C)) + usr.client.admin_modify_whitelist(FALSE, ckey(C.ckey)) diff --git a/code/modules/whitelist/admin_ops.dm b/code/modules/whitelist/admin_ops.dm deleted file mode 100644 index a2c2e16e351..00000000000 --- a/code/modules/whitelist/admin_ops.dm +++ /dev/null @@ -1,125 +0,0 @@ -// Rewrites the client's whitelists to disk -/proc/write_whitelist(var/key, var/list/whitelist) - var/filename = "data/player_saves/[copytext(ckey(key),1,2)]/[ckey(key)]/whitelist.json" - log_admin("Writing whitelists to disk for [key] at `[filename]`") - try - // Byond doesn't have a mechanism for in-place modification of a file, so we have to make a new one and then overwrite the old one. - // If this is interrupted, the .tmp file exists and can be loaded at the start of the next round. - // The in-game list represents the set of valid entries within the whitelist file, so we may as well remove invalid lines in the process. - text2file(json_encode(whitelist), filename + ".tmp") - if(fexists(filename) && !fdel(filename)) - error("Exception when overwriting whitelist file [filename]") - if(fcopy(filename + ".tmp", filename)) - if(!fdel(filename + ".tmp")) - error("Exception when deleting tmp whitelist file [filename].tmp") - catch(var/exception/E) - error("Exception when writing to whitelist file [filename]: [E]") - - -// Add the selected path to the player's whitelists, if it's valid. -/client/proc/add_whitelist(var/path) - if(istext(path)) - path = text2path(path) - if(!ispath(path)) - return - // If they're already whitelisted, do nothing (Also loads the whitelist) - if(is_whitelisted(path)) - return - - log_and_message_admins("[usr ? usr : "SYSTEM"] giving [path] whitelist to [src]", usr) - src.whitelists[path] = TRUE - write_whitelist(src.ckey, src.whitelists) - -// Remove the selected path from the player's whitelists. -/client/proc/remove_whitelist(var/path) - if(istext(path)) - path = text2path(path) - if(!ispath(path)) - return - // If they're not whitelisted, do nothing (Also loads the whitelist) - if(!is_whitelisted(path)) - return - - log_and_message_admins("[usr ? usr : "SYSTEM"] removing [path] whitelist from [src]", usr) - src.whitelists -= path - write_whitelist(src.ckey, src.whitelists) - - -/client/proc/admin_add_whitelist() - set name = "Whitelist Add Player" - set category = "Admin" - set desc = "Give a whitelist to a target player" - admin_modify_whitelist(TRUE) - - -/client/proc/admin_del_whitelist() - set name = "Whitelist Remove Player" - set category = "Admin" - set desc = "Remove a whitelist from the target player" - admin_modify_whitelist(FALSE) - - -/client/proc/admin_modify_whitelist(var/set_value) - if(!check_rights(R_ADMIN|R_DEBUG)) - return - - // Get the person to whitelist. - var/key = input(src, "Please enter the CKEY of the player whose whitelist you wish to modify:", "Whitelist ckey", "") as text|null - if(!key || !length(key)) - return - - key = ckey(key) - if(!fexists("data/player_saves/[copytext(key,1,2)]/[key]/preferences.sav")) - to_chat(src, "That player doesn't seem to exist...") - return - - // Get the whitelist thing to modify. - var/entry = input(src, "Please enter the path of the whitelist you wish to modify:", "Whitelist target", "") as text|null - if(!entry || !ispath(text2path(entry))) - return - - // If they're logged in, modify it directly. - var/client/C = ckey2client(key) - if(istype(C)) - set_value ? C.add_whitelist(entry) : C.remove_whitelist(entry) - return - - log_and_message_admins("[src] [set_value ? "giving [entry] whitelist to" : "removing [entry] whitelist from"] [key]", src) - - // Else, we have to find and modify the whitelist file ourselves. - var/list/whitelists = load_whitelist(key) - - // They're already whitelisted. - if(whitelists[entry] == set_value) - return - - whitelists[entry] = set_value - write_whitelist(key, whitelists) - - -/client/vv_get_dropdown() - . = ..() - VV_DROPDOWN_OPTION(VV_HK_ADD_WHITELIST, "Add whitelist") - VV_DROPDOWN_OPTION(VV_HK_DEL_WHITELIST, "Remove whitelist") - - -/client/vv_do_topic(list/href_list) - . = ..() - IF_VV_OPTION(VV_HK_ADD_WHITELIST) - if(!check_rights(R_ADMIN|R_DEBUG)) - return - var/entry = input(usr, "Please enter the path of the whitelist you wish to add:", "Whitelist target", "") as text|null - if(!entry || !ispath(text2path(entry))) - return - var/client/C = locate(href_list["target"]) - if(istype(C)) - C.add_whitelist(entry) - IF_VV_OPTION(VV_HK_DEL_WHITELIST) - if(!check_rights(R_ADMIN|R_DEBUG)) - return - var/entry = input(usr, "Please enter the path of the whitelist you wish to remove:", "Whitelist target", "") as text|null - if(!entry || !ispath(text2path(entry))) - return - var/client/C = locate(href_list["target"]) - if(istype(C)) - C.remove_whitelist(entry) diff --git a/code/modules/whitelist/legacy.dm b/code/modules/whitelist/legacy.dm deleted file mode 100644 index cf5fb7f3378..00000000000 --- a/code/modules/whitelist/legacy.dm +++ /dev/null @@ -1,65 +0,0 @@ -// Proc to convert the old whitelist systems into the new, shiny, modern system. -// This has to do a lot of file I/O because it handles _everyone's_ whitelists, so it's expected to be pretty expensive. -// Hence, this has to be manually called by an admin. -/proc/load_legacy_whitelist() - var/static/list/alienwhitelist_dict = list( - "Alai" = /datum/language/tajsign, - "Common Skrellian" = /datum/language/skrell, - "Diona" = /datum/species/diona, - "Promethean" = /datum/species/shapeshifter/promethean, - "Schechi" = /datum/language/teshari, - "Siik" = /datum/language/tajaran, - "Sinta'Unathi" = /datum/language/unathi, - "Skrell" = /datum/species/skrell, - "Sol Common" = /datum/language/human, - "Tajara" = /datum/species/tajaran, - "Teshari" = /datum/species/teshari, - "Unathi" = /datum/species/unathi, - "Zaddat" = /datum/species/zaddat, - ) - - var/list/whitelists_to_write = list() - - // Load in the alien whitelists - for(var/line in read_lines("config/alienwhitelist.txt")) - if(!length(line)) - continue - var/static/regex/R = regex(" - ") - var/list/tok = splittext(line, R) - // Whitelist is no longer valid. - if(length(tok) < 2 || !(tok[2] in alienwhitelist_dict)) - continue - - var/key = ckey(tok[1]) - // If they don't have a preferences save file, then they probably don't play here any more. - if(!fexists("data/player_saves/[copytext(key,1,2)]/[key]/preferences.sav")) - continue - - LAZYADDASSOC(whitelists_to_write[key], alienwhitelist_dict[tok[2]], TRUE) - - // Load in the genemod whitelist - for(var/line in read_commentable("config/genemodwhitelist.txt")) - var/key = ckey(line) - // If they don't have a preferences save file, then they probably don't play here any more. - if(!fexists("data/player_saves/[copytext(key,1,2)]/[key]/preferences.sav")) - continue - - LAZYADDASSOC(whitelists_to_write[key], /whitelist/genemod, TRUE) - - // Write the whitelists to files. Second stage, so we don't make a million individual writes. - for(var/key in whitelists_to_write) - var/filename = "data/player_saves/[copytext(key,1,2)]/[key]/whitelist.json" - var/list/whitelist = whitelists_to_write[key] - try - // If the file already exists, don't just blindly overwrite it. - if(fexists(filename)) - var/prior_whitelist = file2text(filename) || "" - if(length(prior_whitelist)) - whitelist |= json_decode(prior_whitelist) - text2file(json_encode(whitelist), filename + ".tmp") - if(fexists(filename) && !fdel(filename)) - error("Error overwriting whitelist file [filename]") - if(!fcopy(filename + ".tmp", filename) || !fdel(filename + ".tmp")) - error("Exception when deleting tmp whitelist file [filename].tmp") - catch(var/exception/E) - error("Exception when writing to whitelist file [filename]: [E]") diff --git a/code/modules/whitelist/phony_paths.dm b/code/modules/whitelist/phony_paths.dm deleted file mode 100644 index 16bdcf97213..00000000000 --- a/code/modules/whitelist/phony_paths.dm +++ /dev/null @@ -1,4 +0,0 @@ -// This file is reserved for creating paths that can be used to whitelist -// things that aren't directly attributable to specific paths. -/whitelist/genemod // This whitelists a collection of sprite_accessories - var/name = "Genemods" diff --git a/code/modules/whitelist/whitelist.dm b/code/modules/whitelist/whitelist.dm index 2bc269acf7e..d93a3b08adc 100644 --- a/code/modules/whitelist/whitelist.dm +++ b/code/modules/whitelist/whitelist.dm @@ -1,4 +1,24 @@ -/client/var/list/whitelists = null +var/list/whitelists = list() +var/list/whitelistable = list( + SPECIES_DIONA, + SPECIES_PROMETHEAN, + SPECIES_SKRELL, + SPECIES_TAJ, + SPECIES_TESHARI, + SPECIES_UNATHI, + SPECIES_VOX, + SPECIES_ZADDAT, + LANGUAGE_AKHANI, + LANGUAGE_ALAI, + LANGUAGE_SCHECHI, + LANGUAGE_SIIK, + LANGUAGE_SKRELLIAN, + LANGUAGE_SKRELLIANFAR, + LANGUAGE_SOL_COMMON, + LANGUAGE_UNATHI, + LANGUAGE_ZADDAT, + "Genemods", +) // Prints the client's whitelist entries @@ -10,58 +30,32 @@ to_chat(src, "You are whitelisted for:") to_chat(src, jointext(get_whitelists_list(), "\n")) + /client/proc/get_whitelists_list() - . = list() - if(src.whitelists == null) - src.whitelists = load_whitelist(src.ckey) - for(var/key in src.whitelists) - try - . += initial(initial(key:name)) - catch() - . += key - - -/proc/load_whitelist(var/key) - var/filename = "data/player_saves/[copytext(ckey(key),1,2)]/[ckey(key)]/whitelist.json" + return (ckey in global.whitelists) ? global.whitelists[ckey] : list() + + +/proc/load_whitelist() + var/filename = "config/whitelists.json" try - // Check the player-specific whitelist file, if it exists. if(fexists(filename)) - // Load the whitelist entries from file, or empty string if empty.` - . = list() - for(var/T in json_decode(file2text(filename) || "")) - T = text2path(T) - if(!ispath(T)) - continue - .[T] = TRUE - - // Something was removing an entry from the whitelist and interrupted mid-overwrite. - else if(fexists(filename + ".tmp") && fcopy(filename + ".tmp", filename)) - . = load_whitelist(key) - if(!fdel(filename + ".tmp")) - error("Exception when deleting tmp whitelist file [filename].tmp") - - // Whitelist file doesn't exist, so they aren't whitelisted for anything. Create the file. - else if(fexists("data/player_saves/[copytext(ckey(key),1,2)]/[ckey(key)]/preferences.sav")) - text2file("", filename) - . = list() + global.whitelists = json_decode(file2text(filename) || "") catch(var/exception/E) error("Exception when loading whitelist file [filename]: [E]") // Returns true if the specified path is in the player's whitelists, false otw. -/client/proc/is_whitelisted(var/path) - if(istext(path)) - path = text2path(path) - if(!ispath(path)) - return - // If it hasn't already been loaded, load it. - if(src.whitelists == null) - src.whitelists = load_whitelist(src.ckey) - return src.whitelists[path] - - -/proc/is_alien_whitelisted(mob/M, var/datum/species/species) +/client/proc/is_whitelisted(var/w_key) + if(istype(w_key, /datum)) + var/datum/D = w_key + w_key = D:name + if(!istext(w_key)) + return FALSE // Not set. + return key in global.whitelists[ckey] + + +/proc/is_alien_whitelisted(mob/M, datum/species/species) //They are admin or the whitelist isn't in use if(whitelist_overrides(M)) return TRUE @@ -75,10 +69,10 @@ return TRUE var/client/C = (!isclient(M)) ? M.client : M - return C.is_whitelisted(species.type) + return C.is_whitelisted(species.name) -/proc/is_lang_whitelisted(mob/M, var/datum/language/language) +/proc/is_lang_whitelisted(mob/M, datum/language/language) //They are admin or the whitelist isn't in use if(whitelist_overrides(M)) return TRUE @@ -93,7 +87,7 @@ if(!(language.flags & WHITELISTED)) return TRUE - return C.is_whitelisted(language.type) + return C.is_whitelisted(language) /proc/whitelist_overrides(mob/M) diff --git a/polaris.dme b/polaris.dme index 69b9e621505..e28ab20e77b 100644 --- a/polaris.dme +++ b/polaris.dme @@ -3226,9 +3226,7 @@ #include "code\modules\webhooks\webhook_roundend.dm" #include "code\modules\webhooks\webhook_roundprep.dm" #include "code\modules\webhooks\webhook_roundstart.dm" -#include "code\modules\whitelist\admin_ops.dm" -#include "code\modules\whitelist\legacy.dm" -#include "code\modules\whitelist\phony_paths.dm" +#include "code\modules\whitelist\admin.dm" #include "code\modules\whitelist\whitelist.dm" #include "code\modules\xenoarcheaology\anomaly_container.dm" #include "code\modules\xenoarcheaology\boulder.dm" diff --git a/tools/whitelistupdate5000.py b/tools/whitelistupdate5000.py new file mode 100644 index 00000000000..0c71148a35b --- /dev/null +++ b/tools/whitelistupdate5000.py @@ -0,0 +1,63 @@ +import os +import json + +def scan_whitelist(): + whitelist_dict = {} + path = "../data/player_saves" + for subdir in os.listdir(path): + path = f"../data/player_saves/{subdir}" + if not os.path.isdir(path): + continue + for player_dir in os.listdir(path): + whitelist_file = f"{path}/{player_dir}/whitelist.json" + print(f"Opening {whitelist_file}") + if not os.path.exists(whitelist_file): + continue + with open(whitelist_file) as contents: + if os.path.getsize(whitelist_file) == 1: + continue + whitelist_dict[player_dir] = [] + for key in json.load(contents): + whitelist_dict[player_dir].append(translate_key(key)) + return whitelist_dict + +def translate_key(key): + if key == "/datum/language/tajsign": + return "Alai" + if key == "/datum/language/skrell": + return "Common Skrellian" + if key == "/datum/language/skrellfar": + return "High Skrellian" + if key == "/datum/species/diona": + return "Diona" + if key == "/datum/species/shapeshifter/promethean": + return "Promethean" + if key == "/datum/language/teshari": + return "Schechi" + if key == "/datum/language/tajaran": + return "Siik" + if key == "/datum/language/unathi": + return "Sinta'Unathi" + if key == "/datum/species/skrell": + return "Skrell" + if key == "/datum/language/human": + return "Sol Common" + if key == "/datum/species/tajaran": + return "Tajara" + if key == "/datum/species/teshari": + return "Teshari" + if key == "/datum/species/unathi": + return "Unathi" + if key == "/datum/species/zaddat": + return "Zaddat" + if key == "/whitelist/genemod": + return "Genemods" + if key == "/datum/species/vox": + return "Vox" + if key == "/datum/language/zaddat": + return "Vedahq" + +new_dict = scan_whitelist() +print(new_dict) +with open("../config/whitelists.json", "w") as whitelist: + whitelist.write(json.dumps(new_dict, indent=4))