public function execute(AuthenticationCredentials $authCreds)
 {
     $authService = AuthenticationService::instance();
     // Make sure the creds are valid
     if (!$authCreds->isValid()) {
         Application::instance()->getLogger()->error(sprintf('Error validating auth credentials %s', var_export($authCreds, true)));
         throw new Exception('Invalid auth credentials');
     }
     // Account merge
     if (Session::set('accountMerge') === '1') {
         // Must be logged in to do a merge
         if (!Session::hasRole(UserRole::USER)) {
             throw new Exception('Authentication required for account merge');
         }
         $authService->handleAuthAndMerge($authCreds);
         return 'redirect: /profile/authentication';
     }
     // Follow url *notice the set, returning and clearing the var
     $follow = Session::set('follow');
     // If the user profile doesnt exist, go to the register page
     if (!$authService->getUserAuthProfileExists($authCreds)) {
         Session::set('authSession', $authCreds);
         $url = '/register?code=' . urlencode($authCreds->getAuthCode());
         if (!empty($follow)) {
             $url .= '&follow=' . urlencode($follow);
         }
         return 'redirect: ' . $url;
     }
     // User exists, handle the auth
     $authService->handleAuthCredentials($authCreds);
     if (!empty($follow) && substr($follow, 0, 1) == '/') {
         return 'redirect: ' . $follow;
     }
     return 'redirect: /profile';
 }
Example #2
0
 /**
  * Expires subscritions based on their end date
  *
  * @return int the number of expired subscriptions
  */
 public function expiredSubscriptions()
 {
     $conn = Application::instance()->getConnection();
     $authenticationService = AuthenticationService::instance();
     // Expire recurring subs with a 24 hour grace period
     $stmt = $conn->prepare('SELECT subscriptionId,userId FROM dfl_users_subscriptions WHERE recurring = 1 AND status = :status AND endDate + INTERVAL 1 HOUR <= NOW()');
     $stmt->bindValue('status', SubscriptionStatus::ACTIVE, \PDO::PARAM_STR);
     $stmt->execute();
     $subscriptions = $stmt->fetchAll();
     if (!empty($subscriptions)) {
         foreach ($subscriptions as $sub) {
             $authenticationService->flagUserForUpdate($sub['userId']);
             $conn->update('dfl_users_subscriptions', array('status' => SubscriptionStatus::EXPIRED), array('subscriptionId' => $sub['subscriptionId']));
         }
     }
     // Expire NONE recurring subs immediately
     $stmt = $conn->prepare('SELECT subscriptionId,userId FROM dfl_users_subscriptions WHERE (recurring = 0 OR recurring IS NULL) AND status = :status AND endDate <= NOW()');
     $stmt->bindValue('status', SubscriptionStatus::ACTIVE, \PDO::PARAM_STR);
     $stmt->execute();
     $subscriptions = $stmt->fetchAll();
     if (!empty($subscriptions)) {
         foreach ($subscriptions as $sub) {
             $authenticationService->flagUserForUpdate($sub['userId']);
             $conn->update('dfl_users_subscriptions', array('status' => SubscriptionStatus::EXPIRED), array('subscriptionId' => $sub['subscriptionId']));
         }
     }
 }
 /**
  * @Route ("/impersonate")
  * @HttpMethod ({"GET"})
  *
  * @param array $params
  * @throws Exception
  * @return string
  */
 public function impersonate(array $params)
 {
     if (!Config::$a['allowImpersonation']) {
         throw new Exception('Impersonating is not allowed');
     }
     $userId = isset($params['userId']) && !empty($params['userId']) ? $params['userId'] : '';
     $username = isset($params['username']) && !empty($params['username']) ? $params['username'] : '';
     if (empty($userId) && empty($username)) {
         throw new Exception('[username] or [userId] required');
     }
     $authService = AuthenticationService::instance();
     $userService = UserService::instance();
     if (!empty($userId)) {
         $user = $userService->getUserById($userId);
     } else {
         if (!empty($username)) {
             $user = $userService->getUserByUsername($username);
         }
     }
     if (empty($user)) {
         throw new Exception('User not found. Try a different userId or username');
     }
     $credentials = $authService->getUserCredentials($user, 'impersonating');
     Session::start();
     Session::updateCredentials($credentials);
     ChatIntegrationService::instance()->setChatSession($credentials, Session::getSessionId());
     return 'redirect: /';
 }
Example #4
0
 public function execute()
 {
     $log = Application::instance()->getLogger();
     $authenticationService = AuthenticationService::instance();
     $subscriptionService = SubscriptionsService::instance();
     $users = array();
     // Renew any subscription that has an active payment profile.
     $subscriptions = $subscriptionService->getRecurringSubscriptionsToRenew();
     foreach ($subscriptions as $subscription) {
         try {
             $subType = $subscriptionService->getSubscriptionType($subscription['subscriptionType']);
             // Because subscriptions can be revived after months of skipped payments;
             // The end date may not simply be behind by the subscription frequency.
             $end = Date::getDateTime($subscription['endDate']);
             $diff = $end->diff(new \DateTime('NOW'));
             $end->modify('+' . (intval($diff->format('%y') * 12) + intval($diff->format('%m'))) . ' month');
             //
             $end->modify('+' . $subType['billingFrequency'] . ' ' . strtolower($subType['billingPeriod']));
             $subscriptionService->updateSubscription(array('subscriptionId' => $subscription['subscriptionId'], 'endDate' => $end->format('Y-m-d H:i:s'), 'status' => SubscriptionStatus::ACTIVE));
             $this->sendResubscribeBroadcast($subscription);
             $users[] = $subscription['userId'];
         } catch (\Exception $e) {
             $log->critical("Could not roll over subscription", $subscription);
         }
     }
     // Expire subscriptions
     $subscriptions = $subscriptionService->getSubscriptionsToExpire();
     if (!empty($subscriptions)) {
         foreach ($subscriptions as $subscription) {
             $users[] = $subscription['userId'];
             $subscriptionService->updateSubscription(array('subscriptionId' => $subscription['subscriptionId'], 'status' => SubscriptionStatus::EXPIRED));
         }
     }
     // Update users
     $users = array_unique($users);
     foreach ($users as $id) {
         $authenticationService->flagUserForUpdate($id);
     }
     // Clean-up old unfinished subscriptions (where users have aborted the process)
     $conn = Application::instance()->getConnection();
     $stmt = $conn->prepare('
       DELETE FROM `dfl_users_subscriptions`
       WHERE `status` = :status AND `createdDate` < (NOW() - INTERVAL 24 HOUR)
     ');
     $stmt->bindValue('status', SubscriptionStatus::_NEW, \PDO::PARAM_STR);
     $stmt->execute();
 }
Example #5
0
 /**
  * @param array $params
  * @return Response
  * @throws Exception
  */
 public function authenticate(array $params)
 {
     if (!isset($params['authtoken']) || empty($params['authtoken'])) {
         return new Response(Http::STATUS_FORBIDDEN, 'Invalid or empty authToken');
     }
     $authToken = ApiAuthenticationService::instance()->getAuthToken($params['authtoken']);
     if (empty($authToken)) {
         return new Response(Http::STATUS_FORBIDDEN, 'Auth token not found');
     }
     $user = UserService::instance()->getUserById($authToken['userId']);
     if (empty($user)) {
         return new Response(Http::STATUS_FORBIDDEN, 'User not found');
     }
     $authenticationService = AuthenticationService::instance();
     $credentials = $authenticationService->getUserCredentials($user, 'API');
     $response = new Response(Http::STATUS_OK, json_encode($credentials->getData()));
     $response->addHeader(Http::HEADER_CONTENTTYPE, MimeType::JSON);
     return $response;
 }
Example #6
0
 /**
  * Checks the users current session status
  * Does a remember me login
  * @return void
  */
 public function init()
 {
     $app = Application::instance();
     $authService = AuthenticationService::instance();
     // If the session hasnt started, or the data is not valid (result from php clearing the session data), check the Remember me cookie
     if (!Session::isStarted() || !Session::getCredentials()->isValid()) {
         $userId = $authService->getRememberMe();
         if ($userId !== false) {
             $userManager = UserService::instance();
             $user = $userManager->getUserById($userId);
             if (!empty($user)) {
                 Session::start(Session::START_NOCOOKIE);
                 $credentials = $authService->getUserCredentials($user, 'rememberme');
                 Session::updateCredentials($credentials);
                 ChatIntegrationService::instance()->setChatSession($credentials, Session::getSessionId());
                 $authService->setRememberMe($user);
             }
         }
     }
 }
Example #7
0
 /**
  * @param array $params         
  * @throws Exception
  */
 public function authenticate(array $params)
 {
     $UserService = UserService::instance();
     $authService = AuthenticationService::instance();
     if (!isset($params['oauth_token']) || empty($params['oauth_token']) || !isset($params['oauth_verifier']) || empty($params['oauth_verifier'])) {
         throw new Exception('Authentication failed');
     }
     $oauth = Session::set('oauth');
     if ($params['oauth_token'] !== $oauth['oauth_token']) {
         throw new Exception('Invalid login session');
     }
     $twitterOAuthConf = Config::$a['oauth']['providers']['twitter'];
     $tmhOAuth = new \tmhOAuth(array('consumer_key' => $twitterOAuthConf['clientId'], 'consumer_secret' => $twitterOAuthConf['clientSecret'], 'token' => $oauth['oauth_token'], 'secret' => $oauth['oauth_token_secret'], 'curl_connecttimeout' => Config::$a['curl']['connecttimeout'], 'curl_timeout' => Config::$a['curl']['timeout'], 'curl_ssl_verifypeer' => Config::$a['curl']['verifypeer']));
     $code = $tmhOAuth->user_request(array('method' => 'POST', 'url' => $tmhOAuth->url('oauth/access_token', ''), 'params' => array('oauth_verifier' => trim($params['oauth_verifier']))));
     if ($code != 200) {
         throw new Exception('Failed to retrieve user data');
     }
     $data = $tmhOAuth->extract_params($tmhOAuth->response['response']);
     $authCreds = $this->getAuthCredentials($oauth['oauth_token'], $data);
     $authCredHandler = new AuthenticationRedirectionFilter();
     return $authCredHandler->execute($authCreds);
 }
Example #8
0
 /**
  * @Route ("/admin/user/{id}/subscription/{subscriptionId}/save")
  * @Route ("/admin/user/{id}/subscription/save")
  * @Secure ({"ADMIN"})
  * @HttpMethod ({"POST"})
  *
  * @param array $params         
  * @param ViewModel $model          
  * @throws Exception
  * @return string
  */
 public function subscriptionSave(array $params, ViewModel $model)
 {
     FilterParams::required($params, 'subscriptionType');
     FilterParams::required($params, 'status');
     FilterParams::required($params, 'createdDate');
     FilterParams::required($params, 'endDate');
     $subscriptionsService = SubscriptionsService::instance();
     $subscriptionType = $subscriptionsService->getSubscriptionType($params['subscriptionType']);
     $subscription = array();
     $subscription['subscriptionType'] = $subscriptionType['id'];
     $subscription['subscriptionTier'] = $subscriptionType['tier'];
     $subscription['status'] = $params['status'];
     $subscription['createdDate'] = $params['createdDate'];
     $subscription['endDate'] = $params['endDate'];
     $subscription['userId'] = $params['id'];
     $subscription['subscriptionSource'] = isset($params['subscriptionSource']) && !empty($params['subscriptionSource']) ? $params['subscriptionSource'] : Config::$a['subscriptionType'];
     if (isset($params['subscriptionId']) && !empty($params['subscriptionId'])) {
         $subscription['subscriptionId'] = $params['subscriptionId'];
         $subscriptionId = $subscription['subscriptionId'];
         $subscriptionsService->updateSubscription($subscription);
         Session::set('modelSuccess', 'Subscription updated!');
     } else {
         $subscriptionId = $subscriptionsService->addSubscription($subscription);
         Session::set('modelSuccess', 'Subscription created!');
     }
     $authService = AuthenticationService::instance();
     $authService->flagUserForUpdate($params['id']);
     return 'redirect: /admin/user/' . urlencode($params['id']) . '/subscription/' . urlencode($subscriptionId) . '/edit';
 }
Example #9
0
 /**
  * @Route ("/profile/update")
  * @HttpMethod ({"POST"})
  * @Secure ({"USER"})
  *
  * @param array $params
  * @return string
  * @throws Exception
  * @throws \Doctrine\DBAL\DBALException
  * @throws \Exception
  */
 public function profileSave(array $params)
 {
     // Get user
     $userService = UserService::instance();
     $authenticationService = AuthenticationService::instance();
     $userId = Session::getCredentials()->getUserId();
     $user = $userService->getUserById($userId);
     if (empty($user)) {
         throw new Exception('Invalid user');
     }
     $username = isset($params['username']) && !empty($params['username']) ? $params['username'] : $user['username'];
     $email = isset($params['email']) && !empty($params['email']) ? $params['email'] : $user['email'];
     $country = isset($params['country']) && !empty($params['country']) ? $params['country'] : $user['country'];
     $allowGifting = isset($params['allowGifting']) ? $params['allowGifting'] : $user['allowGifting'];
     $minecraftname = isset($params['minecraftname']) && !empty($params['minecraftname']) ? $params['minecraftname'] : $user['minecraftname'];
     try {
         $authenticationService->validateUsername($username, $user);
         $authenticationService->validateEmail($email, $user);
         if (!empty($country)) {
             $countryArr = Country::getCountryByCode($country);
             if (empty($countryArr)) {
                 throw new Exception('Invalid country');
             }
             $country = $countryArr['alpha-2'];
         }
     } catch (Exception $e) {
         Session::set('modelError', $e->getMessage());
         return 'redirect: /profile';
     }
     // Date for update
     $userData = array('username' => $username, 'country' => $country, 'email' => $email, 'minecraftname' => $minecraftname, 'allowGifting' => $allowGifting);
     // Is the user changing their name?
     if (strcasecmp($username, $user['username']) !== 0) {
         $nameChangeCount = intval($user['nameChangedCount']);
         // have they hit their limit
         if ($nameChangeCount >= Config::$a['profile']['nameChangeLimit']) {
             throw new Exception('You have reached your name change limit');
         } else {
             $userData['nameChangedDate'] = Date::getDateTime('NOW')->format('Y-m-d H:i:s');
             $userData['nameChangedCount'] = $nameChangeCount + 1;
         }
     }
     try {
         // Update user
         $userService->updateUser($user['userId'], $userData);
     } catch (\Doctrine\DBAL\DBALException $e) {
         // get PDO exception, extract info
         $info = $e->getPrevious()->errorInfo;
         // a unique key constraint failure
         if ($info[0] === "23000") {
             // extract key name
             if (!preg_match("/^Duplicate entry '.+' for key '(.+)'\$/iu", $info[2], $match)) {
                 throw $e;
             }
             // WELL F**K I GUESS ITS NOT MYSQL
             $key = $match[1];
             $keyToField = array('minecraftname' => '"Minecraft name"');
             throw new Exception('Duplicate value for ' . $keyToField[$key]);
         }
     }
     $authenticationService->flagUserForUpdate($user['userId']);
     Session::set('modelSuccess', 'Your profile has been updated');
     return 'redirect: /profile';
 }
Example #10
0
 /**
  * @Route ("/api/addtwitchsubscription")
  * @HttpMethod ({"POST"})
  *
  * Expects the following POST variables:
  *     privatekey=XXXXXXXX
  *
  * @param array $params
  * @return Response
  */
 public function addSubscription(array $params)
 {
     $response = array();
     // TODO GET RID OF THE COPY PASTE
     try {
         FilterParams::required($params, 'privatekey');
         if (!$this->checkPrivateKey($params['privatekey'])) {
             throw new Exception('Invalid shared private key.');
         }
         /*
          * The expected json schema is: {"123": 1, "431": 0}
          * where the key is the twitch user id and the value is whether
          * the user is a subscriber or not
          */
         $data = json_decode(file_get_contents('php://input'), true);
         $userService = UserService::instance();
         $authid = $userService->getTwitchIDFromNick($data['nick']);
         if ($authid) {
             $users = $userService->updateTwitchSubscriptions(array($authid => 1));
             $chatIntegrationService = ChatIntegrationService::instance();
             $authenticationService = AuthenticationService::instance();
             foreach ($users as $user) {
                 $authenticationService->flagUserForUpdate($user['userId']);
                 if (!$user['istwitchsubscriber']) {
                     // do not announce non-subs
                     continue;
                 }
                 $chatIntegrationService->sendBroadcast(sprintf("%s is now a Twitch subscriber!", $user['username']));
             }
         }
         $response = new Response(Http::STATUS_NO_CONTENT);
     } catch (Exception $e) {
         $response['success'] = false;
         $response['error'] = $e->getMessage();
         $response = new Response(Http::STATUS_BAD_REQUEST, json_encode($response));
         $response->addHeader(Http::HEADER_CONTENTTYPE, MimeType::JSON);
     }
     return $response;
 }
Example #11
0
use Destiny\Common\Session;
use Destiny\Common\Config;
use Destiny\Common\Routing\Router;
use Destiny\Common\Routing\RouteAnnotationClassLoader;
use Destiny\Common\DirectoryClassIterator;
use Destiny\Common\Authentication\RememberMeService;
use Destiny\Common\Authentication\AuthenticationService;
use Doctrine\Common\Annotations\FileCacheReader;
use Doctrine\Common\Annotations\AnnotationReader;
use Destiny\Common\Request;
ini_set('session.gc_maxlifetime', 5 * 60 * 60);
$context = new \stdClass();
$context->log = 'web';
require __DIR__ . '/../lib/boot.php';
$app = Application::instance();
$app->setRouter(new Router());
$app->setAnnotationReader(new FileCacheReader(new AnnotationReader(), realpath(Config::$a['cache']['path']) . '/annotation/'));
// Annotation reader and routing
RouteAnnotationClassLoader::loadClasses(new DirectoryClassIterator(_BASEDIR . '/lib/', 'Destiny/Controllers/'), $app->getAnnotationReader());
// Setup user session
$session = new SessionInstance();
$session->setSessionCookie(new SessionCookie(Config::$a['cookie']));
$session->setCredentials(new SessionCredentials());
$app->setSession($session);
// Start the session if a valid session cookie is found
Session::start(Session::START_IFCOOKIE);
// Startup the remember me and auth service
AuthenticationService::instance()->init();
RememberMeService::instance()->init();
// Attempts to find a route and execute it
$app->executeRequest(new Request());
Example #12
0
 /**
  * @Route ("/admin/user/{userId}/ban/remove")
  * @Secure ({"ADMIN"})
  *
  * @param array $params
  */
 public function removeBan(array $params)
 {
     if (!isset($params['userId']) || empty($params['userId'])) {
         throw new Exception('userId required');
     }
     $userService = UserService::instance();
     $authenticationService = AuthenticationService::instance();
     // if there were rows modified there were bans removed, so an update is
     // required, removeUserBan returns the number of rows modified
     if ($userService->removeUserBan($params['userId'])) {
         $authenticationService->flagUserForUpdate($params['userId']);
     }
     if (isset($params['follow']) and substr($params['follow'], 0, 1) == '/') {
         return 'redirect: ' . $params['follow'];
     }
     return 'redirect: /admin/user/' . $params['userId'] . '/edit';
 }
 /**
  * @Route ("/subscription/process")
  * @Secure ({"USER"})
  * @Transactional
  *
  * We were redirected here from PayPal after the buyer approved/cancelled the payment
  *
  * @param array $params
  */
 public function subscriptionProcess(array $params, ViewModel $model)
 {
     FilterParams::isRequired($params, 'orderId');
     FilterParams::isRequired($params, 'token');
     FilterParams::isThere($params, 'success');
     $ordersService = OrdersService::instance();
     $userService = UserService::instance();
     $subscriptionsService = SubscriptionsService::instance();
     $payPalApiService = PayPalApiService::instance();
     $chatIntegrationService = ChatIntegrationService::instance();
     $authenticationService = AuthenticationService::instance();
     $userId = Session::getCredentials()->getUserId();
     // Get the order
     $order = $ordersService->getOrderByIdAndUserId($params['orderId'], $userId);
     if (empty($order) || strcasecmp($order['state'], OrderStatus::_NEW) !== 0) {
         throw new Exception('Invalid order record');
     }
     try {
         // If we got a failed response URL
         if ($params['success'] == '0' || $params['success'] == 'false' || $params['success'] === false) {
             throw new Exception('Order request failed');
         }
         // Get the subscription from the order
         $orderSubscription = $subscriptionsService->getSubscriptionByOrderId($order['orderId']);
         $subscriptionUser = $userService->getUserById($orderSubscription['userId']);
         // Make sure the subscription is valid
         if (empty($orderSubscription)) {
             throw new Exception('Invalid order subscription');
         }
         // Make sure the subscription is either owned or gifted by the user
         if ($subscriptionUser['userId'] != $userId && $orderSubscription['gifter'] != $userId) {
             throw new Exception('Invalid order subscription');
         }
         $subscriptionType = $subscriptionsService->getSubscriptionType($orderSubscription['subscriptionType']);
         $paymentProfile = $ordersService->getPaymentProfileByOrderId($order['orderId']);
         // Get the checkout info
         $ecResponse = $payPalApiService->retrieveCheckoutInfo($params['token']);
         if (!isset($ecResponse) || $ecResponse->Ack != 'Success') {
             throw new Exception('Failed to retrieve express checkout details');
         }
         // Moved this down here, as if the order status is error, the payerID is not returned
         FilterParams::isRequired($params, 'PayerID');
         // Point of no return - we only every want a person to get here if their order was a successful sequence
         Session::set('token');
         Session::set('orderId');
         // Recurring payment
         if (!empty($paymentProfile)) {
             $createRPProfileResponse = $payPalApiService->createRecurringPaymentProfile($paymentProfile, $params['token'], $subscriptionType);
             if (!isset($createRPProfileResponse) || $createRPProfileResponse->Ack != 'Success') {
                 throw new Exception('Failed to create recurring payment request');
             }
             $paymentProfileId = $createRPProfileResponse->CreateRecurringPaymentsProfileResponseDetails->ProfileID;
             $paymentStatus = $createRPProfileResponse->CreateRecurringPaymentsProfileResponseDetails->ProfileStatus;
             if (empty($paymentProfileId)) {
                 throw new Exception('Invalid recurring payment profileId returned from Paypal');
             }
             // Set the payment profile to active, and paymetProfileId
             $ordersService->updatePaymentProfileId($paymentProfile['profileId'], $paymentProfileId, $paymentStatus);
             // Update the payment profile
             $subscriptionsService->updateSubscriptionPaymentProfile($orderSubscription['subscriptionId'], $paymentProfile['profileId'], true);
         }
         // Complete the checkout
         $DoECResponse = $payPalApiService->getECPaymentResponse($params['PayerID'], $params['token'], $order);
         if (isset($DoECResponse) && $DoECResponse->Ack == 'Success') {
             if (isset($DoECResponse->DoExpressCheckoutPaymentResponseDetails->PaymentInfo)) {
                 $payPalApiService->recordECPayments($DoECResponse, $params['PayerID'], $order);
                 $ordersService->updateOrderState($order['orderId'], $order['state']);
             } else {
                 throw new Exception('No payments for express checkout order');
             }
         } else {
             throw new Exception($DoECResponse->Errors[0]->LongMessage);
         }
         // If the user already has a subscription and ONLY if this subscription was NOT a gift
         if (!isset($orderSubscription['gifter']) || empty($orderSubscription['gifter'])) {
             $activeSubscription = $subscriptionsService->getUserActiveSubscription($subscriptionUser['userId']);
             if (!empty($activeSubscription)) {
                 // Cancel any attached payment profiles
                 $ordersService = OrdersService::instance();
                 $paymentProfile = $ordersService->getPaymentProfileById($activeSubscription['paymentProfileId']);
                 if (!empty($paymentProfile)) {
                     $payPalApiService->cancelPaymentProfile($activeSubscription, $paymentProfile);
                     $subscriptionsService->updateSubscriptionRecurring($activeSubscription['subscriptionId'], false);
                 }
                 // Cancel the active subscription
                 $subscriptionsService->updateSubscriptionState($activeSubscription['subscriptionId'], SubscriptionStatus::CANCELLED);
             }
         }
         // Check if this is a gift, check that the giftee is still eligable
         if (!empty($orderSubscription['gifter']) && !$subscriptionsService->getCanUserReceiveGift($userId, $subscriptionUser['userId'])) {
             // Update the state to ERROR and log a critical error
             Application::instance()->getLogger()->critical('Duplicate subscription attempt, Gifter: %d GifteeId: %d, OrderId: %d', $userId, $subscriptionUser['userId'], $order['orderId']);
             $subscriptionsService->updateSubscriptionState($orderSubscription['subscriptionId'], SubscriptionStatus::ERROR);
         } else {
             // Unban the user if a ban is found
             $ban = $userService->getUserActiveBan($subscriptionUser['userId']);
             // only unban the user if the ban is non-permanent or the tier of the subscription is >= 2
             // we unban the user if no ban is found because it also unmutes
             if (empty($ban) or (!empty($ban['endtimestamp']) or $orderSubscription['subscriptionTier'] >= 2)) {
                 $chatIntegrationService->sendUnban($subscriptionUser['userId']);
             }
             // Activate the subscription (state)
             $subscriptionsService->updateSubscriptionState($orderSubscription['subscriptionId'], SubscriptionStatus::ACTIVE);
             // Flag the user for 'update'
             $authenticationService->flagUserForUpdate($subscriptionUser['userId']);
             // Random emote
             $randomEmote = Config::$a['chat']['customemotes'][array_rand(Config::$a['chat']['customemotes'])];
             // Broadcast
             if (!empty($orderSubscription['gifter'])) {
                 $gifter = $userService->getUserById($orderSubscription['gifter']);
                 $userName = $gifter['username'];
                 $chatIntegrationService->sendBroadcast(sprintf("%s is now a %s subscriber! gifted by %s %s", $subscriptionUser['username'], $subscriptionType['tierLabel'], $gifter['username'], $randomEmote));
             } else {
                 $userName = $subscriptionUser['username'];
                 $chatIntegrationService->sendBroadcast(sprintf("%s is now a %s subscriber! %s", $subscriptionUser['username'], $subscriptionType['tierLabel'], $randomEmote));
             }
             // Get the subscription message, and remove it from the session
             $subMessage = Session::set('subMessage');
             if (!empty($subMessage)) {
                 $chatIntegrationService->sendBroadcast(sprintf("%s: %s", $userName, $subMessage));
             }
         }
         // Redirect to completion page
         return 'redirect: /subscription/' . urlencode($order['orderId']) . '/complete';
     } catch (Exception $e) {
         if (!empty($order)) {
             $ordersService->updateOrderState($order['orderId'], OrderStatus::ERROR);
         }
         if (!empty($paymentProfile)) {
             $ordersService->updatePaymentStatus($paymentProfile['paymentId'], PaymentStatus::ERROR);
         }
         if (!empty($orderSubscription)) {
             $subscriptionsService->updateSubscriptionState($orderSubscription['subscriptionId'], SubscriptionStatus::ERROR);
         }
         $log = Application::instance()->getLogger();
         $log->error($e->getMessage(), $order);
         return 'redirect: /subscription/' . urlencode($order['orderId']) . '/error';
     }
 }
Example #14
0
<?php

use Destiny\Common\Application;
use Destiny\Common\SessionCredentials;
use Destiny\Common\SessionInstance;
use Destiny\Common\Cookie;
use Destiny\Common\Config;
use Destiny\Common\Authentication\AuthenticationService;
use Destiny\Common\Request;
ini_set('session.gc_maxlifetime', 5 * 60 * 60);
require __DIR__ . '/../lib/boot.php';
$app = Application::instance();
// Setup user session
$session = new SessionInstance();
$session->setSessionCookie(new Cookie('sid', Config::$a['cookie']));
$session->setRememberMeCookie(new Cookie('rememberme', Config::$a['cookie']));
$session->setCredentials(new SessionCredentials());
$app->setSession($session);
// Startup the authentication service, handles logged in session, remember me session
AuthenticationService::instance()->startSession();
// Attempts to find a route and execute it
$app->executeRequest(new Request());
 /**
  * @Route ("/subscription/process")
  * @Secure ({"USER"})
  *
  * We were redirected here from PayPal after the buyer approved/cancelled the payment
  *
  * @param array $params
  * @return string
  * @throws Exception
  * @throws \Destiny\Common\Utils\FilterParamsException
  * TODO clean this method up
  */
 public function subscriptionProcess(array $params)
 {
     FilterParams::required($params, 'subscriptionId');
     FilterParams::required($params, 'token');
     FilterParams::declared($params, 'success');
     $userId = Session::getCredentials()->getUserId();
     $userService = UserService::instance();
     $ordersService = OrdersService::instance();
     $subscriptionsService = SubscriptionsService::instance();
     $payPalApiService = PayPalApiService::instance();
     $chatIntegrationService = ChatIntegrationService::instance();
     $authenticationService = AuthenticationService::instance();
     $log = Application::instance()->getLogger();
     $subscription = $subscriptionsService->getSubscriptionById($params['subscriptionId']);
     if (empty($subscription) || strcasecmp($subscription['status'], SubscriptionStatus::_NEW) !== 0) {
         throw new Exception('Invalid subscription record');
     }
     try {
         $subscriptionType = $subscriptionsService->getSubscriptionType($subscription['subscriptionType']);
         $user = $userService->getUserById($subscription['userId']);
         if ($user['userId'] != $userId && $subscription['gifter'] != $userId) {
             throw new Exception('Invalid subscription');
         }
         if ($params['success'] == '0' || $params['success'] == 'false' || $params['success'] === false) {
             throw new Exception('Order request failed');
         }
         if (!$payPalApiService->retrieveCheckoutInfo($params['token'])) {
             throw new Exception('Failed to retrieve express checkout details');
         }
         FilterParams::required($params, 'PayerID');
         // if the order status is an error, the payerID is not returned
         Session::set('subscriptionId');
         Session::set('token');
         // Create the payment profile
         // Payment date is 1 day before subscription rolls over.
         if ($subscription['recurring'] == 1 || $subscription['recurring'] == true) {
             $startPaymentDate = Date::getDateTime();
             $nextPaymentDate = Date::getDateTime();
             $nextPaymentDate->modify('+' . $subscriptionType['billingFrequency'] . ' ' . strtolower($subscriptionType['billingPeriod']));
             $nextPaymentDate->modify('-1 DAY');
             $reference = $subscription['userId'] . '-' . $subscription['subscriptionId'];
             $paymentProfileId = $payPalApiService->createRecurringPaymentProfile($params['token'], $reference, $user['username'], $nextPaymentDate, $subscriptionType);
             if (empty($paymentProfileId)) {
                 throw new Exception('Invalid recurring payment profileId returned from Paypal');
             }
             $subscriptionsService->updateSubscription(array('subscriptionId' => $subscription['subscriptionId'], 'paymentStatus' => PaymentStatus::ACTIVE, 'paymentProfileId' => $paymentProfileId, 'billingStartDate' => $startPaymentDate->format('Y-m-d H:i:s'), 'billingNextDate' => $nextPaymentDate->format('Y-m-d H:i:s')));
         }
         // Record the payments as well as check if any are not in the completed state
         // we put the subscription into "PENDING" state if a payment is found not completed
         $subscriptionStatus = SubscriptionStatus::ACTIVE;
         $DoECResponse = $payPalApiService->getECPaymentResponse($params['PayerID'], $params['token'], $subscriptionType['amount']);
         $payments = $payPalApiService->getResponsePayments($DoECResponse);
         foreach ($payments as $payment) {
             $payment['subscriptionId'] = $subscription['subscriptionId'];
             $payment['payerId'] = $params['PayerID'];
             $ordersService->addPayment($payment);
             // TODO: Payment provides no way of telling if the transaction with ALL payments was successful
             if ($payment['paymentStatus'] != PaymentStatus::COMPLETED) {
                 $subscriptionStatus = SubscriptionStatus::PENDING;
             }
         }
         // Update subscription status
         $subscriptionsService->updateSubscription(array('subscriptionId' => $subscription['subscriptionId'], 'status' => $subscriptionStatus));
     } catch (Exception $e) {
         $subscriptionsService->updateSubscription(array('subscriptionId' => $subscription['subscriptionId'], 'status' => SubscriptionStatus::ERROR));
         $log->critical($e->getMessage(), $subscription);
         return 'redirect: /subscription/' . urlencode($subscription['subscriptionId']) . '/error';
     }
     // only unban the user if the ban is non-permanent or the tier of the subscription is >= 2
     // we unban the user if no ban is found because it also unmutes
     $ban = $userService->getUserActiveBan($user['userId']);
     if (empty($ban) or (!empty($ban['endtimestamp']) or $subscriptionType['tier'] >= 2)) {
         $chatIntegrationService->sendUnban($user['userId']);
     }
     // Broadcast
     $randomEmote = Config::$a['chat']['customemotes'][array_rand(Config::$a['chat']['customemotes'])];
     if (!empty($subscription['gifter'])) {
         $gifter = $userService->getUserById($subscription['gifter']);
         $userName = $gifter['username'];
         $chatIntegrationService->sendBroadcast(sprintf("%s is now a %s subscriber! gifted by %s %s", $user['username'], $subscriptionType['tierLabel'], $gifter['username'], $randomEmote));
     } else {
         $userName = $user['username'];
         $chatIntegrationService->sendBroadcast(sprintf("%s is now a %s subscriber! %s", $user['username'], $subscriptionType['tierLabel'], $randomEmote));
     }
     $subMessage = Session::set('subMessage');
     if (!empty($subMessage)) {
         $chatIntegrationService->sendBroadcast(sprintf("%s: %s", $userName, $subMessage));
     }
     // Update the user
     $authenticationService->flagUserForUpdate($user['userId']);
     // Redirect to completion page
     return 'redirect: /subscription/' . urlencode($subscription['subscriptionId']) . '/complete';
 }
Example #16
0
 /**
  * @Route ("/register")
  * @HttpMethod ({"POST"})
  * @Transactional
  *
  * Handle the confirmation request
  * @param array $params
  * @throws Exception
  */
 public function registerProcess(array $params, ViewModel $model, Request $request)
 {
     $userService = UserService::instance();
     $authService = AuthenticationService::instance();
     $authCreds = $this->getSessionAuthenticationCredentials($params);
     $username = isset($params['username']) && !empty($params['username']) ? $params['username'] : '';
     $email = isset($params['email']) && !empty($params['email']) ? $params['email'] : '';
     $country = isset($params['country']) && !empty($params['country']) ? $params['country'] : '';
     $rememberme = isset($params['rememberme']) && !empty($params['rememberme']) ? true : false;
     $authCreds->setUsername($username);
     $authCreds->setEmail($email);
     try {
         if (!isset($params['g-recaptcha-response']) || empty($params['g-recaptcha-response'])) {
             throw new Exception('You must solve the recaptcha.');
         }
         $googleRecaptchaHandler = new GoogleRecaptchaHandler();
         $googleRecaptchaHandler->resolve(Config::$a['g-recaptcha']['secret'], $params['g-recaptcha-response'], $request->ipAddress());
         $authService->validateUsername($username);
         $authService->validateEmail($email);
         if (!empty($country)) {
             $countryArr = Country::getCountryByCode($country);
             if (empty($countryArr)) {
                 throw new Exception('Invalid country');
             }
             $country = $countryArr['alpha-2'];
         }
         $user = array();
         $user['username'] = $username;
         $user['email'] = $email;
         $user['userStatus'] = 'Active';
         $user['country'] = $country;
         $user['userId'] = $userService->addUser($user);
         $userService->addUserAuthProfile(array('userId' => $user['userId'], 'authProvider' => $authCreds->getAuthProvider(), 'authId' => $authCreds->getAuthId(), 'authCode' => $authCreds->getAuthCode(), 'authDetail' => $authCreds->getAuthDetail()));
         Session::set('authSession');
         $authCredHandler = new AuthenticationRedirectionFilter();
         return $authCredHandler->execute($authCreds);
     } catch (Exception $e) {
         $model->title = 'Register Error';
         $model->username = $username;
         $model->email = $email;
         $model->follow = isset($params['follow']) ? $params['follow'] : '';
         $model->authProvider = $authCreds->getAuthProvider();
         $model->code = $authCreds->getAuthCode();
         $model->error = $e;
         return 'register';
     }
 }
Example #17
0
 /**
  * @Route ("/profile/update")
  * @HttpMethod ({"POST"})
  * @Secure ({"USER"})
  * @Transactional
  *
  * @param array $params         
  * @param ViewModel $model          
  * @throws Exception
  * @return string
  */
 public function profileSave(array $params, ViewModel $model)
 {
     // Get user
     $userService = UserService::instance();
     $userFeaturesService = UserFeaturesService::instance();
     $subscriptionsService = SubscriptionsService::instance();
     $authenticationService = AuthenticationService::instance();
     $userId = Session::getCredentials()->getUserId();
     $user = $userService->getUserById($userId);
     if (empty($user)) {
         throw new Exception('Invalid user');
     }
     $username = isset($params['username']) && !empty($params['username']) ? $params['username'] : $user['username'];
     $email = isset($params['email']) && !empty($params['email']) ? $params['email'] : $user['email'];
     $country = isset($params['country']) && !empty($params['country']) ? $params['country'] : $user['country'];
     $allowGifting = isset($params['allowGifting']) ? $params['allowGifting'] : $user['allowGifting'];
     try {
         $authenticationService->validateUsername($username, $user);
         $authenticationService->validateEmail($email, $user);
         if (!empty($country)) {
             $countryArr = Country::getCountryByCode($country);
             if (empty($countryArr)) {
                 throw new Exception('Invalid country');
             }
             $country = $countryArr['alpha-2'];
         }
     } catch (Exception $e) {
         Session::set('modelError', $e->getMessage());
         return 'redirect: /profile';
     }
     // Date for update
     $userData = array('username' => $username, 'country' => $country, 'email' => $email, 'allowGifting' => $allowGifting);
     // Is the user changing their name?
     if (strcasecmp($username, $user['username']) !== 0) {
         $nameChangeCount = intval($user['nameChangedCount']);
         // have they hit their limit
         if ($nameChangeCount >= Config::$a['profile']['nameChangeLimit']) {
             throw new Exception('You have reached your name change limit');
         } else {
             $userData['nameChangedDate'] = Date::getDateTime('NOW')->format('Y-m-d H:i:s');
             $userData['nameChangedCount'] = $nameChangeCount + 1;
         }
     }
     // Update user
     $userService->updateUser($user['userId'], $userData);
     $authenticationService->flagUserForUpdate($user['userId']);
     Session::set('modelSuccess', 'Your profile has been updated');
     return 'redirect: /profile';
 }
Example #18
0
 /**
  * @Route ("/logout")
  *
  * @param array $params         
  */
 public function logout(array $params)
 {
     AuthenticationService::instance()->logout();
     return 'redirect: /';
 }
Example #19
0
 /**
  * Handles the IPN message
  *
  * @param PPIPNMessage $ipnMessage
  */
 protected function handleIPNTransaction($txnId, $txnType, array $data)
 {
     $log = Application::instance()->getLogger();
     $orderService = OrdersService::instance();
     $subService = SubscriptionsService::instance();
     $authService = AuthenticationService::instance();
     switch (strtolower($txnType)) {
         // Post back from checkout, make sure the payment lines up
         // This is sent when a express checkout has been performed by a user
         case 'express_checkout':
             $payment = $orderService->getPaymentByTransactionId($txnId);
             if (!empty($payment)) {
                 // Make sure the payment values are the same
                 if (number_format($payment['amount'], 2) != number_format($data['mc_gross'], 2)) {
                     throw new Exception('Amount for payment do not match');
                 }
                 // Update the payment status
                 $orderService->updatePaymentStatus($payment['paymentId'], $data['payment_status']);
                 $log->notice(sprintf('Updated payment status %s status %s', $data['txn_id'], $data['payment_status']));
                 // If the payment status WAS PENDING, and the IPN payment status is COMPLETED
                 // Then we need to activate the attached subscription and complete the order
                 // This is for the ECHECK payment method
                 if (strcasecmp($payment['paymentStatus'], PaymentStatus::PENDING) === 0 && strcasecmp($data['payment_status'], PaymentStatus::COMPLETED) === 0) {
                     $order = $orderService->getOrderByPaymentId($payment['paymentId']);
                     if (!empty($order)) {
                         $orderService->updateOrderState($order['orderId'], OrderStatus::COMPLETED);
                         $log->debug(sprintf('Updated order status %s status %s', $order['orderId'], OrderStatus::COMPLETED));
                         $subscription = $subService->getUserPendingSubscription($order['userId']);
                         if (!empty($subscription)) {
                             $subService->updateSubscriptionState($subscription['subscriptionId'], SubscriptionStatus::ACTIVE);
                             $log->notice(sprintf('Updated subscription status %s status %s', $order['orderId'], SubscriptionStatus::ACTIVE));
                             $authService->flagUserForUpdate($subscription['userId']);
                         }
                     }
                 }
             } else {
                 $log->info(sprintf('Express checkout IPN called, but no payment found [%s]', $txnId));
             }
             break;
             // Recurring payment, renew subscriptions, or set to pending depending on the type
             // This is sent from paypal when a recurring payment is billed
         // Recurring payment, renew subscriptions, or set to pending depending on the type
         // This is sent from paypal when a recurring payment is billed
         case 'recurring_payment':
             if (!isset($data['payment_status'])) {
                 throw new Exception('Invalid payment status');
             }
             if (!isset($data['next_payment_date'])) {
                 throw new Exception('Invalid next_payment_date');
             }
             $paymentProfile = $this->getPaymentProfile($data);
             // We dont care about what state the sub is in....
             $subscription = $subService->getSubscriptionByOrderId($paymentProfile['orderId']);
             if (empty($subscription)) {
                 $log->critical('Invalid recurring_payment', $data);
                 throw new Exception('Invalid subscription for recurring payment');
             }
             if ($subscription['userId'] != $paymentProfile['userId'] && $subscription['gifter'] != $paymentProfile['userId']) {
                 throw new Exception(sprintf('Invalid subscription for user %s', $subscription['userId']));
             }
             $nextPaymentDate = Date::getDateTime($data['next_payment_date']);
             $orderService->updatePaymentProfileNextPayment($paymentProfile['profileId'], $nextPaymentDate);
             // Update the subscription end date regardless if the payment was successful or not
             // We dont actually know if paypal moves the automatic payment forward if one fails and is then manually processed
             $end = Date::getDateTime($subscription['endDate']);
             $end->modify('+' . $paymentProfile['billingFrequency'] . ' ' . strtolower($paymentProfile['billingPeriod']));
             // Update subscription end-date
             $subService->updateSubscriptionDateEnd($subscription['subscriptionId'], $end);
             $log->debug(sprintf('Update Subscription end date %s [%s]', $subscription['subscriptionId'], $end->format(Date::FORMAT)));
             // Change the subscription state depending on the payment state
             if (strcasecmp($data['payment_status'], PaymentStatus::PENDING) === 0) {
                 $subService->updateSubscriptionState($subscription['subscriptionId'], SubscriptionStatus::PENDING);
                 $log->debug(sprintf('Updated subscription state %s status %s', $subscription['subscriptionId'], SubscriptionStatus::PENDING));
             } else {
                 if (strcasecmp($data['payment_status'], PaymentStatus::COMPLETED) === 0) {
                     $subService->updateSubscriptionState($subscription['subscriptionId'], SubscriptionStatus::ACTIVE);
                     $log->debug(sprintf('Updated subscription %s status %s', $subscription['subscriptionId'], SubscriptionStatus::ACTIVE));
                 } else {
                     $log->notice(sprintf('Subscription status %s not changed for payment profile %s', $subscription['subscriptionId'], $paymentProfile['profileId']));
                 }
             }
             // Add a payment to the order
             $payment = array();
             $payment['orderId'] = $paymentProfile['orderId'];
             $payment['payerId'] = $data['payer_id'];
             $payment['amount'] = $data['mc_gross'];
             $payment['currency'] = $data['mc_currency'];
             $payment['transactionId'] = $txnId;
             $payment['transactionType'] = $txnType;
             $payment['paymentType'] = $data['payment_type'];
             $payment['paymentStatus'] = $data['payment_status'];
             $payment['paymentDate'] = Date::getDateTime($data['payment_date'])->format('Y-m-d H:i:s');
             $orderService->addOrderPayment($payment);
             $log->notice(sprintf('Added order payment %s status %s', $data['recurring_payment_id'], $data['profile_status']));
             $authService->flagUserForUpdate($subscription['userId']);
             break;
             // Sent if user cancels subscription from Paypal's site.
         // Sent if user cancels subscription from Paypal's site.
         case 'recurring_payment_profile_cancel':
             $paymentProfile = $this->getPaymentProfile($data);
             $orderService->updatePaymentProfileState($paymentProfile['profileId'], $data['profile_status']);
             $log->debug(sprintf('Payment profile cancelled %s status %s', $data['recurring_payment_id'], $data['profile_status']));
             break;
             // sent on first postback when the user subscribes
         // sent on first postback when the user subscribes
         case 'recurring_payment_profile_created':
             $paymentProfile = $this->getPaymentProfile($data);
             if (strcasecmp($data['profile_status'], 'Active') === 0) {
                 $data['profile_status'] = 'ActiveProfile';
             }
             $orderService->updatePaymentProfileState($paymentProfile['profileId'], $data['profile_status']);
             $log->debug(sprintf('Updated payment profile %s status %s', $data['recurring_payment_id'], $data['profile_status']));
             break;
     }
 }