function users_register_post() { $u = new Users_User(); $u->email_address = $_REQUEST['email_address']; if ($u->retrieve()) { $key = 'this email'; throw new Users_Exception_AlreadyVerified(compact('key')); } // Insert a new user into the database $user = new Users_User(); $user->username = $_REQUEST['username']; if ($user->retrieve()) { throw new Users_Exception_UsernameExists(array(), array('username')); } $user->icon = 'default'; $user->password_hash = ''; $user->save(); // sets the user's id // Import the user's icon if (isset($_REQUEST['icon'])) { $folder = 'user_id_' . $user->id; users_register_post_download($_REQUEST['icon'], $folder, 80); users_register_post_download($_REQUEST['icon'], $folder, 40); $user->icon = $folder; $user->save(); } // Add an email to the user, that they'll have to verify $user->addEmail($_REQUEST['email_address']); Users::setLoggedInUser($user); Users::$cache['user'] = $user; }
function Websites_before_Streams_Stream_save_Websites_article($params) { $stream = $params['stream']; $modifiedFields = $params['modifiedFields']; if ($stream->wasRetrieved()) { return; } $user = new Users_User(); if (empty($stream->userId) and empty($modifiedFields['userId'])) { if ($liu = Users::loggedInUser()) { $stream->userId = $liu->id; } else { throw new Q_Exception_RequiredField(array('field' => 'userId')); } } $user->id = $stream->userId; if (!$user->retrieve()) { throw new Users_Exception_NoSuchUser(); } $title = Streams::displayName($user, array('fullAccess' => true)); if (isset($title)) { $stream->title = $title; } $stream->icon = $user->iconUrl(); $s = Streams::fetchOne($user->id, $user->id, "Streams/user/icon"); if (!$s or !($sizes = $s->getAttribute('sizes', null))) { $sizes = Q_Config::expect('Users', 'icon', 'sizes'); sort($sizes); } $stream->setAttribute('sizes', $sizes); }
function users_activate_post() { $email_address = Pie_Dispatcher::uri()->email_address; $mobile_number = Pie_Dispatcher::uri()->mobile_number; $email = null; $mobile = null; if ($email_address) { $email = new Users_Email(); $email->address = $email_address; // NOTE: not sharded by user_id if (!$email->retrieve()) { throw new Pie_Exception_MissingRow(array('table' => 'email', 'criteria' => "address = {$email_address}")); } $user = new Users_User(); $user->id = $email->user_id; if (!$user->retrieve()) { throw new Pie_Exception_MissingRow(array('table' => 'user', 'criteria' => 'id = ' . $user->id)); } if ($email->activation_code != $_REQUEST['code']) { throw new Pie_Exception("The activation code does not match.", 'code'); } $user->setEmailAddress($email->address); // may throw exception $type = "email address"; } if ($mobile_number) { $mobile = new Users_Mobile(); $mobile->number = $mobile_number; // NOTE: not sharded by user_id if (!$mobile->retrieve()) { throw new Pie_Exception_MissingRow(array('table' => 'mobile phone', 'criteria' => "number = {$mobile_number}")); } $user = new Users_User(); $user->id = $mobile->user_id; if (!$user->retrieve()) { throw new Pie_Exception_MissingRow(array('table' => 'user', 'criteria' => 'id = ' . $user->id)); } if ($mobile->activation_code != $_REQUEST['code']) { throw new Pie_Exception("The activation code does not match.", 'code'); } $user->setMobileNumber($mobile->number); // may throw exception $type = "mobile number"; } if ($type) { Pie_Response::addNotice("users/activate", "Your {$type} has been activated."); } Users::$cache['user'] = $user; }
function Users_resend_post() { $identifier = Users::requestedIdentifier($type); if ($type !== 'email' and $type !== 'mobile') { throw new Q_Exception("Expecting a valid email or mobile number", array('identifier', 'emailAddress', 'mobileNumber')); } if ($type === 'email') { $thing = 'email address'; $field = 'emailAddress'; $row = new Users_Email(); $row->address = $identifier; } else { if ($type === 'mobile') { $thing = 'mobile number'; $field = 'mobileNumber'; $row = new Users_Mobile(); $row->number = $identifier; } else { throw new Q_Exception("Expecting a valid email or mobile number", array('identifier', 'emailAddress', 'mobileNumber')); } } if ($row->retrieve()) { $userId = $row->userId; } else { if ($ui = Users::identify($type, $identifier, 'future')) { $userId = $ui->userId; } else { throw new Q_Exception("That {$thing} was not found in the system", array('identifier', $field)); } } $user = new Users_User(); $user->id = $userId; if (!$user->retrieve()) { throw new Q_Exception("No user corresponds to that {$thing}", array('identifier', $field)); } if ($logged_in_user = Users::loggedInUser() and $logged_in_user->id != $user->id) { throw new Q_Exception("That {$thing} belongs to someone else", array('identifier', $field)); } if ($type === 'email') { $existing = $user->addEmail($identifier); } else { $existing = $user->addMobile($identifier); } if ($existing) { $existing->resendActivationMessage(); } Users::$cache['user'] = $user; }
function Streams_invite_response_accountStatus() { if (empty($_REQUEST['token'])) { throw new Q_Exception("Missing token!"); } $invite = new Streams_Invite(); $invite->token = $_REQUEST['token']; if (!$invite->retrieve()) { throw new Q_Exception("Wrong token '" . $invite->token . "'!"); } $user = new Users_User(); $user->id = $invite->userId; if (!$user->retrieve()) { throw new Users_Exception_NoSuchUser(); } if (!empty($user->passphraseHash) || !empty($user->fb_uid)) { return "complete"; } }
function users_user_response_json() { $email_address = $_REQUEST['email_address']; // check our db $user = new Users_User(); $user->email_address = $email_address; if ($user->retrieve()) { return array('username' => $user->username, 'icon' => $user->icon); } $email_hash = md5(strtolower(trim($email_address))); $json = file_get_contents("http://www.gravatar.com/{$email_hash}.json"); $result = json_decode($json); if ($result) { return $result; } // otherwise, return default $email_parts = explode('@', $email_address, 2); return array("entry" => array(array("id" => "571", "hash" => "357a20e8c56e69d6f9734d23ef9517e8", "requestHash" => "357a20e8c56e69d6f9734d23ef9517e8", "profileUrl" => "http:\\/\\/gravatar.com\\/test", "preferredUsername" => $email_parts[0], "thumbnailUrl" => "http://gravatar.com/avatar/{$email_hash}?r=g&d=wavatar&s=80", "photos" => array(), "displayName" => "", "urls" => array()))); }
/** * Intelligently retrieves user by id * @method fetch * @static * @param {string} $userId * @param {boolean} [$throwIfMissing=false] If true, throws an exception if the user can't be fetched * @return {Users_User|null} * @throws {Users_Exception_NoSuchUser} If the URI contains an invalid "username" */ static function fetch($userId, $throwIfMissing = false) { if (empty($userId)) { $result = null; } else { if (!empty(self::$cache['getUser'][$userId])) { $result = self::$cache['getUser'][$userId]; } else { $user = new Users_User(); $user->id = $userId; if (!$user->retrieve()) { $user = null; } self::$cache['getUser'][$userId] = $user; $result = $user; } } if (!$result and $throwIfMissing) { throw new Users_Exception_NoSuchUser(); } return $result; }
function Users_activate_objects_mobile($mobileNumber, &$mobile) { Q_Response::removeNotice('Users/activate/objects'); $mobile = new Users_Mobile(); if (!Q_Valid::phone($mobileNumber, $normalized)) { return; } $mobile->number = $normalized; if (!$mobile->retrieve()) { throw new Q_Exception_MissingRow(array('table' => 'mobile phone', 'criteria' => "number {$normalized}")); } $user = Users::loggedInUser(); if ($user) { if ($user->id != $mobile->userId) { throw new Q_Exception("You are logged in as a different user. Please log out and click the link again."); } } else { $user = new Users_User(); $user->id = $mobile->userId; if (!$user->retrieve()) { throw new Q_Exception_MissingRow(array('table' => 'user', 'criteria' => 'id = ' . $user->id)); } } if ($mobile->activationCode != $_REQUEST['code']) { throw new Q_Exception("The activation code does not match. Did you get a newer message?", 'code'); } $timestamp = Users_Mobile::db()->getCurrentTimestamp(); if ($timestamp > Users_Mobile::db()->fromDateTime($mobile->activationCodeExpires)) { throw new Q_Exception("Activation code expired"); } if (Q_Request::method() !== 'POST' and empty($_REQUEST['p']) and isset($user->mobileNumber) and $user->mobileNumber == $mobile->number) { $displayName = Streams::displayName($user); Q_Response::setNotice('Users/activate/objects', "{$normalized} has already been activated for {$displayName}", true); return $user; } return $user; }
function resendActivationMessage($subject = null, $view = null, $fields = array(), $options = array()) { if (!isset($subject)) { $subject = Q_Config::get('Users', 'transactional', 'resend', 'subject', Q_Config::get('Users', 'transactional', 'activation', 'subject', 'Did you forget your passphrase?')); } if (!isset($view)) { $view = Q_Config::get('Users', 'transactional', 'resend', 'body', Q_Config::get('Users', 'transactional', 'activation', 'body', 'Users/email/activation.php')); } if (!isset($options['html'])) { $options['html'] = true; } $user = $this->get('user', null); if (!$user) { $user = new Users_User(); $user->id = $this->userId; if (!$user->retrieve()) { throw new Q_Exception_NotVerified(array('type' => 'email address'), 'emailAddress'); } } $minutes = Q_Config::get('Users', 'activation', 'expires', 60 * 24 * 7); $this->activationCode = strtolower(Q_Utils::unique(7)); $this->activationCodeExpires = new Db_Expression("CURRENT_TIMESTAMP + INTERVAL {$minutes} MINUTE"); $this->authCode = md5(microtime() + mt_rand()); $link = 'Users/activate?p=1&code=' . urlencode($this->activationCode) . ' emailAddress=' . urlencode($this->address); /** * @event Users/resend {before} * @param {string} user * @param {string} email */ Q::event('Users/resend', compact('user', 'email', 'link'), 'before'); $this->save(); $email = $this; $fields2 = array_merge($fields, array('user' => $user, 'email' => $this, 'app' => Q_Config::expect('Q', 'app'), 'baseUrl' => Q_Request::baseUrl(), 'link' => $link)); $this->sendMessage($subject, $view, $fields2, $options); // may throw exception if badly configured /** * @event Users/resend {after} * @param {string} user * @param {string} email */ Q::event('Users/resend', compact('user', 'email'), 'after'); }
function Streams_before_Q_objects() { $token = Q_Request::special('Streams.token', null); if ($token === null) { return; } $invite = Streams_Invite::fromToken($token); if (!$invite) { throw new Q_Exception_MissingRow(array('table' => 'invite', 'criteria' => "token = '{$token}"), 'token'); } // did invite expire? $ts = Streams_Invite::db()->select("CURRENT_TIMESTAMP")->fetchAll(PDO::FETCH_NUM); if (isset($invite->expireTime) and $invite->expireTime < $ts[0][0]) { $invite->state = 'expired'; $invite->save(); } // is invite still pending? if ($invite->state !== 'pending') { switch ($invite->state) { case 'expired': $exception = new Streams_Exception_AlreadyExpired(null, 'token'); break; case 'accepted': $exception = new Streams_Exception_AlreadyAccepted(null, 'token'); break; case 'declined': $exception = new Streams_Exception_AlreadyDeclined(null, 'token'); break; case 'forwarded': $exception = new Streams_Exception_AlreadyForwarded(null, 'token'); break; default: $exception = new Q_Exception("This invite has already been " . $invite->state, 'token'); break; } $shouldThrow = Q::event('Streams/objects/inviteException', compact('invite', 'exception'), 'before'); if ($shouldThrow === null) { Q_Response::setNotice('Streams/objects', $exception->getMessage(), true); } else { if ($shouldThrow === true) { throw $exception; } } } // now process the invite $invitedUser = Users_User::fetch($invite->userId, true); $stream = Streams::fetchOne($invitedUser->id, $invite->publisherId, $invite->streamName); if (!$stream) { throw new Q_Exception_MissingRow(array('table' => 'stream', 'criteria' => "publisherId = '{$invite->publisherId}', name = '{$invite->streamName}'")); } $byUser = Users_User::fetch($invite->invitingUserId, true); $byStream = Streams::fetchOne($byUser->id, $invite->publisherId, $invite->streamName); if (!$byStream) { throw new Q_Exception_MissingRow(array('table' => 'stream', 'criteria' => "publisherId = '{$invite->publisherId}', name = '{$invite->streamName}'")); } $access = new Streams_Access(); $access->publisherId = $byStream->publisherId; $access->streamName = $byStream->name; $access->ofUserId = $invite->userId; $specified_access = false; foreach (array('readLevel', 'writeLevel', 'adminLevel') as $level_type) { $access->{$level_type} = -1; if (empty($invite->{$level_type})) { continue; } // Give access level from the invite. // However, if inviting user has a lower access level now, // then give that level instead, unless it is lower than // what the invited user would have had otherwise. $min = min($invite->{$level_type}, $byStream->get($level_type, 0)); if ($min > $stream->get($level_type, 0)) { $access->{$level_type} = $min; $specified_access = true; } } if ($specified_access) { $access->save(true); } // now log invited user in $user = Users::loggedInUser(); if (empty($user) or $user->id !== $invite->userId) { $user = new Users_User(); $user->id = $invite->userId; if (!$user->retrieve()) { // The user who was invited doesn't exist // This shouldn't happen. We just silently log it and return. Q::log("Sanity check failed: invite with {$invite->token} pointed to nonexistent user"); return; } Users::setLoggedInUser($user); } // accept invite and autosubscribe if first time if ($invite->accept() and !$stream->subscription($user->id)) { $stream->subscribe(); } // retain the invite object for further processing Streams::$followedInvite = $invite; }
/** * Returns a user in the database that will correspond to a new user in the future * once they authenticate or follow an invite. * Inserts a new user if one doesn't already exist. * * @method futureUser * @param {string} $type Could be one of "email", "mobile", "email_hashed", "mobile_hashed", "facebook", "twitter" or "none". * @param {string} $value The value corresponding to the type. If $type is: * * * "email" - this is one of the user's email addresses * * "mobile" - this is one of the user's mobile numbers * * "email_hashed" - this is the email, already hashed with Q_Utils::hash() * * "mobile_hashed" - this is the email, already hashed with Q_Utils::hash() * * "facebook" - this is the user's id on facebook * * "twitter" - this is the user's id on twitter * * "none" - the type is ignored, no "identify" rows are inserted into the db, etc. * * With every type except "none", the user will be * * NOTE: If the person we are representing here comes and registers the regular way, * and then later adds an email, mobile, or authenticates with a provider, * which happens to match the "future" mapping we inserted in users_identify table, * then this futureUser will not be converted, since they already registered * a different user. Later on, we may have some sort function to merge users together. * * @param {&string} [$status=null] The status of the user - 'verified' or 'future' * @return {Users_User} * @throws {Q_Exception_WrongType} If $type is not supported * @throws {Q_Exception_MissingRow} If identity for user exists but user does not exists */ static function futureUser($type, $value, &$status = null) { if (!array_key_exists($type, self::$types)) { throw new Q_Exception_WrongType(array('field' => 'type', 'type' => 'one of the supported types')); } if ($type !== 'none') { $ui = Users::identify($type, $value, null); if ($ui && !empty($ui->userId)) { $user = new Users_User(); $user->id = $ui->userId; if ($user->retrieve()) { $status = $ui->state; return $user; } else { $userId = $ui->userId; throw new Q_Exception_MissingRow(array('table' => 'user', 'criteria' => 'that id'), 'userId'); } } } // Make a user row to represent a "future" user and give them an empty username $user = new Users_User(); if ($field = self::$types[$type]) { $user->{$field} = $value; } $user->signedUpWith = 'none'; // this marks it as a future user for now $user->username = ""; $user->icon = 'future'; $during = 'future'; /** * @event Users/insertUser {before} * @param {string} during * @param {Users_User} 'user' */ Q::event('Users/insertUser', compact('user', 'during'), 'before'); $user->save(); // sets the user's id /** * @event Users/insertUser {after} * @param {string} during * @param {Users_User} user */ Q::event('Users/insertUser', compact('user', 'during'), 'after'); if ($type != 'email' and $type != 'mobile') { if ($type !== 'none') { // Save an identifier => user pair for this future user $ui = new Users_Identify(); $ui->identifier = "{$type}:{$value}"; $ui->state = 'future'; if (!$ui->retrieve()) { $ui->userId = $user->id; $ui->save(); } $status = $ui->state; } else { $status = 'future'; } } else { // Save hashed version $ui = new Users_Identify(); $hashed = Q_Utils::hash($value); $ui->identifier = $type . "_hashed:{$hashed}"; $ui->state = 'future'; if (!$ui->retrieve()) { $ui->userId = $user->id; $ui->save(); } $status = $ui->state; } return $user; }
/** * Updates the publisher's avatars, which may have changed with the taintedAccess. * This function should be called during rare events that may cause the * publisher's avatar to change appearance for certain users viewing it.<br/> * * You should rarely have to call this function. It is used internally by the model, * in two main situations: * * 1) adding, removing or modifying a Streams_Access row for Streams/user/firstName or Streams/user/lastName * In this case, the function is able to update exactly the avatars that need updating. * * 2) adding, removing or modifying a Stream row for Streams/user/firstName or Streams/user/lastName * In this case, there may be some avatars which this function will miss. * These correspond to users which are reachable by the access array for one stream, * but not the other. For example, if Streams/user/firstName is being updated, but * a particular user is reachable only by the access array for Streams/user/lastName, then * their avatar will not be updated and contain a stale value for firstName. * To fix this, the Streams_Stream model passes true in the 4th parameter to this function. * @method updateAvatars * @static * @param {string} $publisherId * id of the publisher whose avatar to update * @param {array} $taintedAccess * array of Streams_Access objects representing access information that is either * about to be saved, are about to be overwritten, or will be deleted * @param {string|Streams_Stream} $streamName * pass the stream name here. You can also pass a Stream_Stream object here, * in which case it will be used, instead of selecting that stream from the database. * @param {boolean} $updateToPublicValue=false * if you want to first update all the avatars for this stream * to the what the public would see, to avoid the situation described in 2). */ static function updateAvatars($publisherId, $taintedAccess, $streamName, $updateToPublicValue = false) { if (!isset($streamName)) { $streamAccesses = array(); foreach ($taintedAccess as $access) { $streamAccesses[$access->streamName][] = $access; } if (count($streamAccesses) > 1) { foreach ($streamAccesses as $k => $v) { self::updateAvatars($publisherId, $v, $k); } return false; } } if ($streamName instanceof Streams_Stream) { $stream = $streamName; $streamName = $stream->name; } // If we are here, all the Stream_Access objects have the same streamName if ($streamName !== 'Streams/user/firstName' and $streamName !== 'Streams/user/lastName' and $streamName !== 'Streams/user/username') { // we don't care about access to other streams being updated return false; } $showToUserIds = array(); // Select the user corresponding to this publisher $user = new Users_User(); $user->id = $publisherId; if (!$user->retrieve(null, null, array('ignoreCache' => true))) { throw new Q_Exception_MissingRow(array('table' => 'user', 'criteria' => 'id = ' . $user->id)); } // Obtain the stream object to use if (isset($stream)) { if (!isset($stream->content)) { $stream->content = ''; } } else { // If the $stream isn't already defined, select it $stream = new Streams_Stream(); $stream->publisherId = $publisherId; $stream->name = $streamName; if (!$stream->retrieve()) { // Strange, this stream doesn't exist. // Well, we will just silently set the content to '' then $stream->content = ''; } } $content_readLevel = Streams::$READ_LEVEL['content']; $readLevels = array(); $label_readLevels = array(); $contact_label_list = array(); $removed_labels = array(); // First, assign all the readLevels that are directly set for specific users, // and aggregate the contact_labels from the other accesses, for an upcoming select. foreach ($taintedAccess as $access) { if ($userId = $access->ofUserId) { $readLevel = $access->readLevel; $readLevels[$userId] = $readLevel; if ($readLevel < 0) { $showToUserIds[$userId] = null; // not determined yet } else { if ($readLevel >= $content_readLevel) { $showToUserIds[$userId] = true; } else { $showToUserIds[$userId] = false; } } } else { if ($access->ofContactLabel) { $ofContactLabel = $access->ofContactLabel; $contact_label_list[] = $ofContactLabel; if ($access->get('removed', false)) { $removed_labels[$ofContactLabel] = true; } else { $label_readLevels[$ofContactLabel] = $access->readLevel; } } } } // Now, get all the people affected by this change, and their readLevels $readLevels2 = array(); if ($contact_label_list) { $contact_label_list = array_unique($contact_label_list); $contacts = Users_Contact::select('*')->where(array('userId' => $publisherId, 'label' => $contact_label_list))->fetchDbRows(null, '', 'contactUserId'); foreach ($contacts as $contact) { $contactUserId = $contact->contactUserId; if (isset($showToUserIds[$contactUserId])) { // this user had their read level set directly by the access, // which overrides read levels set by access using ofContactLabel continue; } if (isset($removed_labels[$ofContactLabel])) { // this label doesn't affect readLevels anymore, since it was deleted // but put this contact's id on a list whose readLevels need to be determined $showToUserIds[$contactUserId] = null; continue; } if (!isset($label_readLevels[$contact->label])) { continue; } $readLevel = $label_readLevels[$contact->label]; if (!isset($readLevels2[$contactUserId])) { $readLevels2[$contactUserId] = $readLevel; } else { $readLevels2[$contactUserId] = max($readLevels2[$contactUserId], $readLevel); } } } // Now step through all the users we found who were found through ofContactLabel // and make sure we update the avatar rows that were meant for them. foreach ($readLevels2 as $userId => $rl) { if ($rl >= $content_readLevel) { $showToUserIds[$userId] = true; } else { // in order for this to happen, two things had to be true: // 1) there was no access that directly set a readLevel >= $content_readLevel // 2) there was no access that set a readLevel >= $content_readLevel for any label containing this user // therefore, their view should be the public view $showToUserIds[$userId] = 'public'; } } // Resolve all the undetermined readLevels foreach ($showToUserIds as $userId => $v) { if (!isset($v)) { // if the readLevel hasn't been determined by now, it's the same as the public one $showToUserIds[$userId] = 'public'; } } // Set up the self avatar: $showToUserIds[$publisherId] = true; // Finally, set up the public avatar: if (!isset($stream->readLevel)) { $stream->readLevel = Streams_Stream::$DEFAULTS['readLevel']; } $showToUserIds[""] = $stream->readLevel >= $content_readLevel; // Now, we update the avatars: $parts = explode('/', $streamName); $field = end($parts); $rows_that_show = array(); $rows_that_hide = array(); foreach ($showToUserIds as $userId => $show) { if ($show === 'public') { // If no show is explicitly specified, use the value used for the rest of the public $show = $showToUserIds[""]; } if ($show === true) { $rows_that_show[] = array('publisherId' => $publisherId, 'toUserId' => $userId, 'username' => $user->username, 'icon' => $user->icon, 'updatedTime' => new Db_Expression("CURRENT_TIMESTAMP"), $field => $stream->content); } else { if ($show === false) { $rows_that_hide[] = array('publisherId' => $publisherId, 'toUserId' => $userId, 'username' => $user->username, 'icon' => $user->icon, 'updatedTime' => new Db_Expression("CURRENT_TIMESTAMP"), $field => ''); } } } $updates_that_show = array('username' => $user->username, 'icon' => $user->icon, 'updatedTime' => new Db_Expression("CURRENT_TIMESTAMP"), $field => $stream->content); $updates_that_hide = array('username' => $user->username, 'icon' => $user->icon, 'updatedTime' => new Db_Expression("CURRENT_TIMESTAMP"), $field => ''); // We are now ready to make changes to the database. if ($updateToPublicValue) { Streams_Avatar::update()->set(array($field => $showToUserIds[""] ? $stream->content : ''))->where(compact('publisherId'))->execute(); } Streams_Avatar::insertManyAndExecute($rows_that_show, array('onDuplicateKeyUpdate' => $updates_that_show)); Streams_Avatar::insertManyAndExecute($rows_that_hide, array('onDuplicateKeyUpdate' => $updates_that_hide)); }
/** * Logs a user in using a login identifier and a pasword * @param string $identifier * Could be an email address, a mobile number, or a user id. * @param string $password * The password to hash, etc. */ static function login($identifier, $password) { $return = null; $return = Pie::event('users/login', compact('identifier', 'password'), 'before'); if (isset($return)) { return $return; } Pie_Session::start(); $session_id = Pie_Session::id(); // First, see if we've already logged in somehow if ($user = self::loggedInUser()) { // Get logged in user from session return $user; } $user = new Users_User(); $user->identifier = $identifier; if ($user->retrieve()) { // User exists in database. Now check the password. $password_hash = self::hashPassword($password, $user->password_hash); if ($password_hash != $user->password_hash) { // Passwords don't match! throw new Users_Exception_WrongPassword(compact('identifier')); } // Do we need to update it? if (!isset($user->session_key) or $user->session_key != $session_id) { Pie::event('users/loginUpdateUser', compact('user'), 'before'); $user->session_key = $session_id; $user->save(); // update session_key in user Pie::event('users/loginUpdateUser', compact('user'), 'after'); } } else { // No user in database. Will insert a new one! // These users might be shared across apps. $user->password_hash = self::hashPassword($password); $user->session_key = $session_id; Pie::event('users/loginInsertUser', compact('user'), 'before'); $user->save(); Pie::event('users/loginInsertUser', compact('user'), 'after'); $inserted_new_user = true; } // Now save this user in the session as the logged-in user self::setLoggedInUser($user); Pie::event('users/login', compact('identifier', 'password', 'inserted_new_user', 'user'), 'after'); }
function resendActivationMessage($view = null, $fields = array(), $options = array()) { if (!isset($view)) { $view = Q_Config::get('Users', 'transactional', 'resend', 'sms', Q_Config::get('Users', 'transactional', 'resend', 'sms', 'Users/sms/activation.php')); } $user = $this->get('user', null); if (!$user) { $user = new Users_User(); $user->id = $this->userId; if (!$user->retrieve()) { throw new Q_Exception_NotVerified(array('type' => 'mobile number'), 'mobileNumber'); } } $minutes = Q_Config::get('Users', 'activation', 'expires', 60 * 24 * 7); $this->activationCode = strtolower(Q_Utils::unique(5)); $this->activationCodeExpires = new Db_Expression("CURRENT_TIMESTAMP + INTERVAL {$minutes} MINUTE"); $this->authCode = md5(microtime() + mt_rand()); $number = $this->number; if (substr($number, 0, 2) == '+1') { $number = substr($number, 2); } $link = 'Users/activate?p=1&code=' . urlencode($this->activationCode) . ' mobileNumber=' . urlencode($number); /** * @event Users/resend {before} * @param {string} user * @param {string} mobile */ Q::event('Users/resend', compact('user', 'mobile', 'link'), 'before'); $this->save(); $fields2 = array_merge($fields, array('user' => $user, 'mobile' => $this, 'app' => Q_Config::expect('Q', 'app'), 'baseUrl' => Q_Request::baseUrl(), 'link' => $link)); $this->sendMessage($view, $fields2, $options); // may throw exception if badly configured /** * @event Users/resend {after} * @param {string} user * @param {string} mobile */ Q::event('Users/resend', compact('user', 'mobile'), 'after'); }