<?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>muhuk.com &#187; authentication</title>
	<atom:link href="http://www.muhuk.com/tag/authentication/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.muhuk.com</link>
	<description>know thyself</description>
	<lastBuildDate>Thu, 29 Dec 2011 05:05:14 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Django Permission System</title>
		<link>http://www.muhuk.com/2009/05/django-permission-system/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=django-permission-system</link>
		<comments>http://www.muhuk.com/2009/05/django-permission-system/#comments</comments>
		<pubDate>Thu, 14 May 2009 13:40:22 +0000</pubDate>
		<dc:creator>Atamert Ölçgen</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[authentication]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[object oriented]]></category>

		<guid isPermaLink="false">http://www.muhuk.com/?p=210</guid>
		<description><![CDATA[Permission system that comes with django.contrib.auth allows you to create and assign permissions for your models. Permissions can be assigned to users or groups. A user has permissions directly assigned to her as well as permissions inherited from her groups. Permission scope is always model classess (as opposed to individual model instances). That means if [...]<div><a class="addthis_button" href="//addthis.com/bookmark.php?v=250" addthis:url='http://www.muhuk.com/2009/05/django-permission-system/' addthis:title='Django Permission System '><img src="//cache.addthis.com/cachefly/static/btn/v2/lg-share-en.gif" width="125" height="16" alt="Bookmark and Share" style="border:0"/></a></div>]]></description>
			<content:encoded><![CDATA[<p>Permission system that comes with <code>django.contrib.auth</code> allows you to create and assign permissions for your models. <a href="http://docs.djangoproject.com/en/dev/topics/auth/#permissions">Permissions</a> can be assigned to <a href="http://docs.djangoproject.com/en/dev/topics/auth/#users">users</a> or <a href="http://docs.djangoproject.com/en/dev/topics/auth/#groups">groups</a>. A user has permissions directly assigned to her as well as permissions inherited from her groups. Permission scope is always model classess (as opposed to individual model instances). That means if you are just checking <code>FooModel</code>.<code>can_do_bar</code> permission on a user; that user can <code>do bar</code> on all <code>FooModel</code> instances.</p>

<p>This built-in permission system is simple; as in you shouldn&#8217;t expect complex authorization schemes to be implemented easily. It is mainly used by <code>django.contrib.admin</code> and you can use it without any hassle for your very simple authorization requirements. Beauty of this permission system is it&#8217;s simplicity. Here are a few strong points:</p>

<ul>
<li>All your models get <strong>add</strong>, <strong>change</strong> and <strong>delete</strong> permissions created automatically.<sup>1</sup> These three are all you need for most of your models.</li>
<li><code>Admin</code> uses permissions internally. But more importantly permissions can be granted/revoked dynamically via admin.</li>
<li>Simple design encourages you to keep authorization scheme clean.<sup>2</sup></li>
</ul>

<p>The last point is very important; permissions shouldn&#8217;t leak into business logic. If you have a project that goes beyond a CMS, you probably have <em>business objects</em>. Business objects might have quite complex states and typically interact with each other in more than straightforward ways. On the other hand models in CMS style projects have simple states that are independent (of other models). Take a blog post; it is either published or not and its author is simply a <code>ForeignKey</code> to <code>User</code>s. If you depend heavily upon permissions for complex state transitions of your models you will soon find yourself in a dead end.</p>

<h3>Permissions in Fixtures</h3>

<p>One problem, and it&#8217;s a big problem, I&#8217;ve had with permissions is that; <strong>you can&#8217;t store permissions in <a href="http://docs.djangoproject.com/en/dev/topics/serialization/">fixtures</a></strong>. Here is what happens:</p>

<ol>
<li>Relationships are stored in fixtures as primary keys.</li>
<li>Permission are created by the framework programmatically in a specific order.</li>
<li>When you add/delete a new model or add/delete a custom permission this order changes.</li>
<li>Therefore primary keys of permissions change.</li>
<li>As a result permission data in your fixture are invalid.</li>
</ol>

<p>I&#8217;m a big fan of fixtures. More often than not you have some models that will be used as definitions (they&#8217;re partially fixed data) or you want to kickstart your project with placeholder data. It&#8217;s quite easy in Django. After creating your models, launch admin and create your data. Then simply <code>dumpdata</code>, maybe post-process a little bit and you have your <code>initial_data</code>! Not so easy if you have permissions in that basket.</p>

<p>Best solution I can come up with now is to <a href="http://docs.djangoproject.com/en/dev/topics/signals/#listening-to-signals">hook a <code>post_syncdb</code> function</a> and add your permissions programmatically.</p>

<h3>Authorization</h3>

<p>Basic usage of permissions is to check if a user has a certain <code>Permission</code> and branch accordingly:</p>

<pre>@login_required
def some_view(request):
    user = request.user
    <b>if user.has_perm('foo.bar_baz'):
        <i># go on and bar that baz</i>
    else:
        <i># display an error message</i></b>
    # ...rest of the view
</pre>

<p>When you need to combine conditions, it is a good idea to abstract authorization check in a function:</p>

<pre>class Foo(models.Model):
    # stuff that goes into a model

    <b>def can_bar(self, user):
        return user.has_perm('app.bar_foo') and user.baz >= self.baz</b></pre>

<p>You can combine this with techniques explained in <a href="http://www.b-list.org/weblog/2008/nov/09/dynamic-forms/">here</a> and <a href="http://www.b-list.org/weblog/2008/dec/24/admin/">here</a> to achieve column level permissions.</p>

<p>Row level permissions are cooking as well. There is a branch for <a href="http://code.djangoproject.com/wiki/RowLevelPermissions">per object permissions</a>. You can checkout this branch from subversion with the following command:</p>

<pre><code>svn co http://code.djangoproject.com/svn/django/branches/per-object-permissions
</code></pre>

<h3>Generic Permissions</h3>

<p>Let&#8217;s define permissions problem in a more generic way. A permission determines if:</p>

<ul>
<li>An <strong>actor</strong> can</li>
<li>Perform an <strong>action</strong></li>
<li>On an <strong>object</strong></li>
<li>Depending on arbitrary number of runtime <strong>conditions</strong> [optional]</li>
</ul>

<p>In our little implementation actors will be <code>auth.User</code> instances and objects, naturally, models. Actions will simply be keys of string type. Because of the possibility that our permission can have conditions, it should be a callable. Then we will have all the power Python/Django has.</p>

<p>Let&#8217;s place our permissions on our models:</p>

<pre><span style="color:#555555">   1 </span><span style="color:#000000; font-weight:bold">class</span> <span style="color:#010181">FooPermissions</span><span style="color:#000000">(</span>PermissionMixin<span style="color:#000000">):</span>
<span style="color:#555555">   2 </span>    <span style="color:#000000; font-weight:bold">def</span> <span style="color:#010181">__warg</span><span style="color:#000000">(</span>self<span style="color:#000000">):</span>
<span style="color:#555555">   3 </span>        <span style="color:#000000; font-weight:bold">return</span> <span style="color:#830000">max</span><span style="color:#000000">(</span>self<span style="color:#000000">.</span>quux <span style="color:#000000">-</span> self<span style="color:#000000">.</span>parent<span style="color:#000000">.</span>quux<span style="color:#000000">,</span> <span style="color:#2928ff">1</span><span style="color:#000000">)</span>
<span style="color:#555555">   4 </span>
<span style="color:#555555">   5 </span>    <span style="color:#000000">&#64;</span><span style="color:#830000">staticmethod</span>
<span style="color:#555555">   6 </span>    <span style="color:#000000; font-weight:bold">def</span> <span style="color:#010181">allows_bar_for</span><span style="color:#000000">(</span>actor<span style="color:#000000">):</span>
<span style="color:#555555">   7 </span>        <span style="color:#000000; font-weight:bold">return</span> actor<span style="color:#000000">.</span><span style="color:#010181">has_perm</span><span style="color:#000000">(</span><span style="color:#ff0000">'app.bar_foo'</span><span style="color:#000000">)</span> <span style="color:#000000; font-weight:bold">and</span> actor<span style="color:#000000">.</span>status <span style="color:#000000">==</span> <span style="color:#ff0000">'barrable'</span>
<span style="color:#555555">   8 </span>
<span style="color:#555555">   9 </span>    <span style="color:#000000; font-weight:bold">def</span> <span style="color:#010181">allows_baz_for</span><span style="color:#000000">(</span>self<span style="color:#000000">,</span> actor<span style="color:#000000">):</span>
<span style="color:#555555">  10 </span>        <span style="color:#000000; font-weight:bold">if</span> self<span style="color:#000000">.</span>qux_set<span style="color:#000000">.</span><span style="color:#010181">count</span><span style="color:#000000">() &gt;</span> <span style="color:#2928ff">10</span><span style="color:#000000">:</span>
<span style="color:#555555">  11 </span>            <span style="color:#000000; font-weight:bold">return True</span>
<span style="color:#555555">  12 </span>        <span style="color:#000000; font-weight:bold">else</span><span style="color:#000000">:</span>
<span style="color:#555555">  13 </span>            <span style="color:#000000; font-weight:bold">return</span> self<span style="color:#000000">.</span><span style="color:#010181">__warg</span><span style="color:#000000">() &gt;</span> <span style="color:#2928ff">5</span> <span style="color:#000000; font-weight:bold">or</span> actor<span style="color:#000000">.</span>is_staff
<span style="color:#555555">  14 </span>
<span style="color:#555555">  15 </span>
<span style="color:#555555">  16 </span><span style="color:#000000; font-weight:bold">class</span> <span style="color:#010181">Foo</span><span style="color:#000000">(</span>models<span style="color:#000000">.</span>Model<span style="color:#000000">,</span> FooPermissions<span style="color:#000000">):</span>
<span style="color:#555555">  17 </span>    <span style="color:#838183; font-style:italic"># fields, managers, etc...</span>
</pre>

<p>First we created a permissions mixin, subclassing a <code>PermissionMixin</code> I&#8217;ll show it to you in a minute, and mixed it with our model definition. This way we keep permissions seperate at the source level. Also, for instance <code>__warg</code> method will not be <a href="http://www.python.org/doc/current/tutorial/classes.html#private-variables">accessible</a> from our model. You can do anything inside your permissions class, you can even have side effects if you like. all you have to do is to follow a naming convention for your permission methods. Here is the <code>PermissionMixin</code> class:</p>

<pre><span style="color:#555555">   1 </span><span style="color:#000000; font-weight:bold">from</span> django<span style="color:#000000">.</span>contrib<span style="color:#000000">.</span>auth<span style="color:#000000">.</span>models <span style="color:#000000; font-weight:bold">import</span> User
<span style="color:#555555">   2 </span>
<span style="color:#555555">   3 </span>
<span style="color:#555555">   4 </span><span style="color:#000000; font-weight:bold">class</span> <span style="color:#010181">PermissionError</span><span style="color:#000000">(</span><span style="color:#000000; font-weight:bold">StandardError</span><span style="color:#000000">):</span>
<span style="color:#555555">   5 </span>    <span style="color:#000000; font-weight:bold">pass</span>
<span style="color:#555555">   6 </span>
<span style="color:#555555">   7 </span>
<span style="color:#555555">   8 </span><span style="color:#000000; font-weight:bold">class</span> <span style="color:#010181">PermissionMixin</span><span style="color:#000000">(</span><span style="color:#830000">object</span><span style="color:#000000">):</span>
<span style="color:#555555">   9 </span>    <span style="color:#000000; font-weight:bold">def</span> <span style="color:#010181">attempt</span><span style="color:#000000">(</span>self<span style="color:#000000">,</span> action<span style="color:#000000">,</span> actor<span style="color:#000000">,</span> msg<span style="color:#000000">=</span><span style="color:#000000; font-weight:bold">None</span><span style="color:#000000">):</span>
<span style="color:#555555">  10 </span>        <span style="color:#000000; font-weight:bold">return</span> PermissionMixin<span style="color:#000000">.</span><span style="color:#010181">_attempt</span><span style="color:#000000">(</span>self<span style="color:#000000">,</span> action<span style="color:#000000">,</span> actor<span style="color:#000000">,</span> msg<span style="color:#000000">=</span><span style="color:#000000; font-weight:bold">None</span><span style="color:#000000">)</span>
<span style="color:#555555">  11 </span>
<span style="color:#555555">  12 </span>    <span style="color:#000000">&#64;</span><span style="color:#830000">classmethod</span>
<span style="color:#555555">  13 </span>    <span style="color:#000000; font-weight:bold">def</span> <span style="color:#010181">cls_attempt</span><span style="color:#000000">(</span>cls<span style="color:#000000">,</span> action<span style="color:#000000">,</span> actor<span style="color:#000000">,</span> msg<span style="color:#000000">=</span><span style="color:#000000; font-weight:bold">None</span><span style="color:#000000">):</span>
<span style="color:#555555">  14 </span>        <span style="color:#000000; font-weight:bold">return</span> PermissionMixin<span style="color:#000000">.</span><span style="color:#010181">_attempt</span><span style="color:#000000">(</span>cls<span style="color:#000000">,</span> action<span style="color:#000000">,</span> actor<span style="color:#000000">,</span> msg<span style="color:#000000">=</span><span style="color:#000000; font-weight:bold">None</span><span style="color:#000000">)</span>
<span style="color:#555555">  15 </span>
<span style="color:#555555">  16 </span>    <span style="color:#000000">&#64;</span><span style="color:#830000">staticmethod</span>
<span style="color:#555555">  17 </span>    <span style="color:#000000; font-weight:bold">def</span> <span style="color:#010181">_attempt</span><span style="color:#000000">(</span>obj<span style="color:#000000">,</span> action<span style="color:#000000">,</span> actor<span style="color:#000000">,</span> msg<span style="color:#000000">):</span>
<span style="color:#555555">  18 </span>        <span style="color:#000000; font-weight:bold">if</span> actor<span style="color:#000000">.</span>__class__ <span style="color:#000000">!=</span> User <span style="color:#000000; font-weight:bold">or not</span> <span style="color:#830000">isinstance</span><span style="color:#000000">(</span>action<span style="color:#000000">,</span> basestring<span style="color:#000000">):</span>
<span style="color:#555555">  19 </span>            <span style="color:#000000; font-weight:bold">raise</span> <span style="color:#000000; font-weight:bold">TypeError</span>
<span style="color:#555555">  20 </span>        <span style="color:#000000; font-weight:bold">if</span> <span style="color:#830000">getattr</span><span style="color:#000000">(</span>obj<span style="color:#000000">,</span> <span style="color:#ff0000">'allows_%s_for'</span> <span style="color:#000000">%</span> action<span style="color:#000000">.</span><span style="color:#010181">lower</span><span style="color:#000000">().</span><span style="color:#010181">replace</span><span style="color:#000000">(</span><span style="color:#ff0000">' '</span><span style="color:#000000">,</span>
<span style="color:#555555">  21 </span>                                                                 <span style="color:#ff0000">'_'</span><span style="color:#000000">))(</span>actor<span style="color:#000000">):</span>
<span style="color:#555555">  22 </span>            <span style="color:#000000; font-weight:bold">return True</span>
<span style="color:#555555">  23 </span>        <span style="color:#000000; font-weight:bold">else</span><span style="color:#000000">:</span>
<span style="color:#555555">  24 </span>            <span style="color:#000000; font-weight:bold">if</span> msg <span style="color:#000000; font-weight:bold">is None</span><span style="color:#000000">:</span>
<span style="color:#555555">  25 </span>                msg <span style="color:#000000">=</span> u<span style="color:#ff0000">'%s doesn</span><span style="color:#ff00ff">\'</span><span style="color:#ff0000">t have permission to %s %s'</span> <span style="color:#000000">% (</span>actor<span style="color:#000000">.</span>username<span style="color:#000000">,</span>
<span style="color:#555555">  26 </span>                                                                 action<span style="color:#000000">.</span><span style="color:#010181">lower</span><span style="color:#000000">(),</span>
<span style="color:#555555">  27 </span>                                                                 <span style="color:#830000">repr</span><span style="color:#000000">(</span>obj<span style="color:#000000">))</span>
<span style="color:#555555">  28 </span>            <span style="color:#000000; font-weight:bold">raise</span> <span style="color:#010181">PermissionError</span><span style="color:#000000">(</span>msg<span style="color:#000000">)</span>
</pre>

<p>When you want to check for a permission you just need it&#8217;s key (name of the action) and have your <code>User</code> at hand:</p>

<pre><span style="color:#838183; font-style:italic"># Check a permission on a model:</span>
Foo<span style="color:#000000">.</span><span style="color:#010181">cls_attempt</span><span style="color:#000000">(</span><span style="color:#ff0000">'bar'</span><span style="color:#000000">,</span> user<span style="color:#000000">)</span>

<span style="color:#838183; font-style:italic"># Check a permission on an instance:</span>
foo<span style="color:#000000">.</span><span style="color:#010181">attempt</span><span style="color:#000000">(</span><span style="color:#ff0000">'baz'</span><span style="color:#000000">,</span> user<span style="color:#000000">)</span>
</pre>

<p>Notice that we are still using <code>Permission</code>s from <code>auth</code>. Our <code>PermissionMixin</code> can do complex logic, but its hard-coded. We still need something like <code>Permission</code>s for dynamic behaviour. Why not use what&#8217;s built-in?</p>

<p>You can find <code>PermissionMixin</code>&#8216;s code at <a href="http://www.djangosnippets.org/snippets/1502/">Django snipplets</a>.</p>

<h3>Conclusion</h3>

<p>Before employing a similar mechanism, you should think hard if you absolutely positively need it. Maybe you can simplify your UI? Maybe there is a nice tradeoff between code complexity and interactivity of your application? Maybe you can move this logic into <code>model.save()</code> or <code>form.save()</code> or <code>form.clean()</code>? Or maybe your code will be best organized if you use <code>PermissionMixin</code>s.</p>

<p>I just wanted to show that you can build on <code>auth</code>&#8216;s <code>Permission</code>s. Just don&#8217;t get discouraged when you find out <em>you can&#8217;t do x out of the box</em>. Be it permissions or some model magic or making something available in your templates; Django is Python, it can be extended easily.</p>

<hr />

<p><strong>1</strong>: Provided you have <code>auth</code> app installed of course.</p>

<p><strong>2</strong>: Ask yourself; &#8220;Is this <strong>really</strong> a must?&#8221;, and not only for permission related complications.</p>
<div><a class="addthis_button" href="http://www.muhuk.com//addthis.com/bookmark.php?v=250" addthis:url='http://www.muhuk.com/2009/05/django-permission-system/' addthis:title='Django Permission System '><img src="//cache.addthis.com/cachefly/static/btn/v2/lg-share-en.gif" width="125" height="16" alt="Bookmark and Share" style="border:0"/></a></div><p>Related posts:<ol>
<li><a href='http://www.muhuk.com/2011/11/working-with-files-in-django/' rel='bookmark' title='Working with files in Django &#8211; Part 1'>Working with files in Django &#8211; Part 1</a></li>
<li><a href='http://www.muhuk.com/2011/11/working-with-files-in-django-part-2/' rel='bookmark' title='Working with files in Django &#8211; Part 2'>Working with files in Django &#8211; Part 2</a></li>
<li><a href='http://www.muhuk.com/2011/11/working-with-files-in-django-part-3/' rel='bookmark' title='Working with files in Django &#8211; Part 3'>Working with files in Django &#8211; Part 3</a></li>
</ol></p> <p><a href="http://www.muhuk.com/?flattrss_redirect&amp;id=210&amp;md5=faa7d29c3d020ddb9a5464baf6af1961" title="Flattr" target="_blank"><img src="http://www.muhuk.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.muhuk.com/2009/05/django-permission-system/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<atom:link rel="payment" href="http://www.muhuk.com/?flattrss_redirect&amp;id=210&amp;md5=faa7d29c3d020ddb9a5464baf6af1961" type="text/html" />
	</item>
	</channel>
</rss>

