<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <title>Passing Curiosity: Posts tagged authorisation</title>
    <link href="https://passingcuriosity.com/tags/authorisation/authorisation.xml" rel="self" />
    <link href="https://passingcuriosity.com" />
    <id>https://passingcuriosity.com/tags/authorisation/authorisation.xml</id>
    <author>
        <name>Thomas Sutton</name>
        
        <email>me@thomas-sutton.id.au</email>
        
    </author>
    <updated>2009-03-30T00:00:00Z</updated>
    <entry>
    <title>Authorising user actions in SPIP</title>
    <link href="https://passingcuriosity.com/2009/authorising-user-actions-in-spip/" />
    <id>https://passingcuriosity.com/2009/authorising-user-actions-in-spip/</id>
    <published>2009-03-30T00:00:00Z</published>
    <updated>2009-03-30T00:00:00Z</updated>
    <summary type="html"><![CDATA[<p>One of the APIs that many SPIP plug-ins will need to use is <code>autoriser()</code> –
the function which determines whether a user should be permitted to perform a
given operation. As I couldn’t find any document on using this function, I’ll
provide a few notes below.</p>
<p>Checking that a user if authorised to perform an action is a little more
haphazard than I’d like in SPIP (“No authorisation check? No worries!” is not
a particularly comforting approach), but it seems to get the job done even if
it does depend on more developer discipline than seems warranted. Checking
that a user is “authorised” to perform an action is done by calling the
<a href="http://doc.spip.org/@autoriser"><code>autoriser()</code></a> function with arguments to
describe the operation. If it returns <code>true</code> then the operation is authorised,
it not, then it isn’t.</p>
<p>Like most of SPIP’s core functions, <code>autoriser</code> is implemented in a way that
makes it easy to override and extend its functions: rather than make any
decision itself, it simply delegates the decision to the first function it
finds that can decide for that type of operation and object (or object, or
operation).</p>
<p>First, though, lets look at <code>autoriser</code>’s arguments:</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode php"><code class="sourceCode php"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">function</span> autoriser_dist(<span class="va">$faire</span><span class="ot">,</span> <span class="va">$type</span><span class="op">=</span><span class="st">''</span><span class="ot">,</span> <span class="va">$id</span><span class="op">=</span><span class="dv">0</span><span class="ot">,</span> <span class="va">$qui</span> <span class="op">=</span> <span class="kw">NULL</span><span class="ot">,</span> <span class="va">$opt</span> <span class="op">=</span> <span class="kw">NULL</span>)</span></code></pre></div>
<p>This first (and only required) argument is <code>$faire</code> (French, I’m told, for “to
do”) which takes a string: the name of the operation. The second argument
<code>$type</code> is another string: the type of object being operated on; and the third
is an integer: the ID of the particular object, if there is one. The fourth,
<code>$qui</code> (“who”) is an array of details of the current user; and the fifth, I
assume, is an array of optional values if the previous four are not enough to
make some decisions).</p>
<p>Only the first of these – the operation being performed – is required and
only the first should need to be specified in the vast majority of situations
(it’ll work out the user by itself and there are many operations without a
<code>$type</code> or an <code>$id</code>). Once it’s been called, <code>autoriser</code> uses these values to
look for a function that can make a decision for the given type and
operations.</p>
<p>You can see the code of <a href="http://trac.rezo.net/trac/spip/browser/spip/ecrire/inc/autoriser.php#L87"><code>/ecrire/inc/autoriser.php</code> (around line
87)</a>
for the particular functions that it will call, but the full list of
alternatives that ‘’autoriser($faire, $type, $id, $qui, $opts)’’ is (in order
of preference):</p>
<ol type="1">
<li><code>autoriser_$type_$faire()</code></li>
<li><code>autoriser_$type()</code></li>
<li><code>autoriser_$faire()</code></li>
<li><code>autoriser_default()</code></li>
<li><code>autoriser_$type_$faire_dist()</code></li>
<li><code>autoriser_$type_dist()</code></li>
<li><code>autoriser_$faire_dist()</code></li>
<li><code>autoriser_default_dist()</code></li>
</ol>
<p>Adding authorisation checks to your plug-in is easy: just implement one of
these checking functions (in a file that’ll be included by a <code>&lt;fonctons&gt;</code>
entry in your <code>plugin.xml</code> file is probably best) and then get <code>autoriser</code> to
call it when appropriate.</p>
<p>From <code>aplugin_fonctions.php</code> or some other file:</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode php"><code class="sourceCode php"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="co">/**</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a><span class="co"> * Perform authorisation checks for &quot;elephant&quot; objects.</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a><span class="co"> */</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a><span class="kw">function</span> autoriser_elephant(<span class="va">$faire</span><span class="ot">,</span> <span class="va">$type</span><span class="op">=</span><span class="st">'elephant'</span><span class="ot">,</span> <span class="va">$id</span><span class="op">=</span><span class="dv">0</span><span class="ot">,</span> <span class="va">$qui</span><span class="op">=</span><span class="kw">NULL</span><span class="ot">,</span> <span class="va">$opt</span><span class="op">=</span><span class="kw">NULL</span>) {</span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a>   <span class="cf">if</span> ( <span class="st">'0minirezo'</span> <span class="op">==</span> <span class="va">$qui</span>[<span class="st">'statut'</span>] ) {</span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a>       <span class="cf">return</span> <span class="kw">true</span><span class="ot">;</span></span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a>   }</span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a>   <span class="cf">return</span> <span class="kw">false</span><span class="ot">;</span></span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a>}</span></code></pre></div>
<p>With this code in place, only administrators will be able to perform actions
(or, strictly speaking, perform actions checked with the <code>autoriser</code> function)
on <em>elephant</em> objects. Any call specifying <code>$type='elephant'</code> will use the
above function to determine if the operation should proceed.</p>
<p>In <code>exec/anaction.php</code> or similar, we might use code like this:</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode php"><code class="sourceCode php"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="cf">if</span> ( autoriser(<span class="st">'kill'</span><span class="ot">,</span> <span class="st">'elephant'</span><span class="ot">,</span> <span class="va">$id_elephant</span>) ) {</span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>   launch_missiles_at(<span class="st">'elephant'</span><span class="ot">,</span> <span class="va">$id_elephant</span>)<span class="ot">;</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a>} <span class="cf">else</span> {</span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a>   <span class="kw">echo</span> <span class="cn">_T</span>(<span class="st">'aplugin:cannot_shoot_elephant'</span>)<span class="ot">,</span> <span class="cn">_T</span>(<span class="st">'aplugin:permission_denied'</span>)<span class="ot">;</span></span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a>}</span></code></pre></div>
<p>Which will try the following functions, in order, to decide whether or not to
<code>launch_missiles_at()</code> our poor elephant:</p>
<ol type="1">
<li><code>autoriser_elephant_kill()</code></li>
<li><code>autoriser_elephant()</code></li>
<li><code>autoriser_kill()</code></li>
<li><code>autoriser_default()</code></li>
<li><code>autoriser_elephant_kill_dist()</code></li>
<li><code>autoriser_elephant_dist()</code></li>
<li><code>autoriser_kill_dist()</code></li>
<li><code>autoriser_default_dist()</code></li>
</ol>
<p>That’s about all there is to it. Of course, there’s a lot more you can do to
make your authorisation decisions: per-user and per-object configurations you
might like implement (similar to the way SPIP allows us to restrict
administrators and editors “to a section”), time-based or geographic
restrictions (editing during working hours only, or from an IP address in
Africa), or restricting access to those within your organisation’s network.</p>
<p>The world of authorisation is your oyster!</p>]]></summary>
</entry>
<entry>
    <title>Hierarchical Rights in Drupal</title>
    <link href="https://passingcuriosity.com/2009/hierarchical-rights-in-drupal/" />
    <id>https://passingcuriosity.com/2009/hierarchical-rights-in-drupal/</id>
    <published>2009-03-05T00:00:00Z</published>
    <updated>2009-03-05T00:00:00Z</updated>
    <summary type="html"><![CDATA[<p>I discovered a blog post called <a href="http://www.garfieldtech.com/blog/hierarchical-acls">More flexible rights
management?</a> by Larry
Garfield at some point over the last three days (that being how long Safari
has been running). Having a few thoughts about it and a pressing need to write
a blog post for today, I’ll get them down “on paper” and call it a job done.
Larry references Markus Wolff and his description (in a post called <a href="http://blog.wolff-hamburg.de/archives/25-A-pragmatic-approach-to-rights-management.html">A
pragmatic approach to rights
management</a>)
of an permissions management system. Markus’ system (he in turn references a
former boss, but I shall ascribe it to him anyway) looks like this:</p>
<ul>
<li><p>Rights are denoted by dot-separated, reverse hierarchical names (e.g:
‘’Application.Component.Subcomponent.Right’’).</p></li>
<li><p>Permissions can specify rights with wild-cards (e.g. ’’Application.*’’).</p></li>
<li><p>Rights can also be negated (e.g. ’‘-Application.Shutdown’’).</p></li>
</ul>
<p>Thus a user who can do anything <em>except</em> shut the application down might have
a permissions list like:</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode php"><code class="sourceCode php"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a>    <span class="va">$user</span>-&gt;perm <span class="op">=</span> <span class="dt">array</span>(<span class="st">&quot;Application.*&quot;</span><span class="ot">,</span> <span class="st">&quot;-Application.Shutdown&quot;</span>)<span class="ot">;</span></span></code></pre></div>
<p>As such schemes go this one is adequate, but as a replacement for Drupal’s
current system it’s not that crash hot. In fact, all it brings to the table is
a little more convenience: it is no more expressive than the current system.
Now convenience is a pretty cool thing and the Drupal permissions system could
really, <em>really</em>, <strong>really</strong> do with some more convenience, but if there’s to
be a new system, I’d much rather see something genuinely more powerful.</p>
<p>My suggestion is this: rather than have a single hierarchy of rights which
jumbles variously the rights, the objects, and the implementers of both into
one great big messy tree, why not have rights permissions be a tuple of a
right and an object specifier. This will result in two smaller, less
complicated trees the paths of which can be clearly and easily interpreted.
With this scheme, many of the permissions seen on most Drupal sites would be
replaced with a much smaller collection of rights and a similarly small number
of object specifiers.</p>
<p>The current system includes five permissions (create, delete own, delete any,
edit own, and edit any) for each and every content type. In my suggested
system, these would be replaces with just those five rights which would, when
granted, be applied to particular object specifiers. The “edit any story
content” permission might become “(Core.EditAny, Node.Story)”, for example.</p>
<p>One advantage such a scheme would have is in breaking down some of the super
permissions like the various “administer …” permissions. Rather than
creating large numbers of new permissions, it would be possible to grant
“Core.Administer” right to a particular group of settings. Again, this will
reduce the large number of permissions (approaching one per module) and
replace them with a single reusable permission applied to a range of domains.
The “administer menu” permission might be replaced with “(Core.Administer,
Menu)” or, more excitingly, with “(Core.Administer, Menu.PrimaryLinks)”.</p>
<p>Having written a little about this, I’m not entirely sure that it’s a good
idea or a good fit for Drupal. Such a flexible system would certainly have a
smaller UI (in terms of screen real-estate) than the current approach, but it
would be more complex. It would make core more powerful, but it wouldn’t
obviate the need for third-party modules to augment or replace the system when
it can’t implement a required policy. In fact it’s a stupid idea, so forget
about it and lets all just pretend that I didn’t say anything.</p>]]></summary>
</entry>

</feed>
