feat: 微人大 web 登录 + 课程成绩展示#6
Merged
Merged
Conversation
Add a browser-only 微人大 login path and a read-only course-grade view so
students can sign in on the web (no CLI/key) and see their externally-computed
final grade for a lab.
Web login:
- auth.BuildWebLoginAuthorizeURL / HandleWebLoginCallback (UpsertUser by
student_id; no device_auth_requests, no user_key)
- GET /auth/login mints a CSRF state (double-submit cookie) and redirects to
微人大; the shared /api/device/verify callback routes to web login when the
labkit_oauth_state cookie matches, else falls through to the device flow
- browser session gains a Source marker; web sessions are key-less
- /auth/login proxied via vite (dev) and Caddy (prod)
Final grades:
- final_grades table (lab_id, student_id, total + breakdown, published_at)
- grade service: CSV import (header-matched), publish, published-only read
- GET /api/labs/{labID}/grade (browser session or CLI signature)
- POST /api/admin/labs/{labID}/grades/{import,publish} under adminGuard
Frontend:
- LoginView (微人大登录) and GradeView (total, breakdown, formula, remark;
404 -> 成绩尚未发布, 401 -> login), /login, /grade, /labs/:labID/grade
Submit/keys/board stay key-only; web sessions can't reach them. Bumped the
migrate runner migration-count assertion 10 -> 11.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…baseline test
- Reject read-only web-login sessions (Source=="web") on profile write
endpoints (UpdateProfile/Nickname/Track) with 403; device-paired sessions
and CLI signatures still write. Submit/keys/board were already key-only.
- Add DELETE /api/admin/labs/{labID}/grades (DeleteGrades) under adminGuard so
a corrected grade CSV can be re-imported cleanly.
- Fix pre-existing failure in apps/migrate runner: applyLegacyMigrations now
applies only up to a given version, so Baseline(7)+Up() replays 8+ as the
normal forward sequence instead of re-running non-idempotent migration 0008.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
让学生用微人大(CAS RUC)在网页上直接登录(不依赖 CLI/密钥),登录后只读查看自己在某个 Lab 的最终课程成绩。成绩由助教在外部算好(CSV),经 Admin 导入 LabKit,学生在 Web 端查看。
Web 登录
device_auth_requests、不建user_key的 web 登录路径:微人大 → 学号 →UpsertUser(student_id)→ 签发 browser session。GET /auth/login生成 CSRF state(double-submit cookie)并 302 到微人大;复用的/api/device/verify回调按labkit_oauth_statecookie 是否匹配?state=分流到 web 登录,否则维持原有 device flow(逻辑不变)。Source标记;web 会话不绑 key。/auth/login在 vite(dev)与 Caddy(prod)中代理到 API。Source=="web"在 profile 写接口(改昵称/赛道)返回 403;device 会话与 CLI 签名照常可写。submit/keys/board 本就只认 key,web 会话进不去。课程成绩
final_grades(lab_id, student_id,总评 + 分项,published_at控制可见性)。GET /api/labs/{labID}/grade(browser session 优先,CLI 签名兼容)。POST .../grades/import、POST .../grades/publish、DELETE .../grades。前端
LoginView(微人大登录,自动判断已登录态)、GradeView(总评 + 分项 + 计分公式 + 备注;404 → 成绩尚未发布,401 → 引导登录),路由/login、/grade、/labs/:labID/grade,导航加 "Grade" 入口。顺带修复
apps/migrate的TestBaselineMarksLegacyDatabaseWithoutReplayingMigrations此前既有失败:其applyLegacyMigrations把所有迁移先全跑一遍,再从 baseline 7 重放,撞上非幂等的0008。现支持只应用到指定版本,使Baseline(7)+Up()等价于正常前向序列。同步把全量迁移计数断言10 → 11并新增final_grades存在性校验。验证
go test ./...通过(含修复后的 migrate baseline 测试);新增单测覆盖 web 登录分流、CSRF、成绩 service/handler、web 会话只读 403、admin 导入/发布/删除。已知/取舍
colab-2026-p2(可用?lab=或/labs/:id/grade覆盖);成绩页只展示remark,不含申诉入口/排名。🤖 Generated with Claude Code