Repository navigation
fix(classroom): Google Classroom 共有失敗の本当の原因を表示する (#1175) - #1183
Conversation
…g an assignment Posting an assignment collapsed every non-401/403 Google failure into a bare 502 "Google Classroom API error", so a teacher (and CloudWatch) learned nothing about why the share failed. Google's error.status/message are now parsed, logged (never the access token) and passed through with a stable reason key, and the UI translates each reason into an actionable Japanese message instead of echoing the raw server string. The consent screen also lets a teacher untick classroom.coursework.students, which is required to create course work; the token is now checked with hasGrantedAllScopes and re-requested with prompt=consent, and a 403 drops the cached token. Refs #1175 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
🤖 autopilot status
Linked issue #1175. Maintained by autopilot (single writer); do not edit. |
|
🚀 Preview deployed: https://smalruby.jp/smalruby3-editor/topic/autopilot-1175/ |
再同意のポップアップは最初のクリックから時間が経ってから開くため、ブラウザに ブロックされたり先生が閉じたりしうる。その拒否を googlePermissionDenied として 扱い、GIS の生の英語エラーが UI に出るのを防ぐ。state 不一致 (CSRF の疑い) は この扱いから除外する。 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
[Must] 再同意(
このエラーには 修正内容:
|
|
[Question] 全スコープ必須化により、コース一覧・インポートまで巻き添えでブロックされる(人間の判断に委ねる)
「投稿に必要なスコープを最初から確実に取る」という意図は理解できるし、オール・オア・ナッシングの方が 選択肢:
改修コストは 2 の方が高く(呼び出し側の分岐 + トークンキャッシュを「どのスコープを持つか」付きで |
|
[Question] 新メッセージが「配信(投稿)」前提の文言だが、コース一覧・インポートの失敗でも出る(人間の判断に委ねる)
英語の生文字列よりは明確に改善しているので退行ではありませんが、先生が「配信してないのに?」と |
|
[Question] ドキュメント DoD の取りこぼし(修正済み: 491b156)
どちらも機械的な追従なのでこちらで直しました。 |
|
[FYI]
|
|
[FYI]
|
…lot-1175 fix(classroom): Google Classroom 共有失敗の本当の原因を表示する (#1175)
Summary
課題の「Google Classroom に共有」で
Google Classroom API errorとしか出ず、原因が誰にも(先生にも CloudWatch にも)分からない状態を解消する。
Lambda の Google Classroom プロキシは、401 / 403 以外のすべての失敗を一律 502
「Google Classroom API error」に潰し、Google が返したエラー本文を捨てていた。
今回の報告はまさにこの分岐(= Google は 401/403 以外を返している)。
このPRで:
error.status/error.messageをパースして レスポンスとログに透過(アクセストークンは記録しない)。UI 翻訳用の安定キー
reasonを付与。googleCourseNotFound(コース削除済み / そのコースの先生ではない)googleInvalidRequest(FAILED_PRECONDITION等を含む)googleTokenExpired/googlePermissionDenied)Google の 401 を「クラスのセッション切れ」と誤訳していた分岐も解消。
classroom.coursework.studentsをhasGrantedAllScopesで検証し、不足していればprompt: 'consent'で再要求。403 ではキャッシュ済みトークンを破棄して次回再認可する。原因について(重要・未確定)
prod のログ / AWS 認証にアクセスできないため、Google が返している具体的なステータスは
特定できていない。確実に言えるのは「401 でも 403 でもない」こと(UI の文言から逆算)。
有力候補は 404(ひもづけ先コースが消えた / 共同管理者がその Google Classroom コースの
先生ではない)と 400 系。
本PRは その切り分けを可能にし、かつ有力候補それぞれを先生が自力で直せるメッセージに
するところまでを対象にしている。次に同じ報告が来た時点で(またはこの変更を stg/prod に
反映後に再現してもらえば)
googleStatus/googleMessageから一発で確定できる。確定後に追加の修正が要る場合は別 Issue で扱う。
Changes Made
infra/smalruby-classroom/lambda/handler.tsparseGoogleApiErrorBody()/googleApiErrorResponse()を純粋関数として追加・exportcallGoogleClassroomAPIが失敗時に本文をパースし CloudWatch に記録(トークンは出さない)GoogleAPIErrorにgoogleStatus/googleMessageを保持packages/scratch-gui/src/containers/classroom-error-utils.js—reasonごとの翻訳を追加packages/scratch-gui/src/lib/google-classroom-auth.js— 付与スコープの検証 + 再同意packages/scratch-gui/src/containers/use-google-classroom.js— 403 でもトークン破棄src/locales/ja.js/ja-Hira.js— 新メッセージ 5 件(対で追加)docs/classroom/architecture.md— GC プロキシのエラーレスポンス仕様を追記Test Coverage
infra/smalruby-classroom/lambda/tests/handler-google-error.test.ts(新規 13 件)— パーサの異常系(HTML / 非 JSON / 型違い / 長文切り詰め)とステータス写像
packages/scratch-gui/test/unit/lib/google-classroom-auth.test.js(新規 6 件)— 全許可 / 一部許可→再同意 / それでも不足 / キャッシュしない / 旧 GIS 互換
packages/scratch-gui/test/unit/containers/classroom-error-utils.test.js(+7 件)実行結果: infra 全テスト 328 passed / scratch-gui 該当 2 ファイル 21 passed /
npm run lint(eslint --max-warnings 0 + prettier)クリーン。デプロイ
Lambda 側の変更を含むため、stg / prod への反映は人間が実施(worker は
cdk deployしない)。stg で試す場合は PR に
deploy-stgラベルを付ける。Related Issues
Closes #1175