Commit 02d4ba69 authored by Yassine Doghri's avatar Yassine Doghri
Browse files

feat(install): init database and create superadmin using CLI

closes #380
parent 97d793f5
Loading
Loading
Loading
Loading
+17 −0
Original line number Diff line number Diff line
@@ -123,6 +123,23 @@ based on the `.env.example` file.

:::

### Using CLI

1. Create a `.env` file in the package root based on the `.env.example` file.
2. Initialize the database using:

   ```sh
   php spark install:init-database
   ```

3. Create the superadmin user using:

   ```sh
   php spark install:create-superadmin
   ```

4. Head on to your admin gateway to start podcasting!

### Email/SMTP setup

Email configuration is required for some features to work properly (eg.
+139 −0
Original line number Diff line number Diff line
<?php

declare(strict_types=1);

namespace Modules\Install\Commands;

use CodeIgniter\Shield\Commands\BaseCommand;
use CodeIgniter\Shield\Commands\Exceptions\BadInputException;
use CodeIgniter\Shield\Commands\Exceptions\CancelException;
use CodeIgniter\Shield\Entities\User;
use CodeIgniter\Shield\Validation\ValidationRules;

class CreateSuperadmin extends BaseCommand
{
    /**
     * @var string
     */
    protected $group = 'Install';

    /**
     * @var string
     */
    protected $name = 'install:create-superadmin';

    /**
     * @var string
     */
    protected $description = 'Creates the instance superadmin.';

    /**
     * Validation rules for user fields
     *
     * @var array<string, array<string, array{rules: string[]}>>
     */
    private array $validationRules = [];

    public function run(array $params): void
    {
        // first, check that super admin does not exist
        $userModel = model('UserModel');
        $isSuperAdminCreated = $userModel->where('is_owner', true)
            ->countAllResults();

        if ($isSuperAdminCreated > 0) {
            $this->write('Super admin was already created!', 'red');

            exit(EXIT_ERROR);
        }

        $this->setValidationRules();

        $username = $params['n'] ?? null;
        $email = $params['e'] ?? null;

        $data = [
            'is_owner' => true,
        ];

        if ($username === null) {
            $username = $this->prompt('Username', null, $this->validationRules['username']['rules']);
        }

        $data['username'] = $username;

        if ($email === null) {
            $email = $this->prompt('Email', null, $this->validationRules['email']['rules']);
        }

        $data['email'] = $email;

        $password = $this->prompt('Password', null, $this->validationRules['password']['rules']);
        $passwordConfirm = $this->prompt(
            'Password confirmation',
            null,
            $this->validationRules['password']['rules']
        );

        if ($password !== $passwordConfirm) {
            throw new BadInputException("The passwords don't match");
        }

        $data['password'] = $password;

        // Run validation if the user has passed username and/or email via command line
        $validation = service('validation');
        $validation->setRules($this->validationRules);

        if (! $validation->run($data)) {
            foreach ($validation->getErrors() as $message) {
                $this->write($message, 'red');
            }

            throw new CancelException('Super admin creation aborted');
        }

        $userModel = model('UserModel');

        $user = new User($data);
        $userModel->save($user);

        $this->write('Super admin "' . $username . '" created', 'green');
    }

    private function setValidationRules(): void
    {
        $validationRules = new ValidationRules();

        $rules = $validationRules->getRegistrationRules();

        // Remove `strong_password` because it only supports use cases
        // to check the user's own password.
        $passwordRules = $rules['password']['rules'];
        if (is_string($passwordRules)) {
            $passwordRules = explode('|', $passwordRules);
        }

        if (($key = array_search('strong_password[]', $passwordRules, true)) !== false) {
            unset($passwordRules[$key]);
        }

        if (($key = array_search('strong_password', $passwordRules, true)) !== false) {
            unset($passwordRules[$key]);
        }

        /** @var Auth $config */
        $config = config('Auth');

        // Add `min_length`
        $passwordRules[] = 'min_length[' . $config->minimumPasswordLength . ']';

        $rules['password']['rules'] = $passwordRules;

        $this->validationRules = [
            'username' => $rules['username'],
            'email'    => $rules['email'],
            'password' => $rules['password'],
        ];
    }
}
+39 −0
Original line number Diff line number Diff line
<?php

declare(strict_types=1);

namespace Modules\Install\Commands;

use CodeIgniter\CLI\BaseCommand;
use Config\Database;
use Config\Services;

class InitDatabase extends BaseCommand
{
    /**
     * @var string
     */
    protected $group = 'Install';

    /**
     * @var string
     */
    protected $name = 'install:init-database';

    /**
     * @var string
     */
    protected $description = 'Runs all database migrations for Castopod.';

    public function run(array $params): void
    {
        // Run all migrations
        $migrate = Services::migrations();
        $migrate->setNamespace(null)
            ->latest();

        // Seed database
        $seeder = Database::seeder();
        $seeder->call('AppSeeder');
    }
}