Your SlideShare is downloading. ×
0
Node Access in Drupal 7 (and Drupal 8)
Node Access in Drupal 7 (and Drupal 8)
Node Access in Drupal 7 (and Drupal 8)
Node Access in Drupal 7 (and Drupal 8)
Node Access in Drupal 7 (and Drupal 8)
Node Access in Drupal 7 (and Drupal 8)
Node Access in Drupal 7 (and Drupal 8)
Node Access in Drupal 7 (and Drupal 8)
Node Access in Drupal 7 (and Drupal 8)
Node Access in Drupal 7 (and Drupal 8)
Node Access in Drupal 7 (and Drupal 8)
Node Access in Drupal 7 (and Drupal 8)
Node Access in Drupal 7 (and Drupal 8)
Node Access in Drupal 7 (and Drupal 8)
Node Access in Drupal 7 (and Drupal 8)
Node Access in Drupal 7 (and Drupal 8)
Node Access in Drupal 7 (and Drupal 8)
Node Access in Drupal 7 (and Drupal 8)
Node Access in Drupal 7 (and Drupal 8)
Node Access in Drupal 7 (and Drupal 8)
Node Access in Drupal 7 (and Drupal 8)
Node Access in Drupal 7 (and Drupal 8)
Node Access in Drupal 7 (and Drupal 8)
Node Access in Drupal 7 (and Drupal 8)
Node Access in Drupal 7 (and Drupal 8)
Node Access in Drupal 7 (and Drupal 8)
Node Access in Drupal 7 (and Drupal 8)
Node Access in Drupal 7 (and Drupal 8)
Node Access in Drupal 7 (and Drupal 8)
Node Access in Drupal 7 (and Drupal 8)
Node Access in Drupal 7 (and Drupal 8)
Node Access in Drupal 7 (and Drupal 8)
Node Access in Drupal 7 (and Drupal 8)
Node Access in Drupal 7 (and Drupal 8)
Node Access in Drupal 7 (and Drupal 8)
Node Access in Drupal 7 (and Drupal 8)
Node Access in Drupal 7 (and Drupal 8)
Node Access in Drupal 7 (and Drupal 8)
Node Access in Drupal 7 (and Drupal 8)
Node Access in Drupal 7 (and Drupal 8)
Node Access in Drupal 7 (and Drupal 8)
Node Access in Drupal 7 (and Drupal 8)
Node Access in Drupal 7 (and Drupal 8)
Node Access in Drupal 7 (and Drupal 8)
Node Access in Drupal 7 (and Drupal 8)
Node Access in Drupal 7 (and Drupal 8)
Node Access in Drupal 7 (and Drupal 8)
Node Access in Drupal 7 (and Drupal 8)
Node Access in Drupal 7 (and Drupal 8)
Node Access in Drupal 7 (and Drupal 8)
Node Access in Drupal 7 (and Drupal 8)
Node Access in Drupal 7 (and Drupal 8)
Node Access in Drupal 7 (and Drupal 8)
Node Access in Drupal 7 (and Drupal 8)
Node Access in Drupal 7 (and Drupal 8)
Node Access in Drupal 7 (and Drupal 8)
Node Access in Drupal 7 (and Drupal 8)
Node Access in Drupal 7 (and Drupal 8)
Node Access in Drupal 7 (and Drupal 8)
Node Access in Drupal 7 (and Drupal 8)
Node Access in Drupal 7 (and Drupal 8)
Node Access in Drupal 7 (and Drupal 8)
Node Access in Drupal 7 (and Drupal 8)
Node Access in Drupal 7 (and Drupal 8)
Node Access in Drupal 7 (and Drupal 8)
Node Access in Drupal 7 (and Drupal 8)
Node Access in Drupal 7 (and Drupal 8)
Node Access in Drupal 7 (and Drupal 8)
Node Access in Drupal 7 (and Drupal 8)
Node Access in Drupal 7 (and Drupal 8)
Node Access in Drupal 7 (and Drupal 8)
Node Access in Drupal 7 (and Drupal 8)
Node Access in Drupal 7 (and Drupal 8)
Node Access in Drupal 7 (and Drupal 8)
Node Access in Drupal 7 (and Drupal 8)
Node Access in Drupal 7 (and Drupal 8)
Node Access in Drupal 7 (and Drupal 8)
Node Access in Drupal 7 (and Drupal 8)
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

Node Access in Drupal 7 (and Drupal 8)

8,516

Published on

This talk will look at the features and changes in the Node Access system for Drupal 7. …

This talk will look at the features and changes in the Node Access system for Drupal 7.

Out of the box, Drupal is a great system for creating and managing content. However, there are cases where your needs require additional requirements for which users can create, view, edit and delete content. To solve this problem, Drupal provides its Node Access system.

Node Access provides an API for determining the grants, or permissions, that a user has for each node. By understanding how these grants work, a module developer can create and enforce complex access rules.

We will cover some (or all) of the following topics.

- Node Access compared to user_access() and other permission checks.
- How Drupal grants node permissions.
- The node_access() function.
- hook_node_access() compared to {node_access}.
- Controlling permission to create content.
- Using hook_node_access().
- When to write a Node Access module.
- The {node_access} table and its role.
- Defining your moduleâs access rules.
- Using hook_node_access_records().
- Using hook_node_grants().
- Rebuilding the {node_access} table.
- Modifying the behavior of other modules.
- Using hook_node_access_records_alter().
- Using hook_node_grants_alter().
- Testing and debugging you module.
- Using Devel Node Access
- Roadmap for Drupal 8

Ken Rickard is the maintainer of the Domain Access module and wrote several of the patches for Node Access in Drupal 7.

Published in: Technology, Business
0 Comments
6 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
8,516
On Slideshare
0
From Embeds
0
Number of Embeds
2
Actions
Shares
0
Downloads
33
Comments
0
Likes
6
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. Node Access in Drupal 7 (and Drupal 8) Ken Rickard NYCamp 2012Sunday, July 22, 2012
  • 2. • Who the heck are you? • What is Node Access? • What changed in Drupal 7? • How do I....? • What’s up for Drupal 8?Sunday, July 22, 2012
  • 3. • Ken Rickard • Drupal since 2004 • Domain Access • rickard@Palantir.net • @agentrickardSunday, July 22, 2012
  • 4. Sunday, July 22, 2012
  • 5. Drupal 7 Module DevelopmentSunday, July 22, 2012
  • 6. AaronWinborn.comSunday, July 22, 2012
  • 7. What is Node Access?Sunday, July 22, 2012
  • 8. Sunday, July 22, 2012
  • 9. • Powerful • Unintelligible • Unpredictable • Multi-dimensionalSunday, July 22, 2012
  • 10. What is Node Access? Drupal’s system for controlling the access to nodes (content) for: • View • Edit • Delete • and now...CreateSunday, July 22, 2012
  • 11. Drupal 7 Goodness • Create permissions! • Alter hooks! • ‘Bypass node access’ • Access control modules • Node Access API modulesSunday, July 22, 2012
  • 12. Sunday, July 22, 2012
  • 13. chx moshe Crell Dave some Cohen guySunday, July 22, 2012
  • 14. Sunday, July 22, 2012
  • 15. Node Access is multipurpose • Filter listing queries. • Assert access rights on CRUD. • API for managing access rights.Sunday, July 22, 2012
  • 16. Sunday, July 22, 2012
  • 17. • Drupal 6: hook_db_rewrite_sql() • Drupal 7: ‘node access’ query flag.Sunday, July 22, 2012
  • 18. Filter queries in Drupal 6 $result = db_query(db_rewrite_sql( “SELECT nid FROM {node} WHERE status = 1 AND promote = 1 ORDER BY sticky DESC, created DESC” ));Sunday, July 22, 2012
  • 19. Filter queries in Drupal 7 $result = db_select(node, n) ->fields(n, array(nid)) ->condition(promote, 1) ->condition(status, 1) ->orderBy(sticky, DESC) ->orderBy(created, DESC) ->addTag(node_access) ->execute();Sunday, July 22, 2012
  • 20. Failure to tag your query is a security violation.Sunday, July 22, 2012
  • 21. Sunday, July 22, 2012
  • 22. Why?Sunday, July 22, 2012
  • 23. Sunday, July 22, 2012
  • 24. Sunday, July 22, 2012
  • 25. Blue Red Green Grey Our ClientsSunday, July 22, 2012
  • 26. Blue Red Green Grey Organic GroupsSunday, July 22, 2012
  • 27. With proper access control Recent Blue PostsSunday, July 22, 2012
  • 28. Without proper access control BlueSunday, July 22, 2012
  • 29. Sunday, July 22, 2012
  • 30. • Node Access is not user_access(). • Node Access is an API for content CRUD permissions. • It extends Drupal’s core permissions system. • It is contextual.Sunday, July 22, 2012
  • 31. Boolean assertions if (user_access(‘administer nodes’)) { return t(“I’ll be back.”); }Sunday, July 22, 2012
  • 32. Conditional access check hook_node_grants($account, $op) hook_node_access($node, $op, $account)Sunday, July 22, 2012
  • 33. Sunday, July 22, 2012
  • 34. • Those two functions look similar. • But they aren’t.Sunday, July 22, 2012
  • 35. node_access() Walk-through function node_access($op, $node, $account = NULL) { $rights = &drupal_static(__FUNCTION__, array()); if (!$node || !in_array($op, array(view, update, delete, create), TRUE)) { // If there was no node to check against, or the $op was not one of the // supported ones, we return access denied. return FALSE; } // If no user object is supplied, the access check is for the current user. if (empty($account)) { $account = $GLOBALS[user]; }Sunday, July 22, 2012
  • 36. // $node may be either an object or a node type. Since node types cannot be // an integer, use either nid or type as the static cache id. $cid = is_object($node) ? $node->nid : $node; // If weve already checked access for this node, user and op, return from // cache. if (isset($rights[$account->uid][$cid][$op])) { return $rights[$account->uid][$cid][$op]; } if (user_access(bypass node access, $account)) { $rights[$account->uid][$cid][$op] = TRUE; return TRUE; } if (!user_access(access content, $account)) { $rights[$account->uid][$cid][$op] = FALSE; return FALSE; }Sunday, July 22, 2012
  • 37. // We grant access to the node if both of the following conditions are met: // - No modules say to deny access. // - At least one module says to grant access. // If no module specified either allow or deny, we fall back to the // node_access table. $access = module_invoke_all(node_access, $node, $op, $account); if (in_array(NODE_ACCESS_DENY, $access, TRUE)) { $rights[$account->uid][$cid][$op] = FALSE; return FALSE; } elseif (in_array(NODE_ACCESS_ALLOW, $access, TRUE)) { $rights[$account->uid][$cid][$op] = TRUE; return TRUE; } // Check if authors can view their own unpublished nodes. if ($op == view && !$node->status && user_access(view own unpublished content, $account) && $account->uid == $node->uid && $account->uid != 0) { $rights[$account->uid][$cid][$op] = TRUE; return TRUE; }Sunday, July 22, 2012
  • 38. foreach (node_access_grants($op, $account) as $realm => $gids) { foreach ($gids as $gid) { $grants->condition(db_and() ->condition(gid, $gid) ->condition(realm, $realm) ); } } if (count($grants) > 0) { $query->condition($grants); } $result = (bool) $query ->execute() ->fetchField(); $rights[$account->uid][$cid][$op] = $result; return $result; }Sunday, July 22, 2012
  • 39. elseif (is_object($node) && $op == view && $node->status) { // If no modules implement hook_node_grants(), the default behavior is to // allow all users to view published nodes, so reflect that here. $rights[$account->uid][$cid][$op] = TRUE; return TRUE; } } return FALSE; }Sunday, July 22, 2012
  • 40. Sunday, July 22, 2012
  • 41. hook_node_access($node, $op, $account) • Replaces hook_access(). • Can be run by any module! • Can return TRUE, FALSE or NULL. • Used for access to individual nodes.Sunday, July 22, 2012
  • 42. Access control modules • Act on Create, View, Update & Delete. • No tables*. • No queries*. • Just business logic. • DENY, ALLOW, IGNORESunday, July 22, 2012
  • 43. The operation condition matters! ‘create’ ‘delete’ ‘update’ ‘view’Sunday, July 22, 2012
  • 44. Sunday, July 22, 2012
  • 45. /** * Implement hook_node_access(). * * Only allow posts by users more than two days old. */ function delay_node_access($node, $op, $account) { if ($op != create) { return NODE_ACCESS_IGNORE; } if (empty($account->created) || $account->created > (REQUEST_TIME - (48*3600))) { return NODE_ACCESS_DENY; } return NODE_ACCESS_IGNORE; }Sunday, July 22, 2012
  • 46. Hooray!Sunday, July 22, 2012
  • 47. • No more hook_menu_alter(). • Explicit DENY grants. • Explicit ALLOW grants. • Apply to all node types! • Apply to node creation!Sunday, July 22, 2012
  • 48. Boo!Sunday, July 22, 2012
  • 49. • Individual nodes / actions only. • Running lookup queries per node can be expensive. • Can override other modules. • Cannot generate accurate lists.Sunday, July 22, 2012
  • 50. Sunday, July 22, 2012
  • 51. NODE ACCESS API • Uses {node_access} for list queries. • Creates JOINs to return lists of nodes. • Does not act on ‘create’ operation. • Requires numeric keys.Sunday, July 22, 2012
  • 52. The {node_access} table.Sunday, July 22, 2012
  • 53. hook_node_access_records() Data Entry node_save() node_access_acquire_grants() {node_access}Sunday, July 22, 2012
  • 54. function example_node_access_records($node) { $grants[] = array( realm => example_author, gid => $node->uid, grant_view => 1, grant_update => 1, grant_delete => 1, priority => 0, ); return $grants; }Sunday, July 22, 2012
  • 55. hook_node_grants() Inbound Request $user node_access_grants() Page / Request RenderSunday, July 22, 2012
  • 56. function example_node_grants($account, $op) { if (user_access(access private content, $account)) { $grants[example] = array(1); } $grants[example_owner] = array($account->uid); return $grants; }Sunday, July 22, 2012
  • 57. • Map the user’s grants to the stored grants. • JOIN {node_access} to the query. • Return the node or not. • OR based access logic.Sunday, July 22, 2012
  • 58. • Two-part system! • One query does not cover all cases! ‘create’ ‘delete’ ‘update’ ‘view’Sunday, July 22, 2012
  • 59. Sunday, July 22, 2012
  • 60. Rebuilding the {node_access} tableSunday, July 22, 2012
  • 61. • Make sure you hook_node_load() your data. • node_load() must match node_save() • Other modules may depend on you!Sunday, July 22, 2012
  • 62. Devel Node Access • Debugging tools for developers. • And site administrators!Sunday, July 22, 2012
  • 63. hook_node_access_explain() /** * Implements hook_node_access_explain for devel.module */ function domain_node_access_explain($row) { $_domain = domain_get_domain(); $active = $_domain[subdomain]; $domain = domain_lookup($row->gid); $return = t(Domain Access) . -- ; switch ($row->realm) { case domain_all: if (domain_grant_all() == TRUE) { $return .= t(True: Allows content from all domains to be shown.); } else { $return .= t(False: Only allows content from the active domain (%domain) or from all affiliates., array(%domain => $active)); }Sunday, July 22, 2012
  • 64. Sunday, July 22, 2012
  • 65. Add debugging to your module, tooSunday, July 22, 2012
  • 66. Sunday, July 22, 2012
  • 67. hook_node_access_records_alter() • Change storage rules before they are written to the database! • Remember to alter node storage as needed, too!* • * Runs after node_save() :-(Sunday, July 22, 2012
  • 68. function hook_node_access_records_alter(&$grants, $node) { // Our module allows editors to mark specific articles // with the is_preview field. if ($node->is_preview) { // Our module grants are set in $grants[example]. $temp = $grants[example]; // Now remove all module grants but our own. $grants = array(example => $temp); } }Sunday, July 22, 2012
  • 69. hook_node_grants_alter() • Alter the user’s grants at request time. • Quick and easy!Sunday, July 22, 2012
  • 70. function hook_node_grants_alter(&$grants, $account, $op) { // Get our list of banned roles. $restricted = variable_get(example_restricted_roles, array()); if ($op != view && !empty($restricted)) { foreach ($restricted as $role_id) { if (isset($user->roles[$role_id])) { $grants = array(); } } }}Sunday, July 22, 2012
  • 71. hook_query_alter() /** * Implements hook_query_TAG_alter(). * * If enabled, force admins to use Domain Access rules. */ function domain_query_node_access_alter($query) { $admin_force = variable_get(domain_force_admin, FALSE); // In any of the following cases, do not enforce any rules. if (empty($admin_force) || !user_access(bypass node access) || domain_grant_all()) { return; } domain_alter_node_query($query); }Sunday, July 22, 2012
  • 72. Sunday, July 22, 2012
  • 73. It’s not a tumor.Sunday, July 22, 2012
  • 74. Drupal 8 Changes • Language-sensitive • Abstract to all entities • Remove hook_node_access()? • Better list queries in core? • Support AND and OR logic?Sunday, July 22, 2012
  • 75. function node_access($op, $node, $account = NULL, $langcode = NULL) { $rights = &drupal_static(__FUNCTION__, array()); ... // If weve already checked access for this node, user and op, return from // cache. if (isset($rights[$account->uid][$cid][$langcode][$op])) { return $rights[$account->uid][$cid][$langcode][$op]; } if (user_access(bypass node access, $account)) { $rights[$account->uid][$cid][$langcode][$op] = TRUE; return TRUE; } if (!user_access(access content, $account)) { $rights[$account->uid][$cid][$langcode][$op] = FALSE; return FALSE; }Sunday, July 22, 2012
  • 76. Key issues • Make a general access API • http://drupal.org/node/777578 • Make node_access() language aware • http://drupal.org/node/1658814 • Query madness • http://drupal.org/node/1349080Sunday, July 22, 2012
  • 77. Let’s get to workSunday, July 22, 2012
  • 78. • THANK YOU! • Ken Rickard • rickard@Palantir.net • @agentrickardSunday, July 22, 2012

×