Having field-level permissions is important to replace functionality provided by the profile.module using the Fields API (see #394720: Migrate profile module data to field API).

One of the problems with field permissions is that they quickly become unmanageable when more than a few fields exist. Being able to optionally expose individual fields to the permission system would be a good alternative.

Comments

moshe weitzman’s picture

I'm willing to do a straight port of CCK's content permissions module. Do folks think thats sufficient? flobruit's suggestion to selectively enable access control for a field is reasonable but then we hit a problem - there is no UI in core for fields.

yched’s picture

Also, a UI for "selectively enable access control for a field" would possibly mean that the field_perms.module needs to add a new field setting, 'access_enable' to all field types, and a corresponding checkbox on the UI. Field API curently doesn't allow that.
This is in fact another D7 use case for the CCK D6 #417122: Allow drupal_alter() on Field and Widget Settings...

yched’s picture

#502522: Allow drupal_alter() on the various Field API declarative hooks should allow "selectively enable access control for a field".
A patch for CCK HEAD will follow for the 'field settings forms" part.

Moshe, if you're willing to port content_permissions, it would be a cool opportunity to check we're doing this right :-)

tstoeckler’s picture

I think the current, potentially overwhelming state of the permissions page should not lead to special-casing certain fields as being "permissionable". There are sites that have 20+ content types, each with their own "create", "edit", "edit own", "read", and "delete" permissions, so it is already an issue that is not necessarily connected to field API. I would find it strongly inconsistent to handle permissions differently between content types and fields.

rickvug’s picture

@tstoeckler You bring up a good point about content type permissions making the permissions page overwhelming. What if permission were broken up into 3 tabs to control the chaos? The three tabs would be Module Permissions, Content Type Permissions and Field Permissions. I could see major contrib modules (Views & OG perhaps) also following the tabs pattern, making permission settings easier to find through consolidation.

tstoeckler’s picture

#5 is something for a different issue.

... which should definitely be opened by someone! The current permissions UI can be quite horrific in certain scenarios.

I just looked at the D6 content permissions module. It provides "edit" and "view" permissions. I think that's fine for a first patch, but I do think we should sync those permissions with content type permissions in a second step.

rickvug’s picture

@tstoeckler I completely agree that tabs for the permission screen is another issue that shouldn't be intertwined here. I'll look to file soon.

EvanDonovan’s picture

Title: field permissions in core » Field Permissions in Core

Is anyone still working on this for core? If not, is this something that the Field API could support in contrib? It is absolutely critical for my site, and I believe, for a lot of sites that use CCK.

If this goes into core, I would suggest that it is improved by making the content permissions "opt-in" so they don't apply to every field by default. The best way, imo, to do this would be if every time a field is created there would a screen that would ask whether to activate content permissions on the field. (That is, if content permissions were globally active.)

floretan’s picture

Now that we opted on a different mechanism to choose what fields could get displayed on the registration form, I don't think that field permissions need to be in core. There's of course no reason that this can't be part of the CCK in contrib.

webchick’s picture

Version: 7.x-dev » 8.x-dev

Agreed. Moving to 8.x for possible inclusion there, but contrib is fine for 7.x.

webchick’s picture

Category: task » feature
bjaspan’s picture

Why is this not a wontfix? Most sites do not need field permissions; why should it be in core?

EvanDonovan’s picture

@bjaspan: It doesn't have to be in core necessarily. For my site, it would be fine if it were in contrib. There just has to be the possibility of doing it. As long as Field API has the potential to support it, that's cool.

Field Permissions was part of the package when CCK was in contrib, so I thought it might be moved into core though, since the rest of CCK was.

markus_petrux’s picture

One thing that is missing in field_access() is something I added recently to CCK for D6. We have the $node as a new argument that is also passed to hook_field_access(). This allows other modules check permissions based not only on user roles, but also in context. The counterpart for D7 would be $obj_type and $object (or $entity) I guess. For this I have opened a separate task: #597832: Add $obj_type, $object arguments to field_access() to enhance the context for hook_field_access().

Once this is done, I was planning to upgrade the Content Permissions module in D6 with 'view own', 'edit own' (something that needs to know the uid in the $node), and also use hook_field_settings_alter() to add a radios element to the field settings form that allows sites to selectively enable field permissions per field. That way you do not need to care about fields that can perfectly inherit permissions from the node they are.

The main code of this Content Permissions module I would like to push for D6 follows. I guess it could be used too for D7. We need a hook_update_N() to enable field permissions for all fields for those that have this module already enabled. They could then disable permissions per field where they need to. This upgrade is necessary for compatibility with current implementation of Content Permissions module.

/**
 * Implementation of hook_field_settings_alter().
 */
function content_permissions_field_settings_alter(&$settings, $op, $field) {
  switch ($op) {
    case 'form':
      $settings['field_permissions'] = array(
        '#title' => t('Field permissions'),
        '#type' => 'radios',
        '#options' => array(
          '' => t('Disabled'),
          'any' => t('Enable view and edit permissions for this field in any node.'),
          'own' => t('Enable view and edit permissions for this field in any node and nodes owned by the current user.'),
        ),
        '#default_value' => (!empty($field['field_permissions']) ? $field['field_permissions'] : ''),
        '#description' => t('Use this option to enable role based permissions for this field.
When permissions are enabled, access to this field is denied by default. You should assign permissions to the proper user roles from the <a href="!admin-permissions">permissions administration</a> page.
On the other hand, when this option is disabled, field permissions are inherited from node view and/or edit permissions. ie. users allowed to view a node will also be able to view all fields where this option is not enabled.', array(
          '!admin-permissions' => url('admin/user/permissions'),
        )),
        '#weight' => -1,
      );
      break;

    case 'save':
      $settings[] = 'field_permissions';
      break;
  }
}

/**
 *  Implementation of hook_perm().
 */
function content_permissions_perm() {
  $perms = array();
  foreach (content_fields() as $field) {
    if (!empty($field['field_permissions'])) {

      // Build list of permission types enabled for this field.
      $permission_types = array('view', 'edit');
      if ($field['field_permissions'] == 'own') {
        $permission_types = array_merge($permission_types, array('view own', 'edit own'));
      }

      // Generate the permissions for this field.
      foreach ($permission_types as $permission_type) {
        $perms[] = $permission_type .' '. $field['field_name'];
      }
    }
  }
  return $perms;
}

/**
 * Implementation of hook_field_access().
 *
 * @see content_access().
 */
function content_permissions_field_access($op, $field, $account, $node = NULL) {
  // Check access only if permissions has been enabled for this field.
  if (!empty($field['field_permissions']) && ($op == 'view' || $op == 'edit')) {
    // Check if user has access to view/edit this field in any node.
    if (user_access($op .' '. $field['field_name'], $account)) {
      return TRUE;
    }

    // Check if user has access to view/edit this field in own nodes,
    // but only if 'own' permissions have been enabled for this field.
    if ($field['field_permissions'] == 'own' && user_access($op .' own '. $field['field_name'], $account)) {

      // When content_access('view') is invoked, it may or may not provide a
      // node object. It will almost always, except when this function is
      // invoked as as a field access callback from Views, where it is used to
      // evaluate if the field can be included in the query itself. In this
      // case we should grant access. Views will invoke content_access('view')
      // again, indirectly, when rendering the fields using content_format(),
      // and this time it will provide a pseudo node object that includes the
      // uid of the node creator, so here is where we have the chance to
      // evaluate node ownership to check for 'view own <field>' permission.
      if ($op == 'view') {
        return (!isset($node) || $node->uid == $account->uid);
      }

      // When content_access('edit') is invoked, it always provides a node,
      // so we can always check the ownership of the node.
      if ($op == 'edit') {
        return (isset($node) && $node->uid == $account->uid);
      }
    }
    return FALSE;
  }
  return TRUE;
}
markus_petrux’s picture

In case people is so busy with other things now, one question: this feature in contrib for D7 means in CCK? ...I'm asking this because if yes, I could do this now in CCK for D6. Otherwise, I would use a separate project.

moshe weitzman’s picture

I think it will be clearer if we abandon the cck project for d7 and use separate projects. I propose a separate field permissions project for this ... your plan about settings_alter sounds great to me.

markus_petrux’s picture

Ok, here's the project page:

http://drupal.org/project/field_permissions

I'll commit code asap. And I'll also provide a version for D7 as well, as soon as the other issue about field_access() contexts is in: #597832: Add $obj_type, $object arguments to field_access() to enhance the context for hook_field_access().

EvanDonovan’s picture

Thanks for working on this! Sounds good...

markus_petrux’s picture

I have already started the port to D7: #598924: Port of Field Permissions to D7.

markus_petrux’s picture

I need advice to properly implement Field Permissions for D7. Here, I need to extend attributes for all fields with the permissions option (permissions disabled? enable view/edit permissions?, etc.). However, I'm not sure which is the best practice in D7 to do it. Do I need to implement hook_field_info_alter() + hook_form_alter() ? Is there any module out there that extends field attributes I can look at as an example? Knowing which hooks I need to implement would be enough to go, though.

yched’s picture

hook_field_info_alter() + hook_form_alter() sounds like the way to go.

markus_petrux’s picture

@yched: Thanks! :)

I think I already got a working version of Field Permissions for D7. It should be available from next nightly snapshot (or checking out from CVS). Those interested on this feature, please monitor this issue: #598924: Port of Field Permissions to D7.

Only node related fields seem to work in core, though. I'll revisit core in the future to see if the port can be finished with similar features as in the D6 version.

RobLoach’s picture

Hitting the fake subscribe button.

klonos’s picture

...me too ;)

geerlingguy’s picture

Subscribe.

michaelfavia’s picture

Subscribe as well.

grota’s picture

Subscribe.

swentel’s picture

Status: Active » Closed (duplicate)

There's another issue re: field permission that's older, see #366416: Field Permissions UI