Newer
Older

Yassine Doghri
committed
<?php
/**
* @copyright 2020 Podlibre
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
* @link https://castopod.org/
*/
namespace App\Controllers;
use App\Models\UserModel;
use CodeIgniter\Controller;

Yassine Doghri
committed
use Config\Services;
use Dotenv\Dotenv;
class Install extends Controller

Yassine Doghri
committed
{
protected $helpers = ['form', 'components', 'svg'];
/**
* Constructor.
*/
public function initController(
\CodeIgniter\HTTP\RequestInterface $request,
\CodeIgniter\HTTP\ResponseInterface $response,
\Psr\Log\LoggerInterface $logger
) {
// Do Not Edit This Line
parent::initController($request, $response, $logger);
}

Yassine Doghri
committed
/**
* Every operation goes through this method to handle
* the install logic.
*
* If all required actions have already been performed,
* the install route will show a 404 page.
*/
public function index()
{
try {
// Check if .env is created and has all required fields
$dotenv = Dotenv::createUnsafeImmutable(ROOTPATH);

Yassine Doghri
committed
$dotenv->load();
} catch (\Throwable $e) {

Benjamin Bellamy
committed
$this->createEnv();

Yassine Doghri
committed
}
// Check if the created .env file is writable to continue install process

Yassine Doghri
committed
if (is_really_writable(ROOTPATH . '.env')) {
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
try {
$dotenv->required([
'app.baseURL',
'app.adminGateway',
'app.authGateway',
]);
} catch (\Dotenv\Exception\ValidationException $e) {
// form to input instance configuration
return $this->instanceConfig();
}
try {
$dotenv->required([
'database.default.hostname',
'database.default.database',
'database.default.username',
'database.default.password',
'database.default.DBPrefix',
]);
} catch (\Dotenv\Exception\ValidationException $e) {
return $this->databaseConfig();
}
try {
$dotenv->required('cache.handler');
} catch (\Dotenv\Exception\ValidationException $e) {
return $this->cacheConfig();
}
} else {
try {
$dotenv->required([
'app.baseURL',
'app.adminGateway',
'app.authGateway',
'database.default.hostname',
'database.default.database',
'database.default.username',
'database.default.password',
'database.default.DBPrefix',
'cache.handler',
]);
} catch (\Dotenv\Exception\ValidationException $e) {
return view('install/manual_config');
}
}

Yassine Doghri
committed
try {
$db = db_connect();
// Check if superadmin has been created, meaning migrations and seeds have passed
if (
$db->tableExists('users') &&
(new UserModel())->countAll() > 0
) {
// if so, show a 404 page
throw \CodeIgniter\Exceptions\PageNotFoundException::forPageNotFound();
}
} catch (\CodeIgniter\Database\Exceptions\DatabaseException $e) {
// Could not connect to the database
// show database config view to fix value
session()->setFlashdata(
'error',
lang('Install.messages.databaseConnectError')
);
return view('install/database_config');

Yassine Doghri
committed
}
// migrate if no user has been created
$this->migrate();
// Check if all seeds have succeeded
$this->seed();
return $this->createSuperAdmin();
}
/**
* Returns the form to generate the .env config file for the instance.
*/
public function createEnv()
{
// create empty .env file
try {
$envFile = fopen(ROOTPATH . '.env', 'w');
fclose($envFile);
} catch (\Throwable $e) {
// Could not create the .env file, redirect to a view with manual instructions on how to add it
return view('install/manual_config');
}

Yassine Doghri
committed
}
public function instanceConfig()

Yassine Doghri
committed
{
return view('install/instance_config');
}
public function attemptInstanceConfig()
{
$rules = [
'hostname' => 'required|validate_url',
'admin_gateway' => 'required',
'auth_gateway' => 'required|differs[admin_gateway]',
];
if (!$this->validate($rules)) {

Yassine Doghri
committed
return redirect()

Yassine Doghri
committed
->to(
(empty(host_url()) ? config('App')->baseURL : host_url()) .
config('App')->installGateway
)
->withInput()

Yassine Doghri
committed
->with('errors', $this->validator->getErrors());
}
$baseUrl = $this->request->getPost('hostname');
$mediaBaseUrl = $this->request->getPost('media_base_url');
self::writeEnv([
'app.baseURL' => $baseUrl,
'app.mediaBaseURL' => empty($mediaBaseUrl)
? $baseUrl
: $mediaBaseUrl,
'app.adminGateway' => $this->request->getPost('admin_gateway'),
'app.authGateway' => $this->request->getPost('auth_gateway'),
]);

Yassine Doghri
committed
helper('text');
// redirect to full install url with new baseUrl input
return redirect(0)->to(
reduce_double_slashes(
$baseUrl . '/' . config('App')->installGateway
)
);

Yassine Doghri
committed
public function databaseConfig()
{
return view('install/database_config');
}
public function attemptDatabaseConfig()
{
$rules = [
'db_hostname' => 'required',
'db_name' => 'required',
'db_username' => 'required',
'db_password' => 'required',
];
if (!$this->validate($rules)) {

Yassine Doghri
committed
return redirect()
->back()
->withInput()
->with('errors', $this->validator->getErrors());

Yassine Doghri
committed
}
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
self::writeEnv([
'database.default.hostname' => $this->request->getPost(
'db_hostname'
),
'database.default.database' => $this->request->getPost('db_name'),
'database.default.username' => $this->request->getPost(
'db_username'
),
'database.default.password' => $this->request->getPost(
'db_password'
),
'database.default.DBPrefix' => $this->request->getPost('db_prefix'),
]);
return redirect()->back();
}
public function cacheConfig()
{
return view('install/cache_config');
}
public function attemptCacheConfig()
{
$rules = [
'cache_handler' => 'required',
];
if (!$this->validate($rules)) {
return redirect()
->back()
->withInput()
->with('errors', $this->validator->getErrors());
}
self::writeEnv([
'cache.handler' => $this->request->getPost('cache_handler'),
]);
return redirect()->back();

Yassine Doghri
committed
}
/**
* Runs all database migrations required for instance.
*/
public function migrate()
{
$migrations = \Config\Services::migrations();
!$migrations->setNamespace('Myth\Auth')->latest();
!$migrations->setNamespace('ActivityPub')->latest();
!$migrations->setNamespace(APP_NAMESPACE)->latest();

Yassine Doghri
committed
}
/**
* Runs all database seeds required for instance.
*/
public function seed()
{
$seeder = \Config\Database::seeder();

Yassine Doghri
committed
// Seed database
$seeder->call('AppSeeder');

Yassine Doghri
committed
}
/**
* Returns the form to create a the first superadmin user for the instance.
*/
public function createSuperAdmin()
{
return view('install/create_superadmin');

Yassine Doghri
committed
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
}
/**
* Creates the first superadmin user or redirects back to form if any error.
*
* After creation, user is redirected to login page to input its credentials.
*/
public function attemptCreateSuperAdmin()
{
$userModel = new UserModel();
// Validate here first, since some things,
// like the password, can only be validated properly here.
$rules = array_merge(
$userModel->getValidationRules(['only' => ['username']]),
[
'email' => 'required|valid_email|is_unique[users.email]',
'password' => 'required|strong_password',
]
);
if (!$this->validate($rules)) {
return redirect()
->back()
->withInput()
->with('errors', $this->validator->getErrors());
}
// Save the user
$user = new \App\Entities\User($this->request->getPost());
// Activate user
$user->activate();
$db = \Config\Database::connect();
$db->transStart();
if (!($userId = $userModel->insert($user, true))) {
$db->transRollback();

Yassine Doghri
committed
return redirect()
->back()
->withInput()
->with('errors', $userModel->errors());
}
// add newly created user to superadmin group
$authorization = Services::authorization();
$authorization->addUserToGroup($userId, 'superadmin');
$db->transComplete();
// Success!
// set redirect_url session as admin area to go to after login
session()->set('redirect_url', route_to('admin'));

Yassine Doghri
committed
return redirect()
->route('login')
->with('message', lang('Install.messages.createSuperAdminSuccess'));
}
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
/**
* writes config values in .env file
* overwrites any existing key and appends new ones
*
* @param array $data key/value config pairs
*
* @return void
*/
public static function writeEnv($configData)
{
$envData = file(ROOTPATH . '.env'); // reads an array of lines
foreach ($configData as $key => $value) {
$replaced = false;
$keyVal = $key . '="' . $value . '"' . PHP_EOL;
$envData = array_map(function ($line) use (
$key,
$keyVal,
&$replaced
) {
if (strpos($line, $key) === 0) {
$replaced = true;
return $keyVal;
}
return $line;
},
$envData);
if (!$replaced) {
array_push($envData, $keyVal);
}
}
file_put_contents(ROOTPATH . '.env', implode('', $envData));
}