Compare commits

..
17 Commits
15 changed files with 218 additions and 61 deletions
+6
View File
@@ -2,6 +2,12 @@
Download latest version:
https://robomongo.org/download
Robo 3T 1.4.4 (Aug/2021)
New Features:
- Support for Standard Connection String Format (Mongo URI)
Fixes:
- Fix Welcome Tab not loading the new content issue by disable/bypass HTTP cache
Robo 3T 1.4.3 (Jan/2021)
New Features:
- macOS Big Sur support
+1 -1
View File
@@ -7,7 +7,7 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake")
# Project version
set(PROJECT_VERSION_MAJOR "1")
set(PROJECT_VERSION_MINOR "4")
set(PROJECT_VERSION_PATCH "3")
set(PROJECT_VERSION_PATCH "4")
set(PROJECT_VERSION_BUILD "")
set(PROJECT_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}${PROJECT_VERSION_BUILD}")
+2 -1
View File
@@ -1,3 +1,4 @@
About Robo 3T
===============
@@ -131,7 +132,7 @@ You can:
License
=======
Copyright 2014-2020 [3T Software Labs Ltd](https://studio3t.com/). All rights reserved.
Copyright 2014-2021 [3T Software Labs Ltd](https://studio3t.com/). All rights reserved.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License version 3 as
+3 -2
View File
@@ -246,17 +246,18 @@ if(SYSTEM_WINDOWS)
target_link_libraries(robomongo PRIVATE Qt5::WinMain)
elseif(SYSTEM_MACOSX)
string(TIMESTAMP CURRENT_YEAR "%Y")
set_target_properties(robomongo PROPERTIES
INSTALL_RPATH "@executable_path/../Frameworks"
OUTPUT_NAME "Robo 3T"
MACOSX_BUNDLE_INFO_PLIST "${CMAKE_SOURCE_DIR}/install/macosx/Info.plist.in"
MACOSX_BUNDLE_BUNDLE_NAME "Robo 3T"
MACOSX_BUNDLE_GUI_IDENTIFIER "com.3tsoftwarelabs.robo3t"
MACOSX_BUNDLE_INFO_STRING "Robo 3T ${PROJECT_VERSION}. Copyright 3T Software Labs Ltd, 2014 - 2017"
MACOSX_BUNDLE_INFO_STRING "Robo 3T ${PROJECT_VERSION}. Copyright 3T Software Labs Ltd, 2014 - ${CURRENT_YEAR}"
MACOSX_BUNDLE_SHORT_VERSION "${PROJECT_VERSION}"
MACOSX_BUNDLE_LONG_VERSION "${PROJECT_VERSION}"
MACOSX_BUNDLE_BUNDLE_VERSION "${PROJECT_VERSION}"
MACOSX_BUNDLE_COPYRIGHT "Copyright 3T Software Labs Ltd, 2014 - 2017"
MACOSX_BUNDLE_COPYRIGHT "Copyright 3T Software Labs Ltd, 2014 - ${CURRENT_YEAR}"
MACOSX_BUNDLE_ICON_FILE "robomongo")
elseif(SYSTEM_LINUX)
@@ -75,6 +75,7 @@ namespace Robomongo
// be defined and placed into the vector initializer list below in order.
std::vector<QString> const SettingsManager::_configFilesOfOldVersions
{
QString("%1/.3T/robo-3t/1.4.3/robo3t.json").arg(QDir::homePath()), // CONFIG_FILE_1_4_3
QString("%1/.3T/robo-3t/1.4.2/robo3t.json").arg(QDir::homePath()), // CONFIG_FILE_1_4_2
QString("%1/.3T/robo-3t/1.4.1/robo3t.json").arg(QDir::homePath()), // CONFIG_FILE_1_4_1
QString("%1/.3T/robo-3t/1.4.0/robo3t.json").arg(QDir::homePath()), // CONFIG_FILE_1_4_0
@@ -11,7 +11,6 @@
#include "robomongo/core/settings/CredentialSettings.h"
#include "robomongo/core/utils/QtUtils.h"
#include "robomongo/gui/GuiRegistry.h"
#include "robomongo/gui/utils/GuiConstants.h"
namespace Robomongo
{
@@ -141,12 +140,28 @@ namespace Robomongo
_settings->addCredential(credential);
}
void ConnectionAuthTab::setAuthTab(QString const db, QString const username, QString const pwd)
{
void ConnectionAuthTab::setAuthTab(
QString const db,
QString const username,
QString const pwd,
AuthMechanism authMech
) {
_useAuth->setChecked(true);
_databaseName->setText(db);
_userName->setText(username);
_userPassword->setText(pwd);
_mechanismComboBox->setCurrentIndex(int(authMech));
}
void ConnectionAuthTab::clearTab()
{
_useAuth->setChecked(false);
_databaseName->clear();
_userName->clear();
_userPassword->clear();
_mechanismComboBox->setCurrentIndex(0);
_useManuallyVisibleDbs->setChecked(false);
_manuallyVisibleDbs->clear();
}
void ConnectionAuthTab::toggleEchoMode()
+10 -1
View File
@@ -1,6 +1,9 @@
#pragma once
#include <QWidget>
#include "robomongo/gui/utils/GuiConstants.h"
QT_BEGIN_NAMESPACE
class QLineEdit;
class QLabel;
@@ -20,7 +23,13 @@ namespace Robomongo
public:
ConnectionAuthTab(ConnectionSettings *settings);
void accept();
void setAuthTab(QString const db, QString const username, QString const pwd);
void setAuthTab(
QString const db,
QString const username,
QString const pwd,
AuthMechanism authMech
);
void clearTab();
private Q_SLOTS:
void toggleEchoMode();
@@ -111,17 +111,17 @@ namespace Robomongo
auto hline = new QFrame();
hline->setFrameShape(QFrame::HLine);
hline->setFrameShadow(QFrame::Sunken);
_srvEdit = new QLineEdit();
_srvEdit->setPlaceholderText("Import connection details from MongoDB SRV connection string");
_srvButton = new QPushButton("From SRV");
_uriEdit = new QLineEdit();
_uriEdit->setPlaceholderText("Import connection details from MongoDB URI connection string");
_uriButton = new QPushButton("From URI");
#ifdef _WIN32
_srvButton->setMaximumHeight(HighDpiConstants::WIN_HIGH_DPI_BUTTON_HEIGHT);
_srvButton->setMinimumWidth(60);
_uriButton->setMaximumHeight(HighDpiConstants::WIN_HIGH_DPI_BUTTON_HEIGHT);
_uriButton->setMinimumWidth(60);
#else // MacOS
_srvButton->setMaximumHeight(HighDpiConstants::MACOS_HIGH_DPI_BUTTON_HEIGHT);
_srvButton->setMaximumWidth(90);
_uriButton->setMaximumHeight(HighDpiConstants::MACOS_HIGH_DPI_BUTTON_HEIGHT);
_uriButton->setMaximumWidth(90);
#endif
VERIFY(connect(_srvButton, SIGNAL(clicked()), this, SLOT(on_srvButton_clicked())));
VERIFY(connect(_uriButton, SIGNAL(clicked()), this, SLOT(on_uriButton_clicked())));
auto connLayout = new QGridLayout;
connLayout->setVerticalSpacing(8);
@@ -142,8 +142,8 @@ namespace Robomongo
connLayout->addWidget(_setNameEdit, 9, 1, 1, 3, Qt::AlignTop);
connLayout->addWidget(fakeSpacer, 10, 0);
connLayout->addWidget(hline, 11, 0, 1, 4);
connLayout->addWidget(_srvButton, 13, 0);
connLayout->addWidget(_srvEdit, 13, 1, 1, 3);
connLayout->addWidget(_uriButton, 13, 0);
connLayout->addWidget(_uriEdit, 13, 1, 1, 3);
connLayout->setRowStretch(10, 1);
#ifdef __APPLE__
@@ -225,6 +225,16 @@ namespace Robomongo
return true;
}
void ConnectionBasicTab::clearTab()
{
_connectionType->setCurrentIndex(0);
_connectionName->setText("New Connection");
_serverAddress->clear();
_serverPort->clear();
_members->clear();
_setNameEdit->clear();
}
void ConnectionBasicTab::on_ConnectionTypeChange(int index)
{
bool const isReplica = static_cast<bool>(index);
@@ -318,38 +328,71 @@ namespace Robomongo
item->setText(0, str);
}
void ConnectionBasicTab::on_srvButton_clicked()
void ConnectionBasicTab::on_uriButton_clicked()
{
QString srvStr = _srvEdit->text().simplified();
srvStr.replace(" ", "");
auto const statusWithMongoURI = mongo::MongoURI::parse(srvStr.toStdString());
if (!statusWithMongoURI.isOK()) {
// Parse Mongo URI
QString uriStr = _uriEdit->text().simplified();
uriStr.replace(" ", "");
auto const statusWithURI = mongo::MongoURI::parse(uriStr.toStdString());
if (!statusWithURI.isOK()) {
QMessageBox errorBox;
errorBox.critical(this, "Error", ("MongoDB SRV:\n" + statusWithMongoURI.getStatus().toString()).c_str());
errorBox.critical(
this, "Error", ("MongoDB URI:\n" + statusWithURI.getStatus().toString()).c_str()
);
errorBox.show();
return;
}
auto const mongoUri = statusWithMongoURI.getValue();
auto const db = QString::fromStdString(mongoUri.getDatabase());
auto const mongoUri = statusWithURI.getValue();
// Clear tabs
clearTab();
_connectionDialog->clearConnAuthTab();
_connectionDialog->clearSslTab();
// Set Basic (this) Tab
auto const isReplicaSet = mongoUri.type() == mongo::ConnectionString::ConnectionType::SET;
if(isReplicaSet) {
_connectionType->setCurrentIndex(1); // Switch to Replica Set
for (auto const& hostAndPort : mongoUri.getServers()) {
auto host = QString::fromStdString(hostAndPort.host());
host.endsWith('.') ? host.remove(host.size()-1, 1) : "no-op";
auto const newHostAndPort = host + ':' + QString::number(hostAndPort.port());
auto item = new QTreeWidgetItem;
item->setText(0, newHostAndPort);
item->setFlags(item->flags() | Qt::ItemIsEditable);
_members->addTopLevelItem(item);
}
_setNameEdit->setText(QString::fromStdString(mongoUri.getSetName()));
}
else { // Standalone
_connectionType->setCurrentIndex(0);
_serverAddress->setText(QString::fromStdString(mongoUri.getServers()[0].host()));
_serverPort->setText(QString::number(mongoUri.getServers()[0].port()));
}
// Set Auth Tab
auto const user = QString::fromStdString(mongoUri.getUser());
auto const pwd = QString::fromStdString(mongoUri.getPassword());
auto const authDb = QString::fromStdString(mongoUri.getAuthenticationDatabase());
auto const authMechanism = mongoUri.getOption("authMechanism").get_value_or("");
if(!user.isEmpty()) _connectionDialog->setAuthTab(
authDb, user, pwd, authMechanismFromStr(authMechanism)
);
// Set SSL Tab
if(mongoUri.getSSLMode() == mongo::transport::ConnectSSLMode::kEnableSSL) {
auto tlsAllowInvalidCertificates = mongoUri.getOption("tlsAllowInvalidCertificates");
int const authMethodIndex = tlsAllowInvalidCertificates.get_value_or("") == "true" ? 0 : 1;
auto const caFile = mongoUri.getOption("tlsCAFile").get_value_or("");
auto const certKeyFile = mongoUri.getOption("tlsCertificateKeyFile").get_value_or("");
auto const certKeyFilePwd =
mongoUri.getOption("tlsCertificateKeyFilePassword").get_value_or("");
auto const allowInvalidHostnames =
mongoUri.getOption("tlsAllowInvalidHostnames").get_value_or("") == "true";
// Basic (this) Tab
_members->clear();
_connectionType->setCurrentIndex(1); // Switch to Replica Set
for (auto const& hostAndPort : mongoUri.getServers()) {
auto host = QString::fromStdString(hostAndPort.host());
host.endsWith('.') ? host.remove(host.size()-1, 1) : "no-op";
auto const newHostAndPort = host + ':' + QString::number(hostAndPort.port());
auto item = new QTreeWidgetItem;
item->setText(0, newHostAndPort);
item->setFlags(item->flags() | Qt::ItemIsEditable);
_members->addTopLevelItem(item);
_connectionDialog->setSslTab(
authMethodIndex, allowInvalidHostnames, caFile, certKeyFile, certKeyFilePwd
);
}
_setNameEdit->setText(QString::fromStdString(mongoUri.getSetName()));
_connectionDialog->setAuthTab(authDb, user, pwd); // Auth Tab
_connectionDialog->enableSslBasic(); // TLS Tab
_connectionDialog->setDefaultDb(db); // Advanced Tab
// Advanced Tab
_connectionDialog->setDefaultDb(QString::fromStdString(mongoUri.getDatabase()));
}
}
}
@@ -24,6 +24,7 @@ namespace Robomongo
public:
ConnectionBasicTab(ConnectionSettings *settings, ConnectionDialog *connectionDialog);
bool accept();
void clearTab();
private Q_SLOTS:
void on_ConnectionTypeChange(int index);
@@ -31,7 +32,7 @@ namespace Robomongo
void on_addButton_clicked();
void on_removeButton_clicked();
void on_replicaMemberItemEdit(QTreeWidgetItem* item, int column);
void on_srvButton_clicked();
void on_uriButton_clicked();
private:
QLabel *_typeLabel;
@@ -51,8 +52,8 @@ namespace Robomongo
QDialogButtonBox *_minusPlusButtonBox;
QLabel *_setNameLabel;
QLineEdit *_setNameEdit;
QLineEdit *_srvEdit;
QPushButton *_srvButton;
QLineEdit *_uriEdit;
QPushButton *_uriButton;
QPushButton *_discoverButton;
QLabel *_readPrefLabel;
QComboBox *_readPreference;
+27 -8
View File
@@ -99,14 +99,13 @@ namespace Robomongo
QWidget::closeEvent(event);
}
void ConnectionDialog::setAuthTab(QString const& db, QString const& username, QString const& pwd)
{
_authTab->setAuthTab(db, username, pwd);
}
void ConnectionDialog::enableSslBasic()
{
_sslTab->enableSslBasic();
void ConnectionDialog::setAuthTab(
QString const& db,
QString const& username,
QString const& pwd,
AuthMechanism authMech
) {
_authTab->setAuthTab(db, username, pwd, authMech);
}
void ConnectionDialog::setDefaultDb(QString const& defaultDb)
@@ -123,6 +122,26 @@ namespace Robomongo
_sshTab->toggleSshCheckboxToolTip(isReplicaSet);
}
void ConnectionDialog::clearConnAuthTab()
{
_authTab->clearTab();
}
void ConnectionDialog::clearSslTab()
{
_sslTab->clearTab();
}
void ConnectionDialog::setSslTab(
int index,
bool allowInvalidHostnames,
std::string_view caFile,
std::string_view certPemFile,
std::string_view certPemFilePwd
) {
_sslTab->setSslOptions(index, allowInvalidHostnames, caFile, certPemFile, certPemFilePwd);
}
void ConnectionDialog::restoreWindowSettings()
{
QSettings settings("3T", "Robomongo");
+18 -2
View File
@@ -3,6 +3,7 @@
#include <QDialog>
#include "robomongo/core/Core.h"
#include "robomongo/gui/utils/GuiConstants.h"
namespace Robomongo
{
@@ -12,6 +13,7 @@ namespace Robomongo
class ConnectionAdvancedTab;
class SSLTab;
class SshTunnelTab;
/**
* @brief This Dialog allows to edit single connection
*/
@@ -26,10 +28,24 @@ namespace Robomongo
ConnectionDialog(ConnectionSettings *connection, QWidget *parent = nullptr);
ConnectionSettings *const connection() const { return _connection; }
void setAuthTab(QString const& db, QString const& username, QString const& pwd);
void enableSslBasic();
void setAuthTab(
QString const& db,
QString const& username,
QString const& pwd,
AuthMechanism authMech
);
void setDefaultDb(QString const& defaultDb);
void toggleSshSupport(bool isReplicaSet);
void clearConnAuthTab();
void clearSslTab();
void setSslTab(
int index,
bool allowInvalidHostnames,
std::string_view caFile,
std::string_view certPemFile,
std::string_view certPemFilePwd
);
public Q_SLOTS:
/**
+27 -4
View File
@@ -207,10 +207,34 @@ namespace Robomongo
return _useSslCheckBox->isChecked();
}
void SSLTab::enableSslBasic()
void SSLTab::clearTab()
{
_authMethodComboBox->setCurrentIndex(1);
_caFilePathLineEdit->clear();
_usePemFileCheckBox->setChecked(false);
_pemFilePathLineEdit->clear();
_pemPassLineEdit->clear();
_useAdvancedOptionsCheckBox->setChecked(false);
_allowInvalidHostnamesComboBox->setCurrentIndex(0);
}
void SSLTab::setSslOptions(
int index,
bool allowInvalidHostnames,
std::string_view caFile,
std::string_view certPemFile,
std::string_view certPemFilePwd
) {
_useSslCheckBox->setChecked(true);
_authMethodComboBox->setCurrentIndex(0);
_authMethodComboBox->setCurrentIndex(index);
_caFilePathLineEdit->setText(QString::fromStdString(std::string(caFile)));
if(!certPemFile.empty()) _usePemFileCheckBox->setChecked(true);
_pemFilePathLineEdit->setText(QString::fromStdString(std::string(certPemFile)));
_pemPassLineEdit->setText(QString::fromStdString(std::string(certPemFilePwd)));
if (allowInvalidHostnames) _useAdvancedOptionsCheckBox->setChecked(true);
_allowInvalidHostnamesComboBox->setCurrentIndex(allowInvalidHostnames);
}
void SSLTab::useSslCheckBoxStateChange(int state)
@@ -399,5 +423,4 @@ namespace Robomongo
return QDir::toNativeSeparators(fileName);
}
}
}
+8 -1
View File
@@ -39,7 +39,14 @@ namespace Robomongo
*/
bool sslEnabled() const;
void enableSslBasic();
void clearTab();
void setSslOptions(
int index,
bool allowInvalidHostnames,
std::string_view caFile,
std::string_view certPemFile,
std::string_view certPemFilePwd
);
private Q_SLOTS :
+14 -1
View File
@@ -8,4 +8,17 @@ namespace Robomongo
int const MACOS_HIGH_DPI_BUTTON_HEIGHT = 34;
}
} /* end of Robomongo namespace */
enum AuthMechanism {
SCRAM_SHA_1,
SCRAM_SHA_256,
MONGODB_CR
};
inline AuthMechanism authMechanismFromStr(std::string_view str) {
if (str == "SCRAM-SHA-1") return SCRAM_SHA_1;
else if (str == "SCRAM-SHA-256") return SCRAM_SHA_256;
else if (str == "MONGODB-CR") return MONGODB_CR;
else return SCRAM_SHA_1;
}
} /* end of Robomongo namespace */
@@ -18,6 +18,8 @@ namespace Robomongo {
webView->setPage(new MyWebPage(this));
webView->page()->setUrl(URL);
webView->setContextMenuPolicy(Qt::NoContextMenu);
webView->page()->triggerAction(QWebEnginePage::WebAction::ReloadAndBypassCache);
webView->page()->profile()->setHttpCacheType(QWebEngineProfile::HttpCacheType::NoCache);
auto mainLayout = new QHBoxLayout;
mainLayout->setContentsMargins(-10, -10, -1, -1);