AbstractDatabase.php 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. <?php
  2. /**
  3. * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
  4. * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
  5. * SPDX-License-Identifier: AGPL-3.0-only
  6. */
  7. namespace OC\Setup;
  8. use OC\DB\Connection;
  9. use OC\DB\ConnectionFactory;
  10. use OC\DB\MigrationService;
  11. use OC\SystemConfig;
  12. use OCP\IL10N;
  13. use OCP\Migration\IOutput;
  14. use OCP\Security\ISecureRandom;
  15. use Psr\Log\LoggerInterface;
  16. abstract class AbstractDatabase {
  17. /** @var IL10N */
  18. protected $trans;
  19. /** @var string */
  20. protected $dbUser;
  21. /** @var string */
  22. protected $dbPassword;
  23. /** @var string */
  24. protected $dbName;
  25. /** @var string */
  26. protected $dbHost;
  27. /** @var string */
  28. protected $dbPort;
  29. /** @var string */
  30. protected $tablePrefix;
  31. /** @var SystemConfig */
  32. protected $config;
  33. /** @var LoggerInterface */
  34. protected $logger;
  35. /** @var ISecureRandom */
  36. protected $random;
  37. /** @var bool */
  38. protected $tryCreateDbUser;
  39. public function __construct(IL10N $trans, SystemConfig $config, LoggerInterface $logger, ISecureRandom $random) {
  40. $this->trans = $trans;
  41. $this->config = $config;
  42. $this->logger = $logger;
  43. $this->random = $random;
  44. }
  45. public function validate($config) {
  46. $errors = [];
  47. if (empty($config['dbuser']) && empty($config['dbname'])) {
  48. $errors[] = $this->trans->t('Enter the database Login and name for %s', [$this->dbprettyname]);
  49. } elseif (empty($config['dbuser'])) {
  50. $errors[] = $this->trans->t('Enter the database Login for %s', [$this->dbprettyname]);
  51. } elseif (empty($config['dbname'])) {
  52. $errors[] = $this->trans->t('Enter the database name for %s', [$this->dbprettyname]);
  53. }
  54. if (substr_count($config['dbname'], '.') >= 1) {
  55. $errors[] = $this->trans->t('You cannot use dots in the database name %s', [$this->dbprettyname]);
  56. }
  57. return $errors;
  58. }
  59. public function initialize($config) {
  60. $dbUser = $config['dbuser'];
  61. $dbPass = $config['dbpass'];
  62. $dbName = $config['dbname'];
  63. $dbHost = !empty($config['dbhost']) ? $config['dbhost'] : 'localhost';
  64. $dbPort = !empty($config['dbport']) ? $config['dbport'] : '';
  65. $dbTablePrefix = $config['dbtableprefix'] ?? 'oc_';
  66. $createUserConfig = $this->config->getValue('setup_create_db_user', true);
  67. // accept `false` both as bool and string, since setting config values from env will result in a string
  68. $this->tryCreateDbUser = $createUserConfig !== false && $createUserConfig !== 'false';
  69. $this->config->setValues([
  70. 'dbname' => $dbName,
  71. 'dbhost' => $dbHost,
  72. 'dbport' => $dbPort,
  73. 'dbtableprefix' => $dbTablePrefix,
  74. ]);
  75. $this->dbUser = $dbUser;
  76. $this->dbPassword = $dbPass;
  77. $this->dbName = $dbName;
  78. $this->dbHost = $dbHost;
  79. $this->dbPort = $dbPort;
  80. $this->tablePrefix = $dbTablePrefix;
  81. }
  82. /**
  83. * @param array $configOverwrite
  84. * @return \OC\DB\Connection
  85. */
  86. protected function connect(array $configOverwrite = []): Connection {
  87. $connectionParams = [
  88. 'host' => $this->dbHost,
  89. 'user' => $this->dbUser,
  90. 'password' => $this->dbPassword,
  91. 'tablePrefix' => $this->tablePrefix,
  92. 'dbname' => $this->dbName
  93. ];
  94. // adding port support through installer
  95. if (!empty($this->dbPort)) {
  96. if (ctype_digit($this->dbPort)) {
  97. $connectionParams['port'] = $this->dbPort;
  98. } else {
  99. $connectionParams['unix_socket'] = $this->dbPort;
  100. }
  101. } elseif (strpos($this->dbHost, ':')) {
  102. // Host variable may carry a port or socket.
  103. [$host, $portOrSocket] = explode(':', $this->dbHost, 2);
  104. if (ctype_digit($portOrSocket)) {
  105. $connectionParams['port'] = $portOrSocket;
  106. } else {
  107. $connectionParams['unix_socket'] = $portOrSocket;
  108. }
  109. $connectionParams['host'] = $host;
  110. }
  111. $connectionParams = array_merge($connectionParams, $configOverwrite);
  112. $connectionParams = array_merge($connectionParams, ['primary' => $connectionParams, 'replica' => [$connectionParams]]);
  113. $cf = new ConnectionFactory($this->config);
  114. $connection = $cf->getConnection($this->config->getValue('dbtype', 'sqlite'), $connectionParams);
  115. $connection->ensureConnectedToPrimary();
  116. return $connection;
  117. }
  118. /**
  119. * @param string $username
  120. */
  121. abstract public function setupDatabase($username);
  122. public function runMigrations(?IOutput $output = null) {
  123. if (!is_dir(\OC::$SERVERROOT . '/core/Migrations')) {
  124. return;
  125. }
  126. $ms = new MigrationService('core', \OC::$server->get(Connection::class), $output);
  127. $ms->migrate('latest', true);
  128. }
  129. }