/** * Returns a report with all user activity for a contest. * * @param Request $r * @return array * @throws InvalidDatabaseOperationException */ public static function apiActivityReport(Request $r) { self::validateDetails($r); if (!$r['contest_admin']) { throw new ForbiddenAccessException(); } $accesses = ContestAccessLogDAO::GetAccessForContest($r['contest']); $submissions = SubmissionLogDAO::GetSubmissionsForContest($r['contest']); // Merge both logs. $result['events'] = array(); $lenAccesses = count($accesses); $lenSubmissions = count($submissions); $iAccesses = 0; $iSubmissions = 0; while ($iAccesses < $lenAccesses && $iSubmissions < $lenSubmissions) { if ($accesses[$iAccesses]['time'] < $submissions[$iSubmissions]['time']) { array_push($result['events'], ContestController::processAccess($accesses[$iAccesses++])); } else { array_push($result['events'], ContestController::processSubmission($submissions[$iSubmissions++])); } } while ($iAccesses < $lenAccesses) { array_push($result['events'], ContestController::processAccess($accesses[$iAccesses++])); } while ($iSubmissions < $lenSubmissions) { array_push($result['events'], ContestController::processSubmission($submissions[$iSubmissions++])); } // Anonimize data. $ipMapping = array(); foreach ($result['events'] as &$entry) { if (!array_key_exists($entry['ip'], $ipMapping)) { $ipMapping[$entry['ip']] = count($ipMapping); } $entry['ip'] = $ipMapping[$entry['ip']]; } $result['status'] = 'ok'; return $result; }
/** * Tests that user can get contest details with the scoreboard token */ public function testDetailsUsingToken() { // Get a private contest $contestData = ContestsFactory::createContest(null, 0); // Create our user not added to the contest $externalUser = UserFactory::createUser(); $originalContestAccessLog = ContestAccessLogDAO::getAll(); // Get the scoreboard url by using the MyList api being the // contest director $response = ContestController::apiMyList(new Request(array('auth_token' => $this->login($contestData['director'])))); // Look for our contest from the list and save the scoreboard tokens $scoreboard_url = null; $scoreboard_admin_url = null; foreach ($response['results'] as $c) { if ($c['alias'] === $contestData['request']['alias']) { $scoreboard_url = $c['scoreboard_url']; $scoreboard_admin_url = $c['scoreboard_url_admin']; break; } } $this->assertNotNull($scoreboard_url); $this->assertNotNull($scoreboard_admin_url); // Call details using token $detailsResponse = ContestController::apiDetails(new Request(array('auth_token' => $this->login($externalUser), 'contest_alias' => $contestData['request']['alias'], 'token' => $scoreboard_url))); $this->assertContestDetails($contestData, array(), $detailsResponse); // Call details using admin token $detailsResponse = ContestController::apiDetails(new Request(array('auth_token' => $this->login($externalUser), 'contest_alias' => $contestData['request']['alias'], 'token' => $scoreboard_admin_url))); $this->assertContestDetails($contestData, array(), $detailsResponse); // All requests were done using tokens, so the log must be identical. $contestAccessLog = ContestAccessLogDAO::getAll(); $this->assertEquals($originalContestAccessLog, $contestAccessLog); }