Reworked.
This commit is contained in:
@@ -14,6 +14,7 @@ message(STATUS "Project description: ${PROJECT_DESCRIPTION}")
|
|||||||
# ----------------------------------------------------------------------------------------------------------------------
|
# ----------------------------------------------------------------------------------------------------------------------
|
||||||
set(INSTALL_AS_ROOT ON CACHE BOOL "Install as root")
|
set(INSTALL_AS_ROOT ON CACHE BOOL "Install as root")
|
||||||
set(WITH_POSTGRESQL OFF CACHE BOOL "Build with PostgreSQL")
|
set(WITH_POSTGRESQL OFF CACHE BOOL "Build with PostgreSQL")
|
||||||
|
set(WITH_SSL ON CACHE BOOL "Build with SSL")
|
||||||
set(WITH_SQLITE3 OFF CACHE BOOL "Build with Sqlite3")
|
set(WITH_SQLITE3 OFF CACHE BOOL "Build with Sqlite3")
|
||||||
set(WITH_CURL OFF CACHE BOOL "Build with cURL")
|
set(WITH_CURL OFF CACHE BOOL "Build with cURL")
|
||||||
set(WITH_BITCOIN_CLIENT ON CACHE BOOL "Build with libbitcoin-client")
|
set(WITH_BITCOIN_CLIENT ON CACHE BOOL "Build with libbitcoin-client")
|
||||||
@@ -256,7 +257,7 @@ target_compile_definitions(${CORE_LIB_NAME} PUBLIC
|
|||||||
APP_DOC_ROOT="www/"
|
APP_DOC_ROOT="www/"
|
||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries(${CORE_LIB_NAME} pthread ${PQ_LIB_NAME} ${SQLITE3_LIB_NAME} ${CURL_LIB_NAME} yaml-cpp ssl crypto)
|
target_link_libraries(${CORE_LIB_NAME} pthread ${PQ_LIB_NAME} ${SQLITE3_LIB_NAME} ${CURL_LIB_NAME} ${SSL_LIB_NAME} yaml-cpp crypto)
|
||||||
|
|
||||||
# Apostol modules
|
# Apostol modules
|
||||||
# ----------------------------------------------------------------------------------------------------------------------
|
# ----------------------------------------------------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -22,6 +22,16 @@ workers=1
|
|||||||
## default: true
|
## default: true
|
||||||
master=true
|
master=true
|
||||||
|
|
||||||
|
## Module: Web Service
|
||||||
|
[module/WebService]
|
||||||
|
## default: true
|
||||||
|
enable=true
|
||||||
|
|
||||||
|
## Module: Web Socket
|
||||||
|
[module/WebSocket]
|
||||||
|
## default: false
|
||||||
|
enable=false
|
||||||
|
|
||||||
[daemon]
|
[daemon]
|
||||||
## Run as daemon
|
## Run as daemon
|
||||||
## default: true
|
## default: true
|
||||||
|
|||||||
@@ -1,50 +1,9 @@
|
|||||||
{
|
{
|
||||||
"web": {
|
|
||||||
"issuers": ["accounts.bitdeals.org"],
|
|
||||||
"scopes": ["bitdeals"],
|
|
||||||
"client_id": "web-bitdeals.org",
|
|
||||||
"client_secret": "4aJEJi3dsSypeUSRCah4gIIs",
|
|
||||||
"algorithm": "HS256",
|
|
||||||
"auth_uri": "/oauth2/authorize",
|
|
||||||
"token_uri": "/oauth2/token",
|
|
||||||
"redirect_uris": [
|
|
||||||
"http://localhost:4977/oauth2/code",
|
|
||||||
"http://localhost:4977/dashboard/",
|
|
||||||
"http://localhost:4999/oauth2/code",
|
|
||||||
"http://localhost:4999/dashboard/",
|
|
||||||
"http://65.21.101.151/oauth2/code",
|
|
||||||
"http://65.21.101.151/dashboard",
|
|
||||||
"https://oauthdebugger.com/debug"
|
|
||||||
],
|
|
||||||
"javascript_origins": [
|
|
||||||
"http://localhost:4977",
|
|
||||||
"http://localhost:4999",
|
|
||||||
"http://65.21.101.151"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"service": {
|
|
||||||
"issuers": ["accounts.bitdeals.org"],
|
|
||||||
"scopes": ["bitdeals"],
|
|
||||||
"client_id": "service-bitdeals.org",
|
|
||||||
"client_secret": "TjcILDtLa06YABJnepcVM32O",
|
|
||||||
"algorithm": "HS256",
|
|
||||||
"auth_uri": "/oauth2/authorize",
|
|
||||||
"token_uri": "/oauth2/token",
|
|
||||||
"redirect_uris": [
|
|
||||||
"http://localhost:4977/dashboard",
|
|
||||||
"http://65.21.101.151/dashboard",
|
|
||||||
"https://oauthdebugger.com/debug"
|
|
||||||
],
|
|
||||||
"javascript_origins": [
|
|
||||||
"http://localhost:4977",
|
|
||||||
"http://65.21.101.151"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"module": {
|
"module": {
|
||||||
"issuers": ["accounts.bitdeals.org"],
|
"issuers": ["accounts.bitdeals.org"],
|
||||||
"scopes": ["bitdeals"],
|
"scopes": ["bitdeals"],
|
||||||
"client_id": "dm-bitdeals.org",
|
"client_id": "dm-bitdeals.org",
|
||||||
"client_secret": "TypQHP4TK44khO3cvOyuHYg3",
|
"client_secret": "",
|
||||||
"algorithm": "HS256",
|
"algorithm": "HS256",
|
||||||
"auth_uri": "/oauth2/authorize",
|
"auth_uri": "/oauth2/authorize",
|
||||||
"token_uri": "/oauth2/token",
|
"token_uri": "/oauth2/token",
|
||||||
@@ -54,33 +13,8 @@
|
|||||||
"https://oauthdebugger.com/debug"
|
"https://oauthdebugger.com/debug"
|
||||||
],
|
],
|
||||||
"javascript_origins": [
|
"javascript_origins": [
|
||||||
"http://localhost:4999"
|
"http://localhost:4999",
|
||||||
]
|
"http://95.217.251.153:4999"
|
||||||
},
|
|
||||||
"android": {
|
|
||||||
"issuers": ["accounts.bitdeals.org"],
|
|
||||||
"scopes": ["bitdeals"],
|
|
||||||
"client_id": "android-bitdeals.org",
|
|
||||||
"client_secret": "HaBAde09xWKb29NizXZfIMpl",
|
|
||||||
"algorithm": "HS256",
|
|
||||||
"auth_uri": "/oauth2/authorize",
|
|
||||||
"token_uri": "/oauth2/token",
|
|
||||||
"redirect_uris": [
|
|
||||||
"http://127.0.0.1/oauth2/code",
|
|
||||||
"http://127.0.0.1/oauth2/callback"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"ios": {
|
|
||||||
"issuers": ["accounts.bitdeals.org"],
|
|
||||||
"scopes": ["bitdeals"],
|
|
||||||
"client_id": "ios-bitdeals.org",
|
|
||||||
"client_secret": "kWqJivDfaR7vbzkZz07zi7DO",
|
|
||||||
"algorithm": "HS256",
|
|
||||||
"auth_uri": "/oauth2/authorize",
|
|
||||||
"token_uri": "/oauth2/token",
|
|
||||||
"redirect_uris": [
|
|
||||||
"http://127.0.0.1/oauth2/code",
|
|
||||||
"http://127.0.0.1/oauth2/callback"
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ namespace Apostol {
|
|||||||
}
|
}
|
||||||
//--------------------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
CString DateToString(const CDateTime &Value, const CString &Format) {
|
CString DateToString(CDateTime Value, const CString &Format) {
|
||||||
TCHAR Buffer[25] = {0};
|
TCHAR Buffer[25] = {0};
|
||||||
DateTimeToStr(Value, Buffer, sizeof(Buffer), Format.c_str());
|
DateTimeToStr(Value, Buffer, sizeof(Buffer), Format.c_str());
|
||||||
return Buffer;
|
return Buffer;
|
||||||
@@ -226,9 +226,9 @@ namespace Apostol {
|
|||||||
CDealType CDeal::StringToType(const CString &Value) {
|
CDealType CDeal::StringToType(const CString &Value) {
|
||||||
const auto &status = Value.Lower();
|
const auto &status = Value.Lower();
|
||||||
|
|
||||||
if (status.Find("prepaid") != CString::npos || status.Find("prepayment") != CString::npos) {
|
if (status.Find("prepayment") != CString::npos || status.Find("prepaid") != CString::npos) {
|
||||||
return dtPrepaid;
|
return dtPrepaid;
|
||||||
} else if (status.Find("postpaid") != CString::npos || status.Find("postpayment") != CString::npos) {
|
} else if (status.Find("postpayment") != CString::npos || status.Find("postpaid") != CString::npos) {
|
||||||
return dtPostpaid;
|
return dtPostpaid;
|
||||||
} else {
|
} else {
|
||||||
throw ExceptionFrm(R"(Invalid order type value: "%s".)", status.c_str());
|
throw ExceptionFrm(R"(Invalid order type value: "%s".)", status.c_str());
|
||||||
@@ -239,9 +239,9 @@ namespace Apostol {
|
|||||||
CString CDeal::TypeToString(CDealType Type) {
|
CString CDeal::TypeToString(CDealType Type) {
|
||||||
switch (Type) {
|
switch (Type) {
|
||||||
case dtPrepaid:
|
case dtPrepaid:
|
||||||
return "Prepaid";
|
return "Prepayment";
|
||||||
case dtPostpaid:
|
case dtPostpaid:
|
||||||
return "Postpaid";
|
return "Postpayment";
|
||||||
default:
|
default:
|
||||||
return "Unknown";
|
return "Unknown";
|
||||||
}
|
}
|
||||||
@@ -250,9 +250,9 @@ namespace Apostol {
|
|||||||
|
|
||||||
CString CDeal::TypeCodeToString(const CString &Code) {
|
CString CDeal::TypeCodeToString(const CString &Code) {
|
||||||
if (Code == "prepaid.deal") {
|
if (Code == "prepaid.deal") {
|
||||||
return CString("Prepaid");
|
return {"Prepayment"};
|
||||||
} else if (Code == "postpaid.deal") {
|
} else if (Code == "postpaid.deal") {
|
||||||
return CString("Postpaid");
|
return {"Postpayment"};
|
||||||
} else {
|
} else {
|
||||||
throw ExceptionFrm(R"(Invalid type code value: "%s".)", Code.c_str());
|
throw ExceptionFrm(R"(Invalid type code value: "%s".)", Code.c_str());
|
||||||
}
|
}
|
||||||
@@ -526,7 +526,6 @@ namespace Apostol {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
using namespace Apostol::Deal;
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif // __cplusplus
|
#endif // __cplusplus
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ namespace Apostol {
|
|||||||
CString DoubleToBTC(const double &Value, const CString &Format = _T("%f BTC"));
|
CString DoubleToBTC(const double &Value, const CString &Format = _T("%f BTC"));
|
||||||
|
|
||||||
CDateTime StringToDate(const CString &Value, const CString &Format = _T("%04d-%02d-%02d %02d:%02d:%02d"));
|
CDateTime StringToDate(const CString &Value, const CString &Format = _T("%04d-%02d-%02d %02d:%02d:%02d"));
|
||||||
CString DateToString(const CDateTime &Value, const CString &Format = _T("%Y-%m-%d %H:%M:%S UTC"));
|
CString DateToString(CDateTime Value, const CString &Format = _T("%Y-%m-%d %H:%M:%S UTC"));
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
Program name:
|
Program name:
|
||||||
|
|
||||||
ship-safety
|
dm
|
||||||
|
|
||||||
Module Name:
|
Module Name:
|
||||||
|
|
||||||
@@ -10,7 +10,7 @@ Module Name:
|
|||||||
|
|
||||||
Notices:
|
Notices:
|
||||||
|
|
||||||
Ship Safety Service
|
Deal Module
|
||||||
|
|
||||||
Author:
|
Author:
|
||||||
|
|
||||||
@@ -21,8 +21,8 @@ Author:
|
|||||||
|
|
||||||
--*/
|
--*/
|
||||||
|
|
||||||
#ifndef APOSTOL_HEADER_HPP
|
#ifndef APOSTOL_DM_HEADER_HPP
|
||||||
#define APOSTOL_HEADER_HPP
|
#define APOSTOL_DM_HEADER_HPP
|
||||||
//----------------------------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
#include <wait.h>
|
#include <wait.h>
|
||||||
@@ -38,9 +38,10 @@ Author:
|
|||||||
#include "PGP.hpp"
|
#include "PGP.hpp"
|
||||||
#include "Bitcoin.hpp"
|
#include "Bitcoin.hpp"
|
||||||
#include "Deal.hpp"
|
#include "Deal.hpp"
|
||||||
|
#include "Context.hpp"
|
||||||
//----------------------------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
#include "Core.hpp"
|
#include "Core.hpp"
|
||||||
//----------------------------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
#endif //APOSTOL_HEADER_HPP
|
#endif //APOSTOL_DM_HEADER_HPP
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
/*++
|
/*++
|
||||||
|
|
||||||
Library name:
|
Program name:
|
||||||
|
|
||||||
apostol-module
|
dm
|
||||||
|
|
||||||
Module Name:
|
Module Name:
|
||||||
|
|
||||||
@@ -27,12 +27,6 @@ Author:
|
|||||||
#include "WebService.hpp"
|
#include "WebService.hpp"
|
||||||
//----------------------------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
#include "jwt.h"
|
|
||||||
//----------------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
#include <random>
|
|
||||||
//----------------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
#define BPS_PGP_HASH "SHA512"
|
#define BPS_PGP_HASH "SHA512"
|
||||||
#define BM_PREFIX "BM-"
|
#define BM_PREFIX "BM-"
|
||||||
//----------------------------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------------------------
|
||||||
@@ -46,13 +40,15 @@ extern "C++" {
|
|||||||
|
|
||||||
namespace Apostol {
|
namespace Apostol {
|
||||||
|
|
||||||
namespace Workers {
|
namespace Module {
|
||||||
|
|
||||||
CString to_string(unsigned long Value) {
|
CString to_string(unsigned long Value) {
|
||||||
TCHAR szString[_INT_T_LEN + 1] = {0};
|
TCHAR szString[_INT_T_LEN + 1] = {0};
|
||||||
sprintf(szString, "%lu", Value);
|
sprintf(szString, "%lu", Value);
|
||||||
return {szString};
|
return {szString};
|
||||||
}
|
}
|
||||||
|
//--------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
@@ -60,21 +56,16 @@ namespace Apostol {
|
|||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
CWebService::CWebService(CModuleProcess *AProcess): CApostolModule(AProcess, "web service") {
|
CWebService::CWebService(CModuleProcess *AProcess): CApostolModule(AProcess, "web service", "module/WebService") {
|
||||||
|
m_NexServerTime = 0;
|
||||||
|
m_ServerIndex = -1;
|
||||||
m_SyncPeriod = BPS_DEFAULT_SYNC_PERIOD;
|
m_SyncPeriod = BPS_DEFAULT_SYNC_PERIOD;
|
||||||
m_ActiveIndex = -1;
|
|
||||||
|
|
||||||
m_FixedDate = 0;
|
|
||||||
|
|
||||||
m_Status = psStopped;
|
m_Status = psStopped;
|
||||||
|
|
||||||
m_DefaultServer.Name() = BPS_BM_SERVER_ADDRESS;
|
|
||||||
m_DefaultServer.Value().URI = BPS_SERVER_URL;
|
|
||||||
m_DefaultServer.Value().PGP.Name = BPS_BM_SERVER_ADDRESS;
|
|
||||||
|
|
||||||
m_CurrentServer = m_DefaultServer;
|
|
||||||
|
|
||||||
CWebService::InitMethods();
|
CWebService::InitMethods();
|
||||||
|
|
||||||
|
//InitServerList();
|
||||||
|
Reload();
|
||||||
}
|
}
|
||||||
//--------------------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
@@ -103,18 +94,62 @@ namespace Apostol {
|
|||||||
}
|
}
|
||||||
//--------------------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
CDateTime CWebService::GetRandomDate(int a, int b, CDateTime Date) {
|
void CWebService::InitServerList() {
|
||||||
std::random_device rd;
|
m_DefaultServer.Value().Name() = m_DefaultServer.Name();
|
||||||
std::mt19937 gen(rd());
|
m_DefaultServer.Value().PGP().Name = "PUBLIC";
|
||||||
std::uniform_int_distribution<> time(a, b);
|
|
||||||
CDateTime delta = time(gen);
|
if (m_Servers.Count() == 0) {
|
||||||
return Date + (CDateTime) (delta / SecsPerDay);
|
#ifdef _DEBUG
|
||||||
|
int index = m_Servers.AddPair(BPS_BM_DEBUG_ADDRESS, CContext(CLocation(BPS_SERVER_URL)));
|
||||||
|
m_Servers[index].Value().Name() = m_Servers[index].Name();
|
||||||
|
m_Servers[index].Value().PGP().Name = "PUBLIC";
|
||||||
|
#else
|
||||||
|
m_Servers.Add(m_DefaultServer);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//--------------------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
void CWebService::LoadOAuth2(const CString &FileName, const CString &ProviderName, const CString &ApplicationName,
|
void CWebService::UpdateServerList(const CString &Key) {
|
||||||
CProviders &Providers) {
|
CStringPairs ServerList;
|
||||||
|
CStringList Keys;
|
||||||
|
|
||||||
|
ParsePGPKey(Key, ServerList, Keys);
|
||||||
|
|
||||||
|
if (ServerList.Count() != 0) {
|
||||||
|
CStringPairs::ConstEnumerator em(ServerList);
|
||||||
|
while (em.MoveNext()) {
|
||||||
|
const auto ¤t = em.Current();
|
||||||
|
if (m_Servers.IndexOfName(current.Name()) == -1 && !current.Value().IsEmpty()) {
|
||||||
|
m_Servers.AddPair(current.Name(), CContext(CLocation(current.Value())));
|
||||||
|
auto &Context = m_Servers.Last().Value();
|
||||||
|
Context.Name() = current.Name();
|
||||||
|
Context.PGP().Name = "PUBLIC";
|
||||||
|
Context.PGP().Key = Key;
|
||||||
|
Context.BTCKeys() = Keys;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//--------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void CWebService::UpdateOAuth2() {
|
||||||
|
const auto &oauth2 = Config()->IniFile().ReadString(CONFIG_SECTION_NAME, "oauth2", "oauth2/service.json");
|
||||||
|
const auto &provider = CString(SYSTEM_PROVIDER_NAME);
|
||||||
|
const auto &application = CString(SERVICE_APPLICATION_NAME);
|
||||||
|
|
||||||
|
for (int i = 0; i < m_Servers.Count(); i++) {
|
||||||
|
auto &Context = m_Servers[i].Value();
|
||||||
|
if (!oauth2.empty() && Context.Status() == Context::csInitialization) {
|
||||||
|
LoadOAuth2(oauth2, provider, application, Context.Providers());
|
||||||
|
Context.SetStatus(Context::csInitialized);
|
||||||
|
}
|
||||||
|
Context.SetCheckDate(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//--------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void CWebService::LoadOAuth2(const CString &FileName, const CString &ProviderName, const CString &ApplicationName, CProviders &Providers) {
|
||||||
CString ConfigFile(FileName);
|
CString ConfigFile(FileName);
|
||||||
|
|
||||||
if (!path_separator(ConfigFile.front())) {
|
if (!path_separator(ConfigFile.front())) {
|
||||||
@@ -136,6 +171,12 @@ namespace Apostol {
|
|||||||
}
|
}
|
||||||
//--------------------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void CWebService::CheckKeyForNull(LPCTSTR Key, LPCTSTR Value) {
|
||||||
|
if (Value == nullptr)
|
||||||
|
throw ExceptionFrm("Invalid format: key \"%s\" cannot be empty.", Key);
|
||||||
|
}
|
||||||
|
//--------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
bool CWebService::FindURLInLine(const CString &Line, CStringList &List) {
|
bool CWebService::FindURLInLine(const CString &Line, CStringList &List) {
|
||||||
CString URL;
|
CString URL;
|
||||||
|
|
||||||
@@ -196,12 +237,6 @@ namespace Apostol {
|
|||||||
}
|
}
|
||||||
//--------------------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
void CWebService::CheckKeyForNull(LPCTSTR Key, LPCTSTR Value) {
|
|
||||||
if (Value == nullptr)
|
|
||||||
throw ExceptionFrm("Invalid format: key \"%s\" cannot be empty.", Key);
|
|
||||||
}
|
|
||||||
//--------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
int CWebService::CheckFee(const CString &Fee) {
|
int CWebService::CheckFee(const CString &Fee) {
|
||||||
if (!Fee.IsEmpty()) {
|
if (!Fee.IsEmpty()) {
|
||||||
|
|
||||||
@@ -236,186 +271,59 @@ namespace Apostol {
|
|||||||
}
|
}
|
||||||
//--------------------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
void CWebService::ExceptionToJson(int ErrorCode, const std::exception &E, CString& Json) {
|
void CWebService::CreateAccessToken(const CProvider &Provider, const CString &Application, CContext &Context) {
|
||||||
Json.Format(R"({"error": {"code": %u, "message": "%s"}})", ErrorCode, Delphi::Json::EncodeJsonString(E.what()).c_str());
|
|
||||||
}
|
|
||||||
//--------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
CString CWebService::CreateToken(const CProvider &Provider, const CString &Application) {
|
auto OnDone = [&Context](CTCPConnection *Sender) {
|
||||||
auto token = jwt::create()
|
|
||||||
.set_issuer(Provider.Issuer(Application))
|
|
||||||
.set_audience(Provider.ClientId(Application))
|
|
||||||
.set_issued_at(std::chrono::system_clock::now())
|
|
||||||
.set_expires_at(std::chrono::system_clock::now() + std::chrono::seconds{3600})
|
|
||||||
.sign(jwt::algorithm::hs256{std::string(Provider.Secret(Application))});
|
|
||||||
|
|
||||||
return token;
|
|
||||||
}
|
|
||||||
//--------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
void CWebService::FetchAccessToken(const CString &URI, const CString &Assertion, COnSocketExecuteEvent &&OnDone,
|
|
||||||
COnSocketExceptionEvent &&OnFailed) {
|
|
||||||
|
|
||||||
auto OnRequest = [](CHTTPClient *Sender, CHTTPRequest *ARequest) {
|
|
||||||
|
|
||||||
const auto &token_uri = Sender->Data()["token_uri"];
|
|
||||||
const auto &grant_type = Sender->Data()["grant_type"];
|
|
||||||
const auto &assertion = Sender->Data()["assertion"];
|
|
||||||
|
|
||||||
ARequest->Content = _T("grant_type=");
|
|
||||||
ARequest->Content << CHTTPServer::URLEncode(grant_type);
|
|
||||||
|
|
||||||
ARequest->Content << _T("&assertion=");
|
|
||||||
ARequest->Content << CHTTPServer::URLEncode(assertion);
|
|
||||||
|
|
||||||
CHTTPRequest::Prepare(ARequest, _T("POST"), token_uri.c_str(), _T("application/x-www-form-urlencoded"));
|
|
||||||
|
|
||||||
DebugRequest(ARequest);
|
|
||||||
};
|
|
||||||
|
|
||||||
auto OnException = [this](CTCPConnection *Sender, const Delphi::Exception::Exception &E) {
|
|
||||||
|
|
||||||
auto pConnection = dynamic_cast<CHTTPClientConnection *> (Sender);
|
|
||||||
auto pClient = dynamic_cast<CHTTPClient *> (pConnection->Client());
|
|
||||||
|
|
||||||
DebugReply(pConnection->Reply());
|
|
||||||
|
|
||||||
m_FixedDate = Now() + (CDateTime) 30 / SecsPerDay;
|
|
||||||
|
|
||||||
Log()->Error(APP_LOG_ERR, 0, "[%s:%d] %s", pClient->Host().c_str(), pClient->Port(), E.what());
|
|
||||||
};
|
|
||||||
|
|
||||||
CLocation token_uri(URI);
|
|
||||||
|
|
||||||
auto pClient = GetClient(token_uri.hostname, token_uri.port);
|
|
||||||
|
|
||||||
pClient->Data().Values("token_uri", token_uri.pathname);
|
|
||||||
pClient->Data().Values("grant_type", "urn:ietf:params:oauth:grant-type:jwt-bearer");
|
|
||||||
pClient->Data().Values("assertion", Assertion);
|
|
||||||
|
|
||||||
pClient->OnRequest(OnRequest);
|
|
||||||
pClient->OnExecute(static_cast<COnSocketExecuteEvent &&>(OnDone));
|
|
||||||
pClient->OnException(OnFailed == nullptr ? OnException : static_cast<COnSocketExceptionEvent &&>(OnFailed));
|
|
||||||
|
|
||||||
pClient->Active(true);
|
|
||||||
}
|
|
||||||
//--------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
void CWebService::CreateAccessToken(const CProvider &Provider, const CString &Application, CStringList &Tokens) {
|
|
||||||
|
|
||||||
auto OnDone = [this, &Tokens](CTCPConnection *Sender) {
|
|
||||||
|
|
||||||
auto pConnection = dynamic_cast<CHTTPClientConnection *> (Sender);
|
auto pConnection = dynamic_cast<CHTTPClientConnection *> (Sender);
|
||||||
auto pReply = pConnection->Reply();
|
auto pReply = pConnection->Reply();
|
||||||
|
|
||||||
DebugReply(pReply);
|
DebugReply(pReply);
|
||||||
|
|
||||||
const CJSON Json(pReply->Content);
|
if (pReply->Status == CHTTPReply::ok) {
|
||||||
|
const CJSON Json(pReply->Content);
|
||||||
|
|
||||||
Tokens.Values("access_token", Json["access_token"].AsString());
|
Context.SetStatus(csAuthorized);
|
||||||
|
|
||||||
m_Status = psRunning;
|
Context.Session() = Json["session"].AsString();
|
||||||
|
Context.Secret() = Json["secret"].AsString();
|
||||||
|
|
||||||
return true;
|
Context.Tokens().Values("access_token", Json["access_token"].AsString());
|
||||||
};
|
|
||||||
|
|
||||||
CString server_uri("http://localhost:4977");
|
Context.SetFixedDate(0);
|
||||||
|
Context.SetCheckDate(Now() + (CDateTime) 55 / MinsPerDay); // 55 min
|
||||||
const auto &token_uri = Provider.TokenURI(Application);
|
|
||||||
const auto &service_token = CreateToken(Provider, Application);
|
|
||||||
|
|
||||||
Tokens.Values("service_token", service_token);
|
|
||||||
|
|
||||||
if (!token_uri.IsEmpty()) {
|
|
||||||
FetchAccessToken(token_uri.front() == '/' ? server_uri + token_uri : token_uri, service_token, OnDone);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//--------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
void CWebService::FetchCerts(CProvider &Provider, const CString &Application) {
|
|
||||||
|
|
||||||
const auto& URI = Provider.CertURI(Application);
|
|
||||||
|
|
||||||
if (URI.IsEmpty()) {
|
|
||||||
Log()->Error(APP_LOG_INFO, 0, _T("Certificate URI in provider \"%s\" is empty."), Provider.Name().c_str());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Log()->Error(APP_LOG_INFO, 0, _T("Trying to fetch public keys from: %s"), URI.c_str());
|
|
||||||
|
|
||||||
auto OnRequest = [&Provider, &Application](CHTTPClient *Sender, CHTTPRequest *ARequest) {
|
|
||||||
const auto& client_x509_cert_url = std::string(Provider.Applications()[Application]["client_x509_cert_url"].AsString());
|
|
||||||
|
|
||||||
Provider.KeyStatusTime(Now());
|
|
||||||
Provider.KeyStatus(ksFetching);
|
|
||||||
|
|
||||||
CLocation Location(client_x509_cert_url);
|
|
||||||
CHTTPRequest::Prepare(ARequest, "GET", Location.pathname.c_str());
|
|
||||||
};
|
|
||||||
|
|
||||||
auto OnExecute = [this, &Provider, &Application](CTCPConnection *AConnection) {
|
|
||||||
|
|
||||||
auto pConnection = dynamic_cast<CHTTPClientConnection *> (AConnection);
|
|
||||||
auto pReply = pConnection->Reply();
|
|
||||||
|
|
||||||
try {
|
|
||||||
DebugRequest(pConnection->Request());
|
|
||||||
DebugReply(pReply);
|
|
||||||
|
|
||||||
Provider.KeyStatusTime(Now());
|
|
||||||
|
|
||||||
Provider.Keys().Clear();
|
|
||||||
Provider.Keys() << pReply->Content;
|
|
||||||
|
|
||||||
Provider.KeyStatus(ksSuccess);
|
|
||||||
|
|
||||||
CreateAccessToken(Provider, Application, m_Tokens[Provider.Name()]);
|
|
||||||
} catch (Delphi::Exception::Exception &E) {
|
|
||||||
Provider.KeyStatus(ksFailed);
|
|
||||||
Log()->Error(APP_LOG_ERR, 0, "[Certificate] Message: %s", E.what());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pConnection->CloseConnection(true);
|
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
auto OnException = [&Provider](CTCPConnection *AConnection, const Delphi::Exception::Exception &E) {
|
auto OnHTTPClient = [this](const CLocation &URI) {
|
||||||
auto pConnection = dynamic_cast<CHTTPClientConnection *> (AConnection);
|
return GetClient(URI.hostname, URI.port);
|
||||||
auto pClient = dynamic_cast<CHTTPClient *> (pConnection->Client());
|
|
||||||
|
|
||||||
Provider.KeyStatusTime(Now());
|
|
||||||
Provider.KeyStatus(ksFailed);
|
|
||||||
|
|
||||||
Log()->Error(APP_LOG_ERR, 0, "[%s:%d] %s", pClient->Host().c_str(), pClient->Port(), E.what());
|
|
||||||
};
|
};
|
||||||
|
|
||||||
CLocation Location(URI);
|
CString server_uri(Context.URL().Origin());
|
||||||
auto pClient = GetClient(Location.hostname, Location.port);
|
|
||||||
|
|
||||||
pClient->OnRequest(OnRequest);
|
const auto &token_uri = Provider.TokenURI(Application);
|
||||||
pClient->OnExecute(OnExecute);
|
const auto &service_token = CToken::CreateToken(Provider, Application);
|
||||||
pClient->OnException(OnException);
|
|
||||||
|
|
||||||
pClient->Active(true);
|
Context.Tokens().Values("service_token", service_token);
|
||||||
|
|
||||||
|
if (!token_uri.IsEmpty()) {
|
||||||
|
CToken::FetchAccessToken(token_uri.front() == '/' ? server_uri + token_uri : token_uri, service_token, OnHTTPClient, OnDone);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//--------------------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
void CWebService::FetchProviders() {
|
void CWebService::FetchProviders(CDateTime Now, CContext &Context) {
|
||||||
for (int i = 0; i < m_Providers.Count(); i++) {
|
for (int i = 0; i < Context.Providers().Count(); i++) {
|
||||||
auto& Provider = m_Providers[i].Value();
|
auto &Provider = Context.Providers()[i].Value();
|
||||||
for (int j = 0; j < Provider.Applications().Count(); ++j) {
|
for (int j = 0; j < Provider.Applications().Count(); ++j) {
|
||||||
const auto &app = Provider.Applications().Members(j);
|
const auto &app = Provider.Applications().Members(j);
|
||||||
if (app["type"].AsString() == "service_account") {
|
if (app["type"].AsString() == "service_account") {
|
||||||
if (!app["auth_provider_x509_cert_url"].AsString().IsEmpty()) {
|
if (Provider.KeyStatus() == ksUnknown) {
|
||||||
if (Provider.KeyStatus() == ksUnknown) {
|
CreateAccessToken(Provider, app.String(), Context);
|
||||||
FetchCerts(Provider, app.String());
|
Provider.KeyStatusTime(Now);
|
||||||
}
|
Provider.KeyStatus(ksSuccess);
|
||||||
} else {
|
|
||||||
if (Provider.KeyStatus() == ksUnknown) {
|
|
||||||
Provider.KeyStatusTime(Now());
|
|
||||||
CreateAccessToken(Provider, app.String(), m_Tokens[Provider.Name()]);
|
|
||||||
Provider.KeyStatus(ksSuccess);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -423,19 +331,22 @@ namespace Apostol {
|
|||||||
}
|
}
|
||||||
//--------------------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
void CWebService::CheckProviders() {
|
void CWebService::CheckProviders(CDateTime Now, CContext &Context) {
|
||||||
for (int i = 0; i < m_Providers.Count(); i++) {
|
for (int i = 0; i < Context.Providers().Count(); i++) {
|
||||||
auto& Provider = m_Providers[i].Value();
|
auto& Provider = Context.Providers()[i].Value();
|
||||||
if (Provider.KeyStatus() != ksUnknown) {
|
if (Provider.KeyStatus() != ksUnknown) {
|
||||||
Provider.KeyStatusTime(Now());
|
Provider.KeyStatusTime(Now);
|
||||||
Provider.KeyStatus(ksUnknown);
|
Provider.KeyStatus(ksUnknown);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//--------------------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
void CWebService::DoVerbose(CSocketEvent *Sender, CTCPConnection *AConnection, LPCTSTR AFormat, va_list args) {
|
int CWebService::NextServerIndex() {
|
||||||
Log()->Debug(0, AFormat, args);
|
m_ServerIndex++;
|
||||||
|
if (m_ServerIndex >= m_Servers.Count())
|
||||||
|
m_ServerIndex = -1;
|
||||||
|
return m_ServerIndex;
|
||||||
}
|
}
|
||||||
//--------------------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
@@ -574,13 +485,13 @@ namespace Apostol {
|
|||||||
}
|
}
|
||||||
//--------------------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
void CWebService::RouteUser(CHTTPServerConnection *AConnection, const CString& Method, const CString& URI) {
|
void CWebService::DoUser(CHTTPServerConnection *AConnection, const CString& Method, const CString& URI) {
|
||||||
|
|
||||||
auto pProxy = GetProxy(AConnection);
|
auto pProxy = GetProxy(AConnection);
|
||||||
auto pServerRequest = AConnection->Request();
|
auto pServerRequest = AConnection->Request();
|
||||||
auto pProxyRequest = pProxy->Request();
|
auto pProxyRequest = pProxy->Request();
|
||||||
|
|
||||||
const auto& caModuleAddress = Config()->IniFile().ReadString("module", "address", "");
|
const auto& caModuleAddress = m_Module["address"];
|
||||||
|
|
||||||
const auto& caOrigin = pServerRequest->Headers["origin"];
|
const auto& caOrigin = pServerRequest->Headers["origin"];
|
||||||
const auto& caUserAddress = pServerRequest->Params["address"];
|
const auto& caUserAddress = pServerRequest->Params["address"];
|
||||||
@@ -588,7 +499,7 @@ namespace Apostol {
|
|||||||
const auto& pgpValue = pServerRequest->Params["pgp"];
|
const auto& pgpValue = pServerRequest->Params["pgp"];
|
||||||
|
|
||||||
const auto& caServerParam = pServerRequest->Params["server"];
|
const auto& caServerParam = pServerRequest->Params["server"];
|
||||||
const auto& caServer = caServerParam.IsEmpty() ? CurrentServer().Value().URI : caServerParam;
|
const auto& caServer = caServerParam.IsEmpty() ? m_CurrentServer.URL().Origin() : caServerParam;
|
||||||
|
|
||||||
CLocation Location(caServer);
|
CLocation Location(caServer);
|
||||||
|
|
||||||
@@ -766,8 +677,8 @@ namespace Apostol {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//DebugMessage("[RouteUser] Server request:\n%s\n", pServerRequest->Content.c_str());
|
//DebugMessage("[DoUser] Server request:\n%s\n", pServerRequest->Content.c_str());
|
||||||
//DebugMessage("[RouteUser] sPayload:\n%s\n", sPayload.c_str());
|
//DebugMessage("[DoUser] sPayload:\n%s\n", sPayload.c_str());
|
||||||
|
|
||||||
CJSON Json(jvtObject);
|
CJSON Json(jvtObject);
|
||||||
|
|
||||||
@@ -786,7 +697,7 @@ namespace Apostol {
|
|||||||
|
|
||||||
CHTTPRequest::Prepare(pProxyRequest, Method.c_str(), URI.c_str());
|
CHTTPRequest::Prepare(pProxyRequest, Method.c_str(), URI.c_str());
|
||||||
|
|
||||||
pProxyRequest->AddHeader("Authorization", "Bearer " + m_Tokens[SYSTEM_PROVIDER_NAME]["access_token"]);
|
pProxyRequest->AddHeader("Authorization", "Bearer " + m_CurrentServer.Tokens()["access_token"]);
|
||||||
|
|
||||||
if (!caModuleAddress.IsEmpty())
|
if (!caModuleAddress.IsEmpty())
|
||||||
pProxyRequest->AddHeader("Module-Address", caModuleAddress);
|
pProxyRequest->AddHeader("Module-Address", caModuleAddress);
|
||||||
@@ -860,14 +771,14 @@ namespace Apostol {
|
|||||||
}
|
}
|
||||||
//--------------------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
void CWebService::RouteDeal(CHTTPServerConnection *AConnection, const CString &Method, const CString &URI, const CString &Action) {
|
void CWebService::DoDeal(CHTTPServerConnection *AConnection, const CString &Method, const CString &URI, const CString &Action) {
|
||||||
|
|
||||||
auto pProxy = GetProxy(AConnection);
|
auto pProxy = GetProxy(AConnection);
|
||||||
auto pServerRequest = AConnection->Request();
|
auto pServerRequest = AConnection->Request();
|
||||||
auto pProxyRequest = pProxy->Request();
|
auto pProxyRequest = pProxy->Request();
|
||||||
|
|
||||||
const auto& caModuleAddress = Config()->IniFile().ReadString("module", "address", "");
|
const auto& caModuleAddress = m_Module["address"];
|
||||||
const auto& caModuleFee = Config()->IniFile().ReadString("module", "fee", "0.1%");
|
const auto& caModuleFee = m_Module["fee"];
|
||||||
|
|
||||||
const auto checkFee = CheckFee(caModuleFee);
|
const auto checkFee = CheckFee(caModuleFee);
|
||||||
if (checkFee == -1)
|
if (checkFee == -1)
|
||||||
@@ -879,7 +790,7 @@ namespace Apostol {
|
|||||||
const auto& pgpValue = pServerRequest->Params["pgp"];
|
const auto& pgpValue = pServerRequest->Params["pgp"];
|
||||||
|
|
||||||
const auto& caServerParam = pServerRequest->Params["server"];
|
const auto& caServerParam = pServerRequest->Params["server"];
|
||||||
const auto& caServer = caServerParam.IsEmpty() ? CurrentServer().Value().URI : caServerParam;
|
const auto& caServer = caServerParam.IsEmpty() ? m_CurrentServer.URL().Origin() : caServerParam;
|
||||||
|
|
||||||
CLocation Location(caServer);
|
CLocation Location(caServer);
|
||||||
|
|
||||||
@@ -1167,7 +1078,7 @@ namespace Apostol {
|
|||||||
Node = YAML::Load(pServerRequest->Content.c_str());
|
Node = YAML::Load(pServerRequest->Content.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto &BTCKeys = CurrentServer().Value().BTCKeys;
|
const auto &BTCKeys = m_CurrentServer.BTCKeys();
|
||||||
|
|
||||||
if (BTCKeys.Count() < 2)
|
if (BTCKeys.Count() < 2)
|
||||||
throw ExceptionFrm("Bitcoin keys cannot be empty.");
|
throw ExceptionFrm("Bitcoin keys cannot be empty.");
|
||||||
@@ -1222,8 +1133,8 @@ namespace Apostol {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//DebugMessage("[RouteDeal] Server request:\n%s\n", pServerRequest->Content.c_str());
|
//DebugMessage("[DoDeal] Server request:\n%s\n", pServerRequest->Content.c_str());
|
||||||
//DebugMessage("[RouteDeal] sPayload:\n%s\n", sPayload.c_str());
|
//DebugMessage("[DoDeal] sPayload:\n%s\n", sPayload.c_str());
|
||||||
|
|
||||||
CJSON Json(jvtObject);
|
CJSON Json(jvtObject);
|
||||||
|
|
||||||
@@ -1243,7 +1154,7 @@ namespace Apostol {
|
|||||||
|
|
||||||
CHTTPRequest::Prepare(pProxyRequest, Method.c_str(), URI.c_str());
|
CHTTPRequest::Prepare(pProxyRequest, Method.c_str(), URI.c_str());
|
||||||
|
|
||||||
pProxyRequest->AddHeader("Authorization", "Bearer " + m_Tokens[SYSTEM_PROVIDER_NAME]["access_token"]);
|
pProxyRequest->AddHeader("Authorization", "Bearer " + m_CurrentServer.Tokens()["access_token"]);
|
||||||
|
|
||||||
if (!caModuleAddress.IsEmpty())
|
if (!caModuleAddress.IsEmpty())
|
||||||
pProxyRequest->AddHeader("Module-Address", caModuleAddress);
|
pProxyRequest->AddHeader("Module-Address", caModuleAddress);
|
||||||
@@ -1259,7 +1170,7 @@ namespace Apostol {
|
|||||||
}
|
}
|
||||||
//--------------------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
void CWebService::RouteSignature(CHTTPServerConnection *AConnection) {
|
void CWebService::DoSignature(CHTTPServerConnection *AConnection) {
|
||||||
|
|
||||||
auto pRequest = AConnection->Request();
|
auto pRequest = AConnection->Request();
|
||||||
auto pReply = AConnection->Reply();
|
auto pReply = AConnection->Reply();
|
||||||
@@ -1269,7 +1180,7 @@ namespace Apostol {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto& caServerKey = CurrentServer().Value().PGP.Key;
|
const auto& caServerKey = m_CurrentServer.PGP().Key;
|
||||||
|
|
||||||
if (caServerKey.IsEmpty())
|
if (caServerKey.IsEmpty())
|
||||||
throw ExceptionFrm("Server PGP key not added.");
|
throw ExceptionFrm("Server PGP key not added.");
|
||||||
@@ -1350,9 +1261,9 @@ namespace Apostol {
|
|||||||
}
|
}
|
||||||
|
|
||||||
CString sRoute;
|
CString sRoute;
|
||||||
for (int I = 0; I < slRouts.Count(); ++I) {
|
for (int i = 0; i < slRouts.Count(); ++i) {
|
||||||
sRoute.Append('/');
|
sRoute.Append('/');
|
||||||
sRoute.Append(slRouts[I]);
|
sRoute.Append(slRouts[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -1370,19 +1281,19 @@ namespace Apostol {
|
|||||||
|
|
||||||
pRequest->Content.Clear();
|
pRequest->Content.Clear();
|
||||||
|
|
||||||
RouteUser(AConnection, "GET", sRoute);
|
DoUser(AConnection, "GET", sRoute);
|
||||||
|
|
||||||
} else if (caCommand == "account" && caAction == "status") {
|
} else if (caCommand == "account" && caAction == "status") {
|
||||||
|
|
||||||
pRequest->Content.Clear();
|
pRequest->Content.Clear();
|
||||||
|
|
||||||
RouteUser(AConnection, "GET", sRoute);
|
DoUser(AConnection, "GET", sRoute);
|
||||||
|
|
||||||
} else if (caCommand == "deal" && caAction == "status") {
|
} else if (caCommand == "deal" && caAction == "status") {
|
||||||
|
|
||||||
pRequest->Content.Clear();
|
pRequest->Content.Clear();
|
||||||
|
|
||||||
RouteDeal(AConnection, "GET", sRoute, caAction);
|
DoDeal(AConnection, "GET", sRoute, caAction);
|
||||||
|
|
||||||
} else if (caCommand == "bc" && caAction == "history") {
|
} else if (caCommand == "bc" && caAction == "history") {
|
||||||
|
|
||||||
@@ -1409,10 +1320,10 @@ namespace Apostol {
|
|||||||
|
|
||||||
} else if (caCommand == "bc" && caAction == "header") {
|
} else if (caCommand == "bc" && caAction == "header") {
|
||||||
|
|
||||||
const auto& LHeight = pRequest->Params["height"];
|
const auto& caHeight = pRequest->Params["height"];
|
||||||
const auto& LHash = pRequest->Params["hash"];
|
const auto& caHash = pRequest->Params["hash"];
|
||||||
|
|
||||||
if (LHeight.IsEmpty() && LHash.IsEmpty()) {
|
if (caHeight.IsEmpty() && caHash.IsEmpty()) {
|
||||||
AConnection->SendStockReply(CHTTPReply::bad_request);
|
AConnection->SendStockReply(CHTTPReply::bad_request);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1420,10 +1331,10 @@ namespace Apostol {
|
|||||||
try {
|
try {
|
||||||
CJSON header;
|
CJSON header;
|
||||||
|
|
||||||
if (!LHash.IsEmpty()) {
|
if (!caHash.IsEmpty()) {
|
||||||
fetch_header(hash256(std::string(LHash.c_str())), header);
|
fetch_header(hash256(std::string(caHash.c_str())), header);
|
||||||
} else {
|
} else {
|
||||||
uint32_t height = StrToInt(LHeight.c_str());
|
uint32_t height = StrToInt(caHeight.c_str());
|
||||||
fetch_header(height, header);
|
fetch_header(height, header);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1504,24 +1415,24 @@ namespace Apostol {
|
|||||||
}
|
}
|
||||||
|
|
||||||
CString sRoute;
|
CString sRoute;
|
||||||
for (int I = 0; I < slRouts.Count(); ++I) {
|
for (int i = 0; i < slRouts.Count(); ++i) {
|
||||||
sRoute.Append('/');
|
sRoute.Append('/');
|
||||||
sRoute.Append(slRouts[I]);
|
sRoute.Append(slRouts[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
if (caCommand == "account") {
|
if (caCommand == "account") {
|
||||||
|
|
||||||
RouteUser(AConnection, "POST", sRoute);
|
DoUser(AConnection, "POST", sRoute);
|
||||||
|
|
||||||
} else if (caCommand == "deal") {
|
} else if (caCommand == "deal") {
|
||||||
|
|
||||||
RouteDeal(AConnection, "POST", sRoute, caAction);
|
DoDeal(AConnection, "POST", sRoute, caAction);
|
||||||
|
|
||||||
} else if (caCommand == "signature") {
|
} else if (caCommand == "signature") {
|
||||||
|
|
||||||
RouteSignature(AConnection);
|
DoSignature(AConnection);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
@@ -1538,37 +1449,11 @@ namespace Apostol {
|
|||||||
}
|
}
|
||||||
//--------------------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
const CServer &CWebService::CurrentServer() const {
|
const CContext &CWebService::CurrentServer() const {
|
||||||
return m_CurrentServer;
|
return m_CurrentServer;
|
||||||
}
|
}
|
||||||
//--------------------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
int CWebService::NextServerIndex() {
|
|
||||||
m_ActiveIndex++;
|
|
||||||
if (m_ActiveIndex >= m_Servers.Count())
|
|
||||||
m_ActiveIndex = -1;
|
|
||||||
return m_ActiveIndex;
|
|
||||||
}
|
|
||||||
//--------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
CServer &CWebService::ActiveServer() {
|
|
||||||
if (m_Servers.Count() == 0 && m_ActiveIndex == -1)
|
|
||||||
return m_DefaultServer;
|
|
||||||
if (m_ActiveIndex == -1)
|
|
||||||
return m_Servers[0];
|
|
||||||
return m_Servers[m_ActiveIndex];
|
|
||||||
}
|
|
||||||
//--------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
const CServer &CWebService::ActiveServer() const {
|
|
||||||
if (m_Servers.Count() == 0 && m_ActiveIndex == -1)
|
|
||||||
return m_DefaultServer;
|
|
||||||
if (m_ActiveIndex == -1)
|
|
||||||
return m_Servers[0];
|
|
||||||
return m_Servers[m_ActiveIndex];
|
|
||||||
}
|
|
||||||
//--------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
bool CWebService::CheckVerifyPGPSignature(int VerifyPGPSignature, CString &Message) {
|
bool CWebService::CheckVerifyPGPSignature(int VerifyPGPSignature, CString &Message) {
|
||||||
if (VerifyPGPSignature == -2) {
|
if (VerifyPGPSignature == -2) {
|
||||||
Message = "PGP public key is not meaningful.";
|
Message = "PGP public key is not meaningful.";
|
||||||
@@ -1617,29 +1502,22 @@ namespace Apostol {
|
|||||||
for (int i = 0; i < List.Count(); i++) {
|
for (int i = 0; i < List.Count(); i++) {
|
||||||
|
|
||||||
const auto& uid = List[i];
|
const auto& uid = List[i];
|
||||||
|
|
||||||
|
DebugMessage("%s (%s)\n", uid.Name.c_str(), uid.Desc.c_str());
|
||||||
|
|
||||||
const auto& name = uid.Name.Lower();
|
const auto& name = uid.Name.Lower();
|
||||||
const auto& data = uid.Desc.Lower();
|
const auto& data = uid.Desc.Lower();
|
||||||
|
|
||||||
if (name == "technical_data") {
|
if (name == "technical_data") {
|
||||||
SplitColumns(data, Data, ';');
|
SplitColumns(data, Data, ';');
|
||||||
|
|
||||||
DebugMessage("Technical data: ");
|
|
||||||
if (Data.Count() == 3) {
|
if (Data.Count() == 3) {
|
||||||
m_SyncPeriod = StrToIntDef(Data[1].Trim().c_str(), BPS_DEFAULT_SYNC_PERIOD);
|
m_SyncPeriod = StrToIntDef(Data[1].Trim().c_str(), BPS_DEFAULT_SYNC_PERIOD);
|
||||||
DebugMessage("\n - Fee : %s", Data[0].Trim().c_str());
|
|
||||||
DebugMessage("\n - Period: %s", Data[1].Trim().c_str());
|
|
||||||
DebugMessage("\n - Keys : %s", Data[2].Trim().c_str());
|
|
||||||
} else if (Data.Count() == 2) {
|
} else if (Data.Count() == 2) {
|
||||||
m_SyncPeriod = StrToIntDef(Data[0].Trim().c_str(), BPS_DEFAULT_SYNC_PERIOD);
|
m_SyncPeriod = StrToIntDef(Data[0].Trim().c_str(), BPS_DEFAULT_SYNC_PERIOD);
|
||||||
DebugMessage("\n - Period: %s", Data[0].Trim().c_str());
|
|
||||||
DebugMessage("\n - Keys : %s", Data[1].Trim().c_str());
|
|
||||||
} else if (Data.Count() == 1) {
|
} else if (Data.Count() == 1) {
|
||||||
m_SyncPeriod = StrToIntDef(Data[0].Trim().c_str(), BPS_DEFAULT_SYNC_PERIOD);
|
m_SyncPeriod = StrToIntDef(Data[0].Trim().c_str(), BPS_DEFAULT_SYNC_PERIOD);
|
||||||
DebugMessage("\n - Period: %s", Data[0].Trim().c_str());
|
|
||||||
} else {
|
|
||||||
DebugMessage("Unknown error.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} if (uid.Name.Length() >= 35 && uid.Name.SubString(0, 3) == BM_PREFIX) {
|
} if (uid.Name.Length() >= 35 && uid.Name.SubString(0, 3) == BM_PREFIX) {
|
||||||
CStringList urlList;
|
CStringList urlList;
|
||||||
if (FindURLInLine(uid.Desc, urlList)) {
|
if (FindURLInLine(uid.Desc, urlList)) {
|
||||||
@@ -1659,8 +1537,9 @@ namespace Apostol {
|
|||||||
Name = "bitcoin_key";
|
Name = "bitcoin_key";
|
||||||
Name << i;
|
Name << i;
|
||||||
const auto& key = KeyList[Name];
|
const auto& key = KeyList[Name];
|
||||||
if (!key.IsEmpty())
|
if (!key.IsEmpty()) {
|
||||||
BTCKeys.Add(key);
|
BTCKeys.Add(key);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//--------------------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------------------
|
||||||
@@ -1681,25 +1560,30 @@ namespace Apostol {
|
|||||||
}
|
}
|
||||||
//--------------------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
void CWebService::FetchPGP(CServer &Server) {
|
void CWebService::FetchPGP(CContext &Context) {
|
||||||
|
|
||||||
Log()->Debug(0, "Trying to fetch a PGP key \"%s\" from: %s", Server.Name().c_str(), Server.Value().URI.c_str());
|
Log()->Debug(APP_LOG_DEBUG_CORE, "Trying to fetch a PGP key \"%s\" from: %s", Context.Name().c_str(), Context.URL().Origin().c_str());
|
||||||
|
|
||||||
auto OnRequest = [this, &Server](CHTTPClient *Sender, CHTTPRequest *ARequest) {
|
auto OnRequest = [&Context](CHTTPClient *Sender, CHTTPRequest *ARequest) {
|
||||||
auto &PGP = Server.Value().PGP;
|
|
||||||
|
|
||||||
PGP.StatusTime = Now();
|
Context.PGP().Status = CKeyContext::ksFetching;
|
||||||
PGP.Status = CKeyContext::ksFetching;
|
Context.PGP().StatusTime = Now();
|
||||||
PGP.RunTime = PGP.StatusTime + (CDateTime) 30 / SecsPerDay;
|
|
||||||
|
|
||||||
CHTTPRequest::Prepare(ARequest, "GET", CString().Format("/api/v1/key/public?account=%s&type=pgp", PGP.Name.c_str()).c_str());
|
ARequest->ContentType = CHTTPRequest::json;
|
||||||
|
ARequest->Content = CString().Format(R"({"type": "pgp", "account": "%s", "code": "%s", "fields": ["data"]})", Context.Name().c_str(), Context.PGP().Name.c_str());
|
||||||
|
|
||||||
ARequest->AddHeader("Authorization", "Bearer " + m_Tokens[SYSTEM_PROVIDER_NAME]["access_token"]);
|
CHTTPRequest::Prepare(ARequest, "POST", "/api/v1/key/public");
|
||||||
|
|
||||||
|
const auto &access_token = Context.Tokens()["access_token"];
|
||||||
|
|
||||||
|
if (!access_token.empty()) {
|
||||||
|
ARequest->AddHeader("Authorization", "Bearer " + access_token);
|
||||||
|
}
|
||||||
|
|
||||||
DebugRequest(ARequest);
|
DebugRequest(ARequest);
|
||||||
};
|
};
|
||||||
|
|
||||||
auto OnExecute = [this, &Server](CTCPConnection *AConnection) {
|
auto OnExecute = [this, &Context](CTCPConnection *AConnection) {
|
||||||
|
|
||||||
auto pConnection = dynamic_cast<CHTTPClientConnection *> (AConnection);
|
auto pConnection = dynamic_cast<CHTTPClientConnection *> (AConnection);
|
||||||
|
|
||||||
@@ -1708,47 +1592,24 @@ namespace Apostol {
|
|||||||
|
|
||||||
DebugReply(pReply);
|
DebugReply(pReply);
|
||||||
|
|
||||||
auto &PGP = Server.Value().PGP;
|
CString Key;
|
||||||
|
|
||||||
PGP.StatusTime = Now();
|
|
||||||
PGP.Status = CKeyContext::ksError;
|
|
||||||
PGP.RunTime = PGP.StatusTime + (CDateTime) 30 / SecsPerDay;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
JsonStringToKey(pReply->Content, PGP.Key);
|
JsonStringToKey(pReply->Content, Key);
|
||||||
|
|
||||||
if (PGP.Key.IsEmpty())
|
if (Key.IsEmpty())
|
||||||
throw Delphi::Exception::Exception("Not found.");
|
throw Delphi::Exception::Exception("Not found.");
|
||||||
|
|
||||||
CStringPairs ServerList;
|
Context.PGP().Status = CKeyContext::ksSuccess;
|
||||||
|
Context.PGP().StatusTime = Now();
|
||||||
|
|
||||||
ParsePGPKey(PGP.Key, ServerList, Server.Value().BTCKeys);
|
Context.PGP().Key = Key;
|
||||||
|
|
||||||
if (ServerList.Count() != 0) {
|
UpdateServerList(Key);
|
||||||
CStringPairs::ConstEnumerator em(ServerList);
|
|
||||||
while (em.MoveNext()) {
|
|
||||||
const auto ¤t = em.Current();
|
|
||||||
if (m_Servers.IndexOfName(current.Name()) == -1) {
|
|
||||||
m_Servers.AddPair(current.Name(), CServerContext(current.Value()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
PGP.Status = CKeyContext::ksSuccess;
|
Context.SetStatus(csRunning);
|
||||||
PGP.RunTime = GetRandomDate(10 * 60, m_SyncPeriod * 60, PGP.StatusTime); // 10..m_SyncPeriod min
|
|
||||||
|
|
||||||
m_CurrentServer = Server;
|
|
||||||
|
|
||||||
Log()->Debug(APP_LOG_DEBUG_CORE, "[CurrentServer]\n");
|
|
||||||
Log()->Debug(APP_LOG_DEBUG_CORE, "[Name]\n%s", m_CurrentServer.Name().c_str());
|
|
||||||
|
|
||||||
const auto &key = m_CurrentServer.Value().PGP.Key;
|
|
||||||
Log()->Debug(APP_LOG_DEBUG_CORE, "[PGP]\n%s", key.IsEmpty() ? "<null>" : key.c_str());
|
|
||||||
|
|
||||||
const auto &keys = m_CurrentServer.Value().BTCKeys.Text();
|
|
||||||
Log()->Debug(APP_LOG_DEBUG_CORE, "[BTCKeys]\n%s", keys.IsEmpty() ? "<null>" : keys.c_str());
|
|
||||||
} catch (Delphi::Exception::Exception &e) {
|
} catch (Delphi::Exception::Exception &e) {
|
||||||
Log()->Error(APP_LOG_INFO, 0, "[CurrentServer] Message: %s", e.what());
|
Log()->Error(APP_LOG_INFO, 0, "[FetchPGP] %s", e.what());
|
||||||
}
|
}
|
||||||
|
|
||||||
pConnection->CloseConnection(true);
|
pConnection->CloseConnection(true);
|
||||||
@@ -1757,28 +1618,27 @@ namespace Apostol {
|
|||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
auto OnException = [&Server](CTCPConnection *AConnection, const Delphi::Exception::Exception &E) {
|
auto OnException = [&Context](CTCPConnection *AConnection, const Delphi::Exception::Exception &E) {
|
||||||
auto pConnection = dynamic_cast<CHTTPClientConnection *> (AConnection);
|
auto pConnection = dynamic_cast<CHTTPClientConnection *> (AConnection);
|
||||||
|
|
||||||
if (pConnection != nullptr) {
|
if (pConnection != nullptr) {
|
||||||
auto pClient = dynamic_cast<CHTTPClient *> (pConnection->Client());
|
auto pClient = dynamic_cast<CHTTPClient *> (pConnection->Client());
|
||||||
|
|
||||||
if (pClient != nullptr) {
|
if (pClient != nullptr) {
|
||||||
Log()->Error(APP_LOG_EMERG, 0, "[%s:%d] %s", pClient->Host().c_str(), pClient->Port(), E.what());
|
Log()->Error(APP_LOG_EMERG, 0, "[%s:%d] %s", pClient->Host().c_str(), pClient->Port(), E.what());
|
||||||
|
|
||||||
auto &PGP = Server.Value().PGP;
|
|
||||||
|
|
||||||
PGP.StatusTime = Now();
|
|
||||||
PGP.Status = CKeyContext::ksError;
|
|
||||||
PGP.RunTime = PGP.StatusTime + (CDateTime) 30 / SecsPerDay;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DebugReply(pConnection->Reply());
|
DebugReply(pConnection->Reply());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Context.SetStatus(Context::csAuthorized);
|
||||||
|
|
||||||
|
Context.PGP().Status = CKeyContext::ksError;
|
||||||
|
Context.PGP().StatusTime = Now();
|
||||||
};
|
};
|
||||||
|
|
||||||
CLocation Location(Server.Value().URI);
|
Context.PGP().Status = CKeyContext::ksUnknown;
|
||||||
auto pClient = GetClient(Location.hostname, Location.port == 0 ? BPS_SERVER_PORT : Location.port);
|
Context.PGP().StatusTime = Now();
|
||||||
|
Context.PGP().RunTime = Context.PGP().StatusTime;
|
||||||
|
|
||||||
|
auto pClient = GetClient(Context.URL().hostname, Context.URL().port == 0 ? BPS_SERVER_PORT : Context.URL().port);
|
||||||
|
|
||||||
pClient->OnRequest(OnRequest);
|
pClient->OnRequest(OnRequest);
|
||||||
pClient->OnExecute(OnExecute);
|
pClient->OnExecute(OnExecute);
|
||||||
@@ -1788,143 +1648,59 @@ namespace Apostol {
|
|||||||
}
|
}
|
||||||
//--------------------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
void CWebService::FetchBTC(CServer &Server) {
|
|
||||||
|
|
||||||
Log()->Debug(0, "Trying to fetch a BTC key \"%s\" from: %s", Server.Name().c_str(), Server.Value().URI.c_str());
|
|
||||||
|
|
||||||
auto OnRequest = [this, &Server](CHTTPClient *Sender, CHTTPRequest *ARequest) {
|
|
||||||
|
|
||||||
auto &BTC = Server.Value().BTC;
|
|
||||||
|
|
||||||
BTC.StatusTime = Now();
|
|
||||||
BTC.Status = CKeyContext::ksFetching;
|
|
||||||
BTC.RunTime = BTC.StatusTime + (CDateTime) 30 / SecsPerDay;
|
|
||||||
|
|
||||||
CHTTPRequest::Prepare(ARequest, "GET", CString().Format("/api/v1/key/public?account=%s&type=btc", BTC.Name.c_str()).c_str());
|
|
||||||
|
|
||||||
ARequest->AddHeader("Authorization", "Bearer " + m_Tokens[SYSTEM_PROVIDER_NAME]["access_token"]);
|
|
||||||
};
|
|
||||||
|
|
||||||
auto OnExecute = [this, &Server](CTCPConnection *AConnection) {
|
|
||||||
|
|
||||||
auto pConnection = dynamic_cast<CHTTPClientConnection *> (AConnection);
|
|
||||||
auto pReply = pConnection->Reply();
|
|
||||||
|
|
||||||
auto &BTC = Server.Value().BTC;
|
|
||||||
|
|
||||||
BTC.StatusTime = Now();
|
|
||||||
BTC.Status = CKeyContext::ksError;
|
|
||||||
BTC.RunTime = BTC.StatusTime + (CDateTime) 30 / SecsPerDay;
|
|
||||||
|
|
||||||
try {
|
|
||||||
CString Key;
|
|
||||||
JsonStringToKey(pReply->Content, Key);
|
|
||||||
if (!Key.IsEmpty()) {
|
|
||||||
Server.Value().BTCKeys.Add(Key);
|
|
||||||
}
|
|
||||||
} catch (Delphi::Exception::Exception &e) {
|
|
||||||
Log()->Error(APP_LOG_INFO, 0, "[BTC] Message: %s", e.what());
|
|
||||||
|
|
||||||
if (Server.Value().BTCKeys.Count() == 0) {
|
|
||||||
BTC.Status = CKeyContext::ksError;
|
|
||||||
} else {
|
|
||||||
BTC.Status = CKeyContext::ksSuccess;
|
|
||||||
BTC.RunTime = GetRandomDate(10 * 60, m_SyncPeriod * 60, BTC.StatusTime); // 10..m_SyncPeriod min
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pConnection->CloseConnection(true);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
auto OnException = [&Server](CTCPConnection *AConnection, const Delphi::Exception::Exception &E) {
|
|
||||||
auto pConnection = dynamic_cast<CHTTPClientConnection *> (AConnection);
|
|
||||||
auto pClient = dynamic_cast<CHTTPClient *> (pConnection->Client());
|
|
||||||
|
|
||||||
Log()->Error(APP_LOG_EMERG, 0, "[%s:%d] %s", pClient->Host().c_str(), pClient->Port(), E.what());
|
|
||||||
|
|
||||||
auto &BTC = Server.Value().BTC;
|
|
||||||
|
|
||||||
BTC.StatusTime = Now();
|
|
||||||
BTC.Status = CKeyContext::ksError;
|
|
||||||
BTC.RunTime = BTC.StatusTime + (CDateTime) 30 / SecsPerDay;
|
|
||||||
};
|
|
||||||
|
|
||||||
CLocation Location(Server.Value().URI);
|
|
||||||
auto pClient = GetClient(Location.hostname, Location.port == 0 ? BPS_SERVER_PORT : Location.port);
|
|
||||||
|
|
||||||
pClient->OnRequest(OnRequest);
|
|
||||||
pClient->OnExecute(OnExecute);
|
|
||||||
pClient->OnException(OnException);
|
|
||||||
|
|
||||||
pClient->Active(true);
|
|
||||||
}
|
|
||||||
//--------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
void CWebService::FetchKeys(CDateTime Now) {
|
|
||||||
while (NextServerIndex() != -1) {
|
|
||||||
auto& Server = ActiveServer();
|
|
||||||
auto& PGP = Server.Value().PGP;
|
|
||||||
if (Now >= PGP.RunTime) {
|
|
||||||
PGP.Status = CKeyContext::ksUnknown;
|
|
||||||
FetchPGP(Server);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//--------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
void CWebService::Reload() {
|
void CWebService::Reload() {
|
||||||
|
Config()->IniFile().ReadSectionValues("module", &m_Module);
|
||||||
|
|
||||||
m_Providers.Clear();
|
const auto& caPublicKey = Config()->IniFile().ReadString("pgp", "public", "dm.pub");
|
||||||
m_Tokens.Clear();
|
|
||||||
|
|
||||||
const auto &oauth2 = Config()->IniFile().ReadString(CONFIG_SECTION_NAME, "oauth2", "oauth2/service.json");
|
if (FileExists(caPublicKey.c_str())) {
|
||||||
const auto &provider = CString(SYSTEM_PROVIDER_NAME);
|
CString Key;
|
||||||
const auto &application = CString(SERVICE_APPLICATION_NAME);
|
Key.LoadFromFile(caPublicKey.c_str());
|
||||||
|
|
||||||
if (!oauth2.empty()) {
|
UpdateServerList(Key);
|
||||||
m_Tokens.AddPair(provider, CStringList());
|
UpdateOAuth2();
|
||||||
LoadOAuth2(oauth2, provider, application, m_Providers);
|
} else {
|
||||||
|
Log()->Error(APP_LOG_WARN, 0, APP_FILE_NOT_FOUND, caPublicKey.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
m_FixedDate = 0;
|
|
||||||
}
|
}
|
||||||
//--------------------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
void CWebService::Initialization(CModuleProcess *AProcess) {
|
void CWebService::Heartbeat(CDateTime Now) {
|
||||||
CApostolModule::Initialization(AProcess);
|
for (int i = 0; i < m_Servers.Count(); i++) {
|
||||||
Reload();
|
auto &Context = m_Servers[i].Value();
|
||||||
}
|
|
||||||
//--------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
void CWebService::Heartbeat() {
|
if (Now >= Context.CheckDate()) {
|
||||||
const auto now = Now();
|
Context.SetCheckDate(Now + (CDateTime) 30 / SecsPerDay); // 30 sec
|
||||||
|
if ((Context.Status() == Context::csInitialized) || (Context.Status() == Context::csRunning)) {
|
||||||
|
Context.SetStatus(Context::csAuthorization);
|
||||||
|
|
||||||
if ((now >= m_FixedDate)) {
|
CheckProviders(Now, Context);
|
||||||
m_FixedDate = now + (CDateTime) 55 / MinsPerDay; // 55 min
|
FetchProviders(Now, Context);
|
||||||
CheckProviders();
|
}
|
||||||
FetchProviders();
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (m_Servers.Count() == 0) {
|
if (Context.Status() == Context::csAuthorized) {
|
||||||
#ifdef _DEBUG
|
if (Now >= Context.FixedDate()) {
|
||||||
int Index = m_Servers.AddPair(BPS_BM_DEBUG_ADDRESS, CServerContext(BPS_SERVER_URL));
|
Context.SetFixedDate(Now + (CDateTime) 30 / SecsPerDay); // 30 sec
|
||||||
m_Servers[Index].Value().PGP.Name = m_Servers[Index].Name();
|
Context.SetStatus(Context::csInProgress);
|
||||||
#else
|
|
||||||
m_Servers.Add(m_DefaultServer);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_Status == psRunning) {
|
FetchPGP(Context);
|
||||||
FetchKeys(now);
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Context.Status() >= Context::csAuthorized) {
|
||||||
|
if (Now >= m_NexServerTime) {
|
||||||
|
m_NexServerTime = GetRandomDate(10 * 60, m_SyncPeriod * 60, Now);
|
||||||
|
m_CurrentServer = Context;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//--------------------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
bool CWebService::Enabled() {
|
bool CWebService::Enabled() {
|
||||||
if (m_ModuleStatus == msUnknown)
|
if (m_ModuleStatus == msUnknown)
|
||||||
m_ModuleStatus = msEnabled;
|
m_ModuleStatus = Config()->IniFile().ReadBool(SectionName().c_str(), "enable", true) ? msEnabled : msDisabled;
|
||||||
return m_ModuleStatus == msEnabled;
|
return m_ModuleStatus == msEnabled;
|
||||||
}
|
}
|
||||||
//--------------------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
/*++
|
/*++
|
||||||
|
|
||||||
Library name:
|
Program name:
|
||||||
|
|
||||||
apostol-module
|
dm
|
||||||
|
|
||||||
Module Name:
|
Module Name:
|
||||||
|
|
||||||
@@ -21,104 +21,15 @@ Author:
|
|||||||
|
|
||||||
--*/
|
--*/
|
||||||
|
|
||||||
#ifndef APOSTOL_WEBSERVICE_HPP
|
#ifndef DM_WEB_SERVICE_MODULE_HPP
|
||||||
#define APOSTOL_WEBSERVICE_HPP
|
#define DM_WEB_SERVICE_MODULE_HPP
|
||||||
//----------------------------------------------------------------------------------------------------------------------
|
|
||||||
#define BPS_DEFAULT_SYNC_PERIOD 30
|
|
||||||
#define BPS_SERVER_PORT 4988
|
|
||||||
#define BPS_SERVER_URL "http://localhost:4988"
|
|
||||||
#define BPS_BM_SERVER_ADDRESS "BM-2cX8y9u9yEi3fdqQfndx9F6NdR5Hv79add"
|
|
||||||
#define BPS_BM_DEBUG_ADDRESS "BM-2cXtL92m3CavBKx8qsV2LbZtAU3eQxW2rB"
|
|
||||||
//----------------------------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
extern "C++" {
|
extern "C++" {
|
||||||
|
|
||||||
namespace Apostol {
|
namespace Apostol {
|
||||||
|
|
||||||
namespace Workers {
|
namespace Module {
|
||||||
|
|
||||||
struct CKeyContext {
|
|
||||||
|
|
||||||
CString Name;
|
|
||||||
CString Key;
|
|
||||||
|
|
||||||
enum CKeyStatus {
|
|
||||||
ksUnknown = -1,
|
|
||||||
ksFetching,
|
|
||||||
ksSuccess,
|
|
||||||
ksError,
|
|
||||||
} Status;
|
|
||||||
|
|
||||||
CDateTime StatusTime;
|
|
||||||
CDateTime RunTime;
|
|
||||||
|
|
||||||
CKeyContext(): Status(ksUnknown), StatusTime(Now()), RunTime(0) {
|
|
||||||
Name = BPS_BM_SERVER_ADDRESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
CKeyContext(const CString &Name, const CString &Key): CKeyContext() {
|
|
||||||
this->Name = Name;
|
|
||||||
this->Key = Key;
|
|
||||||
}
|
|
||||||
|
|
||||||
CKeyContext(const CKeyContext &KeyContext): CKeyContext() {
|
|
||||||
Assign(KeyContext);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Assign(const CKeyContext &KeyContext) {
|
|
||||||
this->Name = KeyContext.Name;
|
|
||||||
this->Key = KeyContext.Key;
|
|
||||||
this->Status = KeyContext.Status;
|
|
||||||
this->StatusTime = KeyContext.StatusTime;
|
|
||||||
this->RunTime = KeyContext.RunTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
CKeyContext& operator= (const CKeyContext &KeyContext) {
|
|
||||||
if (this != &KeyContext) {
|
|
||||||
Assign(KeyContext);
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
};
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
struct CServerContext {
|
|
||||||
|
|
||||||
CString URI {};
|
|
||||||
|
|
||||||
CKeyContext PGP {};
|
|
||||||
CKeyContext BTC {};
|
|
||||||
|
|
||||||
CStringList BTCKeys;
|
|
||||||
|
|
||||||
CServerContext() = default;
|
|
||||||
|
|
||||||
explicit CServerContext(const CString& URI) {
|
|
||||||
this->URI = URI;
|
|
||||||
}
|
|
||||||
|
|
||||||
CServerContext(const CServerContext &ServerContext): CServerContext() {
|
|
||||||
Assign(ServerContext);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Assign(const CServerContext &ServerContext) {
|
|
||||||
this->URI = ServerContext.URI;
|
|
||||||
this->PGP = ServerContext.PGP;
|
|
||||||
this->BTC = ServerContext.BTC;
|
|
||||||
this->BTCKeys = ServerContext.BTCKeys;
|
|
||||||
}
|
|
||||||
|
|
||||||
CServerContext& operator= (const CServerContext &ServerContext) {
|
|
||||||
if (this != &ServerContext) {
|
|
||||||
Assign(ServerContext);
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
};
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef TPair<CServerContext> CServer;
|
|
||||||
typedef TPairs<CServerContext> CServerList;
|
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
@@ -129,68 +40,62 @@ namespace Apostol {
|
|||||||
class CWebService: public CApostolModule {
|
class CWebService: public CApostolModule {
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
CStringList m_Module;
|
||||||
|
|
||||||
|
int m_ServerIndex;
|
||||||
|
|
||||||
CProcessStatus m_Status;
|
CProcessStatus m_Status;
|
||||||
|
|
||||||
CServer m_DefaultServer {};
|
CContextPair m_DefaultServer { BPS_BM_SERVER_ADDRESS, CContext(CLocation(BPS_SERVER_URL)) };
|
||||||
CServer m_CurrentServer {};
|
CContextList m_Servers {};
|
||||||
|
|
||||||
|
CContext m_CurrentServer {};
|
||||||
|
|
||||||
int m_SyncPeriod;
|
int m_SyncPeriod;
|
||||||
int m_ActiveIndex;
|
|
||||||
|
|
||||||
CDateTime m_FixedDate;
|
CDateTime m_NexServerTime;
|
||||||
|
|
||||||
CServerList m_Servers;
|
|
||||||
|
|
||||||
CProviders m_Providers;
|
|
||||||
CStringListPairs m_Tokens;
|
|
||||||
|
|
||||||
CHTTPProxyManager m_ProxyManager;
|
CHTTPProxyManager m_ProxyManager;
|
||||||
|
|
||||||
CHTTPProxy *GetProxy(CHTTPServerConnection *AConnection);
|
|
||||||
|
|
||||||
void InitMethods() override;
|
void InitMethods() override;
|
||||||
|
|
||||||
void FetchCerts(CProvider &Provider, const CString &Application);
|
void InitServerList();
|
||||||
|
void UpdateServerList(const CString &Key);
|
||||||
|
void UpdateOAuth2();
|
||||||
|
|
||||||
void FetchProviders();
|
void FetchProviders(CDateTime Now, CContext &Context);
|
||||||
void CheckProviders();
|
void CheckProviders(CDateTime Now, CContext &Context);
|
||||||
|
|
||||||
void RouteUser(CHTTPServerConnection *AConnection, const CString &Method, const CString &URI);
|
void CreateAccessToken(const CProvider &Provider, const CString &Application, CContext &Context);
|
||||||
void RouteDeal(CHTTPServerConnection *AConnection, const CString &Method, const CString &URI, const CString &Action);
|
void ParsePGPKey(const CString& Key, CStringPairs& ServerList, CStringList& BTCKeys);
|
||||||
|
|
||||||
void RouteSignature(CHTTPServerConnection *AConnection);
|
void FetchPGP(CContext &Context);
|
||||||
|
|
||||||
void FetchAccessToken(const CString &URI, const CString &Assertion,
|
|
||||||
COnSocketExecuteEvent && OnDone, COnSocketExceptionEvent && OnFailed = nullptr);
|
|
||||||
void CreateAccessToken(const CProvider &Provider, const CString &Application, CStringList &Tokens);
|
|
||||||
|
|
||||||
static CString CreateToken(const CProvider& Provider, const CString &Application);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
int NextServerIndex();
|
int NextServerIndex();
|
||||||
|
|
||||||
const CServer &CurrentServer() const;
|
CHTTPProxy *GetProxy(CHTTPServerConnection *AConnection);
|
||||||
|
|
||||||
CServer &ActiveServer();
|
const CContext &CurrentServer() const;
|
||||||
const CServer &ActiveServer() const;
|
|
||||||
|
|
||||||
void FetchPGP(CServer& Server);
|
|
||||||
void FetchBTC(CServer& Server);
|
|
||||||
|
|
||||||
static int CheckFee(const CString& Fee);
|
static int CheckFee(const CString& Fee);
|
||||||
|
|
||||||
static void CheckKeyForNull(LPCTSTR Key, LPCTSTR Value);
|
static void CheckKeyForNull(LPCTSTR Key, LPCTSTR Value);
|
||||||
|
|
||||||
|
void DoUser(CHTTPServerConnection *AConnection, const CString &Method, const CString &URI);
|
||||||
|
void DoDeal(CHTTPServerConnection *AConnection, const CString &Method, const CString &URI, const CString &Action);
|
||||||
|
|
||||||
|
void DoSignature(CHTTPServerConnection *AConnection);
|
||||||
|
|
||||||
void DoAPI(CHTTPServerConnection *AConnection);
|
void DoAPI(CHTTPServerConnection *AConnection);
|
||||||
|
|
||||||
void DoGet(CHTTPServerConnection *AConnection) override;
|
void DoGet(CHTTPServerConnection *AConnection) override;
|
||||||
void DoPost(CHTTPServerConnection *AConnection);
|
void DoPost(CHTTPServerConnection *AConnection);
|
||||||
|
|
||||||
void DoVerbose(CSocketEvent *Sender, CTCPConnection *AConnection, LPCTSTR AFormat, va_list args);
|
|
||||||
bool DoProxyExecute(CTCPConnection *AConnection);
|
bool DoProxyExecute(CTCPConnection *AConnection);
|
||||||
void DoProxyException(CTCPConnection *AConnection, const Delphi::Exception::Exception &E);
|
void DoProxyException(CTCPConnection *AConnection, const Delphi::Exception::Exception &E);
|
||||||
void DoEventHandlerException(CPollEventHandler *AHandler, const Delphi::Exception::Exception &E);
|
void DoEventHandlerException(CPollEventHandler *AHandler, const Delphi::Exception::Exception &E) override;
|
||||||
|
|
||||||
void DoProxyConnected(CObject *Sender);
|
void DoProxyConnected(CObject *Sender);
|
||||||
void DoProxyDisconnected(CObject *Sender);
|
void DoProxyDisconnected(CObject *Sender);
|
||||||
@@ -205,36 +110,25 @@ namespace Apostol {
|
|||||||
return new CWebService(AProcess);
|
return new CWebService(AProcess);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Initialization(CModuleProcess *AProcess) override;
|
void Heartbeat(CDateTime Now) override;
|
||||||
|
|
||||||
void Heartbeat() override;
|
|
||||||
|
|
||||||
bool Enabled() override;
|
bool Enabled() override;
|
||||||
|
|
||||||
void FetchKeys(CDateTime Now);
|
|
||||||
|
|
||||||
void Reload();
|
void Reload();
|
||||||
|
|
||||||
static void JsonStringToKey(const CString& jsonString, CString& Key);
|
static void JsonStringToKey(const CString& jsonString, CString& Key);
|
||||||
|
|
||||||
void ParsePGPKey(const CString& Key, CStringPairs& ServerList, CStringList& BTCKeys);
|
|
||||||
|
|
||||||
static void CheckDeal(const CDeal& Deal);
|
static void CheckDeal(const CDeal& Deal);
|
||||||
|
|
||||||
static bool CheckVerifyPGPSignature(int VerifyPGPSignature, CString &Message);
|
static bool CheckVerifyPGPSignature(int VerifyPGPSignature, CString &Message);
|
||||||
static int VerifyPGPSignature(const CString &ClearText, const CString &Key, CString &Message);
|
static int VerifyPGPSignature(const CString &ClearText, const CString &Key, CString &Message);
|
||||||
|
|
||||||
static bool FindURLInLine(const CString &Line, CStringList &List);
|
static bool FindURLInLine(const CString &Line, CStringList &List);
|
||||||
static void ExceptionToJson(int ErrorCode, const std::exception &AException, CString& Json);
|
static void LoadOAuth2(const CString &FileName, const CString &ProviderName, const CString &ApplicationName, CProviders &Providers);
|
||||||
|
|
||||||
static CDateTime GetRandomDate(int a, int b, CDateTime Date = Now());
|
|
||||||
|
|
||||||
static void LoadOAuth2(const CString &FileName, const CString &ProviderName, const CString &ApplicationName,
|
|
||||||
CProviders &Providers);
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
using namespace Apostol::Workers;
|
using namespace Apostol::Module;
|
||||||
}
|
}
|
||||||
#endif //APOSTOL_WEBSERVICE_HPP
|
#endif //DM_WEB_SERVICE_MODULE_HPP
|
||||||
|
|||||||
@@ -25,10 +25,13 @@ Author:
|
|||||||
#define APOSTOL_WORKERS_HPP
|
#define APOSTOL_WORKERS_HPP
|
||||||
//----------------------------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include "WebSocket/WebSocketClient.hpp"
|
||||||
|
#include "WebSocket/WebSocket.hpp"
|
||||||
#include "WebService/WebService.hpp"
|
#include "WebService/WebService.hpp"
|
||||||
//----------------------------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
static inline void CreateWorkers(CModuleProcess *AProcess) {
|
static inline void CreateWorkers(CModuleProcess *AProcess) {
|
||||||
|
CWebSocketModule::CreateModule(AProcess);
|
||||||
CWebService::CreateModule(AProcess);
|
CWebService::CreateModule(AProcess);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -582,7 +582,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="form-group col-md-4">
|
<div class="form-group col-md-4">
|
||||||
<label for="serverURL">Server</label>
|
<label for="serverURL">Server</label>
|
||||||
<input type="text" class="form-control" id="serverURL" aria-describedby="serverURLHelp" placeholder="Default: http://localhost:4988" value="http://localhost:4988">
|
<input type="text" class="form-control" id="serverURL" aria-describedby="serverURLHelp" placeholder="Default: http://localhost:4977" value="http://localhost:4977">
|
||||||
<small id="serverURLHelp" class="form-text text-muted">BPS server URL.</small>
|
<small id="serverURLHelp" class="form-text text-muted">BPS server URL.</small>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group col-md-4">
|
<div class="form-group col-md-4">
|
||||||
@@ -1287,7 +1287,7 @@
|
|||||||
let execute = $("button[id='btnDealForm']");
|
let execute = $("button[id='btnDealForm']");
|
||||||
execute.prop('disabled', true);
|
execute.prop('disabled', true);
|
||||||
|
|
||||||
AsyncFetch(api + '/deal/' + formOrder.val() + settings, 'POST', formData, {'Content-Type': 'multipart/form-data'})
|
AsyncFetch(api + '/deal/' + formOrder.val().toLowerCase() + settings, 'POST', formData, {'Content-Type': 'multipart/form-data'})
|
||||||
.then(function(json) {
|
.then(function(json) {
|
||||||
let html;
|
let html;
|
||||||
let payload;
|
let payload;
|
||||||
|
|||||||
Reference in New Issue
Block a user