<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>CodeUtopia - The blog of Jani Hartikainen &#187; Zend_Acl</title>
	<atom:link href="http://codeutopia.net/blog/tag/zend_acl/feed/" rel="self" type="application/rss+xml" />
	<link>http://codeutopia.net/blog</link>
	<description>Software development with a focus on web-related technologies</description>
	<lastBuildDate>Wed, 08 Sep 2010 19:50:40 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>Zend_Acl part 3: creating and storing dynamic ACLs</title>
		<link>http://codeutopia.net/blog/2009/02/18/zend_acl-part-3-creating-and-storing-dynamic-acls/</link>
		<comments>http://codeutopia.net/blog/2009/02/18/zend_acl-part-3-creating-and-storing-dynamic-acls/#comments</comments>
		<pubDate>Wed, 18 Feb 2009 10:15:52 +0000</pubDate>
		<dc:creator>Jani Hartikainen</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Zend Framework]]></category>
		<category><![CDATA[Zend_Acl]]></category>

		<guid isPermaLink="false">http://codeutopia.net/blog/2009/02/18/zend_acl-part-3-creating-and-storing-dynamic-acls/</guid>
		<description><![CDATA[In this third post of the series, I'll talk about using dynamic ACLs: How to store an ACL in a database, and construct it from there when needed. We will first look at a simple example with users and pages, and then we'll have a more complex example, involving building a much more complex ACL with inheritance, role types and other stuff.]]></description>
			<content:encoded><![CDATA[<p>In this third post of the series, I&#8217;ll talk about using dynamic ACLs: How to store an ACL in a database, and construct it from there when needed. This post builds on the things introduced in <a href="http://codeutopia.net/blog/2009/02/06/zend_acl-part-1-misconceptions-and-simple-acls/">part 1</a> and <a href="http://codeutopia.net/blog/2009/02/11/zend_acl-part-2-different-roles-and-resources-more-on-access/">part 2</a>.</p>
<p>We will first look at a simple example with users and pages, and then we&#8217;ll have a more complex example, involving building a much more complex ACL with inheritance, role types and other stuff.</p>
<p><span id="more-202"></span></p>
<h3>The idea behind dynamic ACLs</h3>
<p>As we have previously looked at ACLs which are hardcoded, we will now look at building a &#8220;dynamic&#8221; ACL. Previously shown &#8220;static&#8221; ACLs are good for quick and simple sites, but when you actually require the ability for administrators to define access rights on the fly using an admin panel, they quickly lose their usefulness.</p>
<p>Also, when working with very large amounts of users or roles, it may not be a very good idea to always construct the full ACL. This is one of the things we&#8217;ll discuss in this part: Creating ACLs with only the parts that are required to perform a specific access check.</p>
<p>Let&#8217;s say you have a user, and you have to check if the user has access to a specific page. Would it make sense to load the complete ACL, with all your users, all your pages and then set up all their access rights? Nope, not really. It&#8217;s a better idea to simply create an ACL with just the single user, and the single resource we need to check against.</p>
<h3>A simple example with users and pages</h3>
<p>Let&#8217;s first start with a relatively simple case: We have a site with some pages, and we need to be able to define which users can access which pages. By default, nobody can access a page, unless we specifically allow it. Later in this post, we&#8217;ll look at a more complex set up.</p>
<div class="image right resize"><a href="http://codeutopia.net/acl1.jpg"><img src="http://codeutopia.net/acl1.jpg" alt="" /><br /></a></div>
<p>To the right you can see a database table schema for this example. As you can see, it&#8217;s relatively simple with just three tables.</p>
<ol>
<li>Pages table holds our site&#8217;s pages</li>
<li>Users table holds our site&#8217;s users</li>
<li>Page_privileges table holds data on which user has been granted access to which page</li>
</ol>
<p>In this case, it makes sense to store ACL roles and resources as numbers: Each user is a role, and each page is a resource, thus we can easily store them in the ACL as their respective ID&#8217;s from the database.</p>
<h4 style="clear: both">An ACL factory</h4>
<p>Before going any further, let&#8217;s introduce a concept we&#8217;ll be using throughout this post &#8211; an ACL factory class. The factory will be used to construct our ACL instances. This will allow us to keep better track of the code that is creating the ACL, and keep everything related to its initialization in a single place. By doing this, we can also specify things like table names or such in later on the post.</p>
<p>This is the basic factory we&#8217;ll be using now:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span> AclFactory <span style="color: #009900;">&#123;</span>
  <span style="color: #009933; font-style: italic;">/**
   * Creates an ACL for a specific page
   * @param Page $page
   * @return Zend_Acl
   */</span>
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> createAcl<span style="color: #009900;">&#40;</span>Page <span style="color: #000088;">$page</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #666666; font-style: italic;">//Lets assume we have a model for the page_privileges with a method like this</span>
    <span style="color: #666666; font-style: italic;">//which would return PagePrivilege objects with the page_id passed as the param.</span>
    <span style="color: #000088;">$privileges</span> <span style="color: #339933;">=</span> PagePrivilege<span style="color: #339933;">::</span><span style="color: #004000;">findByPageId</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$page</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getId</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000088;">$acl</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Zend_Acl<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$acl</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">add</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> Zend_Acl_Resource<span style="color: #009900;">&#40;</span><span style="color: #000088;">$page</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getId</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">foreach</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$privileges</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$privilege</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #000088;">$acl</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addRole</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> Zend_Acl_Role<span style="color: #009900;">&#40;</span><span style="color: #000088;">$privilege</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getUserId</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      <span style="color: #000088;">$acl</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">allow</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$privilege</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getUserId</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$page</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getId</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #b1b100;">return</span> <span style="color: #000088;">$acl</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>The way the method works is it first gets all privileges for the page &#8211; every row with the page&#8217;s ID as the page_id. We then create a new Zend_Acl instance, and add a resource with the page&#8217;s ID. Then it&#8217;s simply a loop, which adds each user_id found from the table to the ACL as a role, and marks the page as allowed for the user.</p>
<p>But how does this work? Because we are using the user IDs as the role IDs, we can loop over each found privilege, and add the user id in it to the ACL. This way, the ACL will have all possible roles for this resource in it. Similarily, since the privilege means the user has access to the page, we also allow the user to access the page.</p>
<h4>Using the ACL factory</h4>
<p>Now that we have the code which can build an ACL for us, let&#8217;s see how it could be used:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">//Lets say $page is a page we want to access</span>
<span style="color: #000088;">$factory</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> AclFactory<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$acl</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$factory</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">createAcl</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$page</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">//and $user is the currently logged in user</span>
<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$acl</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">hasRole</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$user</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getId</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&amp;&amp;</span> <span style="color: #000088;">$acl</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">isAllowed</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$user</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getId</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$page</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getId</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
  <span style="color: #666666; font-style: italic;">//Access OK</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>So we use the factory to build an ACL, and then we use it as normal. This time we also use the hasRole method to test if the ACL actually even has the user&#8217;s role &#8211; since we are only adding the roles that actually <i>have access</i> to the page, the user may not be in the ACL, and if the role does not exist when you call isAllowed, you will get an exception.</p>
<h3>Complex example: A file directory</h3>
<p>Now that we&#8217;ve covered the basics, let&#8217;s dive in a bit deeper: How to implement an ACL system for a system which can be used to serve files to users.</p>
<div class="image right resize"><a href="http://codeutopia.net/acl_file.jpg"><img src="http://codeutopia.net/acl_file.jpg" alt="" /><br />Click for bigger image</a></div>
<p>The file system&#8217;s access will be defined like this:</p>
<ul>
<li>It can have multiple categories, which can contain one or more files</li>
<li>Access to categories or files will be inherited from the parent(s)</li>
<li>Users can belong to one or more groups</li>
<li>A user or a group can have access defined to specific files or categories</li>
</ul>
<p>So in terms of Zend_Acl, we can talk of categories and files as resources. Files will inherit permissions from the category they belong to, and categories will inherit from any parent categories they may have.</p>
<p>Since we won&#8217;t go into much details about the database and all that, you can take a look at the database diagram presented on the right. Full source code for a ZF file system application based on this is also available towards the end of this post, which contains SQL for creating the tables, and all the code required.</p>
<h4>Initial set up</h4>
<p>We&#8217;ll assume few things on the system: we will have a predefined group in the database: guests</p>
<p>A user who isn&#8217;t logged in will be assigned an identity which belongs only to the group guests. Thus we can limit access to guests using the ACL if we want.</p>
<p>We&#8217;ll also have a model class representing each of the tables with getters and setters, in a similar fashion as the NewsPost example model shown in the <a href="http://codeutopia.net/blog/2009/02/16/practical-uses-for-reflection/">practical uses for reflection</a> post. In addition, we will have some classes which can be used to fetch instances of the models from the database, or store them.</p>
<h4>Starting out</h4>
<p>Most of the big things will be going on in the ACL factory class. We will modify the one introduced earlier to suit this more complex example. It will have two public methods: createFileAcl and createCategoryAcl. We&#8217;ll take a look at the latter first:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> createCategoryAcl<span style="color: #009900;">&#40;</span>Category <span style="color: #000088;">$category</span><span style="color: #339933;">,</span> User <span style="color: #000088;">$user</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
  <span style="color: #000088;">$acl</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Zend_Acl<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_createRoles<span style="color: #009900;">&#40;</span><span style="color: #000088;">$acl</span><span style="color: #339933;">,</span> <span style="color: #000088;">$user</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #000088;">$categories</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$category</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getParents</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">+</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$category</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #666666; font-style: italic;">//Top category has no parent, so it's null at first</span>
  <span style="color: #000088;">$parent</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">;</span>
  <span style="color: #b1b100;">foreach</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$categories</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$c</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$acl</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">add</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$c</span><span style="color: #339933;">,</span> <span style="color: #000088;">$parent</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #666666; font-style: italic;">//next will have this as the parent</span>
    <span style="color: #000088;">$parent</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$c</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #000088;">$privileges</span> <span style="color: #339933;">=</span> Privilege<span style="color: #339933;">::</span><span style="color: #004000;">findByCategories</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$categories</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_setPrivileges<span style="color: #009900;">&#40;</span><span style="color: #000088;">$acl</span><span style="color: #339933;">,</span> <span style="color: #000088;">$privileges</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #b1b100;">return</span> <span style="color: #000088;">$acl</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>So basically the method takes a Category object and a User object as its parameters. We will look at the _createRoles and _setPrivileges methods soon.</p>
<p>The Category class implements the Zend_Acl_Resource_Interface <a href="http://codeutopia.net/blog/2009/02/11/zend_acl-part-2-different-roles-and-resources-more-on-access/">as shown previously</a>, so the code in the factory can simply pass the objects to add() when creating the ACL.</p>
<p>This also shows how resource inheritance can be done: We simply take all the parents of the category and make them inherit from each other by passing them as arguments to add. </p>
<p>The getParents method will return all parents of a Category, as the farthest parent at 0, and closer at 1, 2 and so on. As the top level category will not have a parent, we first make it null. As we process the array, we change the parent category to the processed one, so the next category gets it as its parent.</p>
<p>The Privilege class&#8217; method findByCategories will return all privilege objects for certain categories. Refer to the database diagram to see what it represents.</p>
<h4>Private methods</h4>
<p>In the category acl method, the code calls _createRoles. The job of this function is to create the role entries for the user object in question.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000000; font-weight: bold;">function</span> _createRoles<span style="color: #009900;">&#40;</span>Zend_Acl <span style="color: #000088;">$acl</span><span style="color: #339933;">,</span> User <span style="color: #000088;">$user</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
  <span style="color: #666666; font-style: italic;">//add groups first so user can inherit them</span>
  <span style="color: #b1b100;">foreach</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$user</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getGroups</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$group</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$acl</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addRole</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$group</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #000088;">$acl</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addRole</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$user</span><span style="color: #339933;">,</span> <span style="color: #000088;">$user</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getGroups</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>So by calling this method, the ACL gets filled with all the user&#8217;s roles. Similar to the Category class, the User and Group classes implements Zend_Acl_Role_Interface, so we can again just pass them to addRole without having to worry about it. You can later take a look at the code at the end of the post for a better idea of these classes.</p>
<p>The _setPrivileges method has a bit more code: its job is to look at the Privilege objects, and see if it needs to allow or deny access based on them</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000000; font-weight: bold;">function</span> _setPrivileges<span style="color: #009900;">&#40;</span><span style="color: #000088;">$acl</span><span style="color: #339933;">,</span> <span style="color: #000088;">$privileges</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
  <span style="color: #b1b100;">foreach</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$privileges</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$privilege</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$role</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$privilege</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getRole</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$resource</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$privilege</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getResource</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #666666; font-style: italic;">//the user's roles should already exist so we can</span>
    <span style="color: #666666; font-style: italic;">//ignore the ones that don't</span>
    <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #000088;">$acl</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">hasRole</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$role</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #b1b100;">continue</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$privilege</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getMode</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> <span style="color: #0000ff;">'allow'</span><span style="color: #009900;">&#41;</span>
      <span style="color: #000088;">$acl</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">allow</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$role</span><span style="color: #339933;">,</span> <span style="color: #000088;">$resource</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">else</span>
      <span style="color: #000088;">$acl</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">deny</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$role</span><span style="color: #339933;">,</span> <span style="color: #000088;">$resource</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>The Privilege class has methods for getting the relevant role and resource classes. Depending on the type, the role returned could be a User object or a Group object, and the resource could be a Category object or a File object. Since they all implement the interfaces for their types, they can be passed to Zend_Acl right away without having to do any additional logic.</p>
<h4>ACLs for files</h4>
<p>Now for the other public method in the class.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> createFileAcl<span style="color: #009900;">&#40;</span><span style="color: #990000;">File</span> <span style="color: #000088;">$file</span><span style="color: #339933;">,</span> User <span style="color: #000088;">$user</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
  <span style="color: #000088;">$acl</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">;</span>
  <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$file</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getCategoryId</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">!=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #666666; font-style: italic;">//if the file belongs to a category</span>
    <span style="color: #666666; font-style: italic;">//we need to build the whole category based acl</span>
    <span style="color: #000088;">$category</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$file</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getCategory</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$acl</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">createCategoryAcl</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$category</span><span style="color: #339933;">,</span> <span style="color: #000088;">$user</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$acl</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">add</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$file</span><span style="color: #339933;">,</span> <span style="color: #000088;">$category</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
  <span style="color: #b1b100;">else</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$acl</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Zend_Acl<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_createRoles<span style="color: #009900;">&#40;</span><span style="color: #000088;">$acl</span><span style="color: #339933;">,</span> <span style="color: #000088;">$user</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$acl</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">add</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$file</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #000088;">$privileges</span> <span style="color: #339933;">=</span> Privilege<span style="color: #339933;">::</span><span style="color: #004000;">findByFile</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$file</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_setPrivileges<span style="color: #009900;">&#40;</span><span style="color: #000088;">$acl</span><span style="color: #339933;">,</span> <span style="color: #000088;">$privileges</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #b1b100;">return</span> <span style="color: #000088;">$acl</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Since a File can belong to a category, we need to build the category ACL first. This can be easily done by calling the other method. In the case the File doesn&#8217;t belong to any category, it&#8217;s assumed to be on the top level, and it won&#8217;t inherit from anything. The file itself may also have some privileges of its own, so we fetch them and call the _setPrivileges method to process them.</p>
<h4>Final bunch of code</h4>
<p>We have one more ACL related class to look at: The plugin, or how to use the ACL factory in this case. This one is a bit longer, but it should be easy to understand as it&#8217;s pretty typical stuff:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #000000; font-weight: bold;">class</span> App_Plugin_AccessCheck <span style="color: #000000; font-weight: bold;">extends</span> Zend_Controller_Plugin_Abstract <span style="color: #009900;">&#123;</span>
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> preDispatch<span style="color: #009900;">&#40;</span>Zend_Controller_Request_Abstract <span style="color: #000088;">$request</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_accessValid<span style="color: #009900;">&#40;</span><span style="color: #000088;">$request</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #666666; font-style: italic;">//we throw an exception because the error controller</span>
      <span style="color: #666666; font-style: italic;">//can easily handle these</span>
      throw <span style="color: #000000; font-weight: bold;">new</span> App_Exception_AccessDenied<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Access denied'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000000; font-weight: bold;">function</span> _accessValid<span style="color: #009900;">&#40;</span>Zend_Controller_Request_Abstract <span style="color: #000088;">$request</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$user</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$request</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getParam</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'user'</span><span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">//the identityloader plugin should have added a user to</span>
    <span style="color: #666666; font-style: italic;">//the request and if it doesn't exist something is wrong</span>
    <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$user</span> <span style="color: #339933;">===</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span>
      <span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000088;">$params</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$request</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getParams</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$factory</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> App_AclFactory<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$resource</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">isset</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$params</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'file'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #000088;">$resource</span> <span style="color: #339933;">=</span> <span style="color: #990000;">File</span><span style="color: #339933;">::</span><span style="color: #004000;">findById</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$params</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'file'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      <span style="color: #000088;">$acl</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$factory</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">createFileAcl</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$resource</span><span style="color: #339933;">,</span> <span style="color: #000088;">$user</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #b1b100;">elseif</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">isset</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$params</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'category'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #000088;">$resource</span> <span style="color: #339933;">=</span> Category<span style="color: #339933;">::</span><span style="color: #004000;">findById</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$params</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'category'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      <span style="color: #000088;">$acl</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$factory</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">createCategoryAcl</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$resource</span><span style="color: #339933;">,</span> <span style="color: #000088;">$user</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #b1b100;">else</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #666666; font-style: italic;">//since we only care about access to files/categories,</span>
      <span style="color: #666666; font-style: italic;">//we'll return true if those aren't being accessed</span>
      <span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #b1b100;">return</span> <span style="color: #000088;">$acl</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">hasRole</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$user</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&amp;&amp;</span> <span style="color: #000088;">$acl</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">has</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$resource</span><span style="color: #009900;">&#41;</span>
      <span style="color: #339933;">&amp;&amp;</span> <span style="color: #000088;">$acl</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">isAllowed</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$user</span><span style="color: #339933;">,</span> <span style="color: #000088;">$resource</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>This is a plugin which will use the ACL to test access. As we mentioned earlier, by default users who haven&#8217;t logged in will automatically belong to a guests-group, so we have some other code that loads a user object to the request. We take this parameter in the accessValid method and test it against the ACL.</p>
<p>It also looks at some other parameters of the request to determine if the user is trying to access a file or a category, and acts accordingly.</p>
<h3>Summing up</h3>
<p>So this time we had a bit more complex usage of Zend_Acl. I didn&#8217;t write all about the models used, the SQL and all that to keep it at least on a some kind of manageable level for you, but fear not &#8211; all the code that I did not show is downloadable!</p>
<p><a href="http://codeutopia.net/filesystem.zip">Click here to download the filesystem project</a></p>
<p>I have commented certain parts of the code, but I must warn you that the code is probably quite far from optimal. It does not always use safe SQL, it does lots of extra queries in certain cases, it probably does not take care of possible erroneus conditions very well&#8230; but it does what it&#8217;s supposed to: it demonstrates how you can implement a more complex database-backed dynamic ACL system!&#8230; Oh, and it doesn&#8217;t have an admin page, so you&#8217;ll have to insert all the test data to the DB yourself</p>
<p>I don&#8217;t have any more chapters to this series planned out, but if you have any questions, or if some part of this wasn&#8217;t particularily clear, feel free to have your say in the comments! I might write a followup post to answer your questions if there are some more complex ones on anyones mind.</p>
<p>You may have noticed I didn&#8217;t cover Zend_Acl_Assertions. That&#8217;s because I couldn&#8217;t think of any use for them. =)</p>
<p><b>If you liked this series,</b> remember to <a href="http://codeutopia.net/blog/feed/">subscribe to the RSS feed</a> to get new posts automatically to your feed reader. </p>
<p><b>Further reading:</b><br />
In addition to this series on Zend_Acl, I&#8217;ve written the following posts which look a bit more on the theory side of access control and authentication:<br />
<a href="http://codeutopia.net/blog/2008/08/21/implementing-swappable-authentication-methods/">Implementing swappable authentication methods</a>, which explains how you could make your authentication method easily changeable between, for example, LDAP and a database.<br />
<a href="http://codeutopia.net/blog/2008/09/01/more-on-extensible-authenticationaccess-control/">Extensible authentication and access-control</a>, which talks more about creating a generic auth/acl system which can be easily extended so it works with different systems like database or LDAP</p>
]]></content:encoded>
			<wfw:commentRss>http://codeutopia.net/blog/2009/02/18/zend_acl-part-3-creating-and-storing-dynamic-acls/feed/</wfw:commentRss>
		<slash:comments>22</slash:comments>
		</item>
		<item>
		<title>Zend_Acl part 2: different roles and resources, more on access</title>
		<link>http://codeutopia.net/blog/2009/02/11/zend_acl-part-2-different-roles-and-resources-more-on-access/</link>
		<comments>http://codeutopia.net/blog/2009/02/11/zend_acl-part-2-different-roles-and-resources-more-on-access/#comments</comments>
		<pubDate>Wed, 11 Feb 2009 14:04:41 +0000</pubDate>
		<dc:creator>Jani Hartikainen</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Zend Framework]]></category>
		<category><![CDATA[Zend_Acl]]></category>

		<guid isPermaLink="false">http://codeutopia.net/blog/2009/02/11/zend_acl-part-2-different-roles-and-resources-more-on-access/</guid>
		<description><![CDATA[Applications often have different resources: For example, you might have pages, some user generated content like comments, and an admin area. You might also have files, or even real-life objects like a coffee machine.

In the context of Zend_Acl, access to resources is given to roles: A role might be a user's name, a group a user belongs to, or just roles, which have been assigned to a user from the admin panel.

Since Zend_Acl only defines an "abstract" role, resource and privilege, how do we deal with all of these using it?]]></description>
			<content:encoded><![CDATA[<p><b>First a quick announcement:</b> please let me know if the blog seems slow/sluggish. I have been experiencing some slowness, and I recently installed WP Super Cache which seems to have helped, but let me know if you encounter anything!</p>
<p><b>Now, the post:</b> This time, we&#8217;ll look at Zend_Acl a bit deeper after <a href="http://codeutopia.net/blog/2009/02/06/zend_acl-part-1-misconceptions-and-simple-acls/">the first part</a></p>
<p>Applications often have different resources: For example, you might have pages, some user generated content like comments, and an admin area. You might also have files, or even real-life objects like a coffee machine.</p>
<p>In the context of Zend_Acl, access to resources is given to roles: A role might be a user&#8217;s name, a group a user belongs to, or just roles, which have been assigned to a user from the admin panel.</p>
<p>Since Zend_Acl only defines an &#8220;abstract&#8221; role, resource and privilege, how do we deal with all of these using it? Read more to find out! I&#8217;ll also be addressing some more ways to deal with allowing and denying access.</p>
<p><span id="more-199"></span></p>
<h3>Dealing with individual users and usergroups</h3>
<p>Let&#8217;s say we want to be able to limit access to specific resources based on a user, or a usergroup. How do we accomplish this?</p>
<p>Since each role in Zend_Acl is identified by a string, we can come up with our own role-scheme: For users, the role id will be user-username, and for usergroups, the role id will be group-groupname.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$acl</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addRole</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> Zend_Acl_Role<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'user-john'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$acl</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addRole</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> Zend_Acl_Role<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'group-accounting'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>To check against the ACL in this kind of a scenario, we could have something like this:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">//We'll assume $user is some kind of a User object</span>
<span style="color: #000088;">$name</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$user</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getName</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$groups</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$user</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getGroups</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000088;">$roles</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'user-'</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$name</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">foreach</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$groups</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$g</span><span style="color: #009900;">&#41;</span> 
  <span style="color: #000088;">$roles</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'group-'</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$g</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getName</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #b1b100;">foreach</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$roles</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$r</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
  <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$acl</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">isAllowed</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$r</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'someresource'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'someprivilege'</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #666666; font-style: italic;">//allowed, do something.</span>
  <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<h3>Improving the user/group example by using Zend_Acl_Role_Interface</h3>
<p>In our above example with the strings, there&#8217;s a small problem: The strings.</p>
<p>We use user-something and group-something. What if we need to use it in some other place too? We may easily end up with code duplication, and it can become difficult to keep track of changes. In the case we add even more possible role types, it may become an even bigger mess if we introduce some more code which converts the new role type into a string!</p>
<p>Luckily, there&#8217;s a quite simple way out of this: by using Zend_Acl_Role_Interface with our objects.</p>
<p>As the user and groups in the example are classes, we could have them implement the role interface. That way we can simply pass the objects to the ACL instead of having to turn them into strings.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span> User implements Zend_Acl_Role_Interface <span style="color: #009900;">&#123;</span>
  <span style="color: #666666; font-style: italic;">//contents of the class here</span>
&nbsp;
  <span style="color: #666666; font-style: italic;">//this method is for the role interface:</span>
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> getRoleId<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">return</span> <span style="color: #0000ff;">'user-'</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_name<span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>So we add a method called getRoleId to the class, which returns an identifier for the object. We&#8217;ll also add that to our Group class, but with the difference that it returns an id with group- prefix. The earlier code which checks the ACL now looks like this:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">//We simply put the user and the groups in an array and be done with it</span>
<span style="color: #000088;">$roles</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$user</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">+</span> <span style="color: #000088;">$user</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getGroups</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">foreach</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$roles</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$r</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
  <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$acl</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">isAllowed</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$r</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'someresource'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'someprivilege'</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #666666; font-style: italic;">//allowed, do something.</span>
  <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<h3>Different resource types</h3>
<p>Just like roles, resources are strings. Resources can also be represented by objects which implement an interface &#8211; Zend_Acl_Resource_Interface. You can apply the code shown for roles in this.</p>
<p>Let&#8217;s take a quick example with files. Remember our plugin from <a href="http://codeutopia.net/blog/2009/02/06/zend_acl-part-1-misconceptions-and-simple-acls/">the first in the series?</a> Here&#8217;s it again:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span> My_Plugin_Acl <span style="color: #000000; font-weight: bold;">extends</span> Zend_Controller_Plugin_Abstract <span style="color: #009900;">&#123;</span>
  <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000088;">$_acl</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> __construct<span style="color: #009900;">&#40;</span>Zend_Acl <span style="color: #000088;">$acl</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_acl <span style="color: #339933;">=</span> <span style="color: #000088;">$acl</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> preDispatch<span style="color: #009900;">&#40;</span>Zend_Controller_Request_Abstract <span style="color: #000088;">$request</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #666666; font-style: italic;">//As in the earlier example, authed users will have the role user</span>
    <span style="color: #000088;">$role</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>Zend_Auth<span style="color: #339933;">::</span><span style="color: #004000;">getInstance</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">hasIdentity</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
          ? <span style="color: #0000ff;">'user'</span>
          <span style="color: #339933;">:</span> <span style="color: #0000ff;">'guest'</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">//For this example, we will use the controller as the resource:</span>
    <span style="color: #000088;">$resource</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$request</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getControllerName</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_acl<span style="color: #339933;">-&gt;</span><span style="color: #004000;">isAllowed</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$role</span><span style="color: #339933;">,</span> <span style="color: #000088;">$resource</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'view'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #666666; font-style: italic;">//If the user has no access we send him elsewhere by changing the request</span>
      <span style="color: #000088;">$request</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setModuleName</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'auth'</span><span style="color: #009900;">&#41;</span>
              <span style="color: #339933;">-&gt;</span><span style="color: #004000;">setControllerName</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'auth'</span><span style="color: #009900;">&#41;</span>
              <span style="color: #339933;">-&gt;</span><span style="color: #004000;">setActionName</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'login'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
  <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Let&#8217;s modify this so we can also use files with our ACL. </p>
<h4>Creating our resources</h4>
<p>We will first create a resource type for controllers, as it isn&#8217;t very simple to just create them on the fly for the sake of ACL testing, and then we will look at the File resource.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span> Resource_Controller implements Zend_Acl_Resource_Interface <span style="color: #009900;">&#123;</span>
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> __construct<span style="color: #009900;">&#40;</span><span style="color: #000088;">$id</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_id <span style="color: #339933;">=</span> <span style="color: #000088;">$id</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> getResourceId<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">return</span> <span style="color: #0000ff;">'controller-'</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_id<span style="color: #339933;">;</span> 
  <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>We create this resource class for the controllers because it would be a bit tricky to create the controller in the ACL just so we could check against it. This class will make the job easier on us.</p>
<p>Now, you probably should have a model class which represents a file, so you&#8217;ll just need to make the class implement the Zend_Acl_Resource_Interface</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span> <span style="color: #990000;">File</span> implements Zend_Acl_Resource_Interface <span style="color: #009900;">&#123;</span>
  <span style="color: #666666; font-style: italic;">/* we can have some methods related to the file model here */</span>
&nbsp;
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> getResourceId<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">return</span> <span style="color: #0000ff;">'file-'</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_name<span style="color: #339933;">;</span> 
  <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>So this assumes that your File model has a property $_name. The name is then used with the resource id.</p>
<h4>Modifying the plugin</h4>
<p>Now, we need to first modify the ACL plugin to use the controller resource. We&#8217;ll also modify it to use the earlier introduced User class as the role:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> preDispatch<span style="color: #009900;">&#40;</span>Zend_Controller_Request_Abstract <span style="color: #000088;">$request</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
  <span style="color: #666666; font-style: italic;">//Let's assume that the identity is a User object this time</span>
  <span style="color: #000088;">$user</span> <span style="color: #339933;">=</span> Zend_Auth<span style="color: #339933;">::</span><span style="color: #004000;">getInstance</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getIdentity</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #666666; font-style: italic;">//We need to create a new controller resource using the name:</span>
  <span style="color: #000088;">$resource</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Resource_Controller<span style="color: #009900;">&#40;</span><span style="color: #000088;">$request</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getControllerName</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_acl<span style="color: #339933;">-&gt;</span><span style="color: #004000;">isAllowed</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$user</span><span style="color: #339933;">,</span> <span style="color: #000088;">$resource</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'view'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #666666; font-style: italic;">//If the user has no access we send him elsewhere by changing the request</span>
    <span style="color: #000088;">$request</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setModuleName</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'auth'</span><span style="color: #009900;">&#41;</span>
            <span style="color: #339933;">-&gt;</span><span style="color: #004000;">setControllerName</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'auth'</span><span style="color: #009900;">&#41;</span>
            <span style="color: #339933;">-&gt;</span><span style="color: #004000;">setActionName</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'login'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Okay, so as the user object already implements the role interface, we can pass it to isAllowed. Same with the resource.</p>
<p><b>Important:</b> Remember that you need to use the Resource_Controller and User classes when creating the ACL! Otherwise this will not work!</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">//assume $someUser is an user object</span>
<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addRole</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$someUser</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">//assume $someController is a Resource_Controller object</span>
<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">add</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$someController</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">allow</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$someUser</span><span style="color: #339933;">,</span> <span style="color: #000088;">$someController</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'view'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>You may notice that this approach doesn&#8217;t work very well with static ACLs which are written in code. Next week, we will look at how to create dynamic ACLs, where this kind of approach works better! But for now, let&#8217;s continue.</p>
<h4>Creating a new plugin</h4>
<p>We could add the code for checking access to files to our earlier plugin, but if we create a separate plugin for it, it will be easier to reuse with other code. Let&#8217;s assume that we have some code which serves files to our users. When a user wants to download a file, the request will have the parameter file, which will contain the file&#8217;s name.</p>
<p>This will be a very similar plugin to the first:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span> My_Plugin_Acl_File <span style="color: #000000; font-weight: bold;">extends</span> Zend_Controller_Plugin_Abstract <span style="color: #009900;">&#123;</span>
  <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000088;">$_acl</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> __construct<span style="color: #009900;">&#40;</span>Zend_Acl <span style="color: #000088;">$acl</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_acl <span style="color: #339933;">=</span> <span style="color: #000088;">$acl</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> preDispatch<span style="color: #009900;">&#40;</span>Zend_Controller_Request_Abstract <span style="color: #000088;">$request</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #666666; font-style: italic;">//This too will use the user object from zend_auth</span>
    <span style="color: #000088;">$user</span> <span style="color: #339933;">=</span> Zend_Auth<span style="color: #339933;">::</span><span style="color: #004000;">getInstance</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getIdentity</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>    
&nbsp;
    <span style="color: #666666; font-style: italic;">//Instead of using the controllers name, we'll use the parameter</span>
    <span style="color: #000088;">$filename</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$request</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getParam</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'file'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">//If the request is not for a file we can just exit here without doing anything</span>
    <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">empty</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$filename</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
      <span style="color: #b1b100;">return</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000088;">$resource</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #990000;">File</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$resource</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setName</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$filename</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_acl<span style="color: #339933;">-&gt;</span><span style="color: #004000;">isAllowed</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$role</span><span style="color: #339933;">,</span> <span style="color: #000088;">$resource</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'view'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #000088;">$request</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setModuleName</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'auth'</span><span style="color: #009900;">&#41;</span>
              <span style="color: #339933;">-&gt;</span><span style="color: #004000;">setControllerName</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'auth'</span><span style="color: #009900;">&#41;</span>
              <span style="color: #339933;">-&gt;</span><span style="color: #004000;">setActionName</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'login'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
  <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>So this is basically the same as the earlier, but instead of checking for the controller, we check for a file.</p>
<p><b>Note:</b> instead of creating a new File(), it may be a good idea to use some class to fetch a file model, and to check if there even is a file with the required name.</p>
<h3>More on allowing and denying access</h3>
<p>As we have seen a few times, we can allow access to ACL resources with the allow method. However, there are some additional things I haven&#8217;t mentioned yet.</p>
<p>If you allow access to resource null, but with some privilege, it effectively means the role will have that privilege for <i>all</i> resources, unless explicitly denied:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">//myrole will get dosomething privilege on *all* resources</span>
<span style="color: #000088;">$acl</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">allow</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'myrole'</span><span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'dosomething'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Similarily, allowing on null privilege will give every privilege on a resource:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">//myrole will get all privileges on someresource (privilege defaults to null)</span>
<span style="color: #000088;">$acl</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">allow</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'myrole'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'someresource'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>The isAllowed method has similar features. If you don&#8217;t define the privilege while checking for access to a resource, it will require that the role has all privileges on the resource.</p>
<p>You can also give access to all resources and all privileges by leaving out both the resource and privilege when calling allow. Or, you can omit the role too, which will allow everyone access to everything &#8211; essentially requiring you to explicitly deny access if you don&#8217;t want certain roles accessing certain resources. This can be useful for creating blacklist-style behavior.</p>
<h3>In closing</h3>
<p>Even though we have gone through lots of ways to use Zend_Acl, there&#8217;s still a much to cover. Next week we will look at how to build &#8220;dynamic&#8221; ACLs from database or files, and we will again improve our ACL code and plugins.</p>
<p>You can <a href="http://codeutopia.net/blog/2009/02/18/zend_acl-part-3-creating-and-storing-dynamic-acls/">read the third post of the series here</a></p>
<p><b>Notes:</b> it may be a good idea to modify the plugins introduced in this post to actually check if there is an identity before proceeding. If there is no identity, it&#8217;s very likely that isAllow will throw an exception, or behave in an unexpected way. You also should check if the resource/role exist in the ACL, or you will likely get an exception.</p>
<p>Much of the examples in this post will work better when the ACL is created dynamically from a database. This is because models and such require database access to begin with, and creating them on the fly as seen in the examples may not be a good idea. However, it&#8217;s important to understand these things before moving on.</p>
<p>These things will be addressed in future posts in the series.</p>
]]></content:encoded>
			<wfw:commentRss>http://codeutopia.net/blog/2009/02/11/zend_acl-part-2-different-roles-and-resources-more-on-access/feed/</wfw:commentRss>
		<slash:comments>14</slash:comments>
		</item>
		<item>
		<title>Zend_Acl part 1: Misconceptions and simple ACLs</title>
		<link>http://codeutopia.net/blog/2009/02/06/zend_acl-part-1-misconceptions-and-simple-acls/</link>
		<comments>http://codeutopia.net/blog/2009/02/06/zend_acl-part-1-misconceptions-and-simple-acls/#comments</comments>
		<pubDate>Fri, 06 Feb 2009 05:35:18 +0000</pubDate>
		<dc:creator>Jani Hartikainen</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Zend Framework]]></category>
		<category><![CDATA[Zend_Acl]]></category>

		<guid isPermaLink="false">http://codeutopia.net/blog/2009/02/06/zend_acl-part-1-misconceptions-and-simple-acls/</guid>
		<description><![CDATA[I’m going to be writing a weekly series of posts on Zend_Acl. This first post will clear up some common misconceptions regarding Zend_Acl, introduce creating ACLs for simple applications, and give some examples on using the ACL in both non-Zend Framework and Zend Framework applications.]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m going to be writing a weekly series of posts on Zend_Acl. This first post will clear up some common misconceptions regarding Zend_Acl, introduce creating ACLs for simple applications, and give some examples on using the ACL in both non-Zend Framework and Zend Framework applications.</p>
<p>Later in the post series I&#8217;ll be talking about some more advanced ways of utilizing Zend_Acl, and topics such as database-backed ACLs.</p>
<p>A russian translation of this post is <a href="http://zendframework.ru/articles/zend_acl-misconceptions-and-simple-acls-part-1">available here</a>, courtesy of Rashad Surkin.</p>
<p><span id="more-198"></span></p>
<h3>Zend_Acl misconceptions</h3>
<p>Many people think that the ACL &#8220;resource&#8221; and &#8220;privilege&#8221; are the same as the controller and the action. This is not true!</p>
<p>The resource in Zend_Acl can be anything &#8211; a controller, a file, a model&#8230;</p>
<p>The privilege, just like the resource, can be anything related to the resource &#8211; for example, it could be an action if the resource is a controller, or it could be &#8220;read&#8221; or &#8220;write&#8221; if it&#8217;s a file or a model.</p>
<p>Later in the series, I&#8217;ll show some other ways of using acl resources, privileges and roles.</p>
<h3>Building a simple ACL</h3>
<p>As mentioned earlier, Zend_Acl constists of resources, privileges, and additionally, roles. Resources can be anything ranging from controllers to files. Privileges are different levels of access on the resource. Roles determine who can access a resource, and with what privileges. Roles can be users, user groups or anything you wish to associate such data with.</p>
<p>The very simplest way you can use Zend_Acl is <b>building the ACL in code</b>. This is often a useful approach for simple cases, where you only have a handful of resources and roles.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span> My_Acl <span style="color: #000000; font-weight: bold;">extends</span> Zend_Acl <span style="color: #009900;">&#123;</span>
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> __construct<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #666666; font-style: italic;">//Add a new role called &quot;guest&quot;</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addRole</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> Zend_Acl_Role<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'guest'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">//Add a role called user, which inherits from guest</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addRole</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> Zend_Acl_Role<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'user'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'guest'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">//Add a resource called page</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">add</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> Zend_Acl_Resource<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'page'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">//Add a resource called news, which inherits page</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">add</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> Zend_Acl_Resource<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'news'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'page'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">//Finally, we want to allow guests to view pages</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">allow</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'guest'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'page'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'view'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">//and users can comment news</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">allow</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'user'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'news'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'comment'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Now, by creating a new instance of My_Acl, we could perform simple checks against the acl. But what is allowed, and for who? </p>
<p>The guest role gets a privilege called view on the resource page. Since the user role inherits from guest, it also gets this privilege. The news resource inherits from page, so everyone who has privileges on the page resource, has the same privileges on news. In the last line of the constructor, we add a privilege comment for the user role on news. Only the user role has the privilege comment in the news resource &#8211; guest does not.</p>
<p><b>Note:</b> The names used in the example for the roles and resources are just <i>identifiers</i>. They could be 1, 2, or whatever, but it&#8217;s often easier to understand identifiers that are human-readable. However, when generating ACLs from databases or other source, it may not be necessary to have human-readable identifiers &#8211; the primary key from a database row will do just fine. Again, later in the series I&#8217;ll show an example of this.</p>
<h3>Using the simple ACL</h3>
<p>Using an ACL class is quite simple. You just call the method isAllowed with a role, resource and a privilege. The main difficulty is in determining <i>what is the role, resource and the privilege</i>.</p>
<p>How do we determine, what is the role? This can be a very simple if-clause: if there is a logged-in user, then the role is user, otherwise it is guest.</p>
<p>What about the resource? Depending on the application, this could be guessed from the file name included. For example, with our simple ACL, we could have a file called page.php and a file called news.php. page would check against the page resource, and news would check against the news resource.</p>
<p>And lastly, the privilege? When simply loading the page, you could use the view privilege. The code could later on check for other privileges: for example, the code could check if you have access to the comment privilege and display a comment box.</p>
<p>Here&#8217;s a really simple example:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$role</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'guest'</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">isset</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$_SESSION</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'auth'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
  <span style="color: #000088;">$role</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'user'</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000088;">$acl</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> My_Acl<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$acl</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">isAllowed</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$role</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'news'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'comment'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
  <span style="color: #666666; font-style: italic;">//Some code here to display a news box</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>As you can see, it&#8217;s quite easy to use the ACL even without Zend Framework, and you can easily speed up development of non-ZF apps by using the ACL component as it will save time when you won&#8217;t need to implement complex authorization checking code.</p>
<p>The above example may be very simple, but it shows you the basic way ACLs are used. </p>
<h3>Using the simple ACL in Zend Framework applications</h3>
<p>In Zend Framework applications, the resource and privilege can often be determined from the request object.</p>
<p>Typically, we would create a plugin which checks the acl for us:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span> My_Plugin_Acl <span style="color: #000000; font-weight: bold;">extends</span> Zend_Controller_Plugin_Abstract <span style="color: #009900;">&#123;</span>
  <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000088;">$_acl</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> __construct<span style="color: #009900;">&#40;</span>Zend_Acl <span style="color: #000088;">$acl</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_acl <span style="color: #339933;">=</span> <span style="color: #000088;">$acl</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> preDispatch<span style="color: #009900;">&#40;</span>Zend_Controller_Request_Abstract <span style="color: #000088;">$request</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #666666; font-style: italic;">//As in the earlier example, authed users will have the role user</span>
    <span style="color: #000088;">$role</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>Zend_Auth<span style="color: #339933;">::</span><span style="color: #004000;">getInstance</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">hasIdentity</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
          ? <span style="color: #0000ff;">'user'</span>
          <span style="color: #339933;">:</span> <span style="color: #0000ff;">'guest'</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">//For this example, we will use the controller as the resource:</span>
    <span style="color: #000088;">$resource</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$request</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getControllerName</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_acl<span style="color: #339933;">-&gt;</span><span style="color: #004000;">isAllowed</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$role</span><span style="color: #339933;">,</span> <span style="color: #000088;">$resource</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'view'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #666666; font-style: italic;">//If the user has no access we send him elsewhere by changing the request</span>
      <span style="color: #000088;">$request</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setModuleName</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'auth'</span><span style="color: #009900;">&#41;</span>
              <span style="color: #339933;">-&gt;</span><span style="color: #004000;">setControllerName</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'auth'</span><span style="color: #009900;">&#41;</span>
              <span style="color: #339933;">-&gt;</span><span style="color: #004000;">setActionName</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'login'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
  <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>We could have made the ACL static &#8211; instead of passing it in the constructor, we could have just created it in the preDispatch method. However, by passing it as a parameter, we make it easier to reuse this plugin. If we create a different ACL class, this plugin will still work with it without modifications.</p>
<p>Now that we have a plugin, we need to add it to the front controller in the boostrap:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$acl</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> My_Acl<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">//assuming $fc is the front controller</span>
<span style="color: #000088;">$fc</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">registerPlugin</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> My_Plugin_Acl<span style="color: #009900;">&#40;</span><span style="color: #000088;">$acl</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Now every request will be checked against the acl, and anyone without the view privilege would not get through.</p>
<p><b>Note:</b> if you use the My_Acl class as-is, you may get an infinite loop! The code in the plugin is sending the user to Auth module&#8217;s AuthController&#8217;s loginAction. It also uses the controller&#8217;s name as the resource ID&#8230; but My_Acl does not have a resource called auth! So if you want to make it work, you need to add a resource called auth to the ACL, and have it inherit from page, as we already gave guest the necessary privileges to page.</p>
<p>But how do we check for the comment privilege?</p>
<p>You could add some code to the controller, which checks for the required privilege, and then sets a variable in the view to true:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> someAction<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
  <span style="color: #000088;">$role</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>Zend_Auth<span style="color: #339933;">::</span><span style="color: #004000;">getInstance</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">hasIdentity</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
        ? <span style="color: #0000ff;">'user'</span>
        <span style="color: #339933;">:</span> <span style="color: #0000ff;">'guest'</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #666666; font-style: italic;">//assuming $this-&gt;_acl contains the acl</span>
  <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">view</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">canComment</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_acl<span style="color: #339933;">-&gt;</span><span style="color: #004000;">isAllowed</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$role</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'news'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'comment'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>It may be a good idea to modify the code so that you won&#8217;t need to duplicate the role check. For example, you could store the role in the auth identity, or you could create an action helper which is used to access the acl and contains all relevant data.</p>
<h3>In closing</h3>
<p>Armed with this knowledge, you should be able to get started with Zend_Acl!</p>
<p>Next week&#8217;s post is going to deal with some more advanced Zend_Acl usage scenarios: </p>
<ul>
<li>Dealing with different resource types, such as controllers and files</li>
<li>Dealing with different role types, such as users and user groups</li>
</ul>
<p><a href="http://codeutopia.net/blog/2009/02/11/zend_acl-part-2-different-roles-and-resources-more-on-access/">You can read the next post in the series here</a></p>
]]></content:encoded>
			<wfw:commentRss>http://codeutopia.net/blog/2009/02/06/zend_acl-part-1-misconceptions-and-simple-acls/feed/</wfw:commentRss>
		<slash:comments>33</slash:comments>
		</item>
	</channel>
</rss>
