Django, I deleted AnonymousUser, how to restore - django

(amazing, I have not found such a question yet!)
I deleted part of my users in the db, and accidentally also the AnonymousUser-instance.
How do I restore him? (well... him or her, for the sake of political correctness :-P)
I do need an instance of him in the db, right? (so far, by quickly browsing my site, I have not run into issues). What would be the problems without him, by the way?
But there is no AnonymousUser.objects-manager to create one. And save() is not implemeted anyway, like the docs say. So do I drop the users table and migrate? Will it help and/or can I proceed differently?
Thanks a lot :)

Anonymous user is an instance of django.contrib.auth.models.AnonymousUser and is created on the fly when the auth backend does not found any authenticated user in session and it is not stored in the database, hence save is not implemented on this and id is always None as the doc states.
Update after comment
django-userena uses django-guardian to manage per object permissions, and django-guardian will create this user automatically listening to signals.post_migrate signal. So simply run migrate command and you should have your so called anonymous user back (This is not an instance of django.contrib.auth.models.AnonymousUser it is an actual user instance of your user model).
You can disable this behavior altogether depending on your needs, check django-guardian docs.

Related

How to add more features to user permission in django?

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

How to store additional information about the Users in Django ?

I have several notifications that can be sent out from my Django application for users. These users are managed with the django.contrib.auth app.
I need to keep track for each whether the user has specified he/she wants to get that notification.
Where should I save this information?
I was going to create my own custom table but I've seen perhaps I can save that information somewhere in the auth module?
User Profiles are a good way to go.
https://docs.djangoproject.com/en/dev/topics/auth/#storing-additional-information-about-users
Set up a model with a OneToOneField to your User object as described and you have easy access to an arbitrary table of extra information.
PS: Heed the note about the fact that profiles are not automatically created. There is an example about how to use a Signal to automatically create one whenever a User is created.

django: Persist post request across a login

On logging in, the request's session key changes.
This makes it hard to use sessions, for activities that should persist across login, such as, say a shopping cart, where the login is prompted only while check out.
What is the best way to implement such a cart, which persists across login. One solution would be to have a table with session keys and products and on login, associate the user to it.
It could be simpler, I feel, particularly, all you want is to persist just a single post request.
This used to be a feature of Django, but it was removed, because it was a security issue. If you're going to implement something similar, you'd be wise to understand the security implications of it (which I don't, I just know there were issues).
I think the feature used to work by pickling the post data, and storing it in a hidden field of the login form.
The relevant announcement is here, and the code change is here.

Pinax Signup and Accounts

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.

In Django, what is the right place to plug in changes to the user instance during the login process?

Background
I have a custom authentication back end for our django applications that refers to an LDAP server.
As soon as I authenticate someone, I have a wealth of information that our network infrastructure guys put in the LDAP server about the user - their last names (which can change, for instance, if they marry), their e-mails (which can also change), plus other company specific information that would be useful to transfer to the Django auth_user table or profile table for local reference. (*)
To take advantage of this data, as of now, in our custom authenticate method I'm looking up (if it is an existing user logging in) or creating a new (if a new user that never logged in to our Django apps) user, making any changes to it and saving it.
This smells bad to me. Authentication should be about saying yay or nay in granting access, not about collecting information about the user to store. I believe that should happen elsewhere!
But I don't know where that elsewhere is...
My current implementation also causes a problem on the very first login of a user to one of our Django apps, because:
New user to our apps logs in - request.user now has a user with no user.id
My custom authenticate method saves the user information. Now the user exists in the DB
django.contrib.auth.login() kicks in and retrieves the request.user (which still has no user.id and no idea that authenticate saved the user) and tries to save an update to last logged in date.
Save fails because there is already a row in the database for that username (unique constraint violation)
Yes, this only happens the very first time a user logs in; the next time around it will be an update, request.user will have a user.id and everything is fine.
Edit: I'm investigating the striked-out area above. The login code clearly only uses the request.user if the user is None (which, coming out of the validation of the AuthenticationForm it shouldn't be. I probably am doing something wrong in my code...
But it still smells bad to have the authentication doing more than just, you know, authenticating...
Question
What is the right place to plug in changes to the user instance during the login process?
Ideally I would be able to, in my custom authenticate method, state that after login the information collected from a LDAP server should be written to the user instance and potentially the user profile instance.
(*) I do this local caching of the ldap information because I don't want to depend on it being up and running to let users log in to my systems; if ldap is down, the last username and password in auth_user are accepted.
I've done similar things by writing my own authentication backend and putting it in the authenticate() method. The code is public and up here. I also included a pluggable system of "mappers" to do most of the work that isn't just authenticating the user (eg, getting fullname from ldap, automatically creating groups based on "affiliations" that our auth service gives us, and mapping certain users and affiliations into staff/superuser roles automatically).
Basically, the authenticate method looks like:
def authenticate(self, ticket=None):
if ticket is None:
return None
# "wind" is our local auth service
(response,username,groups) = validate_wind_ticket(ticket)
if response is True:
try:
user = User.objects.get(username=username)
except User.DoesNotExist:
user = User(username=username, password='wind user')
user.set_unusable_password()
# give plugins a chance to pull up more info on the user
for handler in self.get_profile_handlers():
handler.process(user)
user.save()
# give plugins a chance to map affiliations to groups
for handler in self.get_mappers():
handler.map(user,groups)
return user
else:
# i don't know how to actually get this error message
# to bubble back up to the user. must dig into
# django auth deeper.
pass
return None
So I pretty much agree with you that authentication should be just a yes/no affair and other stuff should happen elsewhere, but I think with the way Django sets things up, the path of least resistance is to put it in with authentication. I do recommend making your own authentication code delegate that stuff to plugins though since that's within your control.
I'm only fetching the LDAP data on their very first login though (when the auth_user row gets added). Anytime they login after that, it just uses what it already has locally. That means that if their LDAP info changes, it won't automatically propagate down to my apps. That's a tradeoff I'm willing to make for simplicity.
I'm not sure why you're running into problems with the first login though; I'm taking a very similar approach and haven't run into that. Maybe because the login process on my apps always involves redirecting them to another page immediately after authentication, so the dummy request.user never gets touched?
This will be a two part answer to my own question.
What is the right place to plug in changes to the user instance during the login process?
Judging from the Django code, my current implementation, and thraxil's answer above, I can only assume that it is expected and OK to modify the user instance in a custom authenticate() method.
It smells wrong to me, as I said in my question, but the django code clearly assumes that it is possible that a user instance will be modified and I can find no other hooks to apply changes to the user model AFTER authentication, elsewhere.
So, if you need an example, look at thraxil's code - in the selected answer to my question.
Why my implementation is working differently from thraxil's and generating a unique constraint violation?
This one was rather nasty to figure out.
There is absolutely nothing wrong with Django. Well, if it already supported multiple databases (it is coming, I know!!!) I probably wouldn't have the problem.
I have multiple databases, and different applications connect to one or more different ones. I'm using SQL Server 2005 (with django_pyodbc). I wanted to share the auth_user table between all my applications.
With that in mind, what I did was create the auth models in one of the databases, and then create SQL Server synonyms for the tables in the other databases.
It works just fine: allowing me to, when using database B, select/insert/update/delete from B.dbo.auth_user as if it were a real table; although what is really happening is that I'm operating on A.dbo.auth_user.
But it does break down in one case: to find the generated identity, django_pyodbc does a:
SELECT CAST(IDENT_CURRENT(%s) as bigint) % [table_name]
and that doesn't appear to work against synonyms. It always returns nulls. So when in my authenticate() method I did user.save(), the saving part worked fine, but the retrieval of the identity column didn't - it would keep the user instance with a id of None, which would indicate to the django code that it should be inserted, not updated.
The workaround: I had two choices:
a) Use views instead of synonyms (this is what I did)
b) Reload the user right after a user.save() using User.objects.get(username=username)
Hope that might help someone else.