diff --git a/code/__HELPERS/type2type.dm b/code/__HELPERS/type2type.dm index 960f894d676f..4e4a1b3ff31c 100644 --- a/code/__HELPERS/type2type.dm +++ b/code/__HELPERS/type2type.dm @@ -226,7 +226,6 @@ if(rights & R_POSSESS) . += "[seperator]+POSSESS" if(rights & R_PERMISSIONS) . += "[seperator]+PERMISSIONS" if(rights & R_STEALTH) . += "[seperator]+STEALTH" - if(rights & R_REJUVINATE) . += "[seperator]+REJUVINATE" if(rights & R_COLOR) . += "[seperator]+COLOR" if(rights & R_VAREDIT) . += "[seperator]+VAREDIT" if(rights & R_SOUNDS) . += "[seperator]+SOUND" diff --git a/code/_globalvars/bitfields.dm b/code/_globalvars/bitfields.dm index 121d1e305e43..09b55accf16d 100644 --- a/code/_globalvars/bitfields.dm +++ b/code/_globalvars/bitfields.dm @@ -25,7 +25,6 @@ DEFINE_BITFIELD(rights, list( "POSSESS" = R_POSSESS, "PERMISSIONS" = R_PERMISSIONS, "STEALTH" = R_STEALTH, - "REJUVENATE" = R_REJUVINATE, "COLOR" = R_COLOR, "VAREDIT" = R_VAREDIT, "SOUNDS" = R_SOUNDS, diff --git a/code/controllers/configuration/configuration.dm b/code/controllers/configuration/configuration.dm index 86d5a11a668e..938fc9cc66ca 100644 --- a/code/controllers/configuration/configuration.dm +++ b/code/controllers/configuration/configuration.dm @@ -24,6 +24,7 @@ /datum/controller/configuration/proc/admin_reload() if(IsAdminAdvancedProcCall()) + alert_proccall("configuration admin_reload") return log_admin("[key_name(usr)] has forcefully reloaded the configuration from disk.") message_admins("[key_name_admin(usr)] has forcefully reloaded the configuration from disk.") @@ -33,6 +34,7 @@ /datum/controller/configuration/proc/Load(_directory) if(IsAdminAdvancedProcCall()) //If admin proccall is detected down the line it will horribly break everything. + alert_proccall("configuration Load") return if(_directory) directory = _directory @@ -117,6 +119,7 @@ /datum/controller/configuration/proc/full_wipe() if(IsAdminAdvancedProcCall()) + alert_proccall("configuration full_wipe") return entries_by_type.Cut() QDEL_LIST_ASSOC_VAL(entries) @@ -163,6 +166,7 @@ /datum/controller/configuration/proc/LoadEntries(filename, list/stack = list()) if(IsAdminAdvancedProcCall()) + alert_proccall("configuration LoadEntries") return var/filename_to_test = world.system_type == MS_WINDOWS ? lowertext(filename) : filename diff --git a/code/global.dm b/code/global.dm index c5c6bdf84066..ae03341d23c8 100644 --- a/code/global.dm +++ b/code/global.dm @@ -12,20 +12,19 @@ #define R_POSSESS (1<<5) #define R_PERMISSIONS (1<<6) #define R_STEALTH (1<<7) -#define R_REJUVINATE (1<<8) -#define R_COLOR (1<<9) -#define R_VAREDIT (1<<10) -#define R_SOUNDS (1<<11) -#define R_SPAWN (1<<12) -#define R_MOD (1<<13) -#define R_MENTOR (1<<14) -#define R_HOST (1<<15) -#define R_PROFILER (1<<16) -#define R_NOLOCK (1<<17) -#define R_EVENT (1<<18) +#define R_COLOR (1<<8) +#define R_VAREDIT (1<<9) +#define R_SOUNDS (1<<10) +#define R_SPAWN (1<<11) +#define R_MOD (1<<12) +#define R_MENTOR (1<<13) +#define R_HOST (1<<14) +#define R_PROFILER (1<<15) +#define R_NOLOCK (1<<16) +#define R_EVENT (1<<17) /// The sum of all other rank permissions. -#define R_EVERYTHING ((1<<19)-1) +#define R_EVERYTHING ((1<<18)-1) // 512.1430 increases maximum bit flags from 16 to 24, so the following flags should be available for future changes: //================================================= diff --git a/code/modules/admin/IsBanned.dm b/code/modules/admin/IsBanned.dm index 36e70d311ac0..166acf528b1c 100644 --- a/code/modules/admin/IsBanned.dm +++ b/code/modules/admin/IsBanned.dm @@ -1,9 +1,9 @@ #ifndef OVERRIDE_BAN_SYSTEM -//Blocks an attempt to connect before even creating our client datum thing. +/// Blocks an attempt to connect before even creating our client datum thing. /world/IsBanned(key,address,computer_id, type, real_bans_only=FALSE) var/ckey = ckey(key) - // This is added siliently. Thanks to MSO for this fix. You will see it when/if we go OS + /// This is added siliently. Thanks to MSO for this fix. You will see it when/if we go OS if (type == "world") return ..() //shunt world topic banchecks to purely to byond's internal ban system @@ -11,28 +11,33 @@ if (C && ckey == C.ckey && computer_id == C.computer_id && address == C.address) return //don't recheck connected clients. - //Guest Checking + /// Guest Checking if(IsGuestKey(key)) log_access("Failed Login: [key] - Guests not allowed") message_admins("Failed Login: [key] - Guests not allowed") return list("reason"="guest", "desc"="\nReason: Guests not allowed. Please sign in with a byond account.") WAIT_DB_READY - if(admin_datums[ckey] && (admin_datums[ckey].rights & R_MOD)) - return ..() - - if(CONFIG_GET(number/limit_players) && CONFIG_GET(number/limit_players) < GLOB.clients.len) + /// Staff can always connect through cap, for safety. + var/staff_player = FALSE + var/player_limit = CONFIG_GET(number/limit_players) + if(admin_datums[ckey]) + staff_player = TRUE + if(admin_datums[ckey].rights & R_PERMISSIONS) + return ..() + + if(!(staff_player && (player_limit && player_limit < GLOB.clients.len))) return list("reason"="POP CAPPED", "desc"="\nReason: Server is pop capped at the moment at [CONFIG_GET(number/limit_players)] players. Attempt reconnection in 2-3 minutes.") var/datum/entity/player/P = get_player_from_key(ckey) - //check if the IP address is a known TOR node + /// check if the IP address is a known TOR node if(CONFIG_GET(flag/ToRban) && ToRban_isbanned(address)) log_access("Failed Login: [src] - Banned: ToR") message_admins("Failed Login: [src] - Banned: ToR") return list("reason"="Using ToR", "desc"="\nReason: The network you are using to connect has been banned.\nIf you believe this is a mistake, please request help at [CONFIG_GET(string/banappeals)]") - // wait for database to be ready + /// wait for database to be ready . = P.check_ban(computer_id, address) if(.) diff --git a/code/modules/admin/NewBan.dm b/code/modules/admin/NewBan.dm index fab0c24622fe..3e77fda210aa 100644 --- a/code/modules/admin/NewBan.dm +++ b/code/modules/admin/NewBan.dm @@ -226,6 +226,10 @@ var/savefile/Banlist RemoveBan(A) /client/proc/cmd_admin_do_ban(mob/M) + if(IsAdminAdvancedProcCall()) + alert_proccall("cmd_admin_do_ban") + return + if(!check_rights(R_BAN|R_MOD)) return if(!ismob(M)) return @@ -248,3 +252,39 @@ var/savefile/Banlist if(P.is_time_banned && alert(usr, "Ban already exists. Proceed?", "Confirmation", "Yes", "No") != "Yes") return P.add_timed_ban(reason, mins) + + + +/client/proc/cmd_do_management_ban(mob/M, nameless = TRUE, anti_staff = FALSE) + if(IsAdminAdvancedProcCall()) + alert_proccall("cmd_do_management_ban") + return + if(!check_rights(R_PERMISSIONS)) + to_chat(src, SPAN_BOLDWARNING("Warning: You do not have access to this command.")) + return + + if(!ismob(M)) + to_chat(src, SPAN_BOLDWARNING("Warning: Mob not found.")) + return + + if(!anti_staff) + if(M.client && M.client.admin_holder && (M.client.admin_holder.rights & R_MOD)) + to_chat(src, SPAN_BOLDWARNING("Warning: This command cannot execute on staff.")) + return + + if(!M.ckey) + to_chat(usr, SPAN_BOLDWARNING("Warning: Mob ckey for [M.name] not found.")) + return + var/mob_key = M.ckey + var/mins = tgui_input_number(usr,"How long (in minutes)? \n 180 = 3 hours \n 1440 = 1 day \n 4320 = 3 days \n 10080 = 7 days \n 43800 = 1 Month \n 262800 = 6 Months \n Max = 1 Year","Ban time", 1440, 525599, 1) + if(!mins) + return + if(mins >= 525600) mins = 525599 + var/reason = input(usr,"Reason? \n\nPress 'OK' to finalize the ban.","reason","Griefer") as message|null + if(!reason) + return + var/datum/entity/player/P = get_player_from_key(mob_key) // you may not be logged in, but I will find you and I will ban you + if(P.is_time_banned && alert(usr, "Ban already exists. Proceed?", "Confirmation", "Yes", "No") != "Yes") + return + ///Below proc needs replacing for nameless to function + P.add_timed_ban(reason, mins) diff --git a/code/modules/admin/admin_ranks.dm b/code/modules/admin/admin_ranks.dm index dd67a963047e..f887903a23d7 100644 --- a/code/modules/admin/admin_ranks.dm +++ b/code/modules/admin/admin_ranks.dm @@ -34,11 +34,10 @@ var/list/admin_ranks = list() //list of all ranks with associated rights if("permissions","rights") rights |= R_PERMISSIONS if("possess") rights |= R_POSSESS if("stealth") rights |= R_STEALTH - if("rejuv","rejuvinate") rights |= R_REJUVINATE if("color") rights |= R_COLOR if("varedit") rights |= R_VAREDIT if("event") rights |= R_EVENT - if("everything","host","all") rights |= (R_HOST|R_BUILDMODE|R_ADMIN|R_BAN|R_SERVER|R_DEBUG|R_PERMISSIONS|R_POSSESS|R_STEALTH|R_REJUVINATE|R_COLOR|R_VAREDIT|R_EVENT|R_SOUNDS|R_NOLOCK|R_SPAWN|R_MOD|R_MENTOR) + if("everything","host","all") rights |= (R_HOST|R_BUILDMODE|R_ADMIN|R_BAN|R_SERVER|R_DEBUG|R_PERMISSIONS|R_POSSESS|R_STEALTH|R_COLOR|R_VAREDIT|R_EVENT|R_SOUNDS|R_NOLOCK|R_SPAWN|R_MOD|R_MENTOR) if("sound","sounds") rights |= R_SOUNDS if("nolock") rights |= R_NOLOCK if("spawn","create") rights |= R_SPAWN diff --git a/code/modules/admin/callproc.dm b/code/modules/admin/callproc.dm index f84121785360..3b4241c20c53 100644 --- a/code/modules/admin/callproc.dm +++ b/code/modules/admin/callproc.dm @@ -72,6 +72,7 @@ GLOBAL_PROTECT(LastAdminCalledProc) */ /proc/HandleUserlessProcCall(user, datum/target, procname, list/arguments) if(IsAdminAdvancedProcCall()) + alert_proccall("HandleUserlessProcCall") return var/mob/proccall_handler/handler = GLOB.AdminProcCallHandler handler.add_caller(user) @@ -90,6 +91,7 @@ GLOBAL_PROTECT(LastAdminCalledProc) */ /proc/HandleUserlessSDQL(user, query_text) if(IsAdminAdvancedProcCall()) + alert_proccall("HandleUserlessSDQL") return var/mob/proccall_handler/handler = GLOB.AdminProcCallHandler @@ -224,6 +226,10 @@ GLOBAL_PROTECT(LastAdminCalledProc) /proc/IsAdminAdvancedProcCall() return (GLOB.AdminProcCaller && GLOB.AdminProcCaller == usr?.client?.ckey) || (GLOB.AdminProcCallHandler && usr == GLOB.AdminProcCallHandler) +/proc/alert_proccall(procname = "Unknown") + to_chat(usr, SPAN_BOLDWARNING("Warning: Force attempt has been logged.")) + message_admins("[key_name(usr)] has attempted to execute a restricted proc. ([procname])") + /client/proc/callproc_datum(datum/called_datum as null|area|mob|obj|turf) set category = "Debug" set name = "Datum ProcCall" diff --git a/code/modules/admin/holder2.dm b/code/modules/admin/holder2.dm index a119d4c0519f..4103d046cd40 100644 --- a/code/modules/admin/holder2.dm +++ b/code/modules/admin/holder2.dm @@ -129,6 +129,9 @@ you will have to do something like if(client.admin_holder.rights & R_ADMIN) your return 0 /client/proc/deadmin() + if(IsAdminAdvancedProcCall()) + alert_proccall("deadmin") + return if(admin_holder) admin_holder.disassociate() QDEL_NULL(admin_holder) diff --git a/code/modules/admin/player_panel/actions/management.dm b/code/modules/admin/player_panel/actions/management.dm new file mode 100644 index 000000000000..04bb963cf067 --- /dev/null +++ b/code/modules/admin/player_panel/actions/management.dm @@ -0,0 +1,37 @@ +/datum/player_action/nameless_ban + action_tag = "nameless_ban" + name = "Nameless Ban" + permissions_required = R_PERMISSIONS + +/datum/player_action/nameless_ban/act(client/user, mob/target, list/params) + user.cmd_admin_do_ban(target) + return TRUE + + +/datum/player_action/perma_ban + action_tag = "perma_ban" + name = "Permanent Ban" + permissions_required = R_PERMISSIONS + +/datum/player_action/perma_ban/act(client/user, mob/target, list/params) + user.cmd_admin_do_ban(target) + return TRUE + +/datum/player_action/ban_staff + action_tag = "ban_staff" + name = "Ban Staff" + permissions_required = R_PERMISSIONS + +/datum/player_action/ban_staff/act(client/user, mob/target, list/params) + user.cmd_admin_do_ban(target) + return TRUE + + +/datum/player_action/shadowban + action_tag = "shadow_ban" + name = "Shadow Ban" + permissions_required = R_PERMISSIONS + +/datum/player_action/shadowban/act(client/user, mob/target, list/params) + user.cmd_admin_do_ban(target) + return TRUE diff --git a/code/modules/admin/player_panel/player_panel.dm b/code/modules/admin/player_panel/player_panel.dm index 12686e683521..64b2cdb3468d 100644 --- a/code/modules/admin/player_panel/player_panel.dm +++ b/code/modules/admin/player_panel/player_panel.dm @@ -565,6 +565,7 @@ GLOBAL_LIST_INIT(pp_status_flags, list( .["is_human"] = ishuman(targetMob) .["is_xeno"] = isxeno(targetMob) + .["is_manager"] = check_rights(R_PERMISSIONS, FALSE) .["glob_status_flags"] = GLOB.pp_status_flags .["glob_limbs"] = GLOB.pp_limbs diff --git a/code/modules/admin/topic/topic.dm b/code/modules/admin/topic/topic.dm index b371db087be6..1f8f4fc20f8a 100644 --- a/code/modules/admin/topic/topic.dm +++ b/code/modules/admin/topic/topic.dm @@ -982,7 +982,7 @@ message_admins("[key_name_admin(usr)] has sent [key_name_admin(M)] to the thunderdome. (Observer.)", 1) else if(href_list["revive"]) - if(!check_rights(R_REJUVINATE)) return + if(!check_rights(R_MOD)) return var/mob/living/L = locate(href_list["revive"]) if(!istype(L)) diff --git a/code/modules/client/client_procs.dm b/code/modules/client/client_procs.dm index 6926175c835a..4bcd845e33c7 100644 --- a/code/modules/client/client_procs.dm +++ b/code/modules/client/client_procs.dm @@ -616,6 +616,7 @@ GLOBAL_LIST_INIT(whitelisted_client_procs, list( */ /client/proc/init_verbs() if(IsAdminAdvancedProcCall()) + alert_proccall("init_verbs") return var/list/verblist = list() var/list/verbstoprocess = verbs.Copy() diff --git a/config/example/admin_ranks.txt b/config/example/admin_ranks.txt index e8d13e4f24fb..87a1ceddcf6a 100644 --- a/config/example/admin_ranks.txt +++ b/config/example/admin_ranks.txt @@ -19,7 +19,6 @@ # +BAN = the ability to ban, jobban and fullban # +STEALTH = the ability to stealthmin (make yourself appear with a fake name to everyone but other admins # +POSSESS = the ability to possess objects -# +REJUV (or +REJUVINATE) = the ability to heal, respawn, modify damage and use godmode # +COLOR = the ability to use the OOC > "Set OOC Color - Self" verb # +BUILD (or +BUILDMODE) = the ability to use buildmode # +SERVER = higher-risk admin verbs and abilities, such as those which affect the server configuration. diff --git a/tgui/packages/tgui/interfaces/PlayerPanel.js b/tgui/packages/tgui/interfaces/PlayerPanel.js index 81e43423e0da..8075146e8cf9 100644 --- a/tgui/packages/tgui/interfaces/PlayerPanel.js +++ b/tgui/packages/tgui/interfaces/PlayerPanel.js @@ -10,6 +10,15 @@ const PAGES = [ color: 'green', icon: 'tools', }, + { + title: 'Management', + component: () => ManagementActions, + color: 'purple', + icon: 'ban', + canAccess: (data) => { + return !!data.is_manager; + }, + }, { title: 'Punish', component: () => PunishmentActions, @@ -891,3 +900,62 @@ const PhysicalActions = (props, context) => { ); }; +const ManagementActions = (props, context) => { + const { act, data } = useBackend(context); + const { glob_mute_bits, client_muted } = data; + return ( +
+
+ + act('nameless_ban')} + /> + act('perma_ban')} + /> + act('shadow_ban')} + /> + act('ban_staff')} + /> + +
+ +
+ +
+
+ ); +};