From bbe7354265b7695388eebd3acef452da9bfd56dc Mon Sep 17 00:00:00 2001 From: carnie Date: Sun, 11 Aug 2013 20:43:18 +0100 Subject: [PATCH] Fixes #1147 - type-mismatch 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! --- code/__DEFINES.dm | 5 - code/__HELPERS/text.dm | 18 +- code/__HELPERS/type2type.dm | 15 +- code/modules/admin/admin_ranks.dm | 290 +++++++++++++----- code/modules/admin/admin_verbs.dm | 32 +- code/modules/admin/holder2.dm | 42 +-- .../admin/permissionverbs/permissionedit.dm | 60 ++-- code/modules/admin/topic.dm | 93 +----- code/modules/client/preferences.dm | 2 +- code/modules/mob/mob.dm | 2 +- config/admin_ranks.txt | 38 +-- config/admins.txt | 59 ++-- 12 files changed, 335 insertions(+), 321 deletions(-) diff --git a/code/__DEFINES.dm b/code/__DEFINES.dm index b5f7a43b1c3..dd7905829d5 100644 --- a/code/__DEFINES.dm +++ b/code/__DEFINES.dm @@ -389,11 +389,6 @@ var/list/TAGGERLOCATIONS = list("Disposals", #define R_MAXPERMISSION 4096 //This holds the maximum value for a permission. It is used in iteration, so keep it updated. - -//IMPORTANT! The permissions system supports flags up to 2^30 (possibly 2^31), HOWEVER, once the flag 65536 -//starts being used, an edit to rights2text(rights, seperator="") needs to happen! The edit is prepared -//and commented out. Please uncomment it before assigning that flag. Once you do, delete this note. ~Errorage - //Preference toggles #define SOUND_ADMINHELP 1 #define SOUND_MIDI 2 diff --git a/code/__HELPERS/text.dm b/code/__HELPERS/text.dm index 88c1be1a59d..7b7ba3f78ba 100644 --- a/code/__HELPERS/text.dm +++ b/code/__HELPERS/text.dm @@ -368,11 +368,11 @@ var/list/binary = list("0","1") if(!istext(into)) into = "" if(!istext(from)) from = "" var/null_ascii = istext(null_char) ? text2ascii(null_char,1) : null_char - + var/previous = 0 var/start = 1 var/end = length(into) + 1 - + for(var/i=1, i= 65536) - var/rights_pt2 = rights / 65536 - if(rights_pt2 & 1) .+= "[seperator]+NUKESERVER" - if(rights_pt2 & 2) .+= "[seperator]+DDOSALLPLAYERS" - if(rights_pt2 & 4) .+= "[seperator]+SPAWN_RL_SINGULARITY" - */ - +/proc/rights2text(rights, seperator="", list/adds, list/subs) if(rights & R_BUILDMODE) . += "[seperator]+BUILDMODE" if(rights & R_ADMIN) . += "[seperator]+ADMIN" if(rights & R_BAN) . += "[seperator]+BAN" @@ -245,6 +237,11 @@ proc/tg_list2text(list/list, glue=",") if(rights & R_VAREDIT) . += "[seperator]+VAREDIT" if(rights & R_SOUNDS) . += "[seperator]+SOUND" if(rights & R_SPAWN) . += "[seperator]+SPAWN" + + for(var/verbpath in adds) + . += "[seperator]+[verbpath]" + for(var/verbpath in subs) + . += "[seperator]-[verbpath]" return . /proc/ui_style2icon(ui_style) diff --git a/code/modules/admin/admin_ranks.dm b/code/modules/admin/admin_ranks.dm index 0f02fe9cdb3..e8cd48844c5 100644 --- a/code/modules/admin/admin_ranks.dm +++ b/code/modules/admin/admin_ranks.dm @@ -1,57 +1,106 @@ -var/list/admin_ranks = list() //list of all ranks with associated rights +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() - var/previous_rights = 0 + 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 - //load text from file - var/list/Lines = file2list("config/admin_ranks.txt") + var/next = findtext(line, "=") + var/datum/admin_rank/R = new(ckeyEx(copytext(line, 1, next))) + if(!R) continue + admin_ranks += R - //process each line seperately - for(var/line in Lines) - if(!length(line)) continue - if(copytext(line,1,2) == "#") continue + 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/list/List = text2list(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 |= ((2 * R_MAXPERMISSION) - 1) - if("sound","sounds") rights |= R_SOUNDS - if("spawn","create") rights |= R_SPAWN - - /* --ONCE FLAGS LARGER OR EQUAL THAN 2^16 = 65536 START BEING USED, USE THIS CODE! - if("nukeeverything") rights += R_NUKEEVERYTHING - */ - - admin_ranks[rank] = rights - previous_rights = rights + 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/rank in admin_ranks) - msg += "\t[rank] - [admin_ranks[rank]]\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 @@ -63,43 +112,39 @@ var/list/admin_ranks = list() //list of all ranks with associated rights 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_admin_ranks() - //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(copytext(line,1,2) == "#") continue + if(findtextEx(line,"#",1,2)) continue - //Split the line at every "-" - var/list/List = text2list(line, "-") + //Split the line at every "=" + var/list/List = text2list(line, "=") if(!List.len) continue - //ckey is before the first "-" + //ckey is before the first "=" var/ckey = ckey(List[1]) if(!ckey) continue - //rank follows the first "-" + //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(directory[ckey]) + 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 - //The current admin system uses SQL - establish_db_connection() if(!dbcon.IsConnected()) world.log << "Failed to connect to database in load_admins(). Reverting to legacy system." @@ -108,33 +153,20 @@ var/list/admin_ranks = list() //list of all ranks with associated rights load_admins() return - var/DBQuery/query = dbcon.NewQuery("SELECT ckey, rank, level, flags FROM erro_admin") + var/DBQuery/query = dbcon.NewQuery("SELECT ckey, rank 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(directory[ckey]) - if(!admin_datums) - world.log << "The database query in load_admins() resulted in no admins being added to the list. Reverting to legacy system." - diary << "The database query in load_admins() resulted in no admins being added to the list. Reverting to legacy system." - config.admin_legacy_system = 1 - load_admins() - return + 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/rank var/datum/admins/D = admin_datums[ckey] - if(D) rank = D.rank - msg += "\t[ckey] - [rank]\n" + msg += "\t[ckey] - [D.rank.name]\n" testing(msg) #endif @@ -143,18 +175,110 @@ var/list/admin_ranks = list() //list of all ranks with associated rights /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) + holder = new /datum/admins(newrank,ckey) remove_admin_verbs() holder.associate(src) /client/verb/changerights(newrights as num) if(holder) - holder.rights = newrights + 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 << "Error: Topic 'editrights': [new_ckey] is already an admin" + return + adm_ckey = new_ckey + task = "rank" + else + adm_ckey = ckey(href_list["ckey"]) + if(!adm_ckey) + usr << "Error: Topic 'editrights': No valid ckey" + 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() \ No newline at end of file diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index c8848ddba8b..354f2cd9720 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -198,19 +198,25 @@ var/list/admin_verbs_hideable = list( /client/proc/add_admin_verbs() if(holder) + var/rights = holder.rank.rights verbs += admin_verbs_default - if(holder.rights & R_BUILDMODE) verbs += /client/proc/togglebuildmodeself - if(holder.rights & R_ADMIN) verbs += admin_verbs_admin - if(holder.rights & R_BAN) verbs += admin_verbs_ban - if(holder.rights & R_FUN) verbs += admin_verbs_fun - if(holder.rights & R_SERVER) verbs += admin_verbs_server - if(holder.rights & R_DEBUG) verbs += admin_verbs_debug - if(holder.rights & R_POSSESS) verbs += admin_verbs_possess - if(holder.rights & R_PERMISSIONS) verbs += admin_verbs_permissions - if(holder.rights & R_STEALTH) verbs += /client/proc/stealth - if(holder.rights & R_REJUVINATE) verbs += admin_verbs_rejuv - if(holder.rights & R_SOUNDS) verbs += admin_verbs_sounds - if(holder.rights & R_SPAWN) verbs += admin_verbs_spawn + if(rights & R_BUILDMODE) verbs += /client/proc/togglebuildmodeself + if(rights & R_ADMIN) verbs += admin_verbs_admin + if(rights & R_BAN) verbs += admin_verbs_ban + if(rights & R_FUN) verbs += admin_verbs_fun + if(rights & R_SERVER) verbs += admin_verbs_server + if(rights & R_DEBUG) verbs += admin_verbs_debug + if(rights & R_POSSESS) verbs += admin_verbs_possess + if(rights & R_PERMISSIONS) verbs += admin_verbs_permissions + if(rights & R_STEALTH) verbs += /client/proc/stealth + if(rights & R_REJUVINATE) verbs += admin_verbs_rejuv + if(rights & R_SOUNDS) verbs += admin_verbs_sounds + if(rights & R_SPAWN) verbs += admin_verbs_spawn + + for(var/path in holder.rank.adds) + verbs += path + for(var/path in holder.rank.subs) + verbs -= path /client/proc/remove_admin_verbs() verbs.Remove( @@ -246,6 +252,8 @@ var/list/admin_verbs_hideable = list( /client/proc/kaboom, /client/proc/cmd_admin_areatest ) + if(holder) + verbs.Remove(holder.rank.adds) /client/proc/hide_most_verbs()//Allows you to keep some functionality while hiding some verbs set name = "Adminverbs - Hide Most" diff --git a/code/modules/admin/holder2.dm b/code/modules/admin/holder2.dm index 00c77eb7d78..cd84af74980 100644 --- a/code/modules/admin/holder2.dm +++ b/code/modules/admin/holder2.dm @@ -1,9 +1,9 @@ var/list/admin_datums = list() /datum/admins - var/rank = "Temporary Admin" + var/datum/admin_rank/rank + var/client/owner = null - var/rights = 0 var/fakekey = null var/datum/marked_datum @@ -13,14 +13,17 @@ var/list/admin_datums = list() var/datum/feed_channel/admincaster_feed_channel = new /datum/feed_channel var/admincaster_signature //What you'll sign the newsfeeds as -/datum/admins/New(initial_rank = "Temporary Admin", initial_rights = 0, ckey) +/datum/admins/New(datum/admin_rank/R, ckey) if(!ckey) error("Admin datum created without a ckey argument. Datum has been deleted") del(src) return + if(!istype(R)) + error("Admin datum created without a rank. Datum has been deleted") + del(src) + return + rank = R admincaster_signature = "Nanotrasen Officer #[rand(0,9)][rand(0,9)][rand(0,9)]" - rank = initial_rank - rights = initial_rights admin_datums[ckey] = src /datum/admins/proc/associate(client/C) @@ -65,14 +68,10 @@ you will have to do something like if(client.rights & R_ADMIN) yourself. if(usr.client.holder) if(!other || !other.holder) return 1 - - var/usr_rights_pt2 = usr.client.holder.rights / 65536 - var/other_rights_pt2 = other.holder.rights / 65536 - if( (usr_rights_pt2 & other_rights_pt2) == other_rights_pt2 ) //Check values larger than 65535 - if(usr.client.holder.rights != other.holder.rights) //Check values smaller than 65536 - if( (usr.client.holder.rights & other.holder.rights) == other.holder.rights ) - return 1 //we have all the rights they have and more - usr << "Error: Cannot proceed. They have more or equal rights to us." + if(usr.client.holder.rank.rights != other.holder.rank.rights) //Check values smaller than 65536 + if( (usr.client.holder.rank.rights & other.holder.rank.rights) == other.holder.rank.rights ) + return 1 //we have all the rights they have and more + usr << "Error: Cannot proceed. They have greater or equal rights to us." return 0 @@ -85,17 +84,8 @@ you will have to do something like if(client.rights & R_ADMIN) yourself. //This proc checks whether subject has at least ONE of the rights specified in rights_required. /proc/check_rights_for(client/subject, rights_required) - if(subject) - if(rights_required) - if(subject.holder) - if(rights_required >= 65536) - var/rights_required_pt2 = rights_required / 65536 - var/rights_pt2 = subject.holder.rights / 65536 - if(rights_required_pt2 & rights_pt2) - return 1 - if(rights_required & subject.holder.rights) - return 1 - else - if(subject.holder) - return 1 + if(subject && subject.holder && subject.holder.rank) + if(rights_required && !(rights_required & subject.holder.rank.rights)) + return 0 + return 1 return 0 \ No newline at end of file diff --git a/code/modules/admin/permissionverbs/permissionedit.dm b/code/modules/admin/permissionverbs/permissionedit.dm index 26d1c8b88cf..174dba2ddd7 100644 --- a/code/modules/admin/permissionverbs/permissionedit.dm +++ b/code/modules/admin/permissionverbs/permissionedit.dm @@ -19,21 +19,24 @@
- + + + "} 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," ") + + var/rights = rights2text(D.rank.rights," ") if(!rights) rights = "*none*" - + output += "" output += "" - output += "" - output += "" + output += "" + output += "" + output += "" output += "" output += {" @@ -42,7 +45,7 @@ "} - usr << browse(output,"window=editrights;size=600x500") + usr << browse(output,"window=editrights;size=900x650") /datum/admins/proc/log_admin_rank_modification(var/adm_ckey, var/new_rank) if(config.admin_legacy_system) return @@ -93,55 +96,30 @@ log_query.Execute() usr << "\blue Admin rank changed." + /datum/admins/proc/log_admin_permission_modification(var/adm_ckey, var/new_permission) if(config.admin_legacy_system) return - - if(!usr.client) - return - - if (check_rights(R_PERMISSIONS)) - return + if(!usr.client) return + if(check_rights(R_PERMISSIONS)) return establish_db_connection() if(!dbcon.IsConnected()) usr << "\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)) + if(!adm_ckey || !istext(adm_ckey) || !isnum(new_permission)) return var/DBQuery/select_query = dbcon.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]) - if(!admin_id) - return + if(!admin_id) return - if(admin_rights & new_permission) //This admin already has this permission, so we are removing it. - var/DBQuery/insert_query = dbcon.NewQuery("UPDATE `erro_admin` SET flags = [admin_rights & ~new_permission] WHERE id = [admin_id]") - insert_query.Execute() - var/DBQuery/log_query = dbcon.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() - usr << "\blue Permission removed." - else //This admin doesn't have this permission, so we are adding it. - var/DBQuery/insert_query = dbcon.NewQuery("UPDATE `erro_admin` SET flags = '[admin_rights | new_permission]' WHERE id = [admin_id]") - insert_query.Execute() - var/DBQuery/log_query = dbcon.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() - usr << "\blue Permission added." \ No newline at end of file + var/DBQuery/insert_query = dbcon.NewQuery("UPDATE `erro_admin` SET flags = [new_permission] WHERE id = [admin_id]") + insert_query.Execute() + var/DBQuery/log_query = dbcon.NewQuery("INSERT INTO `test`.`erro_admin_log` (`id` ,`datetime` ,`adminckey` ,`adminip` ,`log` ) VALUES (NULL , NOW( ) , '[usr.ckey]', '[usr.client.address]', 'Edit permission [rights2text(new_permission)] (flag = [new_permission]) to admin [adm_ckey]');") + log_query.Execute() diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm index d0e4d15b2ba..2b68a0f4583 100644 --- a/code/modules/admin/topic.dm +++ b/code/modules/admin/topic.dm @@ -146,98 +146,7 @@ DB_ban_record(bantype, playermob, banduration, banreason, banjob, null, banckey, banip, bancid ) 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(input(usr,"New admin's ckey","Admin ckey", null) as text|null) - if(!new_ckey) return - if(new_ckey in admin_datums) - usr << "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) - usr << "Error: Topic 'editrights': No valid ckey" - return - - var/datum/admins/D = admin_datums[adm_ckey] - - if(task == "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") - - else if(task == "rank") - var/new_rank - if(admin_ranks.len) - new_rank = input("Please select a rank", "New rank", null, null) as null|anything in (admin_ranks|"*New Rank*") - else - new_rank = input("Please select a rank", "New rank", null, null) as null|anything in 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 = input("Please input a new rank", "New custom rank", null, null) as null|text - if(config.admin_legacy_system) - new_rank = ckeyEx(new_rank) - if(!new_rank) - usr << "Error: Topic 'editrights': Invalid rank" - return - if(config.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.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 = 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 = input("Select a permission to turn on/off", "Permission toggle", null, null) as null|anything in 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)) return diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index 54d2f35038a..2dc35b85ce4 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -210,7 +210,7 @@ datum/preferences dat += "Adminhelp Sound: " dat += "[(toggles & SOUND_ADMINHELP)?"On":"Off"]
" - if(unlock_content || check_rights_for(user, R_ADMIN)) + if(unlock_content || check_rights_for(user.client, R_ADMIN)) dat += "OOC:   Change
" if(unlock_content) diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 25db03a46ab..e7db4dce795 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -380,7 +380,7 @@ var/list/slot_equipment_priority = list( \ set category = "OOC" var/is_admin = 0 - if(client.holder && (client.holder.rights & R_ADMIN)) + if(check_rights_for(client,R_ADMIN)) is_admin = 1 else if(stat != DEAD || istype(src, /mob/new_player)) usr << "\blue You must be observing to use this!" diff --git a/config/admin_ranks.txt b/config/admin_ranks.txt index 2a33adb3b80..67c08182b01 100644 --- a/config/admin_ranks.txt +++ b/config/admin_ranks.txt @@ -1,15 +1,15 @@ -######################################################################################## -# ADMIN RANK DEFINES # -# The format of this is very simple. Rank name goes first. # -# Rank is CASE-SENSITIVE, all punctuation will be stripped so spaces don't matter. # -# Each rank is then followed by keywords with the prefix "+". # -# These keywords represent groups of verbs and abilities which are given to that rank. # -# +@ (or +prev) is a special shorthand which adds all the rights of the rank above it. # -# Ranks with no keywords will just be given the most basic verbs and abilities ~Carn # -######################################################################################## +############################################################################################################## +# ADMIN RANK DEFINES # +# The format of this is very simple. Rank name goes first. # +# Rank is CASE-SENSITIVE, all punctuation save for '-', '_' and '@' will be stripped so spaces don't matter. # +# You can then define permissions for each rank by adding a '=' followed by keywords # +# These keywords represent groups of verbs and abilities. # +# keywords are preceded by either a '+' or a '-', + adds permissions, - takes them away. # +# +@ (or +prev) is a special shorthand which adds all the rights of the rank above it. # +# You can also specify verbs like so +/client/proc/some_added_verb or -/client/proc/some_restricted_verb # +# Ranks with no keywords will just be given the most basic verbs and abilities ~Carn # +############################################################################################################## # PLEASE NOTE: depending on config options, some abilities will be unavailable regardless if you have permission to use them! -# ALSO NOTE: this is a WorkInProgress at the moment. Most of this is just arbitrarily thrown in whatever group because LoadsaWork2Do+LittleTime. -# I'll be doing more moving around as feedback comes in. So be sure to check the notes after updates. # KEYWORDS: # +ADMIN = general admin tools, verbs etc @@ -28,13 +28,13 @@ # +EVERYTHING (or +HOST or +ALL) = Simply gives you everything without having to type every flag Admin Observer -Moderator +ADMIN -Admin Candidate +@ -Trial Admin +@ +SPAWN +REJUV +VAREDIT +BAN -Badmin +@ +POSSESS +BUILDMODE +SERVER +FUN -Game Admin +@ +STEALTH +SOUNDS +DEBUG -Game Master +EVERYTHING +Moderator = +ADMIN +Admin Candidate = +@ +Trial Admin = +@ +SPAWN +REJUV +VAREDIT +BAN +Badmin = +@ +POSSESS +BUILDMODE +SERVER +FUN +Game Admin = +@ +STEALTH +SOUNDS +DEBUG +Game Master = +EVERYTHING -Host +EVERYTHING +Host = +EVERYTHING -Coder +DEBUG +VAREDIT +SERVER +SPAWN \ No newline at end of file +Coder = +DEBUG +VAREDIT +SERVER +SPAWN \ No newline at end of file diff --git a/config/admins.txt b/config/admins.txt index 121cad72d0d..47a6a1e9acf 100644 --- a/config/admins.txt +++ b/config/admins.txt @@ -1,29 +1,32 @@ -###################################################################### -# Basically, ckey goes first. Rank goes after the "-" # -# Case is not important for ckey. # -# Case IS important for the rank. However punctuation/spaces are not # -# Ranks can be anything defined in admin_ranks.txt ~Carn # -###################################################################### +############################################################################################### +# Basically, ckey goes first. Rank goes after the "=" # +# Case is not important for ckey. # +# Case IS important for the rank. # +# All punctuation (spaces etc) EXCEPT '-', '_' and '@' will be stripped from rank names. # +# Ranks can be anything defined in admin_ranks.txt # +# NOTE: if the rank-name cannot be found in admin_ranks.txt, they will not be adminned! ~Carn # +# NOTE: syntax was changed to allow hyphenation of ranknames, since spaces are stripped. # +############################################################################################### -quarxink - Game Master -tle - Game Master -xsi - Game Master -scaredofshadows - Game Master -neofite - Game Master -trubblebass - Game Master -mport2004 - Game Master -deuryn - Game Master -agouri - Game Master -errorage - Game Master -superxpdude - Game Master -petethegoat - Game Master -korphaeron - Game Master -nodrak - Game Master -carnwennan - Game Master -ikarrus - Game Master -cheridan - Game Master -giacomand - Game Master -rockdtben - Game Master -sieve - Game Master -aranclanos - Game Master -intigracy - Game Master \ No newline at end of file +quarxink = Game Master +tle = Game Master +xsi = Game Master +scaredofshadows = Game Master +neofite = Game Master +trubblebass = Game Master +mport2004 = Game Master +deuryn = Game Master +agouri = Game Master +errorage = Game Master +superxpdude = Game Master +petethegoat = Game Master +korphaeron = Game Master +nodrak = Game Master +carnwennan = Game Master +ikarrus = Game Master +cheridan = Game Master +giacomand = Game Master +rockdtben = Game Master +sieve = Game Master +aranclanos = Game Master +intigracy = Game Master \ No newline at end of file
CKEY \[+\]RANKPERMISSIONSRANKPERMISSIONSVERB-OVERRIDES
[adm_ckey] \[-\][rank][rights][D.rank.name][rights][rights2text(0," ",D.rank.adds,D.rank.subs)]