🔖

Payloadにおける権限制御についてコンテンツ公開・削除権限の制御を実装して理解する

に公開

はじめに

Payloadにおける権限制御は、他のCMSにあるような管理画面での権限設定ではなく、すべてコードで行います。コンテンツの作成・閲覧・更新・削除・バージョン履歴の閲覧など、操作ごとの権限を制御することが可能です。

この記事では、Payloadにおける権限制御について理解するために、コンテンツ公開・削除権限の制御を実装してみたいと思います。

前提

下書き・バージョン管理機能が有効化されているコレクションに、コンテンツ公開・削除権限の制御を実装する前提で解説します。下書き・バージョン管理機能の設定については、下記の記事をご参照ください。

https://zenn.dev/ksk1kd/articles/0634148d336e22

Payloadにおける権限制御の考え方

Payloadの権限制御はコードで行うため、実装の仕方は多様です。ただし、公式ドキュメントではユーザーのロールに基づいた権限制御方法について解説があり、それに従うのが無難だと考えています。標準ではPayloadのユーザーはロールを持たないため、まずはユーザーにロールフィールドを追加する作業が必要です。その上で、ユーザーが持つロールに基づいた権限制御のコードを実装する流れとなります。

公式のロールに基づく権限制御の解説については、下記のページをご参照ください。

https://payloadcms.com/docs/admin/overview#role-based-access-control

ユーザーコレクションにロールフィールドを追加

はじめに、ユーザーコレクションにロールフィールドを追加します。この記事の例では、下記3つのロールを用意したいと思います。

  • 編集者
    • コンテンツの下書き作成・編集のみ可能
  • 承認者
    • コンテンツの下書き作成・編集に加え、公開と削除も可能
  • 管理者
    • 承認者と同じ

上記のロールをユーザーコレクションにフィールドとして追加するための設定が下記です。src/collections/Users/index.tsで定義しているユーザーコレクションのfieldsキー配下の配列に追加します。

src/collections/Users/index.ts
  // ...
  fields: [
    // ...
    {
      name: 'roles',
      type: 'select',
      options: [
        {
          label: {
            en: 'Editor',
            ja: '編集者',
          },
          value: 'editor',
        },
        {
          label: {
            en: 'Approver',
            ja: '承認者',
          },
          value: 'approver',
        },
        {
          label: {
            en: 'Administrator',
            ja: '管理者',
          },
          value: 'administrator',
        },
      ],
      hasMany: true,
    },
    // ...

上記の設定により、下記キャプチャのように各ユーザーの編集画面にロールフィールドのフォームが表示されます。ユーザーのロールは複数選択できるよう設定しています。

ユーザー編集画面のロールフィールドのフォーム

コレクション設定に権限制御処理を追加

次に、コレクション設定に権限制御処理を追加します。

下記が、管理者と承認者のロールのみがコンテンツを公開・削除できるようにするためのコードです。下書き・バージョン管理機能が有効化されているコレクションの設定に追加することで機能します。

  // ...
  access: {
    // ...
    update: ({ req, data }) => {
      if (!req.user?.roles) return false

      if (data?._status === 'published') {
        return req.user.roles.some((role) => ['administrator', 'approver'].includes(role))
      }

      return true
    },
    delete: ({ req }) => {
      if (!req.user?.roles) return false

      return req.user.roles.some((role) => ['administrator', 'approver'].includes(role))
    },
  },
  // ...
})

accessキー配下が権限制御の設定で、updateキー配下がコンテンツの更新、deleteキー配下がコンテンツの削除に関するものです。コンテンツの更新については、コンテンツのステータスがpublishedの場合、管理者と承認者のみが更新できるよう制御しています。

動作確認

以上の設定・実装によりどのような挙動になるのか動作確認をします。

動作確認のために、下記の通り各ロールを持つサンプルユーザーを作成します。

各ロールを持つユーザーの一覧

まずは、すべての権限を持つ承認者・管理者ロールのユーザーでログインして管理画面を見てみます。前述で権限制御処理を追加したコレクションのコンテンツ編集画面を見ると、画面右上に「Save Draft」ボタン、「Publish changes」ボタン、そしてケバブメニュー(3点リーダのメニュー)内に「Delete」が表示されています。これらをクリックするといずれもエラーなく機能します。

承認者・管理者ロールで見たコンテンツ編集画面

次に、編集者ロールのユーザーでログインして管理画面を見てみます。同じように前述で権限制御処理を追加したコレクションのコンテンツ編集画面を見ると、「Publish changes」ボタンとケバブメニュー内の「Delete」が表示されていません。Paylaodでは操作権限のないUIは表示しない仕組みになっています。

編集者ロールで見たコンテンツ編集画面

以上で、コンテンツ公開・削除の権限を問題なく制御できていることを確認できました。

まとめ

この記事では、Payloadにおける権限制御について理解するために、コンテンツ公開・削除権限の制御を実装してみました。この記事では更新・削除の権限制御のみ実装しましたが、同じ仕組みで作成・閲覧・バージョン履歴の閲覧なども制御可能です。コードで制御することで柔軟に実装でき、複雑な権限制御の要件にも対応できる仕組みになっていると感じました。

参考

https://payloadcms.com/docs/access-control/overview

Discussion