mirror of
https://github.com/humhub/humhub.git
synced 2025-01-16 21:58:17 +01:00
Enh: Attempt to show better error messages when DB-Connection is invalid
This commit is contained in:
parent
28fa6d9485
commit
582a2cac6c
@ -1,6 +1,10 @@
|
||||
HumHub Changelog
|
||||
================
|
||||
|
||||
1.16.0 (Unreleased)
|
||||
--------------------------
|
||||
- Enh #6512: Show error messages when DB connection configuration is invalid
|
||||
|
||||
1.15.0-beta.2 (Unreleased)
|
||||
--------------------------
|
||||
- Enh #6478: Add pseudo test class to allow population of DB with standard test data
|
||||
|
10
index.php
10
index.php
@ -7,6 +7,8 @@
|
||||
*/
|
||||
|
||||
// comment out the following two lines when deployed to production
|
||||
use humhub\helpers\DatabaseHelper;
|
||||
|
||||
defined('YII_DEBUG') or define('YII_DEBUG', true);
|
||||
defined('YII_ENV') or define('YII_ENV', 'dev');
|
||||
|
||||
@ -22,4 +24,10 @@ $config = yii\helpers\ArrayHelper::merge(
|
||||
require(__DIR__ . '/protected/config/web.php')
|
||||
);
|
||||
|
||||
(new humhub\components\Application($config))->run();
|
||||
try {
|
||||
(new humhub\components\Application($config))->run();
|
||||
} catch (\Throwable $ex) {
|
||||
if (null === DatabaseHelper::handleConnectionErrors($ex)) {
|
||||
throw $ex;
|
||||
}
|
||||
}
|
||||
|
@ -9,6 +9,7 @@
|
||||
namespace humhub\commands;
|
||||
|
||||
use humhub\components\Module;
|
||||
use humhub\helpers\DatabaseHelper;
|
||||
use Yii;
|
||||
use yii\console\Exception;
|
||||
use yii\web\Application;
|
||||
@ -78,9 +79,17 @@ class MigrateController extends \yii\console\controllers\MigrateController
|
||||
*/
|
||||
public function beforeAction($action)
|
||||
{
|
||||
// Make sure to define default table storage engine
|
||||
if (in_array(Yii::$app->db->getDriverName(), ['mysql', 'mysqli'], true)) {
|
||||
Yii::$app->db->pdo->exec('SET default_storage_engine=' . Yii::$app->params['databaseDefaultStorageEngine']);
|
||||
// Make sure to define a default table storage engine
|
||||
$db = Yii::$app->db;
|
||||
|
||||
try {
|
||||
$db->open();
|
||||
} catch (\Throwable $ex) {
|
||||
DatabaseHelper::handleConnectionErrors($ex);
|
||||
}
|
||||
|
||||
if (in_array($db->getDriverName(), ['mysql', 'mysqli'], true)) {
|
||||
$db->pdo->exec('SET default_storage_engine=' . Yii::$app->params['databaseDefaultStorageEngine']);
|
||||
}
|
||||
return parent::beforeAction($action);
|
||||
}
|
||||
|
@ -59,7 +59,7 @@ class Application extends \yii\console\Application implements \humhub\interfaces
|
||||
));
|
||||
}
|
||||
|
||||
if (BaseSettingsManager::isDatabaseInstalled()) {
|
||||
if (BaseSettingsManager::isDatabaseInstalled(Yii::$app->params['databaseInstalled'] ?? false)) {
|
||||
$baseUrl = Yii::$app->settings->get('baseUrl');
|
||||
if (!empty($baseUrl)) {
|
||||
if (Yii::getAlias('@web', false) === false) {
|
||||
|
147
protected/humhub/helpers/DatabaseHelper.php
Normal file
147
protected/humhub/helpers/DatabaseHelper.php
Normal file
@ -0,0 +1,147 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* @link https://www.humhub.org/
|
||||
* @copyright Copyright (c) 2017-2023 HumHub GmbH & Co. KG
|
||||
* @license https://www.humhub.com/licences
|
||||
*/
|
||||
|
||||
namespace humhub\helpers;
|
||||
|
||||
use Throwable;
|
||||
use Yii;
|
||||
|
||||
/**
|
||||
* @since 1.15
|
||||
*/
|
||||
class DatabaseHelper
|
||||
{
|
||||
public static function handleConnectionErrors(
|
||||
Throwable $ex,
|
||||
bool $print = true,
|
||||
bool $die = true,
|
||||
bool $forcePlainText = false
|
||||
): ?string {
|
||||
static $last = false;
|
||||
|
||||
if (!$ex instanceof \yii\db\Exception) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($last) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$last = true;
|
||||
|
||||
$trace = debug_backtrace(0);
|
||||
$trace = end($trace);
|
||||
if ($trace && $trace['function'] === 'handleException' && $trace['args'][0] instanceof \yii\db\Exception) {
|
||||
return null;
|
||||
}
|
||||
|
||||
switch ($ex->getCode()) {
|
||||
case 2002:
|
||||
$error = 'Hostname not found.';
|
||||
break;
|
||||
|
||||
case 1044:
|
||||
$error = 'Database not found or not accessible.';
|
||||
break;
|
||||
|
||||
case 1049:
|
||||
$error = 'Database not found.';
|
||||
break;
|
||||
|
||||
default:
|
||||
$error = $ex->getMessage();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see https://www.php.net/manual/en/ref.pdo-odbc.connection.php
|
||||
* @see https://www.php.net/manual/en/ref.pdo-ibm.connection.php
|
||||
* @see https://www.php.net/manual/en/ref.pdo-pgsql.connection.php
|
||||
*/
|
||||
$dsn = preg_replace(
|
||||
'@((?<=:|;)(?:user|uid|User ID|pwd|password)=)(.*?)(?=;(?:$|\w+=)|$)@i',
|
||||
'$1****',
|
||||
Yii::$app->db->dsn
|
||||
);
|
||||
|
||||
try {
|
||||
$additionalInfo = json_encode([get_class($ex), ...$ex->errorInfo], JSON_THROW_ON_ERROR);
|
||||
} catch (\JsonException $e) {
|
||||
$additionalInfo = 'N/A';
|
||||
}
|
||||
|
||||
while ($ex->getPrevious()) {
|
||||
$ex = $ex->getPrevious();
|
||||
}
|
||||
|
||||
$htmlMessage = defined('YII_DEBUG') && YII_DEBUG
|
||||
? sprintf('
|
||||
<h1>Invalid database configuration</h1>
|
||||
<p><strong>%s</strong></p>
|
||||
<p>The following connection string was used:<br><code>%s</code></p>
|
||||
<br>
|
||||
<h2>Technical information</h2>
|
||||
<p><code>%s</code></p>
|
||||
<p><pre>%s</pre></p>
|
||||
', $error, $dsn, $additionalInfo, $ex)
|
||||
: sprintf('
|
||||
<h1>Invalid database configuration</h1>
|
||||
<p><strong>%s</strong></p>
|
||||
', $error);
|
||||
|
||||
$txtMessage = defined('YII_DEBUG') && YII_DEBUG
|
||||
? sprintf('
|
||||
Invalid database configuration
|
||||
==============================
|
||||
|
||||
%s
|
||||
|
||||
The following connection string was used:
|
||||
%s
|
||||
|
||||
|
||||
Technical information
|
||||
---------------------
|
||||
%s
|
||||
|
||||
%s
|
||||
|
||||
', $error, $dsn, $additionalInfo, $ex)
|
||||
: sprintf('
|
||||
Invalid database configuration
|
||||
==============================
|
||||
|
||||
%s
|
||||
|
||||
The following connection string was used:
|
||||
%s
|
||||
|
||||
|
||||
Technical information
|
||||
---------------------
|
||||
%s
|
||||
|
||||
', $error, $dsn, $additionalInfo);
|
||||
|
||||
if ($print) {
|
||||
if ($forcePlainText) {
|
||||
echo $txtMessage;
|
||||
} elseif (Yii::$app instanceof \yii\console\Application && Yii::$app->controller instanceof \yii\console\Controller) {
|
||||
Yii::$app->controller->stderr($txtMessage);
|
||||
} else {
|
||||
header("HTTP/1.1 500 Internal Server Error");
|
||||
echo $htmlMessage;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$die) {
|
||||
return $txtMessage;
|
||||
}
|
||||
|
||||
die(1);
|
||||
}
|
||||
}
|
@ -10,12 +10,12 @@ namespace humhub\libs;
|
||||
|
||||
use humhub\components\SettingActiveRecord;
|
||||
use humhub\exceptions\InvalidArgumentTypeException;
|
||||
use humhub\helpers\DatabaseHelper;
|
||||
use Stringable;
|
||||
use Yii;
|
||||
use yii\base\Component;
|
||||
use yii\base\InvalidArgumentException;
|
||||
use yii\base\InvalidConfigException;
|
||||
use yii\db\conditions\LikeCondition;
|
||||
use yii\db\StaleObjectException;
|
||||
use yii\helpers\Json;
|
||||
|
||||
@ -303,19 +303,20 @@ abstract class BaseSettingsManager extends Component
|
||||
/**
|
||||
* Checks if settings table exists or application is not installed yet
|
||||
*
|
||||
* @return bool
|
||||
* @since 1.3
|
||||
*/
|
||||
public static function isDatabaseInstalled()
|
||||
public static function isDatabaseInstalled(bool $dieOnError = false): bool
|
||||
{
|
||||
try {
|
||||
if (in_array('setting', Yii::$app->db->schema->getTableNames())) {
|
||||
return true;
|
||||
}
|
||||
$db = Yii::$app->db;
|
||||
$db->open();
|
||||
} catch (\Exception $ex) {
|
||||
if ($dieOnError) {
|
||||
DatabaseHelper::handleConnectionErrors($ex);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
return in_array('setting', $db->schema->getTableNames());
|
||||
}
|
||||
}
|
||||
|
@ -8,27 +8,28 @@
|
||||
|
||||
namespace humhub\modules\installer\commands;
|
||||
|
||||
use humhub\helpers\DatabaseHelper;
|
||||
use humhub\libs\DynamicConfig;
|
||||
use humhub\libs\UUID;
|
||||
use humhub\modules\installer\libs\InitialData;
|
||||
use humhub\modules\user\models\Group;
|
||||
use humhub\modules\user\models\Password;
|
||||
use humhub\modules\user\models\User;
|
||||
use Yii;
|
||||
use yii\base\Exception;
|
||||
use yii\console\Controller;
|
||||
use yii\console\ExitCode;
|
||||
use yii\helpers\Console;
|
||||
use yii\base\Exception;
|
||||
use humhub\modules\user\models\User;
|
||||
use humhub\modules\user\models\Password;
|
||||
use humhub\modules\user\models\Group;
|
||||
use humhub\modules\installer\libs\InitialData;
|
||||
use humhub\libs\UUID;
|
||||
use humhub\libs\DynamicConfig;
|
||||
|
||||
/**
|
||||
* Console Install
|
||||
*
|
||||
*
|
||||
* Example usage:
|
||||
* php yii installer/write-db-config "$HUMHUB_DB_HOST" "$HUMHUB_DB_NAME" "$HUMHUB_DB_USER" "$HUMHUB_DB_PASSWORD"
|
||||
* php yii installer/install-db
|
||||
* php yii installer/write-site-config "$HUMHUB_NAME" "$HUMHUB_EMAIL"
|
||||
* php yii installer/create-admin-account
|
||||
*
|
||||
*
|
||||
*/
|
||||
class InstallController extends Controller
|
||||
{
|
||||
@ -42,9 +43,9 @@ class InstallController extends Controller
|
||||
|
||||
return ExitCode::OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tries to open a connection to given db.
|
||||
* Tries to open a connection to given db.
|
||||
* On success: Writes given settings to config-file and reloads it.
|
||||
* On failure: Throws exception
|
||||
*/
|
||||
@ -80,12 +81,12 @@ class InstallController extends Controller
|
||||
$this->stdout("Install DB:\n\n", Console::FG_YELLOW);
|
||||
|
||||
$this->stdout(" * Checking Database Connection\n", Console::FG_YELLOW);
|
||||
if(!$this->checkDBConnection()){
|
||||
throw new Exception("Could not connect to DB!");
|
||||
if (true !== $message = $this->checkDBConnection()) {
|
||||
throw new Exception($message ?? "Could not connect to DB!");
|
||||
}
|
||||
|
||||
$this->stdout(" * Installing Database\n", Console::FG_YELLOW);
|
||||
|
||||
|
||||
Yii::$app->cache->flush();
|
||||
// Disable max execution time to avoid timeouts during migrations
|
||||
@ini_set('max_execution_time', 0);
|
||||
@ -119,7 +120,7 @@ class InstallController extends Controller
|
||||
$user->profile->firstname = 'Sys';
|
||||
$user->profile->lastname = 'Admin';
|
||||
$user->profile->save();
|
||||
|
||||
|
||||
$password = new Password();
|
||||
$password->user_id = $user->id;
|
||||
$password->setPassword($admin_pass);
|
||||
@ -179,6 +180,8 @@ class InstallController extends Controller
|
||||
|
||||
/**
|
||||
* Tries to open global db connection and checks result.
|
||||
*
|
||||
* @return true|null|string
|
||||
*/
|
||||
private function checkDBConnection()
|
||||
{
|
||||
@ -186,10 +189,9 @@ class InstallController extends Controller
|
||||
// call setActive with true to open connection.
|
||||
Yii::$app->db->open();
|
||||
// return the current connection state.
|
||||
return Yii::$app->db->getIsActive();
|
||||
return Yii::$app->db->getIsActive() ?: null;
|
||||
} catch (Exception $e) {
|
||||
$this->stderr($e->getMessage());
|
||||
return DatabaseHelper::handleConnectionErrors($e, false, false, true);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -8,6 +8,8 @@
|
||||
* @license http://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
use humhub\helpers\DatabaseHelper;
|
||||
|
||||
defined('YII_DEBUG') or define('YII_DEBUG', true);
|
||||
|
||||
// fcgi doesn't have STDIN and STDOUT defined by default
|
||||
@ -25,6 +27,11 @@ $config = yii\helpers\ArrayHelper::merge(
|
||||
require(__DIR__ . '/config/console.php')
|
||||
);
|
||||
|
||||
$application = new humhub\components\console\Application($config);
|
||||
$exitCode = $application->run();
|
||||
exit($exitCode);
|
||||
try {
|
||||
$exitCode = (new humhub\components\console\Application($config))->run();
|
||||
exit($exitCode);
|
||||
} catch (\Throwable $ex) {
|
||||
if (null === DatabaseHelper::handleConnectionErrors($ex)) {
|
||||
throw $ex;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user