d83d941993
Run Tests / test (pull_request) Successful in 34s
- 新增主規格 role-authorization,更新 feature-test-coverage 的 middleware 描述 - 勾選手動驗證任務 5.1、5.2(23/23) - CLAUDE.md 授權規範與 openspec/config.yaml 移除「member/provider 只有 auth:sanctum」的過時說明 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
5.1 KiB
5.1 KiB
Spec Delta
Purpose
依使用者角色限制 member、provider 專屬 API 路由群組的存取,避免已登入的其他角色跨角色呼叫課程、時段、預約等業務端點。
ADDED Requirements
Requirement: Member 專屬路由僅限 member 角色存取
/api/member/* 路由群組(不含公開的 POST /api/member/register、POST /api/member/login)SHALL 只允許 role = member 的已登入使用者存取。其他角色 MUST 收到 HTTP 403,回應為 { "status": false, "message": "無權限存取" },且請求 MUST NOT 產生任何資料變更。未帶 token 的請求 MUST 收到 HTTP 401。
Scenario: member 可存取 member 路由
- WHEN 一個
role = member的使用者,以該使用者的 token 呼叫GET /api/member/profile與GET /api/member/bookings - THEN 回傳 HTTP 200,
status為true
Scenario: provider 呼叫 member 路由被拒絕
- WHEN 一個
role = provider的使用者,以該使用者的 token 呼叫GET /api/member/profile、GET /api/member/bookings、POST /api/member/bookings、POST /api/member/reviews - THEN 每個請求都回傳 HTTP 403,body 為
{ "status": false, "message": "無權限存取" }
Scenario: admin 呼叫 member 路由被拒絕
- WHEN 一個
role = admin的使用者,以該使用者的 token 呼叫GET /api/member/profile、GET /api/member/bookings、POST /api/member/bookings - THEN 每個請求都回傳 HTTP 403,body 為
{ "status": false, "message": "無權限存取" }
Scenario: 非 member 建立預約不會產生資料
- WHEN 一個可預約的課程時段,以及一個
role = provider的使用者,以該使用者的 token 呼叫POST /api/member/bookings並帶入合法的時段 id - THEN 回傳 HTTP 403,
bookings資料表筆數不變,該時段的current_participants不變
Scenario: 未登入呼叫 member 路由
- WHEN 不帶 token 呼叫
GET /api/member/profile、GET /api/member/bookings - THEN 回傳 HTTP 401
Requirement: Provider 專屬路由僅限 provider 角色存取
/api/provider/* 路由群組(不含公開的 POST /api/provider/register、POST /api/provider/login)SHALL 只允許 role = provider 的已登入使用者存取,且 MUST NOT 以教練審核狀態作為進入條件。其他角色 MUST 收到 HTTP 403,回應為 { "status": false, "message": "無權限存取" },且請求 MUST NOT 產生任何資料變更。未帶 token 的請求 MUST 收到 HTTP 401。
Scenario: provider 可存取 provider 路由
- WHEN 一個
role = provider的使用者,以該使用者的 token 呼叫GET /api/provider/profile、GET /api/provider/offers、GET /api/provider/schedules、GET /api/provider/bookings - THEN 回傳 HTTP 200,
status為true
Scenario: 未通過審核的 provider 仍可進入 provider 路由
- WHEN 一個
role = provider、verification_status不是 approved(例如 unsubmitted 或 pending)的使用者,以該使用者的 token 呼叫GET /api/provider/verification - THEN 回傳 HTTP 200,不會因角色 middleware 回 403
Scenario: member 呼叫 provider 路由被拒絕
- WHEN 一個
role = member的使用者,以該使用者的 token 呼叫GET /api/provider/profile、GET /api/provider/offers、POST /api/provider/offers、POST /api/provider/schedules、GET /api/provider/bookings、GET /api/provider/verification - THEN 每個請求都回傳 HTTP 403,body 為
{ "status": false, "message": "無權限存取" }
Scenario: admin 呼叫 provider 路由被拒絕
- WHEN 一個
role = admin的使用者,以該使用者的 token 呼叫GET /api/provider/profile、GET /api/provider/offers、POST /api/provider/offers、GET /api/provider/bookings - THEN 每個請求都回傳 HTTP 403,body 為
{ "status": false, "message": "無權限存取" }
Scenario: 非 provider 建立課程不會產生資料
- WHEN 一個
role = member的使用者,以該使用者的 token 呼叫POST /api/provider/offers並帶入通過驗證的完整課程資料 - THEN 回傳 HTTP 403,
diving_offers資料表筆數不變
Scenario: 未登入呼叫 provider 路由
- WHEN 不帶 token 呼叫
GET /api/provider/profile、GET /api/provider/offers - THEN 回傳 HTTP 401
Requirement: 跨角色共用路由不受角色限制影響
通知(/api/notifications/*)與預約即時訊息(/api/bookings/{booking}/messages*、/api/bookings/messages/unread-counts)路由 SHALL 維持既有行為:member 與 provider 皆可存取,存取權限由既有的資源歸屬檢查決定,不套用 member 或 provider 角色限制。
Scenario: member 與 provider 皆可讀取通知
- WHEN 一個
role = member與一個role = provider的使用者,分別以各自的 token 呼叫GET /api/notifications - THEN 兩者皆回傳 HTTP 200
Scenario: member 與 provider 皆可讀取未讀訊息數
- WHEN 一個
role = member與一個role = provider的使用者,分別以各自的 token 呼叫GET /api/bookings/messages/unread-counts - THEN 兩者皆回傳 HTTP 200