Wordpress Access Control

Published
2012-10-04 02:06
Written by

WordPress is the most popular content management systems in the world and CiviCRM is the most popular open source CRM for non-profits and the civic sector. With CiviCRM 4.1 support for Wordpress, Wordpress users were able to use the most powerful CMS + CRM combination ever.      

But Wordpress lacks the fine grained access control feature, which are very well supported in Drupal and Joomla. In CiviCRM 4.1/4.2 If you want a wordpress user to access CiviCRM, you should give them administrator role, which will allow them to not only access all the CiviCRM Components, but also the administrative pages.    

To overcome this drawback in Wordpress + CiviCRM, Access Control feature (similar to permissions in Drupal) was developed for Wordpress and integrated into CiviCRM core and will be in CiviCRM 4.3 release. This feature is developed as CiviCRM Core and independent of any wordpress plugins (unless you want to create new WP roles). When CiviCRM plugin is activated, all the CiviCRM core/component permissions are injected as wordpress capabilities, so that each WP roles can be assigned different capabilities. By default, Administrator role will have all capabilities (permissions) in CiviCRM and all other roles can be assigned capabilities (permissions) in CiviCRM Navigation Menu >> Administer >> Users and Permissions >> Permissions (Access Control)

One other drawback in Wordpress is that Wordpress does not deal with Anonymous users, which makes it hard for administrators to manage access to public event/contribution pages in Wordpress/CiviCRM installation. To overcome this, CiviCRM injects a new role (Anonymous User) in the wordpress instance, so that this role can be used to assign capabilities for anonymous users accessing public event/contribution pages.

 

Wordpress Access Control - Administrative Screen

 

Administrator sets permissions for 'Event Manager' Role

 

'Event Manager' user logged into CiviCRM

 

Filed under

Comments

Does anyone know an estmated release date for version 4.3?

 

BTW, this is fabulous that this is being addressed. thank you so much!

 

I suspect we'll hit code freeze / alpha by end of novemeber or so. 4.3 will be out early next year

Anonymous (not verified)
2012-10-05 - 08:33

Does this mean 4.3 will now enable us to post CiviCRM directory listings to the Wordpress front-end?  I believe when I asked about this capability before, the limitation cited was the lack of Access control (or something like that) in Wordpress?

Anonymous (not verified)
2012-11-08 - 10:14

Can you use the built in Wordpress capabilities to provide a more granular access control? You can add capabilities to a role, so for example when the plugin is installed call wp_civicrm_capability:

// setup capabilities when the plugin is first activated
register_activation_hook(__FILE__, 'wp_civicrm_capability');

instead of the way it is currently called by using an add_action('init', ...

This has the advantage that the capabilities are set ONE time at install and can then be subsequently modified.
Then in wp_civicrm_capability you can add a bunch of custom capabilities to the built in roles of admin, super admin like so:

//access civicrm page menu link to particular roles
$roles = array('super_admin', 'administrator', 'editor');
  foreach ($roles as $role) {
    $wp_roles->add_cap($role, 'civicrm_access_civicrm');
    ...
    if ($role != 'editor') {
      $wp_roles->add_cap($role, 'civicrm_administer_civicrm');
      ...
    }
  }

Then when you build out the access control page in CiviCRM you will expose just the civicrm_... capabilities against the current WordPress roles.

You could also check the permissions of the current user by modifying the check() function in wordpress.php something like this:

	  /**
	   * given a permission string, check for access requirements
	   *
	   * @param string $str the permission to check
	   *
	   * @return boolean true if yes, else false
	   * @static
	   * @access public
	   */
	  static
	  function check($str) {
	    // for administrators give them all permissions
	    if (!function_exists('current_user_can')) {
	      return TRUE;
	    }
	    $cap = 'civicrm_'.strtolower(str_replace(' ', '_', $str));
	    if (current_user_can($cap)) {
	    return TRUE;
	    }

Hi Gavin

We already use the inbuilt wordpress capabilities to manage the access control. The below code is used to inject the minimum capabilities for all wordpress roles and also to create a new role 'Anonuymous user' with miminum capabilities to access online events/contribution/profile pages, when civicrm hook is activated.

 

register_activation_hook( __FILE__, 'civicrm_activate');

function civicrm_activate() {
    // Assign minimum capabilities for all wordpress roles and create anonymous_user' role
    civicrm_wp_set_capabilities();
}

/*
* Function to create anonymous_user' role, if 'anonymous_user' role is not in the wordpress installation     
* and assign minimum capabilities for all wordpress roles
*/
function civicrm_wp_set_capabilities() {
    global $wp_roles;
    if (!isset($wp_roles)) {
      $wp_roles = new WP_Roles();
    }
 
    //Minimum capabilities (Civicrm permissions) arrays
    $min_capabilities =  array(
      'make_online_contributions' => 1,
      'profile_create' => 1,
      'profile_edit' => 1,
      'profile_view' => 1,
      'register_for_events' => 1,
      'view_event_info' => 1,
    );
 
    // Assign the Minimum capabilities (Civicrm permissions) to all WP roles
    foreach ( $wp_roles->role_names as $role => $name ) {
      $roleObj = $wp_roles->get_role($role);
      foreach ($min_capabilities as $capability_name => $capability_value) {
        $roleObj->add_cap($capability_name);
      }
    }
 
    //Add the 'anonymous_user' role with minimum capabilities.
    if (!in_array('anonymous_user' , $wp_roles->roles)) {
      add_role(
        'anonymous_user',
        'Anonymous User',
        $min_capabilities
      );
    }
}

And the capabilities/permissions are checked for the roles in the check function as below

 /**
   * given a permission string, check for access requirements
   *
   * @param string $str the permission to check
   *
   * @return boolean true if yes, else false
   * @static
   * @access public
   */
 public static function check($str) {
    // for administrators give them all permissions
    if (!function_exists('current_user_can')) {
      return TRUE;
    }

    if (current_user_can('super admin') || current_user_can('administrator')) {
      return TRUE;
    }

    // Make string lowercase and convert spaces into underscore
    $str = strtolower($str);
    $str = str_replace(" ","_",$str);

    if ( is_user_logged_in() ) {
      // Check whether the logged in user has the capabilitity
      if (current_user_can($str)) {
        return TRUE;
      }
    }
    else {
      //check the capabilities of Anonymous user)
      $roleObj = new WP_Roles();
      if ($roleObj->get_role('anonymous_user') != NULL && array_key_exists($str, $roleObj->get_role('anonymous_user')->capabilities)) {
        return TRUE;
      }
    }
    return FALSE;
  }

Please review the functions and let me know if i am doing anything wrong.