mirror of
https://github.com/VOREStation/VOREStation.git
synced 2026-08-29 23:17:28 +01:00
[MAJOR CHANGE] Admin rank datum (#17133)
* Admin ranks update * Permissions fix * One missing thing * Further rework to make database also fully work * Adds admin rank bitflag calculator to tools * ZA WARUDO --------- Co-authored-by: C.L. <killer65311@gmail.com>
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
#ifndef OVERRIDE_BAN_SYSTEM
|
||||
//Blocks an attempt to connect before even creating our client datum thing.
|
||||
/world/IsBanned(key,address,computer_id)
|
||||
if(ckey(key) in admin_datums)
|
||||
if(ckey(key) in GLOB.admin_datums)
|
||||
return ..()
|
||||
|
||||
//Guest Checking
|
||||
|
||||
@@ -7,7 +7,7 @@ var/global/floorIsLava = 0
|
||||
//log_adminwarn(msg) //log_and_message_admins is for this
|
||||
|
||||
for(var/client/C in GLOB.admins)
|
||||
if((R_ADMIN|R_MOD) & C.holder.rights)
|
||||
if(check_rights_for(C, (R_ADMIN|R_MOD|R_SERVER)))
|
||||
to_chat(C,
|
||||
type = MESSAGE_TYPE_ADMINLOG,
|
||||
html = msg,
|
||||
@@ -16,7 +16,7 @@ var/global/floorIsLava = 0
|
||||
/proc/msg_admin_attack(var/text) //Toggleable Attack Messages
|
||||
var/rendered = span_filter_attacklog(span_log_message(span_prefix("ATTACK:") + span_message("[text]")))
|
||||
for(var/client/C in GLOB.admins)
|
||||
if((R_ADMIN|R_MOD) & C.holder.rights)
|
||||
if(check_rights_for(C, (R_ADMIN|R_MOD)))
|
||||
if(C.prefs?.read_preference(/datum/preference/toggle/show_attack_logs))
|
||||
var/msg = rendered
|
||||
to_chat(C,
|
||||
@@ -26,8 +26,16 @@ var/global/floorIsLava = 0
|
||||
|
||||
/proc/admin_notice(var/message, var/rights)
|
||||
for(var/mob/M in mob_list)
|
||||
if(check_rights(rights, 0, M))
|
||||
to_chat(M,message)
|
||||
var/C = M.client
|
||||
|
||||
if(!C)
|
||||
return
|
||||
|
||||
if(!(istype(C, /client)))
|
||||
return
|
||||
|
||||
if(check_rights_for(C, rights))
|
||||
to_chat(C, message)
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////Panels
|
||||
|
||||
@@ -49,7 +57,7 @@ var/global/floorIsLava = 0
|
||||
body += "<body>Options panel for" + span_bold("[M]")
|
||||
if(M.client)
|
||||
body += " played by " + span_bold("[M.client]")
|
||||
body += "\[<A href='byond://?src=\ref[src];[HrefToken()];editrights=show'>[M.client.holder ? M.client.holder.rank : "Player"]</A>\]"
|
||||
body += "\[<A href='byond://?src=\ref[src];[HrefToken()];editrights=show'>[M.client.holder ? M.client.holder.rank_names() : "Player"]</A>\]"
|
||||
|
||||
if(isnewplayer(M))
|
||||
body += span_bold(" Hasn't Entered Game")
|
||||
@@ -1353,7 +1361,7 @@ var/datum/announcement/minor/admin_min_announcer = new
|
||||
if(istype(whom, /mob))
|
||||
M = whom
|
||||
C = M.client
|
||||
if(R_HOST & C.holder.rights)
|
||||
if(check_rights_for(C, R_HOST))
|
||||
return 1
|
||||
else
|
||||
return 0
|
||||
@@ -1562,12 +1570,12 @@ var/datum/announcement/minor/admin_min_announcer = new
|
||||
if(P.sender) // sent as a reply
|
||||
log_admin("[key_name(src.owner)] replied to a fax message from [key_name(P.sender)]")
|
||||
for(var/client/C in GLOB.admins)
|
||||
if((R_ADMIN | R_MOD | R_EVENT) & C.holder.rights)
|
||||
if(check_rights_for(C, (R_ADMIN | R_MOD | R_EVENT)))
|
||||
to_chat(C, span_log_message("[span_prefix("FAX LOG:")][key_name_admin(src.owner)] replied to a fax message from [key_name_admin(P.sender)] (<a href='byond://?_src_=holder;[HrefToken()];AdminFaxView=\ref[rcvdcopy]'>VIEW</a>)"))
|
||||
else
|
||||
log_admin("[key_name(src.owner)] has sent a fax message to [destination.department]")
|
||||
for(var/client/C in GLOB.admins)
|
||||
if((R_ADMIN | R_MOD | R_EVENT) & C.holder.rights)
|
||||
if(check_rights_for(C, (R_ADMIN | R_MOD | R_EVENT)))
|
||||
to_chat(C, span_log_message("[span_prefix("FAX LOG:")][key_name_admin(src.owner)] has sent a fax message to [destination.department] (<a href='byond://?_src_=holder;[HrefToken()];AdminFaxView=\ref[rcvdcopy]'>VIEW</a>)"))
|
||||
|
||||
var/plaintext_title = P.sender ? "replied to [key_name(P.sender)]'s fax" : "sent a fax message to [destination.department]"
|
||||
@@ -1590,3 +1598,18 @@ var/datum/announcement/minor/admin_min_announcer = new
|
||||
qdel(P)
|
||||
faxreply = null
|
||||
return
|
||||
|
||||
/datum/admins/proc/set_uplink(mob/living/carbon/human/H as mob)
|
||||
set category = "Debug.Events"
|
||||
set name = "Set Uplink"
|
||||
set desc = "Allows admins to set up an uplink on a character. This will be required for a character to use telecrystals."
|
||||
set popup_menu = FALSE
|
||||
|
||||
if(check_rights(R_ADMIN|R_DEBUG))
|
||||
traitors.spawn_uplink(H)
|
||||
H.mind.tcrystals = DEFAULT_TELECRYSTAL_AMOUNT
|
||||
H.mind.accept_tcrystals = 1
|
||||
var/msg = "[key_name(usr)] has given [H.ckey] an uplink."
|
||||
message_admins(msg)
|
||||
else
|
||||
to_chat(usr, "You do not have access to this command.")
|
||||
|
||||
+368
-136
@@ -1,166 +1,398 @@
|
||||
var/list/admin_ranks = list() //list of all ranks with associated rights
|
||||
GLOBAL_LIST_EMPTY(admin_ranks) //list of all admin_rank datums
|
||||
GLOBAL_PROTECT(admin_ranks)
|
||||
|
||||
//load our rank - > rights associations
|
||||
/proc/load_admin_ranks()
|
||||
admin_ranks.Cut()
|
||||
GLOBAL_LIST_EMPTY(protected_ranks) //admin ranks loaded from txt
|
||||
GLOBAL_PROTECT(protected_ranks)
|
||||
|
||||
var/previous_rights = 0
|
||||
/datum/admin_rank
|
||||
var/name = "NoRank"
|
||||
var/rights = R_DEFAULT
|
||||
var/exclude_rights = NONE
|
||||
var/include_rights = NONE
|
||||
var/can_edit_rights = NONE
|
||||
|
||||
//Clear profile access
|
||||
for(var/A in world.GetConfig("admin"))
|
||||
world.SetConfig("APP/admin", A, null)
|
||||
/datum/admin_rank/New(init_name, init_rights, init_exclude_rights, init_edit_rights)
|
||||
if(IsAdminAdvancedProcCall())
|
||||
alert_to_permissions_elevation_attempt(usr)
|
||||
if (name == "NoRank") //only del if this is a true creation (and not just a New() proc call), other wise trialmins/coders could abuse this to deadmin other admins
|
||||
QDEL_IN(src, 0)
|
||||
CRASH("Admin proc call creation of admin datum")
|
||||
return
|
||||
name = init_name
|
||||
if(!name)
|
||||
qdel(src)
|
||||
CRASH("Admin rank created without name.")
|
||||
if(init_rights)
|
||||
rights = init_rights
|
||||
include_rights = rights
|
||||
if(init_exclude_rights)
|
||||
exclude_rights = init_exclude_rights
|
||||
rights &= ~exclude_rights
|
||||
if(init_edit_rights)
|
||||
can_edit_rights = init_edit_rights
|
||||
|
||||
//load text from file
|
||||
var/list/Lines = file2list("config/admin_ranks.txt")
|
||||
/datum/admin_rank/Destroy()
|
||||
if(IsAdminAdvancedProcCall())
|
||||
alert_to_permissions_elevation_attempt(usr)
|
||||
return QDEL_HINT_LETMELIVE
|
||||
. = ..()
|
||||
|
||||
//process each line seperately
|
||||
for(var/line in Lines)
|
||||
if(!length(line)) continue
|
||||
if(copytext(line,1,2) == "#") continue
|
||||
/datum/admin_rank/vv_edit_var(var_name, var_value)
|
||||
return FALSE
|
||||
|
||||
var/list/List = splittext(line,"+")
|
||||
if(!List.len) continue
|
||||
|
||||
var/rank = ckeyEx(List[1])
|
||||
switch(rank)
|
||||
if(null,"") continue
|
||||
if("Removed") continue //Reserved
|
||||
|
||||
var/rights = 0
|
||||
for(var/i=2, i<=List.len, i++)
|
||||
switch(ckey(List[i]))
|
||||
if("@","prev") rights |= previous_rights
|
||||
if("buildmode","build") rights |= R_BUILDMODE
|
||||
if("admin") rights |= R_ADMIN
|
||||
if("ban") rights |= R_BAN
|
||||
if("fun") rights |= R_FUN
|
||||
if("server") rights |= R_SERVER
|
||||
if("debug") rights |= R_DEBUG
|
||||
if("permissions","rights") rights |= R_PERMISSIONS
|
||||
if("possess") rights |= R_POSSESS
|
||||
if("stealth") rights |= R_STEALTH
|
||||
if("rejuv","rejuvinate") rights |= R_REJUVINATE
|
||||
if("varedit") rights |= R_VAREDIT
|
||||
if("everything","host","all") rights |= (R_HOST | R_BUILDMODE | R_ADMIN | R_BAN | R_FUN | R_SERVER | R_DEBUG | R_PERMISSIONS | R_POSSESS | R_STEALTH | R_REJUVINATE | R_VAREDIT | R_SOUNDS | R_SPAWN | R_MOD| R_EVENT)
|
||||
if("sound","sounds") rights |= R_SOUNDS
|
||||
if("spawn","create") rights |= R_SPAWN
|
||||
if("mod") rights |= R_MOD
|
||||
if("event") rights |= R_EVENT
|
||||
|
||||
admin_ranks[rank] = rights
|
||||
previous_rights = rights
|
||||
// Adds/removes rights to this admin_rank
|
||||
/datum/admin_rank/proc/process_keyword(group, group_count, datum/admin_rank/previous_rank)
|
||||
if(IsAdminAdvancedProcCall())
|
||||
alert_to_permissions_elevation_attempt(usr)
|
||||
return
|
||||
var/list/keywords = splittext(group, " ")
|
||||
var/flag = 0
|
||||
for(var/k in keywords)
|
||||
switch(k)
|
||||
if("BUILD")
|
||||
flag = R_BUILDMODE
|
||||
if("ADMIN")
|
||||
flag = R_ADMIN
|
||||
if("BAN")
|
||||
flag = R_BAN
|
||||
if("FUN")
|
||||
flag = R_FUN
|
||||
if("SERVER")
|
||||
flag = R_SERVER
|
||||
if("DEBUG")
|
||||
flag = R_DEBUG
|
||||
if("PERMISSIONS")
|
||||
flag = R_PERMISSIONS
|
||||
if("POSSESS")
|
||||
flag = R_POSSESS
|
||||
if("STEALTH")
|
||||
flag = R_STEALTH
|
||||
if("REJUVINATE")
|
||||
flag = R_REJUVINATE
|
||||
if("VAREDIT")
|
||||
flag = R_VAREDIT
|
||||
if("EVERYTHING")
|
||||
flag = R_EVERYTHING
|
||||
if("SOUND")
|
||||
flag = R_SOUNDS
|
||||
if("SPAWN")
|
||||
flag = R_SPAWN
|
||||
if("MOD")
|
||||
flag = R_MOD
|
||||
if("EVENT")
|
||||
flag = R_EVENT
|
||||
if("@")
|
||||
if(previous_rank)
|
||||
switch(group_count)
|
||||
if(1)
|
||||
flag = previous_rank.include_rights
|
||||
if(2)
|
||||
flag = previous_rank.exclude_rights
|
||||
if(3)
|
||||
flag = previous_rank.can_edit_rights
|
||||
else
|
||||
continue
|
||||
switch(group_count)
|
||||
if(1)
|
||||
rights |= flag
|
||||
include_rights |= flag
|
||||
if(2)
|
||||
rights &= ~flag
|
||||
exclude_rights |= flag
|
||||
if(3)
|
||||
can_edit_rights |= flag
|
||||
|
||||
/// Loads admin ranks.
|
||||
/// Return a list containing the backup data if they were loaded from the database backup json
|
||||
/proc/load_admin_ranks(dbfail, no_update)
|
||||
if(IsAdminAdvancedProcCall())
|
||||
to_chat(usr, "<span class='admin prefix'>Admin Reload blocked: Advanced ProcCall detected.</span>", confidential = TRUE)
|
||||
return
|
||||
GLOB.admin_ranks.Cut()
|
||||
GLOB.protected_ranks.Cut()
|
||||
//load text from file and process each entry
|
||||
var/ranks_text = file2text("[global.config.directory]/admin_ranks.txt")
|
||||
var/datum/admin_rank/previous_rank
|
||||
var/regex/admin_ranks_regex = new(@"^Name\s*=\s*(.+?)\s*\n+Include\s*=\s*([\l @]*?)\s*\n+Exclude\s*=\s*([\l @]*?)\s*\n+Edit\s*=\s*([\l @]*?)\s*\n*$", "gm")
|
||||
while(admin_ranks_regex.Find(ranks_text))
|
||||
var/datum/admin_rank/R = new(admin_ranks_regex.group[1])
|
||||
if(!R)
|
||||
continue
|
||||
var/count = 1
|
||||
for(var/i in admin_ranks_regex.group - admin_ranks_regex.group[1])
|
||||
if(i)
|
||||
R.process_keyword(i, count, previous_rank)
|
||||
count++
|
||||
GLOB.admin_ranks += R
|
||||
GLOB.protected_ranks += R
|
||||
previous_rank = R
|
||||
if(!CONFIG_GET(flag/admin_legacy_system) && !dbfail)
|
||||
if(CONFIG_GET(flag/load_legacy_ranks_only))
|
||||
if(!no_update)
|
||||
sync_ranks_with_db()
|
||||
else
|
||||
var/datum/db_query/query_load_admin_ranks = SSdbcore.NewQuery("SELECT `rank`, flags, exclude_flags, can_edit_flags FROM [format_table_name("admin_ranks")]")
|
||||
if(!query_load_admin_ranks.Execute())
|
||||
message_admins("Error loading admin ranks from database. Loading from backup.")
|
||||
log_sql("Error loading admin ranks from database. Loading from backup.")
|
||||
dbfail = TRUE
|
||||
else
|
||||
while(query_load_admin_ranks.NextRow())
|
||||
var/skip
|
||||
var/rank_name = query_load_admin_ranks.item[1]
|
||||
for(var/datum/admin_rank/R in GLOB.admin_ranks)
|
||||
if(R.name == rank_name) //this rank was already loaded from txt override
|
||||
skip = 1
|
||||
break
|
||||
if(!skip)
|
||||
var/rank_flags = text2num(query_load_admin_ranks.item[2])
|
||||
var/rank_exclude_flags = text2num(query_load_admin_ranks.item[3])
|
||||
var/rank_can_edit_flags = text2num(query_load_admin_ranks.item[4])
|
||||
var/datum/admin_rank/R = new(rank_name, rank_flags, rank_exclude_flags, rank_can_edit_flags)
|
||||
if(!R)
|
||||
continue
|
||||
GLOB.admin_ranks += R
|
||||
qdel(query_load_admin_ranks)
|
||||
//load ranks from backup file
|
||||
if(dbfail)
|
||||
var/backup_file = file2text("data/admins_backup.json")
|
||||
if(backup_file == null)
|
||||
log_world("Unable to locate admins backup file.")
|
||||
return FALSE
|
||||
var/list/json = json_decode(backup_file)
|
||||
for(var/J in json["ranks"])
|
||||
var/skip
|
||||
for(var/datum/admin_rank/R in GLOB.admin_ranks)
|
||||
if(R.name == "[J]") //this rank was already loaded from txt override
|
||||
skip = TRUE
|
||||
if(skip)
|
||||
continue
|
||||
var/datum/admin_rank/R = new("[J]", json["ranks"]["[J]"]["include rights"], json["ranks"]["[J]"]["exclude rights"], json["ranks"]["[J]"]["can edit rights"])
|
||||
if(!R)
|
||||
continue
|
||||
GLOB.admin_ranks += R
|
||||
return json
|
||||
#ifdef TESTING
|
||||
var/msg = "Permission Sets Built:\n"
|
||||
for(var/rank in admin_ranks)
|
||||
msg += "\t[rank] - [admin_ranks[rank]]\n"
|
||||
for(var/datum/admin_rank/R in GLOB.admin_ranks)
|
||||
msg += "\t[R.name]"
|
||||
var/rights = rights2text(R.rights,"\n\t\t")
|
||||
if(rights)
|
||||
msg += "\t\t[rights]\n"
|
||||
testing(msg)
|
||||
#endif
|
||||
|
||||
/hook/startup/proc/loadAdmins()
|
||||
load_admins()
|
||||
return 1
|
||||
/// Converts a rank name (such as "Coder+Moth") into a list of /datum/admin_rank
|
||||
/proc/ranks_from_rank_name(rank_name)
|
||||
var/list/rank_names = splittext(rank_name, "+")
|
||||
var/list/ranks = list()
|
||||
|
||||
/proc/load_admins()
|
||||
for (var/datum/admin_rank/rank as anything in GLOB.admin_ranks)
|
||||
if (rank.name in rank_names)
|
||||
rank_names -= rank.name
|
||||
ranks += rank
|
||||
|
||||
if (rank_names.len == 0)
|
||||
break
|
||||
|
||||
if (rank_names.len > 0)
|
||||
log_config("Admin rank names were invalid: [jointext(ranks, ", ")]")
|
||||
|
||||
return ranks
|
||||
|
||||
/// Takes a list of rank names and joins them with +
|
||||
/proc/join_admin_ranks(list/datum/admin_rank/ranks)
|
||||
var/list/names = list()
|
||||
|
||||
for (var/datum/admin_rank/rank as anything in ranks)
|
||||
names += rank.name
|
||||
|
||||
return jointext(names, "+")
|
||||
|
||||
/// (Re)Loads the admin list.
|
||||
/// returns TRUE if database admins had to be loaded from the backup json
|
||||
/proc/load_admins(no_update)
|
||||
var/dbfail
|
||||
if(!CONFIG_GET(flag/admin_legacy_system) && !SSdbcore.Connect())
|
||||
message_admins("Failed to connect to database while loading admins. Loading from backup.")
|
||||
log_sql("Failed to connect to database while loading admins. Loading from backup.")
|
||||
dbfail = TRUE
|
||||
//clear the datums references
|
||||
admin_datums.Cut()
|
||||
GLOB.admin_datums.Cut()
|
||||
for(var/client/C in GLOB.admins)
|
||||
C.remove_admin_verbs()
|
||||
C.holder = null
|
||||
GLOB.admins.Cut()
|
||||
GLOB.protected_admins.Cut()
|
||||
GLOB.deadmins.Cut()
|
||||
var/list/backup_file_json = load_admin_ranks(dbfail, no_update)
|
||||
dbfail = backup_file_json != null
|
||||
//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)
|
||||
rank_names[R.name] = R
|
||||
//ckeys listed in admins.txt are always made admins before sql loading is attempted
|
||||
var/admins_text = file2text("[global.config.directory]/admins.txt")
|
||||
var/regex/admins_regex = new(@"^(?!#)(.+?)\s+=\s+(.+)", "gm")
|
||||
|
||||
if(CONFIG_GET(flag/admin_legacy_system))
|
||||
load_admin_ranks()
|
||||
while(admins_regex.Find(admins_text))
|
||||
var/admin_key = admins_regex.group[1]
|
||||
var/admin_rank = admins_regex.group[2]
|
||||
new /datum/admins(ranks_from_rank_name(admin_rank), ckey(admin_key), force_active = FALSE, protected = TRUE)
|
||||
|
||||
//load text from file
|
||||
var/list/Lines = file2list("config/admins.txt")
|
||||
if(!CONFIG_GET(flag/admin_legacy_system) && !dbfail)
|
||||
var/datum/db_query/query_load_admins = SSdbcore.NewQuery("SELECT ckey, `rank`, feedback FROM [format_table_name("admin")] ORDER BY `rank`")
|
||||
if(!query_load_admins.Execute())
|
||||
message_admins("Error loading admins from database. Loading from backup.")
|
||||
log_sql("Error loading admins from database. Loading from backup.")
|
||||
dbfail = 1
|
||||
else
|
||||
while(query_load_admins.NextRow())
|
||||
var/admin_ckey = ckey(query_load_admins.item[1])
|
||||
var/admin_rank = query_load_admins.item[2]
|
||||
var/admin_feedback = query_load_admins.item[3]
|
||||
var/skip
|
||||
|
||||
//process each line seperately
|
||||
for(var/line in Lines)
|
||||
if(!length(line)) continue
|
||||
if(copytext(line,1,2) == "#") continue
|
||||
|
||||
//Split the line at every "-"
|
||||
var/list/List = splittext(line, "-")
|
||||
if(!List.len) continue
|
||||
|
||||
//ckey is before the first "-"
|
||||
var/ckey = ckey(List[1])
|
||||
if(!ckey) continue
|
||||
|
||||
//rank follows the first "-"
|
||||
var/rank = ""
|
||||
if(List.len >= 2)
|
||||
rank = ckeyEx(List[2])
|
||||
|
||||
//load permissions associated with this rank
|
||||
var/rights = admin_ranks[rank]
|
||||
|
||||
//create the admin datum and store it for later use
|
||||
var/datum/admins/D = new /datum/admins(rank, rights, ckey)
|
||||
|
||||
//find the client for a ckey if they are connected and associate them with the new admin datum
|
||||
D.associate(GLOB.directory[ckey])
|
||||
|
||||
else
|
||||
//The current admin system uses SQL
|
||||
|
||||
establish_db_connection()
|
||||
if(!SSdbcore.IsConnected())
|
||||
error("Failed to connect to database in load_admins(). Reverting to legacy system.")
|
||||
log_misc("Failed to connect to database in load_admins(). Reverting to legacy system.")
|
||||
CONFIG_SET(flag/admin_legacy_system, TRUE)
|
||||
load_admins()
|
||||
return
|
||||
|
||||
var/datum/db_query/query = SSdbcore.NewQuery("SELECT ckey, rank, level, flags FROM erro_admin")
|
||||
query.Execute()
|
||||
while(query.NextRow())
|
||||
var/ckey = query.item[1]
|
||||
var/rank = query.item[2]
|
||||
if(rank == "Removed") continue //This person was de-adminned. They are only in the admin list for archive purposes.
|
||||
|
||||
var/rights = query.item[4]
|
||||
if(istext(rights)) rights = text2num(rights)
|
||||
var/datum/admins/D = new /datum/admins(rank, rights, ckey)
|
||||
|
||||
//find the client for a ckey if they are connected and associate them with the new admin datum
|
||||
D.associate(GLOB.directory[ckey])
|
||||
qdel(query)
|
||||
if(!admin_datums)
|
||||
error("The database query in load_admins() resulted in no admins being added to the list. Reverting to legacy system.")
|
||||
log_misc("The database query in load_admins() resulted in no admins being added to the list. Reverting to legacy system.")
|
||||
CONFIG_SET(flag/admin_legacy_system, TRUE)
|
||||
load_admins()
|
||||
return
|
||||
var/list/admin_ranks = ranks_from_rank_name(admin_rank)
|
||||
|
||||
if(admin_ranks.len == 0)
|
||||
message_admins("[admin_ckey] loaded with invalid admin rank [admin_rank].")
|
||||
skip = 1
|
||||
if(GLOB.admin_datums[admin_ckey] || GLOB.deadmins[admin_ckey])
|
||||
skip = 1
|
||||
if(!skip)
|
||||
var/datum/admins/admin_holder = new(admin_ranks, admin_ckey)
|
||||
admin_holder.cached_feedback_link = admin_feedback || NO_FEEDBACK_LINK
|
||||
qdel(query_load_admins)
|
||||
if (!no_update)
|
||||
save_admin_backup()
|
||||
sync_admins_with_db()
|
||||
//load admins from backup file
|
||||
if(dbfail)
|
||||
if(!backup_file_json)
|
||||
if(backup_file_json != null)
|
||||
//already tried
|
||||
return
|
||||
var/backup_file = file2text("data/admins_backup.json")
|
||||
if(backup_file == null)
|
||||
log_world("Unable to locate admins backup file.")
|
||||
return
|
||||
backup_file_json = json_decode(backup_file)
|
||||
for(var/backup_admin_ckey in backup_file_json["admins"])
|
||||
var/skip
|
||||
for(var/admin_ckey in GLOB.admin_datums + GLOB.deadmins)
|
||||
if(ckey(admin_ckey) == ckey("[backup_admin_ckey]")) //this admin was already loaded from txt override
|
||||
skip = TRUE
|
||||
break
|
||||
if(skip)
|
||||
continue
|
||||
new /datum/admins(ranks_from_rank_name(backup_file_json["admins"]["[backup_admin_ckey]"]), ckey("[backup_admin_ckey]"))
|
||||
#ifdef TESTING
|
||||
var/msg = "Admins Built:\n"
|
||||
for(var/ckey in admin_datums)
|
||||
var/rank
|
||||
var/datum/admins/D = admin_datums[ckey]
|
||||
if(D) rank = D.rank
|
||||
msg += "\t[ckey] - [rank]\n"
|
||||
for(var/ckey in GLOB.admin_datums)
|
||||
var/datum/admins/D = GLOB.admin_datums[ckey]
|
||||
msg += "\t[ckey] - [D.rank_names()]\n"
|
||||
testing(msg)
|
||||
#endif
|
||||
return dbfail
|
||||
|
||||
|
||||
#ifdef TESTING
|
||||
/client/verb/changerank(newrank in admin_ranks)
|
||||
if(holder)
|
||||
holder.rank = newrank
|
||||
holder.rights = admin_ranks[newrank]
|
||||
else
|
||||
holder = new /datum/admins(newrank,admin_ranks[newrank],ckey)
|
||||
remove_admin_verbs()
|
||||
holder.associate(src)
|
||||
/proc/sync_ranks_with_db()
|
||||
set waitfor = FALSE
|
||||
|
||||
/client/verb/changerights(newrights as num)
|
||||
if(holder)
|
||||
holder.rights = newrights
|
||||
else
|
||||
holder = new /datum/admins("testing",newrights,ckey)
|
||||
remove_admin_verbs()
|
||||
holder.associate(src)
|
||||
if(IsAdminAdvancedProcCall())
|
||||
to_chat(usr, "<span class='admin prefix'>Admin rank DB Sync blocked: Advanced ProcCall detected.</span>", confidential = TRUE)
|
||||
return
|
||||
|
||||
#endif
|
||||
var/list/sql_ranks = list()
|
||||
for(var/datum/admin_rank/R as anything in GLOB.protected_ranks)
|
||||
sql_ranks += list(list("rank" = R.name, "flags" = R.include_rights, "exclude_flags" = R.exclude_rights, "can_edit_flags" = R.can_edit_rights))
|
||||
SSdbcore.MassInsert(format_table_name("admin_ranks"), sql_ranks, duplicate_key = TRUE)
|
||||
update_everything_flag_in_db()
|
||||
|
||||
|
||||
/proc/update_everything_flag_in_db()
|
||||
for(var/datum/admin_rank/R as anything in GLOB.admin_ranks)
|
||||
var/list/flags = list()
|
||||
if(R.include_rights == R_EVERYTHING)
|
||||
flags += "flags"
|
||||
if(R.exclude_rights == R_EVERYTHING)
|
||||
flags += "exclude_flags"
|
||||
if(R.can_edit_rights == R_EVERYTHING)
|
||||
flags += "can_edit_flags"
|
||||
if(!flags.len)
|
||||
continue
|
||||
var/flags_to_check = flags.Join(" != [R_EVERYTHING] AND ") + " != [R_EVERYTHING]"
|
||||
var/datum/db_query/query_check_everything_ranks = SSdbcore.NewQuery(
|
||||
"SELECT flags, exclude_flags, can_edit_flags FROM [format_table_name("admin_ranks")] WHERE rank = :rank AND ([flags_to_check])",
|
||||
list("rank" = R.name)
|
||||
)
|
||||
if(!query_check_everything_ranks.Execute())
|
||||
qdel(query_check_everything_ranks)
|
||||
return
|
||||
if(query_check_everything_ranks.NextRow()) //no row is returned if the rank already has the correct flag value
|
||||
var/flags_to_update = flags.Join(" = [R_EVERYTHING], ") + " = [R_EVERYTHING]"
|
||||
var/datum/db_query/query_update_everything_ranks = SSdbcore.NewQuery(
|
||||
"UPDATE [format_table_name("admin_ranks")] SET [flags_to_update] WHERE rank = :rank",
|
||||
list("rank" = R.name)
|
||||
)
|
||||
if(!query_update_everything_ranks.Execute())
|
||||
qdel(query_update_everything_ranks)
|
||||
return
|
||||
qdel(query_update_everything_ranks)
|
||||
qdel(query_check_everything_ranks)
|
||||
|
||||
|
||||
/proc/sync_admins_with_db()
|
||||
if(IsAdminAdvancedProcCall())
|
||||
to_chat(usr, "<span class='admin prefix'>Admin rank DB Sync blocked: Advanced ProcCall detected.</span>")
|
||||
return
|
||||
|
||||
if(CONFIG_GET(flag/admin_legacy_system) || !SSdbcore.IsConnected()) //we're already using legacy system so there's nothing to save
|
||||
return
|
||||
sync_ranks_with_db()
|
||||
var/list/sql_admins = list()
|
||||
for(var/holder_ckey in GLOB.protected_admins)
|
||||
var/datum/admins/holder = GLOB.protected_admins[holder_ckey]
|
||||
sql_admins += list(list("ckey" = holder.target, "rank" = holder.rank_names()))
|
||||
SSdbcore.MassInsert(format_table_name("admin"), sql_admins, duplicate_key = TRUE)
|
||||
var/datum/db_query/query_admin_rank_update = SSdbcore.NewQuery("UPDATE [format_table_name("player")] AS p INNER JOIN [format_table_name("admin")] AS a ON p.ckey = a.ckey SET p.lastadminrank = a.rank")
|
||||
query_admin_rank_update.Execute()
|
||||
qdel(query_admin_rank_update)
|
||||
|
||||
/proc/save_admin_backup()
|
||||
if(IsAdminAdvancedProcCall())
|
||||
to_chat(usr, "<span class='admin prefix'>Admin rank DB Sync blocked: Advanced ProcCall detected.</span>")
|
||||
return
|
||||
|
||||
if(CONFIG_GET(flag/admin_legacy_system)) //we're already using legacy system so there's nothing to save
|
||||
return
|
||||
|
||||
//json format backup file generation stored per server
|
||||
var/json_file = file("data/admins_backup.json")
|
||||
var/list/file_data = list(
|
||||
"ranks" = list(),
|
||||
"admins" = list()
|
||||
)
|
||||
for(var/datum/admin_rank/R as anything in GLOB.admin_ranks)
|
||||
file_data["ranks"]["[R.name]"] = list()
|
||||
file_data["ranks"]["[R.name]"]["include rights"] = R.include_rights
|
||||
file_data["ranks"]["[R.name]"]["exclude rights"] = R.exclude_rights
|
||||
file_data["ranks"]["[R.name]"]["can edit rights"] = R.can_edit_rights
|
||||
|
||||
for(var/admin_ckey in GLOB.admin_datums + GLOB.deadmins)
|
||||
var/datum/admins/admin = GLOB.admin_datums[admin_ckey]
|
||||
|
||||
if(!admin)
|
||||
admin = GLOB.deadmins[admin_ckey]
|
||||
if (!admin)
|
||||
continue
|
||||
|
||||
file_data["admins"][admin_ckey] = admin.rank_names()
|
||||
|
||||
//admin.backup_connections()
|
||||
|
||||
fdel(json_file)
|
||||
WRITE_FILE(json_file, json_encode(file_data, JSON_PRETTY_PRINT))
|
||||
|
||||
@@ -55,7 +55,7 @@ var/datum/admin_secrets/admin_secrets = new()
|
||||
return name
|
||||
|
||||
/datum/admin_secret_item/proc/can_view(var/mob/user)
|
||||
return check_rights(permissions, 0, user)
|
||||
return check_rights_for(user.client, permissions)
|
||||
|
||||
/datum/admin_secret_item/proc/can_execute(var/mob/user)
|
||||
if(can_view(user))
|
||||
|
||||
@@ -3,7 +3,7 @@ var/list/admin_verbs_default = list(
|
||||
/datum/admins/proc/show_player_panel, //shows an interface for individual players, with various links (links require additional flags,
|
||||
/client/proc/player_panel_new, //shows an interface for all players, with links to various panels,
|
||||
/client/proc/player_panel,
|
||||
/client/proc/deadmin_self, //destroys our own admin datum so we can play as a regular player,
|
||||
/client/proc/deadmin, //destroys our own admin datum so we can play as a regular player,
|
||||
/client/proc/hide_verbs, //hides all our adminverbs,
|
||||
/client/proc/hide_most_verbs, //hides all our hideable adminverbs,
|
||||
/client/proc/debug_variables, //allows us to -see- the variables of any instance in the game. +VAREDIT needed to modify,
|
||||
@@ -268,7 +268,7 @@ var/list/admin_verbs_rejuv = list(
|
||||
|
||||
//verbs which can be hidden - needs work
|
||||
var/list/admin_verbs_hideable = list(
|
||||
/client/proc/deadmin_self,
|
||||
/client/proc/deadmin,
|
||||
// /client/proc/deadchat,
|
||||
/datum/admins/proc/show_traitor_panel,
|
||||
/datum/admins/proc/toggleenter,
|
||||
|
||||
@@ -3,7 +3,7 @@ var/list/admin_verbs_default = list(
|
||||
// /datum/admins/proc/show_player_panel, //shows an interface for individual players, with various links (links require additional flags, //VOREStation Remove,
|
||||
// /client/proc/player_panel_new, //shows an interface for all players, with links to various panels, //VOREStation Remove,
|
||||
// /client/proc/player_panel, //VOREStation Remove,
|
||||
/client/proc/deadmin_self, //destroys our own admin datum so we can play as a regular player,
|
||||
/client/proc/deadmin, //destroys our own admin datum so we can play as a regular player,
|
||||
/client/proc/cmd_admin_say, //VOREStation Add,
|
||||
/client/proc/cmd_mod_say, //VOREStation Add,
|
||||
/client/proc/cmd_event_say, //VOREStation Add,
|
||||
@@ -311,7 +311,7 @@ var/list/admin_verbs_rejuv = list(
|
||||
|
||||
//verbs which can be hidden - needs work
|
||||
var/list/admin_verbs_hideable = list(
|
||||
/client/proc/deadmin_self,
|
||||
/client/proc/deadmin,
|
||||
// /client/proc/deadchat,
|
||||
/datum/admins/proc/show_traitor_panel,
|
||||
/datum/admins/proc/toggleenter,
|
||||
@@ -580,24 +580,25 @@ var/list/admin_verbs_event_manager = list(
|
||||
|
||||
/client/proc/add_admin_verbs()
|
||||
if(holder)
|
||||
var/rights = holder.rank_flags()
|
||||
add_verb(src, admin_verbs_default)
|
||||
if(holder.rights & R_BUILDMODE) add_verb(src, /client/proc/togglebuildmodeself)
|
||||
if(holder.rights & R_ADMIN) add_verb(src, admin_verbs_admin)
|
||||
if(holder.rights & R_BAN) add_verb(src, admin_verbs_ban)
|
||||
if(holder.rights & R_FUN) add_verb(src, admin_verbs_fun)
|
||||
if(holder.rights & R_SERVER) add_verb(src, admin_verbs_server)
|
||||
if(holder.rights & R_DEBUG)
|
||||
if(rights & R_BUILDMODE) add_verb(src, /client/proc/togglebuildmodeself)
|
||||
if(rights & R_ADMIN) add_verb(src, admin_verbs_admin)
|
||||
if(rights & R_BAN) add_verb(src, admin_verbs_ban)
|
||||
if(rights & R_FUN) add_verb(src, admin_verbs_fun)
|
||||
if(rights & R_SERVER) add_verb(src, admin_verbs_server)
|
||||
if(rights & R_DEBUG)
|
||||
add_verb(src, admin_verbs_debug)
|
||||
if(CONFIG_GET(flag/debugparanoid) && !(holder.rights & R_ADMIN))
|
||||
if(CONFIG_GET(flag/debugparanoid) && !(rights & R_ADMIN))
|
||||
remove_verb(src, admin_verbs_paranoid_debug) //Right now it's just callproc but we can easily add others later on.
|
||||
if(holder.rights & R_POSSESS) add_verb(src, admin_verbs_possess)
|
||||
if(holder.rights & R_PERMISSIONS) add_verb(src, admin_verbs_permissions)
|
||||
if(holder.rights & R_STEALTH) add_verb(src, /client/proc/stealth)
|
||||
if(holder.rights & R_REJUVINATE) add_verb(src, admin_verbs_rejuv)
|
||||
if(holder.rights & R_SOUNDS) add_verb(src, admin_verbs_sounds)
|
||||
if(holder.rights & R_SPAWN) add_verb(src, admin_verbs_spawn)
|
||||
if(holder.rights & R_MOD) add_verb(src, admin_verbs_mod)
|
||||
if(holder.rights & R_EVENT) add_verb(src, admin_verbs_event_manager)
|
||||
if(rights & R_POSSESS) add_verb(src, admin_verbs_possess)
|
||||
if(rights & R_PERMISSIONS) add_verb(src, admin_verbs_permissions)
|
||||
if(rights & R_STEALTH) add_verb(src, /client/proc/stealth)
|
||||
if(rights & R_REJUVINATE) add_verb(src, admin_verbs_rejuv)
|
||||
if(rights & R_SOUNDS) add_verb(src, admin_verbs_sounds)
|
||||
if(rights & R_SPAWN) add_verb(src, admin_verbs_spawn)
|
||||
if(rights & R_MOD) add_verb(src, admin_verbs_mod)
|
||||
if(rights & R_EVENT) add_verb(src, admin_verbs_event_manager)
|
||||
|
||||
/client/proc/remove_admin_verbs()
|
||||
remove_verb(src, list(
|
||||
|
||||
@@ -204,7 +204,7 @@
|
||||
if(!check_rights(R_ADMIN)) return
|
||||
|
||||
if(!warned_ckey || !istext(warned_ckey)) return
|
||||
if(warned_ckey in admin_datums)
|
||||
if(warned_ckey in GLOB.admin_datums)
|
||||
to_chat(usr, span_warning("Error: warn(): You can't warn admins."))
|
||||
return
|
||||
|
||||
@@ -333,36 +333,22 @@
|
||||
log_admin("[key_name(usr)] used 'kill air'.")
|
||||
message_admins(span_blue("[key_name_admin(usr)] used 'kill air'."), 1)
|
||||
|
||||
/client/proc/readmin_self()
|
||||
set name = "Re-Admin self"
|
||||
/client/proc/deadmin()
|
||||
set name = "DeAdmin"
|
||||
set category = "Admin.Misc"
|
||||
set desc = "Shed your admin powers."
|
||||
|
||||
if(deadmin_holder)
|
||||
deadmin_holder.reassociate()
|
||||
log_admin("[src] re-admined themself.")
|
||||
message_admins("[src] re-admined themself.", 1)
|
||||
to_chat(src, span_filter_system(span_interface("You now have the keys to control the planet, or at least a small space station")))
|
||||
remove_verb(src, /client/proc/readmin_self)
|
||||
if(isobserver(mob))
|
||||
var/mob/observer/dead/our_mob = mob
|
||||
our_mob.visualnet?.addVisibility(our_mob, src)
|
||||
|
||||
/client/proc/deadmin_self()
|
||||
set name = "De-admin self"
|
||||
set category = "Admin.Misc"
|
||||
|
||||
if(holder)
|
||||
if(tgui_alert(usr, "Confirm self-deadmin for the round? You can't re-admin yourself without someone promoting you.","Deadmin",list("Yes","No")) == "Yes")
|
||||
log_admin("[src] deadmined themself.")
|
||||
message_admins("[src] deadmined themself.", 1)
|
||||
deadmin()
|
||||
to_chat(src, span_filter_system(span_interface("You are now a normal player.")))
|
||||
add_verb(src, /client/proc/readmin_self)
|
||||
if(isobserver(mob))
|
||||
var/mob/observer/dead/our_mob = mob
|
||||
our_mob.visualnet?.removeVisibility(our_mob, src)
|
||||
src.holder.deactivate()
|
||||
to_chat(src, span_interface("You are now a normal player."))
|
||||
log_admin("[key_name(src)] deadminned themselves.")
|
||||
message_admins("[key_name_admin(src)] deadminned themselves.")
|
||||
//BLACKBOX_LOG_ADMIN_VERB("Deadmin")
|
||||
feedback_add_details("admin_verb","DAS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
if(isobserver(mob))
|
||||
var/mob/observer/dead/our_mob = mob
|
||||
our_mob.visualnet?.removeVisibility(our_mob, src)
|
||||
|
||||
/client/proc/toggle_log_hrefs()
|
||||
set name = "Toggle href logging"
|
||||
set category = "Server.Config"
|
||||
@@ -582,3 +568,144 @@
|
||||
return
|
||||
SSmotiontracker.hide_all = !SSmotiontracker.hide_all
|
||||
log_admin("[key_name(usr)] changed the motion echo visibility to [SSmotiontracker.hide_all ? "hidden" : "visible"].")
|
||||
|
||||
/client/proc/adminorbit()
|
||||
set category = "Fun.Event Kit"
|
||||
set name = "Orbit Things"
|
||||
set desc = "Makes something orbit around something else."
|
||||
set popup_menu = FALSE
|
||||
|
||||
if(!check_rights(R_FUN))
|
||||
return
|
||||
|
||||
var/center
|
||||
var/atom/movable/orbiter
|
||||
var/input
|
||||
|
||||
if(holder.marked_datum)
|
||||
input = tgui_alert(usr, "You have \n[holder.marked_datum] marked, should this be the center of the orbit, or the orbiter?", "Orbit", list("Center", "Orbiter", "Neither"))
|
||||
switch(input)
|
||||
if("Center")
|
||||
center = holder.marked_datum
|
||||
if("Orbiter")
|
||||
orbiter = holder.marked_datum
|
||||
var/list/possible_things = list()
|
||||
for(var/T as mob in view(view)) //Let's do mobs before objects
|
||||
if(ismob(T))
|
||||
possible_things |= T
|
||||
for(var/T as obj in view(view))
|
||||
if(isobj(T))
|
||||
possible_things |= T
|
||||
if(!center)
|
||||
center = tgui_input_list(src, "What should act as the center of the orbit?", "Center", possible_things)
|
||||
possible_things -= center
|
||||
if(!orbiter)
|
||||
orbiter = tgui_input_list(src, "What should act as the orbiter of the orbit?", "Orbiter", possible_things)
|
||||
if(!center || !orbiter)
|
||||
to_chat(usr, span_warning("A center of orbit and an orbiter must be configured. You can also do this by marking a target."))
|
||||
return
|
||||
if(center == orbiter)
|
||||
to_chat(usr, span_warning("The center of the orbit cannot also be the orbiter."))
|
||||
return
|
||||
if(isturf(orbiter))
|
||||
to_chat(usr, span_warning("The orbiter cannot be a turf. It can only be used as a center."))
|
||||
return
|
||||
var/distance = tgui_input_number(usr, "How large will their orbit radius be? (In pixels. 32 is 'near around a character)", "Orbit Radius", 32)
|
||||
var/speed = tgui_input_number(usr, "How fast will they orbit (negative numbers spin clockwise)", "Orbit Speed", 20)
|
||||
var/segments = tgui_input_number(usr, "How many segments will they have in their orbit? (3 is a triangle, 36 is a circle, etc)", "Orbit Segments", 36)
|
||||
var/clock = FALSE
|
||||
if(!distance)
|
||||
distance = 32
|
||||
if(!speed)
|
||||
speed = 20
|
||||
else if (speed < 0)
|
||||
clock = TRUE
|
||||
speed *= -1
|
||||
if(!segments)
|
||||
segments = 36
|
||||
if(tgui_alert(usr, "\The [orbiter] will orbit around [center]. Is this okay?", "Confirm Orbit", list("Yes", "No")) == "Yes")
|
||||
orbiter.orbit(center, distance, clock, speed, segments)
|
||||
|
||||
/client/proc/removetickets()
|
||||
set name = "Security Tickets"
|
||||
set category = "Admin.Investigate"
|
||||
set desc = "Allows one to remove tickets from the global list."
|
||||
|
||||
if(!check_rights(R_ADMIN))
|
||||
return
|
||||
|
||||
if(security_printer_tickets.len >= 1)
|
||||
var/input = tgui_input_list(usr, "Which message?", "Security Tickets", security_printer_tickets)
|
||||
if(!input)
|
||||
return
|
||||
if(tgui_alert(usr, "Do you want to remove the following message from the global list? \"[input]\"", "Remove Ticket", list("Yes", "No")) == "Yes")
|
||||
security_printer_tickets -= input
|
||||
log_and_message_admins("removed a security ticket from the global list: \"[input]\"", usr)
|
||||
|
||||
else
|
||||
tgui_alert_async(usr, "The ticket list is empty.","Empty")
|
||||
|
||||
/client/proc/delbook()
|
||||
set name = "Delete Book"
|
||||
set desc = "Permamently deletes a book from the database."
|
||||
set category = "Admin.Game"
|
||||
if(!src.holder)
|
||||
to_chat(src, "Only administrators may use this command.")
|
||||
return
|
||||
|
||||
var/obj/machinery/librarycomp/our_comp
|
||||
for(var/obj/machinery/librarycomp/l in world)
|
||||
if(istype(l, /obj/machinery/librarycomp))
|
||||
our_comp = l
|
||||
break
|
||||
|
||||
if(!our_comp)
|
||||
to_chat(usr, span_warning("Unable to locate a library computer to use for book deleting."))
|
||||
return
|
||||
|
||||
var/dat = "<HEAD><TITLE>Book Inventory Management</TITLE></HEAD><BODY>\n"
|
||||
dat += "<h3>ADMINISTRATIVE MANAGEMENT</h3>"
|
||||
establish_db_connection()
|
||||
|
||||
if(!SSdbcore.IsConnected())
|
||||
dat += span_red(span_bold("ERROR") + ": Unable to contact External Archive. Please contact your system administrator for assistance.")
|
||||
else
|
||||
dat += {"<A href='byond://?our_comp=\ref[our_comp];[HrefToken()];orderbyid=1'>(Order book by SS<sup>13</sup>BN)</A><BR><BR>
|
||||
<table>
|
||||
<tr><td><A href='byond://?our_comp=\ref[our_comp];[HrefToken()];sort=author>AUTHOR</A></td><td><A href='byond://?our_comp=\ref[our_comp];[HrefToken()];sort=title>TITLE</A></td><td><A href='byond://?our_comp=\ref[our_comp];[HrefToken()];sort=category>CATEGORY</A></td><td></td></tr>"}
|
||||
var/datum/db_query/query = SSdbcore.NewQuery("SELECT id, author, title, category FROM library ORDER BY [our_comp.sortby]")
|
||||
query.Execute()
|
||||
|
||||
var/show_admin_options = check_rights(R_ADMIN, show_msg = FALSE)
|
||||
|
||||
while(query.NextRow())
|
||||
var/id = query.item[1]
|
||||
var/author = query.item[2]
|
||||
var/title = query.item[3]
|
||||
var/category = query.item[4]
|
||||
dat += "<tr><td>[author]</td><td>[title]</td><td>[category]</td><td>"
|
||||
if(show_admin_options) // This isn't the only check, since you can just href-spoof press this button. Just to tidy things up.
|
||||
dat += "<A href='byond://?our_comp=\ref[our_comp];[HrefToken()];delid=[id]'>\[Del\]</A>"
|
||||
dat += "</td></tr>"
|
||||
dat += "</table>"
|
||||
|
||||
qdel(query)
|
||||
usr << browse("<html>[dat]</html>", "window=library")
|
||||
onclose(usr, "library")
|
||||
|
||||
/client/proc/toggle_spawning_with_recolour()
|
||||
set name = "Toggle Simple/Robot recolour verb"
|
||||
set desc = "Makes it so new robots/simple_mobs spawn with a verb to recolour themselves for this round. You must set them separately."
|
||||
set category = "Server.Game"
|
||||
|
||||
if(!check_rights(R_ADMIN|R_EVENT|R_FUN))
|
||||
return
|
||||
|
||||
var/which = tgui_alert(usr, "Which do you want to toggle?", "Choose Recolour Toggle", list("Robot", "Simple Mob"))
|
||||
switch(which)
|
||||
if("Robot")
|
||||
CONFIG_SET(flag/allow_robot_recolor, !CONFIG_GET(flag/allow_robot_recolor))
|
||||
to_chat(usr, "You have [CONFIG_GET(flag/allow_robot_recolor) ? "enabled" : "disabled"] newly spawned cyborgs to spawn with the recolour verb")
|
||||
if("Simple Mob")
|
||||
CONFIG_SET(flag/allow_simple_mob_recolor, !CONFIG_GET(flag/allow_simple_mob_recolor))
|
||||
to_chat(usr, "You have [CONFIG_GET(flag/allow_simple_mob_recolor) ? "enabled" : "disabled"] newly spawned simple mobs to spawn with the recolour verb")
|
||||
|
||||
@@ -1,140 +0,0 @@
|
||||
/client/proc/adminorbit()
|
||||
set category = "Fun.Event Kit"
|
||||
set name = "Orbit Things"
|
||||
set desc = "Makes something orbit around something else."
|
||||
set popup_menu = FALSE
|
||||
|
||||
if(!check_rights(R_FUN))
|
||||
return
|
||||
|
||||
var/center
|
||||
var/atom/movable/orbiter
|
||||
var/input
|
||||
|
||||
if(holder.marked_datum)
|
||||
input = tgui_alert(usr, "You have \n[holder.marked_datum] marked, should this be the center of the orbit, or the orbiter?", "Orbit", list("Center", "Orbiter", "Neither"))
|
||||
switch(input)
|
||||
if("Center")
|
||||
center = holder.marked_datum
|
||||
if("Orbiter")
|
||||
orbiter = holder.marked_datum
|
||||
var/list/possible_things = list()
|
||||
for(var/T as mob in view(view)) //Let's do mobs before objects
|
||||
if(ismob(T))
|
||||
possible_things |= T
|
||||
for(var/T as obj in view(view))
|
||||
if(isobj(T))
|
||||
possible_things |= T
|
||||
if(!center)
|
||||
center = tgui_input_list(src, "What should act as the center of the orbit?", "Center", possible_things)
|
||||
possible_things -= center
|
||||
if(!orbiter)
|
||||
orbiter = tgui_input_list(src, "What should act as the orbiter of the orbit?", "Orbiter", possible_things)
|
||||
if(!center || !orbiter)
|
||||
to_chat(usr, span_warning("A center of orbit and an orbiter must be configured. You can also do this by marking a target."))
|
||||
return
|
||||
if(center == orbiter)
|
||||
to_chat(usr, span_warning("The center of the orbit cannot also be the orbiter."))
|
||||
return
|
||||
if(isturf(orbiter))
|
||||
to_chat(usr, span_warning("The orbiter cannot be a turf. It can only be used as a center."))
|
||||
return
|
||||
var/distance = tgui_input_number(usr, "How large will their orbit radius be? (In pixels. 32 is 'near around a character)", "Orbit Radius", 32)
|
||||
var/speed = tgui_input_number(usr, "How fast will they orbit (negative numbers spin clockwise)", "Orbit Speed", 20)
|
||||
var/segments = tgui_input_number(usr, "How many segments will they have in their orbit? (3 is a triangle, 36 is a circle, etc)", "Orbit Segments", 36)
|
||||
var/clock = FALSE
|
||||
if(!distance)
|
||||
distance = 32
|
||||
if(!speed)
|
||||
speed = 20
|
||||
else if (speed < 0)
|
||||
clock = TRUE
|
||||
speed *= -1
|
||||
if(!segments)
|
||||
segments = 36
|
||||
if(tgui_alert(usr, "\The [orbiter] will orbit around [center]. Is this okay?", "Confirm Orbit", list("Yes", "No")) == "Yes")
|
||||
orbiter.orbit(center, distance, clock, speed, segments)
|
||||
|
||||
/client/proc/removetickets()
|
||||
set name = "Security Tickets"
|
||||
set category = "Admin.Investigate"
|
||||
set desc = "Allows one to remove tickets from the global list."
|
||||
|
||||
if(!check_rights(R_ADMIN))
|
||||
return
|
||||
|
||||
if(security_printer_tickets.len >= 1)
|
||||
var/input = tgui_input_list(usr, "Which message?", "Security Tickets", security_printer_tickets)
|
||||
if(!input)
|
||||
return
|
||||
if(tgui_alert(usr, "Do you want to remove the following message from the global list? \"[input]\"", "Remove Ticket", list("Yes", "No")) == "Yes")
|
||||
security_printer_tickets -= input
|
||||
log_and_message_admins("removed a security ticket from the global list: \"[input]\"", usr)
|
||||
|
||||
else
|
||||
tgui_alert_async(usr, "The ticket list is empty.","Empty")
|
||||
|
||||
/client/proc/delbook()
|
||||
set name = "Delete Book"
|
||||
set desc = "Permamently deletes a book from the database."
|
||||
set category = "Admin.Game"
|
||||
if(!src.holder)
|
||||
to_chat(src, "Only administrators may use this command.")
|
||||
return
|
||||
|
||||
var/obj/machinery/librarycomp/our_comp
|
||||
for(var/obj/machinery/librarycomp/l in world)
|
||||
if(istype(l, /obj/machinery/librarycomp))
|
||||
our_comp = l
|
||||
break
|
||||
|
||||
if(!our_comp)
|
||||
to_chat(usr, span_warning("Unable to locate a library computer to use for book deleting."))
|
||||
return
|
||||
|
||||
var/dat = "<HEAD><TITLE>Book Inventory Management</TITLE></HEAD><BODY>\n"
|
||||
dat += "<h3>ADMINISTRATIVE MANAGEMENT</h3>"
|
||||
establish_db_connection()
|
||||
|
||||
if(!SSdbcore.IsConnected())
|
||||
dat += span_red(span_bold("ERROR") + ": Unable to contact External Archive. Please contact your system administrator for assistance.")
|
||||
else
|
||||
dat += {"<A href='byond://?our_comp=\ref[our_comp];[HrefToken()];orderbyid=1'>(Order book by SS<sup>13</sup>BN)</A><BR><BR>
|
||||
<table>
|
||||
<tr><td><A href='byond://?our_comp=\ref[our_comp];[HrefToken()];sort=author>AUTHOR</A></td><td><A href='byond://?our_comp=\ref[our_comp];[HrefToken()];sort=title>TITLE</A></td><td><A href='byond://?our_comp=\ref[our_comp];[HrefToken()];sort=category>CATEGORY</A></td><td></td></tr>"}
|
||||
var/datum/db_query/query = SSdbcore.NewQuery("SELECT id, author, title, category FROM library ORDER BY [our_comp.sortby]")
|
||||
query.Execute()
|
||||
|
||||
var/show_admin_options = check_rights(R_ADMIN, show_msg = FALSE)
|
||||
|
||||
while(query.NextRow())
|
||||
var/id = query.item[1]
|
||||
var/author = query.item[2]
|
||||
var/title = query.item[3]
|
||||
var/category = query.item[4]
|
||||
dat += "<tr><td>[author]</td><td>[title]</td><td>[category]</td><td>"
|
||||
if(show_admin_options) // This isn't the only check, since you can just href-spoof press this button. Just to tidy things up.
|
||||
dat += "<A href='byond://?our_comp=\ref[our_comp];[HrefToken()];delid=[id]'>\[Del\]</A>"
|
||||
dat += "</td></tr>"
|
||||
dat += "</table>"
|
||||
|
||||
qdel(query)
|
||||
usr << browse("<html>[dat]</html>", "window=library")
|
||||
onclose(usr, "library")
|
||||
|
||||
/client/proc/toggle_spawning_with_recolour()
|
||||
set name = "Toggle Simple/Robot recolour verb"
|
||||
set desc = "Makes it so new robots/simple_mobs spawn with a verb to recolour themselves for this round. You must set them separately."
|
||||
set category = "Server.Game"
|
||||
|
||||
if(!check_rights(R_ADMIN|R_EVENT|R_FUN))
|
||||
return
|
||||
|
||||
var/which = tgui_alert(usr, "Which do you want to toggle?", "Choose Recolour Toggle", list("Robot", "Simple Mob"))
|
||||
switch(which)
|
||||
if("Robot")
|
||||
CONFIG_SET(flag/allow_robot_recolor, !CONFIG_GET(flag/allow_robot_recolor))
|
||||
to_chat(usr, "You have [CONFIG_GET(flag/allow_robot_recolor) ? "enabled" : "disabled"] newly spawned cyborgs to spawn with the recolour verb")
|
||||
if("Simple Mob")
|
||||
CONFIG_SET(flag/allow_simple_mob_recolor, !CONFIG_GET(flag/allow_simple_mob_recolor))
|
||||
to_chat(usr, "You have [CONFIG_GET(flag/allow_simple_mob_recolor) ? "enabled" : "disabled"] newly spawned simple mobs to spawn with the recolour verb")
|
||||
@@ -1,14 +0,0 @@
|
||||
/datum/admins/proc/set_uplink(mob/living/carbon/human/H as mob)
|
||||
set category = "Debug.Events"
|
||||
set name = "Set Uplink"
|
||||
set desc = "Allows admins to set up an uplink on a character. This will be required for a character to use telecrystals."
|
||||
set popup_menu = FALSE
|
||||
|
||||
if(check_rights(R_ADMIN|R_DEBUG))
|
||||
traitors.spawn_uplink(H)
|
||||
H.mind.tcrystals = DEFAULT_TELECRYSTAL_AMOUNT
|
||||
H.mind.accept_tcrystals = 1
|
||||
var/msg = "[key_name(usr)] has given [H.ckey] an uplink."
|
||||
message_admins(msg)
|
||||
else
|
||||
to_chat(usr, "You do not have access to this command.")
|
||||
+205
-78
@@ -1,13 +1,18 @@
|
||||
GLOBAL_LIST_EMPTY(admin_datums)
|
||||
GLOBAL_PROTECT(admin_datums)
|
||||
GLOBAL_LIST_EMPTY(protected_admins)
|
||||
GLOBAL_PROTECT(protected_admins)
|
||||
|
||||
GLOBAL_VAR_INIT(href_token, GenerateToken())
|
||||
GLOBAL_PROTECT(href_token)
|
||||
|
||||
var/list/admin_datums = list()
|
||||
|
||||
/datum/admins
|
||||
var/rank = "Temporary Admin"
|
||||
var/client/owner = null
|
||||
var/rights = 0
|
||||
var/fakekey = null
|
||||
var/list/datum/admin_rank/ranks
|
||||
|
||||
var/target
|
||||
var/name = "nobody's admin datum (no rank)" //Makes for better runtimes
|
||||
var/client/owner = null
|
||||
var/fakekey = null
|
||||
|
||||
var/datum/marked_datum
|
||||
|
||||
@@ -18,49 +23,194 @@ var/list/admin_datums = list()
|
||||
|
||||
var/href_token
|
||||
|
||||
/// Link from the database pointing to the admin's feedback forum
|
||||
var/cached_feedback_link
|
||||
|
||||
/datum/admins/New(initial_rank = "Temporary Admin", initial_rights = 0, ckey)
|
||||
if(!ckey)
|
||||
error("Admin datum created without a ckey argument. Datum has been deleted")
|
||||
qdel(src)
|
||||
var/deadmined
|
||||
|
||||
var/given_profiling = FALSE
|
||||
|
||||
|
||||
/datum/admins/New(list/datum/admin_rank/ranks, ckey, force_active = FALSE, protected)
|
||||
if(IsAdminAdvancedProcCall())
|
||||
alert_to_permissions_elevation_attempt(usr)
|
||||
if (!target) //only del if this is a true creation (and not just a New() proc call), other wise trialmins/coders could abuse this to deadmin other admins
|
||||
QDEL_IN(src, 0)
|
||||
CRASH("Admin proc call creation of admin datum")
|
||||
return
|
||||
if(!ckey)
|
||||
QDEL_IN(src, 0)
|
||||
CRASH("Admin datum created without a ckey")
|
||||
if(!istype(ranks))
|
||||
QDEL_IN(src, 0)
|
||||
CRASH("Admin datum created with invalid ranks: [ranks] ([json_encode(ranks)])")
|
||||
target = ckey
|
||||
name = "[ckey]'s admin datum ([join_admin_ranks(ranks)])"
|
||||
src.ranks = ranks
|
||||
admincaster_signature = "[using_map.company_name] Officer #[rand(0,9)][rand(0,9)][rand(0,9)]"
|
||||
href_token = GenerateToken()
|
||||
rank = initial_rank
|
||||
rights = initial_rights
|
||||
admin_datums[ckey] = src
|
||||
if(rights & R_DEBUG) //grant profile access
|
||||
world.SetConfig("APP/admin", ckey, "role=admin")
|
||||
if(protected)
|
||||
GLOB.protected_admins[target] = src
|
||||
activate()
|
||||
|
||||
/datum/admins/proc/associate(client/C)
|
||||
if(istype(C))
|
||||
owner = C
|
||||
owner.holder = src
|
||||
owner.add_admin_verbs() //TODO
|
||||
owner.init_verbs() //re-initialize the verb list
|
||||
GLOB.admins |= C
|
||||
/datum/admins/Destroy()
|
||||
if(IsAdminAdvancedProcCall())
|
||||
alert_to_permissions_elevation_attempt(usr)
|
||||
return QDEL_HINT_LETMELIVE
|
||||
. = ..()
|
||||
|
||||
/datum/admins/proc/activate()
|
||||
if(IsAdminAdvancedProcCall())
|
||||
alert_to_permissions_elevation_attempt(usr)
|
||||
return
|
||||
GLOB.deadmins -= target
|
||||
GLOB.admin_datums[target] = src
|
||||
deadmined = FALSE
|
||||
//plane_debug = new(src)
|
||||
if (GLOB.directory[target])
|
||||
associate(GLOB.directory[target]) //find the client for a ckey if they are connected and associate them with us
|
||||
|
||||
/datum/admins/proc/deactivate()
|
||||
if(IsAdminAdvancedProcCall())
|
||||
alert_to_permissions_elevation_attempt(usr)
|
||||
return
|
||||
GLOB.deadmins[target] = src
|
||||
GLOB.admin_datums -= target
|
||||
//QDEL_NULL(plane_debug)
|
||||
deadmined = TRUE
|
||||
|
||||
var/client/client = owner || GLOB.directory[target]
|
||||
|
||||
if (!isnull(client))
|
||||
disassociate()
|
||||
add_verb(client, /client/proc/readmin)
|
||||
//client.disable_combo_hud()
|
||||
//client.update_special_keybinds()
|
||||
|
||||
/datum/admins/proc/associate(client/client)
|
||||
if(IsAdminAdvancedProcCall())
|
||||
alert_to_permissions_elevation_attempt(usr)
|
||||
return
|
||||
|
||||
if(!istype(client))
|
||||
return
|
||||
|
||||
if(client?.ckey != target)
|
||||
var/msg = " has attempted to associate with [target]'s admin datum"
|
||||
message_admins("[key_name_admin(client)][msg]")
|
||||
log_admin("[key_name(client)][msg]")
|
||||
return
|
||||
|
||||
if (deadmined)
|
||||
activate()
|
||||
|
||||
owner = client
|
||||
owner.holder = src
|
||||
owner.add_admin_verbs()
|
||||
remove_verb(owner, /client/proc/readmin)
|
||||
owner.init_verbs() //re-initialize the verb list
|
||||
//owner.update_special_keybinds()
|
||||
GLOB.admins |= client
|
||||
|
||||
try_give_profiling()
|
||||
|
||||
/datum/admins/proc/disassociate()
|
||||
if(IsAdminAdvancedProcCall())
|
||||
alert_to_permissions_elevation_attempt(usr)
|
||||
return
|
||||
if(owner)
|
||||
GLOB.admins -= owner
|
||||
owner.remove_admin_verbs()
|
||||
owner.init_verbs() //re-initialize the verb list
|
||||
owner.deadmin_holder = owner.holder
|
||||
// owner.init_verbs() //re-initialize the verb list
|
||||
owner.holder = null
|
||||
owner = null
|
||||
|
||||
/datum/admins/proc/reassociate()
|
||||
if(owner)
|
||||
GLOB.admins += owner
|
||||
owner.holder = src
|
||||
owner.deadmin_holder = null
|
||||
owner.add_admin_verbs()
|
||||
/// Returns the feedback forum thread for the admin holder's owner, as according to DB.
|
||||
/datum/admins/proc/feedback_link()
|
||||
// This intentionally does not follow the 10-second maximum TTL rule,
|
||||
// as this can be reloaded through the Reload-Admins verb.
|
||||
if (cached_feedback_link == NO_FEEDBACK_LINK)
|
||||
return null
|
||||
|
||||
if (!isnull(cached_feedback_link))
|
||||
return cached_feedback_link
|
||||
|
||||
if (!SSdbcore.IsConnected())
|
||||
return FALSE
|
||||
|
||||
var/datum/db_query/feedback_query = SSdbcore.NewQuery("SELECT feedback FROM [format_table_name("admin")] WHERE ckey = '[owner.ckey]'")
|
||||
|
||||
if(!feedback_query.Execute())
|
||||
log_sql("Error retrieving feedback link for [src]")
|
||||
qdel(feedback_query)
|
||||
return FALSE
|
||||
|
||||
if(!feedback_query.NextRow())
|
||||
qdel(feedback_query)
|
||||
return FALSE // no feedback link exists
|
||||
|
||||
cached_feedback_link = feedback_query.item[1] || NO_FEEDBACK_LINK
|
||||
qdel(feedback_query)
|
||||
|
||||
if (cached_feedback_link == NO_FEEDBACK_LINK) // Because we don't want to send fake clickable links.
|
||||
return null
|
||||
|
||||
return cached_feedback_link
|
||||
|
||||
/datum/admins/proc/check_for_rights(rights_required)
|
||||
if(rights_required && !(rights_required & rank_flags()))
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/datum/admins/proc/check_if_greater_rights_than_holder(datum/admins/other)
|
||||
if(!other)
|
||||
return TRUE //they have no rights
|
||||
if(rank_flags() == R_EVERYTHING)
|
||||
return TRUE //we have all the rights
|
||||
if(src == other)
|
||||
return TRUE //you always have more rights than yourself
|
||||
if(rank_flags() != other.rank_flags())
|
||||
if( (rank_flags() & other.rank_flags()) == other.rank_flags() )
|
||||
return TRUE //we have all the rights they have and more
|
||||
return FALSE
|
||||
|
||||
/// Get the rank name of the admin
|
||||
/datum/admins/proc/rank_names()
|
||||
return join_admin_ranks(ranks)
|
||||
|
||||
/// Get the rank flags of the admin
|
||||
/datum/admins/proc/rank_flags()
|
||||
var/combined_flags = NONE
|
||||
|
||||
for (var/datum/admin_rank/rank as anything in ranks)
|
||||
combined_flags |= rank.rights
|
||||
|
||||
return combined_flags
|
||||
|
||||
/// Get the permissions this admin is allowed to edit on other ranks
|
||||
/datum/admins/proc/can_edit_rights_flags()
|
||||
var/combined_flags = NONE
|
||||
|
||||
for (var/datum/admin_rank/rank as anything in ranks)
|
||||
combined_flags |= rank.can_edit_rights
|
||||
|
||||
return combined_flags
|
||||
|
||||
/datum/admins/proc/try_give_profiling()
|
||||
if (CONFIG_GET(flag/forbid_admin_profiling))
|
||||
return
|
||||
|
||||
if (given_profiling)
|
||||
return
|
||||
|
||||
if (!(rank_flags() & R_DEBUG))
|
||||
return
|
||||
|
||||
given_profiling = TRUE
|
||||
world.SetConfig("APP/admin", owner.ckey, "role=admin")
|
||||
|
||||
/datum/admins/vv_edit_var(var_name, var_value)
|
||||
if(var_name == NAMEOF(src, rights) || var_name == NAMEOF(src, owner) || var_name == NAMEOF(src, rank))
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
//TODO: Proccall guard, when all try/catch are removed and WrapAdminProccall is ported.
|
||||
return FALSE //nice try trialmin
|
||||
|
||||
/*
|
||||
checks if usr is an admin with at least ONE of the flags in rights_required. (Note, they don't need all the flags)
|
||||
@@ -69,45 +219,36 @@ if it doesn't return 1 and show_msg=1 it will prints a message explaining why th
|
||||
generally it would be used like so:
|
||||
|
||||
/proc/admin_proc()
|
||||
if(!check_rights(R_ADMIN)) return
|
||||
to_world("you have enough rights!")
|
||||
if(!check_rights(R_ADMIN))
|
||||
return
|
||||
to_chat(world, "you have enough rights!", confidential = TRUE)
|
||||
|
||||
NOTE: It checks usr by default. Supply the "user" argument if you wish to check for a specific mob.
|
||||
NOTE: it checks usr! not src! So if you're checking somebody's rank in a proc which they did not call
|
||||
you will have to do something like if(client.rights & R_ADMIN) yourself.
|
||||
*/
|
||||
/proc/check_rights(rights_required, show_msg=1, var/client/C = usr)
|
||||
if(ismob(C))
|
||||
var/mob/M = C
|
||||
C = M.client
|
||||
if(!C)
|
||||
return FALSE
|
||||
if(!(istype(C, /client))) // If we still didn't find a client, something is wrong.
|
||||
return FALSE
|
||||
if(!C.holder)
|
||||
if(show_msg)
|
||||
to_chat(C, span_filter_adminlog(span_warning("Error: You are not an admin.")))
|
||||
return FALSE
|
||||
|
||||
if(rights_required)
|
||||
if(rights_required & C.holder.rights)
|
||||
/proc/check_rights(rights_required, show_msg=1)
|
||||
if(usr?.client)
|
||||
if (check_rights_for(usr.client, rights_required))
|
||||
return TRUE
|
||||
else
|
||||
if(show_msg)
|
||||
to_chat(C, span_filter_adminlog(span_warning("Error: You do not have sufficient rights to do that. You require one of the following flags:[rights2text(rights_required," ")].")))
|
||||
return FALSE
|
||||
else
|
||||
return TRUE
|
||||
to_chat(usr, "<font color='red'>Error: You do not have sufficient rights to do that. You require one of the following flags:[rights2text(rights_required," ")].</font>", confidential = TRUE)
|
||||
return FALSE
|
||||
|
||||
//probably a bit iffy - will hopefully figure out a better solution
|
||||
/proc/check_if_greater_rights_than(client/other)
|
||||
if(usr && usr.client)
|
||||
if(usr?.client)
|
||||
if(usr.client.holder)
|
||||
if(!other || !other.holder)
|
||||
return 1
|
||||
if(usr.client.holder.rights != other.holder.rights)
|
||||
if( (usr.client.holder.rights & other.holder.rights) == other.holder.rights )
|
||||
return 1 //we have all the rights they have and more
|
||||
to_chat(usr, span_filter_adminlog(span_warning("Error: Cannot proceed. They have more or equal rights to us.")))
|
||||
return 0
|
||||
return TRUE
|
||||
return usr.client.holder.check_if_greater_rights_than_holder(other.holder)
|
||||
return FALSE
|
||||
|
||||
//This proc checks whether subject has at least ONE of the rights specified in rights_required.
|
||||
/proc/check_rights_for(client/subject, rights_required)
|
||||
if(subject?.holder)
|
||||
return subject.holder.check_for_rights(rights_required)
|
||||
return FALSE
|
||||
|
||||
/client/proc/mark_datum(datum/D)
|
||||
if(!holder)
|
||||
@@ -122,20 +263,6 @@ NOTE: It checks usr by default. Supply the "user" argument if you wish to check
|
||||
set name = "Mark Object"
|
||||
mark_datum(D)
|
||||
|
||||
/client/proc/deadmin()
|
||||
if(holder)
|
||||
holder.disassociate()
|
||||
//qdel(holder)
|
||||
return 1
|
||||
|
||||
//This proc checks whether subject has at least ONE of the rights specified in rights_required.
|
||||
/proc/check_rights_for(client/subject, rights_required)
|
||||
if(subject && subject.holder)
|
||||
if(rights_required && !(rights_required & subject.holder.rights))
|
||||
return 0
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/proc/GenerateToken()
|
||||
. = ""
|
||||
for(var/I in 1 to 32)
|
||||
|
||||
@@ -0,0 +1,561 @@
|
||||
/client/proc/edit_admin_permissions()
|
||||
set category = "Admin.Secrets"
|
||||
set name = "Permissions Panel"
|
||||
set desc = "Edit admin permissions"
|
||||
|
||||
if(!check_rights(R_PERMISSIONS))
|
||||
return
|
||||
|
||||
usr.client.holder.edit_admin_permissions()
|
||||
|
||||
/datum/admins/proc/edit_admin_permissions(action, target, operation, page)
|
||||
if(!check_rights(R_PERMISSIONS))
|
||||
return
|
||||
var/datum/asset/asset_cache_datum = get_asset_datum(/datum/asset/group/permissions)
|
||||
asset_cache_datum.send(usr)
|
||||
|
||||
var/list/output = list("<link rel='stylesheet' type='text/css' href='[SSassets.transport.get_asset_url("panels.css")]'><a href='byond://?_src_=holder;[HrefToken()];editrightsbrowser=1'>\[Permissions\]</a>")
|
||||
if(action)
|
||||
output += " | <a href='byond://?_src_=holder;[HrefToken()];editrightsbrowserlog=1;editrightspage=0'>\[Log\]</a> | <a href='byond://?_src_=holder;[HrefToken()];editrightsbrowsermanage=1'>\[Management\]</a><hr style='background:#000000; border:0; height:3px'>"
|
||||
else
|
||||
output += "<br><a href='byond://?_src_=holder;[HrefToken()];editrightsbrowserlog=1;editrightspage=0'>\[Log\]</a><br><a href='byond://?_src_=holder;[HrefToken()];editrightsbrowsermanage=1'>\[Management\]</a>"
|
||||
if(action == 1)
|
||||
var/logcount = 0
|
||||
var/logssperpage = 20
|
||||
var/pagecount = 0
|
||||
page = text2num(page)
|
||||
var/datum/db_query/query_count_admin_logs = SSdbcore.NewQuery(
|
||||
"SELECT COUNT(id) FROM [format_table_name("admin_log")] WHERE (:target IS NULL OR adminckey = :target) AND (:operation IS NULL OR operation = :operation)",
|
||||
list("target" = target, "operation" = operation)
|
||||
)
|
||||
if(!query_count_admin_logs.warn_execute())
|
||||
qdel(query_count_admin_logs)
|
||||
return
|
||||
if(query_count_admin_logs.NextRow())
|
||||
logcount = text2num(query_count_admin_logs.item[1])
|
||||
qdel(query_count_admin_logs)
|
||||
if(logcount > logssperpage)
|
||||
output += "<br><b>Page: </b>"
|
||||
while(logcount > 0)
|
||||
output += "|<a href='byond://?_src_=holder;[HrefToken()];editrightsbrowserlog=1;editrightstarget=[target];editrightsoperation=[operation];editrightspage=[pagecount]'>[pagecount == page ? "<b>\[[pagecount]\]</b>" : "\[[pagecount]\]"]</a>"
|
||||
logcount -= logssperpage
|
||||
pagecount++
|
||||
output += "|"
|
||||
var/datum/db_query/query_search_admin_logs = SSdbcore.NewQuery({"
|
||||
SELECT
|
||||
datetime,
|
||||
round_id,
|
||||
IFNULL((SELECT ckey FROM [format_table_name("erro_player")] WHERE ckey = adminckey), adminckey),
|
||||
operation,
|
||||
IF(ckey IS NULL, target, ckey),
|
||||
log
|
||||
FROM [format_table_name("admin_log")]
|
||||
LEFT JOIN [format_table_name("erro_player")] ON target = ckey
|
||||
WHERE (:target IS NULL OR ckey = :target) AND (:operation IS NULL OR operation = :operation)
|
||||
ORDER BY datetime DESC
|
||||
LIMIT :skip, :take
|
||||
"}, list("target" = target, "operation" = operation, "skip" = logssperpage * page, "take" = logssperpage))
|
||||
if(!query_search_admin_logs.warn_execute())
|
||||
qdel(query_search_admin_logs)
|
||||
return
|
||||
while(query_search_admin_logs.NextRow())
|
||||
var/datetime = query_search_admin_logs.item[1]
|
||||
var/round_id = query_search_admin_logs.item[2]
|
||||
var/admin_key = query_search_admin_logs.item[3]
|
||||
operation = query_search_admin_logs.item[4]
|
||||
target = query_search_admin_logs.item[5]
|
||||
var/log = query_search_admin_logs.item[6]
|
||||
output += "<p style='margin:0px'><b>[datetime] | Round ID [round_id] | Admin [admin_key] | Operation [operation] on [target]</b><br>[log]</p><hr style='background:#000000; border:0; height:3px'>"
|
||||
qdel(query_search_admin_logs)
|
||||
if(action == 2)
|
||||
output += "<h3>Admin ckeys with invalid ranks</h3>"
|
||||
var/datum/db_query/query_check_admin_errors = SSdbcore.NewQuery("SELECT IFNULL((SELECT ckey FROM [format_table_name("erro_player")] WHERE [format_table_name("erro_player")].ckey = [format_table_name("admin")].ckey), ckey), [format_table_name("admin")].`rank` FROM [format_table_name("admin")] LEFT JOIN [format_table_name("admin_ranks")] ON [format_table_name("admin_ranks")].`rank` = [format_table_name("admin")].`rank` WHERE [format_table_name("admin_ranks")].`rank` IS NULL")
|
||||
if(!query_check_admin_errors.warn_execute())
|
||||
qdel(query_check_admin_errors)
|
||||
return
|
||||
while(query_check_admin_errors.NextRow())
|
||||
var/admin_key = query_check_admin_errors.item[1]
|
||||
var/admin_rank = query_check_admin_errors.item[2]
|
||||
output += "[admin_key] has non-existent rank [admin_rank] | <a href='byond://?_src_=holder;[HrefToken()];editrightsbrowsermanage=1;editrightschange=[admin_key]'>\[Change Rank\]</a> | <a href='byond://?_src_=holder;[HrefToken()];editrightsbrowsermanage=1;editrightsremove=[admin_key]'>\[Remove\]</a>"
|
||||
output += "<hr style='background:#000000; border:0; height:1px'>"
|
||||
qdel(query_check_admin_errors)
|
||||
output += "<h3>Unused ranks</h3>"
|
||||
var/datum/db_query/query_check_unused_rank = SSdbcore.NewQuery("SELECT [format_table_name("admin_ranks")].`rank`, flags, exclude_flags, can_edit_flags FROM [format_table_name("admin_ranks")] LEFT JOIN [format_table_name("admin")] ON [format_table_name("admin")].`rank` = [format_table_name("admin_ranks")].`rank` WHERE [format_table_name("admin")].`rank` IS NULL")
|
||||
if(!query_check_unused_rank.warn_execute())
|
||||
qdel(query_check_unused_rank)
|
||||
return
|
||||
while(query_check_unused_rank.NextRow())
|
||||
var/admin_rank = query_check_unused_rank.item[1]
|
||||
output += {"Rank [admin_rank] is not held by any admin | <a href='byond://?_src_=holder;[HrefToken()];editrightsbrowsermanage=1;editrightsremoverank=[admin_rank]'>\[Remove\]</a>
|
||||
<br>Permissions: [rights2text(text2num(query_check_unused_rank.item[2])," ")]
|
||||
<br>Denied: [rights2text(text2num(query_check_unused_rank.item[3])," ", "-")]
|
||||
<br>Allowed to edit: [rights2text(text2num(query_check_unused_rank.item[4])," ", "*")]
|
||||
<hr style='background:#000000; border:0; height:1px'>"}
|
||||
qdel(query_check_unused_rank)
|
||||
else if(!action)
|
||||
output += {"
|
||||
<head>
|
||||
<meta http-equiv='Content-Type' content='text/html; charset=UTF-8'>
|
||||
<title>Permissions Panel</title>
|
||||
<script type='text/javascript' src='[SSassets.transport.get_asset_url("search.js")]'></script>
|
||||
</head>
|
||||
<body onload='selectTextField();updateSearch();'>
|
||||
<div id='main'><table id='searchable' cellspacing='0'>
|
||||
<tr class='title'>
|
||||
<th style='width:150px;'>CKEY <a class='small' href='byond://?src=[REF(src)];[HrefToken()];editrights=add'>\[+\]</a></th>
|
||||
<th style='width:125px;'>RANK</th>
|
||||
<th>PERMISSIONS</th>
|
||||
</tr>
|
||||
"}
|
||||
for(var/adm_ckey in GLOB.admin_datums+GLOB.deadmins)
|
||||
var/datum/admins/D = GLOB.admin_datums[adm_ckey]
|
||||
if(!D)
|
||||
D = GLOB.deadmins[adm_ckey]
|
||||
if (!D)
|
||||
continue
|
||||
var/deadminlink = ""
|
||||
if(D.owner)
|
||||
adm_ckey = D.owner.key
|
||||
if (D.deadmined)
|
||||
deadminlink = " <a class='small' href='byond://?src=[REF(src)];[HrefToken()];editrights=activate;key=[adm_ckey]'>\[RA\]</a>"
|
||||
else
|
||||
deadminlink = " <a class='small' href='byond://?src=[REF(src)];[HrefToken()];editrights=deactivate;key=[adm_ckey]'>\[DA\]</a>"
|
||||
|
||||
var/verify_link = ""
|
||||
//if (D.blocked_by_2fa)
|
||||
// verify_link += " | <a class='small' href='byond://?src=[REF(src)];[HrefToken()];editrights=verify;key=[adm_ckey]'>\[2FA VERIFY\]</a>"
|
||||
|
||||
output += "<tr>"
|
||||
output += "<td style='text-align:center;'>[adm_ckey]<br>[deadminlink]<a class='small' href='byond://?src=[REF(src)];[HrefToken()];editrights=remove;key=[adm_ckey]'>\[-\]</a><a class='small' href='byond://?src=[REF(src)];[HrefToken()];editrights=sync;key=[adm_ckey]'>\[SYNC TGDB\]</a>[verify_link]</td>"
|
||||
output += "<td><a href='byond://?src=[REF(src)];[HrefToken()];editrights=rank;key=[adm_ckey]'>[D.rank_names()]</a></td>"
|
||||
output += "<td><a class='small' href='byond://?src=[REF(src)];[HrefToken()];editrights=permissions;key=[adm_ckey]'>[rights2text(D.rank_flags(), " ")]</a></td>"
|
||||
output += "</tr>"
|
||||
output += "</table></div><div id='top'><b>Search:</b> <input type='text' id='filter' value='' style='width:70%;' onkeyup='updateSearch();'></div></body>"
|
||||
if(QDELETED(usr))
|
||||
return
|
||||
usr << browse("<!DOCTYPE html><html>[jointext(output, "")]</html>","window=editrights;size=1000x650")
|
||||
|
||||
/datum/admins/proc/edit_rights_topic(list/href_list)
|
||||
if(!check_rights(R_PERMISSIONS))
|
||||
message_admins("[key_name_admin(usr)] attempted to edit admin permissions without sufficient rights.")
|
||||
log_admin("[key_name(usr)] attempted to edit admin permissions without sufficient rights.")
|
||||
return
|
||||
if(IsAdminAdvancedProcCall())
|
||||
to_chat(usr, "<span class='admin prefix'>Admin Edit blocked: Advanced ProcCall detected.</span>", confidential = TRUE)
|
||||
return
|
||||
var/datum/asset/permissions_assets = get_asset_datum(/datum/asset/simple/namespaced/common)
|
||||
permissions_assets.send(usr.client)
|
||||
var/admin_key = href_list["key"]
|
||||
var/admin_ckey = ckey(admin_key)
|
||||
|
||||
var/task = href_list["editrights"]
|
||||
var/datum/admins/target_admin_datum = GLOB.admin_datums[admin_ckey]
|
||||
if(!target_admin_datum)
|
||||
target_admin_datum = GLOB.deadmins[admin_ckey]
|
||||
if (!target_admin_datum && task != "add")
|
||||
return
|
||||
var/use_db
|
||||
var/skip
|
||||
var/legacy_only
|
||||
if(task == "activate" || task == "deactivate" || task == "sync" || task == "verify")
|
||||
skip = TRUE
|
||||
if(!CONFIG_GET(flag/admin_legacy_system) && CONFIG_GET(flag/protect_legacy_admins) && task == "rank")
|
||||
if(admin_ckey in GLOB.protected_admins)
|
||||
to_chat(usr, "<span class='admin prefix'>Editing the rank of this admin is blocked by server configuration.</span>", confidential = TRUE)
|
||||
return
|
||||
if(!CONFIG_GET(flag/admin_legacy_system) && CONFIG_GET(flag/protect_legacy_ranks) && task == "permissions")
|
||||
if((target_admin_datum.ranks & GLOB.protected_ranks).len > 0)
|
||||
to_chat(usr, "<span class='admin prefix'>Editing the flags of this rank is blocked by server configuration.</span>", confidential = TRUE)
|
||||
return
|
||||
if(CONFIG_GET(flag/load_legacy_ranks_only) && (task == "add" || task == "rank" || task == "permissions"))
|
||||
to_chat(usr, "<span class='admin prefix'>Database rank loading is disabled, only temporary changes can be made to a rank's permissions and permanently creating a new rank is blocked.</span>", confidential = TRUE)
|
||||
legacy_only = TRUE
|
||||
//if(check_rights(R_DBRANKS, FALSE))
|
||||
if(!skip)
|
||||
if(!SSdbcore.Connect())
|
||||
to_chat(usr, span_danger("Unable to connect to database, changes are temporary only."), confidential = TRUE)
|
||||
use_db = FALSE
|
||||
else
|
||||
use_db = tgui_alert(usr,"Permanent changes are saved to the database for future rounds, temporary changes will affect only the current round", "Permanent or Temporary?", list("Permanent", "Temporary", "Cancel"))
|
||||
if(use_db == "Cancel")
|
||||
return
|
||||
if(use_db == "Permanent")
|
||||
use_db = TRUE
|
||||
else
|
||||
use_db = FALSE
|
||||
if(QDELETED(usr))
|
||||
return
|
||||
|
||||
if(target_admin_datum && (task != "sync" && task != "verify") && !check_if_greater_rights_than_holder(target_admin_datum))
|
||||
message_admins("[key_name_admin(usr)] attempted to change the rank of [admin_key] without sufficient rights.")
|
||||
log_admin("[key_name(usr)] attempted to change the rank of [admin_key] without sufficient rights.")
|
||||
return
|
||||
switch(task)
|
||||
if("add")
|
||||
admin_ckey = add_admin(admin_ckey, admin_key, use_db)
|
||||
if(!admin_ckey)
|
||||
return
|
||||
|
||||
if(!admin_key) // Prevents failures in logging admin rank changes.
|
||||
admin_key = admin_ckey
|
||||
|
||||
change_admin_rank(admin_ckey, admin_key, use_db, null, legacy_only)
|
||||
if("remove")
|
||||
remove_admin(admin_ckey, admin_key, use_db, target_admin_datum)
|
||||
if("rank")
|
||||
change_admin_rank(admin_ckey, admin_key, use_db, target_admin_datum, legacy_only)
|
||||
if("permissions")
|
||||
change_admin_flags(admin_ckey, admin_key, target_admin_datum)
|
||||
if("activate")
|
||||
force_readmin(admin_key, target_admin_datum)
|
||||
if("deactivate")
|
||||
force_deadmin(admin_key, target_admin_datum)
|
||||
if("sync")
|
||||
sync_lastadminrank(admin_ckey, admin_key, target_admin_datum)
|
||||
/*
|
||||
if("verify")
|
||||
var/msg = "has authenticated [admin_ckey]"
|
||||
message_admins("[key_name_admin(usr)] [msg]")
|
||||
log_admin("[key_name(usr)] [msg]")
|
||||
|
||||
target_admin_datum.bypass_2fa = TRUE
|
||||
target_admin_datum.associate(GLOB.directory[admin_ckey])
|
||||
*/
|
||||
edit_admin_permissions()
|
||||
|
||||
/datum/admins/proc/add_admin(admin_ckey, admin_key, use_db)
|
||||
if(admin_ckey)
|
||||
. = admin_ckey
|
||||
else
|
||||
admin_key = input("New admin's key","Admin key") as text|null
|
||||
. = ckey(admin_key)
|
||||
if(!.)
|
||||
return FALSE
|
||||
if(!admin_ckey && (. in (GLOB.admin_datums+GLOB.deadmins)))
|
||||
to_chat(usr, span_danger("[admin_key] is already an admin."), confidential = TRUE)
|
||||
return FALSE
|
||||
if(use_db)
|
||||
//if an admin exists without a datum they won't be caught by the above
|
||||
var/datum/db_query/query_admin_in_db = SSdbcore.NewQuery(
|
||||
"SELECT 1 FROM [format_table_name("admin")] WHERE ckey = :ckey",
|
||||
list("ckey" = .)
|
||||
)
|
||||
if(!query_admin_in_db.warn_execute())
|
||||
qdel(query_admin_in_db)
|
||||
return FALSE
|
||||
if(query_admin_in_db.NextRow())
|
||||
qdel(query_admin_in_db)
|
||||
to_chat(usr, span_danger("[admin_key] already listed in admin database. Check the Management tab if they don't appear in the list of admins."), confidential = TRUE)
|
||||
return FALSE
|
||||
qdel(query_admin_in_db)
|
||||
var/datum/db_query/query_add_admin = SSdbcore.NewQuery(
|
||||
"INSERT INTO [format_table_name("admin")] (ckey, `rank`) VALUES (:ckey, 'NEW ADMIN')",
|
||||
list("ckey" = .)
|
||||
)
|
||||
if(!query_add_admin.warn_execute())
|
||||
qdel(query_add_admin)
|
||||
return FALSE
|
||||
qdel(query_add_admin)
|
||||
var/datum/db_query/query_add_admin_log = SSdbcore.NewQuery({"
|
||||
INSERT INTO [format_table_name("admin_log")] (datetime, round_id, adminckey, adminip, operation, target, log)
|
||||
VALUES (NOW(), :round_id, :adminckey, INET_ATON(:adminip), 'add admin', :target, CONCAT('New admin added: ', :target))
|
||||
"}, list("round_id" = "[GLOB.round_id]", "adminckey" = usr.ckey, "adminip" = usr.client.address, "target" = .))
|
||||
if(!query_add_admin_log.warn_execute())
|
||||
qdel(query_add_admin_log)
|
||||
return FALSE
|
||||
qdel(query_add_admin_log)
|
||||
|
||||
/datum/admins/proc/remove_admin(admin_ckey, admin_key, use_db, datum/admins/D)
|
||||
if(tgui_alert(usr,"Are you sure you want to remove [admin_ckey]?","Confirm Removal",list("Do it","Cancel")) == "Do it")
|
||||
GLOB.admin_datums -= admin_ckey
|
||||
GLOB.deadmins -= admin_ckey
|
||||
if(D)
|
||||
D.disassociate()
|
||||
var/m1 = "[key_name_admin(usr)] removed [admin_key] from the admins list [use_db ? "permanently" : "temporarily"]"
|
||||
var/m2 = "[key_name(usr)] removed [admin_key] from the admins list [use_db ? "permanently" : "temporarily"]"
|
||||
if(use_db)
|
||||
var/datum/db_query/query_add_rank = SSdbcore.NewQuery(
|
||||
"DELETE FROM [format_table_name("admin")] WHERE ckey = :ckey",
|
||||
list("ckey" = admin_ckey)
|
||||
)
|
||||
if(!query_add_rank.warn_execute())
|
||||
qdel(query_add_rank)
|
||||
return
|
||||
qdel(query_add_rank)
|
||||
var/datum/db_query/query_add_rank_log = SSdbcore.NewQuery({"
|
||||
INSERT INTO [format_table_name("admin_log")] (datetime, round_id, adminckey, adminip, operation, target, log)
|
||||
VALUES (NOW(), :round_id, :adminckey, INET_ATON(:adminip), 'remove admin', :admin_ckey, CONCAT('Admin removed: ', :admin_ckey))
|
||||
"}, list("round_id" = "[GLOB.round_id]", "adminckey" = usr.ckey, "adminip" = usr.client.address, "admin_ckey" = admin_ckey))
|
||||
if(!query_add_rank_log.warn_execute())
|
||||
qdel(query_add_rank_log)
|
||||
return
|
||||
qdel(query_add_rank_log)
|
||||
sync_lastadminrank(admin_ckey, admin_key)
|
||||
message_admins(m1)
|
||||
log_admin(m2)
|
||||
|
||||
/datum/admins/proc/force_readmin(admin_key, datum/admins/D)
|
||||
if(!D || !D.deadmined)
|
||||
return
|
||||
D.activate()
|
||||
message_admins("[key_name_admin(usr)] forcefully readmined [admin_key]")
|
||||
log_admin("[key_name(usr)] forcefully readmined [admin_key]")
|
||||
|
||||
/datum/admins/proc/force_deadmin(admin_key, datum/admins/D)
|
||||
if(!D || D.deadmined)
|
||||
return
|
||||
message_admins("[key_name_admin(usr)] forcefully deadmined [admin_key]")
|
||||
log_admin("[key_name(usr)] forcefully deadmined [admin_key]")
|
||||
D.deactivate() //after logs so the deadmined admin can see the message.
|
||||
|
||||
#define RANK_DONE ":) I'm Done"
|
||||
|
||||
/datum/admins/proc/change_admin_rank(admin_ckey, admin_key, use_db, datum/admins/D, legacy_only)
|
||||
if(!check_rights(R_PERMISSIONS))
|
||||
return
|
||||
|
||||
var/list/rank_names = list()
|
||||
if(!use_db || (use_db && !legacy_only))
|
||||
rank_names += "*New Rank*"
|
||||
for(var/datum/admin_rank/admin_rank as anything in GLOB.admin_ranks)
|
||||
if((admin_rank.rights & usr.client.holder.can_edit_rights_flags()) == admin_rank.rights)
|
||||
rank_names[admin_rank.name] = admin_rank
|
||||
|
||||
var/list/new_rank_names = list()
|
||||
var/list/custom_ranks = list()
|
||||
|
||||
while (TRUE)
|
||||
var/list/display_rank_names = list(RANK_DONE)
|
||||
|
||||
if (new_rank_names.len > 0)
|
||||
display_rank_names += "** SELECTED **"
|
||||
for (var/rank_name in new_rank_names)
|
||||
display_rank_names += rank_name
|
||||
display_rank_names += "---------"
|
||||
|
||||
for (var/rank_name in rank_names)
|
||||
if (!(rank_name in display_rank_names))
|
||||
display_rank_names += rank_name
|
||||
|
||||
var/next_rank = input("Please select a rank, or select [RANK_DONE] if you are finished.") as null|anything in display_rank_names
|
||||
|
||||
if (isnull(next_rank))
|
||||
return
|
||||
|
||||
if (next_rank == RANK_DONE)
|
||||
break
|
||||
|
||||
// They clicked "** SELECTED **" or something silly.
|
||||
if (!(next_rank in rank_names))
|
||||
continue
|
||||
|
||||
if (next_rank in new_rank_names)
|
||||
new_rank_names -= next_rank
|
||||
continue
|
||||
|
||||
if (next_rank == "*New Rank*")
|
||||
var/new_rank_name = input("Please input a new rank", "New custom rank") as text|null
|
||||
if (!new_rank_name)
|
||||
return
|
||||
|
||||
var/datum/admin_rank/custom_rank = rank_names[new_rank_name]
|
||||
if (isnull(custom_rank))
|
||||
if (D)
|
||||
custom_rank = new(new_rank_name, D.rank_flags())
|
||||
else
|
||||
custom_rank = new(new_rank_name)
|
||||
|
||||
GLOB.admin_ranks += custom_rank
|
||||
custom_ranks += custom_rank
|
||||
new_rank_names += new_rank_name
|
||||
|
||||
new_rank_names += next_rank
|
||||
|
||||
var/list/new_ranks = list()
|
||||
for (var/datum/admin_rank/admin_rank as anything in GLOB.admin_ranks)
|
||||
if (admin_rank.name in new_rank_names)
|
||||
new_ranks += admin_rank
|
||||
new_rank_names -= admin_rank.name
|
||||
|
||||
if (new_rank_names.len == 0)
|
||||
break
|
||||
|
||||
var/joined_rank = join_admin_ranks(new_ranks)
|
||||
var/m1 = "[key_name_admin(usr)] edited the admin rank of [admin_key] to [joined_rank] [use_db ? "permanently" : "temporarily"]"
|
||||
var/m2 = "[key_name(usr)] edited the admin rank of [admin_key] to [joined_rank] [use_db ? "permanently" : "temporarily"]"
|
||||
if(use_db)
|
||||
//if a player was tempminned before having a permanent change made to their rank they won't yet be in the db
|
||||
var/old_rank
|
||||
var/datum/db_query/query_admin_in_db = SSdbcore.NewQuery(
|
||||
"SELECT `rank` FROM [format_table_name("admin")] WHERE ckey = :admin_ckey",
|
||||
list("admin_ckey" = admin_ckey)
|
||||
)
|
||||
if(!query_admin_in_db.warn_execute())
|
||||
qdel(query_admin_in_db)
|
||||
return
|
||||
if(!query_admin_in_db.NextRow())
|
||||
add_admin(admin_ckey, admin_key, TRUE)
|
||||
old_rank = "NEW ADMIN"
|
||||
else
|
||||
old_rank = query_admin_in_db.item[1]
|
||||
qdel(query_admin_in_db)
|
||||
|
||||
for (var/datum/admin_rank/custom_rank in custom_ranks)
|
||||
//similarly if a temp rank is created it won't be in the db if someone is permanently changed to it
|
||||
var/datum/db_query/query_rank_in_db = SSdbcore.NewQuery(
|
||||
"SELECT 1 FROM [format_table_name("admin_ranks")] WHERE `rank` = :new_rank",
|
||||
list("new_rank" = custom_rank.name)
|
||||
)
|
||||
if(!query_rank_in_db.warn_execute())
|
||||
qdel(query_rank_in_db)
|
||||
return
|
||||
if(!query_rank_in_db.NextRow())
|
||||
QDEL_NULL(query_rank_in_db)
|
||||
var/datum/db_query/query_add_rank = SSdbcore.NewQuery({"
|
||||
INSERT INTO [format_table_name("admin_ranks")] (`rank`, flags, exclude_flags, can_edit_flags)
|
||||
VALUES (:new_rank, '0', '0', '0')
|
||||
"}, list("new_rank" = custom_rank.name))
|
||||
if(!query_add_rank.warn_execute())
|
||||
qdel(query_add_rank)
|
||||
return
|
||||
qdel(query_add_rank)
|
||||
var/datum/db_query/query_add_rank_log = SSdbcore.NewQuery({"
|
||||
INSERT INTO [format_table_name("admin_log")] (datetime, round_id, adminckey, adminip, operation, target, log)
|
||||
VALUES (NOW(), :round_id, :adminckey, INET_ATON(:adminip), 'add rank', :new_rank, CONCAT('New rank added: ', :new_rank))
|
||||
"}, list("round_id" = "[GLOB.round_id]", "adminckey" = usr.ckey, "adminip" = usr.client.address, "new_rank" = custom_rank.name))
|
||||
if(!query_add_rank_log.warn_execute())
|
||||
qdel(query_add_rank_log)
|
||||
return
|
||||
qdel(query_add_rank_log)
|
||||
qdel(query_rank_in_db)
|
||||
var/datum/db_query/query_change_rank = SSdbcore.NewQuery(
|
||||
"UPDATE [format_table_name("admin")] SET `rank` = :new_rank WHERE ckey = :admin_ckey",
|
||||
list("new_rank" = joined_rank, "admin_ckey" = admin_ckey)
|
||||
)
|
||||
if(!query_change_rank.warn_execute())
|
||||
qdel(query_change_rank)
|
||||
return
|
||||
qdel(query_change_rank)
|
||||
var/datum/db_query/query_change_rank_log = SSdbcore.NewQuery({"
|
||||
INSERT INTO [format_table_name("admin_log")] (datetime, round_id, adminckey, adminip, operation, target, log)
|
||||
VALUES (NOW(), :round_id, :adminckey, INET_ATON(:adminip), 'change admin rank', :target, CONCAT('Rank of ', :target, ' changed from ', :old_rank, ' to ', :new_rank))
|
||||
"}, list("round_id" = "[GLOB.round_id]", "adminckey" = usr.ckey, "adminip" = usr.client.address, "target" = admin_ckey, "old_rank" = old_rank, "new_rank" = joined_rank))
|
||||
if(!query_change_rank_log.warn_execute())
|
||||
qdel(query_change_rank_log)
|
||||
return
|
||||
qdel(query_change_rank_log)
|
||||
if(D) //they were previously an admin
|
||||
D.disassociate() //existing admin needs to be disassociated
|
||||
D.ranks = new_ranks //set the admin_rank as our rank
|
||||
//D.bypass_2fa = TRUE // Another admin has cleared us
|
||||
var/client/C = GLOB.directory[admin_ckey]
|
||||
D.associate(C)
|
||||
else
|
||||
D = new(new_ranks, admin_ckey) //new admin
|
||||
//D.bypass_2fa = TRUE // Another admin has cleared us
|
||||
D.activate()
|
||||
message_admins(m1)
|
||||
log_admin(m2)
|
||||
|
||||
#undef RANK_DONE
|
||||
|
||||
/datum/admins/proc/change_admin_flags(admin_ckey, admin_key, datum/admins/admin_holder)
|
||||
var/new_flags = input_bitfield(
|
||||
usr,
|
||||
"Admin rights<br>This will affect only the current admin [admin_key]",
|
||||
"admin_flags",
|
||||
admin_holder.rank_flags(),
|
||||
350,
|
||||
590,
|
||||
allowed_edit_list = usr.client.holder.can_edit_rights_flags(),
|
||||
)
|
||||
|
||||
admin_holder.disassociate()
|
||||
|
||||
if (findtext(admin_holder.rank_names(), "([admin_ckey])"))
|
||||
var/datum/admin_rank/rank = admin_holder.ranks[1]
|
||||
rank.rights = new_flags
|
||||
rank.include_rights = new_flags
|
||||
rank.exclude_rights = NONE
|
||||
rank.can_edit_rights = rank.can_edit_rights
|
||||
else
|
||||
// Not a modified subrank, need to duplicate the admin_rank datum to prevent modifying others too.
|
||||
var/datum/admin_rank/new_admin_rank = new(
|
||||
/* init_name = */ "[admin_holder.rank_names()]([admin_ckey])",
|
||||
/* init_rights = */ new_flags,
|
||||
|
||||
// rank_flags() includes the exclude rights, so we no longer need to handle them separately.
|
||||
/* init_exclude_rights = */ NONE,
|
||||
|
||||
/* init_edit_rights = */ admin_holder.can_edit_rights_flags(),
|
||||
)
|
||||
|
||||
admin_holder.ranks = list(new_admin_rank)
|
||||
|
||||
var/log = "[key_name(usr)] has updated the admin rights of [admin_ckey] into [rights2text(new_flags)]"
|
||||
message_admins(log)
|
||||
log_admin(log)
|
||||
|
||||
var/client/admin_client = GLOB.directory[admin_ckey]
|
||||
admin_holder.associate(admin_client)
|
||||
|
||||
/datum/admins/proc/remove_rank(admin_rank)
|
||||
if(!admin_rank)
|
||||
return
|
||||
for(var/datum/admin_rank/R in GLOB.admin_ranks)
|
||||
if(R.name == admin_rank && (!(R.rights & usr.client.holder.can_edit_rights_flags()) == R.rights))
|
||||
to_chat(usr, "<span class='admin prefix'>You don't have edit rights to all the rights this rank has, rank deletion not permitted.</span>", confidential = TRUE)
|
||||
return
|
||||
if(!CONFIG_GET(flag/admin_legacy_system) && CONFIG_GET(flag/protect_legacy_ranks) && (admin_rank in GLOB.protected_ranks))
|
||||
to_chat(usr, "<span class='admin prefix'>Deletion of protected ranks is not permitted, it must be removed from admin_ranks.txt.</span>", confidential = TRUE)
|
||||
return
|
||||
if(CONFIG_GET(flag/load_legacy_ranks_only))
|
||||
to_chat(usr, "<span class='admin prefix'>Rank deletion not permitted while database rank loading is disabled.</span>", confidential = TRUE)
|
||||
return
|
||||
var/datum/db_query/query_admins_with_rank = SSdbcore.NewQuery(
|
||||
"SELECT 1 FROM [format_table_name("admin")] WHERE `rank` = :admin_rank",
|
||||
list("admin_rank" = admin_rank)
|
||||
)
|
||||
if(!query_admins_with_rank.warn_execute())
|
||||
qdel(query_admins_with_rank)
|
||||
return
|
||||
if(query_admins_with_rank.NextRow())
|
||||
qdel(query_admins_with_rank)
|
||||
to_chat(usr, span_danger("Error: Rank deletion attempted while rank still used; Tell a coder, this shouldn't happen."), confidential = TRUE)
|
||||
return
|
||||
qdel(query_admins_with_rank)
|
||||
if(tgui_alert(usr,"Are you sure you want to remove [admin_rank]?","Confirm Removal",list("Do it","Cancel")) == "Do it")
|
||||
var/m1 = "[key_name_admin(usr)] removed rank [admin_rank] permanently"
|
||||
var/m2 = "[key_name(usr)] removed rank [admin_rank] permanently"
|
||||
var/datum/db_query/query_add_rank = SSdbcore.NewQuery(
|
||||
"DELETE FROM [format_table_name("admin_ranks")] WHERE `rank` = :admin_rank",
|
||||
list("admin_rank" = admin_rank)
|
||||
)
|
||||
if(!query_add_rank.warn_execute())
|
||||
qdel(query_add_rank)
|
||||
return
|
||||
qdel(query_add_rank)
|
||||
var/datum/db_query/query_add_rank_log = SSdbcore.NewQuery({"
|
||||
INSERT INTO [format_table_name("admin_log")] (datetime, round_id, adminckey, adminip, operation, target, log)
|
||||
VALUES (NOW(), :round_id, :adminckey, INET_ATON(:adminip), 'remove rank', :admin_rank, CONCAT('Rank removed: ', :admin_rank))
|
||||
"}, list("round_id" = "[GLOB.round_id]", "adminckey" = usr.ckey, "adminip" = usr.client.address, "admin_rank" = admin_rank))
|
||||
if(!query_add_rank_log.warn_execute())
|
||||
qdel(query_add_rank_log)
|
||||
return
|
||||
qdel(query_add_rank_log)
|
||||
message_admins(m1)
|
||||
log_admin(m2)
|
||||
|
||||
/datum/admins/proc/sync_lastadminrank(admin_ckey, admin_key, datum/admins/D)
|
||||
var/sqlrank = "Player"
|
||||
if (D)
|
||||
sqlrank = D.rank_names()
|
||||
var/datum/db_query/query_sync_lastadminrank = SSdbcore.NewQuery(
|
||||
"UPDATE [format_table_name("erro_player")] SET lastadminrank = :rank WHERE ckey = :ckey",
|
||||
list("rank" = sqlrank, "ckey" = admin_ckey)
|
||||
)
|
||||
if(!query_sync_lastadminrank.warn_execute())
|
||||
qdel(query_sync_lastadminrank)
|
||||
return
|
||||
qdel(query_sync_lastadminrank)
|
||||
to_chat(usr, span_admin("Sync of [admin_key] successful."), confidential = TRUE)
|
||||
@@ -1,158 +0,0 @@
|
||||
/client/proc/edit_admin_permissions()
|
||||
set category = "Admin.Secrets"
|
||||
set name = "Permissions Panel"
|
||||
set desc = "Edit admin permissions"
|
||||
if(!check_rights(R_PERMISSIONS)) return
|
||||
usr.client.holder.edit_admin_permissions()
|
||||
|
||||
/datum/admins/proc/edit_admin_permissions()
|
||||
if(!check_rights(R_PERMISSIONS)) return
|
||||
|
||||
var/output = {"<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Permissions Panel</title>
|
||||
<script type='text/javascript' src='search.js'></script>
|
||||
<link rel='stylesheet' type='text/css' href='panels.css'>
|
||||
</head>
|
||||
<body onload='selectTextField();updateSearch();'>
|
||||
<div id='main'><table id='searchable' cellspacing='0'>
|
||||
<tr class='title'>
|
||||
<th style='width:125px;text-align:right;'>CKEY <a class='small' href='byond://?src=\ref[src];[HrefToken()];editrights=add'>\[+\]</a></th>
|
||||
<th style='width:125px;'>RANK</th><th style='width:100%;'>PERMISSIONS</th>
|
||||
</tr>
|
||||
"}
|
||||
|
||||
for(var/adm_ckey in admin_datums)
|
||||
var/datum/admins/D = admin_datums[adm_ckey]
|
||||
if(!D) continue
|
||||
var/rank = D.rank ? D.rank : "*none*"
|
||||
var/rights = rights2text(D.rights," ")
|
||||
if(!rights) rights = "*none*"
|
||||
|
||||
output += "<tr>"
|
||||
output += "<td style='text-align:right;'>[adm_ckey] <a class='small' href='byond://?src=\ref[src];[HrefToken()];editrights=remove;ckey=[adm_ckey]'>\[-\]</a></td>"
|
||||
output += "<td><a href='byond://?src=\ref[src];[HrefToken()];editrights=rank;ckey=[adm_ckey]'>[rank]</a></td>"
|
||||
output += "<td><a class='small' href='byond://?src=\ref[src];[HrefToken()];editrights=permissions;ckey=[adm_ckey]'>[rights]</a></td>"
|
||||
output += "</tr>"
|
||||
|
||||
output += {"
|
||||
</table></div>
|
||||
<div id='top'><b>Search:</b> <input type='text' id='filter' value='' style='width:70%;' onkeyup='updateSearch();'></div>
|
||||
</body>
|
||||
</html>"}
|
||||
|
||||
usr << browse(output,"window=editrights;size=600x500")
|
||||
|
||||
/datum/admins/proc/log_admin_rank_modification(var/adm_ckey, var/new_rank)
|
||||
if(CONFIG_GET(flag/admin_legacy_system)) return
|
||||
|
||||
if(!usr.client)
|
||||
return
|
||||
|
||||
if(!usr.client.holder || !(usr.client.holder.rights & R_PERMISSIONS))
|
||||
to_chat(usr, span_filter_adminlog("[span_red("You do not have permission to do this!")]"))
|
||||
return
|
||||
|
||||
establish_db_connection()
|
||||
|
||||
if(!SSdbcore.IsConnected())
|
||||
to_chat(usr, span_filter_adminlog("[span_red("Failed to establish database connection")]"))
|
||||
return
|
||||
|
||||
if(!adm_ckey || !new_rank)
|
||||
return
|
||||
|
||||
adm_ckey = ckey(adm_ckey)
|
||||
|
||||
if(!adm_ckey)
|
||||
return
|
||||
|
||||
if(!istext(adm_ckey) || !istext(new_rank))
|
||||
return
|
||||
|
||||
var/datum/db_query/select_query = SSdbcore.NewQuery("SELECT id FROM erro_admin WHERE ckey = '[adm_ckey]'")
|
||||
select_query.Execute()
|
||||
|
||||
var/new_admin = 1
|
||||
var/admin_id
|
||||
while(select_query.NextRow())
|
||||
new_admin = 0
|
||||
admin_id = text2num(select_query.item[1])
|
||||
|
||||
qdel(select_query)
|
||||
if(new_admin)
|
||||
var/datum/db_query/insert_query = SSdbcore.NewQuery("INSERT INTO `erro_admin` (`id`, `ckey`, `rank`, `level`, `flags`) VALUES (null, '[adm_ckey]', '[new_rank]', -1, 0)")
|
||||
insert_query.Execute()
|
||||
qdel(insert_query)
|
||||
var/datum/db_query/log_query = SSdbcore.NewQuery("INSERT INTO `test`.`erro_admin_log` (`id` ,`datetime` ,`adminckey` ,`adminip` ,`log` ) VALUES (NULL , NOW( ) , '[usr.ckey]', '[usr.client.address]', 'Added new admin [adm_ckey] to rank [new_rank]');")
|
||||
log_query.Execute()
|
||||
qdel(log_query)
|
||||
to_chat(usr, span_filter_adminlog("[span_blue("New admin added.")]"))
|
||||
else
|
||||
if(!isnull(admin_id) && isnum(admin_id))
|
||||
var/datum/db_query/insert_query = SSdbcore.NewQuery("UPDATE `erro_admin` SET rank = '[new_rank]' WHERE id = [admin_id]")
|
||||
insert_query.Execute()
|
||||
qdel(insert_query)
|
||||
var/datum/db_query/log_query = SSdbcore.NewQuery("INSERT INTO `test`.`erro_admin_log` (`id` ,`datetime` ,`adminckey` ,`adminip` ,`log` ) VALUES (NULL , NOW( ) , '[usr.ckey]', '[usr.client.address]', 'Edited the rank of [adm_ckey] to [new_rank]');")
|
||||
log_query.Execute()
|
||||
qdel(log_query)
|
||||
to_chat(usr, span_filter_adminlog("[span_blue("Admin rank changed.")]"))
|
||||
|
||||
/datum/admins/proc/log_admin_permission_modification(var/adm_ckey, var/new_permission)
|
||||
if(CONFIG_GET(flag/admin_legacy_system)) return
|
||||
|
||||
if(!usr.client)
|
||||
return
|
||||
|
||||
if(!usr.client.holder || !(usr.client.holder.rights & R_PERMISSIONS))
|
||||
to_chat(usr, span_filter_adminlog("[span_red(">You do not have permission to do this!")]"))
|
||||
return
|
||||
|
||||
establish_db_connection()
|
||||
if(!SSdbcore.IsConnected())
|
||||
to_chat(usr, span_filter_adminlog("[span_red("Failed to establish database connection!")]"))
|
||||
return
|
||||
|
||||
if(!adm_ckey || !new_permission)
|
||||
return
|
||||
|
||||
adm_ckey = ckey(adm_ckey)
|
||||
|
||||
if(!adm_ckey)
|
||||
return
|
||||
|
||||
if(istext(new_permission))
|
||||
new_permission = text2num(new_permission)
|
||||
|
||||
if(!istext(adm_ckey) || !isnum(new_permission))
|
||||
return
|
||||
|
||||
var/datum/db_query/select_query = SSdbcore.NewQuery("SELECT id, flags FROM erro_admin WHERE ckey = '[adm_ckey]'")
|
||||
select_query.Execute()
|
||||
|
||||
var/admin_id
|
||||
var/admin_rights
|
||||
while(select_query.NextRow())
|
||||
admin_id = text2num(select_query.item[1])
|
||||
admin_rights = text2num(select_query.item[2])
|
||||
qdel(select_query)
|
||||
if(!admin_id)
|
||||
return
|
||||
|
||||
if(admin_rights & new_permission) //This admin already has this permission, so we are removing it.
|
||||
var/datum/db_query/insert_query = SSdbcore.NewQuery("UPDATE `erro_admin` SET flags = [admin_rights & ~new_permission] WHERE id = [admin_id]")
|
||||
insert_query.Execute()
|
||||
qdel(insert_query)
|
||||
var/datum/db_query/log_query = SSdbcore.NewQuery("INSERT INTO `test`.`erro_admin_log` (`id` ,`datetime` ,`adminckey` ,`adminip` ,`log` ) VALUES (NULL , NOW( ) , '[usr.ckey]', '[usr.client.address]', 'Removed permission [rights2text(new_permission)] (flag = [new_permission]) to admin [adm_ckey]');")
|
||||
log_query.Execute()
|
||||
qdel(log_query)
|
||||
to_chat(usr, span_filter_adminlog("[span_blue("Permission removed.")]"))
|
||||
else //This admin doesn't have this permission, so we are adding it.
|
||||
var/datum/db_query/insert_query = SSdbcore.NewQuery("UPDATE `erro_admin` SET flags = '[admin_rights | new_permission]' WHERE id = [admin_id]")
|
||||
insert_query.Execute()
|
||||
qdel(insert_query)
|
||||
var/datum/db_query/log_query = SSdbcore.NewQuery("INSERT INTO `test`.`erro_admin_log` (`id` ,`datetime` ,`adminckey` ,`adminip` ,`log` ) VALUES (NULL , NOW( ) , '[usr.ckey]', '[usr.client.address]', 'Added permission [rights2text(new_permission)] (flag = [new_permission]) to admin [adm_ckey]')")
|
||||
log_query.Execute()
|
||||
qdel(log_query)
|
||||
to_chat(usr, span_filter_adminlog("[span_blue("Permission added.")]"))
|
||||
@@ -27,7 +27,7 @@
|
||||
var/datum/player_info/P = new
|
||||
if (user)
|
||||
P.author = user.key
|
||||
P.rank = user.client.holder.rank
|
||||
P.rank = user.client.holder.rank_names()
|
||||
else
|
||||
P.author = "Adminbot"
|
||||
P.rank = "Friendly Robot"
|
||||
|
||||
+18
-94
@@ -126,99 +126,23 @@
|
||||
if((bantype == BANTYPE_PERMA || bantype == BANTYPE_TEMP) && playermob.client)
|
||||
qdel(playermob.client)
|
||||
|
||||
else if(href_list["editrightsbrowser"])
|
||||
edit_admin_permissions(0)
|
||||
|
||||
else if(href_list["editrightsbrowserlog"])
|
||||
edit_admin_permissions(1, href_list["editrightstarget"], href_list["editrightsoperation"], href_list["editrightspage"])
|
||||
|
||||
if(href_list["editrightsbrowsermanage"])
|
||||
if(href_list["editrightschange"])
|
||||
change_admin_rank(ckey(href_list["editrightschange"]), href_list["editrightschange"], TRUE)
|
||||
else if(href_list["editrightsremove"])
|
||||
remove_admin(ckey(href_list["editrightsremove"]), href_list["editrightsremove"], TRUE)
|
||||
else if(href_list["editrightsremoverank"])
|
||||
remove_rank(href_list["editrightsremoverank"])
|
||||
edit_admin_permissions(2)
|
||||
|
||||
else if(href_list["editrights"])
|
||||
if(!check_rights(R_PERMISSIONS))
|
||||
message_admins("[key_name_admin(usr)] attempted to edit the admin permissions without sufficient rights.")
|
||||
log_admin("[key_name(usr)] attempted to edit the admin permissions without sufficient rights.")
|
||||
return
|
||||
|
||||
var/adm_ckey
|
||||
|
||||
var/task = href_list["editrights"]
|
||||
if(task == "add")
|
||||
var/new_ckey = ckey(tgui_input_text(usr,"New admin's ckey","Admin ckey", null))
|
||||
if(!new_ckey) return
|
||||
if(new_ckey in admin_datums)
|
||||
to_chat(usr, span_filter_adminlog(span_warning("Error: Topic 'editrights': [new_ckey] is already an admin")))
|
||||
return
|
||||
adm_ckey = new_ckey
|
||||
task = "rank"
|
||||
else if(task != "show")
|
||||
adm_ckey = ckey(href_list["ckey"])
|
||||
if(!adm_ckey)
|
||||
to_chat(usr, span_filter_adminlog(span_warning("Error: Topic 'editrights': No valid ckey")))
|
||||
return
|
||||
|
||||
var/datum/admins/D = admin_datums[adm_ckey]
|
||||
|
||||
if(task == "remove")
|
||||
if(tgui_alert(usr, "Are you sure you want to remove [adm_ckey]?","Message",list("Yes","Cancel")) == "Yes")
|
||||
if(!D) return
|
||||
admin_datums -= adm_ckey
|
||||
D.disassociate()
|
||||
|
||||
message_admins("[key_name_admin(usr)] removed [adm_ckey] from the admins list")
|
||||
log_admin("[key_name(usr)] removed [adm_ckey] from the admins list")
|
||||
log_admin_rank_modification(adm_ckey, "Removed")
|
||||
|
||||
else if(task == "rank")
|
||||
var/new_rank
|
||||
if(admin_ranks.len)
|
||||
new_rank = tgui_input_list(usr, "Please select a rank", "New rank", (admin_ranks|"*New Rank*"))
|
||||
else
|
||||
new_rank = tgui_input_list(usr, "Please select a rank", "New rank", list("Game Master","Game Admin", "Trial Admin", "Admin Observer","*New Rank*"))
|
||||
|
||||
var/rights = 0
|
||||
if(D)
|
||||
rights = D.rights
|
||||
switch(new_rank)
|
||||
if(null,"") return
|
||||
if("*New Rank*")
|
||||
new_rank = tgui_input_text(usr, "Please input a new rank", "New custom rank")
|
||||
if(CONFIG_GET(flag/admin_legacy_system))
|
||||
new_rank = ckeyEx(new_rank)
|
||||
if(!new_rank)
|
||||
to_chat(usr, span_filter_adminlog(span_warning("Error: Topic 'editrights': Invalid rank")))
|
||||
return
|
||||
if(CONFIG_GET(flag/admin_legacy_system))
|
||||
if(admin_ranks.len)
|
||||
if(new_rank in admin_ranks)
|
||||
rights = admin_ranks[new_rank] //we typed a rank which already exists, use its rights
|
||||
else
|
||||
admin_ranks[new_rank] = 0 //add the new rank to admin_ranks
|
||||
else
|
||||
if(CONFIG_GET(flag/admin_legacy_system))
|
||||
new_rank = ckeyEx(new_rank)
|
||||
rights = admin_ranks[new_rank] //we input an existing rank, use its rights
|
||||
|
||||
if(D)
|
||||
D.disassociate() //remove adminverbs and unlink from client
|
||||
D.rank = new_rank //update the rank
|
||||
D.rights = rights //update the rights based on admin_ranks (default: 0)
|
||||
else
|
||||
D = new /datum/admins(new_rank, rights, adm_ckey)
|
||||
|
||||
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
|
||||
|
||||
message_admins("[key_name_admin(usr)] edited the admin rank of [adm_ckey] to [new_rank]")
|
||||
log_admin("[key_name(usr)] edited the admin rank of [adm_ckey] to [new_rank]")
|
||||
log_admin_rank_modification(adm_ckey, new_rank)
|
||||
|
||||
else if(task == "permissions")
|
||||
if(!D) return
|
||||
var/list/permissionlist = list()
|
||||
for(var/i=1, i<=R_MAXPERMISSION, i<<=1) //that <<= is shorthand for i = i << 1. Which is a left bitshift
|
||||
permissionlist[rights2text(i)] = i
|
||||
var/new_permission = tgui_input_list(usr, "Select a permission to turn on/off", "Permission toggle", permissionlist)
|
||||
if(!new_permission) return
|
||||
D.rights ^= permissionlist[new_permission]
|
||||
|
||||
message_admins("[key_name_admin(usr)] toggled the [new_permission] permission of [adm_ckey]")
|
||||
log_admin("[key_name(usr)] toggled the [new_permission] permission of [adm_ckey]")
|
||||
log_admin_permission_modification(adm_ckey, permissionlist[new_permission])
|
||||
|
||||
edit_admin_permissions()
|
||||
edit_rights_topic(href_list)
|
||||
|
||||
else if(href_list["call_shuttle"])
|
||||
if(!check_rights(R_ADMIN|R_EVENT)) return
|
||||
@@ -689,7 +613,7 @@
|
||||
return
|
||||
|
||||
if(M != usr) //we can jobban ourselves
|
||||
if(M.client && M.client.holder && (M.client.holder.rights & R_BAN)) //they can ban too. So we can't ban them
|
||||
if(M.client && M.client.holder && (check_rights_for(M.client, R_BAN))) //they can ban too. So we can't ban them
|
||||
tgui_alert_async(usr, "You cannot perform this action. You must be of a higher administrative rank!")
|
||||
return
|
||||
|
||||
@@ -1357,7 +1281,7 @@
|
||||
if(ismob(M))
|
||||
var/take_msg = span_notice("<b>ADMINHELP</b>: <b>[key_name(usr.client)]</b> is attending to <b>[key_name(M)]'s</b> adminhelp, please don't dogpile them.")
|
||||
for(var/client/X in GLOB.admins)
|
||||
if((R_ADMIN|R_MOD|R_SERVER) & X.holder.rights) //VOREStation Edit
|
||||
if(check_rights_for(X, (R_ADMIN|R_MOD|R_SERVER)))
|
||||
to_chat(X, take_msg)
|
||||
to_chat(M, span_filter_pm(span_boldnotice("Your adminhelp is being attended to by [usr.client]. Thanks for your patience!")))
|
||||
// VoreStation Edit Start
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
GENERAL_PROTECT_DATUM(/datum/admin_verb)
|
||||
|
||||
/**
|
||||
* This is the admin verb datum. It is used to store the verb's information and handle the verb's functionality.
|
||||
* All of this is setup for you, and you should not be defining this manually.
|
||||
* That means you reader.
|
||||
*/
|
||||
/datum/admin_verb
|
||||
var/name //! The name of the verb.
|
||||
var/description //! The description of the verb.
|
||||
var/category //! The category of the verb.
|
||||
var/permissions //! The permissions required to use the verb.
|
||||
var/visibility_flag //! The flag that determines if the verb is visible.
|
||||
VAR_PROTECTED/verb_path //! The path to the verb proc.
|
||||
|
||||
/datum/admin_verb/Destroy(force)
|
||||
if(!force)
|
||||
return QDEL_HINT_LETMELIVE
|
||||
return ..()
|
||||
|
||||
/// Assigns the verb to the admin.
|
||||
/datum/admin_verb/proc/assign_to_client(client/admin)
|
||||
add_verb(admin, verb_path)
|
||||
|
||||
/// Unassigns the verb from the admin.
|
||||
/datum/admin_verb/proc/unassign_from_client(client/admin)
|
||||
remove_verb(admin, verb_path)
|
||||
@@ -257,7 +257,7 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new)
|
||||
//send this msg to all admins
|
||||
|
||||
for(var/client/X in GLOB.admins)
|
||||
if(!check_rights(R_ADMIN, 0, X))
|
||||
if(!check_rights_for(X, R_ADMIN))
|
||||
continue
|
||||
if(X.prefs?.read_preference(/datum/preference/toggle/holder/play_adminhelp_ping))
|
||||
X << 'sound/effects/adminhelp.ogg'
|
||||
@@ -684,7 +684,7 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new)
|
||||
. = list("total" = list(), "noflags" = list(), "afk" = list(), "stealth" = list(), "present" = list())
|
||||
for(var/client/X in GLOB.admins)
|
||||
.["total"] += X
|
||||
if(requiredflags != 0 && !check_rights(rights_required = requiredflags, show_msg = FALSE, C = X))
|
||||
if(requiredflags != 0 && !check_rights_for(X, requiredflags))
|
||||
.["noflags"] += X
|
||||
else if(X.is_afk())
|
||||
.["afk"] += X
|
||||
|
||||
@@ -203,14 +203,14 @@
|
||||
if(irc)
|
||||
log_admin("PM: [key_name(src)]->IRC: [rawmsg]")
|
||||
for(var/client/X in GLOB.admins)
|
||||
if(!check_rights(R_ADMIN, 0, X))
|
||||
if(!check_rights_for(X, R_ADMIN))
|
||||
continue
|
||||
to_chat(X, span_admin_pm_notice(span_bold("PM: [key_name(src, X, 0)]->IRC:") + " [keywordparsedmsg]"))
|
||||
else
|
||||
log_admin("PM: [key_name(src)]->[key_name(recipient)]: [rawmsg]")
|
||||
//we don't use message_admins here because the sender/receiver might get it too
|
||||
for(var/client/X in GLOB.admins)
|
||||
if(!check_rights(R_ADMIN, 0, X))
|
||||
if(!check_rights_for(X, R_ADMIN))
|
||||
continue
|
||||
if(X.key!=key && X.key!=recipient.key) //check client/X is an admin and isn't the sender or recipient
|
||||
to_chat(X, span_admin_pm_notice(span_bold("PM: [key_name(src, X, 0)]->[key_name(recipient, X, 0)]:") + " [keywordparsedmsg]"))
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
log_adminsay(msg,src)
|
||||
|
||||
for(var/client/C in GLOB.admins)
|
||||
if(check_rights(R_ADMIN, 0, C))
|
||||
if(check_rights_for(C, R_ADMIN))
|
||||
to_chat(C, span_admin_channel(create_text_tag("admin", "ADMIN:", C) + " " + span_name("[key_name(usr, 1)]") + "([admin_jump_link(mob, src)]): " + span_name("[msg]") ))
|
||||
|
||||
feedback_add_details("admin_verb","M") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
@@ -27,10 +27,10 @@
|
||||
display_name = usr.client.holder.fakekey
|
||||
|
||||
// Name shown to other players. Admins whom are not also antags have their rank displayed.
|
||||
var/player_display = (is_admin && !is_antag) ? "[display_name]([usr.client.holder.rank])" : display_name
|
||||
var/player_display = (is_admin && !is_antag) ? "[display_name]([usr.client.holder.rank_names()])" : display_name
|
||||
|
||||
for(var/mob/M in mob_list)
|
||||
if(check_rights(R_ADMIN|R_MOD|R_EVENT, 0, M)) // Staff can see AOOC unconditionally, and with more details.
|
||||
if(check_rights_for(M.client, R_ADMIN|R_MOD|R_EVENT)) // Staff can see AOOC unconditionally, and with more details.
|
||||
to_chat(M, span_ooc(span_aooc("[create_text_tag("aooc", "Antag-OOC:", M.client)] <EM>[get_options_bar(src, 0, 1, 1)]([admin_jump_link(usr, M.client.holder)]):</EM> " + span_message("[msg]"))))
|
||||
else if(M.client) // Players can only see AOOC if observing, or if they are an antag type allowed to use AOOC.
|
||||
var/datum/antagonist/A = null
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
to_chat(src, span_warning("You have deadchat muted."))
|
||||
return
|
||||
|
||||
var/stafftype = uppertext(holder.rank)
|
||||
var/stafftype = uppertext(holder.rank_names())
|
||||
|
||||
msg = sanitize(msg)
|
||||
log_admin("DSAY: [key_name(src)] : [msg]")
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
var/msg = span_filter_pray(span_blue("[icon2html(cross, GLOB.admins)] <b>" + span_purple("PRAY: ") + "[key_name(src, 1)] [ADMIN_QUE(src)] [ADMIN_PP(src)] [ADMIN_VV(src)] [ADMIN_SM(src)] ([admin_jump_link(src, src)]) [ADMIN_CA(src)] [ADMIN_SC(src)] [ADMIN_SMITE(src)]:</b> [raw_msg]"))
|
||||
|
||||
for(var/client/C in GLOB.admins)
|
||||
if(!check_rights(R_ADMIN, 0, C))
|
||||
if(!check_rights_for(C, R_ADMIN))
|
||||
continue
|
||||
if(C.prefs?.read_preference(/datum/preference/toggle/show_chat_prayers))
|
||||
to_chat(C, msg, type = MESSAGE_TYPE_PRAYER, confidential = TRUE)
|
||||
@@ -29,7 +29,7 @@
|
||||
/proc/CentCom_announce(var/msg, var/mob/Sender, var/iamessage)
|
||||
msg = span_blue(span_bold(span_orange("[uppertext(using_map.boss_short)]M[iamessage ? " IA" : ""]:") + "[key_name(Sender, 1)] [ADMIN_PP(Sender)] [ADMIN_VV(Sender)] [ADMIN_SM(Sender)] ([admin_jump_link(Sender)]) [ADMIN_CA(Sender)] [ADMIN_BSA(Sender)] [ADMIN_CENTCOM_REPLY(Sender)]:") + " [msg]")
|
||||
for(var/client/C in GLOB.admins) //VOREStation Edit - GLOB admins
|
||||
if(!check_rights(R_ADMIN, 0, C))
|
||||
if(!check_rights_for(C, R_ADMIN))
|
||||
continue
|
||||
to_chat(C,msg)
|
||||
C << 'sound/machines/signal.ogg'
|
||||
@@ -37,7 +37,7 @@
|
||||
/proc/Syndicate_announce(var/msg, var/mob/Sender)
|
||||
msg = span_blue(span_bold(span_crimson("ILLEGAL:") + "[key_name(Sender, 1)] [ADMIN_PP(Sender)] [ADMIN_VV(Sender)] [ADMIN_SM(Sender)] ([admin_jump_link(Sender)]) [ADMIN_CA(Sender)] [ADMIN_BSA(Sender)] [ADMIN_SYNDICATE_REPLY(Sender)]:") + " [msg]")
|
||||
for(var/client/C in GLOB.admins) //VOREStation Edit - GLOB admins
|
||||
if(!check_rights(R_ADMIN, 0, C))
|
||||
if(!check_rights_for(C, R_ADMIN))
|
||||
continue
|
||||
to_chat(C,msg)
|
||||
C << 'sound/machines/signal.ogg'
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
// Admin Verbs in this file are special and cannot use the AVD system for some reason or another.
|
||||
|
||||
/client/proc/readmin()
|
||||
set name = "Readmin"
|
||||
set category = "Admin.Misc"
|
||||
set desc = "Regain your admin powers."
|
||||
|
||||
var/datum/admins/A = GLOB.deadmins[ckey]
|
||||
|
||||
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
|
||||
|
||||
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, span_interface("You are now an admin."), confidential = TRUE)
|
||||
message_admins("[src] re-adminned themselves.")
|
||||
log_admin("[src] re-adminned themselves.")
|
||||
//BLACKBOX_LOG_ADMIN_VERB("Readmin")
|
||||
|
||||
if(isobserver(mob))
|
||||
var/mob/observer/dead/our_mob = mob
|
||||
our_mob.visualnet?.addVisibility(our_mob, src)
|
||||
@@ -172,21 +172,24 @@
|
||||
/client/VV_ckey_edit()
|
||||
return list("key", "ckey")
|
||||
|
||||
/datum/proc/may_edit_var(var/user, var/var_to_edit)
|
||||
/datum/proc/may_edit_var(var/user, var/var_to_edit) //User must be a CLIENT that is passed to this.
|
||||
if(!user)
|
||||
return FALSE
|
||||
if(ismob(user)) //Failsafe catch in case someone feeds a mob into us.
|
||||
var/mob/living = user
|
||||
user = living.client
|
||||
if(!(var_to_edit in vars))
|
||||
to_chat(user, span_warning("\The [src] does not have a var '[var_to_edit]'"))
|
||||
return FALSE
|
||||
if(var_to_edit in VV_static())
|
||||
return FALSE
|
||||
if((var_to_edit in VV_secluded()) && !check_rights(R_ADMIN|R_DEBUG, FALSE, C = user))
|
||||
if((var_to_edit in VV_secluded()) && !check_rights_for(user, R_ADMIN|R_DEBUG))
|
||||
return FALSE
|
||||
if((var_to_edit in VV_locked()) && !check_rights(R_DEBUG, C = user))
|
||||
if((var_to_edit in VV_locked()) && !check_rights_for(user, R_DEBUG))
|
||||
return FALSE
|
||||
if((var_to_edit in VV_ckey_edit()) && !check_rights(R_SPAWN|R_DEBUG, C = user))
|
||||
if((var_to_edit in VV_ckey_edit()) && !check_rights_for(user, R_SPAWN|R_DEBUG))
|
||||
return FALSE
|
||||
if((var_to_edit in VV_icon_edit_lock()) && !check_rights(R_FUN|R_DEBUG, C = user))
|
||||
if((var_to_edit in VV_icon_edit_lock()) && !check_rights_for(user, R_FUN|R_DEBUG))
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
/datum/asset/simple/generic
|
||||
assets = list(
|
||||
"search.js" = 'html/search.js',
|
||||
"panels.css" = 'html/panels.css',
|
||||
"loading.gif" = 'html/images/loading.gif',
|
||||
"ntlogo.png" = 'html/images/ntlogo.png',
|
||||
"sglogo.png" = 'html/images/sglogo.png',
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
/datum/asset/simple/namespaced/common
|
||||
assets = list("padlock.png" = 'icons/ui/common/padlock.png')
|
||||
parents = list("common.css" = 'html/browser/common.css')
|
||||
@@ -0,0 +1,11 @@
|
||||
/datum/asset/simple/permissions
|
||||
assets = list(
|
||||
"search.js" = 'html/admin/search.js',
|
||||
"panels.css" = 'html/admin/panels.css'
|
||||
)
|
||||
|
||||
/datum/asset/group/permissions
|
||||
children = list(
|
||||
/datum/asset/simple/permissions,
|
||||
/datum/asset/simple/namespaced/common
|
||||
)
|
||||
@@ -40,7 +40,6 @@
|
||||
show_verb_panel = FALSE
|
||||
///Contains admin info. Null if client is not an admin.
|
||||
var/datum/admins/holder = null
|
||||
var/datum/admins/deadmin_holder = null
|
||||
var/buildmode = 0
|
||||
|
||||
///Contains the last message sent by this client - used to protect against copy-paste spamming.
|
||||
|
||||
@@ -260,7 +260,7 @@
|
||||
GLOB.mhelp_tickets.ClientLogin(src)
|
||||
|
||||
//Admin Authorisation
|
||||
holder = admin_datums[ckey]
|
||||
holder = GLOB.admin_datums[ckey]
|
||||
if(holder)
|
||||
GLOB.admins += src
|
||||
holder.owner = src
|
||||
@@ -465,7 +465,7 @@
|
||||
|
||||
var/admin_rank = "Player"
|
||||
if(src.holder)
|
||||
admin_rank = src.holder.rank
|
||||
admin_rank = src.holder.rank_names()
|
||||
|
||||
var/sql_ip = sql_sanitize_text(src.address)
|
||||
var/sql_computerid = sql_sanitize_text(src.computer_id)
|
||||
@@ -475,7 +475,7 @@
|
||||
|
||||
//Panic bunker code
|
||||
if (isnum(player_age) && player_age == 0) //first connection
|
||||
if (CONFIG_GET(flag/panic_bunker) && !holder && !deadmin_holder)
|
||||
if (CONFIG_GET(flag/panic_bunker) && !holder && !GLOB.deadmins[key])
|
||||
log_adminwarn("Failed Login: [key] - New account attempting to connect during panic bunker")
|
||||
message_admins(span_adminnotice("Failed Login: [key] - New account attempting to connect during panic bunker"))
|
||||
disconnect_with_message("Sorry but the server is currently not accepting connections from never before seen players.")
|
||||
|
||||
@@ -60,7 +60,7 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
|
||||
continue
|
||||
if(instance.ckeys_allowed && (!client || !(client.ckey in instance.ckeys_allowed)))
|
||||
continue
|
||||
if(instance.species_allowed && (!species || !(species in instance.species_allowed)) && (!client || !check_rights(R_ADMIN | R_EVENT | R_FUN, 0, client)) && (!custom_base || !(custom_base in instance.species_allowed)))
|
||||
if(instance.species_allowed && (!species || !(species in instance.species_allowed)) && (!client || !check_rights_for(client, R_ADMIN | R_EVENT | R_FUN)) && (!custom_base || !(custom_base in instance.species_allowed)))
|
||||
continue
|
||||
.[instance.name] = instance
|
||||
|
||||
@@ -539,7 +539,7 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
|
||||
else
|
||||
return TOPIC_NOACTION
|
||||
|
||||
if(((!(setting_species.spawn_flags & SPECIES_CAN_JOIN)) || (!is_alien_whitelisted(preference_mob(),setting_species))) && !check_rights(R_ADMIN|R_EVENT, 0) && !(setting_species.spawn_flags & SPECIES_WHITELIST_SELECTABLE))
|
||||
if(((!(setting_species.spawn_flags & SPECIES_CAN_JOIN)) || (!is_alien_whitelisted(user.client,setting_species))) && !check_rights(R_ADMIN|R_EVENT, 0) && !(setting_species.spawn_flags & SPECIES_WHITELIST_SELECTABLE))
|
||||
return TOPIC_NOACTION
|
||||
|
||||
var/prev_species = pref.species
|
||||
@@ -1215,7 +1215,7 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
|
||||
|
||||
if(!(current_species.spawn_flags & SPECIES_CAN_JOIN))
|
||||
restricted = 2
|
||||
else if(!is_alien_whitelisted(preference_mob(),current_species))
|
||||
else if(!is_alien_whitelisted(user.client,current_species))
|
||||
restricted = 1
|
||||
|
||||
if(restricted)
|
||||
|
||||
@@ -83,7 +83,7 @@ var/list/gear_datums = list()
|
||||
if(G.whitelisted && CONFIG_GET(flag/loadout_whitelist) != LOADOUT_WHITELIST_OFF && pref.client) //VOREStation Edit.
|
||||
if(CONFIG_GET(flag/loadout_whitelist) == LOADOUT_WHITELIST_STRICT && G.whitelisted != pref.species)
|
||||
continue
|
||||
if(CONFIG_GET(flag/loadout_whitelist) == LOADOUT_WHITELIST_LAX && !is_alien_whitelisted(preference_mob(), GLOB.all_species[G.whitelisted]))
|
||||
if(CONFIG_GET(flag/loadout_whitelist) == LOADOUT_WHITELIST_LAX && !is_alien_whitelisted(preference_mob.client, GLOB.all_species[G.whitelisted]))
|
||||
continue
|
||||
if(max_cost && G.cost > max_cost)
|
||||
continue
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
if(!.)
|
||||
return
|
||||
|
||||
return check_rights(R_MOD|R_ADMIN, FALSE, preferences.client)
|
||||
return check_rights_for(preferences.client, R_MOD|R_ADMIN)
|
||||
|
||||
/datum/preference/toggle/show_debug_logs
|
||||
category = PREFERENCE_CATEGORY_GAME_PREFERENCES
|
||||
@@ -22,7 +22,7 @@
|
||||
if(!.)
|
||||
return
|
||||
|
||||
return check_rights(R_DEBUG|R_ADMIN, FALSE, preferences.client)
|
||||
return check_rights_for(preferences.client, R_DEBUG|R_ADMIN)
|
||||
|
||||
/datum/preference/toggle/show_chat_prayers
|
||||
category = PREFERENCE_CATEGORY_GAME_PREFERENCES
|
||||
@@ -35,7 +35,7 @@
|
||||
if(!.)
|
||||
return
|
||||
|
||||
return check_rights(R_EVENT|R_ADMIN, FALSE, preferences.client)
|
||||
return check_rights_for(preferences.client, R_EVENT|R_ADMIN)
|
||||
|
||||
// General holder prefs
|
||||
/datum/preference/toggle/holder
|
||||
@@ -85,4 +85,4 @@
|
||||
if(!..(preferences))
|
||||
return FALSE
|
||||
|
||||
return CONFIG_GET(flag/allow_admin_ooccolor) && check_rights(R_ADMIN|R_EVENT|R_FUN, 0, preferences.client)
|
||||
return CONFIG_GET(flag/allow_admin_ooccolor) && check_rights_for(preferences.client, R_ADMIN|R_EVENT|R_FUN)
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
var/list/Lines = list()
|
||||
|
||||
if(check_rights(R_ADMIN|R_SERVER|R_MOD,FALSE,src))
|
||||
if(check_rights_for(src, R_ADMIN|R_SERVER|R_MOD))
|
||||
for(var/client/C in GLOB.clients)
|
||||
var/entry = "<tr><td>[C.key]"
|
||||
if(C.holder && C.holder.fakekey)
|
||||
|
||||
@@ -51,13 +51,13 @@
|
||||
if(holder && !holder.fakekey)
|
||||
ooc_style = "elevated"
|
||||
|
||||
if(holder.rights & R_EVENT) //Retired Admins
|
||||
if(check_rights(R_EVENT)) //Retired Admins
|
||||
ooc_style = "event_manager"
|
||||
if(holder.rights & R_ADMIN && !(holder.rights & R_BAN)) //Game Masters
|
||||
if(check_rights(R_ADMIN) && !(check_rights(R_BAN))) //Game Masters
|
||||
ooc_style = "moderator"
|
||||
if(holder.rights & R_SERVER && !(holder.rights & R_BAN)) //Developers
|
||||
if(check_rights(R_SERVER) && !(check_rights(R_BAN))) //Developers
|
||||
ooc_style = "developer"
|
||||
if(holder.rights & R_ADMIN && holder.rights & R_BAN) //Admins
|
||||
if(check_rights(R_ADMIN) && check_rights(R_BAN)) //Admins
|
||||
ooc_style = "admin"
|
||||
|
||||
msg = GLOB.is_valid_url.Replace(msg,span_linkify("$1"))
|
||||
@@ -74,7 +74,7 @@
|
||||
else
|
||||
display_name = holder.fakekey
|
||||
var/pref_color = prefs.read_preference(/datum/preference/color/ooc_color)
|
||||
if(holder && !holder.fakekey && (holder.rights & R_ADMIN|R_FUN|R_EVENT) && CONFIG_GET(flag/allow_admin_ooccolor) && pref_color != "#010000") // keeping this for the badmins
|
||||
if(holder && !holder.fakekey && (check_rights(R_ADMIN|R_FUN|R_EVENT)) && CONFIG_GET(flag/allow_admin_ooccolor) && pref_color != "#010000") // keeping this for the badmins
|
||||
to_chat(target, span_ooc("<font color='[pref_color]'>" + create_text_tag("ooc", "OOC:", target) + " <EM>[display_name]:</EM> [span_message(msg)]</font>"))
|
||||
else
|
||||
to_chat(target, span_ooc("<span class='[ooc_style]'>" + create_text_tag("ooc", "OOC:", target) + " <EM>[display_name]:</EM> " + span_message(msg)) + "</span>")
|
||||
@@ -163,7 +163,7 @@
|
||||
// Admins with RLOOC displayed who weren't already in
|
||||
for(var/client/admin in GLOB.admins)
|
||||
if(!(admin in receivers) && admin.prefs?.read_preference(/datum/preference/toggle/holder/show_rlooc))
|
||||
if(check_rights(R_SERVER, FALSE, admin)) //Stop rLOOC showing for retired staff
|
||||
if(check_rights_for(admin, R_SERVER)) //Stop rLOOC showing for retired staff
|
||||
r_receivers |= admin
|
||||
|
||||
msg = GLOB.is_valid_url.Replace(msg,span_linkify("$1"))
|
||||
|
||||
@@ -73,19 +73,19 @@
|
||||
if(C.holder.fakekey && !check_rights_for(src, R_ADMIN|R_MOD)) // Only admins and mods can see stealthmins
|
||||
continue
|
||||
// VOREStation Edit End
|
||||
if(check_rights(R_BAN, FALSE, C)) // admins //VOREStation Edit
|
||||
if(check_rights_for(C, R_BAN)) // admins //VOREStation Edit
|
||||
num_admins_online++
|
||||
else if(check_rights(R_ADMIN, FALSE, C) && !check_rights(R_SERVER, FALSE, C)) // mods //VOREStation Edit: Game masters
|
||||
else if(check_rights_for(C, R_ADMIN) && !check_rights_for(C, R_SERVER)) // mods //VOREStation Edit: Game masters
|
||||
category = R_MOD
|
||||
num_mods_online++
|
||||
else if(check_rights(R_SERVER, FALSE, C)) // developers
|
||||
else if(check_rights_for(C, R_SERVER)) // developers
|
||||
category = R_SERVER
|
||||
num_devs_online++
|
||||
else if(check_rights(R_STEALTH, FALSE, C)) // event managers //VOREStation Edit: Retired Staff
|
||||
else if(check_rights_for(C, R_STEALTH)) // event managers //VOREStation Edit: Retired Staff
|
||||
category = R_EVENT
|
||||
num_event_managers_online++
|
||||
|
||||
temp += "\t[C] is a [C.holder.rank]"
|
||||
temp += "\t[C] is a [C.holder.rank_names()]"
|
||||
if(holder)
|
||||
if(C.holder.fakekey)
|
||||
temp += " " + span_italics("(as [C.holder.fakekey])")
|
||||
|
||||
@@ -55,7 +55,7 @@ var/list/mentor_verbs_default = list(
|
||||
if(!target)
|
||||
return
|
||||
var/client/C = targets[target]
|
||||
if(has_mentor_powers(C) || C.deadmin_holder) // If an admin is deadminned you could mentor them and that will cause fuckery if they readmin
|
||||
if(has_mentor_powers(C) || GLOB.deadmins[C.ckey]) // If an admin is deadminned you could mentor them and that will cause fuckery if they readmin
|
||||
to_chat(src, span_admin_pm_warning("Error: They already have mentor powers."))
|
||||
return
|
||||
var/datum/mentor/M = new /datum/mentor(C.ckey)
|
||||
|
||||
@@ -148,7 +148,7 @@
|
||||
visualnet = ghostnet
|
||||
|
||||
/mob/observer/dead/proc/checkStatic()
|
||||
return !(check_rights(R_ADMIN|R_FUN|R_EVENT|R_SERVER, 0, src) || (client && client.buildmode) || isbelly(loc))
|
||||
return !(check_rights_for(src.client, R_ADMIN|R_FUN|R_EVENT|R_SERVER) || (client && client.buildmode) || isbelly(loc))
|
||||
|
||||
/mob/observer/dead/Moved(atom/old_loc, direction, forced)
|
||||
. = ..()
|
||||
@@ -260,7 +260,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
|
||||
announce_ghost_joinleave(ghostize(1))
|
||||
else
|
||||
var/response
|
||||
if(check_rights(R_ADMIN|R_SERVER|R_MOD,FALSE,src)) //No need to sanity check for client and holder here as that is part of check_rights
|
||||
if(check_rights_for(src.client, R_ADMIN|R_SERVER|R_MOD)) //No need to sanity check for client and holder here as that is part of check_rights
|
||||
response = tgui_alert(src, "You have the ability to Admin-Ghost. The regular Ghost verb will announce your presence to dead chat. Both variants will allow you to return to your body using 'aghost'.\n\nWhat do you wish to do?", "Are you sure you want to ghost?", list("Admin Ghost", "Ghost", "Stay in body"))
|
||||
if(response == "Admin Ghost")
|
||||
if(!src.client)
|
||||
@@ -604,7 +604,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
|
||||
return 0
|
||||
|
||||
/mob/observer/dead/check_holy(var/turf/T)
|
||||
if(check_rights(R_ADMIN|R_FUN|R_EVENT, 0, src))
|
||||
if(check_rights_for(src.client, R_ADMIN|R_FUN|R_EVENT))
|
||||
return 0
|
||||
|
||||
return (T && T.holy) && (is_manifest || (mind in cult.current_antagonists))
|
||||
@@ -914,7 +914,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
|
||||
return 1
|
||||
|
||||
/mob/observer/dead/proc/can_admin_interact()
|
||||
return check_rights(R_ADMIN|R_EVENT, 0, src)
|
||||
return check_rights_for(src.client, R_ADMIN|R_EVENT|R_DEBUG)
|
||||
|
||||
/mob/observer/dead/verb/toggle_ghostsee()
|
||||
set name = "Toggle Ghost Vision"
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
/mob/living/carbon/alien/diona/confirm_evolution()
|
||||
|
||||
if(!is_alien_whitelisted(src, GLOB.all_species[SPECIES_DIONA]))
|
||||
if(!is_alien_whitelisted(src.client, GLOB.all_species[SPECIES_DIONA]))
|
||||
tgui_alert(src, "You are currently not whitelisted to play as a full diona.")
|
||||
return null
|
||||
|
||||
|
||||
@@ -180,14 +180,14 @@
|
||||
for(var/current_species_name in GLOB.all_species)
|
||||
var/datum/species/current_species = GLOB.all_species[current_species_name]
|
||||
|
||||
if(check_whitelist && CONFIG_GET(flag/usealienwhitelist) && !check_rights(R_ADMIN|R_EVENT, 0, src)) //If we're using the whitelist, make sure to check it!
|
||||
if(check_whitelist && CONFIG_GET(flag/usealienwhitelist) && !check_rights_for(src.client, R_ADMIN|R_EVENT)) //If we're using the whitelist, make sure to check it!
|
||||
if(!(current_species.spawn_flags & SPECIES_CAN_JOIN))
|
||||
continue
|
||||
if(whitelist.len && !(current_species_name in whitelist))
|
||||
continue
|
||||
if(blacklist.len && (current_species_name in blacklist))
|
||||
continue
|
||||
if((current_species.spawn_flags & SPECIES_IS_WHITELISTED) && !is_alien_whitelisted(src, current_species))
|
||||
if((current_species.spawn_flags & SPECIES_IS_WHITELISTED) && !is_alien_whitelisted(src.client, current_species))
|
||||
continue
|
||||
|
||||
valid_species += current_species_name
|
||||
|
||||
@@ -81,3 +81,4 @@
|
||||
client.images += cloaked_selfimage
|
||||
client.init_verbs()
|
||||
SEND_SIGNAL(src, COMSIG_MOB_CLIENT_LOGIN, client)
|
||||
SEND_SIGNAL(client, COMSIG_CLIENT_MOB_LOGIN, src)
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
update_client_z(null)
|
||||
log_access_out(src)
|
||||
unset_machine()
|
||||
if(admin_datums[src.ckey])
|
||||
if(GLOB.admin_datums[src.ckey])
|
||||
if (ticker && ticker.current_state == GAME_STATE_PLAYING) //Only report this stuff if we are currently playing.
|
||||
var/admins_number = GLOB.admins.len
|
||||
|
||||
@@ -14,4 +14,4 @@
|
||||
send2adminirc("[key_name(src)] logged out - no more admins online.")
|
||||
..()
|
||||
|
||||
return 1
|
||||
return 1
|
||||
|
||||
@@ -467,7 +467,7 @@
|
||||
set category = "OOC.Game"
|
||||
var/is_admin = 0
|
||||
|
||||
if(client.holder && (client.holder.rights & R_ADMIN|R_EVENT))
|
||||
if(check_rights_for(client, R_ADMIN|R_EVENT))
|
||||
is_admin = 1
|
||||
else if(stat != DEAD || isnewplayer(src))
|
||||
to_chat(src, span_filter_notice("[span_blue("You must be observing to use this!")]"))
|
||||
|
||||
@@ -83,7 +83,7 @@
|
||||
|
||||
|
||||
/proc/is_admin(var/mob/user)
|
||||
return check_rights(R_ADMIN|R_EVENT, 0, user) != 0
|
||||
return check_rights_for(user.client, R_ADMIN|R_EVENT) != 0
|
||||
|
||||
/**
|
||||
* Moved into its own file as part of port from CHOMP.
|
||||
@@ -404,7 +404,7 @@ var/list/intents = list(I_HELP,I_DISARM,I_GRAB,I_HURT)
|
||||
return // Can't talk in deadchat if you can't see it.
|
||||
|
||||
for(var/mob/M in player_list)
|
||||
if(M.client && ((!isnewplayer(M) && M.stat == DEAD) || (M.client.holder && M.client.holder.rights && M.client?.prefs?.read_preference(/datum/preference/toggle/holder/show_staff_dsay))) && M.client?.prefs?.read_preference(/datum/preference/toggle/show_dsay))
|
||||
if(M.client && ((!isnewplayer(M) && M.stat == DEAD) || (M.client.holder && check_rights_for(M.client, R_NONE) && M.client?.prefs?.read_preference(/datum/preference/toggle/holder/show_staff_dsay))) && M.client?.prefs?.read_preference(/datum/preference/toggle/show_dsay))
|
||||
var/follow
|
||||
var/lname
|
||||
if(M.forbid_seeing_deadchat && !M.client.holder)
|
||||
@@ -434,7 +434,7 @@ var/list/intents = list(I_HELP,I_DISARM,I_GRAB,I_HURT)
|
||||
|
||||
/proc/say_dead_object(var/message, var/obj/subject = null)
|
||||
for(var/mob/M in player_list)
|
||||
if(M.client && ((!isnewplayer(M) && M.stat == DEAD) || (M.client.holder && M.client.holder.rights && M.client?.prefs?.read_preference(/datum/preference/toggle/holder/show_staff_dsay))) && M.client?.prefs?.read_preference(/datum/preference/toggle/show_dsay))
|
||||
if(M.client && ((!isnewplayer(M) && M.stat == DEAD) || (M.client.holder && check_rights_for(M.client, R_NONE) && M.client?.prefs?.read_preference(/datum/preference/toggle/holder/show_staff_dsay))) && M.client?.prefs?.read_preference(/datum/preference/toggle/show_dsay))
|
||||
var/follow
|
||||
var/lname = "Game Master"
|
||||
if(M.forbid_seeing_deadchat && !M.client.holder)
|
||||
|
||||
@@ -524,7 +524,7 @@
|
||||
|
||||
if(chosen_species && use_species_name)
|
||||
// Have to recheck admin due to no usr at roundstart. Latejoins are fine though.
|
||||
if(is_alien_whitelisted(chosen_species))
|
||||
if(is_alien_whitelisted(src.client, chosen_species))
|
||||
new_character = new(T, use_species_name)
|
||||
|
||||
if(!new_character)
|
||||
@@ -600,9 +600,6 @@
|
||||
src << browse(null, "window=News") //closes news window
|
||||
panel.close()
|
||||
|
||||
/mob/new_player/proc/has_admin_rights()
|
||||
return check_rights(R_ADMIN, 0, src)
|
||||
|
||||
/mob/new_player/get_species()
|
||||
var/datum/species/chosen_species
|
||||
if(client.prefs.species)
|
||||
@@ -611,7 +608,7 @@
|
||||
if(!chosen_species)
|
||||
return SPECIES_HUMAN
|
||||
|
||||
if(is_alien_whitelisted(chosen_species))
|
||||
if(is_alien_whitelisted(src.client, chosen_species))
|
||||
return chosen_species.name
|
||||
|
||||
return SPECIES_HUMAN
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
to_chat(src,span_warning("You have not set your scale yet. Do this on the VORE tab in character setup."))
|
||||
|
||||
//Can they play?
|
||||
if(!is_alien_whitelisted(src,GLOB.all_species[client?.prefs?.species]) && !check_rights(R_ADMIN, 0))
|
||||
if(!is_alien_whitelisted(src.client,GLOB.all_species[client?.prefs?.species]) && !check_rights(R_ADMIN, 0))
|
||||
pass = FALSE
|
||||
to_chat(src,span_warning("You are not allowed to spawn in as this species."))
|
||||
|
||||
|
||||
@@ -398,7 +398,7 @@
|
||||
|
||||
var/adminrank = "Player"
|
||||
if(usr && usr.client && usr.client.holder)
|
||||
adminrank = usr.client.holder.rank
|
||||
adminrank = usr.client.holder.rank_names()
|
||||
|
||||
|
||||
var/datum/db_query/insert_query = SSdbcore.NewQuery("INSERT INTO erro_poll_vote (id ,datetime ,pollid ,optionid ,ckey ,ip ,adminrank) VALUES (null, Now(), [pollid], [optionid], '[usr.ckey]', '[usr.client.address]', '[adminrank]')")
|
||||
@@ -449,7 +449,7 @@
|
||||
|
||||
var/adminrank = "Player"
|
||||
if(usr && usr.client && usr.client.holder)
|
||||
adminrank = usr.client.holder.rank
|
||||
adminrank = usr.client.holder.rank_names()
|
||||
|
||||
|
||||
replytext = replacetext(replytext, "%BR%", "")
|
||||
@@ -522,7 +522,7 @@
|
||||
|
||||
var/adminrank = "Player"
|
||||
if(usr && usr.client && usr.client.holder)
|
||||
adminrank = usr.client.holder.rank
|
||||
adminrank = usr.client.holder.rank_names()
|
||||
|
||||
|
||||
var/datum/db_query/insert_query = SSdbcore.NewQuery("INSERT INTO erro_poll_vote (id ,datetime ,pollid ,optionid ,ckey ,ip ,adminrank, rating) VALUES (null, Now(), [pollid], [optionid], '[usr.ckey]', '[usr.client.address]', '[adminrank]', [(isnull(rating)) ? "null" : rating])")
|
||||
|
||||
@@ -100,7 +100,7 @@
|
||||
/obj/item/modular_computer/attack_ghost(var/mob/observer/dead/user)
|
||||
if(enabled)
|
||||
tgui_interact(user)
|
||||
else if(check_rights(R_ADMIN|R_EVENT, 0, user))
|
||||
else if(check_rights_for(user.client, R_ADMIN|R_EVENT|R_DEBUG))
|
||||
var/response = tgui_alert(user, "This computer is turned off. Would you like to turn it on?", "Admin Override", list("Yes", "No"))
|
||||
if(response == "Yes")
|
||||
turn_on(user)
|
||||
|
||||
@@ -109,7 +109,7 @@
|
||||
return 1
|
||||
|
||||
// Admin override - allows operation of any computer as aghosted admin, as if you had any required access.
|
||||
if(isobserver(user) && check_rights(R_ADMIN|R_EVENT, 0, user))
|
||||
if(isobserver(user) && check_rights_for(user.client, R_ADMIN|R_EVENT|R_DEBUG))
|
||||
return 1
|
||||
|
||||
if(!istype(user))
|
||||
|
||||
@@ -421,7 +421,7 @@ Extracted to its own procedure for easier logic handling with paper bundles.
|
||||
msg = span_notice(msg)
|
||||
|
||||
for(var/client/C in GLOB.admins)
|
||||
if(check_rights((R_ADMIN|R_MOD|R_EVENT),0,C))
|
||||
if(check_rights_for(C, (R_ADMIN|R_MOD|R_EVENT)))
|
||||
to_chat(C,msg)
|
||||
C << 'sound/machines/printer.ogg'
|
||||
|
||||
|
||||
@@ -75,7 +75,7 @@
|
||||
|
||||
var/client/ghost_client = ghost.client
|
||||
|
||||
if(!is_alien_whitelisted(ghost, GLOB.all_species[ghost_client?.prefs?.species]) && !check_rights(R_ADMIN, 0)) // Prevents a ghost ghosting in on a slot and spawning via a resleever with race they're not whitelisted for, getting around normal join restrictions.
|
||||
if(!is_alien_whitelisted(ghost.client, GLOB.all_species[ghost_client?.prefs?.species]) && !check_rights(R_ADMIN, 0)) // Prevents a ghost ghosting in on a slot and spawning via a resleever with race they're not whitelisted for, getting around normal join restrictions.
|
||||
to_chat(ghost, span_warning("You are not whitelisted to spawn as this species!"))
|
||||
return
|
||||
|
||||
|
||||
@@ -63,13 +63,13 @@
|
||||
else
|
||||
keymsg += " (Ingame)"
|
||||
|
||||
if(R_ADMIN & C.holder.rights && R_BAN & C.holder.rights) // R_ADMIN and R_BAN apparently an admin makes
|
||||
if(check_rights_for(C, R_ADMIN) && check_rights_for(C, R_BAN)) // R_ADMIN and R_BAN apparently an admin makes
|
||||
admin_keys += keymsg
|
||||
|
||||
else if(R_ADMIN & C.holder.rights && !(R_SERVER & C.holder.rights)) // R_ADMIN but not R_SERVER makes a moderator
|
||||
else if(check_rights_for(C, R_ADMIN) && !(check_rights_for(C, R_SERVER))) // R_ADMIN but not R_SERVER makes a moderator
|
||||
mod_keys += keymsg
|
||||
|
||||
else if(R_SERVER & C.holder.rights) // R_SERVER makes a dev
|
||||
else if(check_rights_for(C, R_SERVER)) // R_SERVER makes a dev
|
||||
dev_keys += keymsg
|
||||
|
||||
else // No R_ADMIN&&R_BAN, R_ADMIN!R_BAN, R_SERVER, must be a GM or something
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
current_filter = filter
|
||||
|
||||
/datum/tgui_module/player_notes/proc/open_legacy()
|
||||
var/datum/admins/A = admin_datums[usr.ckey]
|
||||
var/datum/admins/A = GLOB.admin_datums[usr.ckey]
|
||||
A.PlayerNotesLegacy()
|
||||
|
||||
/datum/tgui_module/player_notes/tgui_state(mob/user)
|
||||
@@ -113,7 +113,7 @@
|
||||
if(..())
|
||||
return TRUE
|
||||
|
||||
var/datum/admins/A = admin_datums[usr.ckey]
|
||||
var/datum/admins/A = GLOB.admin_datums[usr.ckey]
|
||||
A.show_player_info_legacy(key)
|
||||
|
||||
/datum/tgui_module/player_notes_info/tgui_act(action, params, datum/tgui/ui)
|
||||
|
||||
@@ -126,7 +126,7 @@
|
||||
return
|
||||
|
||||
var/datum/species/S = GLOB.all_species[new_user.client.prefs.species]
|
||||
if(!is_alien_whitelisted(new_user, S))
|
||||
if(!is_alien_whitelisted(new_user.client, S))
|
||||
tgui_alert(new_user, "You are currently not whitelisted to play [new_user.client.prefs.species].")
|
||||
return 0
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
if(isobserver(user))
|
||||
// Admins can always interact.
|
||||
if(check_rights(R_ADMIN|R_EVENT, 0, src))
|
||||
if(check_rights_for(user.client, R_ADMIN|R_EVENT|R_DEBUG))
|
||||
. = max(., STATUS_INTERACTIVE)
|
||||
|
||||
// Regular ghosts can always at least view if in range.
|
||||
|
||||
@@ -12,6 +12,6 @@
|
||||
GLOBAL_DATUM_INIT(tgui_admin_state, /datum/tgui_state/admin_state, new)
|
||||
|
||||
/datum/tgui_state/admin_state/can_use_topic(src_object, mob/user)
|
||||
if(check_rights_for(user.client, R_ADMIN|R_EVENT))
|
||||
if(check_rights_for(user.client, R_ADMIN|R_EVENT|R_DEBUG))
|
||||
return STATUS_INTERACTIVE
|
||||
return STATUS_CLOSE
|
||||
|
||||
@@ -79,6 +79,6 @@ GLOBAL_DATUM_INIT(tgui_default_state, /datum/tgui_state/default, new)
|
||||
return ..()
|
||||
|
||||
/mob/observer/dead/default_can_use_tgui_topic()
|
||||
if(check_rights(R_ADMIN|R_EVENT, 0, src))
|
||||
if(check_rights_for(src.client, R_ADMIN|R_EVENT|R_DEBUG))
|
||||
return STATUS_INTERACTIVE // Admins are more equal
|
||||
return STATUS_UPDATE // Ghosts can view updates
|
||||
|
||||
@@ -14,6 +14,6 @@ GLOBAL_DATUM_INIT(tgui_observer_state, /datum/tgui_state/observer_state, new)
|
||||
/datum/tgui_state/observer_state/can_use_topic(src_object, mob/user)
|
||||
if(isobserver(user))
|
||||
return STATUS_INTERACTIVE
|
||||
if(check_rights(R_ADMIN|R_EVENT, 0, src))
|
||||
if(check_rights_for(user.client, R_ADMIN|R_EVENT))
|
||||
return STATUS_INTERACTIVE
|
||||
return STATUS_CLOSE
|
||||
|
||||
@@ -169,7 +169,7 @@
|
||||
data["question"] = question
|
||||
data["choices"] = choices
|
||||
|
||||
if(show_counts || check_rights(R_ADMIN, FALSE, user))
|
||||
if(show_counts || check_rights_for(user.client, R_ADMIN))
|
||||
data["show_counts"] = TRUE
|
||||
|
||||
var/list/counts = list()
|
||||
|
||||
@@ -97,4 +97,4 @@
|
||||
|
||||
|
||||
/proc/whitelist_overrides(mob/M)
|
||||
return !config.usealienwhitelist || check_rights(R_ADMIN|R_EVENT, 0, M)
|
||||
return !config.usealienwhitelist || check_rights_for(M.client, R_ADMIN|R_EVENT)
|
||||
|
||||
Reference in New Issue
Block a user