Using nodeaccess I have configured access for the node author (of a particular content type) to view and edit their own node. However once a certain condition is meant I need to disable edit access for the node author (of a specific node.)

Any suggestions how to programmatically implement this?

Comments

johnhanley’s picture

I should add that changing the perms via a query in hook_nodeapi is easy. I am specifically asking for info on how best to go about it with nodeaccess enabled.

Anonymous’s picture

You can't do that using the core drupal access functionality, drupal will grant permission as long as there is at least one nodeaccess permission that grants it. To do this you would need to either programatically remove their permission once a condition is met (i.e. delete it from the tables as nodeaccess does) or create another module and do what you need to do there to override it.

johnhanley’s picture

Ok, thanks for the confirmation. I've actually got it working.

Update: Oops, spoke too soon. See below.

johnhanley’s picture

Hmm... The permissions in table nodeaccess aren't being enforced.

UPDATE nodeaccess SET grant_update = 0 WHERE nid = 1 AND gid = 3

Record is correctly updated (grant_update = 0) yet the user is allowed to edit the node.

Does the author have edit access to their own node no matter what?

Anonymous’s picture

Status: Active » Closed (fixed)

If drupal's core permissions allow someone to edit something, then access control modules are not consulted.

magoo’s picture

Issue tags: +access control

My two cents:

Why is it then possible to configure the author permission in the nodeaccess module? If it is not consulted...

btw, the question does not concern this module in particular but it is still unanswered.

There is, however, a hack possible (just though about it and need to test it) :
in a module:

  • define a permission (hook_perm)
  • define an input filter and assign associated permission (i.e. NOT normal users)
  • in a nodeapi hook, change the input of the main field to the value of the previously created filter.

The result is that Drupal will not enable the edition of a node where the filter value has been set to an unauthorized value.

magoo’s picture

I finally got time to do this:

in a module (workflow is the name of my module, change it to suite your needs):

function workflow_install() {
    // parts taken from php code filter module
    $format_exists = db_result(db_query("SELECT COUNT(*) FROM {filter_formats} WHERE name = 'workflow_lock'"));
    if (!$format_exists) {
        db_query("INSERT INTO {filter_formats} (name, roles, cache) VALUES ('workflow lock', '', 1)");
        $format = db_result(db_query("SELECT MAX(format) FROM {filter_formats}"));
    
        $result = db_query("SELECT * from {filters} WHERE format=%d", variable_get('format', 1));
        
        if (db_affected_rows()){
            while ($r = db_fetch_object($result)) {
                db_query("INSERT INTO {filters} (format, module, delta, weight) VALUES (%d, '%s', %d, %d)",
                         $format, $r->module, $r->delta, $r->weight);
            }
        }
        drupal_set_message(t('An input format has been created.'));
        variable_set('workflow_format', $format); // saving id for future uses
    }
}

All this creates an input format of substitution (no role should be allowed to use that format).
I copied the filters associated with the existing format 1 in case it is needed.


function workflow_perm() {
  return array(
    'edit locked content', // roles allowed to edit locked content (published on internet or validation requested)
  );
}

function workflow_nodeapi(&$node, $op) {


  if ($op == 'load') {
        if (CONDITIONS && !user_access('edit locked content')) {
          $node->format = variable_get('workflow_format', 1);
        }
  }
}

Users member of a role having the 'edit locked content' will be able to edit the content.

You must tailor the CONDITION to your needs.

eelkeblok’s picture

I've tried taking this approach, but unfortunately it has one big caveat. I think it might have been because I did a clear cache between implementing the lock and actually viewing the node I had locked again (not on purpose, it just turned out like that), but I ended up with the node showing its raw input, i.e. no input filters had run. This solution relies on the rendered output being available, because if it isn't, and the input filter is changed at node load, rendering the output will not work, for obvious reasons.

Edit: actually, it seems the content is rendered every time. So, for this to work, it seems the input format needs to be identical to the one it is replacing, except for who is allowed to use it.