crafted by Mize ↗
Open Repository Intelligence Open Repository Intelligence
CodeLens ACTIVE
CodeLens Engine
StatusOnline
Versionv0.4
ModelClaude Sonnet
Latency—
0
GOOD
改善余地があります
mize1978/rewardme
ゲームとしての完成度への情熱は伝わるが、スコアをクライアントから丸ごと信頼するガチャ経済圏は「チート歓迎」と書いてあるようなもの——コインの価値を守りたければ今すぐサーバー側検証を実装せよ。
⭐ 2 Stars
·
🍴 0 Forks
·
📝 192 Commits
·
💬 0 Issues
·
🔵 CSS
·
Rails
🔍 重要ファイル 11 件を精査 全 345 ファイル中 AI が優先度順に選択
0
✦ 品質
0
🛡 セキュリティ
0
⚙ 保守性
📋 概要

Ruby on Rails 7 + Hotwire(Turbo/Stimulus)で構築された育成型タスク管理Webアプリ。タスク完了でキャラクターが成長し、ガチャ・ミニゲーム・マイルームなどゲーム要素を多数実装している。

🎯 今すぐ直すべき3点
  1. app/controllers/games_controller.rb GACHA_POOLなどのゲームロジック定数をコントローラから分離し、app/services/gacha_service.rbまたはapp/models/gacha_pool.rbに移動する。コントローラが肥大化しており、単一責任原則に違反している
    ↗
  2. app/controllers/games_controller.rb tap_game_resultアクションのscore受け取り部分(params[:score].to_i.clamp(0, 999))はサーバー側でスコアを再計算せずクライアント値を信頼しているため、改ざんによるコイン不正取得が可能。ゲームセッションIDとサーバー側スコア検証ロジックを追加する
    ↗
  3. app/javascript/controllers/match_game_controller.js / tap_game_controller.js / puzzle_controller.js 各ゲームコントローラが500行超の巨大ファイルになっている可能性が高い(提供コードだけで既に切れている)。ゲームロジック・UI更新・通信処理を別モジュールに分割し、Stimulusコントローラは薄いオーケストレーター層に留める
    ↗
🔍 検出された問題 (7件)
🟥 Critical 📄 app/controllers/games_controller.rb
クライアント送信スコアをそのままコイン計算に使用
games_controller.rbのtap_game_resultアクションがparams[:score]をclampするだけでサーバー側検証なしにコインを付与している。ブラウザのDevToolsやcurlで任意のスコアを送信すれば上限999コインを毎回不正取得できる。ゲーム経済圏全体が崩壊するリスクがある
🟥 Critical 📄 app/controllers/games_controller.rb
ゲームコントローラに巨大なビジネスロジックが集中
games_controller.rbにGACHA_POOL定数・抽選ロジック・コイン計算・スコア処理が混在している。単一ファイルが複数の責務を持つことでテストが困難になり、バグ修正時の影響範囲が読めない。ガチャ不正や確率操作のバグが発見しにくくなる
🟧 Warning 📄 Gemfile
テストコードが存在しない
Gemfileにrspec-railsやminitestのテスト用gemが含まれておらず、group :development, :testにはdebugのみ。ガチャ確率・コイン計算・レベルアップロジックなどゲーム経済に直結するロジックが無テストで運用されており、リグレッションを検知できない
🟧 Warning 📄 app/javascript/controllers/match_game_controller.js
Stimulusコントローラが巨大化・責務過多
match_game_controller.js・tap_game_controller.js・puzzle_controller.jsがそれぞれゲームロジック・タイマー管理・API通信・DOM操作を1ファイルに詰め込んでいる。提供コードだけで既に切れており500行超が予想される。バグ特定・機能追加のコストが高く、Stimulusの設計思想(薄いコントローラ)に反している
🟧 Warning 📄 app/controllers/games_controller.rb
公開エンドポイントにレート制限なし
tap_game_result・gacha pullなどのPOSTエンドポイントにRack::Attackやrails-rate-limiterによるレート制限が確認できない。tap_game_played_today?チェックはあるが、並列リクエストによるレースコンディションでの二重付与や、他エンドポイントへのブルートフォースが可能
🟧 Warning 📄 app/javascript/controllers/ribbon_controller.js
ribbon_controller.jsに大量のハードコードされた文字列定数
ribbon_controller.jsのROOM_MESSAGESとSPECIAL_COMBOSが数百行のJavaScriptハードコード文字列として存在する。コンテンツ変更のたびにJSファイルを編集・デプロイが必要で、将来の多言語化や動的コンテンツ管理が困難になる
🟨 Suggestion 📄 app/javascript/controllers/puzzle_controller.js
puzzle_controller.jsのfetch catch節がサイレント握りつぶし
selectPuzzle関数のcatch節が} catch { /* silent */ }となっており、ネットワークエラーやサーバーエラーをユーザーに通知しない。パズル選択が失敗してもユーザーが気づかず、意図しない画像でゲームが進行する可能性がある
✅ 良い点
  • Dockerfileがマルチステージビルド(builder/runtime分離)を採用しており、ビルド時のARG SECRET_KEY_BASE=dummyが最終イメージに残らない設計になっている点がセキュリティ上適切
  • app/models/letter.rbがActiveRecordを使わずPORO(Plain Old Ruby Object)としてカタログデータを管理しており、DBスキーマを汚染せずにコンテンツを追加できる設計が保守性に優れている
  • games_controller.rbのtap_game_resultでparams[:score].to_i.clamp(0, 999)によりスコアの上限値を制限しており、最低限の入力サニタイズが行われている

作り切ることが第一歩。改善を続けることがエンジニアリング。

🔧 リファクタ提案
  • app/services/gacha_service.rbを作成し、GACHA_POOL定数・重み付き抽選ロジック・コイン付与処理をGamesControllerから分離する。コントローラはGachaService.new(current_user).pull(count)を呼ぶだけにする
  • app/javascript/controllers/match_game_controller.jsのゲームロジック(タイル生成・マッチ判定・スコア計算)をapp/javascript/games/match_game_engine.jsとして純粋なJSクラスに抽出し、StimulusコントローラはイベントハンドリングとDOM更新のみに専念させる
  • ribbon_controller.jsのROOM_MESSAGESをRailsのI18nまたはJSON APIエンドポイント(/api/room_messages)として提供し、JSバンドルサイズを削減するとともにコンテンツ管理をサーバー側に集約する
🔒 セキュリティ注意点
  • tap_game_result・match_game_result等のスコア送信エンドポイントはサーバー側でゲームセッションを発行し(ゲーム開始時にsession[:game_token]を生成)、結果受信時にトークン検証とサーバー側スコア上限チェックを行うことで改ざんを防ぐ必要がある
  • Rack::Attackをconfig/initializers/rack_attack.rbで設定し、/games/*_resultへのPOSTを1ユーザー/分あたり5リクエスト以下に制限することで、レースコンディションによるコイン二重付与とブルートフォースを防ぐべき
📤 PRコメント出力

このレビューをGitHub PRコメントとして貼り付けられるMarkdown形式で出力します。