DokuWiki

It's better when it's simple

User Tools

Site Tools


plugin:superacl

SuperACL Plugin

Compatible with DokuWiki

2010-11-07, 2006-11-06, 2007-06-26, 2008-05-05

plugin Manage ACL settings globally and filter ACL table view

Last updated on
2008-05-25
Provides
Admin

Similar to acl

Tagged with acl, groups, users

Current edition

If you're looking for the SuperACL plugin for pre-2008-05-05 DokuWiki, please scroll down.

This plugin is based on acl, but allows to filter the bottom table of ACLs, so that you don't lose the overview over all the rules applying to your currently selected page/namespace.

Download / Installation

Download the plugin here (manually or via Plugin Manager): http://pb.wh4f.de/dokuwiki/superacl2.zip :!: Use this download only for DokuWiki 2008-05-05 and newer!

Former edition

The following only corresponds to the SuperACL-version for DokuWiki releases 2006-11-06 and 2007-06-26

This plugin is based on acl, but allows to select the namespace where you want to edit access rights, in opposite to the original plugin which requires you to browse a page in the corresponding namespace. This results in better overview about the global ACL situation in the wiki.

Since in big wikis it takes some time to display all namespaces and all the pages of the selected namespace, the new version of SuperACL offers the configuration option to enable “Use AJAX”. This will speedup all roundtrip processes (e.g. set an ACL) by deferring the population of the dropdown-selectors.

Download / Installation

Download the plugin here (manually or via Plugin Manager): http://pb.wh4f.de/dokuwiki/superacl.zip :!: Use this download only for DokuWiki 2006-11-06 or 2007-06-26!
Old version (without AJAX support): http://pb.wh4f.de/dokuwiki/superacl-2007-08-16.zip

Code

admin.php:

admin.php
<?php
/**
 * Global ACL overview
 *
 * Borrowed a lot of code from the aclPlugin
 *
 * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
 * @author     Pascal Bihler <bihler@iai.uni-bonn.de>
 * @author     Frank Schubert <frank@schokilade.de>
 */
// must be run within DokuWiki
if(!defined('DOKU_INC')) die();
 
if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
require_once(DOKU_PLUGIN.'admin.php');
 
/**
 * All DokuWiki plugins to extend the admin function
 * need to inherit from this class
 */
class admin_plugin_superacl extends DokuWiki_Admin_Plugin {
 
    function admin_plugin_superacl(){
        $this->setupLocale();
    }
 
    /**
     * return some info
     */
    function getInfo(){
        return array(
            'author' => 'Pascal Bihler',
            'email'  => 'bihler@iai.uni-bonn.de',
            'date'   => '2008-03-18',
            'name'   => 'SuperACL',
            'desc'   => 'Manage Access Control Lists for all workspaces',
            'url'    => 'http://www.dokuwiki.org/plugin:superacl',
        );
    }
 
    /**
     * access for managers
     */
    function forAdminOnly(){
        return true; // set to false to allow Manager access to Super ACL
    }
 
    /**
     * return prompt for admin menu
     */
    function getMenuText($language) {
        return $this->lang['admin_acl'];
    }
 
    /**
     * return sort order for position in admin menu
     */
    function getMenuSort() {
        return 1;
    }
 
    /**
     * handle user request
     */
    function handle() {
        global $AUTH_ACL;
 
        $cmd   = $_REQUEST['acl_cmd'];
        $scope = $_REQUEST['acl_scope'];
        $type  = $_REQUEST['acl_type'];
        $user  = $_REQUEST['acl_user'];
        $perm  = $_REQUEST['acl_perm'];
 
        if(is_array($perm)){
            //use the maximum
            sort($perm);
            $perm = array_pop($perm);
        }else{
            $perm = 0;
        }
 
        //sanitize
        $user  = auth_nameencode($user);
        if($type == '@') $user = '@'.$user;
        if($user == '@all') $user = '@ALL'; //special group! (now case insensitive)
        $perm  = (int) $perm;
        if($perm > AUTH_DELETE) $perm = AUTH_DELETE;
        //FIXME sanitize scope!!!
 
        //nothing to do?
        if(empty($cmd) || empty($scope) || empty($user)) return;
 
 
        if($cmd == 'save'){
            $this->admin_acl_del($scope, $user);
            $this->admin_acl_add($scope, $user, $perm);
        }elseif($cmd == 'delete'){
            $this->admin_acl_del($scope, $user);
        }
 
        // reload ACL config
        $AUTH_ACL = file(DOKU_CONF.'acl.auth.php');
    }
 
    /**
     * ACL Output function
     *
     * print a table with all significant permissions for the
     * current id
     *
     * @author  Frank Schubert <frank@schokilade.de>
     * @author  Andreas Gohr <andi@splitbrain.org>
     */
    function html() {
 
        print $this->locale_xhtml('intro');
 
        ptln('<div id="acl__manager">');
        ptln('<table class="inline">');
 
        //namespace selector
        $this->admin_superacl_select_ns();
 
        //new
        $this->admin_superacl_html_new();
 
        //current config
        $acls = $this->get_superacl_config($this->get_selected_ns());
        foreach ($acls as $id => $acl){
            $this->admin_superacl_html_current($id,$acl);
        }
 
 
        ptln('</table>');
        ptln('</div>');
    }
 
	/**
	 *
	 * Get current selected namespace (or namespace of $ID as alternative)
	 *
	 */
    function get_selected_ns() {
        global $ID;
 
        $id  = $_REQUEST['superacl_ns'];
 
        if (! $id) $id = getNS($ID);
        if (! $id) $id = '*';
 
        return $id;
    }
 
	/**
	 *
	 * Get current selected acl_scope (or namespace of Selected NS as alternative)
	 *
	 */
    function get_acl_scope() {
 
        $scope  = $_REQUEST['acl_scope'];
 
        if (! $scope) $scope = $this->get_selected_ns() . ':*';
        if (! $scope) $scope = '*';
 
        return $scope;
    }
 
    /**
     * Get matching ACL lines for a namespace
     *
     * $id is namespacename, reads matching lines from $AUTH_ACL,
     * also reads ACLs from namespace
     * returns multi-array with key=pagename and value=array(user, acl)
     *
     * @author Pascal Bihler <bihler@iai.uni-bonn.de>
     * @author  Frank Schubert <frank@schokilade.de>
     */
    function get_superacl_config($id){
        global $AUTH_ACL;
 
 
        $acl_config=array();
 
        // match exact name
        $pages = $this->get_pages($id);
 
        foreach ($pages as $page_id) {
            if ($id != '*') $page_id = $id . ':' . $page_id;
            $matches = preg_grep('/^'.$page_id.'\s+.*/',$AUTH_ACL);
            if(count($matches)){
                foreach($matches as $match){
                    $match = preg_replace('/#.*$/','',$match); //ignore comments
                    $acl   = preg_split('/\s+/',$match);
                    //0 is pagename, 1 is user, 2 is acl
                    $acl_config[$acl[0]][] = array( 'name' => $acl[1], 'perm' => $acl[2]);
                }
            }
        }
 
        $specific_found=array();
 
        // match ns
        for(;$id !== false; $id = getNS($id)){
            $id_pattern = str_replace('+', '\\+',str_replace('*', '\\*', $id));
            $matches = preg_grep('/^'.$id_pattern.':\*\s+.*/',$AUTH_ACL);
 
            if(count($matches)){
                foreach($matches as $match){
                    $match = preg_replace('/#.*$/','',$match); //ignore comments
                    $acl   = preg_split('/\s+/',$match);
                    //0 is pagename, 1 is user, 2 is acl
                    $acl_config[$acl[0]][] = array( 'name' => $acl[1], 'perm' => $acl[2]);
                    $specific_found[]=$acl[1];
                }
            }
        }
 
        //include *-config
        $matches = preg_grep('/^\*\s+.*/',$AUTH_ACL);
        if(count($matches)){
            foreach($matches as $match){
                $match = preg_replace('/#.*$/','',$match); //ignore comments
                $acl   = preg_split('/\s+/',$match);
                // only include * for this user if not already found in ns
                if(!in_array($acl[1], $specific_found)){
                    //0 is pagename, 1 is user, 2 is acl
                    $acl_config[$acl[0]][] = array( 'name' => $acl[1], 'perm' => $acl[2]);
                }
            }
        }
 
        //sort
        //FIXME: better sort algo: first sort by key, then sort by first value
        krsort($acl_config, SORT_STRING);
 
        return($acl_config);
    }
 
 
    /**
     * adds new acl-entry to conf/acl.auth.php
     *
     * @author  Frank Schubert <frank@schokilade.de>
     */
    function admin_acl_add($acl_scope, $acl_user, $acl_level){
        $acl_config = join("",file(DOKU_CONF.'acl.auth.php'));
 
        // max level for pagenames is edit
        if(strpos($acl_scope,'*') === false) {
            if($acl_level > AUTH_EDIT) $acl_level = AUTH_EDIT;
        }
 
        $new_acl = "$acl_scope\t$acl_user\t$acl_level\n";
 
        $new_config = $acl_config.$new_acl;
 
        return io_saveFile(DOKU_CONF.'acl.auth.php', $new_config);
    }
 
    /**
     * remove acl-entry from conf/acl.auth.php
     *
     * @author  Frank Schubert <frank@schokilade.de>
     */
    function admin_acl_del($acl_scope, $acl_user){
        $acl_config = file(DOKU_CONF.'acl.auth.php');
 
        $acl_pattern = '^'.preg_quote($acl_scope,'/').'\s+'.$acl_user.'\s+[0-8].*$';
 
        // save all non!-matching #FIXME invert is available from 4.2.0 only!
        $new_config = preg_grep("/$acl_pattern/", $acl_config, PREG_GREP_INVERT);
 
        return io_saveFile(DOKU_CONF.'acl.auth.php', join('',$new_config));
    }
 
    // --- HTML OUTPUT FUNCTIONS BELOW --- //
 
    /**
     * create dropdown with parent namespaces and pages of one namespace ID
     *
     *
     *
     * @author Pascal Bihler <bihler@iai.uni-bonn.de>
     * @author  Frank Schubert <frank@schokilade.de>
     * @author  Andreas Gohr <andi@splitbrain.org>
     */
    function admin_superacl_html_dropdown($id){
        $cur = $id;
        $ret = '';
        $selected_id = $this->get_acl_scope();
        $opt = array();
 
        //prepare all options (in reversed order)
        $pages = array();
        if ($this->getConf('use_ajax')) {
            $ret .= sprintf('<input type="hidden" id="superacl__aclid" value="%s"/>',$id);
            $ret .= sprintf('<input type="hidden" id="superacl__pageselid" value="%s"/>',$selected_id);
            $ret .= sprintf('<input type="hidden" id="superacl__page_text" value="%s"/>',$this->lang['page']);
            $ret .= sprintf('<input type="hidden" id="superacl__namespace_text" value="%s"/>',$this->lang['namespace']);
        } else {
            // pages in this namespace
            $pages = array_reverse($this->get_pages($id));
        }
 
        // add pages in list
        foreach ($pages as $page_id) {
            $page_id = ($id != '*' ? $id . ':' : '') . $page_id;
            $opt[] = array(
                'value'=> $page_id,
                'text'=> $page_id.' ('.$this->lang['page'].')'
            );
            if ($page_id ==  $selected_id) $opt[count($opt)-1]['sel'] = true;
        }
 
        // add selected page (if not in list above)
        if (!($pages) && ($this->is_page($selected_id))) {
            $opt[] = array(
                'value'=> $selected_id,
                'text'=> $selected_id.' ('.$this->lang['page'].')',
                'sel' => true
            );
        }
 
 
        // additional namespaces
        for(; $id !== false && $id != '*'; $id=getNS($id)){
            $opt[] = array('value'=> $id.':*', 'text'=> $id.':* ('.$this->lang['namespace'].')');
            if ($id.':*' ==  $selected_id) $opt[count($opt)-1]['sel'] = true;
        }
 
        // the top namespace
        $opt[] = array(
            'value'=> '*',
            'text'=> '* ('.$this->lang['namespace'].')'
        );
 
 
 
        // flip options
        $opt = array_reverse($opt);
 
        // create HTML
        $att = array(
            'name'  => 'acl_scope',
            'id' => 'superacl__pageselect',
            'class' => 'edit',
            'title' => $this->lang['page'].'/'.$this->lang['namespace']
        );
 
        $ret .= '<select '.html_attbuild($att).'>';
        foreach($opt as $o){
            $ret .= '<option value="'.$o['value'].'"'.($o['sel'] ? ' selected="selected"' : '').'>'.$o['text'].'</option>';
        }
        $ret .= '</select>';
 
        return $ret;
    }
 
    /**
     * Decides, if a id is a page
     * */
    function is_page($id){
        return (id != "") && ! (substr($id,-1) == '*');
    }
 
     /**
     * creates dropdown with all namespaces
     *
     * @author Pascal Bihler <bihler@iai.uni-bonn.de>
     */
    function admin_superacl_html_ns_dropdown($id){
        global $ID;
        $ret = '';
        $opt = array();
 
 
        $namespaces = array();
 
        if ($this->getConf('use_ajax')) {
            $ret .= sprintf('<input type="hidden" id="superacl__pageid" value="%s"/>',$ID);
            $ret .= sprintf('<input type="hidden" id="superacl__nsselid" value="%s"/>',$id);
        } else {
            $namespaces = $this->get_namespaces();
        }
 
        // add namespaces of current page to the list of namespaces (even if the namespaces doesn't exist yet
        for($ns_id = getNS($ID); $ns_id !== false; $ns_id = getNS($ns_id)){
            if (!in_array($ns_id,$namespaces)) $namespaces[] = $ns_id;
        }
 
        // add selected namespace, if not in list above
        if ($id && !in_array($id,$namespaces)) $namespaces[] = $id;
 
        sort($namespaces);
 
        $namespaces = array_reverse($namespaces);
        foreach ($namespaces as $ns_id) {
            if ($ns_id == "*") continue;
 
            $opt[] = array('value'=> $ns_id, 'text'=> $ns_id.':*');
            if ($ns_id == $id) { // set sel on current selected namespcase
                $opt[count($opt)-1]['sel'] = true;
            }
        }
 
        $opt[] = array('value'=> '*', 'text'=> '*');
 
 
        // flip options
        $opt = array_reverse($opt);
 
 
        // create HTML
        $att = array(
            'name'  => 'superacl_ns',
            'id' => 'superacl__nsselect',
            'class' => 'edit',
            'title' => $this->lang['page'].'/'.$this->lang['namespace']
        );
 
        $ret .= '<select '.html_attbuild($att).' onchange="submit();">';
        foreach($opt as $o){
            $ret .= '<option value="'.$o['value'].'"'.($o['sel'] ? ' selected="selected"' : '').'>'.$o['text'].'</option>';
        }
        $ret .= '</select>';
 
        return $ret;
    }
 
    /**
     * print form to select namespace to modify
     *
     * @author Pascal Bihler <bihler@iai.uni-bonn.de>
     *
     */
     function admin_superacl_select_ns() {
        global $ID;
        global $lang;
 
        // table headers
        ptln('<tr>',2);
        ptln('  <th class="leftalign" colspan="3">'.$this->lang['acl_select'].'</th>',2);
        ptln('</tr>',2);
 
        ptln('<tr>',2);
 
        ptln('<td class="centeralign" colspan="3">',4);
 
        ptln('  <form method="post" action="'.wl($ID).'"><div class="no">',4);
        ptln('    <input type="hidden" name="do"   value="admin" />',4);
        ptln('    <input type="hidden" name="page" value="superacl" />',4);
        ptln('    <input type="hidden" name="acl_cmd" value="select_ns" />',4);
 
        //scope select
        ptln($this->lang['acl_perms'],4);
        ptln($this->admin_superacl_html_ns_dropdown($this->get_selected_ns()),4);
 
        ptln('    <input type="submit" class="button" value="'.$lang['btn_update'].'" />',4);
        ptln('  </div></form>');
        ptln('</td>',4);
        ptln('</tr>',2);
     }
 
 
    /**
     * print form to add new Permissions
     *
     * @author Pascal Bihler <bihler@iai.uni-bonn.de>
     * @author  Frank Schubert <frank@schokilade.de>
     * @author  Andreas Gohr <andi@splitbrain.org>
     */
    function admin_superacl_html_new(){
        global $ID;
        global $lang;
 
        // table headers
        ptln('<tr>',2);
        ptln('  <th class="leftalign" colspan="3">'.$this->lang['acl_new'].'</th>',2);
        ptln('</tr>',2);
 
        ptln('<tr>',2);
 
        ptln('<td class="centeralign" colspan="3">',4);
 
        ptln('  <form method="post" action="'.wl($ID).'"><div class="no">',4);
        ptln('    <input type="hidden" name="do"   value="admin" />',4);
        ptln('    <input type="hidden" name="page" value="superacl" />',4);
        ptln('    <input type="hidden" name="acl_cmd" value="save" />',4);
        ptln('    <input type="hidden" name="superacl_ns" value="' . $this->get_selected_ns() . '" />',4);
 
        //scope select
        ptln($this->lang['acl_perms'],4);
        ptln($this->admin_superacl_html_dropdown($this->get_selected_ns()),4);
 
        $att = array(
            'name'  => 'acl_type',
            'class' => 'edit',
            'title' => $this->lang['acl_user'].'/'.$this->lang['acl_group']
        );
        ptln('    <select '.html_attbuild($att).'>',4);
        ptln('      <option value="@">'.$this->lang['acl_group'].'</option>',4);
        ptln('      <option value="">'.$this->lang['acl_user'].'</option>',4);
        ptln('    </select>',4);
 
        $att = array(
            'name'  => 'acl_user',
            'type'  => 'text',
            'class' => 'edit',
            'title' => $this->lang['acl_user'].'/'.$this->lang['acl_group']
        );
        ptln('    <input '.html_attbuild($att).' />',4);
        ptln('    <br />');
        ptln(     $this->admin_acl_html_checkboxes(0,false),8);
        ptln('    <input type="submit" class="button" value="'.$lang['btn_save'].'" />',4);
        ptln('  </div></form>');
        ptln('</td>',4);
        ptln('</tr>',2);
    }
 
    /**
     * print tablerows with the current permissions for one id
     *
     * @author Pascal Bihler <bihler@iai.uni-bonn.de>
     * @author  Frank Schubert <frank@schokilade.de>
     * @author  Andreas Gohr <andi@splitbrain.org>
     */
    function admin_superacl_html_current($id,$permissions){
        global $lang;
        global $ID;
 
        //is it a page?
        $ispage = $this->is_page($id);
 
        // table headers
        ptln('  <tr>');
        ptln('    <th class="leftalign" colspan="3">');
        ptln($this->lang['acl_perms'],6);
        if($ispage){
            ptln($this->lang['page'],6);
        }else{
            ptln($this->lang['namespace'],6);
        }
        ptln('<em>'.$id.'</em>',6);
        ptln('    </th>');
        ptln('  </tr>');
 
        sort($permissions);
 
        foreach ($permissions as $conf){
        //userfriendly group/user display
        $conf['name'] = rawurldecode($conf['name']);
        if(substr($conf['name'],0,1)=="@"){
            $group = $this->lang['acl_group'];
            $name  = substr($conf['name'],1);
            $type  = '@';
        }else{
            $group = $this->lang['acl_user'];
            $name  = $conf['name'];
            $type  = '';
        }
 
        ptln('<tr>',2);
        ptln('<td class="leftalign">'.htmlspecialchars($group.' '.$name).'</td>',4);
 
        // update form
        ptln('<td class="centeralign">',4);
        ptln('  <form method="post" action="'.wl($ID).'"><div class="no">',4);
        ptln('    <input type="hidden" name="do"   value="admin" />',4);
        ptln('    <input type="hidden" name="page" value="superacl" />',4);
        ptln('    <input type="hidden" name="acl_cmd"   value="save" />',4);
        ptln('    <input type="hidden" name="acl_scope" value="'.formtext($id).'" />',4);
        ptln('    <input type="hidden" name="acl_type" value="'.$type.'" />',4);
        ptln('    <input type="hidden" name="acl_user"  value="'.formtext($name).'" />',4);
        ptln('    <input type="hidden" name="superacl_ns" value="' . $this->get_selected_ns() . '" />',4);
        ptln(     $this->admin_acl_html_checkboxes($conf['perm'],$ispage),8);
        ptln('    <input type="submit" class="button" value="'.$lang['btn_update'].'" />',4);
        ptln('  </div></form>');
        ptln('</td>',4);
 
 
        // deletion form
 
        $ask  = $lang['del_confirm'].'\\n';
        $ask .= $id.'  '.$conf['name'].'  '.$conf['perm'];
        ptln('<td class="centeralign">',4);
        ptln('  <form method="post" action="'.wl($ID).'" onsubmit="return confirm(\''.str_replace('\\\\n','\\n',addslashes($ask)).'\')"><div class="no">',4);
        ptln('    <input type="hidden" name="do"        value="admin" />',4);
        ptln('    <input type="hidden" name="page"      value="superacl" />',4);
        ptln('    <input type="hidden" name="acl_cmd"   value="delete" />',4);
        ptln('    <input type="hidden" name="acl_scope" value="'.formtext($id).'" />',4);
        ptln('    <input type="hidden" name="acl_type" value="'.$type.'" />',4);
        ptln('    <input type="hidden" name="acl_user"  value="'.formtext($name).'" />',4);
        ptln('    <input type="hidden" name="superacl_ns" value="' . $this->get_selected_ns() . '" />',4);
        ptln('    <input type="submit" class="button" value="'.$lang['btn_delete'].'" />',4);
        ptln('  </div></form>',4);
        ptln('</td>',4);
 
        ptln('</tr>',2);
        }
 
    }
 
 
    /**
     * print the permission checkboxes
     *
     * @author  Frank Schubert <frank@schokilade.de>
     * @author  Andreas Gohr <andi@splitbrain.org>
     */
    function admin_acl_html_checkboxes($setperm,$ispage){
        global $lang;
 
        static $label = 0; //number labels
        $ret = '';
 
        foreach(array(AUTH_READ,AUTH_EDIT,AUTH_CREATE,AUTH_UPLOAD,AUTH_DELETE) as $perm){
            $label += 1;
 
            //general checkbox attributes
            $atts = array(
                'type'  => 'checkbox',
                'id'    => 'pbox'.$label,
                'name'  => 'acl_perm[]',
                'value' => $perm
            );
            //dynamic attributes
            if($setperm >= $perm) $atts['checked']  = 'checked';
            $atts['onchange'] = "superacl_autoselect_permissions(this);";
            if($ispage && $perm > AUTH_EDIT) $atts['disabled'] = 'disabled';
 
            //build code
            $ret .= '<label for="pbox'.$label.'" title="'.$this->lang['acl_perm'.$perm].'">';
            $ret .= '<input '.html_attbuild($atts).' />';
            $ret .= $this->lang['acl_perm'.$perm];
            $ret .= "</label>\n";
        }
        return $ret;
    }
 
    function get_pages($tns='') {
        return $this->_getlist($tns,false,false,true);
    }
 
    function get_namespaces($tns='') {
        return $this->_getlist($tns,true,true,false);
    }
    /**
     * inspired from addnewpageplugin:
     */
    function _getlist ($tns='',$recursive = true, $namespaces=true,$pages=false) {
        require_once(DOKU_INC.'inc/search.php');
        global $conf;
 
        if ($tns == '*') $tns = '';
 
        if (!is_dir($tns)) $tns  = str_replace(':','/',$tns);
 
        $data = array();
 
 
        search($data,$conf['datadir'] ."/" . $tns,'search_index',array('ns' => ''));
 
        $data2 = array();
        foreach($data as $k => $v) {
            if ($v['type']=='d') { //Namespace
                if ($namespaces) array_push($data2,$v['id']);
 
                if ($recursive) {
                    $r=$this->_getlist($tns.'/'.$v['id'],$recursive,$namespaces,$pages);
                    foreach ($r as $vv) {
                        array_push($data2,$v['id'].':'.$vv);
                    }
                }
            } elseif ($v['type']=='f') { //Page
                if ($pages) array_push($data2,$v['id']);
            }
        }
        return $data2;
	}
 
}

ajax.php:

FIXME move this to action.php where it can hook the ajax_call_unknown event.

ajax.php
<?php
/**
 * SuperACL Ajax Handler 
 * 
 * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
 * @author    Pascal Bihler <bihler@iai.uni-bonn.de>
 * */
//fix for Opera XMLHttpRequests
if(!count($_POST) && $HTTP_RAW_POST_DATA){
    parse_str($HTTP_RAW_POST_DATA, $_POST);
}
 
if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../../../').'/');
require_once(DOKU_INC.'inc/init.php');
require_once(DOKU_INC.'inc/common.php');
require_once(DOKU_INC.'inc/pageutils.php');
require_once(DOKU_INC.'inc/auth.php');
require_once(DOKU_INC.'inc/JSON.php');
//close session
session_write_close();
 
// check, if user is admin (or at least manager)
if (! auth_ismanager()) {
    exit;
}
 
if ($_POST["q"] == "namespaces") {
    get_namespace_list();
} elseif ($_POST["q"] == "pages") {
    get_pages_list();
}
 
function get_namespace_list() {
 
    $ID = $_POST["pageid"];
    $selid = $_POST["selid"];
 
    $opt = array();
 
    // all namespace
    $namespaces = get_namespaces();
 
    // add namespaces of current page to the list of namespaces (even if the namespaces doesn't exist yet
    for($ns_id = getNS($ID); $ns_id !== false; $ns_id = getNS($ns_id)){
        if (!in_array($ns_id,$namespaces)) $namespaces[] = $ns_id;
    }
    sort($namespaces);
 
    $namespaces = array_reverse($namespaces);
    foreach ($namespaces as $ns_id) {
        $opt[] = array('value'=> $ns_id, 'text'=> $ns_id.':*');
        if ($ns_id == $selid) { // set sel on current selected namespcase 
            $opt[count($opt)-1]['sel'] = true;
        }
    }
 
    $opt[] = array('value'=> '*', 'text'=> '*');
 
 
    // flip options
    $opt = array_reverse($opt); 
 
 
    /* now construct a json */
    $json = new JSON();
 
 
    //header('Content-Type: application/json');
    header('Content-Type: text/javascript');
    print $json->encode($opt);
}
 
 
function get_pages_list() {
 
    $id = $_POST["aclid"];
    $selected_id = $_POST["selid"];
 
    $opt = array();
 
    $pages = array_reverse(get_pages($id));
 
    // add pages in list
    foreach ($pages as $page_id) {
        $page_id = ($id != '*' ? $id . ':' : '') . $page_id;
        $opt[] = array(
            'value'=> $page_id, 
            'text'=> $page_id.' ('.$_POST['page_text'].')'
        );
        if ($page_id ==  $selected_id) $opt[count($opt)-1]['sel'] = true;
    }      
 
    // additional namespaces
    for(; $id !== false && $id != '*'; $id=getNS($id)){
        $opt[] = array('value'=> $id.':*', 'text'=> $id.':* ('.$_POST['ns_text'].')');
        if ($id.':*' ==  $selected_id) $opt[count($opt)-1]['sel'] = true;
    }
 
    // the top namespace
    $opt[] = array('value'=> '*', 'text'=> '* ('.$_POST['ns_text'].')');
 
    // flip options
    $opt = array_reverse($opt);
 
    /* now construct a json */
    $json = new JSON();
 
    //header('Content-Type: application/json');
    header('Content-Type: text/javascript');
    print $json->encode($opt);
}
 
function get_pages($tns='') {
    return _getlist($tns,false,false,true);
}
 
 
function get_namespaces($tns='') {
    return _getlist($tns,true,true,false);
}
 
// inspired from addnewpageplugin: 
function _getlist ($tns='',$recursive = true, $namespaces=true,$pages=false) {
    require_once(DOKU_INC.'inc/search.php');
    global $conf;
 
    if ($tns == '*') $tns = '';
 
    if (!is_dir($tns)) $tns  = str_replace(':','/',$tns);
 
    $data = array();
 
    search($data,$conf['datadir'] ."/" . $tns,'search_index',array('ns' => ''));
 
    $data2 = array();
    foreach($data as $k => $v) {
        if ($v['type']=='d') { //Namespace
            if ($namespaces) array_push($data2,$v['id']);
 
            if ($recursive) {
                $r=_getlist($tns.'/'.$v['id'],$recursive,$namespaces,$pages);
                foreach ($r as $vv) {
                    array_push($data2,$v['id'].':'.$vv);
                }
            }
        } elseif ($v['type']=='f') { //Page
            if ($pages) array_push($data2,$v['id']);
        }
    }
    return $data2;
} 
?>

script.js:

script.js
function superacl_autoselect_permissions(caller) {
    callerLabel = parseInt(caller.id.substring(4));
    baseLabel = caller.id.substring(0,4);
    parent = caller.parentNode.parentNode;
    boxes = parent.getElementsByTagName('input');
	for (i = 0; i < boxes.length; i++) {
	    e = boxes[i];
	    if (! e) continue;
	    id = e.id;
	    if (!id || id.length<4 || id.substring(0,4) != baseLabel) continue;
	    label = parseInt(id.substring(4));
		//check lower rights, too
	    if (caller.checked && label < callerLabel) e.checked = true;
		//uncheck upper rights too
	    else if (! caller.checked && label > callerLabel) e.checked = false;
	}
}
 
 
function ajax_superacl_class() {
	this.sack = null;
	this.inObj = null;
	this.outObj = null;
	this.timer = null;
}
 
function fillNamespaceDropdown()
{
	// fill namespace selector
	if ($('superacl__nsselid')) {
		var ajax_superaclns = new ajax_superacl_class();
		ajax_superaclns.sack = new sack(DOKU_BASE + 'lib/plugins/superacl/ajax.php');
		ajax_superaclns.sack.AjaxFailedAlert = '';
		ajax_superaclns.sack.encodeURIString = false;
		ajax_superaclns.exec = function() {
			pageid = $("superacl__pageid").value;
			ns_selid = $("superacl__nsselid").value;
			ajax_superaclns.sack.runAJAX('q=namespaces&pageid=' + encodeURI(pageid) + '&selid=' + encodeURI(ns_selid));
		};
		ajax_superaclns.sack.onCompletion = function() {
			var data = eval(ajax_superaclns.sack.response);
			if(data === '') return;			   
			// add namespaces to select box
			select = $('superacl__nsselect');
			for(i = 0; i < data.length; ++i) {
				option = new Option(data[i].text, data[i].value, data[i].sel, data[i].sel);
				select.options[i] = option;			
			}
		};
        ajax_superaclns.exec();
    }
 
    // fill page selector
    if ($('superacl__aclid')) {
      	var ajax_superaclpage = new ajax_superacl_class();
		ajax_superaclpage.sack = new sack(DOKU_BASE + 'lib/plugins/superacl/ajax.php');
		ajax_superaclpage.sack.AjaxFailedAlert = '';
		ajax_superaclpage.sack.encodeURIString = false;
		ajax_superaclpage.exec = function() {
			acl_id = $("superacl__aclid").value;
			page_selid = $("superacl__pageselid").value;
			page_text = $("superacl__page_text").value;
			ns_text = $("superacl__namespace_text").value;
			ajax_superaclpage.sack.runAJAX(
				'q=pages&aclid=' + encodeURI(acl_id) +
				'&selid=' + encodeURI(page_selid) +
				'&page_text=' + encodeURI(page_text) +
				'&ns_text=' + encodeURI(ns_text) 
			);
		};
		ajax_superaclpage.sack.onCompletion = function() {
			var data = eval(ajax_superaclpage.sack.response);
			if(data === '') return;
			// add namespaces to select box
			select = $('superacl__pageselect');
			for(i = 0; i < data.length; ++i) {
				option = new Option(data[i].text, data[i].value, data[i].sel, data[i].sel);
				select.options[i] = option;			
			} 
		};
        ajax_superaclpage.exec();
    }
}
 
addInitEvent(function(){fillNamespaceDropdown();});

Patches

Incompatible with "WeatherWax"

Bug : Problem with * and + characters

  • description : if you try to get ACL for “*” (the first namespace in the list) you get at least 2 warnings “warning: Compilation failed: nothing to repeat at offset 1” for preg_grep on line 183.
  • solution I've put the following code just before line 183 :
$id = str_replace('*', '\\*', $id);
$id = str_replace('+', '\\+', $id);

It seems it works…

Thank you for the hint, I included it with the new version 2007-08-13.
Pascal Bihler 2007/08/13 16:06

Bug : wrong variable name

In admin.php line 528

$idpage $ispage = $this→is_page($id);

Ok, fixed

Overriding the ACL Admin Task

Would it be possible to override the ACL task item in the first section of the Administration screen (the list with the big icons) ? — George PetsagourakisGeorge Petsagourakis
petsagouris

Rethymno, Greece
2011/02/13 13:05

plugin/superacl.txt · Last modified: 2014/03/20 18:23 by Aleksandr