Deal with settings read/write errors properly
This commit is contained in:
89
app/Foundation/Exceptions/Displayers/SettingsDisplayer.php
Normal file
89
app/Foundation/Exceptions/Displayers/SettingsDisplayer.php
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Cachet.
|
||||||
|
*
|
||||||
|
* (c) Alt Three Services Limited
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace CachetHQ\Cachet\Foundation\Exceptions\Displayers;
|
||||||
|
|
||||||
|
use CachetHQ\Cachet\Settings\ReadException;
|
||||||
|
use Exception;
|
||||||
|
use GrahamCampbell\Exceptions\Displayers\DisplayerInterface;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
|
||||||
|
|
||||||
|
class SettingsDisplayer implements DisplayerInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The request instance.
|
||||||
|
*
|
||||||
|
* @var \Illuminate\Http\Request
|
||||||
|
*/
|
||||||
|
protected $request;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new redirect displayer instance.
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Http\Request $request
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __construct(Request $request)
|
||||||
|
{
|
||||||
|
$this->request = $request;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the error response associated with the given exception.
|
||||||
|
*
|
||||||
|
* @param \Exception $exception
|
||||||
|
* @param string $id
|
||||||
|
* @param int $code
|
||||||
|
* @param string[] $headers
|
||||||
|
*
|
||||||
|
* @return \Symfony\Component\HttpFoundation\Response
|
||||||
|
*/
|
||||||
|
public function display(Exception $exception, string $id, int $code, array $headers)
|
||||||
|
{
|
||||||
|
return cachet_redirect('setup');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the supported content type.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function contentType()
|
||||||
|
{
|
||||||
|
return 'text/html';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Can we display the exception?
|
||||||
|
*
|
||||||
|
* @param \Exception $original
|
||||||
|
* @param \Exception $transformed
|
||||||
|
* @param int $code
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function canDisplay(Exception $original, Exception $transformed, int $code)
|
||||||
|
{
|
||||||
|
return ($transformed instanceof ReadException) && !$this->request->is('setup*');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Do we provide verbose information about the exception?
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function isVerbose()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -53,7 +53,7 @@ class ReadyForUse
|
|||||||
*/
|
*/
|
||||||
public function handle(Request $request, Closure $next)
|
public function handle(Request $request, Closure $next)
|
||||||
{
|
{
|
||||||
if (!$this->settings->get('app_name')) {
|
if (!$request->is('setup*') && !$this->settings->get('app_name')) {
|
||||||
return cachet_redirect('setup');
|
return cachet_redirect('setup');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
namespace CachetHQ\Cachet\Http\Middleware;
|
namespace CachetHQ\Cachet\Http\Middleware;
|
||||||
|
|
||||||
|
use CachetHQ\Cachet\Settings\ReadException;
|
||||||
use CachetHQ\Cachet\Settings\Repository;
|
use CachetHQ\Cachet\Settings\Repository;
|
||||||
use Closure;
|
use Closure;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
@@ -53,8 +54,12 @@ class SetupAlreadyCompleted
|
|||||||
*/
|
*/
|
||||||
public function handle(Request $request, Closure $next)
|
public function handle(Request $request, Closure $next)
|
||||||
{
|
{
|
||||||
if ($this->settings->get('app_name')) {
|
try {
|
||||||
return cachet_redirect('dashboard');
|
if ($this->settings->get('app_name')) {
|
||||||
|
return cachet_redirect('dashboard');
|
||||||
|
}
|
||||||
|
} catch (ReadException $e) {
|
||||||
|
// not setup then!
|
||||||
}
|
}
|
||||||
|
|
||||||
return $next($request);
|
return $next($request);
|
||||||
|
|||||||
34
app/Settings/ReadException.php
Normal file
34
app/Settings/ReadException.php
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Cachet.
|
||||||
|
*
|
||||||
|
* (c) Alt Three Services Limited
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace CachetHQ\Cachet\Settings;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is the read exception class.
|
||||||
|
*
|
||||||
|
* @author Graham Campbell <graham@alt-three.com>
|
||||||
|
*/
|
||||||
|
class ReadException extends SettingsException
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Create a new read exception instance.
|
||||||
|
*
|
||||||
|
* @param \Exception $e
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __construct(Exception $e)
|
||||||
|
{
|
||||||
|
parent::__construct('Unable to read Cachet settings', $e);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -12,6 +12,7 @@
|
|||||||
namespace CachetHQ\Cachet\Settings;
|
namespace CachetHQ\Cachet\Settings;
|
||||||
|
|
||||||
use CachetHQ\Cachet\Models\Setting;
|
use CachetHQ\Cachet\Models\Setting;
|
||||||
|
use Exception;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is the settings repository class.
|
* This is the settings repository class.
|
||||||
@@ -59,13 +60,19 @@ class Repository
|
|||||||
/**
|
/**
|
||||||
* Returns a setting from the database.
|
* Returns a setting from the database.
|
||||||
*
|
*
|
||||||
|
* @throws \CachetHQ\Cachet\Settings\ReadException
|
||||||
|
*
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function all()
|
public function all()
|
||||||
{
|
{
|
||||||
return $this->model->all(['name', 'value'])->pluck('value', 'name')->map(function ($value, $name) {
|
try {
|
||||||
return $this->castSetting($name, $value);
|
return $this->model->all(['name', 'value'])->pluck('value', 'name')->map(function ($value, $name) {
|
||||||
})->toArray();
|
return $this->castSetting($name, $value);
|
||||||
|
})->toArray();
|
||||||
|
} catch (Exception $e) {
|
||||||
|
throw new ReadException($e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -74,16 +81,22 @@ class Repository
|
|||||||
* @param string $name
|
* @param string $name
|
||||||
* @param string|null $value
|
* @param string|null $value
|
||||||
*
|
*
|
||||||
|
* @throws \CachetHQ\Cachet\Settings\WriteException
|
||||||
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function set($name, $value)
|
public function set($name, $value)
|
||||||
{
|
{
|
||||||
$this->stale = true;
|
$this->stale = true;
|
||||||
|
|
||||||
if ($value === null) {
|
try {
|
||||||
$this->model->where('name', '=', $name)->delete();
|
if ($value === null) {
|
||||||
} else {
|
$this->model->where('name', '=', $name)->delete();
|
||||||
$this->model->updateOrCreate(compact('name'), compact('value'));
|
} else {
|
||||||
|
$this->model->updateOrCreate(compact('name'), compact('value'));
|
||||||
|
}
|
||||||
|
} catch (Exception $e) {
|
||||||
|
throw new WriteException($e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,15 +106,21 @@ class Repository
|
|||||||
* @param string $name
|
* @param string $name
|
||||||
* @param mixed $default
|
* @param mixed $default
|
||||||
*
|
*
|
||||||
|
* @throws \CachetHQ\Cachet\Settings\ReadException
|
||||||
|
*
|
||||||
* @return mixed
|
* @return mixed
|
||||||
*/
|
*/
|
||||||
public function get($name, $default = null)
|
public function get($name, $default = null)
|
||||||
{
|
{
|
||||||
if ($setting = $this->model->where('name', '=', $name)->first()) {
|
try {
|
||||||
return $this->castSetting($name, $setting->value);
|
if ($setting = $this->model->where('name', '=', $name)->first()) {
|
||||||
}
|
return $this->castSetting($name, $setting->value);
|
||||||
|
}
|
||||||
|
|
||||||
return $default;
|
return $default;
|
||||||
|
} catch (Exception $e) {
|
||||||
|
throw new ReadException($e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -109,25 +128,37 @@ class Repository
|
|||||||
*
|
*
|
||||||
* @param string $name
|
* @param string $name
|
||||||
*
|
*
|
||||||
|
* @throws \CachetHQ\Cachet\Settings\WriteException
|
||||||
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function delete($name)
|
public function delete($name)
|
||||||
{
|
{
|
||||||
$this->stale = true;
|
$this->stale = true;
|
||||||
|
|
||||||
$this->model->where('name', '=', $name)->delete();
|
try {
|
||||||
|
$this->model->where('name', '=', $name)->delete();
|
||||||
|
} catch (Exception $e) {
|
||||||
|
throw new WriteException($e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clear all settings.
|
* Clear all settings.
|
||||||
*
|
*
|
||||||
|
* @throws \CachetHQ\Cachet\Settings\WriteException
|
||||||
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function clear()
|
public function clear()
|
||||||
{
|
{
|
||||||
$this->stale = true;
|
$this->stale = true;
|
||||||
|
|
||||||
$this->model->query()->delete();
|
try {
|
||||||
|
$this->model->query()->delete();
|
||||||
|
} catch (Exception $e) {
|
||||||
|
throw new WriteException($e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
35
app/Settings/SettingsException.php
Normal file
35
app/Settings/SettingsException.php
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Cachet.
|
||||||
|
*
|
||||||
|
* (c) Alt Three Services Limited
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace CachetHQ\Cachet\Settings;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is the settings exception class.
|
||||||
|
*
|
||||||
|
* @author Graham Campbell <graham@alt-three.com>
|
||||||
|
*/
|
||||||
|
class SettingsException extends Exception
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Create a new write exception instance.
|
||||||
|
*
|
||||||
|
* @param string $m
|
||||||
|
* @param \Exception $e
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __construct(string $m, Exception $e)
|
||||||
|
{
|
||||||
|
parent::__construct($m, 0, $e);
|
||||||
|
}
|
||||||
|
}
|
||||||
34
app/Settings/WriteException.php
Normal file
34
app/Settings/WriteException.php
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Cachet.
|
||||||
|
*
|
||||||
|
* (c) Alt Three Services Limited
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace CachetHQ\Cachet\Settings;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is the write exception class.
|
||||||
|
*
|
||||||
|
* @author Graham Campbell <graham@alt-three.com>
|
||||||
|
*/
|
||||||
|
class WriteException extends SettingsException
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Create a new write exception instance.
|
||||||
|
*
|
||||||
|
* @param \Exception $e
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __construct(Exception $e)
|
||||||
|
{
|
||||||
|
parent::__construct('Unable to write Cachet settings', $e);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -47,10 +47,11 @@ return [
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
'displayers' => [
|
'displayers' => [
|
||||||
'CachetHQ\Cachet\Foundation\Exceptions\Displayers\JsonValidationDisplayer',
|
'CachetHQ\Cachet\Foundation\Exceptions\Displayers\MaintenanceDisplayer',
|
||||||
|
'CachetHQ\Cachet\Foundation\Exceptions\Displayers\SettingsDisplayer',
|
||||||
'CachetHQ\Cachet\Foundation\Exceptions\Displayers\RedirectDisplayer',
|
'CachetHQ\Cachet\Foundation\Exceptions\Displayers\RedirectDisplayer',
|
||||||
'CachetHQ\Cachet\Foundation\Exceptions\Displayers\ThrottleDisplayer',
|
'CachetHQ\Cachet\Foundation\Exceptions\Displayers\ThrottleDisplayer',
|
||||||
'CachetHQ\Cachet\Foundation\Exceptions\Displayers\MaintenanceDisplayer',
|
'CachetHQ\Cachet\Foundation\Exceptions\Displayers\JsonValidationDisplayer',
|
||||||
'GrahamCampbell\Exceptions\Displayers\DebugDisplayer',
|
'GrahamCampbell\Exceptions\Displayers\DebugDisplayer',
|
||||||
'GrahamCampbell\Exceptions\Displayers\HtmlDisplayer',
|
'GrahamCampbell\Exceptions\Displayers\HtmlDisplayer',
|
||||||
'GrahamCampbell\Exceptions\Displayers\JsonDisplayer',
|
'GrahamCampbell\Exceptions\Displayers\JsonDisplayer',
|
||||||
|
|||||||
Reference in New Issue
Block a user