improved the login in the interaction between terminal api client and main

This commit is contained in:
csoler 2017-07-08 17:38:09 +02:00
parent 7ee527ecbd
commit decbd3514d
5 changed files with 148 additions and 92 deletions

View File

@ -150,24 +150,29 @@ void RsControlModule::run()
} }
// skip account selection if autologin is available // skip account selection if autologin is available
if(initResult != RS_INIT_HAVE_ACCOUNT) bool wait_for_account_select = (initResult != RS_INIT_HAVE_ACCOUNT);
setRunState(WAITING_ACCOUNT_SELECT);
// wait for login request // wait for login request
bool auto_login = false; bool auto_login = false;
bool wait_for_account_select = (initResult != RS_INIT_HAVE_ACCOUNT);
if(wait_for_account_select)
setRunState(WAITING_ACCOUNT_SELECT);
while(wait_for_account_select && !processShouldExit()) while(wait_for_account_select && !processShouldExit())
{ {
usleep(5*1000); usleep(500*1000);
RsStackMutex stack(mDataMtx); // ********** LOCKED ********** RsStackMutex stack(mDataMtx); // ********** LOCKED **********
wait_for_account_select = mLoadPeerId.isNull();
if(!mLoadPeerId.isNull())
wait_for_account_select = wait_for_account_select && !RsAccounts::SelectAccount(mLoadPeerId);
auto_login = mAutoLoginNextTime; auto_login = mAutoLoginNextTime;
if(!wait_for_account_select)
{ //if(!wait_for_account_select)
wait_for_account_select = !RsAccounts::SelectAccount(mLoadPeerId); //{
if(wait_for_account_select) // if(wait_for_account_select)
setRunState(WAITING_ACCOUNT_SELECT); // setRunState(WAITING_ACCOUNT_SELECT);
} //}
} }
if(processShouldExit()) if(processShouldExit())

View File

@ -23,6 +23,8 @@ class ApiServer;
class RsControlModule: public ResourceRouter, NotifyClient, private RsSingleJobThread class RsControlModule: public ResourceRouter, NotifyClient, private RsSingleJobThread
{ {
public: public:
enum RunState { WAITING_INIT, FATAL_ERROR, WAITING_ACCOUNT_SELECT, WAITING_STARTUP, RUNNING_OK, RUNNING_OK_NO_FULL_CONTROL};
// ApiServer will be called once RS is started, to load additional api modules // ApiServer will be called once RS is started, to load additional api modules
// full_control: set to true if this module should handle rsinit and login // full_control: set to true if this module should handle rsinit and login
// set to false if rsinit is handled by the Qt gui // set to false if rsinit is handled by the Qt gui
@ -32,6 +34,9 @@ public:
// returns true if the process should terminate // returns true if the process should terminate
bool processShouldExit(); bool processShouldExit();
// returns the current state of the software booting process
RunState runState() const { return mRunState ; }
// from NotifyClient // from NotifyClient
virtual bool askForPassword(const std::string &title, const std::string& key_details, bool prev_is_bad , std::string& password,bool& canceled) override; virtual bool askForPassword(const std::string &title, const std::string& key_details, bool prev_is_bad , std::string& password,bool& canceled) override;
virtual bool askForDeferredSelfSignature(const void *data, const uint32_t len, unsigned char *sign, unsigned int *signlen,int& signature_result, std::string reason = "") override; virtual bool askForDeferredSelfSignature(const void *data, const uint32_t len, unsigned char *sign, unsigned int *signlen,int& signature_result, std::string reason = "") override;
@ -42,7 +47,6 @@ protected:
virtual void run(); virtual void run();
private: private:
enum RunState { WAITING_INIT, FATAL_ERROR, WAITING_ACCOUNT_SELECT, WAITING_STARTUP, RUNNING_OK, RUNNING_OK_NO_FULL_CONTROL};
void handleRunState(Request& req, Response& resp); void handleRunState(Request& req, Response& resp);
void handleIdentities(Request& req, Response& resp); void handleIdentities(Request& req, Response& resp);
void handleLocations(Request& req, Response& resp); void handleLocations(Request& req, Response& resp);

View File

@ -87,10 +87,8 @@ private:
namespace resource_api { namespace resource_api {
TerminalApiClient::TerminalApiClient(ApiServer *api): TerminalApiClient::TerminalApiClient(ApiServer *api): mApiServer(api)
mApiServer(api)
{ {
start("resapi terminal");
} }
TerminalApiClient::~TerminalApiClient() TerminalApiClient::~TerminalApiClient()
@ -98,13 +96,6 @@ TerminalApiClient::~TerminalApiClient()
fullstop(); fullstop();
} }
struct AccountInfo
{
std::string name ;
std::string location ;
RsPeerId ssl_id ;
};
void TerminalApiClient::data_tick() void TerminalApiClient::data_tick()
{ {
// values in milliseconds // values in milliseconds
@ -228,44 +219,7 @@ void TerminalApiClient::data_tick()
if(!ask_for_password && edge && runstate == "waiting_account_select") if(!ask_for_password && edge && runstate == "waiting_account_select")
{ {
JsonStream reqs; readAvailableAccounts(accounts) ;
JsonStream resps;
Request req(reqs);
std::stringstream ss;
Response resp(resps, ss);
req.mPath.push("locations");
req.mPath.push("control");
reqs.switchToDeserialisation();
ApiServer::RequestId id = mApiServer->handleRequest(req, resp);
waitForResponse(id);
resps.switchToDeserialisation();
if(!resps.hasMore())
std::cout << "Error: No Accounts. Use the Qt-GUI or the webinterface to create an account." << std::endl;
int i = 0;
accounts.clear();
while(resps.hasMore())
{
std::string id;
std::string name;
std::string location;
resps.getStreamToMember()
<< makeKeyValueReference("id", id)
<< makeKeyValueReference("name", name)
<< makeKeyValueReference("location", location);
AccountInfo info ;
info.location = location ;
info.name = name ;
info.ssl_id = RsPeerId(id) ;
accounts.push_back(info);
i++;
}
account_number_size = (int)ceil(log(accounts.size())/log(10.0f)) ; account_number_size = (int)ceil(log(accounts.size())/log(10.0f)) ;
for(uint32_t i=0;i<accounts.size();++i) for(uint32_t i=0;i<accounts.size();++i)
@ -292,19 +246,7 @@ void TerminalApiClient::data_tick()
std::cout << std::endl << "Selected account: " << accounts[selected_account_number].name << " (" << accounts[selected_account_number].location << ") SSL id: " << accounts[selected_account_number].ssl_id << std::endl; std::cout << std::endl << "Selected account: " << accounts[selected_account_number].name << " (" << accounts[selected_account_number].location << ") SSL id: " << accounts[selected_account_number].ssl_id << std::endl;
std::string acc_ssl_id = accounts[selected_account_number].ssl_id.toStdString(); std::string acc_ssl_id = accounts[selected_account_number].ssl_id.toStdString();
JsonStream reqs; sendSelectedAccount(acc_ssl_id) ;
JsonStream resps;
Request req(reqs);
std::stringstream ss;
Response resp(resps, ss);
req.mPath.push("login");
req.mPath.push("control");
reqs << makeKeyValueReference("id", acc_ssl_id);
reqs.switchToDeserialisation();
ApiServer::RequestId id = mApiServer->handleRequest(req, resp);
waitForResponse(id);
inbuf.clear(); inbuf.clear();
} }
@ -330,33 +272,107 @@ void TerminalApiClient::data_tick()
} }
if(ask_for_password && enter_was_pressed && !inbuf.empty()) if(ask_for_password && enter_was_pressed && !inbuf.empty())
{ {
std::cout << "TerminalApiClient: got a password" << std::endl; std::cout << "TerminalApiClient: got a password" << std::endl;
JsonStream reqs;
JsonStream resps;
Request req(reqs);
std::stringstream ss;
Response resp(resps, ss);
req.mPath.push("password"); // Send passwd to api server
req.mPath.push("control"); sendPassword(inbuf) ;
reqs << makeKeyValueReference("password", inbuf);
reqs.switchToDeserialisation();
ApiServer::RequestId id = mApiServer->handleRequest(req, resp); // clears buffer
waitForResponse(id); inbuf.clear();
inbuf.clear();
} }
} }
} }
void TerminalApiClient::waitForResponse(ApiServer::RequestId id) void TerminalApiClient::waitForResponse(ApiServer::RequestId id) const
{ {
while(!mApiServer->isRequestDone(id)) while(!mApiServer->isRequestDone(id))
usleep(20*1000); usleep(20*1000);
} }
void TerminalApiClient::sendPassword(const std::string& passwd) const
{
JsonStream reqs;
JsonStream resps;
Request req(reqs);
std::stringstream ss;
Response resp(resps, ss);
req.mPath.push("password");
req.mPath.push("control");
std::string pass(passwd) ;
reqs << makeKeyValueReference("password", pass);
reqs.switchToDeserialisation();
ApiServer::RequestId id = mApiServer->handleRequest(req, resp);
waitForResponse(id);
}
void TerminalApiClient::sendSelectedAccount(const std::string& ssl_id) const
{
JsonStream reqs;
JsonStream resps;
Request req(reqs);
std::stringstream ss;
Response resp(resps, ss);
std::string acc_ssl_id(ssl_id) ;
req.mPath.push("login");
req.mPath.push("control");
reqs << makeKeyValueReference("id", acc_ssl_id);
reqs.switchToDeserialisation();
ApiServer::RequestId id = mApiServer->handleRequest(req, resp);
waitForResponse(id);
}
void TerminalApiClient::readAvailableAccounts(std::vector<AccountInfo>& accounts) const
{
JsonStream reqs;
JsonStream resps;
Request req(reqs);
std::stringstream ss;
Response resp(resps, ss);
req.mPath.push("locations");
req.mPath.push("control");
reqs.switchToDeserialisation();
ApiServer::RequestId id = mApiServer->handleRequest(req, resp);
waitForResponse(id);
resps.switchToDeserialisation();
if(!resps.hasMore())
std::cout << "Error: No Accounts. Use the Qt-GUI or the webinterface to create an account." << std::endl;
int i = 0;
accounts.clear();
while(resps.hasMore())
{
std::string id;
std::string name;
std::string location;
resps.getStreamToMember()
<< makeKeyValueReference("id", id)
<< makeKeyValueReference("name", name)
<< makeKeyValueReference("location", location);
AccountInfo info ;
info.location = location ;
info.name = name ;
info.ssl_id = RsPeerId(id) ;
accounts.push_back(info);
i++;
}
}
bool TerminalApiClient::isTokenValid(StateToken runstate_state_token) bool TerminalApiClient::isTokenValid(StateToken runstate_state_token)
{ {
JsonStream reqs; JsonStream reqs;

View File

@ -8,7 +8,7 @@ namespace resource_api {
// - account selection // - account selection
// - login // - login
// - shutdown // - shutdown
class TerminalApiClient: private RsTickingThread{ class TerminalApiClient: public RsTickingThread{
public: public:
// zero setup: create an instance of this class and destroy it when not needed anymore // zero setup: create an instance of this class and destroy it when not needed anymore
// no need to call start or stop or something // no need to call start or stop or something
@ -19,9 +19,24 @@ protected:
// from RsThread // from RsThread
virtual void data_tick(); /* called once the thread is started. Should be overloaded by subclasses. */ virtual void data_tick(); /* called once the thread is started. Should be overloaded by subclasses. */
private: private:
void waitForResponse(ApiServer::RequestId id); struct AccountInfo
{
std::string name ;
std::string location ;
RsPeerId ssl_id ;
};
void waitForResponse(ApiServer::RequestId id) const;
bool isTokenValid(StateToken st); bool isTokenValid(StateToken st);
ApiServer* mApiServer; ApiServer* mApiServer;
// Methods to talk to the ApiServer
void sendPassword(const std::string& passwd) const;
void sendSelectedAccount(const std::string& ssl_id) const;
void readAvailableAccounts(std::vector<AccountInfo>& accounts) const;
void getRunningState() const ;
}; };
} // namespace resource_api } // namespace resource_api

View File

@ -100,9 +100,25 @@ int main(int argc, char **argv)
} }
resource_api::TerminalApiClient tac(&api); resource_api::TerminalApiClient tac(&api);
tac.start();
while(ctrl_mod.processShouldExit() == false) while(ctrl_mod.processShouldExit() == false)
{ {
usleep(20*1000); usleep(200*1000);
if(!tac.isRunning())
{
if(!RsInit::isLocationRunning())
{
std::cerr << "Terminal API client stopped but location not set ! Relaunching." ;
tac.start();
}
else if(RsInit::isLocationRunning())
{
std::cerr << "Terminal API client running but location already set ! Stopping it." ;
tac.shutdown();
}
}
} }
if(httpd) if(httpd)