web_service: Change authentication system to use JWT (#4041)
* Change authentication system to JWT * Address review comments * Get rid of global variable, fix some documentations, fix a bug when verificating * Refactor PostJson to avoid code duplication * Rename jwt_token, add functionality to request a new JWT when getting a 401 * Take bools by value instead of const reference * Send request again when JWT is invalid and use forward declarations * Omit brackets
This commit is contained in:
parent
b49d042200
commit
604c1b5fc3
|
@ -24,6 +24,7 @@ struct WebResult {
|
||||||
};
|
};
|
||||||
Code result_code;
|
Code result_code;
|
||||||
std::string result_string;
|
std::string result_string;
|
||||||
|
std::string returned_data;
|
||||||
};
|
};
|
||||||
} // namespace Common
|
} // namespace Common
|
||||||
|
|
||||||
|
|
|
@ -84,7 +84,7 @@ void RoomJson::AddPlayer(const std::string& nickname,
|
||||||
|
|
||||||
std::future<Common::WebResult> RoomJson::Announce() {
|
std::future<Common::WebResult> RoomJson::Announce() {
|
||||||
nlohmann::json json = room;
|
nlohmann::json json = room;
|
||||||
return PostJson(endpoint_url, json.dump(), false, username, token);
|
return PostJson(endpoint_url, json.dump(), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RoomJson::ClearPlayers() {
|
void RoomJson::ClearPlayers() {
|
||||||
|
@ -99,14 +99,13 @@ std::future<AnnounceMultiplayerRoom::RoomList> RoomJson::GetRoomList(std::functi
|
||||||
func();
|
func();
|
||||||
return room_list;
|
return room_list;
|
||||||
};
|
};
|
||||||
return GetJson<AnnounceMultiplayerRoom::RoomList>(DeSerialize, endpoint_url, true, username,
|
return GetJson<AnnounceMultiplayerRoom::RoomList>(DeSerialize, endpoint_url, true);
|
||||||
token);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RoomJson::Delete() {
|
void RoomJson::Delete() {
|
||||||
nlohmann::json json;
|
nlohmann::json json;
|
||||||
json["id"] = room.UID;
|
json["id"] = room.UID;
|
||||||
DeleteJson(endpoint_url, json.dump(), username, token);
|
DeleteJson(endpoint_url, json.dump());
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace WebService
|
} // namespace WebService
|
||||||
|
|
|
@ -82,7 +82,7 @@ void TelemetryJson::Complete() {
|
||||||
SerializeSection(Telemetry::FieldType::UserSystem, "UserSystem");
|
SerializeSection(Telemetry::FieldType::UserSystem, "UserSystem");
|
||||||
|
|
||||||
// Send the telemetry async but don't handle the errors since they were written to the log
|
// Send the telemetry async but don't handle the errors since they were written to the log
|
||||||
future = PostJson(endpoint_url, TopSection().dump(), true, username, token);
|
future = PostJson(endpoint_url, TopSection().dump(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace WebService
|
} // namespace WebService
|
||||||
|
|
|
@ -26,7 +26,8 @@ std::future<bool> VerifyLogin(std::string& username, std::string& token,
|
||||||
|
|
||||||
return username == *iter;
|
return username == *iter;
|
||||||
};
|
};
|
||||||
return GetJson<bool>(get_func, endpoint_url, false, username, token);
|
UpdateCoreJWT(true, username, token);
|
||||||
|
return GetJson<bool>(get_func, endpoint_url, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace WebService
|
} // namespace WebService
|
||||||
|
|
|
@ -6,9 +6,9 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <LUrlParser.h>
|
#include <LUrlParser.h>
|
||||||
#include <httplib.h>
|
|
||||||
#include "common/announce_multiplayer_room.h"
|
#include "common/announce_multiplayer_room.h"
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
|
#include "core/settings.h"
|
||||||
#include "web_service/web_backend.h"
|
#include "web_service/web_backend.h"
|
||||||
|
|
||||||
namespace WebService {
|
namespace WebService {
|
||||||
|
@ -20,6 +20,19 @@ constexpr int HTTPS_PORT = 443;
|
||||||
|
|
||||||
constexpr int TIMEOUT_SECONDS = 30;
|
constexpr int TIMEOUT_SECONDS = 30;
|
||||||
|
|
||||||
|
std::string UpdateCoreJWT(bool force_new_token, const std::string& username,
|
||||||
|
const std::string& token) {
|
||||||
|
static std::string jwt;
|
||||||
|
if (jwt.empty() || force_new_token) {
|
||||||
|
if (!username.empty() && !token.empty()) {
|
||||||
|
std::future<Common::WebResult> future =
|
||||||
|
PostJson("https://api.citra-emu.org/jwt/internal", username, token);
|
||||||
|
jwt = future.get().returned_data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return jwt;
|
||||||
|
}
|
||||||
|
|
||||||
std::unique_ptr<httplib::Client> GetClientFor(const LUrlParser::clParseURL& parsedUrl) {
|
std::unique_ptr<httplib::Client> GetClientFor(const LUrlParser::clParseURL& parsedUrl) {
|
||||||
namespace hl = httplib;
|
namespace hl = httplib;
|
||||||
|
|
||||||
|
@ -43,8 +56,102 @@ std::unique_ptr<httplib::Client> GetClientFor(const LUrlParser::clParseURL& pars
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Common::WebResult PostJsonAsyncFn(const std::string& url,
|
||||||
|
const LUrlParser::clParseURL& parsed_url,
|
||||||
|
const httplib::Headers& params, const std::string& data,
|
||||||
|
bool is_jwt_requested) {
|
||||||
|
static bool is_first_attempt = true;
|
||||||
|
|
||||||
|
namespace hl = httplib;
|
||||||
|
std::unique_ptr<hl::Client> cli = GetClientFor(parsed_url);
|
||||||
|
|
||||||
|
if (cli == nullptr) {
|
||||||
|
return Common::WebResult{Common::WebResult::Code::InvalidURL, "URL is invalid"};
|
||||||
|
}
|
||||||
|
|
||||||
|
hl::Request request;
|
||||||
|
request.method = "POST";
|
||||||
|
request.path = "/" + parsed_url.m_Path;
|
||||||
|
request.headers = params;
|
||||||
|
request.body = data;
|
||||||
|
|
||||||
|
hl::Response response;
|
||||||
|
|
||||||
|
if (!cli->send(request, response)) {
|
||||||
|
LOG_ERROR(WebService, "POST to {} returned null", url);
|
||||||
|
return Common::WebResult{Common::WebResult::Code::LibError, "Null response"};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (response.status >= 400) {
|
||||||
|
LOG_ERROR(WebService, "POST to {} returned error status code: {}", url, response.status);
|
||||||
|
if (response.status == 401 && !is_jwt_requested && is_first_attempt) {
|
||||||
|
LOG_WARNING(WebService, "Requesting new JWT");
|
||||||
|
UpdateCoreJWT(true, Settings::values.citra_username, Settings::values.citra_token);
|
||||||
|
is_first_attempt = false;
|
||||||
|
PostJsonAsyncFn(url, parsed_url, params, data, is_jwt_requested);
|
||||||
|
is_first_attempt = true;
|
||||||
|
}
|
||||||
|
return Common::WebResult{Common::WebResult::Code::HttpError,
|
||||||
|
std::to_string(response.status)};
|
||||||
|
}
|
||||||
|
|
||||||
|
auto content_type = response.headers.find("content-type");
|
||||||
|
|
||||||
|
if (content_type == response.headers.end() ||
|
||||||
|
(content_type->second.find("application/json") == std::string::npos &&
|
||||||
|
content_type->second.find("text/html; charset=utf-8") == std::string::npos)) {
|
||||||
|
LOG_ERROR(WebService, "POST to {} returned wrong content: {}", url, content_type->second);
|
||||||
|
return Common::WebResult{Common::WebResult::Code::WrongContent, ""};
|
||||||
|
}
|
||||||
|
|
||||||
|
return Common::WebResult{Common::WebResult::Code::Success, "", response.body};
|
||||||
|
}
|
||||||
|
|
||||||
std::future<Common::WebResult> PostJson(const std::string& url, const std::string& data,
|
std::future<Common::WebResult> PostJson(const std::string& url, const std::string& data,
|
||||||
bool allow_anonymous, const std::string& username,
|
bool allow_anonymous) {
|
||||||
|
|
||||||
|
using lup = LUrlParser::clParseURL;
|
||||||
|
namespace hl = httplib;
|
||||||
|
|
||||||
|
lup parsedUrl = lup::ParseURL(url);
|
||||||
|
|
||||||
|
if (url.empty() || !parsedUrl.IsValid()) {
|
||||||
|
LOG_ERROR(WebService, "URL is invalid");
|
||||||
|
return std::async(std::launch::deferred, [] {
|
||||||
|
return Common::WebResult{Common::WebResult::Code::InvalidURL, "URL is invalid"};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string jwt =
|
||||||
|
UpdateCoreJWT(false, Settings::values.citra_username, Settings::values.citra_token);
|
||||||
|
|
||||||
|
const bool are_credentials_provided{!jwt.empty()};
|
||||||
|
if (!allow_anonymous && !are_credentials_provided) {
|
||||||
|
LOG_ERROR(WebService, "Credentials must be provided for authenticated requests");
|
||||||
|
return std::async(std::launch::deferred, [] {
|
||||||
|
return Common::WebResult{Common::WebResult::Code::CredentialsMissing,
|
||||||
|
"Credentials needed"};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Built request header
|
||||||
|
hl::Headers params;
|
||||||
|
if (are_credentials_provided) {
|
||||||
|
// Authenticated request if credentials are provided
|
||||||
|
params = {{std::string("Authorization"), fmt::format("Bearer {}", jwt)},
|
||||||
|
{std::string("api-version"), std::string(API_VERSION)},
|
||||||
|
{std::string("Content-Type"), std::string("application/json")}};
|
||||||
|
} else {
|
||||||
|
// Otherwise, anonymous request
|
||||||
|
params = {{std::string("api-version"), std::string(API_VERSION)},
|
||||||
|
{std::string("Content-Type"), std::string("application/json")}};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Post JSON asynchronously
|
||||||
|
return std::async(std::launch::async, PostJsonAsyncFn, url, parsedUrl, params, data, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::future<Common::WebResult> PostJson(const std::string& url, const std::string& username,
|
||||||
const std::string& token) {
|
const std::string& token) {
|
||||||
using lup = LUrlParser::clParseURL;
|
using lup = LUrlParser::clParseURL;
|
||||||
namespace hl = httplib;
|
namespace hl = httplib;
|
||||||
|
@ -53,17 +160,16 @@ std::future<Common::WebResult> PostJson(const std::string& url, const std::strin
|
||||||
|
|
||||||
if (url.empty() || !parsedUrl.IsValid()) {
|
if (url.empty() || !parsedUrl.IsValid()) {
|
||||||
LOG_ERROR(WebService, "URL is invalid");
|
LOG_ERROR(WebService, "URL is invalid");
|
||||||
return std::async(std::launch::deferred, []() {
|
return std::async(std::launch::deferred, [] {
|
||||||
return Common::WebResult{Common::WebResult::Code::InvalidURL, "URL is invalid"};
|
return Common::WebResult{Common::WebResult::Code::InvalidURL, ""};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool are_credentials_provided{!token.empty() && !username.empty()};
|
const bool are_credentials_provided{!token.empty() && !username.empty()};
|
||||||
if (!allow_anonymous && !are_credentials_provided) {
|
if (!are_credentials_provided) {
|
||||||
LOG_ERROR(WebService, "Credentials must be provided for authenticated requests");
|
LOG_ERROR(WebService, "Credentials must be provided for authenticated requests");
|
||||||
return std::async(std::launch::deferred, []() {
|
return std::async(std::launch::deferred, [] {
|
||||||
return Common::WebResult{Common::WebResult::Code::CredentialsMissing,
|
return Common::WebResult{Common::WebResult::Code::CredentialsMissing, ""};
|
||||||
"Credentials needed"};
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,50 +188,14 @@ std::future<Common::WebResult> PostJson(const std::string& url, const std::strin
|
||||||
}
|
}
|
||||||
|
|
||||||
// Post JSON asynchronously
|
// Post JSON asynchronously
|
||||||
return std::async(std::launch::async, [url, parsedUrl, params, data] {
|
return std::async(std::launch::async, PostJsonAsyncFn, url, parsedUrl, params, "", true);
|
||||||
std::unique_ptr<hl::Client> cli = GetClientFor(parsedUrl);
|
|
||||||
|
|
||||||
if (cli == nullptr) {
|
|
||||||
return Common::WebResult{Common::WebResult::Code::InvalidURL, "URL is invalid"};
|
|
||||||
}
|
|
||||||
|
|
||||||
hl::Request request;
|
|
||||||
request.method = "POST";
|
|
||||||
request.path = "/" + parsedUrl.m_Path;
|
|
||||||
request.headers = params;
|
|
||||||
request.body = data;
|
|
||||||
|
|
||||||
hl::Response response;
|
|
||||||
|
|
||||||
if (!cli->send(request, response)) {
|
|
||||||
LOG_ERROR(WebService, "POST to {} returned null", url);
|
|
||||||
return Common::WebResult{Common::WebResult::Code::LibError, "Null response"};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (response.status >= 400) {
|
|
||||||
LOG_ERROR(WebService, "POST to {} returned error status code: {}", url,
|
|
||||||
response.status);
|
|
||||||
return Common::WebResult{Common::WebResult::Code::HttpError,
|
|
||||||
std::to_string(response.status)};
|
|
||||||
}
|
|
||||||
|
|
||||||
auto content_type = response.headers.find("content-type");
|
|
||||||
|
|
||||||
if (content_type == response.headers.end() ||
|
|
||||||
content_type->second.find("application/json") == std::string::npos) {
|
|
||||||
LOG_ERROR(WebService, "POST to {} returned wrong content: {}", url,
|
|
||||||
content_type->second);
|
|
||||||
return Common::WebResult{Common::WebResult::Code::WrongContent, content_type->second};
|
|
||||||
}
|
|
||||||
|
|
||||||
return Common::WebResult{Common::WebResult::Code::Success, ""};
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
std::future<T> GetJson(std::function<T(const std::string&)> func, const std::string& url,
|
std::future<T> GetJson(std::function<T(const std::string&)> func, const std::string& url,
|
||||||
bool allow_anonymous, const std::string& username,
|
bool allow_anonymous) {
|
||||||
const std::string& token) {
|
static bool is_first_attempt = true;
|
||||||
|
|
||||||
using lup = LUrlParser::clParseURL;
|
using lup = LUrlParser::clParseURL;
|
||||||
namespace hl = httplib;
|
namespace hl = httplib;
|
||||||
|
|
||||||
|
@ -136,7 +206,10 @@ std::future<T> GetJson(std::function<T(const std::string&)> func, const std::str
|
||||||
return std::async(std::launch::deferred, [func{std::move(func)}]() { return func(""); });
|
return std::async(std::launch::deferred, [func{std::move(func)}]() { return func(""); });
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool are_credentials_provided{!token.empty() && !username.empty()};
|
const std::string jwt =
|
||||||
|
UpdateCoreJWT(false, Settings::values.citra_username, Settings::values.citra_token);
|
||||||
|
|
||||||
|
const bool are_credentials_provided{!jwt.empty()};
|
||||||
if (!allow_anonymous && !are_credentials_provided) {
|
if (!allow_anonymous && !are_credentials_provided) {
|
||||||
LOG_ERROR(WebService, "Credentials must be provided for authenticated requests");
|
LOG_ERROR(WebService, "Credentials must be provided for authenticated requests");
|
||||||
return std::async(std::launch::deferred, [func{std::move(func)}]() { return func(""); });
|
return std::async(std::launch::deferred, [func{std::move(func)}]() { return func(""); });
|
||||||
|
@ -145,9 +218,7 @@ std::future<T> GetJson(std::function<T(const std::string&)> func, const std::str
|
||||||
// Built request header
|
// Built request header
|
||||||
hl::Headers params;
|
hl::Headers params;
|
||||||
if (are_credentials_provided) {
|
if (are_credentials_provided) {
|
||||||
// Authenticated request if credentials are provided
|
params = {{std::string("Authorization"), fmt::format("Bearer {}", jwt)},
|
||||||
params = {{std::string("x-username"), username},
|
|
||||||
{std::string("x-token"), token},
|
|
||||||
{std::string("api-version"), std::string(API_VERSION)}};
|
{std::string("api-version"), std::string(API_VERSION)}};
|
||||||
} else {
|
} else {
|
||||||
// Otherwise, anonymous request
|
// Otherwise, anonymous request
|
||||||
|
@ -155,7 +226,7 @@ std::future<T> GetJson(std::function<T(const std::string&)> func, const std::str
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get JSON asynchronously
|
// Get JSON asynchronously
|
||||||
return std::async(std::launch::async, [func, url, parsedUrl, params] {
|
return std::async(std::launch::async, [func, url, parsedUrl, params, allow_anonymous] {
|
||||||
std::unique_ptr<hl::Client> cli = GetClientFor(parsedUrl);
|
std::unique_ptr<hl::Client> cli = GetClientFor(parsedUrl);
|
||||||
|
|
||||||
if (cli == nullptr) {
|
if (cli == nullptr) {
|
||||||
|
@ -176,6 +247,13 @@ std::future<T> GetJson(std::function<T(const std::string&)> func, const std::str
|
||||||
|
|
||||||
if (response.status >= 400) {
|
if (response.status >= 400) {
|
||||||
LOG_ERROR(WebService, "GET to {} returned error status code: {}", url, response.status);
|
LOG_ERROR(WebService, "GET to {} returned error status code: {}", url, response.status);
|
||||||
|
if (response.status == 401 && is_first_attempt) {
|
||||||
|
LOG_WARNING(WebService, "Requesting new JWT");
|
||||||
|
UpdateCoreJWT(true, Settings::values.citra_username, Settings::values.citra_token);
|
||||||
|
is_first_attempt = false;
|
||||||
|
GetJson(func, url, allow_anonymous);
|
||||||
|
is_first_attempt = true;
|
||||||
|
}
|
||||||
return func("");
|
return func("");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -193,15 +271,14 @@ std::future<T> GetJson(std::function<T(const std::string&)> func, const std::str
|
||||||
}
|
}
|
||||||
|
|
||||||
template std::future<bool> GetJson(std::function<bool(const std::string&)> func,
|
template std::future<bool> GetJson(std::function<bool(const std::string&)> func,
|
||||||
const std::string& url, bool allow_anonymous,
|
const std::string& url, bool allow_anonymous);
|
||||||
const std::string& username, const std::string& token);
|
|
||||||
template std::future<AnnounceMultiplayerRoom::RoomList> GetJson(
|
template std::future<AnnounceMultiplayerRoom::RoomList> GetJson(
|
||||||
std::function<AnnounceMultiplayerRoom::RoomList(const std::string&)> func,
|
std::function<AnnounceMultiplayerRoom::RoomList(const std::string&)> func,
|
||||||
const std::string& url, bool allow_anonymous, const std::string& username,
|
const std::string& url, bool allow_anonymous);
|
||||||
const std::string& token);
|
|
||||||
|
void DeleteJson(const std::string& url, const std::string& data) {
|
||||||
|
static bool is_first_attempt = true;
|
||||||
|
|
||||||
void DeleteJson(const std::string& url, const std::string& data, const std::string& username,
|
|
||||||
const std::string& token) {
|
|
||||||
using lup = LUrlParser::clParseURL;
|
using lup = LUrlParser::clParseURL;
|
||||||
namespace hl = httplib;
|
namespace hl = httplib;
|
||||||
|
|
||||||
|
@ -212,15 +289,17 @@ void DeleteJson(const std::string& url, const std::string& data, const std::stri
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool are_credentials_provided{!token.empty() && !username.empty()};
|
const std::string jwt =
|
||||||
|
UpdateCoreJWT(false, Settings::values.citra_username, Settings::values.citra_token);
|
||||||
|
|
||||||
|
const bool are_credentials_provided{!jwt.empty()};
|
||||||
if (!are_credentials_provided) {
|
if (!are_credentials_provided) {
|
||||||
LOG_ERROR(WebService, "Credentials must be provided for authenticated requests");
|
LOG_ERROR(WebService, "Credentials must be provided for authenticated requests");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Built request header
|
// Built request header
|
||||||
hl::Headers params = {{std::string("x-username"), username},
|
hl::Headers params = {{std::string("Authorization"), fmt::format("Bearer {}", jwt)},
|
||||||
{std::string("x-token"), token},
|
|
||||||
{std::string("api-version"), std::string(API_VERSION)},
|
{std::string("api-version"), std::string(API_VERSION)},
|
||||||
{std::string("Content-Type"), std::string("application/json")}};
|
{std::string("Content-Type"), std::string("application/json")}};
|
||||||
|
|
||||||
|
@ -248,6 +327,13 @@ void DeleteJson(const std::string& url, const std::string& data, const std::stri
|
||||||
if (response.status >= 400) {
|
if (response.status >= 400) {
|
||||||
LOG_ERROR(WebService, "DELETE to {} returned error status code: {}", url,
|
LOG_ERROR(WebService, "DELETE to {} returned error status code: {}", url,
|
||||||
response.status);
|
response.status);
|
||||||
|
if (response.status == 401 && is_first_attempt) {
|
||||||
|
LOG_WARNING(WebService, "Requesting new JWT");
|
||||||
|
UpdateCoreJWT(true, Settings::values.citra_username, Settings::values.citra_token);
|
||||||
|
is_first_attempt = false;
|
||||||
|
DeleteJson(url, data);
|
||||||
|
is_first_attempt = true;
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,46 +8,76 @@
|
||||||
#include <future>
|
#include <future>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
|
#include <httplib.h>
|
||||||
#include "common/announce_multiplayer_room.h"
|
#include "common/announce_multiplayer_room.h"
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
|
|
||||||
|
namespace LUrlParser {
|
||||||
|
class clParseURL;
|
||||||
|
}
|
||||||
|
|
||||||
namespace WebService {
|
namespace WebService {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Posts JSON to services.citra-emu.org.
|
* Requests a new JWT if necessary
|
||||||
* @param url URL of the services.citra-emu.org endpoint to post data to.
|
* @param force_new_token If true, force to request a new token from the server.
|
||||||
|
* @param username Citra username to use for authentication.
|
||||||
|
* @param token Citra token to use for authentication.
|
||||||
|
* @return string with the current JWT toke
|
||||||
|
*/
|
||||||
|
std::string UpdateCoreJWT(bool force_new_token, const std::string& username,
|
||||||
|
const std::string& token);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Posts JSON to a api.citra-emu.org.
|
||||||
|
* @param url URL of the api.citra-emu.org endpoint to post data to.
|
||||||
|
* @param parsed_url Parsed URL used for the POST request.
|
||||||
|
* @param params Headers sent for the POST request.
|
||||||
|
* @param data String of JSON data to use for the body of the POST request.
|
||||||
|
* @param data If true, a JWT is requested in the function
|
||||||
|
* @return future with the returned value of the POST
|
||||||
|
*/
|
||||||
|
static Common::WebResult PostJsonAsyncFn(const std::string& url,
|
||||||
|
const LUrlParser::clParseURL& parsed_url,
|
||||||
|
const httplib::Headers& params, const std::string& data,
|
||||||
|
bool is_jwt_requested);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Posts JSON to api.citra-emu.org.
|
||||||
|
* @param url URL of the api.citra-emu.org endpoint to post data to.
|
||||||
* @param data String of JSON data to use for the body of the POST request.
|
* @param data String of JSON data to use for the body of the POST request.
|
||||||
* @param allow_anonymous If true, allow anonymous unauthenticated requests.
|
* @param allow_anonymous If true, allow anonymous unauthenticated requests.
|
||||||
|
* @return future with the returned value of the POST
|
||||||
|
*/
|
||||||
|
std::future<Common::WebResult> PostJson(const std::string& url, const std::string& data,
|
||||||
|
bool allow_anonymous);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Posts JSON to api.citra-emu.org.
|
||||||
|
* @param url URL of the api.citra-emu.org endpoint to post data to.
|
||||||
* @param username Citra username to use for authentication.
|
* @param username Citra username to use for authentication.
|
||||||
* @param token Citra token to use for authentication.
|
* @param token Citra token to use for authentication.
|
||||||
* @return future with the error or result of the POST
|
* @return future with the error or result of the POST
|
||||||
*/
|
*/
|
||||||
std::future<Common::WebResult> PostJson(const std::string& url, const std::string& data,
|
std::future<Common::WebResult> PostJson(const std::string& url, const std::string& username,
|
||||||
bool allow_anonymous, const std::string& username = {},
|
const std::string& token);
|
||||||
const std::string& token = {});
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets JSON from services.citra-emu.org.
|
* Gets JSON from api.citra-emu.org.
|
||||||
* @param func A function that gets exectued when the json as a string is received
|
* @param func A function that gets exectued when the json as a string is received
|
||||||
* @param url URL of the services.citra-emu.org endpoint to post data to.
|
* @param url URL of the api.citra-emu.org endpoint to post data to.
|
||||||
* @param allow_anonymous If true, allow anonymous unauthenticated requests.
|
* @param allow_anonymous If true, allow anonymous unauthenticated requests.
|
||||||
* @param username Citra username to use for authentication.
|
|
||||||
* @param token Citra token to use for authentication.
|
|
||||||
* @return future that holds the return value T of the func
|
* @return future that holds the return value T of the func
|
||||||
*/
|
*/
|
||||||
template <typename T>
|
template <typename T>
|
||||||
std::future<T> GetJson(std::function<T(const std::string&)> func, const std::string& url,
|
std::future<T> GetJson(std::function<T(const std::string&)> func, const std::string& url,
|
||||||
bool allow_anonymous, const std::string& username = {},
|
bool allow_anonymous);
|
||||||
const std::string& token = {});
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete JSON to services.citra-emu.org.
|
* Delete JSON to api.citra-emu.org.
|
||||||
* @param url URL of the services.citra-emu.org endpoint to post data to.
|
* @param url URL of the api.citra-emu.org endpoint to post data to.
|
||||||
* @param data String of JSON data to use for the body of the DELETE request.
|
* @param data String of JSON data to use for the body of the DELETE request.
|
||||||
* @param username Citra username to use for authentication.
|
|
||||||
* @param token Citra token to use for authentication.
|
|
||||||
*/
|
*/
|
||||||
void DeleteJson(const std::string& url, const std::string& data, const std::string& username = {},
|
void DeleteJson(const std::string& url, const std::string& data);
|
||||||
const std::string& token = {});
|
|
||||||
|
|
||||||
} // namespace WebService
|
} // namespace WebService
|
||||||
|
|
Reference in New Issue