mirror of
https://github.com/flarum/framework.git
synced 2025-01-19 07:42:48 +08:00
Implement proper update process
If the version in the settings table mismatches the code version, then we return a 503 error for all requests coming through index.php and api.php, while admin.php serves up a form prompting for the database password which will run outstanding migrations.
This commit is contained in:
parent
ddfedcb4dd
commit
1242fa79af
13
error/503.html
Normal file
13
error/503.html
Normal file
|
@ -0,0 +1,13 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head lang="en">
|
||||
<meta charset="UTF-8">
|
||||
<title></title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h1>503 Service Unavailable</h1>
|
||||
<p>This forum is down for maintenance.</p>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -15,7 +15,6 @@ use Flarum\Foundation\Application;
|
|||
use Flarum\Http\AbstractServer;
|
||||
use Zend\Stratigility\MiddlewarePipe;
|
||||
use Flarum\Http\Middleware\HandleErrors;
|
||||
use Franzl\Middleware\Whoops\Middleware as WhoopsMiddleware;
|
||||
|
||||
class Server extends AbstractServer
|
||||
{
|
||||
|
@ -27,18 +26,21 @@ class Server extends AbstractServer
|
|||
$pipe = new MiddlewarePipe;
|
||||
|
||||
if ($app->isInstalled()) {
|
||||
$app->register('Flarum\Admin\AdminServiceProvider');
|
||||
|
||||
$adminPath = parse_url($app->url('admin'), PHP_URL_PATH);
|
||||
$routes = $app->make('flarum.admin.routes');
|
||||
$errorDir = __DIR__ . '/../../error';
|
||||
|
||||
$pipe->pipe($adminPath, $app->make('Flarum\Http\Middleware\AuthenticateWithCookie'));
|
||||
$pipe->pipe($adminPath, $app->make('Flarum\Http\Middleware\ParseJsonBody'));
|
||||
$pipe->pipe($adminPath, $app->make('Flarum\Admin\Middleware\RequireAdministrateAbility'));
|
||||
$pipe->pipe($adminPath, $app->make('Flarum\Http\Middleware\DispatchRoute', compact('routes')));
|
||||
|
||||
$pipe->pipe(new HandleErrors(__DIR__.'/../../error', $app->inDebugMode()));
|
||||
if ($app->isUpToDate()) {
|
||||
$pipe->pipe($adminPath, $app->make('Flarum\Http\Middleware\AuthenticateWithCookie'));
|
||||
$pipe->pipe($adminPath, $app->make('Flarum\Http\Middleware\ParseJsonBody'));
|
||||
$pipe->pipe($adminPath, $app->make('Flarum\Admin\Middleware\RequireAdministrateAbility'));
|
||||
$pipe->pipe($adminPath, $app->make('Flarum\Http\Middleware\DispatchRoute', ['routes' => $app->make('flarum.admin.routes')]));
|
||||
$pipe->pipe($adminPath, new HandleErrors($errorDir, $app->inDebugMode()));
|
||||
} else {
|
||||
$app->register('Flarum\Update\UpdateServiceProvider');
|
||||
|
||||
$pipe->pipe($adminPath, $app->make('Flarum\Http\Middleware\DispatchRoute', ['routes' => $app->make('flarum.update.routes')]));
|
||||
$pipe->pipe($adminPath, new HandleErrors($errorDir, true));
|
||||
}
|
||||
}
|
||||
|
||||
return $pipe;
|
||||
|
|
|
@ -13,6 +13,7 @@ namespace Flarum\Api;
|
|||
|
||||
use Flarum\Foundation\Application;
|
||||
use Flarum\Http\AbstractServer;
|
||||
use Tobscure\JsonApi\Document;
|
||||
use Zend\Stratigility\MiddlewarePipe;
|
||||
|
||||
class Server extends AbstractServer
|
||||
|
@ -24,19 +25,27 @@ class Server extends AbstractServer
|
|||
{
|
||||
$pipe = new MiddlewarePipe;
|
||||
|
||||
if ($app->isInstalled()) {
|
||||
$app->register('Flarum\Api\ApiServiceProvider');
|
||||
|
||||
$routes = $app->make('flarum.api.routes');
|
||||
$apiPath = parse_url($app->url('api'), PHP_URL_PATH);
|
||||
$apiPath = parse_url($app->url('api'), PHP_URL_PATH);
|
||||
|
||||
if ($app->isInstalled() && $app->isUpToDate()) {
|
||||
$pipe->pipe($apiPath, $app->make('Flarum\Http\Middleware\AuthenticateWithCookie'));
|
||||
$pipe->pipe($apiPath, $app->make('Flarum\Api\Middleware\AuthenticateWithHeader'));
|
||||
$pipe->pipe($apiPath, $app->make('Flarum\Http\Middleware\ParseJsonBody'));
|
||||
$pipe->pipe($apiPath, $app->make('Flarum\Api\Middleware\FakeHttpMethods'));
|
||||
$pipe->pipe($apiPath, $app->make('Flarum\Http\Middleware\DispatchRoute', compact('routes')));
|
||||
|
||||
$pipe->pipe($apiPath, $app->make('Flarum\Http\Middleware\DispatchRoute', ['routes' => $app->make('flarum.api.routes')]));
|
||||
$pipe->pipe($apiPath, $app->make('Flarum\Api\Middleware\HandleErrors'));
|
||||
} else {
|
||||
$pipe->pipe($apiPath, function () {
|
||||
$document = new Document;
|
||||
$document->setErrors([
|
||||
[
|
||||
'code' => 503,
|
||||
'title' => 'Service Unavailable'
|
||||
]
|
||||
]);
|
||||
|
||||
return new JsonApiResponse($document, 503);
|
||||
});
|
||||
}
|
||||
|
||||
return $pipe;
|
||||
|
|
|
@ -32,12 +32,9 @@ class Server extends AbstractServer
|
|||
|
||||
$console = new Application('Flarum', $app::VERSION);
|
||||
|
||||
if (! $app->isInstalled()) {
|
||||
$app->register('Flarum\Install\InstallServiceProvider');
|
||||
|
||||
$console->add($app->make('Flarum\Install\Console\InstallCommand'));
|
||||
}
|
||||
$app->register('Flarum\Install\InstallServiceProvider');
|
||||
|
||||
$console->add($app->make('Flarum\Install\Console\InstallCommand'));
|
||||
$console->add($app->make('Flarum\Console\Command\UpgradeCommand'));
|
||||
$console->add($app->make('Flarum\Console\Command\GenerateExtensionCommand'));
|
||||
$console->add($app->make('Flarum\Console\Command\GenerateMigrationCommand'));
|
||||
|
|
|
@ -13,6 +13,7 @@ namespace Flarum\Forum;
|
|||
|
||||
use Flarum\Foundation\Application;
|
||||
use Flarum\Http\AbstractServer;
|
||||
use Zend\Diactoros\Response\HtmlResponse;
|
||||
use Zend\Stratigility\MiddlewarePipe;
|
||||
use Flarum\Http\Middleware\HandleErrors;
|
||||
|
||||
|
@ -25,26 +26,25 @@ class Server extends AbstractServer
|
|||
{
|
||||
$pipe = new MiddlewarePipe;
|
||||
|
||||
$installed = $app->isInstalled();
|
||||
$basePath = parse_url($app->url(), PHP_URL_PATH);
|
||||
$errorDir = __DIR__.'/../../error';
|
||||
|
||||
if ($installed) {
|
||||
$app->register('Flarum\Forum\ForumServiceProvider');
|
||||
|
||||
$routes = $app->make('flarum.forum.routes');
|
||||
|
||||
$pipe->pipe($basePath, $app->make('Flarum\Http\Middleware\AuthenticateWithCookie'));
|
||||
$pipe->pipe($basePath, $app->make('Flarum\Http\Middleware\ParseJsonBody'));
|
||||
} else {
|
||||
if (! $app->isInstalled()) {
|
||||
$app->register('Flarum\Install\InstallServiceProvider');
|
||||
|
||||
$routes = $app->make('flarum.install.routes');
|
||||
$pipe->pipe($basePath, $app->make('Flarum\Http\Middleware\DispatchRoute', ['routes' => $app->make('flarum.install.routes')]));
|
||||
$pipe->pipe($basePath, new HandleErrors($errorDir, true));
|
||||
} elseif ($app->isUpToDate()) {
|
||||
$pipe->pipe($basePath, $app->make('Flarum\Http\Middleware\AuthenticateWithCookie'));
|
||||
$pipe->pipe($basePath, $app->make('Flarum\Http\Middleware\ParseJsonBody'));
|
||||
$pipe->pipe($basePath, $app->make('Flarum\Http\Middleware\DispatchRoute', ['routes' => $app->make('flarum.forum.routes')]));
|
||||
$pipe->pipe($basePath, new HandleErrors($errorDir, $app->inDebugMode()));
|
||||
} else {
|
||||
$pipe->pipe($basePath, function () use ($errorDir) {
|
||||
return new HtmlResponse(file_get_contents($errorDir.'/503.html', 503));
|
||||
});
|
||||
}
|
||||
|
||||
$pipe->pipe($basePath, $app->make('Flarum\Http\Middleware\DispatchRoute', compact('routes')));
|
||||
|
||||
$pipe->pipe(new HandleErrors(__DIR__.'/../../error', $app->inDebugMode() || ! $installed));
|
||||
|
||||
return $pipe;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,16 +44,15 @@ class IndexController extends AbstractHtmlController
|
|||
*/
|
||||
public function render(Request $request, array $routeParams = [])
|
||||
{
|
||||
$view = $this->view->make('flarum.install::app');
|
||||
$view = $this->view->make('flarum.install::app')->with('title', 'Install Flarum');
|
||||
|
||||
$this->prerequisite->check();
|
||||
$errors = $this->prerequisite->getErrors();
|
||||
|
||||
if (count($errors)) {
|
||||
$view->content = $this->view->make('flarum.install::errors');
|
||||
$view->content->errors = $errors;
|
||||
$view->with('content', $this->view->make('flarum.install::errors')->with('errors', $errors));
|
||||
} else {
|
||||
$view->content = $this->view->make('flarum.install::install');
|
||||
$view->with('content', $this->view->make('flarum.install::install'));
|
||||
}
|
||||
|
||||
return $view;
|
||||
|
|
|
@ -12,8 +12,7 @@ namespace Flarum\Install\Controller;
|
|||
|
||||
use Flarum\Http\Controller\ControllerInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
use Zend\Diactoros\Response\EmptyResponse;
|
||||
use Zend\Diactoros\Response\JsonResponse;
|
||||
use Zend\Diactoros\Response\HtmlResponse;
|
||||
use Zend\Diactoros\Response;
|
||||
use Flarum\Install\Console\InstallCommand;
|
||||
use Flarum\Install\Console\DefaultsDataProvider;
|
||||
|
@ -85,9 +84,7 @@ class InstallController implements ControllerInterface
|
|||
try {
|
||||
$this->command->run($input, $output);
|
||||
} catch (Exception $e) {
|
||||
return new JsonResponse([
|
||||
'error' => $e->getMessage()
|
||||
], 500);
|
||||
return new HtmlResponse($e->getMessage(), 500);
|
||||
}
|
||||
|
||||
$token = $this->bus->dispatch(
|
||||
|
|
|
@ -8,15 +8,16 @@
|
|||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Flarum\Console\Command;
|
||||
namespace Flarum\Update\Console;
|
||||
|
||||
use Flarum\Console\Command\AbstractCommand;
|
||||
use Illuminate\Contracts\Container\Container;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
class UpgradeCommand extends AbstractCommand
|
||||
class MigrateCommand extends AbstractCommand
|
||||
{
|
||||
/**
|
||||
* @var Container
|
||||
|
@ -39,8 +40,8 @@ class UpgradeCommand extends AbstractCommand
|
|||
protected function configure()
|
||||
{
|
||||
$this
|
||||
->setName('upgrade')
|
||||
->setDescription("Run Flarum's upgrade script");
|
||||
->setName('migrate')
|
||||
->setDescription("Run outstanding migrations.");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -48,7 +49,7 @@ class UpgradeCommand extends AbstractCommand
|
|||
*/
|
||||
protected function fire()
|
||||
{
|
||||
$this->info('Upgrading Flarum...');
|
||||
$this->info('Migrating Flarum...');
|
||||
|
||||
$this->upgrade();
|
||||
|
||||
|
@ -66,7 +67,7 @@ class UpgradeCommand extends AbstractCommand
|
|||
$migrator->run(base_path('core/migrations'));
|
||||
|
||||
foreach ($migrator->getNotes() as $note) {
|
||||
// $this->info($note);
|
||||
$this->info($note);
|
||||
}
|
||||
|
||||
$extensions = $this->container->make('Flarum\Extension\ExtensionManager');
|
||||
|
@ -78,13 +79,15 @@ class UpgradeCommand extends AbstractCommand
|
|||
continue;
|
||||
}
|
||||
|
||||
// $this->info('Upgrading extension: '.$extension->name);
|
||||
$this->info('Migrating extension: '.$name);
|
||||
|
||||
$extensions->migrate($name);
|
||||
|
||||
foreach ($migrator->getNotes() as $note) {
|
||||
// $this->info($note);
|
||||
$this->info($note);
|
||||
}
|
||||
}
|
||||
|
||||
$this->container->make('Flarum\Settings\SettingsRepositoryInterface')->set('version', $this->container->version());
|
||||
}
|
||||
}
|
45
src/Update/Controller/IndexController.php
Normal file
45
src/Update/Controller/IndexController.php
Normal file
|
@ -0,0 +1,45 @@
|
|||
<?php
|
||||
/*
|
||||
* This file is part of Flarum.
|
||||
*
|
||||
* (c) Toby Zerner <toby.zerner@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Flarum\Update\Controller;
|
||||
|
||||
use Flarum\Http\Controller\AbstractHtmlController;
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
use Illuminate\Contracts\View\Factory;
|
||||
|
||||
class IndexController extends AbstractHtmlController
|
||||
{
|
||||
/**
|
||||
* @var Factory
|
||||
*/
|
||||
protected $view;
|
||||
|
||||
/**
|
||||
* @param Factory $view
|
||||
*/
|
||||
public function __construct(Factory $view)
|
||||
{
|
||||
$this->view = $view;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param array $routeParams
|
||||
* @return \Psr\Http\Message\ResponseInterface
|
||||
*/
|
||||
public function render(Request $request, array $routeParams = [])
|
||||
{
|
||||
$view = $this->view->make('flarum.update::app')->with('title', 'Update Flarum');
|
||||
|
||||
$view->with('content', $this->view->make('flarum.update::update'));
|
||||
|
||||
return $view;
|
||||
}
|
||||
}
|
68
src/Update/Controller/UpdateController.php
Normal file
68
src/Update/Controller/UpdateController.php
Normal file
|
@ -0,0 +1,68 @@
|
|||
<?php
|
||||
/*
|
||||
* This file is part of Flarum.
|
||||
*
|
||||
* (c) Toby Zerner <toby.zerner@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Flarum\Update\Controller;
|
||||
|
||||
use Exception;
|
||||
use Flarum\Foundation\Application;
|
||||
use Flarum\Http\Controller\ControllerInterface;
|
||||
use Flarum\Update\Console\MigrateCommand;
|
||||
use Illuminate\Contracts\Bus\Dispatcher;
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
use Symfony\Component\Console\Input\StringInput;
|
||||
use Symfony\Component\Console\Output\StreamOutput;
|
||||
use Zend\Diactoros\Response;
|
||||
use Zend\Diactoros\Response\HtmlResponse;
|
||||
|
||||
class UpdateController implements ControllerInterface
|
||||
{
|
||||
protected $command;
|
||||
|
||||
/**
|
||||
* @var Application
|
||||
*/
|
||||
protected $app;
|
||||
|
||||
/**
|
||||
* @param MigrateCommand $command
|
||||
* @param Application $app
|
||||
*/
|
||||
public function __construct(MigrateCommand $command, Application $app)
|
||||
{
|
||||
$this->command = $command;
|
||||
$this->app = $app;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param array $routeParams
|
||||
* @return \Psr\Http\Message\ResponseInterface
|
||||
*/
|
||||
public function handle(Request $request, array $routeParams = [])
|
||||
{
|
||||
$input = $request->getParsedBody();
|
||||
|
||||
if (array_get($input, 'databasePassword') !== $this->app->config('database.password')) {
|
||||
return new HtmlResponse('Incorrect database password.', 500);
|
||||
}
|
||||
|
||||
$body = fopen('php://temp', 'wb+');
|
||||
$input = new StringInput('');
|
||||
$output = new StreamOutput($body);
|
||||
|
||||
try {
|
||||
$this->command->run($input, $output);
|
||||
} catch (Exception $e) {
|
||||
return new HtmlResponse($e->getMessage(), 500);
|
||||
}
|
||||
|
||||
return new Response($body, 200);
|
||||
}
|
||||
}
|
57
src/Update/UpdateServiceProvider.php
Normal file
57
src/Update/UpdateServiceProvider.php
Normal file
|
@ -0,0 +1,57 @@
|
|||
<?php
|
||||
/*
|
||||
* This file is part of Flarum.
|
||||
*
|
||||
* (c) Toby Zerner <toby.zerner@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Flarum\Update;
|
||||
|
||||
use Flarum\Http\GenerateRouteHandlerTrait;
|
||||
use Flarum\Http\RouteCollection;
|
||||
use Flarum\Foundation\AbstractServiceProvider;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
|
||||
class UpdateServiceProvider extends AbstractServiceProvider
|
||||
{
|
||||
use GenerateRouteHandlerTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function register()
|
||||
{
|
||||
$this->app->singleton('flarum.update.routes', function () {
|
||||
return $this->getRoutes();
|
||||
});
|
||||
|
||||
$this->loadViewsFrom(__DIR__.'/../../views/install', 'flarum.update');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return RouteCollection
|
||||
*/
|
||||
protected function getRoutes()
|
||||
{
|
||||
$routes = new RouteCollection;
|
||||
|
||||
$toController = $this->getHandlerGenerator($this->app);
|
||||
|
||||
$routes->get(
|
||||
'/',
|
||||
'index',
|
||||
$toController('Flarum\Update\Controller\IndexController')
|
||||
);
|
||||
|
||||
$routes->post(
|
||||
'/',
|
||||
'update',
|
||||
$toController('Flarum\Update\Controller\UpdateController')
|
||||
);
|
||||
|
||||
return $routes;
|
||||
}
|
||||
}
|
|
@ -3,7 +3,7 @@
|
|||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<title>Install Flarum</title>
|
||||
<title><?php echo $title; ?></title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1">
|
||||
|
||||
<style>
|
||||
|
|
|
@ -83,7 +83,7 @@ $(function() {
|
|||
window.location.reload();
|
||||
})
|
||||
.fail(function(data) {
|
||||
$('#error').show().text('Something went wrong:\n\n' + data.responseJSON.error);
|
||||
$('#error').show().text('Something went wrong:\n\n' + data.responseText);
|
||||
|
||||
$button.prop('disabled', false).text('Install Flarum');
|
||||
});
|
||||
|
|
45
views/install/update.php
Normal file
45
views/install/update.php
Normal file
|
@ -0,0 +1,45 @@
|
|||
<h2>Update Flarum</h2>
|
||||
|
||||
<p>Enter your database password to update Flarum. Before you proceed, you should <strong>back up your database</strong>. If you have any trouble, get help on the <a href="http://flarum.org/docs/updating" target="_blank">Flarum website</a>.</p>
|
||||
|
||||
<form method="post">
|
||||
<div id="error" style="display:none"></div>
|
||||
|
||||
<div class="FormGroup">
|
||||
<div class="FormField">
|
||||
<label>Database Password</label>
|
||||
<input type="password" name="databasePassword">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="FormButtons">
|
||||
<button type="submit">Update Flarum</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
|
||||
<script>
|
||||
$(function() {
|
||||
$('form :input:first').select();
|
||||
|
||||
$('form').on('submit', function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
var $button = $(this).find('button')
|
||||
.text('Please Wait...')
|
||||
.prop('disabled', true);
|
||||
|
||||
$.post('', $(this).serialize())
|
||||
.done(function() {
|
||||
window.location.reload();
|
||||
})
|
||||
.fail(function(data) {
|
||||
$('#error').show().text('Something went wrong:\n\n' + data.responseText);
|
||||
|
||||
$button.prop('disabled', false).text('Update Flarum');
|
||||
});
|
||||
|
||||
return false;
|
||||
});
|
||||
});
|
||||
</script>
|
Loading…
Reference in New Issue
Block a user