[MANUAL] English:
[zend.git] / documentation / manual / en / module_specs / Zend_Acl.xml
blobf27b6b3c6aae49d6ae36510ec7b86feac2d79dd6
1 <?xml version="1.0" encoding="UTF-8"?>
2 <!-- Reviewed: no -->
3 <sect1 id="zend.acl.introduction">
4     <title>Introduction</title>
6     <para>
7         <classname>Zend_Acl</classname> provides a lightweight and flexible access control list
8         (<acronym>ACL</acronym>) implementation for privileges management. In general, an
9         application may utilize such <acronym>ACL</acronym>'s to control access to certain
10         protected objects by other requesting objects.
11     </para>
13     <para>
14         For the purposes of this documentation:
15     </para>
17     <itemizedlist>
18         <listitem>
19             <para>
20                 a <emphasis>resource</emphasis> is an object
21                 to which access is controlled.
22             </para>
23         </listitem>
25         <listitem>
26             <para>
27                 a <emphasis>role</emphasis> is an object
28                 that may request access to a Resource.
29             </para>
30         </listitem>
31     </itemizedlist>
33     <para>
34         Put simply, <emphasis>roles request access to resources</emphasis>. For
35         example, if a parking attendant requests access to a car, then the parking attendant is the
36         requesting role, and the car is the resource, since access to the car may not be granted to
37         everyone.
38     </para>
40     <para>
41         Through the specification and use of an <acronym>ACL</acronym>, an application may control
42         how roles are granted access to resources.
43     </para>
45     <sect2 id="zend.acl.introduction.resources">
46         <title>Resources</title>
48         <para>
49             Creating a resource in <classname>Zend_Acl</classname> is very simple.
50             <classname>Zend_Acl</classname> provides the resource,
51             <classname>Zend_Acl_Resource_Interface</classname>, to facilitate creating resources in
52             an application. A class need only implement this interface, which consists of a single
53             method, <methodname>getResourceId()</methodname>, for <classname>Zend_Acl</classname> to
54             recognize the object as a resource. Additionally,
55             <classname>Zend_Acl_Resource</classname> is provided by <classname>Zend_Acl</classname>
56             as a basic resource implementation for developers to extend as needed.
57         </para>
59         <para>
60             <classname>Zend_Acl</classname> provides a tree structure to which multiple resources
61             can be added. Since resources are stored in such a tree structure, they can be
62             organized from the general (toward the tree root) to the specific (toward the tree
63             leaves). Queries on a specific resource will automatically search the resource's
64             hierarchy for rules assigned to ancestor resources, allowing for simple inheritance of
65             rules. For example, if a default rule is to be applied to each building in a city, one
66             would simply assign the rule to the city, instead of assigning the same rule to each
67             building. Some buildings may require exceptions to such a rule, however, and this can
68             be achieved in <classname>Zend_Acl</classname> by assigning such exception rules to
69             each building that requires such an exception. A resource may inherit from only one
70             parent resource, though this parent resource can have its own parent resource, etc.
71         </para>
73         <para>
74             <classname>Zend_Acl</classname> also supports privileges on resources (e.g., "create",
75             "read", "update", "delete"), so the developer can assign rules that affect all
76             privileges or specific privileges on one or more resources.
77         </para>
78     </sect2>
80     <sect2 id="zend.acl.introduction.roles">
81         <title>Roles</title>
83         <para>
84             As with resources, creating a role is also very simple. All roles must implement
85             <classname>Zend_Acl_Role_Interface</classname>. This interface consists of a single
86             method, <methodname>getRoleId()</methodname>, Additionally,
87             <classname>Zend_Acl_Role</classname> is provided by <classname>Zend_Acl</classname> as
88             a basic role implementation for developers to extend as needed.
89         </para>
91         <para>
92             In <classname>Zend_Acl</classname>, a role may inherit from one or more roles. This is
93             to support inheritance of rules among roles. For example, a user role, such as "sally",
94             may belong to one or more parent roles, such as "editor" and "administrator". The
95             developer can assign rules to "editor" and "administrator" separately, and "sally"
96             would inherit such rules from both, without having to assign rules directly to "sally".
97         </para>
99         <para>
100             Though the ability to inherit from multiple roles is very useful, multiple inheritance
101             also introduces some degree of complexity. The following example illustrates the
102             ambiguity condition and how <classname>Zend_Acl</classname> solves it.
103         </para>
105         <example id="zend.acl.introduction.roles.example.multiple_inheritance">
106             <title>Multiple Inheritance among Roles</title>
108             <para>
109                 The following code defines three base roles - "guest",
110                 "member", and "admin" - from which other roles may
111                 inherit. Then, a role identified by "someUser" is established and
112                 inherits from the three other roles. The order in which these roles appear in the
113                 <varname>$parents</varname> array is important. When necessary,
114                 <classname>Zend_Acl</classname> searches for access rules defined not only for the
115                 queried role (herein, "someUser"), but also upon the roles from which
116                 the queried role inherits (herein, "guest", "member", and
117                 "admin"):
118             </para>
120             <programlisting language="php"><![CDATA[
121 $acl = new Zend_Acl();
123 $acl->addRole(new Zend_Acl_Role('guest'))
124     ->addRole(new Zend_Acl_Role('member'))
125     ->addRole(new Zend_Acl_Role('admin'));
127 $parents = array('guest', 'member', 'admin');
128 $acl->addRole(new Zend_Acl_Role('someUser'), $parents);
130 $acl->add(new Zend_Acl_Resource('someResource'));
132 $acl->deny('guest', 'someResource');
133 $acl->allow('member', 'someResource');
135 echo $acl->isAllowed('someUser', 'someResource') ? 'allowed' : 'denied';
136 ]]></programlisting>
138             <para>
139                 Since there is no rule specifically defined for the "someUser" role and
140                 "someResource", <classname>Zend_Acl</classname> must search for rules that may be
141                 defined for roles that "someUser" inherits. First, the "admin" role is visited, and
142                 there is no access rule defined for it. Next, the "member" role is visited, and
143                 <classname>Zend_Acl</classname> finds that there is a rule specifying that "member"
144                 is allowed access to "someResource".
145             </para>
147             <para>
148                 If <classname>Zend_Acl</classname> were to continue examining the rules defined for
149                 other parent roles, however, it would find that "guest" is denied access to
150                 "someResource". This fact introduces an ambiguity because now
151                 "someUser" is both denied and allowed access to "someResource", by reason of having
152                 inherited conflicting rules from different parent roles.
153             </para>
155             <para>
156                 <classname>Zend_Acl</classname> resolves this ambiguity by completing a query when
157                 it finds the first rule that is directly applicable to the query. In this case,
158                 since the "member" role is examined before the "guest" role, the example code would
159                 print "allowed".
160             </para>
161         </example>
163         <note>
164             <para>
165                 When specifying multiple parents for a role, keep in mind that the last parent
166                 listed is the first one searched for rules applicable to an authorization query.
167             </para>
168         </note>
169     </sect2>
171     <sect2 id="zend.acl.introduction.creating">
172         <title>Creating the Access Control List</title>
174         <para>
175             An Access Control List (<acronym>ACL</acronym>) can represent any set of physical or
176             virtual objects that you wish. For the purposes of demonstration, however, we will
177             create a basic Content Management System (<acronym>CMS</acronym>)
178             <acronym>ACL</acronym> that maintains several tiers of groups over a wide variety of
179             areas. To create a new <acronym>ACL</acronym> object, we instantiate the
180             <acronym>ACL</acronym> with no parameters:
181         </para>
183         <programlisting language="php"><![CDATA[
184 $acl = new Zend_Acl();
185 ]]></programlisting>
187         <note>
188             <para>
189                 Until a developer specifies an "allow" rule, <classname>Zend_Acl</classname> denies
190                 access to every privilege upon every resource by every role.
191             </para>
192         </note>
193     </sect2>
195     <sect2 id="zend.acl.introduction.role_registry">
196         <title>Registering Roles</title>
198         <para>
199             <acronym>CMS</acronym>'s will nearly always require a hierarchy of permissions to
200             determine the authoring capabilities of its users. There may be a 'Guest' group to
201             allow limited access for demonstrations, a 'Staff' group for the majority of
202             <acronym>CMS</acronym> users who perform most of the day-to-day operations, an 'Editor'
203             group for those responsible for publishing, reviewing, archiving and deleting content,
204             and finally an 'Administrator' group whose tasks may include all of those of the other
205             groups as well as maintenance of sensitive information, user management, back-end
206             configuration data, backup and export. This set of permissions can be represented in a
207             role registry, allowing each group to inherit privileges from 'parent' groups, as well
208             as providing distinct privileges for their unique group only. The permissions may be
209             expressed as follows:
210         </para>
212         <table id="zend.acl.introduction.role_registry.table.example_cms_access_controls">
213             <title>Access Controls for an Example CMS</title>
214             <tgroup cols="3">
215                 <thead>
216                     <row>
217                         <entry>Name</entry>
218                         <entry>Unique Permissions</entry>
219                         <entry>Inherit Permissions From</entry>
220                     </row>
221                 </thead>
223                 <tbody>
224                     <row>
225                         <entry>Guest</entry>
226                         <entry>View</entry>
227                         <entry>N/A</entry>
228                     </row>
230                     <row>
231                         <entry>Staff</entry>
232                         <entry>Edit, Submit, Revise</entry>
233                         <entry>Guest</entry>
234                     </row>
236                     <row>
237                         <entry>Editor</entry>
238                         <entry>Publish, Archive, Delete</entry>
239                         <entry>Staff</entry>
240                     </row>
242                     <row>
243                         <entry>Administrator</entry>
244                         <entry>(Granted all access)</entry>
245                         <entry>N/A</entry>
246                     </row>
247                 </tbody>
248             </tgroup>
249         </table>
251         <para>
252             For this example, <classname>Zend_Acl_Role</classname> is used, but any object that
253             implements <classname>Zend_Acl_Role_Interface</classname> is acceptable. These groups
254             can be added to the role registry as follows:
255         </para>
257         <programlisting language="php"><![CDATA[
258 $acl = new Zend_Acl();
260 // Add groups to the Role registry using Zend_Acl_Role
261 // Guest does not inherit access controls
262 $roleGuest = new Zend_Acl_Role('guest');
263 $acl->addRole($roleGuest);
265 // Staff inherits from guest
266 $acl->addRole(new Zend_Acl_Role('staff'), $roleGuest);
269 Alternatively, the above could be written:
270 $acl->addRole(new Zend_Acl_Role('staff'), 'guest');
273 // Editor inherits from staff
274 $acl->addRole(new Zend_Acl_Role('editor'), 'staff');
276 // Administrator does not inherit access controls
277 $acl->addRole(new Zend_Acl_Role('administrator'));
278 ]]></programlisting>
279     </sect2>
281     <sect2 id="zend.acl.introduction.defining">
282         <title>Defining Access Controls</title>
284         <para>
285             Now that the <acronym>ACL</acronym> contains the relevant roles, rules can be
286             established that define how resources may be accessed by roles. You may have noticed
287             that we have not defined any particular resources for this example, which is simplified
288             to illustrate that the rules apply to all resources. <classname>Zend_Acl</classname>
289             provides an implementation whereby rules need only be assigned from general to
290             specific, minimizing the number of rules needed, because resources and roles inherit
291             rules that are defined upon their ancestors.
292         </para>
294         <note>
295             <para>
296                 In general, <classname>Zend_Acl</classname> obeys a given rule if and only if a
297                 more specific rule does not apply.
298             </para>
299         </note>
301         <para>
302             Consequently, we can define a reasonably complex set of rules with a minimum amount of
303             code. To apply the base permissions as defined above:
304         </para>
306         <programlisting language="php"><![CDATA[
307 $acl = new Zend_Acl();
309 $roleGuest = new Zend_Acl_Role('guest');
310 $acl->addRole($roleGuest);
311 $acl->addRole(new Zend_Acl_Role('staff'), $roleGuest);
312 $acl->addRole(new Zend_Acl_Role('editor'), 'staff');
313 $acl->addRole(new Zend_Acl_Role('administrator'));
315 // Guest may only view content
316 $acl->allow($roleGuest, null, 'view');
319 Alternatively, the above could be written:
320 $acl->allow('guest', null, 'view');
321 //*/
323 // Staff inherits view privilege from guest, but also needs additional
324 // privileges
325 $acl->allow('staff', null, array('edit', 'submit', 'revise'));
327 // Editor inherits view, edit, submit, and revise privileges from
328 // staff, but also needs additional privileges
329 $acl->allow('editor', null, array('publish', 'archive', 'delete'));
331 // Administrator inherits nothing, but is allowed all privileges
332 $acl->allow('administrator');
333 ]]></programlisting>
335         <para>
336             The <constant>NULL</constant> values in the above <methodname>allow()</methodname> calls
337             are used to indicate that the allow rules apply to all resources.
338         </para>
339     </sect2>
341     <sect2 id="zend.acl.introduction.querying">
342         <title>Querying an ACL</title>
344         <para>
345             We now have a flexible <acronym>ACL</acronym> that can be used to determine whether
346             requesters have permission to perform functions throughout the web application.
347             Performing queries is quite simple using the <methodname>isAllowed()</methodname>
348             method:
349         </para>
351         <programlisting language="php"><![CDATA[
352 echo $acl->isAllowed('guest', null, 'view') ?
353      "allowed" : "denied";
354 // allowed
356 echo $acl->isAllowed('staff', null, 'publish') ?
357      "allowed" : "denied";
358 // denied
360 echo $acl->isAllowed('staff', null, 'revise') ?
361      "allowed" : "denied";
362 // allowed
364 echo $acl->isAllowed('editor', null, 'view') ?
365      "allowed" : "denied";
366 // allowed because of inheritance from guest
368 echo $acl->isAllowed('editor', null, 'update') ?
369      "allowed" : "denied";
370 // denied because no allow rule for 'update'
372 echo $acl->isAllowed('administrator', null, 'view') ?
373      "allowed" : "denied";
374 // allowed because administrator is allowed all privileges
376 echo $acl->isAllowed('administrator') ?
377      "allowed" : "denied";
378 // allowed because administrator is allowed all privileges
380 echo $acl->isAllowed('administrator', null, 'update') ?
381      "allowed" : "denied";
382 // allowed because administrator is allowed all privileges
383 ]]></programlisting>
384     </sect2>
385 </sect1>
386 <!--
387 vim:se ts=4 sw=4 et: