diff --git a/code/__DEFINES/subsystems.dm b/code/__DEFINES/subsystems.dm index 3b3da1b9b7f..52bed0290f7 100644 --- a/code/__DEFINES/subsystems.dm +++ b/code/__DEFINES/subsystems.dm @@ -72,7 +72,8 @@ #define INIT_ORDER_PROFILER 100 #define INIT_ORDER_FAIL2TOPIC 99 #define INIT_ORDER_TITLE 98 -#define INIT_ORDER_GARBAGE 95 +#define INIT_ORDER_GARBAGE 96 +#define INIT_ORDER_BCCM 95 #define INIT_ORDER_DBCORE 94 #define INIT_ORDER_STATPANELS 93 #define INIT_ORDER_BLACKBOX 92 diff --git a/code/__HELPERS/text.dm b/code/__HELPERS/text.dm index d9e75ef92df..f571aa807c7 100644 --- a/code/__HELPERS/text.dm +++ b/code/__HELPERS/text.dm @@ -18,6 +18,23 @@ /proc/format_table_name(table as text) return CONFIG_GET(string/feedback_tableprefix) + table +/proc/sql_sanitize_text(text) + text = replacetext(text, "'", "''") + text = replacetext(text, ";", "") + text = replacetext(text, "&", "") + return text + +/proc/new_sql_sanitize_text(text) + text = replacetext(text, "'", "") + text = replacetext(text, ";", "") + text = replacetext(text, "&", "") + text = replacetext(text, "`", "") + return text + +/proc/remove_all_spaces(text) + text = replacetext(text, " ", "") + return text + /* * Text sanitization */ diff --git a/code/controllers/configuration/configuration.dm b/code/controllers/configuration/configuration.dm index 21b1d4e8760..ce75fdc82d1 100644 --- a/code/controllers/configuration/configuration.dm +++ b/code/controllers/configuration/configuration.dm @@ -23,6 +23,7 @@ // var/policy var/static/regex/ic_filter_regex + var/bccm = TRUE /datum/controller/configuration/proc/admin_reload() if(IsAdminAdvancedProcCall()) diff --git a/code/controllers/subsystem/bccm.dm b/code/controllers/subsystem/bccm.dm new file mode 100644 index 00000000000..5497d3fdee5 --- /dev/null +++ b/code/controllers/subsystem/bccm.dm @@ -0,0 +1,386 @@ +// BCCM (Ban Counter Counter Measures system) ((Name subject to change)), originally inspired by EAMS (Epic Anti-Multiaccount System), by Epicus +//version 1.0.2 + +/datum/bccm_info + var/is_loaded = FALSE + var/is_whitelisted = FALSE + + var/ip + var/ip_as + var/ip_mobile + var/ip_proxy + var/ip_hosting + +/client + var/datum/bccm_info/bccm_info = new + +SUBSYSTEM_DEF(bccm) + name = "BCCM" + init_order = INIT_ORDER_BCCM + flags = SS_NO_FIRE + + var/max_error_count = 4 + + var/is_active = FALSE + var/error_counter = 0 + + var/list/tgui_panel_asn_data = list() + var/list/tgui_panel_wl_data = list() + + var/list/client/postponed_client_queue = new + +/datum/controller/subsystem/bccm/Initialize(timeofday) + if(!config.bccm) + return ..() +/* + if(!sqlenabled) + log_sql("BCCM could not be loaded without SQL enabled") + return ..() +*/ + Toggle() + return ..() + +/datum/controller/subsystem/bccm/stat_entry(msg) + return "[is_active ? "ACTIVE" : "OFFLINE"]" + +/datum/controller/subsystem/bccm/proc/Toggle(mob/user) + if (!initialized && user) + return + + if(!is_active && !SSdbcore.Connect()) + log_sql("BCCM could not be loaded because the DB connection could not be established.") + return + + is_active = !is_active + log_sql("BCCM is [is_active ? "enabled" : "disabled"]!") + + . = is_active + if(!.) + return + + tgui_panel_asn_data = GetAsnBanlistDatabase() + tgui_panel_wl_data = GetWhitelistDatabase() + + var/list/clients_to_check = postponed_client_queue.Copy() + postponed_client_queue.Cut() + for (var/client/C in clients_to_check) + CollectClientData(C) + HandleClientAccessCheck(C, postponed = TRUE) + HandleASNbanCheck(C, postponed = TRUE) + CHECK_TICK + +/datum/controller/subsystem/bccm/proc/CheckDBCon() + if(is_active && SSdbcore.Connect()) + return TRUE + + is_active = FALSE + log_and_message_admins("A Database error has occured. BCCM is automatically disabled.") + return FALSE + + +/datum/controller/subsystem/bccm/proc/CollectClientData(client/C) + ASSERT(istype(C)) + + var/_ip_addr = C.address + + if(!is_active) + postponed_client_queue.Add(C) + return + + if(!CheckDBCon()) + return + + C.bccm_info.is_whitelisted = CheckWhitelist(C.ckey) + + if(!_ip_addr || _ip_addr == "127.0.0.1") + return + + var/list/response = GetAPIresponse(_ip_addr, C) + + if(!response) + return + + C.bccm_info.ip = _ip_addr + C.bccm_info.ip_as = response["as"] + C.bccm_info.ip_mobile = response["mobile"] + C.bccm_info.ip_proxy = response["proxy"] + C.bccm_info.ip_hosting = response["hosting"] + + C.bccm_info.is_loaded = TRUE + return + +/datum/controller/subsystem/bccm/proc/GetAPIresponse(ip, client/C = null) + var/list/response = LoadCachedData(ip) + + if(response && C) + log_access("BCCM data for [C] ([ip]) is loaded from cache!") + + while(!response && is_active && error_counter < max_error_count) + var/list/http = world.Export("http://ip-api.com/json/[ip]?fields=17025024") + + if(!http) + if(C) + log_and_message_admins("BCCM: API connection failed, could not check [C], retrying.") + else + log_and_message_admins("BCCM: API connection failed, could not check [ip], retrying.") + error_counter += 1 + sleep(2) + continue + + var/raw_response = file2text(http["CONTENT"]) + + try + response = json_decode(raw_response) + catch (var/exception/e) + log_and_message_admins("BCCM: JSON decode error, could not check [C]. JSON decode error: [e.name]") + return + + if(response["status"] == "fail") + log_and_message_admins("BCCM: Request error, could not check [C]. CheckIP response: [response["message"]]") + return + + if(C) + log_access("BCCM data for [C]([ip]) is loaded from external API!") + CacheData(ip, raw_response) + + if(error_counter >= max_error_count && is_active) + log_and_message_admins("BCCM was disabled due to connection errors!") + is_active = FALSE + return + + return response + +/datum/controller/subsystem/bccm/proc/CheckForAccess(client/C) + ASSERT(istype(C)) + + if(!is_active) + return TRUE + + if(!CheckDBCon()) + return TRUE + + if(!C.address || C.holder) + return TRUE + + if(C.bccm_info.is_whitelisted) + return TRUE + + if(C.bccm_info.is_loaded) + if(!C.bccm_info.ip_proxy && !C.bccm_info.ip_hosting) + return TRUE + return FALSE + + log_and_message_admins("BCCM failed to load info for [C.ckey].") + return TRUE + +/datum/controller/subsystem/bccm/proc/CheckWhitelist(ckey) + . = FALSE + + if(!CheckDBCon()) + return + + var/datum/db_query/query = SSdbcore.NewQuery("SELECT ckey FROM bccm_whitelist WHERE ckey = '[ckey]'") + query.Execute() + + if(query.NextRow()) + . = TRUE + + qdel(query) + + return + +/datum/controller/subsystem/bccm/proc/CheckASNban(client/C) + ASSERT(istype(C)) + + . = TRUE + + if(!is_active) + return + + if(!CheckDBCon()) + return + + var/datum/db_query/query = SSdbcore.NewQuery("SELECT `asn` FROM bccm_asn_ban WHERE asn = '[C.bccm_info.ip_as]'") + query.Execute() + + if(query.NextRow()) + . = FALSE + + qdel(query) + + return + +/datum/controller/subsystem/bccm/proc/LoadCachedData(ip) + ASSERT(istext(ip)) + + if(!CheckDBCon()) + return FALSE + + var/datum/db_query/_Cache_select_query = SSdbcore.NewQuery("SELECT response FROM bccm_ip_cache WHERE ip = '[ip]'") + _Cache_select_query.Execute() + + if(!_Cache_select_query.NextRow()) + . = FALSE + else + . = json_decode(_Cache_select_query.item[1]) + + qdel(_Cache_select_query) + return + +/datum/controller/subsystem/bccm/proc/CacheData(ip, raw_response) + ASSERT(istext(ip)) + ASSERT(istext(raw_response)) + + if(!CheckDBCon()) + return FALSE + + var/datum/db_query/_Cache_insert_query = SSdbcore.NewQuery("INSERT INTO bccm_ip_cache (`ip`, `response`) VALUES ('[ip]', '[raw_response]')") + _Cache_insert_query.Execute() + qdel(_Cache_insert_query) + + return TRUE + +/datum/controller/subsystem/bccm/proc/AddToWhitelist(ckey_input, client/Admin) + ASSERT(istype(Admin)) + + if(!CheckDBCon()) + return + + var/ckey = new_sql_sanitize_text(ckey(ckey_input)) + + if(!ckey) + return + + var/datum/db_query/_Whitelist_Query = SSdbcore.NewQuery("INSERT INTO bccm_whitelist (`ckey`, `a_ckey`, `timestamp`) VALUES ('[ckey]', '[Admin.ckey]', Now())") + _Whitelist_Query.Execute() + qdel(_Whitelist_Query) + + tgui_panel_wl_data = GetWhitelistDatabase() + log_and_message_admins("added [ckey] to BCCM whitelist.") + + return TRUE + +/datum/controller/subsystem/bccm/proc/RemoveFromWhitelist(ckey, client/Admin) + if(!CheckDBCon()) + return FALSE + + if(!CheckWhitelist(ckey)) + return + + var/datum/db_query/_Whitelist_Query = SSdbcore.NewQuery("DELETE FROM bccm_whitelist WHERE `ckey` = '[ckey]'") + _Whitelist_Query.Execute() + qdel(_Whitelist_Query) + + tgui_panel_wl_data = GetWhitelistDatabase() + log_and_message_admins("removed [ckey] from BCCM whitelist.", Admin.mob) + + return TRUE + +/datum/controller/subsystem/bccm/proc/GetWhitelistDatabase() + var/datum/db_query/_Whitelist_DB_Select_Query = SSdbcore.NewQuery("SELECT `ckey`, `a_ckey`, `timestamp` from bccm_whitelist") + _Whitelist_DB_Select_Query.Execute() + + var/list/result = list() + + while(_Whitelist_DB_Select_Query.NextRow()) + var/list/row = list() + row["ckey"] = _Whitelist_DB_Select_Query.item[1] + row["a_ckey"] = _Whitelist_DB_Select_Query.item[2] + row["timestamp"] = _Whitelist_DB_Select_Query.item[3] + + result["displayData"] += list(row) + + qdel(_Whitelist_DB_Select_Query) + + return result + +/datum/controller/subsystem/bccm/proc/AddASNban(address, client/Admin) + if(!CheckDBCon()) + return + + if(!check_rights(R_SERVER, TRUE, Admin)) + return + + var/ip = remove_all_spaces(new_sql_sanitize_text(address)) + + if(length(ip) > 16) + return + + var/list/response = GetAPIresponse(ip) + + var/ip_as = response["as"] + + var/datum/db_query/_ASban_Insert_Query = SSdbcore.NewQuery("INSERT INTO bccm_asn_ban (`ip`, `asn`, `a_ckey`, `timestamp`) VALUES ('[ip]', '[ip_as]', '[Admin.ckey]', Now())") + _ASban_Insert_Query.Execute() + qdel(_ASban_Insert_Query) + + tgui_panel_asn_data = GetAsnBanlistDatabase() + log_and_message_admins("has added '[ip_as]' to the BCCM ASN banlist.", Admin) + + return TRUE + +/datum/controller/subsystem/bccm/proc/RemoveASNban(ip_as, client/Admin) + if(!CheckDBCon()) + return + + if(!check_rights(R_SERVER, TRUE, Admin)) + return + + var/datum/db_query/_ASban_Delete_Query = SSdbcore.NewQuery("DELETE FROM bccm_asn_ban WHERE `asn` = '[ip_as]'") + _ASban_Delete_Query.Execute() + qdel(_ASban_Delete_Query) + + tgui_panel_asn_data = GetAsnBanlistDatabase() + log_and_message_admins("has removed '[ip_as]' from the BCCM ASN banlist.", Admin) + + return TRUE + + +/datum/controller/subsystem/bccm/proc/GetAsnBanlistDatabase() + var/datum/db_query/_ASN_Banlist_Select_Query = SSdbcore.NewQuery("SELECT `asn`, `timestamp`, `a_ckey` from bccm_asn_ban") + _ASN_Banlist_Select_Query.Execute() + + var/list/result = list() + + while(_ASN_Banlist_Select_Query.NextRow()) + var/list/row = list() + row["asn"] = _ASN_Banlist_Select_Query.item[1] + row["timestamp"] = _ASN_Banlist_Select_Query.item[2] + row["a_ckey"] = _ASN_Banlist_Select_Query.item[3] + + result["displayData"] += list(row) + + qdel(_ASN_Banlist_Select_Query) + + return result + + +/datum/controller/subsystem/bccm/proc/HandleClientAccessCheck(client/C, postponed = 0) + if(!SSbccm.CheckForAccess(C) && !(C.ckey in GLOB.admin_datums)) + if(!postponed) + C.log_client_to_db_connection_log() + log_and_message_admins(span_notice("BCCM: Failed Login: [C.key]/[C.ckey]([C.address])([C.computer_id]) failed to pass BCCM check.")) + qdel(C) + return + +/datum/controller/subsystem/bccm/proc/HandleASNbanCheck(client/C, postponed = 0) + if(!SSbccm.CheckASNban(C) && !(C.ckey in GLOB.admin_datums)) + if(!postponed) + C.log_client_to_db_connection_log() + log_and_message_admins(span_notice("BCCM: Failed Login: [C.key]/[C.ckey]([C.address])([C.computer_id]) failed to pass ASN ban check.")) + qdel(C) + return + +/client/proc/BCCM_toggle() + set category = "Server" + set name = "Toggle BCCM" + + if(!check_rights(R_SERVER)) + return + + if(!SSdbcore.Connect()) + to_chat(usr, span_notice("The Database is not connected!")) + return + + var/bccm_status = SSbccm.Toggle() + log_and_message_admins("has [bccm_status ? "enabled" : "disabled"] the BCCM system!") diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index 2d55d4acbe0..107f450863b 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -91,7 +91,9 @@ GLOBAL_PROTECT(admin_verbs_admin) /datum/admins/proc/open_borgopanel, /datum/admins/proc/toggle_sleep, /datum/admins/proc/toggle_sleep_area, - /datum/admins/proc/toggle_faction_join + /datum/admins/proc/toggle_faction_join, + /client/proc/BCCM_toggle, + /client/proc/BCCM_WhitelistPanel ) GLOBAL_LIST_INIT(admin_verbs_ban, list(/client/proc/unban_panel, /client/proc/DB_ban_panel, /client/proc/stickybanpanel)) GLOBAL_PROTECT(admin_verbs_ban) @@ -143,7 +145,8 @@ GLOBAL_LIST_INIT(admin_verbs_server, world.AVerbsServer()) /client/proc/toggle_random_events, /client/proc/forcerandomrotate, /client/proc/adminchangemap, - /client/proc/toggle_hub + /client/proc/toggle_hub, + /client/proc/BCCM_ASNPanel ) GLOBAL_PROTECT(admin_verbs_server) GLOBAL_LIST_INIT(admin_verbs_debug, world.AVerbsDebug()) diff --git a/code/modules/admin/bccm/tgui_asn.dm b/code/modules/admin/bccm/tgui_asn.dm new file mode 100644 index 00000000000..1a7eabd859a --- /dev/null +++ b/code/modules/admin/bccm/tgui_asn.dm @@ -0,0 +1,82 @@ +/client/proc/BCCM_ASNPanel() + set category = "Server" + set name = "BCCM ASN Panel" + + if(!SSdbcore.Connect()) + to_chat(usr, span_warning("Failed to establish database connection")) + return + + if(!check_rights(R_SERVER)) + return + + new /datum/bccm_asn_panel(src) + +/datum/bccm_asn_panel + var/client/holder // client of who is holding this + +/datum/bccm_asn_panel/New(user) + if(user) + setup(user) + else + qdel(src) + return + +/datum/bccm_asn_panel/proc/setup(user) // client or mob + if(!SSdbcore.Connect()) + to_chat(holder, span_warning("Failed to establish database connection")) + qdel(src) + return + + if(istype(user, /client)) + var/client/user_client = user + holder = user_client + else + var/mob/user_mob = user + holder = user_mob.client + + if(!check_rights(R_SERVER, TRUE, holder)) + qdel(src) + return + + ui_interact(holder.mob) + +/datum/bccm_asn_panel/ui_state(mob/user) + return GLOB.admin_state // admin only + +/datum/bccm_asn_panel/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "BCCMASNPanel") + ui.open() + +/datum/bccm_asn_panel/ui_data(mob/user, ui_key) + . = SSbccm.tgui_panel_asn_data + +/datum/bccm_asn_panel/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state) + if(..()) + return + switch(action) + if("asn_remove_entry") + if(!params["asn"]) + return TRUE + if(SSbccm.RemoveASNban(params["asn"], holder)) + SStgui.update_uis(src) + else + return TRUE + if("asn_add_entry") + if(!params["ip"]) + return TRUE + if(SSbccm.AddASNban(params["ip"], holder)) + SStgui.update_uis(src) + else + return TRUE + + if(!length(SSbccm.tgui_panel_asn_data)) + qdel(src) //For some unknown reason it refuses to update UI when it goes from 1 to 0 entries, so last item gets stuck. I can't fix it now, maybe later. ~Tsuru + return + + SStgui.update_user_uis(holder.mob) + return TRUE + +/datum/bccm_asn_panel/ui_close(mob/user) + qdel(src) diff --git a/code/modules/admin/bccm/tgui_whitelist.dm b/code/modules/admin/bccm/tgui_whitelist.dm new file mode 100644 index 00000000000..baaf51ffb6c --- /dev/null +++ b/code/modules/admin/bccm/tgui_whitelist.dm @@ -0,0 +1,82 @@ +/client/proc/BCCM_WhitelistPanel() + set category = "Server" + set name = "BCCM WL Panel" + + if(!SSdbcore.Connect()) + to_chat(usr, span_warning("Failed to establish database connection")) + return + + if(!check_rights(R_BAN)) + return + + new /datum/bccm_wl_panel(src) + +/datum/bccm_wl_panel + var/client/holder // client of who is holding this + +/datum/bccm_wl_panel/New(user) + if(user) + setup(user) + else + qdel(src) + return + +/datum/bccm_wl_panel/proc/setup(user) // client or mob + if(!SSdbcore.Connect()) + to_chat(holder, span_warning("Failed to establish database connection")) + qdel(src) + return + + if(istype(user, /client)) + var/client/user_client = user + holder = user_client + else + var/mob/user_mob = user + holder = user_mob.client + + if(!check_rights(R_BAN, TRUE, holder)) + qdel(src) + return + + ui_interact(holder.mob) + +/datum/bccm_wl_panel/ui_state(mob/user) + return GLOB.admin_state // admin only + +/datum/bccm_wl_panel/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "BCCMWhitelistPanel") + ui.open() + +/datum/bccm_wl_panel/ui_data(mob/user, ui_key) + . = SSbccm.tgui_panel_wl_data + +/datum/bccm_wl_panel/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state) + if(..()) + return + switch(action) + if("wl_remove_entry") + if(!params["ckey"]) + return TRUE + if(SSbccm.RemoveFromWhitelist(params["ckey"], holder)) + SStgui.update_uis(src) + else + return TRUE + if("wl_add_ckey") + if(!params["ckey"]) + return TRUE + if(SSbccm.AddToWhitelist(params["ckey"], holder)) + SStgui.update_uis(src) + else + return TRUE + + if(!length(SSbccm.tgui_panel_wl_data)) + qdel(src) //Same as ASN. ~Tsuru + return + + SStgui.update_user_uis(holder.mob) + return TRUE + +/datum/bccm_wl_panel/ui_close(mob/user) + qdel(src) diff --git a/code/modules/client/client_procs.dm b/code/modules/client/client_procs.dm index 5c615145d98..eba7f45623c 100644 --- a/code/modules/client/client_procs.dm +++ b/code/modules/client/client_procs.dm @@ -261,6 +261,9 @@ GLOBAL_LIST_INIT(warning_ckeys, list()) else new /datum/admins(autorank, ckey) //CITADEL EDIT + SSbccm.CollectClientData(src) + SSbccm.HandleClientAccessCheck(src) + SSbccm.HandleASNbanCheck(src) if(check_rights_for(src, R_DEBUG)) //check if autoadmin gave us it debug_tools_allowed = TRUE if(!debug_tools_allowed) @@ -694,6 +697,15 @@ GLOBAL_LIST_INIT(warning_ckeys, list()) player_age = -1 . = player_age +/client/proc/log_client_to_db_connection_log() + var/sql_ip = sql_sanitize_text(src.address) + var/sql_computerid = sql_sanitize_text(src.computer_id) + var/sql_ckey = sql_sanitize_text(src.ckey) + var/serverip = "[world.internet_address]:[world.port]" + + var/datum/db_query/query_accesslog = SSdbcore.NewQuery("INSERT INTO `erro_connection_log`(`id`,`datetime`,`serverip`,`ckey`,`ip`,`computerid`) VALUES(null,Now(),'[serverip]','[sql_ckey]','[sql_ip]','[sql_computerid]');") + query_accesslog.Execute() + qdel(query_accesslog) /client/proc/findJoinDate() var/list/http = world.Export("http://byond.com/members/[ckey]?format=text") if(!http) diff --git a/code/modules/client/verbs/ooc.dm b/code/modules/client/verbs/ooc.dm index 9bf75b1fc3a..f20f177d245 100644 --- a/code/modules/client/verbs/ooc.dm +++ b/code/modules/client/verbs/ooc.dm @@ -22,6 +22,12 @@ GLOBAL_VAR_INIT(normal_ooc_colour, "#002eb8") if(prefs.muted & MUTE_OOC) to_chat(src, span_danger("You cannot use OOC (muted).")) return + var/static/regex/slurs = regex("nigg|fag|tranny|dyke|kike|pedo|loli|shota", "i") + if(findtext(msg, slurs)) + to_chat(src, "Slurs are not allowed.") + log_admin("[key_name(src)] has triggered the slur filter (OOC): [msg].") + message_admins("[key_name_admin(src)] has triggered the slur filter (OOC): [msg].") + return 0 if(jobban_isbanned(src.mob, "OOC")) to_chat(src, span_danger("You have been banned from OOC.")) return diff --git a/hailmary.dme b/hailmary.dme index 1b25d0bd690..cbfb75769c6 100644 --- a/hailmary.dme +++ b/hailmary.dme @@ -325,6 +325,7 @@ #include "code\controllers\subsystem\atoms.dm" #include "code\controllers\subsystem\augury.dm" #include "code\controllers\subsystem\autotransfer.dm" +#include "code\controllers\subsystem\bccm.dm" #include "code\controllers\subsystem\blackbox.dm" #include "code\controllers\subsystem\callback.dm" #include "code\controllers\subsystem\chat.dm" @@ -1481,6 +1482,8 @@ #include "code\modules\admin\stickyban.dm" #include "code\modules\admin\topic.dm" #include "code\modules\admin\whitelist.dm" +#include "code\modules\admin\bccm\tgui_asn.dm" +#include "code\modules\admin\bccm\tgui_whitelist.dm" #include "code\modules\admin\callproc\callproc.dm" #include "code\modules\admin\DB_ban\functions.dm" #include "code\modules\admin\verbs\adminhelp.dm" diff --git a/tgui/packages/tgui/interfaces/BCCMASNPanel.tsx b/tgui/packages/tgui/interfaces/BCCMASNPanel.tsx new file mode 100644 index 00000000000..913ccf74d74 --- /dev/null +++ b/tgui/packages/tgui/interfaces/BCCMASNPanel.tsx @@ -0,0 +1,104 @@ +import { useBackend, useLocalState } from '../backend'; +import { Section, Flex, Stack, Button, Box, Input, NoticeBox } from '../components'; +import { Window } from '../layouts'; + +type BCCMDisplayData = { + a_ckey: string; + timestamp: string; + asn: string; +}; + +type Data = { + displayData: Array; +}; + +export const BCCMASNPanel = (props, context) => { + const { act, data } = useBackend(context); + const { displayData } = data; + const [inputIP, setinputIP] = useLocalState(context, 'inputIPkey', ''); + return ( + + +
+ + + { + setinputIP(value); + }} + /> + + +
+
+ {((displayData?.length || 0) !== 0 && ( + + + + + ASN + + + TIMESTAMP + + + ADMIN CKEY + + + + + + {displayData.map((displayRow, index) => { + return ( + + + + + {displayRow.asn} + + + {displayRow.timestamp} + + + {displayRow.a_ckey} + + +
+
+
+ ); +}; diff --git a/tgui/packages/tgui/interfaces/BCCMWhitelistPanel.tsx b/tgui/packages/tgui/interfaces/BCCMWhitelistPanel.tsx new file mode 100644 index 00000000000..6f83759a6ea --- /dev/null +++ b/tgui/packages/tgui/interfaces/BCCMWhitelistPanel.tsx @@ -0,0 +1,108 @@ +import { useBackend, useLocalState } from '../backend'; +import { Section, Flex, Stack, Button, Box, Input, NoticeBox } from '../components'; +import { Window } from '../layouts'; + +type BCCMDisplayData = { + ckey: string; + timestamp: string; + a_ckey: string; +}; + +type Data = { + displayData: Array; +}; + +export const BCCMWhitelistPanel = (props, context) => { + const { act, data } = useBackend(context); + const { displayData } = data; + const [inputWLCkey, setInputWLCkey] = useLocalState( + context, + 'inputWLCkey', + '' + ); + return ( + + +
+ + + { + setInputWLCkey(value); + }} + /> + + +
+
+ {((displayData?.length || 0)!== 0 && ( + + + + + CKEY + + + TIMESTAMP + + + ADMIN CKEY + + + + + + {displayData.map((displayRow, index) => { + return ( + + + + + {displayRow.ckey} + + + {displayRow.timestamp} + + + {displayRow.a_ckey} + + +
+
+
+ ); +};