Author image Slaven Rezić


WE::Util::Permissions - rule-based permission model


    use WE::Util::Permissions;
    $p = WE::Util::Permissions->new(-file => $permissionsfile);
    $p->is_allowed(-user => "user", -group => \@groups, -process => "delete");


This is a rule-based permission system. All permissions are stored in a single file, so it is easy to see all the permissions on one look.

See "PERMISSION FILE SYNTAX" for a description of this file's syntax.


new($class, %args)

Create a WE::Util::Permissions object. At least one of the following named parameters should be given:

-string => $string

A string with the permission data.

-file => $file

A file with the permission data.

-objectfromfile => $file

A file containg a dump of a Permission object.


Internal function. Parse the $string into the internal representation. Normally, this is called automatically on construction time.


Save the Permission object to file $file. The file may be reread using the -objectfromfile argument in new.


Return true, if the process for the specified user/group and specified page is allowed. The keys of %args may be: -user, -group (an array reference to a group list), -process, and -page.

get_all_users($usersref, $process, $page)

Return a list of all users which are allowed to do $process in $page. The $usersref should contain all users in the system and may be a reference to an array or a reference to an hash. In the latter case, the keys are the user names and the values an array reference to the groups of the user. For example:

    $p->get_all_users([qw(eserte ole veit)], "publish", "home");

    $p->get_all_users({eserte => ['admin','editor'],
                       ole    => ['admin'],
                       veit   => ['editor']}, "publish", "home");
get_all_page_permissions($usersref, $processref, $page)

Return permissions for all users for the specified $page. Arguments are similar to that of get_all_users, except that $processref takes an array reference with all allowed processes. The returned object is a hash reference with the following format:

    { process1 => [user1, user2, ...],
      process2 => [user3, user4, ...],

Return the value of the global directive $directive, or undef.


The permission file consists of a set of rules, each rule in one line. Rules with indentation are attached to the previous rule (the rule with one space less as the current rule). Such a rule chain may be read from top to bottom, if all rules in a rule chain apply, then the query is successful.

Rules consists of tokens followed by a space or comma separated list of arguments. The following tokens may be used: user, group, process, and page.

The semantics of users, groups, processes and pages are usually defined in another layer.


A list of users.


A list of groups. Groups and users may be specified in the same line; in this case they should be separated by a semicolon.

If you want a section-role based group model, then it is recommended to use a separator (e.g. "/") to separate section and role. For example, a "chiefeditor" for the section "relations" should be specified as "relations/chiefeditor". If the current rule applies for all members of the "relations" section, then it could easily be written as "relations/*". On the other hand, if the rule applies to all chief editors, then it could be written as "*/chiefeditor".


A process is an operation like "publish", "edit", or "delete".


This can be a path, for example like a common Unix path separated by "/". See WE::DB::Obj/pathname for more information about the pathname syntax. By default, the pathnames are composed by the english titles, but this can be changed by setting the directive primarylang:

    ! primarylang: de

If multiple arguments are put in a rule, then at least one of the arguments have to match. If an argument is preceded by "!", then the rule will not match for this argument. For example if you want to deny "admin" rights, but grant all other rights, then you can write

    process !admin *

By default, simple "glob" matching is used: the "*" character is recognized as a joker (matches zero to many characters) and the "?" character matches exactly one character. See </BUGS> for using spaces in tokens.

By specifying the directive

    ! match: regexp

on top of the permission file, regular expression matching is turned on. It is not possible to specify multiple match directives.


Here are some rule chain examples for permission files:

    ! match: glob
    group admin
     process *

Use globbing instead of regular expressions for matching and allow the "admin" group to have rights for all processes. There is no page restriction, so the rights are valid for all objects.

    group chiefeditor
     process release publish edit

The chiefeditors have rights for the processes "release", "publish" and "edit". Here too, there are no page restrictions.

    ! match: regexp
    group news
     page /News/.*
      process edit change-folder new-doc rm-doc release publish

The members of the group "news" are allowed to do the following operations in all objects below "/News/": "edit", "change-folder", "new-doc", "rm-doc", "release" and "publish". Note that a regular expression match is used here (there is no "! match" directive).

    ! match: glob
    group *
     process !*

This rule chain should be the last one in every permissions file. It forbids all operations for all groups and is only fired, if no other rule chain is successful.


There is currently no way to specify a token with spaces or slashes. To workaround this, use glob matches and the "?" meta character to match a space. For example, to match everything under "/Handset Matrix/", use this rule:

 page /Handset?Matrix/*

This may change by introducing quotes and escape characters à la unix shells, so do not use single or double quotes or backslashes in path specifications.

Diagnostics is poor. Unrecognized tokens won't cause errors or warnings. For some debugging aid, set the DEBUG constant in this module to a true value.


Slaven Rezic -



2 POD Errors

The following errors were encountered while parsing the POD:

Around line 367:

alternative text 'WE::DB::Obj/pathname' contains non-escaped | or /

Around line 441:

Non-ASCII character seen before =encoding in 'à'. Assuming ISO8859-1