diff options
author | ArthurHoaro <arthur@hoa.ro> | 2020-10-13 12:05:08 +0200 |
---|---|---|
committer | ArthurHoaro <arthur@hoa.ro> | 2020-10-13 12:05:08 +0200 |
commit | b6f678a5a1d15acf284ebcec16c905e976671ce1 (patch) | |
tree | 33c7da831482ed79c44896ef19c73c72ada84f2e /application/front/controller/visitor/InstallController.php | |
parent | b14687036b9b800681197f51fdc47e62f0c88e2e (diff) | |
parent | 1c1520b6b98ab20201bfe15577782a52320339df (diff) | |
download | Shaarli-b6f678a5a1d15acf284ebcec16c905e976671ce1.tar.gz Shaarli-b6f678a5a1d15acf284ebcec16c905e976671ce1.tar.zst Shaarli-b6f678a5a1d15acf284ebcec16c905e976671ce1.zip |
Merge branch 'v0.12' into latest
Diffstat (limited to 'application/front/controller/visitor/InstallController.php')
-rw-r--r-- | application/front/controller/visitor/InstallController.php | 165 |
1 files changed, 165 insertions, 0 deletions
diff --git a/application/front/controller/visitor/InstallController.php b/application/front/controller/visitor/InstallController.php new file mode 100644 index 00000000..7cb32777 --- /dev/null +++ b/application/front/controller/visitor/InstallController.php | |||
@@ -0,0 +1,165 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Shaarli\Front\Controller\Visitor; | ||
6 | |||
7 | use Shaarli\ApplicationUtils; | ||
8 | use Shaarli\Container\ShaarliContainer; | ||
9 | use Shaarli\Front\Exception\AlreadyInstalledException; | ||
10 | use Shaarli\Front\Exception\ResourcePermissionException; | ||
11 | use Shaarli\Languages; | ||
12 | use Shaarli\Security\SessionManager; | ||
13 | use Slim\Http\Request; | ||
14 | use Slim\Http\Response; | ||
15 | |||
16 | /** | ||
17 | * Slim controller used to render install page, and create initial configuration file. | ||
18 | */ | ||
19 | class InstallController extends ShaarliVisitorController | ||
20 | { | ||
21 | public const SESSION_TEST_KEY = 'session_tested'; | ||
22 | public const SESSION_TEST_VALUE = 'Working'; | ||
23 | |||
24 | public function __construct(ShaarliContainer $container) | ||
25 | { | ||
26 | parent::__construct($container); | ||
27 | |||
28 | if (is_file($this->container->conf->getConfigFileExt())) { | ||
29 | throw new AlreadyInstalledException(); | ||
30 | } | ||
31 | } | ||
32 | |||
33 | /** | ||
34 | * Display the install template page. | ||
35 | * Also test file permissions and sessions beforehand. | ||
36 | */ | ||
37 | public function index(Request $request, Response $response): Response | ||
38 | { | ||
39 | // Before installation, we'll make sure that permissions are set properly, and sessions are working. | ||
40 | $this->checkPermissions(); | ||
41 | |||
42 | if (static::SESSION_TEST_VALUE | ||
43 | !== $this->container->sessionManager->getSessionParameter(static::SESSION_TEST_KEY) | ||
44 | ) { | ||
45 | $this->container->sessionManager->setSessionParameter(static::SESSION_TEST_KEY, static::SESSION_TEST_VALUE); | ||
46 | |||
47 | return $this->redirect($response, '/install/session-test'); | ||
48 | } | ||
49 | |||
50 | [$continents, $cities] = generateTimeZoneData(timezone_identifiers_list(), date_default_timezone_get()); | ||
51 | |||
52 | $this->assignView('continents', $continents); | ||
53 | $this->assignView('cities', $cities); | ||
54 | $this->assignView('languages', Languages::getAvailableLanguages()); | ||
55 | |||
56 | return $response->write($this->render('install')); | ||
57 | } | ||
58 | |||
59 | /** | ||
60 | * Route checking that the session parameter has been properly saved between two distinct requests. | ||
61 | * If the session parameter is preserved, redirect to install template page, otherwise displays error. | ||
62 | */ | ||
63 | public function sessionTest(Request $request, Response $response): Response | ||
64 | { | ||
65 | // This part makes sure sessions works correctly. | ||
66 | // (Because on some hosts, session.save_path may not be set correctly, | ||
67 | // or we may not have write access to it.) | ||
68 | if (static::SESSION_TEST_VALUE | ||
69 | !== $this->container->sessionManager->getSessionParameter(static::SESSION_TEST_KEY) | ||
70 | ) { | ||
71 | // Step 2: Check if data in session is correct. | ||
72 | $msg = t( | ||
73 | '<pre>Sessions do not seem to work correctly on your server.<br>'. | ||
74 | 'Make sure the variable "session.save_path" is set correctly in your PHP config, '. | ||
75 | 'and that you have write access to it.<br>'. | ||
76 | 'It currently points to %s.<br>'. | ||
77 | 'On some browsers, accessing your server via a hostname like \'localhost\' '. | ||
78 | 'or any custom hostname without a dot causes cookie storage to fail. '. | ||
79 | 'We recommend accessing your server via it\'s IP address or Fully Qualified Domain Name.<br>' | ||
80 | ); | ||
81 | $msg = sprintf($msg, $this->container->sessionManager->getSavePath()); | ||
82 | |||
83 | $this->assignView('message', $msg); | ||
84 | |||
85 | return $response->write($this->render('error')); | ||
86 | } | ||
87 | |||
88 | return $this->redirect($response, '/install'); | ||
89 | } | ||
90 | |||
91 | /** | ||
92 | * Save installation form and initialize config file and datastore if necessary. | ||
93 | */ | ||
94 | public function save(Request $request, Response $response): Response | ||
95 | { | ||
96 | $timezone = 'UTC'; | ||
97 | if (!empty($request->getParam('continent')) | ||
98 | && !empty($request->getParam('city')) | ||
99 | && isTimeZoneValid($request->getParam('continent'), $request->getParam('city')) | ||
100 | ) { | ||
101 | $timezone = $request->getParam('continent') . '/' . $request->getParam('city'); | ||
102 | } | ||
103 | $this->container->conf->set('general.timezone', $timezone); | ||
104 | |||
105 | $login = $request->getParam('setlogin'); | ||
106 | $this->container->conf->set('credentials.login', $login); | ||
107 | $salt = sha1(uniqid('', true) .'_'. mt_rand()); | ||
108 | $this->container->conf->set('credentials.salt', $salt); | ||
109 | $this->container->conf->set('credentials.hash', sha1($request->getParam('setpassword') . $login . $salt)); | ||
110 | |||
111 | if (!empty($request->getParam('title'))) { | ||
112 | $this->container->conf->set('general.title', escape($request->getParam('title'))); | ||
113 | } else { | ||
114 | $this->container->conf->set( | ||
115 | 'general.title', | ||
116 | 'Shared bookmarks on '.escape(index_url($this->container->environment)) | ||
117 | ); | ||
118 | } | ||
119 | |||
120 | $this->container->conf->set('translation.language', escape($request->getParam('language'))); | ||
121 | $this->container->conf->set('updates.check_updates', !empty($request->getParam('updateCheck'))); | ||
122 | $this->container->conf->set('api.enabled', !empty($request->getParam('enableApi'))); | ||
123 | $this->container->conf->set( | ||
124 | 'api.secret', | ||
125 | generate_api_secret( | ||
126 | $this->container->conf->get('credentials.login'), | ||
127 | $this->container->conf->get('credentials.salt') | ||
128 | ) | ||
129 | ); | ||
130 | $this->container->conf->set('general.header_link', $this->container->basePath . '/'); | ||
131 | |||
132 | try { | ||
133 | // Everything is ok, let's create config file. | ||
134 | $this->container->conf->write($this->container->loginManager->isLoggedIn()); | ||
135 | } catch (\Exception $e) { | ||
136 | $this->assignView('message', t('Error while writing config file after configuration update.')); | ||
137 | $this->assignView('stacktrace', $e->getMessage() . PHP_EOL . $e->getTraceAsString()); | ||
138 | |||
139 | return $response->write($this->render('error')); | ||
140 | } | ||
141 | |||
142 | $this->container->sessionManager->setSessionParameter( | ||
143 | SessionManager::KEY_SUCCESS_MESSAGES, | ||
144 | [t('Shaarli is now configured. Please login and start shaaring your bookmarks!')] | ||
145 | ); | ||
146 | |||
147 | return $this->redirect($response, '/login'); | ||
148 | } | ||
149 | |||
150 | protected function checkPermissions(): bool | ||
151 | { | ||
152 | // Ensure Shaarli has proper access to its resources | ||
153 | $errors = ApplicationUtils::checkResourcePermissions($this->container->conf); | ||
154 | if (empty($errors)) { | ||
155 | return true; | ||
156 | } | ||
157 | |||
158 | $message = t('Insufficient permissions:') . PHP_EOL; | ||
159 | foreach ($errors as $error) { | ||
160 | $message .= PHP_EOL . $error; | ||
161 | } | ||
162 | |||
163 | throw new ResourcePermissionException($message); | ||
164 | } | ||
165 | } | ||