mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-06-07 18:44:08 +00:00
first implementation of controller
This commit is contained in:
parent
1734727029
commit
a02b9edc45
@ -1,13 +0,0 @@
|
||||
?php
|
||||
|
||||
namespace Chill\TaskBundle\Controller;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
|
||||
|
||||
class DefaultController extends Controller
|
||||
{
|
||||
public function indexAction()
|
||||
{
|
||||
return $this->render('ChillTaskBundle:Default:index.html.twig');
|
||||
}
|
||||
}
|
101
Controller/SingleTaskController.php
Normal file
101
Controller/SingleTaskController.php
Normal file
@ -0,0 +1,101 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\TaskBundle\Controller;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
|
||||
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
|
||||
use Doctrine\ORM\EntityManager;
|
||||
use Chill\PersonBundle\Entity\Person;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Chill\TaskBundle\Entity\SingleTask;
|
||||
use Chill\TaskBundle\Form\SingleTaskType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
|
||||
use Symfony\Component\Form\FormFactoryInterface;
|
||||
use Chill\TaskBundle\Security\Authorization\TaskVoter;
|
||||
|
||||
class SingleTaskController extends Controller
|
||||
{
|
||||
/**
|
||||
*
|
||||
* @var EntityManager
|
||||
*/
|
||||
protected $em;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var FormFactoryInterface
|
||||
*/
|
||||
protected $formFactory;
|
||||
|
||||
/*public function __construct(
|
||||
EntityManager $em,
|
||||
FormFactoryInterface $formFactory)
|
||||
{
|
||||
$this->em = $em;
|
||||
$this->formFactory = $formFactory;
|
||||
}*/
|
||||
|
||||
/**
|
||||
* @Route("/{_locale}/task/single-task/new")
|
||||
*/
|
||||
public function newAction(Request $request)
|
||||
{
|
||||
$personId = $request->query->getInt('person_id', null);
|
||||
|
||||
if ($personId === null) {
|
||||
return new Response("You must provide a person_id", Response::HTTP_BAD_REQUEST);
|
||||
}
|
||||
|
||||
$person = $this->getDoctrine()->getManager()
|
||||
->getRepository(Person::class)
|
||||
->find($personId);
|
||||
|
||||
if ($person === null) {
|
||||
throw $this->createNotFoundException("Invalid person id");
|
||||
}
|
||||
|
||||
$task = (new SingleTask())
|
||||
->setPerson($person)
|
||||
->setAssignee($this->getUser())
|
||||
;
|
||||
|
||||
$this->denyAccessUnlessGranted(TaskVoter::CREATE, $task, 'You are not '
|
||||
. 'allowed to create this task');
|
||||
|
||||
$form = $this->createCreateForm($task);
|
||||
|
||||
$form->handleRequest($request);
|
||||
|
||||
if ($form->isSubmitted() && $form->isValid()) {
|
||||
$em = $this->getDoctrine()->getManager();
|
||||
$em->persist($task);
|
||||
|
||||
$this->addFlash('success', "The task is created");
|
||||
|
||||
$em->flush();
|
||||
}
|
||||
|
||||
return $this->render('ChillTaskBundle:SingleTask:new.html.twig', array(
|
||||
'form' => $form->createView(),
|
||||
'task' => $task
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param SingleTask $task
|
||||
* @return \Symfony\Component\Form\FormInterface
|
||||
*/
|
||||
protected function createCreateForm(SingleTask $task)
|
||||
{
|
||||
$form = $this->createForm(SingleTaskType::class, $task, [
|
||||
'center' => $task->getCenter()
|
||||
]);
|
||||
|
||||
$form->add('submit', SubmitType::class);
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
}
|
86
DataFixtures/ORM/LoadTaskACL.php
Normal file
86
DataFixtures/ORM/LoadTaskACL.php
Normal file
@ -0,0 +1,86 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright (C) 2015 Julien Fastré <julien.fastre@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\TaskBundle\DataFixtures\ORM;
|
||||
|
||||
use Doctrine\Common\DataFixtures\AbstractFixture;
|
||||
use Doctrine\Common\DataFixtures\OrderedFixtureInterface;
|
||||
use Doctrine\Common\Persistence\ObjectManager;
|
||||
use Chill\MainBundle\DataFixtures\ORM\LoadPermissionsGroup;
|
||||
use Chill\MainBundle\Entity\RoleScope;
|
||||
use Chill\MainBundle\DataFixtures\ORM\LoadScopes;
|
||||
use Chill\TaskBundle\Security\Authorization\TaskVoter;
|
||||
|
||||
/**
|
||||
* Add a role UPDATE & CREATE for all groups except administrative,
|
||||
* and a role SEE for administrative
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*/
|
||||
class LoadTaskACL extends AbstractFixture implements OrderedFixtureInterface
|
||||
{
|
||||
public function getOrder()
|
||||
{
|
||||
return 16000;
|
||||
}
|
||||
|
||||
|
||||
public function load(ObjectManager $manager)
|
||||
{
|
||||
foreach (LoadPermissionsGroup::$refs as $permissionsGroupRef) {
|
||||
$permissionsGroup = $this->getReference($permissionsGroupRef);
|
||||
foreach (LoadScopes::$references as $scopeRef){
|
||||
$scope = $this->getReference($scopeRef);
|
||||
//create permission group
|
||||
switch ($permissionsGroup->getName()) {
|
||||
case 'social':
|
||||
if ($scope->getName()['en'] === 'administrative') {
|
||||
break 2; // we do not want any power on administrative
|
||||
}
|
||||
break;
|
||||
case 'administrative':
|
||||
case 'direction':
|
||||
if (in_array($scope->getName()['en'], array('administrative', 'social'))) {
|
||||
break 2; // we do not want any power on social or administrative
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
printf("Adding CHILL_TASK_TASK_UPDATE & CHILL_TASK_TASK_CREATE permissions to %s "
|
||||
. "permission group, scope '%s' \n",
|
||||
$permissionsGroup->getName(), $scope->getName()['en']);
|
||||
$roleScopeUpdate = (new RoleScope())
|
||||
->setRole(TaskVoter::UPDATE)
|
||||
->setScope($scope);
|
||||
$permissionsGroup->addRoleScope($roleScopeUpdate);
|
||||
$roleScopeCreate = (new RoleScope())
|
||||
->setRole(TaskVoter::CREATE)
|
||||
->setScope($scope);
|
||||
$permissionsGroup->addRoleScope($roleScopeCreate);
|
||||
|
||||
$manager->persist($roleScopeUpdate);
|
||||
$manager->persist($roleScopeCreate);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$manager->flush();
|
||||
}
|
||||
|
||||
}
|
@ -23,6 +23,7 @@ class ChillTaskExtension extends Extension
|
||||
$config = $this->processConfiguration($configuration, $configs);
|
||||
|
||||
$loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
|
||||
//$loader->load('services.yml');
|
||||
$loader->load('services/controller.yml');
|
||||
$loader->load('services/security.yml');
|
||||
}
|
||||
}
|
||||
|
@ -6,13 +6,15 @@ use Doctrine\ORM\Mapping as ORM;
|
||||
use Chill\MainBundle\Entity\User;
|
||||
use Chill\PersonBundle\Entity\Person;
|
||||
use Chill\MainBundle\Entity\Scope;
|
||||
use Chill\MainBundle\Entity\HasScopeInterface;
|
||||
use Chill\MainBundle\Entity\HasCenterInterface;
|
||||
|
||||
/**
|
||||
* AbstractTask
|
||||
*
|
||||
* @ORM\MappedSuperclass()
|
||||
*/
|
||||
abstract class AbstractTask
|
||||
abstract class AbstractTask implements HasScopeInterface, HasCenterInterface
|
||||
{
|
||||
|
||||
/**
|
||||
@ -27,7 +29,7 @@ abstract class AbstractTask
|
||||
*
|
||||
* @ORM\Column(name="current_states", type="json")
|
||||
*/
|
||||
private $currentStates = '';
|
||||
private $currentStates = [];
|
||||
|
||||
/**
|
||||
* @var string
|
||||
@ -165,5 +167,55 @@ abstract class AbstractTask
|
||||
{
|
||||
return $this->description;
|
||||
}
|
||||
|
||||
public function getAssignee(): ?User
|
||||
{
|
||||
return $this->assignee;
|
||||
}
|
||||
|
||||
public function getPerson(): ?Person
|
||||
{
|
||||
return $this->person;
|
||||
}
|
||||
|
||||
public function getCircle(): ?Scope
|
||||
{
|
||||
return $this->circle;
|
||||
}
|
||||
|
||||
public function setAssignee(User $assignee)
|
||||
{
|
||||
$this->assignee = $assignee;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setPerson(Person $person)
|
||||
{
|
||||
$this->person = $person;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setCircle(Scope $circle)
|
||||
{
|
||||
$this->circle = $circle;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getCenter(): ?\Chill\MainBundle\Entity\Center
|
||||
{
|
||||
if ($this->getPerson() instanceof Person) {
|
||||
return $this->getPerson()->getCenter();
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
public function getScope(): ?\Chill\MainBundle\Entity\Scope
|
||||
{
|
||||
return $this->getCircle();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
@ -130,9 +130,21 @@ class SingleTask extends AbstractTask
|
||||
*
|
||||
* @return \DateInterval
|
||||
*/
|
||||
public function getWarningInterval(): ?\DateInterval
|
||||
public function getWarningInterval()
|
||||
{
|
||||
return $this->warningInterval;
|
||||
}
|
||||
|
||||
function getRecurringTask(): RecurringTask
|
||||
{
|
||||
return $this->recurringTask;
|
||||
}
|
||||
|
||||
function setRecurringTask(RecurringTask $recurringTask)
|
||||
{
|
||||
$this->recurringTask = $recurringTask;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
74
Form/SingleTaskType.php
Normal file
74
Form/SingleTaskType.php
Normal file
@ -0,0 +1,74 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright (C) 2018 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\TaskBundle\Form;
|
||||
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Chill\MainBundle\Form\Type\ChillDateType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
|
||||
use Chill\MainBundle\Form\Type\UserPickerType;
|
||||
use Chill\MainBundle\Form\Type\ScopePickerType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\HiddenType;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
use Symfony\Component\Security\Core\Role\Role;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*/
|
||||
class SingleTaskType extends AbstractType
|
||||
{
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
{
|
||||
$builder
|
||||
->add('title', TextType::class)
|
||||
->add('description', TextareaType::class, [
|
||||
'required' => false
|
||||
])
|
||||
->add('assignee', UserPickerType::class, [
|
||||
'required' => false,
|
||||
'center' => $options['center'],
|
||||
'role' => new Role(\Chill\PersonBundle\Security\Authorization\PersonVoter::UPDATE)
|
||||
])
|
||||
->add('circle', ScopePickerType::class, [
|
||||
'center' => $options['center'],
|
||||
'role' => new Role(\Chill\ActivityBundle\Security\Authorization\ActivityVoter::SEE)
|
||||
])
|
||||
->add('startDate', ChillDateType::class, [
|
||||
'required' => false
|
||||
])
|
||||
->add('endDate', ChillDateType::class, [
|
||||
'required' => false
|
||||
])
|
||||
->add('warningInterval', TextType::class, [
|
||||
'required' => false
|
||||
])
|
||||
;
|
||||
}
|
||||
|
||||
public function configureOptions(OptionsResolver $resolver)
|
||||
{
|
||||
$resolver
|
||||
->setRequired('center')
|
||||
->setAllowedTypes('center', [ \Chill\MainBundle\Entity\Center::class ])
|
||||
;
|
||||
}
|
||||
}
|
@ -1 +1,3 @@
|
||||
|
||||
chill_task_controllers:
|
||||
resource: "@ChillTaskBundle/Controller"
|
||||
type: annotation
|
||||
|
2
Resources/config/services.yml
Normal file
2
Resources/config/services.yml
Normal file
@ -0,0 +1,2 @@
|
||||
services:
|
||||
|
4
Resources/config/services/controller.yml
Normal file
4
Resources/config/services/controller.yml
Normal file
@ -0,0 +1,4 @@
|
||||
services:
|
||||
#chill_task.single_task_controller:
|
||||
# class: Chill\TaskBundle\Controller\SingleTaskController
|
||||
# autowire: true
|
10
Resources/config/services/security.yml
Normal file
10
Resources/config/services/security.yml
Normal file
@ -0,0 +1,10 @@
|
||||
services:
|
||||
chill_task.task_voter:
|
||||
class: Chill\TaskBundle\Security\Authorization\TaskVoter
|
||||
arguments:
|
||||
- "@security.access.decision_manager"
|
||||
- "@chill.main.security.authorization.helper"
|
||||
- "@logger"
|
||||
tags:
|
||||
- { name: security.voter }
|
||||
- { name: chill.role }
|
29
Resources/views/SingleTask/new.html.twig
Normal file
29
Resources/views/SingleTask/new.html.twig
Normal file
@ -0,0 +1,29 @@
|
||||
{#
|
||||
* Copyright (C) 2014, Champs Libres Cooperative SCRLFS, <http://www.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/>.
|
||||
#}
|
||||
{% extends "ChillPersonBundle::layout.html.twig" %}
|
||||
|
||||
{% set activeRouteKey = 'chill_task_single_task_new' %}
|
||||
{% set person = task.person %}
|
||||
|
||||
{% block title %}{{ 'New task'|trans }}{% endblock %}
|
||||
|
||||
{% block personcontent %}
|
||||
<h1>{{ 'New task'|trans }}</h1>
|
||||
|
||||
{{ form(form) }}
|
||||
|
||||
{% endblock %}
|
131
Security/Authorization/TaskVoter.php
Normal file
131
Security/Authorization/TaskVoter.php
Normal file
@ -0,0 +1,131 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright (C) 2018 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\TaskBundle\Security\Authorization;
|
||||
|
||||
use Chill\MainBundle\Security\Authorization\AbstractChillVoter;
|
||||
use Chill\TaskBundle\Entity\AbstractTask;
|
||||
use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface;
|
||||
use Chill\MainBundle\Security\Authorization\AuthorizationHelper;
|
||||
use Chill\PersonBundle\Security\Authorization\PersonVoter;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Chill\MainBundle\Security\ProvideRoleHierarchyInterface;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
||||
use Chill\MainBundle\Entity\User;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*/
|
||||
class TaskVoter extends AbstractChillVoter implements ProvideRoleHierarchyInterface
|
||||
{
|
||||
const CREATE = 'CHILL_TASK_TASK_CREATE';
|
||||
const UPDATE = 'CHILL_TASK_TASK_UPDATE';
|
||||
const SHOW = 'CHILL_TASK_TASK_SHOW';
|
||||
|
||||
const ROLES = [
|
||||
self::CREATE,
|
||||
self::UPDATE,
|
||||
self::SHOW
|
||||
];
|
||||
|
||||
/**
|
||||
*
|
||||
* @var AuthorizationHelper
|
||||
*/
|
||||
protected $authorizationHelper;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var AccessDecisionManagerInterface
|
||||
*/
|
||||
protected $accessDecisionManager;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var LoggerInterface
|
||||
*/
|
||||
protected $logger;
|
||||
|
||||
public function __construct(
|
||||
AccessDecisionManagerInterface $accessDecisionManager,
|
||||
AuthorizationHelper $authorizationHelper,
|
||||
LoggerInterface $logger
|
||||
) {
|
||||
$this->accessDecisionManager = $accessDecisionManager;
|
||||
$this->authorizationHelper = $authorizationHelper;
|
||||
$this->logger = $logger;
|
||||
}
|
||||
|
||||
public function supports($attribute, $subject)
|
||||
{
|
||||
return $subject instanceof AbstractTask
|
||||
&& in_array($attribute, self::ROLES);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param string $attribute
|
||||
* @param AbstractTask $subject
|
||||
* @param TokenInterface $token
|
||||
* @return boolean
|
||||
*/
|
||||
protected function voteOnAttribute($attribute, $subject, TokenInterface $token)
|
||||
{
|
||||
$this->logger->debug(sprintf("Voting from %s class", self::class));
|
||||
|
||||
if (!$token->getUser() instanceof User) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($subject->getPerson() === null) {
|
||||
throw new \LogicException("You should associate a person with task "
|
||||
. "in order to check autorizations");
|
||||
}
|
||||
|
||||
if (!$this->accessDecisionManager->decide($token, [PersonVoter::SEE], $subject->getPerson())) {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->authorizationHelper->userHasAccess(
|
||||
$token->getUser(),
|
||||
$subject,
|
||||
$attribute
|
||||
);
|
||||
}
|
||||
|
||||
public function getRoles()
|
||||
{
|
||||
return self::ROLES;
|
||||
}
|
||||
|
||||
public function getRolesWithHierarchy(): array
|
||||
{
|
||||
return [
|
||||
'Task' => self::ROLES
|
||||
];
|
||||
}
|
||||
|
||||
public function getRolesWithoutScope()
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user