mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-06-13 13:54:23 +00:00
improve CRUD and switch to symfony3
This commit is contained in:
parent
a1ee85b0c0
commit
eda8f2c033
@ -11,6 +11,8 @@ use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Chill\PersonBundle\Entity\Person;
|
||||
use Symfony\Component\Security\Core\Role\Role;
|
||||
use Chill\PersonBundle\Security\Authorization\PersonVoter;
|
||||
use Chill\DocStoreBundle\Security\Authorization\PersonDocumentVoter;
|
||||
|
||||
/**
|
||||
* @Route("/{_locale}/person/{person}/document")
|
||||
@ -30,11 +32,11 @@ class DocumentPersonController extends Controller
|
||||
throw $this->createNotFoundException('Person not found');
|
||||
}
|
||||
|
||||
$this->denyAccessUnlessGranted('CHILL_PERSON_SEE', $person);
|
||||
$this->denyAccessUnlessGranted(PersonVoter::SEE, $person);
|
||||
|
||||
$reachableScopes = $this->get('chill.main.security.authorization.helper')
|
||||
->getReachableScopes(
|
||||
$this->getUser(), new Role('CHILL_PERSON_DOCUMENT_SEE'),
|
||||
$this->getUser(), new Role(PersonDocumentVoter::SEE),
|
||||
$person->getCenter());
|
||||
|
||||
$documents = $em
|
||||
@ -61,11 +63,10 @@ class DocumentPersonController extends Controller
|
||||
throw $this->createNotFoundException('person not found');
|
||||
}
|
||||
|
||||
$this->denyAccessUnlessGranted('CHILL_PERSON_SEE', $person);
|
||||
$this->denyAccessUnlessGranted(PersonVoter::SEE, $person);
|
||||
|
||||
$user = $this->get('security.context')->getToken()->getUser();
|
||||
$document = new PersonDocument();
|
||||
$document->setUser($user);
|
||||
$document->setUser($this->getUser());
|
||||
$document->setPerson($person);
|
||||
$document->setDate(new \DateTime('Now'));
|
||||
|
||||
@ -115,8 +116,7 @@ class DocumentPersonController extends Controller
|
||||
$this->denyAccessUnlessGranted('CHILL_PERSON_SEE', $person);
|
||||
$this->denyAccessUnlessGranted('CHILL_PERSON_DOCUMENT_UPDATE', $document);
|
||||
|
||||
$user = $this->get('security.context')->getToken()->getUser();
|
||||
$document->setUser($user);
|
||||
$document->setUser($this->getUser());
|
||||
$document->setDate(new \DateTime('Now'));
|
||||
|
||||
$form = $this->createForm(
|
||||
|
@ -7,6 +7,7 @@ use Symfony\Component\Config\FileLocator;
|
||||
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
|
||||
use Symfony\Component\DependencyInjection\Loader;
|
||||
use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface;
|
||||
use Chill\DocStoreBundle\Security\Authorization\PersonDocumentVoter;
|
||||
|
||||
/**
|
||||
* This is the class that loads and manages your bundle configuration
|
||||
@ -30,6 +31,7 @@ class ChillDocStoreExtension extends Extension implements PrependExtensionInterf
|
||||
public function prepend(ContainerBuilder $container)
|
||||
{
|
||||
$this->prependRoute($container);
|
||||
$this->prependAuthorization($container);
|
||||
}
|
||||
|
||||
protected function prependRoute(ContainerBuilder $container)
|
||||
@ -43,4 +45,16 @@ class ChillDocStoreExtension extends Extension implements PrependExtensionInterf
|
||||
)
|
||||
));
|
||||
}
|
||||
|
||||
protected function prependAuthorization(ContainerBuilder $container)
|
||||
{
|
||||
$container->prependExtensionConfig('security', array(
|
||||
'role_hierarchy' => array(
|
||||
PersonDocumentVoter::UPDATE => [PersonDocumentVoter::SEE_DETAILS],
|
||||
PersonDocumentVoter::CREATE => [PersonDocumentVoter::SEE_DETAILS],
|
||||
PersonDocumentVoter::DELETE => [PersonDocumentVoter::SEE_DETAILS],
|
||||
PersonDocumentVoter::SEE_DETAILS => [PersonDocumentVoter::SEE],
|
||||
)
|
||||
));
|
||||
}
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ class Document implements HasScopeInterface
|
||||
/**
|
||||
* @ORM\Column(type="text")
|
||||
*/
|
||||
private $description;
|
||||
private $description = '';
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="Chill\DocStoreBundle\Entity\DocumentCategory")
|
||||
@ -83,9 +83,9 @@ class Document implements HasScopeInterface
|
||||
return $this->description;
|
||||
}
|
||||
|
||||
public function setDescription(string $description): self
|
||||
public function setDescription($description): self
|
||||
{
|
||||
$this->description = $description;
|
||||
$this->description = (string) $description;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
@ -17,12 +17,14 @@ use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInt
|
||||
use Chill\MainBundle\Security\Authorization\AuthorizationHelper;
|
||||
use Doctrine\Common\Persistence\ObjectManager;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelper;
|
||||
use Chill\MainBundle\Form\Type\ChillDateType;
|
||||
use Chill\MainBundle\Form\Type\ScopePickerType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
|
||||
|
||||
|
||||
class PersonDocumentType extends AbstractType
|
||||
{
|
||||
use AppendScopeChoiceTypeTrait;
|
||||
|
||||
/**
|
||||
* the user running this form
|
||||
*
|
||||
@ -49,18 +51,9 @@ class PersonDocumentType extends AbstractType
|
||||
protected $translatableStringHelper;
|
||||
|
||||
public function __construct(
|
||||
TokenStorageInterface $tokenStorage,
|
||||
AuthorizationHelper $authorizationHelper,
|
||||
ObjectManager $om,
|
||||
TranslatableStringHelper $translatableStringHelper
|
||||
)
|
||||
{
|
||||
if (!$tokenStorage->getToken()->getUser() instanceof User) {
|
||||
throw new \RuntimeException("you should have a valid user");
|
||||
}
|
||||
$this->user = $tokenStorage->getToken()->getUser();
|
||||
$this->authorizationHelper = $authorizationHelper;
|
||||
$this->om = $om;
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
}
|
||||
|
||||
@ -68,12 +61,16 @@ class PersonDocumentType extends AbstractType
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
{
|
||||
$builder
|
||||
->add('title')
|
||||
->add('description')
|
||||
->add('title', TextType::class)
|
||||
->add('description', TextareaType::class, [
|
||||
'required' => false
|
||||
])
|
||||
->add('content')
|
||||
//->add('center')
|
||||
->add('scope')
|
||||
->add('date', 'date', array('required' => false, 'widget' => 'single_text', 'format' => 'dd-MM-yyyy'))
|
||||
->add('scope', ScopePickerType::class, [
|
||||
'center' => $options['center'],
|
||||
'role' => $options['role']
|
||||
])
|
||||
->add('date', ChillDateType::class)
|
||||
->add('category', EntityType::class, array(
|
||||
'class' => 'ChillDocStoreBundle:DocumentCategory',
|
||||
'query_builder' => function (EntityRepository $er) {
|
||||
@ -87,10 +84,6 @@ class PersonDocumentType extends AbstractType
|
||||
))
|
||||
;
|
||||
|
||||
$this->appendScopeChoices($builder, $options['role'],
|
||||
$options['center'], $this->user, $this->authorizationHelper,
|
||||
$this->translatableStringHelper, $this->om);
|
||||
|
||||
}
|
||||
|
||||
public function configureOptions(OptionsResolver $resolver)
|
||||
@ -99,6 +92,9 @@ class PersonDocumentType extends AbstractType
|
||||
'data_class' => Document::class,
|
||||
]);
|
||||
|
||||
$this->appendScopeChoicesOptions($resolver);
|
||||
$resolver->setRequired(['role', 'center'])
|
||||
->setAllowedTypes('role', [ \Symfony\Component\Security\Core\Role\Role::class ])
|
||||
->setAllowedTypes('center', [ \Chill\MainBundle\Entity\Center::class ])
|
||||
;
|
||||
}
|
||||
}
|
||||
|
@ -11,9 +11,6 @@ services:
|
||||
Chill\DocStoreBundle\Form\PersonDocumentType:
|
||||
class: Chill\DocStoreBundle\Form\PersonDocumentType
|
||||
arguments:
|
||||
- "@security.token_storage"
|
||||
- "@chill.main.security.authorization.helper"
|
||||
- "@doctrine.orm.entity_manager"
|
||||
- "@chill.main.helper.translatable_string"
|
||||
tags:
|
||||
- { name: form.type, alias: chill_docstorebundle_form_document }
|
||||
|
39
Resources/migrations/Version20180605102533.php
Normal file
39
Resources/migrations/Version20180605102533.php
Normal file
@ -0,0 +1,39 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Application\Migrations;
|
||||
|
||||
use Doctrine\DBAL\Migrations\AbstractMigration;
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
|
||||
/**
|
||||
* Create schema for chill_doc
|
||||
*/
|
||||
final class Version20180605102533 extends AbstractMigration
|
||||
{
|
||||
public function up(Schema $schema) : void
|
||||
{
|
||||
$this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'postgresql', 'Migration can only be executed safely on \'postgresql\'.');
|
||||
|
||||
$this->addSql('CREATE SCHEMA chill_doc');
|
||||
$this->addSql('CREATE SEQUENCE chill_doc.person_document_id_seq INCREMENT BY 1 MINVALUE 1 START 1');
|
||||
$this->addSql('CREATE TABLE chill_doc.document_category (bundle_id VARCHAR(255) NOT NULL, id_inside_bundle INT NOT NULL, document_class VARCHAR(255) NOT NULL, name JSON NOT NULL, PRIMARY KEY(bundle_id, id_inside_bundle))');
|
||||
$this->addSql('COMMENT ON COLUMN chill_doc.document_category.name IS \'(DC2Type:json_array)\'');
|
||||
$this->addSql('CREATE TABLE chill_doc.person_document (id INT NOT NULL, category_bundle_id VARCHAR(255) DEFAULT NULL, category_id_inside_bundle INT DEFAULT NULL, scope_id INT DEFAULT NULL, user_id INT DEFAULT NULL, person_id INT DEFAULT NULL, title TEXT NOT NULL, description TEXT NOT NULL, content TEXT NOT NULL, date TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, PRIMARY KEY(id))');
|
||||
$this->addSql('CREATE INDEX IDX_41DA53C369A0BE36EF62EFC ON chill_doc.person_document (category_bundle_id, category_id_inside_bundle)');
|
||||
$this->addSql('CREATE INDEX IDX_41DA53C682B5931 ON chill_doc.person_document (scope_id)');
|
||||
$this->addSql('CREATE INDEX IDX_41DA53CA76ED395 ON chill_doc.person_document (user_id)');
|
||||
$this->addSql('CREATE INDEX IDX_41DA53C217BBB47 ON chill_doc.person_document (person_id)');
|
||||
$this->addSql('ALTER TABLE chill_doc.person_document ADD CONSTRAINT FK_41DA53C369A0BE36EF62EFC FOREIGN KEY (category_bundle_id, category_id_inside_bundle) REFERENCES chill_doc.document_category (bundle_id, id_inside_bundle) NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||
$this->addSql('ALTER TABLE chill_doc.person_document ADD CONSTRAINT FK_41DA53C682B5931 FOREIGN KEY (scope_id) REFERENCES scopes (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||
$this->addSql('ALTER TABLE chill_doc.person_document ADD CONSTRAINT FK_41DA53CA76ED395 FOREIGN KEY (user_id) REFERENCES users (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||
$this->addSql('ALTER TABLE chill_doc.person_document ADD CONSTRAINT FK_41DA53C217BBB47 FOREIGN KEY (person_id) REFERENCES chill_person_person (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||
}
|
||||
|
||||
public function down(Schema $schema) : void
|
||||
{
|
||||
$this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'postgresql', 'Migration can only be executed safely on \'postgresql\'.');
|
||||
|
||||
$this->addSql('DROP SCHEMA chill_doc CASCADE');
|
||||
|
||||
}
|
||||
}
|
@ -1,4 +1 @@
|
||||
{{ form_start(form) }}
|
||||
{{ form_widget(form) }}
|
||||
<button class="sc-button bt-create">{{ button_label|default('Save') }}</button>
|
||||
{{ form_end(form) }}
|
||||
{{ form_widget(form) }}
|
||||
|
@ -23,11 +23,26 @@
|
||||
{% block personcontent %}
|
||||
<h1>{{ 'Edit Document' | trans }}</h1>
|
||||
|
||||
{{ form_start(form) }}
|
||||
{{ include('ChillDocStoreBundle:PersonDocument:_form.html.twig', {'button_label': 'Update'}) }}
|
||||
|
||||
<a href="{{ path('person_document_index', {'person': person.id}) }} " class="sc-button">
|
||||
{{ 'Back to list' | trans }}
|
||||
</a>
|
||||
<ul class="record_actions">
|
||||
<li class="cancel">
|
||||
<a href="{{ path('person_document_index', {'person': person.id}) }}" class="sc-button bt-cancel">
|
||||
{{ 'Back to the list' | trans }}
|
||||
</a>
|
||||
</li>
|
||||
<li class="edit">
|
||||
<button class="sc-button bt-edit">{{ 'Edit'|trans }}</button>
|
||||
</li>
|
||||
{% if is_granted('CHILL_PERSON_DOCUMENT_DELETE', document) %}
|
||||
<li class="delete">
|
||||
{{ include('ChillDocStoreBundle:PersonDocument:_delete_form.html.twig') }}
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
|
||||
{{ form_end(form) }}
|
||||
|
||||
|
||||
{{ include('ChillDocStoreBundle:PersonDocument:_delete_form.html.twig') }}
|
||||
{% endblock %}
|
||||
|
@ -28,10 +28,8 @@
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{{ 'Title' | trans }}</th>
|
||||
<th>{{ 'Description' | trans }}</th>
|
||||
<th>{{ 'Content' | trans }}</th>
|
||||
<th>{{ 'Last modification by' | trans }}</th>
|
||||
<th>{{ 'Last update' | trans }}</th>
|
||||
<th>{{ 'Category'|trans }}</th>
|
||||
<th>{{ 'Circle' | trans }}</th>
|
||||
<th>{{ 'Actions' | trans }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
@ -39,28 +37,42 @@
|
||||
{% for document in documents %}
|
||||
<tr>
|
||||
<td>{{ document.title }}</td>
|
||||
<td>{{ document.description }}</td>
|
||||
<td>{{ document.content }}</td>
|
||||
<td>{{ document.user }}</td>
|
||||
<td>{{ document.date ? document.date|date('Y-m-d H:i:s') : '' }}</td>
|
||||
<td>{{ document.category.name|localize_translatable_string }}</td>
|
||||
<td>{{ document.scope.name|localize_translatable_string }}</td>
|
||||
<td>
|
||||
<a href="{{ path('person_document_show', {'person': person.id, 'id': document.id}) }}" class="sc-button">
|
||||
show
|
||||
</a>
|
||||
<a href="{{ path('person_document_edit', {'person': person.id, 'id': document.id}) }}" class="sc-button bt-edit">
|
||||
edit
|
||||
</a>
|
||||
<ul class="record_actions">
|
||||
{% if is_granted('CHILL_PERSON_DOCUMENT_SEE_DETAILS', document) %}
|
||||
<li>
|
||||
<a href="{{ path('person_document_show', {'person': person.id, 'id': document.id}) }}" class="sc-button">
|
||||
{{ 'See'|trans }}
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% if is_granted('CHILL_PERSON_DOCUMENT_UPDATE', document) %}
|
||||
<li>
|
||||
<a href="{{ path('person_document_edit', {'person': person.id, 'id': document.id}) }}" class="sc-button bt-edit">
|
||||
{{ 'Edit'|trans }}
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
{% else %}
|
||||
<tr>
|
||||
<td colspan="9">no records found</td>
|
||||
<td colspan="9"><span class="chill-no-data-statement">{{ 'Any document found'|trans }}</span></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<a href="{{ path('person_document_new', {'person': person.id}) }}" class="sc-button bt-create">
|
||||
{{ 'Create new' | trans }}
|
||||
</a>
|
||||
{% if is_granted('CHILL_PERSON_DOCUMENT_CREATE', person) %}
|
||||
<ul class="record_actions">
|
||||
<li class="create">
|
||||
<a href="{{ path('person_document_new', {'person': person.id}) }}" class="sc-button bt-create">
|
||||
{{ 'Create new document' | trans }}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
@ -23,9 +23,18 @@
|
||||
{% block personcontent %}
|
||||
<h1>{{ 'Create new Document' | trans }}</h1>
|
||||
|
||||
{{ form_start(form) }}
|
||||
{{ include('ChillDocStoreBundle:PersonDocument:_form.html.twig') }}
|
||||
|
||||
<a href="{{ path('person_document_index', {'person': person.id}) }}" class="sc-button bt-create">
|
||||
{{ 'back to list' | trans }}
|
||||
</a>
|
||||
<ul class="record_actions">
|
||||
<li class="cancel">
|
||||
<a href="{{ path('person_document_index', {'person': person.id}) }}" class="sc-button bt-cancel">
|
||||
{{ 'Back to the list' | trans }}
|
||||
</a>
|
||||
</li>
|
||||
<li class="create">
|
||||
<button class="sc-button bt-create">{{ 'Create'|trans }}</button>
|
||||
</li>
|
||||
</ul>
|
||||
{{ form_end(form) }}
|
||||
{% endblock %}
|
||||
|
@ -21,12 +21,14 @@ namespace Chill\DocStoreBundle\Security\Authorization;
|
||||
|
||||
use Chill\MainBundle\Security\Authorization\AbstractChillVoter;
|
||||
use Chill\MainBundle\Security\Authorization\AuthorizationHelper;
|
||||
use Chill\MainBundle\Security\ProvideRoleInterface;
|
||||
use Chill\MainBundle\Security\ProvideRoleHierarchyInterface;
|
||||
use Chill\DocStoreBundle\Entity\PersonDocument;
|
||||
use Chill\PersonBundle\Entity\Person;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
class PersonDocumentVoter extends AbstractChillVoter implements ProvideRoleInterface
|
||||
class PersonDocumentVoter extends AbstractChillVoter implements ProvideRoleHierarchyInterface
|
||||
{
|
||||
const CREATE = 'CHILL_PERSON_DOCUMENT_CREATE';
|
||||
const SEE = 'CHILL_PERSON_DOCUMENT_SEE';
|
||||
@ -45,15 +47,28 @@ class PersonDocumentVoter extends AbstractChillVoter implements ProvideRoleInter
|
||||
$this->helper = $helper;
|
||||
}
|
||||
|
||||
protected function getSupportedAttributes()
|
||||
public function getRoles()
|
||||
{
|
||||
return array(self::CREATE, self::SEE, self::UPDATE, self::DELETE,
|
||||
self::SEE_DETAILS);
|
||||
return [
|
||||
self::CREATE,
|
||||
self::SEE,
|
||||
self::SEE_DETAILS,
|
||||
self::UPDATE,
|
||||
self::DELETE
|
||||
];
|
||||
}
|
||||
|
||||
protected function getSupportedClasses()
|
||||
protected function supports($attribute, $subject)
|
||||
{
|
||||
return array('Chill\DocStoreBundle\Entity\PersonDocument');
|
||||
if (\in_array($attribute, $this->getRoles()) && $subject instanceof PersonDocument) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($subject instanceof Person && $attribute === self::CREATE) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function isGranted($attribute, $report, $user = null)
|
||||
@ -65,11 +80,6 @@ class PersonDocumentVoter extends AbstractChillVoter implements ProvideRoleInter
|
||||
return $this->helper->userHasAccess($user, $report, $attribute);
|
||||
}
|
||||
|
||||
public function getRoles()
|
||||
{
|
||||
return $this->getSupportedAttributes();
|
||||
}
|
||||
|
||||
public function getRolesWithoutScope()
|
||||
{
|
||||
return array();
|
||||
|
Loading…
x
Reference in New Issue
Block a user