new: [metafield editor permission] added

- users/org admins/group admins/community admins can now only modify metafield data on any object if the permission is set for their role
- Since some communities use this for ACL to secondary tools, this will allow them to restrict who can modify them
pull/170/merge
iglocska 2024-08-24 16:25:58 +02:00
parent 25e55a620b
commit 6270ae8e18
No known key found for this signature in database
GPG Key ID: BEA224F1FEF113AC
4 changed files with 53 additions and 8 deletions

View File

@ -0,0 +1,30 @@
<?php
declare(strict_types=1);
use Migrations\AbstractMigration;
use Phinx\Db\Adapter\MysqlAdapter;
final class RoleMetaEditor extends AbstractMigration
{
public $autoId = false; // turn off automatic `id` column create. We want it to be `int(10) unsigned`
public function change(): void
{
$exists = $this->table('roles')->hasColumn('perm_meta_field_editor');
if (!$exists) {
$this->table('roles')
->addColumn('perm_meta_field_editor', 'boolean', [
'default' => 0,
'null' => false,
])
->addIndex('perm_meta_field_editor')
->update();
}
$builder = $this->getQueryBuilder();
$builder
->update('roles')
->set('perm_meta_field_editor', true)
->where(['perm_admin' => true])
->execute();
}
}

View File

@ -427,7 +427,9 @@ class CRUDComponent extends Component
public function add(array $params = []): void public function add(array $params = []): void
{ {
$data = $this->Table->newEmptyEntity(); $data = $this->Table->newEmptyEntity();
if ($this->metaFieldsSupported()) { $user = $this->Controller->ACL->getUser();
$metaFieldsEnabled = $user['role']['perm_meta_field_editor'] && $this->metaFieldsSupported();
if ($metaFieldsEnabled) {
$metaTemplates = $this->getMetaTemplates(); $metaTemplates = $this->getMetaTemplates();
$data = $this->attachMetaTemplatesIfNeeded($data, $metaTemplates->toArray()); $data = $this->attachMetaTemplatesIfNeeded($data, $metaTemplates->toArray());
if (isset($params['afterFind'])) { if (isset($params['afterFind'])) {
@ -452,7 +454,7 @@ class CRUDComponent extends Component
throw new NotFoundException(__('Could not save {0} due to the marshaling failing. Your input is bad and you should feel bad.', $this->ObjectAlias)); throw new NotFoundException(__('Could not save {0} due to the marshaling failing. Your input is bad and you should feel bad.', $this->ObjectAlias));
} }
} }
if ($this->metaFieldsSupported()) { if ($metaFieldsEnabled) {
$massagedData = $this->massageMetaFields($data, $input, $metaTemplates); $massagedData = $this->massageMetaFields($data, $input, $metaTemplates);
unset($input['MetaTemplates']); // Avoid MetaTemplates to be overriden when patching entity unset($input['MetaTemplates']); // Avoid MetaTemplates to be overriden when patching entity
$data = $massagedData['entity']; $data = $massagedData['entity'];
@ -526,10 +528,10 @@ class CRUDComponent extends Component
if (!empty($errors)) { if (!empty($errors)) {
if (count($errors) == 1) { if (count($errors) == 1) {
$field = array_keys($errors)[0]; $field = array_keys($errors)[0];
$fieldError = json_encode($errors[$field]); $fieldError = implode(', ', array_values($errors[$field]));
$validationMessage = __('{0}: {1}', $field, $fieldError); $validationMessage = __('{0}: {1}', $field, $fieldError);
} else { } else {
$validationMessage = __('There has been validation issues with multiple fields: {0}', json_encode($errors)); $validationMessage = __('There has been validation issues with multiple fields');
} }
} }
return $validationMessage; return $validationMessage;
@ -692,7 +694,9 @@ class CRUDComponent extends Component
$params['contain'][] = 'Tags'; $params['contain'][] = 'Tags';
$this->setAllTags(); $this->setAllTags();
} }
if ($this->metaFieldsSupported()) { $user = $this->Controller->ACL->getUser();
$metaFieldsEnabled = $user['role']['perm_meta_field_editor'] && $this->metaFieldsSupported();
if ($metaFieldsEnabled) {
if (empty($params['contain'])) { if (empty($params['contain'])) {
$params['contain'] = []; $params['contain'] = [];
} }
@ -710,7 +714,7 @@ class CRUDComponent extends Component
$query->where($params['conditions']); $query->where($params['conditions']);
} }
$data = $query->first(); $data = $query->first();
if ($this->metaFieldsSupported()) { if ($metaFieldsEnabled) {
$metaTemplates = $this->getMetaTemplates(); $metaTemplates = $this->getMetaTemplates();
$data = $this->attachMetaTemplatesIfNeeded($data, $metaTemplates->toArray()); $data = $this->attachMetaTemplatesIfNeeded($data, $metaTemplates->toArray());
} }
@ -734,7 +738,7 @@ class CRUDComponent extends Component
throw new NotFoundException(__('Could not save {0} due to the marshaling failing. Your input is bad and you should feel bad.', $this->ObjectAlias)); throw new NotFoundException(__('Could not save {0} due to the marshaling failing. Your input is bad and you should feel bad.', $this->ObjectAlias));
} }
} }
if ($this->metaFieldsSupported()) { if ($metaFieldsEnabled) {
$massagedData = $this->massageMetaFields($data, $input, $metaTemplates); $massagedData = $this->massageMetaFields($data, $input, $metaTemplates);
unset($input['MetaTemplates']); // Avoid MetaTemplates to be overriden when patching entity unset($input['MetaTemplates']); // Avoid MetaTemplates to be overriden when patching entity
$data = $massagedData['entity']; $data = $massagedData['entity'];
@ -749,7 +753,7 @@ class CRUDComponent extends Component
} }
$savedData = $this->Table->save($data); $savedData = $this->Table->save($data);
if ($savedData !== false) { if ($savedData !== false) {
if ($this->metaFieldsSupported() && !empty($metaFieldsToDelete)) { if ($metaFieldsEnabled && !empty($metaFieldsToDelete)) {
foreach ($metaFieldsToDelete as $k => $v) { foreach ($metaFieldsToDelete as $k => $v) {
if ($v === null) { if ($v === null) {
unset($metaFieldsToDelete[$k]); unset($metaFieldsToDelete[$k]);

View File

@ -32,6 +32,11 @@
'type' => 'checkbox', 'type' => 'checkbox',
'label' => 'Sync permission' 'label' => 'Sync permission'
], ],
[
'field' => 'perm_meta_field_editor',
'type' => 'checkbox',
'label' => 'Meta field modification privilege'
],
[ [
'field' => 'is_default', 'field' => 'is_default',
'type' => 'checkbox', 'type' => 'checkbox',

View File

@ -74,6 +74,12 @@ echo $this->element('genericElements/IndexTable/index_table', [
'data_path' => 'perm_sync', 'data_path' => 'perm_sync',
'element' => 'boolean' 'element' => 'boolean'
], ],
[
'name' => __('Meta field Editor'),
'sort' => 'perm_meta_field_editor',
'data_path' => 'perm_meta_field_editor',
'element' => 'boolean'
],
[ [
'name' => 'Default', 'name' => 'Default',
'sort' => 'is_default', 'sort' => 'is_default',