Commit 56277e00 authored by good_man's avatar good_man

removing everything from master branch, and keeping the README file

parent a87776da
This is a plain master branch, don't use it, use the other versions branches,
Content Access Module
-----------------------
by Wolfgang Ziegler, nuppla@zites.net
<<<<<<< HEAD
Yet another node access module.
This module allows you to manage permissions for content types by role. It allows you to specifiy
custom view, view own, edit, edit own, delete and delete own permissions for each content type.
Optionally you can enable per content access settings, so you can customize the access for each
content node.
In particular
* it comes with sensible defaults, so you need not configure anything and everything stays working
* it is as flexible as you want. It can work with per content type settings, per content node settings
as well as with flexible Access Control Lists (with the help of the ACL module).
* it trys to reuse existing functionality instead of reimplementing it. So one can install the ACL
module and set per user access control settings per content node.
Furthermore the module provides conditions and actions for the rules module, which allows one
to configure even rule-based access permissions.
* it optimizes the written content node grants, so that only the really necessary grants are written.
This is important for the performance of your site.
* it takes access control as important as it is. E.g. the module has a bunch of simpletests to ensure
everything is working right.
* it respects and makes use of drupal's built in permissions as far as possible. Which means the
access control tab provided by this module takes them into account and provides you a good overview
about the really applied access control settings. [1]
So the module is simple to use, but can be configured to provide really fine-grained permissions!
Installation
------------
* Copy the content access module's directory to your modules directory and activate the module.
* Optionally download and install the ACL module too.
* Edit a content type at admin/content/types. There will be a new tab "Access Control".
ACL Module
-----------
You can find the ACL module at http://drupal.org/project/acl. To make use of Access Control Lists
you'll need to enable per content node access control settings for a content type. At the access
control tab of such a content node you are able to grant view, edit or delete permission for specific
users.
Running multiple node access modules on a site (Advanced!)
-----------------------------------------------------------
A drupal node access module can only grant access to content nodes, but not deny it. So if you
are using multiple node access modules, access will be granted to a node as soon as one of the
module grants access to it.
However you can influence the behaviour by changing the priority of the content access module as
drupal applies *only* the grants with the highest priority. So if content access has the highest
priority *alone*, only its grants will be applied.
By default node access modules use priority 0.
Footnotes
----------
[1] Note that this overview can't take other modules into account, which might also alter node access.
If you have multiple modules installed that alter node access, read the paragraph about "Running
multiple node access modules on a site".
=======
For the code have a look at the branches DRUPAL-5, ..
>>>>>>> 12d1e2400e3d4936cac12671420c0e4fd1175ba1
Upgrade from 5.x
----------------
You can easily upgrade from drupal 5 installations. After upgrading your drupal installation
just install the latest module and run update.php - it will automatically run the upgrade routine
which is update 6001.
After that the content access permissions for your site needs to be rebuilt. Just go to your
site and follow the instructions.
Notes for workflow-ng users
----------------------------
The workflow-ng integration has been properly upgraded to its 6.x version, the rules module.
However it has been a bit refactored: The 'Set content permissions' action has been removed in
favor of the 'Grant content permissions by role' and 'Revoke content permissions by role' as
this gives us more flexibility.
So the automatic upgrade of your configured rules converts the 'Set content permissions' action
to an 'Grant content permissions by role' action. If this doesn't fit, you'll have to edit it
manually.
All other conditions and actions have their equivalent in rules and will be automatically converted.
This diff is collapsed.
name = Content Access
description = Provides flexible content access control.
core = 7.x
package = Access control
files[] = content_access.rules.inc
files[] = tests/content_access.test
files[] = tests/content_access_acl.test
\ No newline at end of file
<?php
/**
* @file
* Install Content Access DB schema.
*
*/
/**
* Implementation of hook_uninstall().
*/
function content_access_uninstall() {
variable_del('content_access_settings');
}
/**
* Implementation of hook_schema().
*/
function content_access_schema() {
$schema['content_access'] = array(
'fields' => array(
'nid' => array(
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0
),
'settings' => array(
'type' => 'text',
'not null' => FALSE,
'size' => 'medium'
),
),
'primary key' => array('nid')
);
return $schema;
}
//@todo: do we need an upgrade function from D6 to D7?
\ No newline at end of file
This diff is collapsed.
<?php
/**
* @file
* Rules specific functions that expose content_access' API.
*/
/**
* Implementation of hook_action_info().
*/
function content_access_rules_action_info() {
$actions = array(
'content_access_action_grant_node_permissions' => array(
'label' => t('Grant content permissions by role'),
),
'content_access_action_revoke_node_permissions' => array(
'label' => t('Revoke content permissions by role'),
),
'content_access_action_reset_node_permissions' => array(
'label' => t('Reset content permissions'),
),
);
$items = array();
foreach ($actions as $name => $action) {
$items[$name] = array(
'label' => $action['label'],
'named parameter' => TRUE,
'parameter' => array(
'node' => array(
'type' => 'node',
'label' => t('Content'),
'description' => t('Add Desc.'),
),
'content_access' => array(
'type' => 'list<text>',
'label' => t('Role Based Access Control Settings'),
'optional' => TRUE,
'options list' => 'content_access_action_roles_permissions_list',
'restriction' => 'input',
),
),
'group' => t('Content Access'),
'callbacks' => array(
#'access' => 'rules_action_entity_createfetch_access',
'form_alter' => 'content_access_action_form_alter',
),
);
}
return $items;
}
/**
* Desc.
*/
function content_access_action_roles_permissions_list() {
return _content_access_roles_list();
}
/**
* Returns an array of operations used by the module.
*/
function _content_access_roles_list() {
$defaults = array();
$roles = array_map('filter_xss_admin', user_roles());
// Make sure defaults are set properly
foreach (_content_access_get_operations() as $op) {
foreach ($roles as $role) {
$defaults[$op][$op . ':' . $role] = $role;
}
}
return $defaults;
}
/**
* Desc.
*/
function content_access_list_to_checkboxes($element) {
$checkboxes = array();
$operations = _content_access_get_operations();
foreach ($operations as $op) {
$checkboxes[$op] = $element;
$checkboxes[$op]['#title'] = t($op);
$checkboxes[$op]['#type'] = 'checkboxes';
$checkboxes[$op]['#options'] = $element['#options'][$op];
unset($checkboxes[$op]['#default_value']);
// Set defaults values of checkboxes
foreach ($checkboxes[$op]['#options'] as $op_role => $permission) {
if (isset($element['#default_value'][$op_role])) {
$checkboxes[$op]['#default_value'][] = $op_role;
}
}
#$checkboxes[$op]['#process'] = array('form_process_checkboxes', 'content_access_checkboxes');
}
return $checkboxes;
}
/**
* Desc.
*/
function content_access_checkboxes_to_list($element) {
$list = $element[key($element)];
$list['#title'] = 'Value';
$list['#type'] = 'select';
unset($list['#options']);
foreach ($element as $op => $value) {
$list['#options'][$op] = $value['#options'];
}
return $list;
}
/**
* Desc.
*/
function content_access_checkboxes_to_list_submit($element) {
$list = array();
foreach (_content_access_roles_list() as $op => $op_roles) {
foreach ($op_roles as $op_role => $permission) {
if (isset($element[$op][$op_role]) && $element[$op][$op_role]) {
$list[$op_role] = $permission;
}
}
}
return $list;
}
/**
* Desc.
*/
function content_access_action_form_alter(&$form, &$form_state) {
// Include content_access.admin.inc in order to use it's functions
// e.g. content_access_disable_checkboxes() in
// content_access_rules_role_based_form()
#$include_file = drupal_get_path('module', 'content_access') . '/content_access.admin.inc';
#$form_state['build_info']['files']['content_access'] = $include_file;
#module_load_include('inc', 'content_access', 'content_access.admin');
// Desc.
$ca_element =& $form['parameter']['content_access']['settings']['content_access'];
$ca_element = content_access_list_to_checkboxes($ca_element);
// Add submit callback to process content_access_rules_role_based_form() vals
// @todo I think this should go into Rules just like the default form
// behaviour
// rules_ui_edit_element_submit is the default submit callback so we add it
// again
$form['submit']['#submit'] = array('content_access_action_settings_form_submit', 'rules_ui_edit_element_submit');
}
/**
* Desc.
*/
function content_access_action_settings_form_submit($form, &$form_state) {
// Desc.
$ca_element =& $form_state['input']['parameter']['content_access']['settings']['content_access'];
$ca_element = content_access_checkboxes_to_list_submit($ca_element);
$form_state['rules_element']->settings['content_access'] = $ca_element;
}
/**
* Verifies that per content settings are activated for the given node.
*/
function _content_access_rules_check_setting($node) {
// @todo node_get_types is D6 only
if (!content_access_get_settings('per_node', $node->type)) {
rules_log(t("Can't set per content permissions for content type @type. Make sure to have per content settings activated for content types you want to alter access control for.", array('@type' => node_get_types('name', $node->type))), TRUE);
return FALSE;
}
return TRUE;
}
/**
* Desc.
*/
function content_access_action_settings($param) {
$roles_ids = array_flip(user_roles());
foreach (_content_access_get_operations() as $op) {
$settings[$op] = array();
}
foreach ($param as $op_role => $role) {
$op = substr($op_role, 0, strpos($op_role, ':'));
$role_id = $roles_ids[$role];
$settings[$op][] = $role_id;
}
return $settings;
}
/**
* Action implementation: Grant permissions for a node.
*/
function content_access_action_grant_node_permissions($params) {
if (_content_access_rules_check_setting($params['node'])) {
$settings = content_access_action_settings($params['content_access']);
$ca_settings = array();
foreach (_content_access_get_operations() as $op) {
$settings += array($op => array());
$ca_settings[$op] = array_keys(array_flip(content_access_per_node_setting($op, $params['node'])) + array_flip($settings[$op]));
}
content_access_save_per_node_settings($params['node'], $ca_settings);
// A following node_save() updates the grants for us.
return array('node' => $params['node']);
}
}
/**
* Action implementation: Revoke permissions for a node.
*/
function content_access_action_revoke_node_permissions($params) {
if (_content_access_rules_check_setting($params['node'])) {
$settings = content_access_action_settings($params['content_access']);
$ca_settings = array();
foreach (_content_access_get_operations() as $op) {
$settings += array($op => array());
$ca_settings[$op] = array_diff(content_access_per_node_setting($op, $params['node']), $settings[$op]);
}
content_access_save_per_node_settings($params['node'], $ca_settings);
// A following node_save() updates the grants for us.
return array('node' => $params['node']);
}
}
/**
* Action implementation: Reset permissions for a node.
*/
function content_access_action_reset_node_permissions($params) {
if (_content_access_rules_check_setting($params['node'])) {
content_access_delete_per_node_settings($params['node']);
// A following node_save() updates the grants for us.
return array('node' => $params['node']);
}
}
\ No newline at end of file
This diff is collapsed.
<?php
/**
* @file
* Automatd SimpleTest Case for using content access module with acl module
*/
require_once(drupal_get_path('module', 'content_access') .'/tests/content_access_test_help.php');
class ContentAccessACLTestCase extends ContentAccessTestCase {
var $node;
/**
* Implementation of get_info() for information
*/
public static function getInfo() {
return array(
'name' => t('Content Access Module with ACL Module Tests'),
'description' => t('Various tests to check the combination of content access and ACL module.'),
'group' => 'Content Access',
);
}
/**
* Setup configuration before each test
*/
function setUp($module = '') {
parent::setUp('acl');
if (!module_exists('acl')) {
$this->pass('No ACL module present, skipping test');
return;
}
// Create test nodes
$this->node = $this->drupalCreateNode(array('type' => $this->content_type->type));
}
/**
* Test Viewing accessibility with permissions for single users
*/
function testViewAccess() {
// Exit test if ACL module could not be enabled
if (!module_exists('acl')) {
$this->pass('No ACL module present, skipping test');
return;
}
// Restrict access to this content type (access is only allowed for the author)
// Enable per node access control
$access_permissions = array(
'view[1]' => FALSE,
'view[2]' => FALSE,
'per_node' => TRUE,
);
$this->changeAccessContentType($access_permissions);
// Allow access for test user
$edit = array(
'acl[view][add]' => $this->test_user->name,
);
$this->drupalPost('node/'. $this->node->nid .'/access', $edit, t('Add User'));
$this->drupalPost(NULL, array(), t('Submit'));
// Logout admin, try to access the node anonymously
$this->drupalLogout();
$this->drupalGet('node/'. $this->node->nid);
$this->assertText(t('Access denied'), 'node is not viewable');
// Login test user, view access should be allowed now
$this->drupalLogin($this->test_user);
$this->drupalGet('node/'. $this->node->nid);
$this->assertNoText(t('Access denied'), 'node is viewable');
// Login admin and disable per node access
$this->drupalLogin($this->admin_user);
$this->changeAccessPerNode(FALSE);
// Logout admin, try to access the node anonymously
$this->drupalLogout();
$this->drupalGet('node/'. $this->node->nid);
$this->assertText(t('Access denied'), 'node is not viewable');
// Login test user, view access should be denied now
$this->drupalLogin($this->test_user);
$this->drupalGet('node/'. $this->node->nid);
$this->assertText(t('Access denied'), 'node is not viewable');
}
/**
* Test Editing accessibility with permissions for single users
*/
function testEditAccess() {
// Exit test if ACL module could not be enabled
if (!module_exists('acl')) {
$this->pass('No ACL module present, skipping test');
return;
}
// Enable per node access control
$this->changeAccessPerNode();
// Allow edit access for test user
$edit = array(
'acl[update][add]' => $this->test_user->name,
);
$this->drupalPost('node/'. $this->node->nid .'/access', $edit, t('Add User'));
$this->drupalPost(NULL, array(), t('Submit'));
// Logout admin, try to edit the node anonymously
$this->drupalLogout();
$this->drupalGet('node/'. $this->node->nid .'/edit');
$this->assertText(t('Access denied'), 'node is not editable');
// Login test user, edit access should be allowed now
$this->drupalLogin($this->test_user);
$this->drupalGet('node/'. $this->node->nid .'/edit');
$this->assertNoText(t('Access denied'), 'node is editable');
// Login admin and disable per node access
$this->drupalLogin($this->admin_user);
$this->changeAccessPerNode(FALSE);
// Logout admin, try to edit the node anonymously
$this->drupalLogout();
$this->drupalGet('node/'. $this->node->nid .'/edit');
$this->assertText(t('Access denied'), 'node is not editable');
// Login test user, edit access should be denied now
$this->drupalLogin($this->test_user);
$this->drupalGet('node/'. $this->node->nid .'/edit');
$this->assertText(t('Access denied'), 'node is not editable');
}
/**
* Test Deleting accessibility with permissions for single users
*/
function testDeleteAccess() {
// Exit test if ACL module could not be enabled
if (!module_exists('acl')) {
$this->pass('No ACL module present, skipping test');
return;
}
// Enable per node access control
$this->changeAccessPerNode();
// Allow delete access for test user
$edit = array(
'acl[delete][add]' => $this->test_user->name,
);
$this->drupalPost('node/'. $this->node->nid .'/access', $edit, t('Add User'));
$this->drupalPost(NULL, array(), t('Submit'));
// Logout admin, try to delete the node anonymously
$this->drupalLogout();
$this->drupalGet('node/'. $this->node->nid .'/delete');
$this->assertText(t('Access denied'), 'node is not deletable');
// Login test user, delete access should be allowed now
$this->drupalLogin($this->test_user);
$this->drupalGet('node/'. $this->node->nid .'/delete');
$this->assertNoText(t('Access denied'), 'node is deletable');
// Login admin and disable per node access
$this->drupalLogin($this->admin_user);
$this->changeAccessPerNode(FALSE);
// Logout admin, try to delete the node anonymously
$this->drupalLogout();
$this->drupalGet('node/'. $this->node->nid .'/delete');
$this->assertText(t('Access denied'), 'node is not deletable');
// Login test user, delete access should be denied now
$this->drupalLogin($this->test_user);
$this->drupalGet('node/'. $this->node->nid .'/delete');
$this->assertText(t('Access denied'), 'node is not deletable');
}
}
\ No newline at end of file
<?php
/**
* @file
* Helper class with auxiliary functions for content access module tests
*/
class ContentAccessTestCase extends DrupalWebTestCase {
var $test_user;
var $rid;
var $admin_user;
var $content_type;
var $url_content_type_name;
var $node1;
var $node2;
/**
* Preparation work that is done before each test.
* Test users, content types, nodes etc. are created.
*/
function setUp($module = '') {
if (empty($module)) {
// Enable content access module
parent::setUp('content_access');
}
else {
// Enable content access module plus another module
parent::setUp('content_access', $module);
// Stop setup when module could not be enabled
if (!module_exists($module)) {
$this->pass('No ' . $module . ' module present, skipping test');
return;
}
}
// Create test user with seperate role
$this->test_user = $this->drupalCreateUser();
// Get the value of the new role
// Needed in D7 because it's by default create two roles for new users
// one role is Authenticated and the second is new default one
// @see drupalCreateUser()
foreach ($this->test_user->roles as $rid => $role) {
if (!in_array($rid, array(DRUPAL_AUTHENTICATED_RID))) {
$this->rid = $rid;
break;
}
}
// Create admin user
$this->admin_user = $this->drupalCreateUser(array('access content', 'administer content types', 'grant content access', 'grant own content access', 'administer nodes', 'access administration pages'));
$this->drupalLogin($this->admin_user);
// Rebuild content access permissions
node_access_rebuild();
// Create test content type
$this->content_type = $this->drupalCreateContentType();
}
/**
* Change access permissions for a content type
*/
function changeAccessContentType($access_settings) {
$this->drupalPost('admin/structure/types/manage/'. $this->content_type->type .'/access', $access_settings, t('Submit'));
$this->assertText(t('Your changes have been saved.'), 'access rules of content type were updated successfully');
}
/**
* Change access permissions for a content type by a given keyword (view, update or delete)
* for the role of the user
*/
function changeAccessContentTypeKeyword($keyword, $access = TRUE, $user = NULL) {
if ($user === NULL) {
$user = $this->test_user;
$roles[$this->rid] = $user->roles[$this->rid];
} else {
foreach ($user->roles as $rid => $role) {
if (!in_array($rid, array(DRUPAL_AUTHENTICATED_RID))) {
$roles[$rid] = $user->roles[$rid];
break;
}
}
}
$access_settings = array(
$keyword .'['. key($roles) .']' => $access,
);
$this->changeAccessContentType($access_settings);
}
/**
* Change the per node access setting for a content type
*/
function changeAccessPerNode($access = TRUE) {
$access_permissions = array(
'per_node' => $access,
);
$this->changeAccessContentType($access_permissions);
}
/**
* Change access permissions for a node by a given keyword (view, update or delete)
*/
function changeAccessNodeKeyword($node, $keyword, $access = TRUE) {
$user = $this->test_user;
$roles[$this->rid] = $user->roles[$this->rid];
$access_settings = array(
$keyword .'['. key($roles) .']' => $access,
);
$this->changeAccessNode($node, $access_settings);
}
/**
* Change access permission for a node
*/
function changeAccessNode($node, $access_settings) {
$this->drupalPost('node/'. $node->nid .'/access', $access_settings, t('Submit'));
$this->assertText(t('Your changes have been saved.'), 'access rules of node were updated successfully');
}
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment