Filemanager - allow notification props update on read grant
authorPaul Mehrer <p.mehrer@metaways.de>
Tue, 6 Jun 2017 07:04:58 +0000 (09:04 +0200)
committerPaul Mehrer <p.mehrer@metaways.de>
Tue, 6 Jun 2017 08:09:36 +0000 (10:09 +0200)
allow to edit ones own notification properties with only read
grant given

added test

Change-Id: I237cdbc320f66867143c1d72a064cc04bb0c8315
Reviewed-on: http://gerrit.tine20.com/customers/4825
Tested-by: Jenkins CI (http://ci.tine20.com/)
Reviewed-by: Paul Mehrer <p.mehrer@metaways.de>
Tested-by: Paul Mehrer <p.mehrer@metaways.de>
tests/tine20/Filemanager/ControllerTests.php
tine20/Filemanager/Controller/Node.php

index 2d0f0cb..b25da72 100644 (file)
@@ -65,4 +65,63 @@ class Filemanager_ControllerTests extends TestCase
         self::setExpectedException('Tinebase_Exception_NotFound', 'child:');
         Tinebase_FileSystem::getInstance()->stat($personalFolderPath);
     }
+
+    public function testNotificationUpdateForReadOnly()
+    {
+        $oldUser = Tinebase_Core::getUser();
+        /** @var Tinebase_Model_FullUser $sclever */
+        $sclever = $this->_personas['sclever'];
+        try {
+            $personalFolderPath = $this->_getPersonalPath($oldUser);
+            $translation = Tinebase_Translation::getTranslation('Tinebase');
+            $fileSystem = Tinebase_FileSystem::getInstance();
+            $fileManager = Filemanager_Controller_Node::getInstance();
+            $personalFolderName = sprintf($translation->_("%s's personal files"), $oldUser->accountFullName);
+            $node = $fileSystem->stat($personalFolderPath . '/' . $personalFolderName);
+
+            // try a failing update
+            Tinebase_Core::set(Tinebase_Core::USER, $sclever);
+            $scleverNotificationProps = array(
+                Tinebase_Model_Tree_Node::XPROPS_NOTIFICATION_ACCOUNT_ID => $sclever->getId(),
+                Tinebase_Model_Tree_Node::XPROPS_NOTIFICATION_ACCOUNT_TYPE => Tinebase_Acl_Rights::ACCOUNT_TYPE_USER,
+                Tinebase_Model_Tree_Node::XPROPS_NOTIFICATION_ACTIVE => true,
+            );
+            $node->xprops(Tinebase_Model_Tree_Node::XPROPS_NOTIFICATION)[] = $scleverNotificationProps;
+            $failed = false;
+            try {
+                $fileManager->update($node);
+            } catch (Tinebase_Exception_AccessDenied $tead) {
+                $failed = true;
+            }
+            static::assertTrue($failed);
+
+            // now set grants so update can work
+            Tinebase_Core::set(Tinebase_Core::USER, $oldUser);
+            $node = $fileManager->get($node->getId());
+            $node->grants = $fileSystem->getGrantsOfContainer($node);
+            $node->grants->addRecord(new Tinebase_Model_Grants(array(
+                'account_type'      => Tinebase_Acl_Rights::ACCOUNT_TYPE_USER,
+                'account_id'        => $sclever->getId(),
+                Tinebase_Model_Grants::GRANT_READ => true,
+            )));
+            $node = $fileManager->update($node);
+
+            // do update again, it should work now
+            Tinebase_Core::set(Tinebase_Core::USER, $sclever);
+            $scleverNotificationProps = array(
+                Tinebase_Model_Tree_Node::XPROPS_NOTIFICATION_ACCOUNT_ID => $sclever->getId(),
+                Tinebase_Model_Tree_Node::XPROPS_NOTIFICATION_ACCOUNT_TYPE => Tinebase_Acl_Rights::ACCOUNT_TYPE_USER,
+                Tinebase_Model_Tree_Node::XPROPS_NOTIFICATION_ACTIVE => true,
+            );
+            $node->xprops(Tinebase_Model_Tree_Node::XPROPS_NOTIFICATION)[] = $scleverNotificationProps;
+            $node = $fileManager->update($node);
+            static::assertEquals(1, count($node->xprops(Tinebase_Model_Tree_Node::XPROPS_NOTIFICATION)));
+            static::assertTrue(
+                isset($node->xprops(Tinebase_Model_Tree_Node::XPROPS_NOTIFICATION)[0]) &&
+                $scleverNotificationProps == $node->xprops(Tinebase_Model_Tree_Node::XPROPS_NOTIFICATION)[0]
+            );
+        } finally {
+            Tinebase_Core::set(Tinebase_Core::USER, $oldUser);
+        }
+    }
 }
index f5ddddb..30e98b2 100644 (file)
@@ -108,7 +108,43 @@ class Filemanager_Controller_Node extends Tinebase_Controller_Record_Abstract
     public function update(Tinebase_Record_Interface $_record)
     {
         if (! $this->_backend->checkACLNode($_record, 'update')) {
-            throw new Tinebase_Exception_AccessDenied('No permission to update nodes.');
+            if (! $this->_backend->checkACLNode($_record, 'get')) {
+                throw new Tinebase_Exception_AccessDenied('No permission to update nodes.');
+            }
+            // we allow only notification updates for the current user itself
+            $usersNotificationSettings = null;
+            $currentUserId = Tinebase_Core::getUser()->getId();
+            foreach ($_record->xprops(Tinebase_Model_Tree_Node::XPROPS_NOTIFICATION) as $xpNotification) {
+                if (isset($xpNotification[Tinebase_Model_Tree_Node::XPROPS_NOTIFICATION_ACCOUNT_ID]) &&
+                        isset($xpNotification[Tinebase_Model_Tree_Node::XPROPS_NOTIFICATION_ACCOUNT_TYPE]) &&
+                        Tinebase_Acl_Rights::ACCOUNT_TYPE_USER === $xpNotification[Tinebase_Model_Tree_Node::XPROPS_NOTIFICATION_ACCOUNT_TYPE] &&
+                        $currentUserId ===  $xpNotification[Tinebase_Model_Tree_Node::XPROPS_NOTIFICATION_ACCOUNT_ID]) {
+                    $usersNotificationSettings = $xpNotification;
+                    break;
+                }
+            }
+
+            if (null !== $usersNotificationSettings) {
+                // we reset all input and then just apply the notification settings for the current user
+                $_record = $this->get($_record->getId());
+                $found = false;
+                foreach ($_record->xprops(Tinebase_Model_Tree_Node::XPROPS_NOTIFICATION) as &$xpNotification) {
+                    if (isset($xpNotification[Tinebase_Model_Tree_Node::XPROPS_NOTIFICATION_ACCOUNT_ID]) &&
+                            isset($xpNotification[Tinebase_Model_Tree_Node::XPROPS_NOTIFICATION_ACCOUNT_TYPE]) &&
+                            Tinebase_Acl_Rights::ACCOUNT_TYPE_USER === $xpNotification[Tinebase_Model_Tree_Node::XPROPS_NOTIFICATION_ACCOUNT_TYPE] &&
+                            $currentUserId ===  $xpNotification[Tinebase_Model_Tree_Node::XPROPS_NOTIFICATION_ACCOUNT_ID]) {
+                        $xpNotification = $usersNotificationSettings;
+                        $found = true;
+                        break;
+                    }
+                }
+                if (false === $found) {
+                    $_record->xprops(Tinebase_Model_Tree_Node::XPROPS_NOTIFICATION)[] = $usersNotificationSettings;
+                }
+                // now continue to do the update
+            } else {
+                throw new Tinebase_Exception_AccessDenied('No permission to update nodes.');
+            }
         }
 
         return parent::update($_record);