fixed start/stop of jsonapi in GUI

This commit is contained in:
csoler 2019-11-16 14:30:36 +01:00
parent a304ec20ef
commit 6878a7773d
No known key found for this signature in database
GPG key ID: 7BCA522266C0804C
6 changed files with 89 additions and 71 deletions

View file

@ -117,6 +117,39 @@ JsonApiServer::corsOptionsHeaders =
return false; return false;
} }
static bool is_alphanumeric(char c) { return (c>='0' && c<'9') || (c>='a' && c<='z') || (c>='A' && c<='Z') ;}
static bool is_alphanumeric(const std::string& s)
{
for(uint32_t i=0;i<s.size();++i)
if(!is_alphanumeric(s[i]))
return false;
return true;
}
bool RsJsonAPI::parseToken(const std::string& clear_token,std::string& user,std::string& passwd)
{
uint32_t last_index=0;
uint32_t nb_colons=0;
for(uint32_t i=0;i<clear_token.length();++i)
if(clear_token[i]==':')
{
++nb_colons;
last_index = i;
}
else if(!is_alphanumeric(clear_token[i]))
return false;
if(nb_colons != 1)
return false;
user = clear_token.substr(0,last_index);
passwd = clear_token.substr(last_index+1,(int)clear_token.size()-(int)last_index-2);
return true;
}
JsonApiServer::JsonApiServer(): configMutex("JsonApiServer config") JsonApiServer::JsonApiServer(): configMutex("JsonApiServer config")
{ {
registerHandler("/rsLoginHelper/createLocation", registerHandler("/rsLoginHelper/createLocation",
@ -436,38 +469,6 @@ bool JsonApiServer::requestNewTokenAutorization(const std::string& user)
return false; return false;
} }
static bool is_alphanumeric(char c) { return (c>='0' && c<'9') || (c>='a' && c<='z') || (c>='A' && c<='Z') ;}
static bool is_alphanumeric(const std::string& s)
{
for(uint32_t i=0;i<s.size();++i)
if(!is_alphanumeric(s[i]))
return false;
return true;
}
static bool parseToken(const std::string& clear_token,std::string& user,std::string& passwd)
{
uint32_t last_index=0;
uint32_t nb_colons=0;
for(uint32_t i=0;i<clear_token.length();++i)
if(clear_token[i]==':')
{
++nb_colons;
last_index = i;
}
else if(!is_alphanumeric(clear_token[i]))
return false;
if(nb_colons != 1)
return false;
user = clear_token.substr(0,last_index);
passwd = clear_token.substr(last_index+1,(int)clear_token.size()-(int)last_index-2);
return true;
}
bool JsonApiServer::isAuthTokenValid(const std::string& token) bool JsonApiServer::isAuthTokenValid(const std::string& token)
{ {

View file

@ -64,7 +64,7 @@ public:
bool isAuthTokenValid(const std::string& token) override; bool isAuthTokenValid(const std::string& token) override;
bool requestNewTokenAutorization(const std::string& user) override; bool requestNewTokenAutorization(const std::string& user) override;
// private API // private API. These methods may be moved to RsJsonAPI so as to be visible in http mode, if needed.
/** /**
* @brief Get decoded version of the given encoded token * @brief Get decoded version of the given encoded token

View file

@ -58,7 +58,7 @@ public:
try try
{ {
std::cerr << "(II) Starting web service on port " << std::dec << _listening_port << std::endl; std::cerr << "(II) Starting restbed service on port " << std::dec << _listening_port << std::endl;
_service->start( settings ); _service->start( settings );
} }
catch(std::exception& e) catch(std::exception& e)
@ -67,7 +67,7 @@ public:
return; return;
} }
std::cerr << "(II) webui service stopped." << std::endl; std::cerr << "(II) restbed service stopped." << std::endl;
} }
void stop() void stop()
{ {
@ -77,7 +77,7 @@ public:
while(isRunning()) while(isRunning())
{ {
std::cerr << "(II) shutting down webui service." << std::endl; std::cerr << "(II) shutting down restbed service." << std::endl;
rstime::rs_usleep(1000*1000); rstime::rs_usleep(1000*1000);
} }
} }
@ -112,7 +112,7 @@ RestbedService::~RestbedService()
bool RestbedService::restart() bool RestbedService::restart()
{ {
RsDbg() << "Restarting web interface listening on port " << _restbed_thread->listeningPort() << std::endl; RsDbg() << "Restarting restbed service listening on port " << _restbed_thread->listeningPort() << std::endl;
if(_restbed_thread->isRunning()) if(_restbed_thread->isRunning())
_restbed_thread->stop(); _restbed_thread->stop();

View file

@ -20,6 +20,8 @@
*******************************************************************************/ *******************************************************************************/
#pragma once #pragma once
#include <string>
class RsJsonAPI class RsJsonAPI
{ {
public: public:
@ -59,6 +61,12 @@ public:
*/ */
virtual bool requestNewTokenAutorization(const std::string& token)=0; virtual bool requestNewTokenAutorization(const std::string& token)=0;
//=============================================================================================//
// Utility methods //
//=============================================================================================//
static bool parseToken(const std::string& clear_token,std::string& user,std::string& passwd);
//=============================================================================================// //=============================================================================================//
// API methods that SHOULD NOT be accessible through http // // API methods that SHOULD NOT be accessible through http //
//=============================================================================================// //=============================================================================================//
@ -91,7 +99,7 @@ public:
* @param[in] token decoded * @param[in] token decoded
* @return tru if authorized, false otherwise * @return tru if authorized, false otherwise
*/ */
virtual bool isAuthTokenValid(const std::string& token); virtual bool isAuthTokenValid(const std::string& token)=0;
}; };

View file

@ -37,6 +37,26 @@ JsonApiPage::JsonApiPage(QWidget */*parent*/, Qt::WindowFlags /*flags*/)
connect( ui.removeTokenPushButton, SIGNAL(clicked()), this, SLOT(removeTokenClicked() )); connect( ui.removeTokenPushButton, SIGNAL(clicked()), this, SLOT(removeTokenClicked() ));
connect( ui.tokensListView, SIGNAL(clicked()), this, SLOT(tokenClicked() )); connect( ui.tokensListView, SIGNAL(clicked()), this, SLOT(tokenClicked() ));
connect( ui.applyConfigPushButton, SIGNAL(clicked()), this, SLOT(onApplyClicked() )); connect( ui.applyConfigPushButton, SIGNAL(clicked()), this, SLOT(onApplyClicked() ));
connect( ui.portSpinBox, SIGNAL(valueChanged(int)), this, SLOT(updateParams() ));
connect( ui.listenAddressLineEdit, SIGNAL(textChanged(QString)), this, SLOT(updateParams() ));
// This limits the possible tokens to alphanumeric
QString anRange = "{[a-z]|[A-Z]|[0-9]}+";
QRegExp anRegex ("^" + anRange + ":" + anRange + "$");
QRegExpValidator *anValidator = new QRegExpValidator(anRegex, this);
ui.tokenLineEdit->setValidator(anValidator);
// This limits the possible tokens to alphanumeric
QString ipRange = "(?:[0-1]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])";
// You may want to use QRegularExpression for new code with Qt 5 (not mandatory).
QRegExp ipRegex ("^" + ipRange + "\\." + ipRange + "\\." + ipRange + "\\." + ipRange + "$");
QRegExpValidator *ipValidator = new QRegExpValidator(ipRegex, this);
ui.listenAddressLineEdit->setValidator(ipValidator);
} }
void JsonApiPage::enableJsonApi(bool checked) void JsonApiPage::enableJsonApi(bool checked)
@ -45,6 +65,8 @@ void JsonApiPage::enableJsonApi(bool checked)
ui.applyConfigPushButton->setEnabled(checked); ui.applyConfigPushButton->setEnabled(checked);
ui.removeTokenPushButton->setEnabled(checked); ui.removeTokenPushButton->setEnabled(checked);
ui.tokensListView->setEnabled(checked); ui.tokensListView->setEnabled(checked);
ui.portSpinBox->setEnabled(checked);
ui.listenAddressLineEdit->setEnabled(checked);
Settings->setJsonApiEnabled(checked); Settings->setJsonApiEnabled(checked);
@ -54,43 +76,26 @@ void JsonApiPage::enableJsonApi(bool checked)
checkShutdownJsonApi(); checkShutdownJsonApi();
} }
bool JsonApiPage::updateParams(QString &errmsg) bool JsonApiPage::updateParams()
{ {
bool ok = true; bool ok = true;
bool changed = false; bool changed = false;
bool enabled = ui.enableCheckBox->isChecked();
if( enabled != Settings->getJsonApiEnabled())
{
Settings->setJsonApiEnabled(enabled);
changed = true;
}
uint16_t port = static_cast<uint16_t>(ui.portSpinBox->value()); uint16_t port = static_cast<uint16_t>(ui.portSpinBox->value());
if(port != Settings->getJsonApiPort())
{
Settings->setJsonApiPort(port);
changed = true;
}
QString listenAddress = ui.listenAddressLineEdit->text(); QString listenAddress = ui.listenAddressLineEdit->text();
if(listenAddress != Settings->getJsonApiListenAddress()) Settings->setJsonApiEnabled(ui.enableCheckBox->isChecked());
{ Settings->setJsonApiPort(port);
Settings->setJsonApiListenAddress(listenAddress); Settings->setJsonApiListenAddress(listenAddress);
changed = true;
}
return ok; return ok;
} }
void JsonApiPage::load() void JsonApiPage::load()
{ {
whileBlocking(ui.enableCheckBox)->setChecked(Settings->getJsonApiEnabled());
whileBlocking(ui.portSpinBox)->setValue(Settings->getJsonApiPort()); whileBlocking(ui.portSpinBox)->setValue(Settings->getJsonApiPort());
whileBlocking(ui.listenAddressLineEdit)->setText(Settings->getJsonApiListenAddress()); whileBlocking(ui.listenAddressLineEdit)->setText(Settings->getJsonApiListenAddress());
whileBlocking(ui.enableCheckBox)->setChecked(Settings->getJsonApiEnabled());
QStringList newTk; QStringList newTk;
@ -102,17 +107,21 @@ void JsonApiPage::load()
QString JsonApiPage::helpText() const { return ""; } QString JsonApiPage::helpText() const { return ""; }
/*static*/ bool JsonApiPage::checkStartJsonApi() bool JsonApiPage::checkStartJsonApi()
{ {
if(Settings->getJsonApiEnabled()) if(!Settings->getJsonApiEnabled())
rsJsonAPI->restart(); return false;
rsJsonAPI->setListeningPort(Settings->getJsonApiPort());
rsJsonAPI->setBindingAddress(Settings->getJsonApiListenAddress().toStdString());
rsJsonAPI->restart();
return true; return true;
} }
/*static*/ void JsonApiPage::checkShutdownJsonApi() /*static*/ void JsonApiPage::checkShutdownJsonApi()
{ {
rsJsonAPI->isRunning()) if(RsJsonAPI::JSONAPI_STATUS_RUNNING != rsJsonAPI->status())
return; return;
rsJsonAPI->stop(); // this is a blocking call until the thread is terminated. rsJsonAPI->stop(); // this is a blocking call until the thread is terminated.
@ -148,17 +157,18 @@ void JsonApiPage::onApplyClicked(bool)
// restart // restart
checkShutdownJsonApi(); checkShutdownJsonApi();
rsJsonAPI->setListeningPort(ui.portSpinBox->value());
rsJsonAPI->setBindingAddress(ui.listenAddressLineEdit->text().toStdString());
checkStartJsonApi(); checkStartJsonApi();
} }
void JsonApiPage::addTokenClicked(bool) void JsonApiPage::addTokenClicked(bool)
{ {
QString token(ui.tokenLineEdit->text()); QString token(ui.tokenLineEdit->text());
rsJsonAPI->authorizeUser(token.toStdString()); std::string user,passwd;
if(!RsJsonAPI::parseToken(token.toStdString(),user,passwd))
return;
rsJsonAPI->authorizeUser(user,passwd);
QStringList newTk; QStringList newTk;

View file

@ -54,9 +54,8 @@ public slots:
void removeTokenClicked(bool); void removeTokenClicked(bool);
void tokenClicked(const QModelIndex& index); void tokenClicked(const QModelIndex& index);
void enableJsonApi(bool checked); void enableJsonApi(bool checked);
bool updateParams();
private: private:
Ui::JsonApiPage ui; /// Qt Designer generated object Ui::JsonApiPage ui; /// Qt Designer generated object
bool updateParams(QString &errmsg);
}; };