diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5318fef1572..b2ccff57f48 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -2,9 +2,7 @@ name: CI on: push: - branches: - - main - pull_request: + # pull_request: workflow_dispatch: env: @@ -27,575 +25,586 @@ concurrency: jobs: - ansible-lint: - name: Ansible Lint - runs-on: ubuntu-22.04 - steps: - - uses: actions/checkout@v4 - - name: Run ansible-lint - uses: ansible/ansible-lint@main - with: - args: .setup/ansible - - - css-lint: - name: CSS Lint - runs-on: ubuntu-22.04 - defaults: - run: - working-directory: site - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: ${{ env.NODE_VERSION }} - - name: Cache Node Modules - uses: actions/cache@v4 - with: - path: ~/.npm - key: ${{ runner.os }}-cache-node-modules-${{ hashFiles('**/package-lock.json') }} - restore-keys: | - ${{ runner.os }}-cache-node-modules- - - run: npm install - - name: Run stylelint - run: npm run css-stylelint - - - js-lint: - name: JavaScript Lint - runs-on: ubuntu-22.04 - defaults: - run: - working-directory: site - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: ${{ env.NODE_VERSION }} - - name: Cache Node Modules - uses: actions/cache@v4 - with: - path: ~/.npm - key: ${{ runner.os }}-cache-node-modules-${{ hashFiles('**/package-lock.json') }} - restore-keys: | - ${{ runner.os }}-cache-node-modules- - - run: npm install - - name: Run eslint - run: npm run eslint - - name: Run npm build (tsc and esbuild) - run: npm run build - - - js-unit: - name: JavaScript Unit - runs-on: ubuntu-22.04 - defaults: - run: - working-directory: site - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: ${{ env.NODE_VERSION }} - - name: Cache Node Modules - uses: actions/cache@v4 - with: - path: ~/.npm - key: ${{ runner.os }}-cache-node-modules-${{ hashFiles('**/package-lock.json') }} - restore-keys: | - ${{ runner.os }}-cache-node-modules- - - run: npm install - - run: npm run test - - name: Upload Coverage - uses: codecov/codecov-action@v3 - with: - files: site/tests/report/jest/clover.xml - flags: js - - - php-lint: - name: PHP Lint - runs-on: ubuntu-22.04 - defaults: - run: - working-directory: site - steps: - - uses: actions/checkout@v4 - - uses: shivammathur/setup-php@2.31.1 - with: - php-version: ${{ env.PHP_VER }} - - name: Cache Composer - id: composer-cache - run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT - - name: Install Composer - uses: actions/cache@v4 - with: - path: ${{ steps.composer-cache.outputs.dir }} - key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} - restore-keys: | - ${{ runner.os }}-composer- - - - name: Install dependencies - run: composer install --prefer-dist --dev - - name: Check syntax - run: find -L . -path ./vendor -prune -o -name '*.php' -print0 | xargs -0 -n 1 -P 4 php -l - - name: Lint PHP code - run: | - php vendor/bin/phpcs --version - php vendor/bin/phpcs - - name: Static analysis - run: | - php vendor/bin/phpstan --version - php vendor/bin/phpstan analyze app public/index.php socket/index.php - - - php-unit: - name: PHP Unit - runs-on: ubuntu-22.04 - defaults: - run: - working-directory: site - steps: - - uses: actions/checkout@v4 - - uses: shivammathur/setup-php@2.31.1 - with: - php-version: ${{ env.PHP_VER }} - extensions: imagick - coverage: pcov - - name: Cache Composer - id: composer-cache - run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT - - name: Install Composer - uses: actions/cache@v4 - with: - path: ${{ steps.composer-cache.outputs.dir }} - key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} - restore-keys: | - ${{ runner.os }}-composer- - - name: Install dependencies - run: composer install --prefer-dist --dev - - name: Run php unit tests - run: php vendor/bin/phpunit - - name: Upload Coverage - uses: codecov/codecov-action@v3 - with: - files: site/tests/report/clover.xml - flags: php - - - python-lint: - name: Python Lint - runs-on: ubuntu-22.04 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-python@v5 - with: - python-version: ${{ env.PYTHON_VERSION }} - - name: Cache Pip - uses: actions/cache@v4 - with: - path: ~/.cache/pip - key: ${{ runner.os }}-${{ github.job }}-pip-${{ github.sha }} - restore-keys: | - ${{ runner.os }}-${{ github.job }}-pip- - - name: Install python libraries - run: python3 -m pip install -r .setup/pip/dev_requirements.txt - - name: Run flake8 - run: python3 -m flake8 - - name: Run pylint - run: python3 -m pylint --recursive=y . - - python-unit: - name: Python Unit - runs-on: ubuntu-22.04 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-python@v5 - with: - python-version: ${{ env.PYTHON_VERSION }} - - name: Cache Pip - uses: actions/cache@v4 - with: - path: ~/.cache/pip - key: ${{ runner.os }}-${{ github.job }}-pip-${{ hashFiles('**/system_requirements.txt') }} - restore-keys: | - ${{ runner.os }}-${{ github.job }}-pip- - - name: Install python libraries - run: | - python3 -m pip install -r .setup/pip/system_requirements.txt - python3 -m pip install coverage # Testing util. - - # Submitty utils install & unit testing, must be put before auto grader - # testing as auto grader depends on submitty utils to function. - - name: Run python_submitty_utils python unit tests - working-directory: python_submitty_utils - run: | - pip3 install . - coverage run -m unittest discover - coverage xml - - name: Upload submitty python utils Coverage - uses: codecov/codecov-action@v3 - with: - files: python_submitty_utils/coverage.xml - flags: python_submitty_utils - - # Migrator unit test - - name: Run migrator python unit tests - working-directory: migration - run: | - coverage run -m unittest discover - coverage xml - - name: Upload migrator Coverage - uses: codecov/codecov-action@v3 - with: - files: migration/coverage.xml - flags: migrator - - # Auto grader unit test - - name: Run autograder python unit tests - working-directory: autograder - run: | - coverage run -m unittest discover - coverage xml - - name: Upload autograder Coverage - uses: codecov/codecov-action@v3 - with: - files: autograder/coverage.xml - flags: autograder - - # submitty_daemon_jobs unit tests - - name: Install bulk upload dependencies - run: | - sudo apt-get update - sudo apt-get install -y poppler-utils - sudo apt-get install -y libzbar0 - - - name: Run bulk upload unit tests - working-directory: sbin/submitty_daemon_jobs - run: | - coverage run -m unittest discover tests -t . - coverage xml -i - - - name: Upload submitty_daemon_jobs Coverage - uses: codecov/codecov-action@v3 - with: - files: sbin/submitty_daemon_jobs/coverage.xml - flags: submitty_daemon_jobs - - yaml-lint: - name: YAML Lint - runs-on: ubuntu-22.04 - steps: - - uses: actions/checkout@v4 - - name: install yamllint - run: sudo apt-get install -y yamllint - - name: Run yamllint - run: yamllint . - - - shellcheck: - name: Shell Lint - runs-on: ubuntu-22.04 - steps: - - uses: actions/checkout@v4 - - name: install ShellCheck - run: sudo apt-get install -y shellcheck - - name: Run ShellCheck - run: python3 run_shellcheck.py # Uses the default Python installed with Ubuntu - - - colors-css: - name: colors.css Check - runs-on: ubuntu-22.04 - - steps: - - name: Checkout main branch - uses: actions/checkout@v4 - with: - ref: main - path: MAIN - - - name: Checkout PR branch - uses: actions/checkout@v4 - with: - path: PR - - - name: Compare file size - run: | - FILEPATH="site/public/css/colors.css" - MAIN_FILE="MAIN/$FILEPATH" - PR_FILE="PR/$FILEPATH" - - if [ ! -f "$MAIN_FILE" ]; then - echo "Main file $MAIN_FILE does not exist." - exit 1 - fi - - if [ ! -f "$PR_FILE" ]; then - echo "PR file $PR_FILE does not exist." - exit 1 - fi - - LINES_DIFF=$(($(wc -l < "$PR_FILE") - $(wc -l < "$MAIN_FILE"))) - - if [ $LINES_DIFF -gt 0 ]; then - echo "::error::colors.css has increased in size by $LINES_DIFF lines in this PR." - echo "::error::Please use existing colors in colors.css instead of adding new ones, to keep the size of the file manageable." - echo "::error::If adding to colors.css really is necessary for your PR, this requirement may be waived on maintainer review." - exit $LINES_DIFF - else - echo "No lines added. OK." - fi - - - db-check: - name: DB Check - runs-on: ubuntu-22.04 - env: - PGPASSWORD: submitty_dbuser - MAIN_INSTALL_PATH: ${{ github.WORKSPACE }}/main - MAIN_DATA_PATH: ${{ github.WORKSPACE }}/main/var - MAIN_REPO_PATH: ${{ github.WORKSPACE }}/main/GIT_CHECKOUT - PR_INSTALL_PATH: ${{ github.WORKSPACE }}/branch - PR_DATA_PATH: ${{ github.WORKSPACE }}/branch/var - PR_REPO_PATH: ${{ github.WORKSPACE }}/branch/GIT_CHECKOUT - - services: - postgres-main: - image: postgres:12 - env: - POSTGRES_PASSWORD: submitty_dbuser - POSTGRES_USER: postgres - TZ: America/New_York - ports: - - 5432 - - postgres-branch: - image: postgres:12 - env: - POSTGRES_PASSWORD: submitty_dbuser - POSTGRES_USER: postgres - TZ: America/New_York - ports: - - 5432 - - steps: - - name: Setup Dependencies - run: | - sudo sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list' - wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add - - - sudo apt-get update - sudo apt-get autoremove -y postgresql-14 postgresql-client-common - sudo apt-get install -y postgresql-12 - sudo rm /etc/postgresql/14 -rf - - - name: Checkout Current Branch - uses: actions/checkout@v4 - with: - path: branch/GIT_CHECKOUT/Submitty - fetch-depth: 0 - - - name: Find Merge Base - run: | - echo MBASE=$(git --git-dir ${PR_REPO_PATH}/Submitty/.git merge-base \ - -a origin/main ${{ github.sha }}) >> $GITHUB_ENV - - - name: Checkout main Branch - uses: actions/checkout@v4 - with: - ref: ${{ env.MBASE || 'main' }} - path: main/GIT_CHECKOUT/Submitty - - - name: Download Required Packages - run: | - pip install -r <( - grep -e "tzlocal" -e "sqlalchemy" -e "ruamel" \ - -e "psycopg2" -e "docker" \ - ${MAIN_REPO_PATH}/Submitty/.setup/pip/system_requirements.txt - ) - pip install ${MAIN_REPO_PATH}/Submitty/python_submitty_utils - - - - name: Create Users and Groups - run: | # Create users and groups - sudo -E python3 ${MAIN_REPO_PATH}/Submitty/.setup/bin/create_untrusted_users.py - - sudo addgroup submitty_daemonphp - sudo addgroup submitty_daemoncgi - sudo addgroup submitty_daemonphpcgi - sudo addgroup submitty_course_builders - sudo addgroup submitty_phpgrp - - sudo adduser submitty_php --disabled-password --no-create-home - sudo adduser submitty_cgi --disabled-password --no-create-home - sudo adduser submitty_cgi submitty_phpgrp --no-create-home - sudo adduser submitty_php shadow --no-create-home - sudo adduser submitty_cgi shadow --no-create-home - sudo adduser submitty_daemon --disabled-password --no-create-home - sudo adduser submitty_php submitty_daemonphp --no-create-home - sudo adduser submitty_daemon submitty_daemonphp --no-create-home - sudo adduser submitty_cgi submitty_daemoncgi --no-create-home - sudo adduser submitty_daemon submitty_daemoncgi --no-create-home - sudo adduser submitty_daemon submitty_daemonphpcgi --no-create-home - sudo adduser submitty_php submitty_daemonphpcgi --no-create-home - sudo adduser submitty_cgi submitty_daemonphpcgi --no-create-home - sudo adduser submitty_daemon docker --no-create-home - - sudo useradd -p $(openssl passwd -1 submitty_dbuser) submitty_dbuser - - - name: Configure Submitty - run: | - configure_submitty() { - # $1->MAIN_INSTALL_PATH, $2->MAIN_DATA_PATH, $3->MAIN_REPO_PATH, $4->DB_PORT - mkdir -vp "$2" && chmod -vR 777 "$2" - mkdir -vp "$1/config" && chmod -vR 777 "$1/config" - mkdir -vp "$1/site" && chmod -vR 777 "$1/site" - mkdir -vp "$2/courses" && chmod -vR 777 "$2/courses" - - ( - echo "localhost" # database host - echo "$4" # database port - echo "" # global db user - echo "submitty_dbuser" # global db pass - echo "" # course db user - echo "submitty_dbuser" # course db pass - echo "" # timezone - echo "" # default locale - echo "http://localhost" # submitty url - echo "" # vcs url - echo "" # institution name - echo "" # sysadmin email - echo "" # where to report - echo "1" # PamAuth - echo "" # sysadmin username - echo "n" # email notification - ) | tee /dev/stderr \ - | sudo -E python3 "$3/Submitty/.setup/CONFIGURE_SUBMITTY.py" \ - --install-dir "$1" --data-dir "$2" --debug - - # Copy necessary files to the installation path - cp -vr "$3/Submitty/sbin" "$1" - sudo chmod -vR 777 "$1/config" - sudo chmod -vR 777 "$1/sbin" - } - - configure_submitty "${MAIN_INSTALL_PATH}" "${MAIN_DATA_PATH}" \ - "${MAIN_REPO_PATH}" "${{ job.services.postgres-main.ports['5432'] }}" - configure_submitty "${PR_INSTALL_PATH}" "${PR_DATA_PATH}" \ - "${PR_REPO_PATH}" "${{ job.services.postgres-branch.ports['5432'] }}" - - - - name: Create Databases - run: | - psql -d postgres -h localhost -U postgres -p ${{ job.services.postgres-main.ports['5432'] }} \ - -c "CREATE ROLE submitty_dbuser WITH SUPERUSER CREATEDB CREATEROLE LOGIN PASSWORD 'submitty_dbuser'"\ - -c "CREATE ROLE submitty_course_dbuser WITH LOGIN PASSWORD 'submitty_dbuser'" - psql -d postgres -h localhost -U submitty_dbuser -p ${{ job.services.postgres-main.ports['5432'] }} \ - -c "CREATE DATABASE submitty" - - psql -d postgres -h localhost -U postgres -p ${{ job.services.postgres-branch.ports['5432'] }} \ - -c "CREATE ROLE submitty_dbuser WITH SUPERUSER CREATEDB CREATEROLE LOGIN PASSWORD 'submitty_dbuser'"\ - -c "CREATE ROLE submitty_course_dbuser WITH LOGIN PASSWORD 'submitty_dbuser'" - psql -d postgres -h localhost -U submitty_dbuser -p ${{ job.services.postgres-branch.ports['5432'] }} \ - -c "CREATE DATABASE submitty" - - - name: Create Database Dumper - run: | # the original dumper requires a `su`, which is not needed when psql as a service - ( - echo 'pg_dump -Osx -d "$1" -f "$2" -h localhost -p "$3" -U postgres ' - echo 'sed -i -e "'"/SELECT pg_catalog.set_config('search_path'/d"'"\' - echo ' -e "/-- Dumped \(from\|by\)/d" \' - echo ' -e "/SET default_table_access_method = /d" \' - echo ' -e "s/FOR EACH ROW EXECUTE FUNCTION/FOR EACH ROW EXECUTE PROCEDURE/g" "$2"' - ) > dbdump.sh - chmod +x dbdump.sh - - echo M=$([ "$(date +%-m)" -lt "7" ] && echo 's' || echo 'f') >> $GITHUB_ENV - echo Y=$(date +%y) >> $GITHUB_ENV - - mkdir -vp ${GITHUB_WORKSPACE}/dumped/main - mkdir -vp ${GITHUB_WORKSPACE}/dumped/branch - - - name: Setup Databases and Courses for main - run: | # migrate main according to dumped master database (assume it is correct) - python3 ${MAIN_REPO_PATH}/Submitty/migration/run_migrator.py -e master migrate --initial - - sudo ln -vs /usr/bin/true /usr/bin/ldapadd - sudo -E python3 ${MAIN_REPO_PATH}/Submitty/.setup/bin/setup_sample_courses.py \ - blank --no_grading --data_dir ${MAIN_DATA_PATH} --install_dir ${MAIN_INSTALL_PATH} - - sudo chmod -vR 777 ${MAIN_DATA_PATH}/courses - - - name: Apply New Migrations from Current Branch - run: | - python3 ${PR_REPO_PATH}/Submitty/migration/run_migrator.py \ - -e master -e course -c ${MAIN_INSTALL_PATH}/config migrate - - - name: Setup Databases and Courses for Current Branch - run: | - python3 ${PR_REPO_PATH}/Submitty/migration/run_migrator.py -e master migrate --initial - - sudo -E python3 ${PR_REPO_PATH}/Submitty/.setup/bin/setup_sample_courses.py \ - blank --no_grading --data_dir ${PR_DATA_PATH} --install_dir ${PR_INSTALL_PATH} - - sudo chmod -vR 777 ${PR_DATA_PATH}/courses - - - name: Dump Migrated Databases - run: | - ./dbdump.sh "submitty" "${GITHUB_WORKSPACE}/dumped/main/master.sql"\ - "${{ job.services.postgres-main.ports['5432'] }}" - ./dbdump.sh "submitty_${M}${Y}_blank" "${GITHUB_WORKSPACE}/dumped/main/course.sql"\ - "${{ job.services.postgres-main.ports['5432'] }}" - - ./dbdump.sh "submitty" "${GITHUB_WORKSPACE}/dumped/branch/master.sql"\ - "${{ job.services.postgres-branch.ports['5432'] }}" - ./dbdump.sh "submitty_${M}${Y}_blank" "${GITHUB_WORKSPACE}/dumped/branch/course.sql"\ - "${{ job.services.postgres-branch.ports['5432'] }}" - - - name: Compare Migrated master Databases - if: always() - run: | - diff --color ${GITHUB_WORKSPACE}/dumped/main/master.sql \ - ${GITHUB_WORKSPACE}/dumped/branch/master.sql || { - echo "::error:: Master databases are not identical, please check your migration" - exit 1 - } - - - name: Compare Migrated course Databases - if: always() - run: | - diff --color ${GITHUB_WORKSPACE}/dumped/main/course.sql \ - ${GITHUB_WORKSPACE}/dumped/branch/course.sql || { - echo "::error:: Course databases are not identical, please check your migration" - exit 1 - } - - - name: Compare Migrated master Database with Provided Dump - if: always() - run: | - diff --color ${GITHUB_WORKSPACE}/dumped/branch/master.sql \ - ${PR_REPO_PATH}/Submitty/migration/migrator/data/submitty_db.sql || { - echo "::error:: Wrong provided dump, please check your database dumps" - exit 1 - } - - - name: Compare Migrated course Database with Provided Dump - if: always() - run: | - diff --color ${GITHUB_WORKSPACE}/dumped/branch/course.sql \ - ${PR_REPO_PATH}/Submitty/migration/migrator/data/course_tables.sql || { - echo "::error:: Wrong provided dump, please check your database dumps" - exit 1 - } - - - name: Pack Artifacts - if: failure() - uses: actions/upload-artifact@v4 - with: - name: dumped_database - path: ${{ github.WORKSPACE }}/dumped/**/*.sql - retention-days: 3 + # ansible-lint: + # name: Ansible Lint + # runs-on: ubuntu-22.04 + # steps: + # - uses: actions/checkout@v4 + # - name: Run ansible-lint + # uses: ansible/ansible-lint@main + # with: + # args: .setup/ansible + + + # css-lint: + # name: CSS Lint + # runs-on: ubuntu-22.04 + # defaults: + # run: + # working-directory: site + # steps: + # - uses: actions/checkout@v4 + # - uses: actions/setup-node@v4 + # with: + # node-version: ${{ env.NODE_VERSION }} + # - name: Cache Node Modules + # uses: actions/cache@v4 + # with: + # path: ~/.npm + # key: ${{ runner.os }}-cache-node-modules-${{ hashFiles('**/package-lock.json') }} + # restore-keys: | + # ${{ runner.os }}-cache-node-modules- + # - run: npm install + # - name: Run stylelint + # run: npm run css-stylelint + + + # js-lint: + # name: JavaScript Lint + # runs-on: ubuntu-22.04 + # defaults: + # run: + # working-directory: site + # steps: + # - uses: actions/checkout@v4 + # - uses: actions/setup-node@v4 + # with: + # node-version: ${{ env.NODE_VERSION }} + # - name: Cache Node Modules + # uses: actions/cache@v4 + # with: + # path: ~/.npm + # key: ${{ runner.os }}-cache-node-modules-${{ hashFiles('**/package-lock.json') }} + # restore-keys: | + # ${{ runner.os }}-cache-node-modules- + # - run: npm install + # - name: Run eslint + # run: npm run eslint + # - name: Run npm build (tsc and esbuild) + # run: npm run build + + + # js-unit: + # name: JavaScript Unit + # runs-on: ubuntu-22.04 + # defaults: + # run: + # working-directory: site + # steps: + # - uses: actions/checkout@v4 + # - uses: actions/setup-node@v4 + # with: + # node-version: ${{ env.NODE_VERSION }} + # - name: Cache Node Modules + # uses: actions/cache@v4 + # with: + # path: ~/.npm + # key: ${{ runner.os }}-cache-node-modules-${{ hashFiles('**/package-lock.json') }} + # restore-keys: | + # ${{ runner.os }}-cache-node-modules- + # - run: npm install + # - run: npm run test + # - name: Upload Coverage + # uses: codecov/codecov-action@v3 + # with: + # files: site/tests/report/jest/clover.xml + # flags: js + + + # php-lint: + # name: PHP Lint + # runs-on: ubuntu-22.04 + # defaults: + # run: + # working-directory: site + # steps: + # - uses: actions/checkout@v4 + # - uses: shivammathur/setup-php@2.31.1 + # with: + # php-version: ${{ env.PHP_VER }} + # - name: Cache Composer + # id: composer-cache + # run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT + # - name: Install Composer + # uses: actions/cache@v4 + # with: + # path: ${{ steps.composer-cache.outputs.dir }} + # key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} + # restore-keys: | + # ${{ runner.os }}-composer- + + # - name: Install dependencies + # run: composer install --prefer-dist --dev + # - name: Check syntax + # run: find -L . -path ./vendor -prune -o -name '*.php' -print0 | xargs -0 -n 1 -P 4 php -l + # - name: Lint PHP code + # run: | + # php vendor/bin/phpcs --version + # php vendor/bin/phpcs + # - name: Static analysis + # run: | + # php vendor/bin/phpstan --version + # php vendor/bin/phpstan analyze app public/index.php socket/index.php + + + # php-unit: + # name: PHP Unit + # runs-on: ubuntu-22.04 + # defaults: + # run: + # working-directory: site + # steps: + # - uses: actions/checkout@v4 + # - uses: shivammathur/setup-php@2.31.1 + # with: + # php-version: ${{ env.PHP_VER }} + # extensions: imagick + # coverage: pcov + # - name: Cache Composer + # id: composer-cache + # run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT + # - name: Install Composer + # uses: actions/cache@v4 + # with: + # path: ${{ steps.composer-cache.outputs.dir }} + # key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} + # restore-keys: | + # ${{ runner.os }}-composer- + # - name: Install dependencies + # run: composer install --prefer-dist --dev + # - name: Run php unit tests + # run: php vendor/bin/phpunit + # - name: Upload Coverage + # uses: codecov/codecov-action@v3 + # with: + # files: site/tests/report/clover.xml + # flags: php + + + # python-lint: + # name: Python Lint + # runs-on: ubuntu-22.04 + # steps: + # - uses: actions/checkout@v4 + # - uses: actions/setup-python@v5 + # with: + # python-version: ${{ env.PYTHON_VERSION }} + # - name: Cache Pip + # uses: actions/cache@v4 + # with: + # path: ~/.cache/pip + # key: ${{ runner.os }}-${{ github.job }}-pip-${{ github.sha }} + # restore-keys: | + # ${{ runner.os }}-${{ github.job }}-pip- + # - name: Install python libraries + # run: python3 -m pip install -r .setup/pip/dev_requirements.txt + # - name: Run flake8 + # run: python3 -m flake8 + # - name: Run pylint + # run: python3 -m pylint --recursive=y . + + # python-unit: + # name: Python Unit + # runs-on: ubuntu-22.04 + # steps: + # - uses: actions/checkout@v4 + # - uses: actions/setup-python@v5 + # with: + # python-version: ${{ env.PYTHON_VERSION }} + # - name: Cache Pip + # uses: actions/cache@v4 + # with: + # path: ~/.cache/pip + # key: ${{ runner.os }}-${{ github.job }}-pip-${{ hashFiles('**/system_requirements.txt') }} + # restore-keys: | + # ${{ runner.os }}-${{ github.job }}-pip- + # - name: Install python libraries + # run: | + # python3 -m pip install -r .setup/pip/system_requirements.txt + # python3 -m pip install coverage # Testing util. + + # # Submitty utils install & unit testing, must be put before auto grader + # # testing as auto grader depends on submitty utils to function. + # - name: Run python_submitty_utils python unit tests + # working-directory: python_submitty_utils + # run: | + # pip3 install . + # coverage run -m unittest discover + # coverage xml + # - name: Upload submitty python utils Coverage + # uses: codecov/codecov-action@v3 + # with: + # files: python_submitty_utils/coverage.xml + # flags: python_submitty_utils + + # # Migrator unit test + # - name: Run migrator python unit tests + # working-directory: migration + # run: | + # coverage run -m unittest discover + # coverage xml + # - name: Upload migrator Coverage + # uses: codecov/codecov-action@v3 + # with: + # files: migration/coverage.xml + # flags: migrator + + # # Auto grader unit test + # - name: Run autograder python unit tests + # working-directory: autograder + # run: | + # coverage run -m unittest discover + # coverage xml + # - name: Upload autograder Coverage + # uses: codecov/codecov-action@v3 + # with: + # files: autograder/coverage.xml + # flags: autograder + + # # submitty_daemon_jobs unit tests + # - name: Install bulk upload dependencies + # run: | + # sudo apt-get update + # sudo apt-get install -y poppler-utils + # sudo apt-get install -y libzbar0 + + # - name: Run bulk upload unit tests + # working-directory: sbin/submitty_daemon_jobs + # run: | + # coverage run -m unittest discover tests -t . + # coverage xml -i + + # - name: Upload submitty_daemon_jobs Coverage + # uses: codecov/codecov-action@v3 + # with: + # files: sbin/submitty_daemon_jobs/coverage.xml + # flags: submitty_daemon_jobs + + # yaml-lint: + # name: YAML Lint + # runs-on: ubuntu-22.04 + # steps: + # - uses: actions/checkout@v4 + # - name: install yamllint + # run: sudo apt-get install -y yamllint + # - name: Run yamllint + # run: yamllint . + + + # shellcheck: + # name: Shell Lint + # runs-on: ubuntu-22.04 + # steps: + # - uses: actions/checkout@v4 + # - name: install ShellCheck + # run: sudo apt-get install -y shellcheck + # - name: Run ShellCheck + # run: python3 run_shellcheck.py # Uses the default Python installed with Ubuntu + + + # colors-css: + # name: colors.css Check + # runs-on: ubuntu-22.04 + + # steps: + # - name: Checkout main branch + # uses: actions/checkout@v4 + # with: + # ref: main + # path: MAIN + + # - name: Checkout PR branch + # uses: actions/checkout@v4 + # with: + # path: PR + + # - name: Compare file size + # run: | + # FILEPATH="site/public/css/colors.css" + # MAIN_FILE="MAIN/$FILEPATH" + # PR_FILE="PR/$FILEPATH" + + # if [ ! -f "$MAIN_FILE" ]; then + # echo "Main file $MAIN_FILE does not exist." + # exit 1 + # fi + + # if [ ! -f "$PR_FILE" ]; then + # echo "PR file $PR_FILE does not exist." + # exit 1 + # fi + + # LINES_DIFF=$(($(wc -l < "$PR_FILE") - $(wc -l < "$MAIN_FILE"))) + + # if [ $LINES_DIFF -gt 0 ]; then + # echo "::error::colors.css has increased in size by $LINES_DIFF lines in this PR." + # echo "::error::Please use existing colors in colors.css instead of adding new ones, to keep the size of the file manageable." + # echo "::error::If adding to colors.css really is necessary for your PR, this requirement may be waived on maintainer review." + # exit $LINES_DIFF + # else + # echo "No lines added. OK." + # fi + + # db-check: + # name: DB Check + # runs-on: ubuntu-22.04 + # env: + # PGPASSWORD: submitty_dbuser + # MAIN_INSTALL_PATH: ${{ github.WORKSPACE }}/main + # MAIN_DATA_PATH: ${{ github.WORKSPACE }}/main/var + # MAIN_REPO_PATH: ${{ github.WORKSPACE }}/main/GIT_CHECKOUT + # PR_INSTALL_PATH: ${{ github.WORKSPACE }}/branch + # PR_DATA_PATH: ${{ github.WORKSPACE }}/branch/var + # PR_REPO_PATH: ${{ github.WORKSPACE }}/branch/GIT_CHECKOUT + + # services: + # postgres-main: + # image: postgres:12 + # env: + # POSTGRES_PASSWORD: submitty_dbuser + # POSTGRES_USER: postgres + # TZ: America/New_York + # ports: + # - 5432 + + # postgres-branch: + # image: postgres:12 + # env: + # POSTGRES_PASSWORD: submitty_dbuser + # POSTGRES_USER: postgres + # TZ: America/New_York + # ports: + # - 5432 + + # steps: + # - name: Setup Dependencies + # run: | + # sudo sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list' + # wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add - + + # sudo apt-get update + # sudo apt-get autoremove -y postgresql-14 postgresql-client-common + # sudo apt-get install -y postgresql-12 + # sudo rm /etc/postgresql/14 -rf + + # - name: Checkout Current Branch + # uses: actions/checkout@v4 + # with: + # path: branch/GIT_CHECKOUT/Submitty + # fetch-depth: 0 + + # - name: Find Merge Base + # run: | + # echo MBASE=$(git --git-dir ${PR_REPO_PATH}/Submitty/.git merge-base \ + # -a origin/main ${{ github.sha }}) >> $GITHUB_ENV + + # - name: Checkout main Branch + # uses: actions/checkout@v4 + # with: + # ref: ${{ env.MBASE || 'main' }} + # path: main/GIT_CHECKOUT/Submitty + + # - name: Download Required Packages + # run: | + # pip install -r <( + # grep -e "tzlocal" -e "sqlalchemy" -e "ruamel" \ + # -e "psycopg2" -e "docker" \ + # ${MAIN_REPO_PATH}/Submitty/.setup/pip/system_requirements.txt + # ) + # pip install ${MAIN_REPO_PATH}/Submitty/python_submitty_utils + + + # - name: Create Users and Groups + # run: | # Create users and groups + # sudo -E python3 ${MAIN_REPO_PATH}/Submitty/.setup/bin/create_untrusted_users.py + + # sudo addgroup submitty_daemonphp + # sudo addgroup submitty_daemoncgi + # sudo addgroup submitty_daemonphpcgi + # sudo addgroup submitty_course_builders + # sudo addgroup submitty_phpgrp + + # sudo adduser submitty_php --disabled-password --no-create-home + # sudo adduser submitty_cgi --disabled-password --no-create-home + # sudo adduser submitty_cgi submitty_phpgrp --no-create-home + # sudo adduser submitty_php shadow --no-create-home + # sudo adduser submitty_cgi shadow --no-create-home + # sudo adduser submitty_daemon --disabled-password --no-create-home + # sudo adduser submitty_php submitty_daemonphp --no-create-home + # sudo adduser submitty_daemon submitty_daemonphp --no-create-home + # sudo adduser submitty_cgi submitty_daemoncgi --no-create-home + # sudo adduser submitty_daemon submitty_daemoncgi --no-create-home + # sudo adduser submitty_daemon submitty_daemonphpcgi --no-create-home + # sudo adduser submitty_php submitty_daemonphpcgi --no-create-home + # sudo adduser submitty_cgi submitty_daemonphpcgi --no-create-home + # sudo adduser submitty_daemon docker --no-create-home + + # sudo useradd -p $(openssl passwd -1 submitty_dbuser) submitty_dbuser + + # - name: Configure Submitty + # run: | + # configure_submitty() { + # # $1->MAIN_INSTALL_PATH, $2->MAIN_DATA_PATH, $3->MAIN_REPO_PATH, $4->DB_PORT + # mkdir -vp "$2" && chmod -vR 777 "$2" + # mkdir -vp "$1/config" && chmod -vR 777 "$1/config" + # mkdir -vp "$1/site" && chmod -vR 777 "$1/site" + # mkdir -vp "$2/courses" && chmod -vR 777 "$2/courses" + + # ( + # echo "localhost" # database host + # echo "$4" # database port + # echo "" # global db user + # echo "submitty_dbuser" # global db pass + # echo "" # course db user + # echo "submitty_dbuser" # course db pass + # echo "" # timezone + # echo "" # default locale + # echo "http://localhost" # submitty url + # echo "" # vcs url + # echo "" # institution name + # echo "y" # user create account + # echo "" # sysadmin email + # echo "" # where to report + # echo "1" # PamAuth + # echo "" # sysadmin username + # echo "n" # email notification + # ) | tee /dev/stderr \ + # | sudo -E python3 "$3/Submitty/.setup/CONFIGURE_SUBMITTY.py" \ + # --install-dir "$1" --data-dir "$2" --debug + + # # Copy necessary files to the installation path + # cp -vr "$3/Submitty/sbin" "$1" + # sudo chmod -vR 777 "$1/config" + # sudo chmod -vR 777 "$1/sbin" + # } + + # configure_submitty "${MAIN_INSTALL_PATH}" "${MAIN_DATA_PATH}" \ + # "${MAIN_REPO_PATH}" "${{ job.services.postgres-main.ports['5432'] }}" + # configure_submitty "${PR_INSTALL_PATH}" "${PR_DATA_PATH}" \ + # "${PR_REPO_PATH}" "${{ job.services.postgres-branch.ports['5432'] }}" + + + # - name: Create Databases + # run: | + # psql -d postgres -h localhost -U postgres -p ${{ job.services.postgres-main.ports['5432'] }} \ + # -c "CREATE ROLE submitty_dbuser WITH SUPERUSER CREATEDB CREATEROLE LOGIN PASSWORD 'submitty_dbuser'"\ + # -c "CREATE ROLE submitty_course_dbuser WITH LOGIN PASSWORD 'submitty_dbuser'" + # psql -d postgres -h localhost -U submitty_dbuser -p ${{ job.services.postgres-main.ports['5432'] }} \ + # -c "CREATE DATABASE submitty" + + # psql -d postgres -h localhost -U postgres -p ${{ job.services.postgres-branch.ports['5432'] }} \ + # -c "CREATE ROLE submitty_dbuser WITH SUPERUSER CREATEDB CREATEROLE LOGIN PASSWORD 'submitty_dbuser'"\ + # -c "CREATE ROLE submitty_course_dbuser WITH LOGIN PASSWORD 'submitty_dbuser'" + # psql -d postgres -h localhost -U submitty_dbuser -p ${{ job.services.postgres-branch.ports['5432'] }} \ + # -c "CREATE DATABASE submitty" + + # - name: Create Database Dumper + # run: | # the original dumper requires a `su`, which is not needed when psql as a service + # ( + # echo 'pg_dump -Osx -d "$1" -f "$2" -h localhost -p "$3" -U postgres ' + # echo 'sed -i -e "'"/SELECT pg_catalog.set_config('search_path'/d"'"\' + # echo ' -e "/-- Dumped \(from\|by\)/d" \' + # echo ' -e "/SET default_table_access_method = /d" \' + # echo ' -e "s/FOR EACH ROW EXECUTE FUNCTION/FOR EACH ROW EXECUTE PROCEDURE/g" "$2"' + # ) > dbdump.sh + # chmod +x dbdump.sh + + # echo M=$([ "$(date +%-m)" -lt "7" ] && echo 's' || echo 'f') >> $GITHUB_ENV + # echo Y=$(date +%y) >> $GITHUB_ENV + + # mkdir -vp ${GITHUB_WORKSPACE}/dumped/main + # mkdir -vp ${GITHUB_WORKSPACE}/dumped/branch + + # - name: Setup Databases and Courses for main + # run: | # migrate main according to dumped master database (assume it is correct) + # python3 ${MAIN_REPO_PATH}/Submitty/migration/run_migrator.py -e master migrate --initial + + # sudo ln -vs /usr/bin/true /usr/bin/ldapadd + # sudo -E python3 ${MAIN_REPO_PATH}/Submitty/.setup/bin/setup_sample_courses.py \ + # blank --no_grading --data_dir ${MAIN_DATA_PATH} --install_dir ${MAIN_INSTALL_PATH} + + # sudo chmod -vR 777 ${MAIN_DATA_PATH}/courses + + # - name: Apply New Migrations from Current Branch + # run: | + # python3 ${PR_REPO_PATH}/Submitty/migration/run_migrator.py \ + # -e master -e course -c ${MAIN_INSTALL_PATH}/config migrate + + # - name: Setup Databases and Courses for Current Branch + # run: | + # python3 ${PR_REPO_PATH}/Submitty/migration/run_migrator.py -e master migrate --initial + + # sudo -E python3 ${PR_REPO_PATH}/Submitty/.setup/bin/setup_sample_courses.py \ + # blank --no_grading --data_dir ${PR_DATA_PATH} --install_dir ${PR_INSTALL_PATH} + + # sudo chmod -vR 777 ${PR_DATA_PATH}/courses + + # - name: Dump Migrated Databases + # run: | + # ./dbdump.sh "submitty" "${GITHUB_WORKSPACE}/dumped/main/master.sql"\ + # "${{ job.services.postgres-main.ports['5432'] }}" + # ./dbdump.sh "submitty_${M}${Y}_blank" "${GITHUB_WORKSPACE}/dumped/main/course.sql"\ + # "${{ job.services.postgres-main.ports['5432'] }}" + + # ./dbdump.sh "submitty" "${GITHUB_WORKSPACE}/dumped/branch/master.sql"\ + # "${{ job.services.postgres-branch.ports['5432'] }}" + # ./dbdump.sh "submitty_${M}${Y}_blank" "${GITHUB_WORKSPACE}/dumped/branch/course.sql"\ + # "${{ job.services.postgres-branch.ports['5432'] }}" + + # - name: Compare Migrated master Databases + # if: always() + # run: | + # diff --color ${GITHUB_WORKSPACE}/dumped/main/master.sql \ + # ${GITHUB_WORKSPACE}/dumped/branch/master.sql || { + # echo "::error:: Master databases are not identical, please check your migration" + # exit 1 + # } + + # - name: Compare Migrated course Databases + # if: always() + # run: | + # diff --color ${GITHUB_WORKSPACE}/dumped/main/course.sql \ + # ${GITHUB_WORKSPACE}/dumped/branch/course.sql || { + # echo "::error:: Course databases are not identical, please check your migration" + # exit 1 + # } + + # - name: Compare Migrated master Database with Provided Dump + # if: always() + # run: | + # diff --color ${GITHUB_WORKSPACE}/dumped/branch/master.sql \ + # ${PR_REPO_PATH}/Submitty/migration/migrator/data/submitty_db.sql || { + # echo "::error:: Wrong provided dump, please check your database dumps" + # exit 1 + # } + + # - name: Compare Migrated course Database with Provided Dump + # if: always() + # run: | + # diff --color ${GITHUB_WORKSPACE}/dumped/branch/course.sql \ + # ${PR_REPO_PATH}/Submitty/migration/migrator/data/course_tables.sql || { + # echo "::error:: Wrong provided dump, please check your database dumps" + # exit 1 + # } + + # - name: Checkout + # uses: actions/checkout@v4 + + # - name: Run git tests + # run: | + # cd ${PR_REPO_PATH} + # SEMESTER=$(python3 -c 'from datetime import datetime; today = datetime.today(); semester = ("s" if today.month < 7 else "f") + str(today.year)[-2:]; print(semester)') + # sudo python3 /usr/local/submitty/bin/generate_repos.py ${SEMESTER} sample open_homework + # bash tests/git_test.sh + # shell: bash + + # - name: Pack Artifacts + # if: failure() + # uses: actions/upload-artifact@v4 + # with: + # name: dumped_database + # path: ${{ github.WORKSPACE }}/dumped/**/*.sql + # retention-days: 3 Cypress-System: @@ -635,250 +644,250 @@ jobs: npm install file-saver --save npm install --production=false - - name: Run accessibility test - uses: cypress-io/github-action@v6 - with: - config: baseUrl=http://localhost - spec: cypress/e2e/Cypress-System/accessibility.spec.js - working-directory: ${{env.SUBMITTY_REPOSITORY}}/site - browser: chrome - - - name: Run API tests - working-directory: ${{env.SUBMITTY_REPOSITORY}}/site - run: npm run test:api - env: - BASE_URL: http://localhost - - - name: Stop autograding services - run: | - sudo systemctl stop submitty_autograding_worker - sudo systemctl stop submitty_autograding_shipper - - - name: Run autograding status test - uses: cypress-io/github-action@v6 - with: - config: baseUrl=http://localhost - spec: cypress/e2e/Cypress-System/autograding_status_1.spec.js - working-directory: ${{env.SUBMITTY_REPOSITORY}}/site - browser: chrome - env: autograding_shipper_off=True - - - name: Restart autograding shipper - run: | - sudo systemctl restart submitty_autograding_shipper - - - name: Run autograding status test - uses: cypress-io/github-action@v6 - with: - config: baseUrl=http://localhost - spec: cypress/e2e/Cypress-System/autograding_status_2.spec.js - working-directory: ${{env.SUBMITTY_REPOSITORY}}/site - browser: chrome - env: autograding_shipper_off=True - - - name: Restart autograding worker - run: | - sudo systemctl restart submitty_autograding_worker - - - name: Run cypress e2e login tests with PAM auth - uses: cypress-io/github-action@v6 - with: - config: baseUrl=http://localhost,chromeWebSecurity=false - spec: cypress/e2e/Cypress-System/login.spec.js - working-directory: ${{env.SUBMITTY_REPOSITORY}}/site - browser: chrome - - - name: Switch to database auth - run: sudo sed -ie "s/Pam/Database/g" ${SUBMITTY_INSTALL_DIR}/config/authentication.json - - - name: Run cypress e2e login tests with database auth - uses: cypress-io/github-action@v6 - with: - config: baseUrl=http://localhost - spec: cypress/e2e/Cypress-System/login.spec.js - working-directory: ${{env.SUBMITTY_REPOSITORY}}/site - browser: chrome - - - name: Switch to LDAP auth - run: sudo sed -ie "s/Database/Ldap/g" ${SUBMITTY_INSTALL_DIR}/config/authentication.json - - - name: Run cypress e2e login tests with LDAP auth - uses: cypress-io/github-action@v6 - with: - config: baseUrl=http://localhost - spec: cypress/e2e/Cypress-System/login.spec.js - working-directory: ${{env.SUBMITTY_REPOSITORY}}/site - browser: chrome - - - name: Setup SAML - run: | - cd $SUBMITTY_REPOSITORY - sudo -E env "PATH=$PATH" bash .setup/testing/setup_saml.sh - - - name: Switch to SAML auth - run: sudo sed -ie "s/Ldap/Saml/g" ${SUBMITTY_INSTALL_DIR}/config/authentication.json - - - name: Run cypress e2e login tests with SAML auth - uses: cypress-io/github-action@v6 - with: - config: baseUrl=http://localhost,chromeWebSecurity=false - spec: cypress/e2e/Cypress-System/login.spec.js - working-directory: ${{env.SUBMITTY_REPOSITORY}}/site - browser: chrome - - - name: Setup HTTP/2 - run: | - cd $SUBMITTY_REPOSITORY - if [ -f .setup/dev-upgrade-h2.sh ]; then - sudo sed -e "s/:80/:443/g" --in-place /etc/apache2/sites-available/submitty.conf - sudo -E env "PATH=$PATH" bash .setup/dev-upgrade-h2.sh up --i-know-what-i-am-doing-please-go-ahead \ - && echo "Setup OK" \ - || { - echo "::warning::Setup Failed" - sudo sed -e "s/:443/:80/g" --in-place /etc/apache2/sites-available/submitty.conf - } - else - echo "Could not find dev-upgrade-h2.sh, skipping" - fi - - - name: Test HTTP/2 Connection - run: | - http_ver=$(curl -ksI https://localhost -o/dev/null -w "%{http_version}\n") - [ "$http_ver" = "2" ] && echo "Pass" || echo "::warning::Failed" - - - - uses: actions/upload-artifact@v4 - if: failure() - with: - name: cypress-screenshots - path: ${{env.SUBMITTY_REPOSITORY}}/site/cypress/screenshots - - uses: actions/upload-artifact@v4 - if: failure() - with: - name: cypress-videos - path: ${{env.SUBMITTY_REPOSITORY}}/site/cypress/videos - - - name: Check for site errors - working-directory: ${{ env.SUBMITTY_REPOSITORY }} - run: sudo bash tests/test_site_error_log.sh - - Cypress: - runs-on: ubuntu-22.04 - strategy: - fail-fast: false - matrix: - containers: ["Admin", "Feature", "Gradeable", "TAGrading", "UI"] - services: - postgres: - image: postgres - env: - POSTGRES_PASSWORD: submitty_dbuser - POSTGRES_USER: postgres - TZ: America/New_York - options: >- - --health-cmd pg_isready - --health-interval 10s - --health-timeout 5s - --health-retries 5 - ports: - - 5432:5432 - - steps: - - name: Checkout repository - uses: actions/checkout@v4 - - uses: ./.github/actions/e2e-Setup-Composite - # TODO: Remove this block after upgrading jsPDF - - name: Cache Node Modules - uses: actions/cache@v4 - with: - path: ~/.npm - key: ${{ runner.os }}-cache-node-modules-dev-${{ hashFiles('**/package-lock.json') }} - restore-keys: | - ${{ runner.os }}-cache-node-modules-dev - - - name: Install node dependencies - working-directory: ${{env.SUBMITTY_REPOSITORY}}/site - run: | - npm install file-saver --save - npm install --production=false - - - name: Run cypress e2e tests with pam auth - uses: cypress-io/github-action@v6 - with: - config: baseUrl=http://localhost - working-directory: ${{env.SUBMITTY_REPOSITORY}}/site - spec: cypress/e2e/Cypress-${{matrix.containers}}/* - browser: chrome - env: run_area=CI - - - name: Check for site errors - working-directory: ${{ env.SUBMITTY_REPOSITORY }} - run: sudo bash tests/test_site_error_log.sh - - - uses: actions/upload-artifact@v4 - if: failure() - with: - name: cypress-screenshots - path: ${{env.SUBMITTY_REPOSITORY}}/site/cypress/screenshots - - uses: actions/upload-artifact@v4 - if: failure() - with: - name: cypress-videos - path: ${{env.SUBMITTY_REPOSITORY}}/site/cypress/videos - - - Integration: - name: Integration - runs-on: ubuntu-22.04 - # Postgres should not be needed for the integration tests. - # But unfortunately Configure test suite seems to use it at the moment, and - # Configure test suite seems to be necessary for the Integration tests - services: - postgres: - image: postgres - env: - POSTGRES_PASSWORD: submitty_dbuser - POSTGRES_USER: postgres - TZ: America/New_York - options: >- - --health-cmd pg_isready - --health-interval 10s - --health-timeout 5s - --health-retries 5 - ports: - - 5432:5432 - - steps: - - name: Checkout repository - uses: actions/checkout@v4 - - uses: ./.github/actions/e2e-Setup-Composite - - name: Run integration tests - run: sudo -E env "PATH=$PATH" python3 /usr/local/submitty/test_suite/integrationTests/run.py - - - ansible-install: - name: Ansible Install - runs-on: ubuntu-22.04 - steps: - - uses: actions/checkout@v4 - - name: Setup SSH - shell: bash - run: | - ssh-keygen -t rsa -b 4096 -C "github_ci" -N '' -f /home/runner/.ssh/id_rsa - ssh-keyscan -t rsa localhost >> /home/runner/.ssh/known_hosts - cat /home/runner/.ssh/id_rsa.pub >> /home/runner/.ssh/authorized_keys - ssh -T localhost - sudo systemctl start postgresql - - - name: Run ansible script - shell: bash - run: | - cd .setup/ansible - ansible-playbook --private-key /home/runner/.ssh/id_rsa -e 'ansible_user=runner' -i inventory/submitty playbooks/submitty_install.yml - - name: Validate image - run: curl --show-error --fail --include http://localhost/authentication/login - - uses: actions/upload-artifact@v4 - if: failure() - with: - name: install-log - path: /usr/local/submitty/install.log + # - name: Run accessibility test + # uses: cypress-io/github-action@v6 + # with: + # config: baseUrl=http://localhost + # spec: cypress/e2e/Cypress-System/accessibility.spec.js + # working-directory: ${{env.SUBMITTY_REPOSITORY}}/site + # browser: chrome + + # - name: Run API tests + # working-directory: ${{env.SUBMITTY_REPOSITORY}}/site + # run: npm run test:api + # env: + # BASE_URL: http://localhost + + # - name: Stop autograding services + # run: | + # sudo systemctl stop submitty_autograding_worker + # sudo systemctl stop submitty_autograding_shipper + + # - name: Run autograding status test + # uses: cypress-io/github-action@v6 + # with: + # config: baseUrl=http://localhost + # spec: cypress/e2e/Cypress-System/autograding_status_1.spec.js + # working-directory: ${{env.SUBMITTY_REPOSITORY}}/site + # browser: chrome + # env: autograding_shipper_off=True + + # - name: Restart autograding shipper + # run: | + # sudo systemctl restart submitty_autograding_shipper + + # - name: Run autograding status test + # uses: cypress-io/github-action@v6 + # with: + # config: baseUrl=http://localhost + # spec: cypress/e2e/Cypress-System/autograding_status_2.spec.js + # working-directory: ${{env.SUBMITTY_REPOSITORY}}/site + # browser: chrome + # env: autograding_shipper_off=True + + # - name: Restart autograding worker + # run: | + # sudo systemctl restart submitty_autograding_worker + + # - name: Run cypress e2e login tests with PAM auth + # uses: cypress-io/github-action@v6 + # with: + # config: baseUrl=http://localhost,chromeWebSecurity=false + # spec: cypress/e2e/Cypress-System/login.spec.js + # working-directory: ${{env.SUBMITTY_REPOSITORY}}/site + # browser: chrome + + # - name: Switch to database auth + # run: sudo sed -ie "s/Pam/Database/g" ${SUBMITTY_INSTALL_DIR}/config/authentication.json + + # - name: Run cypress e2e login tests with database auth + # uses: cypress-io/github-action@v6 + # with: + # config: baseUrl=http://localhost + # spec: cypress/e2e/Cypress-System/login.spec.js + # working-directory: ${{env.SUBMITTY_REPOSITORY}}/site + # browser: chrome + + # - name: Switch to LDAP auth + # run: sudo sed -ie "s/Database/Ldap/g" ${SUBMITTY_INSTALL_DIR}/config/authentication.json + + # - name: Run cypress e2e login tests with LDAP auth + # uses: cypress-io/github-action@v6 + # with: + # config: baseUrl=http://localhost + # spec: cypress/e2e/Cypress-System/login.spec.js + # working-directory: ${{env.SUBMITTY_REPOSITORY}}/site + # browser: chrome + + # - name: Setup SAML + # run: | + # cd $SUBMITTY_REPOSITORY + # sudo -E env "PATH=$PATH" bash .setup/testing/setup_saml.sh + + # - name: Switch to SAML auth + # run: sudo sed -ie "s/Ldap/Saml/g" ${SUBMITTY_INSTALL_DIR}/config/authentication.json + + # - name: Run cypress e2e login tests with SAML auth + # uses: cypress-io/github-action@v6 + # with: + # config: baseUrl=http://localhost,chromeWebSecurity=false + # spec: cypress/e2e/Cypress-System/login.spec.js + # working-directory: ${{env.SUBMITTY_REPOSITORY}}/site + # browser: chrome + + # - name: Setup HTTP/2 + # run: | + # cd $SUBMITTY_REPOSITORY + # if [ -f .setup/dev-upgrade-h2.sh ]; then + # sudo sed -e "s/:80/:443/g" --in-place /etc/apache2/sites-available/submitty.conf + # sudo -E env "PATH=$PATH" bash .setup/dev-upgrade-h2.sh up --i-know-what-i-am-doing-please-go-ahead \ + # && echo "Setup OK" \ + # || { + # echo "::warning::Setup Failed" + # sudo sed -e "s/:443/:80/g" --in-place /etc/apache2/sites-available/submitty.conf + # } + # else + # echo "Could not find dev-upgrade-h2.sh, skipping" + # fi + + # - name: Test HTTP/2 Connection + # run: | + # http_ver=$(curl -ksI https://localhost -o/dev/null -w "%{http_version}\n") + # [ "$http_ver" = "2" ] && echo "Pass" || echo "::warning::Failed" + + + # - uses: actions/upload-artifact@v4 + # if: failure() + # with: + # name: cypress-screenshots + # path: ${{env.SUBMITTY_REPOSITORY}}/site/cypress/screenshots + # - uses: actions/upload-artifact@v4 + # if: failure() + # with: + # name: cypress-videos + # path: ${{env.SUBMITTY_REPOSITORY}}/site/cypress/videos + + # - name: Check for site errors + # working-directory: ${{ env.SUBMITTY_REPOSITORY }} + # run: sudo bash tests/test_site_error_log.sh + + # Cypress: + # runs-on: ubuntu-22.04 + # strategy: + # fail-fast: false + # matrix: + # containers: ["Admin", "Feature", "Gradeable", "TAGrading", "UI"] + # services: + # postgres: + # image: postgres + # env: + # POSTGRES_PASSWORD: submitty_dbuser + # POSTGRES_USER: postgres + # TZ: America/New_York + # options: >- + # --health-cmd pg_isready + # --health-interval 10s + # --health-timeout 5s + # --health-retries 5 + # ports: + # - 5432:5432 + + # steps: + # - name: Checkout repository + # uses: actions/checkout@v4 + # - uses: ./.github/actions/e2e-Setup-Composite + # # TODO: Remove this block after upgrading jsPDF + # - name: Cache Node Modules + # uses: actions/cache@v4 + # with: + # path: ~/.npm + # key: ${{ runner.os }}-cache-node-modules-dev-${{ hashFiles('**/package-lock.json') }} + # restore-keys: | + # ${{ runner.os }}-cache-node-modules-dev + + # - name: Install node dependencies + # working-directory: ${{env.SUBMITTY_REPOSITORY}}/site + # run: | + # npm install file-saver --save + # npm install --production=false + + # - name: Run cypress e2e tests with pam auth + # uses: cypress-io/github-action@v6 + # with: + # config: baseUrl=http://localhost + # working-directory: ${{env.SUBMITTY_REPOSITORY}}/site + # spec: cypress/e2e/Cypress-${{matrix.containers}}/* + # browser: chrome + # env: run_area=CI + + # - name: Check for site errors + # working-directory: ${{ env.SUBMITTY_REPOSITORY }} + # run: sudo bash tests/test_site_error_log.sh + + # - uses: actions/upload-artifact@v4 + # if: failure() + # with: + # name: cypress-screenshots + # path: ${{env.SUBMITTY_REPOSITORY}}/site/cypress/screenshots + # - uses: actions/upload-artifact@v4 + # if: failure() + # with: + # name: cypress-videos + # path: ${{env.SUBMITTY_REPOSITORY}}/site/cypress/videos + + + # Integration: + # name: Integration + # runs-on: ubuntu-22.04 + # # Postgres should not be needed for the integration tests. + # # But unfortunately Configure test suite seems to use it at the moment, and + # # Configure test suite seems to be necessary for the Integration tests + # services: + # postgres: + # image: postgres + # env: + # POSTGRES_PASSWORD: submitty_dbuser + # POSTGRES_USER: postgres + # TZ: America/New_York + # options: >- + # --health-cmd pg_isready + # --health-interval 10s + # --health-timeout 5s + # --health-retries 5 + # ports: + # - 5432:5432 + + # steps: + # - name: Checkout repository + # uses: actions/checkout@v4 + # - uses: ./.github/actions/e2e-Setup-Composite + # - name: Run integration tests + # run: sudo -E env "PATH=$PATH" python3 /usr/local/submitty/test_suite/integrationTests/run.py + + + # ansible-install: + # name: Ansible Install + # runs-on: ubuntu-22.04 + # steps: + # - uses: actions/checkout@v4 + # - name: Setup SSH + # shell: bash + # run: | + # ssh-keygen -t rsa -b 4096 -C "github_ci" -N '' -f /home/runner/.ssh/id_rsa + # ssh-keyscan -t rsa localhost >> /home/runner/.ssh/known_hosts + # cat /home/runner/.ssh/id_rsa.pub >> /home/runner/.ssh/authorized_keys + # ssh -T localhost + # sudo systemctl start postgresql + + # - name: Run ansible script + # shell: bash + # run: | + # cd .setup/ansible + # ansible-playbook --private-key /home/runner/.ssh/id_rsa -e 'ansible_user=runner' -i inventory/submitty playbooks/submitty_install.yml + # - name: Validate image + # run: curl --show-error --fail --include http://localhost/authentication/login + # - uses: actions/upload-artifact@v4 + # if: failure() + # with: + # name: install-log + # path: /usr/local/submitty/install.log diff --git a/.setup/CONFIGURE_SUBMITTY.py b/.setup/CONFIGURE_SUBMITTY.py index cb897a83384..2486ed0491c 100644 --- a/.setup/CONFIGURE_SUBMITTY.py +++ b/.setup/CONFIGURE_SUBMITTY.py @@ -185,6 +185,7 @@ def __call__(self, parser, namespace, values, option_string=None): 'authentication_method': 0, 'institution_name' : '', 'institution_homepage' : '', + 'user_create_account' : False, 'timezone' : str(tzlocal.get_localzone()), 'submitty_admin_username': '', 'email_user': '', @@ -309,7 +310,16 @@ def __call__(self, parser, namespace, values, option_string=None): INSTITUTION_HOMEPAGE = '' print() - + while True: + user_create_account = get_input("Enable Create New Account feature? [y/n]", 'y') + if (user_create_account.lower() in ['yes', 'y']): + USER_CREATE_ACCOUNT = True + break + elif (user_create_account.lower() in ['no', 'n']): + USER_CREATE_ACCOUNT = False + break + print() + SYS_ADMIN_EMAIL = get_input("What is the email for system administration?", defaults['sys_admin_email']) SYS_ADMIN_URL = get_input("Where to report problems with Submitty (url for help link)?", defaults['sys_admin_url']) @@ -445,6 +455,7 @@ def __call__(self, parser, namespace, values, option_string=None): config['institution_name'] = INSTITUTION_NAME config['institution_homepage'] = INSTITUTION_HOMEPAGE + config['user_create_account'] = USER_CREATE_ACCOUNT config['debugging_enabled'] = DEBUGGING_ENABLED # site_log_path is a holdover name. This could more accurately be called the "log_path" @@ -627,6 +638,27 @@ def write(x=''): config['sys_admin_url'] = SYS_ADMIN_URL # site_log_path is a holdover name. This could more accurately be called the "log_path" config['site_log_path'] = TAGRADING_LOG_PATH +user_id_requirements = { + "all": True, + "require_name": False, + "length": 25, + "name_requirements": { + "given_first": False, + "given_name": 2, + "family_name": 4 + }, + "require_email": False, + "email_requirements": { + "whole_email": False, + "whole_prefix": False, + "prefix_count": 6 + } +} + +accepted_emails = { + "gmail.com": True, + "rpi.edu": True +} if not args.worker: config['submission_url'] = SUBMISSION_URL @@ -638,6 +670,9 @@ def write(x=''): config['timezone'] = TIMEZONE config['default_locale'] = DEFAULT_LOCALE config['duck_special_effects'] = False + config['user_create_account'] = USER_CREATE_ACCOUNT + config['accepted_emails'] = accepted_emails + config['user_id_requirements'] = user_id_requirements config['worker'] = True if args.worker == 1 else False diff --git a/.setup/ansible/roles/submitty_install/defaults/main.yml b/.setup/ansible/roles/submitty_install/defaults/main.yml index 84768b0513d..cee9ffb82ec 100644 --- a/.setup/ansible/roles/submitty_install/defaults/main.yml +++ b/.setup/ansible/roles/submitty_install/defaults/main.yml @@ -11,6 +11,7 @@ submitty_install_language: en_US submitty_install_submitty_url: localhost submitty_install_vcs_url: git.localhost submitty_install_institution_name: Example University +submitty_install_self_account_creation: n submitty_install_sysadmin_email: sysadmin@localhost submitty_install_submitty_email: submitty@localhost submitty_install_institution_url: localhost diff --git a/.setup/ansible/roles/submitty_install/tasks/main.yml b/.setup/ansible/roles/submitty_install/tasks/main.yml index 3c9264aadee..f1c15ac2460 100644 --- a/.setup/ansible/roles/submitty_install/tasks/main.yml +++ b/.setup/ansible/roles/submitty_install/tasks/main.yml @@ -44,6 +44,7 @@ {{ 'https' if submitty_install_ssl_enabled else 'http' }}://{{ submitty_install_submitty_url }} {{ submitty_install_vcs_url }} {{ submitty_install_institution_name }} + {{ submitty_install_self_account_creation }} {{ submitty_install_sysadmin_email }} {{ submitty_install_submitty_email }} {{ submitty_install_institution_url }} diff --git a/.setup/data/courses/sample.yml b/.setup/data/courses/sample.yml index c5d0b59a851..91d27fc1ca8 100644 --- a/.setup/data/courses/sample.yml +++ b/.setup/data/courses/sample.yml @@ -7,246 +7,316 @@ no_rotating_students: 15 unregistered_students: 15 make_customization: true gradeables: - - g_id: future_peer_grading - g_title: Future Peer Homework - gradeable_config: python_simple_homework - eg_peer_grading: true - components: - - gc_lower_clamp: 0 - gc_is_peer: true - gc_default: 2 - gc_max_value: 2 - gc_upper_clamp: 2 - gc_title: Read Me - marks: - - gcm_note: Full Credit - gcm_points: 0 - - gcm_note: Minor errors in Read Me - gcm_points: -1 - - gcm_note: Major errors in Read Me or Read Me missing - gcm_points: -2 - - gc_lower_clamp: 0 - gc_default: 5 - gc_is_peer: true - gc_max_value: 5 - gc_upper_clamp: 5 - gc_title: Coding Style - marks: - - gcm_note: Full Credit - gcm_points: 0 - - gcm_note: Code is unreadable - gcm_points: -5 - - gcm_note: Code is very difficult to understand - gcm_points: -3 - - gcm_note: Code is difficult to understand - gcm_points: -1 - - gc_lower_clamp: 0 - gc_default: 5 - gc_max_value: 5 - gc_upper_clamp: 5 - gc_is_peer: true - gc_title: Documentation - marks: - - gcm_note: Full Credit - gcm_points: 0 - - gcm_note: No documentation - gcm_points: -5 - - gcm_note: Very little documentation or documentation makes no sense - gcm_points: -3 - - gcm_note: Way too much documentation and/or documentation makes no sense - gcm_points: -1 - - gc_lower_clamp: 0 - gc_default: 0 - gc_max_value: 0 - gc_upper_clamp: 5 - gc_title: Extra Credit - marks: - - gcm_note: No Credit - gcm_points: 0 - - gcm_note: Extra credit done poorly - gcm_points: 2 - - gcm_note: Extra credit is acceptable - gcm_points: 5 - g_ta_view_start_date: 9994-12-31 23:59:59 - eg_submission_open_date: 9995-12-31 23:59:59 - eg_submission_due_date: 9996-12-31 23:59:59 - g_grade_start_date: 9997-12-31 23:59:59 - g_grade_due_date: 9998-12-31 23:59:59 - g_grade_released_date: 9998-12-31 23:59:59 - eg_grade_inquiry_start_date: 9999-01-01 23:59:59 - eg_grade_inquiry_due_date: 9999-01-06 23:59:59 - eg_has_due_date: true - eg_has_release_date: true - g_bucket: homework + # - g_id: future_peer_grading + # g_title: Future Peer Homework + # gradeable_config: python_simple_homework + # eg_peer_grading: true + # components: + # - gc_lower_clamp: 0 + # gc_is_peer: true + # gc_default: 2 + # gc_max_value: 2 + # gc_upper_clamp: 2 + # gc_title: Read Me + # marks: + # - gcm_note: Full Credit + # gcm_points: 0 + # - gcm_note: Minor errors in Read Me + # gcm_points: -1 + # - gcm_note: Major errors in Read Me or Read Me missing + # gcm_points: -2 + # - gc_lower_clamp: 0 + # gc_default: 5 + # gc_is_peer: true + # gc_max_value: 5 + # gc_upper_clamp: 5 + # gc_title: Coding Style + # marks: + # - gcm_note: Full Credit + # gcm_points: 0 + # - gcm_note: Code is unreadable + # gcm_points: -5 + # - gcm_note: Code is very difficult to understand + # gcm_points: -3 + # - gcm_note: Code is difficult to understand + # gcm_points: -1 + # - gc_lower_clamp: 0 + # gc_default: 5 + # gc_max_value: 5 + # gc_upper_clamp: 5 + # gc_is_peer: true + # gc_title: Documentation + # marks: + # - gcm_note: Full Credit + # gcm_points: 0 + # - gcm_note: No documentation + # gcm_points: -5 + # - gcm_note: Very little documentation or documentation makes no sense + # gcm_points: -3 + # - gcm_note: Way too much documentation and/or documentation makes no sense + # gcm_points: -1 + # - gc_lower_clamp: 0 + # gc_default: 0 + # gc_max_value: 0 + # gc_upper_clamp: 5 + # gc_title: Extra Credit + # marks: + # - gcm_note: No Credit + # gcm_points: 0 + # - gcm_note: Extra credit done poorly + # gcm_points: 2 + # - gcm_note: Extra credit is acceptable + # gcm_points: 5 + # g_ta_view_start_date: 9994-12-31 23:59:59 + # eg_submission_open_date: 9995-12-31 23:59:59 + # eg_submission_due_date: 9996-12-31 23:59:59 + # g_grade_start_date: 9997-12-31 23:59:59 + # g_grade_due_date: 9998-12-31 23:59:59 + # g_grade_released_date: 9998-12-31 23:59:59 + # eg_grade_inquiry_start_date: 9999-01-01 23:59:59 + # eg_grade_inquiry_due_date: 9999-01-06 23:59:59 + # eg_has_due_date: true + # eg_has_release_date: true + # g_bucket: homework - - g_id: future_no_tas_homework - g_title: Future (No TAs) Homework - gradeable_config: python_simple_homework - components: - - gc_lower_clamp: 0 - gc_default: 2 - gc_max_value: 2 - gc_upper_clamp: 2 - gc_title: Read Me - marks: - - gcm_note: Full Credit - gcm_points: 0 - - gcm_note: Minor errors in Read Me - gcm_points: -1 - - gcm_note: Major errors in Read Me or Read Me missing - gcm_points: -2 - - gc_lower_clamp: 0 - gc_default: 5 - gc_max_value: 5 - gc_upper_clamp: 5 - gc_title: Coding Style - marks: - - gcm_note: Full Credit - gcm_points: 0 - - gcm_note: Code is unreadable - gcm_points: -5 - - gcm_note: Code is very difficult to understand - gcm_points: -3 - - gcm_note: Code is difficult to understand - gcm_points: -1 - - gc_lower_clamp: 0 - gc_default: 5 - gc_max_value: 5 - gc_upper_clamp: 5 - gc_title: Documentation - marks: - - gcm_note: Full Credit - gcm_points: 0 - - gcm_note: No documentation - gcm_points: -5 - - gcm_note: Very little documentation or documentation makes no sense - gcm_points: -3 - - gcm_note: Way too much documentation and/or documentation makes no sense - gcm_points: -1 - - gc_lower_clamp: 0 - gc_default: 0 - gc_max_value: 0 - gc_upper_clamp: 5 - gc_title: Extra Credit - marks: - - gcm_note: No Credit - gcm_points: 0 - - gcm_note: Extra credit done poorly - gcm_points: 2 - - gcm_note: Extra credit is acceptable - gcm_points: 5 - g_ta_view_start_date: 9994-12-31 23:59:59 - eg_submission_open_date: 9995-12-31 23:59:59 - eg_submission_due_date: 9996-12-31 23:59:59 - g_grade_start_date: 9997-12-31 23:59:59 - g_grade_due_date: 9998-12-31 23:59:59 - g_grade_released_date: 9998-12-31 23:59:59 - eg_grade_inquiry_start_date: 9999-01-01 23:59:59 - eg_grade_inquiry_due_date: 9999-01-06 23:59:59 - eg_has_due_date: true - eg_has_release_date: true - g_bucket: homework + # - g_id: future_no_tas_homework + # g_title: Future (No TAs) Homework + # gradeable_config: python_simple_homework + # components: + # - gc_lower_clamp: 0 + # gc_default: 2 + # gc_max_value: 2 + # gc_upper_clamp: 2 + # gc_title: Read Me + # marks: + # - gcm_note: Full Credit + # gcm_points: 0 + # - gcm_note: Minor errors in Read Me + # gcm_points: -1 + # - gcm_note: Major errors in Read Me or Read Me missing + # gcm_points: -2 + # - gc_lower_clamp: 0 + # gc_default: 5 + # gc_max_value: 5 + # gc_upper_clamp: 5 + # gc_title: Coding Style + # marks: + # - gcm_note: Full Credit + # gcm_points: 0 + # - gcm_note: Code is unreadable + # gcm_points: -5 + # - gcm_note: Code is very difficult to understand + # gcm_points: -3 + # - gcm_note: Code is difficult to understand + # gcm_points: -1 + # - gc_lower_clamp: 0 + # gc_default: 5 + # gc_max_value: 5 + # gc_upper_clamp: 5 + # gc_title: Documentation + # marks: + # - gcm_note: Full Credit + # gcm_points: 0 + # - gcm_note: No documentation + # gcm_points: -5 + # - gcm_note: Very little documentation or documentation makes no sense + # gcm_points: -3 + # - gcm_note: Way too much documentation and/or documentation makes no sense + # gcm_points: -1 + # - gc_lower_clamp: 0 + # gc_default: 0 + # gc_max_value: 0 + # gc_upper_clamp: 5 + # gc_title: Extra Credit + # marks: + # - gcm_note: No Credit + # gcm_points: 0 + # - gcm_note: Extra credit done poorly + # gcm_points: 2 + # - gcm_note: Extra credit is acceptable + # gcm_points: 5 + # g_ta_view_start_date: 9994-12-31 23:59:59 + # eg_submission_open_date: 9995-12-31 23:59:59 + # eg_submission_due_date: 9996-12-31 23:59:59 + # g_grade_start_date: 9997-12-31 23:59:59 + # g_grade_due_date: 9998-12-31 23:59:59 + # g_grade_released_date: 9998-12-31 23:59:59 + # eg_grade_inquiry_start_date: 9999-01-01 23:59:59 + # eg_grade_inquiry_due_date: 9999-01-06 23:59:59 + # eg_has_due_date: true + # eg_has_release_date: true + # g_bucket: homework - - g_id: future_tas_homework - components: - - gc_lower_clamp: 0 - gc_default: 2 - gc_max_value: 2 - gc_upper_clamp: 2 - gc_title: Read Me - marks: - - gcm_note: Full Credit - gcm_points: 0 - - gcm_note: Minor errors in Read Me - gcm_points: -1 - - gcm_note: Major errors in Read Me or Read Me missing - gcm_points: -2 - - gc_lower_clamp: 0 - gc_default: 5 - gc_max_value: 5 - gc_upper_clamp: 5 - gc_title: Coding Style - marks: - - gcm_note: Full Credit - gcm_points: 0 - - gcm_note: Code is unreadable - gcm_points: -5 - - gcm_note: Code is very difficult to understand - gcm_points: -3 - - gcm_note: Code is difficult to understand - gcm_points: -1 - - gc_lower_clamp: 0 - gc_default: 5 - gc_max_value: 5 - gc_upper_clamp: 5 - gc_title: Documentation - marks: - - gcm_note: Full Credit - gcm_points: 0 - - gcm_note: No documentation - gcm_points: -5 - - gcm_note: Very little documentation or documentation makes no sense - gcm_points: -3 - - gcm_note: Way too much documentation and/or documentation makes no sense - gcm_points: -1 - - gc_lower_clamp: 0 - gc_default: 0 - gc_max_value: 0 - gc_upper_clamp: 5 - gc_title: Extra Credit - marks: - - gcm_note: No Credit - gcm_points: 0 - - gcm_note: Extra credit done poorly - gcm_points: 2 - - gcm_note: Extra credit is acceptable - gcm_points: 5 - eg_submission_due_date: 9996-12-31 23:59:59 - eg_submission_open_date: 9995-12-31 23:59:59 - g_grade_due_date: 9998-12-31 23:59:59 - g_grade_released_date: 9998-12-31 23:59:59 - g_grade_start_date: 9997-12-31 23:59:59 - g_ta_view_start_date: 1970-01-01 23:59:59 - eg_grade_inquiry_start_date: 9999-01-01 23:59:59 - eg_grade_inquiry_due_date: 9999-01-06 23:59:59 - eg_has_due_date: true - eg_has_release_date: true - g_title: Future (TAs) Homework - gradeable_config: python_simple_homework - g_bucket: homework + # - g_id: future_tas_homework + # components: + # - gc_lower_clamp: 0 + # gc_default: 2 + # gc_max_value: 2 + # gc_upper_clamp: 2 + # gc_title: Read Me + # marks: + # - gcm_note: Full Credit + # gcm_points: 0 + # - gcm_note: Minor errors in Read Me + # gcm_points: -1 + # - gcm_note: Major errors in Read Me or Read Me missing + # gcm_points: -2 + # - gc_lower_clamp: 0 + # gc_default: 5 + # gc_max_value: 5 + # gc_upper_clamp: 5 + # gc_title: Coding Style + # marks: + # - gcm_note: Full Credit + # gcm_points: 0 + # - gcm_note: Code is unreadable + # gcm_points: -5 + # - gcm_note: Code is very difficult to understand + # gcm_points: -3 + # - gcm_note: Code is difficult to understand + # gcm_points: -1 + # - gc_lower_clamp: 0 + # gc_default: 5 + # gc_max_value: 5 + # gc_upper_clamp: 5 + # gc_title: Documentation + # marks: + # - gcm_note: Full Credit + # gcm_points: 0 + # - gcm_note: No documentation + # gcm_points: -5 + # - gcm_note: Very little documentation or documentation makes no sense + # gcm_points: -3 + # - gcm_note: Way too much documentation and/or documentation makes no sense + # gcm_points: -1 + # - gc_lower_clamp: 0 + # gc_default: 0 + # gc_max_value: 0 + # gc_upper_clamp: 5 + # gc_title: Extra Credit + # marks: + # - gcm_note: No Credit + # gcm_points: 0 + # - gcm_note: Extra credit done poorly + # gcm_points: 2 + # - gcm_note: Extra credit is acceptable + # gcm_points: 5 + # eg_submission_due_date: 9996-12-31 23:59:59 + # eg_submission_open_date: 9995-12-31 23:59:59 + # g_grade_due_date: 9998-12-31 23:59:59 + # g_grade_released_date: 9998-12-31 23:59:59 + # g_grade_start_date: 9997-12-31 23:59:59 + # g_ta_view_start_date: 1970-01-01 23:59:59 + # eg_grade_inquiry_start_date: 9999-01-01 23:59:59 + # eg_grade_inquiry_due_date: 9999-01-06 23:59:59 + # eg_has_due_date: true + # eg_has_release_date: true + # g_title: Future (TAs) Homework + # gradeable_config: python_simple_homework + # g_bucket: homework - - g_id: bulk_upload_test - g_title: Bulk Upload Scanned Exam - gradeable_config: pdf_exam - components: - - gc_lower_clamp: 0 - gc_default: 5 - gc_max_value: 5 - gc_upper_clamp: 5 - gc_title: Question 1 - marks: - - gcm_note: Full Credit - gcm_points: 0 - - gcm_note: Question 1 Mark 1 - gcm_points: -5 - g_ta_view_start_date: 9994-12-31 23:59:59 - eg_submission_open_date: 9995-12-31 23:59:59 - eg_submission_due_date: 9996-12-31 23:59:59 - g_grade_start_date: 9997-12-31 23:59:59 - g_grade_due_date: 9998-12-31 23:59:59 - g_grade_released_date: 9998-12-31 23:59:59 - eg_grade_inquiry_start_date: 9999-01-01 23:59:59 - eg_grade_inquiry_due_date: 9999-01-06 23:59:59 - eg_has_due_date: true - eg_has_release_date: true - g_bucket: homework - eg_bulk_test: true + # - g_id: bulk_upload_test + # g_title: Bulk Upload Scanned Exam + # gradeable_config: pdf_exam + # components: + # - gc_lower_clamp: 0 + # gc_default: 5 + # gc_max_value: 5 + # gc_upper_clamp: 5 + # gc_title: Question 1 + # marks: + # - gcm_note: Full Credit + # gcm_points: 0 + # - gcm_note: Question 1 Mark 1 + # gcm_points: -5 + # g_ta_view_start_date: 9994-12-31 23:59:59 + # eg_submission_open_date: 9995-12-31 23:59:59 + # eg_submission_due_date: 9996-12-31 23:59:59 + # g_grade_start_date: 9997-12-31 23:59:59 + # g_grade_due_date: 9998-12-31 23:59:59 + # g_grade_released_date: 9998-12-31 23:59:59 + # eg_grade_inquiry_start_date: 9999-01-01 23:59:59 + # eg_grade_inquiry_due_date: 9999-01-06 23:59:59 + # eg_has_due_date: true + # eg_has_release_date: true + # g_bucket: homework + # eg_bulk_test: true - - g_id: open_peer_homework - eg_peer_grading: true + # - g_id: open_peer_homework + # eg_peer_grading: true + # components: + # - gc_lower_clamp: 0 + # gc_is_peer: true + # gc_default: 2 + # gc_max_value: 2 + # gc_upper_clamp: 2 + # gc_title: Read Me + # marks: + # - gcm_note: Full Credit + # gcm_points: 0 + # - gcm_note: Minor errors in Read Me + # gcm_points: -1 + # - gcm_note: Major errors in Read Me or Read Me missing + # gcm_points: -2 + # - gc_lower_clamp: 0 + # gc_default: 5 + # gc_is_peer: true + # gc_max_value: 5 + # gc_upper_clamp: 5 + # gc_title: Coding Style + # marks: + # - gcm_note: Full Credit + # gcm_points: 0 + # - gcm_note: Code is unreadable + # gcm_points: -5 + # - gcm_note: Code is very difficult to understand + # gcm_points: -3 + # - gcm_note: Code is difficult to understand + # gcm_points: -1 + # - gc_lower_clamp: 0 + # gc_default: 5 + # gc_is_peer: true + # gc_max_value: 5 + # gc_upper_clamp: 5 + # gc_title: Documentation + # marks: + # - gcm_note: Full Credit + # gcm_points: 0 + # - gcm_note: No documentation + # gcm_points: -5 + # - gcm_note: Very little documentation or documentation makes no sense + # gcm_points: -3 + # - gcm_note: Way too much documentation and/or documentation makes no sense + # gcm_points: -1 + # - gc_lower_clamp: 0 + # gc_default: 0 + # gc_max_value: 0 + # gc_upper_clamp: 5 + # gc_title: Extra Credit + # marks: + # - gcm_note: No Credit + # gcm_points: 0 + # - gcm_note: Extra credit done poorly + # gcm_points: 2 + # - gcm_note: Extra credit is acceptable + # gcm_points: 5 + # eg_submission_due_date: 9996-12-31 23:59:59 + # eg_submission_open_date: 1971-01-01 23:59:59 + # g_grade_due_date: 9998-12-31 23:59:59 + # g_grade_released_date: 9998-12-31 23:59:59 + # g_grade_start_date: 9997-12-31 23:59:59 + # g_ta_view_start_date: 1970-01-01 23:59:59 + # eg_grade_inquiry_start_date: 9999-01-01 23:59:59 + # eg_grade_inquiry_due_date: 9999-01-06 23:59:59 + # eg_has_due_date: true + # eg_has_release_date: true + # g_title: Open Peer Homework + # gradeable_config: python_simple_homework + # g_bucket: homework + + - g_id: open_homework components: - gc_lower_clamp: 0 - gc_is_peer: true gc_default: 2 gc_max_value: 2 gc_upper_clamp: 2 @@ -260,7 +330,6 @@ gradeables: gcm_points: -2 - gc_lower_clamp: 0 gc_default: 5 - gc_is_peer: true gc_max_value: 5 gc_upper_clamp: 5 gc_title: Coding Style @@ -275,7 +344,6 @@ gradeables: gcm_points: -1 - gc_lower_clamp: 0 gc_default: 5 - gc_is_peer: true gc_max_value: 5 gc_upper_clamp: 5 gc_title: Documentation @@ -310,1698 +378,1630 @@ gradeables: eg_grade_inquiry_due_date: 9999-01-06 23:59:59 eg_has_due_date: true eg_has_release_date: true - g_title: Open Peer Homework + g_title: Open Homework gradeable_config: python_simple_homework g_bucket: homework - - g_id: open_homework - components: - - gc_lower_clamp: 0 - gc_default: 2 - gc_max_value: 2 - gc_upper_clamp: 2 - gc_title: Read Me - marks: - - gcm_note: Full Credit - gcm_points: 0 - - gcm_note: Minor errors in Read Me - gcm_points: -1 - - gcm_note: Major errors in Read Me or Read Me missing - gcm_points: -2 - - gc_lower_clamp: 0 - gc_default: 5 - gc_max_value: 5 - gc_upper_clamp: 5 - gc_title: Coding Style - marks: - - gcm_note: Full Credit - gcm_points: 0 - - gcm_note: Code is unreadable - gcm_points: -5 - - gcm_note: Code is very difficult to understand - gcm_points: -3 - - gcm_note: Code is difficult to understand - gcm_points: -1 - - gc_lower_clamp: 0 - gc_default: 5 - gc_max_value: 5 - gc_upper_clamp: 5 - gc_title: Documentation - marks: - - gcm_note: Full Credit - gcm_points: 0 - - gcm_note: No documentation - gcm_points: -5 - - gcm_note: Very little documentation or documentation makes no sense - gcm_points: -3 - - gcm_note: Way too much documentation and/or documentation makes no sense - gcm_points: -1 - - gc_lower_clamp: 0 - gc_default: 0 - gc_max_value: 0 - gc_upper_clamp: 5 - gc_title: Extra Credit - marks: - - gcm_note: No Credit - gcm_points: 0 - - gcm_note: Extra credit done poorly - gcm_points: 2 - - gcm_note: Extra credit is acceptable - gcm_points: 5 - eg_submission_due_date: 9996-12-31 23:59:59 - eg_submission_open_date: 1971-01-01 23:59:59 - g_grade_due_date: 9998-12-31 23:59:59 - g_grade_released_date: 9998-12-31 23:59:59 - g_grade_start_date: 9997-12-31 23:59:59 - g_ta_view_start_date: 1970-01-01 23:59:59 - eg_grade_inquiry_start_date: 9999-01-01 23:59:59 - eg_grade_inquiry_due_date: 9999-01-06 23:59:59 - eg_has_due_date: true - eg_has_release_date: true - g_title: Open Homework - gradeable_config: python_simple_homework - g_bucket: homework - - - g_id: open_team_homework - components: - - gc_lower_clamp: 0 - gc_default: 2 - gc_max_value: 2 - gc_upper_clamp: 2 - gc_title: Read Me - marks: - - gcm_note: Full Credit - gcm_points: 0 - - gcm_note: Minor errors in Read Me - gcm_points: -1 - - gcm_note: Major errors in Read Me or Read Me missing - gcm_points: -2 - - gc_lower_clamp: 0 - gc_default: 5 - gc_max_value: 5 - gc_upper_clamp: 5 - gc_title: Coding Style - marks: - - gcm_note: Full Credit - gcm_points: 0 - - gcm_note: Code is unreadable - gcm_points: -5 - - gcm_note: Code is very difficult to understand - gcm_points: -3 - - gcm_note: Code is difficult to understand - gcm_points: -1 - - gc_lower_clamp: 0 - gc_default: 5 - gc_max_value: 5 - gc_upper_clamp: 5 - gc_title: Documentation - marks: - - gcm_note: Full Credit - gcm_points: 0 - - gcm_note: No documentation - gcm_points: -5 - - gcm_note: Very little documentation or documentation makes no sense - gcm_points: -3 - - gcm_note: Way too much documentation and/or documentation makes no sense - gcm_points: -1 - - gc_lower_clamp: 0 - gc_default: 0 - gc_max_value: 0 - gc_upper_clamp: 5 - gc_title: Extra Credit - marks: - - gcm_note: No Credit - gcm_points: 0 - - gcm_note: Extra credit done poorly - gcm_points: 2 - - gcm_note: Extra credit is acceptable - gcm_points: 5 - eg_submission_due_date: 9996-12-31 23:59:59 - eg_submission_open_date: 1971-01-01 23:59:59 - g_grade_due_date: 9998-12-31 23:59:59 - g_grade_released_date: 9998-12-31 23:59:59 - g_grade_start_date: 9997-12-31 23:59:59 - eg_grade_inquiry_start_date: 9999-01-01 23:59:59 - eg_grade_inquiry_due_date: 9999-01-06 23:59:59 - eg_has_due_date: true - eg_has_release_date: true - eg_team_assignment: true - eg_max_team_size: 3 - g_ta_view_start_date: 1970-01-01 23:59:59 - g_title: Open Team Homework - gradeable_config: python_simple_homework - g_bucket: homework - - - g_id: no_due_date_no_release - components: - - gc_lower_clamp: 0 - gc_default: 2 - gc_max_value: 2 - gc_upper_clamp: 2 - gc_title: Component - marks: - - gcm_note: Full Credit - gcm_points: 0 - eg_submission_due_date: 9997-12-31 23:59:59 - eg_submission_open_date: 1971-01-01 23:59:59 - eg_has_due_date: false - eg_has_release_date: false - g_grade_due_date: 9998-12-31 23:59:59 - g_grade_released_date: 9999-01-01 23:59:59 - g_grade_start_date: 9997-12-31 23:59:59 - eg_grade_inquiry_start_date: 9999-01-01 23:59:59 - eg_grade_inquiry_due_date: 9999-01-06 23:59:59 - g_ta_view_start_date: 1970-01-01 23:59:59 - g_title: No Due Date, No Release Date - gradeable_config: python_simple_homework - g_bucket: homework - - - g_id: open_vcs_homework - components: - - gc_lower_clamp: 0 - gc_default: 2 - gc_max_value: 2 - gc_upper_clamp: 2 - gc_title: Read Me - marks: - - gcm_note: Full Credit - gcm_points: 0 - - gcm_note: Minor errors in Read Me - gcm_points: -1 - - gcm_note: Major errors in Read Me or Read Me missing - gcm_points: -2 - - gc_lower_clamp: 0 - gc_default: 5 - gc_max_value: 5 - gc_upper_clamp: 5 - gc_title: Coding Style - marks: - - gcm_note: Full Credit - gcm_points: 0 - - gcm_note: Code is unreadable - gcm_points: -5 - - gcm_note: Code is very difficult to understand - gcm_points: -3 - - gcm_note: Code is difficult to understand - gcm_points: -1 - - gc_lower_clamp: 0 - gc_default: 5 - gc_max_value: 5 - gc_upper_clamp: 5 - gc_title: Documentation - marks: - - gcm_note: Full Credit - gcm_points: 0 - - gcm_note: No documentation - gcm_points: -5 - - gcm_note: Very little documentation or documentation makes no sense - gcm_points: -3 - - gcm_note: Way too much documentation and/or documentation makes no sense - gcm_points: -1 - - gc_lower_clamp: 0 - gc_default: 0 - gc_max_value: 0 - gc_upper_clamp: 5 - gc_title: Extra Credit - marks: - - gcm_note: No Credit - gcm_points: 0 - - gcm_note: Extra credit done poorly - gcm_points: 2 - - gcm_note: Extra credit is acceptable - gcm_points: 5 - eg_submission_due_date: 9996-12-31 23:59:59 - eg_submission_open_date: 1971-01-01 23:59:59 - g_grade_due_date: 9998-12-31 23:59:59 - g_grade_released_date: 9998-12-31 23:59:59 - g_grade_start_date: 9997-12-31 23:59:59 - eg_grade_inquiry_start_date: 9999-01-01 23:59:59 - eg_grade_inquiry_due_date: 9999-01-06 23:59:59 - g_ta_view_start_date: 1970-01-01 23:59:59 - eg_is_repository: true - eg_vcs_partial_path: "{$gradeable_id}/{$user_id}" - eg_using_subdirectory: false - eg_vcs_subdirectory: "" - g_title: Open VCS Homework - gradeable_config: vcs_submissions - g_bucket: homework - - - g_id: subdirectory_vcs_homework - components: - - gc_lower_clamp: 0 - gc_default: 2 - gc_max_value: 2 - gc_upper_clamp: 2 - gc_title: Read Me - marks: - - gcm_note: Full Credit - gcm_points: 0 - - gcm_note: Minor errors in Read Me - gcm_points: -1 - - gcm_note: Major errors in Read Me or Read Me missing - gcm_points: -2 - - gc_lower_clamp: 0 - gc_default: 5 - gc_max_value: 5 - gc_upper_clamp: 5 - gc_title: Coding Style - marks: - - gcm_note: Full Credit - gcm_points: 0 - - gcm_note: Code is unreadable - gcm_points: -5 - - gcm_note: Code is very difficult to understand - gcm_points: -3 - - gcm_note: Code is difficult to understand - gcm_points: -1 - - gc_lower_clamp: 0 - gc_default: 5 - gc_max_value: 5 - gc_upper_clamp: 5 - gc_title: Documentation - marks: - - gcm_note: Full Credit - gcm_points: 0 - - gcm_note: No documentation - gcm_points: -5 - - gcm_note: Very little documentation or documentation makes no sense - gcm_points: -3 - - gcm_note: Way too much documentation and/or documentation makes no sense - gcm_points: -1 - - gc_lower_clamp: 0 - gc_default: 0 - gc_max_value: 0 - gc_upper_clamp: 5 - gc_title: Extra Credit - marks: - - gcm_note: No Credit - gcm_points: 0 - - gcm_note: Extra credit done poorly - gcm_points: 2 - - gcm_note: Extra credit is acceptable - gcm_points: 5 - eg_submission_due_date: 9996-12-31 23:59:59 - eg_submission_open_date: 1971-01-01 23:59:59 - g_grade_due_date: 9998-12-31 23:59:59 - g_grade_released_date: 9998-12-31 23:59:59 - g_grade_start_date: 9997-12-31 23:59:59 - eg_grade_inquiry_start_date: 9999-01-01 23:59:59 - eg_grade_inquiry_due_date: 9999-01-06 23:59:59 - g_ta_view_start_date: 1970-01-01 23:59:59 - eg_is_repository: true - eg_vcs_partial_path: "{$gradeable_id}/{$user_id}" - eg_using_subdirectory: true - eg_vcs_subdirectory: "src" - g_title: Subdirectory VCS Homework - gradeable_config: vcs_submissions - g_bucket: homework - - - g_id: grading_team_homework - components: - - gc_lower_clamp: 0 - gc_default: 2 - gc_max_value: 2 - gc_upper_clamp: 2 - gc_title: Read Me - marks: - - gcm_note: Full Credit - gcm_points: 0 - - gcm_note: Minor errors in Read Me - gcm_points: -1 - - gcm_note: Major errors in Read Me or Read Me missing - gcm_points: -2 - - gc_lower_clamp: 0 - gc_default: 5 - gc_max_value: 5 - gc_upper_clamp: 5 - gc_title: Coding Style - marks: - - gcm_note: Full Credit - gcm_points: 0 - - gcm_note: Code is unreadable - gcm_points: -5 - - gcm_note: Code is very difficult to understand - gcm_points: -3 - - gcm_note: Code is difficult to understand - gcm_points: -1 - - gc_lower_clamp: 0 - gc_default: 5 - gc_max_value: 5 - gc_upper_clamp: 5 - gc_title: Documentation - marks: - - gcm_note: Full Credit - gcm_points: 0 - - gcm_note: No documentation - gcm_points: -5 - - gcm_note: Very little documentation or documentation makes no sense - gcm_points: -3 - - gcm_note: Way too much documentation and/or documentation makes no sense - gcm_points: -1 - - gc_lower_clamp: 0 - gc_default: 0 - gc_max_value: 0 - gc_upper_clamp: 5 - gc_title: Extra Credit - marks: - - gcm_note: No Credit - gcm_points: 0 - - gcm_note: Extra credit done poorly - gcm_points: 2 - - gcm_note: Extra credit is acceptable - gcm_points: 5 - eg_submission_due_date: 1972-01-01 23:59:59 - eg_submission_open_date: 1971-01-01 23:59:59 - g_grade_due_date: 9998-12-31 23:59:59 - g_grade_released_date: 9998-12-31 23:59:59 - g_grade_start_date: 1973-01-01 23:59:59 - eg_grade_inquiry_start_date: 9999-01-01 23:59:59 - eg_grade_inquiry_due_date: 9999-01-06 23:59:59 - eg_has_due_date: true - eg_has_release_date: true - eg_team_assignment: true - eg_max_team_size: 3 - g_ta_view_start_date: 1970-01-01 23:59:59 - g_title: Grading Team Homework - gradeable_config: python_simple_homework - g_bucket: homework - - - g_id: grading_only_peer_team_homework - eg_peer_grading: true - components: - - gc_lower_clamp: 0 - gc_is_peer: true - gc_default: 2 - gc_max_value: 2 - gc_upper_clamp: 2 - gc_title: Read Me - marks: - - gcm_note: Full Credit - gcm_points: 0 - - gcm_note: Minor errors in Read Me - gcm_points: -1 - - gcm_note: Major errors in Read Me or Read Me missing - gcm_points: -2 - - gc_lower_clamp: 0 - gc_default: 5 - gc_is_peer: true - gc_max_value: 5 - gc_upper_clamp: 5 - gc_title: Coding Style - marks: - - gcm_note: Full Credit - gcm_points: 0 - - gcm_note: Code is unreadable - gcm_points: -5 - - gcm_note: Code is very difficult to understand - gcm_points: -3 - - gcm_note: Code is difficult to understand - gcm_points: -1 - - gc_lower_clamp: 0 - gc_default: 5 - gc_is_peer: true - gc_max_value: 5 - gc_upper_clamp: 5 - gc_title: Documentation - marks: - - gcm_note: Full Credit - gcm_points: 0 - - gcm_note: No documentation - gcm_points: -5 - - gcm_note: Very little documentation or documentation makes no sense - gcm_points: -3 - - gcm_note: Way too much documentation and/or documentation makes no sense - gcm_points: -1 - - gc_lower_clamp: 0 - gc_default: 0 - gc_is_peer: true - gc_max_value: 0 - gc_upper_clamp: 5 - gc_title: Extra Credit - marks: - - gcm_note: No Credit - gcm_points: 0 - - gcm_note: Extra credit done poorly - gcm_points: 2 - - gcm_note: Extra credit is acceptable - gcm_points: 5 - eg_submission_due_date: 1972-01-01 23:59:59 - eg_submission_open_date: 1971-01-01 23:59:59 - g_grade_due_date: 9998-12-31 23:59:59 - g_grade_released_date: 9998-12-31 23:59:59 - g_grade_start_date: 1973-01-01 23:59:59 - eg_grade_inquiry_start_date: 9999-01-01 23:59:59 - eg_grade_inquiry_due_date: 9999-01-06 23:59:59 - eg_has_due_date: true - eg_has_release_date: true - eg_team_assignment: true - eg_max_team_size: 3 - g_ta_view_start_date: 1970-01-01 23:59:59 - g_title: Closed Peer Team Homework - gradeable_config: python_simple_homework - g_bucket: homework - - - g_id: closed_peer_team_homework - eg_peer_grading: true - components: - - gc_lower_clamp: 0 - gc_default: 2 - gc_is_peer: true - gc_max_value: 2 - gc_upper_clamp: 2 - gc_title: Read Me - marks: - - gcm_note: Full Credit - gcm_points: 0 - - gcm_note: Minor errors in Read Me - gcm_points: -1 - - gcm_note: Major errors in Read Me or Read Me missing - gcm_points: -2 - - gc_lower_clamp: 0 - gc_default: 5 - gc_is_peer: true - gc_max_value: 5 - gc_upper_clamp: 5 - gc_title: Coding Style - marks: - - gcm_note: Full Credit - gcm_points: 0 - - gcm_note: Code is unreadable - gcm_points: -5 - - gcm_note: Code is very difficult to understand - gcm_points: -3 - - gcm_note: Code is difficult to understand - gcm_points: -1 - - gc_lower_clamp: 0 - gc_default: 5 - gc_is_peer: true - gc_max_value: 5 - gc_upper_clamp: 5 - gc_title: Documentation - marks: - - gcm_note: Full Credit - gcm_points: 0 - - gcm_note: No documentation - gcm_points: -5 - - gcm_note: Very little documentation or documentation makes no sense - gcm_points: -3 - - gcm_note: Way too much documentation and/or documentation makes no sense - gcm_points: -1 - - gc_lower_clamp: 0 - gc_default: 0 - gc_max_value: 0 - gc_upper_clamp: 5 - gc_title: Extra Credit - marks: - - gcm_note: No Credit - gcm_points: 0 - - gcm_note: Extra credit done poorly - gcm_points: 2 - - gcm_note: Extra credit is acceptable - gcm_points: 5 - eg_submission_due_date: 1972-01-01 23:59:59 - eg_submission_open_date: 1971-01-01 23:59:59 - g_grade_due_date: 9998-12-31 23:59:59 - g_grade_released_date: 9998-12-31 23:59:59 - eg_grade_inquiry_start_date: 9999-01-01 23:59:59 - eg_grade_inquiry_due_date: 9999-01-06 23:59:59 - eg_has_due_date: true - eg_has_release_date: true - g_grade_start_date: 9997-12-31 23:59:59 - eg_team_assignment: true - eg_max_team_size: 3 - g_ta_view_start_date: 1970-01-01 23:59:59 - g_title: Closed Peer Team Homework - gradeable_config: cpp_hidden_tests - g_bucket: homework - - - g_id: grading_pdf_peer_homework - eg_peer_grading: true - components: - - gc_lower_clamp: 0 - gc_is_peer: true - gc_default: 2 - gc_max_value: 2 - gc_upper_clamp: 2 - gc_title: Read Me - marks: - - gcm_note: Full Credit - gcm_points: 0 - - gcm_note: Minor errors in Read Me - gcm_points: -1 - - gcm_note: Major errors in Read Me or Read Me missing - gcm_points: -2 - - gc_lower_clamp: 0 - gc_default: 5 - gc_is_peer: true - gc_max_value: 5 - gc_upper_clamp: 5 - gc_title: Coding Style - marks: - - gcm_note: Full Credit - gcm_points: 0 - - gcm_note: Code is unreadable - gcm_points: -5 - - gcm_note: Code is very difficult to understand - gcm_points: -3 - - gcm_note: Code is difficult to understand - gcm_points: -1 - - gc_lower_clamp: 0 - gc_default: 5 - gc_is_peer: true - gc_max_value: 5 - gc_upper_clamp: 5 - gc_title: Documentation - marks: - - gcm_note: Full Credit - gcm_points: 0 - - gcm_note: No documentation - gcm_points: -5 - - gcm_note: Very little documentation or documentation makes no sense - gcm_points: -3 - - gcm_note: Way too much documentation and/or documentation makes no sense - gcm_points: -1 - - gc_lower_clamp: 0 - gc_default: 0 - gc_is_peer: true - gc_max_value: 0 - gc_upper_clamp: 5 - gc_title: Extra Credit - marks: - - gcm_note: No Credit - gcm_points: 0 - - gcm_note: Extra credit done poorly - gcm_points: 2 - - gcm_note: Extra credit is acceptable - gcm_points: 5 - eg_submission_due_date: 1972-01-01 23:59:59 - eg_submission_open_date: 1971-01-01 23:59:59 - g_grade_due_date: 1974-01-01 23:59:59 - g_grade_released_date: 1974-01-01 23:59:59 - eg_grade_inquiry_start_date: 1974-01-08 23:59:59 - eg_grade_inquiry_due_date: 1974-01-13 23:59:59 - eg_has_due_date: true - eg_has_release_date: true - g_grade_start_date: 1973-01-01 23:59:59 - g_ta_view_start_date: 1970-01-01 23:59:59 - g_title: Released Peer PDF Homework - gradeable_config: multiple_pdf_annotations - g_bucket: homework - g_grader_assignment_method: 2 - eg_annotated_pdf: true - - - g_id: grading_pdf_peer_team_homework - eg_peer_grading: true - components: - - gc_lower_clamp: 0 - gc_is_peer: true - gc_default: 2 - gc_max_value: 2 - gc_upper_clamp: 2 - gc_title: Read Me - marks: - - gcm_note: Full Credit - gcm_points: 0 - - gcm_note: Minor errors in Read Me - gcm_points: -1 - - gcm_note: Major errors in Read Me or Read Me missing - gcm_points: -2 - - gc_lower_clamp: 0 - gc_default: 5 - gc_is_peer: true - gc_max_value: 5 - gc_upper_clamp: 5 - gc_title: Coding Style - marks: - - gcm_note: Full Credit - gcm_points: 0 - - gcm_note: Code is unreadable - gcm_points: -5 - - gcm_note: Code is very difficult to understand - gcm_points: -3 - - gcm_note: Code is difficult to understand - gcm_points: -1 - - gc_lower_clamp: 0 - gc_default: 5 - gc_is_peer: true - gc_max_value: 5 - gc_upper_clamp: 5 - gc_title: Documentation - marks: - - gcm_note: Full Credit - gcm_points: 0 - - gcm_note: No documentation - gcm_points: -5 - - gcm_note: Very little documentation or documentation makes no sense - gcm_points: -3 - - gcm_note: Way too much documentation and/or documentation makes no sense - gcm_points: -1 - - gc_lower_clamp: 0 - gc_default: 0 - gc_is_peer: true - gc_max_value: 0 - gc_upper_clamp: 5 - gc_title: Extra Credit - marks: - - gcm_note: No Credit - gcm_points: 0 - - gcm_note: Extra credit done poorly - gcm_points: 2 - - gcm_note: Extra credit is acceptable - gcm_points: 5 - eg_submission_due_date: 1972-01-01 23:59:59 - eg_submission_open_date: 1971-01-01 23:59:59 - g_grade_due_date: 1974-01-01 23:59:59 - g_grade_released_date: 1974-01-01 23:59:59 - eg_grade_inquiry_start_date: 1974-01-08 23:59:59 - eg_grade_inquiry_due_date: 1974-01-13 23:59:59 - eg_has_due_date: true - eg_has_release_date: true - eg_team_assignment: true - eg_max_team_size: 3 - g_grade_start_date: 1973-01-01 23:59:59 - g_ta_view_start_date: 1970-01-01 23:59:59 - g_title: Released Peer Team PDF Homework - gradeable_config: multiple_pdf_annotations - g_bucket: homework - g_grader_assignment_method: 2 - eg_annotated_pdf: true - - - g_id: closed_team_homework - eg_peer_grading: true - components: - - gc_lower_clamp: 0 - gc_default: 2 - gc_max_value: 2 - gc_upper_clamp: 2 - gc_title: Read Me - marks: - - gcm_note: Full Credit - gcm_points: 0 - - gcm_note: Minor errors in Read Me - gcm_points: -1 - - gcm_note: Major errors in Read Me or Read Me missing - gcm_points: -2 - - gc_lower_clamp: 0 - gc_default: 5 - gc_max_value: 5 - gc_upper_clamp: 5 - gc_title: Coding Style - marks: - - gcm_note: Full Credit - gcm_points: 0 - - gcm_note: Code is unreadable - gcm_points: -5 - - gcm_note: Code is very difficult to understand - gcm_points: -3 - - gcm_note: Code is difficult to understand - gcm_points: -1 - - gc_lower_clamp: 0 - gc_default: 5 - gc_max_value: 5 - gc_upper_clamp: 5 - gc_title: Documentation - marks: - - gcm_note: Full Credit - gcm_points: 0 - - gcm_note: No documentation - gcm_points: -5 - - gcm_note: Very little documentation or documentation makes no sense - gcm_points: -3 - - gcm_note: Way too much documentation and/or documentation makes no sense - gcm_points: -1 - - gc_lower_clamp: 0 - gc_default: 0 - gc_max_value: 0 - gc_upper_clamp: 5 - gc_title: Extra Credit - marks: - - gcm_note: No Credit - gcm_points: 0 - - gcm_note: Extra credit done poorly - gcm_points: 2 - - gcm_note: Extra credit is acceptable - gcm_points: 5 - eg_submission_due_date: 1972-01-01 23:59:59 - eg_submission_open_date: 1971-01-01 23:59:59 - g_grade_due_date: 9998-12-31 23:59:59 - g_grade_released_date: 9998-12-31 23:59:59 - eg_grade_inquiry_start_date: 9999-01-01 23:59:59 - eg_grade_inquiry_due_date: 9999-01-06 23:59:59 - eg_has_due_date: true - eg_has_release_date: true - g_grade_start_date: 9997-12-31 23:59:59 - eg_team_assignment: true - eg_max_team_size: 3 - g_ta_view_start_date: 1970-01-01 23:59:59 - g_title: Closed Team Homework - gradeable_config: cpp_hidden_tests - g_bucket: homework - - - g_id: closed_homework - components: - - gc_lower_clamp: 0 - gc_default: 2 - gc_max_value: 2 - gc_upper_clamp: 2 - gc_title: Read Me - marks: - - gcm_note: Full Credit - gcm_points: 0 - - gcm_note: Minor errors in Read Me - gcm_points: -1 - - gcm_note: Major errors in Read Me or Read Me missing - gcm_points: -2 - - gc_lower_clamp: 0 - gc_default: 5 - gc_max_value: 5 - gc_upper_clamp: 5 - gc_title: Coding Style - marks: - - gcm_note: Full Credit - gcm_points: 0 - - gcm_note: Code is unreadable - gcm_points: -5 - - gcm_note: Code is very difficult to understand - gcm_points: -3 - - gcm_note: Code is difficult to understand - gcm_points: -1 - - gc_lower_clamp: 0 - gc_default: 5 - gc_max_value: 5 - gc_upper_clamp: 5 - gc_title: Documentation - marks: - - gcm_note: Full Credit - gcm_points: 0 - - gcm_note: No documentation - gcm_points: -5 - - gcm_note: Very little documentation or documentation makes no sense - gcm_points: -3 - - gcm_note: Way too much documentation and/or documentation makes no sense - gcm_points: -1 - - gc_lower_clamp: 0 - gc_default: 0 - gc_max_value: 0 - gc_upper_clamp: 5 - gc_title: Extra Credit - marks: - - gcm_note: No Credit - gcm_points: 0 - - gcm_note: Extra credit done poorly - gcm_points: 2 - - gcm_note: Extra credit is acceptable - gcm_points: 5 - eg_submission_due_date: 1972-01-01 23:59:59 - eg_submission_open_date: 1971-01-01 23:59:59 - g_grade_due_date: 9998-12-31 23:59:59 - g_grade_released_date: 9998-12-31 23:59:59 - eg_grade_inquiry_start_date: 9999-01-01 23:59:59 - eg_grade_inquiry_due_date: 9999-01-06 23:59:59 - eg_has_due_date: true - eg_has_release_date: true - g_grade_start_date: 9997-12-31 23:59:59 - g_ta_view_start_date: 1970-01-01 23:59:59 - g_title: Closed Homework - gradeable_config: python_simple_homework - g_bucket: homework - - - g_id: late_allowed_homework - components: - - gc_lower_clamp: 0 - gc_default: 5 - gc_max_value: 5 - gc_upper_clamp: 5 - gc_title: Question 1 - eg_submission_due_date: 1972-01-01 03:59:59 - eg_submission_open_date: 1971-01-01 03:59:59 - g_grade_due_date: 9998-12-31 23:59:59 - g_grade_released_date: 9998-12-31 23:59:59 - eg_grade_inquiry_start_date: 9999-01-01 23:59:59 - eg_grade_inquiry_due_date: 9999-01-06 23:59:59 - eg_has_due_date: true - eg_has_release_date: true - eg_late_days: 1 - g_grade_start_date: 9997-12-31 23:59:59 - g_ta_view_start_date: 1970-01-01 03:59:59 - g_title: Late Allowed Homework - gradeable_config: python_simple_homework - g_bucket: homework - - - g_id: grading_homework - components: - - gc_lower_clamp: 0 - gc_default: 2 - gc_max_value: 2 - gc_upper_clamp: 2 - gc_title: Read Me - marks: - - gcm_note: Full Credit - gcm_points: 0 - - gcm_note: Minor errors in Read Me - gcm_points: -1 - - gcm_note: Major errors in Read Me or Read Me missing - gcm_points: -2 - - gc_lower_clamp: 0 - gc_default: 5 - gc_max_value: 5 - gc_upper_clamp: 5 - gc_title: Coding Style - marks: - - gcm_note: Full Credit - gcm_points: 0 - - gcm_note: Code is unreadable - gcm_points: -5 - - gcm_note: Code is very difficult to understand - gcm_points: -3 - - gcm_note: Code is difficult to understand - gcm_points: -1 - - gc_lower_clamp: 0 - gc_default: 5 - gc_max_value: 5 - gc_upper_clamp: 5 - gc_title: Documentation - marks: - - gcm_note: Full Credit - gcm_points: 0 - - gcm_note: No documentation - gcm_points: -5 - - gcm_note: Very little documentation or documentation makes no sense - gcm_points: -3 - - gcm_note: Way too much documentation and/or documentation makes no sense - gcm_points: -1 - - gc_lower_clamp: 0 - gc_default: 0 - gc_max_value: 0 - gc_upper_clamp: 5 - gc_title: Extra Credit - marks: - - gcm_note: No Credit - gcm_points: 0 - - gcm_note: Extra credit done poorly - gcm_points: 2 - - gcm_note: Extra credit is acceptable - gcm_points: 5 - eg_submission_due_date: 1972-01-01 23:59:59 - eg_submission_open_date: 1971-01-01 23:59:59 - g_grade_due_date: 9998-12-31 23:59:59 - g_grade_released_date: 9998-12-31 23:59:59 - eg_grade_inquiry_start_date: 9999-01-01 23:59:59 - eg_grade_inquiry_due_date: 9999-01-06 23:59:59 - eg_has_due_date: true - eg_has_release_date: true - g_grade_start_date: 1973-01-01 23:59:59 - g_ta_view_start_date: 1970-01-01 23:59:59 - g_title: Grading Homework - gradeable_config: python_simple_homework - g_bucket: homework + # - g_id: open_team_homework + # components: + # - gc_lower_clamp: 0 + # gc_default: 2 + # gc_max_value: 2 + # gc_upper_clamp: 2 + # gc_title: Read Me + # marks: + # - gcm_note: Full Credit + # gcm_points: 0 + # - gcm_note: Minor errors in Read Me + # gcm_points: -1 + # - gcm_note: Major errors in Read Me or Read Me missing + # gcm_points: -2 + # - gc_lower_clamp: 0 + # gc_default: 5 + # gc_max_value: 5 + # gc_upper_clamp: 5 + # gc_title: Coding Style + # marks: + # - gcm_note: Full Credit + # gcm_points: 0 + # - gcm_note: Code is unreadable + # gcm_points: -5 + # - gcm_note: Code is very difficult to understand + # gcm_points: -3 + # - gcm_note: Code is difficult to understand + # gcm_points: -1 + # - gc_lower_clamp: 0 + # gc_default: 5 + # gc_max_value: 5 + # gc_upper_clamp: 5 + # gc_title: Documentation + # marks: + # - gcm_note: Full Credit + # gcm_points: 0 + # - gcm_note: No documentation + # gcm_points: -5 + # - gcm_note: Very little documentation or documentation makes no sense + # gcm_points: -3 + # - gcm_note: Way too much documentation and/or documentation makes no sense + # gcm_points: -1 + # - gc_lower_clamp: 0 + # gc_default: 0 + # gc_max_value: 0 + # gc_upper_clamp: 5 + # gc_title: Extra Credit + # marks: + # - gcm_note: No Credit + # gcm_points: 0 + # - gcm_note: Extra credit done poorly + # gcm_points: 2 + # - gcm_note: Extra credit is acceptable + # gcm_points: 5 + # eg_submission_due_date: 9996-12-31 23:59:59 + # eg_submission_open_date: 1971-01-01 23:59:59 + # g_grade_due_date: 9998-12-31 23:59:59 + # g_grade_released_date: 9998-12-31 23:59:59 + # g_grade_start_date: 9997-12-31 23:59:59 + # eg_grade_inquiry_start_date: 9999-01-01 23:59:59 + # eg_grade_inquiry_due_date: 9999-01-06 23:59:59 + # eg_has_due_date: true + # eg_has_release_date: true + # eg_team_assignment: true + # eg_max_team_size: 3 + # g_ta_view_start_date: 1970-01-01 23:59:59 + # g_title: Open Team Homework + # gradeable_config: python_simple_homework + # g_bucket: homework - - g_id: grades_released_homework - components: - - gc_lower_clamp: 0 - gc_default: 5 - gc_max_value: 5 - gc_upper_clamp: 5 - gc_title: Question 1 - - gc_is_extra_credit: true - gc_lower_clamp: 0 - gc_default: 5 - gc_max_value: 5 - gc_upper_clamp: 5 - gc_title: Question 2 - eg_submission_due_date: 1972-01-01 23:59:59 - eg_submission_open_date: 1971-01-01 23:59:59 - g_grade_due_date: 1974-01-01 23:59:59 - g_grade_released_date: 1974-01-01 23:59:59 - eg_grade_inquiry_start_date: 1974-01-01 23:59:59 - eg_grade_inquiry_due_date: 1974-01-08 23:59:59 - eg_has_due_date: true - eg_has_release_date: true - g_grade_start_date: 1973-01-01 23:59:59 - g_ta_view_start_date: 1970-01-01 23:59:59 - g_title: Grades Released Homework - gradeable_config: python_simple_homework - g_bucket: homework + # - g_id: no_due_date_no_release + # components: + # - gc_lower_clamp: 0 + # gc_default: 2 + # gc_max_value: 2 + # gc_upper_clamp: 2 + # gc_title: Component + # marks: + # - gcm_note: Full Credit + # gcm_points: 0 + # eg_submission_due_date: 9997-12-31 23:59:59 + # eg_submission_open_date: 1971-01-01 23:59:59 + # eg_has_due_date: false + # eg_has_release_date: false + # g_grade_due_date: 9998-12-31 23:59:59 + # g_grade_released_date: 9999-01-01 23:59:59 + # g_grade_start_date: 9997-12-31 23:59:59 + # eg_grade_inquiry_start_date: 9999-01-01 23:59:59 + # eg_grade_inquiry_due_date: 9999-01-06 23:59:59 + # g_ta_view_start_date: 1970-01-01 23:59:59 + # g_title: No Due Date, No Release Date + # gradeable_config: python_simple_homework + # g_bucket: homework - - g_id: future_no_tas_lab - components: - - gc_title: Question 1 - gc_lower_clamp: 0 - gc_default: 0 - gc_max_value: 1 - gc_upper_clamp: 1 - - gc_title: Question 2 - gc_lower_clamp: 0 - gc_default: 0 - gc_max_value: 0 - gc_upper_clamp: 1 - g_grade_due_date: 9998-12-31 23:59:59 - g_grade_released_date: 9998-12-31 23:59:59 - g_grade_start_date: 9997-12-31 23:59:59 - g_ta_view_start_date: 9996-12-31 23:59:59 - g_title: Future (No TAs) Lab - g_type: 1 - g_bucket: lab + # - g_id: open_vcs_homework + # components: + # - gc_lower_clamp: 0 + # gc_default: 2 + # gc_max_value: 2 + # gc_upper_clamp: 2 + # gc_title: Read Me + # marks: + # - gcm_note: Full Credit + # gcm_points: 0 + # - gcm_note: Minor errors in Read Me + # gcm_points: -1 + # - gcm_note: Major errors in Read Me or Read Me missing + # gcm_points: -2 + # - gc_lower_clamp: 0 + # gc_default: 5 + # gc_max_value: 5 + # gc_upper_clamp: 5 + # gc_title: Coding Style + # marks: + # - gcm_note: Full Credit + # gcm_points: 0 + # - gcm_note: Code is unreadable + # gcm_points: -5 + # - gcm_note: Code is very difficult to understand + # gcm_points: -3 + # - gcm_note: Code is difficult to understand + # gcm_points: -1 + # - gc_lower_clamp: 0 + # gc_default: 5 + # gc_max_value: 5 + # gc_upper_clamp: 5 + # gc_title: Documentation + # marks: + # - gcm_note: Full Credit + # gcm_points: 0 + # - gcm_note: No documentation + # gcm_points: -5 + # - gcm_note: Very little documentation or documentation makes no sense + # gcm_points: -3 + # - gcm_note: Way too much documentation and/or documentation makes no sense + # gcm_points: -1 + # - gc_lower_clamp: 0 + # gc_default: 0 + # gc_max_value: 0 + # gc_upper_clamp: 5 + # gc_title: Extra Credit + # marks: + # - gcm_note: No Credit + # gcm_points: 0 + # - gcm_note: Extra credit done poorly + # gcm_points: 2 + # - gcm_note: Extra credit is acceptable + # gcm_points: 5 + # eg_submission_due_date: 9996-12-31 23:59:59 + # eg_submission_open_date: 1971-01-01 23:59:59 + # g_grade_due_date: 9998-12-31 23:59:59 + # g_grade_released_date: 9998-12-31 23:59:59 + # g_grade_start_date: 9997-12-31 23:59:59 + # eg_grade_inquiry_start_date: 9999-01-01 23:59:59 + # eg_grade_inquiry_due_date: 9999-01-06 23:59:59 + # g_ta_view_start_date: 1970-01-01 23:59:59 + # eg_is_repository: true + # eg_vcs_partial_path: "{$gradeable_id}/{$user_id}" + # eg_using_subdirectory: false + # eg_vcs_subdirectory: "" + # g_title: Open VCS Homework + # gradeable_config: vcs_submissions + # g_bucket: homework - - g_id: future_tas_lab - components: - - gc_title: Question 1 - gc_lower_clamp: 0 - gc_default: 0 - gc_max_value: 1 - gc_upper_clamp: 1 - - gc_title: Question 2 - gc_lower_clamp: 0 - gc_default: 0 - gc_max_value: 0 - gc_upper_clamp: 1 - g_grade_due_date: 9998-12-31 23:59:59 - g_grade_released_date: 9998-12-31 23:59:59 - g_grade_start_date: 9997-12-31 23:59:59 - g_ta_view_start_date: 1970-01-01 23:59:59 - g_title: Future (TAs) Lab - g_type: 1 - g_bucket: lab + # - g_id: subdirectory_vcs_homework + # components: + # - gc_lower_clamp: 0 + # gc_default: 2 + # gc_max_value: 2 + # gc_upper_clamp: 2 + # gc_title: Read Me + # marks: + # - gcm_note: Full Credit + # gcm_points: 0 + # - gcm_note: Minor errors in Read Me + # gcm_points: -1 + # - gcm_note: Major errors in Read Me or Read Me missing + # gcm_points: -2 + # - gc_lower_clamp: 0 + # gc_default: 5 + # gc_max_value: 5 + # gc_upper_clamp: 5 + # gc_title: Coding Style + # marks: + # - gcm_note: Full Credit + # gcm_points: 0 + # - gcm_note: Code is unreadable + # gcm_points: -5 + # - gcm_note: Code is very difficult to understand + # gcm_points: -3 + # - gcm_note: Code is difficult to understand + # gcm_points: -1 + # - gc_lower_clamp: 0 + # gc_default: 5 + # gc_max_value: 5 + # gc_upper_clamp: 5 + # gc_title: Documentation + # marks: + # - gcm_note: Full Credit + # gcm_points: 0 + # - gcm_note: No documentation + # gcm_points: -5 + # - gcm_note: Very little documentation or documentation makes no sense + # gcm_points: -3 + # - gcm_note: Way too much documentation and/or documentation makes no sense + # gcm_points: -1 + # - gc_lower_clamp: 0 + # gc_default: 0 + # gc_max_value: 0 + # gc_upper_clamp: 5 + # gc_title: Extra Credit + # marks: + # - gcm_note: No Credit + # gcm_points: 0 + # - gcm_note: Extra credit done poorly + # gcm_points: 2 + # - gcm_note: Extra credit is acceptable + # gcm_points: 5 + # eg_submission_due_date: 9996-12-31 23:59:59 + # eg_submission_open_date: 1971-01-01 23:59:59 + # g_grade_due_date: 9998-12-31 23:59:59 + # g_grade_released_date: 9998-12-31 23:59:59 + # g_grade_start_date: 9997-12-31 23:59:59 + # eg_grade_inquiry_start_date: 9999-01-01 23:59:59 + # eg_grade_inquiry_due_date: 9999-01-06 23:59:59 + # g_ta_view_start_date: 1970-01-01 23:59:59 + # eg_is_repository: true + # eg_vcs_partial_path: "{$gradeable_id}/{$user_id}" + # eg_using_subdirectory: true + # eg_vcs_subdirectory: "src" + # g_title: Subdirectory VCS Homework + # gradeable_config: vcs_submissions + # g_bucket: homework - - g_id: grading_lab - components: - - gc_title: Question 1 - gc_lower_clamp: 0 - gc_default: 0 - gc_max_value: 1 - gc_upper_clamp: 1 - - gc_title: Question 2 - gc_lower_clamp: 0 - gc_default: 0 - gc_max_value: 0 - gc_upper_clamp: 1 - g_grade_due_date: 9998-12-31 23:59:59 - g_grade_released_date: 9998-12-31 23:59:59 - g_grade_start_date: 1971-01-01 23:59:59 - g_ta_view_start_date: 1970-01-01 23:59:59 - g_title: Grading Lab - g_type: 1 - g_bucket: lab + # - g_id: grading_team_homework + # components: + # - gc_lower_clamp: 0 + # gc_default: 2 + # gc_max_value: 2 + # gc_upper_clamp: 2 + # gc_title: Read Me + # marks: + # - gcm_note: Full Credit + # gcm_points: 0 + # - gcm_note: Minor errors in Read Me + # gcm_points: -1 + # - gcm_note: Major errors in Read Me or Read Me missing + # gcm_points: -2 + # - gc_lower_clamp: 0 + # gc_default: 5 + # gc_max_value: 5 + # gc_upper_clamp: 5 + # gc_title: Coding Style + # marks: + # - gcm_note: Full Credit + # gcm_points: 0 + # - gcm_note: Code is unreadable + # gcm_points: -5 + # - gcm_note: Code is very difficult to understand + # gcm_points: -3 + # - gcm_note: Code is difficult to understand + # gcm_points: -1 + # - gc_lower_clamp: 0 + # gc_default: 5 + # gc_max_value: 5 + # gc_upper_clamp: 5 + # gc_title: Documentation + # marks: + # - gcm_note: Full Credit + # gcm_points: 0 + # - gcm_note: No documentation + # gcm_points: -5 + # - gcm_note: Very little documentation or documentation makes no sense + # gcm_points: -3 + # - gcm_note: Way too much documentation and/or documentation makes no sense + # gcm_points: -1 + # - gc_lower_clamp: 0 + # gc_default: 0 + # gc_max_value: 0 + # gc_upper_clamp: 5 + # gc_title: Extra Credit + # marks: + # - gcm_note: No Credit + # gcm_points: 0 + # - gcm_note: Extra credit done poorly + # gcm_points: 2 + # - gcm_note: Extra credit is acceptable + # gcm_points: 5 + # eg_submission_due_date: 1972-01-01 23:59:59 + # eg_submission_open_date: 1971-01-01 23:59:59 + # g_grade_due_date: 9998-12-31 23:59:59 + # g_grade_released_date: 9998-12-31 23:59:59 + # g_grade_start_date: 1973-01-01 23:59:59 + # eg_grade_inquiry_start_date: 9999-01-01 23:59:59 + # eg_grade_inquiry_due_date: 9999-01-06 23:59:59 + # eg_has_due_date: true + # eg_has_release_date: true + # eg_team_assignment: true + # eg_max_team_size: 3 + # g_ta_view_start_date: 1970-01-01 23:59:59 + # g_title: Grading Team Homework + # gradeable_config: python_simple_homework + # g_bucket: homework - - g_id: grading_lab_rotating - components: - - gc_title: Question 1 - gc_lower_clamp: 0 - gc_default: 0 - gc_max_value: 1 - gc_upper_clamp: 1 - - gc_title: Question 2 - gc_lower_clamp: 0 - gc_default: 0 - gc_max_value: 0 - gc_upper_clamp: 1 - g_grade_due_date: 9998-12-31 23:59:59 - g_grade_released_date: 9998-12-31 23:59:59 - g_grade_start_date: 1971-01-01 23:59:59 - g_ta_view_start_date: 1970-01-01 23:59:59 - g_title: Grading Lab (Rotating Sections) - g_type: 1 - g_bucket: lab - g_grader_assignment_method: 0 + # - g_id: grading_only_peer_team_homework + # eg_peer_grading: true + # components: + # - gc_lower_clamp: 0 + # gc_is_peer: true + # gc_default: 2 + # gc_max_value: 2 + # gc_upper_clamp: 2 + # gc_title: Read Me + # marks: + # - gcm_note: Full Credit + # gcm_points: 0 + # - gcm_note: Minor errors in Read Me + # gcm_points: -1 + # - gcm_note: Major errors in Read Me or Read Me missing + # gcm_points: -2 + # - gc_lower_clamp: 0 + # gc_default: 5 + # gc_is_peer: true + # gc_max_value: 5 + # gc_upper_clamp: 5 + # gc_title: Coding Style + # marks: + # - gcm_note: Full Credit + # gcm_points: 0 + # - gcm_note: Code is unreadable + # gcm_points: -5 + # - gcm_note: Code is very difficult to understand + # gcm_points: -3 + # - gcm_note: Code is difficult to understand + # gcm_points: -1 + # - gc_lower_clamp: 0 + # gc_default: 5 + # gc_is_peer: true + # gc_max_value: 5 + # gc_upper_clamp: 5 + # gc_title: Documentation + # marks: + # - gcm_note: Full Credit + # gcm_points: 0 + # - gcm_note: No documentation + # gcm_points: -5 + # - gcm_note: Very little documentation or documentation makes no sense + # gcm_points: -3 + # - gcm_note: Way too much documentation and/or documentation makes no sense + # gcm_points: -1 + # - gc_lower_clamp: 0 + # gc_default: 0 + # gc_is_peer: true + # gc_max_value: 0 + # gc_upper_clamp: 5 + # gc_title: Extra Credit + # marks: + # - gcm_note: No Credit + # gcm_points: 0 + # - gcm_note: Extra credit done poorly + # gcm_points: 2 + # - gcm_note: Extra credit is acceptable + # gcm_points: 5 + # eg_submission_due_date: 1972-01-01 23:59:59 + # eg_submission_open_date: 1971-01-01 23:59:59 + # g_grade_due_date: 9998-12-31 23:59:59 + # g_grade_released_date: 9998-12-31 23:59:59 + # g_grade_start_date: 1973-01-01 23:59:59 + # eg_grade_inquiry_start_date: 9999-01-01 23:59:59 + # eg_grade_inquiry_due_date: 9999-01-06 23:59:59 + # eg_has_due_date: true + # eg_has_release_date: true + # eg_team_assignment: true + # eg_max_team_size: 3 + # g_ta_view_start_date: 1970-01-01 23:59:59 + # g_title: Closed Peer Team Homework + # gradeable_config: python_simple_homework + # g_bucket: homework - - g_id: grades_released_lab - components: - - gc_title: Question 1 - gc_lower_clamp: 0 - gc_default: 0 - gc_max_value: 1 - gc_upper_clamp: 1 - - gc_title: Question 2 - gc_lower_clamp: 0 - gc_default: 0 - gc_max_value: 0 - gc_upper_clamp: 1 - g_grade_due_date: 1972-01-01 23:59:59 - g_grade_released_date: 1972-01-01 23:59:59 - g_grade_start_date: 1971-01-01 23:59:59 - g_ta_view_start_date: 1970-01-01 23:59:59 - g_title: Grades Released Lab - g_type: 1 - g_bucket: lab + # - g_id: closed_peer_team_homework + # eg_peer_grading: true + # components: + # - gc_lower_clamp: 0 + # gc_default: 2 + # gc_is_peer: true + # gc_max_value: 2 + # gc_upper_clamp: 2 + # gc_title: Read Me + # marks: + # - gcm_note: Full Credit + # gcm_points: 0 + # - gcm_note: Minor errors in Read Me + # gcm_points: -1 + # - gcm_note: Major errors in Read Me or Read Me missing + # gcm_points: -2 + # - gc_lower_clamp: 0 + # gc_default: 5 + # gc_is_peer: true + # gc_max_value: 5 + # gc_upper_clamp: 5 + # gc_title: Coding Style + # marks: + # - gcm_note: Full Credit + # gcm_points: 0 + # - gcm_note: Code is unreadable + # gcm_points: -5 + # - gcm_note: Code is very difficult to understand + # gcm_points: -3 + # - gcm_note: Code is difficult to understand + # gcm_points: -1 + # - gc_lower_clamp: 0 + # gc_default: 5 + # gc_is_peer: true + # gc_max_value: 5 + # gc_upper_clamp: 5 + # gc_title: Documentation + # marks: + # - gcm_note: Full Credit + # gcm_points: 0 + # - gcm_note: No documentation + # gcm_points: -5 + # - gcm_note: Very little documentation or documentation makes no sense + # gcm_points: -3 + # - gcm_note: Way too much documentation and/or documentation makes no sense + # gcm_points: -1 + # - gc_lower_clamp: 0 + # gc_default: 0 + # gc_max_value: 0 + # gc_upper_clamp: 5 + # gc_title: Extra Credit + # marks: + # - gcm_note: No Credit + # gcm_points: 0 + # - gcm_note: Extra credit done poorly + # gcm_points: 2 + # - gcm_note: Extra credit is acceptable + # gcm_points: 5 + # eg_submission_due_date: 1972-01-01 23:59:59 + # eg_submission_open_date: 1971-01-01 23:59:59 + # g_grade_due_date: 9998-12-31 23:59:59 + # g_grade_released_date: 9998-12-31 23:59:59 + # eg_grade_inquiry_start_date: 9999-01-01 23:59:59 + # eg_grade_inquiry_due_date: 9999-01-06 23:59:59 + # eg_has_due_date: true + # eg_has_release_date: true + # g_grade_start_date: 9997-12-31 23:59:59 + # eg_team_assignment: true + # eg_max_team_size: 3 + # g_ta_view_start_date: 1970-01-01 23:59:59 + # g_title: Closed Peer Team Homework + # gradeable_config: cpp_hidden_tests + # g_bucket: homework - - g_id: future_no_tas_test - components: - - gc_lower_clamp: 0 - gc_default: 0 - gc_max_value: 0 - gc_upper_clamp: 5 - gc_title: Question 1 - - gc_lower_clamp: 0 - gc_default: 0 - gc_max_value: 5 - gc_upper_clamp: 5 - gc_title: Question 2 - - gc_is_text: true - gc_title: Text 1 - g_grade_due_date: 9998-12-31 23:59:59 - g_grade_released_date: 9998-12-31 23:59:59 - g_grade_start_date: 9997-12-31 23:59:59 - g_ta_view_start_date: 9996-12-31 23:59:59 - g_title: Future (No TAs) Test - g_type: 2 - g_bucket: test + # - g_id: grading_pdf_peer_homework + # eg_peer_grading: true + # components: + # - gc_lower_clamp: 0 + # gc_is_peer: true + # gc_default: 2 + # gc_max_value: 2 + # gc_upper_clamp: 2 + # gc_title: Read Me + # marks: + # - gcm_note: Full Credit + # gcm_points: 0 + # - gcm_note: Minor errors in Read Me + # gcm_points: -1 + # - gcm_note: Major errors in Read Me or Read Me missing + # gcm_points: -2 + # - gc_lower_clamp: 0 + # gc_default: 5 + # gc_is_peer: true + # gc_max_value: 5 + # gc_upper_clamp: 5 + # gc_title: Coding Style + # marks: + # - gcm_note: Full Credit + # gcm_points: 0 + # - gcm_note: Code is unreadable + # gcm_points: -5 + # - gcm_note: Code is very difficult to understand + # gcm_points: -3 + # - gcm_note: Code is difficult to understand + # gcm_points: -1 + # - gc_lower_clamp: 0 + # gc_default: 5 + # gc_is_peer: true + # gc_max_value: 5 + # gc_upper_clamp: 5 + # gc_title: Documentation + # marks: + # - gcm_note: Full Credit + # gcm_points: 0 + # - gcm_note: No documentation + # gcm_points: -5 + # - gcm_note: Very little documentation or documentation makes no sense + # gcm_points: -3 + # - gcm_note: Way too much documentation and/or documentation makes no sense + # gcm_points: -1 + # - gc_lower_clamp: 0 + # gc_default: 0 + # gc_is_peer: true + # gc_max_value: 0 + # gc_upper_clamp: 5 + # gc_title: Extra Credit + # marks: + # - gcm_note: No Credit + # gcm_points: 0 + # - gcm_note: Extra credit done poorly + # gcm_points: 2 + # - gcm_note: Extra credit is acceptable + # gcm_points: 5 + # eg_submission_due_date: 1972-01-01 23:59:59 + # eg_submission_open_date: 1971-01-01 23:59:59 + # g_grade_due_date: 1974-01-01 23:59:59 + # g_grade_released_date: 1974-01-01 23:59:59 + # eg_grade_inquiry_start_date: 1974-01-08 23:59:59 + # eg_grade_inquiry_due_date: 1974-01-13 23:59:59 + # eg_has_due_date: true + # eg_has_release_date: true + # g_grade_start_date: 1973-01-01 23:59:59 + # g_ta_view_start_date: 1970-01-01 23:59:59 + # g_title: Released Peer PDF Homework + # gradeable_config: multiple_pdf_annotations + # g_bucket: homework + # g_grader_assignment_method: 2 + # eg_annotated_pdf: true - - g_id: notebook_filesubmission - gradeable_config: notebook_filesubmission - components: - - gc_lower_clamp: 0 - gc_default: 5 - gc_max_value: 5 - gc_upper_clamp: 5 - gc_title: Question 1 - marks: - - gcm_note: Full Credit - gcm_points: 0 - - gcm_note: Question 1 Mark 1 - gcm_points: -5 - g_ta_view_start_date: -2 days - eg_submission_open_date: -1 days - eg_submission_due_date: +1000 days - g_grade_start_date: +1005 days - g_grade_due_date: +1010 days - g_grade_released_date: +1010 days - eg_grade_inquiry_start_date: +1012 days - eg_grade_inquiry_due_date: +1015 days - eg_has_due_date: true - eg_has_release_date: true - eg_max_random_submissions: 0 + # - g_id: grading_pdf_peer_team_homework + # eg_peer_grading: true + # components: + # - gc_lower_clamp: 0 + # gc_is_peer: true + # gc_default: 2 + # gc_max_value: 2 + # gc_upper_clamp: 2 + # gc_title: Read Me + # marks: + # - gcm_note: Full Credit + # gcm_points: 0 + # - gcm_note: Minor errors in Read Me + # gcm_points: -1 + # - gcm_note: Major errors in Read Me or Read Me missing + # gcm_points: -2 + # - gc_lower_clamp: 0 + # gc_default: 5 + # gc_is_peer: true + # gc_max_value: 5 + # gc_upper_clamp: 5 + # gc_title: Coding Style + # marks: + # - gcm_note: Full Credit + # gcm_points: 0 + # - gcm_note: Code is unreadable + # gcm_points: -5 + # - gcm_note: Code is very difficult to understand + # gcm_points: -3 + # - gcm_note: Code is difficult to understand + # gcm_points: -1 + # - gc_lower_clamp: 0 + # gc_default: 5 + # gc_is_peer: true + # gc_max_value: 5 + # gc_upper_clamp: 5 + # gc_title: Documentation + # marks: + # - gcm_note: Full Credit + # gcm_points: 0 + # - gcm_note: No documentation + # gcm_points: -5 + # - gcm_note: Very little documentation or documentation makes no sense + # gcm_points: -3 + # - gcm_note: Way too much documentation and/or documentation makes no sense + # gcm_points: -1 + # - gc_lower_clamp: 0 + # gc_default: 0 + # gc_is_peer: true + # gc_max_value: 0 + # gc_upper_clamp: 5 + # gc_title: Extra Credit + # marks: + # - gcm_note: No Credit + # gcm_points: 0 + # - gcm_note: Extra credit done poorly + # gcm_points: 2 + # - gcm_note: Extra credit is acceptable + # gcm_points: 5 + # eg_submission_due_date: 1972-01-01 23:59:59 + # eg_submission_open_date: 1971-01-01 23:59:59 + # g_grade_due_date: 1974-01-01 23:59:59 + # g_grade_released_date: 1974-01-01 23:59:59 + # eg_grade_inquiry_start_date: 1974-01-08 23:59:59 + # eg_grade_inquiry_due_date: 1974-01-13 23:59:59 + # eg_has_due_date: true + # eg_has_release_date: true + # eg_team_assignment: true + # eg_max_team_size: 3 + # g_grade_start_date: 1973-01-01 23:59:59 + # g_ta_view_start_date: 1970-01-01 23:59:59 + # g_title: Released Peer Team PDF Homework + # gradeable_config: multiple_pdf_annotations + # g_bucket: homework + # g_grader_assignment_method: 2 + # eg_annotated_pdf: true - - g_id: future_tas_test - components: - - gc_lower_clamp: 0 - gc_default: 0 - gc_max_value: 0 - gc_upper_clamp: 5 - gc_title: Question 1 - - gc_lower_clamp: 0 - gc_default: 0 - gc_max_value: 5 - gc_upper_clamp: 5 - gc_title: Question 2 - - gc_is_text: true - gc_title: Text 1 - g_grade_due_date: 9998-12-31 23:59:59 - g_grade_released_date: 9998-12-31 23:59:59 - g_grade_start_date: 9997-12-31 23:59:59 - g_ta_view_start_date: 1970-01-01 23:59:59 - g_title: Future (TAs) Test - g_type: 2 - g_bucket: test + # - g_id: closed_team_homework + # eg_peer_grading: true + # components: + # - gc_lower_clamp: 0 + # gc_default: 2 + # gc_max_value: 2 + # gc_upper_clamp: 2 + # gc_title: Read Me + # marks: + # - gcm_note: Full Credit + # gcm_points: 0 + # - gcm_note: Minor errors in Read Me + # gcm_points: -1 + # - gcm_note: Major errors in Read Me or Read Me missing + # gcm_points: -2 + # - gc_lower_clamp: 0 + # gc_default: 5 + # gc_max_value: 5 + # gc_upper_clamp: 5 + # gc_title: Coding Style + # marks: + # - gcm_note: Full Credit + # gcm_points: 0 + # - gcm_note: Code is unreadable + # gcm_points: -5 + # - gcm_note: Code is very difficult to understand + # gcm_points: -3 + # - gcm_note: Code is difficult to understand + # gcm_points: -1 + # - gc_lower_clamp: 0 + # gc_default: 5 + # gc_max_value: 5 + # gc_upper_clamp: 5 + # gc_title: Documentation + # marks: + # - gcm_note: Full Credit + # gcm_points: 0 + # - gcm_note: No documentation + # gcm_points: -5 + # - gcm_note: Very little documentation or documentation makes no sense + # gcm_points: -3 + # - gcm_note: Way too much documentation and/or documentation makes no sense + # gcm_points: -1 + # - gc_lower_clamp: 0 + # gc_default: 0 + # gc_max_value: 0 + # gc_upper_clamp: 5 + # gc_title: Extra Credit + # marks: + # - gcm_note: No Credit + # gcm_points: 0 + # - gcm_note: Extra credit done poorly + # gcm_points: 2 + # - gcm_note: Extra credit is acceptable + # gcm_points: 5 + # eg_submission_due_date: 1972-01-01 23:59:59 + # eg_submission_open_date: 1971-01-01 23:59:59 + # g_grade_due_date: 9998-12-31 23:59:59 + # g_grade_released_date: 9998-12-31 23:59:59 + # eg_grade_inquiry_start_date: 9999-01-01 23:59:59 + # eg_grade_inquiry_due_date: 9999-01-06 23:59:59 + # eg_has_due_date: true + # eg_has_release_date: true + # g_grade_start_date: 9997-12-31 23:59:59 + # eg_team_assignment: true + # eg_max_team_size: 3 + # g_ta_view_start_date: 1970-01-01 23:59:59 + # g_title: Closed Team Homework + # gradeable_config: cpp_hidden_tests + # g_bucket: homework - - g_id: grading_test - components: - - gc_lower_clamp: 0 - gc_default: 0 - gc_max_value: 0 - gc_upper_clamp: 5 - gc_title: Question 1 - - gc_lower_clamp: 0 - gc_default: 0 - gc_max_value: 5 - gc_upper_clamp: 5 - gc_title: Question 2 - - gc_is_text: true - gc_title: Text 1 - g_grade_due_date: 9998-12-31 23:59:59 - g_grade_released_date: 9998-12-31 23:59:59 - g_grade_start_date: 1971-01-01 23:59:59 - g_ta_view_start_date: 1970-01-01 23:59:59 - g_title: Grading Test - g_type: 2 - g_bucket: test + # - g_id: closed_homework + # components: + # - gc_lower_clamp: 0 + # gc_default: 2 + # gc_max_value: 2 + # gc_upper_clamp: 2 + # gc_title: Read Me + # marks: + # - gcm_note: Full Credit + # gcm_points: 0 + # - gcm_note: Minor errors in Read Me + # gcm_points: -1 + # - gcm_note: Major errors in Read Me or Read Me missing + # gcm_points: -2 + # - gc_lower_clamp: 0 + # gc_default: 5 + # gc_max_value: 5 + # gc_upper_clamp: 5 + # gc_title: Coding Style + # marks: + # - gcm_note: Full Credit + # gcm_points: 0 + # - gcm_note: Code is unreadable + # gcm_points: -5 + # - gcm_note: Code is very difficult to understand + # gcm_points: -3 + # - gcm_note: Code is difficult to understand + # gcm_points: -1 + # - gc_lower_clamp: 0 + # gc_default: 5 + # gc_max_value: 5 + # gc_upper_clamp: 5 + # gc_title: Documentation + # marks: + # - gcm_note: Full Credit + # gcm_points: 0 + # - gcm_note: No documentation + # gcm_points: -5 + # - gcm_note: Very little documentation or documentation makes no sense + # gcm_points: -3 + # - gcm_note: Way too much documentation and/or documentation makes no sense + # gcm_points: -1 + # - gc_lower_clamp: 0 + # gc_default: 0 + # gc_max_value: 0 + # gc_upper_clamp: 5 + # gc_title: Extra Credit + # marks: + # - gcm_note: No Credit + # gcm_points: 0 + # - gcm_note: Extra credit done poorly + # gcm_points: 2 + # - gcm_note: Extra credit is acceptable + # gcm_points: 5 + # eg_submission_due_date: 1972-01-01 23:59:59 + # eg_submission_open_date: 1971-01-01 23:59:59 + # g_grade_due_date: 9998-12-31 23:59:59 + # g_grade_released_date: 9998-12-31 23:59:59 + # eg_grade_inquiry_start_date: 9999-01-01 23:59:59 + # eg_grade_inquiry_due_date: 9999-01-06 23:59:59 + # eg_has_due_date: true + # eg_has_release_date: true + # g_grade_start_date: 9997-12-31 23:59:59 + # g_ta_view_start_date: 1970-01-01 23:59:59 + # g_title: Closed Homework + # gradeable_config: python_simple_homework + # g_bucket: homework - - g_id: grading_test_rotating - components: - - gc_lower_clamp: 0 - gc_default: 0 - gc_max_value: 0 - gc_upper_clamp: 5 - gc_title: Question 1 - - gc_lower_clamp: 0 - gc_default: 0 - gc_max_value: 5 - gc_upper_clamp: 5 - gc_title: Question 2 - - gc_is_text: true - gc_title: Text 1 - g_grade_due_date: 9998-12-31 23:59:59 - g_grade_released_date: 9998-12-31 23:59:59 - g_grade_start_date: 1971-01-01 23:59:59 - g_ta_view_start_date: 1970-01-01 23:59:59 - g_title: Grading Test (Rotating Sections) - g_type: 2 - g_bucket: test - g_grader_assignment_method: 0 + # - g_id: late_allowed_homework + # components: + # - gc_lower_clamp: 0 + # gc_default: 5 + # gc_max_value: 5 + # gc_upper_clamp: 5 + # gc_title: Question 1 + # eg_submission_due_date: 1972-01-01 03:59:59 + # eg_submission_open_date: 1971-01-01 03:59:59 + # g_grade_due_date: 9998-12-31 23:59:59 + # g_grade_released_date: 9998-12-31 23:59:59 + # eg_grade_inquiry_start_date: 9999-01-01 23:59:59 + # eg_grade_inquiry_due_date: 9999-01-06 23:59:59 + # eg_has_due_date: true + # eg_has_release_date: true + # eg_late_days: 1 + # g_grade_start_date: 9997-12-31 23:59:59 + # g_ta_view_start_date: 1970-01-01 03:59:59 + # g_title: Late Allowed Homework + # gradeable_config: python_simple_homework + # g_bucket: homework - - g_id: grades_released_test - components: - - gc_lower_clamp: 0 - gc_default: 0 - gc_max_value: 0 - gc_upper_clamp: 5 - gc_title: Question 1 - - gc_lower_clamp: 0 - gc_default: 0 - gc_max_value: 5 - gc_upper_clamp: 5 - gc_title: Question 2 - - gc_is_text: true - gc_title: Text 1 - g_grade_due_date: 1972-01-01 23:59:59 - g_grade_released_date: 1972-01-01 23:59:59 - g_grade_start_date: 1971-01-01 23:59:59 - g_ta_view_start_date: 1970-01-01 23:59:59 - g_title: Grades Released Test - g_type: 2 - g_bucket: test + # - g_id: grading_homework + # components: + # - gc_lower_clamp: 0 + # gc_default: 2 + # gc_max_value: 2 + # gc_upper_clamp: 2 + # gc_title: Read Me + # marks: + # - gcm_note: Full Credit + # gcm_points: 0 + # - gcm_note: Minor errors in Read Me + # gcm_points: -1 + # - gcm_note: Major errors in Read Me or Read Me missing + # gcm_points: -2 + # - gc_lower_clamp: 0 + # gc_default: 5 + # gc_max_value: 5 + # gc_upper_clamp: 5 + # gc_title: Coding Style + # marks: + # - gcm_note: Full Credit + # gcm_points: 0 + # - gcm_note: Code is unreadable + # gcm_points: -5 + # - gcm_note: Code is very difficult to understand + # gcm_points: -3 + # - gcm_note: Code is difficult to understand + # gcm_points: -1 + # - gc_lower_clamp: 0 + # gc_default: 5 + # gc_max_value: 5 + # gc_upper_clamp: 5 + # gc_title: Documentation + # marks: + # - gcm_note: Full Credit + # gcm_points: 0 + # - gcm_note: No documentation + # gcm_points: -5 + # - gcm_note: Very little documentation or documentation makes no sense + # gcm_points: -3 + # - gcm_note: Way too much documentation and/or documentation makes no sense + # gcm_points: -1 + # - gc_lower_clamp: 0 + # gc_default: 0 + # gc_max_value: 0 + # gc_upper_clamp: 5 + # gc_title: Extra Credit + # marks: + # - gcm_note: No Credit + # gcm_points: 0 + # - gcm_note: Extra credit done poorly + # gcm_points: 2 + # - gcm_note: Extra credit is acceptable + # gcm_points: 5 + # eg_submission_due_date: 1972-01-01 23:59:59 + # eg_submission_open_date: 1971-01-01 23:59:59 + # g_grade_due_date: 9998-12-31 23:59:59 + # g_grade_released_date: 9998-12-31 23:59:59 + # eg_grade_inquiry_start_date: 9999-01-01 23:59:59 + # eg_grade_inquiry_due_date: 9999-01-06 23:59:59 + # eg_has_due_date: true + # eg_has_release_date: true + # g_grade_start_date: 1973-01-01 23:59:59 + # g_ta_view_start_date: 1970-01-01 23:59:59 + # g_title: Grading Homework + # gradeable_config: python_simple_homework + # g_bucket: homework - - g_id: grades_released_homework_onlyta - components: - - gc_lower_clamp: 0 - gc_default: 5 - gc_max_value: 5 - gc_upper_clamp: 5 - gc_title: Question 1 - marks: - - gcm_note: Full Credit - gcm_points: 0 - eg_submission_due_date: 1972-01-01 23:59:59 - eg_submission_open_date: 1971-01-01 23:59:59 - g_grade_due_date: 1974-01-01 23:59:59 - g_grade_released_date: 1974-01-01 23:59:59 - eg_grade_inquiry_start_date: 1974-01-02 23:59:59 - eg_grade_inquiry_due_date: 1974-01-08 23:59:59 - eg_has_due_date: true - eg_has_release_date: true - g_grade_start_date: 1973-01-01 23:59:59 - g_ta_view_start_date: 1970-01-01 23:59:59 - g_title: TA Grade Only Homework (Upload Only) - gradeable_config: upload_only - g_bucket: homework + # - g_id: grades_released_homework + # components: + # - gc_lower_clamp: 0 + # gc_default: 5 + # gc_max_value: 5 + # gc_upper_clamp: 5 + # gc_title: Question 1 + # - gc_is_extra_credit: true + # gc_lower_clamp: 0 + # gc_default: 5 + # gc_max_value: 5 + # gc_upper_clamp: 5 + # gc_title: Question 2 + # eg_submission_due_date: 1972-01-01 23:59:59 + # eg_submission_open_date: 1971-01-01 23:59:59 + # g_grade_due_date: 1974-01-01 23:59:59 + # g_grade_released_date: 1974-01-01 23:59:59 + # eg_grade_inquiry_start_date: 1974-01-01 23:59:59 + # eg_grade_inquiry_due_date: 1974-01-08 23:59:59 + # eg_has_due_date: true + # eg_has_release_date: true + # g_grade_start_date: 1973-01-01 23:59:59 + # g_ta_view_start_date: 1970-01-01 23:59:59 + # g_title: Grades Released Homework + # gradeable_config: python_simple_homework + # g_bucket: homework - # For no autograding, still need components, but also need eg_use_ta_grading flag - - g_id: grades_released_homework_onlyauto - components: - - gc_lower_clamp: 0 - gc_default: 2 - gc_max_value: 2 - gc_upper_clamp: 2 - gc_title: Read Me - marks: - - gcm_note: Full Credit - gcm_points: 0 - - gcm_note: Minor errors in Read Me - gcm_points: -1 - - gcm_note: Major errors in Read Me or Read Me missing - gcm_points: -2 - - gc_lower_clamp: 0 - gc_default: 5 - gc_max_value: 5 - gc_upper_clamp: 5 - gc_title: Coding Style - marks: - - gcm_note: Full Credit - gcm_points: 0 - - gcm_note: Code is unreadable - gcm_points: -5 - - gcm_note: Code is very difficult to understand - gcm_points: -3 - - gcm_note: Code is difficult to understand - gcm_points: -1 - - gc_lower_clamp: 0 - gc_default: 5 - gc_max_value: 5 - gc_upper_clamp: 5 - gc_title: Documentation - marks: - - gcm_note: Full Credit - gcm_points: 0 - - gcm_note: No documentation - gcm_points: -5 - - gcm_note: Very little documentation or documentation makes no sense - gcm_points: -3 - - gcm_note: Way too much documentation and/or documentation makes no sense - gcm_points: -1 - - gc_lower_clamp: 0 - gc_default: 0 - gc_max_value: 0 - gc_upper_clamp: 5 - gc_title: Extra Credit - marks: - - gcm_note: No Credit - gcm_points: 0 - - gcm_note: Extra credit done poorly - gcm_points: 2 - - gcm_note: Extra credit is acceptable - gcm_points: 5 - eg_submission_due_date: 1972-01-01 23:59:59 - eg_submission_open_date: 1971-01-01 23:59:59 - g_grade_due_date: 1974-01-01 23:59:59 - g_grade_released_date: 1974-01-01 23:59:59 - eg_grade_inquiry_start_date: 1974-01-02 23:59:59 - eg_grade_inquiry_due_date: 1974-01-08 23:59:59 - eg_has_due_date: true - eg_has_release_date: true - g_grade_start_date: 1973-01-01 23:59:59 - g_ta_view_start_date: 1970-01-01 23:59:59 - g_title: Autograde Only Homework (Simple Python) - gradeable_config: 01_simple_python - eg_use_ta_grading: False - g_bucket: homework + # - g_id: future_no_tas_lab + # components: + # - gc_title: Question 1 + # gc_lower_clamp: 0 + # gc_default: 0 + # gc_max_value: 1 + # gc_upper_clamp: 1 + # - gc_title: Question 2 + # gc_lower_clamp: 0 + # gc_default: 0 + # gc_max_value: 0 + # gc_upper_clamp: 1 + # g_grade_due_date: 9998-12-31 23:59:59 + # g_grade_released_date: 9998-12-31 23:59:59 + # g_grade_start_date: 9997-12-31 23:59:59 + # g_ta_view_start_date: 9996-12-31 23:59:59 + # g_title: Future (No TAs) Lab + # g_type: 1 + # g_bucket: lab - - g_id: grades_released_homework_autota - components: - - gc_lower_clamp: 0 - gc_default: 2 - gc_max_value: 2 - gc_upper_clamp: 2 - gc_title: Read Me - marks: - - gcm_note: Full Credit - gcm_points: 0 - - gcm_note: Minor errors in Read Me - gcm_points: -1 - - gcm_note: Major errors in Read Me or Read Me missing - gcm_points: -2 - - gc_lower_clamp: 0 - gc_default: 5 - gc_max_value: 5 - gc_upper_clamp: 5 - gc_title: Coding Style - marks: - - gcm_note: Full Credit - gcm_points: 0 - - gcm_note: Code is unreadable - gcm_points: -5 - - gcm_note: Code is very difficult to understand - gcm_points: -3 - - gcm_note: Code is difficult to understand - gcm_points: -1 - - gc_lower_clamp: 0 - gc_default: 5 - gc_max_value: 5 - gc_upper_clamp: 5 - gc_title: Documentation - marks: - - gcm_note: Full Credit - gcm_points: 0 - - gcm_note: No documentation - gcm_points: -5 - - gcm_note: Very little documentation or documentation makes no sense - gcm_points: -3 - - gcm_note: Way too much documentation and/or documentation makes no sense - gcm_points: -1 - - gc_lower_clamp: 0 - gc_default: 0 - gc_max_value: 0 - gc_upper_clamp: 5 - gc_title: Extra Credit - marks: - - gcm_note: No Credit - gcm_points: 0 - - gcm_note: Extra credit done poorly - gcm_points: 2 - - gcm_note: Extra credit is acceptable - gcm_points: 5 - eg_submission_due_date: 1972-01-01 23:59:59 - eg_submission_open_date: 1971-01-01 23:59:59 - g_grade_due_date: 1974-01-01 23:59:59 - g_grade_released_date: 1974-01-01 23:59:59 - eg_grade_inquiry_start_date: 1974-01-02 23:59:59 - eg_grade_inquiry_due_date: 1974-01-08 23:59:59 - eg_has_due_date: true - eg_has_release_date: true - g_grade_start_date: 1973-01-01 23:59:59 - g_ta_view_start_date: 1970-01-01 23:59:59 - g_title: Autograde and TA Homework (C System Calls) - gradeable_config: 12_system_calls - g_bucket: homework + # - g_id: future_tas_lab + # components: + # - gc_title: Question 1 + # gc_lower_clamp: 0 + # gc_default: 0 + # gc_max_value: 1 + # gc_upper_clamp: 1 + # - gc_title: Question 2 + # gc_lower_clamp: 0 + # gc_default: 0 + # gc_max_value: 0 + # gc_upper_clamp: 1 + # g_grade_due_date: 9998-12-31 23:59:59 + # g_grade_released_date: 9998-12-31 23:59:59 + # g_grade_start_date: 9997-12-31 23:59:59 + # g_ta_view_start_date: 1970-01-01 23:59:59 + # g_title: Future (TAs) Lab + # g_type: 1 + # g_bucket: lab - - g_id: grades_released_homework_autohiddenEC - components: - - gc_lower_clamp: 0 - gc_default: 2 - gc_max_value: 2 - gc_upper_clamp: 2 - gc_title: Read Me - marks: - - gcm_note: Full Credit - gcm_points: 0 - - gcm_note: Minor errors in Read Me - gcm_points: -1 - - gcm_note: Major errors in Read Me or Read Me missing - gcm_points: -2 - - gc_lower_clamp: 0 - gc_default: 5 - gc_max_value: 5 - gc_upper_clamp: 5 - gc_title: Coding Style - marks: - - gcm_note: Full Credit - gcm_points: 0 - - gcm_note: Code is unreadable - gcm_points: -5 - - gcm_note: Code is very difficult to understand - gcm_points: -3 - - gcm_note: Code is difficult to understand - gcm_points: -1 - - gc_lower_clamp: 0 - gc_default: 5 - gc_max_value: 5 - gc_upper_clamp: 5 - gc_title: Documentation - marks: - - gcm_note: Full Credit - gcm_points: 0 - - gcm_note: No documentation - gcm_points: -5 - - gcm_note: Very little documentation or documentation makes no sense - gcm_points: -3 - - gcm_note: Way too much documentation and/or documentation makes no sense - gcm_points: -1 - - gc_lower_clamp: 0 - gc_default: 0 - gc_max_value: 0 - gc_upper_clamp: 5 - gc_title: Extra Credit - marks: - - gcm_note: No Credit - gcm_points: 0 - - gcm_note: Extra credit done poorly - gcm_points: 2 - - gcm_note: Extra credit is acceptable - gcm_points: 5 - eg_submission_due_date: 1972-01-01 23:59:59 - eg_submission_open_date: 1971-01-01 23:59:59 - g_grade_due_date: 1974-01-01 23:59:59 - g_grade_released_date: 1974-01-01 23:59:59 - eg_grade_inquiry_start_date: 1974-01-02 23:59:59 - eg_grade_inquiry_due_date: 1974-01-08 23:59:59 - eg_has_due_date: true - eg_has_release_date: true - g_grade_start_date: 1973-01-01 23:59:59 - g_ta_view_start_date: 1970-01-01 23:59:59 - g_title: Autograder Hidden and Extra Credit (C++ Hidden Tests) - gradeable_config: cpp_hidden_tests - g_bucket: homework + # - g_id: grading_lab + # components: + # - gc_title: Question 1 + # gc_lower_clamp: 0 + # gc_default: 0 + # gc_max_value: 1 + # gc_upper_clamp: 1 + # - gc_title: Question 2 + # gc_lower_clamp: 0 + # gc_default: 0 + # gc_max_value: 0 + # gc_upper_clamp: 1 + # g_grade_due_date: 9998-12-31 23:59:59 + # g_grade_released_date: 9998-12-31 23:59:59 + # g_grade_start_date: 1971-01-01 23:59:59 + # g_ta_view_start_date: 1970-01-01 23:59:59 + # g_title: Grading Lab + # g_type: 1 + # g_bucket: lab + + # - g_id: grading_lab_rotating + # components: + # - gc_title: Question 1 + # gc_lower_clamp: 0 + # gc_default: 0 + # gc_max_value: 1 + # gc_upper_clamp: 1 + # - gc_title: Question 2 + # gc_lower_clamp: 0 + # gc_default: 0 + # gc_max_value: 0 + # gc_upper_clamp: 1 + # g_grade_due_date: 9998-12-31 23:59:59 + # g_grade_released_date: 9998-12-31 23:59:59 + # g_grade_start_date: 1971-01-01 23:59:59 + # g_ta_view_start_date: 1970-01-01 23:59:59 + # g_title: Grading Lab (Rotating Sections) + # g_type: 1 + # g_bucket: lab + # g_grader_assignment_method: 0 + + # - g_id: grades_released_lab + # components: + # - gc_title: Question 1 + # gc_lower_clamp: 0 + # gc_default: 0 + # gc_max_value: 1 + # gc_upper_clamp: 1 + # - gc_title: Question 2 + # gc_lower_clamp: 0 + # gc_default: 0 + # gc_max_value: 0 + # gc_upper_clamp: 1 + # g_grade_due_date: 1972-01-01 23:59:59 + # g_grade_released_date: 1972-01-01 23:59:59 + # g_grade_start_date: 1971-01-01 23:59:59 + # g_ta_view_start_date: 1970-01-01 23:59:59 + # g_title: Grades Released Lab + # g_type: 1 + # g_bucket: lab + + # - g_id: future_no_tas_test + # components: + # - gc_lower_clamp: 0 + # gc_default: 0 + # gc_max_value: 0 + # gc_upper_clamp: 5 + # gc_title: Question 1 + # - gc_lower_clamp: 0 + # gc_default: 0 + # gc_max_value: 5 + # gc_upper_clamp: 5 + # gc_title: Question 2 + # - gc_is_text: true + # gc_title: Text 1 + # g_grade_due_date: 9998-12-31 23:59:59 + # g_grade_released_date: 9998-12-31 23:59:59 + # g_grade_start_date: 9997-12-31 23:59:59 + # g_ta_view_start_date: 9996-12-31 23:59:59 + # g_title: Future (No TAs) Test + # g_type: 2 + # g_bucket: test + + # - g_id: notebook_filesubmission + # gradeable_config: notebook_filesubmission + # components: + # - gc_lower_clamp: 0 + # gc_default: 5 + # gc_max_value: 5 + # gc_upper_clamp: 5 + # gc_title: Question 1 + # marks: + # - gcm_note: Full Credit + # gcm_points: 0 + # - gcm_note: Question 1 Mark 1 + # gcm_points: -5 + # g_ta_view_start_date: -2 days + # eg_submission_open_date: -1 days + # eg_submission_due_date: +1000 days + # g_grade_start_date: +1005 days + # g_grade_due_date: +1010 days + # g_grade_released_date: +1010 days + # eg_grade_inquiry_start_date: +1012 days + # eg_grade_inquiry_due_date: +1015 days + # eg_has_due_date: true + # eg_has_release_date: true + # eg_max_random_submissions: 0 + + # - g_id: future_tas_test + # components: + # - gc_lower_clamp: 0 + # gc_default: 0 + # gc_max_value: 0 + # gc_upper_clamp: 5 + # gc_title: Question 1 + # - gc_lower_clamp: 0 + # gc_default: 0 + # gc_max_value: 5 + # gc_upper_clamp: 5 + # gc_title: Question 2 + # - gc_is_text: true + # gc_title: Text 1 + # g_grade_due_date: 9998-12-31 23:59:59 + # g_grade_released_date: 9998-12-31 23:59:59 + # g_grade_start_date: 9997-12-31 23:59:59 + # g_ta_view_start_date: 1970-01-01 23:59:59 + # g_title: Future (TAs) Test + # g_type: 2 + # g_bucket: test + + # - g_id: grading_test + # components: + # - gc_lower_clamp: 0 + # gc_default: 0 + # gc_max_value: 0 + # gc_upper_clamp: 5 + # gc_title: Question 1 + # - gc_lower_clamp: 0 + # gc_default: 0 + # gc_max_value: 5 + # gc_upper_clamp: 5 + # gc_title: Question 2 + # - gc_is_text: true + # gc_title: Text 1 + # g_grade_due_date: 9998-12-31 23:59:59 + # g_grade_released_date: 9998-12-31 23:59:59 + # g_grade_start_date: 1971-01-01 23:59:59 + # g_ta_view_start_date: 1970-01-01 23:59:59 + # g_title: Grading Test + # g_type: 2 + # g_bucket: test + + # - g_id: grading_test_rotating + # components: + # - gc_lower_clamp: 0 + # gc_default: 0 + # gc_max_value: 0 + # gc_upper_clamp: 5 + # gc_title: Question 1 + # - gc_lower_clamp: 0 + # gc_default: 0 + # gc_max_value: 5 + # gc_upper_clamp: 5 + # gc_title: Question 2 + # - gc_is_text: true + # gc_title: Text 1 + # g_grade_due_date: 9998-12-31 23:59:59 + # g_grade_released_date: 9998-12-31 23:59:59 + # g_grade_start_date: 1971-01-01 23:59:59 + # g_ta_view_start_date: 1970-01-01 23:59:59 + # g_title: Grading Test (Rotating Sections) + # g_type: 2 + # g_bucket: test + # g_grader_assignment_method: 0 + + # - g_id: grades_released_test + # components: + # - gc_lower_clamp: 0 + # gc_default: 0 + # gc_max_value: 0 + # gc_upper_clamp: 5 + # gc_title: Question 1 + # - gc_lower_clamp: 0 + # gc_default: 0 + # gc_max_value: 5 + # gc_upper_clamp: 5 + # gc_title: Question 2 + # - gc_is_text: true + # gc_title: Text 1 + # g_grade_due_date: 1972-01-01 23:59:59 + # g_grade_released_date: 1972-01-01 23:59:59 + # g_grade_start_date: 1971-01-01 23:59:59 + # g_ta_view_start_date: 1970-01-01 23:59:59 + # g_title: Grades Released Test + # g_type: 2 + # g_bucket: test + + # - g_id: grades_released_homework_onlyta + # components: + # - gc_lower_clamp: 0 + # gc_default: 5 + # gc_max_value: 5 + # gc_upper_clamp: 5 + # gc_title: Question 1 + # marks: + # - gcm_note: Full Credit + # gcm_points: 0 + # eg_submission_due_date: 1972-01-01 23:59:59 + # eg_submission_open_date: 1971-01-01 23:59:59 + # g_grade_due_date: 1974-01-01 23:59:59 + # g_grade_released_date: 1974-01-01 23:59:59 + # eg_grade_inquiry_start_date: 1974-01-02 23:59:59 + # eg_grade_inquiry_due_date: 1974-01-08 23:59:59 + # eg_has_due_date: true + # eg_has_release_date: true + # g_grade_start_date: 1973-01-01 23:59:59 + # g_ta_view_start_date: 1970-01-01 23:59:59 + # g_title: TA Grade Only Homework (Upload Only) + # gradeable_config: upload_only + # g_bucket: homework + + # # For no autograding, still need components, but also need eg_use_ta_grading flag + # - g_id: grades_released_homework_onlyauto + # components: + # - gc_lower_clamp: 0 + # gc_default: 2 + # gc_max_value: 2 + # gc_upper_clamp: 2 + # gc_title: Read Me + # marks: + # - gcm_note: Full Credit + # gcm_points: 0 + # - gcm_note: Minor errors in Read Me + # gcm_points: -1 + # - gcm_note: Major errors in Read Me or Read Me missing + # gcm_points: -2 + # - gc_lower_clamp: 0 + # gc_default: 5 + # gc_max_value: 5 + # gc_upper_clamp: 5 + # gc_title: Coding Style + # marks: + # - gcm_note: Full Credit + # gcm_points: 0 + # - gcm_note: Code is unreadable + # gcm_points: -5 + # - gcm_note: Code is very difficult to understand + # gcm_points: -3 + # - gcm_note: Code is difficult to understand + # gcm_points: -1 + # - gc_lower_clamp: 0 + # gc_default: 5 + # gc_max_value: 5 + # gc_upper_clamp: 5 + # gc_title: Documentation + # marks: + # - gcm_note: Full Credit + # gcm_points: 0 + # - gcm_note: No documentation + # gcm_points: -5 + # - gcm_note: Very little documentation or documentation makes no sense + # gcm_points: -3 + # - gcm_note: Way too much documentation and/or documentation makes no sense + # gcm_points: -1 + # - gc_lower_clamp: 0 + # gc_default: 0 + # gc_max_value: 0 + # gc_upper_clamp: 5 + # gc_title: Extra Credit + # marks: + # - gcm_note: No Credit + # gcm_points: 0 + # - gcm_note: Extra credit done poorly + # gcm_points: 2 + # - gcm_note: Extra credit is acceptable + # gcm_points: 5 + # eg_submission_due_date: 1972-01-01 23:59:59 + # eg_submission_open_date: 1971-01-01 23:59:59 + # g_grade_due_date: 1974-01-01 23:59:59 + # g_grade_released_date: 1974-01-01 23:59:59 + # eg_grade_inquiry_start_date: 1974-01-02 23:59:59 + # eg_grade_inquiry_due_date: 1974-01-08 23:59:59 + # eg_has_due_date: true + # eg_has_release_date: true + # g_grade_start_date: 1973-01-01 23:59:59 + # g_ta_view_start_date: 1970-01-01 23:59:59 + # g_title: Autograde Only Homework (Simple Python) + # gradeable_config: 01_simple_python + # eg_use_ta_grading: False + # g_bucket: homework + + # - g_id: grades_released_homework_autota + # components: + # - gc_lower_clamp: 0 + # gc_default: 2 + # gc_max_value: 2 + # gc_upper_clamp: 2 + # gc_title: Read Me + # marks: + # - gcm_note: Full Credit + # gcm_points: 0 + # - gcm_note: Minor errors in Read Me + # gcm_points: -1 + # - gcm_note: Major errors in Read Me or Read Me missing + # gcm_points: -2 + # - gc_lower_clamp: 0 + # gc_default: 5 + # gc_max_value: 5 + # gc_upper_clamp: 5 + # gc_title: Coding Style + # marks: + # - gcm_note: Full Credit + # gcm_points: 0 + # - gcm_note: Code is unreadable + # gcm_points: -5 + # - gcm_note: Code is very difficult to understand + # gcm_points: -3 + # - gcm_note: Code is difficult to understand + # gcm_points: -1 + # - gc_lower_clamp: 0 + # gc_default: 5 + # gc_max_value: 5 + # gc_upper_clamp: 5 + # gc_title: Documentation + # marks: + # - gcm_note: Full Credit + # gcm_points: 0 + # - gcm_note: No documentation + # gcm_points: -5 + # - gcm_note: Very little documentation or documentation makes no sense + # gcm_points: -3 + # - gcm_note: Way too much documentation and/or documentation makes no sense + # gcm_points: -1 + # - gc_lower_clamp: 0 + # gc_default: 0 + # gc_max_value: 0 + # gc_upper_clamp: 5 + # gc_title: Extra Credit + # marks: + # - gcm_note: No Credit + # gcm_points: 0 + # - gcm_note: Extra credit done poorly + # gcm_points: 2 + # - gcm_note: Extra credit is acceptable + # gcm_points: 5 + # eg_submission_due_date: 1972-01-01 23:59:59 + # eg_submission_open_date: 1971-01-01 23:59:59 + # g_grade_due_date: 1974-01-01 23:59:59 + # g_grade_released_date: 1974-01-01 23:59:59 + # eg_grade_inquiry_start_date: 1974-01-02 23:59:59 + # eg_grade_inquiry_due_date: 1974-01-08 23:59:59 + # eg_has_due_date: true + # eg_has_release_date: true + # g_grade_start_date: 1973-01-01 23:59:59 + # g_ta_view_start_date: 1970-01-01 23:59:59 + # g_title: Autograde and TA Homework (C System Calls) + # gradeable_config: 12_system_calls + # g_bucket: homework - - g_id: grading_homework_pdf - components: - - gc_lower_clamp: 0 - gc_default: 2 - gc_max_value: 2 - gc_upper_clamp: 2 - gc_title: Read Me - marks: - - gcm_note: Full Credit - gcm_points: 0 - - gcm_note: Minor errors in Read Me - gcm_points: -1 - - gcm_note: Major errors in Read Me or Read Me missing - gcm_points: -2 - - gc_lower_clamp: 0 - gc_default: 5 - gc_max_value: 5 - gc_upper_clamp: 5 - gc_title: Coding Style - marks: - - gcm_note: Full Credit - gcm_points: 0 - - gcm_note: Code is unreadable - gcm_points: -5 - - gcm_note: Code is very difficult to understand - gcm_points: -3 - - gcm_note: Code is difficult to understand - gcm_points: -1 - - gc_lower_clamp: 0 - gc_default: 5 - gc_max_value: 5 - gc_upper_clamp: 5 - gc_title: Documentation - marks: - - gcm_note: Full Credit - gcm_points: 0 - - gcm_note: No documentation - gcm_points: -5 - - gcm_note: Very little documentation or documentation makes no sense - gcm_points: -3 - - gcm_note: Way too much documentation and/or documentation makes no sense - gcm_points: -1 - - gc_lower_clamp: 0 - gc_default: 0 - gc_max_value: 0 - gc_upper_clamp: 5 - gc_title: Extra Credit - marks: - - gcm_note: No Credit - gcm_points: 0 - - gcm_note: Extra credit done poorly - gcm_points: 2 - - gcm_note: Extra credit is acceptable - gcm_points: 5 - eg_submission_due_date: 1972-01-01 23:59:59 - eg_submission_open_date: 1971-01-01 23:59:59 - g_grade_due_date: 9998-12-31 23:59:59 - g_grade_released_date: 9998-12-31 23:59:59 - eg_grade_inquiry_start_date: 9999-01-01 23:59:59 - eg_grade_inquiry_due_date: 9999-01-06 23:59:59 - eg_has_due_date: true - eg_has_release_date: true - g_grade_start_date: 1973-01-01 23:59:59 - g_ta_view_start_date: 1970-01-01 23:59:59 - g_title: Grading Homework PDF - gradeable_config: pdf_word_count - g_bucket: homework + # - g_id: grades_released_homework_autohiddenEC + # components: + # - gc_lower_clamp: 0 + # gc_default: 2 + # gc_max_value: 2 + # gc_upper_clamp: 2 + # gc_title: Read Me + # marks: + # - gcm_note: Full Credit + # gcm_points: 0 + # - gcm_note: Minor errors in Read Me + # gcm_points: -1 + # - gcm_note: Major errors in Read Me or Read Me missing + # gcm_points: -2 + # - gc_lower_clamp: 0 + # gc_default: 5 + # gc_max_value: 5 + # gc_upper_clamp: 5 + # gc_title: Coding Style + # marks: + # - gcm_note: Full Credit + # gcm_points: 0 + # - gcm_note: Code is unreadable + # gcm_points: -5 + # - gcm_note: Code is very difficult to understand + # gcm_points: -3 + # - gcm_note: Code is difficult to understand + # gcm_points: -1 + # - gc_lower_clamp: 0 + # gc_default: 5 + # gc_max_value: 5 + # gc_upper_clamp: 5 + # gc_title: Documentation + # marks: + # - gcm_note: Full Credit + # gcm_points: 0 + # - gcm_note: No documentation + # gcm_points: -5 + # - gcm_note: Very little documentation or documentation makes no sense + # gcm_points: -3 + # - gcm_note: Way too much documentation and/or documentation makes no sense + # gcm_points: -1 + # - gc_lower_clamp: 0 + # gc_default: 0 + # gc_max_value: 0 + # gc_upper_clamp: 5 + # gc_title: Extra Credit + # marks: + # - gcm_note: No Credit + # gcm_points: 0 + # - gcm_note: Extra credit done poorly + # gcm_points: 2 + # - gcm_note: Extra credit is acceptable + # gcm_points: 5 + # eg_submission_due_date: 1972-01-01 23:59:59 + # eg_submission_open_date: 1971-01-01 23:59:59 + # g_grade_due_date: 1974-01-01 23:59:59 + # g_grade_released_date: 1974-01-01 23:59:59 + # eg_grade_inquiry_start_date: 1974-01-02 23:59:59 + # eg_grade_inquiry_due_date: 1974-01-08 23:59:59 + # eg_has_due_date: true + # eg_has_release_date: true + # g_grade_start_date: 1973-01-01 23:59:59 + # g_ta_view_start_date: 1970-01-01 23:59:59 + # g_title: Autograder Hidden and Extra Credit (C++ Hidden Tests) + # gradeable_config: cpp_hidden_tests + # g_bucket: homework - - g_id: grading_homework_team_pdf - components: - - gc_lower_clamp: 0 - gc_default: 2 - gc_max_value: 2 - gc_upper_clamp: 2 - gc_title: Read Me - marks: - - gcm_note: Full Credit - gcm_points: 0 - - gcm_note: Minor errors in Read Me - gcm_points: -1 - - gcm_note: Major errors in Read Me or Read Me missing - gcm_points: -2 - - gc_lower_clamp: 0 - gc_default: 5 - gc_max_value: 5 - gc_upper_clamp: 5 - gc_title: Coding Style - marks: - - gcm_note: Full Credit - gcm_points: 0 - - gcm_note: Code is unreadable - gcm_points: -5 - - gcm_note: Code is very difficult to understand - gcm_points: -3 - - gcm_note: Code is difficult to understand - gcm_points: -1 - - gc_lower_clamp: 0 - gc_default: 5 - gc_max_value: 5 - gc_upper_clamp: 5 - gc_title: Documentation - marks: - - gcm_note: Full Credit - gcm_points: 0 - - gcm_note: No documentation - gcm_points: -5 - - gcm_note: Very little documentation or documentation makes no sense - gcm_points: -3 - - gcm_note: Way too much documentation and/or documentation makes no sense - gcm_points: -1 - - gc_lower_clamp: 0 - gc_default: 0 - gc_max_value: 0 - gc_upper_clamp: 5 - gc_title: Extra Credit - marks: - - gcm_note: No Credit - gcm_points: 0 - - gcm_note: Extra credit done poorly - gcm_points: 2 - - gcm_note: Extra credit is acceptable - gcm_points: 5 - eg_submission_due_date: 1972-01-01 23:59:59 - eg_submission_open_date: 1971-01-01 23:59:59 - g_grade_due_date: 9998-12-31 23:59:59 - g_grade_released_date: 9998-12-31 23:59:59 - eg_grade_inquiry_start_date: 9999-01-01 23:59:59 - eg_grade_inquiry_due_date: 9999-01-06 23:59:59 - eg_has_due_date: true - eg_has_release_date: true - eg_team_assignment: true - eg_max_team_size: 3 - g_grade_start_date: 1973-01-01 23:59:59 - g_ta_view_start_date: 1970-01-01 23:59:59 - g_title: Grading Homework Team PDF - gradeable_config: pdf_word_count - g_bucket: homework - g_grader_assignment_method: 0 + # - g_id: grading_homework_pdf + # components: + # - gc_lower_clamp: 0 + # gc_default: 2 + # gc_max_value: 2 + # gc_upper_clamp: 2 + # gc_title: Read Me + # marks: + # - gcm_note: Full Credit + # gcm_points: 0 + # - gcm_note: Minor errors in Read Me + # gcm_points: -1 + # - gcm_note: Major errors in Read Me or Read Me missing + # gcm_points: -2 + # - gc_lower_clamp: 0 + # gc_default: 5 + # gc_max_value: 5 + # gc_upper_clamp: 5 + # gc_title: Coding Style + # marks: + # - gcm_note: Full Credit + # gcm_points: 0 + # - gcm_note: Code is unreadable + # gcm_points: -5 + # - gcm_note: Code is very difficult to understand + # gcm_points: -3 + # - gcm_note: Code is difficult to understand + # gcm_points: -1 + # - gc_lower_clamp: 0 + # gc_default: 5 + # gc_max_value: 5 + # gc_upper_clamp: 5 + # gc_title: Documentation + # marks: + # - gcm_note: Full Credit + # gcm_points: 0 + # - gcm_note: No documentation + # gcm_points: -5 + # - gcm_note: Very little documentation or documentation makes no sense + # gcm_points: -3 + # - gcm_note: Way too much documentation and/or documentation makes no sense + # gcm_points: -1 + # - gc_lower_clamp: 0 + # gc_default: 0 + # gc_max_value: 0 + # gc_upper_clamp: 5 + # gc_title: Extra Credit + # marks: + # - gcm_note: No Credit + # gcm_points: 0 + # - gcm_note: Extra credit done poorly + # gcm_points: 2 + # - gcm_note: Extra credit is acceptable + # gcm_points: 5 + # eg_submission_due_date: 1972-01-01 23:59:59 + # eg_submission_open_date: 1971-01-01 23:59:59 + # g_grade_due_date: 9998-12-31 23:59:59 + # g_grade_released_date: 9998-12-31 23:59:59 + # eg_grade_inquiry_start_date: 9999-01-01 23:59:59 + # eg_grade_inquiry_due_date: 9999-01-06 23:59:59 + # eg_has_due_date: true + # eg_has_release_date: true + # g_grade_start_date: 1973-01-01 23:59:59 + # g_ta_view_start_date: 1970-01-01 23:59:59 + # g_title: Grading Homework PDF + # gradeable_config: pdf_word_count + # g_bucket: homework - - g_id: grades_released_homework_onlytaEC - components: - - gc_lower_clamp: 0 - gc_default: 2 - gc_max_value: 2 - gc_upper_clamp: 2 - gc_title: Read Me - marks: - - gcm_note: Full Credit - gcm_points: 0 - - gcm_note: Minor errors in Read Me - gcm_points: -1 - - gcm_note: Major errors in Read Me or Read Me missing - gcm_points: -2 - - gc_lower_clamp: 0 - gc_default: 5 - gc_max_value: 5 - gc_upper_clamp: 5 - gc_title: Coding Style - marks: - - gcm_note: Full Credit - gcm_points: 0 - - gcm_note: Code is unreadable - gcm_points: -5 - - gcm_note: Code is very difficult to understand - gcm_points: -3 - - gcm_note: Code is difficult to understand - gcm_points: -1 - - gc_lower_clamp: 0 - gc_default: 5 - gc_max_value: 5 - gc_upper_clamp: 5 - gc_title: Documentation - marks: - - gcm_note: Full Credit - gcm_points: 0 - - gcm_note: No documentation - gcm_points: -5 - - gcm_note: Very little documentation or documentation makes no sense - gcm_points: -3 - - gcm_note: Way too much documentation and/or documentation makes no sense - gcm_points: -1 - - gc_lower_clamp: 0 - gc_default: 0 - gc_max_value: 0 - gc_upper_clamp: 5 - gc_title: Extra Credit - marks: - - gcm_note: No Credit - gcm_points: 0 - - gcm_note: Extra credit done poorly - gcm_points: 2 - - gcm_note: Extra credit is acceptable - gcm_points: 5 - eg_submission_due_date: 1972-01-01 23:59:59 - eg_submission_open_date: 1971-01-01 23:59:59 - g_grade_due_date: 1974-01-01 23:59:59 - g_grade_released_date: 1974-01-01 23:59:59 - eg_grade_inquiry_start_date: 1974-01-02 23:59:59 - eg_grade_inquiry_due_date: 1974-01-08 23:59:59 - eg_has_due_date: true - eg_has_release_date: true - g_grade_start_date: 1973-01-01 23:59:59 - g_ta_view_start_date: 1970-01-01 23:59:59 - g_title: TA Only w/ Extra Credit (Upload Only) - gradeable_config: upload_only - g_bucket: homework + # - g_id: grading_homework_team_pdf + # components: + # - gc_lower_clamp: 0 + # gc_default: 2 + # gc_max_value: 2 + # gc_upper_clamp: 2 + # gc_title: Read Me + # marks: + # - gcm_note: Full Credit + # gcm_points: 0 + # - gcm_note: Minor errors in Read Me + # gcm_points: -1 + # - gcm_note: Major errors in Read Me or Read Me missing + # gcm_points: -2 + # - gc_lower_clamp: 0 + # gc_default: 5 + # gc_max_value: 5 + # gc_upper_clamp: 5 + # gc_title: Coding Style + # marks: + # - gcm_note: Full Credit + # gcm_points: 0 + # - gcm_note: Code is unreadable + # gcm_points: -5 + # - gcm_note: Code is very difficult to understand + # gcm_points: -3 + # - gcm_note: Code is difficult to understand + # gcm_points: -1 + # - gc_lower_clamp: 0 + # gc_default: 5 + # gc_max_value: 5 + # gc_upper_clamp: 5 + # gc_title: Documentation + # marks: + # - gcm_note: Full Credit + # gcm_points: 0 + # - gcm_note: No documentation + # gcm_points: -5 + # - gcm_note: Very little documentation or documentation makes no sense + # gcm_points: -3 + # - gcm_note: Way too much documentation and/or documentation makes no sense + # gcm_points: -1 + # - gc_lower_clamp: 0 + # gc_default: 0 + # gc_max_value: 0 + # gc_upper_clamp: 5 + # gc_title: Extra Credit + # marks: + # - gcm_note: No Credit + # gcm_points: 0 + # - gcm_note: Extra credit done poorly + # gcm_points: 2 + # - gcm_note: Extra credit is acceptable + # gcm_points: 5 + # eg_submission_due_date: 1972-01-01 23:59:59 + # eg_submission_open_date: 1971-01-01 23:59:59 + # g_grade_due_date: 9998-12-31 23:59:59 + # g_grade_released_date: 9998-12-31 23:59:59 + # eg_grade_inquiry_start_date: 9999-01-01 23:59:59 + # eg_grade_inquiry_due_date: 9999-01-06 23:59:59 + # eg_has_due_date: true + # eg_has_release_date: true + # eg_team_assignment: true + # eg_max_team_size: 3 + # g_grade_start_date: 1973-01-01 23:59:59 + # g_ta_view_start_date: 1970-01-01 23:59:59 + # g_title: Grading Homework Team PDF + # gradeable_config: pdf_word_count + # g_bucket: homework + # g_grader_assignment_method: 0 - - g_id: grades_released_homework_onlytaPenalty - components: - - gc_lower_clamp: 0 - gc_default: 2 - gc_max_value: 2 - gc_upper_clamp: 2 - gc_title: Read Me - marks: - - gcm_note: Full Credit - gcm_points: 0 - - gcm_note: Minor errors in Read Me - gcm_points: -1 - - gcm_note: Major errors in Read Me or Read Me missing - gcm_points: -2 - - gc_lower_clamp: 0 - gc_default: 5 - gc_max_value: 5 - gc_upper_clamp: 5 - gc_title: Coding Style - marks: - - gcm_note: Full Credit - gcm_points: 0 - - gcm_note: Code is unreadable - gcm_points: -5 - - gcm_note: Code is very difficult to understand - gcm_points: -3 - - gcm_note: Code is difficult to understand - gcm_points: -1 - - gc_lower_clamp: 0 - gc_default: 5 - gc_max_value: 5 - gc_upper_clamp: 5 - gc_title: Documentation - marks: - - gcm_note: Full Credit - gcm_points: 0 - - gcm_note: No documentation - gcm_points: -5 - - gcm_note: Very little documentation or documentation makes no sense - gcm_points: -3 - - gcm_note: Way too much documentation and/or documentation makes no sense - gcm_points: -1 - - gc_lower_clamp: 0 - gc_default: 0 - gc_max_value: 0 - gc_upper_clamp: 5 - gc_title: Extra Credit - marks: - - gcm_note: No Credit - gcm_points: 0 - - gcm_note: Extra credit done poorly - gcm_points: 2 - - gcm_note: Extra credit is acceptable - gcm_points: 5 - eg_submission_due_date: 1972-01-01 23:59:59 - eg_submission_open_date: 1971-01-01 23:59:59 - g_grade_due_date: 1974-01-01 23:59:59 - g_grade_released_date: 1974-01-01 23:59:59 - eg_grade_inquiry_start_date: 1974-01-02 23:59:59 - eg_grade_inquiry_due_date: 1974-01-08 23:59:59 - eg_has_due_date: true - eg_has_release_date: true - g_grade_start_date: 1973-01-01 23:59:59 - g_ta_view_start_date: 1970-01-01 23:59:59 - g_title: TA Only w/ Penalty (Upload Only) - gradeable_config: upload_only - g_bucket: homework + # - g_id: grades_released_homework_onlytaEC + # components: + # - gc_lower_clamp: 0 + # gc_default: 2 + # gc_max_value: 2 + # gc_upper_clamp: 2 + # gc_title: Read Me + # marks: + # - gcm_note: Full Credit + # gcm_points: 0 + # - gcm_note: Minor errors in Read Me + # gcm_points: -1 + # - gcm_note: Major errors in Read Me or Read Me missing + # gcm_points: -2 + # - gc_lower_clamp: 0 + # gc_default: 5 + # gc_max_value: 5 + # gc_upper_clamp: 5 + # gc_title: Coding Style + # marks: + # - gcm_note: Full Credit + # gcm_points: 0 + # - gcm_note: Code is unreadable + # gcm_points: -5 + # - gcm_note: Code is very difficult to understand + # gcm_points: -3 + # - gcm_note: Code is difficult to understand + # gcm_points: -1 + # - gc_lower_clamp: 0 + # gc_default: 5 + # gc_max_value: 5 + # gc_upper_clamp: 5 + # gc_title: Documentation + # marks: + # - gcm_note: Full Credit + # gcm_points: 0 + # - gcm_note: No documentation + # gcm_points: -5 + # - gcm_note: Very little documentation or documentation makes no sense + # gcm_points: -3 + # - gcm_note: Way too much documentation and/or documentation makes no sense + # gcm_points: -1 + # - gc_lower_clamp: 0 + # gc_default: 0 + # gc_max_value: 0 + # gc_upper_clamp: 5 + # gc_title: Extra Credit + # marks: + # - gcm_note: No Credit + # gcm_points: 0 + # - gcm_note: Extra credit done poorly + # gcm_points: 2 + # - gcm_note: Extra credit is acceptable + # gcm_points: 5 + # eg_submission_due_date: 1972-01-01 23:59:59 + # eg_submission_open_date: 1971-01-01 23:59:59 + # g_grade_due_date: 1974-01-01 23:59:59 + # g_grade_released_date: 1974-01-01 23:59:59 + # eg_grade_inquiry_start_date: 1974-01-02 23:59:59 + # eg_grade_inquiry_due_date: 1974-01-08 23:59:59 + # eg_has_due_date: true + # eg_has_release_date: true + # g_grade_start_date: 1973-01-01 23:59:59 + # g_ta_view_start_date: 1970-01-01 23:59:59 + # g_title: TA Only w/ Extra Credit (Upload Only) + # gradeable_config: upload_only + # g_bucket: homework - - gradeable_config: leaderboard - components: - - gc_lower_clamp: 0 - gc_default: 11 - gc_max_value: 11 - gc_upper_clamp: 11 - gc_title: Question 1 - marks: - - gcm_note: Full Credit - gcm_points: 0 - g_ta_view_start_date: 1970-01-01 23:59:59 - eg_submission_open_date: 1971-01-01 23:59:59 - eg_submission_due_date: 9996-12-31 23:59:59 - g_grade_start_date: 9997-12-31 23:59:59 - g_grade_due_date: 9998-12-31 23:59:59 - g_grade_released_date: 9998-12-31 23:59:59 - eg_grade_inquiry_start_date: 9999-01-01 23:59:59 - eg_grade_inquiry_due_date: 9999-01-06 23:59:59 - eg_has_due_date: true - eg_has_release_date: true + # - g_id: grades_released_homework_onlytaPenalty + # components: + # - gc_lower_clamp: 0 + # gc_default: 2 + # gc_max_value: 2 + # gc_upper_clamp: 2 + # gc_title: Read Me + # marks: + # - gcm_note: Full Credit + # gcm_points: 0 + # - gcm_note: Minor errors in Read Me + # gcm_points: -1 + # - gcm_note: Major errors in Read Me or Read Me missing + # gcm_points: -2 + # - gc_lower_clamp: 0 + # gc_default: 5 + # gc_max_value: 5 + # gc_upper_clamp: 5 + # gc_title: Coding Style + # marks: + # - gcm_note: Full Credit + # gcm_points: 0 + # - gcm_note: Code is unreadable + # gcm_points: -5 + # - gcm_note: Code is very difficult to understand + # gcm_points: -3 + # - gcm_note: Code is difficult to understand + # gcm_points: -1 + # - gc_lower_clamp: 0 + # gc_default: 5 + # gc_max_value: 5 + # gc_upper_clamp: 5 + # gc_title: Documentation + # marks: + # - gcm_note: Full Credit + # gcm_points: 0 + # - gcm_note: No documentation + # gcm_points: -5 + # - gcm_note: Very little documentation or documentation makes no sense + # gcm_points: -3 + # - gcm_note: Way too much documentation and/or documentation makes no sense + # gcm_points: -1 + # - gc_lower_clamp: 0 + # gc_default: 0 + # gc_max_value: 0 + # gc_upper_clamp: 5 + # gc_title: Extra Credit + # marks: + # - gcm_note: No Credit + # gcm_points: 0 + # - gcm_note: Extra credit done poorly + # gcm_points: 2 + # - gcm_note: Extra credit is acceptable + # gcm_points: 5 + # eg_submission_due_date: 1972-01-01 23:59:59 + # eg_submission_open_date: 1971-01-01 23:59:59 + # g_grade_due_date: 1974-01-01 23:59:59 + # g_grade_released_date: 1974-01-01 23:59:59 + # eg_grade_inquiry_start_date: 1974-01-02 23:59:59 + # eg_grade_inquiry_due_date: 1974-01-08 23:59:59 + # eg_has_due_date: true + # eg_has_release_date: true + # g_grade_start_date: 1973-01-01 23:59:59 + # g_ta_view_start_date: 1970-01-01 23:59:59 + # g_title: TA Only w/ Penalty (Upload Only) + # gradeable_config: upload_only + # g_bucket: homework + + # - gradeable_config: leaderboard + # components: + # - gc_lower_clamp: 0 + # gc_default: 11 + # gc_max_value: 11 + # gc_upper_clamp: 11 + # gc_title: Question 1 + # marks: + # - gcm_note: Full Credit + # gcm_points: 0 + # g_ta_view_start_date: 1970-01-01 23:59:59 + # eg_submission_open_date: 1971-01-01 23:59:59 + # eg_submission_due_date: 9996-12-31 23:59:59 + # g_grade_start_date: 9997-12-31 23:59:59 + # g_grade_due_date: 9998-12-31 23:59:59 + # g_grade_released_date: 9998-12-31 23:59:59 + # eg_grade_inquiry_start_date: 9999-01-01 23:59:59 + # eg_grade_inquiry_due_date: 9999-01-06 23:59:59 + # eg_has_due_date: true + # eg_has_release_date: true diff --git a/.setup/install_system.sh b/.setup/install_system.sh index 0238f2b998d..0eab50d4b92 100644 --- a/.setup/install_system.sh +++ b/.setup/install_system.sh @@ -708,6 +708,7 @@ en_US ${SUBMISSION_URL} +y sysadmin@example.com https://example.com 1 diff --git a/.setup/testing/setup.sh b/.setup/testing/setup.sh index 661b91259b6..12f17822876 100644 --- a/.setup/testing/setup.sh +++ b/.setup/testing/setup.sh @@ -58,6 +58,7 @@ en_US http://localhost +y sysadmin@example.com https://example.com 1 diff --git a/autograder/tests/data/submitty_config.json b/autograder/tests/data/submitty_config.json index a13c8a0111c..fe51a716b41 100644 --- a/autograder/tests/data/submitty_config.json +++ b/autograder/tests/data/submitty_config.json @@ -12,9 +12,30 @@ "cgi_url": "https://submitty.test.com/cgi-bin", "websocket_port": 8443, "institution_name": "Test University", + "user_create_account": false, "institution_homepage": "https://test.com", "timezone": "America/Los_Angeles", "duck_special_effects": false, - "worker": false + "worker": false, + "user_id_requirements": { + "all": true, + "require_name": false, + "length": 25, + "name_requirements": { + "given_first": false, + "given_name": 2, + "family_name": 4 + }, + "require_email": false, + "email_requirements": { + "whole_email": false, + "whole_prefix": false, + "prefix_count": 6 + } + }, + "accepted_emails": { + "gmail.com": true, + "rpi.edu": true + } } } \ No newline at end of file diff --git a/migration/migrator/data/submitty_db.sql b/migration/migrator/data/submitty_db.sql index 978f09ddf66..1a7d9e44a89 100644 --- a/migration/migrator/data/submitty_db.sql +++ b/migration/migrator/data/submitty_db.sql @@ -646,6 +646,21 @@ CREATE TABLE public.terms ( ); +-- +-- Name: unverified_users; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.unverified_users ( + user_id character varying NOT NULL, + user_givenname character varying NOT NULL, + user_password character varying, + user_familyname character varying NOT NULL, + user_email character varying NOT NULL, + verification_code character varying(50) DEFAULT 'none'::character varying NOT NULL, + verification_expiration timestamp without time zone DEFAULT CURRENT_TIMESTAMP +); + + -- -- Name: users; Type: TABLE; Schema: public; Owner: - -- diff --git a/migration/migrator/migrations/master/20240805165505_user_verification_code.py b/migration/migrator/migrations/master/20240805165505_user_verification_code.py new file mode 100644 index 00000000000..04179e5f7f2 --- /dev/null +++ b/migration/migrator/migrations/master/20240805165505_user_verification_code.py @@ -0,0 +1,35 @@ +"""Migration for the Submitty master database.""" + + +def up(config, database): + """ + Run up migration. + + :param config: Object holding configuration details about Submitty + :type config: migrator.config.Config + :param database: Object for interacting with given database for environment + :type database: migrator.db.Database + """ + + database.execute(''' + CREATE TABLE if not exists public.unverified_users ( + user_id character varying NOT NULL, + user_givenname character varying NOT NULL, + user_password character varying, + user_familyname character varying NOT NULL, + user_email character varying NOT NULL, + verification_code character varying(50) NOT NULL DEFAULT 'none', + verification_expiration timestamp DEFAULT current_timestamp + ) + ''') + +def down(config, database): + """ + Run down migration (rollback). + + :param config: Object holding configuration details about Submitty + :type config: migrator.config.Config + :param database: Object for interacting with given database for environment + :type database: migrator.db.Database + """ + pass diff --git a/migration/migrator/migrations/system/20240814131600_self_account_creation.py b/migration/migrator/migrations/system/20240814131600_self_account_creation.py new file mode 100644 index 00000000000..676e1e75a5f --- /dev/null +++ b/migration/migrator/migrations/system/20240814131600_self_account_creation.py @@ -0,0 +1,50 @@ +"""Migration for the Submitty system.""" +import json +user_id_requirements = { + "all": True, + "require_name": False, + "length": 25, + "name_requirements": { + "given_first": False, + "given_name": 2, + "family_name": 4 + }, + "require_email": False, + "email_requirements": { + "whole_email": False, + "whole_prefix": False, + "prefix_count": 6 + } +} + +accepted_emails = { + "gmail.com": True, + "rpi.edu": True +} + +def up(config): + """ + Run up migration. + + :param config: Object holding configuration details about Submitty + :type config: migrator.config.Config + """ + edited_config = config.submitty + if ('user_create_account' not in edited_config): + edited_config['user_create_account'] = False + if ('user_id_requirements' not in edited_config): + edited_config['user_id_requirements'] = user_id_requirements + if ('accepted_emails' not in edited_config): + edited_config['accepted_emails'] = accepted_emails + + with open(config.config_path / 'submitty.json', 'w') as file_path: + json.dump(edited_config, file_path, indent=4) + +def down(config): + """ + Run down migration (rollback). + + :param config: Object holding configuration details about Submitty + :type config: migrator.config.Config + """ + pass diff --git a/site/app/controllers/AuthenticationController.php b/site/app/controllers/AuthenticationController.php index e101f7112c6..4988373ff32 100644 --- a/site/app/controllers/AuthenticationController.php +++ b/site/app/controllers/AuthenticationController.php @@ -13,6 +13,8 @@ use app\libraries\Logger; use app\libraries\response\MultiResponse; use app\views\AuthenticationView; +use app\models\User; +use app\models\Email; use app\repositories\VcsAuthTokenRepository; use Symfony\Component\Routing\Annotation\Route; @@ -308,4 +310,287 @@ public function userSelection() { return new WebResponse(AuthenticationView::class, 'userSelection', $users); } + + // /** + // * Check if password has at least one of the following, Upper case letter, Lower case letter, Special character, and number + // */ + // public function checkChars(string $password): bool { + // $upperCase = preg_match('/[A-Z]/', $password); + // $lowerCase = preg_match('/[a-z]/', $password); + // $specialChar = preg_match('/[^A-Za-z0-9]/', $password); + // $numericVal = preg_match('/[0-9]/', $password); + // return $upperCase >= 1 && $lowerCase >= 1 && $specialChar >= 1 && $numericVal >= 1; + // } + + // /** + // * Check if the user ID meets requirements + // */ + // public function isAcceptedUserId(string $user_id, string $given_name, string $family_name, string $email): bool { + // $requirements = $this->core->getConfig()->getUserIdRequirements(); + + // // If length is -1, allow any length + // if ($requirements['length'] !== -1 && strlen($user_id) > $requirements['length']) { + // return false; + // } + + // if ($requirements['all'] === true) { + // return true; + // } + // elseif ($requirements['require_name'] === true) { + // $name_requirements = $requirements['name_requirements']; + // $given_first = $name_requirements['given_first'] === 'true'; + + // $id_given_name = substr($user_id, ($given_first ? 0 : $name_requirements['family_name']), ($given_first ? $name_requirements['given_name'] : strlen($user_id))); + // $id_family_name = substr($user_id, ($given_first ? $name_requirements['given_name'] : 0), ($given_first ? strlen($user_id) : $name_requirements['family_name'])); + // $is_given_name = (strtolower($id_given_name) === substr(strtolower($given_name), 0, $name_requirements['given_name'])); + // $is_family_name = (strtolower($id_family_name) === substr(strtolower($family_name), 0, $name_requirements['family_name'])); + // if ($is_family_name && $is_given_name) { + // return true; + // } + // return false; + // } + // elseif ($requirements['require_email'] === true) { + // if ($requirements['email_requirements']['whole_email']) { + // return $user_id === $email; + // } + // elseif ($requirements['email_requirements']['whole_prefix']) { + // $split_email = explode('@', $email); + // $email_extension = array_pop($split_email); + // return $user_id === implode('', $split_email); + // } + // else { + // return substr($user_id, 0, $requirements['email_requirements']['prefix_count']) === substr($email, 0, $requirements['email_requirements']['prefix_count']); + // } + // } + // else { + // return false; + // } + // } + + // /** + // * Returns true if the password is greater than or equal to 12 characters, and has the required characters + // */ + // public function isGoodPassword(string $password): bool { + // return strlen($password) >= 12 && $this->checkChars($password); + // } + + // /** + // * Checks if the email extension is in the accepted emails part of the Submitty config file + // */ + // public function isAcceptedEmail(string $email): bool { + // $emails = $this->core->getConfig()->getAcceptedEmails(); + // // Check if the file was read successfully + // try { + // $split_email = explode('@', $email); + // $email_extension = $split_email[count($split_email) - 1]; + // } + // catch (\Error $error) { + // return false; + // } + // return in_array($email_extension, array_keys($emails), true); + // } + + // /** + // * @return array + // */ + // public function generateVerificationCode(): array { + // $code = rand(1111111111, 9999999999); + // $timestamp = time() + 60 * 15; + // return ['code' => strval($code), 'exp' => $timestamp]; + // } + + // public function sendVerificationEmail(string $email, string $verification_code): void { + // $subject = "Submitty Email Verification"; + // $url = $this->core->getConfig()->getBaseUrl() . 'authentication/verify_email?verification_code=' . $verification_code; + // $body = << $subject, "body" => $body, "email_address" => $email, 'to_name' => 'test']; + // $email = new Email($this->core, $details); + // $emails = [$email]; + // $this->core->getNotificationFactory()->sendEmails($emails); + // } + + // /** + // * Display the form for creating a new account + // */ + // #[Route("/authentication/create_account", methods: ['GET'])] + // public function signupForm(): ResponseInterface { + // // Check if the user is already logged in, if yes, redirect to home or another appropriate page + // if ($this->logged_in) { + // return new RedirectResponse($this->core->buildUrl(['home'])); + // } + // if (!$this->core->getConfig()->isUserCreateAccount()) { + // $this->core->addErrorMessage('Users cannot create their own account, Please have your system administrator add you.'); + // return new RedirectResponse($this->core->buildUrl(['authentication', 'login'])); + // } + // return new WebResponse('Authentication', 'signupForm', ['email' => $this->core->getConfig()->getAcceptedEmails(), 'user_id' => $this->core->getConfig()->getUserIdRequirements()]); + // } + + // /** + // * Display the form for creating a new account + // */ + // #[Route("/authentication/email_verification")] + // public function showVerifyEmailForm(): ResponseInterface { + // // Check if the user is already logged in, if yes, redirect to home or another appropriate page + // // if ($this->logged_in) { + // // return new RedirectResponse($this->core->buildUrl(['home'])); + // // } + // if (!$this->core->getConfig()->isUserCreateAccount()) { + // $this->core->addErrorMessage('Users cannot create their own account, Please have your system administrator add you.'); + // return new RedirectResponse($this->core->buildUrl(['authentication', 'login'])); + // } + // return new WebResponse('Authentication', 'verificationForm'); + // } + + // /** + // * Display the form for creating a new account + // */ + // #[Route("/authentication/resend_email")] + // public function resendVerificationEmail(): ResponseInterface { + // // Check if the user is already logged in, if yes, redirect to home or another appropriate page + // if ($this->logged_in) { + // return new RedirectResponse($this->core->buildUrl(['home'])); + // } + // if (!$this->core->getConfig()->isUserCreateAccount()) { + // $this->core->addErrorMessage('Users cannot create their own account, Please have your system administrator add you.'); + // return new RedirectResponse($this->core->buildUrl(['authentication', 'login'])); + // } + // if (!isset($_GET['email'])) { + // $this->core->addErrorMessage('You must specify an email to send the verification to.'); + // return new RedirectResponse($this->core->buildUrl(['authentication', 'email_verification'])); + // } + // if (count($this->core->getQueries()->getUnverifiedUserIdEmailExists($_GET['email'], '')) > 0) { + // $this->core->addErrorMessage('That email is not associated with an account.'); + // return new RedirectResponse($this->core->buildUrl(['authentication', 'email_verification'])); + // } + // $verification_values = $this->generateVerificationCode(); + // $this->core->getQueries()->updateUserVerificationValues($_GET['email'], $verification_values['code'], $verification_values['exp']); + // $this->sendVerificationEmail($_GET['email'], $verification_values['code']); + // $this->core->addSuccessMessage('Verification email resent.'); + // return new RedirectResponse($this->core->buildUrl(['authentication', 'email_verification'])); + // } + + // #[Route("/authentication/verify_email")] + // public function verifyEmail(): RedirectResponse { + // // Check if the user is already logged in, if yes, redirect to home or another appropriate page + // if (!$this->core->getConfig()->isUserCreateAccount()) { + // $this->core->addErrorMessage('Users cannot create their own account, Please have your system administrator add you.'); + // return new RedirectResponse($this->core->buildUrl(['authentication', 'login'])); + // } + // $verification_values = $this->core->getQueries()->getUserVerificationValuesByCode($_GET['verification_code']); + // if ($verification_values === []) { + // $this->core->addErrorMessage('The verification code is not correct.'); + // return new RedirectResponse($this->core->buildUrl(['authentication', 'email_verification'])); + // } + // if (count($verification_values) < 2) { + // $this->core->addErrorMessage('That user_id was not associated with an account.'); + // return new RedirectResponse($this->core->buildUrl(['authentication', 'signup'])); + // } + // if ($verification_values['verification_expiration'] < time()) { + // $this->core->addErrorMessage('The verification code has expired, click resend email to receive a new code.'); + // return new RedirectResponse($this->core->buildUrl(['authentication', 'email_verification'])); + // } + // $this->core->addSuccessMessage('You have successfully verified your email.'); + // $user = $this->core->getQueries()->getUnverifiedUserByCode($_GET['verification_code']); + // $this->core->getQueries()->insertSubmittyUser($user); + // $this->core->getQueries()->removeUnverifiedUserByCode($_GET['verification_code']); + // return new RedirectResponse($this->core->buildUrl(['authentication', 'login'])); + // } + + // /** + // * Handles the submission of the new account creation form + // */ + // #[Route("/authentication/self_add_user")] + // public function addNewUser(): RedirectResponse { + // // Check if the user is already logged in, if yes, redirect to home or another appropriate page + // if ($this->logged_in) { + // return new RedirectResponse($this->core->buildUrl(['home'])); + // } + + // // Should never happen, however they can visit this URL manually, so this is to prevent unwanted account creation. + // if (!$this->core->getConfig()->isUserCreateAccount()) { + // $this->core->addErrorMessage('Users cannot create their own account, Please have your system administrator add you.'); + // return new RedirectResponse($this->core->buildUrl(['authentication', 'login'])); + // } + + // $user_id = $_POST['user_id']; + // $email = $_POST['email']; + // $password = $_POST['password']; + // $confirm_password = $_POST['confirm_password']; + + // $verified_users = $this->core->getQueries()->getUserIdEmailExists($email, $user_id); + // $unverified_users = $this->core->getQueries()->getUnverifiedUserIdEmailExists($email, $user_id); + + // if (in_array($email, array_column($unverified_users, 'user_email'), true)) { + // $this->core->addErrorMessage('Email already exists, please verify your email.'); + // return new RedirectResponse($this->core->buildUrl(['authentication', 'email_verification'])); + // } + + // if (in_array($email, array_column($verified_users, 'user_email'), true)) { + // $this->core->addErrorMessage('Email already exists'); + // return new RedirectResponse($this->core->buildUrl(['authentication', 'create_account'])); + // } + + // if (in_array($user_id, array_column($verified_users, 'user_id'), true)) { + // $this->core->addErrorMessage('User ID already exists'); + // return new RedirectResponse($this->core->buildUrl(['authentication', 'create_account'])); + // } + + // if (!$this->isGoodPassword($password)) { + // $this->core->addErrorMessage('Password does not meet the requirements.'); + // return new RedirectResponse($this->core->buildUrl(['authentication', 'create_account'])); + // } + + // if ($password !== $confirm_password) { + // $this->core->addErrorMessage('Passwords did not match.'); + // return new RedirectResponse($this->core->buildUrl(['authentication', 'create_account'])); + // } + + // if (!$this->isAcceptedEmail($email)) { + // $this->core->addErrorMessage('This email is not accepted.'); + // return new RedirectResponse($this->core->buildUrl(['authentication', 'create_account'])); + // } + + // if (!$this->isAcceptedUserId($user_id, $_POST['given_name'], $_POST['family_name'], $email)) { + // $this->core->addErrorMessage('This user id does not meet requirements.'); + // return new RedirectResponse($this->core->buildUrl(['authentication', 'create_account'])); + // } + // $verification_values = $this->generateVerificationCode(); + // $user = new User($this->core, [ + // 'user_id' => $user_id, + // 'user_givenname' => $_POST['given_name'], + // 'user_familyname' => $_POST['family_name'], + // 'user_password' => $password, + // 'user_pronouns' => '', + // 'display_pronouns' => false, + // 'user_email' => $email, + // 'user_email_secondary' => '', + // 'user_email_secondary_notify' => false, + // 'user_numeric_id' => time(), + // 'user_verification_code' => $verification_values['code'], + // 'user_verification_expiration' => $verification_values['exp'] + // ]); + + // try { + // $this->core->getQueries()->insertUnverifiedSubmittyUser($user); + // $this->sendVerificationEmail($email, $verification_values['code']); + // $this->core->addSuccessMessage('Verification Email Sent'); + // return new RedirectResponse($this->core->buildUrl(['authentication', 'email_verification'])); + // } + // catch (\Error $e) { + // $this->core->addErrorMessage('Failed to create the account.'); + // return new RedirectResponse($this->core->buildUrl(['authentication', 'create_account'])); + // } + // } } diff --git a/site/app/libraries/database/DatabaseQueries.php b/site/app/libraries/database/DatabaseQueries.php index 67ad19a7439..6832eb7c568 100644 --- a/site/app/libraries/database/DatabaseQueries.php +++ b/site/app/libraries/database/DatabaseQueries.php @@ -157,6 +157,24 @@ public function getUserById(string $user_id): ?User { return $this->getUser($user_id); } + /** + * Gets an unverified user from the database given a verification code. + * + * @return User|null + */ + public function getUnverifiedUserByCode(string $code): ?User { + $this->submitty_db->query("SELECT * FROM unverified_users WHERE verification_code=?", [$code]); + return new User($this->core, $this->submitty_db->row()); + } + + /** + * Removes an unverified user from the database given a verification code. + * + */ + public function removeUnverifiedUserByCode(string $code): void { + $this->submitty_db->query("DELETE FROM unverified_users WHERE verification_code=?", [$code]); + } + /** * Gets a user from the database given a numeric user_id. * @@ -535,7 +553,6 @@ public function insertSubmittyUser(User $user) { $user->getLegalFamilyName(), $user->getPreferredFamilyName(), $user->getEmail(), $this->submitty_db->convertBoolean($user->isUserUpdated()), $this->submitty_db->convertBoolean($user->isInstructorUpdated())]; - $this->submitty_db->query( "INSERT INTO users (user_id, user_password, user_numeric_id, user_givenname, user_preferred_givenname, user_familyname, user_preferred_familyname, user_email, user_updated, instructor_updated) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", @@ -543,6 +560,33 @@ public function insertSubmittyUser(User $user) { ); } + /** + * @param User $user + */ + public function insertUnverifiedSubmittyUser(User $user): void { + $array = [ + $user->getId(), + $user->getPassword(), + $user->getLegalGivenName(), + $user->getLegalFamilyName(), + $user->getEmail(), + $user->getVerificationExpiration(), + $user->getVerificationCode() + ]; + $this->submitty_db->query( + "INSERT INTO unverified_users ( + user_id, + user_password, + user_givenname, + user_familyname, + user_email, + verification_expiration, + verification_code + ) VALUES (?, ?, ?, ?, ?, to_timestamp(?), ?)", + $array + ); + } + /** * Helper function for generating sql query according to the given requirements */ @@ -7840,6 +7884,45 @@ public function getEmailListWithIds() { return $this->course_db->rows(); } + /** + * Gets a list of emails with user ids for all active particpants in Submitty + * array + * @return array + */ + public function getUserIdEmailExists(string $email, string $user_id): array { + $parameters = [$email, $user_id]; + $this->submitty_db->query('SELECT user_id, user_email FROM users where user_email=? or user_id=?', $parameters); + return $this->submitty_db->rows(); + } + + /** + * Gets a list of emails with user ids for all active particpants in Submitty + * @return array + */ + public function getUnverifiedUserIdEmailExists(string $email, string $user_id): array { + $parameters = [$email, $user_id]; + $this->submitty_db->query('SELECT user_id, user_email FROM unverified_users where user_email=? or user_id=?', $parameters); + return $this->submitty_db->rows(); + } + + /** + * Gets verification values given a verification code + * @return array + */ + public function getUserVerificationValuesByCode(string $code): array { + $parameters = [$code]; + $this->submitty_db->query('SELECT verification_code, verification_expiration FROM unverified_users where verification_code=?', $parameters); + return $this->submitty_db->row(); + } + + /** + * Updates a users verification values given an email + */ + public function updateUserVerificationValues(string $email, string $code, int $timestamp): void { + $parameters = [$code, $timestamp, $email]; + $this->submitty_db->query('UPDATE unverified_users SET verification_code=?, verification_expiration=to_timestamp(?) where user_email=?', $parameters); + } + /** * Gives true if thread is locked */ diff --git a/site/app/models/Config.php b/site/app/models/Config.php index 43bee9bf307..b4eb972a39f 100644 --- a/site/app/models/Config.php +++ b/site/app/models/Config.php @@ -55,6 +55,7 @@ * @method string getSysAdminEmail() * @method string getSysAdminUrl() * @method string getCourseEmail() + * @method bool isUserCreateAccount() * @method string getVcsUser() * @method string getVcsType() * @method string getPrivateRepository() @@ -62,6 +63,8 @@ * @method void setRoomSeatingGradeableId(string $gradeable_id) * @method bool isSeatingOnlyForInstructor() * @method array getCourseJson() + * @method array getAcceptedEmails() + * @method array getUserIdRequirements() * @method string getSecretSession() * @method string getAutoRainbowGrades() * @method string|null getVerifiedSubmittyAdminUser() @@ -109,6 +112,14 @@ class Config extends AbstractModel { * @var array */ protected $course_json = []; + /** @prop + * @var array */ + protected $user_id_requirements = []; + + /** @prop + * @var array */ + protected $accepted_emails = []; + /** * Indicates whether a course config has been successfully loaded. * @var bool @@ -292,6 +303,9 @@ class Config extends AbstractModel { /** @prop * @var bool */ protected $seating_only_for_instructor; + /** @prop + * @var bool */ + protected $user_create_account; /** @prop * @var string|null */ protected $room_seating_gradeable_id; @@ -421,6 +435,10 @@ public function loadMasterConfigs($config_path) { $this->sys_admin_email = $submitty_json['sys_admin_email'] ?? ''; $this->sys_admin_url = $submitty_json['sys_admin_url'] ?? ''; + $this->user_create_account = $submitty_json['user_create_account'] === true; + $this->user_id_requirements = $submitty_json['user_id_requirements']; + $this->accepted_emails = $submitty_json['accepted_emails']; + if (isset($submitty_json['timezone'])) { if (!in_array($submitty_json['timezone'], \DateTimeZone::listIdentifiers())) { throw new ConfigException("Invalid Timezone identifier: {$submitty_json['timezone']}"); diff --git a/site/app/models/User.php b/site/app/models/User.php index a6050a7630d..90d286ed19a 100644 --- a/site/app/models/User.php +++ b/site/app/models/User.php @@ -31,6 +31,8 @@ * @method int getLastInitialFormat() * @method string getDisplayNameOrder() * @method void setDisplayNameOrder() + * @method string getVerificationCode() + * @method int getVerificationExpiration() * @method string getEmail() * @method void setEmail(string $email) * @method string getSecondaryEmail() @@ -139,6 +141,12 @@ class User extends AbstractModel { /** @prop * @var string The secondary email of the user */ protected $secondary_email; + /** @prop + * @var string Email verification code */ + protected $verification_code; + /** @prop + * @var int Timestamp of the expiration of the verification code */ + protected $verification_expiration; /** @prop * @var string Determines whether or not user chose to receive emails to secondary email */ protected $email_both; @@ -290,6 +298,11 @@ public function __construct(Core $core, $details = []) { $this->time_zone = $details['time_zone'] ?? 'NOT_SET/NOT_SET'; + if (isset($details['user_verification_code'])) { + $this->core->getQueries()->updateUserVerificationValues($details['user_email'], $details['user_verification_code'], $details['user_verification_expiration']); + $this->verification_expiration = $details['user_verification_expiration']; + $this->verification_code = $details['user_verification_code']; + } if (isset($details['user_preferred_locale'])) { $this->preferred_locale = $details['user_preferred_locale']; $this->core->getConfig()->setLocale($this->preferred_locale); diff --git a/site/app/templates/Authentication.twig b/site/app/templates/Authentication.twig index bf8c2cd6b90..d3c5fb5953c 100644 --- a/site/app/templates/Authentication.twig +++ b/site/app/templates/Authentication.twig @@ -24,6 +24,9 @@ + {% if user_create_account and is_database_auth %} + {{ new_account_text }} + {% endif %} {% endif %} diff --git a/site/app/templates/CreateNewAccount.twig b/site/app/templates/CreateNewAccount.twig new file mode 100644 index 00000000000..c1f36995d22 --- /dev/null +++ b/site/app/templates/CreateNewAccount.twig @@ -0,0 +1,77 @@ +
+
+ +

Sign Up + +

+
+ +
+

Email

+
+ Accepted Email Extensions:
+ {% for email, bool in requirements['email'] %} + @{{ email }}
+ {% endfor %} +
+ +
+
+

User ID

+
+ UserID Requirements:
+ {% if requirements['user_id']['all'] == true %} + All user ids of {{ requirements['user_id']['length'] == -1 ? 'any length' : "length: requirements['user_id']['length']" }} are accepted + {% elseif requirements['user_id']['require_name'] == true %} + Must start with {{ requirements['user_id']['name_requirements']['givenname_first'] ? (requirements['user_id']['name_requirements']['given_name'] + 'characters of your given name') : (requirements['user_id']['name_requirements']['family_name'] + 'characters of your family name')}} + {% elseif requirements['user_id']['require_email'] == true %} + + {% endif %} +
+ +
+
+ Given Name + +
+ +
+

Password

+
+ Password Requires at least:
+ 1 Capital Letter
+ 1 Lowercase Letter
+ 1 Number
+ 1 Special Character
+ 12 Characters
+
+ +
+ + +
+
+ + + + diff --git a/site/app/templates/VerifyEmailForm.twig b/site/app/templates/VerifyEmailForm.twig new file mode 100644 index 00000000000..7170e707eab --- /dev/null +++ b/site/app/templates/VerifyEmailForm.twig @@ -0,0 +1,24 @@ +
+
+ +

Verify your Email + +

+
+ + +
+ Enter Verification Code + + +
+
+
+ Resend Verification Code + + +
+ + +
+ diff --git a/site/app/views/AuthenticationView.php b/site/app/views/AuthenticationView.php index 881cdd16eb2..557d299208c 100644 --- a/site/app/views/AuthenticationView.php +++ b/site/app/views/AuthenticationView.php @@ -2,6 +2,7 @@ namespace app\views; +use app\authentication\DatabaseAuthentication; use app\libraries\Access; use app\libraries\FileUtils; @@ -21,12 +22,22 @@ public function loginForm($old = null, $isSaml = false) { $login_content = file_get_contents($path); } + $new_account_text = "New to Submitty? Sign up here."; + $path = FileUtils::joinPaths($this->core->getConfig()->getConfigPath(), "new_account.md"); + if (file_exists($path) && is_readable($path)) { + $new_account_text = file_get_contents($path); + } + return $this->core->getOutput()->renderTwigTemplate("Authentication.twig", [ "login_url" => $this->core->buildUrl(['authentication', 'check_login']) . '?' . http_build_query(['old' => $old]), "is_saml" => $isSaml, "saml_url" => $this->core->buildUrl(['authentication', 'saml_start']) . '?' . http_build_query(['old' => $old]), "saml_name" => $this->core->getConfig()->getSamlOptions()['name'], - "login_content" => $login_content + "login_content" => $login_content, + "user_create_account" => $this->core->getConfig()->isUserCreateAccount(), + "is_database_auth" => $this->core->getAuthentication() instanceof DatabaseAuthentication, + "new_account_url" => $this->core->buildUrl(['authentication', 'create_account']), + "new_account_text" => "New to Submitty? Sign up now!" ]); } @@ -38,4 +49,36 @@ public function userSelection(array $users) { "login_url" => $this->core->buildUrl(['authentication', 'check_login']) ]); } + + /** + * @param array $content + */ + public function signupForm(array $content): string { + $this->core->getOutput()->addInternalCss("input.css"); + $this->core->getOutput()->addInternalCss("links.css"); + $this->core->getOutput()->addInternalCss("authentication.css"); + $this->core->getOutput()->enableMobileViewport(); + + $signup_content = "# Sign Up"; + $path = FileUtils::joinPaths($this->core->getConfig()->getConfigPath(), "signup.md"); + if (file_exists($path) && is_readable($path)) { + $signup_content = file_get_contents($path); + } + return $this->core->getOutput()->renderTwigTemplate("CreateNewAccount.twig", [ + "signup_url" => $this->core->buildUrl(['authentication', 'self_add_user']), + "signup_content" => $signup_content, + "requirements" => $content + ]); + } + + public function verificationForm(): string { + $this->core->getOutput()->addInternalCss("input.css"); + $this->core->getOutput()->addInternalCss("links.css"); + $this->core->getOutput()->addInternalCss("authentication.css"); + $this->core->getOutput()->enableMobileViewport(); + return $this->core->getOutput()->renderTwigTemplate("VerifyEmailForm.twig", [ + 'verify_email_url' => $this->core->buildUrl(['authentication', 'verify_email']), + 'resend_email_url' => $this->core->buildUrl(['authentication', 'resend_email']), + ]); + } } diff --git a/site/public/css/authentication.css b/site/public/css/authentication.css index 69762b92e51..d66486c36c3 100644 --- a/site/public/css/authentication.css +++ b/site/public/css/authentication.css @@ -50,3 +50,45 @@ #saml-login { color: var(--btn-text-white); } + +.hidden-helper { + display: none; + padding: 10px; + font-size: small; +} + +.display-box input { + display: block; + width: 100%; +} + +.requirements-button { + display: inline-block; + font-weight: 400; + color: #212529; + text-align: center; + vertical-align: middle; + background-color: transparent; + border: 1px solid; + padding: 0.3rem; + font-size: x-small; + line-height: 1; + border-radius: 0.25rem; + transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; +} + + +@media (prefers-color-scheme: dark) { + .hidden-helper { + display: none; + position: absolute; + background-color: gray; + left: 42%; + height: 150px; + width: 225px; + padding-left: 10px; + padding-top: 10px; + border-radius: 20px; + } +} + diff --git a/site/tests/app/controllers/admin/ConfigurationControllerTester.php b/site/tests/app/controllers/admin/ConfigurationControllerTester.php index c7d63a2e878..c6d270549cd 100644 --- a/site/tests/app/controllers/admin/ConfigurationControllerTester.php +++ b/site/tests/app/controllers/admin/ConfigurationControllerTester.php @@ -32,7 +32,7 @@ public function setUpConfig($seating_dirs = []): void { 'email' => '{"email_enabled":true,"email_user":"","email_password":"","email_sender":"submitty@vagrant","email_reply_to":"do-not-reply@vagrant","email_server_hostname":"localhost","email_server_port":25}', 'secrets_submitty_php' => '{"session":"cGRZSDnVxdDjQwGyiq4ECnJyiZ8IQXEL1guSsJ1XlSKSEqisqvdCPhCRcYDEjpjm"}', 'submitty_admin' => '{"submitty_admin_username":"submitty-admin","token":"token"}', - 'submitty' => '{"submitty_install_dir":' . json_encode($this->test_dir) . ',"submitty_repository":' . json_encode($this->test_dir) . ',"submitty_data_dir":' . json_encode($this->test_dir) . ',"autograding_log_path":' . json_encode($this->test_dir) . ',"site_log_path":' . json_encode($this->test_dir) . ',"submission_url":"http:\/\/localhost:1501","vcs_url":"","cgi_url":"http:\/\/localhost:1501\/cgi-bin","institution_name":"","username_change_text":"foo","institution_homepage":"" ,"sys_admin_email": "admin@example.com","sys_admin_url": "https:\/\/example.com\/admin","timezone":"America\/New_York","worker":false,"duck_special_effects" : false}', + 'submitty' => '{"submitty_install_dir":' . json_encode($this->test_dir) . ',"submitty_repository":' . json_encode($this->test_dir) . ',"submitty_data_dir":' . json_encode($this->test_dir) . ',"autograding_log_path":' . json_encode($this->test_dir) . ',"site_log_path":' . json_encode($this->test_dir) . ',"submission_url":"http:\/\/localhost:1501","vcs_url":"","cgi_url":"http:\/\/localhost:1501\/cgi-bin","institution_name":"","username_change_text":"foo","institution_homepage":"" ,"sys_admin_email": "admin@example.com","sys_admin_url": "https:\/\/example.com\/admin","timezone":"America\/New_York","worker":false,"duck_special_effects":false,"user_create_account":false,"user_id_requirements":{"all":true,"require_name":false,"length":25,"name_requirements":{"given_first":false,"given_name": 2,"family_name": 4},"require_email": false,"email_requirements": {"whole_email": false,"whole_prefix": false,"prefix_count": 6}},"accepted_emails":{"gmail.com": true,"rpi.edu": true}}', 'submitty_users' => '{"num_grading_scheduler_workers":5,"num_untrusted":60,"first_untrusted_uid":900,"first_untrusted_gid":900,"daemon_uid":1003,"daemon_gid":1006,"daemon_user":"submitty_daemon","course_builders_group":"submitty_course_builders","php_uid":1001,"php_gid":1004,"php_user":"submitty_php","cgi_user":"submitty_cgi","daemonphp_group":"submitty_daemonphp","daemoncgi_group":"submitty_daemoncgi","verified_submitty_admin_user":"submitty-admin"}', 'version' => '{"installed_commit":"7da8417edd6ff46f1d56e1a938b37c054a7dd071","short_installed_commit":"7da8417ed","most_recent_git_tag":"v19.09.04"}' ]; diff --git a/site/tests/app/models/ConfigTester.php b/site/tests/app/models/ConfigTester.php index 69d5103612b..2f885f2d311 100644 --- a/site/tests/app/models/ConfigTester.php +++ b/site/tests/app/models/ConfigTester.php @@ -94,8 +94,29 @@ private function createConfigFile($extra = []) { "course_code_requirements" => "Please follow your school's convention for course code.", "institution_homepage" => "https://rpi.edu", 'system_message' => "Some system message", + 'user_create_account' => false, "duck_special_effects" => false, "default_locale" => "default", + "user_id_requirements" => [ + "all" => true, + "require_name" => false, + "length" => 25, + "name_requirements" => [ + "given_first" => false, + "given_name" => 2, + "family_name" => 4 + ], + "require_email" => false, + "email_requirements" => [ + "whole_email" => false, + "whole_prefix" => false, + "prefix_count" => 6 + ] + ], + "accepted_emails" => [ + "gmail.com" => true, + "rpi.edu" => true + ] ]; $config = array_replace($config, $extra); FileUtils::writeJsonFile(FileUtils::joinPaths($this->config_path, "submitty.json"), $config); @@ -330,6 +351,27 @@ public function testConfig() { 'vcs_url' => 'http://example.com/{$vcs_type}/', 'wrapper_files' => [], 'system_message' => 'Some system message', + 'user_create_account' => false, + "user_id_requirements" => [ + "all" => true, + "require_name" => false, + "length" => 25, + "name_requirements" => [ + "given_first" => false, + "given_name" => 2, + "family_name" => 4 + ], + "require_email" => false, + "email_requirements" => [ + "whole_email" => false, + "whole_prefix" => false, + "prefix_count" => 6 + ] + ], + "accepted_emails" => [ + "gmail.com" => true, + "rpi.edu" => true + ], 'secret_session' => 'LIW0RT5XAxOn2xjVY6rrLTcb6iacl4IDNRyPw58M0Kn0haQbHtNvPfK18xpvpD93', 'email_enabled' => true, 'auto_rainbow_grades' => false, diff --git a/site/tests/app/models/UserTester.php b/site/tests/app/models/UserTester.php index 4b79476c5f8..d8b45d3d254 100644 --- a/site/tests/app/models/UserTester.php +++ b/site/tests/app/models/UserTester.php @@ -195,7 +195,9 @@ public function testToObject() { 'self_notification_email' => false ], 'registration_subsection' => '', - 'enforce_single_session' => false + 'enforce_single_session' => false, + 'verification_code' => null, + 'verification_expiration' => null ]; $this->assertEquals($expected, $actual); } diff --git a/tests/git_test.sh b/tests/git_test.sh index 4b7b348c7cf..2e82b602bc8 100644 --- a/tests/git_test.sh +++ b/tests/git_test.sh @@ -38,10 +38,11 @@ set -ev mkdir /tmp/submitty_git pushd /tmp/submitty_git +ls -alF test_git instructor instructor test_git instructor student test_git student student - + EXIT_CODE=0 git clone http://student:student@localhost/git/${SEMESTER}/sample/open_homework/instructor > /tmp/submitty_git/git_stdout 2> /tmp/submitty_git/git_stderr || EXIT_CODE=$? test ${EXIT_CODE} -ne 0