Skip to content
Snippets Groups Projects
class.user.php 38.3 KiB
Newer Older
  • Learn to ignore specific revisions
  •         return $this->hasStatus(UserAccountStatus::REQUIRE_PASSWD_RESET);
    
        }
    
        function isPasswdResetEnabled() {
    
            return !$this->hasStatus(UserAccountStatus::FORBID_PASSWD_RESET);
    
    Peter Rotich's avatar
    Peter Rotich committed
        function getInfo() {
            return $this->ht;
        }
    
    
        function getId() {
            return $this->get('id');
        }
    
        function getUserId() {
            return $this->get('user_id');
        }
    
        function getUser() {
    
        function getExtraAttr($attr=false, $default=null) {
            if (!isset($this->_extra))
    
                $this->_extra = JsonDataParser::decode($this->get('extra', ''));
    
    
            return $attr ? (@$this->_extra[$attr] ?: $default) : $this->_extra;
        }
    
        function setExtraAttr($attr, $value) {
            $this->getExtraAttr();
            $this->_extra[$attr] = $value;
        }
    
        /**
         * Function: getLanguage
         *
         * Returns the language preference for the user or false if no
         * preference is defined. False indicates the browser indicated
         * preference should be used. For requests apart from browser requests,
         * the last language preference of the browser is set in the
         * 'browser_lang' extra attribute upon logins. Send the LANG_MAILOUTS
         * flag to also consider this saved value. Such is useful when sending
         * the user a message (such as an email), and the user's browser
         * preference is not available in the HTTP request.
         *
         * Parameters:
         * $flags - (int) Send UserAccount::LANG_MAILOUTS if the user's
         *      last-known browser preference should be considered. Normally
         *      only the user's saved language preference is considered.
         *
         * Returns:
         * Current or last-known language preference or false if no language
         * preference is currently set or known.
         */
        function getLanguage($flags=false) {
            $lang = $this->get('lang', false);
            if (!$lang && ($flags & UserAccount::LANG_MAILOUTS))
                $lang = $this->getExtraAttr('browser_lang', false);
    
            return $lang;
        }
    
    
        function getTimezone() {
            return $this->timezone;
        }
    
    
        function save($refetch=false) {
            // Serialize the extra column on demand
            if (isset($this->_extra)) {
                $this->extra = JsonDataEncoder::encode($this->_extra);
            }
            return parent::save($refetch);
    
        function hasPassword() {
            return (bool) $this->get('passwd');
        }
    
        function sendResetEmail() {
    
    Peter Rotich's avatar
    Peter Rotich committed
            return static::sendUnlockEmail('pwreset-client') === true;
    
        }
    
        function sendConfirmEmail() {
    
    Peter Rotich's avatar
    Peter Rotich committed
            return static::sendUnlockEmail('registration-client') === true;
    
        function setPassword($new) {
    
            $this->set('passwd', Passwd::hash($new));
    
        protected function sendUnlockEmail($template) {
            global $ost, $cfg;
    
            $token = Misc::randCode(48); // 290-bits
    
            $email = $cfg->getDefaultEmail();
    
            $content = Page::lookupByType($template);
    
    
            if (!$email ||  !$content)
    
                return new BaseError(sprintf(_S('%s: Unable to retrieve template'),
    
    
            $vars = array(
                'url' => $ost->getConfig()->getBaseUrl(),
                'token' => $token,
                'user' => $this->getUser(),
                'recipient' => $this->getUser(),
                'link' => sprintf(
                    "%s/pwreset.php?token=%s",
                    $ost->getConfig()->getBaseUrl(),
                    $token),
            );
            $vars['reset_link'] = &$vars['link'];
    
            $info = array('email' => $email, 'vars' => &$vars, 'log'=>true);
    
            Signal::send('auth.pwreset.email', $this->getUser(), $info);
    
            $lang = $this->getLanguage(UserAccount::LANG_MAILOUTS);
    
            $msg = $ost->replaceTemplateVariables(array(
    
                'subj' => $content->getLocalName($lang),
                'body' => $content->getLocalBody($lang),
    
            ), $vars);
    
            $_config = new Config('pwreset');
    
            $_config->set($vars['token'], 'c'.$this->getUser()->getId());
    
    Peter Rotich's avatar
    Peter Rotich committed
            $email->send($this->getUser()->getEmail(),
    
                Format::striptags($msg['subj']), $msg['body']);
    
    Peter Rotich's avatar
    Peter Rotich committed
    
            return true;
    
    Peter Rotich's avatar
    Peter Rotich committed
        function __toString() {
            return (string) $this->getStatus();
        }
    
        /*
         * This assumes the staff is doing the update
         */
        function update($vars, &$errors) {
            global $thisstaff;
    
    
            if (!$thisstaff) {
    
                $errors['err'] = __('Access denied');
    
    Peter Rotich's avatar
    Peter Rotich committed
                return false;
            }
    
            // TODO: Make sure the username is unique
    
    
            // Timezone selection is not required. System default is a valid
            // fallback
    
    Peter Rotich's avatar
    Peter Rotich committed
    
            // Changing password?
            if ($vars['passwd1'] || $vars['passwd2']) {
                if (!$vars['passwd1'])
    
                    $errors['passwd1'] = __('New password is required');
    
    Peter Rotich's avatar
    Peter Rotich committed
                elseif ($vars['passwd1'] && strlen($vars['passwd1'])<6)
    
                    $errors['passwd1'] = __('Must be at least 6 characters');
    
    Peter Rotich's avatar
    Peter Rotich committed
                elseif ($vars['passwd1'] && strcmp($vars['passwd1'], $vars['passwd2']))
    
                    $errors['passwd2'] = __('Passwords do not match');
    
            // Make sure the username is not an email.
            if ($vars['username'] && Validator::is_email($vars['username']))
                $errors['username'] =
                    __('Users can always sign in with their email address');
    
    
    Peter Rotich's avatar
    Peter Rotich committed
            if ($errors) return false;
    
    
            $this->set('timezone', $vars['timezone']);
    
    Peter Rotich's avatar
    Peter Rotich committed
            $this->set('username', $vars['username']);
    
            if ($vars['passwd1']) {
    
                $this->setPassword($vars['passwd1']);
    
                $this->setStatus(UserAccountStatus::CONFIRMED);
    
    Peter Rotich's avatar
    Peter Rotich committed
            // Set flags
    
            foreach (array(
    
                    'pwreset-flag' => UserAccountStatus::REQUIRE_PASSWD_RESET,
                    'locked-flag' => UserAccountStatus::LOCKED,
                    'forbid-pwchange-flag' => UserAccountStatus::FORBID_PASSWD_RESET
    
            ) as $ck=>$flag) {
                if ($vars[$ck])
                    $this->setStatus($flag);
                else
                    $this->clearStatus($flag);
            }
    
    Peter Rotich's avatar
    Peter Rotich committed
            return $this->save(true);
        }
    
    
        static function createForUser($user, $defaults=false) {
    
            $acct = new static(array('user_id'=>$user->getId()));
    
            if ($defaults && is_array($defaults)) {
                foreach ($defaults as $k => $v)
                    $acct->set($k, $v);
            }
            return $acct;
    
        }
    
        static function lookupByUsername($username) {
            if (strpos($username, '@') !== false)
                $user = static::lookup(array('user__emails__address'=>$username));
            else
                $user = static::lookup(array('username'=>$username));
    
            return $user;
        }
    
        static function register($user, $vars, &$errors) {
    
    Peter Rotich's avatar
    Peter Rotich committed
    
            if (!$user || !$vars)
                return false;
    
            //Require temp password.
    
            if ((!$vars['backend'] || $vars['backend'] != 'client')
                    && !isset($vars['sendemail'])) {
    
    Peter Rotich's avatar
    Peter Rotich committed
                if (!$vars['passwd1'])
    
                    $errors['passwd1'] = 'Temporary password required';
    
    Peter Rotich's avatar
    Peter Rotich committed
                elseif ($vars['passwd1'] && strlen($vars['passwd1'])<6)
                    $errors['passwd1'] = 'Must be at least 6 characters';
                elseif ($vars['passwd1'] && strcmp($vars['passwd1'], $vars['passwd2']))
    
                    $errors['passwd2'] = 'Passwords do not match';
    
    Peter Rotich's avatar
    Peter Rotich committed
            }
    
            if ($errors) return false;
    
    
            $account = new UserAccount(array(
                'user_id' => $user->getId(),
                'timezone' => $vars['timezone'],
                'backend' => $vars['backend'],
            ));
    
    Peter Rotich's avatar
    Peter Rotich committed
    
            if ($vars['username'] && strcasecmp($vars['username'], $user->getEmail()))
                $account->set('username', $vars['username']);
    
            if ($vars['passwd1'] && !$vars['sendemail']) {
    
                $account->set('passwd', Passwd::hash($vars['passwd1']));
    
                $account->setStatus(UserAccountStatus::CONFIRMED);
    
                    $account->setStatus(UserAccountStatus::REQUIRE_PASSWD_RESET);
    
                if ($vars['forbid-pwreset-flag'])
    
                    $account->setStatus(UserAccountStatus::FORBID_PASSWD_RESET);
    
    Peter Rotich's avatar
    Peter Rotich committed
            }
    
            elseif ($vars['backend'] && $vars['backend'] != 'client') {
                // Auto confirm remote accounts
    
                $account->setStatus(UserAccountStatus::CONFIRMED);
    
    Peter Rotich's avatar
    Peter Rotich committed
    
            $account->save(true);
    
    
            if (!$account->isConfirmed() && $vars['sendemail'])
    
    Peter Rotich's avatar
    Peter Rotich committed
                $account->sendConfirmEmail();
    
            return $account;
        }
    
    
    class UserAccountStatus {
    
        var $flag;
    
        const CONFIRMED             = 0x0001;
        const LOCKED                = 0x0002;
        const REQUIRE_PASSWD_RESET  = 0x0004;
        const FORBID_PASSWD_RESET   = 0x0008;
    
        function __construct($flag) {
            $this->flag = $flag;
        }
    
        function check($flag) {
            return 0 !== ($this->flag & $flag);
        }
    
        function isLocked() {
            return $this->check(self::LOCKED);
        }
    
        function isConfirmed() {
            return $this->check(self::CONFIRMED);
        }
    
        function __toString() {
    
            if ($this->isLocked())
    
                return __('Locked (Administrative)');
    
    
            if (!$this->isConfirmed())
    
                return __('Locked (Pending Activation)');
    
            // ... Other flags here (password reset, etc).
    
    
            return __('Active (Registered)');
    
    /*
     *  Generic user list.
     */
    
    class UserList extends ListObject
    implements TemplateVariable {
    
    
        function __toString() {
    
            return $this->getNames();
        }
    
        function getNames() {
    
            $list = array();
    
            foreach($this->storage as $user) {
    
                if (is_object($user))
                    $list [] = $user->getName();
            }
            return $list ? implode(', ', $list) : '';
        }
    
    
        function getFull() {
            $list = array();
            foreach($this->storage as $user) {
                if (is_object($user))
                    $list[] = sprintf("%s <%s>", $user->getName(), $user->getEmail());
            }
    
            return $list ? implode(', ', $list) : '';
        }
    
        function getEmails() {
            $list = array();
            foreach($this->storage as $user) {
                if (is_object($user))
                    $list[] = $user->getEmail();
            }
            return $list ? implode(', ', $list) : '';
        }
    
        static function getVarScope() {
            return array(
    
                'names' => __('List of names'),
                'emails' => __('List of email addresses'),
                'full' => __('List of names and email addresses'),