Field-level Page editing permissions

Silverstripe Version: 3.2

Question:

I’ve been asked to implement field-level permissions in a Page model.

For example, let’s pretend I have an ArticlePage.php model. It has the usual fields like $MenuTitle and $Content, and I’ve other properties like $Subtitle and $Author.

I can protect the whole model by using providePermissions() and the associated canEdit() methods, but I need to protect individual fields / page properties.

What I need to do is:

  • Admins should be able to edit all fields
  • Users in another permissions group should only be able to edit and save $Subtitle

Is this possible in SilverStripe 3.2? Is there a SilverStripe way of doing it?

If not, is there a way I can Identify the user group of the current user and then perhaps conditionally show the $field->addFieldToTab() code? Is it possible to stop the user saving a field by posting the data maliciously, perhaps by adding the missing fields via inspector?

Any advice gratefully received!

There’s no out-of-the-box way as far as I know.

Yes… you should be able to use the Member::inGroup() method to test whether a user is in the relevant group and conditionally use addFieldToTab()

You could do something similar to the above in an onBeforeWrite() if you’re worried about it, and conditionally remove the unwanted data. You could possibly do something in a custom validator too if you wanted. That said, if you’re at the stage where you have CMS users deliberately rewriting the DOM to send data into the system, I’d have to question whether you want those users to have CMS access at all!

https://api.silverstripe.org/3/Member.html#method_inGroup

I think that if you’ve removed or made some fields read only for a given user, they shouldn’t be able to edit those fields through a CMS form post, even if they’ve manipulated the post data, as the values should be validated against the modified form object before saving.

You could do something like

if (<some permission check fails>) {
    $fields->dataFieldByName('MyField')->performReadOnlyTransformation();
}