Previous Page Next Page

Verifying Permissions

The process of adding code to verify permissions is similar to that of verifying authentication. Just like authentication, you can verify permissions in both your view functions and template files. The following sections describe this process.

Verifying Permissions in View Functions

You can use the User.has_perm() function of the User object in the HttpRequest of a view function to determine if the user has specific permissions. Then you can modify the view's behavior, depending on what permissions the user has.

The has_perm() function accepts a string representation of the permission in the format application.permission identifier. If the User object has the permission specified, the has_perm() function returns True. For example, the following line of code returns True if the user object has the can_modify permission for an application called Report:

user.has_perm.('Report.can_modify')

The permission identifier comes from the permission definition. In the case of custom permissions, it is the first string specified in the definition. In the case of the default permissions that are automatically created for the admin interface, the value is add_ with the object name appended. For example, if you defined an object named Person in your model, the identifiers for the add, delete, and change permissions would be add_Person, delete_Person, and change_Person, respectively.

By the Way

You can also determine if the User object has any permissions in an application by using the User.has_module_perms() function. The has_module_perms() function accepts an application name as an argument and returns True if the User object has any permissions set in the module. The following is an example of using the has_module_perms() function:

if user.has_module_perms('Report'):


The following code snippet shows an example of using the has_perm() function in a view to render two completely different templates, depending on what permission the user has:

def blog_view(request):
    if request.users.has_perm('Blog.blog_edit'):
        return render_to_response('blog_form.html', {})

    else:
        return render_to_response('blog_form.html', {})

Verifying Permissions in Templates

You can also verify user permissions in a template by passing in a RequestContext and then accessing the perms template variable. The perms template variable is an instance of the django.core.context_processors.PermWrapper object, which wraps the permissions together in a template-friendly form.

The permissions can be accessed using the perms variable in two different levels—the module level and the permission level. The module level is equivalent to using the User.has_module_perms() function. For example, to access the permissions for an application named Blog at the module level, you would use the following template code:

{{ perms.Blog }}

The permission level is equivalent to using the User.has_perms() function. For example, to access the can_edit permissions for an application named Blog at the permission level, you would use the following template code:

{{ perms.Blog.can_edit }}

Using the perms variable, you can determine in your template what permissions the user has and render the template based on those permissions. For example, the following code snippet determines if the user has the can_edit permission for the Report application. It displays editable data if the user has permission and view-only data if he doesn't:

{% if perms.Report.can_edit %}
  {{ reportUpdateForm }}
{% else %}
  {{ viewOnlyData }}
{% endif %}

Try It Yourself: Use User Permissions to Limit Access in Views and Templates

In this section, you will use the can_blog permission that you created in Hour 14 to limit access to the add_blog() view. You will first modify the person_details.html template to determine if the user has the can_blog permission and see whether the request user matches the userID of the Person object that is being displayed. If those two things don't match, omit the link to the add_blog() view. That will stop people who don't have permission from seeing the link.

Next, you will modify the add_blog() function directly to verify that the user has the can_blog permission. If he doesn't, he is redirected to the home page. This will stop users who try to directly access the add_blog() view. You will also modify the add_blog() function to use the User object from the HttpRequest to find the Person object that the Blog will be added to.

By the Way

We are using a permission created in the Blog class to show that permissions are tied to the module and not the object. The People application has two classes—Blog and Person. However, to access the can_blog permission, you use the People module. Be careful how you name your permissions if the same model has multiple classes so that two classes don't end up with the same permission name.


Follow these steps to implement the can_blog permission to limit access to the add_blog() view:

1.
Open the iFriends/templates/People/person_details.html file in an editor.

2.
Modify the add_blog() view link using the following lines of code, shown in Listing 15.7. The link to add Blog objects shows up only if the user has the can_blog permission and if the user.id from the request matches the userID.id from the Person object passed to the details() view:

{% if perms.People.can_blog %}
  {% ifequal user p.userID %}
    <a href="{% url iFriends.People.views.add_blog pID=p.id %}">[+]</a>
  {% endifequal %}
{% endif %}

3.
Save the iFriends/templates/People/person_details.html file.

4.
Open the iFriends/People/views.py file.

5.
Add the following lines of code to the beginning of the add_blog() function, as shown in Listing 15.8, to see whether the user has the can_blog permission. If she doesn't, she is redirected to the home page:

if not request.user.has_perm('People.can_blog'):
    return HttpResponseRedirect('/')

6.
Modify the get_object_or_404() function, shown in Listing 15.8, as follows:

p = get_object_or_404(Person, userID=request.user)

This gets the Person object that matches the user from the request by matching the userID field to the user object in the request.

7.
Save the iFriends/People/views.py file.

8.
Open the home page in a web browser by accessing the following URL:

http://127.0.0.1:8000/

9.
Click the person you are currently logged in as, and verify that the + link to add a new blog entry is still there (refer to Figure 15.4).

10.
Click the Back button in the browser. Access a different user, and verify that the + link is gone, as shown in Figure 15.5.

Figure 15.5. The People details() view for a different person than the one who is currently logged in, with no + link to add a new blog.


Listing 15.7. Table Column Entry That Displays the Blog List in the iFriends/templates/People/person_details.html File

<td width="70%" bgcolor="eeeeee" colspan="2" valign="top">
    <font size="4">
    {% with p.blogs.all as bl %}
    <h3>
        {{ bl|length|yesno:"Blog,No Blog"}}
        Entr{{ bl|length|pluralize:"y,ies"}}
        {% if perms.People.can_blog %}
          {% ifequal user.id p.userID.id %}
            <a href="{% url iFriends.People.views.add_blog pID=p.id %}">[+]</a>
          {% endifequal %}
        {% endif %}
    </h3>
    {% for b in bl %}
    <li>{{ b.title }} -
        <font size="2"> {{ b.date|date:"M d, Y g:ma" }}</font>
    </li>
    {% endfor %}
    {% endwith %}
    </font>
</td>


					  

Listing 15.8. Beginning of the add_blog() View Function in the iFriends/People/views.py File

def add_blog(request, pID='0'):
    if not request.user.has_perm('People.can_blog'):
        return HttpResponseRedirect('/')

    BlogForm = forms.form_for_model(Blog, fields=('title', 'text'))
    bf = BlogForm()
    message = 'Unknown Request'
    p = get_object_or_404(Person, userID=request.user)
. . .


Previous Page Next Page