From 55247e9bdf2ce443f4ce692c8e8cec863fb1be5e Mon Sep 17 00:00:00 2001 From: Kyle Spier-Swenson Date: Wed, 13 Dec 2017 19:03:37 -0800 Subject: [PATCH] Deadmin tweaks: Admins without +AUTOLOGIN start deadmined. AUTOLOGIN defaults to on. --- code/__DEFINES/admin.dm | 29 +++--- code/controllers/subsystem/vote.dm | 2 +- code/modules/admin/IsBanned.dm | 2 +- code/modules/admin/admin_ranks.dm | 74 ++++++++------- code/modules/admin/admin_verbs.dm | 24 ++--- code/modules/admin/holder2.dm | 91 ++++++++++++++----- .../admin/permissionverbs/permissionedit.dm | 22 +++-- code/modules/client/client_procs.dm | 19 ++-- code/modules/mob/login.dm | 3 - config/admin_ranks.txt | 10 +- config/admins.txt | 2 +- 11 files changed, 178 insertions(+), 100 deletions(-) diff --git a/code/__DEFINES/admin.dm b/code/__DEFINES/admin.dm index 833aaa62cb..65d028ea34 100644 --- a/code/__DEFINES/admin.dm +++ b/code/__DEFINES/admin.dm @@ -94,19 +94,22 @@ #define BANTYPE_ANY_JOB 9 //used to remove jobbans //Admin Permissions -#define R_BUILDMODE 1 -#define R_ADMIN 2 -#define R_BAN 4 -#define R_FUN 8 -#define R_SERVER 16 -#define R_DEBUG 32 -#define R_POSSESS 64 -#define R_PERMISSIONS 128 -#define R_STEALTH 256 -#define R_POLL 512 -#define R_VAREDIT 1024 -#define R_SOUNDS 2048 -#define R_SPAWN 4096 +#define R_BUILDMODE 0x1 +#define R_ADMIN 0x2 +#define R_BAN 0x4 +#define R_FUN 0x8 +#define R_SERVER 0x10 +#define R_DEBUG 0x20 +#define R_POSSESS 0x40 +#define R_PERMISSIONS 0x80 +#define R_STEALTH 0x100 +#define R_POLL 0x200 +#define R_VAREDIT 0x400 +#define R_SOUNDS 0x800 +#define R_SPAWN 0x1000 +#define R_AUTOLOGIN 0x2000 + +#define R_DEFAULT R_AUTOLOGIN #if DM_VERSION > 512 #error Remove the flag below , its been long enough diff --git a/code/controllers/subsystem/vote.dm b/code/controllers/subsystem/vote.dm index 55624a866c..37811c183f 100644 --- a/code/controllers/subsystem/vote.dm +++ b/code/controllers/subsystem/vote.dm @@ -165,7 +165,7 @@ SUBSYSTEM_DEF(vote) var/admin = FALSE var/ckey = ckey(initiator_key) - if((GLOB.admin_datums[ckey]) || (ckey in GLOB.deadmins)) + if(GLOB.admin_datums[ckey]) admin = TRUE if(next_allowed_time > world.time && !admin) diff --git a/code/modules/admin/IsBanned.dm b/code/modules/admin/IsBanned.dm index f43803631b..73fc0d43f3 100644 --- a/code/modules/admin/IsBanned.dm +++ b/code/modules/admin/IsBanned.dm @@ -18,7 +18,7 @@ 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/ckey = ckey(key) - if((ckey in GLOB.admin_datums) || (ckey in GLOB.deadmins)) + if(GLOB.admin_datums[ckey] || GLOB.deadmins[ckey]) admin = 1 //Whitelist diff --git a/code/modules/admin/admin_ranks.dm b/code/modules/admin/admin_ranks.dm index be9e423a17..201fe75979 100644 --- a/code/modules/admin/admin_ranks.dm +++ b/code/modules/admin/admin_ranks.dm @@ -3,7 +3,7 @@ GLOBAL_PROTECT(admin_ranks) /datum/admin_rank var/name = "NoRank" - var/rights = 0 + var/rights = R_DEFAULT var/list/adds var/list/subs @@ -56,11 +56,13 @@ GLOBAL_PROTECT(admin_ranks) if("varedit") flag = R_VAREDIT if("everything","host","all") - flag = 65535 + flag = ALL if("sound","sounds") flag = R_SOUNDS if("spawn","create") flag = R_SPAWN + if("autologin", "autoadmin") + flag = R_AUTOLOGIN if("@","prev") flag = previous_rights if("rejuv","rejuvinate") @@ -171,21 +173,19 @@ GLOBAL_PROTECT(admin_ranks) #endif -/proc/load_admins(target = null) - if(IsAdminAdvancedProcCall()) - to_chat(usr, "Admin Reload blocked: Advanced ProcCall detected.") - return +/proc/load_admins() //clear the datums references - if(!target) - GLOB.admin_datums.Cut() - for(var/client/C in GLOB.admins) - C.remove_admin_verbs() - C.holder = null - GLOB.admins.Cut() - load_admin_ranks() - //Clear profile access - for(var/A in world.GetConfig("admin")) - world.SetConfig("APP/admin", A, null) + + GLOB.admin_datums.Cut() + for(var/client/C in GLOB.admins) + C.remove_admin_verbs() + C.holder = null + GLOB.admins.Cut() + GLOB.deadmins.Cut() + load_admin_ranks() + //Clear profile access + for(var/A in world.GetConfig("admin")) + world.SetConfig("APP/admin", A, null) var/list/rank_names = list() for(var/datum/admin_rank/R in GLOB.admin_ranks) @@ -208,13 +208,11 @@ GLOBAL_PROTECT(admin_ranks) var/ckey = ckey(entry[1]) var/rank = ckeyEx(entry[2]) - if(!ckey || !rank || (target && ckey != target)) + if(!ckey || !rank) continue - var/datum/admins/D = new(rank_names[rank], ckey) //create the admin datum and store it for later use - if(!D) - continue //will occur if an invalid rank is provided - D.associate(GLOB.directory[ckey]) //find the client for a ckey if they are connected and associate them with the new admin datum + new /datum/admins(rank_names[rank], ckey) + else if(!SSdbcore.Connect()) log_world("Failed to connect to database in load_admins(). Reverting to legacy system.") @@ -229,19 +227,12 @@ GLOBAL_PROTECT(admin_ranks) while(query_load_admins.NextRow()) var/ckey = ckey(query_load_admins.item[1]) var/rank = ckeyEx(query_load_admins.item[2]) - if(target && ckey != target) - continue if(rank_names[rank] == null) WARNING("Admin rank ([rank]) does not exist.") continue - var/datum/admins/D = new(rank_names[rank], ckey) //create the admin datum and store it for later use - if(!D) - continue //will occur if an invalid rank is provided - if(D.rank.rights & R_DEBUG) //grant profile access - world.SetConfig("APP/admin", ckey, "role=admin") - D.associate(GLOB.directory[ckey]) //find the client for a ckey if they are connected and associate them with the new admin datum + new /datum/admins(rank_names[rank], ckey) #ifdef TESTING var/msg = "Admins Built:\n" @@ -298,6 +289,8 @@ GLOBAL_PROTECT(admin_ranks) return var/datum/admins/D = GLOB.admin_datums[adm_ckey] + if (!D) + D = GLOB.deadmins[adm_ckey] switch(task) if("remove") @@ -309,6 +302,7 @@ GLOBAL_PROTECT(admin_ranks) log_admin("[key_name(usr)] attempted to remove [adm_ckey] from the admins list without sufficient rights.") return GLOB.admin_datums -= adm_ckey + GLOB.deadmins -= adm_ckey D.disassociate() updateranktodb(adm_ckey, "player") @@ -350,11 +344,9 @@ GLOBAL_PROTECT(admin_ranks) if(D) //they were previously an admin D.disassociate() //existing admin needs to be disassociated D.rank = R //set the admin_rank as our rank + D.associate() else - D = new(R,adm_ckey) //new admin - - var/client/C = GLOB.directory[adm_ckey] //find the client with the specified ckey (if they are logged in) - D.associate(C) //link up with the client and add verbs + D = new(R, adm_ckey, TRUE) //new admin updateranktodb(adm_ckey, new_rank) message_admins("[key_name_admin(usr)] edited the admin rank of [adm_ckey] to [new_rank]") @@ -387,6 +379,22 @@ GLOBAL_PROTECT(admin_ranks) message_admins("[key_name(usr)] added keyword [keyword] to permission of [adm_ckey]") log_admin("[key_name(usr)] added keyword [keyword] to permission of [adm_ckey]") log_admin_permission_modification(adm_ckey, D.rank.rights) + if("activate") //forcefully readmin + if(!D || !D.deadmined) + return + + D.activate() + + message_admins("[key_name_admin(usr)] forcefully readmined [adm_ckey]") + log_admin("[key_name(usr)] forcefully readmined [adm_ckey]") + if("deactivate") //forcefully deadmin + if(!D || D.deadmined) + return + + message_admins("[key_name_admin(usr)] forcefully deadmined [adm_ckey]") + log_admin("[key_name(usr)] forcefully deadmined [adm_ckey]") + + D.deactivate() //after logs so the deadmined admin can see the message. edit_admin_permissions() diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index c0bc15eacc..8b8da5baa4 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -638,12 +638,7 @@ GLOBAL_LIST_INIT(admin_verbs_hideable, list( if(has_antag_hud()) toggle_antag_hud() - holder.disassociate() - qdel(holder) - - GLOB.deadmins += ckey - GLOB.admin_datums -= ckey - verbs += /client/proc/readmin + holder.deactivate() to_chat(src, "You are now a normal player.") log_admin("[src] deadmined themself.") @@ -655,13 +650,20 @@ GLOBAL_LIST_INIT(admin_verbs_hideable, list( set category = "Admin" set desc = "Regain your admin powers." - load_admins(ckey) + var/datum/admins/A = GLOB.deadmins[ckey] - if(!holder) // Something went wrong... - return + if(!A) + A = GLOB.admin_datums[ckey] + if (!A) + var/msg = " is trying to readmin but they have no deadmin entry" + message_admins("[key_name_admin(src)][msg]") + log_admin_private("[key_name(src)][msg]") + return - GLOB.deadmins -= ckey - verbs -= /client/proc/readmin + A.associate(src) + + if (!holder) + return //This can happen if an admin attempts to vv themself into somebody elses's deadmin datum by getting ref via brute force to_chat(src, "You are now an admin.") message_admins("[src] re-adminned themselves.") diff --git a/code/modules/admin/holder2.dm b/code/modules/admin/holder2.dm index cdc53ae338..4ba5dc37f3 100644 --- a/code/modules/admin/holder2.dm +++ b/code/modules/admin/holder2.dm @@ -7,6 +7,8 @@ GLOBAL_PROTECT(href_token) /datum/admins var/datum/admin_rank/rank + var/target + var/name = "nobody's admin datum (no rank)" //Makes for better runtimes var/client/owner = null var/fakekey = null @@ -19,9 +21,12 @@ GLOBAL_PROTECT(href_token) var/datum/newscaster/wanted_message/admincaster_wanted_message = new /datum/newscaster/wanted_message var/datum/newscaster/feed_channel/admincaster_feed_channel = new /datum/newscaster/feed_channel var/admin_signature + var/href_token -/datum/admins/New(datum/admin_rank/R, ckey) + var/deadmined + +/datum/admins/New(datum/admin_rank/R, ckey, force_active = FALSE) if(!ckey) QDEL_IN(src, 0) throw EXCEPTION("Admin datum created without a ckey") @@ -30,34 +35,36 @@ GLOBAL_PROTECT(href_token) QDEL_IN(src, 0) throw EXCEPTION("Admin datum created without a rank") return + target = ckey + name = "[ckey]'s admin datum ([R])" rank = R admin_signature = "Nanotrasen Officer #[rand(0,9)][rand(0,9)][rand(0,9)]" href_token = GenerateToken() - GLOB.admin_datums[ckey] = src if(R.rights & R_DEBUG) //grant profile access world.SetConfig("APP/admin", ckey, "role=admin") + //only admins with +ADMIN start admined + if (force_active || (R.rights & R_AUTOLOGIN)) + activate() + else + deactivate() -/proc/GenerateToken() - . = "" - for(var/I in 1 to 32) - . += "[rand(10)]" -/proc/RawHrefToken(forceGlobal = FALSE) - var/tok = GLOB.href_token - if(!forceGlobal && usr) - var/client/C = usr.client - if(!C) - CRASH("No client for HrefToken()!") - var/datum/admins/holder = C.holder - if(holder) - tok = holder.href_token - return tok +/datum/admins/proc/activate() + GLOB.deadmins -= target + GLOB.admin_datums[target] = src + deadmined = FALSE + if (GLOB.directory[target]) + associate(GLOB.directory[target]) //find the client for a ckey if they are connected and associate them with us -/proc/HrefToken(forceGlobal = FALSE) - return "admin_token=[RawHrefToken(forceGlobal)]" -/proc/HrefTokenFormField(forceGlobal = FALSE) - return "" +/datum/admins/proc/deactivate() + GLOB.deadmins[target] = src + GLOB.admin_datums -= target + deadmined = TRUE + var/client/C + if ((C = owner) || (C = GLOB.directory[target])) + disassociate() + C.verbs += /client/proc/readmin /datum/admins/proc/associate(client/C) if(IsAdminAdvancedProcCall()) @@ -65,10 +72,18 @@ GLOBAL_PROTECT(href_token) message_admins("[key_name_admin(usr)][msg]") log_admin_private("[key_name(usr)][msg]") return + if(istype(C)) + if(C.ckey != target) + var/msg = " has attempted to associate with [target]'s admin datum" + message_admins("[key_name_admin(C)][msg]") + log_admin_private("[key_name(C)][msg]") + return + if (deadmined) + activate() owner = C owner.holder = src - owner.add_admin_verbs() //TODO + owner.add_admin_verbs() //TODO <--- todo what? the proc clearly exists and works since its the backbone to our entire admin system owner.verbs -= /client/proc/readmin GLOB.admins |= C @@ -79,6 +94,12 @@ GLOBAL_PROTECT(href_token) owner.holder = null owner = null +/datum/admins/proc/check_for_rights(rights_required) + if(rights_required && !(rights_required & rank.rights)) + return 0 + return 1 + + /datum/admins/proc/check_if_greater_rights_than_holder(datum/admins/other) if(!other) return 1 //they have no rights @@ -128,8 +149,36 @@ you will have to do something like if(client.rights & R_ADMIN) yourself. //This proc checks whether subject has at least ONE of the rights specified in rights_required. /proc/check_rights_for(client/subject, rights_required) +<<<<<<< HEAD if(subject && subject.holder && subject.holder.rank) if(rights_required && !(rights_required & subject.holder.rank.rights)) return 0 return 1 return 0 +======= + if(subject && subject.holder) + return subject.holder.check_for_rights(rights_required) + return 0 + +/proc/GenerateToken() + . = "" + for(var/I in 1 to 32) + . += "[rand(10)]" + +/proc/RawHrefToken(forceGlobal = FALSE) + var/tok = GLOB.href_token + if(!forceGlobal && usr) + var/client/C = usr.client + if(!C) + CRASH("No client for HrefToken()!") + var/datum/admins/holder = C.holder + if(holder) + tok = holder.href_token + return tok + +/proc/HrefToken(forceGlobal = FALSE) + return "admin_token=[RawHrefToken(forceGlobal)]" + +/proc/HrefTokenFormField(forceGlobal = FALSE) + return "" +>>>>>>> 4e929c7... Deadmin tweaks: Admins without +AUTOLOGIN start deadmined. AUTOLOGIN defaults to on. (#33480) diff --git a/code/modules/admin/permissionverbs/permissionedit.dm b/code/modules/admin/permissionverbs/permissionedit.dm index 26d2c87b48..a0035afa9d 100644 --- a/code/modules/admin/permissionverbs/permissionedit.dm +++ b/code/modules/admin/permissionverbs/permissionedit.dm @@ -10,7 +10,7 @@ if(!check_rights(R_PERMISSIONS)) return - var/output = {" + var/list/output = list({" Permissions Panel @@ -25,18 +25,26 @@ PERMISSIONS VERB-OVERRIDES -"} +"}) - for(var/adm_ckey in GLOB.admin_datums) + for(var/adm_ckey in GLOB.admin_datums+GLOB.deadmins) var/datum/admins/D = GLOB.admin_datums[adm_ckey] if(!D) - continue + D = GLOB.deadmins[adm_ckey] + if (!D) + continue var/rights = rights2text(D.rank.rights," ") - if(!rights) rights = "*none*" + if(!rights) + rights = "*none*" + var/deadminlink = "" + if (D.deadmined) + deadminlink = " \[RA\]" + else + deadminlink = " \[DA\]" output += "" - output += "[adm_ckey] \[-\]" + output += "[adm_ckey] [deadminlink]\[-\]" output += "[D.rank.name]" output += "[rights]" output += "[rights2text(0," ",D.rank.adds,D.rank.subs)]" @@ -48,7 +56,7 @@ "} - usr << browse(output,"window=editrights;size=900x650") + usr << browse(jointext(output, ""),"window=editrights;size=900x650") /datum/admins/proc/log_admin_rank_modification(adm_ckey, new_rank) if(CONFIG_GET(flag/admin_legacy_system)) diff --git a/code/modules/client/client_procs.dm b/code/modules/client/client_procs.dm index 43ae694b84..cb1712dff5 100644 --- a/code/modules/client/client_procs.dm +++ b/code/modules/client/client_procs.dm @@ -160,7 +160,7 @@ GLOBAL_LIST(external_rsc_urls) GLOB.directory[ckey] = src GLOB.ahelp_tickets.ClientLogin(src) - + var/connecting_admin = FALSE //because de-admined admins connecting should be treated like admins. //Admin Authorisation var/localhost_addresses = list("127.0.0.1", "::1") if(address && (address in localhost_addresses)) @@ -184,6 +184,11 @@ GLOBAL_LIST(external_rsc_urls) if(holder) GLOB.admins |= src holder.owner = src + connecting_admin = TRUE + + else if(GLOB.deadmins[ckey]) + verbs += /client/proc/readmin + connecting_admin = TRUE //preferences datum - also holds some persistent data for the client (because we may as well keep these datums to a minimum) prefs = GLOB.preferences_datums[ckey] @@ -227,8 +232,8 @@ GLOBAL_LIST(external_rsc_urls) chatOutput.start() // Starts the chat if(alert_mob_dupe_login) - set waitfor = FALSE - alert(mob, "You have logged in already with another key this round, please log out of this one NOW or risk being banned!") + spawn() + alert(mob, "You have logged in already with another key this round, please log out of this one NOW or risk being banned!") connection_time = world.time connection_realtime = world.realtime @@ -242,7 +247,7 @@ GLOBAL_LIST(external_rsc_urls) to_chat(src, "Your version: [byond_version]") to_chat(src, "Required version: [cev] or later") to_chat(src, "Visit http://www.byond.com/download/ to get the latest version of byond.") - if (holder) + if (connecting_admin) to_chat(src, "Because you are an admin, you are being allowed to walk past this limitation, But it is still STRONGLY suggested you upgrade") else qdel(src) @@ -262,7 +267,7 @@ GLOBAL_LIST(external_rsc_urls) to_chat(src, "Required version to remove this message: [cwv] or later") to_chat(src, "Visit http://www.byond.com/download/ to get the latest version of byond.") - if (connection == "web" && !holder) + if (connection == "web" && !connecting_admin) if (!CONFIG_GET(flag/allow_webclient)) to_chat(src, "Web client is disabled") qdel(src) @@ -427,7 +432,7 @@ GLOBAL_LIST(external_rsc_urls) if (src.holder && src.holder.rank) admin_rank = src.holder.rank.name else - if (check_randomizer(connectiontopic)) + if (!GLOB.deadmins[ckey] && check_randomizer(connectiontopic)) return var/sql_ip = sanitizeSQL(address) var/sql_computerid = sanitizeSQL(computer_id) @@ -437,7 +442,7 @@ GLOBAL_LIST(external_rsc_urls) if(!query_client_in_db.Execute()) return if(!query_client_in_db.NextRow()) - if (CONFIG_GET(flag/panic_bunker) && !holder && !(ckey in GLOB.deadmins)) + if (CONFIG_GET(flag/panic_bunker) && !holder && !GLOB.deadmins[ckey]) log_access("Failed Login: [key] - New account attempting to connect during panic bunker") message_admins("Failed Login: [key] - New account attempting to connect during panic bunker") to_chat(src, "Sorry but the server is currently not accepting connections from never before seen players.") diff --git a/code/modules/mob/login.dm b/code/modules/mob/login.dm index e7608f524b..9ffbff5619 100644 --- a/code/modules/mob/login.dm +++ b/code/modules/mob/login.dm @@ -26,9 +26,6 @@ reload_fullscreen() // Reload any fullscreen overlays this mob has. - if(ckey in GLOB.deadmins) - verbs += /client/proc/readmin - add_click_catcher() sync_mind() diff --git a/config/admin_ranks.txt b/config/admin_ranks.txt index 96737c5484..77d52eb871 100644 --- a/config/admin_ranks.txt +++ b/config/admin_ranks.txt @@ -27,17 +27,23 @@ # +RIGHTS (or +PERMISSIONS) = allows you to promote and/or demote people. # +SOUND (or +SOUNDS) = allows you to upload and play sounds # +SPAWN (or +CREATE) = mob transformations, spawning of most atoms including mobs (high-risk atoms, e.g. blackholes, will require the +FUN flag too) +# +AUTOLOGIN = admin gains powers upon connect. This defaults to on, you can use -AUTOLOGIN to make a role require using the readmin verb to gain powers. (this does not effect the admin's ability to walk past bans or other on-connect limitations like panic bunker or pop limit.) # +EVERYTHING (or +HOST or +ALL) = Simply gives you everything without having to type every flag # END_KEYWORDS -Admin Observer +Admin Observer = -AUTOLOGIN Moderator = +ADMIN Admin Candidate = +@ Trial Admin = +@ +SPAWN +REJUV +VAREDIT +BAN Badmin = +@ +POSSESS +BUILDMODE +SERVER +FUN Game Admin = +@ +STEALTH +SOUNDS +DEBUG Game Master = +EVERYTHING +Lazy Master = +EVERYTHING -AUTOLOGIN Host = +EVERYTHING -Coder = +DEBUG +VAREDIT +SERVER +SPAWN \ No newline at end of file +<<<<<<< HEAD +Coder = +DEBUG +VAREDIT +SERVER +SPAWN +======= +Coder = +DEBUG +VAREDIT +SERVER +SPAWN +POLL -AUTOLOGIN +>>>>>>> 4e929c7... Deadmin tweaks: Admins without +AUTOLOGIN start deadmined. AUTOLOGIN defaults to on. (#33480) diff --git a/config/admins.txt b/config/admins.txt index b7d8cf0e6b..0f5684b465 100644 --- a/config/admins.txt +++ b/config/admins.txt @@ -15,7 +15,7 @@ Optimumtact = Host NewSta = Game Master Expletives = Game Master kingofkosmos = Game Master -MrStonedOne = Game Master +MrStonedOne = Lazy Master microscopics = Game Master Gun Hog = Game Master KorPhaeron = Game Master