Skip to content
Snippets Groups Projects
class.user.php 31.4 KiB
Newer Older
<?php
/*********************************************************************
    class.user.php

    External end-user identification for osTicket

    Peter Rotich <peter@osticket.com>
    Jared Hancock <jared@osticket.com>
    Copyright (c)  2006-2013 osTicket
    http://www.osticket.com

    Released under the GNU General Public License WITHOUT ANY WARRANTY.
    See LICENSE.TXT for details.

    vim: expandtab sw=4 ts=4 sts=4:
**********************************************************************/
require_once(INCLUDE_DIR . 'class.orm.php');

class UserEmailModel extends VerySimpleModel {
    static $meta = array(
        'table' => USER_EMAIL_TABLE,
        'pk' => array('id'),
        'joins' => array(
            'user' => array(
                'constraint' => array('user_id' => 'UserModel.id')
            )
        )
    );
}

class TicketModel extends VerySimpleModel {
    static $meta = array(
        'table' => TICKET_TABLE,
        'pk' => array('ticket_id'),
        'joins' => array(
            'user' => array(
                'constraint' => array('user_id' => 'UserModel.id')
            )
        )
    );

    function getId() {
        return $this->ticket_id;
    }

    function delete() {

        if (($ticket=Ticket::lookup($this->getId())) && @$ticket->delete())
            return true;

        return false;
    }
}

class UserModel extends VerySimpleModel {
    static $meta = array(
        'table' => USER_TABLE,
        'pk' => array('id'),
        'joins' => array(
            'emails' => array(
                'reverse' => 'UserEmailModel.user',
            'tickets' => array(
                'reverse' => 'TicketModel.user',
            ),
            'account' => array(
                'list' => false,
Peter Rotich's avatar
Peter Rotich committed
                'reverse' => 'UserAccount.user',
            'org' => array(
                'constraint' => array('org_id' => 'Organization.id')
            ),
            'default_email' => array(
                'null' => true,
                'constraint' => array('default_email_id' => 'UserEmailModel.id')
            ),
        )
    );

    const PRIMARY_ORG_CONTACT   = 0x0001;

    static function objects() {
        $qs = parent::objects();
        #$qs->select_related('default_email');
        return $qs;
    }

    function getId() {
        return $this->id;
    }

    function getDefaultEmailAddress() {
        return $this->getDefaultEmail()->address;
    }

    function getDefaultEmail() {
        return $this->default_email;
    }

    function getAccount() {
        return $this->account;
    }

    function getOrgId() {
         return $this->get('org_id');
    }

    function getOrganization() {
        return $this->org;
    }

    function setOrganization($org, $save=true) {
        $this->set('org', $org);
        if ($save)
            $this->save();

    protected function hasStatus($flag) {
        return $this->get('status') & $flag !== 0;
    }

    protected function clearStatus($flag) {
        return $this->set('status', $this->get('status') & ~$flag);
    }

    protected function setStatus($flag) {
        return $this->set('status', $this->get('status') | $flag);
    }

    function isPrimaryContact() {
        return $this->hasStatus(User::PRIMARY_ORG_CONTACT);
    }

    function setPrimaryContact($flag) {
        if ($flag)
            $this->setStatus(User::PRIMARY_ORG_CONTACT);
        else
            $this->clearStatus(User::PRIMARY_ORG_CONTACT);
    }
}

class User extends UserModel {

Peter Rotich's avatar
Peter Rotich committed
    var $_forms;
    static function fromVars($vars) {
        // Try and lookup by email address
        $user = static::lookupByEmail($vars['email']);
            $name = $vars['name'];
            if (!$name)
                list($name) = explode('@', $vars['email'], 2);

            $user = User::create(array(
                'name' => Format::htmldecode(Format::sanitize($name, false)),
                'created' => new SqlFunction('NOW'),
                'updated' => new SqlFunction('NOW'),
                //XXX: Do plain create once the cause
                // of the detached emails is fixed.
                'default_email' => UserEmail::ensure($vars['email'])
            // Is there an organization registered for this domain
            list($mailbox, $domain) = explode('@', $vars['email'], 2);
            if (isset($vars['org_id']))
                $user->set('org_id', $vars['org_id']);
            elseif ($org = Organization::forDomain($domain))
                $user->setOrganization($org, false);

            try {
                $user->save(true);
                $user->emails->add($user->default_email);
                // Attach initial custom fields
                $user->addDynamicData($vars);
            }
            catch (OrmException $e) {
                return null;
            }
Peter Rotich's avatar
Peter Rotich committed
    static function fromForm($form) {

        if(!$form) return null;

        //Validate the form
        $valid = true;
        if (!$form->isValid())
            $valid  = false;

        //Make sure the email is not in-use
        if (($field=$form->getField('email'))
                && $field->getClean()
                && User::lookup(array('emails__address'=>$field->getClean()))) {
            $field->addError('Email is assigned to another user');
            $valid = false;
        }

        return $valid ? self::fromVars($form->getClean()) : null;
    }

    function getEmail() {
        return $this->default_email->address;
    }

    function getFullName() {
        return $this->name;
    }

    function getPhoneNumber() {
        foreach ($this->getDynamicData() as $e)
            if ($a = $e->getAnswer('phone'))
                return $a;
    }

    function getName() {
        if (!$this->name)
            list($name) = explode('@', $this->getDefaultEmailAddress(), 2);
        else
            $name = $this->name;
        return new PersonsName($name);
Peter Rotich's avatar
Peter Rotich committed
    function getUpdateDate() {
        return $this->updated;
    }

Peter Rotich's avatar
Peter Rotich committed
    function getCreateDate() {
        return $this->created;
    }

    function addForm($form, $sort=1) {
        $form = $form->instanciate();
        $form->set('sort', $sort);
        $form->set('object_type', 'U');
        $form->set('object_id', $this->getId());
        $form->save();
    }

    function to_json() {

        $info = array(
                'id'  => $this->getId(),
                'name' => Format::htmlchars($this->getName()),
                'email' => (string) $this->getEmail(),
                'phone' => (string) $this->getPhoneNumber());

        return JsonDataEncoder::encode($info);
    }

    function asVar() {
        return (string) $this->getName();
    }

    function getVar($tag) {
        if($tag && is_callable(array($this, 'get'.ucfirst($tag))))
            return call_user_func(array($this, 'get'.ucfirst($tag)));

        $tag = mb_strtolower($tag);
        foreach ($this->getDynamicData() as $e)
            if ($a = $e->getAnswer($tag))
                return $a;
Peter Rotich's avatar
Peter Rotich committed
    function addDynamicData($data) {
        $uf = UserForm::getNewInstance();
Peter Rotich's avatar
Peter Rotich committed
        $uf->setClientId($this->id);
        foreach ($uf->getFields() as $f)
            if (isset($data[$f->get('name')]))
                $uf->setAnswer($f->get('name'), $data[$f->get('name')]);
        $uf->save();

        return $uf;
    }

    function getDynamicData() {
        if (!isset($this->_entries)) {
            $this->_entries = DynamicFormEntry::forClient($this->id)->all();
            if (!$this->_entries) {
                $g = UserForm::getNewInstance();
                $g->setClientId($this->id);
Peter Rotich's avatar
Peter Rotich committed
                $g->save();
                $this->_entries[] = $g;
            }
        return $this->_entries;
    function getFilterData() {
        $vars = array();
        foreach ($this->getDynamicData() as $entry) {
            if ($entry->getForm()->get('type') != 'U')
                continue;
            $vars += $entry->getFilterData();
            // Add in special `name` and `email` fields
            foreach (array('name', 'email') as $name) {
                if ($f = $entry->getForm()->getField($name))
                    $vars['field.'.$f->get('id')] = $this->getName();
            }
        }
        return $vars;
    }

    function getForms($data=null) {
Peter Rotich's avatar
Peter Rotich committed

        if (!isset($this->_forms)) {
            $this->_forms = array();
            foreach ($this->getDynamicData() as $cd) {
                $cd->addMissingFields();
                if(!$data
Peter Rotich's avatar
Peter Rotich committed
                        && ($form = $cd->getForm())
                        && $form->get('type') == 'U' ) {
                    foreach ($cd->getFields() as $f) {
                        if ($f->get('name') == 'name')
                            $f->value = $this->getFullName();
                        elseif ($f->get('name') == 'email')
                            $f->value = $this->getEmail();
                    }
                }

                $this->_forms[] = $cd->getForm();
            }
        }

        return $this->_forms;
    }

Peter Rotich's avatar
Peter Rotich committed
    function getAccountStatus() {

Peter Rotich's avatar
Peter Rotich committed
        if (!($account=$this->getAccount()))
            return 'Guest';

        return (string) $account->getStatus();
Peter Rotich's avatar
Peter Rotich committed
    }

    function register($vars, &$errors) {

        // user already registered?
        if ($this->getAccount())
            return true;

Peter Rotich's avatar
Peter Rotich committed
        return UserAccount::register($this, $vars, $errors);
    static function importCsv($stream, $defaults=array()) {
        //Read the header (if any)
        $headers = array('name' => 'Full Name', 'email' => 'Email Address');
        $uform = UserForm::getUserForm();
        $all_fields = $uform->getFields();
        $named_fields = array();
        $has_header = true;
        foreach ($all_fields as $f)
            if ($f->get('name'))
                $named_fields[] = $f;

        if (!($data = fgetcsv($stream, 1000, ",")))
            return 'Whoops. Perhaps you meant to send some CSV records';

        if (Validator::is_email($data[1])) {
            $has_header = false; // We don't have an header!
        }
        else {
            $headers = array();
            foreach ($data as $h) {
                $found = false;
                foreach ($all_fields as $f) {
                    if (in_array(mb_strtolower($h), array(
                            mb_strtolower($f->get('name')), mb_strtolower($f->get('label'))))) {
                        $found = true;
                        if (!$f->get('name'))
                            return $h.': Field must have `variable` set to be imported';
                        $headers[$f->get('name')] = $f->get('label');
                        break;
                    }
                }
                if (!$found) {
                    $has_header = false;
                    if (count($data) == count($named_fields)) {
                        // Number of fields in the user form matches the number
                        // of fields in the data. Assume things line up
                        $headers = array();
                        foreach ($named_fields as $f)
                            $headers[$f->get('name')] = $f->get('label');
                    else {
                        return $h.': Unable to map header to a user field';
                    }
                }
            }
        }

        // 'name' and 'email' MUST be in the headers
        if (!isset($headers['name']) || !isset($headers['email']))
            return 'CSV file must include `name` and `email` columns';

        if (!$has_header)
            fseek($stream, 0);

        $users = $fields = $keys = array();
        foreach ($headers as $h => $label) {
            if (!($f = $uform->getField($h)))
                continue;

            $name = $keys[] = $f->get('name');
            $fields[$name] = $f->getImpl();
        }

        // Add default fields (org_id, etc).
        foreach ($defaults as $key => $val) {
            // Don't apply defaults which are also being imported
            if (isset($header[$key]))
                unset($defaults[$key]);
            $keys[] = $key;
        }

        while (($data = fgetcsv($stream, 1000, ",")) !== false) {
            if (count($data) == 1 && $data[0] == null)
                // Skip empty rows
                continue;
            elseif (count($data) != count($headers))
                return 'Bad data. Expected: '.implode(', ', $headers);
            // Validate according to field configuration
            $i = 0;
            foreach ($headers as $h => $label) {
                $f = $fields[$h];
                $T = $f->parse($data[$i]);
                if ($f->validateEntry($T) && $f->errors())
                    return $label.': Invalid data: '.implode(', ', $f->errors());
                // Convert to database format
                $data[$i] = $f->to_database($T);
                $i++;
            }
            // Add default fields
            foreach ($defaults as $key => $val)
                $data[] = $val;

            $users[] = $data;
        }

        foreach ($users as $u) {
            $vars = array_combine($keys, $u);
            if (!static::fromVars($vars))
                return 'Unable to import user: '.print_r($vars, true);
        }

        return count($users);
    }

    function importFromPost($stuff, $extra=array()) {
        if (is_array($stuff) && !$stuff['error']) {
            // Properly detect Macintosh style line endings
            ini_set('auto_detect_line_endings', true);
            $stream = fopen($stuff['tmp_name'], 'r');
        }
        elseif ($stuff) {
            $stream = fopen('php://temp', 'w+');
            fwrite($stream, $stuff);
            rewind($stream);
        }
        else {
            return 'Unable to parse submitted users';
        }

        return User::importCsv($stream, $extra);
    }

Peter Rotich's avatar
Peter Rotich committed
    function updateInfo($vars, &$errors) {
Peter Rotich's avatar
Peter Rotich committed

        $valid = true;
        $forms = $this->getDynamicData();
Peter Rotich's avatar
Peter Rotich committed
        foreach ($forms as $cd) {
            $cd->setSource($vars);
            if (!$cd->isValidForClient())
Peter Rotich's avatar
Peter Rotich committed
                $valid = false;
            elseif ($cd->get('type') == 'U'
                        && ($form= $cd->getForm())
                        && ($f=$form->getField('email'))
                        && $f->getClean()
Peter Rotich's avatar
Peter Rotich committed
                        && ($u=User::lookup(array('emails__address'=>$f->getClean())))
                        && $u->id != $this->getId()) {
                $valid = false;
                $f->addError('Email is assigned to another user');
            }
Peter Rotich's avatar
Peter Rotich committed
        if (!$valid)
            return false;
Peter Rotich's avatar
Peter Rotich committed
        foreach ($this->getDynamicData() as $cd) {
            if (($f=$cd->getForm()) && $f->get('type') == 'U') {
                if (($name = $f->getField('name'))) {
                    $this->name = $name->getClean();
Peter Rotich's avatar
Peter Rotich committed
                    $this->save();
                }
Peter Rotich's avatar
Peter Rotich committed

                if (($email = $f->getField('email'))) {
                    $this->default_email->address = $email->getClean();
Peter Rotich's avatar
Peter Rotich committed
                    $this->default_email->save();
                }
            }
            $cd->save();
        }

        return true;
    }

    function save($refetch=false) {
        // Drop commas and reorganize the name without them
        $parts = array_map('trim', explode(',', $this->name));
        switch (count($parts)) {
            case 2:
                // Assume last, first --or-- last suff., first
                $this->name = $parts[1].' '.$parts[0];
                // XXX: Consider last, first suff.
                break;
            case 3:
                // Assume last, first, suffix, write 'first last suffix'
                $this->name = $parts[1].' '.$parts[0].' '.$parts[2];
                break;
        }

        // Handle email addresses -- use the box name
        if (Validator::is_email($this->name)) {
            list($box, $domain) = explode('@', $this->name, 2);
            if (strpos($box, '.') !== false)
                $this->name = str_replace('.', ' ', $box);
            else
                $this->name = $box;
            $this->name = mb_convert_case($this->name, MB_CASE_TITLE);
        }

Peter Rotich's avatar
Peter Rotich committed
        if (count($this->dirty)) //XXX: doesn't work??
            $this->set('updated', new SqlFunction('NOW'));
        return parent::save($refetch);
    }

    function delete() {

        // Refuse to delete a user with tickets
        if ($this->tickets->count())
        // Delete account record (if any)
        if ($this->getAccount())
            $this->getAccount()->delete();

        // Delete emails.
        $this->emails->expunge();
Peter Rotich's avatar
Peter Rotich committed

        // Delete user
        return parent::delete();

    static function lookupByEmail($email) {
        return self::lookup(array('emails__address'=>$email));
    }
    static $formats = array(
        'first' => array("First", 'getFirst'),
        'last' => array("Last", 'getLast'),
        'full' => array("First Last", 'getFull'),
        'legal' => array("First M. Last", 'getLegal'),
        'lastfirst' => array("Last, First", 'getLastFirst'),
        'formal' => array("Mr. Last", 'getFormal'),
        'short' => array("First L.", 'getShort'),
        'shortformal' => array("F. Last", 'getShortFormal'),
        'complete' => array("Mr. First M. Last Sr.", 'getComplete'),
        'original' => array('-- As Entered --', 'getOriginal'),
    function __construct($name, $format=null) {
        global $cfg;

        if ($format && !isset(static::$formats[$format]))
            $this->format = $format;
        elseif($cfg)
            $this->format = $cfg->getDefaultNameFormat();

        $this->parts = static::splitName($name);
        $this->name = $name;
    }

    function getFirst() {
        return $this->parts['first'];
    }

    function getLast() {
        return $this->parts['last'];
    }

    function getMiddle() {
        return $this->parts['middle'];
    }

    function getMiddleInitial() {
        return mb_substr($this->parts['middle'],0,1).'.';
    }

    function getFormal() {
        return trim($this->parts['salutation'].' '.$this->parts['last']);
    }

    function getFull() {
        return trim($this->parts['first'].' '.$this->parts['last']);
    }

    function getLegal() {
        $parts = array(
            $this->parts['first'],
            mb_substr($this->parts['middle'],0,1),
            $this->parts['last'],
        );
        if ($parts[1]) $parts[1] .= '.';
        return implode(' ', array_filter($parts));
    }

    function getComplete() {
        $parts = array(
            $this->parts['salutation'],
            $this->parts['first'],
            mb_substr($this->parts['middle'],0,1),
            $this->parts['last'],
            $this->parts['suffix']
        );
        if ($parts[2]) $parts[2] .= '.';
        return implode(' ', array_filter($parts));
    }

    function getLastFirst() {
        $name = $this->parts['last'].', '.$this->parts['first'];
        if ($this->parts['suffix'])
            $name .= ', '.$this->parts['suffix'];
        return $name;
    function getShort() {
        return $this->parts['first'].' '.mb_substr($this->parts['last'],0,1).'.';
    }

    function getShortFormal() {
        return mb_substr($this->parts['first'],0,1).'. '.$this->parts['last'];
    }

    function getOriginal() {
        return $this->name;
    }

    function getInitials() {
        $names = array($this->parts['first']);
        $names = array_merge($names, explode(' ', $this->parts['middle']));
        $names[] = $this->parts['last'];
        $initials = '';
        foreach (array_filter($names) as $n)
            $initials .= mb_substr($n,0,1);
        return mb_convert_case($initials, MB_CASE_UPPER);
    }

    function asVar() {
        return $this->__toString();
    }

    function __toString() {
Peter Rotich's avatar
Peter Rotich committed

        @list(, $func) = static::$formats[$this->format];
        if (!$func) $func = 'getFull';
        return (string) call_user_func(array($this, $func));
    }

    static function allFormats() {
        return static::$formats;
    }

    /**
     * Thanks, http://stackoverflow.com/a/14420217
     */
    static function splitName($name) {
        $results = array();

        $r = explode(' ', $name);
        $size = count($r);

        //check first for period, assume salutation if so
        if (mb_strpos($r[0], '.') === false)
        {
            $results['salutation'] = '';
            $results['first'] = $r[0];
        }
        else
        {
            $results['salutation'] = $r[0];
            $results['first'] = $r[1];
        }

        //check last for period, assume suffix if so
        if (mb_strpos($r[$size - 1], '.') === false)
        {
            $results['suffix'] = '';
        }
        else
        {
            $results['suffix'] = $r[$size - 1];
        }

        //combine remains into last
        $start = ($results['salutation']) ? 2 : 1;
        $end = ($results['suffix']) ? $size - 2 : $size - 1;

        for ($i = $start; $i <= $end; $i++)
        {
            $middle[] = $r[$i];
        }
        if (count($middle) > 1) {
            $results['last'] = array_pop($middle);
            $results['middle'] = implode(' ', $middle);
        }
        else {
            $results['last'] = $middle[0];
            $results['middle'] = '';
        }

        return $results;
    }

}

class UserEmail extends UserEmailModel {
    static function ensure($address) {
        $email = static::lookup(array('address'=>$address));
        if (!$email) {
            $email = static::create(array('address'=>$address));
            $email->save();
        }
        return $email;
    }
}
Peter Rotich's avatar
Peter Rotich committed
class UserAccountModel extends VerySimpleModel {
    static $meta = array(
        'table' => USER_ACCOUNT_TABLE,
        'pk' => array('id'),
        'joins' => array(
            'user' => array(
                'null' => false,
                'constraint' => array('user_id' => 'User.id')
    var $_status;

    function __construct() {
        call_user_func_array(array('parent', '__construct'), func_get_args());
        $this->_status = new UserAccountStatus($this->get('status'));
    }
    protected function hasStatus($flag) {
        return $this->_status->check($flag);
    protected function clearStatus($flag) {
Peter Rotich's avatar
Peter Rotich committed
        return $this->set('status', $this->get('status') & ~$flag);
    }

    protected function setStatus($flag) {
Peter Rotich's avatar
Peter Rotich committed
        return $this->set('status', $this->get('status') | $flag);
    }

    function confirm() {
        $this->setStatus(UserAccountStatus::CONFIRMED);
        return $this->save();
    }

    function isConfirmed() {
        return $this->_status->isConfirmed();
        $this->setStatus(UserAccountStatus::LOCKED);
        $this->save();
    }

    function isLocked() {
        return $this->_status->isLocked();
    }

    function forcePasswdReset() {
        $this->setStatus(UserAccountStatus::REQUIRE_PASSWD_RESET);
        return $this->save();
    }

    function isPasswdResetForced() {
        return $this->hasStatus(UserAccountStatus::REQUIRE_PASSWD_RESET);
    }

    function isPasswdResetEnabled() {
        return !$this->hasStatus(UserAccountStatus::FORBID_PASSWD_RESET);
Peter Rotich's avatar
Peter Rotich committed
    function getStatus() {
        return $this->_status;
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() {
        $this->user->set('account', $this);
        return $this->user;
}

class UserAccount extends UserAccountModel {

    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;
    }

    protected function sendUnlockEmail($template) {
        global $ost, $cfg;

        $token = Misc::randCode(48); // 290-bits

        $email = $cfg->getDefaultEmail();
        $content = Page::lookup(Page::getIdByType($template));

        if (!$email ||  !$content)
Peter Rotich's avatar
Peter Rotich committed
            return new Error($template.': 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);

        $msg = $ost->replaceTemplateVariables(array(
            'subj' => $content->getName(),
            'body' => $content->getBody(),
        ), $vars);

        $_config = new Config('pwreset');
Peter Rotich's avatar
Peter Rotich committed
        $_config->set($vars['token'], $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';
            return false;
        }

        // TODO: Make sure the username is unique

        if (!$vars['timezone_id'])
            $errors['timezone_id'] = 'Time zone required';

        // Changing password?
        if ($vars['passwd1'] || $vars['passwd2']) {
            if (!$vars['passwd1'])
Peter Rotich's avatar
Peter Rotich committed
                $errors['passwd1'] = 'New 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'] = 'Password(s) do not match';
        }

        if ($errors) return false;

        $this->set('timezone_id', $vars['timezone_id']);
        $this->set('dst', isset($vars['dst']) ? 1 : 0);

        // Make sure the username is not an email.
        if ($vars['username'] && Validator::is_email($vars['username']))
             $vars['username'] = '';

        $this->set('username', $vars['username']);

        if ($vars['passwd1']) {
            $this->set('passwd', Passwd::hash($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 = static::create(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'] = 'Temp. password required';
            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'] = 'Password(s) do not match';
        }

        if ($errors) return false;

        $account = UserAccount::create(array('user_id' => $user->getId()));
        if (!$account)
            return false;

        $account->set('dst', isset($vars['dst'])?1:0);
        $account->set('timezone_id', $vars['timezone_id']);
        $account->set('backend', $vars['backend']);