diff --git a/code/controllers/configuration.dm b/code/controllers/configuration.dm index d1a8e5e00f..cd82e2f487 100644 --- a/code/controllers/configuration.dm +++ b/code/controllers/configuration.dm @@ -89,7 +89,8 @@ var/metroid_delay = 0 var/animal_delay = 0 - var/admin_legacy_system = 0 //Defines whether the server uses the legacy admin system with admins.txt or the SQL system. + var/admin_legacy_system = 0 //Defines whether the server uses the legacy admin system with admins.txt or the SQL system. Config option in config.txt + var/ban_legacy_system = 0 //Defines whether the server uses the legacy banning system with the files in /data or the SQL system. Config option in config.txt /datum/configuration/New() var/list/L = typesof(/datum/game_mode) - /datum/game_mode @@ -139,6 +140,9 @@ if ("admin_legacy_system") config.admin_legacy_system = 1 + if ("ban_legacy_system") + config.ban_legacy_system = 1 + if ("log_ooc") config.log_ooc = 1 diff --git a/code/defines/procs/statistics.dm b/code/defines/procs/statistics.dm index 328f17d85e..810bfb79aa 100644 --- a/code/defines/procs/statistics.dm +++ b/code/defines/procs/statistics.dm @@ -10,7 +10,7 @@ proc/sql_poll_players() log_game("SQL ERROR during player polling. Failed to connect.") else var/sqltime = time2text(world.realtime, "YYYY-MM-DD hh:mm:ss") - var/DBQuery/query = dbcon.NewQuery("INSERT INTO population (playercount, time) VALUES ([playercount], '[sqltime]')") + var/DBQuery/query = dbcon_old.NewQuery("INSERT INTO population (playercount, time) VALUES ([playercount], '[sqltime]')") if(!query.Execute()) var/err = query.ErrorMsg() log_game("SQL ERROR during player polling. Error : \[[err]\]\n") @@ -25,7 +25,7 @@ proc/sql_poll_admins() log_game("SQL ERROR during admin polling. Failed to connect.") else var/sqltime = time2text(world.realtime, "YYYY-MM-DD hh:mm:ss") - var/DBQuery/query = dbcon.NewQuery("INSERT INTO population (admincount, time) VALUES ([admincount], '[sqltime]')") + var/DBQuery/query = dbcon_old.NewQuery("INSERT INTO population (admincount, time) VALUES ([admincount], '[sqltime]')") if(!query.Execute()) var/err = query.ErrorMsg() log_game("SQL ERROR during admin polling. Error : \[[err]\]\n") diff --git a/code/modules/admin/DB ban/functions.dm b/code/modules/admin/DB ban/functions.dm index 9cfc41ab9c..9499ff912e 100644 --- a/code/modules/admin/DB ban/functions.dm +++ b/code/modules/admin/DB ban/functions.dm @@ -1,5 +1,5 @@ -datum/admins/proc/DB_ban_record(var/bantype, var/mob/banned_mob, var/duration = -1, var/reason, var/job = "", var/rounds = 0) +datum/admins/proc/DB_ban_record(var/bantype, var/mob/banned_mob, var/duration = -1, var/reason, var/job = "", var/rounds = 0, var/banckey = null) establish_db_connection() if(!dbcon.IsConnected()) return @@ -35,6 +35,17 @@ datum/admins/proc/DB_ban_record(var/bantype, var/mob/banned_mob, var/duration = if(banned_mob.client) computerid = banned_mob.client.computer_id ip = banned_mob.client.address + else if(banckey) + ckey = ckey(banckey) + + var/DBQuery/query = dbcon.NewQuery("SELECT id FROM erro_player WHERE ckey = '[ckey]'") + query.Execute() + var/validckey = 0 + if(query.NextRow()) + validckey = 1 + if(!validckey) + message_admins("[key_name_admin(usr)] attempted to ban [ckey], but [ckey] has not been seen yet. Please only ban actual players.",1) + return var/a_ckey var/a_computerid @@ -64,6 +75,8 @@ datum/admins/proc/DB_ban_record(var/bantype, var/mob/banned_mob, var/duration = var/sql = "INSERT INTO erro_ban VALUES (null, Now(), '[serverip]', '[bantype_str]', '[reason]', '[job]', [(duration)?"[duration]":"0"], [(rounds)?"[rounds]":"0"], Now() + INTERVAL [(duration>0) ? duration : 0] MINUTE, '[ckey]', '[computerid]', '[ip]', '[a_ckey]', '[a_computerid]', '[a_ip]', '[who]', '[adminwho]', '', null, null, null, null, null)" var/DBQuery/query_insert = dbcon.NewQuery(sql) query_insert.Execute() + usr << "\blue Ban saved to database." + message_admins("[key_name_admin(usr)] has added a [bantype_str] for [ckey] [(job)?"([job])":""] [(duration > 0)?"([duration] minutes)":""] with the reason: \"[reason]\" to the ban database.",1) @@ -129,10 +142,67 @@ datum/admins/proc/DB_ban_unban(var/ckey, var/bantype, var/job = "") DB_ban_unban_by_id(ban_id) +datum/admins/proc/DB_ban_edit(var/banid = null, var/param = null) + + if(!isnum(banid) || !istext(param)) + usr << "Cancelled" + return + + var/DBQuery/query = dbcon.NewQuery("SELECT ckey, duration, reason FROM erro_ban WHERE id = [banid]") + query.Execute() + + var/eckey = usr.ckey //Editing admin ckey + var/pckey //(banned) Player ckey + var/duration //Old duration + var/reason //Old reason + + if(query.NextRow()) + pckey = query.item[1] + duration = query.item[2] + reason = query.item[3] + else + usr << "Invalid ban id. Contact the database admin" + return + + reason = sql_sanitize_text(reason) + var/value + + switch(param) + if("reason") + if(!value) + value = input("Insert the new reason for [pckey]'s ban", "New Reason", "[reason]", null) as null|text + value = sql_sanitize_text(value) + if(!value) + usr << "Cancelled" + return + + var/DBQuery/update_query = dbcon.NewQuery("UPDATE erro_ban SET reason = '[value]', edits = CONCAT(edits,'- [eckey] changed ban reason from \\\"[reason]\\\" to \\\"[value]\\\"
') WHERE id = [banid]") + update_query.Execute() + message_admins("[key_name_admin(usr)] has edited a ban for [pckey]'s reason from [reason] to [value]",1) + if("duration") + if(!value) + value = input("Insert the new duration (in minutes) for [pckey]'s ban", "New Duration", "[duration]", null) as null|num + if(!isnum(value) || !value) + usr << "Cancelled" + return + + var/DBQuery/update_query = dbcon.NewQuery("UPDATE erro_ban SET duration = [value], edits = CONCAT(edits,'- [eckey] changed ban duration from [duration] to [value]
'), expiration_time = DATE_ADD(bantime, INTERVAL [value] MINUTE) WHERE id = [banid]") + message_admins("[key_name_admin(usr)] has edited a ban for [pckey]'s duration from [duration] to [value]",1) + update_query.Execute() + if("unban") + if(alert("Unban [pckey]?", "Unban?", "Yes", "No") == "Yes") + DB_ban_unban_by_id(banid) + return + else + usr << "Cancelled" + return + else + usr << "Cancelled" + return datum/admins/proc/DB_ban_unban_by_id(var/id) - var/sql = "SELECT id FROM erro_ban WHERE id = [id]" + var/sql = "SELECT ckey FROM erro_ban WHERE id = [id]" establish_db_connection() if(!dbcon.IsConnected()) @@ -140,9 +210,11 @@ datum/admins/proc/DB_ban_unban_by_id(var/id) var/ban_number = 0 //failsafe + var/pckey var/DBQuery/query = dbcon.NewQuery(sql) query.Execute() while(query.NextRow()) + pckey = query.item[1] ban_number++; if(ban_number == 0) @@ -161,7 +233,159 @@ datum/admins/proc/DB_ban_unban_by_id(var/id) var/unban_ip = src.owner:address var/sql_update = "UPDATE erro_ban SET unbanned = 1, unbanned_datetime = Now(), unbanned_ckey = '[unban_ckey]', unbanned_computerid = '[unban_computerid]', unbanned_ip = '[unban_ip]' WHERE id = [id]" - + message_admins("[key_name_admin(usr)] has lifted [pckey]'s ban.",1) var/DBQuery/query_update = dbcon.NewQuery(sql_update) - query_update.Execute() \ No newline at end of file + query_update.Execute() + + +/client/proc/DB_ban_panel() + set category = "Admin" + set name = "Banning Panel" + set desc = "Edit admin permissions" + + if(!holder) + return + + holder.DB_ban_panel() + + +/datum/admins/proc/DB_ban_panel(var/playerckey = null, var/adminckey = null) + if(!usr.client) + return + + //if(check_rights(R_BAN)) + // usr << "\red You do not have permission to do this!" + // return + + establish_db_connection() + if(!dbcon.IsConnected()) + usr << "\red Failed to establish database connection" + return + + var/output = "
" + + output += "" + + output += "" + output += "" + output += "
" + output += "

Banning panel

" + output += "
" + + output += "
Add custom ban: (ONLY use this if you can't ban through any other method)" + output += "" + output += "" + output += "" + output += "" + output += "" + output += "
Ban type:Ckey:
Duration: Job:
" + output += "Reason:

" + output += "" + output += "
" + + output += "
" + + output += "
Search: " + output += "" + output += "Ckey: " + output += "Admin ckey: " + output += "" + output += "
" + output += "Please note that all jobban bans or unbans are in-effect the following round." + + if(adminckey || playerckey) + + var/blcolor = "#ffeeee" //banned light + var/bdcolor = "#ffdddd" //banned dark + var/ulcolor = "#eeffee" //unbanned light + var/udcolor = "#ddffdd" //unbanned dark + + output += "" + output += "" + output += "" + output += "" + output += "" + output += "" + output += "" + output += "" + + adminckey = ckey(adminckey) + playerckey = ckey(playerckey) + var/adminsearch = "" + var/playersearch = "" + if(adminckey) + adminsearch = "AND a_ckey = '[adminckey]' " + if(playerckey) + playersearch = "AND ckey = '[playerckey]' " + + var/DBQuery/select_query = dbcon.NewQuery("SELECT id, bantime, bantype, reason, job, duration, expiration_time, ckey, a_ckey, unbanned, unbanned_ckey, unbanned_datetime, edits FROM erro_ban WHERE 1 [playersearch] [adminsearch] ORDER BY bantime DESC") + select_query.Execute() + + while(select_query.NextRow()) + var/banid = select_query.item[1] + var/bantime = select_query.item[2] + var/bantype = select_query.item[3] + var/reason = select_query.item[4] + var/job = select_query.item[5] + var/duration = select_query.item[6] + var/expiration = select_query.item[7] + var/ckey = select_query.item[8] + var/ackey = select_query.item[9] + var/unbanned = select_query.item[10] + var/unbanckey = select_query.item[11] + var/unbantime = select_query.item[12] + var/edits = select_query.item[13] + + var/lcolor = blcolor + var/dcolor = bdcolor + if(unbanned) + lcolor = ulcolor + dcolor = udcolor + + var/typedesc ="" + switch(bantype) + if("PERMABAN") + typedesc = "PERMABAN" + if("TEMPBAN") + typedesc = "TEMPBAN
([duration] minutes [(unbanned) ? "" : "(Edit))"]
Expires [expiration]
" + if("JOB_PERMABAN") + typedesc = "JOBBAN
([job])" + + output += "" + output += "" + output += "" + output += "" + output += "" + output += "" + output += "" + output += "" + output += "" + output += "" + if(edits) + output += "" + output += "" + output += "" + output += "" + output += "" + output += "" + if(unbanned) + output += "" + output += "" + output += "" + output += "" + output += "" + output += "" + + output += "
TYPECKEYTIME APPLIEDADMINOPTIONS
[typedesc][ckey][bantime][ackey][(unbanned) ? "" : "Unban"]
Reason: [(unbanned) ? "" : "(Edit)"] \"[reason]\"
EDITS
[edits]
UNBANNED by admin [unbanckey] on [unbantime]
 
" + + usr << browse(output,"window=lookupbans;size=900x500") \ No newline at end of file diff --git a/code/modules/admin/IsBanned.dm b/code/modules/admin/IsBanned.dm index a65b5beb36..09df6dbe73 100644 --- a/code/modules/admin/IsBanned.dm +++ b/code/modules/admin/IsBanned.dm @@ -1,27 +1,63 @@ //Blocks an attempt to connect before even creating our client datum thing. world/IsBanned(key,address,computer_id) - if(ckey(key) in admin_datums) - return ..() + //if(ckey(key) in admin_datums) + // return ..() - //Guest Checking - if( !guests_allowed && IsGuestKey(key) ) - log_access("Failed Login: [key] - Guests not allowed") - message_admins("\blue Failed Login: [key] - Guests not allowed") - return list("reason"="guest", "desc"="\nReason: Guests not allowed. Please sign in with a byond account.") + if(config.ban_legacy_system) - //check if the IP address is a known TOR node - if( config && config.ToRban && ToRban_isbanned(address) ) - log_access("Failed Login: [src] - Banned: ToR") - message_admins("\blue Failed Login: [src] - Banned: ToR") - //ban their computer_id and ckey for posterity - AddBan(ckey(key), computer_id, "Use of ToR", "Automated Ban", 0, 0) - return list("reason"="Using ToR", "desc"="\nReason: The network you are using to connect has been banned.\nIf you believe this is a mistake, please request help at [config.banappeals]") + //Guest Checking + if( !guests_allowed && IsGuestKey(key) ) + log_access("Failed Login: [key] - Guests not allowed") + message_admins("\blue Failed Login: [key] - Guests not allowed") + return list("reason"="guest", "desc"="\nReason: Guests not allowed. Please sign in with a byond account.") - //Ban Checking - . = CheckBan( ckey(key), computer_id, address ) - if(.) - log_access("Failed Login: [key] [computer_id] [address] - Banned [.["reason"]]") - message_admins("\blue Failed Login: [key] id:[computer_id] ip:[address] - Banned [.["reason"]]") - return . + //check if the IP address is a known TOR node + if( config && config.ToRban && ToRban_isbanned(address) ) + log_access("Failed Login: [src] - Banned: ToR") + message_admins("\blue Failed Login: [src] - Banned: ToR") + //ban their computer_id and ckey for posterity + AddBan(ckey(key), computer_id, "Use of ToR", "Automated Ban", 0, 0) + return list("reason"="Using ToR", "desc"="\nReason: The network you are using to connect has been banned.\nIf you believe this is a mistake, please request help at [config.banappeals]") - return ..() //default pager ban stuff + //Ban Checking + . = CheckBan( ckey(key), computer_id, address ) + if(.) + log_access("Failed Login: [key] [computer_id] [address] - Banned [.["reason"]]") + message_admins("\blue Failed Login: [key] id:[computer_id] ip:[address] - Banned [.["reason"]]") + return . + + return ..() //default pager ban stuff + + else + + var/ckeytext = ckey(key) + + if(!establish_db_connection()) + world.log << "Ban database connection failure. Key [ckeytext] not checked" + diary << "Ban database connection failure. Key [ckeytext] not checked" + return + + var/DBQuery/query = dbcon.NewQuery("SELECT ckey, ip, computerid, a_ckey, reason, expiration_time, duration, bantime, bantype FROM erro_Ban WHERE (ckey = '[ckeytext]' OR ip = '[address]' OR computerid = '[computer_id]') AND (bantype = 'PERMABAN' OR (bantype = 'TEMPBAN' AND expiration_time > Now())) AND isnull(unbanned)") + + query.Execute() + + while(query.NextRow()) + var/pckey = query.item[1] + //var/pip = query.item[2] + //var/pcid = query.item[3] + var/ackey = query.item[4] + var/reason = query.item[5] + var/expiration = query.item[6] + var/duration = query.item[7] + var/bantime = query.item[8] + var/bantype = query.item[9] + + var/expires = "" + if(text2num(duration) > 0) + expires = " The ban is for [duration] minutes and expires on [expiration] (server time)." + + var/desc = "\nReason: You, or another user of this computer or connection ([pckey]) is banned from playing here. The ban reason is:\n[reason]\nThis ban was applied by [ackey] on [bantime], [expires]" + + return list("reason"="[bantype]", "desc"="[desc]") + + return ..() //default pager ban stuff \ No newline at end of file diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index 7ad9a89c75..344bb02407 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -59,7 +59,8 @@ var/list/admin_verbs_admin = list( var/list/admin_verbs_ban = list( /client/proc/unban_panel, /client/proc/jobbans, - /client/proc/unjobban_panel + /client/proc/unjobban_panel, + /client/proc/DB_ban_panel ) var/list/admin_verbs_sounds = list( /client/proc/play_local_sound, @@ -368,7 +369,10 @@ var/list/admin_verbs_hideable = list( set name = "Display Job bans" set category = "Admin" if(holder) - holder.Jobbans() + if(config.ban_legacy_system) + holder.Jobbans() + else + holder.DB_ban_panel() feedback_add_details("admin_verb","VJB") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! return @@ -376,7 +380,10 @@ var/list/admin_verbs_hideable = list( set name = "Unban Panel" set category = "Admin" if(holder) - holder.unbanpanel() + if(config.ban_legacy_system) + holder.unbanpanel() + else + holder.DB_ban_panel() feedback_add_details("admin_verb","UBP") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! return diff --git a/code/modules/admin/banjob.dm b/code/modules/admin/banjob.dm index dd10d33f99..94c09c54ee 100644 --- a/code/modules/admin/banjob.dm +++ b/code/modules/admin/banjob.dm @@ -48,24 +48,31 @@ DEBUG */ /proc/jobban_loadbanfile() - var/savefile/S=new("data/job_full.ban") - S["keys[0]"] >> jobban_keylist - log_admin("Loading jobban_rank") - S["runonce"] >> jobban_runonce + if(config.ban_legacy_system) + var/savefile/S=new("data/job_full.ban") + S["keys[0]"] >> jobban_keylist + log_admin("Loading jobban_rank") + S["runonce"] >> jobban_runonce - /* - for(var/i = 1; i <= length(jobban_keylist); i++) - if( findtext(jobban_keylist[i],"##") ) - var/index = findtext(jobban_keylist[i],"##") - var/s = jobban_keylist[i] - s = copytext( s , 1 , index ) //Removes the reason for the ban from this list - jobban_keylist[i] = s - world << "DEBUG: index: [index] - s: [s] - jobban_keylist\[[i]\] = [jobban_keylist[i]]"*/ + if (!length(jobban_keylist)) + jobban_keylist=list() + log_admin("jobban_keylist was empty") + else + if(!establish_db_connection()) + world.log << "Database connection failed. Reverting to the legacy ban system." + diary << "Database connection failed. Reverting to the legacy ban system." + config.ban_legacy_system = 1 + jobban_loadbanfile() + return - if (!length(jobban_keylist)) - jobban_keylist=list() - log_admin("jobban_keylist was empty") + var/DBQuery/query = dbcon.NewQuery("SELECT ckey, job FROM erro_ban WHERE bantype = 'JOB_PERMABAN' AND isnull(unbanned)") + query.Execute() + while(query.NextRow()) + var/ckey = query.item[1] + var/job = query.item[2] + + jobban_keylist.Add("[ckey] - [job]") /proc/jobban_savebanfile() var/savefile/S=new("data/job_full.ban") diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm index 17780619fb..e68aaf6d6d 100644 --- a/code/modules/admin/topic.dm +++ b/code/modules/admin/topic.dm @@ -45,6 +45,60 @@ log_admin("[key_name(usr)] has spawned a death squad.") if(!src.makeDeathsquad()) usr << "\red Unfortunatly there were no candidates available" + else if(href_list["dbsearchckey"] || href_list["dbsearchadmin"]) + var/adminckey = href_list["dbsearchadmin"] + var/playerckey = href_list["dbsearchckey"] + + DB_ban_panel(playerckey, adminckey) + return + + else if(href_list["dbbanedit"]) + var/banedit = href_list["dbbanedit"] + var/banid = text2num(href_list["dbbanid"]) + if(!banedit || !banid) + return + + DB_ban_edit(banid, banedit) + return + + else if(href_list["dbbanaddtype"]) + + var/bantype = text2num(href_list["dbbanaddtype"]) + var/banckey = href_list["dbbanaddckey"] + var/banduration = text2num(href_list["dbbaddduration"]) + var/banjob = href_list["dbbanaddjob"] + var/banreason = href_list["dbbanreason"] + + banckey = ckey(banckey) + + switch(bantype) + if(BANTYPE_PERMA) + if(!banckey || !banreason) + usr << "Not enough parameters (Requires ckey and reason)" + return + banduration = null + banjob = null + if(BANTYPE_TEMP) + if(!banckey || !banreason || !banduration) + usr << "Not enough parameters (Requires ckey, reason and duration)" + return + banjob = null + if(BANTYPE_JOB_PERMA) + if(!banckey || !banreason || !banjob) + usr << "Not enough parameters (Requires ckey, reason and job)" + return + banduration = null + + var/mob/playermob + + for(var/mob/M in player_list) + if(M.ckey == banckey) + playermob = M + break + + banreason = "(MANUAL BAN) "+banreason + + DB_ban_record(bantype, playermob, banduration, banreason, banjob, null, banckey) else if(href_list["editadminpermissions"]) var/adm_ckey = href_list["editadminckey"] @@ -595,6 +649,10 @@ //Unbanning joblist //all jobs in joblist are banned already OR we didn't give a reason (implying they shouldn't be banned) if(joblist.len) //at least 1 banned job exists in joblist so we have stuff to unban. + if(!config.ban_legacy_system) + usr << "Unfortunately, database based unbanning cannot be done through this panel" + DB_ban_panel(usr.client.ckey) + return var/msg for(var/job in joblist) var/reason = jobban_isbanned(M, job) diff --git a/config/config.txt b/config/config.txt index 8280fec0b7..20cdea4fea 100644 --- a/config/config.txt +++ b/config/config.txt @@ -9,9 +9,12 @@ ALERT_RED_UPTO There is an immediate serious threat to the station. Security may ALERT_RED_DOWNTO The self-destruct mechanism has been deactivated, there is still however an immediate serious threat to the station. Security may have weapons unholstered at all times, random searches are allowed and advised. ALERT_DELTA The station's self-destruct mechanism has been engaged. All crew are instructed to obey all instructions given by heads of staff. Any violations of these orders can be punished by death. This is not a drill. -## Add a # infront of this if you want to use the SQL based admin system, the legacy system uses admins.txt +## Add a # infront of this if you want to use the SQL based admin system, the legacy system uses admins.txt. You need to set up your database to use the SQL based system. ADMIN_LEGACY_SYSTEM +## Add a # infront of this if you want to use the SQL based banning system. The legacy systems use the files in the data folder. You need to set up your database to use the SQL based system. +BAN_LEGACY_SYSTEM + ## log OOC channel LOG_OOC