事實盤點(no code change)。分支
fix/v1.8.0-bugs。 涵蓋模組:api/survey、api/task_survey。 路徑前綴/api/1.0(兩個 blueprint 都是)。 每個 WRITE method(post/put/delete/patch)一列;敏感 GET(export/download/report)一列。總結論:兩模組全站無任何角色 / participant / admin 守門。所有 service(本地
app/survey、app/task_survey+ 外部jedi_survey套件)trace 到底皆無assert_project_manager/require_platform_admin/require_super_admin/SspPermissionChecker/assert_workflow_project_participant/ 手動ForbiddenError。task_survey_service 內唯一的TaskAssignee引用(task_survey_service.py:461)是「通知收件人查詢」,非授權。已驗證 survey 為裸區屬實。 另有 2 個敏感 GET(範本下載)連@jwt_required()都沒有 → 完全未認證。
| Route path | Method | Route file:line | @jwt_required? | 呼叫的 service method | 現況守門 | 備註 |
|---|---|---|---|---|---|---|
/api/1.0/surveys |
POST | api/survey/routes/survey_route.py:59 | 是 | SurveyAppService.get_surveys_and_pager |
僅 JWT | POST 實為分頁查詢(讀) |
/api/1.0/survey / /survey/<uid> |
POST | api/survey/routes/survey_route.py:103 | 是 | SurveyService.add_survey(jedi_survey) |
僅 JWT | 新增問卷;裸區 |
/api/1.0/survey/<uid> |
PUT | api/survey/routes/survey_route.py:127 | 是 | SurveyService.update_survey(jedi_survey) |
僅 JWT | 更新問卷;裸區 |
/api/1.0/survey/<uid> |
DELETE | api/survey/routes/survey_route.py:146 | 是 | SurveyService.delete_survey(jedi_survey) |
僅 JWT | 刪除問卷;裸區 |
/api/1.0/survey/excel-import |
POST | api/survey/routes/survey_route.py:157 | 是 | SurveyService.import_survey(jedi_survey) |
僅 JWT | Excel 匯入問卷(寫入);裸區 |
/api/1.0/survey/import-template |
GET | api/survey/routes/survey_route.py:198 | 否 | 無(send_from_directory 靜態檔) |
無 JWT | 敏感 GET(範本下載);連 JWT 都缺 |
/api/1.0/survey/move |
POST | api/survey/routes/survey_route.py:209 | 是 | SurveyService.move_survey(jedi_survey) |
僅 JWT | 移動問卷(寫入);裸區 |
/api/1.0/survey/<uid>/clone |
POST | api/survey/routes/survey_route.py:229 | 是 | SurveyCloneService.clone_survey |
僅 JWT | 深度複製問卷(寫入);裸區 |
/api/1.0/survey/<uid>/release |
PUT | api/survey/routes/survey_route.py:252 | 是 | SurveyDomainService.release_survey(jedi_survey) |
僅 JWT | 發布問卷(publish);裸區 |
/api/1.0/survey/<uid>/release |
DELETE | api/survey/routes/survey_route.py:266 | 是 | SurveyDomainService.unrelease_survey(jedi_survey) |
僅 JWT | 取消發布(unpublish);裸區 |
/api/1.0/survey-folders |
POST | api/survey/routes/survey_folder_route.py:39 | 是 | SurveyFolderService.get_folders(jedi_survey) |
僅 JWT | POST 實為分頁查詢(讀) |
/api/1.0/survey-folder / /survey-folder/<uid> |
POST | api/survey/routes/survey_folder_route.py:67 | 是 | SurveyFolderService.add_folder(jedi_survey) |
僅 JWT | 新增資料夾;裸區 |
/api/1.0/survey-folder/<uid> |
PUT | api/survey/routes/survey_folder_route.py:82 | 是 | SurveyFolderService.update_folder(jedi_survey) |
僅 JWT | 更新資料夾;裸區 |
/api/1.0/survey-folder/<uid> |
DELETE | api/survey/routes/survey_folder_route.py:95 | 是 | SurveyFolderService.delete_folder(jedi_survey) |
僅 JWT | 刪除資料夾;裸區 |
/api/1.0/survey-question / /survey-question/<uid> |
POST | api/survey/routes/survey_question_route.py:34 | 是 | SurveyQuestionDomainService.add_question(jedi_survey) |
僅 JWT | 新增題目;裸區 |
/api/1.0/survey-question/<uid> |
PUT | api/survey/routes/survey_question_route.py:61 | 是 | SurveyQuestionDomainService.update_question(jedi_survey) |
僅 JWT | 更新題目;裸區 |
/api/1.0/survey-question/<uid> |
DELETE | api/survey/routes/survey_question_route.py:91 | 是 | SurveyQuestionDomainService.delete_question(jedi_survey) |
僅 JWT | 刪除題目;裸區 |
/api/1.0/survey-questions/reorder |
POST | api/survey/routes/survey_question_route.py:106 | 是 | SurveyQuestionDomainService.reorder_questions(jedi_survey) |
僅 JWT | 題目重排序(寫入);裸區 |
/api/1.0/survey-question/move |
POST | api/survey/routes/survey_question_route.py:125 | 是 | SurveyQuestionDomainService.move_question(jedi_survey) |
僅 JWT | 移動題目(寫入);裸區 |
/api/1.0/survey-page / /survey-page/<uid> |
POST | api/survey/routes/survey_page_route.py:34 | 是 | SurveyPageDomainService.add_page(jedi_survey) |
僅 JWT | 新增頁面;裸區 |
/api/1.0/survey-page/<uid> |
PUT | api/survey/routes/survey_page_route.py:60 | 是 | SurveyPageDomainService.update_page(jedi_survey) |
僅 JWT | 更新頁面;裸區 |
/api/1.0/survey-page/<uid> |
DELETE | api/survey/routes/survey_page_route.py:83 | 是 | SurveyPageDomainService.delete_page(jedi_survey) |
僅 JWT | 刪除頁面;裸區 |
/api/1.0/survey-pages/reorder |
POST | api/survey/routes/survey_page_route.py:97 | 是 | SurveyPageDomainService.reorder_pages(jedi_survey) |
僅 JWT | 頁面重排序(寫入);裸區 |
/api/1.0/survey-page/move |
POST | api/survey/routes/survey_page_route.py:116 | 是 | SurveyPageDomainService.move_page(jedi_survey) |
僅 JWT | 移動頁面(寫入);裸區 |
/api/1.0/survey-discussions |
POST | api/survey/routes/survey_discussion_route.py:26 | 是 | SurveyDiscussionService.get_survey_discussions |
僅 JWT | POST 實為查詢(讀) |
/api/1.0/survey-discussion / /survey-discussion/<uid> |
POST | api/survey/routes/survey_discussion_route.py:44 | 是 | SurveyDiscussionService.add_discussion |
僅 JWT | 新增討論;裸區 |
/api/1.0/survey-discussion/<uid> |
PUT | api/survey/routes/survey_discussion_route.py:64 | 是 | SurveyDiscussionService.update_discussion |
僅 JWT | 更新討論;裸區 |
/api/1.0/survey-discussion/<uid> |
DELETE | api/survey/routes/survey_discussion_route.py:83 | 是 | SurveyDiscussionService.delete_discussion |
僅 JWT | 刪除討論;裸區 |
| Route path | Method | Route file:line | @jwt_required? | 呼叫的 service method | 現況守門 | 備註 |
|---|---|---|---|---|---|---|
/api/1.0/task-surveys |
POST | api/task_survey/routes/task_survey_route.py:31 | 是 | TaskSurveyService.get_task_surveys |
僅 JWT | POST 實為查詢(讀) |
/api/1.0/task-survey/<uid> |
PUT | api/task_survey/routes/task_survey_route.py:50 | 是 | TaskSurveyService.update_task_survey |
僅 JWT | 更新 task survey(可換問卷);有 project/round context 但未檢查 participant |
/api/1.0/task-survey/import-template/<task_uid> |
GET | api/task_survey/routes/task_survey_route.py:62 | 否 | TaskSurveyService.generate_task_survey_question_import_excel_template_data |
無 JWT | 敏感 GET(範本下載 xlsx,含 task 題目內容);連 JWT 都缺 |
/api/1.0/task-survey/import-answers |
POST | api/task_survey/routes/task_survey_route.py:130 | 是 | TaskSurveyService.batch_import_task_survey_questions |
僅 JWT | Excel 批次上傳專案調查結果(寫入);未檢查 participant |
/api/1.0/task-survey/configured/<uid> |
PUT | api/task_survey/routes/task_survey_route.py:169 | 是 | TaskSurveyService.update_task_survey_configure |
僅 JWT | 更新 configured(approval_required/換卷,寫入);未檢查 participant |
/api/1.0/project-survey/answers/<uid> |
PUT | api/task_survey/routes/question_answer_route.py:38 | 是 | QuestionAnswerService.update_task_survey_answer |
僅 JWT | 更新答案(寫入);填答者面(assignee) 但未驗 assignee/participant |
/api/1.0/project-survey/answers/<uid>/patch |
POST | api/task_survey/routes/question_answer_route.py:55 | 是 | QuestionAnswerService.patch_task_survey_answer |
僅 JWT | 單題批次 patch(socket/keepalive flush 寫入);填答者面(assignee) 但未驗 |
/api/1.0/project-survey/answers/<uid>/checkpoint |
POST | api/task_survey/routes/question_answer_route.py:85 | 是 | QuestionAnswerService.checkpoint_task_survey_answer |
僅 JWT | 暫存/提交答案(寫入);填答者面(assignee) 但未驗 |
/api/1.0/project-survey/histories |
POST | api/task_survey/routes/question_answer_history_route.py:35 | 是 | QuestionAnswerHistoryService.get_all_question_answer_history |
僅 JWT | POST 實為查詢(讀) |
/api/1.0/project-survey/history/revert |
POST | api/task_survey/routes/question_answer_history_route.py:46 | 是 | QuestionAnswerHistoryService.revert_question_answer_from_history |
僅 JWT | 還原歷史答案(寫入,會 socket emit reload);未驗 participant |
/api/1.0/project-survey/history-details |
POST | api/task_survey/routes/question_answer_history_detail_route.py:21 | 是 | QuestionAnswerHistoryDetailService.get_all_question_answer_history_detail |
僅 JWT | POST 實為查詢(讀) |
GET /api/1.0/survey/import-template(survey_route.py:198)— 純靜態檔下載,無 JWT。GET /api/1.0/task-survey/import-template/<task_uid>(task_survey_route.py:62)— 動態產生含該 task 實際題目/答案選項的 xlsx,無 JWT,任意人帶 task_uid 可下載題庫內容。update_task_survey / update_task_survey_configure / answer 系列 / revert 皆能經 task_survey → task_id 反查所屬專案輪次,但無一處驗證呼叫者是否為該專案 participant 或 assignee。SurveyMenuRoute GET、SurveyRoute GET、SurveyFolderMenuRoute/SurveyFolderRoute GET、SurveysRoute 已列、TaskSurveyRoute GET、TaskSurveysAnswersRoute GET、QuestionAnswerHistoryMenuRoute GET)皆 @jwt_required() 且非 export/download/report,故不納敏感 GET 清單。