mirror of
https://github.com/silverqx/TinyORM.git
synced 2025-12-30 07:19:34 -06:00
added SSL-related PostgreSQL configuration
Added a new SSL-related configuration options to the top-level configuration level for PostgreSQL database. They are sslmode, sslcert, sslkey, and sslrootcert. These options are copied from the top-level configuration to the options option hash during configuration parsing by the PostgresConfigurationParser. If both are defined, then the top-level option overwrites a option in the 'options' hash. - also added constants - functional test - updated docs
This commit is contained in:
@@ -206,7 +206,99 @@ You have to pass the [`sslmode`](https://www.postgresql.org/docs/current/libpq-s
|
||||
|
||||
And place your __client__ certificates to the `~/.postgres/` on [Linux](https://www.postgresql.org/docs/current/libpq-ssl.html#LIBPQ-SSL-FILE-USAGE) and `$env:APPDATA/postgres/` on Windows. Everything is described in the PostgreSQL's [libpq client](https://www.postgresql.org/docs/current/libpq-ssl.html) and [server](https://www.postgresql.org/docs/15/ssl-tcp.html#SSL-FILE-USAGE) documentation.
|
||||
|
||||
You may also use the `ConfigUtils::postgresSslOptions()` or the `ConfigUtils::insertPostgresSslOptions()` methods to insert the `sslmode` option for you and define it using the `DB_PGSQL_SSLMODE` environment variable.
|
||||
If you want to keep your __client__ certificates in your own location, you can set the `sslcert`, `sslkey`, and `sslrootcert` options.
|
||||
|
||||
<Tabs groupId={shell}>
|
||||
<TabItem value={pwsh} label={pwsh_label}>
|
||||
|
||||
#include <orm/db.hpp>
|
||||
|
||||
using Orm::DB;
|
||||
|
||||
// Ownership of a shared_ptr()
|
||||
auto manager = DB::create({
|
||||
{"driver", "QPSQL"},
|
||||
{"host", qEnvironmentVariable("DB_PGSQL_HOST", "127.0.0.1")},
|
||||
...
|
||||
// highlight-next-line
|
||||
{"options", QVariantHash({{"sslmode", "verify-full"},
|
||||
// highlight-start
|
||||
{"sslcert", "C:/example/postgres.crt"},
|
||||
{"sslkey", "C:/example/postgres.key"},
|
||||
{"sslrootcert", "C:/example/root.crt"}})},
|
||||
// highlight-end
|
||||
});
|
||||
|
||||
</TabItem>
|
||||
<TabItem value={bash} label={bash_label}>
|
||||
|
||||
#include <orm/db.hpp>
|
||||
|
||||
using Orm::DB;
|
||||
|
||||
// Ownership of a shared_ptr()
|
||||
auto manager = DB::create({
|
||||
{"driver", "QPSQL"},
|
||||
{"host", qEnvironmentVariable("DB_PGSQL_HOST", "127.0.0.1")},
|
||||
...
|
||||
// highlight-next-line
|
||||
{"options", QVariantHash({{"sslmode", "verify-full"},
|
||||
// highlight-start
|
||||
{"sslcert", "/example/postgres.crt"},
|
||||
{"sslkey", "/example/postgres.key"},
|
||||
{"sslrootcert", "/example/root.crt"}})},
|
||||
// highlight-end
|
||||
});
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
You can define these SSL-related options in the top-level configuration, they will be copied to the `options` option hash during configuration parsing. The top-level configuration takes precedence and overwrites the options in the `options` hash.
|
||||
|
||||
<Tabs groupId={shell}>
|
||||
<TabItem value={pwsh} label={pwsh_label}>
|
||||
|
||||
#include <orm/db.hpp>
|
||||
|
||||
using Orm::DB;
|
||||
|
||||
// Ownership of a shared_ptr()
|
||||
auto manager = DB::create({
|
||||
{"driver", "QPSQL"},
|
||||
{"host", qEnvironmentVariable("DB_PGSQL_HOST", "127.0.0.1")},
|
||||
...
|
||||
// highlight-start
|
||||
{"sslmode", "verify-full"},
|
||||
{"sslcert", "C:/example/postgres.crt"},
|
||||
{"sslkey", "C:/example/postgres.key"},
|
||||
{"sslrootcert", "C:/example/root.crt"}
|
||||
// highlight-end
|
||||
});
|
||||
|
||||
</TabItem>
|
||||
<TabItem value={bash} label={bash_label}>
|
||||
|
||||
#include <orm/db.hpp>
|
||||
|
||||
using Orm::DB;
|
||||
|
||||
// Ownership of a shared_ptr()
|
||||
auto manager = DB::create({
|
||||
{"driver", "QPSQL"},
|
||||
{"host", qEnvironmentVariable("DB_PGSQL_HOST", "127.0.0.1")},
|
||||
...
|
||||
// highlight-start
|
||||
{"sslmode", "verify-full"},
|
||||
{"sslcert", "/example/postgres.crt"},
|
||||
{"sslkey", "/example/postgres.key"},
|
||||
{"sslrootcert", "/example/root.crt"}
|
||||
// highlight-end
|
||||
});
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
You may also use the `ConfigUtils::postgresSslOptions()` or the `ConfigUtils::insertPostgresSslOptions()` methods to insert the `sslmode`, `sslcert`, `sslkey`, and `sslrootcert` options for you and define them using the `DB_PGSQL_SSLMODE`, `DB_PGSQL_SSLCERT`, `DB_PGSQL_SSLKEY`, and `DB_PGSQL_SSLROOTCERT` environment variable.
|
||||
|
||||
#include <orm/db.hpp>
|
||||
#include <orm/utils/configuration.hpp>
|
||||
@@ -225,7 +317,7 @@ You may also use the `ConfigUtils::postgresSslOptions()` or the `ConfigUtils::in
|
||||
});
|
||||
|
||||
:::info
|
||||
The PostgreSQL's libpq client library provides the [`PGSSLMODE`](https://www.postgresql.org/docs/current/libpq-envars.html#id-1.7.3.22.3.4.13.1.1) environment variable, so you don't have to use TinyORM's `options` configuration and may use the `PGSSLMODE` instead.
|
||||
The PostgreSQL's libpq client library provides the [`PGSSLMODE`](https://www.postgresql.org/docs/current/libpq-envars.html#id-1.7.3.22.3.4.13.1.1), [`PGSSLCERT`](https://www.postgresql.org/docs/current/libpq-envars.html#id-1.7.3.22.3.4.16.1.1), [`PGSSLKEY`](https://www.postgresql.org/docs/current/libpq-envars.html#id-1.7.3.22.3.4.17.1.1), and [`PGSSLROOTCERT`](https://www.postgresql.org/docs/current/libpq-envars.html#id-1.7.3.22.3.4.18.1.1) environment variables, so you don't have to use TinyORM's `options` configuration and may use these environment variables instead.
|
||||
:::
|
||||
|
||||
:::tip
|
||||
|
||||
@@ -29,6 +29,10 @@ namespace Orm::Configurations
|
||||
void parseDriverSpecificOptions() const final;
|
||||
/*! Parse the driver-specific 'options' configuration option. */
|
||||
void parseDriverSpecificOptionsOption(QVariantHash &options) const final;
|
||||
|
||||
private:
|
||||
/*! Add the SSL-related options to the connection 'options' hash. */
|
||||
void addSslOptions(QVariantHash &options) const;
|
||||
};
|
||||
|
||||
} // namespace Orm::Configurations
|
||||
|
||||
@@ -99,6 +99,9 @@ namespace Orm::Constants
|
||||
|
||||
// PostgreSQL SSL
|
||||
SHAREDLIB_EXPORT extern const QString sslmode_;
|
||||
SHAREDLIB_EXPORT extern const QString sslcert;
|
||||
SHAREDLIB_EXPORT extern const QString sslkey;
|
||||
SHAREDLIB_EXPORT extern const QString sslrootcert;
|
||||
|
||||
SHAREDLIB_EXPORT extern const QString isolation_level;
|
||||
SHAREDLIB_EXPORT extern const QString foreign_key_constraints;
|
||||
|
||||
@@ -98,6 +98,9 @@ namespace Orm::Constants
|
||||
|
||||
// PostgreSQL SSL
|
||||
inline const QString sslmode_ = QStringLiteral("sslmode");
|
||||
inline const QString sslcert = QStringLiteral("sslcert");
|
||||
inline const QString sslkey = QStringLiteral("sslkey");
|
||||
inline const QString sslrootcert = QStringLiteral("sslrootcert");
|
||||
|
||||
inline const QString
|
||||
isolation_level = QStringLiteral("isolation_level");
|
||||
|
||||
@@ -6,6 +6,10 @@ TINYORM_BEGIN_COMMON_NAMESPACE
|
||||
|
||||
using Orm::Constants::dont_drop;
|
||||
using Orm::Constants::spatial_ref_sys;
|
||||
using Orm::Constants::sslmode_;
|
||||
using Orm::Constants::sslcert;
|
||||
using Orm::Constants::sslkey;
|
||||
using Orm::Constants::sslrootcert;
|
||||
|
||||
namespace Orm::Configurations
|
||||
{
|
||||
@@ -20,8 +24,39 @@ void PostgresConfigurationParser::parseDriverSpecificOptions() const
|
||||
}
|
||||
|
||||
void PostgresConfigurationParser::parseDriverSpecificOptionsOption(
|
||||
QVariantHash &/*unused*/) const
|
||||
{}
|
||||
QVariantHash &options) const
|
||||
{
|
||||
// Copy all SSL-related options from the top-level config. to the 'options' hash
|
||||
addSslOptions(options);
|
||||
}
|
||||
|
||||
/* private */
|
||||
|
||||
void PostgresConfigurationParser::addSslOptions(QVariantHash &options) const
|
||||
{
|
||||
/* Copy all SSL-related connection options from the top-level configuration level
|
||||
to the 'options' hash. If the options hash already contains the same option, then
|
||||
it will be overwritten. */
|
||||
for (auto &&option : {sslmode_, sslcert, sslkey, sslrootcert}) {
|
||||
// Nothing to do, the original configuration doesn't contain it
|
||||
if (!config().contains(option))
|
||||
continue;
|
||||
|
||||
// Copy the value to the 'options' hash
|
||||
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
|
||||
if (const auto &newValue = config()[option];
|
||||
!newValue.value<QString>().isEmpty()
|
||||
)
|
||||
options.insert(option, newValue);
|
||||
#else
|
||||
if (auto newValue = config().value(option);
|
||||
!newValue.value<QString>().isEmpty()
|
||||
)
|
||||
options.emplace(std::move(const_cast<QString &>(option)),
|
||||
std::move(newValue));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Orm::Configurations
|
||||
|
||||
|
||||
@@ -88,6 +88,9 @@ namespace Orm::Constants
|
||||
|
||||
// PostgreSQL SSL
|
||||
const QString sslmode_ = QStringLiteral("sslmode");
|
||||
const QString sslcert = QStringLiteral("sslcert");
|
||||
const QString sslkey = QStringLiteral("sslkey");
|
||||
const QString sslrootcert = QStringLiteral("sslrootcert");
|
||||
|
||||
const QString isolation_level = QStringLiteral("isolation_level");
|
||||
const QString foreign_key_constraints = QStringLiteral("foreign_key_constraints");
|
||||
|
||||
@@ -159,9 +159,13 @@ namespace
|
||||
QVariantHash getPostgresSslOptions()
|
||||
{
|
||||
QVariantHash options;
|
||||
options.reserve(1);
|
||||
options.reserve(4);
|
||||
|
||||
insertDbOption(options, sslmode_, qEnvironmentVariable("DB_PGSQL_SSLMODE"));
|
||||
insertDbOption(options, sslmode_, qEnvironmentVariable("DB_PGSQL_SSLMODE"));
|
||||
insertDbOption(options, sslcert, qEnvironmentVariable("DB_PGSQL_SSLCERT"));
|
||||
insertDbOption(options, sslkey, qEnvironmentVariable("DB_PGSQL_SSLKEY"));
|
||||
insertDbOption(options, sslrootcert,
|
||||
qEnvironmentVariable("DB_PGSQL_SSLROOTCERT"));
|
||||
|
||||
return options;
|
||||
}
|
||||
@@ -170,7 +174,7 @@ namespace
|
||||
QVariantHash Configuration::postgresSslOptions()
|
||||
{
|
||||
QVariantHash options;
|
||||
options.reserve(6);
|
||||
options.reserve(9);
|
||||
|
||||
options.insert(getPostgresSslOptions());
|
||||
|
||||
|
||||
@@ -31,6 +31,10 @@ using Orm::Constants::qt_timezone;
|
||||
using Orm::Constants::return_qdatetime;
|
||||
using Orm::Constants::schema_;
|
||||
using Orm::Constants::spatial_ref_sys;
|
||||
using Orm::Constants::sslcert;
|
||||
using Orm::Constants::sslkey;
|
||||
using Orm::Constants::sslmode_;
|
||||
using Orm::Constants::sslrootcert;
|
||||
using Orm::Constants::username_;
|
||||
|
||||
using Orm::DatabaseManager;
|
||||
@@ -52,6 +56,8 @@ private Q_SLOTS:
|
||||
void default_PostgreSQL_ConfigurationValues() const;
|
||||
void default_SQLite_ConfigurationValues() const;
|
||||
|
||||
void ssl_PostgreSQL_ConfigurationValues() const;
|
||||
|
||||
// NOLINTNEXTLINE(readability-redundant-access-specifiers)
|
||||
private:
|
||||
/*! The Database Manager used in this test case. */
|
||||
@@ -322,6 +328,91 @@ void tst_DatabaseManager::default_SQLite_ConfigurationValues() const
|
||||
// Restore
|
||||
QVERIFY(m_dm->removeConnection(connectionName));
|
||||
}
|
||||
|
||||
void tst_DatabaseManager::ssl_PostgreSQL_ConfigurationValues() const
|
||||
{
|
||||
const auto connectionName =
|
||||
QStringLiteral(
|
||||
"tinyorm_pgsql_tests-tst_DatabaseMannager-"
|
||||
"ssl_PostgreSQL_ConfigurationValues");
|
||||
|
||||
// Top level
|
||||
const auto sslmodeValue = QStringLiteral("verify-full");
|
||||
const auto sslcertValue = QStringLiteral("C:/example/psql.crt");
|
||||
const auto sslkeyValue = QStringLiteral("C:/example/psql.key");
|
||||
const auto sslrootcertValue = QStringLiteral("C:/example/ca.crt");
|
||||
// The 'options' level
|
||||
const auto sslcertOptionsValue = QStringLiteral("D:/example/pg.crt");
|
||||
const auto sslkeyOptionsValue = QStringLiteral("D:/example/pg.key");
|
||||
|
||||
const QVariantHash initialConfiguration({
|
||||
{driver_, QPSQL},
|
||||
{sslmode_, sslmodeValue},
|
||||
{sslcert, sslcertValue},
|
||||
{sslkey, sslkeyValue},
|
||||
{sslrootcert, sslrootcertValue},
|
||||
{options_, QVariantHash({{sslcert, sslcertOptionsValue},
|
||||
{sslkey, sslkeyOptionsValue}})}
|
||||
});
|
||||
|
||||
// Create database connection
|
||||
m_dm->addConnections({
|
||||
{connectionName, initialConfiguration},
|
||||
// Don't setup any default connection
|
||||
}, EMPTY);
|
||||
|
||||
// Original configuration
|
||||
// Connection isn't created and configuration options are not parsed yet
|
||||
const auto &originalConfig = m_dm->originalConfig(connectionName);
|
||||
QCOMPARE(originalConfig, initialConfiguration);
|
||||
|
||||
/* Force the creation of a connection and parse the connection configuration options.
|
||||
The SSL-related options are only parsed in the connection configuration,
|
||||
the original configuration is untouched. */
|
||||
m_dm->connection(connectionName);
|
||||
QCOMPARE(originalConfig,
|
||||
QVariantHash({
|
||||
{driver_, QPSQL},
|
||||
{NAME, connectionName},
|
||||
{database_, EMPTY},
|
||||
{prefix_, EMPTY},
|
||||
{prefix_indexes, false},
|
||||
{options_, QVariantHash()},
|
||||
{dont_drop, QStringList {spatial_ref_sys}},
|
||||
{sslmode_, sslmodeValue},
|
||||
{sslcert, sslcertValue},
|
||||
{sslkey, sslkeyValue},
|
||||
{sslrootcert, sslrootcertValue},
|
||||
{options_, QVariantHash({{sslcert, sslcertOptionsValue},
|
||||
{sslkey, sslkeyOptionsValue}})}
|
||||
}));
|
||||
|
||||
// Connection configuration
|
||||
QCOMPARE(m_dm->getConfig(connectionName),
|
||||
QVariantHash({
|
||||
{driver_, QPSQL},
|
||||
{NAME, connectionName},
|
||||
{database_, EMPTY},
|
||||
{prefix_, EMPTY},
|
||||
{prefix_indexes, false},
|
||||
{options_, QVariantHash()},
|
||||
{dont_drop, QStringList {spatial_ref_sys}},
|
||||
{qt_timezone, QVariant::fromValue(
|
||||
QtTimeZoneConfig {QtTimeZoneType::DontConvert, {}}
|
||||
)},
|
||||
{sslmode_, sslmodeValue},
|
||||
{sslcert, sslcertValue},
|
||||
{sslkey, sslkeyValue},
|
||||
{sslrootcert, sslrootcertValue},
|
||||
{options_, QVariantHash({{sslmode_, sslmodeValue},
|
||||
{sslcert, sslcertValue},
|
||||
{sslkey, sslkeyValue},
|
||||
{sslrootcert, sslrootcertValue}})}
|
||||
}));
|
||||
|
||||
// Restore
|
||||
QVERIFY(m_dm->removeConnection(connectionName));
|
||||
}
|
||||
// NOLINTEND(readability-convert-member-functions-to-static)
|
||||
|
||||
QTEST_MAIN(tst_DatabaseManager)
|
||||
|
||||
Reference in New Issue
Block a user