Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: Cal-CS-61A-Staff/seating
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: master
Choose a base ref
...
head repository: berkeley-cdss/seating
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: main
Choose a head ref
Can’t automatically merge. Don’t worry, you can still create the pull request.
Loading
Showing with 6,457 additions and 1,346 deletions.
  1. +54 −0 .env.sample
  2. +5 −0 .flake8
  3. +24 −0 .github/actions/bootstrap/action.yml
  4. +31 −0 .github/workflows/a11y.yml
  5. +56 −0 .github/workflows/audit.yml
  6. +81 −0 .github/workflows/codeql.yml
  7. +26 −0 .github/workflows/lint.yml
  8. +62 −0 .github/workflows/test.yml
  9. +17 −1 .gitignore
  10. +14 −0 .vscode/settings.json
  11. +1 −1 Procfile
  12. +18 −207 README.md
  13. +10 −0 cli/__init__.py
  14. +46 −0 cli/db.py
  15. +52 −0 cli/qa.py
  16. +2 −0 codecov.yml
  17. +88 −29 config.py
  18. +0 −180 download_bcourses_photos.py
  19. +10 −0 requirements-dev.txt
  20. +18 −12 requirements.txt
  21. +1 −2 runtime.txt
  22. +83 −7 server/__init__.py
  23. +0 −98 server/auth.py
  24. +15 −0 server/cache.py
  25. +123 −0 server/controllers/__init__.py
  26. +55 −0 server/controllers/auth_controllers.py
  27. +56 −0 server/controllers/dev_login_controllers.py
  28. +27 −0 server/controllers/health_controllers.py
  29. +202 −0 server/forms.py
  30. +167 −75 server/models.py
  31. +63 −0 server/services/auth/__init__.py
  32. +7 −0 server/services/auth/scope.py
  33. +43 −0 server/services/c1c/__init__.py
  34. +17 −0 server/services/c1c/fake_data/__init__.py
  35. +6 −0 server/services/c1c/fake_data/photos.json
  36. BIN server/services/c1c/fake_data/photos/sample1.jpg
  37. +133 −0 server/services/canvas/__init__.py
  38. +56 −0 server/services/canvas/fake_canvas.py
  39. +15 −0 server/services/canvas/fake_data/__init__.py
  40. +30 −0 server/services/canvas/fake_data/fake_courses.json
  41. +93 −0 server/services/canvas/fake_data/fake_enrollments.json
  42. +42 −0 server/services/canvas/fake_data/fake_users.json
  43. 0 server/services/core/__init__.py
  44. +120 −0 server/services/core/assign.py
  45. +86 −0 server/services/core/data.py
  46. +44 −0 server/services/core/export.py
  47. +89 −0 server/services/core/room.py
  48. +170 −0 server/services/core/student.py
  49. +41 −0 server/services/csv/__init__.py
  50. +70 −0 server/services/email/__init__.py
  51. +121 −0 server/services/email/smtp.py
  52. +47 −0 server/services/email/templates/__init__.py
  53. +31 −0 server/services/email/templates/assignment_inform_email.html
  54. +5 −0 server/services/email/templates/assignment_inform_email.json
  55. +77 −0 server/services/google/__init__.py
  56. +46 −0 server/static/css/flash.css
  57. +16 −9 server/static/css/style.css
  58. +5 −0 server/static/js/utils.js
  59. +2 −0 server/templates/assign.html.j2
  60. +40 −0 server/templates/assign_single.html.j2
  61. +94 −23 server/templates/base.html.j2
  62. +3 −1 server/templates/delete_students.html.j2
  63. +19 −0 server/templates/dev_login.html.j2
  64. +95 −0 server/templates/edit_students.html.j2
  65. +54 −24 server/templates/email.html.j2
  66. +20 −4 server/templates/exam.html.j2
  67. +0 −73 server/templates/help.html.j2
  68. +24 −0 server/templates/index.html.j2
  69. +154 −41 server/templates/macros.html.j2
  70. +18 −0 server/templates/new_offerings.html.j2
  71. +0 −10 server/templates/new_photos.html.j2
  72. +77 −36 server/templates/new_room.html.j2
  73. +84 −52 server/templates/new_students.html.j2
  74. +1 −1 server/templates/room.html.j2
  75. +3 −3 server/templates/seat.html.j2
  76. +86 −0 server/templates/select_exam.html.j2
  77. +87 −0 server/templates/select_offering.html.j2
  78. +7 −6 server/templates/student.html.j2
  79. +94 −19 server/templates/students.html.j2
  80. +43 −0 server/templates/upsert_exam.html.j2
  81. +103 −0 server/templates/upsert_room.html.j2
  82. 0 server/typings/__init__.py
  83. +39 −0 server/typings/enum.py
  84. +68 −0 server/typings/exception.py
  85. 0 server/utils/__init__.py
  86. +30 −0 server/utils/date.py
  87. +23 −0 server/utils/misc.py
  88. +937 −432 server/views.py
  89. +10 −0 tests/.coveragerc
  90. 0 tests/__init__.py
  91. 0 tests/a11y/__init__.py
  92. +12 −0 tests/a11y/axe.min.js
  93. +7 −0 tests/a11y/axe_config.js
  94. +34 −0 tests/a11y/test_a11y_student.py
  95. +51 −0 tests/a11y/utils.py
  96. +107 −0 tests/conftest.py
  97. 0 tests/e2e/__init__.py
  98. +24 −0 tests/e2e/test_student.py
  99. +15 −0 tests/e2e/test_ta.py
  100. +29 −0 tests/e2e/test_web.py
  101. +20 −0 tests/fixtures/__init__.py
  102. +14 −0 tests/fixtures/exam.json
  103. +35 −0 tests/fixtures/offering.json
  104. +15 −0 tests/fixtures/room.json
  105. +65 −0 tests/fixtures/seat.json
  106. +12 −0 tests/fixtures/seat_assignment.json
  107. +43 −0 tests/fixtures/student.json
  108. +28 −0 tests/fixtures/user.json
  109. 0 tests/unit/__init__.py
  110. +227 −0 tests/unit/test_email.py
  111. +16 −0 tests/unit/test_health.py
  112. +86 −0 tests/unit/test_hello.py
  113. +585 −0 tests/unit/test_student_prepare.py
54 changes: 54 additions & 0 deletions .env.sample
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# env var required by flask framework. Value must be server
FLASK_APP=server
# env flag. available values: development, production, testing
FLASK_ENV=development
# where the server is hosted. Put base url here
SERVER_BASE_URL=http://localhost:5000/
# where the app wiki is hosted. Put base url here
WIKI_BASE_URL=https://github.com/berkeley-cdss/seating/wiki/
# database url. In dev mode this is ignored and sqlite is used
DATABASE_URL=
# secret key for flask app. In dev mode this is ignored and a default value is used
# must generate a random flask secret key for production!
SECRET_KEY=
# server timezone; not used yet
LOCAL_TIMEZONE=US/Pacific

# whether to use mock canvas api
MOCK_CANVAS=false
# canvas server url, client id and secret, get them from school LTI team
CANVAS_SERVER_URL=
CANVAS_CLIENT_ID=
CANVAS_CLIENT_SECRET=

# gcp service account credentials
# available vaGCP_SA_CRED_TYPE values: env, file
# if GCP_SA_CRED_TYPE is env, put the encoded cred value in GCP_SA_CRED_VALUE
# if GCP_SA_CRED_TYPE is file, put the cred file full path in GCP_SA_CRED_FILE
GCP_SA_CRED_TYPE=file
GCP_SA_CRED_FILE=gcp-service-account-credentials.json
GCP_SA_CRED_VALUE=""

# url for the master room sheet
# this pre-filled value should be the latest version of the sheet
MASTER_ROOM_SHEET_URL="https://docs.google.com/spreadsheets/d/16a1uZJl54A5_J2XpyzIBblH7LPlFCKc5Cx86CFTbZTA/edit?usp=sharing"

# smtp server configs, for sending emails
EMAIL_SERVER=
EMAIL_PORT=
EMAIL_USE_TLS=
EMAIL_USERNAME=

# Cal1Card API URL
MOCK_C1C=false
C1C_API_DOMAIN=
C1C_API_USERNAME=
C1C_API_PASSWORD=
# if using a proxy to access c1c, set the proxy URL here
C1C_PROXY_URL=
# in seconds, how long to cache c1c photos
C1C_PHOTO_CACHE_LIFE=7776000

# codecov token
# not needed if not using codecov
CODECOV_TOKEN=
5 changes: 5 additions & 0 deletions .flake8
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[flake8]
max-line-length = 127
exclude = .git,__pycache__,venv,build,dist,docs
ignore = E722, F401
max-complexity = 10
24 changes: 24 additions & 0 deletions .github/actions/bootstrap/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
name: "bootstrap"
description: "Sets up Python, exports all GitHub environments and installs dependencies"
inputs:
dev-dep:
description: "Whether to install development dependencies"
required: false
default: "true"
python-version:
description: "Python version to use"
required: false
default: "3.10"
runs:
using: "composite"
steps:
- name: Set up Python ${{ inputs.python-version }}
uses: actions/setup-python@v3
with:
python-version: ${{ inputs.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
if [ "${{ inputs.dev-dep }}" = "true" ]; then pip install -r requirements-dev.txt; fi
shell: bash
31 changes: 31 additions & 0 deletions .github/workflows/a11y.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
name: A11y

on:
push:
branches: ["main"]
pull_request:
branches: ["main"]

permissions:
contents: read
pull-requests: write
issues: write

jobs:
audit-a11y-with-axe:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Bootstrap
uses: ./.github/actions/bootstrap
- name: Exports all GitHub Environment Secrets
uses: oNaiPs/secrets-to-env-action@v1
with:
secrets: ${{ toJSON(secrets) }}
- name: Exports all GitHub Environment Variables
uses: oNaiPs/secrets-to-env-action@v1
with:
secrets: ${{ toJSON(vars) }}
- name: Run A11y Audit
run: |
pytest -s tests/a11y
56 changes: 56 additions & 0 deletions .github/workflows/audit.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
name: Audit

on:
push:
branches: ["main"]
pull_request:
branches: ["main"]

permissions:
contents: read

jobs:
check-broken-dependencies:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Bootstrap
uses: ./.github/actions/bootstrap
- name: Audit with pip
# returns 1 if there are broken dependencies, 0 otherwise
# so, CI will fail if there are broken dependencies
run: |
pip check
check-package-updates:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Bootstrap
uses: ./.github/actions/bootstrap
- name: Audit with pip
# only informational, does not fail CI
run: |
pip list --outdated
audit-with-safety:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Bootstrap
uses: ./.github/actions/bootstrap
- name: Audit with safety
# returns 255 if there are vulnerabilities, 0 otherwise
# we use `|| true` to make sure CI does not fail whatsoever
run: |
safety check || true
continue-on-error: true
audit-with-pip-audit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Bootstrap
uses: ./.github/actions/bootstrap
# returns 1 if there are vulnerabilities, 0 otherwise
# we use `|| true` to make sure CI does not fail whatsoever
- name: Audit with pip-audit
run: |
pip-audit || true
81 changes: 81 additions & 0 deletions .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL"

on:
push:
branches: ["main"]
pull_request:
# The branches below must be a subset of the branches above
branches: ["main"]
schedule:
- cron: "45 22 * * 5"

jobs:
analyze:
name: Analyze
# Runner size impacts CodeQL analysis time. To learn more, please see:
# - https://gh.io/recommended-hardware-resources-for-running-codeql
# - https://gh.io/supported-runners-and-hardware-resources
# - https://gh.io/using-larger-runners
# Consider using larger runners for possible analysis time improvements.
runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }}
timeout-minutes: ${{ (matrix.language == 'swift' && 120) || 360 }}
permissions:
actions: read
contents: read
security-events: write

strategy:
fail-fast: false
matrix:
language: ["python"]
# CodeQL supports [ 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'swift' ]
# Use only 'java-kotlin' to analyze code written in Java, Kotlin or both
# Use only 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both
# Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support

steps:
- name: Checkout repository
uses: actions/checkout@v3

# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.

# For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
# queries: security-extended,security-and-quality

# Autobuild attempts to build any compiled languages (C/C++, C#, Go, Java, or Swift).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v2

# ℹ️ Command-line programs to run using the OS shell.
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun

# If the Autobuild fails above, remove it and uncomment the following three lines.
# modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.

# - run: |
# echo "Run, Build Application using script"
# ./location_of_script_within_repo/buildscript.sh

- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
with:
category: "/language:${{matrix.language}}"
26 changes: 26 additions & 0 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
name: Lint

on:
push:
branches: ["main"]
pull_request:
branches: ["main"]

permissions:
contents: read

jobs:
lint-with-flake8:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Bootstrap
uses: ./.github/actions/bootstrap
- name: Lint with flake8
run: |
# specifically checks for syntax errors or undefined names
# only proceed further to check styles if there are no syntax errors
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
# --exit-zero to treats all errors as warnings.
# this can pick up .flake8 config
flake8 . --exit-zero --count --statistics
62 changes: 62 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
name: Test

on:
push:
branches: ["main"]
pull_request:
branches: ["main"]

permissions:
contents: read
pull-requests: write
issues: write

jobs:
unit-test-with-pytest:
strategy:
matrix:
test-type: ["unit", "e2e"]
python-version: ["3.10", "3.11", "3.12"]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Bootstrap
uses: ./.github/actions/bootstrap
with:
python-version: ${{ matrix.python-version }}
# values set in GitHub repo vars/secrets are available as env vars in os
# but flask app expects them from os (flask uses os.getenv to fetech them)
# so we need to export them to os
- name: Exports all GitHub Environment Secrets
uses: oNaiPs/secrets-to-env-action@v1
with:
secrets: ${{ toJSON(secrets) }}
- name: Exports all GitHub Environment Variables
uses: oNaiPs/secrets-to-env-action@v1
with:
secrets: ${{ toJSON(vars) }}
- name: Prepare reports directory
run: |
mkdir -p reports
touch reports/pytest-${{ matrix.test-type }}.txt
touch reports/pytest-coverage-${{ matrix.test-type }}.txt
- name: Run tests with pytest and generate reports
run: |
# make sure pipe propogates exit code to fail CI on test failure
set -o pipefail
pytest --junitxml=reports/pytest-${{ matrix.test-type }}.xml --cov-report=term-missing:skip-covered --cov=server tests/${{ matrix.test-type }}/ | tee reports/pytest-coverage-${{ matrix.test-type }}.txt
set +o pipefail
- name: Pytest coverage comment
uses: MishaKav/pytest-coverage-comment@main
# no need to comment on merging to main; only need for pr
# it will fail anyway because of branch protection rejects commit comments
if: github.event_name == 'pull_request'
with:
title: Coverage for ${{ matrix.test-type }} tests for Python ${{ matrix.python-version }}
create-new-comment: true
pytest-coverage-path: reports/pytest-coverage-${{ matrix.test-type }}.txt
junitxml-path: reports/pytest-${{ matrix.test-type }}.xml
- name: Upload coverage reports to Codecov
uses: codecov/codecov-action@v3
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
18 changes: 17 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Database
app.db
*.db

# Secrets
secrets.sh
@@ -52,6 +52,7 @@ nosetests.xml
coverage.xml
*,cover
.hypothesis/
.pytest_cache/

# Translations
*.mo
@@ -99,3 +100,18 @@ ENV/

# configs
config.py

# coverage report
reports/

# a11y report
axe/

# gcp credentials
gcp-service-account-credentials.json

# bootstrap
setup*.sh

# cache
.cache/
14 changes: 14 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"[python]": {
"editor.defaultFormatter": "ms-python.autopep8",
"editor.insertSpaces": true,
"editor.formatOnSave": true,
"editor.tabSize": 4
},
"autopep8.args": ["--max-line-length=127"],
"python.analysis.autoImportCompletions": true,
// "python.analysis.typeCheckingMode": "basic",
"python.analysis.inlayHints.variableTypes": true,
"python.analysis.inlayHints.functionReturnTypes": true,
"python.analysis.inlayHints.pytestParameters": true
}
Loading