承認者以外に公開権限を渡さずにDrupal予約公開を実現する方法
Drupalで大企業サイトを構築する際、コンテンツの承認ワークフローと予約公開機能を組み合わせたいという要件は頻出します。
ところが実際に構築を進めると、「予約公開を動作させるには対象ユーザーに公開権限が必要」というDrupal本来の仕様が、「編集者には公開権限を持たせず、承認者のみが公開できる」という承認ワークフローの前提と、直接的な矛盾として顕在化するケースがあります。
本記事では、Drupal導入初期のエンジニアや、承認フローを厳格に運用したいWeb担当者の方向けに、この権限衝突の発生メカニズム、実プロジェクトで採用される回避策、そして中長期的な権限設計の改善方向について整理します。
目次
発生する問題の整理
承認ワークフローの一般的な要件
大企業サイトでは、コンテンツ更新に対して以下のような責任範囲の分離が求められます。
- 編集者:下書き作成・修正のみ実施
- 承認者(上長・広報など):内容確認と公開判断
- 最上位管理者:ワークフロー自体の設計と例外対応
Drupalでは、Content ModerationモジュールとWorkflowsモジュールを組み合わせ、Draft(下書き)→ Needs Review(レビュー中)→ Published(公開)といった状態遷移で標準化するのが定石です。
予約公開の要件
一方、大量のコンテンツを扱うサイトでは、日時指定での自動公開が欠かせません。Drupalでは Scheduler モジュールが広く使われており、指定日時に cron 経由で自動的に公開状態へ切り替える仕組みを提供します。
両者を組み合わせたときの衝突
ここで問題になるのは、権限が複数のレイヤーにまたがって関わってくる点です。Schedulerのcron処理は「匿名ユーザー(uid 0)」のコンテキストで実行されます。Webから cron URL を叩く方式でも、Drush で実行する方式でも、既定では特定の管理ユーザーとして走るわけではありません。この前提を押さえておかないと、後述する回避策の意味が分かりにくくなります。そのうえで、Content Moderationの状態遷移を伴う場合は、その遷移を許可する権限が別途必要になります。また、予約日時を入力するフィールド自体の表示・編集にも、フィールド単位の権限設定が関係します。
つまり、「編集者にcron実行権限がないから動かない」という単純な話ではなく、予約フィールドへのアクセス権限、状態遷移権限、公開権限という複数の権限が噛み合わなければ、予約公開の設定ができない、あるいは設定はできても意図通りに公開まで進まないという事象が起こります。
承認ワークフローの前提では、編集者に公開権限や公開に至る遷移権限を持たせない設計が理想ですが、この状態では編集者が予約日時を設定してもスケジュールが機能しない、あるいは設定画面自体が表示されないという状態に陥ります。結果として、「承認は通したが公開日時の指定は承認者に依頼する」といった運用が発生し、工数が増える構図となります。
問題が顕在化する順番
実プロジェクトで見られる典型的な発生の流れは次の通りです。
- 要件定義段階では「承認ワークフロー」と「予約公開」の両方が要件に並ぶが、権限モデルとしては別々に検討される
- 構築段階でContent ModerationとSchedulerを個別に導入し、単体では正常に動作する
- 結合テストで、編集者アカウントに予約公開フィールドが表示されない、あるいは表示されても保存後に反映されないことが判明する
- Schedulerが提供する予約公開用パーミッション(バージョンやコンテンツタイプ別設定により名称が異なる場合があるため、管理画面のパーミッション一覧(admin/people/permissions)で要確認)を編集者に付与しても、公開権限や状態遷移権限を持たないため、cron実行時に公開処理がスキップされる
- 権限の見直しか、運用フローの見直しかの二択を迫られる
この分岐点で採用される対処法によって、その後の運用負荷が大きく変わります。
実務での回避策
サービスアカウントによる実行コンテキストの切り替え
もっとも直接的な回避策は、cronによる予約公開処理を、公開権限を持つ専用のサービスアカウントで実行するようカスタムモジュールで介入する方法です。
具体的には、Schedulerが提供するイベントサブスクライバに処理を追加し、公開実行時のコンテキストユーザーを一時的に切り替えます。ただし、対応バージョンによってイベントの定義方法が異なるため、導入時はモジュールのCHANGELOG.mdおよびDrupal.org公式ドキュメントで、利用中のバージョンのイベント名・クラスを必ず確認してください。編集者は予約日時の入力のみを行い、実際の公開処理は権限を持つ別ユーザーが担う構造です。
実行コンテキストの切り替えには、Drupalコアが提供するAccountSwitcherInterface(\Drupal\Core\Session\AccountSwitcherInterface)のswitchTo()とswitchBack()を用いることが推奨されます。これにより、処理の前後でユーザーコンテキストを安全に入れ替え、元のコンテキストへの復帰漏れを防ぐことができます。
ただし、この方式にはいくつかの注意点があります。
- 監査ログ上の「公開実行者」がサービスアカウントになるため、承認者との紐づけを別途保持する必要がある
- Content Moderationの状態遷移との連動を明示的に実装しないと、ワークフロー状態と公開状態が乖離する
- Drupalコアやモジュールのバージョンアップ時に、イベントサブスクライバの動作を再検証する工数が発生する
承認プロセスに予約日時を組み込む方式
もう一つの現実解は、予約日時を承認プロセスの一部として扱う設計です。編集者は下書き作成と希望公開日時の入力までを担当し、承認者がレビュー時に予約日時を確定し、承認と同時に予約公開をセットします。
この場合、予約公開の権限は承認者以上に限定されるため、Drupal本来の仕様と矛盾しません。ただし、承認者の作業項目が増えるため、運用フロー側での標準化と、UI上での希望日時と確定日時の区別が必要になります。
Content Moderation対応版Schedulerの活用
Schedulerモジュールとは別に提供されているコントリビュートモジュール「Scheduler Content Moderation Integration」(scheduler_content_moderation_integration、以下 SCMI)を利用すると、状態遷移として「予約日時に達したらPublishedへ遷移」を定義できます。遷移権限の設計により、編集者が「Needs Review」への遷移に予約日時を付与し、承認者の承認をトリガーに予約が有効化されるといった構造も設計できます。
ただし、このモジュールを入れれば権限設計だけで解決する、とは言えません。 SCMI は「予約日時に設定した遷移を、その場でユーザーが実行できるか」を保存時とcron実行時にチェックします。そのため「公開への遷移権限を持たない編集者が、公開予約だけは設定できる」という要件は、素の状態では成立しません。編集者が予約日時を入れて保存しようとすると、遷移権限が無いというバリデーションエラーで弾かれます。
実案件(弊社で構築したコーポレートサイト)では、この要件を満たすために SCMI 側の権限チェックを無効化する対応を取りました。具体的には次の3箇所です。
- 遷移権限チェックの戻り値を
AccessResult::forbidden()からAccessResult::neutral()に変更 - ユーザーの遷移権限による、予約公開の選択肢フィルターを無効化
- 保存時の遷移権限バリデーション(
TransitionAccessConstraintValidator)を無効化
これは権限チェックの意図的な無効化であり、採用する場合はセキュリティ上のトレードオフを明示的に受け入れる必要があります。 ワークフロー権限を厳格に設計しても、予約公開経路ではその制限が効かなくなるためです。また、コントリビュートモジュールを改変するため、バージョンアップのたびに同じ改変を再適用し、予約公開の動作を再検証する運用が必要になります。
要件として「編集者に予約公開だけを許可する」を通す場合は、この改変コストと権限上のリスクを見積もりに含めてください。厳格な権限分離を優先するなら、「承認者が予約日時を確定する」方式のほうが素直です。
なお、SCMI のメンテナンス状況やバージョン互換性は変動するため、導入前にDrupal.orgのプロジェクトページで最新のリリース情報および対応バージョン(Drupal 10 / 11、Scheduler 2.x系との組み合わせ)を必ず確認してください。また、遷移権限とフィールド権限の設計項目が増えるため、初期構築時の設計工数は増加します。
権限設計の改善方向
短期的には上記の回避策で対応可能ですが、中長期では以下の観点で権限設計を見直すことが望まれます。
- 責任分界の明文化:予約日時の入力責任と公開実行責任を分けて定義する
- ロールの粒度:編集者・レビュアー・承認者・公開実行者を分離し、必要に応じて統合する
- 自動化ユーザーの定義:cronやAPI経由の処理を担う専用のサービスアカウントを標準化し、監査ログ上で識別可能にする
- 変更管理:Drupalおよび関連モジュールのバージョンアップ時に、権限マトリクスの再検証をリリースプロセスに組み込む
- 改変箇所の管理:コントリビュートモジュールを改変して要件を満たした場合は、改変箇所をコード上のマーカーコメントと運用ドキュメントの両方に記録し、バージョンアップ手順に「改変の再適用」を必須ステップとして組み込む
大企業サイトでは、これらを最上位管理者が管理するドキュメントとして整備し、運用フェーズでの属人化を防ぐことが重要です。
まとめ
Drupalの予約公開と承認ワークフローの併用は、単純な機能追加ではなく、権限モデルの再設計を伴う課題です。「予約公開には公開権限や状態遷移権限が必要」という仕様を前提として、以下のいずれかを選択する必要があります。
- サービスアカウントによる代理実行で権限衝突を回避する
- 予約日時の設定を承認者側の作業に組み込む
- Content Moderation連携で状態遷移として予約公開を扱う(ただし、編集者に公開遷移権限を渡さないまま予約公開を許可する場合は、モジュール側の権限チェックへの介入が必要)
いずれの方式にも初期構築および運用上のトレードオフがあるため、要件定義の段階で運用フローと権限設計を同時に検討することが、後工程での手戻りを抑える鍵となります。
よくある質問(FAQ)
Q. Scheduler モジュール以外で予約公開を実現する選択肢はありますか。
Content Moderation の状態遷移をcronで発火させる自前実装や、外部ジョブスケジューラからのAPI呼び出しといった選択肢もあります。ただし、いずれも監査ログや権限モデルの整合性を別途設計する必要があるため、標準モジュールとの差分を明確にした上で選定することを推奨します。
Q. サービスアカウントで公開処理を代行する方式は、監査要件に抵触しませんか。
監査要件によります。実際の承認者と実行アカウントが乖離するため、承認記録と公開ログを紐づけて保持する仕組みを併設することで、多くの内部統制要件には対応可能です。監査部門との事前すり合わせを推奨します。
Q. 既存サイトで承認ワークフローを後から追加する場合、権限設計はどこから着手すべきですか。
まず現状のロールと付与されている権限を棚卸しし、責任分界を可視化することから始めるのが安全です。その上で、予約公開・多言語・メディア管理など、権限に影響する機能ごとにあるべき状態を定義し、段階的に移行する計画を立てることで、運用中の調整を最小化できます。
LYZONが提供するWebサービス
Webに関するお悩みは、まずLYZONへ
構築・運用・AIまで、Webに関わる課題をワンストップで対応。まず何ができるかをご覧ください。
2025年に中途未経験採用でLYZONに入社。
東京に引っ越してきてから色んなサウナに行くことにハマっている。