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>
7.1 KiB
7.1 KiB
Tasks
測試集中在新檔 tests/Feature/RoleAuthorizationTest.php(結構參考 tests/Feature/AdminEndpointAuthTest.php)。每個測試的 docblock 要寫明「為什麼」:跨角色呼叫曾可建立非教練課程、非會員預約。
1. Member 角色 middleware
- 1.1 [後端] 新增
app/Http/Middleware/EnsureMember.php(結構同EnsureAdmin,改用isMember()),並在bootstrap/app.php的$middleware->alias([...])加上'member' => \App\Http\Middleware\EnsureMember::class;驗證:1.3 起的測試通過 - 1.2 [後端]
routes/api.php的 member 群組改為Route::middleware(['auth:sanctum', 'member'])->prefix('member');驗證:php artisan route:list --path=api/member顯示membermiddleware,且register、login不受影響 - 1.3 [整合測試]
test_member_can_access_member_routes:member 呼叫GET /api/member/profile、GET /api/member/bookings回 200(對應 Scenario「member 可存取 member 路由」) - 1.4 [整合測試]
test_provider_is_rejected_on_member_routes:provider 呼叫GET /api/member/profile、GET /api/member/bookings、POST /api/member/bookings、POST /api/member/reviews,皆回 403,並斷言 body 為{ status: false, message: "無權限存取" };POST /api/member/reviews另斷言reviews筆數不變(對應 Scenario「provider 呼叫 member 路由被拒絕」) - 1.5 [整合測試]
test_admin_is_rejected_on_member_routes:admin 呼叫GET /api/member/profile、GET /api/member/bookings、POST /api/member/bookings,皆回 403 與相同 body(對應 Scenario「admin 呼叫 member 路由被拒絕」) - 1.6 [整合測試]
test_non_member_booking_attempt_creates_no_booking:建立可預約時段,provider 帶合法schedule_id呼叫POST /api/member/bookings,回 403,bookings筆數與current_participants不變(對應 Scenario「非 member 建立預約不會產生資料」) - 1.7 [整合測試]
test_unauthenticated_request_is_rejected_on_member_routes:不帶 token 呼叫GET /api/member/profile、GET /api/member/bookings回 401(對應 Scenario「未登入呼叫 member 路由」)
2. Provider 角色 middleware
- 2.1 [後端] 新增
app/Http/Middleware/EnsureProvider.php(結構同EnsureAdmin,改用isProvider(),不檢查verification_status),並在bootstrap/app.php加上'provider' => \App\Http\Middleware\EnsureProvider::class;驗證:2.3 起的測試通過 - 2.2 [後端]
routes/api.php的 provider 群組改為Route::middleware(['auth:sanctum', 'provider'])->prefix('provider');驗證:php artisan route:list --path=api/provider顯示providermiddleware,且register、login不受影響 - 2.3 [整合測試]
test_provider_can_access_provider_routes:provider(含providerProfile)呼叫GET /api/provider/profile、/offers、/schedules、/bookings回 200(對應 Scenario「provider 可存取 provider 路由」) - 2.4 [整合測試]
test_unapproved_provider_can_access_verification:verification_status為unsubmitted、pending、rejected的 provider 呼叫GET /api/provider/verification回 200(對應 Scenario「未通過審核的 provider 仍可進入 provider 路由」) - 2.5 [整合測試]
test_member_is_rejected_on_provider_routes:member 呼叫GET /api/provider/profile、GET /api/provider/offers、POST /api/provider/offers、POST /api/provider/schedules、GET /api/provider/bookings、GET /api/provider/verification,皆回 403 與{ status: false, message: "無權限存取" };POST /api/provider/schedules另斷言course_schedules筆數不變(對應 Scenario「member 呼叫 provider 路由被拒絕」) - 2.6 [整合測試]
test_admin_is_rejected_on_provider_routes:admin 呼叫GET /api/provider/profile、GET /api/provider/offers、POST /api/provider/offers、GET /api/provider/bookings,皆回 403 與相同 body(對應 Scenario「admin 呼叫 provider 路由被拒絕」) - 2.7 [整合測試]
test_non_provider_offer_attempt_creates_no_offer:member 帶通過驗證的完整課程資料呼叫POST /api/provider/offers,回 403,diving_offers筆數不變(對應 Scenario「非 provider 建立課程不會產生資料」) - 2.8 [整合測試]
test_unauthenticated_request_is_rejected_on_provider_routes:不帶 token 呼叫GET /api/provider/profile、GET /api/provider/offers回 401(對應 Scenario「未登入呼叫 provider 路由」)
3. 共用路由與既有規格的回歸
- 3.1 [整合測試]
test_member_and_provider_can_read_notifications:member 與 provider 各自呼叫GET /api/notifications回 200(對應 Scenario「member 與 provider 皆可讀取通知」) - 3.2 [整合測試]
test_member_and_provider_can_read_unread_message_counts:member 與 provider 各自呼叫GET /api/bookings/messages/unread-counts回 200(對應 Scenario「member 與 provider 皆可讀取未讀訊息數」) - 3.3 [整合測試] 執行
php artisan test --filter=BookingListTest,確認feature-test-coverage「預約列表端點測試覆蓋」的四個 Scenario(member 隔離、provider 隔離、admin 全部、未認證 401)在新 middleware 下仍全綠(「非 member/非 provider 於 middleware 層 403」由 1.4、1.5、2.5、2.6 覆蓋);同時更新tests/Feature/BookingListTest.php第 19–24 行 docblock 中「無 role check」「不靠 middleware role 強制」的過時描述
4. 全套回歸、Swagger 與格式
- 4.1 [整合測試] 執行完整
php artisan test(需在容器內,因CourseImageTest需要 GD);若有既有測試因角色錯誤改回 403,判斷是測試用錯角色(修正測試並在 commit 說明)還是依賴跨角色行為(停下回報) - 4.2 [後端] 核對
app/Docs/MemberApiDoc.php、app/Docs/ProviderApiDoc.php每個端點的 403 回應描述涵蓋「角色不符」;缺的補上,並執行php artisan l5-swagger:generate確認無錯誤 - 4.3 [後端] 執行
./vendor/bin/pint --test app/Http/Middleware/EnsureMember.php app/Http/Middleware/EnsureProvider.php bootstrap/app.php routes/api.php tests/Feature/RoleAuthorizationTest.php(以及 4.1/4.2 若有修改的檔案),確認無格式問題
5. 手動驗證
- 5.1 [整合測試](手動,非自動化測試)本機 Docker 環境以 member token 呼叫
POST /api/provider/offers,以 provider token 呼叫POST /api/member/bookings,確認兩者皆回 403 - 5.2 [整合測試](手動,非自動化測試)本機前端:會員端登入後瀏覽「我的預約」、教練端登入後瀏覽課程/時段/預約/審核頁,確認功能正常、沒有出現 403
Workflow follow-up
- 實作完成後依 CLAUDE.md 執行
hardenerskill,再呼叫strict-reviewer - 執行
verify-and-reportskill 回報結果 - 實作與歸檔各自獨立 PR;歸檔時同步
openspec/config.yaml後端慣例段落(移除「member/provider 路由群組目前僅有auth:sanctum」的描述)、CLAUDE.md「授權規範」的已知缺口描述,以及docs/analysis/2026-10-14-project-review-todo.mdH1 的完成狀態