Если есть возможность, то нужно регистрировать пользователя МС при запуске МС с указанными в конфиге bitcoin и PGP ключами.

This commit is contained in:
Преподобный Ален
2022-09-18 00:42:20 +03:00
parent 16c1abefe5
commit fe4d665e8c
7 changed files with 338 additions and 94 deletions

View File

@@ -54,6 +54,8 @@ namespace Apostol {
m_Status = psStopped;
CWebService::InitMethods();
InitServerList();
}
//--------------------------------------------------------------------------------------------------------------
@@ -83,14 +85,15 @@ namespace Apostol {
//--------------------------------------------------------------------------------------------------------------
void CWebService::InitServerList() {
m_DefaultServer.Value().Name() = m_DefaultServer.Name();
m_DefaultServer.Value().PGP().Name = "PUBLIC";
m_DefaultServer.Value().PGP().Add(CKeyContext(CString("PUBLIC"), CString()));
m_DefaultServer.Value().PGP().Add(CKeyContext(m_DefaultServer.Name(), CString()));
if (m_Servers.Count() == 0) {
#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";
int index = m_Servers.AddPair(BPS_BM_DEBUG_ADDRESS, CClientContext(BPS_BM_DEBUG_ADDRESS, CLocation(BPS_SERVER_URL)));
auto &Keys = m_Servers[index].Value().PGP();
Keys.Add(CKeyContext(CString("PUBLIC"), CString()));
Keys.Add(CKeyContext(CString(BPS_BM_DEBUG_ADDRESS), CString()));
#else
m_Servers.Add(m_DefaultServer);
#endif
@@ -101,21 +104,34 @@ namespace Apostol {
void CWebService::UpdateServerList(const CString &Key) {
CStringPairs ServerList;
CStringList Keys;
int index;
ParsePGPKey(Key, ServerList, Keys);
if (ServerList.Count() != 0) {
CStringPairs::ConstEnumerator em(ServerList);
while (em.MoveNext()) {
const auto &current = 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;
const auto &caCurrent = em.Current();
#ifndef _DEBUG
if (caCurrent.Name() == BPS_BM_DEBUG_ADDRESS)
continue;
#endif
index = m_Servers.IndexOfName(caCurrent.Name());
if (index == -1) {
index = m_Servers.AddPair(caCurrent.Name(), CClientContext(caCurrent.Name(), CLocation(caCurrent.Value())));
auto &Context = m_Servers[index].Value();
Context.PGP().Add(CKeyContext(CString("PUBLIC"), Key));
Context.PGP().Add(CKeyContext(caCurrent.Name(), CString()));
} else {
auto &Context = m_Servers[index].Value();
Context.URL() = caCurrent.Value();
Context.PGP().First().Key = Key;
}
auto &Context = m_Servers[index].Value();
Context.BTCKeys() = Keys;
UpdateOAuth2(Context, m_OAuth2.Object());
}
}
}
@@ -245,7 +261,7 @@ namespace Apostol {
void CWebService::CreateAccessToken(const CProvider &Provider, const CString &Application, CContext &Context) {
auto OnDone = [&Context](CTCPConnection *Sender) {
auto OnDone = [this, &Context](CTCPConnection *Sender) {
auto pConnection = dynamic_cast<CHTTPClientConnection *> (Sender);
auto pReply = pConnection->Reply();
@@ -255,15 +271,12 @@ namespace Apostol {
if (pReply->Status == CHTTPReply::ok) {
const CJSON Json(pReply->Content);
Context.SetStatus(csAuthorized);
Context.Session() = Json["session"].AsString();
Context.Secret() = Json["secret"].AsString();
Context.Tokens().Values("access_token", Json["access_token"].AsString());
Context.SetFixedDate(0);
Context.SetCheckDate(Now() + (CDateTime) 50 / MinsPerDay); // 50 min
ModuleStatus(Context);
}
return true;
@@ -465,14 +478,14 @@ namespace Apostol {
auto pServerRequest = AConnection->Request();
auto pProxyRequest = pProxy->Request();
const auto& caModuleAddress = m_Module["address"];
const auto &caModuleAddress = m_Module["address"];
const auto &caHost = pServerRequest->Headers["host"];
const auto &caOrigin = pServerRequest->Headers["origin"];
const auto &caUserAddress = pServerRequest->Params["address"];
const auto& caOrigin = pServerRequest->Headers["origin"];
const auto& caUserAddress = pServerRequest->Params["address"];
const auto &pgpValue = pServerRequest->Params["pgp"];
const auto &caServerParam = pServerRequest->Params["server"];
const auto& pgpValue = pServerRequest->Params["pgp"];
const auto& caServerParam = pServerRequest->Params["server"];
const auto& caServer = caServerParam.IsEmpty() ? m_CurrentServer.URL().Origin() : caServerParam;
CLocation Location(caServer);
@@ -646,8 +659,18 @@ namespace Apostol {
//DebugMessage("[DoAccount] sPayload:\n%s\n", sPayload.c_str());
CJSON Json(jvtObject);
CJSONValue Module(jvtObject);
Json.Object().AddPair("id", ApostolUID());
Module.Object().AddPair("address", caModuleAddress);
Json.Object().AddPair("id", GetUID(16).Lower());
Json.Object().AddPair("host", caHost);
if (!caOrigin.IsEmpty()) {
Json.Object().AddPair("origin", caOrigin);
}
Json.Object().AddPair("module", Module);
Json.Object().AddPair("address", caUserAddress.IsEmpty() ? caModuleAddress : caUserAddress);
if (!sPayload.IsEmpty())
@@ -743,19 +766,25 @@ namespace Apostol {
auto pServerRequest = AConnection->Request();
auto pProxyRequest = pProxy->Request();
const auto& caModuleAddress = m_Module["address"];
const auto& caModuleFee = m_Module["fee"];
const auto &caModuleAddress = m_Module["address"];
const auto &caModuleFee = m_Module["fee"];
const auto checkFee = CheckFee(caModuleFee);
if (checkFee == -1)
throw ExceptionFrm("Invalid module fee value: %s", caModuleFee.c_str());
const auto& caOrigin = pServerRequest->Headers["origin"];
const auto& caUserAddress = pServerRequest->Params["address"];
const auto &caHost = pServerRequest->Headers["host"];
const auto &caOrigin = pServerRequest->Headers["origin"];
const auto& pgpValue = pServerRequest->Params["pgp"];
const auto &address = pServerRequest->Params["address"];
const auto &code = pServerRequest->Params["code"];
const auto &caUserAddress = address.length() == 40 ? CString() : address;
const auto &caDealCode = !code.empty() ? code : address.length() == 40 ? address : CString();
const auto &pgpValue = pServerRequest->Params["pgp"];
const auto &caServerParam = pServerRequest->Params["server"];
const auto& caServerParam = pServerRequest->Params["server"];
const auto& caServer = caServerParam.IsEmpty() ? m_CurrentServer.URL().Origin() : caServerParam;
CLocation Location(caServer);
@@ -1091,10 +1120,26 @@ namespace Apostol {
}
CJSON Json(jvtObject);
CJSONValue Module(jvtObject);
Json.Object().AddPair("id", ApostolUID());
if (!caUserAddress.IsEmpty())
Json.Object().AddPair("address", caUserAddress.IsEmpty() ? caModuleAddress : caUserAddress);
Module.Object().AddPair("address", caModuleAddress);
Module.Object().AddPair("fee", caModuleFee);
Json.Object().AddPair("id", GetUID(16).Lower());
Json.Object().AddPair("host", caHost);
if (!caOrigin.IsEmpty()) {
Json.Object().AddPair("origin", caOrigin);
}
Json.Object().AddPair("module", Module);
Json.Object().AddPair("address", caUserAddress.IsEmpty() ? caModuleAddress : caUserAddress);
if (!caDealCode.IsEmpty()) {
CJSONValue Deal(jvtObject);
Deal.Object().AddPair("code", caDealCode);
Json.Object().AddPair("deal", Deal);
}
if (!sPayload.IsEmpty())
Json.Object().AddPair("payload", base64_encode(sPayload));
@@ -1129,7 +1174,6 @@ namespace Apostol {
//--------------------------------------------------------------------------------------------------------------
void CWebService::DoSignature(CHTTPServerConnection *AConnection) {
auto pRequest = AConnection->Request();
auto pReply = AConnection->Reply();
@@ -1138,10 +1182,20 @@ namespace Apostol {
return;
}
const auto& caServerKey = m_CurrentServer.PGP().Key;
auto &Keys = m_CurrentServer.PGP();
int index = 0;
while (index < Keys.Count() && Keys[index].Name != m_CurrentServer.Name()) {
index++;
}
if (index == Keys.Count())
throw ExceptionFrm("PGP key not found.");
const auto& caServerKey = Keys[index].Key;
if (caServerKey.IsEmpty())
throw ExceptionFrm("Server PGP key not added.");
throw ExceptionFrm("PGP key not added.");
CString message;
CJSON Json(jvtObject);
@@ -1426,16 +1480,16 @@ namespace Apostol {
}
//--------------------------------------------------------------------------------------------------------------
int CWebService::VerifyPGPSignature(const CString &caClearText, const CString &Key, CString &Message) {
int CWebService::VerifyPGPSignature(const CString &ClearText, const CString &Key, CString &Message) {
const OpenPGP::Key signer(Key.c_str());
const OpenPGP::CleartextSignature cleartext(caClearText.c_str());
const OpenPGP::CleartextSignature cleartext(ClearText.c_str());
if (!cleartext.meaningful())
return -2;
const int verified = OpenPGP::Verify::cleartext_signature(signer, cleartext);
if (verified) {
if (verified == 1) {
Message = cleartext.get_message().c_str();
}
@@ -1524,11 +1578,23 @@ namespace Apostol {
auto OnRequest = [&Context](CHTTPClient *Sender, CHTTPRequest *ARequest) {
Context.PGP().Status = CKeyContext::ksFetching;
Context.PGP().StatusTime = Now();
const auto &name = Sender->Data()["name"];
auto &Keys = Context.PGP();
int index = 0;
while (index < Keys.Count() && Keys[index].Name != name) {
index++;
}
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());
if (index < Keys.Count()) {
auto &Key = Keys[index];
Key.Status = CKeyContext::ksFetching;
Key.StatusTime = Now();
}
ARequest->Content = CString().Format(R"({"type": "pgp", "account": "%s", "code": "%s", "fields": ["code", "data"]})", Context.Name().c_str(), name.c_str());
CHTTPRequest::Prepare(ARequest, "POST", "/api/v1/key/public");
@@ -1546,24 +1612,36 @@ namespace Apostol {
auto pConnection = dynamic_cast<CHTTPClientConnection *> (AConnection);
if (pConnection != nullptr) {
auto pClient = dynamic_cast<CHTTPClient *> (pConnection->Client());
auto pReply = pConnection->Reply();
DebugReply(pReply);
CString Key;
CString Content;
try {
JsonStringToKey(pReply->Content, Key);
JsonStringToKey(pReply->Content, Content);
if (Key.IsEmpty())
if (Content.IsEmpty())
throw Delphi::Exception::Exception("Not found.");
Context.PGP().Status = CKeyContext::ksSuccess;
Context.PGP().StatusTime = Now();
const auto &name = pClient->Data()["name"];
auto &Keys = Context.PGP();
Context.PGP().Key = Key;
int index = 0;
while (index < Keys.Count() && Keys[index].Name != name) {
index++;
}
UpdateServerList(Key);
if (index < Keys.Count()) {
auto &Key = Keys[index];
Key.Status = CKeyContext::ksSuccess;
Key.StatusTime = Now();
Key.Key = Content;
UpdateServerList(Content);
}
Context.SetStatus(csRunning);
} catch (Delphi::Exception::Exception &e) {
@@ -1581,29 +1659,48 @@ namespace Apostol {
if (pConnection != nullptr) {
auto pClient = dynamic_cast<CHTTPClient *> (pConnection->Client());
if (pClient != nullptr) {
const auto &name = pClient->Data()["name"];
auto &Keys = Context.PGP();
int index = 0;
while (index < Keys.Count() && Keys[index].Name != name) {
index++;
}
if (index < Keys.Count()) {
auto &Key = Keys[index];
Key.Status = CKeyContext::ksError;
Key.StatusTime = Now();
}
Log()->Error(APP_LOG_EMERG, 0, "[%s:%d] %s", pClient->Host().c_str(), pClient->Port(), E.what());
}
DebugReply(pConnection->Reply());
}
Context.SetStatus(Context::csAuthorized);
Context.PGP().Status = CKeyContext::ksError;
Context.PGP().StatusTime = Now();
};
Context.PGP().Status = CKeyContext::ksUnknown;
Context.PGP().StatusTime = Now();
Context.PGP().RunTime = Context.PGP().StatusTime;
auto &Keys = Context.PGP();
auto pClient = GetClient(Context.URL().hostname, Context.URL().port == 0 ? BPS_SERVER_PORT : Context.URL().port);
for (int i = 0; i < Keys.Count(); i++ ) {
auto &Key = Keys[i];
pClient->OnRequest(OnRequest);
pClient->OnExecute(OnExecute);
pClient->OnException(OnException);
Key.Status = CKeyContext::ksUnknown;
Key.StatusTime = Now();
Key.RunTime = Key.StatusTime;
pClient->AutoFree(true);
pClient->Active(true);
auto pClient = GetClient(Context.URL().hostname, Context.URL().port == 0 ? BPS_SERVER_PORT : Context.URL().port);
pClient->Data().AddPair("name", Key.Name);
pClient->OnRequest(OnRequest);
pClient->OnExecute(OnExecute);
pClient->OnException(OnException);
pClient->AutoFree(true);
pClient->Active(true);
}
}
//--------------------------------------------------------------------------------------------------------------