DokuWiki

It's better when it's simple

Benutzer-Werkzeuge

Webseiten-Werkzeuge


de:tips:homepages

Wie man Benutzerhomepages erstellt

Autor: Oliver Geisen
Überblick: Erstelle Homepages für DokuWiki-User ohne aufwendige ACL's
Basiert auf: dokuwiki-2006-03-09
Gebrauchte Plugins: keines

:!: Achtung: Dieser Tipp ist ein einfacher Hack. Man sollte das Ganze noch einmal überdenken und eine einfachere Lösung finden, um Homepages für Benutzer anzubieten, besonders die Art der Autorisierung in den namespaces, wo sie sich befinden. Man kann im ACL möglicherweise eine Variable wie %USERID% verwenden.

Motivation

Wir (DokuWiki Admins) möchten euch DokuWiki-Usern die Möglichkeit bieten, eure eigenen Homepages zu erstellen. Diese sollten in der Verantwortung des Users liegen und daher in ihren eigenen namespaces liegen. Der User kann so viele Seiten in seinem namespace erstellen, wie er möchte (Hintergedanke: „Sollte es keine Art Begrenzung geben?“). Jeder User, der mit dem Usermanager erstellt wurde, sollte einen eigenen namespace und ein simples Anfangs-Template haben. Es sollte auch ein „My Page“(=„Meine Seite“)-Button im Menü sein, damit Benutzer einfach auf ihre Seite zugreifen können.

Wie macht man das jetzt?

Jede Seite, die der User sieht wird vom Browser wie folgt abgerufen:

http://<server>/doku.php?id=<wiki-path>

doku.php selbst initialisiert einige Einrichtungen, setzt globale Variablen, checkt ACL's und ruft dann main.php vom aktuell ausgewählten Template auf, das man hier finden kann:

lib/tpl/<template>/main.php

Also müssen wir entscheiden, wo wir den Code hacken: Während dem ACL-Check oder dort, wo die Seite angezeigt wird. Ich entschied mich, die ganze Sache noch bevor die Seite angezeigt wird zu erledigen, da ich die ACL's sauber und einfach halten wollte. Dafür müssen wir jetzt ein paar Entscheidungen treffen:

  1. Wo soll der namespace der Homepage sein ?
  2. Sollen andere User Zugriff darauf haben (read-only) ?

Ich entschied mich dafür:

  • starte meinen User-namespace bei: home: (genau wie es linux macht)
  • User-Seiten bleiben privat. Um die Seiten zu editieren, muss man
    home:*  @ALL    0
    home:*  @user   16

    zu conf/acl.auth.php hinzufügen.

Extend ACL if user requests his own homepage-namespace

The next challenge was to find the place in code where user should be given full access to his namespace. We've discovered that main.php is called at least, so let's look inside and we found a call like:

<?php tpl_content()?>

Let's do a simple grep-search inside the dokuwiki base-directory to find the lib which exports this function:

grep -r "function tpl_content" *

The answer is: inc/template.php. So lets look inside the function and determine how it works. It imports some globals, where $ID contains the wiki-url to the page requested and $ACT the thing to do (mostly „show“).

So this leads us to „html_show()“, which we can find, using grep-search like before, inside „inc/html.php“. Further look show that it simply displays/renders the wiki-source-text, so this is too deep to implement the code needed. I decide to put in into „tpl_content()“ right after the global definitions:

  ... global imports ...
 
  // if $ID (requested page) starts with 'home:' and we are not the "admin" do some extra checking
  if((substr($ID,0,5) == 'home:') && ($INFO['perm'] != AUTH_ADMIN)){
    $userid = $_SESSION[$conf['title']]['auth']['user'];
    $allowed = 'home:'.$userid.':';
    // if user requests the page of another users homedir, deny access to it
    if(substr($ID,0,strlen($allowed)) != $allowed){
      print p_locale_xhtml('denied');
      return;
    }
  }
  // only admins, users requesting pages from their own homespace, or users requesting other namespaces will get here
 
  ... regular code continues ...

Add "My page" button to navigation bar

Add the code to display the new button inside main.php of the template:

  <?php tpl_button('mypage') ?>

Now let's find out where tpl_button comes from. Just use grep-search again and see it's inside inc/template.php (haha, surprise surpise, who had thought that all functions prefixed with „tpl_“ comes from template.php ;-)))

Ok, i just added a new case-statement for my button:

  ...
  case 'mypage':
    $uid = $_SESSION[$conf['title']]['auth']['user'];
    $id = 'home:'.$uid.':index';
    print html_btn('mypage',$id,'u',array("do" => "show"));
    break;
  ...

Next, we need to add the button-label for „mypage“. A quick look inside „html_btn“ (which is found in inc/html.php) shows that each label is prefixed with „btn_“, which results in „btn_mypage“ in our case, and is looked up in the language-file. This is found at:

inc/lang/<language>/lang.php

Here i append a new line containing:

$lang['btn_mypage']     = 'Meine Seite';

Please note „Meine Seite“ is German. Just put whatever YOU want, of course ;-)

Now you can try it, and find a good place for the button inside main.php.

Autocreate homespace for users

Because users are not able to create own namespace in „home:“ we must provide them one. Best place to do this is when adding the user with the usermanager. The usermanager is a default plugin of dokuwiki and it's code is found at:

lib/plugins/usermanager/

Next we must find the place where the new user is created to add our code to create the homespace as well. In the „handle()“ function we found a case-switch with a case „add“ : $this→_addUser(); break; - this is our man!

So lets follow the call to the function „_addUser()“. It first gets data from the POSTed form, which normally contains the params of the new user to be created (name, mail, password, etc.). Next it wraps to $this→_auth→createUser($user,$pass,$name,$mail,$grps);. This function is not contained here, because „_auth“ is another object which will be dynamically set by the choosen authentication method.

I use „plaintext“ authentication so i found out that inc/auth/plaintext.php is the place to search for „createUser“. All this function do is to add the credentials given to the „user database“ and returns „false“ if the user already exists, „null“ when an error has occured and „true“ if everything went well.

Because our solution should not depend upon the selected authentication method, it's best to add it to the usermanager code. The problem here is how to build up the path to the namespace for the user to create with mkdir (or better io_mkdir_p() from inc/io.php).

So lets start thinking reverse again. What happens if one clicks on „Create page“? Yes, a page opens with an empty editfield and a „Save“ button under it. This buttons is worth a closer look, so check HTML-source and found out that it will call doku.php with „do=save“ and „id=<pageid>“. Now i go all the way through doku.php down until inc/actions.php where „save“ is handled and came up to the function „act_save($ACT)“. After a few checks it will call „saveWikiText(…)“ which i found in inc/common.php.

Here i found two very interesting things:

  1. the call to „wikiFN($id)“ which in result gives us the full path into the local filesystem, where page $id is/should be stored
  2. and the call to „io_saveFile($file,$text);“ which will store the wiki-page into $file, where all needed dirs will be created

For now „io_saveFile()“ seems of interest and i found it in inc/io.php. There i found how it's done. The call to

io_makeFileDir($file);

creates the needed directory structure upon the given filepath. So this is the function to use in the usermanager plugin.

Now all there is to do is just create the path to the wanted namespace-id, which is in our case „home:<userid>:index“, and create the directory.

One note about the wikiFN-function. If the last part of the argument given is ':', it results in a path where the element just before the ':' is suffixed with '.txt'. I think this is an error, but maybe not… just keep this in mind ! For heavens sake „io_makeFileDir()“ expects also a file as last argument, so there is no problem at all.

Now it's time to fill our code into the appropriate functions of /lib/plugins/usermanager/admin.php:

append new function

    /*
     * Create homedir (namespace) for user
     */
    function _createHomedir($user, $name){
 
        $userhome = dirname(wikiFN("home:$user:index"));
        $homebase = dirname($userhome);
 
        // create directory
        if(! @is_dir($userhome)) {
            io_makeFileDir($userhome.'/dummy.txt');
            msg("Homedir for user created", 1);
        }
 
        // copy template from parent (modify this to fit YOUR needs !)
        $userpage = $userhome.'/index.txt';
        if(! @is_file($userpage)){
            $tpl = $homebase.'/template.txt';
            if(@is_file($tpl)) {
                $page = io_readFile($tpl);
                $page = preg_replace('/@USERNAME@/', $name, $page);
                io_saveFile($userpage, $page);
                msg("Template copied to homedir", 1);
            }
        }
    }

change _modifyUser()

        if (empty($newuser)) return false;
 
        # create homedir for new/existing user
        $this->_createHomedir($newuser,$newname);
 
        $changes = array();

change _addUser()

        if (empty($user)) return false;
 
        # create homedir for new/existing user
        $this->_createHomedir($user,$name);
 
        return $this->_auth->createUser($user,$pass,$name,$mail,$grps); 

Kommentare

OK, das wär's! Bitte alles sorgfältig lesen und vergesst nicht, das es schwierig wird DokuWiki mit diesen Änderungen so einfach upzugraden.

FIXME: Übersetzung wegen Zeitmangel unvollständig, wer etwas verbessern kann und/oder möchte soll es bitte tun!

de/tips/homepages.txt · Zuletzt geändert: 2010-09-04 21:09 von 85.216.75.29

Falls nicht anders bezeichnet, ist der Inhalt dieses Wikis unter der folgenden Lizenz veröffentlicht: CC Attribution-Share Alike 4.0 International
CC Attribution-Share Alike 4.0 International Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki