How can I implement security which allows members to only publish an entry in an assigned category / topic?


  • The site is a business directory.
  • Business listings are published in cities: New York, California.
  • Content managers are assigned to either New York or California.
  • Content managers can only publish in the city they are assigned to.
  • Content managers can only see entries in the city they are assigned to.

I first thought this could be done with a custom field that only shows the cities a content manager is assigned to. That shouldn't be so hard.

However I'd need to also limit the entry indexes in the Control Panel.

Edit: Just found the onBeforeBuildElementsQuery event: https://craftcms.com/docs/plugins/events-reference#elements-onBeforeBuildElementsQuery

    craft()->on('elements.onBeforeBuildElementsQuery', function(Event $event) {
       // $event->params['criteria']['tennant'] = 'new-york';

Any ideas?

2 Answers 2


So you could definitely use the onBeforeBuildElementQuery event to keep them from showing up in the CP (though you'd have to detect if the query is coming from the CP).

I'd also recommend your plugin uses the onBeforeSaveElement event. From there you could check the element's related categories to see if the user has them on their user account, and then allow/deny them to be able to save the element from there. While hiding it from the CP would likely keep them from finding it, putting in more validation will make sure that no one emails an edit link to someone who isn't supposed to be able to edit it.

  • Yeah there would need to be lots of other checks… CP, user group, entry type etc. onBeforeBuildElementsQuery is the hook I'm after. Adding modifyEntrySources would also enhance the interface for those content managers who are assigned to multiple cities. Commented Apr 12, 2016 at 23:04
  • Are you thinking of this for client work or as a workflow plugin? Would love to see some sort of one-size-fits-most of the latter. Commented Apr 12, 2016 at 23:11
  • It's for a couple of clients actually. Multiple publishing groups publishing into topics. One case it's city based, another it's a school group publishing news into each school. In both cases there is some kind of tenancy. Commented Apr 12, 2016 at 23:21

This can be achieved using the onBeforeBuildElementsQuery event:

craft()->on('elements.onBeforeBuildElementsQuery', function(Event $event) {
   // $event->params['criteria']['tennant'] = 'new-york';

With some smarts around group permissions:

public function registerUserPermissions()
    return array(
        'tennants' => array('label' => Craft::t('Tennants'), 'nested' => array(
            'newcastle' =>  array('label' =>  Craft::t('Newcastle')),
            'gosford' =>  array('label' =>  Craft::t('Gosford')),

a custom plugin for this functionality should be possible.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.