/** * @param array $params * @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'); } $credentials = new SessionCredentials($user); $credentials->setAuthProvider('API'); $credentials->addRoles(UserRole::USER); $credentials->addFeatures(UserFeaturesService::instance()->getUserFeatures($authToken['userId'])); $credentials->addRoles(UserService::instance()->getUserRolesByUserId($authToken['userId'])); $subscription = SubscriptionsService::instance()->getUserActiveSubscription($authToken['userId']); if (!empty($subscription)) { $credentials->addRoles(UserRole::SUBSCRIBER); $credentials->addFeatures(UserFeature::SUBSCRIBER); if ($subscription['subscriptionTier'] == 2) { $credentials->addFeatures(UserFeature::SUBSCRIBERT2); } if ($subscription['subscriptionTier'] == 3) { $credentials->addFeatures(UserFeature::SUBSCRIBERT3); } } $response = new Response(Http::STATUS_OK, json_encode($credentials->getData())); $response->addHeader(Http::HEADER_CONTENTTYPE, MimeType::JSON); return $response; }
/** * @param SessionCredentials $credentials */ public function refreshChatUserSession(SessionCredentials $credentials) { $redis = Application::instance()->getRedis(); $json = json_encode($credentials->getData()); $redis->setOption(\Redis::OPT_SERIALIZER, \Redis::SERIALIZER_NONE); $redis->publish(sprintf('refreshuser-%s', Config::$a['redis']['database']), $json); $redis->setOption(\Redis::OPT_SERIALIZER, \Redis::SERIALIZER_PHP); }
/** * Updates the session variables * * @param SessionCredentials $credentials */ public static function updateCredentials(SessionCredentials $credentials) { $session = self::instance(); $params = $credentials->getData(); foreach ($params as $name => $value) { $session->set($name, $value); } $session->setCredentials($credentials); }
/** * Check if a user is allowed to send a message based on various criteria * * @param \Destiny\Common\SessionCredentials $user * @param int $targetuserid * @return boolean */ public function canSend($user, $targetuserid) { if ($user->hasRole(UserRole::ADMIN)) { return true; } $userid = $user->getUserId(); $conn = Application::instance()->getConnection(); $stmt = $conn->prepare("\n SELECT\n userid,\n targetuserid,\n isread,\n UNIX_TIMESTAMP(timestamp) AS timestamp\n FROM privatemessages\n WHERE\n (\n userid = :userid OR\n targetuserid = :userid\n ) AND\n DATE_SUB(NOW(), INTERVAL 1 HOUR) < timestamp\n ORDER BY id ASC\n "); $stmt->bindValue('userid', $userid, \PDO::PARAM_INT); $stmt->execute(); $now = time(); $cansend = true; $timelimit = 60 * 60 * 1; $messagelimit = 3; $general_unread_count = 0; $target_unread_count = 0; while ($row = $stmt->fetch()) { if ($row['userid'] == $userid && !$row['isread']) { // $userid sent a message that was NOT read $general_unread_count += 1; // immediatly throttle if sent more than $messagelimit unread // messages to the same $targetuserid in the last $timelimit minutes // ONLY a reply can cancel this, otherwise it would `return false` if ($row['targetuserid'] != $targetuserid) { continue; } $target_unread_count += 1; if ($target_unread_count > $messagelimit && $now - $row['timestamp'] < $timelimit) { $cansend = false; } } else { if ($row['userid'] == $targetuserid) { $target_unread_count -= $messagelimit; $general_unread_count -= $messagelimit; $cansend = true; // avoid rate limiting quick replies // received a message in the last $timelimit minutes, reset if ($now - $row['timestamp'] < $timelimit) { return true; } } else { // $userid sent a message that was read OR // $userid recieved a message from someone unrelated to this conversation $general_unread_count -= 2; } } } // sent message count outweighs the received message count, deny // considering this is the last hour, and most people don't mark as read if ($target_unread_count > 7 || $general_unread_count > 21) { $cansend = false; } return $cansend; }
/** * @Route ("/api/messages/send") * @HttpMethod ({"POST"}) * * Expects the following GET|POST variables: * privatekey=XXXXXXXX * message=string * userid=999 * targetuserid=999 * * @param array $params * @return Response */ public function sendMessage(array $params) { $privateMessageService = PrivateMessageService::instance(); $chatIntegrationService = ChatIntegrationService::instance(); $userService = UserService::instance(); $response = array(); try { FilterParams::required($params, 'privatekey'); FilterParams::required($params, 'message'); FilterParams::required($params, 'userid'); FilterParams::required($params, 'targetuserid'); if (!$this->checkPrivateKey($params['privatekey'])) { throw new Exception('Invalid shared private key.'); } if ($params['userid'] == $params['targetuserid']) { throw new Exception('Cannot send messages to yourself.'); } $ban = $userService->getUserActiveBan($params['userid']); if (!empty($ban)) { throw new Exception("privmsgbanned"); } $oldEnough = $userService->isUserOldEnough($params['userid']); if (!$oldEnough) { throw new Exception("privmsgaccounttooyoung"); } $user = $userService->getUserById($params['userid']); $credentials = new SessionCredentials($user); $credentials->addRoles($userService->getUserRolesByUserId($params['userid'])); $targetuser = $userService->getUserById($params['targetuserid']); if (empty($targetuser)) { throw new Exception('notfound'); } $canSend = $privateMessageService->canSend($credentials, $params['targetuserid']); if (!$canSend) { throw new Exception("throttled"); } if (empty($user)) { throw new Exception('notfound'); } $message = array('userid' => $params['userid'], 'targetuserid' => $params['targetuserid'], 'message' => $params['message'], 'isread' => 0); $message['id'] = $privateMessageService->addMessage($message); $chatIntegrationService->publishPrivateMessage(array('messageid' => $message['id'], 'message' => $message['message'], 'username' => $user['username'], 'userid' => $user['userId'], 'targetusername' => $targetuser['username'], 'targetuserid' => $targetuser['userId'])); $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; }
/** * @param array $user * @param string $authProvider * @return SessionCredentials */ public function getUserCredentials(array $user, $authProvider) { $credentials = new SessionCredentials($user); $credentials->setAuthProvider($authProvider); $credentials->addRoles(UserRole::USER); $credentials->addFeatures(UserFeaturesService::instance()->getUserFeatures($user['userId'])); $credentials->addRoles(UserService::instance()->getUserRolesByUserId($user['userId'])); $subscription = SubscriptionsService::instance()->getUserActiveSubscription($user['userId']); if (!empty($subscription) or $user['istwitchsubscriber']) { $credentials->addRoles(UserRole::SUBSCRIBER); $credentials->addFeatures(UserFeature::SUBSCRIBER); if ($user['istwitchsubscriber']) { $credentials->addFeatures(UserFeature::SUBSCRIBERT0); } } if (!empty($subscription)) { if ($subscription['subscriptionTier'] == 2) { $credentials->addFeatures(UserFeature::SUBSCRIBERT2); } if ($subscription['subscriptionTier'] == 3) { $credentials->addFeatures(UserFeature::SUBSCRIBERT3); } if ($subscription['subscriptionTier'] == 4) { $credentials->addFeatures(UserFeature::SUBSCRIBERT4); } } return $credentials; }
/** * Check if the security credentials have the correct values for the route * @param Route $route * @param Route $credentials * @return boolean */ private function hasRouteSecurity(Route $route, SessionCredentials $credentials) { // Check the route security against the user roles and features $secure = $route->getSecure(); if (!empty($secure)) { foreach ($secure as $role) { if (!$credentials->hasRole($role)) { return false; } } } $features = $route->getFeature(); if (!empty($features)) { foreach ($features as $feature) { if (!$credentials->hasFeature($feature)) { return false; } } } return true; }