[commits] [Wiki] changed: Doc/Dev/PermsPackage

Wiki Guest wikiguest at horde.org
Tue Dec 27 09:25:04 UTC 2016


guest [31.16.251.178]  Tue, 27 Dec 2016 09:25:04 +0000

Modified page: https://wiki.horde.org/Doc/Dev/PermsPackage
New Revision:  13
Change log:  Rewrote docs for Horde 5

@@ -1,5 +1,8 @@
  +Horde Permissions Framework
+
+This documentation is for Horde 5 and mostly also applies to Horde 4.
+
  There are three aspects to the permissions framework.  The first is  
to tell Horde what permissions your application has.  Horde uses a  
unified tree structure to track all permissions, with each application  
having a branch off the root.  In your application, you must create a  
list of permissions that Horde will then merge with other applications.

  Next, an administrator needs to be able to assign or revoke  
privileges.  This part is completely abstracted and there isn't much  
to say for developers.  Horde itself has a UI for administering  
permissions, but it's just a front-end to the permissions API.   
Therefore, your application can choose to manage permissions in its  
own UI or business logic, but it doesn't strictly need to (and  
probably shouldn't).

@@ -8,40 +11,32 @@
  ++Defining Available Permissions
  To allow Horde to manage your permissions, it needs to know what  
they are.  This is where the design stage comes in.  Internally, Horde  
identifies permissions via a tree.

  Each application defines its portion of the tree.  Whenever the  
Horde API is invoked, it needs to resolve a permission name, so it  
calls a function called _app_perms() within each application (if it  
exists) and merges its results.
-In this example we'll add the permission "arbitrary_permission" to  
application foo.
+In this example we'll add the boolean (yes/no) permission  
"arbitrary_permission" to our application and then add a numeric  
(count) sub-permission

-In foo/lib/api.php:
+In foo/lib/Application.php:

  <code type="php">
-$_services['perms'] = array(
-    'args' => array(),
-    'type' => '{urn:horde}stringArray'
-);
-
-function _foo_perms()
-{
-    static $perms = array();
-    if (!empty($perms)) {
-        return $perms;
-   }
-
-   $perms['tree']['foo']['arbitrary_permission'] = false;
-   $perms['title']['foo:arbitrary_permission'] = _("Textual description");
-   $perms['type']['foo:arbitrary_permission'] = 'boolean';
-   /* example of a sub permission of arbitrary_permission, this time  
a number value */
-    
$perms['tree']['foo']['arbitrary_permission']['some_count_permission']  
= false;
-   $perms['title']['foo:arbitrary_permission:some_count_permission']  
= _("Textual description");
-   $perms['type']['foo:arbitrary_permission:some_count_permission'] = 'int';
-
+  public function perms()
+    {
+        $permissions = array(
+            'arbitrary_permission' => array(
+                'title' => _("Textual description"),
+                'type' => 'boolean'
+            ),
+            'arbitrary_permission:some_count_permission' => array(
+                'title' => _("Textual description"),
+                'type' => 'int'
+            )
+        );
     return $perms;
  }
  </code>

  Now you can go to the Horde administration workflow and click on  
'Permissions'.  On this page, you will be able to see the permissions  
tree.  Add a child node for your 'foo' application.  Then when you add  
a child to the 'foo' application, you will see your new permission in  
the list of permissions (the only item in this list in this example).

-This example is obviously very simplistic.  The flexibility comes in  
when populating the above list dynamically from persistent storage.   
For example, if your application manages widgets, you can make a  
database call in _foo_perms()  and loop over your result set.
+This example is obviously very simplistic.  The flexibility comes in  
when populating the above list dynamically from persistent storage.   
For example, if your application manages widgets, you can make a  
database call in perms()  and loop over your result set.

  <code type="php">
  while(($row = ($resultSet->next()) !== null) {
      $widgetId = $row['widgetId'];
@@ -51,35 +46,86 @@
      $perms['title']["foo:$widgetId"] = $widgetName
  }
  </code>

-Using this strategy, one can create ACL's that apply to a specific  
object, rather than static permissions, like "create widgets".   
Permissions can even be nested.  One can create a static permission  
called "widgets" whose permission mappings represent what a given user  
can do to ALL widgets, then dynamically add children permissions for  
specific widgets.
+Using this strategy, one can create ACL's that apply to a specific  
object, rather than static permissions, like "create widgets".   
Permissions can even be nested.
+One can create a static permission called "widgets" whose permission  
mappings represent what a given user can do to ALL widgets, then  
dynamically add children permissions for specific widgets.

-Notice the use of $perms['type'].  There are two types of  
permissions, which determine the levels of that permission a user may  
have.  In the first example, type Boolean, the user either has the  
permission, or they don't.  The second type (default if not specified)  
is 'matrix', which allows for various levels, specifically, SHOW,  
READ, EDIT, and DELETE.  A user may have any of these levels assigned,  
or none.
+Notice the use of the array key ['type'].  There are three types of  
permissions, which determine the levels of that permission a user may  
have.  In the first example, type Boolean, the user either has the  
permission, or they don't.  The second type (default if not specified)  
is 'matrix', which allows for various levels, specifically, SHOW,  
READ, EDIT, and DELETE.  A user may have any of these levels assigned,  
or none. The last type of permission is "int" or numeric which is  
handy to define limits (allow max 10 widgets for this user).

  ++Applying Permissions / Persistent Storage

  This part of the process is completely abstracted and your  
application shouldn't deal with it.  However, it is obviously  
important to understand.  Horde exposes its API via two classes: Perms  
and Horde_Permission.
  Perms contains the actions one performs, such as adding or removing  
permissions.  Horde_Permission is an entity class that represents a  
permission.  The PhpDocumentor documentation at  
http://dev.horde.org/api/framework/ (choose the Horde_Perms package)  
covers these classes fairly well.
-Note that the Permissions class is a singleton.  The instance is  
usually already defined in a global variable $GLOBALS['perms'].  It's  
also possible to access the static singleton method like so:
  <code type="php">
-$perms = &Perms::singleton();
+// Get a Horde_Perms_Base related instance
+$perms = $injector->getInstance('Horde_Perms');
  </code>

-To add a new permission (assuming it's already defined) into  
persistent storage, use Perms::newPermission(), which gives you back a  
Horde_Permission object that you can then populate with users and  
permission assignments.  Calling Perms::addPermission() with that same  
object will push it into persistent storage so that the specified  
users will have the permission.
+To add a new permission (assuming it's already defined) into  
persistent storage, use $perms->newPermission(), which gives you back  
a Horde_Permission object that you can then populate with users and  
permission assignments.
+

  <code type="php">
-global $perms;
-$p = $perms->newPermission('foo:arbitrary_permission');
-$p->addUserPermission('someUser', PERMS_SHOW | PERMS_READ |  
PERMS_EDIT | PERMS_DELETE);
-$perms->addPermission($p);
+// See the permission tree. Useful for traversal, admin scripts or  
for looking at things when debugging
+$perms->getTree();
+</code>
+Example Output:
+    [4] => foo
+    [5] => foo:administrator
+    [14] => foo:configure
+    [12] => foo:download
+    [11] => foo:read
+    [9] => foo:reseller
+    [10] => foo:rest-api
+
+<code type="php">
+// Get a Horde_Perms_Permission object representing a node in the  
permission tree
+
+$permission = $perms->getPermission('foo:download');
+</code>
+
+<code type="php">
+// Make sure we loaded the right permission
+
+echo $permission->getName();
+</code>
+foo:download
+
+<code>
+// add a boolean true for this permission for user lang and  
immediately save to backend
+
+$permission->addUserPermission('lang', true);
+$permission->save();
+
+// The same, but shorter
+
+$permission->addUserPermission('lang', true, true);
+
+// Most permissions are matrix permissions.
+$permission->addUserPermission('lang', Horde_Perms::SHOW);
+$permission->addUserPermission('lang', Horde_Perms::READ);
+$permission->addUserPermission('lang', Horde_Perms::EDIT);
+$permission->addUserPermission('lang', Horde_Perms::DELETE);
+
+// Give all permission levels at once for this permission and this user
+$permission->addUserPermission('lang', Horde_Perms::ALL);
+// Don't forget to save
+$permission->save();
+
+// Group permissions are just the same - give all trainees read and  
show, then save.
+
+$permission->addGroupPermission('trainees', Horde_Perms:READ);
+$permission->addGroupPermission('trainees', Horde_Perms:SHOW, true);
  </code>

  ++Using / Enforcing Permissions

  None of this code matters if your application doesn't actually check  
these permissions.  This is best done in your business logic and NOT  
at the user interface level.  To check if a user has a given  
permission, simply call Perms::hasPermission() through the singleton  
object.  For example:

  <code type="php">
+// TODO: H5 registry-> example
+
+// Old H3 example
  public function myBusinessMethod($widgetId)
  {
      if(!$GLOBALS['perms']->hasPermission("foo:$widgetId",  
Auth::getAuth(), PERMS_EDIT))
              throw new Exception(_("Access denied."));



More information about the commits mailing list