The Framework Code

class/framework/model/user.php

File List

<?php
/**
 * A model class for the RedBean object User
 *
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! This is a Framework system class - do not edit !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 *
 * @author Lindsay Marshall <lindsay.marshall@ncl.ac.uk>
 * @copyright 2013-2021 Newcastle University
 * @package Framework\Model
 */
    namespace Framework\Model;

    use \Config\Framework as FW;
    use \Support\Context;
/**
 * A class implementing a RedBean model for User beans
 * @psalm-suppress UnusedClass
 */
    final class User extends \RedBeanPHP\SimpleModel
    {
/**
 * @var string   The type of the bean that stores roles for this page
 * @phpcsSuppress SlevomatCodingStandard.Classes.UnusedPrivateElements
 */
        private string $roletype = FW::ROLE;
/**
 * @var array<array<bool>>  Key is name of field and the array contains flags for checks
 * @phpcsSuppress SlevomatCodingStandard.Classes.UnusedPrivateElements
 */
        private static array $editfields = [
            'email'     => [TRUE, FALSE],         // [NOTEMPTY]
        ];

        use \ModelExtend\User;
        use \ModelExtend\FWEdit;
        use \ModelExtend\MakeGuard;
        use \Framework\Support\HandleRole;
/**
 * Add a User from a form - invoked by the AJAX bean operation
 *
 * @see \Framework\Ajax\Bean
 *
 * @throws \Framework\Exception\BadValue
 */
        public static function add(Context $context) : \RedBeanPHP\OODBBean
        {
            $now = $context->utcnow(); // make sure time is in UTC
            $fdt = $context->formdata('post');
            $pw = $fdt->mustFetch('password'); // make sure we have a password...
            if (self::pwValid($pw))
            {
                $login = $fdt->mustFetch('login');
                if (\is_object(\R::findOne(FW::USER, 'login=?', [$login])))
                {
                    throw new \Framework\Exception\BadValue('Login name already exists');
                }
                $u = \R::dispense(FW::USER);
                $u->login = $login;
                $u->email = $fdt->mustFetch('email');
                $u->active = 1;
                $u->confirm = 1;
                $u->joined = $now;
                \R::store($u);
                $u->setpw($pw); // set the password
                if ($fdt->fetch('admin', 0) == 1)
                {
                    $u->addrole(FW::FWCONTEXT, FW::ADMINROLE, '', $now);
                }
                if ($fdt->fetch('devel', 0) == 1)
                {
                    $u->addrole(FW::FWCONTEXT, FW::DEVELROLE, '', $now);
                }
                $u->addData($context);
                return $u;
            }
            // bad password return
            throw new \Framework\Exception\BadValue('Invalid Password');
        }
/**
 * Is this user an admin?
 */
        public function isAdmin() : bool
        {
            return \is_object($this->hasrole(FW::FWCONTEXT, FW::ADMINROLE));
        }
/**
 * Is this user active?
 */
        public function isActive() : bool
        {
            return $this->bean->active != 0;
        }
/**
 * Is this user confirmed?
 */
        public function isConfirmed() : bool
        {
            return $this->bean->confirm != 0;
        }
/**
 * Is this user a developer?
 */
        public function isDeveloper() : bool
        {
            return \is_object($this->hasRole(FW::FWCONTEXT, FW::DEVELROLE));
        }
/**
 * Set the user's password
 */
        public function setPW(string $password) : void
        {
            $this->bean->password = \password_hash($password, PASSWORD_DEFAULT);
            \R::store($this->bean);
        }
/**
 * Check a password
 */
        public function pwOK(string $password) : bool
        {
            return \password_verify($password, $this->bean->password);
        }
/**
 * Set the email confirmation flag
 */
        public function doConfirm() : void
        {
            $this->bean->active = 1;
            $this->bean->confirm = 1;
            \R::store($this->bean);
        }
/**
 * Generate a JWT token for this user that can be used as a unique id from a phone.
 *
 * @param $url    The URL of the site
 * @param $device  Currently not used!!
 *
 * @psalm-suppress UnusedVariable
 * @phpcsSuppress SlevomatCodingStandard.Functions.UnusedParameter
 */
        public function makeToken(string $url, string $device = '') : string
        {
            $token = (object) ['iss' => $url, 'iat' => \idate('U'), 'sub' => $this->bean->getID()];
            /** @psalm-suppress UndefinedClass - JWT is not currently included in the psalm checks... */
            return \Framework\Utility\JWT\JWT::encode($token, FW::AUTHKEY);
        }
/**
 * Setup for an edit
 *
 * @phpcsSuppress SlevomatCodingStandard.Functions.UnusedParameter
 */
        public function startEdit(Context $context, array $rest) : void
        {
            // nothing to do
        }
/**
 * Handle an edit form for this user
 *
 * @return array  [TRUE if error, [error messages]]
 */
        public function edit(Context $context) : array
        {
            $fdt = $context->formData('post');
            $emess = $this->doFields($fdt);

            $pw = $fdt->fetch('pw', '');
            if ($pw !== '')
            {
                if ($pw === $fdt->fetch('rpw', ''))
                {
                    $this->setpw($pw); // setting the password will do a store
                }
                else
                {
                    $emess[] = 'Passwords do not match';
                }
            }
            $this->editroles($context);
            return [!empty($emess), $emess];
        }
/**
 * Return the user's 2FA secret
 */
        public function secret() : string
        {
            return $this->bean->secret;
        }
    }
?>