Am I mistaken, any user can add a node with a taxonomy term that I have forbid them to view? This module should strip out terms from the "node create new ..." forms and "update node forms" so only terms that they have access to "Create" appear. This could also have a check when the node is validated to ensure that only terms the users is allowed to use have been selected.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

Dave Cohen’s picture

Status: Active » Closed (won't fix)

tac_lite will hide terms from a user if they have no permission to view the terms. In that case, the terms will never appear on the node create/edit form, or anywhere else on the site.

Drupal's node_access features dont cover create permissions. (user privileges do.) It's not clear to me that tac_lite can offer a feature for this that is safe for sites to use. In particular, I don't want one user to tag a node with certain terms, then have another user un-intentionally remove those terms when editing a node. This can happen if the second user cannot see the same terms. This can happen today - I may make changes to avoid that - I won't make changes that make it more likely.

For your case you can write a custom module that uses hook_form_alter to do what you want. If someone writes a good module that does this in conjunction with tac_lite, I'd consider adding tac_lite/contrib and placing it there.

markDrupal’s picture

So it almost does exactly what I want, only change would be to restrict showing the user the term unless they have permission to edit those terms.

Any chance you could point me to the spot where I could patch your module to allow only users with the "edit" permission to use it? If you don't think it is possible, I'll try writing a custom module.

Here is my problem:

My site has a shared documents section where different departments can upload documents to their section, and edit others documents as long as they are in their department. So someone from the HR department can edit/delete any document in the HR section. Only problem is that anyone in any department, say IT department, can add a document to the HR section by using the taxonomy term "HR"

I don't want to hide all the HR documents from the IT guys, I just want to restrict access to add an HR document to only HR people.

markDrupal’s picture

Status: Closed (won't fix) » Needs review
FileSize
186 bytes

UPDATE---THIS VERSION IS OUTDATED---
I made a module that does this... attaching, guess I cant attach module files, so I'll just post the code here. Only known issue with this is if the user dosen't have access to update any term, and the term is required. But I guess in that case the user dosen't have access to post, maybe we should put in an access_denyed() instead of the node/add node/edit page in those situations.

START
tac_create.info

; $Id:$
name = Taxonomy Access Control Lite Create
description = Restrict Taxonomy selection on node add/edit forms to only terms the user can update
dependencies[] = tac_lite
core = 6.x

START
tac_create.module

/* 
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/**
 * Implementation of hook_form_alter()
 */
function tac_create_form_alter(&$form, $form_state, $form_id) {
  if(strpos($form_id, 'node_form') !== FALSE){
    global $user;

    if (user_access('administer tac_lite') || variable_get("tac_lite_config_create_restriction", 1) == 1) {
      // no need to restrict based on update permission in these cases
      return;
    }

    // the vocabularies containing protected info.
    $vids = variable_get('tac_lite_categories', array(0));

    // the terms this user is allowed to edit
    $tids = array();
    for ($i = 1; $i <= variable_get('tac_lite_schemes', 1); $i++) {
      $config = _tac_lite_config($i);
      if (in_array('grant_update', $config['perms'])) {
        $tids = array_merge($tids, _tac_lite_user_tids($user, $i));
      }
    }

    foreach((array)$form['taxonomy'] as $vid => $data){
      if (!is_numeric($vid) || !in_array($vid, $vids)){
        continue;
      }
      foreach($data['#options'] as $num => $term){
        if (!is_numeric($num)){
          continue;
        }
        if(!in_array(key($term->option), $tids)){
          unset($form['taxonomy'][$vid]['#options'][$num]);
        }
        if(count($form['taxonomy'][$vid]['#options']) == 1){
          unset($form['taxonomy'][$vid]);
        }
      }
    }
  }
  elseif ($form_id == 'tac_lite_admin_settings'){
    $form["tac_lite_config_create_restriction"] = array(
      '#type' => 'radios',
      '#title' => t('General Usage based on'),
      '#description' => t('Which permission should be used to limit the display of taxonomy terms when creating or editing a node? I.E. only users with this permission can create new nodes using that term.'),
      '#options' => array(1 => 'View', 2 => 'Update'),
      '#required' => TRUE,
      '#default_value' => variable_get("tac_lite_config_create_restriction", 1),
      '#weight' => -1,
    );
  }
}

markDrupal’s picture

Ends up that didn't cut it for me.
I had to change it in order to allow for both wiki style, everyone-can-edit ,and normal blog style, only-creator-can-edit, permissions on creating new nodes while allowing restrictions to taxonomy terms that can be used in the node add/edit forms. I also added in the access denied when a user tries to create a node for which they have no update/create permissions for the required vocabulary

You can add in the 'Create" permission the same as any other permission after you enable this module

/* 
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/**
 * Implementation of hook_form_alter()
 */
function tac_create_form_alter(&$form, $form_state, $form_id) {
  if(strpos($form_id, 'node_form') !== FALSE){
    global $user;

    if (user_access('administer tac_lite')) {
      // no need to restrict based on update permission in this cases
      return;
    }

    // the vocabularies containing protected info.
    $vids = variable_get('tac_lite_categories', array(0));

    // the terms this user is allowed to edit
    $tids = array();
    for ($i = 1; $i <= variable_get('tac_lite_schemes', 1); $i++) {
      $config = _tac_lite_config($i);
      if (in_array('grant_create', $config['perms']) || in_array('grant_update', $config['perms'])) {
        $tids = array_merge($tids, _tac_lite_user_tids($user, $i));
      }
    }

    foreach((array)$form['taxonomy'] as $vid => $data){
      if (!is_numeric($vid) || !in_array($vid, $vids)){
        //If not a vid, or not controled under TAC_lite
        continue;
      }
      foreach($data['#options'] as $num => $term){
        if (!is_numeric($num)){
          continue;
        }
        if(!in_array(key($term->option), $tids)){
          unset($form['taxonomy'][$vid]['#options'][$num]);
        }
        if(count($form['taxonomy'][$vid]['#options']) == 1){
          if($form['taxonomy'][$vid]['#required'] == TRUE){
           drupal_set_message(t('You have no permissions to add content to the required %name vocabulary. Please contact the site administrator if you believe you should have permission to add content.', array('%name' => $form['taxonomy'][$vid]['#title'])));
           drupal_access_denied();
           exit();
          }
          unset($form['taxonomy'][$vid]);
        }
      }
    }
  }
  elseif ($form_id == 'tac_lite_admin_scheme_form'){
    $scheme = $form['#parameters'][2];
    if ($scheme === 1){
      $config = variable_get('tac_lite_config_scheme_' . $scheme,
        array('name' => t('read and create'),
          'perms' => array('grant_view', 'grant_create')));
    }
    else{
      $config = variable_get('tac_lite_config_scheme_' . $scheme,
         array('name' => NULL, 'perms' => array()));
    }
    $form["tac_lite_config_scheme_$scheme"]['perms']['#options']['grant_create'] = t("create");
    $form["tac_lite_config_scheme_$scheme"]['perms']['#default_value'] = $config['perms'];
    $form["tac_lite_config_scheme_$scheme"]['perms']['#description'] .= t(' The "create" permission does not override add * node permissions. It only adds restrictions on the useable taxonomy terms when creating or editing a node. "update" permission always implies "create" permission. Without "view" permission, "create", "update", and "delete" permissions are meaningless');
  }
}

markDrupal’s picture

Anyone want to test this out?
It is working good for me

jaron’s picture

Would that apply to comments on a node as well? I'm having an issue where I'm using tac-lite with a forum to create private forums. The problem is that I'd like the forums and comments to be un-editable, meaning once they are posted, they are permanent. The create function on a node would handle the forum topic, but would the limitation also apply to comments on that topic? If so, I'd love to try it!

I should also mention I'm very new to Drupal, so any implementation advice would be helpful...not sure exactly what to do with all that code.
Thanks.

markDrupal’s picture

In short, no, currently this makes no attempt to restrict comment postings.

But I believe it is possible to patch this module to add that functionality. Your best bet is to add a hook_comment or hook_nodeapi to this module and remove the comment box when users are lacking the 'create' permission :

http://api.drupal.org/api/function/hook_comment/6
http://api.drupal.org/api/function/hook_nodeapi/6

for nodeapi, you'd probably have to edit the $node variable during the "prepare" operation.
for commentapi, it looks like you could only remove the edit/delete links during the "view" operation. To remove the comment box entirely, my guess is to do it in the nodeapi 'prepare' op.

good luck. I can offer more help if you need it.
Mark

markDrupal’s picture

In addition, you may be able to disallow editing comments if you change the permissions in the administration interface. But if you need more complex permissions based on Taxonomy, try patching this module

jaron’s picture

Added it and it's working great. Much appreciated. I'll post if I encounter any issues. Thanks!

Dave Cohen’s picture

I'm still pondering whether this really belongs in the module. I do see how it useful. But I also see that it

  • Adds overhead to every node form rendered by Drupal
  • Introduces potentially tricky issues

The tricky issues being... say I create a node and have full privileges for every term. You can edit the node, but cant create every term that I've tagged the node with. When you submit your changes, you also remove the terms I've tagged the node with.

Maybe this should be in its own module, say tac_lite_create.module, which people can enable at their own risk. Reasonable?

jaron’s picture

That's actually how I added it in. I didn't change the tac_lite module. I'm also using very delineated use of taxonomy so the multiple terms issue wouldn't be a problem for me.
By the way, tac_lite is great. Thanks.

markDrupal’s picture

I created it as it's own module that can be enabled if needed.

currently the name is tac_create, so create a subdirectory(within tac_lite) called tac_create and throw in the .info file and .module file

markDrupal’s picture

@Dave
The other point you make about if a node has terms "ABC" and "XYZ" and I can edit(edit permission implies create) "ABC" but cannot edit or create "XYZ" it is true that the term "XYZ" will be removed from the node when the user resaves it.

question is
Since the user has no permissions to edit "XYZ" should this be allowed to happen? Shouldn't the user be required to have all the permissions to edit the node?

If your answer is no, you can fix it by changing

        if(!in_array(key($term->option), $tids)){
          unset($form['taxonomy'][$vid]['#options'][$num]);
        }

to

        if(!in_array(key($term->option), $tids)){
          if(!in_array(key($term->option), $form['taxonomy'][$vid]['#default_value'])){
            unset($form['taxonomy'][$vid]['#options'][$num]);
          }
        }

Here is the new module/info file changing the name to tac_lite_create.module, tac_lite_create.info and the fix above


/**
 * Implementation of hook_form_alter()
 */
function tac_lite_create_form_alter(&$form, $form_state, $form_id) {
  if(strpos($form_id, 'node_form') !== FALSE){
    global $user;

    if (user_access('administer tac_lite')) {
      // no need to restrict based on update permission in this cases
      return;
    }

    // the vocabularies containing protected info.
    $vids = variable_get('tac_lite_categories', array(0));

    // the terms this user is allowed to edit
    $tids = array();
    for ($i = 1; $i <= variable_get('tac_lite_schemes', 1); $i++) {
      $config = _tac_lite_config($i);
      if (in_array('grant_create', $config['perms']) || in_array('grant_update', $config['perms'])) {
        $tids = array_merge($tids, _tac_lite_user_tids($user, $i));
      }
    }

    foreach((array)$form['taxonomy'] as $vid => $data){
      if (!is_numeric($vid) || !in_array($vid, $vids)){
        //If not a vid, or not controled under TAC_lite
        continue;
      }
      foreach($data['#options'] as $num => $term){
        if (!is_numeric($num)){
          continue;
        }
        if(!in_array(key($term->option), $tids)){
          //if the taxonmy is selected, allow the user to use it
          if(!in_array(key($term->option), $form['taxonomy'][$vid]['#default_value'])){
            unset($form['taxonomy'][$vid]['#options'][$num]);
          }
        }
        if(count($form['taxonomy'][$vid]['#options']) == 1){
          if($form['taxonomy'][$vid]['#required'] == TRUE){
           drupal_set_message(t('You have no permissions to add content to the required %name vocabulary. Please contact the site administrator if you believe you should have permission to add content.', array('%name' => $form['taxonomy'][$vid]['#title'])));
           drupal_access_denied();
           exit();
          }
          unset($form['taxonomy'][$vid]);
        }
      }
    }
  }
  elseif ($form_id == 'tac_lite_admin_scheme_form'){
    $scheme = $form['#parameters'][2];
    if ($scheme === 1){
      $config = variable_get('tac_lite_config_scheme_' . $scheme,
        array('name' => t('read and create'),
          'perms' => array('grant_view', 'grant_create')));
    }
    else{
      $config = variable_get('tac_lite_config_scheme_' . $scheme,
         array('name' => NULL, 'perms' => array()));
    }
    $form["tac_lite_config_scheme_$scheme"]['perms']['#options']['grant_create'] = t("create");
    $form["tac_lite_config_scheme_$scheme"]['perms']['#default_value'] = $config['perms'];
    $form["tac_lite_config_scheme_$scheme"]['perms']['#description'] .= t(' The "create" permission does not override add * node permissions. It only adds restrictions on the useable taxonomy terms when creating or editing a node. "update" permission always implies "create" permission.');
  }
}

name = Taxonomy Access Control Lite Create
description = Restrict Taxonomy selection on node add/edit forms to only terms the user can create
dependencies[] = tac_lite
core = 6.x
Dave Cohen’s picture

I'm OK with the files the way you've pasted them into code above. But for future reference you should learn how to create a patch. Patches are easier for maintainers to deal with.

As for the permission question, I don't know what most people would want or what is better. In Drupal, access control permissions are generally ORed together (rather than ANDed), so having one edit permission will let you edit a node, even if the node is tagged with terms you don't have permission to edit. On the other hand, if you have permission to edit a node but no privilege to use the node's input format you will be denied edit permission. So in a sense drupal has a precedent for both approaches. I'm inclined to the think the second user should be allowed to edit the node, and the hidden terms should either be lost, or preserved by the module without the user ever seeing them.

streever’s picture

I've installed this, but my user (who has create selected) is unable to see that term.

Could there be a conflicting permission? Permissions are typically designed with AND, not OR, correct? So adding permission in one place should be enough?

Sorry, to clarify--when they click "Create Content", no terms show up for the vocabulary. At one point I had Tax Acc Control full, with the same error. Could that be in conflict with this? I DID re-build permissions to use Tax Lite.

markDrupal’s picture

I don't think you should ever see an empty taxonomy box. If there are no terms available, it should error out with an access denied.

the create permission will not need to have the permissions rebuilt, they operate differently.

My guess is your user dosen't have the 'view' permission for that taxonomy term.
try to ensure the user can 'view' those taxonomy terms.

So if the user is missing the 'view' permission, the create permission cannot be used.

streever’s picture

You are correct Mark: thank you so much! (Sorry for my late reply)

norio’s picture

Thank you Mark & Dave! This new module + tac lite was exactly what I needed for a new site I'm putting together where a handful of authors are responsible for content in specific categories.

Thank you!

2ndmile’s picture

subscribe

John Pitcairn’s picture

Subscribing. Unsure whether we'll be using TAC lite to control view and edit/delete privileges (possibly just view), but if we do go with it for edit/delete control we'll need create control as well. Definitely not using TAC (full) for this because of the roles requirement, we'd need a ton of roles. Roles on their own may suffice for edit/delete/create however.

GuillaumeDuveau’s picture

sub

Oleksa-1’s picture

Very important feature for TAC lite.
But it looks that tac_lite_create does not work with forum. When user without create permissions for some term of forum, go to this term and above there is "create new forum topic" and user post topic to this (not allowed for him) term of forum.

UPD: module version tac_create from #4 works OK with forum terms

indytechcook’s picture

FileSize
1.17 KB

I took a different approach to this. I tried using the method above first, but it isn't compatible with Hierarchical Select. Instead I modified the hook_db_rewrite_sql to see if we are on a node add page.

Attached is a patch.

attheshow’s picture

subscribing

attheshow’s picture

Status: Needs review » Reviewed & tested by the community

Patch from indytechcook on comment 23 works correctly for me. Adds create permissions correctly and limits users from being able to create with taxonomy terms that they don't have access to create in.

Dave Cohen’s picture

Status: Reviewed & tested by the community » Active

The approach in #23 has problems. It makes terms disappear entirely from the site on all node/add pages. It's possible for modules to create content on other pages.

The better approach is to create another module which implements hook_form_alter to remove some terms from node create forms.

alexkb’s picture

markDrupal, thanks so much for this module/addon to the almost perfectly working tac_lite module - works great.

Dave Cohen’s picture

Version: 6.x-1.3 » 6.x-1.x-dev
Status: Active » Fixed

thanks to markDrupal, and by popular demand, just added this to modules/tac_lite.

I did change it slightly. I took 'create' out of the perms select field, and made it a checkbox instead. My feeling is that 'grant_create' was misleading because 'grants' are what you find in the node_access table, and create is not one of those.

So, if you're using the module as written above, you have to manually check the checkbox on the tac_lite admin forms for each scheme that applies. The latest 6.x-1.x.-dev build includes modules/tac_lite/tac_lite_create.module.

attheshow’s picture

Status: Fixed » Needs work

The dev version with the tac_lite_create.module does appear to work well. I do, however, think that the UI might be backwards. It seems like if the admin wants to limit create permissions, he should be checking the box for "create". It appears that in this implementation, you have to uncheck the "create" box in order to make it limit the list of terms the user sees. Does anyone else agree or am I way off?

Dave Cohen’s picture

Hmmm.... in the original module, create was listed as a permission alongside view, update, delete. That way the UI may have been more intuitive. Because create is similar to view, if they are not selected the user will not see the terms.

Here's how it is supposed to work...

1) If you enable tac_lite_create.module, the terms shown on node edit forms will be limited.
2) For each scheme where you check 'create', the terms associated with those schemes will be included on the node edit forms.

Any specific suggestions for improving the UI?

attheshow’s picture

Ok, that's starting to make more sense now. Thanks for the explanation. Maybe it should say something like what you've said above next to the checkbox. Maybe instead of "create", it should say "Do not limit the terms displayed on node edit forms".

Oleksa-1’s picture

Actually it is already mentioned in #22 that patch from #13 (which used in new dev version) does not work with forum. Patch from #4 works.
Usecase:
if you create forum topic this way
http://testsite.com/node/add/forum (you do not see term in select list for which you do not have "create permission")
but if you create forum topic this way
http://testsite.com/node/add/forum/116 (you see and can add forum topic to term for wich you do not have "create" permission.

For 116 - user has "view" perm, but does not have "create" perm

attheshow’s picture

@Oleksa, please use the 6.x-1.x-dev version of the module as opposed to one of the earlier patches. The discussion and code have progressed since that time.

Oleksa-1’s picture

really it is not clear from my post, but I am talking about 6.x-1.x-dev from 2010-Jun-22. It has issues with forum_module

attheshow’s picture

FileSize
2.46 KB

Just noticed that I'm getting an error when logged in with a non-admin user account and trying to add a node type that doesn't have taxonomy on it. Here's a patch where I've just added a check for $form['taxonomy']:

Johnny vd Laar’s picture

on line 52 of the tac_lite_create module there is this:
if (count($form['taxonomy'][$vid]['#options']) == 1) {

shouldn't that be a 0?

because you should still be able to create the node when there is 1 option. but not when there are none

Johnny vd Laar’s picture

There is also an issue when you are using multiple languages with i18n. When I create a translation then i suddenly get access to the taxonomy terms in the original node because they are set as the default option upon creation, while I shouldn't have permissions to them.

i've turned line 47 of tac_lite_create.module into this:
if (!in_array(key($term->option), $form['taxonomy'][$vid]['#default_value']) || is_null($form['nid']['#value'])) {

what do you think about it?

Dave Cohen’s picture

Johnny,

regarding #36, the code was trying to eliminate the select boxes with only "" in them. I've just checked in a fix.

#37, I'm not confident in that change. It seems to me that if some other module is providing defaults, we should honor that. Its not the job of this module to be smarter than the i18n module or any other. You're better off writing a form_alter in a custom module.

Dave Cohen’s picture

Status: Needs work » Fixed

I'm resolving this because tac_lite_create.module is checked in, and will be in the tac_lite 1.4 release. Thanks everyone!

Thanks attheshow, I checked in your change about the php notice.

I also changed the text on the admin form to (hopefully) make it more obvious how the various checkboxes affect the node forms.

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.

mstrelan’s picture

FYI - The term_permissions module has this exact functionality, but I much prefer to use TAC Lite. I wrote a patch for term_permissions to integrate with TAC Lite before finding this post. Just letting you know in case you want to collaborate.