[BUGFIX] Only show inline field if allowed 56/47456/2
authorStefan Froemken <froemken@gmail.com>
Fri, 5 Feb 2016 13:47:31 +0000 (14:47 +0100)
committerChristian Kuhn <lolli@schwarzbu.ch>
Thu, 31 Mar 2016 09:34:11 +0000 (11:34 +0200)
If an editor does not have access to fields of a related
record, the rendering should be stopped right then.

Resolves: #73146
Releases: master,7.6
Change-Id: I720c872a8a21d62a6aa48b6d11735f69310b5f6e
Reviewed-on: https://review.typo3.org/47456
Reviewed-by: Christian Kuhn <lolli@schwarzbu.ch>
Tested-by: Christian Kuhn <lolli@schwarzbu.ch>
typo3/sysext/backend/Classes/Form/FormDataProvider/TcaInline.php
typo3/sysext/backend/Tests/Unit/Form/FormDataProvider/TcaInlineTest.php [new file with mode: 0644]

index 3bc75fa..126c552 100644 (file)
@@ -41,7 +41,7 @@ class TcaInline extends AbstractDatabaseRecordProvider implements FormDataProvid
         $result = $this->addInlineFirstPid($result);
 
         foreach ($result['processedTca']['columns'] as $fieldName => $fieldConfig) {
-            if (empty($fieldConfig['config']['type']) || $fieldConfig['config']['type'] !== 'inline') {
+            if (!$this->isInlineField($fieldConfig) || !$this->isUserAllowedToModify($fieldConfig)) {
                 continue;
             }
             $result['processedTca']['columns'][$fieldName]['children'] = [];
@@ -55,6 +55,28 @@ class TcaInline extends AbstractDatabaseRecordProvider implements FormDataProvid
     }
 
     /**
+     * Is column of type "inline"
+     *
+     * @param array $fieldConfig
+     * @return bool
+     */
+    protected function isInlineField($fieldConfig)
+    {
+        return !empty($fieldConfig['config']['type']) && $fieldConfig['config']['type'] === 'inline';
+    }
+
+    /**
+     * Is user allowed to modify child elements
+     *
+     * @param array $fieldConfig
+     * @return bool
+     */
+    protected function isUserAllowedToModify($fieldConfig)
+    {
+        return $this->getBackendUser()->check('tables_modify', $fieldConfig['config']['foreign_table']);
+    }
+
+    /**
      * The "entry" pid for inline records. Nested inline records can potentially hang around on different
      * pid's, but the entry pid is needed for AJAX calls, so that they would know where the action takes place on the page structure.
      *
diff --git a/typo3/sysext/backend/Tests/Unit/Form/FormDataProvider/TcaInlineTest.php b/typo3/sysext/backend/Tests/Unit/Form/FormDataProvider/TcaInlineTest.php
new file mode 100644 (file)
index 0000000..06e7c24
--- /dev/null
@@ -0,0 +1,151 @@
+<?php
+namespace TYPO3\CMS\Backend\Tests\Unit\Form\FormDataProvider;
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+use Prophecy\Prophecy\ObjectProphecy;
+use TYPO3\CMS\Backend\Form\FormDataProvider\TcaInline;
+use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
+use TYPO3\CMS\Core\Tests\UnitTestCase;
+
+/**
+ * Test case
+ */
+class TcaInlineTest extends UnitTestCase
+{
+    /**
+     * @var TcaInline
+     */
+    protected $subject;
+
+    /**
+     * @var BackendUserAuthentication | ObjectProphecy
+     */
+    protected $beUserProphecy;
+
+    protected function setUp()
+    {
+        $this->beUserProphecy = $this->prophesize(BackendUserAuthentication::class);
+        $GLOBALS['BE_USER'] = $this->beUserProphecy->reveal();
+
+        $this->subject = new TcaInline();
+    }
+
+    /**
+     * @var array Set of default controls
+     */
+    protected $defaultConfig = [
+        'processedTca' => [
+            'columns' => [
+                'aField' => [
+                    'config' => [
+                        'type' => 'inline',
+                        'foreign_table' => 'aForeignTableName'
+                    ],
+                ],
+            ],
+        ],
+        'inlineFirstPid' => 0,
+    ];
+
+    /**
+     * @test
+     */
+    public function addDataWithoutModifyRightsButWithInlineTypeWillNotParseChildren()
+    {
+        $input = [
+            'processedTca' => [
+                'columns' => [
+                    'aField' => [
+                        'config' => [
+                            'type' => 'inline',
+                            'foreign_table' => 'aForeignTableName',
+                        ],
+                    ],
+                ],
+            ],
+        ];
+
+        $this->beUserProphecy
+            ->check(
+                'tables_modify',
+                $input['processedTca']['columns']['aField']['config']['foreign_table']
+            )
+            ->shouldBeCalled()
+            ->willReturn(false);
+
+        $this->assertEquals($this->defaultConfig, $this->subject->addData($input));
+    }
+
+    /**
+     * @test
+     */
+    public function addDataWithUserRightsButWithoutInlineTypeWillNotParseChildren()
+    {
+        $input = [
+            'processedTca' => [
+                'columns' => [
+                    'aField' => [
+                        'config' => [
+                            'type' => 'input',
+                            'foreign_table' => 'aForeignTableName',
+                        ],
+                    ],
+                ],
+            ],
+        ];
+
+        $this->beUserProphecy
+            ->check(
+                'tables_modify',
+                $input['processedTca']['columns']['aField']['config']['foreign_table']
+            )
+            ->shouldNotBeCalled();
+
+        $expected = $this->defaultConfig;
+        $expected['processedTca']['columns']['aField']['config']['type'] = 'input';
+        $this->assertEquals($expected, $this->subject->addData($input));
+    }
+
+    /**
+     * @test
+     */
+    public function addDataWithInlineTypeAndModifyRightsWillAddChildren()
+    {
+        $input = [
+            'processedTca' => [
+                'columns' => [
+                    'aField' => [
+                        'config' => [
+                            'type' => 'inline',
+                            'foreign_table' => 'aForeignTableName',
+                        ],
+                    ],
+                ],
+            ],
+        ];
+
+        $this->beUserProphecy
+            ->check(
+                'tables_modify',
+                $input['processedTca']['columns']['aField']['config']['foreign_table']
+            )
+            ->shouldBeCalled()
+            ->willReturn(true);
+
+        $expected = $this->defaultConfig;
+        $expected['processedTca']['columns']['aField']['children'] = [];
+        $this->assertEquals($expected, $this->subject->addData($input));
+    }
+}