You are here

acl.module in ACL 6

Same filename and directory in other branches
  1. 8 acl.module
  2. 5 acl.module
  3. 7 acl.module

An API module providing by-user access control lists.

This module handles ACLs on behalf of other modules. The two main reasons to do this are so that modules using ACLs can share them with each other without having to actually know much about them, and so that ACLs can easily co-exist with the existing node_access system.

File

acl.module
View source
<?php

/**
 * @file
 * An API module providing by-user access control lists.
 *
 * This module handles ACLs on behalf of other modules. The two main reasons
 * to do this are so that modules using ACLs can share them with each
 * other without having to actually know much about them, and so that
 * ACLs can easily co-exist with the existing node_access system.
 */

/**
 * Create a new ACL.
 *
 * The client module will have to keep track of the ACL. For that it can
 * assign either a $name or a $number to this ACL.
 *
 * @param $module
 *   The name of the client module.
 * @param $name
 *   An arbitrary name for this ACL, freely defined by the client module.
 * @param $number
 *   An arbitrary number for this ACL, freely defined by the client module.
 * @return
 *   The ID of the newly created ACL.
 */
function acl_create_new_acl($module, $name = NULL, $number = NULL) {
  $acl = array(
    'module' => $module,
    'name' => $name,
    'number' => $number,
  );
  drupal_write_record('acl', $acl);
  return $acl['acl_id'];
}

/**
 * Delete an existing ACL.
 */
function acl_delete_acl($acl_id) {
  db_query("DELETE FROM {acl} WHERE acl_id = %d", $acl_id);
  acl_remove_all_users($acl_id);
  db_query("DELETE FROM {acl_node} WHERE acl_id = %d", $acl_id);
}

/**
 * Add the specified UID to an ACL.
 */
function acl_add_user($acl_id, $uid) {
  $test_uid = db_result(db_query("SELECT uid FROM {acl_user} WHERE acl_id = %d AND uid = %d ", $acl_id, $uid));
  if (!$test_uid) {
    db_query("INSERT INTO {acl_user} (acl_id, uid) VALUES (%d, %d)", $acl_id, $uid);
  }
}

/**
 * Remove the specified UID from an ACL.
 */
function acl_remove_user($acl_id, $uid) {
  db_query("DELETE FROM {acl_user} WHERE acl_id = %d AND uid = %d ", $acl_id, $uid);
}

/**
 * Remove all users from an ACL.
 */
function acl_remove_all_users($acl_id) {
  db_query("DELETE FROM {acl_user} WHERE acl_id = %d", $acl_id);
}

/**
 * Provide a form to edit the ACL that can be embedded in other forms.
 * Pass $new_acl=TRUE if you have no ACL yet, but do supply a string
 * like 'my_module_new_acl' as $acl_id anyway.
 */
function acl_edit_form($acl_id, $label = NULL, $new_acl = FALSE) {
  module_load_include('admin.inc', 'acl');
  return _acl_edit_form($acl_id, $label, $new_acl);
}

/**
 * Provide access control to a node based upon an ACL id.
 */
function acl_node_add_acl($nid, $acl_id, $view, $update, $delete, $priority = 0) {
  db_query("DELETE FROM {acl_node} WHERE acl_id = %d AND nid = %d", $acl_id, $nid);
  db_query("INSERT INTO {acl_node} (acl_id, nid, grant_view, grant_update, grant_delete, priority) VALUES (%d, %d, %d, %d, %d, %d)", $acl_id, $nid, $view, $update, $delete, $priority);
}

/**
 * Remove an ACL completely from a node.
 */
function acl_node_remove_acl($nid, $acl_id) {
  db_query("DELETE FROM {acl_node} WHERE acl_id = %d AND nid = %d", $acl_id, $nid);
}

/**
 * Clear all of a module's ACL's from a node.
 */
function acl_node_clear_acls($nid, $module) {
  $result = db_query("SELECT acl_id FROM {acl} WHERE module = '%s'", $module);
  while ($o = db_fetch_object($result)) {
    $acls[] = $o->acl_id;
  }
  if ($acls) {
    db_query("DELETE FROM {acl_node} WHERE nid = %d AND acl_id IN (" . db_placeholders($acls) . ")", array_merge(array(
      $nid,
    ), $acls));
  }
}

/**
 * Gets the id of an ACL by name.
 */
function acl_get_id_by_name($module, $name) {
  return db_result(db_query("SELECT acl_id FROM {acl} WHERE module = '%s' AND name = '%s'", $module, $name));
}

/**
 * Gets the id of an ACL by number.
 */
function acl_get_id_by_number($module, $number) {
  return db_result(db_query("SELECT acl_id FROM {acl} WHERE module = '%s' AND number = %d", $module, $number));
}

/**
 * Determines if an acl has some assigned users
 */
function acl_has_users($acl_id) {
  return db_result(db_query("SELECT COUNT(uid) FROM {acl_user} WHERE acl_id = %d", $acl_id));
}

/**
 * Determines if an acl has a specific assigned user
 */
function acl_has_user($acl_id, $uid) {
  return 0 != db_result(db_query("SELECT COUNT(uid) FROM {acl_user} WHERE acl_id = %d AND uid = %d", $acl_id, $uid));
}

/**
 * Gets the uids of an acl
 */
function acl_get_uids($acl_id) {
  $result = db_query("SELECT uid FROM {acl_user} WHERE acl_id = '%d'", $acl_id);
  $return = array();
  while ($row = db_fetch_object($result)) {
    $return[$row->uid] = $row->uid;
  }
  return empty($return) ? NULL : $return;
}

/**
 * Implementation of hook_node_access_records().
 */
function acl_node_access_records($node) {
  if (!$node->nid) {
    return;
  }
  $result = db_query("SELECT n.*, 'acl' AS realm, n.acl_id AS gid, a.module FROM {acl_node} n INNER JOIN {acl} a ON n.acl_id = a.acl_id WHERE nid = %d", $node->nid);
  $grants = array();
  while ($grant = db_fetch_array($result)) {
    if (module_exists($grant['module']) && module_invoke($grant['module'], 'enabled')) {
      if (acl_has_users($grant['gid'])) {
        $grants[] = $grant;
      }
      else {

        //just deny access
        $grants[] = array(
          'realm' => 'acl',
          'gid' => $grant['gid'],
          'grant_view' => 0,
          'grant_update' => 0,
          'grant_delete' => 0,
          'priority' => $grant['priority'],
        );
      }
    }
  }
  return $grants;
}

/**
 * Implementation of hook_node_grants().
 */
function acl_node_grants($account, $op) {
  $array = array(
    'acl' => array(),
  );
  $result = db_query("SELECT acl_id FROM {acl_user} WHERE uid = %d", $account->uid);
  while ($row = db_fetch_object($result)) {
    $array['acl'][] = $row->acl_id;
  }
  return !empty($array['acl']) ? $array : NULL;
}

/**
 * Implementation of hook_nodeapi().
 */
function acl_nodeapi(&$node, $op, $teaser = NULL, $page = NULL) {
  switch ($op) {
    case 'delete':
      db_query("DELETE FROM {acl_node} WHERE nid = %d", $node->nid);
      break;
  }
}

/**
 * Implementation of hook_user().
 */
function acl_user($op, &$edit, &$account, $category = NULL) {
  switch ($op) {
    case 'delete':
      db_query("DELETE FROM {acl_user} WHERE uid = %d", $account->uid);
      break;
  }
}

/**
 * Implementation of hook_form_alter().
 *
 * Add a compatibility error message to the module display view if needed.
 */
function acl_form_system_modules_alter(&$form, $form_state) {
  if (!isset($form['#theme']) || $form['#theme'] != 'confirm_form') {
    if (module_exists('authcache')) {
      module_load_install('acl');
      $requirements = acl_requirements('runtime');
      drupal_set_message($requirements['acl']['title'] . ': ' . $requirements['acl']['value'], 'error');
    }
  }
}

/**
 * Implementation of hook_node_access_explain().
 */
function acl_node_access_explain($row) {
  static $interpretations = array();
  if ($row->realm == 'acl') {
    if (!isset($interpretations[$row->gid])) {
      $acl = db_fetch_object(db_query("SELECT * FROM {acl} WHERE acl_id = %d", $row->gid));
      $acl->tag = '?';
      if (!isset($acl->name)) {
        $acl->tag = $acl->number;
      }
      elseif (!isset($acl->number)) {
        $acl->tag = $acl->name;
      }
      else {
        $acl->tag = $acl->name . '-' . $acl->number;
      }
      $result = db_query("SELECT u.name FROM {acl_user} au, {users} u WHERE au.acl_id = %d AND au.uid = u.uid", $row->gid);
      while ($user = db_fetch_object($result)) {
        $users[] = $user->name;
      }
      if (isset($users)) {
        $users = implode(', ', $users);
        $interpretations[$row->gid] = _acl_get_explanation("{$acl->module}/{$acl->tag}: {$users}", $acl->acl_id, $acl->module, $acl->name, $acl->number, $users);
      }
      elseif ($row->gid == 0) {
        $result = db_query("SELECT an.acl_id, a.module, a.name FROM {acl_node} an JOIN {acl} a ON an.acl_id = a.acl_id LEFT JOIN {acl_user} au ON a.acl_id = au.acl_id WHERE an.nid = %d AND au.uid IS NULL", $row->nid);
        while ($acl = db_fetch_object($result)) {
          $rows[] = _acl_get_explanation("{$acl->acl_id}:&nbsp;{$acl->module}/{$acl->tag}", $acl->acl_id, $acl->module, $acl->name, $acl->number);
        }
        if (!empty($rows)) {
          return implode('<br />', $rows);
        }
        return 'No access via ACL.';
      }
      else {
        $interpretations[$row->gid] = _acl_get_explanation("{$acl->module}/{$acl->tag}: no users!", $acl->acl_id, $acl->module, $acl->name, $acl->number);
      }
    }
    return $interpretations[$row->gid];
  }
}

/**
 * Asks the client for its interpretation of the given grant record.
 */
function _acl_get_explanation($text, $acl_id, $module, $name, $number, $users = NULL) {
  $hook = $module . '_acl_explain';
  if (function_exists($hook)) {
    return '<span title="' . $hook($acl_id, $name, $number, $users) . '">' . $text . '</span>';
  }
  return $text;
}

Functions

Namesort descending Description
acl_add_user Add the specified UID to an ACL.
acl_create_new_acl Create a new ACL.
acl_delete_acl Delete an existing ACL.
acl_edit_form Provide a form to edit the ACL that can be embedded in other forms. Pass $new_acl=TRUE if you have no ACL yet, but do supply a string like 'my_module_new_acl' as $acl_id anyway.
acl_form_system_modules_alter Implementation of hook_form_alter().
acl_get_id_by_name Gets the id of an ACL by name.
acl_get_id_by_number Gets the id of an ACL by number.
acl_get_uids Gets the uids of an acl
acl_has_user Determines if an acl has a specific assigned user
acl_has_users Determines if an acl has some assigned users
acl_nodeapi Implementation of hook_nodeapi().
acl_node_access_explain Implementation of hook_node_access_explain().
acl_node_access_records Implementation of hook_node_access_records().
acl_node_add_acl Provide access control to a node based upon an ACL id.
acl_node_clear_acls Clear all of a module's ACL's from a node.
acl_node_grants Implementation of hook_node_grants().
acl_node_remove_acl Remove an ACL completely from a node.
acl_remove_all_users Remove all users from an ACL.
acl_remove_user Remove the specified UID from an ACL.
acl_user Implementation of hook_user().
_acl_get_explanation Asks the client for its interpretation of the given grant record.