Jump to content
Peter Falkenberg Brown

Module to Add UserID to pages and Control Edit Permissions

Recommended Posts

Dear Ryan and All,

I hope I haven't missed a post that answers this. I've viewed a lot of them, but couldn't find this exact function, and wondered how hard it would be for some enterprising module writer to add it. :-) Here's the idea:

- users are given add, edit, and delete permissions for a set of templates

- when they add a page with one of those templates, their user id gets added to the page

- when they go to edit a page, the module checks to see if the 'created_by_user_id' field matches their userid. If so, proceed, if not, they get an error message.

- the same function happens when they try to delete a page (based also on the fact that the page has no children).

- there would be a permission role, used in the module, for assigned user roles to override a page with a different user id, i.e. a superuser or editor who could edit anyone's page.

Thus, this template, if turned on, would add each user's id to any page created by them (as a required, non-editable field), and would thus act as a solid user permission system, which would allow any number of users to log into the admin backend, but only be given permission to edit their own pages.

Somebody want to create it? :-)

Best regards,

Peter

Share this post


Link to post
Share on other sites

PW already adds user id to page. You can get it with created_users_id... or something like this.

Share this post


Link to post
Share on other sites

Dear Soma,

> PW already adds user id to page. You can get it with created_users_id... or something like this.

That's interesting. Thanks. So now... if someone clever would like to add a module that would test for that id, in the admin backend, that would be great.

I know how to block edits, etc, in front end code, but integrating it with the backend admin application is another matter.

Peter

Share this post


Link to post
Share on other sites
<?php

/**
 * Page edit per user created id
 *
 */

class PagesCreatedEdit extends WireData implements Module {

    /**
     * getModuleInfo is a module required by all modules to tell ProcessWire about them
     *
     * @return array
     *
     */
    public static function getModuleInfo() {

        return array(
            'title' => 'Pages created edit',
            'version' => 1,
            'summary' => 'Page edit only for created pages by user',
            'href' => '',
            'singular' => true,
            'autoload' => true,
            );
    }

    public function init() {
        // add edit permission hook for admin pages
        $this->addHookAfter('Page::editable', $this, 'editable');
    }

    public function editable($event){
        $page = $event->object;

        if(!$this->user->hasRole("editor")) return;

        if($event->return) { // only if edit rights are true
            if($page->created_users_id == $this->user->id){
                $event->return = true;
            } else {
                $event->return = false;
            }
        }
    }
}

 

THis will get you there, not many different from frontend coding.

  • Like 4

Share this post


Link to post
Share on other sites

Hi Soma,

Would just like to know what the idea behind this code:

    public function editable($event){
        $page = $event->object;

        if(!$this->user->hasRole("editor")) return;

        if($event->return) { // only if edit rights are true
            if($page->created_users_id == $this->user->id){
                $event->return = true;
            } else {
                $event->return = false;
            }
        }
    }

Why stop if the user doesn't have the "editor" role? Am I correct in thinking that this module targets only *editors* (or other roles specified in the code) and only allows them to edit their own pages?

Share this post


Link to post
Share on other sites

.......Am I correct in thinking that this module targets only *editors* (or other roles specified in the code) and only allows them to edit their own pages?

That's what it says on the tin ;)

- when they add a page with one of those templates, their user id gets added to the page

- when they go to edit a page, the module checks to see if the 'created_by_user_id' field matches their userid. If so, proceed, if not, they get an error message.

Thus, this template, if turned on, would add each user's id to any page created by them (as a required, non-editable field), and would thus act as a solid user permission system, which would allow any number of users to log into the admin backend, but only be given permission to edit their own pages.

Share this post


Link to post
Share on other sites

That's what it says on the tin  ;)

I'm not so sure  ;)

I just tested out the module to confirm what I thought. Here's what the module does.

1. It only does it's thing if the user has the role *editor*.

2. It allows users with the role *editor* to edit only their own pages - pages that they created.

3. To reiterate #1, module doesn't do anything if the user doesn't have the editor role.

Now, before I continue I'd just like to say that I've already found a use for this module - restricting certain users to edit only their own pages. and it kind of solves part of a problem I had with my PageEditPerRole module.. So, thanks Soma  :)

Continuing, I believe what Peter was asking for was:

1. Users can only edit their own pages. (pages they created)

2. If the user has an *editor* role, then they can edit other people's pages.

I think #1 can be improved to say that "users with role *author* can edit only their own pages". Then, there would be another role check for the *editor* role (or something similar) who can edit everything.

As below:

<?php

/**
 * Page edit per user created id
 *
 */

class PagesCreatedEdit extends WireData implements Module {

    /**
     * getModuleInfo is a module required by all modules to tell ProcessWire about them
     *
     * @return array
     *
     */
    public static function getModuleInfo() {

        return array(
            'title' => 'Pages created edit',
            'version' => 1,
            'summary' => 'Page edit only for created pages by user',
            'href' => '',
            'singular' => true,
            'autoload' => true,
            );
    }

    public function init() {
        // add edit permission hook for admin pages
        $this->addHookAfter('Page::editable', $this, 'editable');
    }

    public function editable($event){
        $page = $event->object;

        //I don't think we should stop users if they already have permission to edit
        //Permissions should be additive IMHO - other modules could grant edit permission.
        if($event->return) return;

        //I'm not too good with this kind of conditionals. basically, stop if user doesn't have either of these roles
        //The idea is, the presence of these roles trigger when this module *runs* - does it's permission check 
        //(obviously the module is already running)
        if(!$this->user->hasRole("author") && !$this->user->hasRole('editor')) return;

        /** TODO: author and editor roles may be another name or could be multiple roles **/

        //get highest "role type"
        $roles = $this->user->roles;
        $is_editor = false; //probably don't need this
        foreach($roles as $r){
            if($r->name == 'editor'){
                $is_editor = true;
                $role = $r;
                break;
            } elseif( $r->name == 'author' ){
                $is_editor = false;
                $role = $r;
            }
        }

        //make sure role has page-edit permission. I know user may have page-edit permission from another role.
        //but let's not consider that for now.
        if(!$role->hasPermission('page-edit')) return;

        if($is_editor){
            $event->return = true;
        }elseif( $page->created_users_id == $this->user->id ){
            $event->return = true;
        }

        /**
         * Caveats: (for now)
         *
         * If user has both author and editor roles, then this module will use the editor role for permission check.
         * This means if editor role doesn't have page-edit permission, user won't get permission even if author 
         * has page-edit permission.
         */
        
        
        /*
        if($event->return) { // only if edit rights are true
            if($page->created_users_id == $this->user->id){
                $event->return = true;
            } else {
                //don't think we need to set to false
                //$event->return = false;
            }
        }
        //*/
    }
}
 

  • Like 2

Share this post


Link to post
Share on other sites

Dear Soma and PogiDude,

Thanks to both of you! Yes, PogiDude, you are right. Superusers and editors should be able to edit anything, but 'authors' should only be allowed to edit their own pages. I probably wasn't clear enough.

Soma, Oh Great Module Writer, :-), you wanna turn this into a real live module that we can just go click, click and install?

I think that this would be such a beneficial module that I'll bet you a Virtual Doughnut that Ryan would include it in the core.

It seems to be me to be a missing element in PW's user scheme.

Best regards,

Peter

Share this post


Link to post
Share on other sites
<?php

/**
 * Page edit per user created id
 *
 */

class PagesCreatedEdit extends WireData implements Module {

    /**
     * getModuleInfo is a module required by all modules to tell ProcessWire about them
     *
     * @return array
     *
     */
    public static function getModuleInfo() {

        return array(
            'title' => 'Pages created edit',
            'version' => 1,
            'summary' => 'Page edit only for created pages by user',
            'href' => '',
            'singular' => true,
            'autoload' => true,
            );
    }

    public function init() {
        // add edit permission hook for admin pages
        $this->addHookAfter('Page::editable', $this, 'editable');
    }

    public function editable($event){
        $page = $event->object;

        if(!$this->user->hasRole("editor")) return;

        if($event->return) { // only if edit rights are true
            if($page->created_users_id == $this->user->id){
                $event->return = true;
            } else {
                $event->return = false;
            }
        }
    }
}

 

THis will get you there, not many different from frontend coding.

Soma, this code is perfect for my use with a site using Kongondo's Blog module, except for one thing: It conflicts with the permissions I set up to allow the user to add children to a page via fields in their blog posts. They do not get the option add new children to Page-based fields.

I tried to add an || logical operator to the last portion of your code above but wasn't able to come up with anything that successfully adds exceptions to the user ID comparison. Would really appreciate some input as to how you'd implement that, or if you think it would be preferable to start with PageEditPerUser and strip edit permissions rather than try to build them here. PageEditPerUser works, again, near perfectly for me, except that it lets users edit all other users' content.

Thanks!

Share this post


Link to post
Share on other sites

The function that gets hooked by the module (Page::editable) does exactly what it sounds like. Return if a page is editable by the current user. Page::addable is the function to control the ability to add children. Essentially you'll need another function addable(), which does the same check for users as editable, and in init() a second hook to Page::addable which points to your new function.

  • Like 1

Share this post


Link to post
Share on other sites

The function that gets hooked by the module (Page::editable) does exactly what it sounds like. Return if a page is editable by the current user. Page::addable is the function to control the ability to add children. Essentially you'll need another function addable(), which does the same check for users as editable, and in init() a second hook to Page::addable which points to your new function.

Thanks for the reply! Sorry I didn't see it earlier, I forgot to subscribe to this thread.

The modification ended up being even simpler than I imagined at the time (so I'm very glad I stepped back from it for almost a week...)

I modified the if($event->return) line to read:

if($event->return && $event->object->template == 'blog-post')

..in order to limit the module's influence to just one template. This seems to have done the trick, and now my users can create pages with the tag and category templates. Do let me know if you disapprove of this method for any reason, but it's doing exactly what I need (pending sending my monkeys in to try and break it).

Share this post


Link to post
Share on other sites
<?php

/**
 * Page edit per user created id
 *
 */

class PagesCreatedEdit extends WireData implements Module {

    /**
     * getModuleInfo is a module required by all modules to tell ProcessWire about them
     *
     * @return array
     *
     */
    public static function getModuleInfo() {

        return array(
            'title' => 'Pages created edit',
            'version' => 1,
            'summary' => 'Page edit only for created pages by user',
            'href' => '',
            'singular' => true,
            'autoload' => true,
            );
    }

    public function init() {
        // add edit permission hook for admin pages
        $this->addHookAfter('Page::editable', $this, 'editable');
    }

    public function editable($event){
        $page = $event->object;

        if(!$this->user->hasRole("editor")) return;

        if($event->return) { // only if edit rights are true
            if($page->created_users_id == $this->user->id){
                $event->return = true;
            } else {
                $event->return = false;
            }
        }
    }
}

THis will get you there, not many different from frontend coding.

this is a great module snippet - basically allows you to control edit access on a page using any php/api; +1 vote for this to be on Processwire recipes, if it isn't already

  • Like 1

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...