feat: Cookieポリシー同意取得機能を追加 (#6822)#6844
Conversation
ECサイト利用者から第三者提供(アクセス解析等)についてオプトイン同意を取得する機能を コアに追加する。同意状態はCookieで管理し、サーバは読み書きと記録のみを担うDB非依存の構成。 フルページキャッシュ/CDN配下でも破綻しないよう、同意状態に依存する出し分けはクライアント側で行う。 - 同意バナー(全フロントページ)・設定ページ(/cookie-consent)・ポリシーページ(/help/cookie-policy) - 管理画面「店舗基本情報」で機能ON/OFF(option_cookie_consent)+ツールチップ - コア標準GAブロックを同意連動化(ON=同意時のみ読込/OFF=従来どおり無条件・後方互換)。 発火可否はクライアント側ゲートでキャッシュ安全 - 拡張ポイント公開: Twig is_cookie_consent_accepted()、 JSイベント eccube:cookie-consent:changed + getStatus()(コア標準GAローダーも購読) - 同意操作をMonolog専用チャンネル cookie_consent へ記録(info/rotating_file/365日・ fingers_crossed非経由) - 同意CookieはサーバSet-Cookieに一本化(JS側では書き込まない) - フッターに「クッキー設定」リンク(機能ON時のみ) - テスト: PHPUnit(Service/LogService/Extension/Controller) + E2E(Playwright) front-cookie-consent Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthroughEC-CUBE 4.4にCookie同意取得機能を実装。バナー表示・設定ページ・ポリシーページの新規UI、管理画面ON/OFFトグル、CSRFトークン検証付き同意更新API、専用Monologチャンネル、GA遅延ロード連携、PHPUnit/Playwright E2Eテスト一式を完備。 ChangesCookie同意取得機能
Sequence Diagram(s)sequenceDiagram
participant User as ユーザー(ブラウザ)
participant BannerJS as cookie_consent.js
participant Controller as CookieConsentController
participant LogService as CookieConsentLogService
participant CookieService as CookieConsentService
User->>BannerJS: ページロード (DOMReady)
BannerJS->>BannerJS: getStatus() → eccube_cookie_consent Cookie確認
BannerJS-->>User: 未設定ならバナー表示
User->>BannerJS: 同意ボタンクリック
BannerJS->>Controller: POST /cookie_consent/update (consent_status=accepted, _token)
Controller->>Controller: CSRF検証 (403 if invalid)
Controller->>Controller: consent_status値検証 (400 if invalid)
Controller->>LogService: buildLogData() → saveLog()
Controller->>CookieService: saveConsentStatus(response, accepted, request)
CookieService-->>Controller: Set-Cookie: eccube_cookie_consent=accepted
Controller-->>BannerJS: JSON {success: true}
BannerJS->>BannerJS: dispatchChanged(accepted) → eccube:cookie-consent:changed イベント
BannerJS-->>User: バナー非表示
sequenceDiagram
participant Page as フロントページ
participant GATemplate as google_analytics.twig
participant BannerJS as cookie_consent.js
participant GoogleGA as googletagmanager.com
Page->>GATemplate: ページレンダリング
alt optionCookieConsent = OFF
GATemplate-->>Page: gtag.js 即時ロード
Page->>GoogleGA: スクリプト読み込み
else optionCookieConsent = ON
GATemplate-->>Page: loadGoogleAnalytics関数を定義
Page->>BannerJS: getStatus() → accepted?
alt 同意済み (accepted)
BannerJS->>GoogleGA: loadGoogleAnalytics() → 動的スクリプト挿入
else 未同意/拒否
Note over Page: GA読み込みなし
end
Note over BannerJS: eccube:cookie-consent:changed(accepted)受信時
BannerJS->>GoogleGA: loadGoogleAnalytics() → 動的スクリプト挿入
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 4
🧹 Nitpick comments (1)
src/Eccube/Service/CookieConsentLogService.php (1)
82-101: 💤 Low valueスタイルの一貫性:
\DateTimeのインポートを検討Line 92 で
new \DateTime()を使用していますが、ファイル冒頭でuse DateTime;としてインポートすることでコードの一貫性が向上します(PSR-12のベストプラクティス)。現状でも動作に問題はありません。🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/Eccube/Service/CookieConsentLogService.php` around lines 82 - 101, The buildLogData method uses the fully qualified class name \DateTime instead of importing DateTime at the top of the file. Add a use statement for DateTime at the beginning of the file with other imports, then replace the new \DateTime() instantiation in the buildLogData method with new DateTime() to follow PSR-12 style conventions and improve code consistency throughout the CookieConsentLogService.php class.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@html/template/default/assets/js/cookie_consent.js`:
- Around line 55-57: The getStatus() function currently returns the decoded
cookie value without validating it, allowing invalid values to be returned which
can cause unexpected behavior in the banner display logic at lines 73-76. Modify
the getStatus() function to validate that the decoded cookie value matches one
of the valid consent statuses (such as 'accepted' or 'rejected'), and only
return the value if it is valid; otherwise return null to treat invalid cookie
values as unset. This ensures the banner display logic only responds to
legitimate consent states.
In `@html/template/default/assets/scss/style.scss`:
- Line 43: The `@import` statement for "component/10.1.cookie_consent" violates
the Stylelint no-invalid-position-at-import-rule requirement because it is
positioned after CSS rule definitions. Move all `@import` statements to the
beginning of the file, before any CSS rules (such as body, a, pre, and p
selectors). Ensure the file structure has all `@import` statements at the top,
followed by CSS rule definitions, to comply with SCSS standards and Stylelint
rules.
In `@src/Eccube/Resource/template/default/CookieConsent/cookie_consent.twig`:
- Around line 112-127: The code checks if
window.ECCUBE.cookieConsent.saveConsentStatus exists on line 112 but lacks an
else clause to handle the case when this function is undefined or not loaded.
When the save button is clicked and the API is unavailable, users receive no
feedback. Add an else block after the if statement that calls showMessage with
an appropriate error message (similar to the existing error handling in the
callback) to inform users when the consent saving API is not available.
In `@src/Eccube/Service/CookieConsentService.php`:
- Around line 93-111: The `saveConsentStatus()` method lacks defensive
validation of the `$status` parameter and contains a magic number. Add
validation at the start of the method to ensure `$status` is either
`STATUS_ACCEPTED` or `STATUS_REJECTED`, throwing an exception or logging an
error if invalid. Additionally, extract the hardcoded value `86400` (seconds per
day) as a class constant or replace it with a descriptive constant reference to
make the calculation intent explicit and maintainable.
---
Nitpick comments:
In `@src/Eccube/Service/CookieConsentLogService.php`:
- Around line 82-101: The buildLogData method uses the fully qualified class
name \DateTime instead of importing DateTime at the top of the file. Add a use
statement for DateTime at the beginning of the file with other imports, then
replace the new \DateTime() instantiation in the buildLogData method with new
DateTime() to follow PSR-12 style conventions and improve code consistency
throughout the CookieConsentLogService.php class.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 975be2bd-cd88-4b3f-9dec-ee2cc413b718
📒 Files selected for processing (29)
.github/workflows/e2e-test.ymlapp/config/eccube/packages/codeception/monolog.ymlapp/config/eccube/packages/dev/monolog.ymlapp/config/eccube/packages/monolog.ymlapp/config/eccube/packages/prod/monolog.ymle2e/tests/front-cookie-consent.spec.tshtml/template/default/assets/css/style.csshtml/template/default/assets/js/cookie_consent.jshtml/template/default/assets/scss/component/_10.1.cookie_consent.scsshtml/template/default/assets/scss/style.scsssrc/Eccube/Controller/CookieConsentController.phpsrc/Eccube/Entity/BaseInfo.phpsrc/Eccube/Form/Type/Admin/ShopMasterType.phpsrc/Eccube/Resource/locale/messages.en.yamlsrc/Eccube/Resource/locale/messages.ja.yamlsrc/Eccube/Resource/template/admin/Setting/Shop/shop_master.twigsrc/Eccube/Resource/template/default/Block/cookie_consent_banner.twigsrc/Eccube/Resource/template/default/Block/footer.twigsrc/Eccube/Resource/template/default/Block/google_analytics.twigsrc/Eccube/Resource/template/default/CookieConsent/cookie_consent.twigsrc/Eccube/Resource/template/default/CookieConsent/cookie_policy.twigsrc/Eccube/Resource/template/default/default_frame.twigsrc/Eccube/Service/CookieConsentLogService.phpsrc/Eccube/Service/CookieConsentService.phpsrc/Eccube/Twig/Extension/CookieConsentExtension.phptests/Eccube/Tests/Service/CookieConsentLogServiceTest.phptests/Eccube/Tests/Service/CookieConsentServiceTest.phptests/Eccube/Tests/Twig/Extension/CookieConsentExtensionTest.phptests/Eccube/Tests/Web/CookieConsentControllerTest.php
- アップグレード時はoption_cookie_consentをデフォルトOFF(後方互換)、 新規インストールのみインストーラで明示的にON - CSRF失敗時の到達不能なJSON分岐を削除しisTokenValid()単独呼び出しに統一 - 機能OFF時はupdate APIを404に(index()のリダイレクトと挙動を統一) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- getStatus()でaccepted/rejected以外の値はnull(未設定)扱いに正規化し、 改ざん時もバナー再表示・GA非ロードが破綻しないようにする - 設定ページで保存API未ロード時にelseでエラー表示し無反応を防ぐ - Cookie有効期限計算の86400をSECONDS_PER_DAY定数に切り出し Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
GA静的タグ前提の既存テスト(TopControllerTest/admin-basicinfo)が Cookie同意ON既定で破損していたため、新規インストールも含め既定OFFに統一する (既存テストは無修正で通過。RateLimiter等の失敗はリトライ時のキャッシュ汚染による二次被害)。 - 新規インストールの option_cookie_consent=true 明示INSERTを撤回し既定OFFに統一 (Entity default false のまま。店舗が管理画面でONにするまで一切動作しない後方互換) - BaseInfoのコメントをオプトイン方針に更新 - E2E front-cookie-consent: - ToggleSwitchの操作をlabelクリック方式へ(input非表示でcheck/uncheckが失敗する問題) - 既定OFF化に伴いバナー検証ブロックにbeforeAllで機能ON・afterAllで既定OFF復帰を追加 - 設定ページ保存のレースをexpect.pollで解消 - 各afterAllを既定(OFF)復帰へ修正 ローカルE2E(front-cookie-consent 15件)通過を確認。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
機能OFF時404テストのassertSameに失敗時デバッグ用のレスポンス内容を追加 (AssertSameResponseCodeWithDebugContentsRector。同ファイルの他assertと統一) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## 4.4 #6844 +/- ##
==========================================
+ Coverage 74.78% 74.97% +0.19%
==========================================
Files 463 467 +4
Lines 24029 24125 +96
==========================================
+ Hits 17970 18088 +118
+ Misses 6059 6037 -22
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
概要
Issue #6822 の実装。EC サイト利用者から、アクセス解析等のための Cookie 利用(第三者提供)についてオプトイン同意を取得する機能をコア(
src/Eccube)に追加します。同意状態の真実は Cookie に一元化し、サーバは Cookie の読み書きと操作記録(ログ)のみを担う DB 非依存の軽量構成です。フルページキャッシュ/CDN 配下でも破綻しないよう、同意状態に依存する出し分けはすべてクライアント側で行います。
Closes #6822
実装内容
フロント
/cookie-consent(ログイン不要・会員/ゲスト両対応)/クッキーポリシーページ/help/cookie-policy(汎用ひな型)管理画面
dtb_base_info.option_cookie_consentBOOLEAN, defaulttrue)+ヘルプマーク(ツールチップ)アクセス解析(GA)連動
ga_id未設定は一切出力なしis_cookie_consent_accepted()、クライアント側 DOM イベントeccube:cookie-consent:changed+window.ECCUBE.cookieConsent.getStatus()。コア標準 GA ローダー自身もこの公開フックを購読(コア改変なしで他タグを連動可能)バックエンド/記録
CookieConsentService(Cookie 読み書き・判定)/CookieConsentLogService(Monolog 専用チャンネルcookie_consentへ記録・ベストエフォート)/CookieConsentController(設定・ポリシー表示、更新 API)/CookieConsentExtension(Twig 判定関数)fingers_crossed非経由・rotating_file・level: info・max_files: 365(prod/dev/codeception)。prod で info 証跡が消えない設計Set-Cookieのみで設定(JS 側では Cookie を書かない)。Secure 等の属性はRequest::isSecure()に統一。CSRF 検証必須テスト
CookieConsentService/CookieConsentLogService/CookieConsentExtension/CookieConsentController(会員ログイン経路・CSRF 不正値 400 含む)front-cookie-consent.spec.ts(matrixfront-cookie-consent登録): バナー同意/拒否/閉じる・再表示、設定/ポリシーページ、フッター導線、管理 ON/OFF、GA 連動(ON 未同意=未読込/同意でリロードなし読込/拒否=未読込/OFF=無条件/ga_id 未設定=出力なし)、CSRF 不正 403補足
option_cookie_consentは単純なカラム追加のため Entity 属性+doctrine:schema:updateで反映(マイグレーション不要。GA 機能 PR Googleアナリティクス機能を追加 #4912 と同方針)。新規インストールはLoadDataFixturesEccubeCommandの INSERT で DB default(true)=機能 ON🤖 Generated with Claude Code
Summary by CodeRabbit
リリースノート