/** * Validates a Create or Update Problem API request * * @param Request $r * @throws NotFoundException */ private static function validateCreateOrUpdate(Request $r, $is_update = false) { $is_required = true; // https://github.com/omegaup/omegaup/issues/739 if ($r['current_user']->username == 'omi') { throw new ForbiddenAccessException(); } // In case of update, params are optional if ($is_update) { $is_required = false; // We need to check problem_alias Validators::isStringNonEmpty($r['problem_alias'], 'problem_alias'); try { $r['problem'] = ProblemsDAO::getByAlias($r['problem_alias']); } catch (Exception $e) { throw new InvalidDatabaseOperationException($e); } if (is_null($r['problem'])) { throw new NotFoundException('Problem not found'); } // We need to check that the user can actually edit the problem if (!Authorization::CanEditProblem($r['current_user_id'], $r['problem'])) { throw new ForbiddenAccessException(); } if ($r['problem']->deprecated) { throw new PreconditionFailedException('problemDeprecated'); } } else { Validators::isValidAlias($r['alias'], 'alias'); } Validators::isStringNonEmpty($r['title'], 'title', $is_required); Validators::isStringNonEmpty($r['source'], 'source', $is_required); Validators::isInEnum($r['public'], 'public', array('0', '1'), $is_required); Validators::isInEnum($r['validator'], 'validator', array('token', 'token-caseless', 'token-numeric', 'custom', 'literal'), $is_required); Validators::isNumberInRange($r['time_limit'], 'time_limit', 0, INF, $is_required); Validators::isNumberInRange($r['validator_time_limit'], 'validator_time_limit', 0, INF, $is_required); Validators::isNumberInRange($r['overall_wall_time_limit'], 'overall_wall_time_limit', 0, 60000, $is_required); Validators::isNumberInRange($r['extra_wall_time'], 'extra_wall_time', 0, 5000, $is_required); Validators::isNumberInRange($r['memory_limit'], 'memory_limit', 0, INF, $is_required); Validators::isNumberInRange($r['output_limit'], 'output_limit', 0, INF, $is_required); // HACK! I don't know why "languages" doesn't make it into $r, and I've spent far too much time // on it already, so I'll just leave this here for now... if (!isset($r['languages']) && isset($_REQUEST['languages'])) { $r['languages'] = implode(',', $_REQUEST['languages']); } elseif (isset($r['languages']) && is_array($r['languages'])) { $r['languages'] = implode(',', $r['languages']); } Validators::isValidSubset($r['languages'], 'languages', array('c', 'cpp', 'java', 'py', 'rb', 'pl', 'cs', 'pas', 'kp', 'kj', 'cat', 'hs', 'cpp11'), $is_required); }
/** * 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(); } }
/** * Validates a Create or Update Problem API request * * @param Request $r * @throws NotFoundException */ private static function validateCreateOrUpdate(Request $r, $is_update = false) { $is_required = true; // In case of update, params are optional if ($is_update) { $is_required = false; // We need to check problem_alias Validators::isStringNonEmpty($r["problem_alias"], "problem_alias"); try { $r["problem"] = ProblemsDAO::getByAlias($r["problem_alias"]); } catch (Exception $e) { throw new InvalidDatabaseOperationException($e); } if (is_null($r["problem"])) { throw new NotFoundException("Problem not found"); } // We need to check that the user can actually edit the problem if (!Authorization::CanEditProblem($r["current_user_id"], $r["problem"])) { throw new ForbiddenAccessException(); } if ($r['problem']->deprecated) { throw new PreconditionFailedException('problemDeprecated'); } } else { Validators::isValidAlias($r['alias'], 'alias'); } Validators::isStringNonEmpty($r["title"], "title", $is_required); Validators::isStringNonEmpty($r["source"], "source", $is_required); Validators::isInEnum($r["public"], "public", array("0", "1"), $is_required); Validators::isInEnum($r["validator"], "validator", array("token", "token-caseless", "token-numeric", "custom", "literal"), $is_required); Validators::isNumberInRange($r["time_limit"], "time_limit", 0, INF, $is_required); Validators::isNumberInRange($r["validator_time_limit"], "validator_time_limit", 0, INF, $is_required); Validators::isNumberInRange($r["overall_wall_time_limit"], "overall_wall_time_limit", 0, 60000, $is_required); Validators::isNumberInRange($r["extra_wall_time"], "extra_wall_time", 0, 5000, $is_required); Validators::isNumberInRange($r["memory_limit"], "memory_limit", 0, INF, $is_required); Validators::isNumberInRange($r["output_limit"], "output_limit", 0, INF, $is_required); // HACK! I don't know why "languages" doesn't make it into $r, and I've spent far too much time // on it already, so I'll just leave this here for now... if (!isset($r["languages"]) && isset($_REQUEST["languages"])) { $r["languages"] = implode(",", $_REQUEST["languages"]); } else { if (isset($r["languages"]) && is_array($r["languages"])) { $r["languages"] = implode(",", $r["languages"]); } } Validators::isValidSubset($r["languages"], "languages", array('c', 'cpp', 'java', 'py', 'rb', 'pl', 'cs', 'pas', 'kp', 'kj', 'cat', 'hs', 'cpp11'), $is_required); }
/** * Validates that Request contains expected data to create or update a contest * In case of update, everything is optional except the contest_alias * In case of error, this function throws. * * @param Request $r * @throws InvalidParameterException */ private static function validateCreateOrUpdate(Request $r, $is_update = false) { // Is the parameter required? $is_required = true; if ($is_update === true) { // In case of Update API, required parameters for Create API are not required $is_required = false; try { $r["contest"] = ContestsDAO::getByAlias($r["contest_alias"]); } catch (Exception $e) { throw new InvalidDatabaseOperationException($e); } if (is_null($r["contest_alias"])) { throw new NotFoundException("contestNotFound"); } if (!Authorization::IsContestAdmin($r["current_user_id"], $r["contest"])) { throw new ForbiddenAccessException(); } } Validators::isStringNonEmpty($r["title"], "title", $is_required); Validators::isStringNonEmpty($r["description"], "description", $is_required); Validators::isNumber($r["start_time"], "start_time", $is_required); Validators::isNumber($r["finish_time"], "finish_time", $is_required); // Get the actual start and finish time of the contest, considering that // in case of update, parameters can be optional $start_time = !is_null($r["start_time"]) ? $r["start_time"] : $r["contest"]->getStartTime(); $finish_time = !is_null($r["finish_time"]) ? $r["finish_time"] : $r["contest"]->getFinishTime(); // Validate start & finish time if ($start_time > $finish_time) { throw new InvalidParameterException("contestNewInvalidStartTime"); } // Calculate the actual contest length $contest_length = $finish_time - $start_time; // Window_length is optional if (!is_null($r["window_length"]) && $r["window_length"] !== "NULL") { Validators::isNumberInRange($r["window_length"], "window_length", 0, floor($contest_length) / 60, false); } Validators::isInEnum($r["public"], "public", array("0", "1"), $is_required); Validators::isValidAlias($r["alias"], "alias", $is_required); Validators::isNumberInRange($r["scoreboard"], "scoreboard", 0, 100, $is_required); Validators::isNumberInRange($r["points_decay_factor"], "points_decay_factor", 0, 1, $is_required); Validators::isInEnum($r["partial_score"], "partial_score", array("0", "1"), false); Validators::isNumberInRange($r["submissions_gap"], "submissions_gap", 0, $contest_length, $is_required); Validators::isInEnum($r["feedback"], "feedback", array("no", "yes", "partial"), $is_required); Validators::isInEnum($r["penalty_type"], "penalty_type", array("contest_start", "problem_open", "runtime", "none"), $is_required); Validators::isInEnum($r["penalty_calc_policy"], "penalty_calc_policy", array("sum", "max"), false); // Check that the users passed through the private_users parameter are valid if (!is_null($r["public"]) && $r["public"] != 1 && !is_null($r["private_users"])) { // Validate that the request is well-formed $r["private_users_list"] = json_decode($r["private_users"]); if (is_null($r["private_users_list"])) { throw new InvalidParameterException("parameterInvalid", "private_users"); } // Validate that all users exists in the DB foreach ($r["private_users_list"] as $userkey) { if (is_null(UsersDAO::getByPK($userkey))) { throw new InvalidParameterException("parameterNotFound", "private_users"); } } // Turn on flag to add private users later $r["hasPrivateUsers"] = true; } // Problems is optional if (!is_null($r['problems'])) { $r["problems"] = array(); foreach (json_decode($r['problems']) as $problem) { $p = ProblemsDAO::getByAlias($problem->problem); array_push($r["problems"], array('id' => $p->getProblemId(), 'alias' => $problem->problem, 'points' => $problem->points)); } } // Show scoreboard is always optional Validators::isInEnum($r["show_scoreboard_after"], "show_scoreboard_after", array("0", "1"), false); }
/** * Validates that Request contains expected data to create or update a contest * In case of update, everything is optional except the contest_alias * In case of error, this function throws. * * @param Request $r * @throws InvalidParameterException */ private static function validateCreateOrUpdate(Request $r, $is_update = false) { // Is the parameter required? $is_required = true; if ($is_update === true) { // In case of Update API, required parameters for Create API are not required $is_required = false; try { $r['contest'] = ContestsDAO::getByAlias($r['contest_alias']); } catch (Exception $e) { throw new InvalidDatabaseOperationException($e); } if (is_null($r['contest_alias'])) { throw new NotFoundException('contestNotFound'); } if (!Authorization::IsContestAdmin($r['current_user_id'], $r['contest'])) { throw new ForbiddenAccessException(); } } Validators::isStringNonEmpty($r['title'], 'title', $is_required); Validators::isStringNonEmpty($r['description'], 'description', $is_required); Validators::isNumber($r['start_time'], 'start_time', $is_required); Validators::isNumber($r['finish_time'], 'finish_time', $is_required); // Get the actual start and finish time of the contest, considering that // in case of update, parameters can be optional $start_time = !is_null($r['start_time']) ? $r['start_time'] : $r['contest']->getStartTime(); $finish_time = !is_null($r['finish_time']) ? $r['finish_time'] : $r['contest']->getFinishTime(); // Validate start & finish time if ($start_time > $finish_time) { throw new InvalidParameterException('contestNewInvalidStartTime'); } // Calculate the actual contest length $contest_length = $finish_time - $start_time; // Window_length is optional if (!is_null($r['window_length']) && $r['window_length'] !== 'NULL') { Validators::isNumberInRange($r['window_length'], 'window_length', 0, floor($contest_length) / 60, false); } Validators::isInEnum($r['public'], 'public', array('0', '1'), $is_required); Validators::isValidAlias($r['alias'], 'alias', $is_required); Validators::isNumberInRange($r['scoreboard'], 'scoreboard', 0, 100, $is_required); Validators::isNumberInRange($r['points_decay_factor'], 'points_decay_factor', 0, 1, $is_required); Validators::isInEnum($r['partial_score'], 'partial_score', array('0', '1'), false); Validators::isNumberInRange($r['submissions_gap'], 'submissions_gap', 0, $contest_length, $is_required); Validators::isInEnum($r['feedback'], 'feedback', array('no', 'yes', 'partial'), $is_required); Validators::isInEnum($r['penalty_type'], 'penalty_type', array('contest_start', 'problem_open', 'runtime', 'none'), $is_required); Validators::isInEnum($r['penalty_calc_policy'], 'penalty_calc_policy', array('sum', 'max'), false); // Check that the users passed through the private_users parameter are valid if (!is_null($r['public']) && $r['public'] != 1 && !is_null($r['private_users'])) { // Validate that the request is well-formed $r['private_users_list'] = json_decode($r['private_users']); if (is_null($r['private_users_list'])) { throw new InvalidParameterException('parameterInvalid', 'private_users'); } // Validate that all users exists in the DB foreach ($r['private_users_list'] as $userkey) { if (is_null(UsersDAO::getByPK($userkey))) { throw new InvalidParameterException('parameterNotFound', 'private_users'); } } // Turn on flag to add private users later $r['hasPrivateUsers'] = true; } // Problems is optional if (!is_null($r['problems'])) { $r['problems'] = array(); foreach (json_decode($r['problems']) as $problem) { $p = ProblemsDAO::getByAlias($problem->problem); array_push($r['problems'], array('id' => $p->getProblemId(), 'alias' => $problem->problem, 'points' => $problem->points)); } } // Show scoreboard is always optional Validators::isInEnum($r['show_scoreboard_after'], 'show_scoreboard_after', array('0', '1'), false); }
/** * Create a scoreboard set to a group * * @param Request $r */ public static function apiCreateScoreboard(Request $r) { self::validateGroup($r); Validators::isValidAlias($r["alias"], "alias", true); Validators::isStringNonEmpty($r["name"], "name", true); Validators::isStringNonEmpty($r["description"], "description", false); try { $groupScoreboard = new GroupsScoreboards(array("group_id" => $r["group"]->group_id, "name" => $r["name"], "description" => $r["description"], "alias" => $r["alias"], "create_time" => gmdate('Y-m-d H:i:s', time()))); GroupsScoreboardsDAO::save($groupScoreboard); self::$log->info("New scoreboard created " . $r["alias"]); } catch (Exception $ex) { throw new InvalidDatabaseOperationException($ex); } return array("status" => "ok"); }
/** * Create a scoreboard set to a group * * @param Request $r */ public static function apiCreateScoreboard(Request $r) { self::validateGroup($r); Validators::isValidAlias($r['alias'], 'alias', true); Validators::isStringNonEmpty($r['name'], 'name', true); Validators::isStringNonEmpty($r['description'], 'description', false); try { $groupScoreboard = new GroupsScoreboards(array('group_id' => $r['group']->group_id, 'name' => $r['name'], 'description' => $r['description'], 'alias' => $r['alias'], 'create_time' => gmdate('Y-m-d H:i:s', time()))); GroupsScoreboardsDAO::save($groupScoreboard); self::$log->info('New scoreboard created ' . $r['alias']); } catch (Exception $ex) { throw new InvalidDatabaseOperationException($ex); } return array('status' => 'ok'); }