Group-Management

thanks for the kind permission given by victor manuel varela, who achieved the basic concept.

the following changes have been made to the WakkaAliases:


the following functions are new to the wakka class:

<?
// aliases stuff, written by http://www.nivel0.net/VictorManuelVarela/
function BuildAliasesArray () {
    if (! is_array($this->config['aliases'])) $this->config['aliases'] = array ('+' => $this->config['aliases']);

    // check for aliases in Wakka pages
    if (isset($this->config['aliases']['+'])) {
        $aliasPages = explode(",", $this->config['aliases']['+']);
        for ($i = count($aliasPages)-1; $i >= 0; $i--) { // any idea why the last page should be included first?
            $aliasPage = $this->LoadPage($aliasPages[$i]);
            foreach (explode("\n", $aliasPage['body']) as $line) {
                // stripping comments
                if (preg_match("/^(.*)?#/", $line, $matches)) $line = $matches[1];

                $atmp = explode(':',$line);
                $aliases[trim($atmp[0])] = trim($atmp[1]);
            }
        }
        $this->config['aliases'] = array_merge($this->config['aliases'], $aliases);
        unset($this->config['aliases']['+']);
        unset($this->config['aliases']['']);
    }
}

function ReplaceAliases ($acl) {
    if (!$this->config['aliases']) return $acl;

    $list = array();
    $new_acl = "";
    foreach (explode("\n", $acl) as $line) {
        $line = trim($line);
        // check for inversion character "!"
        if (preg_match("/^[!](.*)$/", $line, $matches)) {
            $negate = "!";
            $line = trim($matches[1]);
        } else $negate = "";

        if ($this->config["aliases"][$line]) $list = $this->GetMembers($line); else $list[] = $line;
        $new_acl .= $negate.join("\n".$negate, $list)."\n";
    }
    return $new_acl;
}

function GetMembers($group) {
    $result = array();
    if ($group && $groups = $this->config['aliases']) {
        $result = array(trim($group));
        do {
            $replaced = false; $list = array();
            foreach ($result as $line) {
                if (isset($groups[$line])) {
                     // old: foreach (explode (',', $current) as $item) $list[] = trim($item);
                    foreach (explode (',', $groups[$line]) as $item) $list[] = trim($item);
                    $replaced = true;
                    $groups[$line] = ''; // include a group only once!
                } else $list[] = trim($line);
            }
            $result = $list;
        } while ($replaced);
    }
    return array_unique($result);
}

function IsMember($group, $user = "") {
    if (!$user) $user = $this->GetUserName();
    if (in_array($user, $this->GetMembers($group))) return true;
}
?>



the first function will be called in the run() routine (see diff for changes, codebase is wikka 1.1.3.8)

<?
    function Run($tag, $method = "")
    {
        // do our stuff!
        if (!$this->method = trim($method)) $this->method = "show";
        if (!$this->tag = trim($tag)) $this->Redirect($this->href("", $this->config["root_page"]));
        $this->BuildAliasesArray();
        if ((!$this->GetUser() && isset($_COOKIE["name"])) && ($user = $this->LoadUser($_COOKIE["name"], $_COOKIE["password"]))) $this->SetUser($user);
        $this->SetPage($this->LoadPage($tag, (isset($_REQUEST["time"]) ? $_REQUEST["time"] :'')));

        $this->LogReferrer();
        $this->ACLs = $this->LoadAllACLs($this->tag);
        $this->ReadInterWikiConfig();
        if(!($this->GetMicroTime()%3)) $this->Maintenance();

        if (preg_match('/\.(xml|cgi|php)$/', $this->method)) // this tweak is not related to the group management, but quite handy ;)
        {
            print($this->Method($this->method));
        }
        elseif (preg_match('/\.(gif|jpg|png)$/', $this->method))
        {
            header('Location: images/' . $this->method);
        }
        elseif (preg_match('/\.css$/', $this->method))
        {
            header('Location: css/' . $this->method);
        }
        else
        {
            header('Last-Modified: '.gmdate("r", strtotime($this->page["time"]))); // just another little fix
            print($this->Header().$this->Method($this->method).$this->Footer());
        }
    }
?>


the second one every time, the hasaccess() function needs an acl list

<?
    function HasAccess($privilege, $tag = "", $user = "")
    {
        // set defaults
        if (!$tag) $tag = $this->GetPageTag();
        if (!$user) $user = $this->GetUserName();

        // if current user is owner, return true. owner can do anything!
        if ($this->UserIsOwner($tag)) return true;

        // see whether user is registered and logged in
        if ($this->GetUser()) $registered = true;

        // load acl
        if ($tag == $this->GetPageTag())
        {  
            $acl = $this->ACLs[$privilege."_acl"];
        }
        else
        {
            $tag_ACLs = $this->LoadAllACLs($tag);
            $acl = $tag_ACLs[$privilege."_acl"];
        }
        // replace group names with the respective member list
        $acl = $this->ReplaceAliases($acl);

        // fine fine... now go through acl
        foreach (explode("\n", $acl) as $line)
        {
            // check for inversion character "!"
            if (preg_match("/^[!](.*)$/", $line, $matches))
            {
                $negate = 1;
                $line = $matches[1];
            }
            else
            {
                $negate = 0;
            }

            // cut off comment (allows comments in one line after an acl item)
            if (preg_match("/^(.*)[#].*$/", $line, $matches)) $line = trim($matches[1]);

            // if there's still anything left... lines with just a "!" don't count!
            if ($line)
            {
                switch ($line[0])
                {
                // everyone
                case "*":
                    return !$negate;
                // only registered users
                case "+":
                    // return ($registered) ? !$negate : false;
                    return ($registered) ? !$negate : $negate;
                // aha! a user entry.
                default:
                    if ($line == $user)
                    {
                        return !$negate;
                    }
                }
            }
        }

        // tough luck.
        return false;
    }
?>


now we can hook in the isAdmin() function (caution: wikka then expects a group in $wakka->config["admins"]!):

<?
function IsAdmin() { return $this->IsMember($this->config["admins"]); }
?>


and the wikka.config.php yet needs to be adjusted

<?
'aliases' => array
    ('Administrators' => 'BillGates,JoseMariaAznar,GeorgeBush',
    'DangerousPeople' => 'Administrators,DreckFehler',
    '+' => 'WikkaGroups,MoreWikkaGroups'),
'admins' => 'Administrators',
?>


if the variable $wakka->config['aliases'] contains a string instead of an array, it is treated as a list of wikipages which maintain the group handling. in that case one of the pages should contain a group named "Administrators" (or whatever is defined in the config['admins'] variable). but to my understanding it's better for security reasons to leave the admin group in the config file (if not, make sure to restrict at least write access to the page that defines the admin group ;))

<? 'aliases' => 'WikkaSystemGroups,WikkaGroups', ?>


a definition in a wikipage looks like this (whoever those spanish guys may be):

Superusers: ManoloCortes,PedroTriguero,JoseVera
Webmasters: JordiDan,LaraGarrido
loopOne: PingUser,loopTwo # these two groups 
loopTwo: PongUser,loopOne # will not mess up the group handling


Another approach


I though about a simple way to deal with GroupManagement - my concept may be different: Give the power to the users and Keep it simple.

Check it at ACLsWithUserGroups --ChristianBarthelemy


CategoryUserContributions
Comments
Comment by GregorLindner
2004-11-29 14:47:49
Is "needs some improvement" a synonym for "makes wikka.php no longer work" or am i just to stupid to Cu&paste?

After pasting the code i always result in a Parse error in line XX, Line XX being in the section // check for aliases in Wakka pages, precisely:

if (preg_match("/^(.*)?#/", $line, $matches) $line = $matches[1];


Any help installing would be appreciated.
Comment by NilsLindenberg
2004-11-30 16:42:05
Seems, that the code isn't compatible with the current version. Perhaps it would be a good idea to make the group system first.
Comment by DudeliDumidi
2006-04-06 06:06:17
Corrected some typos now this should work for the newest version
Comment by BrianKoontz
2006-04-06 14:55:22
What's the advantage of this method (which I've not tried) over Christian's? FWIW, this method (on this page) doesn't seem to offer the ability to create groups unless you have read/write access to wikka.config.php.
Comment by RodMcFarland
2007-10-10 04:25:31
I did my own sort of solution just today. It's a little site-specific (couldn't be bothered to use the proper database functions) but the concept is there, see http://wiki.lidc.sfu.ca (feel free to create an account). The important page is ManageGroups, which allows you to create whatever bunch of users you want under a group name. Then you can use "Group:whatever" in the ACL page (which is also hacked up for usability). The code changes are pretty minimal, actually. Works for me... code on request.
Valid XHTML :: Valid CSS: :: Powered by WikkaWiki