I'm writing a web app, and I'd like to use repoze.what & repoze.who to handle my authorisation & authentication. The problem is that repoze.what seems to be hard-coded to accept a certain permissions model, that is:
Visitors to the site are either a logged in user, or anonymous.
User accounts belong to 0 or more groups.
Groups have 0 or more permissions associated with them.
So, for example, your permissions might be 'can-post-article' and 'can-post-comment', and your groups might be 'author', 'visitor', where 'author' can both post articles & post comments, while visitors can only post comments.
That model probably works for most sites. However, my site allows teams to collaborate with each other on different levels. So the security model that I need is:
Visitors are either a logged in user, or anonymous.
Users are a member of 0 or more groups.
For each group that the user is a member of, that membership will have different permissions. For example, the user might be an 'author' or group A, but a 'commenter' on group B.
The number of groups will change over time, and the memberships of those groups will also change. I can't see any easy way to integrate this permissions model into repoze.what. Am I missing something obvious?
Well, you could easily just have a "Group_A_commenter" group and "Group_B_editor" group. They don't have to be manually generated. :) Your model is really just a matter of grouping the groups.
But you should also be able to make Predicate checkers that implement your rules.
http://what.repoze.org/docs/1.0/Manual/Predicates/index.html#term-predicate
I have an answer, after a bit of fiddling.
The answer is that the only reason to use the authentication schema suggested in the repoze.what documentation is that if you do, you can use their predicates for free. Fortunately, writing & using your own predicates is a piece of cake. It seems to me that the only hard requirement is for a user object (although obviously you can call this whatever you want). In my app I have a bunch of custom predicates that check certain things like:
Is the user a member of this group? (group specified by a parameter)
Is the user logged in?
Does the user hold this particular site role?
I can then use these predicates wherever I want.
Related
In a Django Application, I have a model called application.py which is created by a user say "u". I want to list all the application created by the user "u" later, so i may need to add a reference to the model application.py from user.py.
I have one more requirement , as an admin , i need to provide access to any number of users to the same applications. So I assume this can be done with many to many relation.(Since users can access many applications).
Now the question is , is it possible to implement this behavior with user groups ,with one group is responsible for handling one application, so that in a later point of time i can add as many users as needed from the backend to respective groups to manage the same application.?
Which one is better , managing the users using many to many relation with model application.py or relating a group to application.py
and managing users using groups.
There are multiple ways to solve this, but it from a future flexibility point of view this sounds like a Role, Permission and Group relationship:
Applications have a many-to-many relationship to Users through a Membership.
Each membership would point to a Role. That could be hard-coded to start with (just a string like 'admin' or 'viewer').
This way a User can be associated to an Application as viewer or as an admin.
In the future, to add flexibility, you would have a model Role that describes the role (and could be associated to one or more Permission models to list the permissions for each role). So Membership would have a pointer to Role via a ForeignKey.
Check the documentation on extra fields on a many-to-many relationship.
There are also packages that solve this problem, e.g. django-permissions and django-role-permission
I am currently learning how to use Django. I want to make a web app where you as a user can join groups. These groups have content that just members of this group should be able to see. I learned about users, groups and a bit of authentication.
My first impression is, that this is more about the administration of the website itself and I cannot really believe that I can solve my idea with it.
I just want to know if thats the way to go in Django. I probably have to create groups in Django that have the right to see the content of the group on the website. But that means that everytime a group is created, I have to create a django group. Is that an overkill or the right way?
Groups in django (django.contrib.auth) are used to specify certain rights of viewing content mainly in the admin to certain users. I think your group functionality might be more custom than this and that you're better of creating your own group models, and making your own user and group management structure that suits the way your website is used better.
Please suggest me the best way. I am developing a Django application, you will have 3 types of User: Administrator, Reseller and User. They must have hierarchy. The administrator can see everything. The dealer can see everything that its users did. The User only sees what he did.
How can I make these permissions with hierarchy?
You can handle it with 2 differents ways:
First solution (seems to be better in your case): using Django permissions
Here you're gonna create groups, permissions and users. A good practice is to link permissions to groups, and then to link your users to groups. This way, it's easy to change something in the future.
Second solution: create 3 different profiles that inherits from the User base class. It will be more complicated to handle thought.
I'm working on something similar. Per-line authorizations are a bit of a pain in Django. There are two projects out there that can achieve all you are asking for: django-permission and django-guardian. I needed more finely grained permissions and had to roll my own.
I am currently writing an application which I plan to sell as SaaS. Without giving away "secrets," I can say that it is basically a "document editing system" in which many users will be submitting documents.
The basic heirarchy is this:
Institution
Individual
Document
Sub-document
So each Individual should be able to BROWSE all documents that were submitted by anybody in their institution, but should only be able to EDIT documents that they created.
No individual should even be aware of the existence of another Institution--that should all be completely hidden.
I have written a Django/Python class that would facilitate this, but every document regarding authentication that I have read requires that I use the User object. Is this just a limitation of Django, or is there a way to do this?
If there is a way, how can I get my own "Individual" class details attached to the "request" objects so I can validate the things I should be showing the users?
What you're looking for is authorization, not authentication. Django's built-in authorization system is fairly crude, as you've discovered. You'll need something like django-authority if you want a more complete solution.
The auth module is typically used to cover authentication cases.
Gives you groups (Institutions), Users (Individuals) and permissions.
Using these features you can perform checking if a user is a member of a group or owns a doc before allowing them to see or edit the doc.
http://docs.djangoproject.com/en/dev/topics/auth/
If you need to go beyond the typical use case, supporting LDAP for example, then you can look at writing your own authentication backend.
http://docs.djangoproject.com/en/dev/topics/auth/#other-authentication-sources
In general, if you need to attach more information to the builtin User model, you would create new model which subclasses models.Model (not User), and identify it in settings as AUTH_PROFILE_MODULE. You can get the appropriate instance of your model from a user by calling user.get_profile(). (see http://docs.djangoproject.com/en/dev/topics/auth/#storing-additional-information-about-users).
This is generally useful for adding extra fields to User such as address, contact information, etc. While it would be possible to use this for your authentication needs, you'd most likely be better off using the built in groups, or a more comprehensive solution like django-authority as others have mentioned. I've included this answer only because it seems to be what you were asking for (a way to attach a class to User), but not really what you need (authorization).
I'm making a SAAS and I've been asking a slew of questions on here related to the Auth system built in. I'm having trouble understanding the "why" and "how". Primarily I don't understand how it fits in with my SAAS.
I (do) know the following:
You can do this: http://docs.djangoproject.com/en/dev/topics/auth/#storing-additional-information-about-users
There are many reasons to use the built in auth system (like security) instead of rolling your own
I (don't) know the following:
class MyUserProfile(models.Model):
"""
Administrator for an Account. Can edit tickets and other stuff.
"""
user = AutoOneToOneField(User, primary_key=True)
account = models.ForeignKey(Account)
dogs_name = models.CharField(max_length=255)
In the previous example, account is just what you'd expect; an entity that's paying to use my software. user is my main concern. Somebody goes to a page and creates a UserProfile with a username and password, etc. When they do this, where does the related User get created? Do I need to create it in my view manually based on the request.POST['username'], etc, and then do
myuserprof = MyUserProfile.create(user=foo_user_just_created, account=foo_account, dogs_name='Spot')
I don't know why but for some reason I feel like I'm missing something. This idea of asking somebody to sign up for an account, and then create a MyUserProfile with a form that asks for the password, username, email, et al, and then in my view creating 2 different objects (MyUserProfile and User) with different parts of the form data. I mean I shouldn't have a User form right? Like I said, I feel like I'm either skipping a step or I'm in the wrong paradigm. I'm not new to Django, but for some reason I have trouble with things that I didn't build (I think it might be a mental problem for real at this point).
Maybe there is a good example of this sort of thing being done on some open source project.
Update: Oops, forgot to mention that in the code above I tried to use AutoOneToOneField from django-annoying, but I have no idea where all the User's attributes get set or how to decide which User object to attach to it. This stuff is driving me crazy.
Also, do I need to use the sites app to do this stuff, and finally does a "super user" have all permissions to everything (I don't want people from Account "Acme" to access account "Microshaft" objects)? Or do they just have all permissions to all views?
Somebody goes to a page and creates a UserProfile with a username and password, etc.
UserProfile doesn't have an username or password field. So it should be somebody goes to a page and create an User. Then, it creates an UserProfile associated to that newly created User.
The question is, how and when do you want this UserProfile instance to be created?
Automatically, whenever a new User is created : use signals, as described in the docs
Automatically, whenever the profile is accessed from an user instance : use AutoOneToOneField, and access the profile using user.userprofile instead of user.get_profile()
Manually. But don't forget an user might have no UserProfile associated yet, so user.get_profile() might raise a DoesNotExist exception.
When they do this, where does the related User get created?
It doesn't. You have to create it explicitely.
This idea of asking somebody to sign up for an account, and then create a MyUserProfile with a form that asks for the password, username, email, et al, and then in my view creating 2 different objects (MyUserProfile and User) with different parts of the form data. I mean I shouldn't have a User form right?
Why not? You want here to create an User and his associated profile in one go, right? You could eventually use directly the POST data, or use a Form to access to the fields, or even better, use 2 ModelForm (one for User, one for UserProfile) that you will process in the same view (maybe this question can help?)
Maybe there is a good example of this sort of thing being done on some open source project.
I suggest you check out django-registration and django-profiles.
Note
You have another way of adding information to an User object, by extending the model itsel. It will allow you to put your extra fields directly in the user model and might be easier for you to understand and use.
I won't dive into details here, have a look at that tutorial for more informations.
Other questions
I tried to use AutoOneToOneField from django-annoying, but I have no idea where all the User's attributes get set or how to decide which User object to attach to it. This stuff is driving me crazy
See above on how to use it. If you feel uncomfortable with it, the best is to follow the documentation, which recommend using a ForeignKey with unique=True in user profiles.
Also, do I need to use the sites app to do this stuff
From the site framework docs : Use it if your single Django installation powers more than one site and you need to differentiate between those sites in some way.
and finally does a "super user" have all permissions to everything (I don't want people from Account "Acme" to access account "Microshaft" objects)?
Again, from the docs, Designates that this user has all permissions without explicitly assigning them. That means that everywhere Django is using the built-in permission system (e.g. default administration pages), a super-user will be authorized.
In views you're writing yourself, or if you tweak some ModelAdmin, it's up to you to decide how you are going to check permissions.