2012-02-15 58 views
3

到目前为止,我一直无法在SabreDAV中成功实现ACL(权限)。如何在SabreDAV中为CalDAV实现自定义ACL PHP服务器

我在Code Igniter中使用自己的Auth,Principal和CalDAV后端实现了SabreDAV。从控制器这样的实际代码:

<?php if (! defined('BASEPATH')) exit('No direct script access allowed'); 

class CalDAV extends CI_Controller { 

    public function _remap() { 
     $this->load->library('SabreDAV'); 

     $authBackend = new SabreDAV_DAV_Auth_Backend_Tank_Auth; 
     $principalBackend = new Sabre_DAVACL_PrincipalBackend_Click4Time; 
     $calendarBackend = new Sabre_CalDAV_Backend_Click4Time; 

     // Directory tree 
     $tree = array(
      new Sabre_DAVACL_PrincipalCollection($principalBackend), 
      new Sabre_CalDAV_CalendarRootNode($principalBackend, $calendarBackend) 
     );  

     // The object tree needs in turn to be passed to the server class 
     $server = new Sabre_DAV_Server($tree); 

     // You are highly encouraged to set your WebDAV server base url. Without it, 
     // SabreDAV will guess, but the guess is not always correct. Putting the 
     // server on the root of the domain will improve compatibility. 
     $server->setBaseUri('/caldav/'); 

     // Authentication plugin 
     $authPlugin = new Sabre_DAV_Auth_Plugin($authBackend, 'SabreDAV'); 
     $server->addPlugin($authPlugin); 

     // CalDAV plugin 
     $caldavPlugin = new Sabre_CalDAV_Plugin(); 
     $server->addPlugin($caldavPlugin); 

     // ACL plugin 
     $aclPlugin = new Sabre_DAVACL_Custom; 
     $server->addPlugin($aclPlugin); 

     // Support for html frontend 
     $browser = new Sabre_DAV_Browser_Plugin(); 
     $server->addPlugin($browser); 

     $server->exec(); 
    } 
} 

我在执行权限当前的尝试已经通过我的自定义ACL插件:

<?php 

class Sabre_DAVACL_Custom extends Sabre_DAVACL_Plugin { 

    public $allowAccessToNodesWithoutACL = false; 

    private function _getCurrentUserName() { 
     $authPlugin = $this->server->getPlugin('auth'); 
     if (is_null($authPlugin)) return null; 

     return $authPlugin->getCurrentUser(); 
    } 

    public function getACL($node) { 
     $user = $this->_getCurrentUserName(); 
     $path = $node->getName(); 

     if ($path == 'calendars' || $path == 'principals' || $path == 'root') { 
      return array(
       array(
        'privilege' => '{DAV:}read', 
        'principal' => 'principals/' . $user, 
        'protected' => true, 
       ) 
      ); 
     } 
     else if ($path == 'calendars/' . $user) { 
      return array(
       array(
        'privilege' => '{DAV:}read', 
        'principal' => 'principals/' . $user, 
        'protected' => true, 
       ) 
      ); 
     } 

     return array(); 
    } 
} 

此代码非常作品除了第二支票应授权用户查看他或她自己的日历。我无法获得$ node的完整路径名称。

这可能是错误的实现方式,但我一直无法找到任何文档来确认这是实现ACL的方式。

+0

根据http://code.google.com/p/sabredav/wiki/ACL#Setting_up ACL支持是新的,需要生成自定义节点来得到它的工作。 – 2012-02-15 22:42:42

回答

3

我正在使用不同的尝试,我扩展了插件,就像你做的一样,但后来我替换为getSupportedPrivilegeSet($node)

在sabredav

1.8.6它看起来像这样:

public function getSupportedPrivilegeSet($node) { 

    if (is_string($node)) { 
     $node = $this->server->tree->getNodeForPath($node); 
    } 

    if ($node instanceof IACL) { 
     $result = $node->getSupportedPrivilegeSet(); 

     if ($result) 
      return $result; 
    } 

    return self::getDefaultSupportedPrivilegeSet(); 

} 

现在你可以用它代替我发现更多有用的路径,即类:

class DavCalAcl extends \Sabre\DAVACL\Plugin { 

public function getSupportedPrivilegeSet($node) {  
    if (is_string($node)) { 
     $node = $this->server->tree->getNodeForPath($node); 
    } 

    if($node instanceof \Sabre\CalDAV\Calendar || $node instanceof \Sabre\CalDAV\CalendarObject) { 
     return array(
      array(
       'privilege' => '{DAV:}read', 
       'aggregates' => array(
        array(
         'privilege' => '{DAV:}read-acl', 
         'abstract' => true, 
        ), 
        array(
         'privilege' => '{DAV:}read-current-user-privilege-set', 
         'abstract' => true, 
        ), 
       ), 
      ) 
     ); 
    } 

    if ($node instanceof \Sabre\DAVACL\IACL) { 
     $result = $node->getSupportedPrivilegeSet(); 
     if ($result) 
      return $result; 
    } 

    return self::getDefaultSupportedPrivilegeSet(); 
} 

} 

这是我现在的尝试让iCal将日历识别为只读...我还没有完成但可能这会帮助您更好地识别对象

如果您希望节点的绝对路径我想你总是可以通过根目录搜索当前节点,并记录下你到那里的路径。据我检查sabredav中的节点不支持父项或根属性。

[更新]

最好的办法似乎是在插件覆盖getACL。在这里你可以测试节点的类并返回你真正想要的内容而不是默认对象返回的内容(例如查看UserCalendars-> getACL()。

这是我的工作解决方案,用于只读基于对象类型执行:

class DavCalAcl extends \Sabre\DAVACL\Plugin { 

    /** 
    * Returns the full ACL list. 
    * 
    * Either a uri or a DAV\INode may be passed. 
    * 
    * null will be returned if the node doesn't support ACLs. 
    * 
    * @param string|DAV\INode $node 
    * @return array 
    */ 
    public function getACL($node) { 

     if (is_string($node)) { 
      $node = $this->server->tree->getNodeForPath($node); 
     } 
     if (!$node instanceof \Sabre\DAVACL\IACL) { 
      return null; 
     } 

     if($node instanceof \Sabre\CalDAV\Calendar || 
      $node instanceof \Sabre\CalDAV\CalendarObject || 
      $node instanceof \Sabre\CalDAV\UserCalendars 
     ) { 
      $acl = array(
       array(
        'privilege' => '{DAV:}read', 
        'principal' => $node->getOwner(), 
        'protected' => true, 
       ), 
      ); 
     } else { 
      $acl = $node->getACL();   
     } 

     foreach($this->adminPrincipals as $adminPrincipal) { 
      $acl[] = array(
       'principal' => $adminPrincipal, 
       'privilege' => '{DAV:}all', 
       'protected' => true, 
      ); 
     } 
     return $acl; 

    } 
}