public function testEditProblem() { // Login $author = $this->createUserAndLogin(); // Create a problem $problemData = ProblemsFactory::createProblem(null, null, 1, $author); // Open problem create $this->open('/problemedit.php'); sleep(1); $this->type('name=edit-problem-list', $problemData["request"]["alias"]); $this->waitForValue('name=title', $problemData["request"]["title"]); $problemNewData = ProblemsFactory::getRequest(); $this->type('name=title', $problemNewData["request"]["title"]); $this->type('source', $problemNewData["request"]["source"]); $this->type('time_limit', '666'); $this->type('memory_limit', '1234'); $this->type('validator', 'token-caseless'); $this->type('public', '1'); // Click inicia sesion $this->clickAndWait("//input[@value='Actualizar problema']"); $this->assertElementContainsText('//*[@id="content"]/div[2]/div', "Problem updated succesfully!"); // Verify data in DB $problem_mask = new Problems(); $problem_mask->setTitle($problemNewData["request"]["title"]); $problems = ProblemsDAO::search($problem_mask); // Check that we only retreived 1 element $this->assertEquals(1, count($problems)); $this->assertEquals($problemNewData["request"]["source"], $problems[0]->getSource()); $this->assertEquals(666, $problems[0]->getTimeLimit()); $this->assertEquals(1234, $problems[0]->getMemoryLimit()); $this->assertEquals('token-caseless', $problems[0]->getValidator()); $this->assertEquals('1', $problems[0]->getPublic()); }
public function indexAction() { $this->checkLogin(); $this->view->teams = Teams::find(); $this->view->problems = Problems::find(); $this->view->serverFiles = ServerFiles::find(array("order" => "friendlyName")); }
/** * Test that we can produce a valid alias from the title */ public function testConstructAliasFromTitle() { // Get the problem data $problemData = ProblemsFactory::getRequest(); $r = $problemData['request']; $problemAuthor = $problemData['author']; // Set a valid "complex" title $r['title'] = 'Lá Venganza Del Malvado Dr. Liraaa'; // Login user $r['auth_token'] = $this->login($problemAuthor); // Get File Uploader Mock and tell Omegaup API to use it FileHandler::SetFileUploader($this->createFileUploaderMock()); // Call the API $response = ProblemController::apiCreate($r); // Validate // Verify response $this->assertEquals('ok', $response['status']); $this->assertEquals('testplan', $response['uploaded_files'][10]); // Verify data in DB $problem_mask = new Problems(); $problem_mask->setTitle($r['title']); $problems = ProblemsDAO::search($problem_mask); // Check that we only retreived 1 element $this->assertEquals(1, count($problems)); $problem = $problems[0]; // Verify contest was found $this->assertNotNull($problem); $this->assertNotNull($problem->getProblemId()); // Verify DB data $this->assertEquals($r['title'], $problem->getTitle()); // Verify problem contents were copied $targetpath = PROBLEMS_PATH . DIRECTORY_SEPARATOR . $problem->getAlias() . DIRECTORY_SEPARATOR; $this->assertFileExists($targetpath . 'testplan'); $this->assertFileExists($targetpath . 'cases'); $this->assertFileExists($targetpath . 'statements' . DIRECTORY_SEPARATOR . 'en.html'); }
public static final function byUserType($user_type, $order, $mode, $offset, $rowcount, $query, $user_id, $tag, &$total) { global $conn; // Just in case. if ($mode !== 'asc' && $mode !== 'desc') { $mode = 'desc'; } // Use BINARY mode to force case sensitive comparisons when ordering by title. $collation = $order === 'title' ? 'COLLATE utf8_bin' : ''; $select = ''; $sql = ''; $args = array(); if ($user_type === USER_ADMIN) { $args = array($user_id); $select = ' SELECT 100 / LOG2(GREATEST(accepted, 1) + 1) AS points, accepted / GREATEST(1, submissions) AS ratio, ROUND(100 * COALESCE(ps.score, 0)) AS score, p.*'; $sql = ' FROM Problems p LEFT JOIN ( SELECT Problems.problem_id, MAX(Runs.score) AS score FROM Problems INNER JOIN Runs ON Runs.user_id = ? AND Runs.problem_id = Problems.problem_id GROUP BY Problems.problem_id ) ps ON ps.problem_id = p.problem_id'; $added_where = false; if (!is_null($tag)) { $sql .= ' INNER JOIN Problems_Tags pt ON pt.problem_id = p.problem_id'; $sql .= ' INNER JOIN Tags t ON pt.tag_id = t.tag_id'; $sql .= ' WHERE t.name = ?'; $args[] = $tag; $added_where = true; } if (!is_null($query)) { if (!$added_where) { $sql .= ' WHERE'; } else { $sql .= ' AND'; } $sql .= " title LIKE CONCAT('%', ?, '%') "; $args[] = $query; } } elseif ($user_type === USER_NORMAL && !is_null($user_id)) { $select = ' SELECT 100 / LOG2(GREATEST(p.accepted, 1) + 1) AS points, p.accepted / GREATEST(1, p.submissions) AS ratio, ROUND(100 * COALESCE(ps.score, 0), 2) AS score, p.*'; $sql = ' FROM Problems p LEFT JOIN ( SELECT pi.problem_id, MAX(r.score) AS score FROM Problems pi INNER JOIN Runs r ON r.user_id = ? AND r.problem_id = pi.problem_id GROUP BY pi.problem_id ) ps ON ps.problem_id = p.problem_id LEFT JOIN User_Roles ur ON ur.user_id = ? AND p.problem_id = ur.contest_id LEFT JOIN Groups_Users gu ON gu.user_id = ? LEFT JOIN Group_Roles gr ON gr.group_id = gu.group_id AND p.problem_id = gr.contest_id'; $args[] = $user_id; $args[] = $user_id; $args[] = $user_id; if (!is_null($tag)) { $sql .= ' INNER JOIN Problems_Tags pt ON pt.problem_id = p.problem_id'; $sql .= ' INNER JOIN Tags t ON pt.tag_id = t.tag_id'; $sql .= ' WHERE t.name = ? AND pt.public = 1 AND'; $args[] = $tag; } else { $sql .= ' WHERE'; } $sql .= ' (p.public = 1 OR p.author_id = ? OR ur.role_id = 3 OR gr.role_id = 3) '; $args[] = $user_id; if (!is_null($query)) { $sql .= " AND p.title LIKE CONCAT('%', ?, '%')"; $args[] = $query; } } elseif ($user_type === USER_ANONYMOUS) { $select = ' SELECT 0 AS score, 100 / LOG2(GREATEST(p.accepted, 1) + 1) AS points, accepted / GREATEST(1, p.submissions) AS ratio, p.*'; $sql = ' FROM Problems p'; if (!is_null($tag)) { $sql .= ' INNER JOIN Problems_Tags pt ON pt.problem_id = p.problem_id'; $sql .= ' INNER JOIN Tags t ON pt.tag_id = t.tag_id'; $sql .= ' WHERE t.name = ? AND pt.public = 1 AND'; $args[] = $tag; } else { $sql .= ' WHERE'; } $sql .= ' p.public = 1 '; if (!is_null($query)) { $sql .= " AND p.title LIKE CONCAT('%', ?, '%') "; $args[] = $query; } } $total = $conn->GetOne("SELECT COUNT(*) {$sql}", $args); // Reset the offset to 0 if out of bounds. if ($offset < 0 || $offset > $total) { $offset = 0; } if ($order == 'problem_id') { $sql .= " ORDER BY p.problem_id {$collation} {$mode}"; } elseif ($order == 'points' && $mode == 'desc') { $sql .= ' ORDER BY `points` DESC, `accepted` ASC, `submissions` DESC'; } else { $sql .= " ORDER BY `{$order}` {$collation} {$mode}"; } $sql .= ' LIMIT ?, ?'; $args[] = $offset; $args[] = $rowcount; $result = $conn->Execute("{$select} {$sql}", $args); // Only these fields (plus score, points and ratio) will be returned. $filters = array('title', 'submissions', 'accepted', 'alias', 'public'); $problems = array(); if (!is_null($result)) { foreach ($result as $row) { $temp = new Problems($row); $problem = $temp->asFilteredArray($filters); // score, points and ratio are not actually fields of a Problems object. $problem['score'] = $row['score']; $problem['points'] = $row['points']; $problem['ratio'] = $row['ratio']; $problem['tags'] = ProblemsDAO::getTagsForProblem($temp, true); array_push($problems, $problem); } } return $problems; }
/** * Create a new problem * * @throws ApiException * @throws DuplicatedEntryInDatabaseException * @throws InvalidDatabaseOperationException */ public static function apiCreate(Request $r) { self::authenticateRequest($r); // Validates request self::validateCreateOrUpdate($r); // Populate a new Problem object $problem = new Problems(); $problem->setPublic($r['public']); /* private by default */ $problem->setTitle($r['title']); $problem->setValidator($r['validator']); $problem->setTimeLimit($r['time_limit']); $problem->setValidatorTimeLimit($r['validator_time_limit']); $problem->setOverallWallTimeLimit($r['overall_wall_time_limit']); $problem->setExtraWallTime($r['extra_wall_time']); $problem->setMemoryLimit($r['memory_limit']); $problem->setOutputLimit($r['output_limit']); $problem->setVisits(0); $problem->setSubmissions(0); $problem->setAccepted(0); $problem->setDifficulty(0); $problem->setSource($r['source']); $problem->setOrder('normal'); /* defaulting to normal */ $problem->setAuthorId($r['current_user_id']); $problem->setAlias($r['alias']); $problem->setLanguages($r['languages']); $problem->setStackLimit($r['stack_limit']); $problem->setEmailClarifications($r['email_clarifications']); if (file_exists(PROBLEMS_PATH . DIRECTORY_SEPARATOR . $r['alias'])) { throw new DuplicatedEntryInDatabaseException('problemExists'); } $problemDeployer = new ProblemDeployer($r['alias'], ProblemDeployer::CREATE); // Insert new problem try { ProblemsDAO::transBegin(); // Create file after we know that alias is unique $problemDeployer->deploy(); if ($problemDeployer->hasValidator) { $problem->validator = 'custom'; } elseif ($problem->validator == 'custom') { throw new ProblemDeploymentFailedException('problemDeployerValidatorRequired'); } $problem->slow = $problemDeployer->isSlow($problem); // Calculate output limit. $output_limit = $problemDeployer->getOutputLimit(); if ($output_limit != -1) { $problem->setOutputLimit($output_limit); } // Save the contest object with data sent by user to the database ProblemsDAO::save($problem); ProblemsDAO::transEnd(); // Commit at the very end $problemDeployer->commit('Initial commit', $r['current_user']); } catch (ApiException $e) { // Operation failed in something we know it could fail, rollback transaction ProblemsDAO::transRollback(); throw $e; } catch (Exception $e) { self::$log->error('Failed to upload problem'); self::$log->error($e); // Operation failed unexpectedly, rollback transaction ProblemsDAO::transRollback(); // Alias may be duplicated, 1062 error indicates that if (strpos($e->getMessage(), '1062') !== false) { throw new DuplicatedEntryInDatabaseException('problemTitleExists'); } else { throw new InvalidDatabaseOperationException($e); } } finally { $problemDeployer->cleanup(); } // Adding unzipped files to response $result['uploaded_files'] = $problemDeployer->filesToUnzip; $result['status'] = 'ok'; $result['alias'] = $r['alias']; return $result; }
/** * Tests removed problem admin can't edit a problem anymore * * @expectedException ForbiddenAccessException */ public function testUpdateProblemWithRemovedProblemAdmin() { // Get a problem $problemData = ProblemsFactory::createProblem(); // Create our new admin $problemAdmin = UserFactory::createUser(); // Add admin to the problem $response = ProblemController::apiAddAdmin(new Request(array('usernameOrEmail' => $problemAdmin->username, 'problem_alias' => $problemData['request']['alias'], 'auth_token' => $this->login($problemData['author'])))); $this->assertEquals('ok', $response['status']); // Then remove the user $response = ProblemController::apiRemoveAdmin(new Request(array('usernameOrEmail' => $problemAdmin->username, 'problem_alias' => $problemData['request']['alias'], 'auth_token' => $this->login($problemData['author'])))); $this->assertEquals('ok', $response['status']); //Call API $newTitle = 'new title coadmin'; $response = ProblemController::apiUpdate(new Request(array('problem_alias' => $problemData['request']['alias'], 'title' => $newTitle, 'message' => 'Non-admin powers', 'auth_token' => $this->login($problemAdmin)))); // Verify data in DB $problem_mask = new Problems(); $problem_mask->setTitle($newTitle); $problems = ProblemsDAO::search($problem_mask); }
/** * Tests removed problem admin can't edit a problem anymore * * @expectedException ForbiddenAccessException */ public function testUpdateProblemWithRemovedProblemAdmin() { // Get a problem $problemData = ProblemsFactory::createProblem(); // Create our new admin $problemAdmin = UserFactory::createUser(); // Add admin to the problem $response = ProblemController::apiAddAdmin(new Request(array("usernameOrEmail" => $problemAdmin->username, "problem_alias" => $problemData["request"]["alias"], "auth_token" => $this->login($problemData["author"])))); $this->assertEquals("ok", $response["status"]); // Then remove the user $response = ProblemController::apiRemoveAdmin(new Request(array("usernameOrEmail" => $problemAdmin->username, "problem_alias" => $problemData["request"]["alias"], "auth_token" => $this->login($problemData["author"])))); $this->assertEquals("ok", $response["status"]); //Call API $newTitle = "new title coadmin"; $response = ProblemController::apiUpdate(new Request(array("problem_alias" => $problemData["request"]["alias"], "title" => $newTitle, "message" => 'Non-admin powers', "auth_token" => $this->login($problemAdmin)))); // Verify data in DB $problem_mask = new Problems(); $problem_mask->setTitle($newTitle); $problems = ProblemsDAO::search($problem_mask); }
public function problemsAction() { if (!$this->checkLogin()) { return; } if ($this->request->isPost() && $this->request->hasPost("type") && $this->security->checkToken()) { $this->session->set("changeOccurred", true); $this->session->set("changeSuccessful", true); $this->session->set("teamsGenerated", false); switch ($this->request->getPost("type")) { case 'update': $problem = Problems::findFirst(intval($this->request->getPost("id"))); if ($problem) { $problem->setName($this->request->getPost("name")); $problem->setRuntime($this->request->getPost("runtime")); if ($this->request->hasPost("hasDataFile")) { if ($this->request->hasFiles()) { // Adding data file foreach ($this->request->getUploadedFiles() as $file) { if ($file->getKey() == "dataFile") { unlink($problem->getDataFile()); $dataFileLocation = "../app/data/" . Phalcon\Text::random(Phalcon\Text::RANDOM_ALNUM, rand(13, 17)); $problem->setDataFile($dataFileLocation); $problem->setDataFileFriendly($file->getName()); $file->moveTo($dataFileLocation); } } } } else { if ($problem->getDataFile() != null) { // Removing data file unlink($problem->getDataFile()); $problem->setDataFile(null); $problem->setDataFileFriendly(null); } } if ($this->request->hasPost("hasJudgeFile")) { if ($this->request->hasFiles()) { // Adding judge file foreach ($this->request->getUploadedFiles() as $file) { if ($file->getKey() == "judgeFile") { unlink($problem->getJudgeFile()); $judgeFileLocation = "../app/data/" . Phalcon\Text::random(Phalcon\Text::RANDOM_ALNUM, rand(13, 17)); $problem->setJudgeFile($judgeFileLocation); $problem->setJudgeFileFriendly($file->getName()); $file->moveTo($judgeFileLocation); } } } } else { // Removing judge file if ($problem->getJudgeFile() != null) { unlink($problem->getJudgeFile()); $problem->setJudgeFile(null); $problem->setJudgeFileFriendly(null); } } if (!$problem->save()) { $this->session->set("changeSuccessful", false); } } else { $this->session->set("changeSuccessful", false); } break; case 'create': $error = false; $problem = new Problems(); $problem->setName($this->request->getPost("name")); $problem->setRuntime($this->request->getPost("runtime")); if ($this->request->hasFiles()) { foreach ($this->request->getUploadedFiles() as $file) { if ($file->getKey() == "dataFile" && $this->request->hasPost("hasDataFile")) { $dataFileLocation = "../app/data/" . Phalcon\Text::random(Phalcon\Text::RANDOM_ALNUM, rand(13, 17)); $problem->setDataFile($dataFileLocation); $problem->setDataFileFriendly($file->getName()); $file->moveTo($dataFileLocation); } if ($file->getKey() == "judgeFile" && $this->request->hasPost("hasJudgeFile")) { $judgeFileLocation = "../app/data/" . Phalcon\Text::random(Phalcon\Text::RANDOM_ALNUM, rand(13, 17)); $problem->setJudgeFile($judgeFileLocation); $problem->setJudgeFileFriendly($file->getName()); $file->moveTo($judgeFileLocation); } } } if ($error || !$problem->save()) { $this->session->set("changeSuccessful", false); } break; case 'delete': $problem = Problems::findFirst(intval($this->request->getPost("id"))); $dataLocation = $problem->getDataFile(); $judgeLocation = $problem->getJudgeFile(); if ($problem->delete()) { unlink($dataLocation); unlink($judgeLocation); } else { $this->session->set("changeSuccessful", false); } break; default: $this->session->set("changeSuccessful", false); break; } return $this->response->redirect("/admin/problems"); } else { if ($this->session->has("changeOccurred")) { $this->view->changeOccurred = $this->session->get("changeOccurred"); $this->session->remove("changeOccurred"); } if ($this->session->has("changeSuccessful")) { $this->view->changeSuccessful = $this->session->get("changeSuccessful"); $this->session->remove("changeSuccessful"); } } $this->view->problems = Problems::find(); }