Tinebase_Filesystem - introduce pin protected folders
authorPaul Mehrer <p.mehrer@metaways.de>
Tue, 18 Jul 2017 11:56:44 +0000 (13:56 +0200)
committerPaul Mehrer <p.mehrer@metaways.de>
Thu, 20 Jul 2017 10:30:44 +0000 (12:30 +0200)
Change-Id: I931d1800f543d72a274b2a4bfe622965fcbff8c6
Reviewed-on: http://gerrit.tine20.com/customers/5237
Reviewed-by: Paul Mehrer <p.mehrer@metaways.de>
Tested-by: Paul Mehrer <p.mehrer@metaways.de>
tine20/Filemanager/Controller/Node.php
tine20/Tinebase/Auth/SecondFactor/Abstract.php
tine20/Tinebase/FileSystem.php
tine20/Tinebase/Frontend/WebDAV/Container.php
tine20/Tinebase/Model/Tree/Node.php
tine20/Tinebase/Model/Tree/Node/Filter.php
tine20/Tinebase/Setup/Update/Release10.php
tine20/Tinebase/Setup/setup.xml

index 50b0651..677a0c4 100644 (file)
@@ -171,7 +171,7 @@ class Filemanager_Controller_Node extends Tinebase_Controller_Record_Abstract
     {
         // protect against file object spoofing
         foreach (array_keys($_record->toArray()) as $property) {
-            if (! in_array($property, array('name', 'description', 'relations', 'customfields', 'tags', 'notes', 'acl_node', 'grants', 'quota', Tinebase_Model_Tree_Node::XPROPS_NOTIFICATION, Tinebase_Model_Tree_Node::XPROPS_REVISION))) {
+            if (! in_array($property, array('name', 'description', 'relations', 'customfields', 'tags', 'notes', 'acl_node', 'grants', 'quota', Tinebase_Model_Tree_Node::XPROPS_NOTIFICATION, Tinebase_Model_Tree_Node::XPROPS_REVISION, 'pin_protected'))) {
                 $_record->{$property} = $_oldRecord->{$property};
             }
         }
@@ -179,6 +179,7 @@ class Filemanager_Controller_Node extends Tinebase_Controller_Record_Abstract
         if (!Tinebase_Core::getUser()->hasGrant($_record, Tinebase_Model_Grants::GRANT_ADMIN, 'Tinebase_Model_Tree_Node')) {
             $_record->{Tinebase_Model_Tree_Node::XPROPS_REVISION} = $_oldRecord->{Tinebase_Model_Tree_Node::XPROPS_REVISION};
             $_record->quota = $_oldRecord->quota;
+            $_record->pin_protected = $_oldRecord->pin_protected;
         }
 
         // update node acl
index 8868f11..9c349a2 100644 (file)
@@ -44,9 +44,19 @@ abstract class Tinebase_Auth_SecondFactor_Abstract
      */
     public static function hasValidSecondFactor()
     {
+
         if (! Tinebase_Session::isStarted()) {
-            if (Tinebase_Core::isLogLevel(Zend_Log::INFO)) Tinebase_Core::getLogger()->info(__METHOD__ . '::' . __LINE__
-                . ' No session started to check second factor in session');
+            if (Tinebase_Core::isLogLevel(Zend_Log::INFO)) {
+                Tinebase_Core::getLogger()->info(__METHOD__ . '::' . __LINE__
+                    . ' No session started to check second factor in session');
+            }
+            return true;
+        }
+        if (! Tinebase_Session::getSessionEnabled()) {
+            if (Tinebase_Core::isLogLevel(Zend_Log::INFO)) {
+                Tinebase_Core::getLogger()->info(__METHOD__ . '::' . __LINE__
+                    . ' Session not enabled to check second factor in session');
+            }
             return true;
         }
         $currentValidUntil = Tinebase_Session::getSessionNamespace()->secondFactorValidUntil;
index f2f0fd3..9e01ed0 100644 (file)
@@ -2588,6 +2588,16 @@ class Tinebase_FileSystem implements
     {
         // always refetch node to have current acl_node value
         $node = $this->get($_containerId);
+        if (null !== $node->acl_node && !Tinebase_Auth_SecondFactor_Abstract::hasValidSecondFactor()) {
+            if ($node->getId() !== $node->acl_node) {
+                $acl_node = $this->get($node->acl_node);
+            } else {
+                $acl_node = $node;
+            }
+            if ($acl_node->pin_protected) {
+                return false;
+            }
+        }
         /** @noinspection PhpUndefinedMethodInspection */
         $account = $_accountId instanceof Tinebase_Model_FullUser
             ? $_accountId
index ecf2552..b850d4b 100644 (file)
@@ -167,6 +167,9 @@ class Tinebase_Frontend_WebDAV_Container extends Tinebase_WebDav_Container_Abstr
         
         try {
             $childNode = Tinebase_FileSystem::getInstance()->stat($this->_path . '/' . $name);
+            if (!Tinebase_Core::getUser()->hasGrant($childNode, Tinebase_Model_Grants::GRANT_READ)) {
+                throw new Sabre\DAV\Exception\Forbidden('You do not have access');
+            }
         } catch (Tinebase_Exception_NotFound $tenf) {
             throw new Sabre\DAV\Exception\NotFound('file not found: ' . $this->_path . '/' . $name);
         }
@@ -192,7 +195,9 @@ class Tinebase_Frontend_WebDAV_Container extends Tinebase_WebDav_Container_Abstr
         
         // Loop through the directory, and create objects for each node
         foreach (Tinebase_FileSystem::getInstance()->scanDir($this->_path) as $node) {
-            $children[] = $this->getChild($node->name);
+            if (Tinebase_Core::getUser()->hasGrant($node, Tinebase_Model_Grants::GRANT_READ)) {
+                $children[] = $this->getChild($node->name);
+            }
         }
         
         return $children;
index 9cd9b6e..7d27813 100644 (file)
@@ -34,6 +34,7 @@
  * @property    string             preview_count
  * @property    integer            quota
  * @property    Tinebase_Record_RecordSet grants
+ * @property    bool               pin_protected
  */
 class Tinebase_Model_Tree_Node extends Tinebase_Record_Abstract
 {
@@ -143,6 +144,11 @@ class Tinebase_Model_Tree_Node extends Tinebase_Record_Abstract
         'revision_size'         => array(Zend_Filter_Input::ALLOW_EMPTY => true),
         'preview_count'         => array(Zend_Filter_Input::ALLOW_EMPTY => true, 'Digits',
             Zend_Filter_Input::DEFAULT_VALUE => 0),
+        'pin_protected'         => array(
+            Zend_Filter_Input::ALLOW_EMPTY => true,
+            Zend_Filter_Input::DEFAULT_VALUE => false,
+            array('InArray', array(true, false))
+        ),
 
         // not persistent
         'container_name' => array(Zend_Filter_Input::ALLOW_EMPTY => true),
@@ -153,7 +159,7 @@ class Tinebase_Model_Tree_Node extends Tinebase_Record_Abstract
         'tempFile'       => array(Zend_Filter_Input::ALLOW_EMPTY => true),
         'stream'         => array(Zend_Filter_Input::ALLOW_EMPTY => true),
         // acl grants
-        'grants'                => array(Zend_Filter_Input::ALLOW_EMPTY => true),
+        'grants'         => array(Zend_Filter_Input::ALLOW_EMPTY => true),
     );
 
     /**
index be7f9db..7e250b7 100644 (file)
@@ -130,6 +130,10 @@ class Tinebase_Model_Tree_Node_Filter extends Tinebase_Model_Filter_GrantsFilter
     {
         parent::_appendGrantsFilter($select, $backend, $user);
 
+        if (!Tinebase_Auth_SecondFactor_Abstract::hasValidSecondFactor()) {
+            $select->where('pin_protected = 0');
+        }
+
         // TODO do something when acl_node = NULL?
     }
 
index ff5787e..638f219 100644 (file)
@@ -1970,4 +1970,23 @@ class Tinebase_Setup_Update_Release10 extends Setup_Update_Abstract
 
         return $method;
     }
+
+    /**
+     * update to 10.39
+     *
+     * tree_nodes add
+     */
+    public function update_38()
+    {
+        if (! $this->_backend->columnExists('pin_protected', 'tree_nodes')) {
+            $this->_backend->addCol('tree_nodes', new Setup_Backend_Schema_Field_Xml('<field>
+                    <name>pin_protected</name>
+                    <type>boolean</type>
+                    <default>false</default>
+                    <notnull>true</notnull>
+                </field>'));
+            $this->setTableVersion('tree_nodes', 6);
+        }
+        $this->setApplicationVersion('Tinebase', '10.39');
+    }
 }
index f1057af..292eb27 100644 (file)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 <application>
     <name>Tinebase</name>
-    <version>10.38</version>
+    <version>10.39</version>
     <tables>
         <table>
             <name>applications</name>
 
         <table>
             <name>tree_nodes</name>
-            <version>5</version>
+            <version>6</version>
             <declaration>
                 <field>
                     <name>id</name>
                     <notnull>false</notnull>
                     <length>64</length>
                 </field>
+                <field>
+                    <name>pin_protected</name>
+                    <type>boolean</type>
+                    <default>false</default>
+                    <notnull>true</notnull>
+                </field>
                 <index>
                     <name>id</name>
                     <primary>true</primary>