def add_permitted_methods_for_home(resource, request, response): """Add link methods to home endpoint with an on_post_GET hook. The home endpoint doesn't call any database hooks and no on_pre_GET hook. Therefore authentication needs to be done manually so we can check permissions. """ if resource is None: authenticate() data = _get_data(response) try: links = data['_links']['child'] except KeyError: # Other endpoints like `schemaendpoint` might end u here, but don't # have the same 'link' layout as home, so we can just ignore them pass else: # Add links for home for res_link in links: res_name = res_link['title'] # title equals resource if isinstance(resource_auth(res_name), AmivTokenAuth): check_if_admin(res_name) res_link['methods'] = _get_resource_methods(res_name) _set_data(response, data)
def test_token_parsing_in_authentication(self): """Test all possible ways to send a token. 1. As Basic Authorization header with token as user and no password 2. As Authorization Header: 'Token <token>' (also lowercase) 3. A Authorization Header: 'Bearer <token>' (also lowercase) 4. Authorization header with only 'token' Also test that no or incomplete auth header results in `g.current_token = None` """ # No Header with self.app.test_request_context(): authenticate() self.assertIsNone(g.current_token) token = "ThisIsATokenYeahItIsTheContentDoesntReallyMatter" # Encoding dance for py 2/3 compatibility b64token = b64encode((token + ":").encode('utf-8')).decode('utf-8') # Header variations for header in (token, "Token " + token, "Bearer " + token, "SomeotherKeyword " + token, "Basic " + b64token): with self.app.test_request_context( headers={'Authorization': header}): # Call authenticate, the token should be found and put in g authenticate() self.assertEqual(g.current_token, token)
def test_token_parsing_in_authentication(self): """Test all possible ways to send a token. 1. As Basic Authorization header with token as user and no password 2. As Authorization Header: 'Token <token>' (also lowercase) 3. A Authorization Header: 'Bearer <token>' (also lowercase) 4. Authorization header with only 'token' Also test that no or incomplete auth header results in `g.current_token = None` """ # No Header with self.app.test_request_context(): authenticate() self.assertIsNone(g.current_token) token = "ThisIsATokenYeahItIsTheContentDoesntReallyMatter" # Encoding dance for py 2/3 compatibility b64token = b64encode((token + ":").encode('utf-8')).decode('utf-8') # Header variations for header in ( token, "Token " + token, "Bearer " + token, "SomeotherKeyword " + token, "Basic " + b64token): with self.app.test_request_context( headers={'Authorization': header}): # Call authenticate, the token should be found and put in g authenticate() self.assertEqual(g.current_token, token)
def test_session_lookup_in_authentication(self): """Test that sessions associated with a token are found correctly. If there is no session, `current_session` and `current_user` will be None, otherwise `current_session` will be the data as stored in the db and `current_user` the `user` field taken from the session. Also check that if a session is found the timestamp is updated """ collection = self.db['sessions'] # Provide everything for mongo, doesn't matter that we are not using # proper ObjectIds data = [{ u'_id': u'a', u'user': ObjectId(24 * 'a'), u'token': u'sometoken', u'_updated': datetime.utcnow() - timedelta(seconds=1) }, { u'_id': u'b', u'user': ObjectId(24 * 'b'), u'token': u'othertoken', u'_updated': datetime.utcnow() - timedelta(seconds=1) }] # Put into db collection.insert_many(data) for session in data: with self.app.test_request_context( headers={'Authorization': session['token']}): authenticate() # g.current_user shoudl be a string expected_user = str(session['user']) session_in_db = \ self.db['sessions'].find_one({'_id': session['_id']}) self.assertEqual(g.current_session, session_in_db) for key in '_id', 'user', 'token': self.assertEqual(g.current_session[key], session[key]) self.assertEqual(g.current_user, expected_user) # Normally Eve would deal with timezones for us, # here we have to remove the tzinfo to be able to compare the # time (everything is utc anyways) g.current_session['_updated'] = \ g.current_session['_updated'].replace(tzinfo=None) self.assertGreater(g.current_session['_updated'], session['_updated'])
def test_session_lookup_in_authentication(self): """Test that sessions associated with a token are found correctly. If there is no session, `current_session` and `current_user` will be None, otherwise `current_session` will be the data as stored in the db and `current_user` the `user` field taken from the session. Also check that if a session is found the timestamp is updated """ collection = self.db['sessions'] # Provide everything for mongo, doesn't matter that we are not using # proper ObjectIds data = [ {u'_id': u'a', u'user': ObjectId(24 * 'a'), u'token': u'sometoken', u'_updated': datetime.utcnow() - timedelta(seconds=1)}, {u'_id': u'b', u'user': ObjectId(24 * 'b'), u'token': u'othertoken', u'_updated': datetime.utcnow() - timedelta(seconds=1)} ] # Put into db collection.insert(data) for session in data: with self.app.test_request_context( headers={'Authorization': session['token']}): authenticate() # g.current_user shoudl be a string expected_user = str(session['user']) session_in_db = \ self.db['sessions'].find_one({'_id': session['_id']}) self.assertEqual(g.current_session, session_in_db) for key in '_id', 'user', 'token': self.assertEqual(g.current_session[key], session[key]) self.assertEqual(g.current_user, expected_user) # Normally Eve would deal with timezones for us, # here we have to remove the tzinfo to be able to compare the # time (everything is utc anyways) g.current_session['_updated'] = \ g.current_session['_updated'].replace(tzinfo=None) self.assertGreater(g.current_session['_updated'], session['_updated'])
def test_authentication_defaults(self): """Make sure authenticate sets defaults for all auth values.""" expect_none = 'current_token', 'current_user', 'current_session' expect_false = 'resource_admin', 'resource_admin_readonly' with self.app.test_request_context(): # Nothing there before for item in expect_none + expect_false: with self.assertRaises(AttributeError): getattr(g, item) authenticate() for item in expect_none: self.assertIsNone(getattr(g, item)) check_if_admin('someresource') for item in expect_false: self.assertFalse(getattr(g, item))
def add_permitted_methods_for_home(resource, request, response, payload): """Add link methods to home endpoint with an on_post_GET hook. The home endpoint doesn't call any database hooks and no on_pre_GET hook. Therefore authentication needs to be done manually so we can check permissions. """ if resource is None: authenticate() try: links = payload['_links']['child'] except KeyError: # Other endpoints like `schemaendpoint` end up here, but don't # have the same 'link' layout as home, so we can just ignore them pass else: # Add links for home for res_link in links: res_name = res_link['href'] # href equals resource if isinstance(resource_auth(res_name), AmivTokenAuth): check_if_admin(res_name) res_link['methods'] = _get_resource_methods(res_name)