# Restrict content to the content authors

**URL:** <https://discourse.getcockpit.com/t/restrict-content-to-the-content-authors/285>\
**Category:** Support\
**Created:** [September 19, 2018, 7:57pm UTC](https://discourse.getcockpit.com/t/restrict-content-to-the-content-authors/285 "2018-09-19T19:57:00Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![hellmaca](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.getcockpit.com/hellmaca/32/126_2.png) [@hellmaca](https://discourse.getcockpit.com/u/hellmaca)\
**Post date:** [September 19, 2018, 7:57pm UTC](https://discourse.getcockpit.com/t/restrict-content-to-the-content-authors/285/1 "2018-09-19T19:57:00Z")

</div>

I want my users to be able to view and edit only collection posts they have created. Is this something I would implement in the config file or programmatically? If so, any help would be much appreciated. Also, I will have a hidden boolean field created on each collection post only accessible by admions. Once that field is set to true only admins should be able to see/edit that post. This access to author’s own content will be more restrictive than just user groups.

---

<div class="post-metadata">

**Author:** ![raffaelj](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.getcockpit.com/raffaelj/32/331_2.png) [@raffaelj](https://discourse.getcockpit.com/u/raffaelj)\
**Post date:** [September 19, 2018, 11:19pm UTC](https://discourse.getcockpit.com/t/restrict-content-to-the-content-authors/285/2 "2018-09-19T23:19:28Z")

</div>

Add this code to the read permissions of your collection to restrict entries by owner:

```php
<?php
if ($context->user) {
    $context->options['filter']['_by'] = $context->user['_id'];
}

```

Add this code to the read permissions of your collection to restrict entries by owner, except admins:

```php
<?php
if ($context->user && $context->user['group'] != 'admin') {
    $context->options['filter']['_by'] = $context->user['_id'];
}

```

Filtering + Hiding fields for non-admins can be done this way:

```php
<?php
if ($context->user && $context->user['group'] != 'admin') {
    // filter by admin-boolean
    $context->options['filter']['admin_boolean'] = false;
    // hide field for non-admin --> or use field acl instead
    $context->options['fields']['admin_boolean'] = false;
}

```

~~I tried to test the solution above, but I have some weird bugs with boolean fields right now. I have to check in the next days, if I broke my test cockpit or if it is a real bug…~~

* * *

edit: I tried it again with a fresh installation and it worked.

Instead of adding `$context->options['fields']['admin_boolean'] = false;` to the read permissions, you can add permissions in the context menu of your field to group “admin”. It has the same effect.

For some more permission options, you may have a look at

> <https://github.com/agentejo/cockpit/issues/675>
>
> Hello!
> Cockpit looks like a promising tool for a new project, but I'm having tr…ouble figuring out how to set it up correctly for my use case. Is there any example configuration (\`config.yml\`?) available or is there any place where I can look up all possibilities? I wasn't able to find something appropriate.
> 
> To make it more clear: At the moment I'm mostly interested if it's possible to limit the viewing capabilities of users based on groups. What I basically need is:
> (\* one admin able to see everything/configure the system)
> \* a bunch of editors who should be able to create/edit new items, but should not be able to see the content of other editors
> \* a manager which is able to create/edit/delete all items in the systems, so also all items of every editor.
> 
> Is a configuration like that possible?
> 
> Thanks already for your help!

and

> [@Permission Documentation](https://discourse.getcockpit.com/t/permission-documentation/201):
>
> Hi, I want to use cockpit for a project because I think it’s pretty awesome but I’ve got some questions about the permission section of collections, is there any documentation, because I not sure how to use the „Create“ etc. sections. Any help would be appreciated. Thanks in advance.

---

<div class="post-metadata">

**Author:** ![hellmaca](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.getcockpit.com/hellmaca/32/126_2.png) [@hellmaca](https://discourse.getcockpit.com/u/hellmaca)\
**Post date:** [September 20, 2018, 12:27pm UTC](https://discourse.getcockpit.com/t/restrict-content-to-the-content-authors/285/3 "2018-09-20T12:27:33Z")

</div>

Thank you for your explanation. For some reason, I thought that code had to go into the update permissions as well which ended up disabling the desired functionality. With regards to the boolean field, I have already restricted the viewing and editing of it to admins. The boolean field name is published. Once published is set to true, I would like for all collection posts with a value of published: true to only be edited by admins. Is there a way to implement this functionality? Thank you so much for your help!

---

<div class="post-metadata">

**Author:** ![raffaelj](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.getcockpit.com/raffaelj/32/331_2.png) [@raffaelj](https://discourse.getcockpit.com/u/raffaelj)\
**Post date:** [September 20, 2018, 2:50pm UTC](https://discourse.getcockpit.com/t/restrict-content-to-the-content-authors/285/4 "2018-09-20T14:50:04Z")

</div>

Hmm…, I’m not sure, if this is possible with collections permissions.

You could add this code to `config/bootstrap.php` to interrupt the saving process. But it feels a bit wrong…

```php
<?php

$app->on('collections.save.before.yourcollectionname', function($name, &$entry, $isUpdate) {
    if ($isUpdate && $entry['published'] == true && $this->module('cockpit')->getGroup() != 'admin') {
        die;
    }
});

```

---

<div class="post-metadata">

**Author:** ![hellmaca](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.getcockpit.com/hellmaca/32/126_2.png) [@hellmaca](https://discourse.getcockpit.com/u/hellmaca)\
**Post date:** [September 20, 2018, 5:09pm UTC](https://discourse.getcockpit.com/t/restrict-content-to-the-content-authors/285/5 "2018-09-20T17:09:26Z")

</div>

Thank you for your help. That code did the trick. I like the way you put it that “it feels a bit wrong.” Could the problem be in the way I am imagining how to handle published content? Is there a way to hide content with published:true from all users except admins? I could create a new collection only visible and editable by admins, but unless I am mistaken that would involve an admin manually porting content from one collection to another which doesn’t seem right. I am trying to use published:true as a way to designate which collection posts will generate website content. Once the content has been “approved” by admin to be published to the website, I do not want anyone but an admin to be able to edit it in any way. I am building a Vue app that uses axios to get content from Cockpit with the filter:{published:true}. This code does what I asked, and I really appreciate it. I may just replace the saving failed message with a custom one to alert users as to why they cannot update the specific post. Cheers!

---

<div class="post-metadata">

**Author:** ![raffaelj](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.getcockpit.com/raffaelj/32/331_2.png) [@raffaelj](https://discourse.getcockpit.com/u/raffaelj)\
**Post date:** [September 20, 2018, 9:57pm UTC](https://discourse.getcockpit.com/t/restrict-content-to-the-content-authors/285/6 "2018-09-20T21:57:02Z")

</div>

This was a hard one, but I’m sure, I’ll need it myself in the future.

And I also found another way while fiddling. You don’t need the extra bootstrap.php.

**read permissions:**

```php
<php
if ($context->user && $context->user['group'] != 'admin') {
    
    // filter by content owner
    $context->options['filter']['_by'] = $context->user['_id'];
    
    // return error when trying to edit published entries
    if (isset($context->entry) && (!isset($context->entry['published']) || $context->entry['published']) == true) {
        return cockpit()->stop('{"error": "You can\'t edit published entries."}', 401);
    }
}

```

**delete permissions:**

```php
if ($context->user && $context->user['group'] != 'admin') {
    
    $entries = cockpit()->module('collections')->find($collection['name'], $context->options);
    
    foreach ($entries as $entry) {
        if ($entry['published'] == true) {
            return cockpit()->stop('{"error": "You can\'t delete published entries."}', 401);
        }
    }
    
}

```

Wait with the delete permissions until this PR got merged. Right now, the delete permission has no effect.

> <https://github.com/agentejo/cockpit/pull/864>

**Full example with annotations**

> <https://github.com/raffaelj/cockpit-scripts/blob/master/permissions/restrict-content-to-owner-and-disallow-editing-published-entries.php>

---

<div class="post-metadata">

**Author:** ![artur](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.getcockpit.com/artur/32/4_2.png) [@artur](https://discourse.getcockpit.com/u/artur)\
**Post date:** [September 21, 2018, 7:43am UTC](https://discourse.getcockpit.com/t/restrict-content-to-the-content-authors/285/7 "2018-09-21T07:43:11Z")

</div>

Just a hint:

Instead of

```auto
return cockpit()->stop('{"error": "You can\'t delete published entries."}', 401);

```

you can also do this:

```auto
return 401;

```

---

<div class="post-metadata">

**Author:** ![hellmaca](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.getcockpit.com/hellmaca/32/126_2.png) [@hellmaca](https://discourse.getcockpit.com/u/hellmaca)\
**Post date:** [September 21, 2018, 1:15pm UTC](https://discourse.getcockpit.com/t/restrict-content-to-the-content-authors/285/8 "2018-09-21T13:15:22Z")

</div>

These tips were awesome. Thank you so much for all the help!

---

<div class="post-metadata">

**Author:** ![reddo](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.getcockpit.com/reddo/32/489_2.png) [@reddo](https://discourse.getcockpit.com/u/reddo)\
**Post date:** [February 14, 2020, 8:11am UTC](https://discourse.getcockpit.com/t/restrict-content-to-the-content-authors/285/9 "2020-02-14T08:11:17Z")

</div>

Sorry to revive this old thread, but I would need the code to restrict update permissions. Is it the same as for delete?

---

<div class="post-metadata">

**Author:** ![OGFaisalN](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.getcockpit.com/ogfaisaln/32/1551_2.png) [@OGFaisalN](https://discourse.getcockpit.com/u/OGFaisalN)\
**Post date:** [November 19, 2023, 12:50am UTC](https://discourse.getcockpit.com/t/restrict-content-to-the-content-authors/285/10 "2023-11-19T00:50:43Z")

</div>

@artur is there any equivalent of this for Cockpit v2?

---

<div class="post-metadata">

**Author:** ![OGFaisalN](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.getcockpit.com/ogfaisaln/32/1551_2.png) [@OGFaisalN](https://discourse.getcockpit.com/u/OGFaisalN)\
**Post date:** [November 22, 2023, 8:13pm UTC](https://discourse.getcockpit.com/t/restrict-content-to-the-content-authors/285/11 "2023-11-22T20:13:22Z")

</div>

CC: @raffaelj, I saw that all your snippets are for v1 only and supposedly do not work with v2

---

<div class="post-metadata">

**Author:** ![ronaldaug](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.getcockpit.com/ronaldaug/32/260_2.png) [@ronaldaug](https://discourse.getcockpit.com/u/ronaldaug)\
**Post date:** [February 5, 2024, 4:53am UTC](https://discourse.getcockpit.com/t/restrict-content-to-the-content-authors/285/12 "2024-02-05T04:53:45Z")

</div>

Just sharing what I used to do in Cockpit V2.

- If the request is from `admin`, he/she can perform delete and update.
- If the request is from user, allow to perform `create` but restrict `delete` and `update` (especially protect from overwriting other user’s content)

> Note: this affects all models.

```php

// Before remove 
$this->on('content.remove.before', function ($modelName, &$filter, $collection) {

    $user = $this->helper('auth')->getUser();
    if (!$user) {
        return $this->stop(404);
    }

    $account = $this->dataStorage->findOne('system/users', ['user' => $user['user']]);

    // Protect only when role is user
    if ($user['role'] === 'user') {

        if ($account['_id'] !== $item['_cby']) {
            return $this->stop('{"error": "You can\'t perform this action."}', 401);
        }
    }
});

// Before create or update
$this->on('content.item.save.before', function ($modelName, &$item, $isUpdate, $collection) {

    $user = $this->helper('auth')->getUser();
    if (!$user) {
        return $this->stop(404);
    }

    $account = $this->dataStorage->findOne('system/users', ['user' => $user['user']]);

    // Protect only when role is user and update
    if ($user['role'] === 'user' && $isUpdate === true) {

        if ($account['_id'] !== $item['_mby']) {
            return $this->stop('{"error": "You can\'t perform this action."}', 401);
        }
    }

    // Just make sure when creating a new item, it has _cby and _mby
    $item['_cby'] = $account['_id'];
    $item['_mby'] = $account['_id'];
});

```

Hope this helps someone.
