Exportables and user role IDs in features

Last updated on
22 December 2016

Drupal 7 will no longer be supported after January 5, 2025. Learn more and find resources for Drupal 7 sites

When implementing exportables support, module and feature developers should pay special attention to how role IDs are handled.

Many modules include user role IDs in exported configuration. For example, in Views, if access to a given view display is restricted by role, the view will export with the role id (rid) value of the role on the site on which the view is being exported.

When this view is imported on a new site, access will be granted to an indeterminate role, creating potential security issues.

Features itself provides "faux" exportables for Drupal core configuration that isn't natively exportable. Roles are exported by name. The roles for user permissions are exported as role names and converted to rid values on save. However, role names are not a reliable machine name; they may be manually edited, in which case they may become detached from role ID data.

For Drupal 8 machine names will be used for role IDs. Meantime, Drupal 7 modules need solutions to role ID issues.

If broken role export were a minor concern, perhaps it could be safely ignored--but that's far from being the case. Typically, roles are used to handle access control. Any breakage can leave a site open to security breaches.

Modules that explicitly handle user role names in export and import

A few modules include handling for role names and so don't require special steps for feature authors.

The Flag maintainer is considering a switch to role names, #1204918-4: Export roles as names rather than IDs.

Modules that require special handling

The many modules that include role ID data in exports include:

Strategies for managing role IDs in modules without specific support

Use permissions rather than roles for access handling

One way to avoid role ID issues altogether is to rely on user permissions rather than roles. For example, in building a view for use in a feature, you can restrict view access using one or more user permissions instead of restricting by role. That way, you avoid altogether the issue of role IDs in your exported component.

Leave components with role IDs out of features

One approach is to leave components with rids out of features exports and instead handled them manually. Here is an example using Content access data:

function myfeature_install() {
  // Set content_access view permissions for the member_page content type.
  // While these roles will be created by Features, they will not be available
  // yet when hook_install() is run, so we need to test for and create them
  // here.
  $roles = array();
  foreach (array('member', 'membership administrator') as $name) {
    // If there isn't an existing role by this name, create one.
    if (!$role = user_role_load_by_name($name)) {
      $role = new stdClass();
      $role->name = $name;
      user_role_save($role);
    }
    $roles[] = $role->rid;
  }

  // Don't create an administrator role, but use one if it exists.
  if ($admin_role = user_role_load_by_name('administrator')) {
    $roles[] = $admin_role->rid;
  }

  // Set only the 'view' and 'view_own' access. Other access will be managed by
  // regular user permissions.
  $settings = array(
    'view' => $roles,
    'view_own' => $roles,
  );

  variable_set('content_access_member_page', $settings);

}

Manually edit features to use an alter hook for role IDs

After generating your feature, make the following manual edits:

  • Locate the rid value or values in the exported code generated by features. Edit the exported code and remove the rid values. For example, if using the RedHen membership module, you would edit the [featurename].features.inc file to remove the exported role_id value from. featurename_default_redhen_membership_type()
  • Edit your [featurename].module file and add use an alter hook implementation to inserts the correct role ID. Example (again using RedHen membership):
    /**
     * Implements hook_default_redhen_membership_type_alter().
     *
     * If there is a 'member' role, tie it to the 'standard' membership type.
     */
    function debut_redhen_default_redhen_membership_type_alter(&$items) {
      if (isset($items['standard']) && ($role = user_role_load_by_name('member'))) {
        $items['standard']->role_id = $role->rid;
      }
    }
    
    

Use the Role export module

Role export generates a role machine name that's exported with a feature and used to generate a role ID.

Role export is particularly useful when Features is being used as a tool for dev > staging > live deployment on a single site. But it comes with some quirks and needs to be used carefully, particularly when building features that are designed to be used in distributions or apps.

  • Prior to building the feature, a feature developer must download and install Role export and edit all roles.
  • After enabling and configuring Role export, a site admin needs to remember to go separately to each place that role-related information is stored and edit and resave. Until that's done, the old (now nonexistent) role IDs will be in place and the site, as well as its exports, will be broken.
  • It introduces a dependency for all features involving role data. Without Role export, the feature will be broken.

Help improve this page

Page status: No known problems

You can: