symfony2基于用户限制模型 - 从symfony1升级

时间:2014-12-01 08:13:03

标签: symfony doctrine

我正在构建一个多租户应用程序。在Symfony1中,我将通过访问用户详细信息和扩展createQuery函数来限制对数据的访问:

class PersonTable extends Doctrine_Table{    
    public function createQuery($alias = '')
    {

        $query = parent::createQuery($alias);

        try {
            $user = sfContext::getInstance()->getUser();
        }catch(Exception $e){
            if ($e->getMessage() == 'The "default" context does not exist.'){
                return $query;
            }else{
                throw $e;
            }
        }
        if ($user->hasGroup('Team1')){
            //all good

        }else if ($user->hasGroup('Team2')){

            $user_id = $user->getGuardUser()->getStaff()->getId();
            $alias = $query->getRootAlias();
            $time = date('Y-m-d H:i:s',time());
            $query->andWhere("$alias.type='type1' and pe.assigned_psw_id");
        }
        $query->orderBy('name asc');

        return $query;
    }
}

我知道在sf1中通过sfContext访问用户对象有缺点,但这种方法似乎优于其他方法,因为你不能“忘记”保护控制器免受错误的用户访问。

如何在Symfony2中实现相同的目标?

1 个答案:

答案 0 :(得分:0)

我已通过以下方式解决了这个问题。

标准化在控制器之间获取EntityRepository的方式:

public function getUserRestrictedRepository($entity, $em = null )
{
    $securityContext = $this->get( 'security.context' );
    if (!$em){
        $em = $this->getDoctrine()->getManager();
    }
    return $em
        ->getRepository( 'MyBundle:' . $entity )
        ->setSecurityContext( $securityContext );
}

添加特征以提供带注入安全性查询的查询:

trait UserRestrictedEntityRepository {

    private $securityContext;

    /**
     * @return mixed
     */
    public function getSecurityContext()
    {
        return $this->securityContext;
    }

    /**
     * @param mixed $securityContext
     */
    public function setSecurityContext($securityContext)
    {
        $this->securityContext = $securityContext;
        return $this;
    }


    /**
     * @return mixed
     */
    public function getUser()
    {
        return $this->getSecurityContext()->getToken()->getUser();
    }


    /**
     * @return mixed
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * @param mixed $name
     */
    public function setName($name)
    {
        $this->name = $name;
    }


    function secureQueryWithUser($alias, $qb)
    {
        $qb->where("1=0");
    }


    function appendOrderBy($qb, $orderBy)
    {
        $first = true;
        foreach ($orderBy as $field => $dir) {
            if (!$dir) $dir = 'asc';
            if ($first) {
                $qb->orderBy('c.' . $field, $dir);
                $first = false;
            }else{
                $qb->addOrderBy('c.' . $field, $dir);
            }
        }
    }


    public function createUnrestrictedQueryBuilder($alias)
    {
        return parent::createQueryBuilder($alias);
    }

    /**
     * Creates a new QueryBuilder instance that is prepopulated for this entity name.
     *
     * @param string $alias
     *
     * @return QueryBuilder
     */
    public function createQueryBuilder($alias, $indexBy=NULL)
    {
        if ($this->getUser()) {

            $qb = $this->_em->createQueryBuilder()
                ->select($alias)
                ->from($this->_entityName, $alias);
            if (isset($this->defaultOrder) && $this->defaultOrder){
                $this->appendOrderBy($qb, $this->defaultOrder);
            }
            if ($this->getUser()->isSuperAdmin()){
                return $qb;
            }else{
                return $this->secureQueryWithUser($alias, $qb);
            }

        }else{
            throw new Exception('Run setUser() before querying ' . $this->getName() .' model.');
        }
    }


    /**
     * Finds all entities in the repository.
     *
     * @return array The entities.
     */
    public function findAll()
    {
        return $this->findBy(array());
    }


    /**
     * Finds entities by a set of criteria.
     *
     * @param array      $criteria
     * @param array|null $orderBy
     * @param int|null   $limit
     * @param int|null   $offset
     *
     * @return array The objects.
     */
    public function findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
    {
        $qb = $this->createQueryBuilder('c');

        foreach ($criteria as $fkey => $fval){
            $qb->andWhere($fkey.' = :'.$fval);
        }
        if ($limit){
            $qb->setMaxResults($limit);
        }
        if ($offset){
            $qb->setFirstResult($offset);
        }
        $query = $qb->getQuery();

        return $query->getResult();
    }
}

在EnityRepository中基于用户访问实现查询添加

class FarmerRepository extends EntityRepository
{
    use UserRestrictedEntityRepository;

    private $name = 'Farmer';

    private $defaultOrder = array('name' => 'asc');


    function secureQueryWithUser($alias, $qb)
    {
        if ($this->getSecurityContext()->isGranted( 'ROLE_CLINIC_ADMIN' )) {
            return $qb
                ->innerJoin("$alias.vet", 'v')
                ->innerJoin("v.clinic", "cl")
                ->innerJoin("cl.VetsOfClinic", "vc")
                ->andWhere('vc.user_id= :userid')
                ->setParameter('userid', $this->getUser()->getId());
        }else if ($this->getSecurityContext()->isGranted( 'ROLE_VET' )){
            return $qb
                ->innerJoin("$alias.vet", 'v')
                ->andWhere('v.user_id= :userid')
                ->setParameter('userid', $this->getUser()->getId());
        }else{
            return $qb
                ->where("$alias.user_id= :userid")
                ->setParameter('userid', $this->getUser()->getId());
        }
    }

}