At the moment to configure individual domain settings in /admin/build/domain/conf/(domain ID) , you need the 'administer domains' permission, which also gives you the right to create and assign domains.

However, I'd like to allow people in a 'domain manager' role to configure the settings of that domain, without giving them any rights over other domains. I'm wondering what you think about a separate 'configure domain' permission? It's be something we'd need, so I'd be willing to work up a patch. I just thought I'd run it by you to see if you had any better/simpler ideas :)

This permission could also be used when configuring domain-specific blocks and menus.

Alternatively we could keep the 'administer domains' permission, but when they access the settings page for a domain we check if they are assigned to that domain. However this means they could still access the domain create forms, bulk editing etc., right?

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

agentrickard’s picture

You would need a permission in Domain Conf module, and a custom access callback on the two existing menu items.

The access callback would check if:

-- User can 'administer domains' (or, alternately, 'configure all domains').
- or -
-- User can 'configure assigned domains' AND user is member of the domain being edited.

I would prefer not to make this change right now, as we are trying to get a stable release out.

#443296: Tasks for stable release

A patch would need to include documentation changes.

agentrickard’s picture

Status: Active » Postponed
agentrickard’s picture

Title: 'Domain configuration' permissions » Separate submodule permissions
Status: Postponed » Active

We should consider splitting out the permissions for all sub-modules.

- Domain Alias
- Domain Conf
- Doman Content
- Domain Theme

The others are already separated or not relevant.

Two ideas:

1) Just do it. Give all the submodules their own perms.

2) use hook_domain_perm() to allow modules to add their permissions settings to DA's. I think this makes for a cleaner interface.

agentrickard’s picture

Version: 6.x-2.0-rc6 » 6.x-2.0-rc8
Status: Active » Postponed

No responses. Postponed for D7.

agentrickard’s picture

Status: Postponed » Closed (won't fix)
greg.1.anderson’s picture

Version: 6.x-2.0-rc8 » 7.x-3.x-dev
Issue summary: View changes
Status: Closed (won't fix) » Needs review
FileSize
915 bytes

I needed this functionality as well, only for the domain_conf settings page, and for the domain_theme configuration page. I could get much of the desired behavior just by using hook_menu_alter to adjust the permissions handler for the form that I need. The code looks something like this:

/**
 * Implements hook_permission().
 */
function mymodule_permission() {
  $permissions = array(
    'administer site configuration for assigned domains' => array(
      'title' => t('Administer site configuration for assigned domains'),
      'restrict access' => TRUE,
    ),
  );
  return $permissions;
}

function mymodule_menu_alter(&$items) {
  // This is sufficient to allow our copyright base year to be edited, but other domain form items do not appear.
  $items['admin/structure/domain/view/%domain/config']['access callback'] = '_mymodule_domain_conf_access_callback';
  if (count($items['admin/structure/domain/view/%domain/config']['access arguments'] == 1)) {
    $items['admin/structure/domain/view/%domain/config']['access arguments'][] = 4;
  }
  $items['admin/structure/domain/view/%domain/conf-reset']['access callback'] = '_mymodule_domain_conf_access_callback';
  if (count($items['admin/structure/domain/view/%domain/conf-reset']['access arguments'] == 1)) {
    $items['admin/structure/domain/view/%domain/conf-reset']['access arguments'][] = 4;
  }
  $items['admin/structure/domain/view/%domain/theme/%/theme-settings']['access callback'] = '_mymodule_domain_conf_access_callback';
  if (count($items['admin/structure/domain/view/%domain/theme/%/theme-settings']['access arguments'] == 1)) {
    $items['admin/structure/domain/view/%domain/theme/%/theme-settings']['access arguments'][] = 4;
  }
}

function _mymodule_domain_conf_access_callback($permission, $domain) {
  if (user_access($permission)) {
    return TRUE;
  }
  // If the user is assigned to this domain, then allow them to
  // edit this domain configuration item if they have the right
  // to do so, as granted by our permission
  global $user;
  if (array_key_exists($domain['domain_id'], $user->domain_user)) {
    return user_access('administer site configuration for assigned domains');
  }
  return FALSE;
}

This works pretty well, except that the domain_conf settings page has no contents, due to the way permissions are tested for individual items on the page. The attached patch works around this problem by making an additional test for a similarly-named permission "for assigned domains".

If the overall technique here seems sound, I could roll together a patch that brought the hooks above into the domain_conf module, with documentation. Note, however, that with the current state of this code, there is no good way for a domain admin with limited permissions to navigate to these pages, as the admin pages that contain the links to them are inaccessible. Fixing this would take additional work. I don't have a proposal for this part quite yet, but will be working on it.

You may put this back to "Closed, won't fix" if this feature is not desired.

greg.1.anderson’s picture

Note also that the above example defines only the 'administer site configuration for assigned domains' permission, but some might also want to define additional permissions to enable other sections of the domain_conf settings page. The other permissions currently possible include 'administer domains for assigned domains', 'administer menu for assigned domains', and 'administer themes for assigned domains'.

greg.1.anderson’s picture

To give the user a way to get to the domain_conf settings form and the domain_theme configuration form, I expanded the hook_menu_alter to enable the domain list and domain edit page, and use hook_form_alter to disable the controls on the edit page that I don't want domain admins to be able to edit (unless they have 'administer domains').

function mymodule_form_alter(&$form, &$form_state) {
  if ($form['#form_id'] == 'domain_form') {
    if (!user_access('administer domains')) {
      foreach ($form as $key => $info) {
        if (is_array($info) && (array_key_exists('#type', $info))) {
          $form[$key]['#disabled'] = TRUE;
        }
      }
    }
  }
}

With a little more work to similarly filter the domain list, and also disable theme switching (unless the user has a specific permission to allow that), this should be pretty usable, and could be rolled in to the domain_conf module if desired.

greg.1.anderson’s picture

I refined the permissions and hooks to allow users with configuration permissions for their assigned domains only to still be able to see the top-level pages that they need to (in order to navigate down to the pages that they can edit) without being able to edit items they do not have permission to modify. The patch in #6 combined with the custom module shown below works really well.

I just need some feedback on whether this functionality should be rolled into domain_conf (best option, I think), or kept separate, as shown here. Once that is decided, I can put together another patch with documentation.

/**
 * Implements hook_form_alter
 */
function mymodule_form_alter(&$form, &$form_state) {
  if ($form['#id'] == 'domain_form') {
    if (!user_access('administer domains')) {
      foreach ($form as $key => $info) {
        if (is_array($info) && (array_key_exists('#type', $info))) {
          $form[$key]['#disabled'] = TRUE;
        }
      }
    }
  }
  if ($form['#id'] == 'domain-theme-form') {
    if (!user_access('administer domains') && !user_access('administer themes for assigned domains')) {
      $form['submit']['#disabled'] = TRUE;
      $form['intro'] = array('#markup' => t('You do not have permission to change the theme for this domain, but you may configure the theme settings for the selected theme.'));
      foreach ($form['theme'] as $id => $info) {
        if (isset($info['#type']) && ($info['#type'] == 'radio')) {
          if (!$form['theme'][$id]['#default_value']) {
            unset($form['theme'][$id]);
          }
          else {
            $form['theme'][$id]['#disabled'] = TRUE;
          }
        }
      }
    }
  }
}

/**
 * Implements hook_permission().
 */
function mymodule_permission() {
  $permissions = array(
    'administer site configuration for assigned domains' => array(
      'title' => t('Administer site configuration for assigned domains'),
      'restrict access' => TRUE,
    ),
    'administer menu for assigned domains' => array(
      'title' => t('Administer menu for assigned domains'),
    ),
    'administer themes for assigned domains' => array(
      'title' => t('Administer themes for assigned domains'),
      'description' => t('Select the theme for assigned domains, and adjust theme configuration.'),
    ),
    'administer theme configuration for assigned domains' => array(
      'title' => t('Administer theme configuration for assigned domains'),
      'description' => t("Allow a user who cannot change the domain theme to configure the selected theme's configuration."),
    ),
  );
  return $permissions;
}

function mymodule_menu_alter(&$items) {
  $items['admin/structure/domain']['access callback'] = '_mymodule_domain_view_access_callback';
  $items['admin/structure/domain']['access arguments'] = array('administer site configuration for assigned domains');
  $items['admin/structure/domain/view']['access callback'] = '_mymodule_domain_view_access_callback';
  $items['admin/structure/domain/view']['access arguments'] = array('administer site configuration for assigned domains');
  $items['admin/structure/domain/view/%domain']['access callback'] = '_mymodule_domain_conf_access_callback';
  $items['admin/structure/domain/view/%domain']['access arguments'] = array(4, 'administer site configuration for assigned domains');
  $items['admin/structure/domain/view/%domain/edit']['access callback'] = '_mymodule_domain_conf_access_callback';
  $items['admin/structure/domain/view/%domain/edit']['access arguments'] = array(4, 'administer site configuration for assigned domains');
  $items['admin/structure/domain/view/%domain/config']['access callback'] = '_mymodule_domain_conf_access_callback';
  $items['admin/structure/domain/view/%domain/config']['access arguments'] = array(4, 'administer site configuration for assigned domains');
  $items['admin/structure/domain/view/%domain/conf-reset']['access callback'] = '_mymodule_domain_conf_access_callback';
  $items['admin/structure/domain/view/%domain/conf-reset']['access arguments'] = array(4, 'administer site configuration for assigned domains');
  $items['admin/structure/domain/view/%domain/theme']['access callback'] = '_mymodule_domain_conf_access_callback';
  $items['admin/structure/domain/view/%domain/theme']['access arguments'] = array(4, 'administer themes for assigned domains', 'administer theme configuration for assigned domains');
  $items['admin/structure/domain/view/%domain/theme/%/theme-settings']['access callback'] = '_mymodule_domain_conf_access_callback';
  $items['admin/structure/domain/view/%domain/theme/%/theme-settings']['access arguments'] = array(4, 'administer themes for assigned domains', 'administer theme configuration for assigned domains');
}

function _mymodule_domain_view_access_callback($permission) {
  return user_access('administer domains') || user_access($permission);
}

function _mymodule_domain_conf_access_callback($domain, $permission, $alternate_permission = '') {
  if (user_access('administer domains')) {
    return TRUE;
  }
  // If the user is assigned to this domain, then allow them to
  // edit this domain configuration item if they have the right
  // to do so, as granted by our permission
  global $user;
  if (array_key_exists($domain['domain_id'], $user->domain_user)) {
    return user_access($permission) || (!empty($alternate_permission) && user_access($alternate_permission));
  }
  return FALSE;
}
greg.1.anderson’s picture

I am still using the patch from #6, although the one that is posted is inexplicably missing a $global user declaration. Here's an updated patch that includes that.

This patch represents the minimum amount of changes that could be made to domain_conf to allow a contrib module to provide additional permissions allowing for a site to have administrators that can configure certain admin functions for domains they are assigned to, but not to other domains. If there is any interest in having this as a core feature of the domain module, I'd be happy to expand the patch to include the features shown in #8 and #9 as part of the core domain module, and document it.

agentrickard’s picture

Interesting. I like the small code approach here. Do be careful to check that domain_user values are loaded, there are some edge cases where permissions are checked before a full user load has happened.