Skip to content

Instantly share code, notes, and snippets.

@GDmac
Last active August 29, 2015 14:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save GDmac/0a22abba5327511e650c to your computer and use it in GitHub Desktop.
Save GDmac/0a22abba5327511e650c to your computer and use it in GitHub Desktop.
Protected Pages Bolt.cm extension

ProtectedPages extension

Make sections of your site (template) accessible to members only.

Quick Setup

Create a template with a loginform and the processform tag. The form should at least provide username, password and action. e.g.:

{{ protectedpage_processform() }}

<!-- display error messages here, see below -->

<form class="loginform" method="post">
  <input type=text name=username>
  <input type=text name=password>
  <input type=submit name=action value=login>
</form>

Decide what the uri should be for the login form (e.g. /members-login), and in the extension config.yml set the redirect variable to this uri.

Create a static route to the login template for this uri. (or make a page/entry for this uri that uses this template.)

Protect a template with the tag {{ protectedpage() }}. If a visitor is not logged in (or does not have an allowed role assigned), the visitor will be redirected to the login page. After login, the visitor will be redirected back to the original page.

Settings

In the extension config.yml set member_roles to the roles that should have access to protected pages. Member_roles is the default set, but you can create custom sets of roles for different access levels, and pass the set name to the extension: {{ protectedpage('custom_roles') }}

Next to the default Bolt roles as editor, chief_editor, etc., you can add to Bolt a member role if needed.

Redirect is the uri where the visitor is redirected to when visiting a protected page, but is not logged in, or does not have a correct role.

Error messages

Protected Pages uses app->users->login so any error and success messages are set in session flashMessages. You can copy/paste the content from Bolt, inside /app/view/_messages.twig and place them next to the loginform to display notices etc.

{% if app.session.flashBag.has('info') %}
    <div class="alert alert-info">
        <button class="close" data-dismiss="alert">×</button>
        {% for msg in app.session.flashBag.get('info') %}
            {{ msg|ymllink }}
        {% endfor %}
    </div>
{% endif %}

{% if app.session.flashBag.has('error') %}
    <div class="alert alert-error">
        <button class="close" data-dismiss="alert">×</button>
        {% for msg in app.session.flashBag.get('error') %}
            {{ msg|ymllink }}
        {% endfor %}
    </div>
{% endif %}
# ------------------------------------------------------------------------
# The url to redirect to, when user does not have necessary role (e.g. not logged in).
redirect: '/members/login'
# ------------------------------------------------------------------------
# (default) user roles that are allowed to view member-only pages
member_roles: ['member', 'editor', 'chief-editor', 'admin', 'developer', 'root']
# ------------------------------------------------------------------------
# You can define here, and then pass a parameter to protectedpage()
# so it looks up roles from a different array
#
# admin_roles: ['admin', 'developer', 'root']
custom_roles: ['editor', 'chief-editor', 'admin', 'developer', 'root']
<?php
namespace ProtectedPages;
use Bolt\Extensions\Snippets\Location as SnippetLocation;
class Extension extends \Bolt\BaseExtension
{
public $allowed_roles = 'member_roles'; // default
// ------------------------------------------------------------------------
public function info()
{
$data = array(
'name' =>"ProtectedPages",
'description' => "Pages only visible to logged in users with defined role",
'author' => "GDmac",
'link' => "http://bolt.cm",
'version' => "0.1",
'required_bolt_version' => "1.4",
'highest_bolt_version' => "1.6.1",
'type' => "Twig function",
'first_releasedate' => "2014-05-21",
'latest_releasedate' => "2014-05-21",
);
return $data;
}
// ------------------------------------------------------------------------
public function initialize()
{
$this->addTwigFunction('protectedpage', 'protectedpage');
$this->addTwigFunction('protectedpage_processform', 'protectedpage_processform');
}
// ------------------------------------------------------------------------
public function protectedpage($allowed_roles = 'member_roles')
{
$this->allowed_roles = $allowed_roles;
if ( ! $this->validUser() )
{
if ($this->isRedirectPage() )
{
die("don't use protectedpage() on the redirect-page, to provide login functionality, use a form and protectedpageform()");
}
$this->app['session']->set('returnto', $this->app['request']->getRequestUri() );
simpleredirect($this->config['redirect']);
}
}
// ------------------------------------------------------------------------
public function validUser()
{
// user already logged in and has allowed role ? (currentuser)
if ( $this->app['users']->currentuser != NULL )
{
foreach ($this->config[$this->allowed_roles] as $role)
{
if (in_array($role, $this->app['users']->currentuser['roles']))
{
return true; // role found
}
}
}
return false;
}
// ------------------------------------------------------------------------
public function isRedirectPage()
{
return (rtrim($this->app['request']->getRequestUri(), '/') == $this->config['redirect']);
}
// ------------------------------------------------------------------------
public function protectedpage_processform()
{
$app = $this->app;
$request = $this->app['request'];
// return to previous page or homepage
$returnto = $app['session']->get('returnto');
$returnto = !empty($returnto) ? $returnto : $request->getBaseUrl();
// Logout : ?logout get-parameter was set
if ($request->get('logout') !== NULL)
{
$app['users']->logout();
simpleredirect($request->getBaseUrl());
}
// Form submitted?
if ('POST' == $request->getMethod())
{
switch ($_POST['action'])
{
case 'login':
$result = $app['users']->login($request->get('username'), $request->get('password'));
if ($result)
{
$app['session']->set('returnto', '');
$app['log']->add("Login " . $request->get('username'), 3, '', 'login');
// # success flashbag not needed, because redirecting. unset it?
// $app['session']->getFlashBag()->set('success', NULL);
simpleredirect($returnto);
}
return; // 'login failed...';
// TODO: general account functions
// case 'forgot_password':
// case 'reset_password':
// case 'set_password':
// case 'set_username':
// case 'set_email':
default:
return $app->abort(400, 'Invalid request');
}
}
}
}
@bobdenotter
Copy link

Hi, will you be making a PR out of this? Looks good to me, for starters.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment