Fix database host modification not properly showing SQL errors
This is caused by an old bug relating to not rolling back transactions properly causing session data to not be flashed back to the user properly.
This commit is contained in:
parent
2cda14bffb
commit
02ac308042
6 changed files with 74 additions and 59 deletions
|
@ -10,6 +10,8 @@ This project follows [Semantic Versioning](http://semver.org) guidelines.
|
||||||
value when showing an error state.
|
value when showing an error state.
|
||||||
* Mass deleting files now executes properly and doesn't result in a JS console error.
|
* Mass deleting files now executes properly and doesn't result in a JS console error.
|
||||||
* Scrolling on email settings page now works.
|
* Scrolling on email settings page now works.
|
||||||
|
* Database host management will now properly display an error message to the user when there is any type of MySQL related
|
||||||
|
error encountered during creation or update.
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
* Server listing view now displays the total used disk space for each server.
|
* Server listing view now displays the total used disk space for each server.
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
namespace Pterodactyl\Http\Controllers\Admin;
|
namespace Pterodactyl\Http\Controllers\Admin;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
use PDOException;
|
use PDOException;
|
||||||
use Illuminate\View\View;
|
use Illuminate\View\View;
|
||||||
use Pterodactyl\Models\DatabaseHost;
|
use Pterodactyl\Models\DatabaseHost;
|
||||||
|
@ -118,17 +119,22 @@ class DatabaseController extends Controller
|
||||||
* @param \Pterodactyl\Http\Requests\Admin\DatabaseHostFormRequest $request
|
* @param \Pterodactyl\Http\Requests\Admin\DatabaseHostFormRequest $request
|
||||||
* @return \Illuminate\Http\RedirectResponse
|
* @return \Illuminate\Http\RedirectResponse
|
||||||
*
|
*
|
||||||
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
|
* @throws \Throwable
|
||||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
|
||||||
*/
|
*/
|
||||||
public function create(DatabaseHostFormRequest $request): RedirectResponse
|
public function create(DatabaseHostFormRequest $request): RedirectResponse
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$host = $this->creationService->handle($request->normalize());
|
$host = $this->creationService->handle($request->normalize());
|
||||||
} catch (PDOException $ex) {
|
} catch (Exception $exception) {
|
||||||
$this->alert->danger($ex->getMessage())->flash();
|
if ($exception instanceof PDOException || $exception->getPrevious() instanceof PDOException) {
|
||||||
|
$this->alert->danger(
|
||||||
|
sprintf('There was an error while trying to connect to the host or while executing a query: "%s"', $exception->getMessage())
|
||||||
|
)->flash();
|
||||||
|
|
||||||
return redirect()->route('admin.databases');
|
redirect()->route('admin.databases')->withInput($request->validated());
|
||||||
|
} else {
|
||||||
|
throw $exception;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->alert->success('Successfully created a new database host on the system.')->flash();
|
$this->alert->success('Successfully created a new database host on the system.')->flash();
|
||||||
|
@ -143,8 +149,7 @@ class DatabaseController extends Controller
|
||||||
* @param \Pterodactyl\Models\DatabaseHost $host
|
* @param \Pterodactyl\Models\DatabaseHost $host
|
||||||
* @return \Illuminate\Http\RedirectResponse
|
* @return \Illuminate\Http\RedirectResponse
|
||||||
*
|
*
|
||||||
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
|
* @throws \Throwable
|
||||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
|
||||||
*/
|
*/
|
||||||
public function update(DatabaseHostFormRequest $request, DatabaseHost $host): RedirectResponse
|
public function update(DatabaseHostFormRequest $request, DatabaseHost $host): RedirectResponse
|
||||||
{
|
{
|
||||||
|
@ -153,9 +158,17 @@ class DatabaseController extends Controller
|
||||||
try {
|
try {
|
||||||
$this->updateService->handle($host->id, $request->normalize());
|
$this->updateService->handle($host->id, $request->normalize());
|
||||||
$this->alert->success('Database host was updated successfully.')->flash();
|
$this->alert->success('Database host was updated successfully.')->flash();
|
||||||
} catch (PDOException $ex) {
|
} catch (Exception $exception) {
|
||||||
$this->alert->danger($ex->getMessage())->flash();
|
// Catch any SQL related exceptions and display them back to the user, otherwise just
|
||||||
$redirect->withInput($request->normalize());
|
// throw the exception like normal and move on with it.
|
||||||
|
if ($exception instanceof PDOException || $exception->getPrevious() instanceof PDOException) {
|
||||||
|
$this->alert->danger(
|
||||||
|
sprintf('There was an error while trying to connect to the host or while executing a query: "%s"', $exception->getMessage())
|
||||||
|
)->flash();
|
||||||
|
$redirect->withInput($request->normalize());
|
||||||
|
} else {
|
||||||
|
throw $exception;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $redirect;
|
return $redirect;
|
||||||
|
|
|
@ -65,28 +65,26 @@ class HostCreationService
|
||||||
* @param array $data
|
* @param array $data
|
||||||
* @return \Pterodactyl\Models\DatabaseHost
|
* @return \Pterodactyl\Models\DatabaseHost
|
||||||
*
|
*
|
||||||
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
|
* @throws \Throwable
|
||||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
|
||||||
*/
|
*/
|
||||||
public function handle(array $data): DatabaseHost
|
public function handle(array $data): DatabaseHost
|
||||||
{
|
{
|
||||||
$this->connection->beginTransaction();
|
return $this->connection->transaction(function () use ($data) {
|
||||||
|
$host = $this->repository->create([
|
||||||
|
'password' => $this->encrypter->encrypt(array_get($data, 'password')),
|
||||||
|
'name' => array_get($data, 'name'),
|
||||||
|
'host' => array_get($data, 'host'),
|
||||||
|
'port' => array_get($data, 'port'),
|
||||||
|
'username' => array_get($data, 'username'),
|
||||||
|
'max_databases' => null,
|
||||||
|
'node_id' => array_get($data, 'node_id'),
|
||||||
|
]);
|
||||||
|
|
||||||
$host = $this->repository->create([
|
// Confirm access using the provided credentials before saving data.
|
||||||
'password' => $this->encrypter->encrypt(array_get($data, 'password')),
|
$this->dynamic->set('dynamic', $host);
|
||||||
'name' => array_get($data, 'name'),
|
$this->databaseManager->connection('dynamic')->select('SELECT 1 FROM dual');
|
||||||
'host' => array_get($data, 'host'),
|
|
||||||
'port' => array_get($data, 'port'),
|
|
||||||
'username' => array_get($data, 'username'),
|
|
||||||
'max_databases' => null,
|
|
||||||
'node_id' => array_get($data, 'node_id'),
|
|
||||||
]);
|
|
||||||
|
|
||||||
// Confirm access using the provided credentials before saving data.
|
return $host;
|
||||||
$this->dynamic->set('dynamic', $host);
|
});
|
||||||
$this->databaseManager->connection('dynamic')->select('SELECT 1 FROM dual');
|
|
||||||
$this->connection->commit();
|
|
||||||
|
|
||||||
return $host;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,10 +71,9 @@ class HostUpdateService
|
||||||
*
|
*
|
||||||
* @param int $hostId
|
* @param int $hostId
|
||||||
* @param array $data
|
* @param array $data
|
||||||
* @return mixed
|
* @return \Pterodactyl\Models\DatabaseHost
|
||||||
*
|
*
|
||||||
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
|
* @throws \Throwable
|
||||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
|
||||||
*/
|
*/
|
||||||
public function handle(int $hostId, array $data): DatabaseHost
|
public function handle(int $hostId, array $data): DatabaseHost
|
||||||
{
|
{
|
||||||
|
@ -84,13 +83,12 @@ class HostUpdateService
|
||||||
unset($data['password']);
|
unset($data['password']);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->connection->beginTransaction();
|
return $this->connection->transaction(function () use ($data, $hostId) {
|
||||||
$host = $this->repository->update($hostId, $data);
|
$host = $this->repository->update($hostId, $data);
|
||||||
|
$this->dynamic->set('dynamic', $host);
|
||||||
|
$this->databaseManager->connection('dynamic')->select('SELECT 1 FROM dual');
|
||||||
|
|
||||||
$this->dynamic->set('dynamic', $host);
|
return $host;
|
||||||
$this->databaseManager->connection('dynamic')->select('SELECT 1 FROM dual');
|
});
|
||||||
$this->connection->commit();
|
|
||||||
|
|
||||||
return $host;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,18 +60,20 @@ class HostCreationServiceTest extends TestCase
|
||||||
{
|
{
|
||||||
$model = factory(DatabaseHost::class)->make();
|
$model = factory(DatabaseHost::class)->make();
|
||||||
|
|
||||||
$this->connection->shouldReceive('beginTransaction')->withNoArgs()->once()->andReturnNull();
|
$this->connection->expects('transaction')->with(m::on(function ($closure) {
|
||||||
$this->encrypter->shouldReceive('encrypt')->with('test123')->once()->andReturn('enc123');
|
return ! is_null($closure());
|
||||||
$this->repository->shouldReceive('create')->with(m::subset([
|
}))->andReturn($model);
|
||||||
|
|
||||||
|
$this->encrypter->expects('encrypt')->with('test123')->andReturn('enc123');
|
||||||
|
$this->repository->expects('create')->with(m::subset([
|
||||||
'password' => 'enc123',
|
'password' => 'enc123',
|
||||||
'username' => $model->username,
|
'username' => $model->username,
|
||||||
'node_id' => $model->node_id,
|
'node_id' => $model->node_id,
|
||||||
]))->once()->andReturn($model);
|
]))->andReturn($model);
|
||||||
|
|
||||||
$this->dynamic->shouldReceive('set')->with('dynamic', $model)->once()->andReturnNull();
|
$this->dynamic->expects('set')->with('dynamic', $model)->andReturnNull();
|
||||||
$this->databaseManager->shouldReceive('connection')->with('dynamic')->once()->andReturnSelf();
|
$this->databaseManager->expects('connection')->with('dynamic')->andReturnSelf();
|
||||||
$this->databaseManager->shouldReceive('select')->with('SELECT 1 FROM dual')->once()->andReturnNull();
|
$this->databaseManager->expects('select')->with('SELECT 1 FROM dual')->andReturnNull();
|
||||||
$this->connection->shouldReceive('commit')->withNoArgs()->once()->andReturnNull();
|
|
||||||
|
|
||||||
$response = $this->getService()->handle([
|
$response = $this->getService()->handle([
|
||||||
'password' => 'test123',
|
'password' => 'test123',
|
||||||
|
|
|
@ -60,14 +60,15 @@ class HostUpdateServiceTest extends TestCase
|
||||||
{
|
{
|
||||||
$model = factory(DatabaseHost::class)->make();
|
$model = factory(DatabaseHost::class)->make();
|
||||||
|
|
||||||
$this->encrypter->shouldReceive('encrypt')->with('test123')->once()->andReturn('enc123');
|
$this->connection->expects('transaction')->with(m::on(function ($closure) {
|
||||||
$this->connection->shouldReceive('beginTransaction')->withNoArgs()->once()->andReturnNull();
|
return ! is_null($closure());
|
||||||
$this->repository->shouldReceive('update')->with(1234, ['password' => 'enc123'])->once()->andReturn($model);
|
}))->andReturn($model);
|
||||||
|
|
||||||
$this->dynamic->shouldReceive('set')->with('dynamic', $model)->once()->andReturnNull();
|
$this->encrypter->expects('encrypt')->with('test123')->andReturn('enc123');
|
||||||
$this->databaseManager->shouldReceive('connection')->with('dynamic')->once()->andReturnSelf();
|
$this->repository->expects('update')->with(1234, ['password' => 'enc123'])->andReturn($model);
|
||||||
$this->databaseManager->shouldReceive('select')->with('SELECT 1 FROM dual')->once()->andReturnNull();
|
$this->dynamic->expects('set')->with('dynamic', $model)->andReturnNull();
|
||||||
$this->connection->shouldReceive('commit')->withNoArgs()->once()->andReturnNull();
|
$this->databaseManager->expects('connection')->with('dynamic')->andReturnSelf();
|
||||||
|
$this->databaseManager->expects('select')->with('SELECT 1 FROM dual')->andReturnNull();
|
||||||
|
|
||||||
$response = $this->getService()->handle(1234, ['password' => 'test123']);
|
$response = $this->getService()->handle(1234, ['password' => 'test123']);
|
||||||
$this->assertNotEmpty($response);
|
$this->assertNotEmpty($response);
|
||||||
|
@ -81,13 +82,14 @@ class HostUpdateServiceTest extends TestCase
|
||||||
{
|
{
|
||||||
$model = factory(DatabaseHost::class)->make();
|
$model = factory(DatabaseHost::class)->make();
|
||||||
|
|
||||||
$this->connection->shouldReceive('beginTransaction')->withNoArgs()->once()->andReturnNull();
|
$this->connection->expects('transaction')->with(m::on(function ($closure) {
|
||||||
$this->repository->shouldReceive('update')->with(1234, ['username' => 'test'])->once()->andReturn($model);
|
return ! is_null($closure());
|
||||||
|
}))->andReturn($model);
|
||||||
|
|
||||||
$this->dynamic->shouldReceive('set')->with('dynamic', $model)->once()->andReturnNull();
|
$this->repository->expects('update')->with(1234, ['username' => 'test'])->andReturn($model);
|
||||||
$this->databaseManager->shouldReceive('connection')->with('dynamic')->once()->andReturnSelf();
|
$this->dynamic->expects('set')->with('dynamic', $model)->andReturnNull();
|
||||||
$this->databaseManager->shouldReceive('select')->with('SELECT 1 FROM dual')->once()->andReturnNull();
|
$this->databaseManager->expects('connection')->with('dynamic')->andReturnSelf();
|
||||||
$this->connection->shouldReceive('commit')->withNoArgs()->once()->andReturnNull();
|
$this->databaseManager->expects('select')->with('SELECT 1 FROM dual')->andReturnNull();
|
||||||
|
|
||||||
$response = $this->getService()->handle(1234, ['password' => '', 'username' => 'test']);
|
$response = $this->getService()->handle(1234, ['password' => '', 'username' => 'test']);
|
||||||
$this->assertNotEmpty($response);
|
$this->assertNotEmpty($response);
|
||||||
|
|
Loading…
Reference in a new issue