Having got the basic pages in we now need to restrict access to those page that change the database: adding
and deleting. First of all we need a suitable login and logout page:
examples/sql/login.xml
<page:content>
<t:heading level="1">Paloose Login</t:heading>
<t:p>Please enter your login details for the SQL Example:</t:p>
<form:form>
<form:start url="checkLogin.html">Login</form:start>
<form:field name="username" type="text">User name</form:field>
<form:field name="password" type="password">Password</form:field>
</form:form>
</page:content>
examples/sql/logout.xml
<page:content>
<t:heading level="1">Paloose SQL Example</t:heading>
<t:p>You have now been logged out.</t:p>
<t:p><link:link type="uri" ref="examples/sql/sql.html">Return to SQL Example index</link:link></t:p>
</page:content>
We also need a suitable error notification page:
examples/sql/loginError.xml
<page:content>
<t:heading level="1">Paloose SQL Example</t:heading>
<t:p>Sorry that user/password combination does not seem to work, please try again:</t:p>
<form:form>
<!-- Will become the form's action attribute -->
<form:start url="checkLogin.html">Login</form:start>
<form:field name="username" type="text">User name</form:field>
<form:field name="password" type="password">Password</form:field>
</form:form>
</page:content>
We now have to add in the various authorisation bits into the siteamp. First declare the components:
pp/examples/sql/sitemap.xmap
<map:components>
<map:generators default="file"/>
<map:transformers default="xslt">
<map:transformer name="mysql" src="resource://lib/transforming/SQLTransformer">
<map:parameter name="type" value="mysql"/>
<map:parameter name="host" value="localhost:3306"/>
<map:parameter name="user" value="hsfr"/>
<map:parameter name="password" value="fof-hyd"/>
<!-- Only time I use this password so don't get excited! :-) -->
</map:transformer>
<map:transformer name="password" src="resource://lib/transforming/PasswordTransformer"/>
</map:transformers>
<map:actions>
<map:action name="auth-protect" src="resource://lib/acting/AuthAction"/>
<map:action name="auth-login" src="resource://lib/acting/LoginAction"/>
<map:action name="auth-logout" src="resource://lib/acting/LogoutAction"/>
</map:actions>
<map:serializers default="xml"/>
<map:matchers default="wildcard"/>
</map:components>
Then the authorisation manager:
pp/examples/sql/sitemap.xmap
<map:pipelines>
<map:component-configurations>
<map:authentication-manager>
<!-- This is the means that Paloose checks whether a user is authenticated
and is allowed to see pages protected within the pipeline. If the handler
does not authenticate the use then go to redirect -->
<map:handlers>
<map:handler name="adminHandler">
<!-- Run this if the user needs login (diverts to this sitemap) -->
<map:redirect-to uri="cocoon:/login"/>
<!-- The pipeline used to authenticate the user -->
<map:authentication uri="cocoon:/authenticate-user.html"/>
</map:handler>
</map:handlers>
</map:authentication-manager>
</map:component-configurations>
<!-- pipelines -->
</map:pipelines>
Finally the internal pipeline that processes the above:
pp/examples/sql/sitemap.xmap
<map:pipeline internal-only="true">
<map:match pattern="authenticate-user.html">
<map:generate src="context://configs/adminUsers.xml" label="xml-content"/>
<map:transform src="context://resources/transforms/admin-getLoginQuery.xsl">
<map:parameter name="username" value="{request-param:username}"/>
<map:parameter name="password" value="{request-param:password}"/>
</map:transform>
<!-- Encrypt the password -->
<map:transform type="password"/>
<map:transform src="context://resources/transforms/admin-buildAuthenticateDOM.xsl"/>
<map:serialize type="xml"/>
<!-- The output here is a standard Cocoon authenticate structure
and is returned to the authentication-manager -->
</map:match>
<!-- Login form action -->
<map:match pattern="login">
<!-- We come here when we need the user to log in. It produces a login
form for the user to fill in. -->
<map:aggregate element="root" label="aggr-content">
<map:part src="cocoon:/menus.xml" element="menus" strip-root="true"/>
<map:part src="cocoon:/login.xml" element="content" strip-root="true"/>
</map:aggregate>
<map:call resource="outputPage"/>
</map:match>
<map:match pattern="checkLogin.html">
<!-- Match pattern must be the same match as that on the login form URL -->
<map:act type="auth-login">
<map:parameter name="handler" value="adminHandler"/>
<map:parameter name="username" value="{request-param:username}"/>
<map:parameter name="password" value="{request-param:password}"/>
<!-- Logged in so must have given password and username -->
<map:redirect-to uri="cocoon:/sql.html"/>
</map:act>
<!-- Oops, not logged in properly so give appropriate screen back -->
<map:aggregate element="root" label="aggr-content">
<map:part src="cocoon:/menus.xml" element="menus" strip-root="true"/>
<map:part src="cocoon:/loginError.xml" element="content" strip-root="true"/>
</map:aggregate>
<map:call resource="outputPage"/>
</map:match>
</map:pipeline>
The format of the list of admin users is:
context://configs/adminUsers.xml
<?xml version="1.0" encoding="ISO-8859-1"?>
<authentication>
<users>
<user>
<username>hsfr</username>
<password>672b86ff.............33a92040c5</password>
<data>
<fullname>Hugh Field-Richards</fullname>
<email>hsfr@hsfr.org.uk</email>
</data>
</user>
</users>
</authentication>
This is processed by the transform admin-getLoginQuery.xsl:
context://resources/transforms/admin-getLoginQuery.xsl
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:param name="password"/>
<xsl:param name="username"/>
<xsl:template match="//authentication">
<xsl:element name="authentication" >
<xsl:attribute name="username"><xsl:value-of select="$username" /></xsl:attribute>
<xsl:attribute name="password"><xsl:value-of select="$password" /></xsl:attribute>
<xsl:apply-templates mode="pass"/>
</xsl:element>
</xsl:template>
<xsl:template match="@*|node()" mode="pass">
<xsl:copy>
<xsl:apply-templates select="@*|node()" mode="pass" />
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
This is then run through the password transformer and then the build authenticate DOM transform:
context://resources/transforms/admin-buildAuthenticateDOM.xsl
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:variable name="gPassword" select="//authentication/@password" /> <!-- encrypted -->
<xsl:variable name="gUsername" select="//authentication/@username" />
<!-- -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* -->
<xsl:template match="authentication">
<authentication>
<xsl:apply-templates select="users"/>
</authentication>
</xsl:template>
<!-- -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* -->
<xsl:template match="users">
<xsl:apply-templates select="user"/>
</xsl:template>
<!-- -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* -->
<xsl:template match="user">
<xsl:if test="normalize-space( username ) = $gUsername and normalize-space( password ) = $gPassword">
<ID><xsl:value-of select="username"/></ID>
<data>
<ID><xsl:value-of select="username"/></ID>
<username><xsl:value-of select="username"/></username>
<password><xsl:value-of select="password"/></password>
<fullname><xsl:value-of select="data/fullname"/></fullname>
<xsl:if test="data/telephone">
<telephone><xsl:value-of select="data/telephone"/></telephone>
</xsl:if>
<xsl:if test="data/email">
<email><xsl:value-of select="data/email"/></email>
</xsl:if>
</data>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
Which outputs the necessary data for the authentication manager. Individual pages are protected with the
following additions:
examples/sql/sitemap.xmap
<map:pipeline>
<map:match pattern="addComposer.html">
<map:act type="auth-protect">
<map:parameter name="handler" value="adminHandler"/>
<map:call function="AddComposer::add"/>
</map:act>
</map:match>
<map:match pattern="addComposer.kont">
<map:call function="AddComposer::add"/>
</map:match>
</map:pipeline>
Only externally accessible pages need be protected in the sitemap, all "internal-only" pipelines are protected naturally.
More information on authorising pages can be found in the documentation on authorising
Copyright 2006 — 2010 Hugh Field-Richards. All Rights Reserved.