2012-02-15 57 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; 

    } 
}