function Streams_invite_validate() { if (Q_Request::method() === 'PUT') { return; } if (Q_Request::method() !== 'GET') { Q_Valid::nonce(true); } $fields = array('publisherId', 'streamName'); if (Q_Request::method() === 'POST') { if (Q_Valid::requireFields($fields)) { return; } foreach ($fields as $f) { if (strlen(trim($_REQUEST[$f])) === 0) { Q_Response::addError(new Q_Exception("{$f} can't be empty", $f)); } } } if (isset($_REQUEST['fullName'])) { $length_min = Q_Config::get('Streams', 'inputs', 'fullName', 'lengthMin', 5); $length_max = Q_Config::get('Streams', 'inputs', 'fullName', 'lengthMax', 30); if (strlen($_REQUEST['fullName']) < $length_min) { throw new Q_Exception("A user's full name can't be that short.", 'fullName'); } if (strlen($_REQUEST['fullName']) > $length_max) { throw new Q_Exception("A user's full name can't be that long.", 'fullName'); } } }
/** * Standard tool for making payments. * @class Assets payment * @constructor * @param {array} $options Override various options for this tool * @param {string} $options.payments can be "authnet" or "stripe" * @param {string} $options.amount the amount to pay. * @param {double} [$options.currency="usd"] the currency to pay in. (authnet supports only "usd") * @param {string} [$options.payButton] Can override the title of the pay button * @param {String} [$options.publisherId=Users::communityId()] The publisherId of the Assets/product or Assets/service stream * @param {String} [$options.streamName] The name of the Assets/product or Assets/service stream * @param {string} [$options.name=Users::communityName()] The name of the organization the user will be paying * @param {string} [$options.image] The url pointing to a square image of your brand or product. The recommended minimum size is 128x128px. * @param {string} [$options.description=null] A short name or description of the product or service being purchased. * @param {string} [$options.panelLabel] The label of the payment button in the Stripe Checkout form (e.g. "Pay {{amount}}", etc.). If you include {{amount}}, it will be replaced by the provided amount. Otherwise, the amount will be appended to the end of your label. * @param {string} [$options.zipCode] Specify whether Stripe Checkout should validate the billing ZIP code (true or false). The default is false. * @param {boolean} [$options.billingAddress] Specify whether Stripe Checkout should collect the user's billing address (true or false). The default is false. * @param {boolean} [$options.shippingAddress] Specify whether Checkout should collect the user's shipping address (true or false). The default is false. * @param {string} [$options.email=Users::loggedInUser(true)->emailAddress] You can use this to override the email address, if any, provided to Stripe Checkout to be pre-filled. * @param {boolean} [$options.allowRememberMe=true] Specify whether to include the option to "Remember Me" for future purchases (true or false). * @param {boolean} [$options.bitcoin=false] Specify whether to accept Bitcoin (true or false). * @param {boolean} [$options.alipay=false] Specify whether to accept Alipay ('auto', true, or false). * @param {boolean} [$options.alipayReusable=false] Specify if you need reusable access to the customer's Alipay account (true or false). */ function Assets_payment_tool($options) { Q_Valid::requireFields(array('payments', 'amount'), $options, true); if (empty($options['name'])) { $options['name'] = Users::communityName(); } if (!empty($options['image'])) { $options['image'] = Q_Html::themedUrl($options['image']); } $options['payments'] = strtolower($options['payments']); if (empty($options['email'])) { $options['email'] = Users::loggedInUser(true)->emailAddress; } $payments = ucfirst($options['payments']); $currency = strtolower(Q::ifset($options, 'currency', 'usd')); if ($payments === 'Authnet' and $currency !== 'usd') { throw new Q_Exception("Authnet doesn't support currencies other than USD", 'currency'); } $className = "Assets_Payments_{$payments}"; switch ($payments) { case 'Authnet': $adapter = new $className($options); $token = $options['token'] = $adapter->authToken(); $testing = $options['testing'] = Q_Config::expect('Assets', 'payments', $lcpayments, 'testing'); $action = $options['action'] = $testing ? "https://test.authorize.net/profile/manage" : "https://secure.authorize.net/profile/manage"; break; case 'Stripe': $publishableKey = Q_Config::expect('Assets', 'payments', 'stripe', 'publishableKey'); break; } $titles = array('Authnet' => 'Authorize.net', 'Stripe' => 'Stripe'); Q_Response::setToolOptions($options); $payButton = Q::ifset($options, 'payButton', "Pay with " . $titles[$payments]); return Q::view("Assets/tool/payment/{$payments}.php", compact('token', 'publishableKey', 'action', 'payButton')); }
/** * 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; }
/** * Lets the user search for streams they can relate a given stream to, and relate it * @class Streams relate * @constructor * @param {array} [$options] Override various options for this tool * @param {string} $publisherId publisher id of the stream to relate * @param {string} $streamName name of stream to relate * @param {string} [$communityId=Users::communityId()] id of the user publishing the streams to relate to * @param {array} [$types=Q_Config::expect('Streams','relate','types')] the types of streams the user can select * @param {array} [$typeNames] pairs of array($type => $typeName) to override names of the types, which would otherwise be taken from the types * @param {Boolean} [options.multiple=true] whether the user can select multiple types for the lookup * @param {boolean} [$relateFrom=false] if true, will relate FROM the user-selected stream TO the streamName instead * @param {string} [$types=Q_Config::expect('Streams','relate','types')] the types of streams the user can select * @param {Q.Event} [$options.onRelate] This event handler occurs when a stream is successfully related */ function Streams_relate_tool($options) { Q_Valid::requireFields(array('publisherId', 'streamName'), $options, true); if (!isset($options['communityId'])) { $options['communityId'] = Users::communityId(); } if (!isset($options['types'])) { $options['types'] = Q_Config::get('Streams', 'relate', 'types', array()); } Q_Response::setToolOptions($options); return ''; }
function Users_user_response_users($params = array()) { $req = array_merge($_REQUEST, $params); Q_Valid::requireFields(array('userIds'), $req, true); $userIds = $req['userIds']; if (is_string($userIds)) { $userIds = explode(",", $userIds); } $fields = Q_Config::expect('Users', 'avatarFields'); $users = Users_User::select($fields)->where(array('id' => $userIds))->fetchDbRows(null, null, 'id'); return Q_Response::setSlot('users', Db::exportArray($users, array('asAvatar' => true))); }
/** * Used by HTTP clients to start a subscription * @class HTTP Assets subscription * @method post * @param {array} $_REQUEST * @param {string} $_REQUEST.payments Required. Should be either "authnet" or "stripe" * @param {String} $_REQUEST.planStreamName the name of the subscription plan's stream * @param {String} [$_REQUEST.planPublisherId=Users::communityId()] the publisher of the subscription plan's stream * @param {String} [$_REQUEST.token=null] if using stripe, pass the token here */ function Assets_subscription_post($params = array()) { $req = array_merge($_REQUEST, $params); Q_Valid::requireFields(array('payments'), $req, true); // to be safe, we only start subscriptions from existing plans $planPublisherId = Q::ifset($req, 'planPublisherId', Users::communityId()); $plan = Streams::fetchOne($planPublisherId, $planPublisherId, $req['planStreamName'], true); // the currency will always be assumed to be "USD" for now // and the amount will always be assumed to be in dollars, for now $token = Q::ifset($req, 'token', null); $subscription = Assets::startSubscription($plan, $req['payments'], compact('token')); Q_Response::setSlot('subscription', $subscription); }
/** * Adds contacts to the system. Fills the "contacts" slot. * @param {array} $_REQUEST * @param {string} $_REQUEST.label The label of the contact * @param {string} $_REQUEST.contactUserId The contactUserId of the contact * @param {string} [$_REQUEST.nickname] The nickname of the contact * @param {string} [$_REQUEST.userId=Users::loggedInUser(true)->id] You can override the user id, if another plugin adds a hook that allows you to do this */ function Users_contact_post($params = array()) { if (Q_Request::slotName('batch') or Q_Request::slotName('contacts')) { return; } $req = array_merge($_REQUEST, $params); Q_Valid::requireFields(array('label', 'contactUserId'), $req, true); $loggedInUserId = Users::loggedInUser(true)->id; $userId = Q::ifset($req, 'userId', $loggedInUserId); $contactUserId = $req['contactUserId']; $nickname = Q::ifset($req, 'nickname', null); $contacts = Users_Contact::addContact($userId, $req['label'], $contactUserId, $nickname); Q_Response::setSlot('contacts', Db::exportArray($contacts)); }
function Users_user_response_batch($params = array()) { $req = array_merge($_REQUEST, $params); Q_Valid::requireFields(array('batch'), $req, true); $batch = $req['batch']; $batch = json_decode($batch, true); if (!isset($batch)) { throw new Q_Exception_WrongValue(array('field' => 'batch', 'range' => '{userIds: [userId1, userId2, ...]}')); } Q_Valid::requireFields(array('userIds'), $batch, true); $userIds = $batch['userIds']; $users = Q::event('Users/user/response/users', compact('userIds')); $result = array(); foreach ($userIds as $userId) { $result[] = array('slots' => array('user' => isset($users[$userId]) ? $users[$userId] : null)); } Q_Response::setSlot('batch', $result); }
function Users_contact_response_batch($params = array()) { $req = array_merge($_REQUEST, $params); Q_Valid::requireFields(array('batch'), $req, true); $batch = $req['batch']; $batch = json_decode($batch, true); if (!isset($batch)) { throw new Q_Exception_WrongValue(array('field' => 'batch', 'range' => '{userIds: [...], labels: [...], contactUserIds: [...]}')); } Q_Valid::requireFields(array('userIds', 'labels', 'contactUserIds'), $batch, true); $userIds = $batch['userIds']; $labels = $batch['labels']; $contactUserIds = $batch['contactUserIds']; $contacts = Q::event('Users/contact/response/contacts', compact('userIds', 'labels', 'contactUserIds')); $result = array(); foreach ($contacts as $contact) { $result[] = array('slots' => array('contact' => $contact)); } Q_Response::setSlot('batch', $result); }
/** * Make a one-time charge using the payments processor * @method charge * @param {double} $amount specify the amount (optional cents after the decimal point) * @param {string} [$currency='USD'] set the currency, which will affect the amount * @param {array} [$options=array()] Any additional options * @param {string} [$options.token=null] required unless the user is an existing customer * @param {string} [$options.description=null] description of the charge, to be sent to customer * @param {string} [$options.metadata=null] any additional metadata to store with the charge * @param {string} [$options.subscription=null] if this charge is related to a subscription stream * @param {string} [$options.subscription.publisherId] * @param {string} [$options.subscription.streamName] * @throws \Stripe\Error\Card * @return {string} The customerId of the Assets_Customer that was successfully charged */ function charge($amount, $currency = 'USD', $options = array()) { $options = array_merge($this->options, $options); Q_Valid::requireFields(array('secret', 'user'), $options, true); \Stripe\Stripe::setApiKey($options['secret']); $user = $options['user']; $customer = new Assets_Customer(); $customer->userId = $user->id; $customer->payments = 'stripe'; if (!$customer->retrieve()) { Q_Valid::requireFields(array('token'), $options, true); $sc = \Stripe\Customer::create(array("source" => $options['token']["id"], "description" => $options['user']->displayName())); $customer->customerId = $sc->id; $customer->save(); } $params = array("amount" => $amount * 100, "currency" => $currency, "customer" => $customer->customerId); Q::take($options, array('description', 'metadata'), $params); \Stripe\Charge::create($params); // can throw some exception return $customer->customerId; }
/** * Registers a user in the system. * @method register * @static * @param {string} $username The name of the user * @param {string|array} $identifier Can be an email address or mobile number. Or it could be an array of $type => $info * @param {string} [$identifier.identifier] an email address or phone number * @param {array} [$identifier.device] an array with keys "deviceId", "platform", "version" * to store in the Users_Device table for sending notifications * @param {array|string} [$icon=array()] Array of filename => url pairs * @param {string} [$provider=null] Provider such as "facebook" * @param {array} [$options=array()] An array of options that could include: * @param {string} [$options.activation] The key under "Users"/"transactional" config to use for sending an activation message. Set to false to skip sending the activation message for some reason. * @return {Users_User} * @throws {Q_Exception_WrongType} If identifier is not e-mail or modile * @throws {Q_Exception} If user was already verified for someone else * @throws {Users_Exception_AlreadyVerified} If user was already verified * @throws {Users_Exception_UsernameExists} If username exists */ static function register($username, $identifier, $icon = array(), $provider = null, $options = array()) { if (is_array($provider)) { $options = $provider; $provider = null; } /** * @event Users/register {before} * @param {string} username * @param {string|array} identifier * @param {string} icon * @param {string} provider * @return {Users_User} */ $return = Q::event('Users/register', compact('username', 'identifier', 'icon', 'provider', 'options'), 'before'); if (isset($return)) { return $return; } $during = 'register'; if (is_array($identifier)) { reset($identifier); switch (key($identifier)) { case 'device': $fields = array('deviceId', 'platform', 'version'); Q_Valid::requireFields($fields, $identifier, true); $device = $identifier; if (isset($identifier['identifier'])) { $identifier = $identifier['identifier']; } break; default: throw new Q_Exception_WrongType(array('field' => 'identifier', 'type' => 'an array with entry named "device"')); } } if (Q_Valid::email($identifier, $emailAddress)) { $ui_identifier = $emailAddress; $key = 'email address'; $type = 'email'; } else { if (Q_Valid::phone($identifier, $mobileNumber)) { $key = 'mobile number'; $ui_identifier = $mobileNumber; $type = 'mobile'; } else { throw new Q_Exception_WrongType(array('field' => 'identifier', 'type' => 'email address or mobile number'), array('emailAddress', 'mobileNumber')); } } $user = false; if ($provider) { if ($provider != 'facebook') { throw new Q_Exception_WrongType(array('field' => 'provider', 'type' => '"facebook"')); } $facebook = Users::facebook(); if ($facebook) { $uid = $facebook->getUser(); try { // authenticate (and possibly adopt) an existing provider user // or insert a new user during this authentication $user = Users::authenticate($provider, null, $authenticated, true); } catch (Exception $e) { } if ($user) { // the user is also logged in $adopted = true; // Adopt this provider user /** * @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; } } } } if (!$user) { $user = new Users_User(); // the user we will save in the database } if (empty($adopted)) { // We will be inserting a new user into the database, so check if // this identifier was already verified for someone else. $ui = Users::identify($type, $ui_identifier); if ($ui) { throw new Users_Exception_AlreadyVerified(compact('key'), array('emailAddress', 'mobileNumber', 'identifier')); } } // Insert a new user into the database, or simply modify an existing (adopted) user $user->username = $username; if (!isset($user->signedUpWith) or $user->signedUpWith == 'none') { $user->signedUpWith = $type; } $user->icon = 'default'; $user->passphraseHash = ''; $url_parts = parse_url(Q_Request::baseUrl()); if (isset($url_parts['host'])) { // By default, the user's url would be this: $user->url = $username ? "http://{$username}." . $url_parts['host'] : ""; } /** * @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'); $sizes = Q_Config::expect('Users', 'icon', 'sizes'); sort($sizes); if (empty($icon)) { switch ($provider) { case 'facebook': // let's get this user's icon on facebook if (empty($uid)) { break; } $icon = array(); foreach ($sizes as $size) { $icon["{$size}.png"] = "https://graph.facebook.com/{$uid}/picture?width={$size}&height={$size}"; } break; } } else { // Import the user's icon and save it if (is_string($icon)) { // assume it's from gravatar $iconString = $icon; $icon = array(); foreach ($sizes as $size) { $icon["{$size}.png"] = "{$iconString}&s={$size}"; } } else { // locally generated icons $hash = md5(strtolower(trim($identifier))); $icon = array(); foreach ($sizes as $size) { $icon["{$size}.png"] = array('hash' => $hash, 'size' => $size); } } } if (!Q_Config::get('Users', 'register', 'icon', 'leaveDefault', false)) { self::importIcon($user, $icon); $user->save(); } if (empty($user->emailAddress) and empty($user->mobileNumber)) { // Add an email address or mobile number to the user, that they'll have to verify try { $activation = Q::ifset($options, 'activation', 'activation'); if ($activation) { $subject = Q_Config::get('Users', 'transactional', $activation, "subject", null); $body = Q_Config::get('Users', 'transactional', $activation, "body", null); } else { $subject = $body = null; } if ($type === 'email') { $user->addEmail($identifier, $subject, $body, array(), $options); } else { if ($type === 'mobile') { $p = $options; if ($delay = Q_Config::get('Users', 'register', 'delaySms', 0)) { $p['delay'] = $delay; } $sms = Q_Config::get('Users', 'transactional', $activation, "sms", null); $user->addMobile($mobileNumber, $sms, array(), $p); } } } catch (Exception $e) { // The activation message could not be sent, so remove this user // from the database. This way, this username will be // back on the market. $user->remove(); throw $e; } } if (!empty($device)) { $device['userId'] = $user->id; Users_Device::add($device); } /** * @event Users/register {after} * @param {string} username * @param {string|array} identifier * @param {string} icon * @param {Users_User} user * @param {string} provider * @return {Users_User} */ $return = Q::event('Users/register', compact('username', 'identifier', 'icon', 'user', 'provider', 'options', 'device'), 'after'); return $user; }