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({"