Newer
Older
const LANG_MAILOUTS = 1; // Language preference for mailouts
function getStatus() {
if (!isset($this->_status))
$this->_status = new UserAccountStatus($this->get('status'));
return $this->_status;
protected function hasStatus($flag) {
return $this->getStatus()->check($flag);
protected function clearStatus($flag) {
return $this->set('status', $this->get('status') & ~$flag);
}
protected function setStatus($flag) {
return $this->set('status', $this->get('status') | $flag);
}
$this->setStatus(UserAccountStatus::CONFIRMED);
return $this->save();
}
function isConfirmed() {
return $this->getStatus()->isConfirmed();
}
function lock() {
$this->setStatus(UserAccountStatus::LOCKED);
function unlock() {
$this->clearStatus(UserAccountStatus::LOCKED);
}
function isLocked() {
return $this->getStatus()->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);
function getInfo() {
return $this->ht;
}
function getId() {
return $this->get('id');
}
function getUserId() {
return $this->get('user_id');
}
function getUser() {
return $this->user;
function getExtraAttr($attr=false, $default=null) {
if (!isset($this->_extra))
$this->_extra = JsonDataParser::decode($this->get('extra', ''));
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
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() {
return static::sendUnlockEmail('pwreset-client') === true;
}
function sendConfirmEmail() {
return static::sendUnlockEmail('registration-client') === true;
function setPassword($new) {
$this->set('passwd', Passwd::hash($new));
// Clean sessions
Signal::send('auth.clean', $this->getUser());
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());
Format::striptags($msg['subj']), $msg['body']);
function __toString() {
return (string) $this->getStatus();
}
/*
* Updates may be done by Staff or by the User if registration
* options are set to Public
*/
function update($vars, &$errors) {
// TODO: Make sure the username is unique
// Timezone selection is not required. System default is a valid
// fallback
// Changing password?
if ($vars['passwd1'] || $vars['passwd2']) {
if (!$vars['passwd1'])
$errors['passwd1'] = __('New password is 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'] = __('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');
$this->set('timezone', $vars['timezone']);
$this->set('username', $vars['username']);
if ($vars['passwd1']) {
$this->setPassword($vars['passwd1']);
$this->setStatus(UserAccountStatus::CONFIRMED);
'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);
}
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) {
if (!$user || !$vars)
return false;
//Require temp password.
if ((!$vars['backend'] || $vars['backend'] != 'client')
&& !isset($vars['sendemail'])) {
$errors['passwd1'] = 'Temporary 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'] = 'Passwords do not match';
$account = new UserAccount(array(
'user_id' => $user->getId(),
'timezone' => $vars['timezone'],
'backend' => $vars['backend'],
));
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);
if ($vars['pwreset-flag'])
$account->setStatus(UserAccountStatus::REQUIRE_PASSWD_RESET);
if ($vars['forbid-pwreset-flag'])
$account->setStatus(UserAccountStatus::FORBID_PASSWD_RESET);
elseif ($vars['backend'] && $vars['backend'] != 'client') {
// Auto confirm remote accounts
$account->setStatus(UserAccountStatus::CONFIRMED);
if (!$account->isConfirmed() && $vars['sendemail'])
$account->sendConfirmEmail();
return $account;
}
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
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)');
return __('Locked (Pending Activation)');
// ... Other flags here (password reset, etc).
return __('Active (Registered)');
class UserList extends MailingList {
function add($user) {
if (!$user instanceof ITicketUser)
throw new InvalidArgumentException('User expected');
return parent::add($user);