This question is (I think) about object/row level permissions in Django.
We are building a community and need to be able to set permissions based on actions that users take. For example, you should not be able to start a thread until you have posted so and so many answers.
Also, the users should be able to remove content that belongs to themselves. Based on the Django documentation, it seems like the standard framework does not support permissions for instances.
Should we build on the "empty" API that Django supplies, or should we use an app for this like django-guardian, django-rules, etc? Which ones would you in that case recommend?
Thank you!
you should not be able to start a thread until you have posted so and so many answers.
You don't need to use per-object permissions for that. Actually, you don't need to use permissions for that at all. Just check if user meets the requirements in your views.
Or you can use standard django permissions engine. Create permissions like "Start a Thread", then set up signals to track when users add answers. When singal is emitted check if a user has enough answers and grant him the "Start a Thread" permission.
It's up to you to decide which one works better for you.
Also, the users should be able to remove content that belongs to themselves.
This can be done with per-object permissions. But if it's the only reason to use them then I'd just add a field author to your models and use a simple item.author == request.user check to test if user can delete the item.
So, my general advice is to keep it simple. Analyze your needs. Per-object permissions is a powerful tool which may be an overkill in your situation.
I recommend you to go with Django-guardian.
Django-guardian
Great, DRY, maintained and well-tested app, that solves the issue. As of today, this is the most maintained and actively developed library for implementing per-object permissions.
We are currently using django-guardian in one of our big projects and are very pleased with stability and functionality.
Django-guardian source code is very simple and easy to understand because it is built upon the permission code in Django core.
However, there is a minor issue with Django permissions for proxy models which is not fixed in Django core thus making it really tricky to set permissions (global and per-object alike) for them. One of the ways to overcome this is to declare all permissions in a non-proxy object and query for them every time when you need to check for permission to access a proxy model.
Per-object permission library by OSU Open Source Lab
It is more of a standalone application than Django-guardian and supports older versions of Django. This app is relatively well maintained. (I personally haven't used it.)
Other solutions form older posts.
But most of them are poorly maintained.
Of course, if you need to implement only a few minor checks, row-level permissions are overkill, just like Andrey said.
Related
I am new to django. I want to edit default user auth_permissions. More precisely I want to add an integer field in addition to "label", "code" features to distinct permission types (like strong, moderate and etc.). So far I could not find anything like this. I tried to make custom permissions, but could not add them to the permission database. Anyone could help me?
Per Object permission
When i first got into django i also tried relying on the permissions framework within django, I also found the permissions were too broad and inefficient, which lead me to researching django-guardian, I tried to submit an edit to the Django project itself to make more object-base permissions with no success, they said as per object permissions were too personalised for the framework.
The thing is, after getting to work in the industry i realised how people do these permissions in the industry (which honestly was something that bugged me), they mainly create custom login middlewares to keep track of authentication types and add the checks on the view itself. So basically you will have to check in the view who the user is and if you want to give them permission to whatever.
When in MIT they kept asking me to make some weird permissions and I created a table called ExtraordinaryPermissions, this had a ForeignKey to the user and could be used to check within the views what objects the user had access to
It is troublesome, but as-per-object permissions are handed this way in the industry
good luck
I'm working on a django project in which users can post articles and vote on them. But the users are not supposed to vote on their own articles. Currently I'm using the permission system with django-guardian. My idea is to grant a kind of 'anti-permission' so that only the author can't vote on their own articles.
My reasoning is that in this way all the permissions can be handled in a unified protocol, separately from view functions(instead of putting conditions inside them). And if there comes future requirements like this, they can be handled elegantly.
But it does not look semantically right to use "permissions" in this way. Just wondering if there's a better way of doing it?
Thanks for your help! :)
Write a manager that takes the context and then returns a list of objects that the user can vote on.
Use this manager in your view.
I'm building a Django-based review website where public users create all of the content on the site. Users create reviews for given items and they also create the items themselves that will be reviewed (providing a description and brief summary of the item, along with a few tags).
My question is this: Should I be using Django's admin features for this website (as in, exposing admin controls to the public users)? Or should I just stick with normal forms? I'm not too familiar with the admin-aspect of Django, and so far I've just been using forms for the website, but I've seen a lot of people talking about Django's admin features, and I'm starting to wonder if I should be using them.
Thanks for any feedback!
Maybe. If the admin functionality covers most of what you want to offer, there's no reason why you shouldn't use it as a starting point.
django.contrib.admin is an application like any other, and provides basically a CRUD interface to your models. Access can be controlled via groups/permissions, just like you would for an application you write yourself. You can give full access to a model with a one-liner, but obviously will have to configure properly when opening up to others.
See also my question
Django AdminSite/ModelAdmin for end users?
and similar questions Exposing django admin to users. Harmful? and How to make Django admin site accessed by non-staff user?
Regarding arguments about the "intended use" of the admin, please note Django's security update at the end of last year: http://www.djangoproject.com/weblog/2010/dec/22/security/ regarding querystring parameters in object lists. Such an update (quote: "an attacker with access to the admin [...]") is a clear indication that the admin's implementation of the permission system is being constantly scrutinized.
No. The django admin is not intended for any end-user.
The django admin feature is intended to assist the website developer, and that is all. Even usage by site administrators is contra-indicated, although in practice most small sites get away with it since they're only talking a few people who can call on the developer personally if they get into trouble.
For your purposes, the review items and the workflow in creating the items is a critical part of your application feature set. The admin will give you ideas, but it would be a mistake to attempt to build your application upon it.
I wouldn't expose the admin interface to regular users. You can use the authentication and user-management side (for your purposes), but it's usually best practice to give users a separate way to manage their objects. You also don't run as much of a risk of granting the wrong privileges to users (or allowing them to grant their own).
Have a read though the docs if you want a better overview about what it can do.
I am working on a Django somewhat e-commerce project, where, briefly, I have both a Customer and a Merchant model. The Merchant model is associated with a MerchantStore model which is somehow "complicated", having a plethora of m2m and foreign key relationships to various models.
Following the solution in this post and having not enough "time" to make a custom implementation, I decided to let each Merchant be a "stuff member" and customize his store through the admin interface. Of cource I created a new group with the appropriate permissions.
However, some questions arise:
1) Is this considered harmful? Are there any security threats associated?
2) Isn't this the best way to do it if you have not enough time anyway?
No, I would not consider this harmful.
The "Zen of Admin" as described in Apress's djangobook seemed to imply an assumption of trust as part of the admin's "philosophy", and paired with the often-repeated "admin is not your app" advice, I too was scared at first and think the Django documentation could point out intended, viable use cases.
Please see my almost identical question Django AdminSite/ModelAdmin for end users?
From Jordan's answer (who I gave the bounty):
There is nothing inherently special
about admin. It behaves just like any
other view. So if it is using
permissions to determine access (for
example, if you set a user's .is_staff
to True but give them access only to
specific permissions) then it will be
equally secure to any view you might
create that uses permissions to
determine access.
...
The people who wrote
django.contrib.admin did not write it
with the assumption that anyone with
an is_staff = True could be trusted as
much as a superuser, or was stupid
enough to never take a look at the
source code of a web page. Although
writing your own views is encouraged,
it is still a robust interface.
Also note Django's relatively recent security update http://www.djangoproject.com/weblog/2010/dec/22/security/
regarding querystring parameters in object lists.
Such an update (quote: "an attacker with access to the admin [...]") is a clear indication that the admin's implementation of the permission system is being constantly scrutinized.
Yes, this is considered "harmful", mostly due to the design considerations of the Django developers. The admin revolves around a concept of "trusted users". In other words, if someone is a staff member (thereby having access to the admin), they presumably have enough of your trust to not be worried about security breaches. Now in truth, you could block them from portions they're not supposed to mess with (as you've done), but the point is that Django makes no guarantees in this area. You probably won't have any problems, in all actuality, but you could.
Ironically, I think I've spent more time in my life customizing the Django admin than it would have taken me to build it from scratch. Funny how that goes. Regardless, I'd liken it to using scaffolding in Ruby on Rails. It's a quick way to get something live, but the goal is to replace it as soon as possible.
Does anyone know a good link to documentation about Pinax signup and "Accounts". I'm trying to work out how to implement our sign-up process in Django / Pinax and am trying to navigate my way between Django's User and Profile classes and the Account class in Pinax..
The main issue for us is we have a sign-up form with several extra questions that must be answered at the point of requesting an account. Membership then needs to be accepted by an admin before the account is enabled. At which point, the answers to these extra questions will be stored in the user's profile.
I'm torn between two rival approaches.
1) Create the User and Profile object at the time of the request. But flag them as "pending" in some way, until approval.
2) Create some kind of alternative model class to temporarily store these values until approval. At which point I create the User and Profile objects and copy the information into them.
I'm trying to infer from the Pinax signup code which of these approaches is most "with the grain" of Pinax, but it's not clear.
So, experienced Django/Pinax developers. Which of these is the more "pinactic" way to go about things?
There are two variants of (1): (a) you just rely on the active flag on User; (b) you denomormalize and have a similar flag on your profile to avoid a join.
The main challenge with approach (1) is that you then have to make sure that any time you are retrieving profiles, you filter them based on this flag. Of course, that's not an issue for something like Account which only the logged in user sees. But for Profile that could be a bit of a pain.
(2) doesn't have that problem. You could avoid some redundancy in that case by using an abstract base model shared by both your temporary profile and main profile models.
Bottom line is I don't think there's an obvious "pinactic" way to do it, although personally I'm leaning towards (2).
Most of the documentation is either here: http://pinaxproject.com/docs/dev/ or here: http://code.pinaxproject.com/wiki/ or else in the code base.
It's seems recently they've been working on the code more and documentation less since they're working up to a stable release so those docs aren't very up-to-date.
That said, Pinax already has a mechanism that delays activating accounts until they've validated their e-mail address (approach #1). The related settings are: ACCOUNT_REQUIRED_EMAIL and ACCOUNT_EMAIL_VERIFICATION so a search on the code base should revealed how/where they're used (which you may be able to extend to use for your extra questions).
I believe they accomplish this by giving each User an "Active" flag (Check out the User object in Admin) which isn't set to True until they verify their e-mail address. I vaguely remember setting this manually one time and still being unable to login with that particular User so you'll want to test this out.