Skip to content

feat(cases): add role-filtered map view endpoint - #141

Merged
cg8-5712 merged 3 commits into
mainfrom
feature/issue-28-role-filtered-map-view
Jul 28, 2026
Merged

cg8-5712 merged 3 commits into
mainfrom
feature/issue-28-role-filtered-map-view

Conversation

@cg8-5712

@cg8-5712 cg8-5712 commented Jul 28, 2026 •

Copy link
Copy Markdown
Collaborator
  • expose GET /api/cases/{case_id}/map-view for case members
  • return places, tasks, confirmed clues, and last-seen text fallbacks
  • filter map layers by family, commander, and volunteer permissions
  • preserve records without coordinates for deterministic text location fallback
  • exclude predicted locations and unauthorized internal data
  • document the endpoint and map-view response schemas in API and OpenAPI docs
  • add authentication and role-based map-view integration tests

close #28

Summary by CodeRabbit

  • 新功能
    • 新增案件地图态势接口 GET /api/cases/{case_id}/map-view:以统一地图条目返回地点、线索、任务与最近确认位置,按访问角色裁剪可见内容,并明确不包含预测位置。
    • 坐标缺失时支持文本/字段回退;家属可见的最后出现标记为 pending_review 且 display_name 为 null(不展示为确认进展)。
  • 文档
    • 完善接口说明与响应形态、字段类型与边界(成功/错误状态)。
  • 测试
    • 覆盖角色过滤、坐标/文本回退、越权与未找到场景(401/404)。

- expose GET /api/cases/{case_id}/map-view for case members
- return places, tasks, confirmed clues, and last-seen text fallbacks
- filter map layers by family, commander, and volunteer permissions
- preserve records without coordinates for deterministic text location fallback
- exclude predicted locations and unauthorized internal data
- document the endpoint and map-view response schemas in API and OpenAPI docs
- add authentication and role-based map-view integration tests
Copilot AI review requested due to automatic review settings July 28, 2026 01:57

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@coderabbitai

coderabbitai Bot commented Jul 28, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 5f46e7d3-ca2d-4f05-b398-0cf019a8322b

📥 Commits

Reviewing files that changed from the base of the PR and between 82676a4 and b66e856.

📒 Files selected for processing (5)
  • docs/API.md
  • docs/openapi.yaml
  • src/api/models.rs
  • src/api/routes/cases.rs
  • tests/api/case_map_view_get.rs
🚧 Files skipped from review as they are similar to previous changes (5)
  • docs/openapi.yaml
  • docs/API.md
  • tests/api/case_map_view_get.rs
  • src/api/models.rs
  • src/api/routes/cases.rs

📝 Walkthrough

Walkthrough

新增 GET /api/cases/{case_id}/map-view 接口,返回按角色裁剪的地点、线索、任务和最后出现位置,并支持无坐标时的文字回退。同步补充响应模型、OpenAPI/API 文档、鉴权测试和多角色集成测试。

Changes

案件地图视图

Layer / File(s) Summary
地图视图响应契约
src/api/models.rs, docs/openapi.yaml, docs/API.md
新增地图视图响应模型与 OpenAPI schema,并记录字段、坐标回退和角色可见性规则。
地图视图路由与数据组装
src/api/routes/cases.rs
注册地图视图路由,读取案件与分页任务数据,按角色组装 last_seen、地点、线索和任务条目。
角色与鉴权集成验证
tests/api/case_map_view_get.rs, tests/api/authentication_guards.rs, tests/api/mod.rs
验证多角色返回结果、文字地点回退、任务数量、非成员错误及令牌鉴权。

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant get_map_view
  participant case_service
  participant task_service
  Client->>get_map_view: GET /api/cases/{case_id}/map-view
  get_map_view->>case_service: 获取案件详情
  get_map_view->>task_service: 分页查询案件任务
  get_map_view-->>Client: 返回按角色裁剪的地图条目
Loading

Possibly related PRs

  • AG-Angui/Angui#117:提供本接口使用的案件地点数据及可见性裁剪基础。
  • AG-Angui/Angui#130:提供本接口映射的任务数据模型与任务查询能力。
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning 实现了角色过滤的地图视图和文本回退,但未体现路线、区域、天气路况及低网降级等关键验收要求。 补齐路线、区域和外部服务降级能力,并增加覆盖地理精度、无坐标线索、低网与超时/配额耗尽场景的测试。
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 标题简洁且准确概括了新增按角色过滤的案件地图视图端点。
Out of Scope Changes check ✅ Passed 新增内容集中在地图视图接口、文档和测试,未见明显与目标无关的改动。
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/issue-28-role-filtered-map-view

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 oasdiff (1.23.0)
docs/openapi.yaml

Error: failed to load base spec from "/tmp/coderabbit-oasdiff-base.LdFQrU": failed to unmarshal data: json error: invalid character 'o' looking for beginning of value, yaml error: error converting YAML to JSON: yaml: line 1275: found character that cannot start any token


Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (1)
tests/api/case_map_view_get.rs (1)

71-85: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

建议补上两个关键负向/边界断言。

当前用例验证了"已确认线索出现在指挥视图",但没有覆盖裁剪逻辑最有风险的反向分支:

  1. 未确认线索(pending_review)不得出现在指挥地图层。src/api/routes/cases.rs 第 276 行的 status == "confirmed" 过滤一旦写反或被删除,会把未审核线索当作地图态势暴露,而现有断言全部会继续通过。
  2. 无坐标记录的文本回退——本 PR 的核心行为——目前只由 last_seen 间接覆盖。建议再建一个不带经纬度的 place 或线索,断言其 longitude/latitude 为 null 且 location_text 非空、location_precision == "unknown"。

依据路径指令:tests/** 需检查改动行为具备有意义的正向、负向与边界覆盖。

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/api/case_map_view_get.rs` around lines 71 - 85, 增强 case_map_view_get
测试中的边界覆盖:断言 pending_review 状态的线索不会出现在 commander_items 中;另外创建一个无经纬度的 place
或线索,并断言其 longitude 和 latitude 为 null、location_text 非空且 location_precision 为
"unknown"。保留现有已确认线索和 last_seen 的正向断言。

Source: Path instructions

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/openapi.yaml`:
- Around line 2200-2201: 将 OpenAPI 中 cases 对象的 occurred_at 声明与其数据源字段保持一致,移除该字段的
format: date-time,仅保留 [string, "null"] 类型;不要修改 reported_at 或
ElderProfile.last_seen_at、Clue.occurred_at 的现有声明。

In `@src/api/routes/cases.rs`:
- Around line 219-228: Update the task-loading flow around the list_tasks call
so it does not silently stop at the first 100 tasks: use the returned
tasks.total to request and aggregate every page, or explicitly expose total and
truncation information in the response if pagination must remain limited.
Preserve the existing task mapping behavior while ensuring clients can detect
incomplete results.
- Around line 233-247: Update the last-seen CaseMapItem construction in the case
map route so the self-reported elder_profile.last_seen_location is not marked as
confirmed; use the appropriate unverified/pending review_status and preserve the
corresponding API semantics. Replace the hardcoded “Last confirmed location”
display_name with the object_type-driven client-localized behavior, then
synchronize the changed review_status contract in tests/api/case_map_view_get.rs
and docs/openapi.yaml.

---

Nitpick comments:
In `@tests/api/case_map_view_get.rs`:
- Around line 71-85: 增强 case_map_view_get 测试中的边界覆盖:断言 pending_review 状态的线索不会出现在
commander_items 中;另外创建一个无经纬度的 place 或线索,并断言其 longitude 和 latitude 为
null、location_text 非空且 location_precision 为 "unknown"。保留现有已确认线索和 last_seen
的正向断言。
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: fd1e3171-836b-4018-b4bb-47291434ab80

📥 Commits

Reviewing files that changed from the base of the PR and between 724c6ca and a6ef7a7.

📒 Files selected for processing (7)
  • docs/API.md
  • docs/openapi.yaml
  • src/api/models.rs
  • src/api/routes/cases.rs
  • tests/api/authentication_guards.rs
  • tests/api/case_map_view_get.rs
  • tests/api/mod.rs

Comment thread docs/openapi.yaml
Comment on lines +2200 to +2201
occurred_at: { type: [string, "null"], format: date-time }
reported_at: { type: [string, "null"], format: date-time }

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

occurred_at 标注 format: date-time 与实际数据源不符。

occurred_at 的取值来自 elder_profile.last_seen_at(src/api/routes/cases.rs 第 242 行)和 clue.occurred_at(第 288 行),而本文件中 ElderProfile.last_seen_at(第 1895-1896 行)与 Clue.occurred_at(第 1945-1946 行)都刻意声明为无 format 的 [string, "null"],因为服务端只做 trim、不解析时间格式。这里加上 format: date-time 会让契约校验对同一份数据给出相互矛盾的结论。

📝 建议对齐既有字段声明
-        occurred_at: { type: [string, "null"], format: date-time }
+        occurred_at:
+          type: [string, "null"]
+          description: 可能直接透传未经格式校验的案件/线索时间文本,不保证是 RFC 3339。
         reported_at: { type: [string, "null"], format: date-time }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
occurred_at: { type: [string, "null"], format: date-time }
reported_at: { type: [string, "null"], format: date-time }
occurred_at:
type: [string, "null"]
description: 可能直接透传未经格式校验的案件/线索时间文本,不保证是 RFC 3339。
reported_at: { type: [string, "null"], format: date-time }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/openapi.yaml` around lines 2200 - 2201, 将 OpenAPI 中 cases 对象的
occurred_at 声明与其数据源字段保持一致,移除该字段的 format: date-time,仅保留 [string, "null"] 类型;不要修改
reported_at 或 ElderProfile.last_seen_at、Clue.occurred_at 的现有声明。

Comment thread src/api/routes/cases.rs Outdated
Comment thread src/api/routes/cases.rs
- fetch all task pages instead of limiting map results to 100 tasks
- guard page increments and item count conversions against overflow
- add integration coverage for map views containing more than 100 tasks
@github-actions

Copy link
Copy Markdown

Preview ready

The preview for this build is available at https://pr-141-82676a4b777f.angui.cg8.site.

Temporary demo accounts (all use the password 4fa482e9cd525c0b64dbbb26ccbc096a191f5c72abef56b0):

Role Email
Family family@demo.invalid
Commander commander@demo.invalid
Volunteer volunteer@demo.invalid
Learner learner@demo.invalid
Administrator admin@demo.invalid

These accounts and all preview data belong only to this deployment. The next preview deployment resets the SQLite database and invalidates these credentials.

- return null display names for last-seen map items
- prevent clients from presenting last-seen data as confirmed
- update OpenAPI and API documentation for localized labels
- add map-view coverage for pending-review last-seen entries
@cg8-5712
cg8-5712 merged commit c1d0739 into main Jul 28, 2026
14 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[API] GET /api/cases/{case_id}/map-view - 获取按角色裁剪的地图态势

2 participants