/** * Adds a device to the system, after sending a test notification to it * @param {array} $device * @param {string} $device.userId * @param {string} $device.deviceId * @param {string} [$device.formFactor] * @param {string} [$device.platform] * @param {string} [$device.version] * @param {string} [$device.sessionId] * @param {boolean} [$device.sandbox] * @param {string} [$device.passphrase] * @param {boolean} [$skipNotification=false] if true, skips sending notification * @return {Users_Device} */ static function add($device, $skipNotification = false) { Q_Valid::requireFields(array('userId', 'deviceId'), $device, true); $userId = $device['userId']; $deviceId = $device['deviceId']; if (!$skipNotification) { $app = Q::app(); $sandbox = Q::ifset($device, 'sandbox', null); if (!isset($sandbox)) { $sandbox = Q_Config::get($app, "cordova", "ios", "sandbox", false); } $env = $sandbox ? ApnsPHP_Abstract::ENVIRONMENT_SANDBOX : ApnsPHP_Abstract::ENVIRONMENT_PRODUCTION; $s = $sandbox ? 'sandbox' : 'production'; $cert = APP_LOCAL_DIR . DS . 'Users' . DS . 'certs' . DS . $app . DS . $s . DS . 'bundle.pem'; $authority = USERS_PLUGIN_FILES_DIR . DS . 'Users' . DS . 'certs' . DS . 'EntrustRootCA.pem'; $logger = new Users_ApnsPHP_Logger(); $push = new ApnsPHP_Push($env, $cert); $push->setLogger($logger); $push->setRootCertificationAuthority($authority); if (isset($device['passphrase'])) { $push->setProviderCertificatePassphrase($device['passphrase']); } $push->connect(); $message = new ApnsPHP_Message($deviceId); $message->setCustomIdentifier('Users_Device-adding'); $message->setBadge(0); $message->setText(Q_Config::get($app, "cordova", "ios", "device", "text", "Notifications have been enabled")); $message->setCustomProperty('userId', $userId); $message->setExpiry(5); $push->add($message); $push->send(); $push->disconnect(); $errors = $push->getErrors(); if (!empty($errors)) { $result = reset($errors); throw new Users_Exception_DeviceNotification($result['ERRORS'][0]); } } $sessionId = Q_Session::id(); $user = Users::loggedInUser(); $info = array_merge(Q_Request::userAgentInfo(), array('sessionId' => $sessionId, 'userId' => $user ? $user->id : null, 'deviceId' => null)); $device2 = Q::take($device, $info); $d = new Users_Device($device2); $d->save(true); if ($sessionId) { $s = new Users_Session(); $s->id = $sessionId; if (!$s->retrieve()) { $s->deviceId = $deviceId; } } $_SESSION['Users']['deviceId'] = $deviceId; $device2['Q/method'] = 'Users/device'; Q_Utils::sendToNode($device2); return $d; }
/** * We are going to implement a subset of the OAuth 1.0a functionality for now, * and later we can expand it to match the full OAuth specification. */ function Users_authorize_response() { if (Q_Response::getErrors()) { Q_Dispatcher::showErrors(); } $response_type = 'token'; $token_type = 'bearer'; $client_id = $_REQUEST['client_id']; $state = $_REQUEST['state']; $skip = Q::ifset($_REQUEST, 'skip', false); $scope = Users_OAuth::requestedScope(true, $scopes); $client = Users_User::fetch($client_id, true); if (!$client) { throw new Q_Exception_MissingRow(array('table' => 'client user', 'criteria' => "id = '{$client_id}'"), 'client_id'); } if (empty($client->url)) { throw new Q_Exception("Client app needs to register url", 'client_id'); } $redirect_uri = Q::ifset($_REQUEST, 'redirect_uri', $client->url); $user = Users::loggedInUser(); $oa = null; if (isset(Users::$cache['oAuth'])) { $oa = Users::$cache['oAuth']; } else { if ($user) { $oa = new Users_OAuth(); $oa->client_id = $client_id; $oa->userId = $user->id; $oa->state = $state; $oa = $oa->retrieve(); } } $remaining = $scope; if ($oa and $oa->wasRetrieved()) { // User is logged in and already has a token for this client_id and state $paths = Q_Config::get('Users', 'authorize', 'clients', Q::app(), 'redirectPaths', false); $path = substr($redirect_uri, strlen($client->url) + 1); $p = array('response_type' => $response_type, 'token_type' => $token_type, 'access_token' => $oa->access_token, 'expires_in' => $oa->token_expires_seconds, 'scope' => implode(' ', $scope), 'state' => $oa->state); $p = Q_Utils::sign($p, 'Q.Users.oAuth'); // the redirect uri could be a native app url scheme $s = strpos($redirect_uri, '#') === false ? '#' : '&'; $redirect_uri = Q_Uri::from($redirect_uri . $s . http_build_query($p), false)->toUrl(); if (!Q::startsWith($redirect_uri, $client->url) or is_array($paths) and !in_array($path, $paths)) { throw new Users_Exception_Redirect(array('uri' => $redirect_uri)); } Q_Response::redirect($redirect_uri); return false; } $terms_label = Users::termsLabel('authorize'); Q_Response::setScriptData('Q.Users.authorize', compact('client_id', 'redirect_uri', 'scope', 'scopes', 'remaining', 'state', 'response_type', 'skip')); $content = Q::view('Users/content/authorize.php', compact('client', 'user', 'redirect_uri', 'scope', 'scopes', 'remaining', 'state', 'terms_label', 'response_type', 'skip')); Q_Response::setSlot('content', $content); Q_Response::setSlot('column0', $content); return true; }
/** * Get an array of ($code => $title) pairs from space-separated list in $_REQUEST['scope'], * defaulting to the "all" scope. * @method requestedScope * @static * @param {boolean} [$throwIfMissing=false] * @param {reference} [$scopes] this is filled with an array * @return {array} */ static function requestedScope($throwIfMissing = false, &$scopes = null) { $rs = Q::ifset($_REQUEST, 'scope', 'all'); if (is_string($rs)) { $rs = preg_split("/(,|\\s+|,+\\s*)+/", $rs); } $scopes = Q_Config::get('Users', 'authorize', 'clients', Q::app(), 'scopes', array('all' => 'give this app full access')); if ($throwIfMissing) { foreach ($rs as $s) { if ($s and !isset($scopes[$s])) { throw new Q_Exception_WrongValue(array('field' => 'scope', 'range' => json_encode(array_keys($scopes)))); } } } $scope = array(); // copy them in the order they are found in the config foreach ($scopes as $k => $v) { if (in_array($k, $rs)) { $scope[] = $k; } } return $scope; }
function Users_sessions_delete() { if (empty($_REQUEST["sessionId"])) { throw new Q_Exceptions_RequiredField(array('field' => 'sessionId')); } $session = new Users_Session(); $session->id = $_REQUEST['sessionId']; $session->retrieve(true); $content = Q::json_decode($session->content); $userId = Q::ifset($content, 'Users', 'loggedInUser', 'id', null); $loggedInUserId = Users::loggedInUser(true)->id; if ($userId == $loggedInUserId) { $authorized = true; } else { $app = Q::app(); $roles = Users::roles(); $authorized = !empty($roles["{$app}/admins"]); } if (!$authorized) { throw new Users_Exception_NotAuthorized(); } $session->remove(); Q_Response::setSlot('success', true); }
/** * The default implementation. */ function Q_errors($params) { extract($params); /** * @var Exception $exception * @var boolean $startedResponse */ if (!empty($exception)) { Q_Response::addError($exception); } $errors = Q_Response::getErrors(); $errors_array = Q_Exception::toArray($errors); // Simply return the errors, if this was an AJAX request if ($is_ajax = Q_Request::isAjax()) { try { $errors_json = @Q::json_encode($errors_array); } catch (Exception $e) { $errors_array = array_slice($errors_array, 0, 1); unset($errors_array[0]['trace']); $errors_json = @Q::json_encode($errors_array); } $json = "{\"errors\": {$errors_json}}"; $callback = Q_Request::callback(); switch (strtolower($is_ajax)) { case 'iframe': if (!Q_Response::$batch) { header("Content-type: text/html"); } echo <<<EOT <!doctype html><html lang=en> <head><meta charset=utf-8><title>Q Result</title></head> <body> <script type="text/javascript"> window.result = function () { return {$json} }; </script> </body> </html> EOT; break; case 'json': default: header("Content-type: " . ($callback ? "application/javascript" : "application/json")); echo $callback ? "{$callback}({$json})" : $json; } return; } // Forward internally, if it was requested if ($onErrors = Q_Request::special('onErrors', null)) { $uri1 = Q_Dispatcher::uri(); $uri2 = Q_Uri::from($onErrors); $url2 = $uri2->toUrl(); if (!isset($uri2)) { throw new Q_Exception_WrongValue(array('field' => 'onErrors', 'range' => 'an internal URI reachable from a URL')); } if ($uri1->toUrl() !== $url2) { Q_Dispatcher::forward($uri2); return; // we don't really need this, but it's here anyway } } $params2 = compact('errors', 'exception', 'errors_array', 'exception_array'); if (Q::eventStack('Q/response')) { // Errors happened while rendering response. Just render errors view. return Q::view('Q/errors.php', $params2); } if (!$startedResponse) { try { // Try rendering the response, expecting it to // display the errors along with the rest. $ob = new Q_OutputBuffer(); Q::event('Q/response', $params2); $ob->endFlush(); return; } catch (Exception $e) { if (get_class($e) === 'Q_Exception_DispatcherForward') { throw $e; // if forwarding was requested, do it // for all other errors, continue trying other things } $output = $ob->getClean(); } } if ($errors) { // Try rendering the app's errors response, if any. $app = Q::app(); if (Q::canHandle("{$app}/errors/response/content")) { Q_Dispatcher::forward("{$app}/errors"); } else { echo Q::view("Q/errors.php", compact('errors')); } } if (!empty($e)) { return Q::event('Q/exception', array('exception' => $e)); } }