/** * Validates that group alias and contest alias do exist * * @param Request $r * @throws InvalidDatabaseOperationException * @throws InvalidParameterException */ private static function validateGroupScoreboardAndContest(Request $r) { self::validateGroupScoreboard($r); Validators::isValidAlias($r["contest_alias"], "contest_alias"); try { $r["contest"] = ContestsDAO::getByAlias($r["contest_alias"]); } catch (Exception $ex) { throw new InvalidDatabaseOperationException($ex); } if (is_null($r["contest"])) { throw new InvalidParameterException("parameterNotFound", "Contest"); } if ($r["contest"]->public == 0 && !Authorization::IsContestAdmin($r["current_user_id"], $r["contest"])) { throw new ForbiddenAccessException(); } }
public static function CanEditClarification($user_id, Clarifications $clarification) { if (is_null($clarification) || !is_a($clarification, 'Clarifications')) { return false; } try { $contest = ContestsDAO::getByPK($clarification->getContestId()); $problem = ProblemsDAO::getByPK($clarification->getProblemId()); } catch (Exception $e) { throw new InvalidDatabaseOperationException($e); } if (is_null($contest) || is_null($problem)) { return false; } return $problem->getAuthorId() === $user_id || Authorization::IsContestAdmin($user_id, $contest); }
/** * Tests remove admins */ public function testRemoveAdmin() { // Get a contest $contestData = ContestsFactory::createContest(); // Get users $user = UserFactory::createUser(); $user2 = UserFactory::createUser(); ContestsFactory::addAdminUser($contestData, $user); ContestsFactory::addAdminUser($contestData, $user2); // Prepare request for remove one admin $r = new Request(); $r["auth_token"] = $this->login($contestData["director"]); $r["usernameOrEmail"] = $user->getUsername(); $r["contest_alias"] = $contestData["request"]["alias"]; // Call api ContestController::apiRemoveAdmin($r); $contest = ContestsDAO::getByAlias($contestData['request']['alias']); $this->AssertFalse(Authorization::IsContestAdmin($user->getUserId(), $contest)); $this->AssertTrue(Authorization::IsContestAdmin($user2->getUserId(), $contest)); }
/** * Create a new run * * @param Request $r * @return array * @throws Exception * @throws InvalidDatabaseOperationException * @throws InvalidFilesystemOperationException */ public static function apiCreate(Request $r) { // Init self::initializeGrader(); // Authenticate user self::authenticateRequest($r); // Validate request self::validateCreateRequest($r); self::$log->info('New run being submitted!!'); $response = array(); if (self::$practice) { if (OMEGAUP_LOCKDOWN) { throw new ForbiddenAccessException('lockdown'); } $submit_delay = 0; $contest_id = null; $test = 0; } else { //check the kind of penalty_type for this contest $penalty_type = $r['contest']->penalty_type; switch ($penalty_type) { case 'contest_start': // submit_delay is calculated from the start // of the contest $start = $r['contest']->getStartTime(); break; case 'problem_open': // submit delay is calculated from the // time the user opened the problem $opened = ContestProblemOpenedDAO::getByPK($r['contest']->getContestId(), $r['problem']->getProblemId(), $r['current_user_id']); if (is_null($opened)) { //holy moly, he is submitting a run //and he hasnt even opened the problem //what should be done here? throw new NotAllowedToSubmitException('runEvenOpened'); } $start = $opened->getOpenTime(); break; case 'none': case 'runtime': //we dont care $start = null; break; default: self::$log->error('penalty_type for this contests is not a valid option, asuming `none`.'); $start = null; } if (!is_null($start)) { //ok, what time is it now? $c_time = time(); $start = strtotime($start); //asuming submit_delay is in minutes $submit_delay = (int) (($c_time - $start) / 60); } else { $submit_delay = 0; } $contest_id = $r['contest']->getContestId(); $test = Authorization::IsContestAdmin($r['current_user_id'], $r['contest']) ? 1 : 0; } // Populate new run object $run = new Runs(array('user_id' => $r['current_user_id'], 'problem_id' => $r['problem']->getProblemId(), 'contest_id' => $contest_id, 'language' => $r['language'], 'source' => $r['source'], 'status' => 'new', 'runtime' => 0, 'penalty' => $submit_delay, 'memory' => 0, 'score' => 0, 'contest_score' => $contest_id != null ? 0 : null, 'submit_delay' => $submit_delay, 'guid' => md5(uniqid(rand(), true)), 'verdict' => 'JE', 'test' => $test)); try { // Push run into DB RunsDAO::save($run); SubmissionLogDAO::save(new SubmissionLog(array('user_id' => $run->user_id, 'run_id' => $run->run_id, 'contest_id' => $run->contest_id, 'ip' => ip2long($_SERVER['REMOTE_ADDR'])))); // Update submissions counter++ $r['problem']->setSubmissions($r['problem']->getSubmissions() + 1); ProblemsDAO::save($r['problem']); } catch (Exception $e) { // Operation failed in the data layer throw new InvalidDatabaseOperationException($e); } try { // Create file for the run $filepath = RunController::getSubmissionPath($run); FileHandler::CreateFile($filepath, $r['source']); } catch (Exception $e) { throw new InvalidFilesystemOperationException($e); } // Call Grader try { self::$grader->Grade([$run->guid], false, false); } catch (Exception $e) { self::$log->error('Call to Grader::grade() failed:'); self::$log->error($e); } if (self::$practice) { $response['submission_deadline'] = 0; } else { // Add remaining time to the response try { $contest_user = ContestsUsersDAO::getByPK($r['current_user_id'], $r['contest']->getContestId()); if ($r['contest']->getWindowLength() === null) { $response['submission_deadline'] = strtotime($r['contest']->getFinishTime()); } else { $response['submission_deadline'] = min(strtotime($r['contest']->getFinishTime()), strtotime($contest_user->getAccessTime()) + $r['contest']->getWindowLength() * 60); } } catch (Exception $e) { // Operation failed in the data layer throw new InvalidDatabaseOperationException($e); } } // Happy ending $response['guid'] = $run->getGuid(); $response['status'] = 'ok'; // Expire rank cache UserController::deleteProblemsSolvedRankCacheList(); return $response; }
/** * Validates that request contains contest_alias and the api is contest-admin only * * @param Request $r * @throws InvalidDatabaseOperationException * @throws ForbiddenAccessException */ private static function validateStats(Request $r) { Validators::isStringNonEmpty($r["contest_alias"], "contest_alias"); try { $r["contest"] = ContestsDAO::getByAlias($r["contest_alias"]); } catch (Exception $e) { // Operation failed in the data layer throw new InvalidDatabaseOperationException($e); } // This API is Contest Admin only if (is_null($r["contest"]) || !Authorization::IsContestAdmin($r["current_user_id"], $r["contest"])) { throw new ForbiddenAccessException("userNotAllowed"); } }
/** * Validate problem Details API * * @param Request $r * @throws ApiException * @throws InvalidDatabaseOperationException * @throws NotFoundException * @throws ForbiddenAccessException */ private static function validateDetails(Request $r) { Validators::isStringNonEmpty($r['contest_alias'], 'contest_alias', false); Validators::isStringNonEmpty($r['problem_alias'], 'problem_alias'); // Lang is optional. Default is user's preferred. if (!is_null($r['lang'])) { Validators::isStringOfMaxLength($r['lang'], 'lang', 2); } else { $r['lang'] = UserController::getPreferredLanguage($r); } try { $r['problem'] = ProblemsDAO::getByAlias($r['problem_alias']); } catch (Exception $e) { throw new InvalidDatabaseOperationException($e); } if (is_null($r['problem'])) { throw new NotFoundException('problemNotFound'); } if (isset($r['statement_type']) && !in_array($r['statement_type'], array('html', 'markdown'))) { throw new NotFoundException('invalidStatementType'); } // If we request a problem inside a contest if (!is_null($r['contest_alias'])) { // Is the combination contest_id and problem_id valid? try { $r['contest'] = ContestsDAO::getByAlias($r['contest_alias']); if (is_null($r['contest'])) { throw new NotFoundException('contestNotFound'); } if (is_null(ContestProblemsDAO::getByPK($r['contest']->getContestId(), $r['problem']->getProblemId()))) { throw new NotFoundException('problemNotFoundInContest'); } } catch (ApiException $apiException) { throw $apiException; } catch (Exception $e) { throw new InvalidDatabaseOperationException($e); } // If the contest is private, verify that our user is invited $contest_admin = Authorization::IsContestAdmin($r['current_user_id'], $r['contest']); if ($r['contest']->public != '1') { if (is_null(ContestsUsersDAO::getByPK($r['current_user_id'], $r['contest']->contest_id)) && !$contest_admin) { throw new ForbiddenAccessException(); } } // If the contest has not started, user should not see it, unless // it is admin if (!ContestsDAO::hasStarted($r['contest']) && !$contest_admin) { throw new ForbiddenAccessException('contestNotStarted'); } } else { if (!Authorization::CanEditProblem($r['current_user_id'], $r['problem'])) { // If the problem is requested outside a contest, we need to // check that it is not private if ($r['problem']->public != '1') { throw new ForbiddenAccessException('problemIsPrivate'); } } } }
/** * Tests remove group admins */ public function testRemoveGroupAdmin() { // Get a contest $contestData = ContestsFactory::createContest(); // Get users $user = UserFactory::createUser(); $user2 = UserFactory::createUser(); // Get a group $groupData = GroupsFactory::createGroup(); GroupsFactory::addUserToGroup($groupData, $user); GroupsFactory::addUserToGroup($groupData, $user2); // Prepare request $r = new Request(); $r['auth_token'] = $this->login($contestData['director']); $r['group'] = $groupData['request']['alias']; $r['contest_alias'] = $contestData['request']['alias']; // Call api ContestController::apiAddGroupAdmin($r); $contest = $contestData['contest']; $this->AssertTrue(Authorization::IsContestAdmin($user->getUserId(), $contest)); $this->AssertTrue(Authorization::IsContestAdmin($user2->getUserId(), $contest)); // Prepare request for remove the group $r = new Request(); $r['auth_token'] = $this->login($contestData['director']); $r['group'] = $groupData['request']['alias']; $r['contest_alias'] = $contestData['request']['alias']; // Call api ContestController::apiRemoveGroupAdmin($r); $this->AssertFalse(Authorization::IsContestAdmin($user->getUserId(), $contest)); $this->AssertFalse(Authorization::IsContestAdmin($user2->getUserId(), $contest)); }
/** * Validate problem Details API * * @param Request $r * @throws ApiException * @throws InvalidDatabaseOperationException * @throws NotFoundException * @throws ForbiddenAccessException */ private static function validateDetails(Request $r) { Validators::isStringNonEmpty($r["contest_alias"], "contest_alias", false); Validators::isStringNonEmpty($r["problem_alias"], "problem_alias"); // Lang is optional. Default is user's preferred. if (!is_null($r["lang"])) { Validators::isStringOfMaxLength($r["lang"], "lang", 2); } else { $r['lang'] = UserController::getPreferredLanguage($r); } try { $r["problem"] = ProblemsDAO::getByAlias($r["problem_alias"]); } catch (Exception $e) { throw new InvalidDatabaseOperationException($e); } if (is_null($r["problem"])) { throw new NotFoundException("problemNotFound"); } if (isset($r["statement_type"]) && !in_array($r["statement_type"], array("html", "markdown"))) { throw new NotFoundException("invalidStatementType"); } // If we request a problem inside a contest if (!is_null($r["contest_alias"])) { // Is the combination contest_id and problem_id valid? try { $r["contest"] = ContestsDAO::getByAlias($r["contest_alias"]); if (is_null($r["contest"])) { throw new NotFoundException("contestNotFound"); } if (is_null(ContestProblemsDAO::getByPK($r["contest"]->getContestId(), $r["problem"]->getProblemId()))) { throw new NotFoundException("problemNotFoundInContest"); } } catch (ApiException $apiException) { throw $apiException; } catch (Exception $e) { throw new InvalidDatabaseOperationException($e); } // If the contest is private, verify that our user is invited if ($r["contest"]->getPublic() === 0) { if (is_null(ContestsUsersDAO::getByPK($r["current_user_id"], $r["contest"]->getContestId())) && !Authorization::IsContestAdmin($r["current_user_id"], $r["contest"])) { throw new ForbiddenAccessException(); } } // If the contest has not started, user should not see it, unless it is admin if (!ContestsDAO::hasStarted($r["contest"]) && !Authorization::IsContestAdmin($r["current_user_id"], $r["contest"])) { throw new ForbiddenAccessException("contestNotStarted"); } } else { if (!Authorization::CanEditProblem($r["current_user_id"], $r["problem"])) { // If the problem is requested outside a contest, we need to check that it is not private if ($r["problem"]->getPublic() == "0") { throw new ForbiddenAccessException("problemIsPrivate"); } } } }