ポリシーは、特定のオブジェクトの権限を解決するクラスです。権限チェックを適用したいアプリケーションの任意のクラスのポリシーを作成できます。
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フックは決定を行わなかったため、承認メソッドが呼び出されます。