YetiForceCompany/YetiForceCRM

View on GitHub
app/Cli/Users.php

Summary

Maintainability
C
1 day
Test Coverage
F
29%
<?php
/**
 * Users cli file.
 *
 * @package Cli
 *
 * @copyright YetiForce S.A.
 * @license   YetiForce Public License 6.5 (licenses/LicenseEN.txt or yetiforce.com)
 * @author    Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com>
 */

namespace App\Cli;

/**
 * Users cli class.
 */
class Users extends Base
{
    /** {@inheritdoc} */
    public $moduleName = 'Users';

    /** @var string[] Methods list */
    public $methods = [
        'resetPassword' => 'Reset user password',
        'passwordAuth' => 'Disable 2FA or LDAP auth',
        'resetAllPasswords' => 'Reset all user passwords',
    ];

    /**
     * Reset user password.
     *
     * @return void
     */
    public function resetPassword(): void
    {
        $this->climate->arguments->add([
            'login' => [
                'prefix' => 'l',
                'description' => 'Login/User name',
            ],
            'password' => [
                'prefix' => 'p',
                'description' => 'New password',
            ],
            'confirmation' => [
                'prefix' => 'c',
                'description' => 'Don\'t ask for confirmation',
            ],
        ]);
        if ($this->helpMode) {
            return;
        }
        $this->climate->arguments->parse();
        if ($this->climate->arguments->defined('login')) {
            $userName = $this->climate->arguments->get('login');
        } else {
            $input = $this->climate->input('Enter login/username:');
            $userName = $input->prompt();
        }
        $row = (new \App\Db\Query())->select(['id', 'deleted'])->from('vtiger_users')->where(['or', ['user_name' => $userName], ['user_name' => strtolower($userName)]])->limit(1)->one();
        if (!$row) {
            $this->climate->red('User not found');
            if ($this->climate->arguments->defined('confirmation') || $this->climate->confirm('Re-enter login?')->confirmed()) {
                $this->resetPassword();
            } else {
                $this->cli->actionsList('Users');
            }
            return;
        }
        $userRecordModel = \Users_Record_Model::getInstanceById($row['id'], 'Users');
        $this->climate->lightBlue($userRecordModel->getDisplayName() . ' (' . $userRecordModel->getDisplayValue('roleid', false, true) . ')');
        if (0 !== (int) $row['deleted']) {
            $this->climate->lightGreen('User inactive!!!');
        }
        if ($this->climate->arguments->defined('password')) {
            $password = $this->climate->arguments->get('password');
        } else {
            $password = \App\Encryption::generateUserPassword();
            $this->climate->lightGreen('New password: ' . $password);
        }
        $userRecordModel->set('changeUserPassword', true);
        $userRecordModel->set('user_password', $password);
        $userRecordModel->set('date_password_change', date('Y-m-d H:i:s'));

        $eventHandler = new \App\EventHandler();
        $eventHandler->setRecordModel($userRecordModel);
        $eventHandler->setModuleName('Users');
        $eventHandler->setParams(['action' => 'reset']);
        $eventHandler->trigger('UsersBeforePasswordChange');
        $userRecordModel->save();
        $eventHandler->trigger('UsersAfterPasswordChange');
        if ($this->climate->arguments->defined('confirmation') || $this->climate->confirm('Send password reset link to user\'s email address?')->confirmed()) {
            $expirationDate = date('Y-m-d H:i:s', strtotime('+24 hour'));
            $token = \App\Utils\Tokens::generate('Users_LoginForgotPassword_Action', [$userRecordModel->getId()], $expirationDate);
            \App\Mailer::sendFromTemplate([
                'template' => 'UsersResetPassword',
                'moduleName' => 'Users',
                'recordId' => $userRecordModel->getId(),
                'to' => $userRecordModel->get('email1'),
                'url' => \Config\Main::$site_URL . 'index.php?module=Users&view=LoginPassChange&token=' . $token,
                'expirationDate' => \App\Fields\DateTime::formatToDisplay($expirationDate),
                'token' => $token,
            ]);
        }
        if (!$this->climate->arguments->defined('action')) {
            $this->cli->actionsList('Users');
        }
    }

    /**
     * Reset all user passwords.
     *
     * @return void
     */
    public function resetAllPasswords(): void
    {
        $this->climate->arguments->add([
            'confirmation' => [
                'prefix' => 'c',
                'description' => 'Don\'t ask for confirmation',
            ],
        ]);
        if ($this->helpMode) {
            return;
        }
        $this->climate->lightBlue('New passwords will be sent to the user\'s e-mail, it is required that the e-mail sending works properly.');
        if (!$this->climate->arguments->defined('confirmation') && !$this->climate->confirm('Do you want to reset the passwords of all active users?')->confirmed()) {
            $this->cli->actionsList('Users');
            return;
        }
        $userIds = (new \App\Db\Query())->select(['id'])->from('vtiger_users')->where(['deleted' => 0])->column();
        $progress = $this->climate->progress()->total(\count($userIds));
        $i = 0;
        foreach ($userIds as $userId) {
            $userRecordModel = \Users_Record_Model::getInstanceById($userId, 'Users');
            $userRecordModel->set('changeUserPassword', true);
            $userRecordModel->set('user_password', \App\Encryption::generateUserPassword());
            $userRecordModel->set('date_password_change', date('Y-m-d H:i:s'));

            $eventHandler = new \App\EventHandler();
            $eventHandler->setRecordModel($userRecordModel);
            $eventHandler->setModuleName('Users');
            $eventHandler->setParams(['action' => 'massReset']);
            $eventHandler->trigger('UsersBeforePasswordChange');
            $userRecordModel->save();
            $eventHandler->trigger('UsersAfterPasswordChange');

            $expirationDate = date('Y-m-d H:i:s', strtotime('+24 hour'));
            $token = \App\Utils\Tokens::generate('Users_LoginForgotPassword_Action', [$userRecordModel->getId()], $expirationDate);
            \App\Mailer::sendFromTemplate([
                'template' => 'UsersResetPassword',
                'moduleName' => 'Users',
                'recordId' => $userRecordModel->getId(),
                'to' => $userRecordModel->get('email1'),
                'url' => \Config\Main::$site_URL . 'index.php?module=Users&view=LoginPassChange&token=' . $token,
                'expirationDate' => \App\Fields\DateTime::formatToDisplay($expirationDate),
                'token' => $token,
            ]);
            $progress->advance();
            ++$i;
        }
        $this->climate->lightGreen('Number of passwords reset: ' . $i);
    }

    /**
     * Disable 2FA or LDAP auth of any user.
     *
     * @return void
     */
    public function passwordAuth(): void
    {
        $this->climate->arguments->add([
            'login' => [
                'prefix' => 'l',
                'description' => 'Login/User name',
            ],
        ]);
        if ($this->helpMode) {
            return;
        }
        $this->climate->arguments->parse();
        if ($this->climate->arguments->defined('login')) {
            $userName = $this->climate->arguments->get('login');
        } else {
            $input = $this->climate->input('Enter login/username:');
            $userName = $input->prompt();
        }
        $row = (new \App\Db\Query())->select(['id', 'deleted'])->from('vtiger_users')->where(['or', ['user_name' => $userName], ['user_name' => strtolower($userName)]])->limit(1)->one();
        if (!$row) {
            $this->climate->red('User not found');
            if ($this->climate->confirm('Re-enter login?')->confirmed()) {
                $this->passwordAuth();
            } else {
                $this->cli->actionsList('Users');
            }
            return;
        }
        $userRecordModel = \Users_Record_Model::getInstanceById($row['id'], 'Users');
        $this->climate->lightBlue($userRecordModel->getDisplayName() . ' (' . $userRecordModel->getDisplayValue('roleid', false, true) . ')');
        if (0 !== (int) $row['deleted']) {
            $this->climate->lightGreen('User inactive!!!');
        }
        $userRecordModel->set('login_method', 'PLL_PASSWORD');
        $userRecordModel->set('authy_secret_totp', '');
        $userRecordModel->set('authy_methods', '');
        $userRecordModel->save();
        if (!$this->climate->arguments->defined('action')) {
            $this->cli->actionsList('Users');
        }
    }
}