Skip to content

Instantly share code, notes, and snippets.

@ewinslow
Last active December 15, 2015 08:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ewinslow/446080109b5a69ad69c2 to your computer and use it in GitHub Desktop.
Save ewinslow/446080109b5a69ad69c2 to your computer and use it in GitHub Desktop.
Capabilities API

Permissions System

The permissions system allows you to:

  1. Check whether a user is allowed to take a certain action, and
  2. Customize whether a user is allowed to take a certain action.

[!!] Restricting the visibility of a certain entity is handled by ACLs. [Read more about Elgg's ACLs here.][AccessControl]

Checking permission

List of recognized verbs

We stick to ActivityStreams verbs as much as possible, and encourage you to do the same. Here are some common examples:

  • post
  • edit
  • delete
  • follow
  • join
  • like

More verbs: http://activitystrea.ms/specs/json/schema/activity-schema.html#verbs

Some custom verbs that Elgg supports out of the box:

  • ... list some ...

Note that you can support your new verbs simply by passing a custom string to the $verb argument and registering a hook handler for that verb. If you do this, we recommend namespacing your verb to avoid conflicts.

Examples

Can the user edit a blog?

// For the current user
$session->userCan('edit', $blog);
elgg_user_can('edit', $blog);

// For a particular user, not necessarily logged in
$user->can('edit', $blog);

Customizing permissions

Register a handler for the can, $verb [plugin hook][Hooks] to customize permissions.

elgg_register_plugin_hook_handler('can', 'edit', 'pages_edit_handler');

Your handler will be passed 3 $params arguments:

subject: The user who would be taking the action. A null value should be interpreted as the logged out user.

object: The ElggEntity to be acted upon. E.g. Can $user edit $object. Might be null depending on the verb in use.

target: The target of the action. E.g. Can $user move $blog to $target. Might be null depending on the verb in use.

Examples

Open up edit privileges for Elgg pages.

// start.php

elgg_register_plugin_hook_handler('can', 'edit', 'pages_edit_handler');

function pages_edit_handler($hook, $verb, $defaultResult, array $params) {
  $subject = $params['subject'];
  $page = $params['object'];  
  $target = $params['target']; // The 'edit' verb has no target, so this is null

  if ($verb == 'edit' && elgg_instanceof($page, 'object', 'page')) {
    // Always check for existence of $subject since user could be logged out.
    return $subject && (elgg_acl_has_member($page->write_access_id, $subject->guid)); 
  } else {
    return $defaultResult;
  }
}
<?php
class ElggHooksService {
/**
* Check whether the subject can perform the given action.
*
* Results are cached for the current page.
*
* A null subject should is interpreted as a logged out user.
*/
function can($verb, $subject = null, $object = null, $target = null) {
$params = array(
'subject' => $subject,
'object' => $object,
'target' => $target,
);
// TODO: Cache the result
return $this->trigger('can', $verb, $params, false);
}
}
<?php
class ElggSession {
/**
* Check whether the currently logged in user can perform an action.
*
* Passes "null" for the $subject if not logged in.
*/
function userCan($verb, ElggEntity $object = null, ElggEntity $target = null) {
return $this->hooks->can($verb, $this->getUser(), $object, $target);
}
/**
* Ensures that the user can perform the specified activity. Otherwise forwards to an error page.
*/
function assertUserCan($verb, ElggEntity $object = null, ElggEntity target = null) {
if ($this->userCan($verb, $object, $target)) {
return;
}
// If the user isn't logged in, forward to the login page, which could resolve the permission problem.
$this->assertLoggedIn(); // i.e. gatekeeper()
// emit 403 (permission denied) page ala gatekeeper functions
}
}
<?php
class ElggUser {
/**
* Check whether this user can perform some action.
*/
public function can($verb, ElggEntity $object = null, ElggEntity $target = null) {
return $this->hooks->can($verb, $this, $object, $target);
}
}
@mrclay
Copy link

mrclay commented Mar 24, 2013

Very cool and easy to understand. Implementing a few more examples would provide some idea on how most of the boilerplate is going to look and how we could minimize it.

Depending on plugin design, there could be lots of handlers for "can" hooks. Could get interesting!

@mrclay
Copy link

mrclay commented May 22, 2013

How would we check permission to post a blog (which doesn't yet exist)? I'd think we'd need capabilities like "post blog".

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment