PowerCMS XのAPIを利用した画面で下書きプレビューができない場合の対応

公開

ReactとPowerCMS XのAPIを利用して画面を表示しているのですが、PowerCMS X編集画面でステータスが公開ではないもの(下書き等)をプレビューした時にその画面が正しく表示されないことに気付きました。これはAPIの認証を通さずにオブジェクトをListないしGetしていることが原因です。

対応策1: authenticationエンドポイントで認証を通す

最初に考えられる対応策は、素直にAPIで認証を通すことです。手軽なのですが、この方式の欠点として以下のような点が挙げられます。

  • API専用ユーザーとユーザーに紐付ける権限を作成・管理する必要がある
  • プレビュー画面、もしくはJavaScript内に認証情報を記述する必要がある

対応策2: プラグインでカスタマイズをする

対応策1の欠点を回避する方法はないかと探ってみたところ、プレビュー画面で発生したAPIリクエストにおいても管理画面のセッション情報が渡っていることに気付きました。(ブラウザの仕様です。)これを利用して追加の認証をすることなくステータスが公開でないものを含めることができるようにしました。

具体的には、listエンドポイントの場合、pre_litingコールバックの処理で認証済か否かを判断してstatusカラムの取得条件を変えるようにしました。is_loginメソッドでログイン判定はできるのですが、userメソッドの返値は空でしたのでセッションモデルの情報を確認するようにしています。

public function pre_listing_short_video(&$cb, $app, &$terms, &$args, &$extra) {
    if ($app->id === 'RESTfulAPI') {
        if ($app->is_login()) {
            $cookie = $app->cookie_val($app->cookie_name);
            $session = $app->db->model( 'session' )->load(
                ['name' => $cookie, 'kind' => 'US', 'key' => 'user'],
                ['limit' => 1],
            );
            
            if (count($session) === 1 && $session[0]->expires >= $app->request_time) {
                $user = $app->db->model('user')->load((int) $session[0]->user_id);
                if ($user) {
                    $max_status = $app->max_status($user, 'short_video', $app->workspace_id);
                    $terms['status'] = ['<=' => $max_status];
                }
            }
        }
    }
}

これで下書き等のオブジェクトがAPIのレスポンスに含まれるようになりました。

まとめ

利用しているエンドポイントを整理した上でカスタマイズを実施すると、authenticationエンドポイントで認証を通さなくてもプレビュー対応可能なことが分かりました。私の場合、getエンドポイントで取得できる情報はAPIを利用せずあらかじめ静的JSONファイルを出力するようにしていたため、対応が容易になりました。