I am looking to create a node access method to answer these specific needs:
1. My node represents a Business which is created by some super user.
2. This super user can now edit all of the Business fields.
3. This super user can now dynamically grant node specific access to the business staff members.
4. Business staff can only edit part of the node fields.
5. I would like to use existing (and reliable) modules if possible.

as simple as it may sound I'm still not sure which method is the right one for me.
I am new to drupal so I might be unaware of drupal best practices.
that's why I want your help and knowledge.

These are some of the ways I've come up with although each has it's drawbacks:
* The fields in a business will actually be nodes that reference the main node. use http://drupal.org/project/nodeaccess_nodereference for access control.
* The fields in a business will actually be nodes referenced to by a main node. I still don't know of a good module to handle grants.
* Spliting the Business node to 2 nodes "Business review" and "Business details", only "Business details" will be available for staff members to edit.
(But how do I combine the 2 though?)

(I tried using both http://drupal.org/project/nodeaccess and "content permission" (CCK) to allow staff edit access only to the right fields
- But I have found that total permissions are not INTERSECTED but rather UNION-ED, so staff members get too much access)

I would like to hear anything you think is relevant of your own experience. Thanks.

Comments

cayenne’s picture

I have found that in similar circumstances, using content (CCK) field permissions is a good base.

Let the SUperuser edit/view anything he wants. Let him assign "ownership" of the node to the staff member, but the field permissions only allow editing of "own" fields where permitted.

The "owning" staff member, then, can update only appropriate fields, while the superuser can do everything.

:)

rantebi’s picture

I wrote the original question, this is my answer for your use:

The node access is now managed using the http://drupal.org/project/nodeaccess module.
I reviewed many modules such as:
* http://drupal.org/project/nodeaccess_nodereference - Gives access to users if they have access to a referenced node.
* http://drupal.org/project/nodeaccess_userreference - Gives users access to a node if they are referenced in a CCK User Reference field of the node in question.
* http://drupal.org/project/nodeaccess_autoreference - Gives users automatic access to a node if they are somehow referenced to the node in question.
* http://drupal.org/project/acl - Only works if it is used with another module.
* http://drupal.org/project/content_access - Doesn't give per user per node permissions.
* and so on....

Surprisingly enough http://drupal.org/project/nodeaccess is the only module I've found that gives per user per node access.
it adds a grant tab to the nodes (you select which ones are grantable) in which it let's you handle the grants quite easily.
I don't like the interface looks though. I think it should show yow who already has permissions.

someday I might rewrite the access method using hook_node_grants, but for now it's Okay.

as for the fields and CCK fields that I didn't want to be accessible for all, I used the following code in hook_form_alter:

    if (!user_access('super user')) {
      $form['body_field']['#access'] = FALSE;
      $form['field_business_attributes']['#access'] = FALSE;
      $form['field_business_parameters']['#access'] = FALSE;
      $form['field_business_rating']['#access'] = FALSE;
    }

Hope this helps... :)

ressa’s picture

Hi,

I have just come to the same conclusion; http://drupal.org/project/nodeaccess is the module of choice, if you want to control both general content type access, and individual node accessibility, on a per user basis.

Can I ask you how you integrated the hiding of fields and CCK fields that you only wanted to be accessible for some roles? Did you include some code in your template.php?

Thanks.

cayenne’s picture

I worry.

That module seems almost unmaintained, with a large number of issues unresponded to. Interested to see how it goes....

On the other hand, 3000+ users can't be wrong.

:)

ressa’s picture

Yeah, the numbers are interesting: 3000 users (Nodeaccess) versus 12000 users (Content Access).

I have to correct myself: Content Access combined with the ACL module does seem to be able to control access on a per node per user basis.

Content Access can also override the access setting on a role basis for a node. Example: You want to give only users of the role 'manual' access to a specific node, a standard content type Page. With Content Access you can override the default settings for that content type at the node, whereas you can only add permissions with Nodeaccess. So you would have to create a new content type, and set the overall permissions on the Nodeaccess settings page to accomplish the goal.

Also, Content Access doesn't require the permissions to be rebuilt all the time...

ressa’s picture

I have now tested the Content Access module combined with ACL, and it works just fine. The downside is, that granting access to the individual nodes is done in a way which might not be the easiest for an ordinary user/editor. Access control for Content Profiles is cumbersome to dig out, for example.

An alternative solution is to combine the Content Access module with the Node Access User Reference module:

Allows you to configure a CCK user reference field so that the user whom is referenced in a node is granted access to view the node. There are also options to give the user access to edit or delete the node.

If you on top of that add the Field Permissions module to hide the reference field from ordinary users, admin and editors can reference a user from a drop down on the node edit form, thereby granting the referenced user access to the node.

rantebi’s picture

I was asked:

I read your post about node access control with interest (http://drupal.org/node/666614) and have myself decided to use Content Access with ACL, which seem to work just fine.

But now I want to hide some fields from the normal users, and you state that you did this. May I ask if you used a module, or perhaps added it to template.php?

My answer:

I have added a module and changed the form using hook_form_alter.

function my_module_form_alter(&$form, $form_id......and so on parameters){
  if ($form_id == 'content_type_name_node_form'){
    if (any condition you like you can try user_access function to check for permissions){
      $form['field_name']['#access'] = FALSE;
    }
  }
}

Modifying templates is not advised because they are supposed to handle the Display layer and not the Logical layer.
Also I wanted my fields to be more secured so I used '#access'.
I suggest you use debug (or debug prints) to see the right form_id and field_name.

cayenne’s picture

That works just fine to hide/expose fields. It adds many boxes to your permissions page, but whaddya gonna do?

:)

ressa’s picture

EDIT: Only use this as an example of how to build a module. I have since learned that hiding CCK fields is easier with the field_permissions module: http://drupal.org/project/field_permissions

Thanks for the help rantebi! I'll post my working example:

To build a custom module that hides the two form fields 'Company name' and 'Shop name' on the 'Customer unit' form from users that don't have administer users rights, make two files:

A .info file at sites/all/modules/custom/cck_fields_hide/cck_fields_hide.info:

; $Id$: cck_fields_hide.info
name = "Hide CCK fields"
description = "Hides 'Company name' and 'Shop name' fields from users without administer users rights."
version = "6.x-1.0"
core = "6.x"

... and a .module file at sites/all/modules/custom/cck_fields_hide/cck_fields_hide.module:

<?php
function cck_fields_hide_form_alter(&$form, $form_state, $form_id) {
  if (isset($form['type']) && isset($form['#node'])) {
    if ($form_id == 'customer_unit_node_form' && !user_access('administer users')) {
      $form['field_company_name']['#access'] = FALSE;
      $form['field_shop_name']['#access'] = FALSE;
    }   
  }
}

Go to the modules page and enable the new custom module, called 'Hide CCK fields'. The two fields should now be hidden from users that don't have administer users rights. Press Refresh if needed: Ctrl+F5. This module will only hide the fields on the form, you still have to set the fields to 'Hidden' on the display page to prevent them from being shown in node view.

The names of the fields (customer_unit, field_company_name and field_shop_name) can be found by looking under the content type: admin/content/node-type/customer-unit.

Note that the $form_id should be written with an underscore, and not a dash:
WRONG: customer-unit_node_form
CORRECT: customer_unit_node_form