Jump to content
adrian

Page Protector

Recommended Posts

This module allows you and your site editors to protect a page (and optionally its children, grandchildren etc) from guest access directly from the page's Settings tab. You can also limit access to certain roles.

http://modules.processwire.com/modules/page-protector/

https://github.com/adrianbj/PageProtector

It makes it very easy for editors to set up various password protected areas on their site, or to simply protect a new page or section while they are still working on it.

  • Ability for your site editors to control the user access to pages directly from Settings tab of each page
  • Include whether to protect all children of this page or not
  • Optionally allow access to only specified roles
  • Option to protect all hidden pages (and optionally their children)
  • Ability to change the message on the login page to make it specific to this page
  • Option to have login form and prohibited message injected into a custom template
  • Access to the "Protect this Page" settings panel is controlled by the "page-edit-protected" permission
  • Table in the module config settings that lists the details all of the protected pages
  • Shortcut to protect entire site with one click

In addition to the admin interface, you can also set protection settings via the API:

// all optional, except "page_protected", which must be set to true/false
// if setting it to false, the other options are not relevant

$options = array(
    "page_protected" => true,
    "children_protected" => true,
    "allowed_roles" => array("role1", "role2"),
    "message_override" => "My custom login message",
    "prohibited_message" => "My custom prohibited access message"
);

$page->protect($options);

As alway, I would love any feedback / suggestions for improvements. Hope you find it useful!

Page Protection Settings (settings tab for each page)

post-985-0-73987600-1416875487_thumb.png

Module Config Settings

post-985-0-27882500-1416875500_thumb.png

  • Like 25

Share this post


Link to post
Share on other sites

Nice one Adrian! Minor suggestion, maybe add a note/description to the setting 'Protect children' that the protection cascades to grandchildren, etc. 

  • Like 2

Share this post


Link to post
Share on other sites

This is awesome. It's possible to set a protected page via API?

  • Like 1

Share this post


Link to post
Share on other sites

This is awesome. It's possible to set a protected page via API?

Glad you like it :)

Not currently possible - I didn't really think it would be that useful since this is primarily a tool for site editors. I am willing to add the option - perhaps a new protect method so you could do something like:

$page->protect($options);

where $options would be for children, message, roles, prohibited message.

Would you mind giving me a use case scenario so I can get a better idea of how useful this feature would be ?

  • Like 1

Share this post


Link to post
Share on other sites

In my social network this could be useful for users want to make some pages protected and decide who can view the page based on roles, for groups, pictures, or events etc....right now i make this with bare code, so having a module is always nicer and of course users can't go in admin panel so i need some api implementation :)

Share this post


Link to post
Share on other sites

Ok, I have committed a new version that supports protection via the API.

You can now do:

// all optional, except "page_protected", which must be set to true/false
// if setting it to false, the other options are not relevant

$options = array(
    "page_protected" => true,
    "children_protected" => true,
    "allowed_roles" => array("role1", "role2"),
    "message_override" => "My custom login message",
    "prohibited_message" => "My custom prohibited access message"
);

$page->protect($options);

Let me know if you have any problems.

EDIT: I am wondering if in your case dedicated code might be a better solution. This module stores the protection info in the module's data DB field. While this works great because there is no need for special fields to be added to the templates of a pages to be protected, I am worried you might come across some scaling issues if you have thousands or potentially millions of users, all wanting to protect various pages. I have no idea on the scale of your social network, but this is definitely something to consider. 

  • Like 4

Share this post


Link to post
Share on other sites

I'm probably missing something really obvious with this (php isn't my first language), but when I try to inject the form into a template all I get is an unknown variable warning for  $loginForm.

Share this post


Link to post
Share on other sites

I'm probably missing something really obvious with this (php isn't my first language), but when I try to inject the form into a template all I get is an unknown variable warning for  $loginForm.

Sorry you're having trouble.

All I can think is that you are trying to add it to a template that is not selected under the "Login Template" option in the config settings for this module. Are you trying to add it to an existing PW template file like home.php ?

The way this works is that the module uses the selected "Login Template" instead of the template that is normally used by a page.

Does that make sense / solve your problem?

Share this post


Link to post
Share on other sites

Trying to add it to the basic-page.php template, also selected this template in the "login template" section. I've managed to make it output the login boxes, but only them, nothing else in the source, just the styles and the login form. Even after logging in it still shows a missing variable error.

Share this post


Link to post
Share on other sites

Trying to add it to the basic-page.php template, also selected this template in the "login template" section. I've managed to make it output the login boxes, but only them, nothing else in the source, just the styles and the login form. Even after logging in it still shows a missing variable error.

Yeah, that's what I thought :)

That's not how this works. You need to create a dedicated template for the login form. Perhaps called: loginform.php

This template should only contain the framework of your site, eg the header and footer, like in the example, or however you like to structure things, along with $loginForm where you want it to appear.

This loginform.php template will be called instead of basic-page.php, home.php, etc if the page is protected and the person needs to login.

Does that make more sense now?

Share this post


Link to post
Share on other sites

I just added a couple of new options to this module that allow for automatic protection of unpublished and hidden pages and their children. I am finding the unpublished protection very handy as I can set the parent of a branch to unpublished while it is being developed. With this option enabled, I can send the link to this page direct to clients and they will be presented with the custom login form so they login and then immediately view the page - no need to go via the backend admin panel (just like the normal way this module works), and they won't get the 404 page if they attempt to visit when logged out. Because children can also be protected there is no worry about someone guessing the URL to subpages, the entire branch is protected based on the publication status of the parent. Once the branch is ready to be published, simply publish and it will be live and the protection is removed - no need to give clients access to the control of this module on the settings tab and explain how they work.

Hope you all find it useful!

  • Like 5

Share this post


Link to post
Share on other sites

Hi Adrian, the login template isn't working for me. I setup a custom template (login.php) and select it on the module settings, but the login form doesn't show. I'm using ProcessWire 3.0.3 devns.

login.php:

<?php include("./head.inc"); ?>

<div>
  <?php echo $loginForm; ?>
</div>

<?php include("./foot.inc"); ?>

Edit: When i disable the login template, the custom protected message isn't displaying either. The default "This page is protected. You must log in to view it." message is shown.
 

Share this post


Link to post
Share on other sites

Hi @Sanyaissues - sorry you are having problems. I can replicate the problem with the custom template not working in PW 3.0, but aren't seeing the issue with the custom protected message not working - make sure you are editing the message on the Settings tab of the protected page.

Now back to the custom template problem - do you have debug mode turned on in your config.php file? Do you then see this error: 

Notice: Undefined variable: loginForm in /pathto/site/templates/login.php on line 4

The problem seems to be passing variables using wireRenderFile. It works fine in PW 2.x, but looks like there might be a problem in PW 3.x

Can you please confirm that this is the error you are getting.

I am not really at my computer again fully for another a couple of weeks, but I will try to help figure this out.

Anyone else out there reading this that has seen any problems with passing variables using wireRenderFile in PW 3.x?

Share this post


Link to post
Share on other sites

Hi @adrian thanks for your response. As you say, i get the undefined variable error.

About the custom protected message isn't working. I save a new one but isn't rendering on the front-end. This is what i get:

 <form class='PageProtectorForm' action='./' method='post'>
    <legend></legend>
    <input type='text' name='username' placeholder='Username'>
    <input type='password' name='pass' placeholder='Password'>
    <p><button type='submit' name='login'>Login</button></p>
  </form>

Share this post


Link to post
Share on other sites
Hi @adrian thanks for your response. As you say, i get the undefined variable error.

It was a bug with the File Compiler in PW 3.x - it has been fixed in today's commits to the devns branch.

About the custom protected message isn't working. I save a new one but isn't rendering on the front-end. This is what i get:

That does seem weird - the custom message should be between the <legend> tags. Can you provide a screenshot of the settings tab for the page in question?

Share this post


Link to post
Share on other sites

The settings seems to be ok. I check it on incognito to avoid caching, but the default message persists.  I'll try reinstalling the module, 

i54RNno.png?1

Share this post


Link to post
Share on other sites

You need to change the custom message on the Settings tab of the Home page. 

The message on the module settings page should populate newly added protected pages, but once a page has been protected, it stores its custom message separately.

Let me know if you still have problems.

I assume that the login template option is now working for you with the latest PW 3.x build?

Share this post


Link to post
Share on other sites

@adrian thanks, i did't notice the custom message on the home page, my bad. The login template option isn't working on 3.0.4 

Notice: Undefined variable: loginForm

Share this post


Link to post
Share on other sites
The login template option isn't working on 3.0.4

Have you cleared the compiled templates? 

Modules > Site > Clear Compiled Files

I think the error you are seeing is from a cached compiled template from before the problem was fixed in 3.0.4

Share this post


Link to post
Share on other sites

@Adrian shame on me... is the first time i see the Clear Compiled Files button. The login template it's working. Thanks for your help.

  • Like 1

Share this post


Link to post
Share on other sites

I read all over the docs and the forum about protecting certain pages from access and wonder why my efforts are unsuccessful.

The situation (simplified):

Pages tree

Home
 -   Free Stuff
     - -   Free1
     - -   Free2
 -  Private Stuff
    - -  Private1
    - -  Private2
       
Free Stuff and its children have the template "standard"; Access managing is set to No.  
Private Stuff and its children have the template "private": in its Access settings the page view option is unticked for the guest role.
 
Apart from superuser and guest there are the following roles:
    editor
    member

The editor role grants page edit permission for all the pages.
Users having the member role have to log in to get acces to the private pages.

Now my question:

What do I have to do to give the member users page view access exclusively for the private pages?
(That is, they should not see the pages of template standard.)

What I tried: In the Settings of the page Free Stuff I ticked Protect this page, then Protect children too.
As Allowed roles I selected all but the role member.

So I expected that a member user would no longer have access to the Full Stuff page nor its children. But that doesn't work.

Maybe I'm missing something obvious. Any help is hihgly appreciated!

Share this post


Link to post
Share on other sites
What I tried: In the Settings of the page Free Stuff I ticked Protect this page, then Protect children too.

As Allowed roles I selected all but the role member.

So I expected that a member user would no longer have access to the Full Stuff page nor its children. But that doesn't work.

It sounds like you are using the PageProtector module. It only prevents users from viewing pages on the front-end. I can't tell if that's what you want or if you expect them to also not be able to view and edit them in the backend?

Also, you say that you selected all roles, except the member role. Do the members also have one of the other selected roles? Including "guest"?

  • Like 1

Share this post


Link to post
Share on other sites

Thank you, adrian.

Yes, I'm using the PageProtector module (forgot to mention it).

Members get only page view, not page edit permission. They should not have access to the backend.*

Members have the roles "members" and "guest" - you can't remove the guest role from a user. They don't have any of the roles with page edit permission.

*Edit: This doesn't work - they have access to the pages tree (not wanted), but see just the view buttons.

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.

  • Similar Content

    • By teppo
      Needed a really simple solution to embed audio files within page content and couldn't find a module for that, so here we go. Textformatter Audio Embed works a bit like Textformatter Video Embed, converting this:
      <p>https://www.domain.tld/path/to/file.mp3</p> Into this:
      <audio controls class="TextformatterAudioEmbed"> <source src="https://www.domain.tld/path/to/file.mp3" type="audio/mpeg"> </audio> The audio element has pretty good browser support, so quite often this should be enough to get things rolling 🙂
      GitHub repository: https://github.com/teppokoivula/TextformatterAudioEmbed Modules directory: https://modules.processwire.com/modules/textformatter-audio-embed/
    • By Richard Jedlička
      Tense    
      Tense (Test ENvironment Setup & Execution) is a command-line tool to easily run tests agains multiple versions of ProcessWire CMF.
      Are you building a module, or a template and you need to make sure it works in all supported ProcessWire versions? Then Tense is exactly what you need. Write the tests in any testing framework, tell Tense which ProcessWire versions you are interested in and it will do the rest for you.

      See example or see usage in a real project.
      How to use?
      1. Install it: 
      composer global require uiii/tense 2. Create tense.yml config:
      tense init 3. Run it:
      tense run  
      For detailed instructions see Github page: https://github.com/uiii/tense
       
      This is made possible thanks to the great wireshell tool by @justb3a, @marcus and others.
       
      What do you think about it? Do you find it useful? Do you have some idea? Did you find some bug? Tell me you opinion. Write it here or in the issue tracker.
    • By Chris Bennett
      Hi all, I am going round and round in circles and would greatly appreciate if anyone can point me in the right direction.
      I am sure I am doing something dumb, or missing something I should know, but don't. Story of my life 😉

      Playing round with a module and my basic problem is I want to upload an image and also use InputfieldMarkup and other Inputfields.
      Going back and forth between trying an api generated page defining Fieldgroup, Template, Fields, Page and the InputfieldWrapper method.

      InputfieldWrapper method works great for all the markup stuff, but I just can't wrap my head around what I need to do to save the image to the database.
      Can generate a Field for it (thanks to the api investigations) but not sure what I need to do to link the Inputfield to that. Tried a lot of stuff from various threads, of varying dates without luck.
      Undoubtedly not helped by me not knowing enough.

      Defining Fieldgroup etc through the api seems nice and clean and works great for the images but I can't wrap my head around how/if I can add/append/hook the InputfieldWrapper/InputfieldMarkup stuff I'd like to include on that template as well. Not even sure if it should be where it is on ___install with the Fieldtype stuff or later on . Not getting Tracy errors, just nothing seems to happen.
      If anyone has any ideas or can point me in the right direction, that would be great because at the moment I am stumbling round in the dark.
       
      public function ___install() { parent::___install(); $page = $this->pages->get('name='.self::PAGE_NAME); if (!$page->id) { // Create fieldgroup, template, fields and page // Create new fieldgroup $fmFieldgroup = new Fieldgroup(); $fmFieldgroup->name = MODULE_NAME.'-fieldgroup'; $fmFieldgroup->add($this->fields->get('title')); // needed title field $fmFieldgroup->save(); // Create new template using the fieldgroup $fmTemplate = new Template(); $fmTemplate->name = MODULE_NAME; $fmTemplate->fieldgroup = $fmFieldgroup; $fmTemplate->noSettings = 1; $fmTemplate->noChildren = 1; $fmTemplate->allowNewPages = 0; $fmTemplate->tabContent = MODULE_NAME; $fmTemplate->noChangeTemplate = 1; $fmTemplate->setIcon(ICON); $fmTemplate->save(); // Favicon source $fmField = new Field(); $fmField->type = $this->modules->get("FieldtypeImage"); $fmField->name = 'fmFavicon'; $fmField->label = 'Favicon'; $fmField->focusMode = 'off'; $fmField->gridMode = 'grid'; $fmField->extensions = 'svg png'; $fmField->columnWidth = 50; $fmField->collapsed = Inputfield::collapsedNever; $fmField->setIcon(ICON); $fmField->addTag(MODULE_NAME); $fmField->save(); $fmFieldgroup->add($fmField); // Favicon Silhouette source $fmField = new Field(); $fmField->type = $this->modules->get("FieldtypeImage"); $fmField->name = 'fmFaviconSilhouette'; $fmField->label = 'SVG Silhouette'; $fmField->notes = 'When creating a silhouette/mask svg version for Safari Pinned Tabs and Windows Tiles, we recommend setting your viewbox for 0 0 16 16, as this is what Apple requires. In many cases, the easiest way to do this in something like illustrator is a sacrificial rectangle with no fill, and no stroke at 16 x 16. This forces the desired viewbox and can then be discarded easily using something as simple as notepad. Easy is good, especially when you get the result you want without a lot of hassle.'; $fmField->focusMode = 'off'; $fmField->extensions = 'svg'; $fmField->columnWidth = 50; $fmField->collapsed = Inputfield::collapsedNever; $fmField->setIcon(ICON); $fmField->addTag(MODULE_NAME); $fmField->save(); $fmFieldgroup->add($fmField); // Create: Open Settings Tab $tabOpener = new Field(); $tabOpener->type = new FieldtypeFieldsetTabOpen(); $tabOpener->name = 'fmTab1'; $tabOpener->label = "Favicon Settings"; $tabOpener->collapsed = Inputfield::collapsedNever; $tabOpener->addTag(MODULE_NAME); $tabOpener->save(); // Create: Close Settings Tab $tabCloser = new Field(); $tabCloser->type = new FieldtypeFieldsetClose; $tabCloser->name = 'fmTab1' . FieldtypeFieldsetTabOpen::fieldsetCloseIdentifier; $tabCloser->label = "Close open tab"; $tabCloser->addTag(MODULE_NAME); $tabCloser->save(); // Create: Opens wrapper for Favicon Folder Name $filesOpener = new Field(); $filesOpener->type = new FieldtypeFieldsetOpen(); $filesOpener->name = 'fmOpenFolderName'; $filesOpener->label = 'Wrap Folder Name'; $filesOpener->class = 'inline'; $filesOpener->collapsed = Inputfield::collapsedNever; $filesOpener->addTag(MODULE_NAME); $filesOpener->save(); // Create: Close wrapper for Favicon Folder Name $filesCloser = new Field(); $filesCloser->type = new FieldtypeFieldsetClose(); $filesCloser->name = 'fmOpenFolderName' . FieldtypeFieldsetOpen::fieldsetCloseIdentifier; $filesCloser->label = "Close open fieldset"; $filesCloser->addTag(MODULE_NAME); $filesCloser->save(); // Create Favicon Folder Name $fmField = new Field(); $fmField->type = $this->modules->get("FieldtypeText"); $fmField->name = 'folderName'; $fmField->label = 'Favicon Folder:'; $fmField->description = $this->config->urls->files; $fmField->placeholder = 'Destination Folder for your generated favicons, webmanifest and browserconfig'; $fmField->columnWidth = 100; $fmField->collapsed = Inputfield::collapsedNever; $fmField->setIcon('folder'); $fmField->addTag(MODULE_NAME); $fmField->save(); $fmFieldgroup->add($tabOpener); $fmFieldgroup->add($filesOpener); $fmFieldgroup->add($fmField); $fmFieldgroup->add($filesCloser); $fmFieldgroup->add($tabCloser); $fmFieldgroup->save(); /////////////////////////////////////////////////////////////// // Experimental Markup Tests $wrapperFaviconMagic = new InputfieldWrapper(); $wrapperFaviconMagic->attr('id','faviconMagicWrapper'); $wrapperFaviconMagic->attr('title',$this->_('Favicon Magic')); // field show info what $field = $this->modules->get('InputfieldMarkup'); $field->name = 'use'; $field->label = __('How do I use it?'); $field->collapsed = Inputfield::collapsedNever; $field->icon('info'); $field->attr('value', 'Does this even begin to vaguely work?'); $field->columnWidth = 50; $wrapperFaviconMagic->add($field); $fmTemplate->fields->add($wrapperFaviconMagic); $fmTemplate->fields->save(); ///////////////////////////////////////////////////////////// // Create page $page = $this->wire( new Page() ); $page->template = MODULE_NAME; $page->parent = $this->wire('pages')->get('/'); $page->addStatus(Page::statusHidden); $page->title = 'Favicons'; $page->name = self::PAGE_NAME; $page->process = $this; $page->save(); } }  
    • By Sebi
      Since it's featured in ProcessWire Weekly #310, now is the time to make it official:
      Here is Twack!
      I really like the following introduction from ProcessWire Weekly, so I hope it is ok if I use it here, too. Look at the project's README for more details!
      Twack is a new — or rather newish — third party module for ProcessWire that provides support for reusable components in an Angular-inspired way. Twack is implemented as an installable module, and a collection of helper and base classes. Key concepts introduced by this module are:
      Components, which have separate views and controllers. Views are simple PHP files that handle the output for the component, whereas controllers extend the TwackComponent base class and provide additional data handling capabilities. Services, which are singletons that provide a shared service where components can request data. The README for Twack uses a NewsService, which returns data related to news items, as an example of a service. Twack components are designed for reusability and encapsulating a set of features for easy maintainability, can handle hierarchical or recursive use (child components), and are simple to integrate with an existing site — even when said site wasn't originally developed with Twack.
      A very basic Twack component view could look something like this:
      <?php namespace ProcessWire; ?> <h1>Hello World!</h1> And here's how you could render it via the API:
      <?php namespace Processwire; $twack = $modules->get('Twack'); $hello = $twack->getNewComponent('HelloWorld'); ?> <html> <head> <title>Hello World</title> </head> <body> <?= $hello->render() ?> </body> </html> Now, just to add a bit more context, here's a simple component controller:
      <?php namespace ProcessWire; class HelloWorld extends TwackComponent { public function __construct($args) { parent::__construct($args); $this->title = 'Hello World!'; if(isset($args['title'])) { $this->title = $args['title']; } } } As you can see, there's not a whole lot new stuff to learn here if you'd like to give Twack a try in one of your projects. The Twack README provides a really informative and easy to follow introduction to all the key concepts (as well as some additional examples) so be sure to check that out before getting started. 
      Twack is in development for several years and I use it for every new project I build. Also integrated is an easy to handle workflow to make outputs as JSON, so it can be used to build responses for a REST-api as well. I will work that out in one section in the readme as well. 
      If you want to see the module in an actual project, I have published the code of www.musical-fabrik.de in a repository. It runs completely with Twack and has an app-endpoint with ajax-output as well.
      I really look forward to hear, what you think of Twack🥳!
      Features Installation Usage Quickstart: Creating a component Naming conventions & component variants Component Parameters directory page parameters viewname Asset handling Services Named components Global components Ajax-Output Configuration Versioning License Changelog
    • By Robin S
      Page Reference Default Value
      Most ProcessWire core inputfield types that can be used with a Page Reference field support a "Default value" setting. This module extends support for default values to the following core inputfield types:
      Page List Select Page List Select Multiple Page Autocomplete (single and multiple) Seeing as these inputfield types only support the selection of pages a Page List Select / Page List Select Multiple is used for defining the default value instead of the Text / Textarea field used by the core for other inputfield types. This makes defining a default value a bit more user-friendly.
      Note that as per the core "Default value" setting, the Page Reference field must be set to "required" in order for the default value to be used.
      Screenshot

       
      https://github.com/Toutouwai/PageReferenceDefaultValue
      https://modules.processwire.com/modules/page-reference-default-value/
×
×
  • Create New...