Jump to content

Recommended Posts

This is a description of a 'members' setup, where a 'member' is a processwire user who is able to manage their own branch of the page tree. Based on a simple site that looks a bit like this.

  • Home
    • Members
      • Member A
        • Page A1
        • Page A2
      • Member B
      • Member C
        • Page C1
    • Etc.
  • Section X
    • Page X1
    • Page X2
  • Section Y
    • Page Y1

Members A, B and C can add, edit, sort and delete children of their page Member A/B/C. They may also edit their page Member A/B/C. Without any additional roles they have just ‘view pages’ access elsewhere.

Take Section X above as an example, and two roles ‘editor’ and ‘sub-editor’ where the role ‘editor’ can add/edit/delete pages beneath Section X; and the role ‘sub-editor’ can edit pages beneath Section X. Assigning either of these roles to a user who also has the ‘member’ role does not interfere with either scheme.

Setup
Before adding users I do the following:

  • Enable the permission ‘page-edit-created’
  • Create a role ‘member’ and grant it ‘page-edit’, ‘page-delete’, ‘page-edit-created’, and ‘page-sort’ permissions
  • Create a template ‘member’ and enable access controls granting role ‘member’ ‘edit pages’ and ‘add children’ in addition to the default ‘view pages’
    • Use the ‘Revoke permissions by role’ function to remove ‘page-delete’ for the role ‘member’
    • Enable the advanced option ‘Allow the ‘created user’ to be changed on pages’
  • Create a template ‘members’ and under family settings allow children (specify the ‘member’ template as the allowed template for children/‘members’ template as the allowed parent for template ‘member’); optionally allow only one page using the template ‘members’
  • Create (or reuse) templates for the children of template ‘member’; specify these as the allowed templates for children of template ‘member’; grant ‘edit pages’ and ‘create pages’ to the role ‘member’ on these templates.
  • Insert the following between lines 638 and 640 in file wire/modules/PagePermissions.module
} else if($page->template->name == 'member') {    if($user->id == $page->created_users_id) {    $addable = true;    }

Add/Edit a user (e.g. ‘Member A’) and assign role ‘member’

  • Create a page (e.g. ‘Members’) in the tree with template ‘members’
  • Add a child page (e.g. ‘Member A’) to the page ‘Members’
  • On the page ‘Member A’ under Settings, change the ‘Created by User’ to the user ‘Member A’
  • Repeat for all users assigned the role ‘member’.

Er, that’s it.

It seems obvious to me that this could be made into a module. I haven't the experience, skills, knowledge required to complete that quickly, but the above works nicely in the way I want it to and this may be of benefit to others here.

There may be unintended behaviour that I haven’t located yet. For example (though this is possibly not related to this setup) I’ve seen that when a textarea field has CKeditor as the inputype the ‘member’ users are able to insert images from any page, which is not the desired behaviour. I’ve seen some forum posts that address this, or similar such that I’m confident that this could be overcome.

If it were a module, I think this defines what the module does.

On install/configure

  • Ask for a plural and singular version of your membership.
  • Check for and enable if necessary the permission ‘page-edit-created’
  • Check for and create a role ‘singluar’ and enable permissions ‘page-edit’, ‘page-delete’, ‘page-edit-created’, and ‘page-sort’
  • Check for and create a template ‘plural’
  • Check for and create a template ‘singular’ and assign ‘edit-pages’ and ‘add pages’ to role ‘singular’
    • ‘singular’ template, Allow the ‘created user’ to be changed for pages using this template.
  • Modify the Family rules for the two templates:
    • ‘plural’: Can this template be used for new pages?: One (no more allowed)
    • ‘plural’: Allowed template(s) for children: ‘singular’
    • ‘singular’: Allowed template(s) for parents: ‘plural’
  • Modify the file wire/modules/PagePermissions.module as per the above

In action
When a user is assigned the role ‘singular’, (e.g. user ‘Nic’) the following actions are executed.

  • Check for and add a page ‘Nic’ with template ‘singular’ under parent ‘plural’
  • Change the created user ID for page ‘Nic’ to that of user ‘Nic’.

Other ideas
Ask at install time where the root page ‘plural’ should be created and create it.
What to do when removing the module.
Tackle the CKeditor insert image issue
EDIT/ADDITION:
Either a change to the user template to include a "Full Name" for creating member pages (title field); or less intrusively, add a "Full Name" field to the "member" template and allow the member to enter their own.

  • Like 3
Link to post
Share on other sites

I think that module may be too broad for my needs. What I've described above is, apart from the edit to wire/modules/PagePermissions.module, mainly automation. Prior to the introduction of the page-edit-created permission I would have required a template per user to achieve the same thing (as my vapourware above).

With this design the requirement is cleaner, thanks to the page-edit-created permission. Once the structure has been set up a user manager only need assign the 'member' role to a user and the job is done. It appeals to me because I don't have to consider anything other than whether a user is a 'member'; any access permissions assigned to other roles, to other templates won't interfere; and a user having the role 'member' will not interfere with permissions granted to them by any of their other roles.

One other thing; the design is based on the idea that a user owns an object, not that a group owns an object, which is a distinction worth mentioning I think.

Link to post
Share on other sites

I think that module may be too broad for my needs. 

I think I must be missing something - have you tried the AdminRestrictBranch module? Can you please highlight exactly what it doesn't support for your needs - perhaps they might be a worthwhile addition, or perhaps not :)

Link to post
Share on other sites

I have tried the AdminRestrictBranch module. I used the following options:

  • How to match user to branch: Specified Branch Parent
  • Branch edit exclusions: I selected (using the example above) Section X

Next I created a branch parent for each user, 'Member A', Member B', 'Member C', etc using an appropriate template.

Then I visited a user's profile and selected the appropriate branch, i.e. User:'Member A' - Branch:'Member A'; and repeated that for all users I wished to have manage their own branch.

Are those the settings/actions you would expect in order to replicate what I've described?

Link to post
Share on other sites
Are those the settings/actions you would expect in order to replicate what I've described?

I guess my question for you, is does it work as you want?

Seriously though, I think it should, but if the editors need to directly edit pages under Section X then you would need to use the "Editing Only" option, so that the page tree view is not actually restricted.

With that setting, I think it should work as you described - how did it work out? Was there anything that didn't work as you need?

Link to post
Share on other sites

I guess my question for you, is does it work as you want?

No, I have to repeat the same action x times (where x is the number of users I wish to have manage their own branches) in order to achieve what I want.

Seriously though, I think it should, but if the editors need to directly edit pages under Section X then you would need to use the "Editing Only" option, so that the page tree view is not actually restricted.

I have to repeat the same action on each user I wish to have manage their own branch.

With that setting, I think it should work as you described - how did it work out?

It replicated what I have been doing manually as descibed in my original post, and doesn't remove the requirement to make manual repetitive changes. If I use this module I must still repeat steps I would like to automate, as descibed in my original post.

Was there anything that didn't work as you need?

Yes, the scheme defined in my original post described a system in which the superuser assigns a role to a user and the required page/branch (and it's associated permissions) is created. The AdminRestrictBranch does not do what I described in my original post.

Link to post
Share on other sites

I have to repeat the same action on each user I wish to have manage their own branch.[/background]

Could you put the X, Y, etc branches under an extra parent and just add that to the branch edit exclusions - that will take care of making all new ones excluded.

Yes, the scheme defined in my original post described a system in which the superuser assigns a role to a user and the required page/branch (and it's associated permissions) is created. The AdminRestrictBranch does not do what I described in my original post.

I would suggest that AdminRestrictBranch might still be useful for you - you just need to add an additional hook somewhere that will automatically create the required branch when the user is created - this should be very easy - let us know if you need help.

You might also consider connection the user to the parent branch by one of the other options - role name or PHP custom code - this might be able to automate this process for you.

Good luck with whatever approach you choose!

Link to post
Share on other sites

Can a module accomplish the changes and actions I've described?

You wouldn't need another full module, you could just use AdminRrestrictBranch and add an additional hook that is triggered when a new user is added which takes care of creating the member pages. But, what I would do is use the "Multiple templates or parents for users" ability instead: https://processwire.com/blog/posts/processwire-core-updates-2.5.14/#multiple-templates-or-parents-for-users

That way the member page is the user page, so one less thing to create and maintain.

Sorry my answers aren't complete with examples today - lots to do and not much time :)

Link to post
Share on other sites

Sorry my answers aren't complete with examples today - lots to do and not much time  :)

That is quite alright, I'm not seeking examples.

But, what I would do is use the "Multiple templates or parents for users" ability instead: https://processwire....rents-for-users

 

That way the member page is the user page, so one less thing to create and maintain.

On the surface that seems useful, but additional work is needed in order for it to help with the above. For example, without further modification it isn't possible to change the "Created by user" setting, on a page created using that scheme, to a user created under an alternate branch because the alternate branch is not offered for selection.

So, on the other hand:

Can a module accomplish the changes and actions I've described?

Link to post
Share on other sites
For example, without further modification it isn't possible to change the "Created by user" setting, on a page created using that scheme, to a user created under an alternate branch because the alternate branch is not offered for selection.

What about this setting in Advanced Mode: 

post-985-0-10403700-1449736457_thumb.png

Can a module accomplish the changes and actions I've described?

Modules can accomplish almost anything - if you are willing to make a start, I am sure you will get plenty of help if you need it. There might be something useful in this thread: https://processwire.com/talk/topic/3543-register-users-and-add-page-same-as-username/

You might also like to look at the way the EmailNewUser module triggers an email when a new user is created - you might be able to use that as a starting point for modifying to create the member page instead.

Link to post
Share on other sites

Modules can accomplish almost anything - if you are willing to make a start, I am sure you will get plenty of help if you need it. There might be something useful in this thread: https://processwire....me-as-username/

You might also like to look at the way the EmailNewUser module triggers an email when a new user is created - you might be able to use that as a starting point for modifying to create the member page instead.

Thank you, yes. I'd seen the former, not the latter.

What about this setting in Advanced Mode:

because the alternate branch is not offered for selection.

post-2173-0-74378400-1449739191_thumb.jp
Link to post
Share on other sites

This sounds like a bug / oversight - perhaps you should file a Github issue about this.

Further issues with this include and may not be limited to:

Template access settings are not honoured. These are the settings applied to the alternate user template 'member' for user 'selfedit1' with role 'member'.

post-2173-0-21212100-1449741175_thumb.jp

This is what the user 'selfedit1' is offered in the page tree.

post-2173-0-00040100-1449741517_thumb.jp

i.e. no opportunity to edit the page, or add a child

I'm just saying. :-) I don't think I did, but maybe I set it up wrong.

I appreciate the time you've taken considering all of the above, thank you for that. While it might take me months to create a module that can do what I've described above, I'm perfectly happy with that temporary limitation and as described I can manually achieve what I want.

The site that uses this scheme does not have so many 'members' that building it manually is an onerous task; I can perform the actions I need to in about an hour probably and, in the mean time, hobble on trying to build a module that could do it for me.

I don't think there is anything 'wrong' with what I've described, at least no one has pointed out any failure in the design.

Cheers, Nic

Link to post
Share on other sites

Note.

I think inserting images from within CKEditor is being managed by ProcessPageImageSelect.module, which is using ProcessPageList.module to build a list of pages to select an image from, which I think is using haspermission("view") to construct a tree.

Something like this: https://processwire.com/talk/topic/6315-processpagelist-to-hide-some-pages/?hl=processpagelist

Link to post
Share on other sites
  • 3 months later...

An additional specification.

  • Member
    • Galleries (an index page)
      • Gallery A
      • Gallery B
    • Journals (an index page)
      • Journal 1
      • Journal 2

Allow, for each member page, one and only one page of template 'gallery-index' and one and only one page of template 'journal-index'.

For the Member page, if there exists a child page of template 'gallery-index' and a child page of template 'journal-index' then do not offer 'new' in the page tree options for page Member.

Otherwise offer the 'new' option and when the Member has advanced to /page/add/ if there exists a child page of template gallery-index, offer journal-index; and if there exists a child page of template journal-index, offer gallery-index.

An extension of the Family > Can this template be used for new pages?

Yes/No/One (no more allowed)/One per parent (no more allowed)

Link to post
Share on other sites
  • 4 months later...

Surprising myself, I have figured out how to hook into Page::addable.

class MemberBranchAddable extends WireData implements Module {

  public static function getModuleInfo() {
    return array(
      'title' => 'Member Branch Addable', 
      'version' => 3, 
      'summary' => 'Grant addable access to users on their member page',
      'singular' => true, 
      'autoload' => true, 
    );
  }

	/**
	 * Attach hook to Page::addable
	 *
	 */
	public function init() {
		$this->addHookAfter("Page::addable", $this, 'addable');
	}

	/**
	 * Page::addable hook
	 *
	 * Add children permission is granted based on edit.
	 * If they have edit access, then they can also add children,
	 * but only apply this if the $page->template = 'member'
	 *
	 */
  public function addable(HookEvent $event) {
    $page = $event->object;
    // If page template is $singular continue
	// That $singular should come from the
	// configuration
    if ($page->template->name == 'member') {
      // If page is editable and generally can have children, then allow addable
      if ($page->editable() && !$page->template->noChildren) {
        $event->return = true;
      } else {
        $event->return = false; 
      }
    }
  }

Which takes care of:

Quote

Members A, B and C can add, edit, sort and delete children of their page Member A/B/C. They may also edit their page Member A/B/C. Without any additional roles they have just ‘view pages’ access elsewhere.

And removes the requirement to manually edit wire/modules/PagePermissions.module

Edited by sgt.blikey
Amended code to account for configurability $singular/'member'
  • Like 3
Link to post
Share on other sites

I would like to check for and enable the predefined system permission 'page-edit-created'.

I am currently working in a 3.0.27 installation.

When the permission is enabled in the admin, it has a title, 'Edit only pages user has created'.

I am using the following code (in the context of a module):

if(!wire('permissions')->has('page-edit-created')) {
  wire('permissions')->add('page-edit-created');
}

This creates the permission, but leaves the title blank. Deleting this api created version via the admin restores the title, that is it seems to restore the default version of the permission.

Is there an alternative to add, e.g. enable, that enables the permission as defined by the system?

Am I checking for its presence correctly?

Thanks!

Link to post
Share on other sites

Yes, you are checking for its presence correctly. I think you will just need to manually add the title as well.

Take a look at the function that installs those optional permissions via the admin interface:
https://github.com/ryancramerdesign/ProcessWire/blob/master/wire/modules/Process/ProcessPermission/ProcessPermission.module#L108

Notice where it adds the title:
https://github.com/ryancramerdesign/ProcessWire/blob/master/wire/modules/Process/ProcessPermission/ProcessPermission.module#L133

$permission->title->setLanguageValue($language, $a[$name]);

but of course you don't need to worry about the language.

  • Like 1
Link to post
Share on other sites

@adrian thanks.

I wonder where the names/titles are coming from when populating the form/table in the function beginning here. https://github.com/ryancramerdesign/ProcessWire/blob/master/wire/modules/Process/ProcessPermission/ProcessPermission.module#L37

protected function getOptionalPermissionsForm()

Does this line suggest they exist as pages? https://github.com/ryancramerdesign/ProcessWire/blob/master/wire/modules/Process/ProcessPermission/ProcessPermission.module#L51

$optionalPermissions = $this->wire('permissions')->getOptionalPermissions();

 

Link to post
Share on other sites

Oh, they're in there are they? :-) Okay so I should have:

$ grep -R page-edit-created *

Thanks for pointing me in the right direction.

For pedantry's sake I've gone with:

if(!wire('permissions')->has('page-edit-created')) {
    $permission = wire('permissions')->add('page-edit-created');
    $permission->title = 'Edit only pages user has created';
    $permission->save();
}

 

  • Like 1
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...