To reproduce this:

  1. Create a node as a user with full field permissions, set values for all fields and save.
  2. Edit the node as a user who does not have permission to edit some of the set fields and save the node without changing any actual node values.

The fields that the under-privileged user does not have access to edit will be set to empty (or possibly default values).

The following issues may be related to this problem

Also, there was an issue opened for CCK for this same problem, however the proposed solution does not seem to work: http://drupal.org/node/144263

Comments

harry slaughter’s picture

Version: 5.x-1.9 » 5.x-1.10
Status: Active » Needs work
StatusFileSize
new11 KB

attached patch is against 5.x-1.10

this is not a pretty fix, but it's a start.

the current module completely removes form elements if a user does not have edit access for those fields. however, as far as i can tell, if you submit a cck node with missing form elements, then these fields are overwritten with the default values for the corresponding fields instead of preserving the existing values of those fields.

this patch leaves the form elements in the form and disables them so that the user cannot change them.

this may conflict with the 'view' field setting. if a user has neither view nor edit access to a field, he will still see the grayed out value when he edits a node.

the ideal way to fix this problem would be to somehow tell cck not to write certain fields to the DB, but I don't think that's possible.

the only other option i'm aware of is to make these hidden values, but the user would obviously still be able to 'view' them in the source.

IMHO, this patch is highly preferable to values being erased when a user does not have edit permissions.

harry slaughter’s picture

StatusFileSize
new11.35 KB

bah, i think the above patch is fubard, i'm just going to attach the already patched module.

harry slaughter’s picture

Status: Needs work » Closed (fixed)

disregard this patch, it does not fix the problem.

this problem seems to only occur with userreference fields. it probably can happen with other oddball fields whose data structure is borked.

i'm going to work around this problem by using a native CCK data type (like int/select for user reference).

harry slaughter’s picture

Status: Closed (fixed) » Active
StatusFileSize
new958 bytes

The attached patch DOES fix the problem, but it's got some comments and stuff in it that need to be removed before commit.

I'd be willing to help maintain this module.

hedac’s picture

thanks Harry,
could you attach the complete new .module file instead of the patch ?

ellanylea’s picture

subscribing as patch didn't work in our case...

hillaryneaf’s picture

subscribing...

Fayna’s picture

I am experiencing this same problem, having installed the CCK Permissions module before. It's not on my site anymore, but I still cannot edit nodes without the previous data in all of the fields disappearing. Has my data been messed up because of this module? I'm not sure what I can do.

I don't have any usereference fields, but I do have nodereference and nodereferrer fields.

btully’s picture

subscribing

robloach’s picture

Another use case for this is if you want the CCK field to only use the default value, and not let the user change it. This makes it so that the user doesn't see the widget when editing/creating the node, but the default value still gets saved. Related issue.

Vidarls’s picture

Status: Active » Closed (duplicate)

Tidying up a bit, http://drupal.org/node/118513 basically covers the same.

dericknwq’s picture

I am not sure why this isn't working at the first place but anyhow, I added one line to the _cfp_form_group_fieldset_helper function. Seems to be working for me now but I'm not quite sure if I'm doing the right thing.

Can you even have something like this?

<?php
$form['blabla']['bla'] = array(
  '#tree' => TRUE,
  '#type' => 'hidden'
);
?>

Here's the snippet:

<?php
function _cfp_form_group_fieldset_helper(&$form, $disallowed, $type, $verb){
  if (module_exists("fieldgroup")){
    foreach($form as $name => $item){
      if($disallowed[$name]){
        if (!(user_access(_cfp_content_to_readable($type, $name, $verb)))){
          // derick: START **********
          $form[$name]['#type'] = 'hidden';
          //unset($form[$name]);
          // derick: END **********
        }
      }
      
      // check this item to see if it is a group
      // if group, recurse to check for sub groups and or fieldsets
      if (strstr($name, "group")){
        if(is_array($form[$name])){    
          _cfp_form_group_fieldset_helper($form[$name], $disallowed, $type, $verb);
        }        
      }
    }
  }
} 
?>
socialnicheguru’s picture

Hi, I think this (Patch at #4 above) will solve my problem, but I am not quite sure of the syntax you used for the patch.

"+" "-" vs. "<" :>"
You also have some "unset" but I am not quite sure where they are to be inserted.

Pardon my newbiness :) And thanks!

Chris

liquidcms’s picture

StatusFileSize
new22.54 KB

Just to add my $.02 in to this.

- any of the patches above that do type = hidden are not the right way to do this: hidden is only hidden as long as the person doesn't look at the html source; plus using firebug it is pretty easy to still submit values that are "hidden"

I have patched one of the functions in cck perms to fix up an issue i had posted that Harry lists at the top:

"when a field that is hidden from a user is submitted by that user; the value gets lost" - possibly this may solve other issues here that are similar.

original code (5.10)


function _cfp_form_group_fieldset_helper(&$form, $disallowed, $type, $verb){
  if (module_exists("fieldgroup")){
    foreach($form as $name => $item){
      if($disallowed[$name]){ 
        if (!(user_access(_cfp_content_to_readable($type, $name, $verb)))){        
          unset($form[$name]);
        }
      }
      
      // check this item to see if it is a group
      // if group, recurse to check for sub groups and or fieldsets
      if (strstr($name, "group")){
        if(is_array($form[$name])){    
          _cfp_form_group_fieldset_helper($form[$name], $disallowed, $type, $verb);
        }        
      }
    }
  }
} 

the clue is that the function is ONLY meant to help remove the fieldset itself (hence the function name) - NOT any actual fields. To remove a fieldset it is required to do an unset; whereas if you do an unset on a field; the value will be lost when a submit is done.

my patch simply mods the one if statement to this:

      if($disallowed[$name] && $item['#type'] == 'fieldset'){ 

so that this routine only does what it was intended to do.

the routine which calls this then does the correct way to "hide" fields which is to set #access = false.

i have tested this on select fields, simple text fields, and field groups - haven't tested it with noderefs or other fields.

Peter Lindstrom
LiquidCMS - Content Management Solution Experts

liquidcms’s picture

Status: Closed (duplicate) » Needs review
scottrigby’s picture

I made that one line fix, and got the following error:

warning: array_key_exists() [function.array-key-exists]: The first argument should be either a string or an integer in /home/agilkel8/public_html/sites/all/modules/cck/userreference.module on line 84.
Assigned : Invalid user.

liquidcms’s picture

good to know - but as te last line of my earlier post said:

i have tested this on select fields, simple text fields, and field groups - haven't tested it with noderefs or other fields.

that would include userrefs

is it safe to say (as i would expect) that without the line change it doesnt work either?

scottrigby’s picture

Hi ptalindstrom
Oh I see - The error is just for the userref... ok. I must have been really tired and didn't even look at the error (oops).
But this is what I wanted to hide - actually two fields... One is a user ref, the other is a select field.

Right - without the line change, the default values aren't recorded when users submit a node that don't have field permissions for those fields.

You know - I've read the several related posts that discuss this issue... and I understand the need to do this the 'right way' (that is, so people can't see the fields just by looking at the html, or with firebug). But in my particular case right now, I'm not trying to keep the data private, but just trying to keep certain users from having to see things they don't care about (though certain roles do need to change the default value, so I can't just hide it with CSS unless dynamically per role). With that in mind, do you have any advice for how I might be able to 'work around' this issue on a per role basis? That would be way helpful...

:)
Scott

liquidcms’s picture

sadly though, it doesn't work for userreference fields.. :(

liquidcms’s picture

didn't find a clean solution to make this work for userreference fields; but i do have a solution. But first a few comments:

I had previously patched this module to work with fieldgroups correctly - bnot sure if this is still an outstanding issue or not. Part of the requirement for that was to have this modules system weight higher than that of the fieldgroup module (9). In a separate utility module for the site i am working on i adjust the CFP module weight to be +10.

This is important since the solution for making this work with userrefs needs to have a system weight less than that of the userref module (0). So to get 2 different weights i needed to create a new module just to make CFP work with userrefs. The code for this module is:

/**
 * Implementation of hook_help().
 */
function cck_fieldperms_userref_help($section) {
  if ($section == 'admin/modules#description') {
    return t('Helper module to get cck_field_perms to work with userreference fields. Install hook needs to 
    set system Weight = -20.');
  }
}



/**
 * Implementation of hook_nodeapi().
 *
 */
function cck_fieldperms_userref_nodeapi(&$node, $op, $form = NULL, $a4 = NULL) {
  
  
  // bad hack to get around cck_field_perms not working correctly with
  //  userreference fields
  if ($op == 'validate' || $op == 'submit') {
    $type = $node->type;
    if ($types = variable_get('cfp_types', null)) {
      if ($types[$type]) {
        $disallowed_fields = unserialize(variable_get('cfp_values', null));
        if ($disallowed_fields) { 
          foreach ($disallowed_fields[$type] as $disallowed_field => $value ) {
            if ($value == 0) continue;
            if (!(user_access(_cfp_content_to_readable($type, $disallowed_field, "view")))) {
              if (isset($node->{$disallowed_field}['uids'])) {     
                $node->{$disallowed_field}['uids'] = $node->{$disallowed_field}['uids'][0]; 
              }
            }   
          }
        }   
      }
    }
  }
}
socialnicheguru’s picture

subscribing

hedgefrog’s picture

subscribing
any progress on this?

hedgefrog’s picture

Hope it's ok to post this here but i thought this might help others in a similar situation looking for an alternative solution. I wanted to block certain CCK fields from editing by anyone at all once the node was created. I couldn't get CCK Field Permissions to work because of the bug stated in this thread. My workaround was to create a Workflow-ng rule with event 'Content is going to be saved'. In my conditions, i set my node type (in my case 'performance'). Then for the Actions i set a custom php code and put this in:

drupal_set_message("Once the performance has been saved for the first time, no further changes can be made to the performance date or the play name.");

//my cck date field:
$node->field_performance_date[0]["value"] = $node_unchanged->field_performance_date[0]["value"];

//my cck node reference field:
$node->field_related_play[0] = $node_unchanged->field_related_play[0]; 

node_save($node);

I'm not a programmer but i got help from here: http://drupal.org/node/202874

I imagine that it might also be possible to add in some code to account for user roles in the same place. This is working and at least tiding me over until the bug in this module is sorted out.

1kenthomas’s picture

noop; // subscribing

scott_earnest’s picture

I was able to create a workaround using computed field. This problem was happening for me with a node reference field, and I would imagine it is the same problem that is happening with user reference. I created a computed field that was a saved value of the node reference field. Then, on submit, I would check to see if the node reference field was blank/null/0. If it was, I would set it to the saved value (the case where the user did NOT have perms on the field). If not, I set the saved value to the node reference value (the case where the user DID have perms on the field).

The example code below is assuming that the admin (or user who has perms) will select some value. If the node reference field is not required, you can probablly add some code to see if the user has perms instead of seeing if it's 0.

if ($node->field_NODEREF_EXAMPLE[0]['nid']) {
	$node_field[0]['value'] = $node->field_NODEREF_EXAMPLE[0]['nid'];
}
else {
	$node->field_NODEREF_EXAMPLE[0]['nid'] = $node_field[0]['value'];
}

I needed to update my existing table with data, something like...
UPDATE content_type_CUSTOMTYPE
SET field_EXAMPE_SAVE_value = field_NODEREF_nid;

And followed it up with:
DELETE FROM cache_content

Then I created a view to show me all the nodes that had a missing value for the nodereference field.

That $node_unchanged thing looked nice, but did not seem to be an available object in Drupal 5.x.

scott_earnest’s picture

tag update

alxbridge’s picture

StatusFileSize
new1.52 KB

I was experiencing this problem with a checkbox field. I managed to make it work by extending cck_field_perms_nodeapi so that it reverts to saved values for any fields the user doesn't have permission to edit. See attached patch.

N.B. I've only tested this for my particular problem, so more extensive testing is definitely required.

noamdanon’s picture

Found a working patch for the case described here in this thread for userreference fields:

It should be added to the fix suggested by #14 above on the ckk_field_permissions field (add the check if field is fieldset before unsetting it).
my fix (tested it a few times, seems to work nicely) is to be applied in two places on the userreference cck module, not in the permissions module:

Fix #1 - in function userreference_filed, add the following:

        // In case we are using the CCK_FIELD_PERMS module with the userreference field,
        // there is a known bug reported in drupal http://drupal.org/node/186914 -
        // The bug is: default value is not used if user has no permissions, plus 
        // this kind of user if saving the node can clear/override the previous settings for this field.
        // The FIX: the $item['uid'] appear here as an array instead of simply string - 
        // so take the first element of it.
        // ----------------------------------------------------------------------------------------------
        if (!empty($item['uid']) && is_array($item['uid'])) {
            $item['uid'] = $item['uid'][0]; 
        }

        if (!empty($item['uid']) && !array_key_exists($item['uid'], _userreference_potential_references($field, '', $item['uid']))) {
          form_set_error($error_field, t('%name : Invalid user.', array('%name' => t($field['widget']['label']))));
        }

Fix #2 - in userreference_widget function (under case 'process form values')

        // add these 2 lines
        // ----------------
        if (is_array($items[0]['uid']))
            $items[0]['uid'] = $items[0]['uid'][0];

        // Remove the widget's data representation so it isn't saved.
        unset($items['uids']);
        foreach ($items as $delta => $item) {
          $items[$delta]['error_field'] =  $field['field_name'] .'][uids';
        }

scott_earnest’s picture

#27 worked for me - thanks cogapp_alx !

NOTE: my situation applied to nodereference.

Turns out I was only having a problem with Node Reference fields that were a "Select List" widget. Fields that were autocomplete seemed to maintain their values okay. Other field types that were not affected for me were Text and Link.

scott_earnest’s picture

UPDATE: actually not working on #27 - but pretty close. I tested it as user 1 which is why it worked at first. Looks like the user_access() item to call would be "edit" and not "submit". This is around line 89 of cck_field_perms.module:

            else if ($op == 'submit' && $node->nid) {
-             if (!(user_access(_cfp_content_to_readable($type, $disallowed_field, "submit")))) {
+             if (!(user_access(_cfp_content_to_readable($type, $disallowed_field, "edit")))) {
                $savedNode = node_load($node->nid);