diff --git a/README.md b/README.md
index 5339b61..545bda8 100644
--- a/README.md
+++ b/README.md
@@ -22,7 +22,11 @@ Argon2id. Because the various formats are recognized on-the-fly your db can can
have differing hash string formats at the same time, which eases migration to
newer formats.
-This app supports PostgreSQL and MariaDB/MySQL.
+This app primarily supports PostgreSQL and MariaDB/MySQL but the underlying PHP
+[mechanism](https://www.php.net/manual/en/pdo.drivers.php) also supports
+Firebird, MS SQL, Oracle DB, ODBC, DB2, SQLite, Informix and IBM databases. By
+using an appropriate DSN you should be able to connect to these databases. This
+has not been tested, though.
See [CHANGELOG.md](CHANGELOG.md) for changes in newer versions. This app follows
semantic versioning and there should not be any breaking changes unless the
@@ -45,7 +49,7 @@ This app has no user interface. All configuration is done via Nextcloud's system
//'db_type' => 'postgresql',
//'db_host' => 'localhost',
//'db_port' => '5432',
- 'db_name' => 'theNameOfYourUserDatabase',
+ 'db_name' => 'theNameOfYourDbUser',
'db_user' => 'yourDatabaseUser',
'db_password' => 'thePasswordForTheDatabaseUser',
//'db_password_file' => '/var/secrets/fileContainingThePasswordForTheDatabaseUser',
@@ -70,28 +74,26 @@ There are three types of configuration parameters:
### 1. Database
-that *User Backend SQL Raw* will connect to.
-
-| key | value | default value |
-| ------------------ | ------------------------------------------------------------------------------------------------------------------------ | ------------- |
-| `db_type` | `postgresql` or `mariadb` | `postgresql` |
-| `db_host` | your db host such as `localhost` or `db.example.com` or (only for PostgreSQL) path to socket, e.g. `/var/run/postgresql` | `localhost` |
-| `db_port` | your db port | `5432` |
-| `db_name` | your db name | |
-| `db_user` | your db user | |
-| `db_password` | your db password | |
-| `db_password_file` | path to file containing the db password | |
-| `mariadb_charset` | the charset for mariadb connections | `utf8mb4` |
-
-* Values without a default value are mandatory, except that
- * only one of `db_password` or `db_passowrd_file` must be set.
-* Only the first line of the file specified by `db_passowrd_file` is read.
+that *User Backend SQL Raw* will connect to. There are two mutually exclusive ways to configure the database connection:
+1. PostgreSQL-like
+ * Set `dsn` (containing user and password) and CAN specify `db_user` and (`db_password` or `db_password_file`). Values in DSN have priority.
+2. MySQL-like
+ * Set `dsn` (not containing user and password) and MUST specify `db_user` and (`db_password` or `db_password_file`).
+
+* `dsn`: check how to construct DSNs for [PostgreSQL](https://www.php.net/manual/en/ref.pdo-pgsql.connection.php) and [MySQL](https://www.php.net/manual/en/ref.pdo-mysql.connection.php) Examples:
+ * connect to PostgreSQL via a socket with ident authentication which requires no user or password at all: `pgsql:host=/var/run/postgresql;dbname=theNameOfYourUserDb`
+ * connect to PostgreSQL via TCP and user/password authentication: `pgsql:host=localhost;port=5432;dbname=theNameOfYourUserDb;user=theNameOfYourDbUser;password=thePasswordForTheDbUser`
+ * connect to MySQL via socket which requires no user or password at all: `mysql:unix_socket=/var/run/mysql/mysql.sock;dbname=theNameOfYourUserDb`
+ * connect to MySQL via TCP and user/password authentication: `mysql:host=localhost;port=3306;dbname=testdb` and then also set `db_user` and (`db_password` or `db_password_file`)
+* `db_user`: Needs only be set for "MySQL-type" databases and is the database user that will be used to connect to the database.
+* `db_password`: Needs only be set for "MySQL-type" databases and is the password for the user that will be used to connect to the database.
+* `db_password_file`: Can be set to read the password from a file. Has higher priority than `db_password`, but lower priority than password in DSN. So, for PostgreSQL-like database connections, don't specify the password in the DSN because it would override this. For MySQL-like connections, this one will have priority.
+ * Only the first line of the file specified by `db_password_file` is read.
* Not more than 100 characters of the first line are read.
- * Whitespace-like characters are [stripped](https://www.php.net/manual/en/function.trim.php) from
+ * Whitespace-like characters are [trimmed](https://www.php.net/manual/en/function.trim.php) from
the beginning and end of the read password.
-* If you specify a socket as `db_host` (only for PostgreSQL), you need to put
- dummy values for the mandatory values, although they are not required for the
- socket connection. This will be fixed in a future release.
+
+For other databases check their [PDO driver documentation pages](https://www.php.net/manual/en/pdo.drivers.php) which in-turn link to their respective DSN references.
### 2. SQL Queries
diff --git a/appinfo/info.xml b/appinfo/info.xml
index d4acb81..b76b455 100644
--- a/appinfo/info.xml
+++ b/appinfo/info.xml
@@ -14,7 +14,7 @@ In contrast to the app *SQL user backend*, you write the SQL queries yourself. Y
The app uses prepared statements and is written to be secure by default to prevent SQL injections. It understands the most popular standards for password hash formats: MD5-CRYPT, SHA256-CRYPT, SHA512-CRYPT, BCrypt and the state-of-the-art Argon2i and Argon2id. Because the various formats are recognized on-the-fly your db can can have differing hash string formats at the same time, which eases migration to newer formats.
This app supports PostgreSQL and MariaDB/MySQL.]]>
- 1.5.1
+ 2.0.0
agpl
Alexey Abel
UserBackendSqlRaw
diff --git a/composer.json b/composer.json
index dbdd2be..449b67a 100644
--- a/composer.json
+++ b/composer.json
@@ -24,10 +24,10 @@
}
},
"require": {
- "php": ">=7.0"
+ "php": ">=8.0"
},
"require-dev": {
- "php": ">=7.3",
+ "php": ">=8.0",
"phpunit/phpunit": "^9"
}
}
\ No newline at end of file
diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php
index ee7d61a..c35e7f2 100644
--- a/lib/AppInfo/Application.php
+++ b/lib/AppInfo/Application.php
@@ -21,6 +21,7 @@
namespace OCA\UserBackendSqlRaw\AppInfo;
+use OCA\UserBackendSqlRaw\Db;
use OCP\AppFramework\Bootstrap\IBootContext;
use OCP\AppFramework\Bootstrap\IBootstrap;
use OCP\AppFramework\Bootstrap\IRegistrationContext;
@@ -49,10 +50,9 @@ public function register(IRegistrationContext $context): void
* Nextcloud's dependency injection is partly explained in:
* https://docs.nextcloud.com/server/latest/developer_manual/basics/dependency_injection.html#how-to-deal-with-interface-and-primitive-type-parameters
*/
- $context->registerService('OCA\UserBackendSqlRaw\Db', function (ContainerInterface $container) {
- /** @var \OCA\UserBackendSqlRaw\Config $config */
- $config = $container->get('OCA\UserBackendSqlRaw\Config');
- return $container->get('OCA\UserBackendSqlRaw\Dbs\\' . ucfirst($config->getDbType()));
+ $context->registerService(OCA\UserBackendSqlRaw\Db::class, function (ContainerInterface $container) {
+ // TODO: can be simplified/removed probably
+ return new OCA\UserBackendSqlRaw\Db();
});
}
diff --git a/lib/Config.php b/lib/Config.php
index 986f681..abfdf12 100644
--- a/lib/Config.php
+++ b/lib/Config.php
@@ -26,25 +26,14 @@
class Config
{
-
- const DEFAULT_DB_TYPE = 'postgresql';
- const DEFAULT_DB_HOST = 'localhost';
- const DEFAULT_POSTGRESQL_PORT = '5432';
- const DEFAULT_MARIADB_PORT = '3306';
- const DEFAULT_MARIADB_CHARSET = 'utf8mb4';
const DEFAULT_HASH_ALGORITHM_FOR_NEW_PASSWORDS = 'bcrypt';
-
const MAXIMUM_ALLOWED_PASSWORD_LENGTH = 100;
const CONFIG_KEY = 'user_backend_sql_raw';
- const CONFIG_KEY_DB_TYPE = 'db_type';
- const CONFIG_KEY_DB_HOST = 'db_host';
- const CONFIG_KEY_DB_PORT = 'db_port';
- const CONFIG_KEY_DB_NAME = 'db_name';
+ const CONFIG_KEY_DSN = 'dsn';
const CONFIG_KEY_DB_USER = 'db_user';
const CONFIG_KEY_DB_PASSWORD = 'db_password';
const CONFIG_KEY_DB_PASSWORD_FILE = 'db_password_file';
- const CONFIG_KEY_MARIADB_CHARSET = 'mariadb_charset';
const CONFIG_KEY_HASH_ALGORITHM_FOR_NEW_PASSWORDS = 'hash_algorithm_for_new_passwords';
const CONFIG_KEY_QUERIES = 'queries';
@@ -81,56 +70,29 @@ public function __construct(LoggerInterface $logger, IConfig $nextCloudConfigura
. self::CONFIG_KEY . ' which should contain the configuration '
. 'for the app user_backend_sql_raw.');
}
- }
-
- /**
- * @return string db type to connect to
- */
- public function getDbType()
- {
- $dbTypeFromConfig = $this->getConfigValueOrDefaultValue(self::CONFIG_KEY_DB_TYPE
- , self::DEFAULT_DB_TYPE);
-
- $normalizedDbType = $this->normalize($dbTypeFromConfig);
-
- if (!$this->dbTypeIsSupported($normalizedDbType)) {
- throw new \UnexpectedValueException('The config key '
- . self::CONFIG_KEY_DB_TYPE . ' is set to ' . $dbTypeFromConfig . '. This '
- . 'value is invalid. Only postgresql and mariadb are supported.');
- }
-
- return $normalizedDbType;
- }
- /**
- * @return string db host to connect to
- */
- public function getDbHost()
- {
- return $this->getConfigValueOrDefaultValue(self::CONFIG_KEY_DB_HOST
- , self::DEFAULT_DB_HOST);
+ $this->warnAboutObsoleteConfigKeys();
}
- /**
- * @return int db port to connect to
- */
- public function getDbPort()
+ public function warnAboutObsoleteConfigKeys()
{
-
- $defaultPortForCurrentDb = ($this->getDbType() === 'mariadb')
- ? self::DEFAULT_MARIADB_PORT
- : self::DEFAULT_POSTGRESQL_PORT;
-
- return $this->getConfigValueOrDefaultValue(self::CONFIG_KEY_DB_PORT
- , $defaultPortForCurrentDb);
+ $obsolete_keys = array("db_type", "db_host", "db_port", "db_name", "mariadb_charset");
+ foreach ($obsolete_keys as $key) {
+ // not using getConfigValueOrFalse() here, because we want to also catch empty strings
+ if (array_key_exists(key: $key, array:$this->appConfiguration)) {
+ $this->logger->warning("The configuration key '{$key}' is obsolete since "
+ . "version 2.0.0. It has no effect and can be removed.");
+ }
+ }
}
/**
- * @return string db name to connect to
+ * @return string dsn to use for db connection
+ * @throws \UnexpectedValueException
*/
- public function getDbName()
+ public function getDsn()
{
- return $this->getConfigValueOrThrowException(self::CONFIG_KEY_DB_NAME);
+ return $this->getConfigValueOrThrowException(self::CONFIG_KEY_DSN);
}
/**
@@ -138,7 +100,7 @@ public function getDbName()
*/
public function getDbUser()
{
- return $this->getConfigValueOrThrowException(self::CONFIG_KEY_DB_USER);
+ return $this->getConfigValueOrFalse(self::CONFIG_KEY_DB_USER);
}
/**
@@ -147,24 +109,17 @@ public function getDbUser()
*/
public function getDbPassword()
{
-
$password = $this->getConfigValueOrFalse(self::CONFIG_KEY_DB_PASSWORD);
$passwordFilePath = $this->getConfigValueOrFalse(self::CONFIG_KEY_DB_PASSWORD_FILE);
$passwordIsSet = $password !== false;
$passwordFileIsSet = $passwordFilePath !== false;
- if ($passwordIsSet === $passwordFileIsSet) { // expression is a "not XOR"
- throw new \UnexpectedValueException('Exactly one of ' . self::CONFIG_KEY_DB_PASSWORD . ' or ' . self::CONFIG_KEY_DB_PASSWORD_FILE . ' must be set (not be empty) in the config.');
- }
-
- if ($passwordIsSet) {
- $this->logger->debug("Will use db password specified directly in config.php.");
- return $password;
- }
-
+ // Password from file (db_password_file) has higher priority than password from config (db_password).
if ($passwordFileIsSet) {
- $this->logger->debug("Will use db password stored in file " . $passwordFilePath) . ".";
+ $this->logger->debug("Will use db password stored in file " . $passwordFilePath)
+ . ". Password from config file will not be considered. Password from DSN still has "
+ ."priority.";
$error_message_prefix = "Specified db password file with path {$passwordFilePath}";
if (!file_exists($passwordFilePath)) {
@@ -189,17 +144,19 @@ public function getDbPassword()
fclose($file);
$this->logger->debug("Successfully read db password from file " . $passwordFilePath) . ".";
return trim($first_line);
+ } elseif ($passwordIsSet) {
+ $this->logger->debug("Will use db password specified in config.php. Password from file"
+ ." was not specified. Password from DSN still has priority.");
+ return $password;
+ } else {
+ return false;
}
- }
+ // Priority of password in the DSN over both passwords read here is
+ // implemented in the PDO implementation of PHP. It will simply ignore
+ // the password given as a parameter during PDO object creation and use
+ // the one from the DSN, if the DSN contains it.
- /**
- * @return string charset for mariadb connection
- */
- public function getMariadbCharset()
- {
- return $this->getConfigValueOrDefaultValue(self::CONFIG_KEY_MARIADB_CHARSET
- , self::DEFAULT_MARIADB_CHARSET);
}
/**
@@ -219,23 +176,6 @@ public function getHashAlgorithmForNewPasswords()
. 'to ' . $hashAlgorithmFromConfig . '. This value is invalid. Only '
. 'md5, sha256, sha512, bcrypt, argon2i and argon2id are supported.');
}
-
- if ($normalizedHashAlgorithm === 'argon2i'
- && version_compare(PHP_VERSION, '7.2.0', '<')) {
- throw new \UnexpectedValueException(
- 'You specified Argon2i as the hash algorithm for new '
- . 'passwords. Argon2i is only available in PHP version 7.2.0 and'
- . ' higher, but your PHP version is ' . PHP_VERSION . '.');
- }
-
- if ($normalizedHashAlgorithm === 'argon2id'
- && version_compare(PHP_VERSION, '7.3.0', '<')) {
- throw new \UnexpectedValueException(
- 'You specified Argon2id as the hash algorithm for new '
- . 'passwords. Argon2id is only available in PHP version 7.3.0 and'
- . ' higher, but your PHP version is ' . PHP_VERSION . '.');
- }
-
return $normalizedHashAlgorithm;
}
@@ -364,16 +304,6 @@ private function getQueryStringOrFalse($configKey)
return $this->getValueOrFalse($queryArray[$configKey] ?? false);
}
- /**
- * @param $dbType string db descriptor to check
- * @return bool whether the db is supported
- */
- private function dbTypeIsSupported($dbType)
- {
- return $dbType === 'postgresql'
- || $dbType === 'mariadb';
- }
-
/**
* Checks whether hash algorithm is supported for writing.
* @param $hashAlgorithm string hash algorithm descriptor to check
@@ -400,4 +330,5 @@ private function normalize($string)
{
return strtolower(preg_replace("/[-_]/", "", $string));
}
+
}
diff --git a/lib/Db.php b/lib/Db.php
index 82345b6..f52c186 100644
--- a/lib/Db.php
+++ b/lib/Db.php
@@ -21,6 +21,8 @@
namespace OCA\UserBackendSqlRaw;
+use OCA\UserBackendSqlRaw\Config;
+use Psr\Log\LoggerInterface;
use \PDO;
/**
@@ -28,7 +30,7 @@
* creation.
* @package OCA\UserBackendSqlRaw
*/
-abstract class Db
+class Db
{
/** @var Config */
protected $config;
@@ -36,8 +38,12 @@ abstract class Db
/** @var PDO */
private $dbHandle;
- public function __construct(Config $config)
+ /* @var LoggerInterface */
+ private $logger;
+
+ public function __construct(LoggerInterface $logger, Config $config)
{
+ $this->logger = $logger;
$this->config = $config;
}
@@ -48,7 +54,6 @@ public function __construct(Config $config)
public function getDbHandle()
{
if (is_null($this->dbHandle)) {
-
$this->dbHandle = $this->createDbHandle();
// Some methods of the backend are called by Nextcloud in a way that
// suppresses exceptions, probably to avoid leaking passwords to log
@@ -64,16 +69,26 @@ public function getDbHandle()
}
/**
- * Returns a new PDO db handle for the specific db type
+ * Returns a new PDO db handle
* @return PDO a new PDO object
*/
- abstract protected function createDbHandle();
-
- /**
- * Returns a Data Source Name (DSN) that is used by a PDO object for
- * creating the connection to a database. This is db specific.
- * @return string the DSN string
- */
- abstract protected function assembleDsn();
+ protected function createDbHandle()
+ {
+ $user = $this->config->getDbUser();
+ $password = $this->config->getDbPassword();
+ if ($user xor $password) {
+ throw new \UnexpectedValueException("You set only one of `db_user` and `db_password`"
+ . " but not the other. You must either set both or none. If none are provided, "
+ . "then both values are read from the DSN.");
+ } elseif ($user and $password) {
+ // for e.g. MySQL
+ return new PDO($this->config->getDsn(), $user, $password);
+ } else {
+ // for e.g. PostgreSQL
+ return new PDO($this->config->getDsn());
+ }
+ throw new \LogicException("This should never happen. If you see this error, please report"
+ . " it as a bug.");
+ }
}
diff --git a/lib/Dbs/Mariadb.php b/lib/Dbs/Mariadb.php
deleted file mode 100644
index d50c5ca..0000000
--- a/lib/Dbs/Mariadb.php
+++ /dev/null
@@ -1,42 +0,0 @@
-
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see .
- *
- */
-
-namespace OCA\UserBackendSqlRaw\Dbs;
-
-use OCA\UserBackendSqlRaw\Db;
-use \PDO;
-
-
-class Mariadb extends Db {
-
- protected function createDbHandle() {
- return new PDO($this->assembleDsn(),
- $this->config->getDbUser(),
- $this->config->getDbPassword());
- }
-
- protected function assembleDsn() {
- return 'mysql:host=' . $this->config->getDbHost()
- . ';port=' . $this->config->getDbPort()
- . ';dbname=' . $this->config->getDbName()
- . ';charset=' . $this->config->getMariadbCharset();
- }
-}
diff --git a/lib/Dbs/Postgresql.php b/lib/Dbs/Postgresql.php
deleted file mode 100644
index 4bab004..0000000
--- a/lib/Dbs/Postgresql.php
+++ /dev/null
@@ -1,40 +0,0 @@
-
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see .
- *
- */
-
-namespace OCA\UserBackendSqlRaw\Dbs;
-
-use OCA\UserBackendSqlRaw\Db;
-use \PDO;
-
-class Postgresql extends Db {
-
- protected function createDbHandle() {
- return new PDO($this->assembleDsn());
- }
-
- protected function assembleDsn() {
- return 'pgsql:host=' . $this->config->getDbHost()
- . ';port=' . $this->config->getDbPort()
- . ';dbname=' . $this->config->getDbName()
- . ';user=' . $this->config->getDbUser()
- . ';password=' . $this->config->getDbPassword();
- }
-}
\ No newline at end of file
diff --git a/tests/Dbs/SqliteMemoryTestDb.php b/tests/Dbs/SqliteMemoryTestDb.php
index ba2d238..00a6400 100644
--- a/tests/Dbs/SqliteMemoryTestDb.php
+++ b/tests/Dbs/SqliteMemoryTestDb.php
@@ -28,10 +28,10 @@ class SqliteMemoryTestDb extends Db
{
protected function createDbHandle()
{
- return new PDO($this->assembleDsn());
+ return new PDO($this->getDsn());
}
- protected function assembleDsn()
+ protected function getDsn()
{
return 'sqlite::memory:';
}
diff --git a/tests/Unit/ConfigTest.php b/tests/Unit/ConfigTest.php
index c797750..7f23fa5 100644
--- a/tests/Unit/ConfigTest.php
+++ b/tests/Unit/ConfigTest.php
@@ -59,105 +59,19 @@ public function testThrowsExceptionIfMandatorySettingIsNotSet()
$this->expectException(\UnexpectedValueException::class);
$config = new Config($this->logStub, $this->nextcloudConfigStub);
- $config->getDbName();
+ $config->getDsn();
}
public function testThrowsExceptionIfMandatorySettingIsEmpty()
{
$this->nextcloudConfigStub->method('getSystemValue')
->willReturn(array(
- 'db_name' => '',
+ 'dsn' => '',
));
$this->expectException(\UnexpectedValueException::class);
$config = new Config($this->logStub, $this->nextcloudConfigStub);
- $config->getDbName();
- }
-
- public function testThrowsExceptionIfDbPasswordAndDbPasswordFileAreBothSet()
- {
- $this->nextcloudConfigStub->method('getSystemValue')
- ->willReturn(array(
- 'db_password' => 'such_secret',
- // Specify a file that is always there, so that test does not fail due to missing db password file.
- 'db_password_file' => '/dev/zero',
- ));
-
- $this->expectException(\UnexpectedValueException::class);
- $config = new Config($this->logStub, $this->nextcloudConfigStub);
- $config->getDbPassword();
- }
-
- // Tests that check if default values are uses correctly
-
- public function testDefaultDbTypeIsUsedWhenThatParameterIsNotSet()
- {
- $this->nextcloudConfigStub->method('getSystemValue')
- ->willReturn(array(
- 'the_configuration_is_not_empty' => 'but also contains no usable keys',
- ));
-
- $config = new Config($this->logStub, $this->nextcloudConfigStub);
-
- $expectedDbType = Config::DEFAULT_DB_TYPE;
- $actualDbType = $config->getDbType();
- self::assertEquals($expectedDbType, $actualDbType);
- }
-
- public function testDefaultHostIsUsedWhenThisParameterIsNotSet()
- {
- $this->nextcloudConfigStub->method('getSystemValue')
- ->willReturn(array(
- 'the_configuration_is_not_empty' => 'but also contains no usable keys',
- ));
-
- $config = new Config($this->logStub, $this->nextcloudConfigStub);
-
- $expectedHost = Config::DEFAULT_DB_HOST;
- $actualHost = $config->getDbHost();
- self::assertEquals($expectedHost, $actualHost);
- }
-
- public function testDefaultPostgresqlPortIsUsedWhenThisParameterIsNotSet()
- {
- $this->nextcloudConfigStub->method('getSystemValue')
- ->willReturn(array(
- 'the_configuration_is_not_empty' => 'but also contains no usable keys',
- ));
-
- $config = new Config($this->logStub, $this->nextcloudConfigStub);
-
- $expectedPort = Config::DEFAULT_POSTGRESQL_PORT;
- $actualPort = $config->getDbPort();
- self::assertEquals($expectedPort, $actualPort);
- }
-
- public function testDefaultMariaPortIsUsedWhenThisParameterIsNotSet()
- {
- $this->nextcloudConfigStub->method('getSystemValue')
- ->willReturn(array(
- 'db_type' => 'mariadb',
- ));
-
- $config = new Config($this->logStub, $this->nextcloudConfigStub);
-
- $expectedPort = Config::DEFAULT_MARIADB_PORT;
- $actualPort = $config->getDbPort();
- self::assertEquals($expectedPort, $actualPort);
- }
-
- public function testDefaultMariadbCharsetIsUsedWhenThisParameterIsNotSet()
- {
- $this->nextcloudConfigStub->method('getSystemValue')
- ->willReturn(array(
- 'the_configuration_is_not_empty' => 'but also contains no usable keys',
- ));
-
- $config = new Config($this->logStub, $this->nextcloudConfigStub);
-
- $expectedCharset = Config::DEFAULT_MARIADB_CHARSET;
- $actualCharset = $config->getMariadbCharset();
- self::assertEquals($expectedCharset, $actualCharset);
+ $config->getDsn();
}
public function testDefaultHashAlgorithmForNewPasswordsIsUsedWhenThisParameterIsNotSet()
@@ -191,60 +105,32 @@ public function testEmptyQueryParameterReturnsFalse()
// Tests that check if actual (non-default) values are returned
- public function testDbTypeIsReturnedWhenThisParameterIsSet()
- {
- $this->nextcloudConfigStub->method('getSystemValue')
- ->willReturn(array(
- 'db_type' => 'mariadb',
- ));
-
- $config = new Config($this->logStub, $this->nextcloudConfigStub);
-
- $expectedDbType = 'mariadb';
- $actualDbType = $config->getDbType();
- self::assertEquals($expectedDbType, $actualDbType);
- }
-
- public function testDbHostDomainNameIsReturnedWhenThisParameterIsSet()
- {
- $this->nextcloudConfigStub->method('getSystemValue')
- ->willReturn(array(
- 'db_host' => 'nextcloud.mycompany.com',
- ));
-
- $config = new Config($this->logStub, $this->nextcloudConfigStub);
-
- $expectedHost = 'nextcloud.mycompany.com';
- $actualHost = $config->getDbHost();
- self::assertEquals($expectedHost, $actualHost);
- }
-
- public function testDbHostIpIsReturnedWhenThisParameterIsSet()
+ public function testDsnIsReturnedWhenThisParameterIsSet()
{
$this->nextcloudConfigStub->method('getSystemValue')
->willReturn(array(
- 'db_host' => '43.100.4.0',
+ 'dsn' => 'pgsql:host=/var/run/postgresql;dbname=theName_OfYourUserDb',
));
$config = new Config($this->logStub, $this->nextcloudConfigStub);
- $expectedHost = '43.100.4.0';
- $actualHost = $config->getDbHost();
- self::assertEquals($expectedHost, $actualHost);
+ $expectedDsn = 'pgsql:host=/var/run/postgresql;dbname=theName_OfYourUserDb';
+ $actualDsn = $config->getDsn();
+ self::assertEquals($expectedDsn, $actualDsn);
}
- public function testDbPortIsReturnedWhenThisParameterIsSet()
+ public function testPasswordIsReturnedWhenThisParameterIsSet()
{
+ $expectedPassword = '!I_am V-e rySecr3t9!&äßZ';
$this->nextcloudConfigStub->method('getSystemValue')
->willReturn(array(
- 'db_port' => '54321',
+ 'db_password' => $expectedPassword,
));
$config = new Config($this->logStub, $this->nextcloudConfigStub);
- $expectedPort = '54321';
- $actualPort = $config->getDbPort();
- self::assertEquals($expectedPort, $actualPort);
+ $actualPassword = $config->getDbPassword();
+ self::assertEquals($expectedPassword, $actualPassword);
}
public function testDBPasswordFromPasswordFileIsReturned()
@@ -252,12 +138,12 @@ public function testDBPasswordFromPasswordFileIsReturned()
$expectedPassword = 'v_erY-secr3ttt 909!&äßZ';
- $db_password_file = tempnam("/tmp", "user_backend_sql_raw-db_password_file");
- if ($db_password_file === false) {
+ $dbPasswordFile = tempnam("/tmp", "user_backend_sql_raw-db_password_file");
+ if ($dbPasswordFile === false) {
self::fail("Temporary db password file could not be created.");
}
- $file = fopen($db_password_file, "w");
+ $file = fopen($dbPasswordFile, "w");
if ($file === false) {
self::fail("Temporary db password file could not be opened for writing.");
}
@@ -267,27 +153,27 @@ public function testDBPasswordFromPasswordFileIsReturned()
$this->nextcloudConfigStub->method('getSystemValue')
->willReturn(array(
- 'db_password_file' => $db_password_file,
+ 'db_password_file' => $dbPasswordFile,
));
$config = new Config($this->logStub, $this->nextcloudConfigStub);
$actualPassword = $config->getDbPassword();
- unlink($db_password_file);
+ unlink($dbPasswordFile);
self::assertEquals($expectedPassword, $actualPassword);
}
- public function testDBPasswordFromPasswordFileIsTrimmed()
- {
+ public function testDBPasswordFromPasswordFileIsTrimmed()
+ {
$expectedPassword = 'secret';
- $db_password_file = tempnam("/tmp", "user_backend_sql_raw-db_password_file");
- if ($db_password_file === false) {
+ $dbPasswordFile = tempnam("/tmp", "user_backend_sql_raw-db_password_file");
+ if ($dbPasswordFile === false) {
self::fail("Temporary db password file could not be created.");
}
- $file = fopen($db_password_file, "w");
+ $file = fopen($dbPasswordFile, "w");
if ($file === false) {
self::fail("Temporary db password file could not be opened for writing.");
}
@@ -298,28 +184,45 @@ public function testDBPasswordFromPasswordFileIsTrimmed()
$this->nextcloudConfigStub->method('getSystemValue')
->willReturn(array(
- 'db_password_file' => $db_password_file,
+ 'db_password_file' => $dbPasswordFile,
));
$config = new Config($this->logStub, $this->nextcloudConfigStub);
$actualPassword = $config->getDbPassword();
- unlink($db_password_file);
+ unlink($dbPasswordFile);
self::assertEquals($expectedPassword, $actualPassword);
}
- public function testMariaDbCharsetIsReturnedWhenThisParameterIsSet()
+ public function testPasswordFromPasswordFileOverridesPasswordFromConfig()
{
+ $passwordFromFile = 'password_from_file';
+ $passwordFromConfig = 'password_from_config';
+
+ $dbPasswordFile = tempnam("/tmp", "user_backend_sql_raw-db_password_file");
+ if ($dbPasswordFile === false) {
+ self::fail("Temporary db password file could not be created.");
+ }
+
+ $file = fopen($dbPasswordFile, "w");
+ if ($file === false) {
+ self::fail("Temporary db password file could not be opened for writing.");
+ }
+
+ fwrite($file, "{$passwordFromFile}");
+ fclose($file);
+
$this->nextcloudConfigStub->method('getSystemValue')
->willReturn(array(
- 'mariadb_charset' => 'latin2_czech_cs',
+ 'db_password' => $passwordFromConfig,
+ 'db_password_file' => $dbPasswordFile,
));
$config = new Config($this->logStub, $this->nextcloudConfigStub);
- $expectedCharset = 'latin2_czech_cs';
- $actualCharset = $config->getMariadbCharset();
- self::assertEquals($expectedCharset, $actualCharset);
+ $actualPassword = $config->getDbPassword();
+ unlink($dbPasswordFile);
+ self::assertEquals($passwordFromFile, $actualPassword);
}
public function testHashAlgorithmForNewPasswordsIsReturnedWhenThisParameterIsSet()
@@ -352,7 +255,7 @@ public function testQueryIsReturnedWhenItIsSet()
self::assertEquals($expectedQuery, $actualReturnValue);
}
- // Test that check whether invalid values four countable types are
+ // Tests that check whether invalid values for countable types are
// recognized
public function testExceptionIsThrownForUnsupportedHashAlgorithmForNewPasswords()
@@ -364,33 +267,20 @@ public function testExceptionIsThrownForUnsupportedHashAlgorithmForNewPasswords(
$this->expectException(\UnexpectedValueException::class);
$config = new Config($this->logStub, $this->nextcloudConfigStub);
- $config->getDbPassword();
- }
-
- public function testExceptionIsThrownForUnsupportedDbType()
- {
- $this->nextcloudConfigStub->method('getSystemValue')
- ->willReturn(array(
- 'db_type' => 'oracle',
- ));
-
- $this->expectException(\UnexpectedValueException::class);
- $config = new Config($this->logStub, $this->nextcloudConfigStub);
- $config->getDbType();
+ $config->getHashAlgorithmForNewPasswords();
}
// Test that checks if multiple parameters are recognized simultaneously.
// Previous tests only tested single parameters.
public function testMultipleParametersAreRecognizedSimultaneously()
{
+ $expectedDsn = 'pgsql:host=/var/run/postgresql;dbname=theName_OfYourUserDb';
+ $expectedPassword = '!me SoSec35?äöß1';
// db_type will be left empty to test default value
$this->nextcloudConfigStub->method('getSystemValue')
->willReturn(array(
- 'db_type' => '',
- 'db_port' => '4567',
- 'db_user' => 'JohnDoe',
- 'db_password' => 'bpd_N(z6%aT&$ 'db.cluster.de',
+ 'dsn' => $expectedDsn,
+ 'db_password' => $expectedPassword,
'queries' => array(
'user_exists' => 'SELECT EXISTS(SELECT 1 FROM virtual_users_fqda WHERE fqda = :username)',
'create_user' => 'INSERT INTO virtual_users (local, domain, password_hash) VALUES (split_part(:username, \'@\', 1), split_part(:username, \'@\', 2), :password_hash)',
@@ -400,11 +290,8 @@ public function testMultipleParametersAreRecognizedSimultaneously()
$config = new Config($this->logStub, $this->nextcloudConfigStub);
- self::assertEquals('postgresql', $config->getDbType());
- self::assertEquals('4567', $config->getDbPort());
- self::assertEquals('JohnDoe', $config->getDbUser());
- self::assertEquals('bpd_N(z6%aT&$getDbPassword());
- self::assertEquals('db.cluster.de', $config->getDbHost());
+ self::assertEquals($expectedDsn, $config->getDsn());
+ self::assertEquals($expectedPassword, $config->getDbPassword());
self::assertEquals(
'SELECT EXISTS(SELECT 1 FROM virtual_users_fqda WHERE fqda = :username)'
, $config->getQueryUserExists());