<commit_before><?php

/**
 * @property User $User
 * @property Log $Log
 */
class UserShell extends AppShell
{
    public $uses = ['User', 'Log'];

    public function getOptionParser()
    {
        $parser = parent::getOptionParser();
        $parser->addSubcommand('list', [
            'help' => __('Get list of user accounts.'),
            'parser' => [
                'options' => [
                    'json' => ['help' => __('Output as JSON.'), 'boolean' => true],
                ],
            ]
        ]);
        $parser->addSubcommand('authkey', [
            'help' => __('Get information about given authkey.'),
            'parser' => [
                'arguments' => [
                    'authkey' => ['help' => __('Authentication key. If not provide, it will be read from STDIN.')],
                ],
            ]
        ]);
        $parser->addSubcommand('block', [
            'help' => __('Immediately block user.'),
            'parser' => [
                'arguments' => [
                    'userId' => ['help' => __('User ID or e-mail address.'), 'required' => true],
                ],
            ],
        ]);
        $parser->addSubcommand('unblock', [
            'help' => __('Unblock blocked user.'),
            'parser' => [
                'arguments' => [
                    'userId' => ['help' => __('User ID or e-mail address.'), 'required' => true],
                ],
            ],
        ]);
        $parser->addSubcommand('change_pw', [
            'help' => __('Change user password.'),
            'parser' => [
                'arguments' => [
                    'userId' => ['help' => __('User ID or e-mail address.'), 'required' => true],
                    'password' => ['help' => __('<PASSWORD> password.'), 'required' => true],
                ],
                'options' => [
                    'no_password_change' => ['help' => __('Do not require password change.'), 'boolean' => true],
                ],
            ],
        ]);
        $parser->addSubcommand('change_authkey', [
            'help' => __('Change authkey. When advanced authkeys are enabled, old authkeys will be disabled.'),
            'parser' => [
                'arguments' => [
                    'userId' => ['help' => __('User ID or e-mail address.'), 'required' => true],
                ],
            ],
        ]);
        $parser->addSubcommand('user_ips', [
            'help' => __('Show IP addresses that user uses to access MISP.'),
            'parser' => [
                'arguments' => [
                    'userId' => ['help' => __('User ID or e-mail address.'), 'required' => true],
                ],
                'options' => [
                    'json' => ['help' => __('Output as JSON.'), 'boolean' => true],
                ],
            ],
        ]);
        $parser->addSubcommand('ip_user', [
            'help' => __('Get user ID for user IP. If multiple users use the same IP, only last user ID will be returned.'),
            'parser' => [
                'arguments' => [
                    'ip' => ['help' => __('IPv4 or IPv6 address.'), 'required' => true],
                ],
                'options' => [
                    'json' => ['help' => __('Output as JSON.'), 'boolean' => true],
                ],
            ],
        ]);
        return $parser;
    }

    public function list()
    {
        if ($this->params['json']) {
            // do not fetch sensitive or big values
            $schema = $this->User->schema();
            unset($schema['authkey']);
            unset($schema['password']);
            unset($schema['gpgkey']);
            unset($schema['certif_public']);

            $fields = array_keys($schema);
            $fields[] = 'Role.*';
            $fields[] = 'Organisation.*';

            $users = $this->User->find('all', [
                'recursive' => -1,
                'fields' => $fields,
                'contain' => ['Organisation', 'Role', 'UserSetting'],
            ]);

            $this->out($this->json($users));
        } else {
            $users = $this->User->find('column', [
                'fields' => ['email'],
            ]);
            foreach ($users as $user) {
                $this->out($user);
            }
        }
    }

    public function authkey()
    {
        if (isset($this->args[0])) {
            $authkey = $this->args[0];
        } else {
            $authkey = fgets(STDIN); // read line from STDIN
        }
        $authkey = trim($authkey);
        if (strlen($authkey) !== 40) {
            $this->error('Authkey has not valid format.');
        }
        if (Configure::read('Security.advanced_authkeys')) {
            $user = $this->User->AuthKey->getAuthUserByAuthKey($authkey, true);
            if (empty($user)) {
                $this->error("Given authkey doesn't belong to any user.");
            }

            $isExpired = $user['authkey_expiration'] && $user['authkey_expiration'] < time();

            $this->out($this->json([
                'user_id' => $user['id'],
                'email' => $user['email'],
                'org_id' => $user['org_id'],
                'authkey_id' => $user['authkey_id'],
                'authkey_expiration' => $user['authkey_expiration'],
                'authkey_expired' => $isExpired,
                'allowed_ips' => $user['allowed_ips'],
                'authkey_read_only' => $user['authkey_read_only'],
            ]));

            $this->_stop($isExpired ? 2 : 0);
        } else {
            $user = $this->User->getAuthUserByAuthkey($authkey);
            if (empty($user)) {
                $this->error("Given authkey doesn't belong to any user.");
            }
            $this->out($this->json([
                'user_id' => $user['id'],
                'email' => $user['email'],
                'org_id' => $user['org_id'],
            ]));
        }
    }

    public function block()
    {
        list($userId) = $this->args;
        $user = $this->getUser($userId);
        if ($user['disabled']) {
            $this->error("User $userId is already blocked.");
        }
        $this->User->updateField($user, 'disabled', true);
        $this->out("User $userId blocked.");
    }

    public function unblock()
    {
        list($userId) = $this->args;
        $user = $this->getUser($userId);
        if (!$user['disabled']) {
            $this->error("User $userId is not blocked.");<commit_msg>new: [CLI] user authkey_valid command<commit_after><?php

/**
 * @property User $User
 * @property Log $Log
 */
class UserShell extends AppShell
{
    public $uses = ['User', 'Log'];

    public function getOptionParser()
    {
        $parser = parent::getOptionParser();
        $parser->addSubcommand('list', [
            'help' => __('Get list of user accounts.'),
            'parser' => [
                'options' => [
                    'json' => ['help' => __('Output as JSON.'), 'boolean' => true],
                ],
            ]
        ]);
        $parser->addSubcommand('authkey', [
            'help' => __('Get information about given authkey.'),
            'parser' => [
                'arguments' => [
                    'authkey' => ['help' => __('Authentication key. If not provide, it will be read from STDIN.')],
                ],
            ]
        ]);
        $parser->addSubcommand('authkey_valid', [
            'help' => __('Check if given authkey by STDIN is valid.'),
        ]);
        $parser->addSubcommand('block', [
            'help' => __('Immediately block user.'),
            'parser' => [
                'arguments' => [
                    'userId' => ['help' => __('User ID or e-mail address.'), 'required' => true],
                ],
            ],
        ]);
        $parser->addSubcommand('unblock', [
            'help' => __('Unblock blocked user.'),
            'parser' => [
                'arguments' => [
                    'userId' => ['help' => __('User ID or e-mail address.'), 'required' => true],
                ],
            ],
        ]);
        $parser->addSubcommand('change_pw', [
            'help' => __('Change user password.'),
            'parser' => [
                'arguments' => [
                    'userId' => ['help' => __('User ID or e-mail address.'), 'required' => true],
                    'password' => ['help' => __('<PASSWORD>.'), 'required' => true],
                ],
                'options' => [
                    'no_password_change' => ['help' => __('Do not require password change.'), 'boolean' => true],
                ],
            ],
        ]);
        $parser->addSubcommand('change_authkey', [
            'help' => __('Change authkey. When advanced authkeys are enabled, old authkeys will be disabled.'),
            'parser' => [
                'arguments' => [
                    'userId' => ['help' => __('User ID or e-mail address.'), 'required' => true],
                ],
            ],
        ]);
        $parser->addSubcommand('user_ips', [
            'help' => __('Show IP addresses that user uses to access MISP.'),
            'parser' => [
                'arguments' => [
                    'userId' => ['help' => __('User ID or e-mail address.'), 'required' => true],
                ],
                'options' => [
                    'json' => ['help' => __('Output as JSON.'), 'boolean' => true],
                ],
            ],
        ]);
        $parser->addSubcommand('ip_user', [
            'help' => __('Get user ID for user IP. If multiple users use the same IP, only last user ID will be returned.'),
            'parser' => [
                'arguments' => [
                    'ip' => ['help' => __('IPv4 or IPv6 address.'), 'required' => true],
                ],
                'options' => [
                    'json' => ['help' => __('Output as JSON.'), 'boolean' => true],
                ],
            ],
        ]);
        return $parser;
    }

    public function list()
    {
        if ($this->params['json']) {
            // do not fetch sensitive or big values
            $schema = $this->User->schema();
            unset($schema['authkey']);
            unset($schema['password']);
            unset($schema['gpgkey']);
            unset($schema['certif_public']);

            $fields = array_keys($schema);
            $fields[] = 'Role.*';
            $fields[] = 'Organisation.*';

            $users = $this->User->find('all', [
                'recursive' => -1,
                'fields' => $fields,
                'contain' => ['Organisation', 'Role', 'UserSetting'],
            ]);

            $this->out($this->json($users));
        } else {
            $users = $this->User->find('column', [
                'fields' => ['email'],
            ]);
            foreach ($users as $user) {
                $this->out($user);
            }
        }
    }

    public function authkey()
    {
        if (isset($this->args[0])) {
            $authkey = $this->args[0];
        } else {
            $authkey = fgets(STDIN); // read line from STDIN
        }
        $authkey = trim($authkey);
        if (strlen($authkey) !== 40) {
            $this->error('Authkey has not valid format.');
        }
        if (Configure::read('Security.advanced_authkeys')) {
            $user = $this->User->AuthKey->getAuthUserByAuthKey($authkey, true);
            if (empty($user)) {
                $this->error("Given authkey doesn't belong to any user.");
            }

            $isExpired = $user['authkey_expiration'] && $user['authkey_expiration'] < time();

            $this->out($this->json([
                'user_id' => $user['id'],
                'email' => $user['email'],
                'org_id' => $user['org_id'],
                'authkey_id' => $user['authkey_id'],
                'authkey_expiration' => $user['authkey_expiration'],
                'authkey_expired' => $isExpired,
                'allowed_ips' => $user['allowed_ips'],
                'authkey_read_only' => $user['authkey_read_only'],
            ]));

            $this->_stop($isExpired ? 2 : 0);
        } else {
            $user = $this->User->getAuthUserByAuthkey($authkey);
            if (empty($user)) {
                $this->error("Given authkey doesn't belong to any user.");
            }
            $this->out($this->json([
                'user_id' => $user['id'],
                'email' => $user['email'],
                'org_id' => $user['org_id'],
            ]));
        }
    }

    /**
     * Reads line from stdin and checks if authkey is valid. Returns '1' to stdout if key is valid and '0' if not.
     */
    public function authkey_valid()
    {
        $cache = [];
        do {
            $authkey = fgets(STDIN); // read line from STDIN
            $authkey = trim($authkey);
            if (strlen($authkey) !== 40) {
                fwrite(STDOUT, "0\n");  // authkey is not in valid format
                continue;
            }
            $time = time();
            // Generate hash from authkey to not store raw authkey in memory
            $keyHash = hash('sha256', $authkey, true);
            if (isset($cache[$keyHash]) && $cache[$keyHash][1] > $time) {
                fwrite(STDOUT, $cache[$keyHash][0] ? "1\n" : "0\n");
                continue;
            }

            if (Configure::read('Security.advanced_authkeys')) {
                $user = $this->User->AuthKey->getAuthUserByAuthKey($authkey);
            } else {
                $user = $this->User->getAuthUserByAuthkey($authkey);
            }
            $user = (bool)$user;
            // Cache results for 5 seconds
            $cache[$keyHash] = [$user, $time + 5];
            fwrite(STDOUT, $user ? "1\n" : "0\n");
        } while (true);
    }

    public function block()
    {
        list($userId) = $this->args;
        $user = $this->getUser($userId);
        if ($user['disabled']) {
            $this->error("User $userId is already blocked.");
        }
        $this->User->updateField($user, 'disabled', true);
        $this->out("User $userId blocked.");
    }

    public function unblock()
    {
        list($userId) = $this->args;
        $user = $this->getUser($userId);
        if (!$user['disabled']) {
            $this->error("User $userId is not blocked.");
{'fraction_non_alphanumeric': 0.17708188031803598, 'fraction_numerical': 0.0023713209652671224, 'mean_word_length': 1.4838039147756799, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 251, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4717989', 'n_tokens_mistral': 4056, 'n_tokens_neox': 3916, 'n_words': 867}