Added: Get configuration for OAuth2 service account.
This commit is contained in:
@@ -56,8 +56,7 @@ namespace Apostol {
|
|||||||
|
|
||||||
CWebService::InitMethods();
|
CWebService::InitMethods();
|
||||||
|
|
||||||
//InitServerList();
|
InitServerList();
|
||||||
Reload();
|
|
||||||
}
|
}
|
||||||
//--------------------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
@@ -125,41 +124,116 @@ namespace Apostol {
|
|||||||
}
|
}
|
||||||
//--------------------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
void CWebService::UpdateOAuth2() {
|
void CWebService::FetchOAuth2(CContext &Context) {
|
||||||
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);
|
|
||||||
|
|
||||||
|
Log()->Debug(APP_LOG_DEBUG_CORE, "Trying to fetch a OAuth2 configuration file for module \"%s\" from: %s", Context.Name().c_str(), Context.URL().Origin().c_str());
|
||||||
|
|
||||||
|
auto OnRequest = [this, &Context](CHTTPClient *Sender, CHTTPRequest *ARequest) {
|
||||||
|
|
||||||
|
ARequest->ContentType = CHTTPRequest::text;
|
||||||
|
|
||||||
|
Apostol::PGP::CleartextSignature(
|
||||||
|
m_pgpPrivateKey,
|
||||||
|
m_pgpPassphrase,
|
||||||
|
BPS_PGP_HASH,
|
||||||
|
Context.Name(),
|
||||||
|
ARequest->Content);
|
||||||
|
|
||||||
|
CHTTPRequest::Prepare(ARequest, "POST", "/api/v1/dm/service");
|
||||||
|
|
||||||
|
const auto& caModuleAddress = m_Module["address"];
|
||||||
|
if (!caModuleAddress.IsEmpty())
|
||||||
|
ARequest->AddHeader("Module-Address", caModuleAddress);
|
||||||
|
|
||||||
|
DebugRequest(ARequest);
|
||||||
|
};
|
||||||
|
|
||||||
|
auto OnExecute = [this, &Context](CTCPConnection *AConnection) {
|
||||||
|
|
||||||
|
auto pConnection = dynamic_cast<CHTTPClientConnection *> (AConnection);
|
||||||
|
|
||||||
|
if (pConnection != nullptr) {
|
||||||
|
auto pReply = pConnection->Reply();
|
||||||
|
|
||||||
|
DebugReply(pReply);
|
||||||
|
|
||||||
|
if (Context.Status() == Context::csPreparing) {
|
||||||
|
if (pReply->Status == CHTTPReply::ok) {
|
||||||
|
const CJSON Json(pReply->Content);
|
||||||
|
Json.SaveToFile(m_OAuth2.c_str());
|
||||||
|
UpdateOAuth2(m_OAuth2);
|
||||||
|
} else {
|
||||||
|
Context.SetStatus(Context::csInitialization);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pConnection->CloseConnection(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
auto OnException = [&Context](CTCPConnection *AConnection, const Delphi::Exception::Exception &E) {
|
||||||
|
auto pConnection = dynamic_cast<CHTTPClientConnection *> (AConnection);
|
||||||
|
if (pConnection != nullptr) {
|
||||||
|
auto pClient = dynamic_cast<CHTTPClient *> (pConnection->Client());
|
||||||
|
if (pClient != nullptr) {
|
||||||
|
Log()->Error(APP_LOG_EMERG, 0, "[%s:%d] %s", pClient->Host().c_str(), pClient->Port(), E.what());
|
||||||
|
}
|
||||||
|
DebugReply(pConnection->Reply());
|
||||||
|
}
|
||||||
|
|
||||||
|
Context.SetStatus(Context::csInitialization);
|
||||||
|
};
|
||||||
|
|
||||||
|
Context.SetStatus(Context::csPreparing);
|
||||||
|
|
||||||
|
auto pClient = GetClient(Context.URL().hostname, Context.URL().port == 0 ? BPS_SERVER_PORT : Context.URL().port);
|
||||||
|
|
||||||
|
pClient->OnRequest(OnRequest);
|
||||||
|
pClient->OnExecute(OnExecute);
|
||||||
|
pClient->OnException(OnException);
|
||||||
|
|
||||||
|
pClient->AutoFree(true);
|
||||||
|
pClient->Active(true);
|
||||||
|
}
|
||||||
|
//--------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void CWebService::UpdateOAuth2(const CString &FileName) {
|
||||||
for (int i = 0; i < m_Servers.Count(); i++) {
|
for (int i = 0; i < m_Servers.Count(); i++) {
|
||||||
auto &Context = m_Servers[i].Value();
|
auto &Context = m_Servers[i].Value();
|
||||||
if (!oauth2.empty() && Context.Status() == Context::csInitialization) {
|
if (Context.Status() == Context::csInitialization || Context.Status() == Context::csPreparing) {
|
||||||
LoadOAuth2(oauth2, provider, application, Context.Providers());
|
if (LoadOAuth2(FileName, Context.Providers())) {
|
||||||
Context.SetStatus(Context::csInitialized);
|
Context.SetStatus(Context::csInitialized);
|
||||||
}
|
|
||||||
Context.SetCheckDate(0);
|
Context.SetCheckDate(0);
|
||||||
|
} else {
|
||||||
|
if (Context.Status() != Context::csPreparing) {
|
||||||
|
FetchOAuth2(Context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//--------------------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
void CWebService::LoadOAuth2(const CString &FileName, const CString &ProviderName, const CString &ApplicationName, CProviders &Providers) {
|
bool CWebService::LoadOAuth2(const CString &FileName, CProviders &Providers) {
|
||||||
CString ConfigFile(FileName);
|
const auto &caProviderName = CString(SYSTEM_PROVIDER_NAME);
|
||||||
|
const auto &caApplicationName = CString(SERVICE_APPLICATION_NAME);
|
||||||
|
|
||||||
if (!path_separator(ConfigFile.front())) {
|
if (FileExists(FileName.c_str())) {
|
||||||
ConfigFile = Config()->Prefix() + ConfigFile;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (FileExists(ConfigFile.c_str())) {
|
|
||||||
CJSONObject Json;
|
CJSONObject Json;
|
||||||
Json.LoadFromFile(ConfigFile.c_str());
|
Json.LoadFromFile(FileName.c_str());
|
||||||
|
|
||||||
int index = Providers.IndexOfName(ProviderName);
|
int index = Providers.IndexOfName(caProviderName);
|
||||||
if (index == -1)
|
if (index == -1)
|
||||||
index = Providers.AddPair(ProviderName, CProvider(ProviderName));
|
index = Providers.AddPair(caProviderName, CProvider(caProviderName));
|
||||||
auto& Provider = Providers[index].Value();
|
auto& Provider = Providers[index].Value();
|
||||||
Provider.Applications().AddPair(ApplicationName, Json);
|
Provider.Applications().AddPair(caApplicationName, Json);
|
||||||
} else {
|
|
||||||
Log()->Error(APP_LOG_WARN, 0, APP_FILE_NOT_FOUND, ConfigFile.c_str());
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
//--------------------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
@@ -650,21 +724,12 @@ namespace Apostol {
|
|||||||
caClearText = pServerRequest->Content;
|
caClearText = pServerRequest->Content;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto& caPGPPrivateFile = Config()->IniFile().ReadString("pgp", "private", "");
|
|
||||||
const auto& caPGPPassphrase = Config()->IniFile().ReadString("pgp", "passphrase", "");
|
|
||||||
|
|
||||||
if (!FileExists(caPGPPrivateFile.c_str()))
|
|
||||||
throw Delphi::Exception::Exception("PGP: Private key file not opened.");
|
|
||||||
|
|
||||||
CString sPGPPrivate;
|
|
||||||
sPGPPrivate.LoadFromFile(caPGPPrivateFile.c_str());
|
|
||||||
|
|
||||||
if (pgpValue == "off" || pgpValue == "false") {
|
if (pgpValue == "off" || pgpValue == "false") {
|
||||||
sPayload = caClearText.Text();
|
sPayload = caClearText.Text();
|
||||||
} else {
|
} else {
|
||||||
Apostol::PGP::CleartextSignature(
|
Apostol::PGP::CleartextSignature(
|
||||||
sPGPPrivate,
|
m_pgpPrivateKey,
|
||||||
caPGPPassphrase,
|
m_pgpPassphrase,
|
||||||
BPS_PGP_HASH,
|
BPS_PGP_HASH,
|
||||||
caClearText.Text(),
|
caClearText.Text(),
|
||||||
sPayload);
|
sPayload);
|
||||||
@@ -1105,23 +1170,14 @@ namespace Apostol {
|
|||||||
|
|
||||||
CheckDeal(Deal);
|
CheckDeal(Deal);
|
||||||
|
|
||||||
const auto& caPGPPrivateFile = Config()->IniFile().ReadString("pgp", "private", "");
|
|
||||||
const auto& caPGPPassphrase = Config()->IniFile().ReadString("pgp", "passphrase", "");
|
|
||||||
|
|
||||||
if (!FileExists(caPGPPrivateFile.c_str()))
|
|
||||||
throw Delphi::Exception::Exception("PGP: Private key file not opened.");
|
|
||||||
|
|
||||||
CString sPGPPrivate;
|
|
||||||
sPGPPrivate.LoadFromFile(caPGPPrivateFile.c_str());
|
|
||||||
|
|
||||||
const CString caClearText(YAML::Dump(Node));
|
const CString caClearText(YAML::Dump(Node));
|
||||||
|
|
||||||
if (pgpValue == "off" || pgpValue == "false") {
|
if (pgpValue == "off" || pgpValue == "false") {
|
||||||
sPayload = caClearText;
|
sPayload = caClearText;
|
||||||
} else {
|
} else {
|
||||||
Apostol::PGP::CleartextSignature(
|
Apostol::PGP::CleartextSignature(
|
||||||
sPGPPrivate,
|
m_pgpPrivateKey,
|
||||||
caPGPPassphrase,
|
m_pgpPassphrase,
|
||||||
BPS_PGP_HASH,
|
BPS_PGP_HASH,
|
||||||
caClearText,
|
caClearText,
|
||||||
sPayload);
|
sPayload);
|
||||||
@@ -1157,7 +1213,9 @@ namespace Apostol {
|
|||||||
if (!caOrigin.IsEmpty())
|
if (!caOrigin.IsEmpty())
|
||||||
pProxyRequest->AddHeader("Origin", caOrigin);
|
pProxyRequest->AddHeader("Origin", caOrigin);
|
||||||
|
|
||||||
AConnection->UpdateTimeOut(Now(), 60);
|
AConnection->TimeOutInterval(30 * 1000);
|
||||||
|
AConnection->UpdateTimeOut(Now());
|
||||||
|
|
||||||
AConnection->CloseConnection(false);
|
AConnection->CloseConnection(false);
|
||||||
|
|
||||||
pProxy->Active(true);
|
pProxy->Active(true);
|
||||||
@@ -1638,6 +1696,7 @@ namespace Apostol {
|
|||||||
pClient->OnExecute(OnExecute);
|
pClient->OnExecute(OnExecute);
|
||||||
pClient->OnException(OnException);
|
pClient->OnException(OnException);
|
||||||
|
|
||||||
|
pClient->AutoFree(true);
|
||||||
pClient->Active(true);
|
pClient->Active(true);
|
||||||
}
|
}
|
||||||
//--------------------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------------------
|
||||||
@@ -1645,17 +1704,31 @@ namespace Apostol {
|
|||||||
void CWebService::Reload() {
|
void CWebService::Reload() {
|
||||||
Config()->IniFile().ReadSectionValues("module", &m_Module);
|
Config()->IniFile().ReadSectionValues("module", &m_Module);
|
||||||
|
|
||||||
|
m_OAuth2 = Config()->IniFile().ReadString(CONFIG_SECTION_NAME, "oauth2", "oauth2/service.json");
|
||||||
|
if (!path_separator(m_OAuth2.front())) {
|
||||||
|
m_OAuth2 = Config()->Prefix() + m_OAuth2;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto& caPrivateKey = Config()->IniFile().ReadString("pgp", "private", "module.sec");
|
||||||
const auto& caPublicKey = Config()->IniFile().ReadString("pgp", "public", "dm.pub");
|
const auto& caPublicKey = Config()->IniFile().ReadString("pgp", "public", "dm.pub");
|
||||||
|
|
||||||
|
m_pgpPassphrase = Config()->IniFile().ReadString("pgp", "passphrase", "");
|
||||||
|
|
||||||
|
if (FileExists(caPrivateKey.c_str())) {
|
||||||
|
m_pgpPrivateKey.LoadFromFile(caPrivateKey.c_str());
|
||||||
|
|
||||||
if (FileExists(caPublicKey.c_str())) {
|
if (FileExists(caPublicKey.c_str())) {
|
||||||
CString Key;
|
CString Key;
|
||||||
Key.LoadFromFile(caPublicKey.c_str());
|
Key.LoadFromFile(caPublicKey.c_str());
|
||||||
|
|
||||||
UpdateServerList(Key);
|
UpdateServerList(Key);
|
||||||
UpdateOAuth2();
|
UpdateOAuth2(m_OAuth2);
|
||||||
} else {
|
} else {
|
||||||
Log()->Error(APP_LOG_WARN, 0, APP_FILE_NOT_FOUND, caPublicKey.c_str());
|
Log()->Error(APP_LOG_WARN, 0, APP_FILE_NOT_FOUND, caPublicKey.c_str());
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
Log()->Error(APP_LOG_WARN, 0, APP_FILE_NOT_FOUND, caPrivateKey.c_str());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//--------------------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
@@ -1663,15 +1736,20 @@ namespace Apostol {
|
|||||||
for (int i = 0; i < m_Servers.Count(); i++) {
|
for (int i = 0; i < m_Servers.Count(); i++) {
|
||||||
auto &Context = m_Servers[i].Value();
|
auto &Context = m_Servers[i].Value();
|
||||||
|
|
||||||
if (Now >= Context.CheckDate()) {
|
if ((Now >= Context.CheckDate()) && (Context.Status() == Context::csInitialization)) {
|
||||||
Context.SetCheckDate(Now + (CDateTime) 30 / SecsPerDay); // 30 sec
|
Context.SetCheckDate(Now + (CDateTime) 30 / SecsPerDay); // 30 sec
|
||||||
if (Context.Status() != Context::csAuthorization) {
|
FetchOAuth2(Context);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((Now >= Context.CheckDate()) && (Context.Status() >= Context::csInitialized)) {
|
||||||
|
Context.SetCheckDate(Now + (CDateTime) 30 / SecsPerDay); // 30 sec
|
||||||
|
|
||||||
|
if (Context.Status() == Context::csInitialized)
|
||||||
Context.SetStatus(Context::csAuthorization);
|
Context.SetStatus(Context::csAuthorization);
|
||||||
|
|
||||||
CheckProviders(Now, Context);
|
CheckProviders(Now, Context);
|
||||||
FetchProviders(Now, Context);
|
FetchProviders(Now, Context);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (Context.Status() == Context::csAuthorized) {
|
if (Context.Status() == Context::csAuthorized) {
|
||||||
if (Now >= Context.FixedDate()) {
|
if (Now >= Context.FixedDate()) {
|
||||||
@@ -1682,7 +1760,7 @@ namespace Apostol {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Context.Status() >= Context::csAuthorized) {
|
if (Context.Status() == Context::csRunning) {
|
||||||
if (Now >= m_NexServerTime) {
|
if (Now >= m_NexServerTime) {
|
||||||
m_NexServerTime = GetRandomDate(10 * 60, m_SyncPeriod * 60, Now);
|
m_NexServerTime = GetRandomDate(10 * 60, m_SyncPeriod * 60, Now);
|
||||||
m_CurrentServer = Context;
|
m_CurrentServer = Context;
|
||||||
@@ -1692,6 +1770,15 @@ namespace Apostol {
|
|||||||
}
|
}
|
||||||
//--------------------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void CWebService::Initialization(CModuleProcess *AProcess) {
|
||||||
|
CApostolModule::Initialization(AProcess);
|
||||||
|
|
||||||
|
if (Enabled()) {
|
||||||
|
Reload();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//--------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
bool CWebService::Enabled() {
|
bool CWebService::Enabled() {
|
||||||
if (m_ModuleStatus == msUnknown)
|
if (m_ModuleStatus == msUnknown)
|
||||||
m_ModuleStatus = Config()->IniFile().ReadBool(SectionName().c_str(), "enable", true) ? msEnabled : msDisabled;
|
m_ModuleStatus = Config()->IniFile().ReadBool(SectionName().c_str(), "enable", true) ? msEnabled : msDisabled;
|
||||||
|
|||||||
@@ -42,6 +42,10 @@ namespace Apostol {
|
|||||||
|
|
||||||
CStringList m_Module;
|
CStringList m_Module;
|
||||||
|
|
||||||
|
CString m_OAuth2;
|
||||||
|
CString m_pgpPrivateKey;
|
||||||
|
CString m_pgpPassphrase;
|
||||||
|
|
||||||
int m_ServerIndex;
|
int m_ServerIndex;
|
||||||
|
|
||||||
CProcessStatus m_Status;
|
CProcessStatus m_Status;
|
||||||
@@ -61,7 +65,7 @@ namespace Apostol {
|
|||||||
|
|
||||||
void InitServerList();
|
void InitServerList();
|
||||||
void UpdateServerList(const CString &Key);
|
void UpdateServerList(const CString &Key);
|
||||||
void UpdateOAuth2();
|
void UpdateOAuth2(const CString &FileName);
|
||||||
|
|
||||||
void FetchProviders(CDateTime Now, CContext &Context);
|
void FetchProviders(CDateTime Now, CContext &Context);
|
||||||
void CheckProviders(CDateTime Now, CContext &Context);
|
void CheckProviders(CDateTime Now, CContext &Context);
|
||||||
@@ -69,6 +73,7 @@ namespace Apostol {
|
|||||||
void CreateAccessToken(const CProvider &Provider, const CString &Application, CContext &Context);
|
void CreateAccessToken(const CProvider &Provider, const CString &Application, CContext &Context);
|
||||||
void ParsePGPKey(const CString& Key, CStringPairs& ServerList, CStringList& BTCKeys);
|
void ParsePGPKey(const CString& Key, CStringPairs& ServerList, CStringList& BTCKeys);
|
||||||
|
|
||||||
|
void FetchOAuth2(CContext &Context);
|
||||||
void FetchPGP(CContext &Context);
|
void FetchPGP(CContext &Context);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@@ -110,6 +115,7 @@ namespace Apostol {
|
|||||||
|
|
||||||
void Heartbeat(CDateTime Now) override;
|
void Heartbeat(CDateTime Now) override;
|
||||||
|
|
||||||
|
void Initialization(CModuleProcess *AProcess) override;
|
||||||
bool Enabled() override;
|
bool Enabled() override;
|
||||||
|
|
||||||
void Reload();
|
void Reload();
|
||||||
@@ -124,7 +130,7 @@ namespace Apostol {
|
|||||||
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 LoadOAuth2(const CString &FileName, const CString &ProviderName, const CString &ApplicationName, CProviders &Providers);
|
static bool LoadOAuth2(const CString &FileName, CProviders &Providers);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,7 +58,6 @@ namespace Apostol {
|
|||||||
CWebSocketModule::InitMethods();
|
CWebSocketModule::InitMethods();
|
||||||
|
|
||||||
InitServerList();
|
InitServerList();
|
||||||
Reload();
|
|
||||||
}
|
}
|
||||||
//--------------------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
@@ -113,13 +112,13 @@ namespace Apostol {
|
|||||||
if (ServerList.Count() != 0) {
|
if (ServerList.Count() != 0) {
|
||||||
CStringPairs::ConstEnumerator em(ServerList);
|
CStringPairs::ConstEnumerator em(ServerList);
|
||||||
while (em.MoveNext()) {
|
while (em.MoveNext()) {
|
||||||
const auto ¤t = em.Current();
|
const auto &caCurrent = em.Current();
|
||||||
index = m_Servers.IndexOfName(current.Name());
|
index = m_Servers.IndexOfName(caCurrent.Name());
|
||||||
if (index == -1) {
|
if (index == -1) {
|
||||||
index = m_Servers.AddPair(current.Name(), CClientContext(CLocation(current.Value())));
|
index = m_Servers.AddPair(caCurrent.Name(), CClientContext(CLocation(caCurrent.Value())));
|
||||||
}
|
}
|
||||||
auto &Context = m_Servers[index].Value();
|
auto &Context = m_Servers[index].Value();
|
||||||
Context.Name() = current.Name();
|
Context.Name() = caCurrent.Name();
|
||||||
Context.PGP().Name = "PUBLIC";
|
Context.PGP().Name = "PUBLIC";
|
||||||
Context.PGP().Key = Key;
|
Context.PGP().Key = Key;
|
||||||
Context.BTCKeys() = Keys;
|
Context.BTCKeys() = Keys;
|
||||||
@@ -128,41 +127,116 @@ namespace Apostol {
|
|||||||
}
|
}
|
||||||
//--------------------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
void CWebSocketModule::UpdateOAuth2() {
|
void CWebSocketModule::FetchOAuth2(CContext &Context) {
|
||||||
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);
|
|
||||||
|
|
||||||
|
Log()->Debug(APP_LOG_DEBUG_CORE, "Trying to fetch a OAuth2 configuration file for module \"%s\" from: %s", Context.Name().c_str(), Context.URL().Origin().c_str());
|
||||||
|
|
||||||
|
auto OnRequest = [this, &Context](CHTTPClient *Sender, CHTTPRequest *ARequest) {
|
||||||
|
|
||||||
|
ARequest->ContentType = CHTTPRequest::text;
|
||||||
|
|
||||||
|
Apostol::PGP::CleartextSignature(
|
||||||
|
m_pgpPrivateKey,
|
||||||
|
m_pgpPassphrase,
|
||||||
|
BPS_PGP_HASH,
|
||||||
|
Context.Name(),
|
||||||
|
ARequest->Content);
|
||||||
|
|
||||||
|
CHTTPRequest::Prepare(ARequest, "POST", "/api/v1/dm/service");
|
||||||
|
|
||||||
|
const auto& caModuleAddress = m_Module["address"];
|
||||||
|
if (!caModuleAddress.IsEmpty())
|
||||||
|
ARequest->AddHeader("Module-Address", caModuleAddress);
|
||||||
|
|
||||||
|
DebugRequest(ARequest);
|
||||||
|
};
|
||||||
|
|
||||||
|
auto OnExecute = [this, &Context](CTCPConnection *AConnection) {
|
||||||
|
|
||||||
|
auto pConnection = dynamic_cast<CHTTPClientConnection *> (AConnection);
|
||||||
|
|
||||||
|
if (pConnection != nullptr) {
|
||||||
|
auto pReply = pConnection->Reply();
|
||||||
|
|
||||||
|
DebugReply(pReply);
|
||||||
|
|
||||||
|
if (Context.Status() == Context::csPreparing) {
|
||||||
|
if (pReply->Status == CHTTPReply::ok) {
|
||||||
|
const CJSON Json(pReply->Content);
|
||||||
|
Json.SaveToFile(m_OAuth2.c_str());
|
||||||
|
UpdateOAuth2(m_OAuth2);
|
||||||
|
} else {
|
||||||
|
Context.SetStatus(Context::csInitialization);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pConnection->CloseConnection(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
auto OnException = [&Context](CTCPConnection *AConnection, const Delphi::Exception::Exception &E) {
|
||||||
|
auto pConnection = dynamic_cast<CHTTPClientConnection *> (AConnection);
|
||||||
|
if (pConnection != nullptr) {
|
||||||
|
auto pClient = dynamic_cast<CHTTPClient *> (pConnection->Client());
|
||||||
|
if (pClient != nullptr) {
|
||||||
|
Log()->Error(APP_LOG_EMERG, 0, "[%s:%d] %s", pClient->Host().c_str(), pClient->Port(), E.what());
|
||||||
|
}
|
||||||
|
DebugReply(pConnection->Reply());
|
||||||
|
}
|
||||||
|
|
||||||
|
Context.SetStatus(Context::csInitialization);
|
||||||
|
};
|
||||||
|
|
||||||
|
Context.SetStatus(Context::csPreparing);
|
||||||
|
|
||||||
|
auto pClient = GetClient(Context.URL().hostname, Context.URL().port == 0 ? BPS_SERVER_PORT : Context.URL().port);
|
||||||
|
|
||||||
|
pClient->OnRequest(OnRequest);
|
||||||
|
pClient->OnExecute(OnExecute);
|
||||||
|
pClient->OnException(OnException);
|
||||||
|
|
||||||
|
pClient->AutoFree(true);
|
||||||
|
pClient->Active(true);
|
||||||
|
}
|
||||||
|
//--------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void CWebSocketModule::UpdateOAuth2(const CString &FileName) {
|
||||||
for (int i = 0; i < m_Servers.Count(); i++) {
|
for (int i = 0; i < m_Servers.Count(); i++) {
|
||||||
auto &Context = m_Servers[i].Value();
|
auto &Context = m_Servers[i].Value();
|
||||||
if (!oauth2.empty() && Context.Status() == Context::csInitialization) {
|
if (Context.Status() == Context::csInitialization || Context.Status() == Context::csPreparing) {
|
||||||
LoadOAuth2(oauth2, provider, application, Context.Providers());
|
if (LoadOAuth2(FileName, Context.Providers())) {
|
||||||
Context.SetStatus(Context::csInitialized);
|
Context.SetStatus(Context::csInitialized);
|
||||||
Context.SetCheckDate(0);
|
Context.SetCheckDate(0);
|
||||||
|
} else {
|
||||||
|
if (Context.Status() != Context::csPreparing) {
|
||||||
|
FetchOAuth2(Context);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//--------------------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
void CWebSocketModule::LoadOAuth2(const CString &FileName, const CString &ProviderName, const CString &ApplicationName, CProviders &Providers) {
|
bool CWebSocketModule::LoadOAuth2(const CString &FileName, CProviders &Providers) {
|
||||||
CString ConfigFile(FileName);
|
const auto &caProviderName = CString(SYSTEM_PROVIDER_NAME);
|
||||||
|
const auto &caApplicationName = CString(SERVICE_APPLICATION_NAME);
|
||||||
|
|
||||||
if (!path_separator(ConfigFile.front())) {
|
if (FileExists(FileName.c_str())) {
|
||||||
ConfigFile = Config()->Prefix() + ConfigFile;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (FileExists(ConfigFile.c_str())) {
|
|
||||||
CJSONObject Json;
|
CJSONObject Json;
|
||||||
Json.LoadFromFile(ConfigFile.c_str());
|
Json.LoadFromFile(FileName.c_str());
|
||||||
|
|
||||||
int index = Providers.IndexOfName(ProviderName);
|
int index = Providers.IndexOfName(caProviderName);
|
||||||
if (index == -1)
|
if (index == -1)
|
||||||
index = Providers.AddPair(ProviderName, CProvider(ProviderName));
|
index = Providers.AddPair(caProviderName, CProvider(caProviderName));
|
||||||
auto& Provider = Providers[index].Value();
|
auto& Provider = Providers[index].Value();
|
||||||
Provider.Applications().AddPair(ApplicationName, Json);
|
Provider.Applications().AddPair(caApplicationName, Json);
|
||||||
} else {
|
|
||||||
Log()->Error(APP_LOG_WARN, 0, APP_FILE_NOT_FOUND, ConfigFile.c_str());
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
//--------------------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
@@ -511,7 +585,7 @@ namespace Apostol {
|
|||||||
|
|
||||||
if (Response.Payload.HasOwnProperty("data")) {
|
if (Response.Payload.HasOwnProperty("data")) {
|
||||||
UpdateServerList(Response.Payload["data"].AsString());
|
UpdateServerList(Response.Payload["data"].AsString());
|
||||||
UpdateOAuth2();
|
UpdateOAuth2(m_OAuth2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//--------------------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------------------
|
||||||
@@ -731,21 +805,12 @@ namespace Apostol {
|
|||||||
caClearText = pServerRequest->Content;
|
caClearText = pServerRequest->Content;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto& caPGPPrivateFile = Config()->IniFile().ReadString("pgp", "private", "");
|
|
||||||
const auto& caPGPPassphrase = Config()->IniFile().ReadString("pgp", "passphrase", "");
|
|
||||||
|
|
||||||
if (!FileExists(caPGPPrivateFile.c_str()))
|
|
||||||
throw Delphi::Exception::Exception("PGP: Private key file not opened.");
|
|
||||||
|
|
||||||
CString sPGPPrivate;
|
|
||||||
sPGPPrivate.LoadFromFile(caPGPPrivateFile.c_str());
|
|
||||||
|
|
||||||
if (pgpValue == "off" || pgpValue == "false") {
|
if (pgpValue == "off" || pgpValue == "false") {
|
||||||
sPayload = caClearText.Text();
|
sPayload = caClearText.Text();
|
||||||
} else {
|
} else {
|
||||||
Apostol::PGP::CleartextSignature(
|
Apostol::PGP::CleartextSignature(
|
||||||
sPGPPrivate,
|
m_pgpPrivateKey,
|
||||||
caPGPPassphrase,
|
m_pgpPassphrase,
|
||||||
BPS_PGP_HASH,
|
BPS_PGP_HASH,
|
||||||
caClearText.Text(),
|
caClearText.Text(),
|
||||||
sPayload);
|
sPayload);
|
||||||
@@ -1156,23 +1221,14 @@ namespace Apostol {
|
|||||||
|
|
||||||
CheckDeal(Deal);
|
CheckDeal(Deal);
|
||||||
|
|
||||||
const auto& caPGPPrivateFile = Config()->IniFile().ReadString("pgp", "private", "");
|
|
||||||
const auto& caPGPPassphrase = Config()->IniFile().ReadString("pgp", "passphrase", "");
|
|
||||||
|
|
||||||
if (!FileExists(caPGPPrivateFile.c_str()))
|
|
||||||
throw Delphi::Exception::Exception("PGP: Private key file not opened.");
|
|
||||||
|
|
||||||
CString sPGPPrivate;
|
|
||||||
sPGPPrivate.LoadFromFile(caPGPPrivateFile.c_str());
|
|
||||||
|
|
||||||
const CString caClearText(YAML::Dump(Node));
|
const CString caClearText(YAML::Dump(Node));
|
||||||
|
|
||||||
if (pgpValue == "off" || pgpValue == "false") {
|
if (pgpValue == "off" || pgpValue == "false") {
|
||||||
sPayload = caClearText;
|
sPayload = caClearText;
|
||||||
} else {
|
} else {
|
||||||
Apostol::PGP::CleartextSignature(
|
Apostol::PGP::CleartextSignature(
|
||||||
sPGPPrivate,
|
m_pgpPrivateKey,
|
||||||
caPGPPassphrase,
|
m_pgpPassphrase,
|
||||||
BPS_PGP_HASH,
|
BPS_PGP_HASH,
|
||||||
caClearText,
|
caClearText,
|
||||||
sPayload);
|
sPayload);
|
||||||
@@ -1418,6 +1474,11 @@ namespace Apostol {
|
|||||||
for (int i = 0; i < m_Servers.Count(); i++) {
|
for (int i = 0; i < m_Servers.Count(); i++) {
|
||||||
auto &Context = m_Servers[i].Value();
|
auto &Context = m_Servers[i].Value();
|
||||||
|
|
||||||
|
if ((Now >= Context.CheckDate()) && (Context.Status() == Context::csInitialization)) {
|
||||||
|
Context.SetCheckDate(Now + (CDateTime) 30 / SecsPerDay); // 30 sec
|
||||||
|
FetchOAuth2(Context);
|
||||||
|
}
|
||||||
|
|
||||||
if ((Now >= Context.CheckDate()) && (Context.Status() >= Context::csInitialized)) {
|
if ((Now >= Context.CheckDate()) && (Context.Status() >= Context::csInitialized)) {
|
||||||
Context.SetCheckDate(Now + (CDateTime) 30 / SecsPerDay); // 30 sec
|
Context.SetCheckDate(Now + (CDateTime) 30 / SecsPerDay); // 30 sec
|
||||||
|
|
||||||
@@ -1429,15 +1490,16 @@ namespace Apostol {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (Context.Status() == Context::csAuthorized) {
|
if (Context.Status() == Context::csAuthorized) {
|
||||||
if ((Now >= Context.FixedDate())) {
|
if (Now >= Context.FixedDate()) {
|
||||||
Context.SetFixedDate(Now + (CDateTime) 30 / SecsPerDay); // 30 sec
|
Context.SetFixedDate(Now + (CDateTime) 30 / SecsPerDay); // 30 sec
|
||||||
Context.SetStatus(Context::csInProgress);
|
Context.SetStatus(Context::csInProgress);
|
||||||
|
|
||||||
CreateWebSocketClient(Context);
|
CreateWebSocketClient(Context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Context.Status() == Context::csRunning) {
|
if (Context.Status() == Context::csRunning) {
|
||||||
if ((Now >= Context.FixedDate())) {
|
if (Now >= Context.FixedDate()) {
|
||||||
Context.SetFixedDate(Now + (CDateTime) 30 / SecsPerDay); // 30 sec
|
Context.SetFixedDate(Now + (CDateTime) 30 / SecsPerDay); // 30 sec
|
||||||
|
|
||||||
for (int j = 0; j < Context.ClientManager().Count(); ++j) {
|
for (int j = 0; j < Context.ClientManager().Count(); ++j) {
|
||||||
@@ -1460,17 +1522,40 @@ namespace Apostol {
|
|||||||
void CWebSocketModule::Reload() {
|
void CWebSocketModule::Reload() {
|
||||||
Config()->IniFile().ReadSectionValues("module", &m_Module);
|
Config()->IniFile().ReadSectionValues("module", &m_Module);
|
||||||
|
|
||||||
|
m_OAuth2 = Config()->IniFile().ReadString(CONFIG_SECTION_NAME, "oauth2", "oauth2/service.json");
|
||||||
|
if (!path_separator(m_OAuth2.front())) {
|
||||||
|
m_OAuth2 = Config()->Prefix() + m_OAuth2;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto& caPrivateKey = Config()->IniFile().ReadString("pgp", "private", "module.sec");
|
||||||
const auto& caPublicKey = Config()->IniFile().ReadString("pgp", "public", "dm.pub");
|
const auto& caPublicKey = Config()->IniFile().ReadString("pgp", "public", "dm.pub");
|
||||||
|
|
||||||
|
m_pgpPassphrase = Config()->IniFile().ReadString("pgp", "passphrase", "");
|
||||||
|
|
||||||
|
if (FileExists(caPrivateKey.c_str())) {
|
||||||
|
m_pgpPrivateKey.LoadFromFile(caPrivateKey.c_str());
|
||||||
|
|
||||||
if (FileExists(caPublicKey.c_str())) {
|
if (FileExists(caPublicKey.c_str())) {
|
||||||
CString Key;
|
CString Key;
|
||||||
Key.LoadFromFile(caPublicKey.c_str());
|
Key.LoadFromFile(caPublicKey.c_str());
|
||||||
|
|
||||||
UpdateServerList(Key);
|
UpdateServerList(Key);
|
||||||
UpdateOAuth2();
|
UpdateOAuth2(m_OAuth2);
|
||||||
} else {
|
} else {
|
||||||
Log()->Error(APP_LOG_WARN, 0, APP_FILE_NOT_FOUND, caPublicKey.c_str());
|
Log()->Error(APP_LOG_WARN, 0, APP_FILE_NOT_FOUND, caPublicKey.c_str());
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
Log()->Error(APP_LOG_WARN, 0, APP_FILE_NOT_FOUND, caPrivateKey.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//--------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void CWebSocketModule::Initialization(CModuleProcess *AProcess) {
|
||||||
|
CApostolModule::Initialization(AProcess);
|
||||||
|
|
||||||
|
if (Enabled()) {
|
||||||
|
Reload();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//--------------------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|||||||
@@ -69,6 +69,10 @@ namespace Apostol {
|
|||||||
|
|
||||||
CStringList m_Module;
|
CStringList m_Module;
|
||||||
|
|
||||||
|
CString m_OAuth2;
|
||||||
|
CString m_pgpPrivateKey;
|
||||||
|
CString m_pgpPassphrase;
|
||||||
|
|
||||||
int m_SyncPeriod;
|
int m_SyncPeriod;
|
||||||
|
|
||||||
CClientContextPair m_DefaultServer { BPS_BM_SERVER_ADDRESS, CClientContext(CLocation(BPS_SERVER_URL)) };
|
CClientContextPair m_DefaultServer { BPS_BM_SERVER_ADDRESS, CClientContext(CLocation(BPS_SERVER_URL)) };
|
||||||
@@ -79,7 +83,7 @@ namespace Apostol {
|
|||||||
|
|
||||||
void InitServerList();
|
void InitServerList();
|
||||||
void UpdateServerList(const CString &Key);
|
void UpdateServerList(const CString &Key);
|
||||||
void UpdateOAuth2();
|
void UpdateOAuth2(const CString &FileName);
|
||||||
|
|
||||||
void FetchProviders(CDateTime Now, CClientContext &Context);
|
void FetchProviders(CDateTime Now, CClientContext &Context);
|
||||||
void CheckProviders(CDateTime Now, CClientContext &Context);
|
void CheckProviders(CDateTime Now, CClientContext &Context);
|
||||||
@@ -90,6 +94,8 @@ namespace Apostol {
|
|||||||
CWebSocketClient *GetWebSocketClient(CClientContext &Context);
|
CWebSocketClient *GetWebSocketClient(CClientContext &Context);
|
||||||
void CreateWebSocketClient(CClientContext &Context);
|
void CreateWebSocketClient(CClientContext &Context);
|
||||||
|
|
||||||
|
void FetchOAuth2(CContext &Context);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
void Heartbeat(CDateTime Now) override;
|
void Heartbeat(CDateTime Now) override;
|
||||||
@@ -130,17 +136,18 @@ namespace Apostol {
|
|||||||
return new CWebSocketModule(AProcess);
|
return new CWebSocketModule(AProcess);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Reload();
|
void Initialization(CModuleProcess *AProcess) override;
|
||||||
|
|
||||||
bool Enabled() override;
|
bool Enabled() override;
|
||||||
|
|
||||||
|
void Reload();
|
||||||
|
|
||||||
static CString ToString(unsigned long Value);
|
static CString ToString(unsigned long Value);
|
||||||
static int CheckFee(const CString& Fee);
|
static int CheckFee(const CString& Fee);
|
||||||
static void CheckDeal(const CDeal& Deal);
|
static void CheckDeal(const CDeal& Deal);
|
||||||
static void CheckKeyForNull(LPCTSTR key, const CString& Value);
|
static void CheckKeyForNull(LPCTSTR key, const CString& Value);
|
||||||
|
|
||||||
static bool FindURLInLine(const CString &Line, CStringList &List);
|
static bool FindURLInLine(const CString &Line, CStringList &List);
|
||||||
static void LoadOAuth2(const CString &FileName, const CString &ProviderName, const CString &ApplicationName, CProviders &Providers);
|
static bool LoadOAuth2(const CString &FileName, CProviders &Providers);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user