Skip to content

Commit

Permalink
Enh: Attempt to show better error messages when DB-Connection is invalid
Browse files Browse the repository at this point in the history
  • Loading branch information
martin-rueegg committed Aug 15, 2023
1 parent 31f2cd4 commit 0a05d3e
Show file tree
Hide file tree
Showing 7 changed files with 133 additions and 29 deletions.
1 change: 1 addition & 0 deletions CHANGELOG-DEV.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ HumHub Changelog

1.15.0-beta.2 (Unreleased)
--------------------------
- Enh #6512: Show error messages when DB connection configuration is invalid
- Enh #6505: Introduce Application interface; now also fire the `onInit` event when the web application has initialized
- Fix #6502: Link notification for pending space approval to manage page
- Fix #6472: Initialization of account profile field type "Markdown"
Expand Down
15 changes: 12 additions & 3 deletions protected/humhub/commands/MigrateController.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
namespace humhub\commands;

use humhub\components\Module;
use humhub\libs\Helpers;
use Yii;
use yii\console\Exception;
use yii\web\Application;
Expand Down Expand Up @@ -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) {
Helpers::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);
}
Expand Down
2 changes: 1 addition & 1 deletion protected/humhub/components/console/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ public function init()
));
}

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) {
Expand Down
13 changes: 7 additions & 6 deletions protected/humhub/libs/BaseSettingsManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -303,19 +303,20 @@ public function deleteAll($prefix = null)
/**
* 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) {
Helpers::handleConnectionErrors($ex);
}
return false;
}

return false;
return in_array('setting', $db->schema->getTableNames());
}
}
93 changes: 92 additions & 1 deletion protected/humhub/libs/Helpers.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@

namespace humhub\libs;

use humhub\components\Application;
use Throwable;
use Yii;
use yii\base\InvalidArgumentException;
use yii\base\Exception;
Expand All @@ -19,7 +21,6 @@
*/
class Helpers
{

/**
* Shorten a text string
*
Expand Down Expand Up @@ -264,4 +265,94 @@ public static function SqlMode($event)
}
}

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;

default:
$error = $ex->getMessage();
}

if (!$forcePlainText && Yii::$app instanceof Application) {
header("HTTP/1.1 500 Internal Server Error");
$template = '
<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>
';
} else {
$template = '
Invalid database configuration
==============================
%s
The following connection string was used:
%s
Technical information
---------------------
%s
%s
';
}

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();
}

$message = sprintf($template, $error, Yii::$app->db->dsn, $additionalInfo, $ex);

if ($print) {
if (Yii::$app instanceof \yii\console\Application && Yii::$app->controller instanceof \yii\console\Controller) {
Yii::$app->controller->stderr($message);
} else {
echo $message;
}
}

if (!$die) {
return $message;
}

die(1);
}
}
24 changes: 13 additions & 11 deletions protected/humhub/modules/installer/commands/InstallController.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

namespace humhub\modules\installer\commands;

use humhub\libs\Helpers;
use Yii;
use yii\console\Controller;
use yii\console\ExitCode;
Expand All @@ -22,13 +23,13 @@

/**
* 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
{
Expand All @@ -42,9 +43,9 @@ public function actionAuto()

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
*/
Expand Down Expand Up @@ -80,12 +81,12 @@ public function actionInstallDb()
$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);
Expand Down Expand Up @@ -119,7 +120,7 @@ public function actionCreateAdminAccount($admin_user='admin', $admin_email='humh
$user->profile->firstname = 'Sys';
$user->profile->lastname = 'Admin';
$user->profile->save();

$password = new Password();
$password->user_id = $user->id;
$password->setPassword($admin_pass);
Expand Down Expand Up @@ -179,17 +180,18 @@ private function setDatabaseInstalled()

/**
* Tries to open global db connection and checks result.
*
* @return true|null|string
*/
private function checkDBConnection()
{
try {
// 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 Helpers::handleConnectionErrors($e, false, false, true);
}
return false;
}
}
14 changes: 7 additions & 7 deletions protected/humhub/tests/codeception/config/dynamic.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,28 @@
'name' => 'HumHub',
'language' => 'en-US',
'timeZone' => 'Europe/Berlin',
'components' =>
'components' =>
[
'formatter' =>
'formatter' =>
[
'defaultTimeZone' => 'Europe/Berlin',
],
'user' =>
'user' =>
[
],
'mailer' =>
'mailer' =>
[
'useFileTransport' => true,
],
'cache' =>
'cache' =>
[
'class' => 'yii\\caching\\DummyCache',
'keyPrefix' => 'humhub',
],
],
'params' =>
'params' =>
[
'config_created_at' => 1509135303,
'horImageScrollOnMobile' => null,
],
]; ?>
]; ?>

0 comments on commit 0a05d3e

Please sign in to comment.