views:

132

answers:

2

Certainly not a new question I think, but here it goes:

In my Django based Order system each user (who is not staff) is related to a CustomerProfile object which matches that user to the correct Customer object. This customer users can log in and view outstanding Invoices. To view a customer's invoices you navigate to something like this:

/invoices/customer/97/

(Customer Invoice #97)

Which is fine but I need to incorporate some authentication so a user who is part of a Customer's profile can't view another customer's invoices by manually entering /invoices/customer/92/ for example (invoice 92 belongs to another customer).

I've got this but it's really not good code (and doesn't work):

def customer_invoice_detail(request, object_id):
    user = threadlocals.get_current_user()
    try:
        userprofile = UserProfile.objects.get(user=user)
        user_customer = userprofile.customer.id
    except UserProfile.DoesNotExist:
        user_customer = None
    if (request.user.is_authenticated() and user_customer is not null) or request.user.is_staff():
        invoice = CustomerInvoice.objects.get(pk=object_id)
        product_list = CustomerInvoiceOrder.objects.filter(invoice=object_id)
        context = {
        'object': invoice,
        'product_list': product_list,
        }
        return render_to_response("invoices/customer_invoice_detail.html", context, context_instance=RequestContext(request))
    else:
        return HttpResponse("You are not authorised to view this invoice")

Must be a better/easier way to deal with this - any ideas?

Cheers

+2  A: 

I'd recommend making some business logic for your customer model. This way you could have a get_invoices() method that returns a list of invoices for that customer only. This method in turn would call a is_authenticated() method that ensures that the current state allows retrieval of protected customer data, or raises an exception.

With this, no matter where your code tries to get invoices for a customer, an exception will always be thrown if the current state does not have access to the invoices, and you won't have to worry about inconsistent behavior as long as you use these methods.

Blixt
+1  A: 

Add a field to your invoice model called user:

user = models.ForeignKey(User, related_name="invoices")

then retrieve records for a specific user like this:

invoice = CustomerInvoice.objects.get(pk=object_id, user=request.user)

Retrieving invoices for a given user is then trivial with the reverse relation:

request.user.invoices.all()

Also, look at the @login_required decorator.

Harold