...
 
Commits (36)
CHANGELOG for ACL for Drupal 5
ACL 5.x-1.8 (2010-07-17):
o #836822: Don't anonymize 'deny' grant records.
o #411210: Add German translation.
ACL 5.x-1.7 (2009-05-23):
Enhancements:
o Add new acl_get_uids() function.
o Improve hook_node_access_explain().
o #135687: Implement grant priority.
o #229451: Allow acl_edit_form() without pre-created acl_id.
ACL 5.x-1.6 (2008-03-12):
Enhancements:
o Improve acl_node_access_explain().
o New hook_node_access_explain() to help debugging with devel_node_access.module (existing functionality is unchanged!).
Bugs fixed:
o Implement hook_user('delete') and remove orphaned {acl_user} records.
o #231096: implement hook_nodeapi('delete') and remove orphaned {acl_node} records.
ACL 5.x-1.5:
Bugs fixed (2007-11-17):
o #168750: acl_id created without $db_prefix when using shared table.
o #169985: fixed acl db scheme (primary keys, utf8) and added an uninstallation routine
o #150106: tell the user to rebuild permissions after disabling ACL
o Fixed minor code formatting issue.
ACL 5.x-1.4:
Bugs fixed:
o fixed acl_remove_user()
o Changed acl_has_users() to use a COUNT() query rather than db_affected_rows()
which isn't always reliable on SELECT queries.
o fixed htmlspecialchars() warning if one removes the last user from an
o #135684 follow up, fixes denying access only to nodes that are assigned to an
o #135684 implement hook node grants and some other improvements
o #124070: acl_add_user had a typo preventing it from working.
o #124088: E_ALL fix in acl_edit_form
This module has no UI of its own and unless some other module uses it, it won't appear to add anything to your site. Only bother with this module if some other module tells you to.
\ No newline at end of file
This module has no UI of its own and unless some other module uses it,
it won't appear to add anything to your site. Only bother with this module
if some other module tells you to.
\ No newline at end of file
<?php
// $Id$
function acl_install() {
db_query("create table if not exists {acl} (
acl_id int(10) NOT NULL default 0,
module varchar(255),
name varchar(255),
KEY acl_id (acl_id)
);");
db_query("create table if not exists {acl_user} (
acl_id int(10) NOT NULL default 0,
uid int(10) NOT NULL default 0,
KEY acl_id (acl_id),
KEY uid (uid)
);");
db_query("create table if not exists {acl_node} (
acl_id int(10) NOT NULL default 0,
nid int(10) NOT NULL default 0,
grant_view tinyint(1) unsigned NOT NULL default '0',
grant_update tinyint(1) unsigned NOT NULL default '0',
grant_delete tinyint(1) unsigned NOT NULL default '0',
KEY acl_id (acl_id),
KEY nid (nid)
);");
drupal_set_message("acl database tables created.");
switch ($GLOBALS['db_type']) {
case 'mysql':
case 'mysqli':
db_query("create table if not exists {acl} (
acl_id int(10) NOT NULL default 0,
module varchar(255),
name varchar(255),
PRIMARY KEY (acl_id)
) /*!40100 DEFAULT CHARACTER SET utf8 */;");
db_query("create table if not exists {acl_user} (
acl_id int(10) NOT NULL default 0,
uid int(10) NOT NULL default 0,
PRIMARY KEY (acl_id, uid),
KEY uid (uid)
) /*!40100 DEFAULT CHARACTER SET utf8 */;");
db_query("create table if not exists {acl_node} (
acl_id int(10) NOT NULL default 0,
nid int(10) NOT NULL default 0,
grant_view tinyint(1) unsigned NOT NULL default '0',
grant_update tinyint(1) unsigned NOT NULL default '0',
grant_delete tinyint(1) unsigned NOT NULL default '0',
priority smallint(2) NOT NULL default '0',
PRIMARY KEY (acl_id, nid)
) /*!40100 DEFAULT CHARACTER SET utf8 */;");
break;
case 'pgsql':
db_query("CREATE TABLE {acl} (
acl_id integer NOT NULL DEFAULT 0,
module varchar(255),
name varchar(255),
PRIMARY KEY (acl_id)
);");
db_query("CREATE SEQUENCE {acl}_acl_id_seq;");
db_query("CREATE TABLE {acl_user} (
acl_id integer NOT NULL DEFAULT 0,
uid int NOT NULL DEFAULT 0,
PRIMARY KEY (acl_id, uid)
);");
db_query("CREATE INDEX {acl_user}_uid_index ON {acl_user} (uid)");
db_query("CREATE TABLE {acl_node} (
acl_id integer NOT NULL DEFAULT 0,
nid int NOT NULL DEFAULT 0,
grant_view smallint NOT NULL default 0,
grant_update smallint NOT NULL default 0,
grant_delete smallint NOT NULL default 0,
priority smallint NOT NULL default 0,
PRIMARY KEY (acl_id, nid)
);");
break;
}
}
/*
* Implementation of hook_uninstall
*/
function acl_uninstall() {
if ($GLOBALS['db_type'] == 'pgsql') {
db_query('DROP INDEX {acl_user}_uid_index');
}
db_query('DROP TABLE {acl}');
db_query('DROP TABLE {acl_user}');
db_query('DROP TABLE {acl_node}');
}
/**
* Fixes table prefix
*/
function acl_update_1() {
$ret = array();
switch ($GLOBALS['db_type']) {
case 'mysqli':
case 'mysql':
db_query('LOCK TABLES {sequences} WRITE');
$ret[] = update_sql("UPDATE {sequences} SET name = '". db_prefix_tables('{acl}_acl_id') ."' WHERE name = 'acl_id'");
db_query('UNLOCK TABLES');
break;
case 'pgsql':
db_query('START TRANSACTION;');
$ret[] = update_sql("CREATE SEQUENCE {acl}_acl_id_seq START ". db_next_id('acl_id'));
db_query('COMMIT;');
break;
}
return $ret;
}
/**
* Fixes primary keys
*/
function acl_update_2() {
$ret = array();
switch ($GLOBALS['db_type']) {
case 'mysqli':
case 'mysql':
// drop the previously created indexes (except for acl_user.uid)
$ret[] = update_sql('ALTER TABLE {acl} DROP INDEX acl_id');
$ret[] = update_sql('ALTER TABLE {acl_user} DROP INDEX acl_id');
$ret[] = update_sql('ALTER TABLE {acl_node} DROP INDEX acl_id');
$ret[] = update_sql('ALTER TABLE {acl_node} DROP INDEX nid');
// create new indexes (as primary keys this time)
$ret[] = update_sql('ALTER TABLE {acl} ADD PRIMARY KEY (acl_id)');
$ret[] = update_sql('ALTER TABLE {acl_user} ADD PRIMARY KEY (acl_id, uid)');
$ret[] = update_sql('ALTER TABLE {acl_node} ADD PRIMARY KEY (acl_id, nid)');
break;
case 'pgsql':
$ret[] = update_sql('ALTER TABLE {acl} DROP PRIMARY KEY , ADD PRIMARY KEY (acl_id)');
$ret[] = update_sql('ALTER TABLE {acl_user} DROP PRIMARY KEY , ADD PRIMARY KEY (acl_id, uid)');
$ret[] = update_sql('ALTER TABLE {acl_node} DROP PRIMARY KEY , ADD PRIMARY KEY (acl_id, nid)');
$ret[] = update_sql('CREATE INDEX {acl_user}_uid_index ON {acl_user} (uid)');
break;
}
return $ret;
}
/*
* Updates tables to use utf8 for mysql
*/
function acl_update_3() {
$ret = array();
// Only for MySQL 4.1+
switch ($GLOBALS['db_type']) {
case 'mysqli':
break;
case 'mysql':
if (version_compare(mysql_get_server_info($GLOBALS['active_db']), '4.1.0', '<')) {
return array();
}
break;
case 'pgsql':
return array();
}
$ret = update_convert_table_utf8('acl');
$ret = array_merge($ret, update_convert_table_utf8('acl_node'));
$ret = array_merge($ret, update_convert_table_utf8('acl_user'));
return $ret;
}
/**
* Put back acl_node(nid) index for deleting nodes and clean up {acl_node}.
*/
function acl_update_4() {
$ret = array();
switch ($GLOBALS['db_type']) {
case 'mysqli':
case 'mysql':
$ret[] = update_sql("ALTER TABLE {acl_node} ADD INDEX (nid)");
break;
case 'pgsql':
$ret[] = update_sql('CREATE INDEX {acl_node}_nid_index ON {acl_node} (nid)');
break;
}
db_query("DELETE FROM {acl_node} WHERE nid NOT IN (SELECT nid FROM {node})");
return $ret;
}
/**
* Clean up {acl_user}.
*/
function acl_update_5() {
$ret = array();
db_query("DELETE FROM {acl_user} WHERE uid NOT IN (SELECT uid FROM {users})");
return $ret;
}
/**
* Add priority column.
*/
function acl_update_6() {
$ret = array();
switch ($GLOBALS['db_type']) {
case 'mysqli':
case 'mysql':
$ret[] = update_sql("ALTER TABLE {acl_node} ADD priority smallint(2) NOT NULL default 0");
break;
case 'pgsql':
db_add_column($ret, 'acl_node', 'priority', 'smallint', array('default' => 0, 'not null' => TRUE));
break;
}
return $ret;
}
<?php
// $Id$
/**
/**
* @file acl.module
*
*
* This module handls 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.
*/
/**
* Implementation of hook_help
*/
function acl_help($section) {
switch($section) {
case 'admin/modules#description':
return t('acls module provides an API for other modules to use Access Control List. It contains no user-serviceable parts.');
}
}
/**
* Create a new ACL.
*/
function acl_create_new_acl($module, $name) {
$acl_id = db_next_id('acl_id');
$acl_id = db_next_id('{acl}_acl_id');
db_query("INSERT INTO {acl} (acl_id, module, name) VALUES (%d, '%s', '%s')", $acl_id, $module, $name);
return $acl_id;
}
......@@ -42,7 +31,7 @@ function acl_delete_acl($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));
$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);
}
......@@ -52,14 +41,14 @@ function acl_add_user($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);
db_query("DELETE FROM {acl_user} WHERE acl_id = %d AND uid = %d ", $acl_id, $uid);
}
/**
* Provide a special button type that doesn't get its #name blasted.
*/
function acl_elements() {
$type['acl_button'] = array('#input' => TRUE, '#button_type' => 'submit', '#form_submitted' => FALSE);
$type['acl_button'] = array('#input' => TRUE, '#button_type' => 'submit', '#executes_submit_callback' => FALSE);
return $type;
}
......@@ -69,45 +58,46 @@ function theme_acl_button($element) {
}
/**
* Provide a form to edit the ACL that can be embedded in other
* forms.
* 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) {
// Ensure the ACL in question even exists.
if (!$acl_name = db_result(db_query("SELECT name FROM {acl} WHERE acl_id = %d", $acl_id))) {
return $form;
function acl_edit_form($acl_id, $label = NULL, $new_acl = FALSE) {
$users = array();
if (!$new_acl) {
// Ensure the ACL in question even exists.
if (!$acl_name = db_result(db_query("SELECT name FROM {acl} WHERE acl_id = %d", $acl_id))) {
return array();
}
$result = db_query("SELECT u.uid, u.name FROM {users} u LEFT JOIN {acl_user} aclu ON aclu.uid = u.uid WHERE acl_id = %d", $acl_id);
while ($user = db_fetch_object($result)) {
$users[$user->uid] = $user->name;
}
}
if (!$label) {
$label = $acl_name;
if (!isset($label)) {
$label = (empty($acl_name) ? $acl_id : $acl_name);
}
$form = array(
'#type' => 'fieldset',
'#collapsible' => true,
'#type' => 'fieldset',
'#collapsible' => true,
'#title' => $label,
'#tree' => true);
$result = db_query("SELECT u.uid, u.name FROM {users} u LEFT JOIN {acl_user} aclu ON aclu.uid = u.uid WHERE acl_id = %d", $acl_id);
$users = array();
while ($user = db_fetch_object($result)) {
$users[$user->uid] = $user->name;
}
$form['acl_id'] = array('#type' => 'value', '#value' => $acl_id);
$form['deletions'] = array('#type' => 'hidden'); // placeholder
$form['deletions'] = array('#type' => 'checkboxes'); // placeholder
$form['delete_button'] = array(
'#type' => 'acl_button',
'#label' => t('Remove Checked')
);
$form['add'] = array(
'#type' => 'textfield',
'#title' => t('Add user'),
'#maxlength' => 60,
'#type' => 'textfield',
'#title' => t('Add user'),
'#maxlength' => 60,
'#size' => 40,
'#autocomplete_path' => 'user/autocomplete',
'#autocomplete_path' => 'user/autocomplete',
);
$form['add_button'] = array(
'#type' => 'acl_button',
......@@ -120,7 +110,7 @@ function acl_edit_form($acl_id, $label = NULL) {
);
$form['#after_build'] = array('acl_edit_form_after_build');
return $form;
}
......@@ -144,7 +134,7 @@ function acl_edit_form_after_build($form, $form_values) {
// ok tho cause #value still works for us.
$user_list = unserialize($form['user_list']['#value']);
if ($form['delete_button']['#value'] && is_array($form['deletions']['#value'])) {
foreach($form['deletions']['#value'] as $uid) {
foreach ($form['deletions']['#value'] as $uid) {
unset($user_list[$uid]);
}
}
......@@ -179,11 +169,11 @@ function acl_edit_form_after_build($form, $form_values) {
/**
* Provide access control to a node based upon an ACL id.
* Provide access control to a node based upon an ACL id.
*/
function acl_node_add_acl($nid, $acl_id, $view, $update, $delete) {
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) VALUES (%d, %d, %d, %d, %d)", $acl_id, $nid, $view, $update, $delete);
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);
}
/**
......@@ -207,6 +197,32 @@ function acl_node_clear_acls($nid, $module) {
}
}
/**
* Gets the id of an acl
*/
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));
}
/**
* Determines if an acl has some assigned users
*/
function acl_has_users($acl_id) {
return db_result(db_query("SELECT COUNT(aclu.uid) FROM {acl_user} aclu WHERE acl_id = %d", $acl_id));
}
/**
* 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_grants (from node_access)
*/
......@@ -214,10 +230,96 @@ function acl_node_access_records($node) {
if (!$node->nid) {
return;
}
$result = db_query("SELECT *, 'acl' AS realm, acl_id AS gid FROM {acl_node} WHERE nid = %d", $node->nid);
$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)) {
$grants[] = $grant;
if (module_exists($grant['module']) && module_invoke($grant['module'], 'enabled')) {
if (acl_has_users($grant['gid'])) {
$grants[] = $grant;
}
else {
//just deny access
$grants[] = array('grant_view' => 0, 'realm' => 'acl', 'gid' => $grant['gid']);
}
}
}
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, $a3 = NULL, $a4 = 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_disable
*/
function acl_disable() {
drupal_set_message(t('You have disabled the ACL module&mdash;to avoid permission problems you should now go to !link and click on the [!button] button!', array(
'!link' => l('admin/content/node-settings', 'admin/content/node-settings'),
'!button' => t('Rebuild permissions'),
)));
}
/**
* 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));
$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)) {
$interpretations[$row->gid] = "$acl->module/$acl->name: ". implode(', ', $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->acl_id:&nbsp;$acl->module/$acl->name";
}
if (!empty($rows)) {
return implode('<br />', $rows);
}
return 'No access via ACL.';
}
else {
$interpretations[$row->gid] = "$acl->module/$acl->name: no users!";
}
}
return $interpretations[$row->gid];
}
}