add a ScopePickerType and a UserPickerType

Those type allow easily to

- pick a Scope/circle in form
- pick a user in form
This commit is contained in:
Julien Fastré 2017-04-25 17:29:25 +02:00
parent b038cdfdf5
commit 95145171da
10 changed files with 292 additions and 1 deletions

View File

@ -49,9 +49,16 @@ class PermissionsGroup
*/
private $roleScopes;
/**
*
* @var \Doctrine\Common\Collections\Collection
*/
private $groupCenters;
public function __construct()
{
$this->roleScopes = new \Doctrine\Common\Collections\ArrayCollection();
$this->groupCenters = new \Doctrine\Common\Collections\ArrayCollection();
}
public function getId()

View File

@ -45,8 +45,15 @@ class RoleScope
*/
private $scope;
/**
*
* @var \Doctrine\Common\Collections\Collection
*/
private $permissionsGroups;
public function __construct() {
$this->new = true;
$this->permissionsGroups = new \Doctrine\Common\Collections\ArrayCollection();
}
public function getId()

View File

@ -0,0 +1,124 @@
<?php
/*
* Copyright (C) 2017 Champs Libres Cooperative <info@champs-libres.coop>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
namespace Chill\MainBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Chill\MainBundle\Security\Authorization\AuthorizationHelper;
use Doctrine\ORM\EntityRepository;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\OptionsResolver\Options;
use Chill\MainBundle\Entity\Scope;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Chill\MainBundle\Templating\TranslatableStringHelper;
/**
* Allow to pick amongst available scope for the current
* user.
*
* options :
*
* - `center`: the center of the entity
* - `role` : the role of the user
*
* @author Julien Fastré <julien.fastre@champs-libres.coop>
*/
class ScopePickerType extends AbstractType
{
/**
*
* @var AuthorizationHelper
*/
protected $authorizationHelper;
/**
*
* @var TokenStorageInterface
*/
protected $tokenStorage;
/**
*
* @var EntityRepository
*/
protected $scopeRepository;
/**
*
* @var TranslatableStringHelper
*/
protected $translatableStringHelper;
public function __construct(
AuthorizationHelper $authorizationHelper,
TokenStorageInterface $tokenStorage,
EntityRepository $scopeRepository,
TranslatableStringHelper $translatableStringHelper
) {
$this->authorizationHelper = $authorizationHelper;
$this->tokenStorage = $tokenStorage;
$this->scopeRepository = $scopeRepository;
$this->translatableStringHelper = $translatableStringHelper;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver
// create `center` option
->setRequired('center')
->setAllowedTypes('center', [\Chill\MainBundle\Entity\Center::class ])
// create ``role` option
->setRequired('role')
->setAllowedTypes('role', ['string', \Symfony\Component\Security\Core\Role\Role::class ])
;
$resolver
->setDefault('class', Scope::class)
->setDefault('placeholder', 'Choose the circle')
->setDefault('choice_label', function(Scope $c) {
return $this->translatableStringHelper->localize($c->getName());
})
->setNormalizer('query_builder', function(Options $options) {
$qb = $this->scopeRepository->createQueryBuilder('s');
$qb
// jointure to center
->join('s.roleScopes', 'rs')
->join('rs.permissionsGroups', 'pg')
->join('pg.groupCenters', 'gc')
//->join('gc.users', 'user')
// add center constraint
->where($qb->expr()->eq('IDENTITY(gc.center)', ':center'))
->setParameter('center', $options['center']->getId())
// role constraints
->andWhere($qb->expr()->eq('rs.role', ':role'))
->setParameter('role', $options['role'])
// user contraint
->andWhere(':user MEMBER OF gc.users')
->setParameter('user', $this->tokenStorage->getToken()->getUser())
;
return $qb;
})
;
}
public function getParent()
{
return \Symfony\Bridge\Doctrine\Form\Type\EntityType::class;
}
}

View File

@ -0,0 +1,114 @@
<?php
/*
* Copyright (C) 2017 Champs Libres Cooperative <info@champs-libres.coop>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
namespace Chill\MainBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Chill\MainBundle\Security\Authorization\AuthorizationHelper;
use Doctrine\ORM\EntityRepository;
use Symfony\Component\OptionsResolver\Options;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Chill\MainBundle\Entity\User;
/**
* Pick a user available for the given role and center.
*
* Options :
*
* - `role` : the role the user can reach
* - `center`: the center a user can reach
*
* @author Julien Fastré <julien.fastre@champs-libres.coop>
*/
class UserPickerType extends AbstractType
{
/**
*
* @var AuthorizationHelper
*/
protected $authorizationHelper;
/**
*
* @var TokenStorageInterface
*/
protected $tokenStorage;
/**
*
* @var EntityRepository
*/
protected $userRepository;
public function __construct(
AuthorizationHelper $authorizationHelper,
TokenStorageInterface $tokenStorage,
EntityRepository $userRepository
) {
$this->authorizationHelper = $authorizationHelper;
$this->tokenStorage = $tokenStorage;
$this->userRepository = $userRepository;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver
// create `center` option
->setRequired('center')
->setAllowedTypes('center', [\Chill\MainBundle\Entity\Center::class ])
// create ``role` option
->setRequired('role')
->setAllowedTypes('role', ['string', \Symfony\Component\Security\Core\Role\Role::class ])
;
$resolver
->setDefault('class', User::class)
->setDefault('empty_data', $this->tokenStorage->getToken()->getUser())
->setDefault('choice_label', function(User $u) {
return $u->getUsername();
})
->setNormalizer('query_builder', function(Options $options) {
$qb = $this->userRepository->createQueryBuilder('u');
$qb
// add center constraint
->join('u.groupCenters', 'ug')
->where($qb->expr()->eq('ug.center', ':center'))
->setParameter('center', $options['center'])
// link to permission groups
->join('ug.permissionsGroup', 'pg')
// role constraints
->join('pg.roleScopes', 'roleScope')
->andWhere($qb->expr()->eq('roleScope.role', ':role'))
->setParameter('role', $options['role'])
// add active constraint
->andWhere('u.enabled = :enabled')
->setParameter('enabled', true)
;
return $qb;
})
;
}
public function getParent()
{
return \Symfony\Bridge\Doctrine\Form\Type\EntityType::class;
}
}

View File

@ -19,4 +19,8 @@ Chill\MainBundle\Entity\GroupCenter:
permissionsGroup:
targetEntity: Chill\MainBundle\Entity\PermissionsGroup
cache:
usage: NONSTRICT_READ_WRITE
usage: NONSTRICT_READ_WRITE
manyToMany:
users:
targetEntity: Chill\MainBundle\Entity\User
mappedBy: groupCenters

View File

@ -17,6 +17,11 @@ Chill\MainBundle\Entity\PermissionsGroup:
manyToMany:
roleScopes:
targetEntity: Chill\MainBundle\Entity\RoleScope
inversedBy: permissionsGroups
cache:
usage: NONSTRICT_READ_WRITE
oneToMany:
groupCenters:
targetEntity: Chill\MainBundle\Entity\GroupCenter
mappedBy: permissionsGroup

View File

@ -21,4 +21,8 @@ Chill\MainBundle\Entity\RoleScope:
nullable: true
cache:
usage: NONSTRICT_READ_WRITE
manyToMany:
permissionsGroups:
targetEntity: Chill\MainBundle\Entity\PermissionsGroup
mappedBy: roleScopes

View File

@ -30,6 +30,7 @@ Chill\MainBundle\Entity\User:
manyToMany:
groupCenters:
targetEntity: Chill\MainBundle\Entity\GroupCenter
inversedBy: users
cache:
usage: NONSTRICT_READ_WRITE

View File

@ -89,5 +89,24 @@ services:
chill.main.form.date_type:
class: Chill\MainBundle\Form\Type\ChillDateType
tags:
- { name: form.type }
chill.main.form.pick_user_type:
class: Chill\MainBundle\Form\Type\UserPickerType
arguments:
- "@chill.main.security.authorization.helper"
- "@security.token_storage"
- "@chill.main.user_repository"
tags:
- { name: form.type }
chill.main.form.pick_scope_type:
class: Chill\MainBundle\Form\Type\ScopePickerType
arguments:
- "@chill.main.security.authorization.helper"
- "@security.token_storage"
- "@chill.main.scope_repository"
- "@chill.main.helper.translatable_string"
tags:
- { name: form.type }

View File

@ -10,3 +10,9 @@ services:
factory: ["@doctrine.orm.entity_manager", getRepository]
arguments:
- "Chill\\MainBundle\\Entity\\User"
chill.main.scope_repository:
class: Doctrine\ORM\EntityRepository
factory: ["@doctrine.orm.entity_manager", getRepository]
arguments:
- "Chill\\MainBundle\\Entity\\Scope"