mirror of
https://github.com/Part-DB/Part-DB-server.git
synced 2025-06-21 09:35:49 +02:00
Added permissions for the new functions.
This commit is contained in:
parent
d2bae3a4f2
commit
da14ee942d
14 changed files with 213 additions and 64 deletions
|
@ -12,7 +12,7 @@ groups:
|
|||
|
||||
perms: # Here comes a list with all Permission names (they have a perm_[name] coloumn in DB)
|
||||
|
||||
# Part related permissions
|
||||
# Part related permissions
|
||||
|
||||
parts: # e.g. this maps to perms_parts in User/Group database
|
||||
group: "parts"
|
||||
|
@ -29,10 +29,10 @@ perms: # Here comes a list with all Permission names (they have a perm_[name] co
|
|||
label: "perm.create"
|
||||
bit: 4
|
||||
alsoSet: ['read', 'edit']
|
||||
move:
|
||||
label: "perm.part.move"
|
||||
bit: 6
|
||||
alsoSet: 'read'
|
||||
#move:
|
||||
# label: "perm.part.move"
|
||||
# bit: 6
|
||||
# alsoSet: 'read'
|
||||
delete:
|
||||
label: "perm.delete"
|
||||
bit: 8
|
||||
|
@ -80,15 +80,15 @@ perms: # Here comes a list with all Permission names (they have a perm_[name] co
|
|||
bit: 2
|
||||
alsoSet: 'read'
|
||||
|
||||
parts_category:
|
||||
<<: *PART_ATTRIBUTE
|
||||
label: "perm.part.category"
|
||||
|
||||
parts_description:
|
||||
<<: *PART_ATTRIBUTE
|
||||
label: "perm.part.description"
|
||||
|
||||
parts_instock:
|
||||
<<: *PART_ATTRIBUTE
|
||||
label: "perm.part.instock"
|
||||
|
||||
parts_mininstock:
|
||||
parts_minamount:
|
||||
<<: *PART_ATTRIBUTE
|
||||
label: "perm.part.mininstock"
|
||||
|
||||
|
@ -100,24 +100,61 @@ perms: # Here comes a list with all Permission names (they have a perm_[name] co
|
|||
<<: *PART_ATTRIBUTE
|
||||
label: "perm.part.comment"
|
||||
|
||||
parts_storelocation:
|
||||
<<: *PART_ATTRIBUTE
|
||||
label: "perm.part.storelocation"
|
||||
|
||||
parts_manufacturer:
|
||||
<<: *PART_ATTRIBUTE
|
||||
label: "perm.part.manufacturer"
|
||||
|
||||
parts_orderdetails:
|
||||
parts_mpn:
|
||||
<<: *PART_ATTRIBUTE
|
||||
label: "perm.part.mpn"
|
||||
|
||||
parts_status:
|
||||
<<: *PART_ATTRIBUTE
|
||||
label: "perm.part.status"
|
||||
|
||||
parts_tags:
|
||||
<<: *PART_ATTRIBUTE
|
||||
label: "perm.part.tags"
|
||||
|
||||
parts_unit:
|
||||
<<: *PART_ATTRIBUTE
|
||||
label: "perm.part.unit"
|
||||
|
||||
parts_mass:
|
||||
<<: *PART_ATTRIBUTE
|
||||
label: "perm.part.mass"
|
||||
|
||||
parts_orderdetails: &PART_MULTI_ATTRIBUTE
|
||||
label: "perm.part.orderdetails"
|
||||
group: "parts"
|
||||
operations:
|
||||
read:
|
||||
label: "perm.read"
|
||||
bit: 0
|
||||
edit:
|
||||
label: "perm.edit"
|
||||
bit: 2
|
||||
alsoSet: 'read'
|
||||
create:
|
||||
label: "perm.create"
|
||||
bit: 4
|
||||
alsoSet: ['read', 'edit']
|
||||
delete:
|
||||
label: "perm.delete"
|
||||
bit: 6
|
||||
alsoSet: ['read']
|
||||
|
||||
|
||||
parts_prices:
|
||||
<<: *PART_ATTRIBUTE
|
||||
<<: *PART_MULTI_ATTRIBUTE
|
||||
label: "perm.part.prices"
|
||||
|
||||
parts_lots:
|
||||
<<: *PART_MULTI_ATTRIBUTE
|
||||
label: "perm.part.lots"
|
||||
|
||||
parts_attachments:
|
||||
<<: *PART_ATTRIBUTE
|
||||
<<: *PART_MULTI_ATTRIBUTE
|
||||
label: "perm.part.attachments"
|
||||
|
||||
parts_order:
|
||||
|
@ -150,7 +187,7 @@ perms: # Here comes a list with all Permission names (they have a perm_[name] co
|
|||
label: "perm.list_parts"
|
||||
bit: 10
|
||||
show_users:
|
||||
label: "perm.list_parts"
|
||||
label: "perm.show_users"
|
||||
bit: 12
|
||||
|
||||
footprints:
|
||||
|
@ -177,6 +214,14 @@ perms: # Here comes a list with all Permission names (they have a perm_[name] co
|
|||
<<: *PART_CONTAINING
|
||||
label: "perm.part.attachment_types"
|
||||
|
||||
currencies:
|
||||
<<: *PART_CONTAINING
|
||||
label: "perm.currencies"
|
||||
|
||||
measurement_units:
|
||||
<<: *PART_CONTAINING
|
||||
label: "perm.measurement_units"
|
||||
|
||||
tools:
|
||||
label: "perm.part.tools"
|
||||
operations:
|
||||
|
|
|
@ -130,7 +130,7 @@ class Part extends AttachmentContainingDBElement
|
|||
* @var Orderdetail[]
|
||||
* @ORM\OneToMany(targetEntity="App\Entity\PriceInformations\Orderdetail", mappedBy="part", cascade={"persist", "remove"}, orphanRemoval=true)
|
||||
* @Assert\Valid()
|
||||
* @ColumnSecurity(prefix="orderdetails", type="object")
|
||||
* @ColumnSecurity(prefix="orderdetails", type="collection")
|
||||
*/
|
||||
protected $orderdetails;
|
||||
|
||||
|
|
|
@ -129,6 +129,11 @@ class PermissionsEmbed
|
|||
*/
|
||||
protected $parts_name = 0;
|
||||
|
||||
/** @var int
|
||||
* @ORM\Column(type="smallint")
|
||||
*/
|
||||
protected $parts_category = 0;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
* @ORM\Column(type="smallint")
|
||||
|
@ -139,13 +144,7 @@ class PermissionsEmbed
|
|||
* @var int
|
||||
* @ORM\Column(type="smallint")
|
||||
*/
|
||||
protected $parts_instock = 0;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
* @ORM\Column(type="smallint")
|
||||
*/
|
||||
protected $parts_mininstock = 0;
|
||||
protected $parts_minamount = 0;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
|
@ -157,7 +156,24 @@ class PermissionsEmbed
|
|||
* @var int
|
||||
* @ORM\Column(type="smallint")
|
||||
*/
|
||||
protected $parts_storelocation = 0;
|
||||
protected $parts_lots = 0;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
* @ORM\Column(type="smallint")
|
||||
*/
|
||||
protected $parts_tags = 0;
|
||||
|
||||
/** @var int
|
||||
* @ORM\Column(type="smallint")
|
||||
*/
|
||||
protected $parts_unit = 0;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
* @ORM\Column(type="smallint")
|
||||
*/
|
||||
protected $parts_mass = 0;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
|
@ -165,6 +181,18 @@ class PermissionsEmbed
|
|||
*/
|
||||
protected $parts_manufacturer = 0;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
* @ORM\Column(type="smallint")
|
||||
*/
|
||||
protected $parts_status = 0;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
* @ORM\Column(type="smallint")
|
||||
*/
|
||||
protected $parts_mpn = 0;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
* @ORM\Column(type="smallint")
|
||||
|
@ -243,6 +271,17 @@ class PermissionsEmbed
|
|||
*/
|
||||
protected $attachment_types = 0;
|
||||
|
||||
/** @var int
|
||||
* @ORM\Column(type="integer")
|
||||
*/
|
||||
protected $currencies = 0;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
* @ORM\Column(type="integer")
|
||||
*/
|
||||
protected $measurement_units = 0;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
* @ORM\Column(type="integer")
|
||||
|
@ -276,7 +315,7 @@ class PermissionsEmbed
|
|||
public function getBitValue(string $permission_name, int $bit_n): int
|
||||
{
|
||||
if(!$this->isValidPermissionName($permission_name)) {
|
||||
throw new \InvalidArgumentException('No permission with the given name is existing!');
|
||||
throw new \InvalidArgumentException(sprintf('No permission with the name "%s" is existing!', $permission_name));
|
||||
}
|
||||
|
||||
$perm_int = $this->$permission_name;
|
||||
|
|
|
@ -166,6 +166,12 @@ class User extends NamedDBElement implements UserInterface, HasPermissionsInterf
|
|||
*/
|
||||
protected $group;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
* @ORM\Column(type="json")
|
||||
*/
|
||||
protected $settings = [];
|
||||
|
||||
/** @var PermissionsEmbed
|
||||
* @ORM\Embedded(class="PermissionsEmbed", columnPrefix="perms_")
|
||||
* @ValidPermission()
|
||||
|
@ -173,7 +179,8 @@ class User extends NamedDBElement implements UserInterface, HasPermissionsInterf
|
|||
protected $permissions;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="string", name="config_currency")
|
||||
* @ORM\ManyToOne(targetEntity="App\Entity\PriceInformations\Currency", fetch="EAGER")
|
||||
* @ORM\JoinColumn(name="currency_id", referencedColumnName="id")
|
||||
*/
|
||||
protected $currency = "";
|
||||
|
||||
|
|
|
@ -109,13 +109,13 @@ class PartBaseType extends AbstractType
|
|||
'attr' => ['min' => 0, 'placeholder' => $this->trans->trans('part.editmininstock.placeholder')],
|
||||
'label' => $this->trans->trans('part.edit.mininstock'),
|
||||
'measurement_unit' => $part->getPartUnit(),
|
||||
'disabled' => !$this->security->isGranted('mininstock.edit', $part),
|
||||
'disabled' => !$this->security->isGranted('minamount.edit', $part),
|
||||
])
|
||||
->add('category', StructuralEntityType::class, [
|
||||
'class' => Category::class,
|
||||
'label' => $this->trans->trans('part.edit.category'),
|
||||
'disable_not_selectable' => true,
|
||||
'disabled' => !$this->security->isGranted('move', $part),
|
||||
'disabled' => !$this->security->isGranted('category.edit', $part),
|
||||
])
|
||||
->add('footprint', StructuralEntityType::class, [
|
||||
'class' => Footprint::class,
|
||||
|
@ -129,7 +129,7 @@ class PartBaseType extends AbstractType
|
|||
'label' => $this->trans->trans('part.edit.tags'),
|
||||
'empty_data' => "",
|
||||
'attr' => ['data-role' => 'tagsinput'],
|
||||
'disabled' => !$this->security->isGranted('edit', $part)
|
||||
'disabled' => !$this->security->isGranted('tags.edit', $part)
|
||||
]);
|
||||
|
||||
//Manufacturer section
|
||||
|
@ -139,46 +139,50 @@ class PartBaseType extends AbstractType
|
|||
'label' => $this->trans->trans('part.edit.manufacturer.label'),
|
||||
'disable_not_selectable' => true,
|
||||
'disabled' => !$this->security->isGranted('manufacturer.edit', $part)
|
||||
])
|
||||
])
|
||||
->add('manufacturer_product_url', UrlType::class, [
|
||||
'required' => false,
|
||||
'empty_data' => '',
|
||||
'label' => $this->trans->trans('part.edit.manufacturer_url.label'),
|
||||
'disabled' => !$this->security->isGranted('manufacturer.edit', $part),
|
||||
'disabled' => !$this->security->isGranted('mpn.edit', $part),
|
||||
])
|
||||
->add('manufacturer_product_number', TextType::class, [
|
||||
'required' => false,
|
||||
'empty_data' => '',
|
||||
'label' => $this->trans->trans('part.edit.mpn'),
|
||||
'disabled' => !$this->security->isGranted('manufacturer.edit', $part)])
|
||||
'disabled' => !$this->security->isGranted('mpn.edit', $part)])
|
||||
->add('manufacturing_status', ChoiceType::class, [
|
||||
'label' => $this->trans->trans('part.edit.manufacturing_status'),
|
||||
'choices' => $status_choices,
|
||||
'required' => false,
|
||||
'disabled' => !$this->security->isGranted('manufacturer.edit', $part)
|
||||
'disabled' => !$this->security->isGranted('status.edit', $part)
|
||||
]);
|
||||
|
||||
//Advanced section
|
||||
$builder->add('needsReview', CheckboxType::class, [
|
||||
'label_attr' => ['class' => 'checkbox-custom'],
|
||||
'required' => false,
|
||||
'label' => $this->trans->trans('part.edit.needs_review')
|
||||
'label' => $this->trans->trans('part.edit.needs_review'),
|
||||
'disabled' => !$this->security->isGranted('edit', $part)
|
||||
])
|
||||
->add('favorite', CheckboxType::class, [
|
||||
'label_attr' => ['class' => 'checkbox-custom'],
|
||||
'required' => false,
|
||||
'label' => $this->trans->trans('part.edit.is_favorite')
|
||||
'label' => $this->trans->trans('part.edit.is_favorite'),
|
||||
'disabled' => !$this->security->isGranted('change_favorite', $part)
|
||||
])
|
||||
->add('mass', SIUnitType::class, [
|
||||
'unit' => 'g',
|
||||
'label' => $this->trans->trans('part.edit.mass'),
|
||||
'required' => false
|
||||
'required' => false,
|
||||
'disabled' => !$this->security->isGranted('mass.edit', $part)
|
||||
])
|
||||
->add('partUnit', StructuralEntityType::class, [
|
||||
'class' => MeasurementUnit::class,
|
||||
'required' => false,
|
||||
'disable_not_selectable' => true,
|
||||
'label' => $this->trans->trans('part.edit.partUnit')
|
||||
'label' => $this->trans->trans('part.edit.partUnit'),
|
||||
'disabled' => !$this->security->isGranted('unit.edit', $part)
|
||||
]);
|
||||
|
||||
|
||||
|
@ -193,10 +197,12 @@ class PartBaseType extends AbstractType
|
|||
//Part Lots section
|
||||
$builder->add('partLots', CollectionType::class, [
|
||||
'entry_type' => PartLotType::class,
|
||||
'allow_add' => true, 'allow_delete' => true,
|
||||
'allow_add' => $this->security->isGranted('lots.create', $part),
|
||||
'allow_delete' => $this->security->isGranted('lots.delete', $part),
|
||||
'label' => false,
|
||||
'entry_options' => [
|
||||
'measurement_unit' => $part->getPartUnit()
|
||||
'measurement_unit' => $part->getPartUnit(),
|
||||
'disabled' => !$this->security->isGranted('lots.edit', $part),
|
||||
],
|
||||
'by_reference' => false
|
||||
]);
|
||||
|
@ -204,16 +210,19 @@ class PartBaseType extends AbstractType
|
|||
//Attachment section
|
||||
$builder->add('attachments', CollectionType::class, [
|
||||
'entry_type' => AttachmentFormType::class,
|
||||
'allow_add' => true, 'allow_delete' => true,
|
||||
'allow_add' => $this->security->isGranted('attachments.create', $part),
|
||||
'allow_delete' => $this->security->isGranted('attachments.delete', $part),
|
||||
'label' => false,
|
||||
'entry_options' => [
|
||||
'data_class' => PartAttachment::class
|
||||
'data_class' => PartAttachment::class,
|
||||
'disabled' => !$this->security->isGranted('attachments.edit', $part),
|
||||
],
|
||||
'by_reference' => false
|
||||
]);
|
||||
|
||||
$builder->add('master_picture_attachment', EntityType::class, [
|
||||
'required' => false,
|
||||
'disabled' => !$this->security->isGranted('attachments.edit', $part),
|
||||
'label' => $this->trans->trans('part.edit.master_attachment'),
|
||||
'class' => PartAttachment::class,
|
||||
'attr' => ['class' => 'selectpicker'],
|
||||
|
@ -238,12 +247,14 @@ class PartBaseType extends AbstractType
|
|||
//Orderdetails section
|
||||
$builder->add('orderdetails', CollectionType::class, [
|
||||
'entry_type' => OrderdetailType::class,
|
||||
'allow_add' => true, 'allow_delete' => true,
|
||||
'allow_add' => $this->security->isGranted('orderdetails.create', $part),
|
||||
'allow_delete' => $this->security->isGranted('orderdetails.delete', $part),
|
||||
'label' => false,
|
||||
'by_reference' => false,
|
||||
'prototype_data' => new Orderdetail(),
|
||||
'entry_options' => [
|
||||
'measurement_unit' => $part->getPartUnit()
|
||||
'measurement_unit' => $part->getPartUnit(),
|
||||
'disabled' => !$this->security->isGranted('attachments.edit', $part),
|
||||
]
|
||||
]);
|
||||
|
||||
|
|
|
@ -51,16 +51,19 @@ use Symfony\Component\Form\FormEvent;
|
|||
use Symfony\Component\Form\FormEvents;
|
||||
use Symfony\Component\Form\FormInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
use Symfony\Component\Security\Core\Security;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
use function GuzzleHttp\Promise\queue;
|
||||
|
||||
class PartLotType extends AbstractType
|
||||
{
|
||||
protected $trans;
|
||||
protected $security;
|
||||
|
||||
public function __construct(TranslatorInterface $trans)
|
||||
public function __construct(TranslatorInterface $trans, Security $security)
|
||||
{
|
||||
$this->trans = $trans;
|
||||
$this->security = $security;
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
|
|
41
src/Migrations/Version20190913141126.php
Normal file
41
src/Migrations/Version20190913141126.php
Normal file
|
@ -0,0 +1,41 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DoctrineMigrations;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
/**
|
||||
* Auto-generated Migration: Please modify to your needs!
|
||||
*/
|
||||
final class Version20190913141126 extends AbstractMigration
|
||||
{
|
||||
public function getDescription() : string
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
public function up(Schema $schema) : void
|
||||
{
|
||||
// this up() migration is auto-generated, please modify it to your needs
|
||||
$this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.');
|
||||
|
||||
$this->addSql('ALTER TABLE `groups` ADD perms_parts_category SMALLINT NOT NULL, ADD perms_parts_minamount SMALLINT NOT NULL, ADD perms_parts_lots SMALLINT NOT NULL, ADD perms_parts_tags SMALLINT NOT NULL, ADD perms_parts_unit SMALLINT NOT NULL, ADD perms_parts_mass SMALLINT NOT NULL, ADD perms_parts_status SMALLINT NOT NULL, ADD perms_parts_mpn SMALLINT NOT NULL, ADD perms_currencies INT NOT NULL, ADD perms_measurement_units INT NOT NULL, DROP perms_parts_instock, DROP perms_parts_mininstock, DROP perms_parts_storelocation');
|
||||
$this->addSql('ALTER TABLE users ADD currency_id INT DEFAULT NULL, ADD settings LONGTEXT NOT NULL COMMENT \'(DC2Type:json)\', ADD perms_parts_category SMALLINT NOT NULL, ADD perms_parts_minamount SMALLINT NOT NULL, ADD perms_parts_lots SMALLINT NOT NULL, ADD perms_parts_tags SMALLINT NOT NULL, ADD perms_parts_unit SMALLINT NOT NULL, ADD perms_parts_mass SMALLINT NOT NULL, ADD perms_parts_status SMALLINT NOT NULL, ADD perms_parts_mpn SMALLINT NOT NULL, ADD perms_currencies INT NOT NULL, ADD perms_measurement_units INT NOT NULL, DROP config_currency, DROP perms_parts_instock, DROP perms_parts_mininstock, DROP perms_parts_storelocation');
|
||||
$this->addSql('ALTER TABLE users ADD CONSTRAINT FK_1483A5E938248176 FOREIGN KEY (currency_id) REFERENCES currencies (id)');
|
||||
$this->addSql('CREATE INDEX IDX_1483A5E938248176 ON users (currency_id)');
|
||||
}
|
||||
|
||||
public function down(Schema $schema) : void
|
||||
{
|
||||
// this down() migration is auto-generated, please modify it to your needs
|
||||
$this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.');
|
||||
|
||||
$this->addSql('ALTER TABLE `groups` ADD perms_parts_instock SMALLINT NOT NULL, ADD perms_parts_mininstock SMALLINT NOT NULL, ADD perms_parts_storelocation SMALLINT NOT NULL, DROP perms_parts_category, DROP perms_parts_minamount, DROP perms_parts_lots, DROP perms_parts_tags, DROP perms_parts_unit, DROP perms_parts_mass, DROP perms_parts_status, DROP perms_parts_mpn, DROP perms_currencies, DROP perms_measurement_units');
|
||||
$this->addSql('ALTER TABLE `users` DROP FOREIGN KEY FK_1483A5E938248176');
|
||||
$this->addSql('DROP INDEX IDX_1483A5E938248176 ON `users`');
|
||||
$this->addSql('ALTER TABLE `users` ADD config_currency VARCHAR(255) NOT NULL COLLATE utf8_general_ci, ADD perms_parts_instock SMALLINT NOT NULL, ADD perms_parts_mininstock SMALLINT NOT NULL, ADD perms_parts_storelocation SMALLINT NOT NULL, DROP currency_id, DROP settings, DROP perms_parts_category, DROP perms_parts_minamount, DROP perms_parts_lots, DROP perms_parts_tags, DROP perms_parts_unit, DROP perms_parts_mass, DROP perms_parts_status, DROP perms_parts_mpn, DROP perms_currencies, DROP perms_measurement_units');
|
||||
}
|
||||
}
|
|
@ -30,6 +30,7 @@
|
|||
namespace App\Security\Annotations;
|
||||
|
||||
use Doctrine\Common\Annotations\Annotation;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use \InvalidArgumentException;
|
||||
|
||||
/**
|
||||
|
@ -65,7 +66,7 @@ class ColumnSecurity
|
|||
|
||||
/**
|
||||
* @var string The name of the property. This is used to determine the default placeholder.
|
||||
* @Annotation\Enum({"integer", "string", "object", "boolean", "datetime"})
|
||||
* @Annotation\Enum({"integer", "string", "object", "boolean", "datetime", "collection"})
|
||||
*/
|
||||
public $type = 'string';
|
||||
|
||||
|
@ -97,6 +98,8 @@ class ColumnSecurity
|
|||
return '???';
|
||||
case 'object':
|
||||
return null;
|
||||
case 'collection':
|
||||
return new ArrayCollection();
|
||||
case 'boolean':
|
||||
return false;
|
||||
case 'datetime':
|
||||
|
|
|
@ -26,10 +26,10 @@ class PartVoter extends ExtendedVoter
|
|||
if (false !== strpos($attribute, '.')) {
|
||||
[$perm, $op] = explode('.', $attribute);
|
||||
|
||||
return in_array($op, $this->resolver->listOperationsForPermission('parts_'.$perm), false);
|
||||
return $this->resolver->isValidOperation('parts_' . $perm, $op);
|
||||
}
|
||||
|
||||
return in_array($attribute, $this->resolver->listOperationsForPermission('parts'), false);
|
||||
return $this->resolver->isValidOperation('parts', $attribute);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
|
@ -86,11 +86,9 @@ class StructureVoter extends ExtendedVoter
|
|||
case Supplier::class:
|
||||
return 'suppliers';
|
||||
case Currency::class:
|
||||
//TODO: Implement own permission
|
||||
return 'suppliers';
|
||||
return 'currencies';
|
||||
case MeasurementUnit::class:
|
||||
//TODO: Implement own permission
|
||||
return 'suppliers';
|
||||
return 'measurement_units';
|
||||
}
|
||||
//When the class is not supported by this class return null
|
||||
return null;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{% set delete_btn %}
|
||||
<button type="button" class="btn btn-danger lot_btn_delete" onclick="delete_attachment_entry(this);">
|
||||
<button type="button" class="btn btn-danger lot_btn_delete" onclick="delete_attachment_entry(this);" {% if not is_granted('attachments.delete', part) %}disabled{% endif %}>
|
||||
<i class="fas fa-trash-alt fa-fw"></i>
|
||||
{% trans %}attachment.delete{% endtrans %}
|
||||
</button>
|
||||
|
@ -7,7 +7,7 @@
|
|||
|
||||
{{ form_row(form.master_picture_attachment) }}
|
||||
|
||||
<table class="table table-striped table-sm" id="attachments_table" data-prototype="{{ form_widget(form.attachments.vars.prototype)|e('html_attr') }}">
|
||||
<table class="table table-striped table-sm" id="attachments_table" data-prototype="{% if form.attachments.vars.prototype is defined %}{{ form_widget(form.attachments.vars.prototype)|e('html_attr') }}{% endif %}">
|
||||
<tbody>
|
||||
{% for attachment in form.attachments %}
|
||||
<tr>
|
||||
|
@ -54,7 +54,7 @@
|
|||
</tbody>
|
||||
</table>
|
||||
|
||||
<button type="button" class="btn btn-success" onclick="create_attachment_entry(this)">
|
||||
<button type="button" class="btn btn-success" onclick="create_attachment_entry(this)" {% if not is_granted('attachments.create', part) %}disabled{% endif %}>
|
||||
<i class="fas fa-plus-square fa-fw"></i>
|
||||
{% trans %}attachment.create{% endtrans %}
|
||||
</button>
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
{% set delete_btn %}
|
||||
<button type="button" class="btn btn-danger lot_btn_delete" onclick="delete_lot_entry(this);">
|
||||
<button type="button" class="btn btn-danger lot_btn_delete" onclick="delete_lot_entry(this);"
|
||||
{% if not is_granted('lots.delete', part) %}disabled{% endif %}>
|
||||
<i class="fas fa-trash-alt fa-fw"></i>
|
||||
{% trans %}part_lot.delete{% endtrans %}
|
||||
</button>
|
||||
{% endset %}
|
||||
|
||||
|
||||
<table class="table table-striped table-sm" id="lots_table" data-prototype="{{ form_widget(form.partLots.vars.prototype)|e('html_attr') }}">
|
||||
<table class="table table-striped table-sm" id="lots_table" data-prototype="{% if form.partLots.vars.prototype is defined %}{{ form_widget(form.partLots.vars.prototype)|e('html_attr') }}{% endif %}">
|
||||
<tbody>
|
||||
{% for lot in form.partLots %}
|
||||
<tr>
|
||||
|
@ -21,7 +22,8 @@
|
|||
</tbody>
|
||||
</table>
|
||||
|
||||
<button type="button" class="btn btn-success" onclick="create_lot_entry(this)">
|
||||
<button type="button" class="btn btn-success" onclick="create_lot_entry(this)"
|
||||
{% if not is_granted('lots.create', part) %}disabled{% endif %}>
|
||||
<i class="fas fa-plus-square fa-fw"></i>
|
||||
{% trans %}part_lot.create{% endtrans %}
|
||||
</button>
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
{% form_theme form with ['Parts/edit/edit_form_styles.html.twig', "bootstrap_4_layout.html.twig"] %}
|
||||
|
||||
<table class="table table-striped table-sm" id="orderdetails_table" data-prototype="{{ form_widget(form.orderdetails.vars.prototype)|e('html_attr') }}">
|
||||
<table class="table table-striped table-sm" id="orderdetails_table" data-prototype="{% if form.orderdetails.vars.prototype is defined %}{{ form_widget(form.orderdetails.vars.prototype)|e('html_attr') }}{% endif %}">
|
||||
<tbody>
|
||||
{% for detail in form.orderdetails %}
|
||||
{{ form_widget(detail) }}
|
||||
{{ form_widget(detail, {'disable_delete' : not is_granted('orderdetails.delete', part)}) }}
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<button type="button" class="btn btn-success" onclick="create_orderdetail_entry(this)">
|
||||
<button type="button" class="btn btn-success" onclick="create_orderdetail_entry(this)" {% if not is_granted('orderdetails.create', part) %}disabled{% endif %}>
|
||||
<i class="fas fa-plus-square fa-fw"></i>
|
||||
{% trans %}orderdetail.create{% endtrans %}
|
||||
</button>
|
||||
|
|
|
@ -53,7 +53,7 @@
|
|||
</button>
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" class="btn btn-danger order_btn_delete" onclick="delete_orderdetail_entry(this);" title="{% trans %}orderdetail.delete{% endtrans %}">
|
||||
<button type="button" class="btn btn-danger order_btn_delete" onclick="delete_orderdetail_entry(this);" title="{% trans %}orderdetail.delete{% endtrans %}" {% if disable_delete %}disabled{% endif %}>
|
||||
<i class="fas fa-trash-alt fa-fw"></i>
|
||||
</button>
|
||||
{{ form_errors(form) }}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue