Process Shaarli install through Slim controller
This commit is contained in:
parent
1a8ac737e5
commit
c4ad3d4f06
27 changed files with 722 additions and 221 deletions
application/front
|
@ -43,6 +43,12 @@ class ShaarliMiddleware
|
|||
$this->container->basePath = rtrim($request->getUri()->getBasePath(), '/');
|
||||
|
||||
try {
|
||||
if (!is_file($this->container->conf->getConfigFileExt())
|
||||
&& !in_array($next->getName(), ['displayInstall', 'saveInstall'], true)
|
||||
) {
|
||||
return $response->withRedirect($this->container->basePath . '/install');
|
||||
}
|
||||
|
||||
$this->runUpdates();
|
||||
$this->checkOpenShaarli($request, $response, $next);
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ declare(strict_types=1);
|
|||
|
||||
namespace Shaarli\Front\Controller\Admin;
|
||||
|
||||
use Shaarli\Security\CookieManager;
|
||||
use Shaarli\Security\LoginManager;
|
||||
use Slim\Http\Request;
|
||||
use Slim\Http\Response;
|
||||
|
@ -20,9 +21,12 @@ class LogoutController extends ShaarliAdminController
|
|||
{
|
||||
$this->container->pageCacheManager->invalidateCaches();
|
||||
$this->container->sessionManager->logout();
|
||||
|
||||
// TODO: switch to a simple Cookie manager allowing to check the session, and create mocks.
|
||||
setcookie(LoginManager::$STAY_SIGNED_IN_COOKIE, 'false', 0, $this->container->basePath . '/');
|
||||
$this->container->cookieManager->setCookieParameter(
|
||||
CookieManager::STAY_SIGNED_IN,
|
||||
'false',
|
||||
0,
|
||||
$this->container->basePath . '/'
|
||||
);
|
||||
|
||||
return $this->redirect($response, '/');
|
||||
}
|
||||
|
|
173
application/front/controller/visitor/InstallController.php
Normal file
173
application/front/controller/visitor/InstallController.php
Normal file
|
@ -0,0 +1,173 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Shaarli\Front\Controller\Visitor;
|
||||
|
||||
use Shaarli\ApplicationUtils;
|
||||
use Shaarli\Bookmark\BookmarkFilter;
|
||||
use Shaarli\Container\ShaarliContainer;
|
||||
use Shaarli\Front\Exception\AlreadyInstalledException;
|
||||
use Shaarli\Front\Exception\ResourcePermissionException;
|
||||
use Shaarli\Languages;
|
||||
use Shaarli\Security\SessionManager;
|
||||
use Slim\Http\Request;
|
||||
use Slim\Http\Response;
|
||||
|
||||
/**
|
||||
* Slim controller used to render install page, and create initial configuration file.
|
||||
*/
|
||||
class InstallController extends ShaarliVisitorController
|
||||
{
|
||||
public const SESSION_TEST_KEY = 'session_tested';
|
||||
public const SESSION_TEST_VALUE = 'Working';
|
||||
|
||||
public function __construct(ShaarliContainer $container)
|
||||
{
|
||||
parent::__construct($container);
|
||||
|
||||
if (is_file($this->container->conf->getConfigFileExt())) {
|
||||
throw new AlreadyInstalledException();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the install template page.
|
||||
* Also test file permissions and sessions beforehand.
|
||||
*/
|
||||
public function index(Request $request, Response $response): Response
|
||||
{
|
||||
// Before installation, we'll make sure that permissions are set properly, and sessions are working.
|
||||
$this->checkPermissions();
|
||||
|
||||
if (static::SESSION_TEST_VALUE
|
||||
!== $this->container->sessionManager->getSessionParameter(static::SESSION_TEST_KEY)
|
||||
) {
|
||||
$this->container->sessionManager->setSessionParameter(static::SESSION_TEST_KEY, static::SESSION_TEST_VALUE);
|
||||
|
||||
return $this->redirect($response, '/install/session-test');
|
||||
}
|
||||
|
||||
[$continents, $cities] = generateTimeZoneData(timezone_identifiers_list(), date_default_timezone_get());
|
||||
|
||||
$this->assignView('continents', $continents);
|
||||
$this->assignView('cities', $cities);
|
||||
$this->assignView('languages', Languages::getAvailableLanguages());
|
||||
|
||||
return $response->write($this->render('install'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Route checking that the session parameter has been properly saved between two distinct requests.
|
||||
* If the session parameter is preserved, redirect to install template page, otherwise displays error.
|
||||
*/
|
||||
public function sessionTest(Request $request, Response $response): Response
|
||||
{
|
||||
// This part makes sure sessions works correctly.
|
||||
// (Because on some hosts, session.save_path may not be set correctly,
|
||||
// or we may not have write access to it.)
|
||||
if (static::SESSION_TEST_VALUE
|
||||
!== $this->container->sessionManager->getSessionParameter(static::SESSION_TEST_KEY)
|
||||
) {
|
||||
// Step 2: Check if data in session is correct.
|
||||
$msg = t(
|
||||
'<pre>Sessions do not seem to work correctly on your server.<br>'.
|
||||
'Make sure the variable "session.save_path" is set correctly in your PHP config, '.
|
||||
'and that you have write access to it.<br>'.
|
||||
'It currently points to %s.<br>'.
|
||||
'On some browsers, accessing your server via a hostname like \'localhost\' '.
|
||||
'or any custom hostname without a dot causes cookie storage to fail. '.
|
||||
'We recommend accessing your server via it\'s IP address or Fully Qualified Domain Name.<br>'
|
||||
);
|
||||
$msg = sprintf($msg, $this->container->sessionManager->getSavePath());
|
||||
|
||||
$this->assignView('message', $msg);
|
||||
|
||||
return $response->write($this->render('error'));
|
||||
}
|
||||
|
||||
return $this->redirect($response, '/install');
|
||||
}
|
||||
|
||||
/**
|
||||
* Save installation form and initialize config file and datastore if necessary.
|
||||
*/
|
||||
public function save(Request $request, Response $response): Response
|
||||
{
|
||||
$timezone = 'UTC';
|
||||
if (!empty($request->getParam('continent'))
|
||||
&& !empty($request->getParam('city'))
|
||||
&& isTimeZoneValid($request->getParam('continent'), $request->getParam('city'))
|
||||
) {
|
||||
$timezone = $request->getParam('continent') . '/' . $request->getParam('city');
|
||||
}
|
||||
$this->container->conf->set('general.timezone', $timezone);
|
||||
|
||||
$login = $request->getParam('setlogin');
|
||||
$this->container->conf->set('credentials.login', $login);
|
||||
$salt = sha1(uniqid('', true) .'_'. mt_rand());
|
||||
$this->container->conf->set('credentials.salt', $salt);
|
||||
$this->container->conf->set('credentials.hash', sha1($request->getParam('setpassword') . $login . $salt));
|
||||
|
||||
if (!empty($request->getParam('title'))) {
|
||||
$this->container->conf->set('general.title', escape($request->getParam('title')));
|
||||
} else {
|
||||
$this->container->conf->set(
|
||||
'general.title',
|
||||
'Shared bookmarks on '.escape(index_url($this->container->environment))
|
||||
);
|
||||
}
|
||||
|
||||
$this->container->conf->set('translation.language', escape($request->getParam('language')));
|
||||
$this->container->conf->set('updates.check_updates', !empty($request->getParam('updateCheck')));
|
||||
$this->container->conf->set('api.enabled', !empty($request->getParam('enableApi')));
|
||||
$this->container->conf->set(
|
||||
'api.secret',
|
||||
generate_api_secret(
|
||||
$this->container->conf->get('credentials.login'),
|
||||
$this->container->conf->get('credentials.salt')
|
||||
)
|
||||
);
|
||||
|
||||
try {
|
||||
// Everything is ok, let's create config file.
|
||||
$this->container->conf->write($this->container->loginManager->isLoggedIn());
|
||||
} catch (\Exception $e) {
|
||||
$this->assignView('message', $e->getMessage());
|
||||
$this->assignView('stacktrace', $e->getTraceAsString());
|
||||
|
||||
return $response->write($this->render('error'));
|
||||
}
|
||||
|
||||
if ($this->container->bookmarkService->count(BookmarkFilter::$ALL) === 0) {
|
||||
$this->container->bookmarkService->initialize();
|
||||
}
|
||||
|
||||
$this->container->sessionManager->setSessionParameter(
|
||||
SessionManager::KEY_SUCCESS_MESSAGES,
|
||||
[t('Shaarli is now configured. Please login and start shaaring your bookmarks!')]
|
||||
);
|
||||
|
||||
return $this->redirect($response, '/');
|
||||
}
|
||||
|
||||
protected function checkPermissions(): bool
|
||||
{
|
||||
// Ensure Shaarli has proper access to its resources
|
||||
$errors = ApplicationUtils::checkResourcePermissions($this->container->conf);
|
||||
|
||||
if (empty($errors)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// FIXME! Do not insert HTML here.
|
||||
$message = '<p>'. t('Insufficient permissions:') .'</p><ul>';
|
||||
|
||||
foreach ($errors as $error) {
|
||||
$message .= '<li>'.$error.'</li>';
|
||||
}
|
||||
$message .= '</ul>';
|
||||
|
||||
throw new ResourcePermissionException($message);
|
||||
}
|
||||
}
|
15
application/front/exceptions/AlreadyInstalledException.php
Normal file
15
application/front/exceptions/AlreadyInstalledException.php
Normal file
|
@ -0,0 +1,15 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Shaarli\Front\Exception;
|
||||
|
||||
class AlreadyInstalledException extends ShaarliFrontException
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
$message = t('Shaarli has already been installed. Login to edit the configuration.');
|
||||
|
||||
parent::__construct($message, 401);
|
||||
}
|
||||
}
|
13
application/front/exceptions/ResourcePermissionException.php
Normal file
13
application/front/exceptions/ResourcePermissionException.php
Normal file
|
@ -0,0 +1,13 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Shaarli\Front\Exception;
|
||||
|
||||
class ResourcePermissionException extends ShaarliFrontException
|
||||
{
|
||||
public function __construct(string $message)
|
||||
{
|
||||
parent::__construct($message, 500);
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue