Merge PR #642: Add tunnel proxy remote connection
This commit is contained in:
commit
98a51afc6d
@ -49,17 +49,27 @@ NymeaConfiguration::NymeaConfiguration(JsonRpcClient *client, QObject *parent):
|
||||
m_tcpServerConfigurations(new ServerConfigurations(this)),
|
||||
m_webSocketServerConfigurations(new ServerConfigurations(this)),
|
||||
m_webServerConfigurations(new WebServerConfigurations(this)),
|
||||
m_tunnelProxyServerConfigurations(new TunnelProxyServerConfigurations(this)),
|
||||
m_mqttServerConfigurations(new ServerConfigurations(this)),
|
||||
m_mqttPolicies(new MqttPolicies(this))
|
||||
{
|
||||
client->registerNotificationHandler(this, "Configuration", "notificationReceived");
|
||||
}
|
||||
|
||||
bool NymeaConfiguration::fetchingData() const
|
||||
{
|
||||
return m_fetchingData;
|
||||
}
|
||||
|
||||
void NymeaConfiguration::init()
|
||||
{
|
||||
m_fetchingData = true;
|
||||
emit fetchingDataChanged();
|
||||
|
||||
m_tcpServerConfigurations->clear();
|
||||
m_webSocketServerConfigurations->clear();
|
||||
m_mqttServerConfigurations->clear();
|
||||
m_tunnelProxyServerConfigurations->clear();
|
||||
m_client->sendCommand("Configuration.GetConfigurations", this, "getConfigurationsResponse");
|
||||
m_client->sendCommand("Configuration.GetMqttServerConfigurations", this, "getMqttServerConfigsReply");
|
||||
m_client->sendCommand("Configuration.GetMqttPolicies", this, "getMqttPoliciesReply");
|
||||
@ -123,6 +133,11 @@ WebServerConfigurations *NymeaConfiguration::webServerConfigurations() const
|
||||
return m_webServerConfigurations;
|
||||
}
|
||||
|
||||
TunnelProxyServerConfigurations *NymeaConfiguration::tunnelProxyServerConfigurations() const
|
||||
{
|
||||
return m_tunnelProxyServerConfigurations;
|
||||
}
|
||||
|
||||
ServerConfigurations *NymeaConfiguration::mqttServerConfigurations() const
|
||||
{
|
||||
return m_mqttServerConfigurations;
|
||||
@ -135,16 +150,21 @@ MqttPolicies *NymeaConfiguration::mqttPolicies() const
|
||||
|
||||
ServerConfiguration *NymeaConfiguration::createServerConfiguration(const QString &address, int port, bool authEnabled, bool sslEnabled)
|
||||
{
|
||||
return new ServerConfiguration(QUuid::createUuid().toString(), QHostAddress(address), port, authEnabled, sslEnabled);
|
||||
return new ServerConfiguration(QUuid::createUuid().toString(), address, port, authEnabled, sslEnabled);
|
||||
}
|
||||
|
||||
WebServerConfiguration *NymeaConfiguration::createWebServerConfiguration(const QString &address, int port, bool authEnabled, bool sslEnabled, const QString &publicFolder)
|
||||
{
|
||||
auto ret = new WebServerConfiguration(QUuid::createUuid().toString(), QHostAddress(address), port, authEnabled, sslEnabled);
|
||||
auto ret = new WebServerConfiguration(QUuid::createUuid().toString(), address, port, authEnabled, sslEnabled);
|
||||
ret->setPublicFolder(publicFolder);
|
||||
return ret;
|
||||
}
|
||||
|
||||
TunnelProxyServerConfiguration *NymeaConfiguration::createTunnelProxyServerConfiguration(const QString &address, int port, bool authEnabled, bool sslEnabled, bool ignoreSslErrors)
|
||||
{
|
||||
return new TunnelProxyServerConfiguration(QUuid::createUuid().toString(), address, port, authEnabled, sslEnabled, ignoreSslErrors);
|
||||
}
|
||||
|
||||
MqttPolicy *NymeaConfiguration::createMqttPolicy() const
|
||||
{
|
||||
return new MqttPolicy(QString(), QString(), QString(), {"#"}, {"#"});
|
||||
@ -190,6 +210,20 @@ void NymeaConfiguration::setWebServerConfiguration(WebServerConfiguration *confi
|
||||
m_client->sendCommand("Configuration.SetWebServerConfiguration", params, this, "setWebConfigReply");
|
||||
}
|
||||
|
||||
void NymeaConfiguration::setTunnelProxyServerConfiguration(TunnelProxyServerConfiguration *configuration)
|
||||
{
|
||||
QVariantMap params;
|
||||
QVariantMap configurationMap;
|
||||
configurationMap.insert("id", configuration->id());
|
||||
configurationMap.insert("address", configuration->address());
|
||||
configurationMap.insert("port", configuration->port());
|
||||
configurationMap.insert("authenticationEnabled", configuration->authenticationEnabled());
|
||||
configurationMap.insert("sslEnabled", configuration->sslEnabled());
|
||||
configurationMap.insert("ignoreSslErrors", configuration->ignoreSslErrors());
|
||||
params.insert("configuration", configurationMap);
|
||||
m_client->sendCommand("Configuration.SetTunnelProxyServerConfiguration", params, this, "setTunnelProxyServerConfigReply");
|
||||
}
|
||||
|
||||
void NymeaConfiguration::setMqttServerConfiguration(ServerConfiguration *configuration)
|
||||
{
|
||||
QVariantMap params;
|
||||
@ -224,6 +258,13 @@ void NymeaConfiguration::deleteWebServerConfiguration(const QString &id)
|
||||
m_client->sendCommand("Configuration.DeleteWebServerConfiguration", params, this, "deleteWebConfigReply");
|
||||
}
|
||||
|
||||
void NymeaConfiguration::deleteTunnelProxyServerConfiguration(const QString &id)
|
||||
{
|
||||
QVariantMap params;
|
||||
params.insert("id", id);
|
||||
m_client->sendCommand("Configuration.DeleteTunnelProxyServerConfiguration", params, this, "deleteTunnelProxyServerConfigReply");
|
||||
}
|
||||
|
||||
void NymeaConfiguration::deleteMqttServerConfiguration(const QString &id)
|
||||
{
|
||||
QVariantMap params;
|
||||
@ -268,23 +309,32 @@ void NymeaConfiguration::getConfigurationsResponse(int commandId, const QVariant
|
||||
foreach (const QVariant &tcpServerVariant, params.value("tcpServerConfigurations").toList()) {
|
||||
// qDebug() << "tcp server config:" << tcpServerVariant;
|
||||
QVariantMap tcpConfigMap = tcpServerVariant.toMap();
|
||||
ServerConfiguration *config = new ServerConfiguration(tcpConfigMap.value("id").toString(), QHostAddress(tcpConfigMap.value("address").toString()), tcpConfigMap.value("port").toInt(), tcpConfigMap.value("authenticationEnabled").toBool(), tcpConfigMap.value("sslEnabled").toBool());
|
||||
ServerConfiguration *config = new ServerConfiguration(tcpConfigMap.value("id").toString(), tcpConfigMap.value("address").toString(), tcpConfigMap.value("port").toInt(), tcpConfigMap.value("authenticationEnabled").toBool(), tcpConfigMap.value("sslEnabled").toBool());
|
||||
m_tcpServerConfigurations->addConfiguration(config);
|
||||
}
|
||||
webSocketServerConfigurations()->clear();
|
||||
foreach (const QVariant &websocketServerVariant, params.value("webSocketServerConfigurations").toList()) {
|
||||
QVariantMap websocketConfigMap = websocketServerVariant.toMap();
|
||||
ServerConfiguration *config = new ServerConfiguration(websocketConfigMap.value("id").toString(), QHostAddress(websocketConfigMap.value("address").toString()), websocketConfigMap.value("port").toInt(), websocketConfigMap.value("authenticationEnabled").toBool(), websocketConfigMap.value("sslEnabled").toBool());
|
||||
ServerConfiguration *config = new ServerConfiguration(websocketConfigMap.value("id").toString(), websocketConfigMap.value("address").toString(), websocketConfigMap.value("port").toInt(), websocketConfigMap.value("authenticationEnabled").toBool(), websocketConfigMap.value("sslEnabled").toBool());
|
||||
m_webSocketServerConfigurations->addConfiguration(config);
|
||||
}
|
||||
|
||||
webServerConfigurations()->clear();
|
||||
foreach (const QVariant &webServerVariant, params.value("webServerConfigurations").toList()) {
|
||||
QVariantMap webServerConfigMap = webServerVariant.toMap();
|
||||
WebServerConfiguration* config = new WebServerConfiguration(webServerConfigMap.value("id").toString(), QHostAddress(webServerConfigMap.value("address").toString()), webServerConfigMap.value("port").toInt(), webServerConfigMap.value("authenticationEnabled").toBool(), webServerConfigMap.value("sslEnabled").toBool());
|
||||
WebServerConfiguration* config = new WebServerConfiguration(webServerConfigMap.value("id").toString(), webServerConfigMap.value("address").toString(), webServerConfigMap.value("port").toInt(), webServerConfigMap.value("authenticationEnabled").toBool(), webServerConfigMap.value("sslEnabled").toBool());
|
||||
config->setPublicFolder(webServerConfigMap.value("publicFolder").toString());
|
||||
m_webServerConfigurations->addConfiguration(config);
|
||||
}
|
||||
|
||||
foreach (const QVariant &tunnelProxyServerVariant, params.value("tunnelProxyServerConfigurations").toList()) {
|
||||
QVariantMap tunnelProxyServerConfigMap = tunnelProxyServerVariant.toMap();
|
||||
TunnelProxyServerConfiguration *config = new TunnelProxyServerConfiguration(tunnelProxyServerConfigMap.value("id").toString(), tunnelProxyServerConfigMap.value("address").toString(), tunnelProxyServerConfigMap.value("port").toInt(), tunnelProxyServerConfigMap.value("authenticationEnabled").toBool(), tunnelProxyServerConfigMap.value("sslEnabled").toBool(), tunnelProxyServerConfigMap.value("ignoreSslErrors").toBool());
|
||||
m_tunnelProxyServerConfigurations->addConfiguration(config);
|
||||
}
|
||||
|
||||
m_fetchingData = false;
|
||||
emit fetchingDataChanged();
|
||||
}
|
||||
|
||||
void NymeaConfiguration::setServerNameResponse(int commandId, const QVariantMap ¶ms)
|
||||
@ -342,13 +392,23 @@ void NymeaConfiguration::deleteWebSocketConfigReply(int commandId, const QVarian
|
||||
qDebug() << "Delete web socket server config reply" << commandId << params;
|
||||
}
|
||||
|
||||
void NymeaConfiguration::setTunnelProxyServerConfigReply(int commandId, const QVariantMap ¶ms)
|
||||
{
|
||||
qDebug() << "Set tunnel proxy server config reply" << commandId << params;
|
||||
}
|
||||
|
||||
void NymeaConfiguration::deleteTunnelProxyServerConfigReply(int commandId, const QVariantMap ¶ms)
|
||||
{
|
||||
qDebug() << "Delete tunnel proxy server config reply" << commandId << params;
|
||||
}
|
||||
|
||||
void NymeaConfiguration::getMqttServerConfigsReply(int commandId, const QVariantMap ¶ms)
|
||||
{
|
||||
Q_UNUSED(commandId)
|
||||
m_mqttServerConfigurations->clear();
|
||||
foreach (const QVariant &mqttServerVariant, params.value("mqttServerConfigurations").toList()) {
|
||||
QVariantMap mqttConfigMap = mqttServerVariant.toMap();
|
||||
ServerConfiguration *config = new ServerConfiguration(mqttConfigMap.value("id").toString(), QHostAddress(mqttConfigMap.value("address").toString()), mqttConfigMap.value("port").toInt(), mqttConfigMap.value("authenticationEnabled").toBool(), mqttConfigMap.value("sslEnabled").toBool());
|
||||
ServerConfiguration *config = new ServerConfiguration(mqttConfigMap.value("id").toString(), mqttConfigMap.value("address").toString(), mqttConfigMap.value("port").toInt(), mqttConfigMap.value("authenticationEnabled").toBool(), mqttConfigMap.value("sslEnabled").toBool());
|
||||
m_mqttServerConfigurations->addConfiguration(config);
|
||||
}
|
||||
}
|
||||
@ -393,6 +453,7 @@ void NymeaConfiguration::deleteMqttPolicyReply(int commandId, const QVariantMap
|
||||
void NymeaConfiguration::notificationReceived(const QVariantMap ¬ification)
|
||||
{
|
||||
QString notif = notification.value("notification").toString();
|
||||
qWarning() << "Config notification received" << notif;
|
||||
if (notif == "Configuration.BasicConfigurationChanged") {
|
||||
QVariantMap params = notification.value("params").toMap().value("basicConfiguration").toMap();
|
||||
m_debugServerEnabled = params.value("debugServerEnabled").toBool();
|
||||
@ -422,6 +483,10 @@ void NymeaConfiguration::notificationReceived(const QVariantMap ¬ification)
|
||||
configModel = m_webSocketServerConfigurations;
|
||||
params = notification.value("params").toMap().value("webSocketServerConfiguration").toMap();
|
||||
}
|
||||
if (notif == "Configuration.TunnelProxyServerConfigurationChanged") {
|
||||
configModel = m_tunnelProxyServerConfigurations;
|
||||
params = notification.value("params").toMap().value("tunnelProxyServerConfiguration").toMap();
|
||||
}
|
||||
if (notif == "Configuration.WebServerConfigurationChanged") {
|
||||
configModel = m_webServerConfigurations;
|
||||
params = notification.value("params").toMap().value("webServerConfiguration").toMap();
|
||||
@ -444,6 +509,8 @@ void NymeaConfiguration::notificationReceived(const QVariantMap ¬ification)
|
||||
if (!serverConfig) {
|
||||
if (notif == "Configuration.WebServerConfigurationChanged") {
|
||||
serverConfig = new WebServerConfiguration(params.value("id").toString());
|
||||
} else if (notif == "Configuration.TunnelProxyServerConfigurationChanged") {
|
||||
serverConfig = new TunnelProxyServerConfiguration(params.value("id").toString());
|
||||
} else {
|
||||
serverConfig = new ServerConfiguration(params.value("id").toString());
|
||||
}
|
||||
@ -467,6 +534,10 @@ void NymeaConfiguration::notificationReceived(const QVariantMap ¬ification)
|
||||
m_webSocketServerConfigurations->removeConfiguration(notification.value("params").toMap().value("id").toString());
|
||||
return;
|
||||
}
|
||||
if (notif == "Configuration.TunnelProxyServerConfigurationRemoved") {
|
||||
m_tunnelProxyServerConfigurations->removeConfiguration(notification.value("params").toMap().value("id").toString());
|
||||
return;
|
||||
}
|
||||
if (notif == "Configuration.WebServerConfigurationRemoved") {
|
||||
m_webServerConfigurations->removeConfiguration(notification.value("params").toMap().value("id").toString());
|
||||
return;
|
||||
|
||||
@ -38,6 +38,8 @@ class ServerConfiguration;
|
||||
class ServerConfigurations;
|
||||
class WebServerConfiguration;
|
||||
class WebServerConfigurations;
|
||||
class TunnelProxyServerConfiguration;
|
||||
class TunnelProxyServerConfigurations;
|
||||
class MqttPolicy;
|
||||
class MqttPolicies;
|
||||
|
||||
@ -45,6 +47,8 @@ class NymeaConfiguration : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(bool fetchingData READ fetchingData NOTIFY fetchingDataChanged)
|
||||
|
||||
Q_PROPERTY(QString serverName READ serverName WRITE setServerName NOTIFY serverNameChanged)
|
||||
|
||||
Q_PROPERTY(bool cloudEnabled READ cloudEnabled WRITE setCloudEnabled NOTIFY cloudEnabledChanged)
|
||||
@ -53,6 +57,7 @@ class NymeaConfiguration : public QObject
|
||||
Q_PROPERTY(ServerConfigurations* tcpServerConfigurations READ tcpServerConfigurations CONSTANT)
|
||||
Q_PROPERTY(ServerConfigurations* webSocketServerConfigurations READ webSocketServerConfigurations CONSTANT)
|
||||
Q_PROPERTY(WebServerConfigurations* webServerConfigurations READ webServerConfigurations CONSTANT)
|
||||
Q_PROPERTY(TunnelProxyServerConfigurations* tunnelProxyServerConfigurations READ tunnelProxyServerConfigurations CONSTANT)
|
||||
Q_PROPERTY(ServerConfigurations* mqttServerConfigurations READ mqttServerConfigurations CONSTANT)
|
||||
|
||||
Q_PROPERTY(MqttPolicies* mqttPolicies READ mqttPolicies CONSTANT)
|
||||
@ -60,6 +65,8 @@ class NymeaConfiguration : public QObject
|
||||
public:
|
||||
explicit NymeaConfiguration(JsonRpcClient* client, QObject *parent = nullptr);
|
||||
|
||||
bool fetchingData() const;
|
||||
|
||||
QString serverName() const;
|
||||
void setServerName(const QString &serverName);
|
||||
|
||||
@ -80,21 +87,25 @@ public:
|
||||
ServerConfigurations *tcpServerConfigurations() const;
|
||||
ServerConfigurations *webSocketServerConfigurations() const;
|
||||
WebServerConfigurations *webServerConfigurations() const;
|
||||
TunnelProxyServerConfigurations *tunnelProxyServerConfigurations() const;
|
||||
ServerConfigurations *mqttServerConfigurations() const;
|
||||
MqttPolicies *mqttPolicies() const;
|
||||
|
||||
Q_INVOKABLE ServerConfiguration* createServerConfiguration(const QString &address = "0.0.0.0", int port = 0, bool authEnabled = false, bool sslEnabled = false);
|
||||
Q_INVOKABLE WebServerConfiguration* createWebServerConfiguration(const QString &address = "0.0.0.0", int port = 0, bool authEnabled = false, bool sslEnabled = false, const QString &publicFolder = QString());
|
||||
Q_INVOKABLE TunnelProxyServerConfiguration* createTunnelProxyServerConfiguration(const QString &address, int port, bool authEnabled = true, bool sslEnabled = true, bool ignoreSslErrors = false);
|
||||
Q_INVOKABLE MqttPolicy* createMqttPolicy() const;
|
||||
|
||||
Q_INVOKABLE void setTcpServerConfiguration(ServerConfiguration *configuration);
|
||||
Q_INVOKABLE void setWebSocketServerConfiguration(ServerConfiguration *configuration);
|
||||
Q_INVOKABLE void setWebServerConfiguration(WebServerConfiguration *configuration);
|
||||
Q_INVOKABLE void setTunnelProxyServerConfiguration(TunnelProxyServerConfiguration *configuration);
|
||||
Q_INVOKABLE void setMqttServerConfiguration(ServerConfiguration *configuration);
|
||||
|
||||
Q_INVOKABLE void deleteTcpServerConfiguration(const QString &id);
|
||||
Q_INVOKABLE void deleteWebSocketServerConfiguration(const QString &id);
|
||||
Q_INVOKABLE void deleteWebServerConfiguration(const QString &id);
|
||||
Q_INVOKABLE void deleteTunnelProxyServerConfiguration(const QString &id);
|
||||
Q_INVOKABLE void deleteMqttServerConfiguration(const QString &id);
|
||||
|
||||
Q_INVOKABLE void updateMqttPolicy(MqttPolicy* policy);
|
||||
@ -112,6 +123,8 @@ private:
|
||||
Q_INVOKABLE void deleteTcpConfigReply(int commandId, const QVariantMap ¶ms);
|
||||
Q_INVOKABLE void setWebSocketConfigReply(int commandId, const QVariantMap ¶ms);
|
||||
Q_INVOKABLE void deleteWebSocketConfigReply(int commandId, const QVariantMap ¶ms);
|
||||
Q_INVOKABLE void setTunnelProxyServerConfigReply(int commandId, const QVariantMap ¶ms);
|
||||
Q_INVOKABLE void deleteTunnelProxyServerConfigReply(int commandId, const QVariantMap ¶ms);
|
||||
Q_INVOKABLE void setWebConfigReply(int commandId, const QVariantMap ¶ms);
|
||||
Q_INVOKABLE void deleteWebConfigReply(int commandId, const QVariantMap ¶ms);
|
||||
Q_INVOKABLE void getMqttServerConfigsReply(int commandId, const QVariantMap ¶ms);
|
||||
@ -124,6 +137,7 @@ private:
|
||||
Q_INVOKABLE void notificationReceived(const QVariantMap ¬ification);
|
||||
|
||||
signals:
|
||||
void fetchingDataChanged();
|
||||
void debugServerEnabledChanged();
|
||||
void serverNameChanged();
|
||||
void cloudEnabledChanged();
|
||||
@ -131,6 +145,7 @@ signals:
|
||||
private:
|
||||
JsonRpcClient* m_client = nullptr;
|
||||
|
||||
bool m_fetchingData = false;
|
||||
bool m_debugServerEnabled = false;
|
||||
QString m_serverName;
|
||||
bool m_cloudEnabled = false;
|
||||
@ -138,6 +153,7 @@ private:
|
||||
ServerConfigurations *m_tcpServerConfigurations = nullptr;
|
||||
ServerConfigurations *m_webSocketServerConfigurations = nullptr;
|
||||
WebServerConfigurations* m_webServerConfigurations = nullptr;
|
||||
TunnelProxyServerConfigurations *m_tunnelProxyServerConfigurations = nullptr;
|
||||
ServerConfigurations *m_mqttServerConfigurations = nullptr;
|
||||
MqttPolicies *m_mqttPolicies = nullptr;
|
||||
|
||||
|
||||
@ -30,7 +30,7 @@
|
||||
|
||||
#include "serverconfiguration.h"
|
||||
|
||||
ServerConfiguration::ServerConfiguration(const QString &id, const QHostAddress &address, int port, bool authEnabled, bool sslEnabled, QObject *parent):
|
||||
ServerConfiguration::ServerConfiguration(const QString &id, const QString &address, int port, bool authEnabled, bool sslEnabled, QObject *parent):
|
||||
QObject(parent),
|
||||
m_id(id),
|
||||
m_hostAddress(address),
|
||||
@ -48,13 +48,13 @@ QString ServerConfiguration::id() const
|
||||
|
||||
QString ServerConfiguration::address() const
|
||||
{
|
||||
return m_hostAddress.toString();
|
||||
return m_hostAddress;
|
||||
}
|
||||
|
||||
void ServerConfiguration::setAddress(const QString &address)
|
||||
{
|
||||
if (m_hostAddress != QHostAddress(address)) {
|
||||
m_hostAddress = QHostAddress(address);
|
||||
if (m_hostAddress != address) {
|
||||
m_hostAddress = address;
|
||||
emit addressChanged();
|
||||
}
|
||||
}
|
||||
@ -119,7 +119,26 @@ void WebServerConfiguration::setPublicFolder(const QString &publicFolder)
|
||||
|
||||
ServerConfiguration *WebServerConfiguration::clone() const
|
||||
{
|
||||
WebServerConfiguration *ret = new WebServerConfiguration(id(), QHostAddress(address()), port(), authenticationEnabled(), sslEnabled());
|
||||
WebServerConfiguration *ret = new WebServerConfiguration(id(), address(), port(), authenticationEnabled(), sslEnabled());
|
||||
ret->setPublicFolder(m_publicFolder);
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool TunnelProxyServerConfiguration::ignoreSslErrors() const
|
||||
{
|
||||
return m_ignoreSslErrors;
|
||||
}
|
||||
|
||||
void TunnelProxyServerConfiguration::setIgnoreSslErrors(bool ignoreSslErrors)
|
||||
{
|
||||
if (m_ignoreSslErrors != ignoreSslErrors) {
|
||||
m_ignoreSslErrors = ignoreSslErrors;
|
||||
emit ignoreSslErrorsChanged();
|
||||
}
|
||||
}
|
||||
|
||||
ServerConfiguration *TunnelProxyServerConfiguration::clone() const
|
||||
{
|
||||
TunnelProxyServerConfiguration *ret = new TunnelProxyServerConfiguration(id(), address(), port(), authenticationEnabled(), ignoreSslErrors());
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -45,7 +45,7 @@ class ServerConfiguration : public QObject
|
||||
Q_PROPERTY(bool sslEnabled READ sslEnabled WRITE setSslEnabled NOTIFY sslEnabledChanged)
|
||||
|
||||
public:
|
||||
explicit ServerConfiguration(const QString &id, const QHostAddress &address = QHostAddress(), int port = 0, bool authEnabled = false, bool sslEnabled = false, QObject *parent = nullptr);
|
||||
explicit ServerConfiguration(const QString &id, const QString &address = QString(), int port = 0, bool authEnabled = false, bool sslEnabled = false, QObject *parent = nullptr);
|
||||
|
||||
QString id() const;
|
||||
|
||||
@ -71,7 +71,7 @@ signals:
|
||||
|
||||
private:
|
||||
QString m_id;
|
||||
QHostAddress m_hostAddress;
|
||||
QString m_hostAddress;
|
||||
int m_port;
|
||||
bool m_authEnabled;
|
||||
bool m_sslEnabled;
|
||||
@ -82,7 +82,7 @@ class WebServerConfiguration: public ServerConfiguration
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QString publicFolder READ publicFolder WRITE setPublicFolder NOTIFY publicFolderChanged)
|
||||
public:
|
||||
explicit WebServerConfiguration(const QString &id, const QHostAddress &address = QHostAddress(), int port = 0, bool authEnabled = false, bool sslEnabled = false, QObject *parent = nullptr)
|
||||
explicit WebServerConfiguration(const QString &id, const QString &address = QString(), int port = 0, bool authEnabled = false, bool sslEnabled = false, QObject *parent = nullptr)
|
||||
: ServerConfiguration(id, address, port, authEnabled, sslEnabled, parent) {}
|
||||
|
||||
QString publicFolder() const;
|
||||
@ -97,4 +97,25 @@ private:
|
||||
QString m_publicFolder;
|
||||
};
|
||||
|
||||
class TunnelProxyServerConfiguration: public ServerConfiguration
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(bool ignoreSslErrors READ ignoreSslErrors WRITE setIgnoreSslErrors NOTIFY ignoreSslErrorsChanged)
|
||||
public:
|
||||
explicit TunnelProxyServerConfiguration(const QString &id, const QString &address = QString(), int port = 0, bool authenticationEnabled = false, bool sslEnabled = false, bool ignoreSslErrors = false, QObject *parent = nullptr)
|
||||
: ServerConfiguration(id, address, port, authenticationEnabled, sslEnabled, parent),
|
||||
m_ignoreSslErrors(ignoreSslErrors) {}
|
||||
|
||||
bool ignoreSslErrors() const;
|
||||
void setIgnoreSslErrors(bool ignoreSslErrors);
|
||||
|
||||
Q_INVOKABLE ServerConfiguration* clone() const override;
|
||||
|
||||
signals:
|
||||
void ignoreSslErrorsChanged();
|
||||
|
||||
private:
|
||||
bool m_ignoreSslErrors = false;
|
||||
};
|
||||
|
||||
#endif // SERVERCONFIGURATION_H
|
||||
|
||||
@ -84,4 +84,15 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class TunnelProxyServerConfigurations: public ServerConfigurations
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
TunnelProxyServerConfigurations(QObject *parent = nullptr): ServerConfigurations(parent) {}
|
||||
|
||||
Q_INVOKABLE TunnelProxyServerConfiguration* getTunnelProxyServerConfiguration(int index) const {
|
||||
return dynamic_cast<TunnelProxyServerConfiguration*>(m_list.at(index));
|
||||
}
|
||||
};
|
||||
|
||||
#endif // SERVERCONFIGURATIONS_H
|
||||
|
||||
@ -66,7 +66,7 @@ CloudTransport::CloudTransport(AWSClient *awsClient, QObject *parent):
|
||||
QObject::connect(m_remoteproxyConnection, &RemoteProxyConnection::dataReady, this, [this](const QByteArray &data) {
|
||||
emit dataReady(data);
|
||||
});
|
||||
QObject::connect(m_remoteproxyConnection, &RemoteProxyConnection::errorOccured, this, [] (QAbstractSocket::SocketError error) {
|
||||
QObject::connect(m_remoteproxyConnection, &RemoteProxyConnection::errorOccurred, this, [] (QAbstractSocket::SocketError error) {
|
||||
qDebug() << "Remote proxy Error:" << error;
|
||||
// emit NymeaTransportInterface::error(QAbstractSocket::ConnectionRefusedError);
|
||||
});
|
||||
|
||||
@ -101,6 +101,21 @@ bool NymeaHost::online() const
|
||||
return m_online;
|
||||
}
|
||||
|
||||
void NymeaHost::addTunnelConnection()
|
||||
{
|
||||
for (int i = 0; i < m_connections->rowCount(); i++) {
|
||||
if (m_connections->get(i)->url().scheme() == "tunnel") {
|
||||
return;
|
||||
}
|
||||
}
|
||||
QUrl url;
|
||||
url.setScheme("tunnel");
|
||||
url.setHost(m_uuid.toString().remove(QRegExp("[{}]")));
|
||||
qCritical() << "Adding tunnel connection" << url << m_uuid;
|
||||
Connection *connection = new Connection(url, Connection::BearerTypeCloud, true, "foooobaaaar", this);
|
||||
m_connections->addConnection(connection);
|
||||
}
|
||||
|
||||
void NymeaHost::syncOnlineState()
|
||||
{
|
||||
for (int i = 0; i < m_connections->rowCount(); i++) {
|
||||
@ -217,7 +232,7 @@ Connection *Connections::bestMatch(Connection::BearerTypes bearerTypes) const
|
||||
{
|
||||
Connection *best = nullptr;
|
||||
foreach (Connection *c, m_connections) {
|
||||
// qDebug() << "have connection:" << bearerTypes << c->url() << c->bearerType() << bearerTypes.testFlag(c->bearerType());
|
||||
// qWarning() << "have connection:" << bearerTypes << c->url() << c->bearerType() << bearerTypes.testFlag(c->bearerType());
|
||||
if ((bearerTypes & c->bearerType()) == Connection::BearerTypeNone) {
|
||||
continue;
|
||||
}
|
||||
@ -232,6 +247,12 @@ Connection *Connections::bestMatch(Connection::BearerTypes bearerTypes) const
|
||||
return best;
|
||||
}
|
||||
|
||||
void Connections::addConnection(const QUrl &url, Connection::BearerType bearerType, bool secure, const QString &displayName)
|
||||
{
|
||||
Connection *connection = new Connection(url, bearerType, secure, displayName);
|
||||
addConnection(connection);
|
||||
}
|
||||
|
||||
QHash<int, QByteArray> Connections::roleNames() const
|
||||
{
|
||||
QHash<int, QByteArray> roles;
|
||||
@ -250,7 +271,7 @@ Connection::Connection(const QUrl &url, Connection::BearerType bearerType, bool
|
||||
m_secure(secure),
|
||||
m_displayName(displayName)
|
||||
{
|
||||
|
||||
qRegisterMetaType<Connection::BearerType>("Connection.BearerType");
|
||||
}
|
||||
|
||||
Connection::~Connection()
|
||||
@ -320,6 +341,9 @@ int Connection::priority() const
|
||||
break;
|
||||
case BearerTypeCloud:
|
||||
prio += 200;
|
||||
if (m_url.scheme().startsWith("tunnel")) {
|
||||
prio += 1;
|
||||
}
|
||||
break;
|
||||
case BearerTypeBluetooth:
|
||||
prio += 100;
|
||||
|
||||
@ -109,14 +109,16 @@ public:
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const override;
|
||||
|
||||
void addConnection(Connection *connection);
|
||||
void removeConnection(Connection *connection);
|
||||
void removeConnection(int index);
|
||||
|
||||
Q_INVOKABLE Connection* find(const QUrl &url) const;
|
||||
Q_INVOKABLE Connection* get(int index) const;
|
||||
Q_INVOKABLE Connection* bestMatch(Connection::BearerTypes bearerTypes = Connection::BearerTypeAll) const;
|
||||
|
||||
void addConnection(Connection *connection);
|
||||
Q_INVOKABLE void addConnection(const QUrl &url, Connection::BearerType bearerType, bool secure, const QString &displayName);
|
||||
Q_INVOKABLE void removeConnection(Connection *connection);
|
||||
Q_INVOKABLE void removeConnection(int index);
|
||||
|
||||
signals:
|
||||
void countChanged();
|
||||
void connectionAdded(Connection *connection);
|
||||
@ -156,6 +158,8 @@ public:
|
||||
|
||||
bool online() const;
|
||||
|
||||
Q_INVOKABLE void addTunnelConnection();
|
||||
|
||||
signals:
|
||||
void nameChanged();
|
||||
void versionChanged();
|
||||
|
||||
151
libnymea-app/connection/tunnelproxytransport.cpp
Normal file
151
libnymea-app/connection/tunnelproxytransport.cpp
Normal file
@ -0,0 +1,151 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* Copyright 2013 - 2021, nymea GmbH
|
||||
* Contact: contact@nymea.io
|
||||
*
|
||||
* This file is part of nymea.
|
||||
* This project including source code and documentation is protected by
|
||||
* copyright law, and remains the property of nymea GmbH. All rights, including
|
||||
* reproduction, publication, editing and translation, are reserved. The use of
|
||||
* this project is subject to the terms of a license agreement to be concluded
|
||||
* with nymea GmbH in accordance with the terms of use of nymea GmbH, available
|
||||
* under https://nymea.io/license
|
||||
*
|
||||
* GNU General Public License Usage
|
||||
* Alternatively, this project may be redistributed and/or modified under the
|
||||
* terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation, GNU version 3. This project is distributed in the hope that it
|
||||
* will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||
* Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this project. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* For any further details and any questions please contact us under
|
||||
* contact@nymea.io or see our FAQ/Licensing Information on
|
||||
* https://nymea.io/license/faq
|
||||
*
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#include "tunnelproxytransport.h"
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QUrlQuery>
|
||||
|
||||
using namespace remoteproxyclient;
|
||||
|
||||
#include "logging.h"
|
||||
|
||||
// Note: Re-registering the same category as the proxy lib offers, so we can control it in the app
|
||||
// However, as we can't link the same category twice, let's just create a dummy here with the category string matching the lib
|
||||
NYMEA_LOGGING_CATEGORY(dcTunnelProxyRemoteConnectionDummy, "TunnelProxyRemoteConnection")
|
||||
|
||||
TunnelProxyTransport::TunnelProxyTransport(QObject *parent) :
|
||||
NymeaTransportInterface(parent)
|
||||
{
|
||||
m_remoteConnection = new TunnelProxyRemoteConnection(QUuid::createUuid(), qApp->applicationName(), this);
|
||||
QObject::connect(m_remoteConnection, &TunnelProxyRemoteConnection::stateChanged, this, &TunnelProxyTransport::onRemoteConnectionStateChanged);
|
||||
QObject::connect(m_remoteConnection, &TunnelProxyRemoteConnection::dataReady, this, &TunnelProxyTransport::dataReady);
|
||||
QObject::connect(m_remoteConnection, &TunnelProxyRemoteConnection::errorOccurred, this, &TunnelProxyTransport::onRemoteConnectionErrorOccurred);
|
||||
QObject::connect(m_remoteConnection, &TunnelProxyRemoteConnection::sslErrors, this, [=](const QList<QSslError> &errors){
|
||||
qWarning() << "Remote tunnel proxy server SSL errors occurred:";
|
||||
foreach (const QSslError &sslError, errors) {
|
||||
qWarning() << " --> " << sslError.errorString();
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
bool TunnelProxyTransport::connect(const QUrl &url)
|
||||
{
|
||||
m_url = url;
|
||||
|
||||
QUrl serverUrl;
|
||||
serverUrl.setScheme(url.scheme() == "tunnels" ? "ssl" : "tcp");
|
||||
serverUrl.setHost(url.host());
|
||||
serverUrl.setPort(url.port());
|
||||
QUuid serverUuid = QUrlQuery(url).queryItemValue("uuid");
|
||||
|
||||
qCritical() << "Calling connect on" << serverUrl << serverUuid;
|
||||
|
||||
return m_remoteConnection->connectServer(serverUrl, serverUuid);
|
||||
}
|
||||
|
||||
QUrl TunnelProxyTransport::url() const
|
||||
{
|
||||
return m_url;
|
||||
}
|
||||
|
||||
NymeaTransportInterface::ConnectionState TunnelProxyTransport::connectionState() const
|
||||
{
|
||||
switch (m_remoteConnection->state()) {
|
||||
case TunnelProxyRemoteConnection::StateRemoteConnected:
|
||||
return NymeaTransportInterface::ConnectionStateConnected;
|
||||
case TunnelProxyRemoteConnection::StateConnecting:
|
||||
case TunnelProxyRemoteConnection::StateHostLookup:
|
||||
case TunnelProxyRemoteConnection::StateConnected:
|
||||
case TunnelProxyRemoteConnection::StateInitializing:
|
||||
case TunnelProxyRemoteConnection::StateRegister:
|
||||
return NymeaTransportInterface::ConnectionStateConnecting;
|
||||
case TunnelProxyRemoteConnection::StateDiconnecting:
|
||||
case TunnelProxyRemoteConnection::StateDisconnected:
|
||||
return NymeaTransportInterface::ConnectionStateDisconnected;
|
||||
}
|
||||
}
|
||||
|
||||
void TunnelProxyTransport::disconnect()
|
||||
{
|
||||
m_remoteConnection->disconnectServer();
|
||||
}
|
||||
|
||||
void TunnelProxyTransport::sendData(const QByteArray &data)
|
||||
{
|
||||
m_remoteConnection->sendData(data);
|
||||
}
|
||||
|
||||
void TunnelProxyTransport::ignoreSslErrors(const QList<QSslError> &errors)
|
||||
{
|
||||
// FIXME: once the tunnel connection implements SSL connection trought the tunnel proxy, we need to implement this
|
||||
Q_UNUSED(errors)
|
||||
}
|
||||
|
||||
bool TunnelProxyTransport::isEncrypted() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
QSslCertificate TunnelProxyTransport::serverCertificate() const
|
||||
{
|
||||
// FIXME: once the tunnel connection implements SSL connection trought the tunnel proxy, we need to implement this
|
||||
return QSslCertificate();
|
||||
}
|
||||
|
||||
void TunnelProxyTransport::onRemoteConnectionStateChanged(remoteproxyclient::TunnelProxyRemoteConnection::State state)
|
||||
{
|
||||
switch (state) {
|
||||
case remoteproxyclient::TunnelProxyRemoteConnection::StateRemoteConnected:
|
||||
emit connected();
|
||||
break;
|
||||
case remoteproxyclient::TunnelProxyRemoteConnection::StateDisconnected:
|
||||
emit disconnected();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void TunnelProxyTransport::onRemoteConnectionErrorOccurred(QAbstractSocket::SocketError error)
|
||||
{
|
||||
qWarning() << "Tunnel proxy socket error occurred" << error;
|
||||
}
|
||||
|
||||
NymeaTransportInterface *TunnelProxyTransportFactory::createTransport(QObject *parent) const
|
||||
{
|
||||
return new TunnelProxyTransport(parent);
|
||||
}
|
||||
|
||||
QStringList TunnelProxyTransportFactory::supportedSchemes() const
|
||||
{
|
||||
return { "tunnel", "tunnels" };
|
||||
}
|
||||
74
libnymea-app/connection/tunnelproxytransport.h
Normal file
74
libnymea-app/connection/tunnelproxytransport.h
Normal file
@ -0,0 +1,74 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* Copyright 2013 - 2021, nymea GmbH
|
||||
* Contact: contact@nymea.io
|
||||
*
|
||||
* This file is part of nymea.
|
||||
* This project including source code and documentation is protected by
|
||||
* copyright law, and remains the property of nymea GmbH. All rights, including
|
||||
* reproduction, publication, editing and translation, are reserved. The use of
|
||||
* this project is subject to the terms of a license agreement to be concluded
|
||||
* with nymea GmbH in accordance with the terms of use of nymea GmbH, available
|
||||
* under https://nymea.io/license
|
||||
*
|
||||
* GNU General Public License Usage
|
||||
* Alternatively, this project may be redistributed and/or modified under the
|
||||
* terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation, GNU version 3. This project is distributed in the hope that it
|
||||
* will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||
* Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this project. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* For any further details and any questions please contact us under
|
||||
* contact@nymea.io or see our FAQ/Licensing Information on
|
||||
* https://nymea.io/license/faq
|
||||
*
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#ifndef TUNNELPROXYTRANSPORT_H
|
||||
#define TUNNELPROXYTRANSPORT_H
|
||||
|
||||
#include <QUrl>
|
||||
#include <QObject>
|
||||
|
||||
#include "nymeatransportinterface.h"
|
||||
#include "tunnelproxy/tunnelproxyremoteconnection.h"
|
||||
|
||||
class TunnelProxyTransportFactory: public NymeaTransportInterfaceFactory
|
||||
{
|
||||
public:
|
||||
NymeaTransportInterface* createTransport(QObject *parent = nullptr) const override;
|
||||
QStringList supportedSchemes() const override;
|
||||
};
|
||||
|
||||
|
||||
class TunnelProxyTransport : public NymeaTransportInterface
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit TunnelProxyTransport(QObject *parent = nullptr);
|
||||
|
||||
bool connect(const QUrl &url) override;
|
||||
QUrl url() const override;
|
||||
ConnectionState connectionState() const override;
|
||||
void disconnect() override;
|
||||
void sendData(const QByteArray &data) override;
|
||||
void ignoreSslErrors(const QList<QSslError> &errors) override;
|
||||
|
||||
bool isEncrypted() const override;
|
||||
QSslCertificate serverCertificate() const override;
|
||||
|
||||
private slots:
|
||||
void onRemoteConnectionStateChanged(remoteproxyclient::TunnelProxyRemoteConnection::State state);
|
||||
void onRemoteConnectionErrorOccurred(QAbstractSocket::SocketError error);
|
||||
|
||||
private:
|
||||
QUrl m_url;
|
||||
remoteproxyclient::TunnelProxyRemoteConnection *m_remoteConnection = nullptr;
|
||||
|
||||
};
|
||||
|
||||
#endif // TUNNELPROXYTRANSPORT_H
|
||||
@ -37,6 +37,7 @@
|
||||
#include "connection/websockettransport.h"
|
||||
#include "connection/bluetoothtransport.h"
|
||||
#include "connection/cloudtransport.h"
|
||||
#include "connection/tunnelproxytransport.h"
|
||||
|
||||
#include <QJsonDocument>
|
||||
#include <QVariantMap>
|
||||
@ -61,6 +62,7 @@ JsonRpcClient::JsonRpcClient(QObject *parent) :
|
||||
m_connection->registerTransport(new WebsocketTransportFactory());
|
||||
m_connection->registerTransport(new BluetoothTransportFactoy());
|
||||
m_connection->registerTransport(new CloudTransportFactory());
|
||||
m_connection->registerTransport(new TunnelProxyTransportFactory());
|
||||
|
||||
connect(m_connection, &NymeaConnection::availableBearerTypesChanged, this, &JsonRpcClient::availableBearerTypesChanged);
|
||||
connect(m_connection, &NymeaConnection::connectionStatusChanged, this, &JsonRpcClient::connectionStatusChanged);
|
||||
@ -443,6 +445,7 @@ void JsonRpcClient::processAuthenticate(int /*commandId*/, const QVariantMap &da
|
||||
} else {
|
||||
m_permissionScopes = UserInfo::PermissionScopeAdmin;
|
||||
}
|
||||
emit permissionsChanged();
|
||||
QSettings settings;
|
||||
settings.beginGroup("jsonTokens");
|
||||
settings.setValue(m_serverUuid, m_token);
|
||||
@ -643,7 +646,7 @@ void JsonRpcClient::dataReceived(const QByteArray &data)
|
||||
JsonRpcReply *reply = m_replies.take(commandId);
|
||||
if (reply) {
|
||||
reply->deleteLater();
|
||||
qWarning() << QString("JsonRpc: got response for %1.%2: %3").arg(reply->nameSpace(), reply->method(), QString::fromUtf8(jsonDoc.toJson(QJsonDocument::Indented))) << reply->callback() << reply->callback();
|
||||
// qWarning() << QString("JsonRpc: got response for %1.%2: %3").arg(reply->nameSpace(), reply->method(), QString::fromUtf8(jsonDoc.toJson(QJsonDocument::Indented))) << reply->callback() << reply->callback();
|
||||
|
||||
if (dataMap.value("status").toString() == "unauthorized") {
|
||||
qWarning() << "Something's off with the token";
|
||||
@ -718,6 +721,11 @@ void JsonRpcClient::helloReply(int /*commandId*/, const QVariantMap ¶ms)
|
||||
|
||||
qCInfo(dcJsonRpc()) << "Handshake reply:" << "Protocol version:" << protoVersionString << "InitRequired:" << m_initialSetupRequired << "AuthRequired:" << m_authenticationRequired << "PushButtonAvailable:" << m_pushButtonAuthAvailable;
|
||||
|
||||
if (m_connection->currentHost()->uuid().isNull()) {
|
||||
qCDebug(dcJsonRpc()) << "Updating Server UUID in connection:" << m_connection->currentHost()->uuid().toString() << "->" << m_serverUuid;
|
||||
m_connection->currentHost()->setUuid(m_serverUuid);
|
||||
}
|
||||
|
||||
QVersionNumber minimumRequiredVersion = QVersionNumber(5, 0);
|
||||
QVersionNumber maximumMajorVersion = QVersionNumber(6);
|
||||
if (m_jsonRpcVersion < minimumRequiredVersion) {
|
||||
@ -793,11 +801,6 @@ void JsonRpcClient::helloReply(int /*commandId*/, const QVariantMap ¶ms)
|
||||
|
||||
emit handshakeReceived();
|
||||
|
||||
if (m_connection->currentHost()->uuid().isNull()) {
|
||||
qCDebug(dcJsonRpc()) << "Updating Server UUID in connection:" << m_connection->currentHost()->uuid().toString() << "->" << m_serverUuid;
|
||||
m_connection->currentHost()->setUuid(m_serverUuid);
|
||||
}
|
||||
|
||||
if (m_initialSetupRequired) {
|
||||
qCInfo(dcJsonRpc()) << "Initial setup is required for this nymea instance!";
|
||||
emit initialSetupRequiredChanged();
|
||||
|
||||
@ -256,6 +256,8 @@ void registerQmlTypes() {
|
||||
qmlRegisterUncreatableType<ServerConfigurations>(uri, 1, 0, "ServerConfigurations", "Get it from NymeaConfiguration");
|
||||
qmlRegisterUncreatableType<WebServerConfiguration>(uri, 1, 0, "WebServerConfiguration", "Get it from NymeaConfiguration");
|
||||
qmlRegisterUncreatableType<WebServerConfigurations>(uri, 1, 0, "WebServerConfigurations", "Get it from NymeaConfiguration");
|
||||
qmlRegisterUncreatableType<TunnelProxyServerConfiguration>(uri, 1, 0, "TunnelProxyServerConfiguration", "Get it from NymeaConfiguration");
|
||||
qmlRegisterUncreatableType<TunnelProxyServerConfigurations>(uri, 1, 0, "TunnelProxyServerConfigurations", "Get it from NymeaConfiguration");
|
||||
qmlRegisterUncreatableType<MqttPolicy>(uri, 1, 0, "MqttPolicy", "Get it from NymeaConfiguration");
|
||||
qmlRegisterUncreatableType<MqttPolicies>(uri, 1, 0, "MqttPolicies", "Get it from NymeaConfiguration");
|
||||
|
||||
|
||||
@ -25,6 +25,7 @@ SOURCES += \
|
||||
$$PWD/energy/energymanager.cpp \
|
||||
$$PWD/energy/powerbalancelogs.cpp \
|
||||
$$PWD/energy/thingpowerlogs.cpp \
|
||||
$$PWD/connection/tunnelproxytransport.cpp \
|
||||
$$PWD/models/scriptsproxymodel.cpp \
|
||||
$$PWD/tagwatcher.cpp \
|
||||
$$PWD/zigbee/zigbeenode.cpp \
|
||||
@ -185,6 +186,7 @@ HEADERS += \
|
||||
$$PWD/energy/energymanager.h \
|
||||
$$PWD/energy/powerbalancelogs.h \
|
||||
$$PWD/energy/thingpowerlogs.h \
|
||||
$$PWD/connection/tunnelproxytransport.h \
|
||||
$$PWD/models/scriptsproxymodel.h \
|
||||
$$PWD/tagwatcher.h \
|
||||
$$PWD/zigbee/zigbeenode.h \
|
||||
|
||||
@ -279,6 +279,10 @@ QVariant Users::data(const QModelIndex &index, int role) const
|
||||
switch (role) {
|
||||
case RoleUsername:
|
||||
return m_users.at(index.row())->username();
|
||||
case RoleDisplayName:
|
||||
return m_users.at(index.row())->displayName();
|
||||
case RoleEmail:
|
||||
return m_users.at(index.row())->email();
|
||||
case RoleScopes:
|
||||
return static_cast<int>(m_users.at(index.row())->scopes());
|
||||
}
|
||||
@ -289,6 +293,8 @@ QHash<int, QByteArray> Users::roleNames() const
|
||||
{
|
||||
QHash<int, QByteArray> roles;
|
||||
roles.insert(RoleUsername, "username");
|
||||
roles.insert(RoleDisplayName, "displayName");
|
||||
roles.insert(RoleEmail, "email");
|
||||
roles.insert(RoleScopes, "scopes");
|
||||
return roles;
|
||||
}
|
||||
@ -296,6 +302,18 @@ QHash<int, QByteArray> Users::roleNames() const
|
||||
void Users::insertUser(UserInfo *userInfo)
|
||||
{
|
||||
userInfo->setParent(this);
|
||||
connect(userInfo, &UserInfo::displayNameChanged, this, [=](){
|
||||
int idx = m_users.indexOf(userInfo);
|
||||
if (idx >= 0) {
|
||||
emit dataChanged(index(idx), index(idx), {RoleDisplayName});
|
||||
}
|
||||
});
|
||||
connect(userInfo, &UserInfo::emailChanged, this, [=](){
|
||||
int idx = m_users.indexOf(userInfo);
|
||||
if (idx >= 0) {
|
||||
emit dataChanged(index(idx), index(idx), {RoleEmail});
|
||||
}
|
||||
});
|
||||
connect(userInfo, &UserInfo::scopesChanged, this, [=](){
|
||||
int idx = m_users.indexOf(userInfo);
|
||||
if (idx >= 0) {
|
||||
|
||||
@ -97,6 +97,8 @@ class Users: public QAbstractListModel {
|
||||
public:
|
||||
enum Roles {
|
||||
RoleUsername,
|
||||
RoleDisplayName,
|
||||
RoleEmail,
|
||||
RoleScopes
|
||||
};
|
||||
Q_ENUM(Roles)
|
||||
|
||||
@ -21,23 +21,6 @@ ConfiguredHostsModel::ConfiguredHostsModel(QObject *parent) : QAbstractListModel
|
||||
m_currentIndex = settings.value("currentIndex", 0).toInt();
|
||||
settings.endGroup();
|
||||
|
||||
// If there aren't any in the config, try migrating settings from old tab model
|
||||
if (m_list.isEmpty() && settings.contains("tabCount")) {
|
||||
qCInfo(dcApplication()) << "Migrating tab settings to mainmenumodel";
|
||||
int tabCount = settings.value("tabCount", 0).toInt();
|
||||
qCDebug(dcApplication()) << "Tab count:" << tabCount;
|
||||
|
||||
for (int i = 0; i < tabCount; i++) {
|
||||
settings.beginGroup(QString("tabSettings%1").arg(i));
|
||||
QUuid uuid = settings.value("lastConnectedHost").toUuid();
|
||||
ConfiguredHost *host = new ConfiguredHost(uuid, this);
|
||||
addHost(host);
|
||||
settings.endGroup();
|
||||
}
|
||||
|
||||
settings.remove("tabCount");
|
||||
}
|
||||
|
||||
// There must be always 1 at least
|
||||
if (m_list.isEmpty()) {
|
||||
createHost();
|
||||
|
||||
@ -12,7 +12,6 @@
|
||||
<file>ui/mainviews/FavoritesView.qml</file>
|
||||
<file>ui/mainviews/ThingsView.qml</file>
|
||||
<file>ui/connection/ConnectPage.qml</file>
|
||||
<file>ui/connection/ManualConnectPage.qml</file>
|
||||
<file>ui/connection/ConnectingPage.qml</file>
|
||||
<file>ui/connection/wifisetup/BluetoothDiscoveryPage.qml</file>
|
||||
<file>ui/connection/wifisetup/WirelessSetupPage.qml</file>
|
||||
@ -274,5 +273,6 @@
|
||||
<file>ui/components/NymeaToolTip.qml</file>
|
||||
<file>ui/components/SettingsTile.qml</file>
|
||||
<file>ui/components/NymeaTextField.qml</file>
|
||||
<file>ui/system/TunnelProxyServerConfigurationDialog.qml</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
||||
@ -721,7 +721,6 @@ Page {
|
||||
text: qsTr("Disconnect")
|
||||
Layout.preferredWidth: Math.max(cancelButton.implicitWidth, disconnectButton.implicitWidth)
|
||||
onClicked: {
|
||||
tabSettings.lastConnectedHost = "";
|
||||
engine.jsonRpcClient.disconnectFromHost();
|
||||
}
|
||||
}
|
||||
|
||||
@ -173,7 +173,6 @@ Item {
|
||||
print("opening push button auth")
|
||||
var page = pageStack.push(Qt.resolvedUrl("PushButtonAuthPage.qml"))
|
||||
page.backPressed.connect(function() {
|
||||
// tabSettings.lastConnectedHost = "";
|
||||
engine.jsonRpcClient.disconnectFromHost();
|
||||
init();
|
||||
})
|
||||
@ -182,7 +181,6 @@ Item {
|
||||
if (engine.jsonRpcClient.initialSetupRequired) {
|
||||
var page = pageStack.push(Qt.resolvedUrl("connection/SetupWizard.qml"));
|
||||
page.backPressed.connect(function() {
|
||||
// tabSettings.lastConnectedHost = "";
|
||||
engine.jsonRpcClient.disconnectFromHost()
|
||||
init();
|
||||
})
|
||||
@ -191,7 +189,6 @@ Item {
|
||||
|
||||
var page = pageStack.push(Qt.resolvedUrl("connection/LoginPage.qml"));
|
||||
page.backPressed.connect(function() {
|
||||
// tabSettings.lastConnectedHost = "";
|
||||
engine.jsonRpcClient.disconnectFromHost()
|
||||
init();
|
||||
})
|
||||
@ -314,7 +311,6 @@ Item {
|
||||
if (engine.jsonRpcClient.connected) {
|
||||
nymeaDiscovery.cacheHost(engine.jsonRpcClient.currentHost)
|
||||
configuredHost.uuid = engine.jsonRpcClient.serverUuid
|
||||
// tabSettings.lastConnectedHost = engine.jsonRpcClient.serverUuid
|
||||
}
|
||||
init();
|
||||
}
|
||||
@ -333,17 +329,47 @@ Item {
|
||||
popup.actualVersion = actualVersion;
|
||||
popup.minVersion = minVersion;
|
||||
popup.open()
|
||||
// tabSettings.lastConnectedHost = ""
|
||||
}
|
||||
onInvalidMaximumVersion: {
|
||||
var popup = invalidVersionComponent.createObject(app.contentItem);
|
||||
popup.actualVersion = actualVersion;
|
||||
popup.maxVersion = maxVersion;
|
||||
popup.open()
|
||||
// tabSettings.lastConnectedHost = ""
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: engine.nymeaConfiguration
|
||||
onFetchingDataChanged: {
|
||||
if (!engine.nymeaConfiguration.fetchingData) {
|
||||
syncRemoteConnection()
|
||||
}
|
||||
}
|
||||
}
|
||||
Connections {
|
||||
target: engine.nymeaConfiguration.tunnelProxyServerConfigurations
|
||||
onCountChanged: syncRemoteConnection();
|
||||
}
|
||||
|
||||
function syncRemoteConnection() {
|
||||
for (var i = 0; i < engine.jsonRpcClient.currentHost.connections.count; i++) {
|
||||
var connection = engine.jsonRpcClient.currentHost.connections.get(i)
|
||||
if (connection.url.toString().startsWith("tunnel")) {
|
||||
engine.jsonRpcClient.currentHost.connections.removeConnection(i--);
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = 0; i < engine.nymeaConfiguration.tunnelProxyServerConfigurations.count; i++) {
|
||||
var tunnelProxyConfig = engine.nymeaConfiguration.tunnelProxyServerConfigurations.get(i);
|
||||
var url = tunnelProxyConfig.sslEnabled ? "tunnels://" : "tunnel://";
|
||||
url += tunnelProxyConfig.address
|
||||
url += ":" + tunnelProxyConfig.port
|
||||
url += "?uuid=" + engine.jsonRpcClient.currentHost.uuid
|
||||
engine.jsonRpcClient.currentHost.connections.addConnection(url, Connection.BearerTypeCloud, tunnelProxyConfig.sslEnabled, "Remote proxy connection");
|
||||
}
|
||||
nymeaDiscovery.cacheHost(engine.jsonRpcClient.currentHost)
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: Qt.application
|
||||
enabled: engine.jsonRpcClient.connected && settings.returnToHome
|
||||
|
||||
@ -308,6 +308,12 @@ WizardPageBase {
|
||||
} else {
|
||||
rpcUrl = "ws://" + hostAddress + ":" + port
|
||||
}
|
||||
} else if (connectionTypeComboBox.currentIndex == 2) {
|
||||
if (secureCheckBox.checked) {
|
||||
rpcUrl = "tunnels://" + hostAddress + ":" + port + "?uuid=" + serverUuidTextInput.text
|
||||
} else {
|
||||
rpcUrl = "tunnel://" + hostAddress + ":" + port + "?uuid=" + serverUuidTextInput.text
|
||||
}
|
||||
}
|
||||
|
||||
print("Try to connect ", rpcUrl)
|
||||
@ -331,28 +337,43 @@ WizardPageBase {
|
||||
ComboBox {
|
||||
id: connectionTypeComboBox
|
||||
Layout.fillWidth: true
|
||||
model: [ qsTr("TCP"), qsTr("Websocket") ]
|
||||
model: [ qsTr("TCP"), qsTr("Websocket"), qsTr("Remote proxy") ]
|
||||
}
|
||||
|
||||
Label { text: qsTr("Address:") }
|
||||
Label {
|
||||
text: connectionTypeComboBox.currentIndex < 2 ? qsTr("Address:") : qsTr("Proxy address:")
|
||||
}
|
||||
TextField {
|
||||
id: addressTextInput
|
||||
objectName: "addressTextInput"
|
||||
Layout.fillWidth: true
|
||||
placeholderText: "127.0.0.1"
|
||||
placeholderText: connectionTypeComboBox.currentIndex < 2 ? "127.0.0.1" : "dev-remoteproxy.nymea.io"
|
||||
}
|
||||
|
||||
Label {
|
||||
text: qsTr("%1 UUID:").arg(Configuration.systemName)
|
||||
visible: connectionTypeComboBox.currentIndex == 2
|
||||
}
|
||||
TextField {
|
||||
id: serverUuidTextInput
|
||||
Layout.fillWidth: true
|
||||
visible: connectionTypeComboBox.currentIndex == 2
|
||||
}
|
||||
Label { text: qsTr("Port:") }
|
||||
TextField {
|
||||
id: portTextInput
|
||||
Layout.fillWidth: true
|
||||
placeholderText: connectionTypeComboBox.currentIndex === 0 ? "2222" : "4444"
|
||||
placeholderText: connectionTypeComboBox.currentIndex === 0
|
||||
? "2222"
|
||||
: connectionTypeComboBox.currentIndex == 1
|
||||
? "4444"
|
||||
: "2213"
|
||||
validator: IntValidator{bottom: 1; top: 65535;}
|
||||
}
|
||||
|
||||
Label {
|
||||
Layout.fillWidth: true
|
||||
text: qsTr("Encrypted connection:")
|
||||
text: qsTr("SSL:")
|
||||
}
|
||||
CheckBox {
|
||||
id: secureCheckBox
|
||||
|
||||
@ -136,4 +136,55 @@ SettingsPageBase {
|
||||
popup.open()
|
||||
}
|
||||
}
|
||||
SettingsPageSectionHeader {
|
||||
text: qsTr("Remote connection server interfaces")
|
||||
visible: engine.jsonRpcClient.ensureServerVersion("6.0")
|
||||
}
|
||||
|
||||
Repeater {
|
||||
model: engine.nymeaConfiguration.tunnelProxyServerConfigurations
|
||||
delegate: ConnectionInterfaceDelegate {
|
||||
Layout.fillWidth: true
|
||||
text: qsTr("Server: %1").arg(model.address)
|
||||
iconColor: inUse ? Style.accentColor : Style.iconColor
|
||||
readonly property bool inUse: (engine.jsonRpcClient.currentConnection.hostAddress === model.address || model.address === "0.0.0.0")
|
||||
&& engine.jsonRpcClient.currentConnection.port === model.port
|
||||
canDelete: !inUse
|
||||
onClicked: {
|
||||
var component = Qt.createComponent(Qt.resolvedUrl("TunnelProxyServerConfigurationDialog.qml"));
|
||||
var popup = component.createObject(root, { serverConfiguration: engine.nymeaConfiguration.tunnelProxyServerConfigurations.get(index).clone() });
|
||||
popup.accepted.connect(function() {
|
||||
print("configuring:", popup.serverConfiguration.port)
|
||||
engine.nymeaConfiguration.setTunnelProxyServerConfiguration(popup.serverConfiguration)
|
||||
popup.serverConfiguration.destroy();
|
||||
})
|
||||
popup.rejected.connect(function() {
|
||||
popup.serverConfiguration.destroy();
|
||||
})
|
||||
popup.open()
|
||||
}
|
||||
onDeleteClicked: {
|
||||
engine.nymeaConfiguration.deleteTunnelProxyServerConfiguration(model.id)
|
||||
}
|
||||
}
|
||||
}
|
||||
Button {
|
||||
Layout.fillWidth: true
|
||||
Layout.margins: app.margins
|
||||
text: qsTr("Add")
|
||||
visible: engine.jsonRpcClient.ensureServerVersion("6.0")
|
||||
onClicked: {
|
||||
var config = engine.nymeaConfiguration.createTunnelProxyServerConfiguration("dev-remoteproxy.nymea.io", 2213, true, true, false);
|
||||
var component = Qt.createComponent(Qt.resolvedUrl("TunnelProxyServerConfigurationDialog.qml"));
|
||||
var popup = component.createObject(root, { serverConfiguration: config });
|
||||
popup.accepted.connect(function() {
|
||||
engine.nymeaConfiguration.setTunnelProxyServerConfiguration(popup.serverConfiguration)
|
||||
popup.serverConfiguration.destroy();
|
||||
})
|
||||
popup.rejected.connect(function() {
|
||||
popup.serverConfiguration.destroy();
|
||||
})
|
||||
popup.open()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
114
nymea-app/ui/system/TunnelProxyServerConfigurationDialog.qml
Normal file
114
nymea-app/ui/system/TunnelProxyServerConfigurationDialog.qml
Normal file
@ -0,0 +1,114 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* Copyright 2013 - 2021, nymea GmbH
|
||||
* Contact: contact@nymea.io
|
||||
*
|
||||
* This file is part of nymea.
|
||||
* This project including source code and documentation is protected by
|
||||
* copyright law, and remains the property of nymea GmbH. All rights, including
|
||||
* reproduction, publication, editing and translation, are reserved. The use of
|
||||
* this project is subject to the terms of a license agreement to be concluded
|
||||
* with nymea GmbH in accordance with the terms of use of nymea GmbH, available
|
||||
* under https://nymea.io/license
|
||||
*
|
||||
* GNU General Public License Usage
|
||||
* Alternatively, this project may be redistributed and/or modified under the
|
||||
* terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation, GNU version 3. This project is distributed in the hope that it
|
||||
* will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||
* Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this project. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* For any further details and any questions please contact us under
|
||||
* contact@nymea.io or see our FAQ/Licensing Information on
|
||||
* https://nymea.io/license/faq
|
||||
*
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
import QtQuick 2.9
|
||||
import QtQuick.Controls 2.1
|
||||
import QtQuick.Controls.Material 2.1
|
||||
import QtQuick.Layouts 1.1
|
||||
import Nymea 1.0
|
||||
|
||||
Dialog {
|
||||
id: root
|
||||
title: qsTr("Proxy server configuration")
|
||||
width: parent.width * .8
|
||||
x: (parent.width - width) / 2
|
||||
y: (parent.height - height) / 2
|
||||
|
||||
property ServerConfiguration serverConfiguration: null
|
||||
standardButtons: Dialog.Ok | Dialog.Cancel
|
||||
|
||||
ColumnLayout {
|
||||
anchors { left: parent.left; top: parent.top; right: parent.right }
|
||||
RowLayout {
|
||||
Label {
|
||||
text: qsTr("Proxy server address:")
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
TextField {
|
||||
id: addressTextField
|
||||
Layout.fillWidth: true
|
||||
text: root.serverConfiguration ? root.serverConfiguration.address : ""
|
||||
onEditingFinished: root.serverConfiguration.address = text
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
Label {
|
||||
text: qsTr("Port:")
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
TextField {
|
||||
inputMethodHints: Qt.ImhDigitsOnly
|
||||
text: root.serverConfiguration ? root.serverConfiguration.port : 0
|
||||
validator: IntValidator { bottom: 0; top: 65535 }
|
||||
onEditingFinished: root.serverConfiguration.port = text
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
Label {
|
||||
Layout.fillWidth: true
|
||||
text: qsTr("Require login")
|
||||
}
|
||||
CheckBox {
|
||||
checkState: root.serverConfiguration && root.serverConfiguration.authenticationEnabled ? Qt.Checked : Qt.Unchecked
|
||||
onClicked: root.serverConfiguration.authenticationEnabled = checked
|
||||
}
|
||||
}
|
||||
Label {
|
||||
Layout.fillWidth: true
|
||||
wrapMode: Text.WordWrap
|
||||
text: qsTr("Not requiring a login for the remote connection will allow anyone on the internet to connect to your %1 system.").arg(Configuration.systemName)
|
||||
color: Style.red
|
||||
visible: root.serverConfiguration && !root.serverConfiguration.authenticationEnabled
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
Label {
|
||||
Layout.fillWidth: true
|
||||
text: qsTr("SSL enabled")
|
||||
}
|
||||
CheckBox {
|
||||
checkState: root.serverConfiguration && root.serverConfiguration.sslEnabled ? Qt.Checked : Qt.Unchecked
|
||||
onClicked: root.serverConfiguration.sslEnabled = checked
|
||||
}
|
||||
}
|
||||
RowLayout {
|
||||
Label {
|
||||
Layout.fillWidth: true
|
||||
text: qsTr("Ignore SSL errors")
|
||||
}
|
||||
CheckBox {
|
||||
checkState: root.serverConfiguration && root.serverConfiguration.ignoreSslErrors ? Qt.Checked : Qt.Unchecked
|
||||
onClicked: root.serverConfiguration.ignoreSslErrors = checked
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -278,7 +278,7 @@ SettingsPageBase {
|
||||
model: userManager.users
|
||||
delegate: NymeaItemDelegate {
|
||||
Layout.fillWidth: true
|
||||
text: engine.jsonRpcClient.ensureServerVersion("6.0") && model.displayName ? model.displayName : model.username
|
||||
text: engine.jsonRpcClient.ensureServerVersion("6.0") && model.displayName !== "" ? model.displayName : model.username
|
||||
subText: engine.jsonRpcClient.ensureServerVersion("6.0") && model.displayName ? model.username : ""
|
||||
iconName: "/ui/images/account.svg"
|
||||
iconColor: userManager.userInfo.scopes & UserInfo.PermissionScopeAdmin ? Style.accentColor : Style.iconColor
|
||||
|
||||
@ -1 +1 @@
|
||||
Subproject commit 9c7075192b2b799feb302b48618eb4ef4d942172
|
||||
Subproject commit 32c33ec23f975a457017b3eb7744a040bb4bd257
|
||||
Reference in New Issue
Block a user