import webapp2
from webapp2_extras import sessions
from webapp2_extras import auth
from webapp2_extras.appengine.auth import models
from google.appengine.ext.ndb import model
import test_base
class TestAuth(test_base.BaseTestCase):
def setUp(self):
super(TestAuth, self).setUp()
self.register_model('User', models.User)
self.register_model('UserToken', models.UserToken)
self.register_model('Unique', models.Unique)
def _check_token(self, user_id, token, subject='auth'):
rv = models.UserToken.get(user=user_id, subject=subject, token=token)
return rv is not None
def test_get_user_by_session(self):
app = webapp2.WSGIApplication(config={
'webapp2_extras.sessions': {
'secret_key': 'foo',
}
})
req = webapp2.Request.blank('/')
rsp = webapp2.Response()
req.app = app
s = auth.get_store(app=app)
a = auth.Auth(request=req)
session_store = sessions.get_store(request=req)
# This won't work.
a.set_session_data({})
self.assertEqual(a.session.get('_user'), None)
# This won't work.
a.session['_user'] = {}
self.assertEqual(a.get_session_data(), None)
self.assertEqual(a.session.get('_user'), None)
# Create a user.
m = models.User
success, user = m.create_user(auth_id='auth_id',
password_raw='password')
user_id = user.key.id()
# Get user with session. An anonymous_user is returned.
rv = a.get_user_by_session()
self.assertTrue(rv is None)
# Login with password. User dict is returned.
rv = a.get_user_by_password('auth_id', 'password')
self.assertEqual(rv['user_id'], user_id)
# Save sessions.
session_store.save_sessions(rsp)
# Get user with session. Voila!
cookies = rsp.headers.get('Set-Cookie')
req = webapp2.Request.blank('/', headers=[('Cookie', cookies)])
rsp = webapp2.Response()
req.app = app
a = auth.Auth(request=req)
# only auth_id is returned when there're no
# custom user attributes defined.
rv = a.get_user_by_session()
self.assertEqual(rv['user_id'], user_id)
# If we call get_user_by_token() now, the same user is returned.
rv2 = a.get_user_by_token(rv['user_id'], rv['token'])
self.assertTrue(rv is rv2)
# Let's get it again and check that token is the same.
token = rv['token']
a._user = None
rv = a.get_user_by_session()
self.assertEqual(rv['user_id'], user_id)
self.assertEqual(rv['token'], token)
# Now let's force token to be renewed and check that we have a new one.
s.config['token_new_age'] = -300
a._user = None
rv = a.get_user_by_session()
self.assertEqual(rv['user_id'], user_id)
self.assertNotEqual(rv['token'], token)
# Now let's force token to be invalid.
s.config['token_max_age'] = -300
a._user = None
rv = a.get_user_by_session()
self.assertEqual(rv, None)
def test_get_user_by_password(self):
app = webapp2.WSGIApplication(config={
'webapp2_extras.sessions': {
'secret_key': 'foo',
}
})
req = webapp2.Request.blank('/')
req.app = app
s = auth.get_store(app=app)
a = auth.get_auth(request=req)
session_store = sessions.get_store(request=req)
m = models.User
success, user = m.create_user(auth_id='auth_id',
password_raw='password')
user_id = user.key.id()
# Lets test the cookie max_age when we use remember=True or False.
rv = a.get_user_by_password('auth_id', 'password', remember=True)
self.assertEqual(rv['user_id'], user_id)
self.assertEqual(session_store.sessions['auth'].session_args['max_age'],
86400 * 7 * 3)
# Now remember=False.
rv = a.get_user_by_password('auth_id', 'password')
self.assertEqual(rv['user_id'], user_id)
self.assertEqual(session_store.sessions['auth'].session_args['max_age'],
None)
# User was set so getting it from session will return the same one.
rv = a.get_user_by_session()
self.assertEqual(rv['user_id'], user_id)
# Now try a failed password submission: user will be unset.
rv = a.get_user_by_password('auth_id', 'password_2', silent=True)
self.assertTrue(rv is None)
# And getting by session will no longer work.
rv = a.get_user_by_session()
self.assertTrue(rv is None)
def test_validate_password(self):
app = webapp2.WSGIApplication()
req = webapp2.Request.blank('/')
req.app = app
s = auth.get_store(app=app)
m = models.User
success, user = m.create_user(auth_id='auth_id',
password_raw='foo')
u = s.validate_password('auth_id', 'foo')
self.assertEqual(u, s.user_to_dict(user))
self.assertRaises(auth.InvalidPasswordError,
s.validate_password, 'auth_id', 'bar')
self.assertRaises(auth.InvalidAuthIdError,
s.validate_password, 'auth_id_2', 'foo')
def test_validate_token(self):
app = webapp2.WSGIApplication()
req = webapp2.Request.blank('/')
req.app = app
s = auth.get_store(app=app)
rv = s.validate_token('auth_id', 'token')
self.assertEqual(rv, (None, None))
# Expired timestamp.
rv = s.validate_token('auth_id', 'token', -300)
self.assertEqual(rv, (None, None))
m = models.User
success, user = m.create_user(auth_id='auth_id',
password_raw='foo')
user_id = user.key.id()
token = m.create_auth_token(user_id)
rv = s.validate_token(user_id, token)
self.assertEqual(rv, (s.user_to_dict(user), token))
# Token must still be there.
self.assertTrue(self._check_token(user_id, token))
# Expired timestamp.
token = m.create_auth_token(user_id)
rv = s.validate_token(user_id, token, -300)
self.assertEqual(rv, (None, None))
# Token must have been deleted.
self.assertFalse(self._check_token(user_id, token))
# Force expiration.
token = m.create_auth_token(user_id)
s.config['token_max_age'] = -300
rv = s.validate_token(user_id, token)
self.assertEqual(rv, (None, None))
# Token must have been deleted.
self.assertFalse(self._check_token(user_id, token))
# Revert expiration, force renewal.
token = m.create_auth_token(user_id)
s.config['token_max_age'] = 86400 * 7 * 3
s.config['token_new_age'] = -300
rv = s.validate_token(user_id, token)
self.assertEqual(rv, (s.user_to_dict(user), None))
# Token must have been deleted.
self.assertFalse(self._check_token(user_id, token))
def test_set_auth_store(self):
app = webapp2.WSGIApplication()
req = webapp2.Request.blank('/')
req.app = app
store = auth.AuthStore(app)
self.assertEqual(len(app.registry), 0)
auth.set_store(store, app=app)
self.assertEqual(len(app.registry), 1)
s = auth.get_store(app=app)
self.assertTrue(isinstance(s, auth.AuthStore))
def test_get_auth_store(self):
app = webapp2.WSGIApplication()
req = webapp2.Request.blank('/')
req.app = app
self.assertEqual(len(app.registry), 0)
s = auth.get_store(app=app)
self.assertEqual(len(app.registry), 1)
self.assertTrue(isinstance(s, auth.AuthStore))
def test_set_auth(self):
app = webapp2.WSGIApplication()
req = webapp2.Request.blank('/')
req.app = app
a = auth.Auth(req)
self.assertEqual(len(req.registry), 0)
auth.set_auth(a, request=req)
self.assertEqual(len(req.registry), 1)
a = auth.get_auth(request=req)
self.assertTrue(isinstance(a, auth.Auth))
def test_get_auth(self):
app = webapp2.WSGIApplication()
req = webapp2.Request.blank('/')
req.app = app
self.assertEqual(len(req.registry), 0)
a = auth.get_auth(request=req)
self.assertEqual(len(req.registry), 1)
self.assertTrue(isinstance(a, auth.Auth))
'''
def test_set_callables(self):
app = webapp2.WSGIApplication()
req = webapp2.Request.blank('/')
req.app = app
s = auth.get_store(app=app)
def validate_password(store, auth_id, password):
self.assertTrue(store is s)
self.assertEqual(auth_id, 'auth_id')
self.assertEqual(password, 'password')
return 'validate_password'
def validate_token(store, auth_id, token, token_ts=None):
self.assertTrue(store is s)
self.assertEqual(auth_id, 'auth_id')
self.assertEqual(token, 'token')
self.assertEqual(token_ts, 'token_ts')
return 'validate_token'
s.set_password_validator(validate_password)
rv = s.validate_password('auth_id', 'password')
self.assertEqual(rv, 'validate_password')
s.set_token_validator(validate_token)
rv = s.validate_token('auth_id', 'token', 'token_ts')
self.assertEqual(rv, 'validate_token')
'''
def test_extended_user(self):
class MyUser(models.User):
newsletter = model.BooleanProperty()
age = model.IntegerProperty()
auth_id = 'own:username'
success, info = MyUser.create_user(auth_id, newsletter=True, age=22)
self.assertTrue(success)
app = webapp2.WSGIApplication(config={
'webapp2_extras.auth': {
'user_model': MyUser,
}
})
s = auth.get_store(app=app)
user = s.user_model.get_by_auth_id(auth_id)
self.assertEqual(info, user)
self.assertEqual(user.age, 22)
self.assertTrue(user.newsletter is True)
if __name__ == '__main__':
test_base.main()