How to moderate django_openid_auth - django

I am implementing openid feature using django_openid_auth library which is quite amazing..
However I am looking for very specific moderation settings.
Although openid is made available for everyone..I am looking to implement the below rules
OpenId should provide email address.. Not all guys do provide
The email address should be one of the access granted list present in my db
I started to think quite possible ways like creating custom middleware, custom login_required decorator etc.. But I am unable to think a possible way of fitting them exactly in the bill.
Can anyone add suggestions would be appreciated

aquiring email address is simple enough - you just need to ask openid server for it. django-openid-auth provides settings for it:
OPENID_SREG_EXTRA_FIELDS = ['email']
In my project i also needed to do extra stuff after authentication. I solved it with signal:
def register_login_signal():
from django.contrib.auth.signals import user_logged_in
from django.contrib.auth.models import User
user_logged_in.connect(your_function_name_here, sender = User)
def your_function_name_here(sender, **kwargs):
request = kwargs.get('request')
logout(request) if request.user.email not in your_list_of_authenticated_emails else pass
and dont forget to put register_login_signal() to some place where it gets used like projects init.py file
Edit:
1st comment/question.
The extra fields part is not stated in documentation. Also, if you scan through the github package then you notice nothing like it, i'm sure. I am using older version of https://pypi.python.org/pypi/django-openid-auth/0.5. Download it, unpack and open views.py in django-openid-auth folder. Search for OPENID_SREG_EXTRA_FIELDS and you'll see it. Works like a charm if you define it in settings.py.
2nd question
Async? Nope, not really. Async would be something that gets run outside of current function stack - if you can describe it like that. This is nothing like that. Imagine it like that - in the end of login function there is check, that if there are some functions hooked on the end of login function. And they get run instantly. Its as much async as django middleware is. So not at all.
But is it right place to do it? I imagine that you have your site set up that you check if user has logged with #login_required decorator - or something like that.
So lets see how things will get executed:
1) Your openid server sends you all the information you requested with last request
2) Your django-openid-auth login_complete view takes over and authenticates user using it's backend
3) in the end of that process the signal for which you listen to is triggered, user's email is checked against your list and if the check fails, then he is instantly logged out.
4) Since the view is done, it automatically redirects you to either the url whcih was specified in original view with "next" parameter or to LOGIN_REDIRECT_URL specified in your settings
5) Before that view all the middleware and decorators get used. And if you have used something like #login_required decorator (which is smart thing to do for each login protected page), then it instantly redirects user to login page. If you bothered to add some kind of message to request in signal, then the message is displayed (given that your login/logout page supports that)
And to say something in the end - there is no stronger method than logging out.
/edit

Related

How can I change the view site link in Django admin, depending on which app is used?

I am making a project where each client have their own app. This is because they have similar pages but not exactly the same so I think it's a good approach(I may be wrong) to just copy one app for each new client. I have not tried it yet, I am still planning for it. I see one problem with the view site link in the admin. I will let the clients use the admin. How can I set the view site link to the main page for the client? One way to solve it would be to leave it as is and have a function checking their user name and redirecting to the right app. But is there any other way to solve this problem?
I don't think it will be a good idea to have applications generated for users as that's too much once you reached a specific amount of users.
they have similar pages but not exactly the same
Then what you should do is to, after getting the user in your view, pass in a different context to your template. Something like:
def my_view(request):
# First assign different context to different users
context = {'data': 'whatever each user gets', 'other': 'put in more than 1 data',}
return render(request, 'myapp/index.html', context)
I will let the clients use the admin
That's not a good idea as the clients MUST be a superuser to view the admin site. Otherwise, you need to change the permissions of a superuser, make a separate superuser if you are the maintainer of the site, and all sorts of trouble. Just take some time and make your own templates.

Single-page login in Django app

I'm currently using out-of-the-box django.contrib.auth to handle authentication in my Django app. This means that the user starts at a log in page and is redirected to the app on successful login. I would like to make my app single-page, including this login process, where a redirect doesn't happen, but maybe a "hot" template switch-out or some fancy client-side div magic (that still remains secure). My Google searching turned up pretty short, the closest solution dealing with putting a log in form on every page.
Any direction or ideas here would be much appreciated. I would obviously prefer to work within the existing confines of django.contrib.auth if possible, but I'm open to all solutions.
I'm not sure I understand your question completely. I think you want to have a single page. If so, put logic in your template that checks to see if the user is authenticated. If not, display a login form that POSTS to the appropriate django.contrib.auth view. You can supply an argument to this view to have it redirect back to your page. When you come back, the user will be authenticated, so you won't display the login form.
Have a look at Django-Easy-Pjax https://pypi.python.org/pypi/django-easy-pjax - it works like a charm and is well documented. Everything you like is being made with AJAX requests: links, forms using GET and forms using POST.
Essentially you only need to add a data-pjax="#id_of_the_container_where_the_result_goes" attribute in your a and form tags.
And the great thing about it: It updates the title and location bar of your browser.
One caveat: If you want to upload files in some form, this is not supported by Easy-Pjax, so you might want to use some workaround jQuery library for that.

How can one use Django Postman to set up a back end messaging system like Facebook?

I've done research on Django Postman and it seems to be the most solid private user to user messaging platform out there. I've looked at the Django Postman documentation but it's very template orientated. For developers who use Django as a back end and only care about the views.py and urls.py, the documentation doesn't say much.
I did however find this: https://bitbucket.org/psam/django-postman/src/6ff9fdf9c33f7365a7235a789af2e47f47d9c4fa/postman/views.py?at=default
It seems pretty promising so I'm going to give it a try. My only issue is how can one set up the postman views in views.py and the urls in urls.py to create a messaging system similar to Facebook's?
(ie. A thread like messaging conversation system, a central inbox where all the messages come together from each user showing the last message from each user, messages in the inbox are sorted by conversation rather than the message, the time of the last message sent, allowing multiple recipients)
Below I've posted a picture of Facebook's messaging platform. This is what I am essentially trying to achieve with Django Postman.
Facebook Example http://screenshots.en.sftcdn.net/en/scrn/73000/73077/facebook-19-371x535.jpg
If you have any pointers, hints and ideas on how I can set up the views.py, I would greatly appreciate it! Thank You
I've run into this issue before.
You need to strictly override some of the views in there by clonning/forking the project and install it from your own location, because as you noted, postman is template-oriented because it's meant to only get the needed templates configured and a few settings. I mean, the backend is meant to work as is.
What you need to do is override stuff like:
Message model's recipient field to be a ManyToManyField
customize the views based on your needs and be careful with Message.replied_at
make sure you allow a user to reply to their own messages (by default, it was not allowed when I ran into this, not sure now)
Depending on your needs, maybe you'll want to override something else, but this is a good start. If you need it facebook-like, you'll need to use some push libraries as Pusher or Juggernaut, maybe you're interested in them also.
Good luck! :)

how to check if a user has logged in from outside the US using Django middleware

I am pretty new to Django and wanted to know how I could check if a user logging to a django powered website is from outside the US?
How would I write a class in Middleware to check the same? I want to hide particular sections of the website from users logging out of the US.
I know I am not providing any details and the question might seem vague... but I needed a general idea to get started. I have not started working on the website yet.
I went through the Django Middleware documentation but still did not understand how to do so.
Does the user authentication https://docs.djangoproject.com/en/1.4/topics/auth/#limiting-access-to-logged-in-users provide any such functionality?
You could use the GeoIP module included with django.
A simple middleware could look something like this:
class GeoLocationMiddleware:
def process_request(self, request):
if 'geoip_check' not in request.session:
g = GeoIP()
country = g.country(request.META.get('REMOTE_ADDR'))
do_something(country) #Do something with country result.
request.session['geoip_check'] = True #Could store country result
return None
You'll notice I add a flag to the session. Checking the GeoIP on every request is unnecessary and bad for performance, so we only check it once per session.
Hope this is what you were looking for.
Edit:
If you only want to do this for logged in users, throw this in there:
if request.user.is_authenticated():
at the beginning.

Bypass SESSION_SAVE_ON_EVERY_REQUEST for AJAX call, or better solution

I have a private site that requires login for all pages. When a user goes to edit a record, I don't want to lock the record. I want to keep the record available for others. I devised a system using AJAX calls to django using dajax/dajaxice to get the most recent person and datetime of editing for the record. If the most recent edit was not made by the current user, an alert box notifies the user that another person has made an edit since they've opened the record and they should refresh the page to get the most recent version of the data.
This is all well and good, and works perfectly for our situation. I have a session timing out which, when timed out will send the user to a login prompt. In case the user leaves the page open and leaves the computer, we want the sensitive data protected. This is also working perfectly.
My problem is that when the AJAX call is made to check the version of the data, to see if it is changed, it also saves the session, so the session will never time out no matter how long they are at the page unattended.
Is there a way in a view to bypass the SESSION_SAVE_ON_EVERY_REQUEST, so that only this request does not trigger a save. I know I can manually save the session in every OTHER view, but that seems like the wrong thing to do. I suppose I may be able to write middleware that checks the view requested and only saves the session if it is not this view, but I'm not sure that's the best solution either.
Any suggestions?
Thanks in advance.
I am pretty certain this will work. I added CustomeMiddleWare to settings.py MIDDLEWARE_CLASSES. Also, turned off session saving on every request in settings.py.
class CustomMiddleware(object):
def process_view(self, request, view_func, view_args, view_kwargs):
if view_func.__module__ != "exclude.module" and view_func.__name__ != "excludeMethod":
request.session.save()
Now the problem is that using Dajaxice, the module and name come over as dajaxice_request. Now I don't know how to get the actual method requested. Tried a bunch of things, but haven't been able to. Don't want to hack the DajaxiceRequest code, but may have to.
SOLUTION:
Switched to jQuery ajax for this one method. Created a new urls.py entry to make the single call to get the version of the record. This makes the view_func in process_view available, so I can only save the session on views called other than this one. Woo Hoo! I am still using Dajaxice for all other AJAX methodology.