From db3a3c8bc2cfd90dda6a47c7244458743ec29cd3 Mon Sep 17 00:00:00 2001 From: AffectedArc07 <25063394+AffectedArc07@users.noreply.github.com> Date: Fri, 5 Nov 2021 13:04:49 +0000 Subject: [PATCH] Adds Paradise API support (#16981) --- code/__DEFINES/misc.dm | 3 ++ code/__HELPERS/api.dm | 40 +++++++++++++++++++ code/__HELPERS/unsorted.dm | 3 -- .../sections/system_configuration.dm | 9 +++-- code/modules/admin/IsBanned.dm | 2 +- code/modules/client/2fa.dm | 21 ++-------- config/example/config.toml | 6 ++- paradise.dme | 1 + 8 files changed, 59 insertions(+), 26 deletions(-) create mode 100644 code/__HELPERS/api.dm diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm index c6b7e9ac430..b05cdbb7635 100644 --- a/code/__DEFINES/misc.dm +++ b/code/__DEFINES/misc.dm @@ -496,3 +496,6 @@ // Runechat symbol types #define RUNECHAT_SYMBOL_EMOTE 1 + +/// Waits at a line of code until X is true +#define UNTIL(X) while(!(X)) sleep(world.tick_lag) diff --git a/code/__HELPERS/api.dm b/code/__HELPERS/api.dm new file mode 100644 index 00000000000..1a0b567e959 --- /dev/null +++ b/code/__HELPERS/api.dm @@ -0,0 +1,40 @@ +// This file contains procs for interacting with the internal API + +/** + * Internal API Caller + * + * Makes calls to the internal Paradise API and returns a [/datum/http_response]. + * + * Arguments: + * * method - The relevant HTTP method to use + * * path - The path of the API call. DO NOT USE A LEADING SLASH + * * body - The request body, if applicable + */ +/proc/MakeAPICall(method, path, body) + if(!method || !path) + // Needs valid params + return null + if(!GLOB.configuration.system.api_host || !GLOB.configuration.system.api_key) + // Needs these set in config + return null + + if(IsAdminAdvancedProcCall()) + // Admins shouldnt fuck with this + to_chat(usr, "API interaction blocked: Advanced ProcCall detected.") + message_admins("[key_name(usr)] attempted to interact with the internal API via advanced proc-call") + log_admin("[key_name(usr)] attempted to interact with the internal API via advanced proc-call") + return + + var/datum/http_request/req = new() + var/target_url = "[GLOB.configuration.system.api_host]/[path]" + // You may be asking, "Hey AA, why is the above a var instead of just using it directly?" + // Ill tell you why. This lets you breakpoint it in the debugger to see if the URL is + // what you wanted or not, given how slashes and stuff can break it. + req.prepare(method, target_url, body, list("AuthKey" = GLOB.configuration.system.api_key)) + req.begin_async() + // Check if we are complete + UNTIL(req.is_complete()) + var/datum/http_response/res = req.into_response() + + return res + diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm index 399f669761e..ec66b5b051a 100644 --- a/code/__HELPERS/unsorted.dm +++ b/code/__HELPERS/unsorted.dm @@ -2047,9 +2047,6 @@ GLOBAL_DATUM_INIT(dview_mob, /mob/dview, new) ) return _list -/// Waits at a line of code until X is true -#define UNTIL(X) while(!(X)) sleep(world.tick_lag) - // Check if the source atom contains another atom /atom/proc/contains(atom/location) if(!location) diff --git a/code/controllers/configuration/sections/system_configuration.dm b/code/controllers/configuration/sections/system_configuration.dm index a7623dfacc4..054b8f1438c 100644 --- a/code/controllers/configuration/sections/system_configuration.dm +++ b/code/controllers/configuration/sections/system_configuration.dm @@ -14,8 +14,10 @@ var/is_production = FALSE /// If above is true, you can run a shell command var/shutdown_shell_command = null - /// 2FA backend server host - var/_2fa_auth_host = null + /// Internal API host + var/api_host = null + /// Internal API key + var/api_key = null /// List of IP addresses which bypass world topic rate limiting var/list/topic_ip_ratelimit_bypass = list() /// Server instance ID @@ -32,7 +34,8 @@ CONFIG_LOAD_STR(medal_hub_address, data["medal_hub_address"]) CONFIG_LOAD_STR(medal_hub_password, data["medal_hub_password"]) CONFIG_LOAD_STR(shutdown_shell_command, data["shutdown_shell_command"]) - CONFIG_LOAD_STR(_2fa_auth_host, data["_2fa_auth_host"]) + CONFIG_LOAD_STR(api_host, data["api_host"]) + CONFIG_LOAD_STR(api_key, data["api_key"]) CONFIG_LOAD_LIST(topic_ip_ratelimit_bypass, data["topic_ip_ratelimit_bypass"]) diff --git a/code/modules/admin/IsBanned.dm b/code/modules/admin/IsBanned.dm index 9e04eb3c8ba..c4d6d4ae9c6 100644 --- a/code/modules/admin/IsBanned.dm +++ b/code/modules/admin/IsBanned.dm @@ -51,7 +51,7 @@ // If 2FA is enabled, makes sure they were authed within the last minute - if(check_2fa && GLOB.configuration.system._2fa_auth_host) + if(check_2fa && GLOB.configuration.system.api_host) // First see if they exist at all var/datum/db_query/check_query = SSdbcore.NewQuery("SELECT 2fa_status, ip FROM player WHERE ckey=:ckey", list("ckey" = ckey(key))) diff --git a/code/modules/client/2fa.dm b/code/modules/client/2fa.dm index 930670d1867..c65d52f7c4c 100644 --- a/code/modules/client/2fa.dm +++ b/code/modules/client/2fa.dm @@ -1,12 +1,12 @@ // This is in its own file as it has so much stuff to contend with /client/proc/edit_2fa() - if(!GLOB.configuration.system._2fa_auth_host) + if(!GLOB.configuration.system.api_host) alert(usr, "This server does not have 2FA enabled.") return // Client does not have 2FA enabled. Set it up. if(prefs._2fa_status == _2FA_DISABLED) // Get us an auth token - var/datum/http_response/qrcr = wrap_http_get("[GLOB.configuration.system._2fa_auth_host]/generateQR?ckey=[ckey]") + var/datum/http_response/qrcr = MakeAPICall(RUSTG_HTTP_METHOD_GET, "2fa/generate_qr?ckey=[ckey]") // If this fails, shits gone bad if(qrcr.errored) alert(usr, "Something has gone VERY wrong ingame. Please inform the server host.\nError details: [qrcr.error]") @@ -33,7 +33,7 @@ B.close() return - var/datum/http_response/vr = wrap_http_get("[GLOB.configuration.system._2fa_auth_host]/validateCode?ckey=[ckey]&code=[entered_code]") + var/datum/http_response/vr = MakeAPICall(RUSTG_HTTP_METHOD_GET, "2fa/validate_code?ckey=[ckey]&code=[entered_code]") // If this fails, shits gone bad if(vr.errored) alert(usr, "Something has gone VERY wrong ingame. Please inform the server host.\nError details: [vr.error]") @@ -86,7 +86,7 @@ alert(usr, "2FA deactivation aborted!") return - var/datum/http_response/vr = wrap_http_get("[GLOB.configuration.system._2fa_auth_host]/validateCode?ckey=[ckey]&code=[entered_code]") + var/datum/http_response/vr = MakeAPICall(RUSTG_HTTP_METHOD_GET, "2fa/validate_code?ckey=[ckey]&code=[entered_code]") // If this fails, shits gone bad if(vr.errored) alert(usr, "Something has gone VERY wrong ingame. Please inform the server host.\nError details: [vr.error]") @@ -116,16 +116,3 @@ return "Enabled (Will prompt on IP changes)" if(_2FA_ENABLED_ALWAYS) return "Enabled (Will prompt every time)" - - -// Proc to wrap HTTP requests properly, without needing SShttp firing -/proc/wrap_http_get(url) - var/datum/http_request/req = new() - req.prepare(RUSTG_HTTP_METHOD_GET, url) - req.begin_async() - // Check if we are complete - UNTIL(req.is_complete()) - var/datum/http_response/res = req.into_response() - - return res - diff --git a/config/example/config.toml b/config/example/config.toml index a33c4555891..ad90552155e 100644 --- a/config/example/config.toml +++ b/config/example/config.toml @@ -718,8 +718,10 @@ lavaland_ruin_budget = 60 shutdown_on_reboot = false # If true to above, an optional shell command can be ran. Defaults to killing DD on windows #shutdown_shell_command = "taskkill /im dreamdaemon.exe /f" -# URL for the 2FA backend HTTP host. Do not use https:// or a trailing slash. Comment out to disable -#_2fa_auth_host = "http://127.0.0.1:8080" +# URL for the internal API host. See https://github.com/ParadiseSS13/ParadiseInternalAPI Do not use https:// or a trailing slash. Comment out to disable +#api_host = "http://127.0.0.1:8080" +# Access key for the internal API. +#api_key = "your_secret_here" # List of IP addresses to be ignored by the world/Topic rate limiting. Useful if you have other services topic_ip_ratelimit_bypass = ["127.0.0.1"] # Turn this to true if you are running a production server diff --git a/paradise.dme b/paradise.dme index 98b67164a4f..c0c7df3d96c 100644 --- a/paradise.dme +++ b/paradise.dme @@ -97,6 +97,7 @@ #include "code\__HELPERS\_logging.dm" #include "code\__HELPERS\_string_lists.dm" #include "code\__HELPERS\AnimationLibrary.dm" +#include "code\__HELPERS\api.dm" #include "code\__HELPERS\cmp.dm" #include "code\__HELPERS\constants.dm" #include "code\__HELPERS\debugger.dm"