diff --git a/code/defines/procs/helper_list.dm b/code/defines/procs/helper_list.dm index cfc9a6edefe..827a6348c26 100644 --- a/code/defines/procs/helper_list.dm +++ b/code/defines/procs/helper_list.dm @@ -286,4 +286,22 @@ proc/listclearnulls(list/list) if(Li <= L.len) return (result + L.Copy(Li, 0)) - return (result + R.Copy(Ri, 0)) \ No newline at end of file + return (result + R.Copy(Ri, 0)) + + +//Converts a bitfield to a list of numbers (or words if a wordlist is provided) +/proc/bitfield2list(bitfield = 0, list/wordlist) + var/list/r = list() + if(istype(wordlist,/list)) + var/max = min(wordlist.len,16) + var/bit = 1 + for(var/i=1, i<=max, i++) + if(bitfield & bit) + r += wordlist[i] + bit = bit << 1 + else + for(var/bit=1, bit<=65535, bit = bit << 1) + if(bitfield & bit) + r += bit + + return r \ No newline at end of file diff --git a/code/global.dm b/code/global.dm index 5b77d1acc8c..698fa2397f2 100644 --- a/code/global.dm +++ b/code/global.dm @@ -205,3 +205,31 @@ var/forum_authenticated_group = "10" // For FTP requests. (i.e. downloading runtime logs.) // However it'd be ok to use for accessing attack logs and such too, which are even laggier. var/fileaccess_timer = 1800 //Cannot access files by ftp until the game is finished setting up and stuff. + + +#define BUILDMODE 1 +#define ADMIN 2 +#define BAN 4 +#define FUN 8 +#define SERVER 16 +#define ADMDEBUG 32 +#define POSSESS 64 +#define PERMISSIONS 128 +//Keep this list synced with the #defines above +var/global/list/permissionwords = list("BUILDMODE", "ADMIN", "BAN", "FUN", "SERVER", "DEBUG", "POSSESS", "EDITPERMISSIONS") + + + +//Please do not edit these values. The database assigning proper rights relies on this. You can add new values, just don't change existing ones. +//This list is separate from the list used ingame, so that one can be edited with little consequence. This one is tied to the database +//The database admins should be consulted before any edits to this list. +#define SQL_BUILDMODE 1 +#define SQL_ADMIN 2 +#define SQL_BAN 4 +#define SQL_FUN 8 +#define SQL_SERVER 16 +#define SQL_DEBUG 32 +#define SQL_POSSESS 64 +#define SQL_PERMISSIONS 128 +//Same rules apply to this list as to the values above. You can only add stuff to it. +var/global/list/permissionwords_sql = list("BUILDMODE", "ADMIN", "BAN", "FUN", "SERVER", "DEBUG", "POSSESS", "EDITPERMISSIONS") \ No newline at end of file diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index 7171236bb9f..bd66109623e 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -40,6 +40,7 @@ if(!need_update) return clear_admin_verbs() + handle_permission_verbs() switch(rank) if("Game Master") diff --git a/code/modules/admin/holder2.dm b/code/modules/admin/holder2.dm index c10d4b494fc..7949e046dca 100644 --- a/code/modules/admin/holder2.dm +++ b/code/modules/admin/holder2.dm @@ -19,6 +19,7 @@ var/list/admin_datums = list() var/fakekey = null var/ooccolor = "#b82e00" var/sound_adminhelp = 0 //If set to 1 this will play a sound when adminhelps are received. + var/sql_permissions = 0 //Permissions for different admin command groups. Must not be editable ingame. var/datum/marked_datum @@ -84,6 +85,49 @@ var/list/admin_datums = list() usr << "\red Unfortunatly there were no candidates available" return + if(href_list["editadminpermissions"]) + if(!usr.client) + return + + var/adm_ckey = href_list["editadminckey"] + if(!adm_ckey) + usr << "\red no valid ckey" + return + + if(!usr.client.holder || !(usr.client.holder.sql_permissions & PERMISSIONS)) + usr << "\red You do not have permission to do this!" + message_admins("[key_name_admin(usr)] attempted to edit the admin permissions of [adm_ckey] without authentication!") + log_admin("[key_name(usr)] attempted to edit the admin permissions of [adm_ckey] without authentication!") + return + + switch(href_list["editadminpermissions"]) + if("permissions") + usr << "Currently unavailable since nothing runs off of permissions" + if("rank") + var/new_rank = input("Please, select a rank", "New rank for player", null, null) as null|anything in list("Game Master","Game Admin", "Trial Admin", "Admin Observer") + if(!new_rank) + return + 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("remove") + if(alert("Are you sure you want to remove [adm_ckey]?","Message","Yes","Cancel") == "Yes") + 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("add") + var/new_ckey = input(usr,"New admin's ckey","Admin ckey", null) as text|null + if(!new_ckey) + return + var/new_rank = input("Please, select a rank", "New rank for player", null, null) as null|anything in list("Game Master","Game Admin", "Trial Admin", "Admin Observer") + if(!new_rank) + return + message_admins("[key_name_admin(usr)] added [new_ckey] as a new admin to the rank [new_rank]") + log_admin("[key_name(usr)] added [new_ckey] as a new admin to the rank [new_rank]") + log_admin_rank_modification(new_ckey, new_rank) + + + if(href_list["call_shuttle"]) if (src.rank in list("Trial Admin", "Badmin", "Game Admin", "Game Master")) if( ticker.mode.name == "blob" ) diff --git a/code/modules/admin/permissionverbs/assignment.dm b/code/modules/admin/permissionverbs/assignment.dm new file mode 100644 index 00000000000..66affaa6969 --- /dev/null +++ b/code/modules/admin/permissionverbs/assignment.dm @@ -0,0 +1,12 @@ + + + +//Before this proc is called, the holder variable must already be set, with the proper rank, level and permissions set. +//This proc also DOES NOT CLEAR EXISTING ADMIN VERBS + +/client/proc/handle_permission_verbs() + if(!holder || !holder.rank || !holder.sql_permissions) + return + + if(holder.sql_permissions & PERMISSIONS) + verbs += /client/proc/edit_admin_permissions \ No newline at end of file diff --git a/code/modules/admin/permissionverbs/permissionedit.dm b/code/modules/admin/permissionverbs/permissionedit.dm new file mode 100644 index 00000000000..f69138f23bb --- /dev/null +++ b/code/modules/admin/permissionverbs/permissionedit.dm @@ -0,0 +1,127 @@ +/client/proc/edit_admin_permissions() + set category = "Admin" + set name = "Permissions Panel" + set desc = "Edit admin permissions" + + if(!holder) + return + holder.edit_admin_permissions() + +/datum/admins/proc/edit_admin_permissions() + if(!usr.client) + return + + if(!usr.client.holder || !(usr.client.holder.sql_permissions & PERMISSIONS)) + usr << "\red You do not have permission to do this!" + return + + var/user = sqlfdbklogin + var/pass = sqlfdbkpass + var/db = sqlfdbkdb + var/address = sqladdress + var/port = sqlport + + var/DBConnection/dbcon = new() + dbcon.Connect("dbi:mysql:[db]:[address]:[port]","[user]","[pass]") + if(!dbcon.IsConnected()) + usr << "\red Failed to establish database connection" + return + + var/DBQuery/select_query = dbcon.NewQuery("SELECT ckey, rank, level, flags FROM erro_admin ORDER BY rank, ckey") + select_query.Execute() + + var/output = "
| CKEY | " + output += "RANK | " + output += "LEVEL | " + output += "PERMISSIONS | " + output += "OPTIONS | " + output += "
|---|---|---|---|---|
| [adm_ckey] | " + output += "[adm_rank] | " + output += "[adm_level] | " + var/list/permissionlist = bitfield2list(adm_flags, permissionwords_sql) + output += ""
+ for(var/word in permissionlist)
+ output += "[word] " + output += " | "
+ output += ""
+
+ //Options
+ output += "PERMISSIONS " + output += "RANK " + output += "REMOVE" + + output += " | "
+ output += "