Check permissions in edit part form.

This commit is contained in:
Jan Böhmer 2019-03-19 19:00:39 +01:00
parent 6ed2eeabae
commit 8d36bf913d
3 changed files with 62 additions and 22 deletions

View file

@ -47,30 +47,50 @@ use Symfony\Component\Form\Extension\Core\Type\ResetType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType; use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\Extension\Core\Type\TextType; use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\OptionsResolver\OptionsResolver; use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Security\Core\Security;
class PartType extends AbstractType class PartType extends AbstractType
{ {
protected $security;
public function __construct(Security $security)
{
$this->security = $security;
}
public function buildForm(FormBuilderInterface $builder, array $options) public function buildForm(FormBuilderInterface $builder, array $options)
{ {
$part = $options['data'];
$builder $builder
->add('name', TextType::class, ['empty_data'=>'', 'label'=> 'name.label', ->add('name', TextType::class, ['empty_data'=>'', 'label'=> 'name.label',
'attr' => ['placeholder' => 'part.name.placeholder']]) 'attr' => ['placeholder' => 'part.name.placeholder'],
'disabled' => !$this->security->isGranted('name.edit', $part)])
->add('description', TextType::class, ['required'=>false, 'empty_data'=>'', ->add('description', TextType::class, ['required'=>false, 'empty_data'=>'',
'label'=> 'description.label', 'help' => 'bbcode.hint', 'attr' => ['placeholder' => 'part.description.placeholder']]) 'label'=> 'description.label', 'help' => 'bbcode.hint', 'attr' => ['placeholder' => 'part.description.placeholder'],
'disabled' => !$this->security->isGranted('description.edit', $part)])
->add('instock', IntegerType::class, ->add('instock', IntegerType::class,
['attr' => ['min'=>0, 'placeholder' => 'part.instock.placeholder'], 'label'=> 'instock.label']) ['attr' => ['min'=>0, 'placeholder' => 'part.instock.placeholder'], 'label'=> 'instock.label',
'disabled' => !$this->security->isGranted('instock.edit', $part)])
->add('mininstock', IntegerType::class, ->add('mininstock', IntegerType::class,
['attr' => ['min'=>0, 'placeholder' => 'part.mininstock.placeholder'], 'label'=> 'mininstock.label']) ['attr' => ['min'=>0, 'placeholder' => 'part.mininstock.placeholder'], 'label'=> 'mininstock.label',
'disabled' => !$this->security->isGranted('mininstock.edit', $part)])
->add('category', EntityType::class, ['class' => Category::class, 'choice_label' => 'full_path', ->add('category', EntityType::class, ['class' => Category::class, 'choice_label' => 'full_path',
'attr' => ['class' => 'selectpicker', 'data-live-search' => true], 'label'=> 'category.label']) 'attr' => ['class' => 'selectpicker', 'data-live-search' => true], 'label'=> 'category.label',
'disabled' => !$this->security->isGranted('move', $part)])
->add('storelocation', EntityType::class, ['class' => Storelocation::class, 'choice_label' => 'full_path', ->add('storelocation', EntityType::class, ['class' => Storelocation::class, 'choice_label' => 'full_path',
'attr' => ['class' => 'selectpicker', 'data-live-search' => true], 'required' => false, 'label'=> 'storelocation.label']) 'attr' => ['class' => 'selectpicker', 'data-live-search' => true], 'required' => false, 'label'=> 'storelocation.label',
'disabled' => !$this->security->isGranted('storelocation.edit', $part)])
->add('manufacturer', EntityType::class, ['class' => Manufacturer::class, 'choice_label' => 'full_path', ->add('manufacturer', EntityType::class, ['class' => Manufacturer::class, 'choice_label' => 'full_path',
'attr' => ['class' => 'selectpicker', 'data-live-search' => true], 'required' => false, 'label'=> 'manufacturer.label']) 'attr' => ['class' => 'selectpicker', 'data-live-search' => true], 'required' => false, 'label'=> 'manufacturer.label',
'disabled' => !$this->security->isGranted('manufacturer.edit', $part)])
->add('manufacturer_product_url', UrlType::class, ['required'=>false, 'empty_data' => '', ->add('manufacturer_product_url', UrlType::class, ['required'=>false, 'empty_data' => '',
'label'=> 'manufacturer_url.label']) 'label'=> 'manufacturer_url.label',
'disabled' => !$this->security->isGranted('manufacturer.edit', $part)])
->add('comment', CKEditorType::class, ['required'=>false, ->add('comment', CKEditorType::class, ['required'=>false,
'label'=> 'comment.label', 'attr' => ['rows'=> 4], 'help' => 'bbcode.hint']) 'label'=> 'comment.label', 'attr' => ['rows'=> 4], 'help' => 'bbcode.hint',
'disabled' => !$this->security->isGranted('comment.edit', $part)])
//Buttons //Buttons
->add('save', SubmitType::class, ['label' => 'part.edit.save']) ->add('save', SubmitType::class, ['label' => 'part.edit.save'])

View file

@ -31,7 +31,15 @@ class PartVoter extends ExtendedVoter
if ($subject instanceof Part) if ($subject instanceof Part)
{ {
return in_array($attribute, $this->resolver->listOperationsForPermission('parts'), false);
//Check if a sub permission should be checked -> $attribute has format name.edit
if(strpos($attribute, '.') !== false) {
[$perm, $op] = explode('.', $attribute);
return in_array($op, $this->resolver->listOperationsForPermission('parts_'.$perm), false);
}
return in_array($attribute, $this->resolver->listOperationsForPermission('parts'), false);
} }
return false; return false;
@ -41,6 +49,13 @@ class PartVoter extends ExtendedVoter
protected function voteOnUser($attribute, $subject, User $user): bool protected function voteOnUser($attribute, $subject, User $user): bool
{ {
if($subject instanceof Part) { if($subject instanceof Part) {
//Check for sub permissions
if(strpos($attribute, '.') !== false) {
[$perm, $op] = explode('.', $attribute);
return $this->resolver->inherit($user, 'parts_'. $perm, $op) ?? false;
}
//Null concealing operator means, that no //Null concealing operator means, that no
return $this->resolver->inherit($user, 'parts', $attribute) ?? false; return $this->resolver->inherit($user, 'parts', $attribute) ?? false;
} }

View file

@ -23,7 +23,12 @@
</div> </div>
<div class="col-md-9"> <div class="col-md-9">
<h5 class="text-muted pt-2" title="{% trans %}manufacturer.label{% endtrans %}">{{ part.manufacturer.name ?? ""}}</h5> <h5 class="text-muted pt-2" title="{% trans %}manufacturer.label{% endtrans %}">{{ part.manufacturer.name ?? ""}}</h5>
<h3>{{ part.name }} <a href="{{ part|entityURL('edit') }}"><i class="fas fa-fw fa-sm fa-edit"></i></a></h3> <h3>{{ part.name }}
{# You need edit permission to use the edit button #}
{% if is_granted('edit', part) %}
<a href="{{ part|entityURL('edit') }}"><i class="fas fa-fw fa-sm fa-edit"></i></a>
{% endif %}
</h3>
<h6 class="text-muted"><span title="{% trans %}description.label{% endtrans %}">{{ part.description|bbCode }}</span></h6> <h6 class="text-muted"><span title="{% trans %}description.label{% endtrans %}">{{ part.description|bbCode }}</span></h6>
<h6 class="" title="{% trans %}category.label{% endtrans %}"> <h6 class="" title="{% trans %}category.label{% endtrans %}">
<i class="fas fa-tag fa-fw"></i> <i class="fas fa-tag fa-fw"></i>
@ -63,13 +68,13 @@
<div class="mt-3"> <div class="mt-3">
<ul class="nav nav-tabs" id="partTab" role="tablist"> <ul class="nav nav-tabs" id="partTab" role="tablist">
{% if part.comment is not empty %} {% if part.comment is not empty %}
<li class="nav-item"> <li class="nav-item">
<a class="nav-link active" id="attachment-tab" data-toggle="tab" <a class="nav-link active" id="attachment-tab" data-toggle="tab"
href="#comment" role="tab" aria-controls="home" aria-selected="true"> href="#comment" role="tab" aria-controls="home" aria-selected="true">
<i class="fas fa-comment-alt fa-fw"></i> <i class="fas fa-comment-alt fa-fw"></i>
{% trans %}comment.label{% endtrans %} {% trans %}comment.label{% endtrans %}
</a> </a>
</li> </li>
{% endif %} {% endif %}
<li class="nav-item"> <li class="nav-item">
<a class="nav-link {% if part.comment is empty%} active{% endif %}" id="attachment-tab" data-toggle="tab" <a class="nav-link {% if part.comment is empty%} active{% endif %}" id="attachment-tab" data-toggle="tab"
@ -99,11 +104,11 @@
</ul> </ul>
<div class="tab-content" id="myTabContent"> <div class="tab-content" id="myTabContent">
{% if part.comment is not empty %} {% if part.comment is not empty %}
<div class="tab-pane fade show active" id="comment" role="tabpanel" aria-labelledby="home-tab"> <div class="tab-pane fade show active" id="comment" role="tabpanel" aria-labelledby="home-tab">
<div class="container-fluid mt-2"> <div class="container-fluid mt-2">
{{ part.comment|bbCode }} {{ part.comment|bbCode }}
</div>
</div> </div>
</div>
{% endif %} {% endif %}
<div class="tab-pane fade {% if part.comment is empty %} show active{% endif %}" id="attachments" role="tabpanel" aria-labelledby="profile-tab"> <div class="tab-pane fade {% if part.comment is empty %} show active{% endif %}" id="attachments" role="tabpanel" aria-labelledby="profile-tab">
Test Test