views:

156

answers:

3

I'm working on a platform for online labs registration for my university.

Login View [project views.py]

from django.http import HttpResponse, HttpResponseRedirect, Http404
from django.shortcuts import render_to_response

from django.template import RequestContext
from django.contrib import auth

def index(request):
    return render_to_response('index.html', {}, context_instance = RequestContext(request))

def login(request):
    if request.method == "POST":
        post = request.POST.copy()
        if post.has_key('username') and post.has_key('password'):
            usr = post['username']
            pwd = post['password']
            user = auth.authenticate(username=usr, password=pwd)
            if user is not None and user.is_active:
                auth.login(request, user)
                if user.get_profile().is_teacher:
                    return HttpResponseRedirect('/teachers/'+user.username+'/')
                else:
                    return HttpResponseRedirect('/students/'+user.username+'/')
            else:
                return render_to_response('index.html', {'msg': 'You don\'t belong here.'}, context_instance = RequestContext(request)

    return render_to_response('login.html', {}, context_instance = RequestContext(request))


def logout(request):
    auth.logout(request)

    return render_to_response('index.html', {}, context_instance = RequestContext(request))

URLS

#========== PROJECT URLS ==========#

urlpatterns = patterns('',
    (r'^media/(?P<path>.*)$', 'django.views.static.serve', {'document_root': settings.MEDIA_ROOT }),
    (r'^admin/', include(admin.site.urls)),

    (r'^teachers/', include('diogenis.teachers.urls')),
    (r'^students/', include('diogenis.students.urls')),
    (r'^login/', login),
    (r'^logout/', logout),
    (r'^$', index),
)

#========== TEACHERS APP URLS ==========#

urlpatterns = patterns('',
    (r'^(?P<username>\w{0,50})/', labs),
)

The login view basically checks whether the logged in user is_teacher [UserProfile attribute via get_profile()] and redirects the user to his profile.

Labs View [teachers app views.py]

from django.http import HttpResponse, HttpResponseRedirect, Http404
from django.shortcuts import render_to_response

from django.template import RequestContext
from django.contrib.auth.decorators import user_passes_test

from django.contrib.auth.models import User
from accounts.models import *
from labs.models import *

def user_is_teacher(user):
    return user.is_authenticated() and user.get_profile().is_teacher

@user_passes_test(user_is_teacher, login_url="/login/")
def labs(request, username):
    q1 = User.objects.get(username=username)
    q2 = u'%s %s' % (q1.last_name, q1.first_name)
    q2 = Teacher.objects.get(name=q2)
    results = TeacherToLab.objects.filter(teacher=q2)

    return render_to_response('teachers/labs.html', {'results': results}, context_instance = RequestContext(request))

I'm using @user_passes_test decorator for checking whether the authenticated user has the permission to use this view [labs view].

The problem I'm having with the current logic is that once Django authenticates a teacher user he has access to all teachers profiles basically by typing the teachers username in the url. Once a teacher finds a co-worker's username he has direct access to his data.

Any suggestions would be much appreciated.

A: 

Assuming you have a variable called 'teacher' that represents the profile of the teacher whose profile you're viewing, just do something like this early in the view:

if request.user.get_profile() != teacher:
  ..redirect, throw 404, whatever you fancy 
stevejalim
+2  A: 

A simple way would be to modify the view to add an extra check:

@user_passes_test(user_is_teacher, login_url="/login/")
def labs(request, username):
    if username != request.user.username:
        return HttpResponseNotAllowed()
    ... and so on ...
Daniel Roseman
My first thought, thank you.Is there a way to use a decorator instead?
fuSi0N
A: 

Just a short hint.

...

user = request.user
enrollment = get_object_or_404(Enrollment, id=enrollment_id)
profile = get_object_or_404(Profile, user=user)

if not (enrollment.profile == profile or user.is_staff):
    raise Http404

...

enrollment.delete()

We used such if statements to determine, whether the actual user and the action he requested match. In the example above, only the profile who create an enrollment is allowed to delete it (or someone with staff priviledges).

The MYYN