GradeView is a multi-component grade management system consisting of:
- Frontend: React Web UI
- Backend API: Node.js (data queries, authentication)
- Grade Sync: FastAPI GradeSync (pulls grades from external systems)
- Data Processing: Python scheduled tasks (dbcron)
- Report Generation: Python Progress Report service
- Infrastructure: Redis, PostgreSQL, Nginx reverse proxy
Main responsibilities: user authentication, grade data queries, student information management
api/
├── server.js # Main server entry point
├── Router.js # Route definitions (versioned routes)
├── config/
│ └── default.json # API config (Redis, Sheets, OAuth, admin list)
├── lib/
│ ├── authlib.mjs # Auth middleware (Admin/Student validation)
│ ├── googleAuthHelper.mjs # Google OAuth token verification
│ ├── userlib.mjs # User permission checks
│ ├── dbHelper.mjs # Database connection and queries
│ ├── redisHelper.mjs # Redis cache operations (student data)
│ ├── studentHelper.mjs # Student query logic
│ ├── uploadHandler.mjs # File upload handling
│ └── errors/ # Custom error classes
├── v2/
│ └── index.js # v2 route implementation
└── uploads/ # Upload file storage
Key workflow:
- User login → obtains Google OAuth token
- API validates token (checks
@berkeley.edudomain) - Queries
config.get('admins')to determine admin status - Returns appropriate data based on permissions
Frontend application and static file serving
website/
├── server/ # Node.js server (serves static files and proxies)
│ ├── index.js
│ ├── middleware.js
│ └── package.json
├── src/ # React source code
├── public/ # Static assets
└── build/ # Compiled frontend (mounted in docker dev)
Responsibilities:
- Serve React UI interface
- Proxy backend API requests
- Display grades, reports, and other data
Fetches grades from external systems (Gradescope, PrairieLearn, iClicker) and syncs to PostgreSQL
gradesync/
├── config.json # Course config (enabled systems, buckets, categories)
├── api/
│ ├── app.py # Main FastAPI application
│ ├── config_manager.py # Config loader
│ ├── schemas.py # Data models
│ ├── services/ # Business logic layer
│ └── sync/ # Sync logic
└── docs/ # GradeSync docs
Workflow:
External Systems (Gradescope/PL/iClicker)
↓
GradeSync crawler/API fetches data
↓
Normalize & categorize data (assignment_categories)
↓
Update PostgreSQL
Utility scripts for manual Redis maintenance.
Python Flask/uWSGI application that generates student progress reports
progressReport/
├── app.py # Main application
├── parser.py # Data parser
├── templates/ # HTML templates
├── meta/ # Course metadata (grade distributions, etc.)
└── data/ # Report data
Purpose: Generate visualized reports from grades and provide student feedback
reverseProxy/
└── default.conf.template # Nginx config template
Responsibilities:
- Route requests to Web UI / API / Progress Report
- Configure HTTPS (letsencrypt)
- Load balancing
- scripts/setup_cloud_sql.sh - Cloud SQL Proxy initialization
- docs/test_db_integration.sh - Test script
- docs/demo.html - Demo page
graph LR
User["👤 User<br/>Browser"]
RP["Nginx<br/>Reverse Proxy"]
Web["React<br/>Web UI"]
API["Node.js<br/>API"]
PR["Python<br/>Progress Report"]
Redis[(Redis<br/>Cache)]
DB[(PostgreSQL<br/>DB)]
GS["FastAPI<br/>GradeSync"]
DC["DB Cron<br/>Tasks"]
CSP["Cloud SQL<br/>Proxy"]
ES["🔗 External<br/>Systems<br/>Gradescope<br/>PrairieLearn<br/>iClicker"]
User -->|HTTP/S| RP
RP --> Web
RP --> API
RP --> PR
Web -->|fetch/auth| API
API -->|query/auth| Redis
API -->|query| DB
ES -->|sync| GS
GS -->|write| DB
DB -->|via proxy| CSP
DC -->|update Redis| Redis
PR -->|read| DB
PR -->|generate| User
style User fill:#e1f5ff
style RP fill:#fff3e0
style Web fill:#f3e5f5
style API fill:#e8f5e9
style PR fill:#fce4ec
style Redis fill:#fff9c4
style DB fill:#fff9c4
style GS fill:#ede7f6
style DC fill:#ede7f6
style CSP fill:#f5f5f5
style ES fill:#ffebee
Browser 用户
↓
点击登录 (Google OAuth)
↓
前端获取 token → 发送给 API
↓
API: authlib.mjs validateAdminMiddleware() 或 validateStudentMiddleware()
├─ 验证 token (googleAuthHelper.mjs)
├─ 检查 @berkeley.edu 域名(如果不是直接拒绝)
└─ 查询 config.admins 判断 admin 身份 (userlib.mjs)
↓
返回数据或 403 权限不足
GradeSync 定时任务 / 手动触发
↓
根据 gradesync/config.json 配置课程列表
↓
对每个课程:
├─ Gradescope: 爬虫登录 → 拉成绩 → 整理为标准格式
├─ PrairieLearn: API 调用 → 获取分数
└─ iClicker: 登录 → 同步考勤
↓
按 assignment_categories 分类聚合
↓
写入 PostgreSQL
↓
dbcron 定时更新 Redis 缓存
学生访问页面(已登录)
↓
前端 GET /api/student/{email}/grades
↓
API 中间件校验(token 和权限)
↓
API 查询 Redis → 找到学生缓存数据
├─ Hit: 直接返回
└─ Miss: 查询 PostgreSQL 并写入 Redis
↓
前端展示成绩
- API: PORT, DATABASE_URL
- Database: POSTGRES_HOST, POSTGRES_USER, POSTGRES_PASSWORD
- GradeSync: Gradescope/PrairieLearn/iClicker credentials
-
API (
api/config/default.json)- Redis connection
- OAuth client ID
- Admin list
-
GradeSync (
gradesync/config.json)- Course list
- Enabled sync sources and credentials
- Assignment categories mapping
docker compose -f docker-compose.dev.yml up
- Web UI (3000)
- API (8000)
- GradeSync (8001)
- Progress Report (8080)
- Redis (6379)
- Cloud SQL Proxy (5432 → Cloud SQL)
docker compose -f docker-compose.yml up
- Reverse Proxy (80/443)
- Production DB connection (no Cloud SQL Proxy)
- Read this document
- Review
docker-compose.dev.ymlto understand service dependencies
- Clone repository
-
cp .env.example .envandcp api/config/default.example.json api/config/default.json - Fill in environment variables and config
-
docker compose -f docker-compose.dev.yml up --build - Verify all services start successfully
- Login with Berkeley account (need to be added to
api/config/default.jsonadmins list) - Verify student grade query functionality
- Pick a component to start modifying (e.g., API routes or frontend page)
- Test your changes
- Merge to main branch
- CI/CD automatically builds images and deploys
| Issue | Root Cause | Solution |
|---|---|---|
| Login fails (domain mismatch) | Non-Berkeley account used | Only @berkeley.edu accounts allowed |
| 403 permission denied | Account not in admins list | Admin must add your email to api/config/default.json |
| Redis connection failed | Redis service not running or address mismatch | Check redis host/port in api/config/default.json |
| Gradescope sync fails | Credentials expired or XPath changed | Verify GRADESCOPE_* credentials in .env |
| Grades not appearing in Sheets | GradeSync not running or service account lacks permissions | Check GradeSync logs; ensure service account has Sheets edit permission |
Files you typically need to modify:
| Requirement | File Location |
|---|---|
| Modify login logic | api/lib/authlib.mjs, api/lib/googleAuthHelper.mjs |
| Add new API endpoint | api/Router.js, api/v2/index.js |
| Modify frontend page | website/src/** |
| Change grade sync logic | gradesync/api/**, gradesync/{gradescope,prairieLearn,iclicker}/ |
| Modify database operations | api/lib/dbHelper.mjs, gradesync/api/core/** |
| Change cache logic | api/lib/redisHelper.mjs, dbcron/*.py |
| Configure permissions | api/config/default.json → admins list |
| Configure course sync settings | gradesync/config.json |