Django signals on GAE with django-nonrel - python

I am using django-nonrel for my project on GAE. My requirement is that in my application at a time only one user should login with the given username. I tried to implement the following suggested approaches:
Allow only one concurrent login per user in django app and How can I detect multiple logins into a Django web application from different locations?
But the problem is that both of the approaches working on the development server but didn't work on google app engine. So I switched to django-signals as my alternate approach. I created one post_login signal which will store the username for every login user in a table Visitor in database. On every logout,other signal post_logout will remove the user from this table.The part of codes are as:
#signals.py
post_login = django.dispatch.Signal(providing_args=['request', 'user'])
post_logout = django.dispatch.Signal(providing_args=['request', 'user'])
#models.py
def login_handler(sender,user, **kwargs):
try:
result=Visitor.objects.get(user=user)
print "You already have login with your name"
except:
visitor=Visitor()
visitor.user=user
visitor.save()
post_login.connect(login_handler)
def logout_handler(sender,user, **kwargs):
try:
result=Visitor.objects.get(user=user)
result.delete()
except:
return False
post_logout.connect(logout_handler)
#django.contrib.auth.__init.py__
def login(request):
:
user_logged_in.send(sender=user.__class__, request=request, user=user)
post_login.send(sender=None,request=request, user=user)
def logout(request):
:
user_logged_out.send(sender=user.__class__, request=request, user=user)
post_logout.send(sender=None,request=request, user=user)
Please note that I am getting the following error while running my application on google app engine.
Error: Server Error
The server encountered an error and could not complete your request.
Also I am not able to login into Admin part of the application. Please help me to find right approach to implement this requirement or let me know where I am doing wrong.
Thanks for your patience for reading this huge problem description :-)

1.
You should not be editing the django framework like you are doing. Don't touch the files inside django.contrib.auth
If you wish to send a signal after someone is logged in, then send the signal in your view where you log the person in
2.
Not sure what your actual error is because you are not displaying it (if this is a dev environment set DEBUG = True to get a better stack trace) But by lookingat you code, you are not grabbing the arguments correctly in the signal handler. It should look more like this:
def login_handler(sender, **kwargs):
try:
user = kwargs['user']
request = kwargs['request']
result=Visitor.objects.get(user=user)
print "You already have login with your name"
except:
visitor=Visitor()
visitor.user=user
visitor.save()
post_login.connect(login_handler)

Related

Firebase python admin sdk isNewUser ()

Hi i'm currently using firebase admin sdk on my django server to handle my app. I would like to check if user a user first time login on the server side.I would like to use firebase isNewUser() on the django server but in the firebase admin sdk docs i don't see any information related to that.
My server side to get user from token(send from app):
from utils.firebase_utils import auth
class FirebaseAuthentication(authentication.BaseAuthentication):
def authenticate(self, request):
token = request.META['HTTP_AUTHORIZATION']
if not token:
return None
try:
decoded_token = auth.verify_id_token(token)
uid = decoded_token['uid']
user = auth.get_user(uid, app=None)
# need to check if user first time log in too
except Exception as e:
raise exceptions.AuthenticationFailed('No such user')
return (user, None) # authentication successful
How can i check if a user first time login?
There indeed is no isNewUser method in the Admin SDK for Python.
A workaround is to compare the creation_timestamp and last_sign_in_timestamp properties of the UserMetadata object. If the two are close (within 1 second of each other), it is a new user. This is in fact how the documentation said to check for "newness" of a user record before the isNewUser method was introduced, which happened because there was a granularity difference in the two timestamps for a short while.

Require new login for each page view

I am currently using code found here:
http://flask.pocoo.org/snippets/8/
And I decorate my function accordingly to have the admin authenticate when requesting a specific admin page. However, instead of requiring the admin to keep authenticating each time they admin page, I noticed that it somehow keeps track of the session and no longer requires authentication after successfully authenticating once. Is there some way to force flask to re-authenticate every time an admin requests the given decorated admin page?
Using the included snippet, there is no good way to force a user to log in every time they request the given page.
This is because that snippet is using HTTP Basic Auth and there is no good way to ask the browser to stop sending that header.
What you are looking for can be done with a custom decorator. You can use the sample below. Note that your case will be different, but you can use this as a guide.
from web import app, has_role
#app.route("/admin/my_page")
#login_required
#has_role(role="admin")
def admin_my_page():
//do stuff
Then, in your project init, or an include file you can add the following:
def has_role(role=None):
def _initial_decorator(view_func):
def _decorator(*args, **kwargs):
response = view_func(*args, **kwargs)
if g.user.user_level != role:
from flask import redirect, url_for
return redirect(url_for("no_access"))
return response
return wraps(view_func)(_decorator)
return _initial_decorator
This should at lease give you an idea of how to create a custom decorator, and then check for role permissions. You can expand this to however you need. You can put engine logic, or other checks to fit your project.

Using Flask-Social with Oauth Provider(s) Only, No Local Registration/Login Forms

Is it possible to use Flask-Social and Flask-Security if I only want to use Facebook Login, for example, for user registration and login, i.e. no local registration/login forms?
I looked through the Flask-Social example application and documentation but couldn't tell if this is possible. In the example application, users cannot login with Facebook unless they've previously registered. After registering with the example application, they can associate their Facebook account with their local account.
When I tried to call social.facebook.get_connection() I got an AttributeError 'AnonymousUser' object has no attribute 'id' because there's no current_user, which is defined by flask-security after registration/login.
This is doable without too much extra work using the #login_failed.connect_via decorator. With app as your instance of a Flask app, it would look like
#login_failed.connect_via(app):
def on_login_failed(sender, provider, oauth_response):
connection_values = get_connection_values_from_oauth_response(provider, oauth_response)
ds = current_app.security.datastore
user = ds.create_user( ... ) #fill in relevant stuff here
ds.commit()
connection_values['user_id'] = user.id
connect_handler(connection_values, provider)
login_user(user)
db.commit()
return render_template('success.html')
As for filling in the relevant stuff for creating the user, I just create a random string for the password, and haven't had issues leaving the email null. I also just included the exact same answer on the Flask-Social github page.

Django-Registration: How to prevent logged in user from registering?

I've just started to use django-registration. I have two questions:
How do you prevent a logged in user from going to the register page?
How do you automatically sign in a user after activation?
I prefer not changing any code in the app itself.
For question 2, I've already read the docs where it says to write "a function which listens for the appropriate signal; your function should set the backend attribute of the user to the correct authentication backend, and then call django.contrib.auth.login() to log the user in." I don't know django well enough to understand what this means or how to implement this. Could you guys help/point me in the right direction?
Edit:
Tried doing some signals, does not yet work, not sure what's wrong:
def loginActivationCallback(sender, user, request, **kwargs):
print user
print "registered"
user_registered.connect(loginActivationCallback)
Also because I'm using Django 1.5, I didn't do pip install django-registration(does not fully support 1.5), but instead copied the registration folder into my project. Not sure if this affects the signals.
Simply what you can do is check in your register view
if request.user.is_authenticated:
#redirect user to the profile page
return HttpResponseRedirect('/profile/')
from registration.signals import user_activated
def login_user(sender, user, request, **kwargs):
user.backend='django.contrib.auth.backends.ModelBackend'
login(request,user)
user_activated.connect(login_user)

Django Auth , Login Question

Question Clarification:
I'm trying to test if the user is authenticated or not for each page request.
I'm trying to use Authentication for the first time in Django and I am not grasping how the login view is supposed to handle authentications.
When I use #login_required, I'm redirecting to "/login" to check if the user is logged in and if not, display the login page. However, trying to redirect back to the original page is causing an infinite loop because it's sending me back to the login page over and over again.
I'm clearly not grasping how #login_required is supposed to work but I'm not sure what I'm missing. I've been searching around for awhile for an example, but everyone uses the default #login_required without the 'login_url' parameter.
So for example.. the page I'm trying to access would be...
#login_required(login_url='/login')
def index(request):
And then my login would be.. (obviously incomplete)..
Edit: just to note.. the session variables are set in another view
def login(request):
if '_auth_user_id' in request.session:
# just for testing purposes.. to make sure the id is being set
print "id:",request.session['_auth_user_id']
try:
user = Users.objects.get(id=request.session['_auth_user_id'])
except:
raise Exception("Invalid UserID")
# TODO: Check the backend session key
# this is what I'm having trouble with.. I'm not sure how
# to redirect back to the proper view
return redirect('/')
else:
form = LoginForm()
return render_to_response('login.html',
{'form':form},
context_instance=RequestContext(request)
)
Well, as you say, obviously that's not going to work, because it's incomplete. So, until you complete it, you're going to get an infinite loop - because you haven't written the code that puts _auth_user_id into request.session.
But I don't really know why you're making that test in the first place. The auth documentation has a perfectly good example of how to write a login view: get the username and password from the form, send them to authenticate to get the user object, then pass that to login... done.
Edit I think I might see where your confusion is. The login_required decorator itself does the check for whether the user is logged in - that's exactly what it's for. There's no need for you to write any code to do that. Your job is to write the code that actually logs the user in, by calling authenticate and login.
Try to call login(), see the next please:
https://docs.djangoproject.com/en/dev/topics/auth/#django.contrib.auth.login

Categories

Resources