ポリシー

ポリシーは、特定のオブジェクトの権限を解決するクラスです。権限チェックを適用したいアプリケーションの任意のクラスのポリシーを作成できます。

ポリシーの作成

src/Policyディレクトリにポリシーを作成できます。 ポリシークラスには、実装が期待される共通の基本クラスまたはインターフェースがありません。アプリケーションクラスは、一致するポリシークラスに「解決」されます。ポリシーの解決方法については、ポリシーリゾルバーセクションを参照してください。

通常、ポリシーはsrc/Policyに配置し、Policyクラスのサフィックスを使用します。ここでは、アプリケーションでArticleエンティティのポリシークラスを作成します。src/Policy/ArticlePolicy.phpに次のコンテンツを追加します:

<?php
namespace App\Policy;

use App\Model\Entity\Article;
use Authorization\IdentityInterface;

class ArticlePolicy
{
}

エンティティに加えて、テーブルオブジェクトとクエリはポリシーを解決できます。 クエリオブジェクトのrepository()メソッドが呼び出され、テーブル名に基づいてポリシークラスが生成されます。 App\Model\Table\ArticlesTableのテーブルクラスは、App\Policy\ArticlesTablePolicyにマップされます。

ポリシーメソッドの記述

先ほど作成したポリシークラスは、現時点ではあまり機能しません。 ユーザーが記事を更新できるかどうかを確認できるメソッドを定義しましょう:

public function canUpdate(IdentityInterface $user, Article $article)
{
    return $user->id == $article->user_id;
}

ポリシーメソッドは、成功を示すためにtrueまたはResultオブジェクトを返す必要があります。 他のすべての値は失敗として解釈されます。

認証されていないユーザーを処理する場合、ポリシーメソッドは$userパラメーターにnullを受け取ります。 匿名ユーザーのポリシーメソッドを自動的に失敗させる場合は、IdentityInterfaceタイプヒントを使用できます。

ポリシー結果オブジェクト

ブール値に加えて、ポリシーメソッドはResultオブジェクトを返すことができます。 Resultオブジェクトにより、ポリシーが成功/失敗した理由についてより多くのコンテキストを提供できます:

use Authorization\Policy\Result;

public function canUpdate(IdentityInterface $user, Article $article)
{
    if ($user->id == $article->user_id) {
        return new Result(true);
    }
    // Results let you define a 'reason' for the failure.
    return new Result(false, 'not-owner');
}

trueでない戻り値またはResultInterfaceオブジェクトは失敗と見なされます。

ポリシーのスコープ

ポリシーは合格/不合格の認証チェックを定義できるほか、「スコープ」も定義できます。 スコープメソッドを使用すると、承認条件を適用して別のオブジェクトを変更できます。 これの完璧な使用例は、リストビューを現在のユーザーに制限することです:

namespace App\Policy;

class ArticlesPolicy
{
    public function scopeIndex($user, $query)
    {
        return $query->where(['Articles.user_id' => $user->getIdentifier()]);
    }
}

ポリシーの前提条件

一部のポリシーでは、ポリシー内のすべての操作に共通のチェックを適用したい場合があります。 これは、提供されたリソースに対するすべてのアクションを拒否する必要がある場合に役立ちます。 前提条件を使用するには、ポリシーにBeforePolicyInterfaceを実装する必要があります:

namespace App\Policy;

use Authorization\Policy\BeforePolicyInterface;

class ArticlesPolicy implements BeforePolicyInterface
{
    public function before($user, $resource, $action)
    {
        if ($user->getOriginalData()->is_admin) {
            return true;
        }
        // fall through
    }
}

beforeフックは次の3つの値のいずれかを返すことが期待されています:

  • true ユーザーはアクションを続行できます。
  • false ユーザーはアクションを続行できません。
  • null beforeフックは決定を行わなかったため、承認メソッドが呼び出されます。