Beispiel #1
0
 /**
  * Retrieves the currently logged-in user from the session.
  * If the user was not originally retrieved from the database,
  * inserts a new one.
  * Thus, this can also be used to turn visitors into registered
  * users.
  *
  * @param string $platform
  *  Currently only supports the value "facebook".
  * @param int $app_id
  *  The id of the app within the specified platform.
  *  Used for storing app-specific session information.
  * @param string $password
  *  Sometimes, if the authentication isn't to be trusted,
  *  a password is required. Pass true here to bypass
  *  password checking and log in the user regardless.
  *  Otherwise, this string is hashed and tested.
  */
 static function authenticate($platform, $app_id = null, $password = null)
 {
     if (!isset($app_id)) {
         $app = Pie_Config::expect('pie', 'app');
         $app_id = Pie_Config::expect('users', 'facebookApps', $app, 'appId');
     }
     $return = null;
     $return = Pie::event('users/auth', compact('platform', 'app_id', 'password'), 'before');
     if (isset($return)) {
         return $return;
     }
     if (!isset($platform) or $platform != 'facebook') {
         throw new Pie_Exception_WrongType(array('field' => 'platform', 'type' => '"facebook"'));
     }
     if (!isset($app_id)) {
         throw new Pie_Exception_WrongType(array('field' => 'app_id', 'type' => 'integer'));
     }
     Pie_Session::start();
     // First, see if we've already logged in somehow
     if ($user = self::loggedInUser()) {
         // Get logged in user from session
         $user_was_logged_in = true;
     } else {
         // Get an existing user or create a new one
         $user = new Users_User();
         switch ($platform) {
             case 'facebook':
                 if (!Users::facebook($app_id)) {
                     return false;
                 }
                 if (!Users::facebook($app_id)->user) {
                     return false;
                     // no one logged in
                 }
                 $user->fb_uid = Users::facebook($app_id)->user;
                 break;
             default:
                 return false;
                 // not sure how to log this user in
         }
         $retrieved = $user->retrieve();
         // Now save this user in the session as the logged-in user
         self::setLoggedInUser($user);
         $session_id = Pie_Session::id();
         if ($retrieved) {
             // User exists in database. Do we need to update it?
             if (!isset($user->session_key) or $user->session_key != $session_id) {
                 Pie::event('users/authUpdateUser', compact('user'), 'before');
                 $user->session_key = $session_id;
                 $user->save();
                 // update session_key in user
                 Pie::event('users/authUpdateUser', compact('user'), 'after');
             }
         } else {
             // No user in database. Will insert a new one!
             // These users might be shared across apps.
             Pie::event('users/authInsertUser', compact('user'), 'before');
             $user->session_key = $session_id;
             $user->save();
             $_SESSION['users']['user'] = $user;
             Pie::event('users/authInsertUser', compact('user'), 'after');
             $inserted_new_user = true;
         }
     }
     // Now make sure our master session contains the
     // session info for the platform app.
     if ($platform == 'facebook') {
         $fb_prefix = 'fb_sig_';
         if (!Users::facebook($app_id)) {
             return false;
         }
         $facebook = Users::facebook($app_id);
         if (isset($_SESSION['users']['facebookAppUser'][$app_id])) {
             // Facebook app user exists. Do we need to update it? (Probably not!)
             $app_user = $_SESSION['users']['facebookAppUser'][$app_id];
             $app_user->state = 'added';
             if (!isset($app_user->session_key) or $facebook->api_client->session_key != $app_user->session_key) {
                 Pie::event('users/authUpdateAppUser', compact('user'), 'before');
                 $app_user->session_key = $facebook->api_client->session_key;
                 $app_user->save();
                 // update session_key in app_user
                 Pie::event('users/authUpdateAppUser', compact('user'), 'after');
             }
         } else {
             // We have to put the session info in
             $app_user = new Users_AppUser();
             $app_user->user_id = $user->id;
             $app_user->platform = 'facebook';
             $app_user->app_id = $app_id;
             if ($app_user->retrieve()) {
                 // App user exists in database. Do we need to update it?
                 if (!isset($app_user->session_key) or $app_user->session_key != $facebook->api_client->session_key) {
                     Pie::event('users/authUpdateAppUser', compact('user'), 'before');
                     $app_user->session_key = $facebook->api_client->session_key;
                     $app_user->save();
                     // update session_key in app_user
                     Pie::event('users/authUpdateAppUser', compact('user'), 'after');
                 }
             } else {
                 $app_user->state = 'added';
                 $app_user->session_key = $facebook->api_client->session_key;
                 $app_user->platform_uid = $user->fb_uid;
                 Pie::event('users/authInsertAppUser', compact('user'), 'before');
                 $app_user->save();
                 Pie::event('users/authInsertAppUser', compact('user'), 'after');
             }
         }
         $_SESSION['users']['facebookAppUser'][$app_id] = $app_user;
     }
     Pie::event('users/auth', compact('platform', 'app_id', 'password'), 'after');
     // At this point, $user is set.
     return $user;
 }
Beispiel #2
0
 /**
  * Retrieves the currently logged-in user from the session.
  * If the user was not originally retrieved from the database,
  * inserts a new one.
  * Thus, this can also be used to turn visitors into registered
  * users.
  * @method authenticate
  * @static
  * @param {string} $provider Currently only supports the value "facebook".
  * @param {integer} [$appId=null] The id of the app within the specified provider.
  *  Used for storing app-specific session information.
  * @param {&boolean} [$authenticated=null] If authentication fails, puts false here.
  *  Otherwise, puts one of the following:
  *  'registered' if user just registered,
  *  'adopted' if a futureUser was just adopted,
  *  'connected' if a logged-in user just connected the provider account for the first time,
  *  'authorized' if a logged-in user was connected to provider but just authorized this app for the first time
  *  or true otherwise.
  * @param {boolean} [$import_emailAddress=false] If true, and the user's email address is not set yet,
  *  imports the email address from the provider if it is available,
  *  and sets it as the user's email address without requiring verification.
  * @return {Users_User}
  */
 static function authenticate($provider, $appId = null, &$authenticated = null, $import_emailAddress = false)
 {
     if (!isset($appId)) {
         $app = Q_Config::expect('Q', 'app');
         $appId = Q_Config::expect('Users', 'facebookApps', $app, 'appId');
     }
     $authenticated = null;
     $during = 'authenticate';
     $return = null;
     /**
      * @event Users/authenticate {before}
      * @param {string} provider
      * @param {string} appId
      * @return {Users_User}
      */
     $return = Q::event('Users/authenticate', compact('provider', 'appId'), 'before');
     if (isset($return)) {
         return $return;
     }
     if (!isset($provider) or $provider != 'facebook') {
         throw new Q_Exception_WrongType(array('field' => 'provider', 'type' => '"facebook"'));
     }
     if (!isset($appId)) {
         throw new Q_Exception_WrongType(array('field' => 'appId', 'type' => 'a valid facebook app id'));
     }
     Q_Session::start();
     // First, see if we've already logged in somehow
     if ($user = self::loggedInUser()) {
         // Get logged in user from session
         $user_was_logged_in = true;
         $retrieved = true;
     } else {
         // Get an existing user or create a new one
         $user_was_logged_in = false;
         $retrieved = false;
         $user = new Users_User();
     }
     $authenticated = false;
     $emailAddress = null;
     // Try authenticating the user with the specified provider
     switch ($provider) {
         case 'facebook':
             $facebook = Users::facebook($appId);
             if (!$facebook or !$facebook->getUser()) {
                 // no facebook authentication is happening
                 return $user_was_logged_in ? $user : false;
             }
             if (empty($user->emailAddress)) {
                 $queries = array(array('method' => 'GET', 'relative_url' => '/me/permissions'), array('method' => 'GET', 'relative_url' => '/me'));
                 $batchResponse = $facebook->api('?batch=' . Q::json_encode($queries), 'POST');
                 $permissions = json_decode($batchResponse[0]['body'], true);
                 if (Q::ifset($permissions, 'data', 0, 'email', false)) {
                     $userData = json_decode($batchResponse[1]['body'], true);
                     if (!empty($userData['email'])) {
                         $emailAddress = $userData['email'];
                     }
                 }
             }
             $authenticated = true;
             $fb_uid = $facebook->getUser();
             $re_save_user = false;
             if ($retrieved) {
                 if (empty($user->fb_uid)) {
                     // this is a logged-in user who was never authenticated with facebook.
                     // First, let's find any other user who has authenticated with this facebook uid,
                     // and set their fb_uid to NULL.
                     $authenticated = 'connected';
                     $ui = Users::identify('facebook', $fb_uid);
                     if ($ui) {
                         Users_User::update()->set(array('fb_uid' => 0))->where(array('id' => $ui->userId))->execute();
                         $ui->remove();
                     }
                     // Now, let's associate their account with this facebook uid.
                     $user->fb_uid = $fb_uid;
                     $user->save();
                     // Save the identifier in the quick lookup table
                     $ui = new Users_Identify();
                     $ui->identifier = "facebook:{$fb_uid}";
                     $ui->state = 'verified';
                     $ui->userId = $user->id;
                     $ui->save(true);
                 } else {
                     if ($user->fb_uid !== $fb_uid) {
                         // The logged-in user was authenticated with facebook already,
                         // and associated with a different facebook id.
                         // Most likely, a completely different person has logged into facebook
                         // at this computer. So rather than changing the associated facebook uid
                         // for the logged-in user, simply log out and essentially run this function
                         // from the beginning again.
                         Users::logout();
                         $user_was_logged_in = false;
                         $user = new Users_User();
                         $retrieved = false;
                     }
                 }
             }
             if (!$retrieved) {
                 $ui = Users::identify('facebook', $fb_uid, null);
                 if ($ui) {
                     $user = new Users_User();
                     $user->id = $ui->userId;
                     $exists = $user->retrieve();
                     if (!$exists) {
                         throw new Q_Exception("Users_Identify for fb_uid {$fb_uid} exists but not user with id {$ui->userId}");
                     }
                     $retrieved = true;
                     if ($ui->state === 'future') {
                         $authenticated = 'adopted';
                         $user->fb_uid = $fb_uid;
                         $user->signedUpWith = 'facebook';
                         // should have been "none" before this
                         /**
                          * @event Users/adoptFutureUser {before}
                          * @param {Users_User} user
                          * @param {string} during
                          * @return {Users_User}
                          */
                         $ret = Q::event('Users/adoptFutureUser', compact('user', 'during'), 'before');
                         if ($ret) {
                             $user = $ret;
                         }
                         $user->save();
                         $ui->state = 'verified';
                         $ui->save();
                         /**
                          * @event Users/adoptFutureUser {after}
                          * @param {Users_User} user
                          * @param {array} links
                          * @param {string} during
                          * @return {Users_User}
                          */
                         Q::event('Users/adoptFutureUser', compact('user', 'links', 'during'), 'after');
                     } else {
                         // If we are here, that simply means that we already verified the
                         // $fb_uid => $userId mapping for some existing user who signed up
                         // and has been using the system. So there is nothing more to do besides
                         // setting this user as the logged-in user below.
                     }
                 } else {
                     // user is logged out and no user corresponding to $fb_uid yet
                     $authenticated = 'registered';
                     // If we can import email address from facebook,
                     // try retrieving it quietly
                     if ($import_emailAddress) {
                         // DELAY: The following call may take some time,
                         // but once the user is saved, it will not happen again
                         // for this facebook user, because it would be identified by fb_uid
                         $userData = $facebook->api('/me');
                         if (!empty($userData['email'])) {
                             $emailAddress = $userData['email'];
                         }
                         Users::$cache['facebookUserData'] = $userData;
                     }
                     if (!empty($emailAddress)) {
                         $ui = Users::identify('email', $emailAddress, 'verified');
                         if ($ui) {
                             // existing user  identified from verified email address
                             // load it into $user
                             $user = new Users_User();
                             $user->id = $ui->userId;
                             $user->retrieve(null, null, true)->caching()->resume();
                         }
                     }
                     $user->fb_uid = $fb_uid;
                     /**
                      * @event Users/insertUser {before}
                      * @param {Users_User} user
                      * @param {string} during
                      * @return {Users_User}
                      */
                     $ret = Q::event('Users/insertUser', compact('user', 'during'), 'before');
                     if (isset($ret)) {
                         $user = $ret;
                     }
                     if (!$user->wasRetrieved()) {
                         // Register a new user basically and give them an empty username for now
                         $user->username = "";
                         $user->icon = 'default';
                         $user->signedUpWith = 'facebook';
                         $user->save();
                         // Save the identifier in the quick lookup table
                         $ui = new Users_Identify();
                         $ui->identifier = "facebook:{$fb_uid}";
                         $ui->state = 'verified';
                         $ui->userId = $user->id;
                         $ui->save(true);
                         // Download and save facebook icon for the user
                         $sizes = Q_Config::expect('Users', 'icon', 'sizes');
                         sort($sizes);
                         $icon = array();
                         foreach ($sizes as $size) {
                             $parts = explode('x', $size);
                             $width = Q::ifset($parts, 0, '');
                             $height = Q::ifset($parts, 1, '');
                             $width = $width ? $width : $height;
                             $height = $height ? $height : $width;
                             $icon["{$size}.png"] = "https://graph.facebook.com/{$fb_uid}/picture?width={$width}&height={$height}";
                         }
                         if (!Q_Config::get('Users', 'register', 'icon', 'leaveDefault', false)) {
                             self::importIcon($user, $icon);
                             $user->save();
                         }
                     }
                 }
             }
             Users::$cache['user'] = $user;
             Users::$cache['authenticated'] = $authenticated;
             // Checking if user email is not set, and we have facebook "email" permission,
             // try retrieving it from facebook and verifying the email for the user
             if (!empty($emailAddress)) {
                 $emailSubject = Q_Config::get('Users', 'transactional', 'authenticated', 'subject', false);
                 $emailView = Q_Config::get('Users', 'transactional', 'authenticated', 'body', false);
                 if ($emailSubject !== false and $emailView) {
                     $user->addEmail($emailAddress, $emailSubject, $emailView);
                 }
                 // After this, we automatically verify their email,
                 // even if they never clicked the confirmation link,
                 // because we trust the authentication provider.
                 $user->setEmailAddress($emailAddress, true);
             }
             break;
         default:
             // not sure how to log this user in
             return $user_was_logged_in ? $user : false;
     }
     if (!$user_was_logged_in) {
         self::setLoggedInUser($user);
     }
     if ($retrieved) {
         /**
          * @event Users/updateUser {after}
          * @param {Users_User} user
          * @param {string} during
          */
         Q::event('Users/updateUser', compact('user', 'during'), 'after');
     } else {
         /**
          * @event Users/insertUser {after}
          * @param {string} during
          * @param {Users_User} 'user'
          */
         Q::event('Users/insertUser', compact('user', 'during'), 'after');
     }
     // Now make sure our master session contains the
     // session info for the provider app.
     if ($provider == 'facebook') {
         $access_token = $facebook->getAccessToken();
         if (isset($_SESSION['Users']['appUsers']['facebook_' . $appId])) {
             // Facebook app user exists. Do we need to update it? (Probably not!)
             $pk = $_SESSION['Users']['appUsers']['facebook_' . $appId];
             $app_user = Users_AppUser::select('*')->where($pk)->fetchDbRow();
             if (empty($app_user)) {
                 // somehow this app_user disappeared from the database
                 throw new Q_Exception_MissingRow(array('table' => 'AppUser', 'criteria' => http_build_query($pk, null, ' & ')));
             }
             if (empty($app_user->state) or $app_user->state !== 'added') {
                 $app_user->state = 'added';
             }
             if (!isset($app_user->access_token) or $access_token != $app_user->access_token) {
                 /**
                  * @event Users/authenticate/updateAppUser {before}
                  * @param {Users_User} user
                  */
                 Q::event('Users/authenticate/updateAppUser', compact('user', 'app_user'), 'before');
                 $app_user->access_token = $access_token;
                 $app_user->save();
                 // update access_token in app_user
                 /**
                  * @event Users/authenticate/updateAppUser {after}
                  * @param {Users_User} user
                  */
                 Q::event('Users/authenticate/updateAppUser', compact('user', 'app_user'), 'after');
             }
         } else {
             // We have to put the session info in
             $app_user = new Users_AppUser();
             $app_user->userId = $user->id;
             $app_user->provider = 'facebook';
             $app_user->appId = $appId;
             if ($app_user->retrieve()) {
                 // App user exists in database. Do we need to update it?
                 if (!isset($app_user->access_token) or $app_user->access_token != $access_token) {
                     /**
                      * @event Users/authenticate/updateAppUser {before}
                      * @param {Users_User} user
                      */
                     Q::event('Users/authenticate/updateAppUser', compact('user', 'app_user'), 'before');
                     $app_user->access_token = $access_token;
                     $app_user->save();
                     // update access_token in app_user
                     /**
                      * @event Users/authenticate/updateAppUser {after}
                      * @param {Users_User} user
                      */
                     Q::event('Users/authenticate/updateAppUser', compact('user', 'app_user'), 'after');
                 }
             } else {
                 if (empty($app_user->state) or $app_user->state !== 'added') {
                     $app_user->state = 'added';
                 }
                 $app_user->access_token = $access_token;
                 $app_user->provider_uid = $user->fb_uid;
                 /**
                  * @event Users/insertAppUser {before}
                  * @param {Users_User} user
                  * @param {string} 'during'
                  */
                 Q::event('Users/insertAppUser', compact('user', 'during'), 'before');
                 // The following may update an existing app_user row
                 // in the rare event that someone tries to tie the same
                 // provider account to two different accounts.
                 // A provider account can only reference one account, so the
                 // old connection will be dropped, and the new connection saved.
                 $app_user->save(true);
                 /**
                  * @event Users/authenticate/insertAppUser {after}
                  * @param {Users_User} user
                  */
                 Q::event('Users/authenticate/insertAppUser', compact('user'), 'after');
                 $authenticated = 'authorized';
             }
         }
         $_SESSION['Users']['appUsers']['facebook_' . $appId] = $app_user->getPkValue();
     }
     Users::$cache['authenticated'] = $authenticated;
     /**
      * @event Users/authenticate {after}
      * @param {string} provider
      * @param {string} appId
      */
     Q::event('Users/authenticate', compact('provider', 'appId'), 'after');
     // At this point, $user is set.
     return $user;
 }
Beispiel #3
0
function Users_importContacts_providers_yahoo($params)
{
    #Url fetching function
    $fetch = function ($url) use($params) {
        /** @var $client Zend_Oauth_Client */
        $client = $params['client'];
        $client->setUri($url);
        $client->setParameterGet('format', 'json');
        $response = $client->request(Zend_Http_Client::GET);
        if ($response->getStatus() != 200) {
            #TODO: Should we only throw Users_Exception_OAuthTokenInvalid on error 401?
            throw new Users_Exception_OAuthTokenInvalid();
        }
        return $response->getBody();
    };
    #Find out user's Yahoo GUID
    #Do we have the GUID saved?
    $cu = Users::loggedInUser();
    $user = new Users_AppUser();
    $user->userId = $cu->id;
    $user->provider = 'yahoo';
    $user->appId = Q_Config::expect('Users', 'oAuthProviders', 'yahoo', 'appId');
    $user->retrieve('*', true);
    if (!empty($user->provider_uid)) {
        #We have user's Yahoo GUID saved
        $guid = $user->provider_uid;
    } else {
        $guidjson = json_decode($fetch('http://social.yahooapis.com/v1/me/guid'));
        $guid = $guidjson->guid->value;
        $user->provider_uid = $guid;
        $user->save(true);
    }
    #Request contacts
    $res = json_decode($fetch("http://social.yahooapis.com/v1/user/{$guid}/contacts"));
    echo '<pre>';
    foreach ($res->contacts->contact as $c) {
        $givenName = null;
        $familyName = null;
        $nickName = null;
        $email = null;
        $groups = array();
        foreach ($c->fields as $f) {
            switch ($f->type) {
                case 'nickname':
                    $nickName = $f->value;
                    break;
                case 'email':
                    if (empty($email)) {
                        $email = $f->value;
                    }
                    break;
                case 'name':
                    if (!empty($f->value->givenName)) {
                        $givenName = $f->value->givenName;
                    }
                    if (!empty($f->value->familyName)) {
                        $familyName = $f->value->familyName;
                    }
                    break;
            }
        }
        if (!$email) {
            continue;
        }
        #Detect groups
        foreach ($c->categories as $g) {
            $groups[] = $g->name;
        }
        #Save user
        $alr = Users::addLink($email, 'email', array('firstName' => $givenName, 'lastName' => $familyName, 'labels' => $groups));
        echo $givenName . ($familyName ? ' ' . $familyName : '') . ' [' . $email . ']' . ($groups ? ' (' . implode(', ', $groups) . ')' : '') . ' -> ' . ($alr === true ? 'ADDED' : ($alr ? 'EXISTS: ' . $alr : 'EXISTS')) . PHP_EOL;
    }
    return true;
}