<commit_before><?php

namespace app\controllers\admin;

use app\authentication\DatabaseAuthentication;
use app\controllers\AbstractController;
use app\libraries\Core;
use app\libraries\Output;
use app\libraries\Utils;
use app\libraries\FileUtils;
use app\models\User;

class UsersController extends AbstractController {
    public function run() {
        switch ($_REQUEST['action']) {
            case 'get_user_details':
                $this->ajaxGetUserDetails();
                break;
            case 'update_student':
                $this->updateUser('students');
                break;
            case 'update_grader':
                $this->updateUser('graders');
                break;
            case 'graders':
                $this->core->getOutput()->addBreadcrumb("Graders");
                $this->listGraders();
                break;
            case 'rotating_sections':
                $this->rotatingSectionsForm();
                break;
            case 'update_rotating_sections':
                $this->updateRotatingSections();
                break;
            case 'upload_grader_list':
                $this->uploadGraderList();
                break;
            case 'upload_class_list':
                $this->uploadClassList();
                break;
            case 'students':
            default:
                $this->core->getOutput()->addBreadcrumb("Students");
                $this->listStudents();
                break;
        }
    }

    public function listStudents() {
        $students = $this->core->getQueries()->getAllUsers();
        $use_database = $this->core->getAuthentication() instanceof DatabaseAuthentication;
        $this->core->getOutput()->renderOutput(array('admin', 'Users'), 'listStudents', $students);
        $this->renderUserForm('update_student', $use_database);
        $this->core->getOutput()->renderOutput(array('admin', 'Users'), 'classListForm', $use_database);
    }

    public function listGraders() {
        $graders = $this->core->getQueries()->getAllGraders();
        $use_database = $this->core->getAuthentication() instanceof DatabaseAuthentication;
        $this->core->getOutput()->renderOutput(array('admin', 'Users'), 'listGraders', $graders);
        $this->renderUserForm('update_grader', $use_database);
        $this->core->getOutput()->renderOutput(array('admin', 'Users'), 'graderListForm', $use_database);
    }

    private function renderUserForm($action, $use_database) {
        $reg_sections = $this->core->getQueries()->getRegistrationSections();
        $rot_sections = $this->core->getQueries()->getRotatingSections();
        $this->core->getOutput()->renderOutput(array('admin', 'Users'), 'userForm', $reg_sections, $rot_sections, $action, $use_database);
    }

    public function ajaxGetUserDetails() {
        $user_id = $_REQUEST['user_id'];
        $user = $this->core->getQueries()->getUserById($user_id);
        $this->core->getOutput()->renderJson(array(
            'user_id' => $user->getId(),
            'user_firstname' => $user->getFirstName(),
            'user_lastname' => $user->getLastName(),
            'user_preferred_firstname' => $user->getPreferredFirstName(),
            'user_email' => $user->getEmail(),
            'user_group' => $user->getGroup(),
            'registration_section' => $user->getRegistrationSection(),
            'rotating_section' => $user->getRotatingSection(),
            'manual_registration' => $user->isManualRegistration(),
            'grading_registration_sections' => $user->getGradingRegistrationSections()
        ));
    }

    public function updateUser($action='students') {
        $return_url = $this->core->buildUrl(array('component' => 'admin', 'page' => 'users',
            'action' => $action), 'user-'.$_POST['user_id']);
        if (!$this->core->checkCsrfToken($_POST['csrf_token'])) {
            $this->core->addErrorMessage("Invalid CSRF token.");
            $this->core->redirect($return_url);
        }
        $use_database = $this->core->getAuthentication() instanceof DatabaseAuthentication;

        $error_message = "";
        //Username must contain only lowercase alpha, numbers, underscores, hyphens
        $error_message .= preg_match("~^[a-z0-9_\-]+$~", trim($_POST['user_id'])) ? "" : "Error in username: {$_POST['user_id']}," . PHP_EOL;
        //First and Last name must be alpha characters, white-space, or certain punctuation.
        $error_message .= preg_match("~^[a-zA-Z.'`\- ]+$~", trim($_POST['user_firstname'])) ? "" : "Error in first name: {$_POST['user_firstname']}," . PHP_EOL;
        $error_message .= preg_match("~^[a-zA-Z.'`\- ]+$~", trim($_POST['user_lastname'])) ? "" : "Error in last name: {$_POST['user_lastname']}," . PHP_EOL;
        //Check email address for format "address@domain".
        $error_message .= preg_match("~.+@{1}[a-zA-Z0-9:\.\-\[\]]+$~", trim($_POST['user_email'])) ? "" : "Error in email: {$_POST['user_email']}," . PHP_EOL;
        //Preferred first name must be alpha characters, white-space, or certain punctuation.
        if (isset($_POST['user_preferred_firstname'])) {
            $error_message .= preg_match("~^[a-zA-Z.'`\- ]+$~", trim($_POST['user_preferred_firstname'])) ? "" : "Error in preferred first name: {$_POST['user_preferred_firstname']}," . PHP_EOL;
        }
        //Database password cannot be blank, no check on format
        if ($use_database) {
            $error_message .= $_POST['user_password'] != "" ? "" : "Error must enter password for user" . PHP_EOL;
        }

        if (!empty($error_message)) {
            $this->core->addErrorMessage($error_message." Contact your sysadmin if this should not cause an error.");
            $this->core->redirect($return_url);
        }

        if ($_POST['edit_user'] == "true") {
            $user = $this->core->getQueries()->getSubmittyUser($_POST['user_id']);
            if ($user === null) {
                $this->core->addErrorMessage("No user found with that user id");
                $this->core->redirect($return_url);
            }
        }
        else {
            $user = $this->core->loadModel(User::class);
            $user->setId(trim($_POST['user_id']));
        }

        $user->setFirstName(trim($_POST['user_firstname']));
        if (isset($_POST['user_preferred_firstname'])) {
            $user->setPreferredFirstName(trim($_POST['user_preferred_firstname']));<commit_msg>Make preferred name optional, prevent creating new user with existing ID (#1477)<commit_after><?php

namespace app\controllers\admin;

use app\authentication\DatabaseAuthentication;
use app\controllers\AbstractController;
use app\libraries\Core;
use app\libraries\Output;
use app\libraries\Utils;
use app\libraries\FileUtils;
use app\models\User;

class UsersController extends AbstractController {
    public function run() {
        switch ($_REQUEST['action']) {
            case 'get_user_details':
                $this->ajaxGetUserDetails();
                break;
            case 'update_student':
                $this->updateUser('students');
                break;
            case 'update_grader':
                $this->updateUser('graders');
                break;
            case 'graders':
                $this->core->getOutput()->addBreadcrumb("Graders");
                $this->listGraders();
                break;
            case 'rotating_sections':
                $this->rotatingSectionsForm();
                break;
            case 'update_rotating_sections':
                $this->updateRotatingSections();
                break;
            case 'upload_grader_list':
                $this->uploadGraderList();
                break;
            case 'upload_class_list':
                $this->uploadClassList();
                break;
            case 'students':
            default:
                $this->core->getOutput()->addBreadcrumb("Students");
                $this->listStudents();
                break;
        }
    }

    public function listStudents() {
        $students = $this->core->getQueries()->getAllUsers();
        $use_database = $this->core->getAuthentication() instanceof DatabaseAuthentication;
        $this->core->getOutput()->renderOutput(array('admin', 'Users'), 'listStudents', $students);
        $this->renderUserForm('update_student', $use_database);
        $this->core->getOutput()->renderOutput(array('admin', 'Users'), 'classListForm', $use_database);
    }

    public function listGraders() {
        $graders = $this->core->getQueries()->getAllGraders();
        $use_database = $this->core->getAuthentication() instanceof DatabaseAuthentication;
        $this->core->getOutput()->renderOutput(array('admin', 'Users'), 'listGraders', $graders);
        $this->renderUserForm('update_grader', $use_database);
        $this->core->getOutput()->renderOutput(array('admin', 'Users'), 'graderListForm', $use_database);
    }

    private function renderUserForm($action, $use_database) {
        $reg_sections = $this->core->getQueries()->getRegistrationSections();
        $rot_sections = $this->core->getQueries()->getRotatingSections();
        $this->core->getOutput()->renderOutput(array('admin', 'Users'), 'userForm', $reg_sections, $rot_sections, $action, $use_database);
    }

    public function ajaxGetUserDetails() {
        $user_id = $_REQUEST['user_id'];
        $user = $this->core->getQueries()->getUserById($user_id);
        $this->core->getOutput()->renderJson(array(
            'user_id' => $user->getId(),
            'user_firstname' => $user->getFirstName(),
            'user_lastname' => $user->getLastName(),
            'user_preferred_firstname' => $user->getPreferredFirstName(),
            'user_email' => $user->getEmail(),
            'user_group' => $user->getGroup(),
            'registration_section' => $user->getRegistrationSection(),
            'rotating_section' => $user->getRotatingSection(),
            'manual_registration' => $user->isManualRegistration(),
            'grading_registration_sections' => $user->getGradingRegistrationSections()
        ));
    }

    public function updateUser($action='students') {
        $return_url = $this->core->buildUrl(array('component' => 'admin', 'page' => 'users',
            'action' => $action), 'user-'.$_POST['user_id']);
        if (!$this->core->checkCsrfToken($_POST['csrf_token'])) {
            $this->core->addErrorMessage("Invalid CSRF token.");
            $this->core->redirect($return_url);
        }
        $use_database = $this->core->getAuthentication() instanceof DatabaseAuthentication;

        $error_message = "";
        //Username must contain only lowercase alpha, numbers, underscores, hyphens
        $error_message .= preg_match("~^[a-z0-9_\-]+$~", trim($_POST['user_id'])) ? "" : "Error in username: {$_POST['user_id']}," . PHP_EOL;
        //First and Last name must be alpha characters, white-space, or certain punctuation.
        $error_message .= preg_match("~^[a-zA-Z.'`\- ]+$~", trim($_POST['user_firstname'])) ? "" : "Error in first name: {$_POST['user_firstname']}," . PHP_EOL;
        $error_message .= preg_match("~^[a-zA-Z.'`\- ]+$~", trim($_POST['user_lastname'])) ? "" : "Error in last name: {$_POST['user_lastname']}," . PHP_EOL;
        //Check email address for format "address@domain".
        $error_message .= preg_match("~.+@{1}[a-zA-Z0-9:\.\-\[\]]+$~", trim($_POST['user_email'])) ? "" : "Error in email: {$_POST['user_email']}," . PHP_EOL;
        //Preferred first name must be alpha characters, white-space, or certain punctuation.
        if (isset($_POST['user_preferred_firstname']) && trim($_POST['user_preferred_firstname']) != "") {
            $error_message .= preg_match("~^[a-zA-Z.'`\- ]+$~", trim($_POST['user_preferred_firstname'])) ? "" : "Error in preferred first name: {$_POST['user_preferred_firstname']}," . PHP_EOL;
        }
        //Database password cannot be blank, no check on format
        if ($use_database) {
            $error_message .= $_POST['user_password'] != "" ? "" : "Error must enter password for user" . PHP_EOL;
        }

        if (!empty($error_message)) {
            $this->core->addErrorMessage($error_message." Contact your sysadmin if this should not cause an error.");
            $this->core->redirect($return_url);
        }

        $user = $this->core->getQueries()->getSubmittyUser($_POST['user_id']);
        if ($_POST['edit_user'] == "true") {
            if ($user === null) {
                $this->core->addErrorMessage("No user found with that user id");
                $this->core->redirect($return_url);
            }
        }
        else {
            if ($user !== null) {
                $this->core->addErrorMessage("A user with that ID already exists");
                $this->core->redirect($return_url);
            }
            $user = $this->core->loadModel(User::class);
            $user->setId(trim($_POST['user_id']));
        }

        $user->setFirstName(trim($_POST['user_firstname']));
        if (isset($_POST['user_preferred_firstname']) && trim($_POST['user_preferred_firstname']) != "") {
            $user->setPreferredFirstName(trim($_POST['user_preferred_firstname']));
{'fraction_non_alphanumeric': 0.16962867730469636, 'fraction_numerical': 0.0010587612493382743, 'mean_word_length': 2.7166947723440136, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 213, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '406084', 'n_tokens_mistral': 3797, 'n_tokens_neox': 3702, 'n_words': 645}