Files
NextEdu/bugs/parent_web_test.md
SpecialX 978d9a8309
Some checks failed
Security / deep-security-scan (push) Failing after 20m5s
DR Drill / dr-drill (push) Failing after 1m31s
CI / scheduled-backup (push) Failing after 1m31s
CI / backup-verify (push) Has been skipped
CI / weekly-dr-drill (push) Failing after 0s
CI / build-deploy (push) Has been cancelled
CI / security-scan (push) Has been cancelled
feat: 新增备课模块并修复全模块 P0/P1/P2 缺陷
主要变更:

- 新增 lesson-preparation 模块: 备课编辑器、节点编辑、AI 建议、知识点选择、版本历史、作业发布

- 新增 shared 通用组件: charts/question-bank-filters/schedule-list/ui (chip-nav/filter-bar/page-header/stat-card/stat-item)

- 新增 student/admin 端 loading.tsx 与 error.tsx, 优化加载与错误态体验

- 新增 teacher/lesson-plans 页面 (列表/新建/编辑)

- 新增 drizzle 迁移 0002_tiny_lionheart 及 snapshot

- 新增 textbooks/schema.ts 与 exams/utils/normalize-structure.ts

- 修复 Tiptap v3 SSR hydration 崩溃 (rich-text-block immediatelyRender: false)

- 重构多模块 data-access/actions/组件, 修复权限校验与类型规范

- 同步架构文档 004/005 反映新增模块、导出、依赖关系

- 归档 bugs/* 测试报告与 e2e 测试脚本 (admin/parent/student/teacher web_test)
2026-06-22 01:06:16 +08:00

278 lines
12 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 家长端 Web 功能测试报告
> 测试日期2026-06-20 12:28:43
> 测试范围:家长端所有页面功能 + 跨角色权限隔离
> 测试工具Playwright + Chromium (headless)
> 测试账号parent_g1c1_1@xiaoxue.edu.cn
> Base URLhttp://localhost:3000
---
## 一、测试概览
| 指标 | 数值 |
|------|------|
| 总测试页面数 | 24 |
| 通过 | 17 |
| 失败 | 7 |
| 警告 | 0 |
| 页面通过率 | 70.8% |
| 功能检查通过率 | 24/24 (100.0%) |
| 安全检查通过率 | 1/1 (100.0%) |
---
## 二、关键发现
### ⚠️ 严重:跨角色访问控制失效(安全漏洞)
家长账号可以访问教师端页面,权限隔离失效。根因分析:
- [`src/proxy.ts`](../src/proxy.ts#L10-L16) 中 `/teacher` 路由前缀仅要求 `EXAM_READ` 权限
- [`src/shared/lib/permissions.ts`](../src/shared/lib/permissions.ts#L125-L136) 中家长角色被授予了 `EXAM_READ` 权限
- 因此家长通过了 proxy 的权限检查,可以访问所有 `/teacher/*` 页面
受影响页面:
| 路由 | HTTP | 表现 |
|------|------|------|
| `/teacher/dashboard` | 500 | HTTP 500页面崩溃 |
| `/teacher/exams` | 200 | 成功访问并重定向到 `/teacher/exams/all` |
| `/teacher/homework` | 500 | HTTP 500页面崩溃 |
| `/teacher/grades` | 200 | 成功访问HTTP 200 |
| `/teacher/questions` | 200 | 成功访问HTTP 200 |
| `/teacher/classes` | 200 | 成功访问并重定向到 `/teacher/classes/my` |
| `/teacher/attendance` | 200 | 成功访问HTTP 200 |
**修复建议**
1.`src/proxy.ts` 中为 `/teacher` 路由前缀增加角色校验(要求 `teacher` / `grade_head` / `teaching_head` 角色),或
2.`src/shared/lib/permissions.ts` 中移除家长角色的 `EXAM_READ` 权限(如果家长不需要查看考试),或
3. 在各教师端页面的 Server Component 中增加 `requireRole()` 角色校验,作为深度防御
### ✅ 家长端核心功能正常
- 家长端 10 个页面全部正常加载HTTP 200
- 功能完整性检查 24/24 项通过
- 跨家庭信息隔离正常工作(访问非关联子女返回 Access denied
- 侧边栏导航正确显示家长菜单,未泄露教师/管理员菜单
- 子女详情页邮箱掩码、作业摘要、成绩趋势、今日课表等功能完整
---
## 三、页面测试详情
### Announcements
| 状态 | 路由 | HTTP | 结果 | 备注 |
|------|------|------|------|------|
| ✅ | `/announcements` | 200 | passed | - |
### Attendance
| 状态 | 路由 | HTTP | 结果 | 备注 |
|------|------|------|------|------|
| ✅ | `/parent/attendance` | 200 | passed | - |
### Child Detail
| 状态 | 路由 | HTTP | 结果 | 备注 |
|------|------|------|------|------|
| ✅ | `/parent/children/user_s_g1c1_1` | 200 | passed | 警告: Error text on page: Due 2026年6月18日 |
### Cross-Role Access Control
| 状态 | 路由 | HTTP | 结果 | 备注 |
|------|------|------|------|------|
| ✅ | `/admin/dashboard` | 200 | passed | 重定向: `/parent/dashboard?from=%2Fadmin%2Fdashboard&reason=forbidden`<br>跨角色访问被权限系统拦截 |
| ✅ | `/admin/school` | 200 | passed | 重定向: `/parent/dashboard?from=%2Fadmin%2Fschool&reason=forbidden`<br>跨角色访问被权限系统拦截 |
| ❌ | `/teacher/dashboard` | 500 | failed | 错误: 跨角色访问返回 HTTP 500应被重定向拦截<br>错误: Failed to load resource: the server responded with a status of 500 (Internal Server Error) |
| ❌ | `/teacher/exams` | 200 | failed | 重定向: `/teacher/exams/all`<br>错误: ⚠️ 安全漏洞:家长成功访问了受限页面(最终 URL: http://localhost:3000/teacher/exams/all权限隔离失效<br>错误: %o |
| ❌ | `/teacher/homework` | 500 | failed | 重定向: `/teacher/homework/assignments`<br>错误: 跨角色访问返回 HTTP 500应被重定向拦截<br>错误: Failed to load resource: the server responded with a status of 500 (Internal Server Error) |
| ❌ | `/teacher/grades` | 200 | failed | 错误: ⚠️ 安全漏洞:家长成功访问了受限页面(最终 URL: http://localhost:3000/teacher/grades权限隔离失效 |
| ❌ | `/teacher/questions` | 200 | failed | 错误: ⚠️ 安全漏洞:家长成功访问了受限页面(最终 URL: http://localhost:3000/teacher/questions权限隔离失效 |
| ❌ | `/teacher/classes` | 200 | failed | 重定向: `/teacher/classes/my`<br>错误: ⚠️ 安全漏洞:家长成功访问了受限页面(最终 URL: http://localhost:3000/teacher/classes/my权限隔离失效 |
| ❌ | `/teacher/attendance` | 200 | failed | 错误: ⚠️ 安全漏洞:家长成功访问了受限页面(最终 URL: http://localhost:3000/teacher/attendance权限隔离失效 |
| ✅ | `/student/dashboard` | 200 | passed | 重定向: `/parent/dashboard?from=%2Fstudent%2Fdashboard&reason=forbidden`<br>跨角色访问被权限系统拦截 |
| ✅ | `/student/learning` | 200 | passed | 重定向: `/parent/dashboard?from=%2Fstudent%2Flearning&reason=forbidden`<br>跨角色访问被权限系统拦截 |
| ✅ | `/student/grades` | 200 | passed | 重定向: `/parent/dashboard?from=%2Fstudent%2Fgrades&reason=forbidden`<br>跨角色访问被权限系统拦截 |
| ✅ | `/student/attendance` | 200 | passed | 重定向: `/parent/dashboard?from=%2Fstudent%2Fattendance&reason=forbidden`<br>跨角色访问被权限系统拦截 |
| ✅ | `/management/grade/classes` | 200 | passed | 重定向: `/parent/dashboard?from=%2Fmanagement%2Fgrade%2Fclasses&reason=forbidden`<br>跨角色访问被权限系统拦截 |
### Dashboard
| 状态 | 路由 | HTTP | 结果 | 备注 |
|------|------|------|------|------|
| ✅ | `/parent/dashboard` | 200 | passed | - |
### Grades
| 状态 | 路由 | HTTP | 结果 | 备注 |
|------|------|------|------|------|
| ✅ | `/parent/grades` | 200 | passed | - |
### Messages
| 状态 | 路由 | HTTP | 结果 | 备注 |
|------|------|------|------|------|
| ✅ | `/messages` | 200 | passed | - |
| ✅ | `/messages/compose` | 200 | passed | - |
### Profile
| 状态 | 路由 | HTTP | 结果 | 备注 |
|------|------|------|------|------|
| ✅ | `/profile` | 200 | passed | - |
### Settings
| 状态 | 路由 | HTTP | 结果 | 备注 |
|------|------|------|------|------|
| ✅ | `/settings` | 200 | passed | - |
| ✅ | `/settings/security` | 200 | passed | - |
---
## 四、功能完整性检查
| 状态 | 检查项 | 期望 | 实际 |
|------|--------|------|------|
| ✅ | 返回仪表盘按钮 | 存在 Back to Dashboard 链接 | Found |
| ✅ | 子女姓名标题 | 显示子女姓名 | 小明 |
| ✅ | 邮箱掩码处理 | 邮箱被掩码为 j***@domain.com | Masked |
| ✅ | 作业摘要卡片 | 显示 {childName}'s Homework | Found |
| ✅ | 作业统计 - Pending | 显示 Pending 计数 | Found |
| ✅ | 作业统计 - Submitted | 显示 Submitted 计数 | Found |
| ✅ | 作业统计 - Graded | 显示 Graded 计数 | Found |
| ✅ | 成绩趋势卡片 | 显示成绩信息 | Found |
| ✅ | 今日课表卡片 | 显示 {childName}'s Today Schedule | Found |
| ✅ | View all 链接 | 存在 View all 链接 | Found |
| ✅ | 仪表盘标题 | Parent Dashboard | Parent Dashboard |
| ✅ | 问候语显示 | Good morning/afternoon/evening 或 Welcome | Found |
| ✅ | Grades 快捷入口 | 存在 | Found |
| ✅ | Attendance 快捷入口 | 存在 | Found |
| ✅ | Announcements 快捷入口 | 存在 | Found |
| ✅ | 子女卡片显示 | ≥1 个子女卡片 | 1 个 |
| ✅ | 子女卡片 - Pending 统计 | 显示 Pending 计数 | Found |
| ✅ | 子女卡片 - Overdue 统计 | 显示 Overdue 计数 | Found |
| ✅ | 子女数量提示 | 显示 'N child(ren) linked' | Found |
| ✅ | 侧边栏 - Dashboard | 显示 Dashboard 导航项 | Found |
| ✅ | 侧边栏 - Grades | 显示 Grades 导航项 | Found |
| ✅ | 侧边栏 - Attendance | 显示 Attendance 导航项 | Found |
| ✅ | 侧边栏 - Announcements | 显示 Announcements 导航项 | Found |
| ✅ | 侧边栏 - Messages | 显示 Messages 导航项 | Found |
---
## 五、安全检查
| 状态 | 检查项 | 期望 | 实际 |
|------|--------|------|------|
| ✅ | 访问不存在/非关联子女应被拒绝 | 显示 Access denied 或 404 | Access denied |
---
## 六、失败页面详情
### ❌ `/teacher/dashboard`
- **分类**: Cross-Role Access Control
- **HTTP状态**: 500
- **错误信息**:
- 跨角色访问返回 HTTP 500应被重定向拦截
- Failed to load resource: the server responded with a status of 500 (Internal Server Error)
- %o
%s Error: Teacher not found
at getTeacherIdForMutations (about://React/Server/E:%5CDesktop%5CCICD%5C.next%5Cdev%5Cserver%5Cchunks%5Cssr%5C%5Broot-of-the-server%5D__458f1717._.js?61:9381:27)
at TeacherDashboardPage (about://React/Server/E:%5CDesktop%5CCICD%5C.next%5Cdev%5Cserver%5Cchunks...(已截断)
### ❌ `/teacher/exams`
- **分类**: Cross-Role Access Control
- **HTTP状态**: 200
- **重定向**: `http://localhost:3000/teacher/exams/all`
- **错误信息**:
- ⚠️ 安全漏洞:家长成功访问了受限页面(最终 URL: http://localhost:3000/teacher/exams/all权限隔离失效
- %o
%s Error: Failed query: select `exams`.`id`, `exams`.`title`, `exams`.`description`, `exams`.`structure`, `exams`.`creator_id`, `exams`.`subject_id`, `exams`.`grade_id`, `exams`.`start_time`, `exams`.`end_time`, `exams`.`exam_mode`, `exams`.`duration_minutes`, `exams`.`shuffle_questions`, `exams...(已截断)
### ❌ `/teacher/homework`
- **分类**: Cross-Role Access Control
- **HTTP状态**: 500
- **重定向**: `http://localhost:3000/teacher/homework/assignments`
- **错误信息**:
- 跨角色访问返回 HTTP 500应被重定向拦截
- Failed to load resource: the server responded with a status of 500 (Internal Server Error)
- %o
%s Error: Teacher not found
at getTeacherIdForMutations (about://React/Server/E:%5CDesktop%5CCICD%5C.next%5Cdev%5Cserver%5Cchunks%5Cssr%5C%5Broot-of-the-server%5D__458f1717._.js?47:9381:27)
at AssignmentsPage (about://React/Server/E:%5CDesktop%5CCICD%5C.next%5Cdev%5Cserver%5Cchunks%5Css...(已截断)
### ❌ `/teacher/grades`
- **分类**: Cross-Role Access Control
- **HTTP状态**: 200
- **错误信息**:
- ⚠️ 安全漏洞:家长成功访问了受限页面(最终 URL: http://localhost:3000/teacher/grades权限隔离失效
### ❌ `/teacher/questions`
- **分类**: Cross-Role Access Control
- **HTTP状态**: 200
- **错误信息**:
- ⚠️ 安全漏洞:家长成功访问了受限页面(最终 URL: http://localhost:3000/teacher/questions权限隔离失效
### ❌ `/teacher/classes`
- **分类**: Cross-Role Access Control
- **HTTP状态**: 200
- **重定向**: `http://localhost:3000/teacher/classes/my`
- **错误信息**:
- ⚠️ 安全漏洞:家长成功访问了受限页面(最终 URL: http://localhost:3000/teacher/classes/my权限隔离失效
### ❌ `/teacher/attendance`
- **分类**: Cross-Role Access Control
- **HTTP状态**: 200
- **错误信息**:
- ⚠️ 安全漏洞:家长成功访问了受限页面(最终 URL: http://localhost:3000/teacher/attendance权限隔离失效
---
## 九、测试覆盖范围
### 9.1 家长端路由(来自 `src/modules/layout/config/navigation.ts`
- `/parent/dashboard` - 家长仪表盘
- `/parent/grades` - 子女成绩聚合页
- `/parent/attendance` - 子女考勤聚合页
- `/parent/children/[studentId]` - 单个子女详情页
- `/announcements` - 公告列表(家长有 `ANNOUNCEMENT_READ` 权限)
- `/messages` - 消息列表(家长有 `MESSAGE_READ` 权限)
- `/messages/compose` - 写消息
- `/profile` - 个人资料
- `/settings` - 设置
- `/settings/security` - 安全设置
### 9.2 跨角色访问保护测试
家长账号尝试访问以下路由,应被 `src/proxy.ts` 重定向回 `/parent/dashboard`
- `/admin/*` - 管理员页面(需 `SCHOOL_MANAGE` 权限)
- `/teacher/*` - 教师页面(需 `EXAM_READ` 权限,家长虽有此权限但路由前缀仍会拦截教师专属页面)
- `/student/*` - 学生页面(需 `HOMEWORK_SUBMIT` 权限)
- `/management/*` - 管理页面(需 `GRADE_MANAGE` 权限)
### 9.3 功能完整性检查项
- 仪表盘标题、问候语、快捷入口Grades/Attendance/Announcements、子女卡片、统计计数
- 子女详情页返回按钮、姓名标题、邮箱掩码、作业摘要、成绩趋势、今日课表、View all 链接
- 侧边栏导航:仅显示家长相关菜单,不显示教师/管理员菜单
- 跨家庭隔离:访问非关联子女应被拒绝
---
*报告自动生成于 2026-06-20 12:28:43*