sklinet-nette/authorizator

Nette(类似Symfony)的投票者(Voter)实现

0.1.1 2020-07-23 10:00 UTC

This package is auto-updated.

Last update: 2024-09-12 19:49:09 UTC


README

此授权系统与Symfony投票者(Voters)的工作方式相同。

如何在Nette应用程序中使用

  • 在 config.neon 中注册扩展
    extensions:
      authorizator: SklinetNette\Authorizator\Di\AuthorizatorExtension
    

如果您想创建一个投票者(Voter)类

  • 创建一个新的需要实现接口 SklinetNette\Authorizator\Security\Voter\IVoter 或继承类 SklinetNette\Authorizator\Security\Voter 的投票者类
<?php
namespace App\Security\Voter;

use App\Entity\Article;
use SklinetNette\Authorizator\Security\Voter\Voter;

/**
 * Class Article
 *
 * @package App\Security\Voter
 */
class ArticleVoter extends Voter
{
    const EDIT = 'edit';
    const CREATE = 'create';

    protected function supports(string $attribute, $subject): bool
    {
        if ( ! in_array($attribute, [self::EDIT])) {
            return false;
        }

        if ( ! $subject instanceof Article) {
            return false;
        }

        return true;
    }

    protected function voteOnAttribute(string $attribute, $subject, \Nette\Security\User $securityUser): bool
    {
        //or you can get user entity with entity manager
        if ( ! $securityUser->getId()) {
            return false;
        }

        ////////////////////////////////////////////////////////
        switch ($attribute) {
            case self::EDIT:
                return $this->canEdit($subject, $user);
            default:
                return false;
        }
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    /**
     * @param  \App\Entity\Article  $article
     * @param  \Nette\Security\User $securityUser
     *
     * @return bool
     */
    private function canEdit(Article $article, \Nette\Security\User $securityUser): bool
    {
        if ($securityUser->getId() == $article->getUser()->getId()) {
            return true;
        }

        return false;
    }
}
  • 在 config.neon 中将投票者注册为一个服务
services:
   ArticleVoter:
      class: App\Security\Voter\ArticleVoter
  • 在表示器(Presenter)中使用特性 SklinetNette\Authorizator\Traits\AuthorizatorTrait 或服务 SklinetNette\Authorizator\Authorizator
  • 这两个类都有 isGranted 方法
  • 方法 isGranted(string $attribute, mixed $subject) 接受两个参数。第一个参数 attribute -> 用户可以对资源(编辑、创建等)做什么,第二个参数是资源 -> 资源可以是任何东西(doctrine 实体、字符串、数组、对象等)

    class ArticlePresenter extends \App\Presenters\BasePresenter
    {
      use AuthorizatorTrait;
        
      ...
    
      public function actionEdit($id)
      {
          /** @var \App\Entity\Article $article */
          $article = $this->em
              ->getRepository(Article::class)
              ->findOneBy(['id' => (int)$id]);
    
          if ($this->isGranted('edit', $article)) {
              $this->error();
          }
           
          ...
      }
    }
    
  • 在 Latte 模板中,您可以使用接受与特性方法 isGranted 相同参数的函数 isGranted

<a n:if="isGranted('edit', $article)" role="button" class="btn">
    ...
</a>