mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-31 12:01:47 +00:00
Added helper: /proc/findchar(haystack, needles, start=1, end=0) works like findtext except it finds the first occurrence of one of the characters from the needles string, within haystack. Permissions can now be removed as well as added, by replacing the + with a -. e.g. +BAN adds bans permissions, -BAN removes them. This applies to admin_ranks.txt and the permissions panel. Verb overrides are now possible for admins_ranks. Specific verbs can be forced-on, or forced-off via keywords like +/client/proc/mimespeak or -/client/verb/ooc. This applies both to admin_ranks.txt and the permissions panel. SQL system is not compatible. admin_ranks are now datums. This means admin_ranks actually behave more like permission groups as intended. When you temporarily modify an admin's permissions via the permissions panel, their rank_name is appended with "([ckey])". This prevents modifications to their rights affecting everyone. admin rank names now support - _ and @ characters (since ckeyEx() does not strip these). SQL permissions system was modified. SQL databases will have to be updated or they will no longer work. WARNING: admin_ranks.txt and admins.txt format has changed slightly! You will need to redo those txt files!
284 lines
9.4 KiB
Plaintext
284 lines
9.4 KiB
Plaintext
var/list/admin_ranks = list() //list of all admin_rank datums
|
|
|
|
/datum/admin_rank
|
|
var/name = "NoRank"
|
|
var/rights = 0
|
|
var/list/adds
|
|
var/list/subs
|
|
|
|
/datum/admin_rank/New(init_name, init_rights, list/init_adds, list/init_subs)
|
|
name = init_name
|
|
switch(name)
|
|
if("Removed",null,"")
|
|
error("invalid admin-rank name. datum deleted")
|
|
del(src)
|
|
if(init_rights) rights = init_rights
|
|
if(!init_adds) init_adds = list()
|
|
if(!init_subs) init_subs = list()
|
|
adds = init_adds
|
|
subs = init_subs
|
|
|
|
/datum/admin_rank/proc/process_keyword(word, previous_rights=0)
|
|
var/flag = 0
|
|
switch(ckey(word))
|
|
if("buildmode","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","rights") flag = R_PERMISSIONS
|
|
if("possess") flag = R_POSSESS
|
|
if("stealth") flag = R_STEALTH
|
|
if("rejuv","rejuvinate") flag = R_REJUVINATE
|
|
if("varedit") flag = R_VAREDIT
|
|
if("everything","host","all") flag = 65535
|
|
if("sound","sounds") flag = R_SOUNDS
|
|
if("spawn","create") flag = R_SPAWN
|
|
if("@","prev") flag = previous_rights
|
|
else
|
|
//isn't a keyword so maybe it's a verbpath?
|
|
var/path = text2path(copytext(word,2,findtext(word," ",2,0)))
|
|
if(path)
|
|
switch(text2ascii(word,1))
|
|
if(43)
|
|
if(!subs.Remove(path))
|
|
adds += path //+
|
|
if(45)
|
|
if(!adds.Remove(path))
|
|
subs += path //-
|
|
return
|
|
switch(text2ascii(word,1))
|
|
if(43) rights |= flag //+
|
|
if(45) rights &= ~flag //-
|
|
return
|
|
|
|
//load our rank - > rights associations
|
|
/proc/load_admin_ranks()
|
|
admin_ranks.Cut()
|
|
|
|
if(config.admin_legacy_system)
|
|
var/previous_rights = 0
|
|
//load text from file and process each line seperately
|
|
for(var/line in file2list("config/admin_ranks.txt"))
|
|
if(!line) continue
|
|
if(findtextEx(line,"#",1,2)) continue
|
|
|
|
var/next = findtext(line, "=")
|
|
var/datum/admin_rank/R = new(ckeyEx(copytext(line, 1, next)))
|
|
if(!R) continue
|
|
admin_ranks += R
|
|
|
|
var/prev = findchar(line, "+-", next, 0)
|
|
while(prev)
|
|
next = findchar(line, "+-", prev+1, 0)
|
|
R.process_keyword(copytext(line, prev, next), previous_rights)
|
|
prev = next
|
|
|
|
previous_rights = R.rights
|
|
else
|
|
establish_db_connection()
|
|
if(!dbcon.IsConnected())
|
|
world.log << "Failed to connect to database in load_admin_ranks(). Reverting to legacy system."
|
|
diary << "Failed to connect to database in load_admin_ranks(). Reverting to legacy system."
|
|
config.admin_legacy_system = 1
|
|
load_admin_ranks()
|
|
return
|
|
|
|
var/DBQuery/query = dbcon.NewQuery("SELECT rank, flags FROM erro_admin_ranks")
|
|
query.Execute()
|
|
while(query.NextRow())
|
|
var/rank_name = ckeyEx(query.item[1])
|
|
var/flags = query.item[2]
|
|
if(istext(flags)) flags = text2num(flags)
|
|
var/datum/admin_rank/R = new(rank_name, flags)
|
|
if(!R) continue
|
|
admin_ranks += R
|
|
|
|
#ifdef TESTING
|
|
var/msg = "Permission Sets Built:\n"
|
|
for(var/datum/admin_rank/R in admin_ranks)
|
|
msg += "\t[R.name]"
|
|
var/rights = rights2text(R.rights,"\n\t\t",R.adds,R.subs)
|
|
if(rights) msg += "\t\t[rights]\n"
|
|
testing(msg)
|
|
#endif
|
|
|
|
|
|
/proc/load_admins()
|
|
//clear the datums references
|
|
admin_datums.Cut()
|
|
for(var/client/C in admins)
|
|
C.remove_admin_verbs()
|
|
C.holder = null
|
|
admins.Cut()
|
|
load_admin_ranks()
|
|
|
|
var/list/rank_names = list()
|
|
for(var/datum/admin_rank/R in admin_ranks)
|
|
rank_names[R.name] = R
|
|
|
|
if(config.admin_legacy_system)
|
|
//load text from file
|
|
var/list/Lines = file2list("config/admins.txt")
|
|
|
|
//process each line seperately
|
|
for(var/line in Lines)
|
|
if(!length(line)) continue
|
|
if(findtextEx(line,"#",1,2)) continue
|
|
|
|
//Split the line at every "="
|
|
var/list/List = text2list(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])
|
|
|
|
var/datum/admins/D = new(rank_names[rank], ckey) //create the admin datum and store it for later use
|
|
if(!D) continue //will occur if an invalid rank is provided
|
|
D.associate(directory[ckey]) //find the client for a ckey if they are connected and associate them with the new admin datum
|
|
|
|
else
|
|
establish_db_connection()
|
|
if(!dbcon.IsConnected())
|
|
world.log << "Failed to connect to database in load_admins(). Reverting to legacy system."
|
|
diary << "Failed to connect to database in load_admins(). Reverting to legacy system."
|
|
config.admin_legacy_system = 1
|
|
load_admins()
|
|
return
|
|
|
|
var/DBQuery/query = dbcon.NewQuery("SELECT ckey, rank FROM erro_admin")
|
|
query.Execute()
|
|
while(query.NextRow())
|
|
var/ckey = ckey(query.item[1])
|
|
var/rank = ckeyEx(query.item[2])
|
|
var/datum/admins/D = new(rank, ckey) //create the admin datum and store it for later use
|
|
if(!D) continue //will occur if an invalid rank is provided
|
|
D.associate(directory[ckey]) //find the client for a ckey if they are connected and associate them with the new admin datum
|
|
|
|
#ifdef TESTING
|
|
var/msg = "Admins Built:\n"
|
|
for(var/ckey in admin_datums)
|
|
var/datum/admins/D = admin_datums[ckey]
|
|
msg += "\t[ckey] - [D.rank.name]\n"
|
|
testing(msg)
|
|
#endif
|
|
|
|
|
|
#ifdef TESTING
|
|
/client/verb/changerank(newrank in admin_ranks)
|
|
if(holder)
|
|
holder.rank = newrank
|
|
else
|
|
holder = new /datum/admins(newrank,ckey)
|
|
remove_admin_verbs()
|
|
holder.associate(src)
|
|
|
|
/client/verb/changerights(newrights as num)
|
|
if(holder)
|
|
holder.rank.rights = newrights
|
|
else
|
|
holder = new /datum/admins("testing",newrights,ckey)
|
|
remove_admin_verbs()
|
|
holder.associate(src)
|
|
|
|
#endif
|
|
|
|
/datum/admins/proc/edit_rights_topic(list/href_list)
|
|
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"]
|
|
switch(task)
|
|
if("add")
|
|
var/new_ckey = ckey(input(usr,"New admin's ckey","Admin ckey", null) as text|null)
|
|
if(!new_ckey) return
|
|
if(new_ckey in admin_datums)
|
|
usr << "<font color='red'>Error: Topic 'editrights': [new_ckey] is already an admin</font>"
|
|
return
|
|
adm_ckey = new_ckey
|
|
task = "rank"
|
|
else
|
|
adm_ckey = ckey(href_list["ckey"])
|
|
if(!adm_ckey)
|
|
usr << "<font color='red'>Error: Topic 'editrights': No valid ckey</font>"
|
|
return
|
|
|
|
var/datum/admins/D = admin_datums[adm_ckey]
|
|
|
|
switch(task)
|
|
if("remove")
|
|
if(alert("Are you sure you want to remove [adm_ckey]?","Message","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")
|
|
|
|
if("rank")
|
|
var/datum/admin_rank/R
|
|
|
|
var/list/rank_names = list("*New Rank*")
|
|
for(R in admin_ranks)
|
|
rank_names[R.name] = R
|
|
|
|
var/new_rank = input("Please select a rank", "New rank", null, null) as null|anything in rank_names
|
|
|
|
switch(new_rank)
|
|
if(null) return
|
|
if("*New Rank*")
|
|
new_rank = ckeyEx(input("Please input a new rank", "New custom rank", null, null) as null|text)
|
|
if(!new_rank) return
|
|
|
|
R = rank_names[new_rank]
|
|
if(!R) //rank with that name doesn't exist yet - make it
|
|
if(D) R = new(new_rank, D.rank.rights, D.rank.adds, D.rank.subs) //duplicate our previous admin_rank but with a new name
|
|
else R = new(new_rank) //blank new admin_rank
|
|
admin_ranks += R
|
|
|
|
if(D) //they were previously an admin
|
|
D.disassociate() //existing admin needs to be disassociated
|
|
D.rank = R //set the admin_rank as our rank
|
|
else
|
|
D = new(R,adm_ckey) //new admin
|
|
|
|
var/client/C = 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)
|
|
|
|
if("permissions")
|
|
if(!D) return //they're not an admin!
|
|
|
|
var/keyword = input("Input permission keyword (one at a time):\ne.g. +BAN or -FUN or +/client/proc/someverb", "Permission toggle", null, null) as null|text
|
|
if(!keyword) return
|
|
|
|
D.disassociate()
|
|
|
|
if(!findtext(D.rank.name, "([adm_ckey])")) //not a modified subrank, need to duplicate the admin_rank datum to prevent modifying others too
|
|
D.rank = new("[D.rank.name]([adm_ckey])", D.rank.rights, D.rank.adds, D.rank.subs) //duplicate our previous admin_rank but with a new name
|
|
//we don't add this clone to the admin_ranks list, as it is unique to that ckey
|
|
|
|
D.rank.process_keyword(keyword)
|
|
|
|
var/client/C = 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(usr)] added keyword [keyword] to permission of [adm_ckey]")
|
|
log_admin("[key_name(usr)] added keyword [keyword] to permission of [adm_ckey]")
|
|
log_admin_permission_modification(adm_ckey, D.rank.rights)
|
|
|
|
edit_admin_permissions() |