Skip to content

Commit cb1224b

Browse files
author
Isaiah
committed
#1 finished remaining tests/implementation
1 parent 309cf17 commit cb1224b

File tree

3 files changed

+189
-33
lines changed

3 files changed

+189
-33
lines changed

lowball_arangodb_authdb/authdb.py

Lines changed: 46 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,9 @@ def _init_collection(self):
8484
except KeyError:
8585
self.collection = self.database.createCollection(self.collection_name, waitForSync=True)
8686

87+
def get_now(self):
88+
return datetime.utcnow()
89+
8790
@property
8891
def url(self):
8992
return self._url
@@ -211,8 +214,7 @@ def revoke_token(self, token_id):
211214

212215
def revoke_all(self):
213216

214-
for doc in self.collection.fetchAll():
215-
doc.delete()
217+
self.collection.truncate()
216218

217219
def list_tokens(self):
218220

@@ -229,12 +231,50 @@ def list_tokens(self):
229231

230232
def list_tokens_by_client_id(self, client_id):
231233

232-
pass
234+
QUERY = f"""
235+
FOR token in {self.collection_name}
236+
FILTER token.cid == @client_id
237+
RETURN token
238+
"""
239+
bind_vars = {
240+
"client_id": client_id
241+
}
242+
tokens = self.collection.database.AQLQuery(QUERY, bind_vars=bind_vars)
243+
244+
results = []
245+
for token in tokens:
246+
try:
247+
t = Token(**token.getStore())
248+
results.append(t)
249+
except:
250+
token.delete()
251+
return results
233252

234253
def list_tokens_by_role(self, role):
235254

236-
pass
255+
QUERY = f"""
256+
FOR token in {self.collection_name}
257+
FILTER @role in token.r
258+
return token
259+
"""
260+
bind_vars = {
261+
"role": role
262+
}
263+
tokens = self.collection.database.AQLQuery(QUERY, bind_vars=bind_vars)
264+
265+
results = []
266+
for token in tokens:
267+
try:
268+
t = Token(**token.getStore())
269+
results.append(t)
270+
except:
271+
token.delete()
272+
return results
237273

238274
def cleanup_tokens(self):
239-
240-
pass
275+
QUERY = f"""
276+
FOR token in {self.collection_name}
277+
FILTER token.ets < "{str(self.get_now()).split(".")[0]}"
278+
REMOVE token
279+
"""
280+
self.collection.database.AQLQuery(QUERY)

tests/conftest.py

Lines changed: 75 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -244,8 +244,7 @@ def __init__(self, *args, **kwargs):
244244
class TestMockCollection(Collection):
245245

246246
def __init__(self, *args, **kwargs):
247-
248-
pass
247+
self.database = TestMockDatabase()
249248

250249
class TestMockDocument(Document):
251250

@@ -333,6 +332,13 @@ def mock_get_item(value):
333332
def mock_auth_db(monkeypatch):
334333

335334
monkeypatch.setattr(AuthDB, "__init__", Mock(return_value=None))
335+
AuthDB.url = "http://127.0.0.1"
336+
AuthDB.port = 8529
337+
AuthDB.user = "root"
338+
AuthDB.password = None
339+
AuthDB.verify = True
340+
AuthDB.database_name = "lowball_authdb"
341+
AuthDB.collection_name = "authentication_tokens"
336342
AuthDB.collection = TestMockCollection()
337343

338344

@@ -466,7 +472,7 @@ def mock_collection_fetch_all():
466472
monkeypatch.setattr(TestMockCollection, "fetchDocument", Mock(wraps=mock_collection_fetch_document))
467473
monkeypatch.setattr(TestMockCollection, "__getitem__", Mock(wraps=mock_collection_getitem))
468474
monkeypatch.setattr(TestMockCollection, "fetchAll", Mock(wraps=mock_collection_fetch_all))
469-
475+
monkeypatch.setattr(TestMockCollection, "truncate", Mock())
470476

471477
@pytest.fixture
472478
def mock_filled_token_collection_bad_values(token_dict_map, monkeypatch, mocked_document):
@@ -725,3 +731,69 @@ def admin_user2_test_token2(test_token_id8, admin_user_id2, admin_role, test_rol
725731
tid=test_token_id8
726732
)
727733

734+
@pytest.fixture
735+
def list_tokens_by_client_id_request_response(
736+
basic_user1_test_token1,
737+
basic_user1_test_token2,
738+
basic_user_id1,
739+
monkeypatch
740+
):
741+
742+
response = [basic_user1_test_token1, basic_user1_test_token2]
743+
response_documents = []
744+
for token in response:
745+
doc = TestMockDocument()
746+
doc.token_json = token.to_dict()
747+
doc.test_key = token.token_id
748+
response_documents.append(doc)
749+
bad_doc = TestMockDocument()
750+
bad_doc.token_json = {
751+
"bad_value": "not token"
752+
}
753+
bad_doc.test_key = "bigbaddoc"
754+
response_documents.append(bad_doc)
755+
monkeypatch.setattr(TestMockDatabase, "AQLQuery", Mock(return_value=response_documents))
756+
return basic_user_id1, response
757+
758+
@pytest.fixture
759+
def list_tokens_by_role_request_response(
760+
basic_user1_test_token1,
761+
basic_user1_test_token2,
762+
basic_user2_test_token1,
763+
basic_user2_test_token2,
764+
admin_user1_test_token1,
765+
admin_user2_test_token1,
766+
admin_role,
767+
test_role1,
768+
test_role2,
769+
monkeypatch
770+
):
771+
772+
response = [admin_user1_test_token1, admin_user2_test_token1]
773+
response_documents = []
774+
for token in response:
775+
doc = TestMockDocument()
776+
doc.token_json = token.to_dict()
777+
doc.test_key = token.token_id
778+
response_documents.append(doc)
779+
780+
bad_doc = TestMockDocument()
781+
bad_doc.token_json = {
782+
"bad_value": "not token"
783+
}
784+
bad_doc.test_key = "bigbaddoc"
785+
response_documents.append(bad_doc)
786+
monkeypatch.setattr(TestMockDatabase, "AQLQuery", Mock(return_value=response_documents))
787+
return admin_role, response
788+
789+
790+
@pytest.fixture
791+
def fake_utcnow(monkeypatch):
792+
from datetime import datetime
793+
now = datetime.utcnow()
794+
monkeypatch.setattr(AuthDB, "get_now", Mock(return_value=now))
795+
return now
796+
797+
@pytest.fixture
798+
def simple_mock_aql_query(monkeypatch):
799+
monkeypatch.setattr(TestMockDatabase, "AQLQuery", Mock(return_value=[]))

tests/test_authdb.py

Lines changed: 68 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -392,7 +392,7 @@ def test_calls_delete_on_token_document_when_found(self,
392392

393393
class TestRevokeAll:
394394

395-
def test_calls_delete_on_each_document_in_the_database(self,
395+
def test_calls_revoke_all_on_the_collection(self,
396396
mock_pyarango,
397397
mock_auth_db,
398398
mock_filled_token_collection,
@@ -401,9 +401,7 @@ def test_calls_delete_on_each_document_in_the_database(self,
401401

402402
authdb = AuthDB()
403403
assert authdb.revoke_all() is None
404-
# 6 because that's how many tokens are in our mocked collection map
405-
assert lowball_arangodb_authdb.authdb.Document.delete.call_count == 6
406-
404+
authdb.collection.truncate.assert_called_once()
407405

408406
class TestListTokens:
409407

@@ -468,45 +466,91 @@ class TestListTokensByClientID:
468466
469467
"""
470468

471-
def test_returns_list_of_token_objects(self):
472-
pass
469+
QUERY = """
470+
FOR token in {}
471+
FILTER token.cid == @client_id
472+
RETURN token
473+
"""
473474

474-
def test_all_tokens_in_list_are_owned_by_the_specified_client_id(self):
475-
"""Not sure we can test this properly, as the actual filtering is done on the arango side
475+
def test_calls_query_as_expected_and_cleans_up_bad_tokens(self,
476+
mock_pyarango,
477+
mock_auth_db,
478+
mock_filled_token_collection,
479+
mock_document_delete,
480+
list_tokens_by_client_id_request_response
481+
):
476482

477-
all we can test is calling the query correctly
483+
authdb = AuthDB()
484+
expected_query = self.QUERY.format(authdb.collection_name)
485+
486+
client_id, expected_response = list_tokens_by_client_id_request_response
478487

479-
"""
480-
pass
488+
expected_bind_vars = {
489+
"client_id": client_id
490+
}
481491

482-
def test_aql_query_called_with_correct_inputs(self):
492+
results = authdb.list_tokens_by_client_id(client_id)
483493

484-
pass
494+
assert all(token in results for token in expected_response) and all(token in expected_response for token in results)
495+
authdb.collection.database.AQLQuery.assert_called_once_with(expected_query, bind_vars=expected_bind_vars)
496+
lowball_arangodb_authdb.authdb.Document.delete.assert_called_once()
485497

486498

487499
class TestListTokensByRole:
488500
"""This may be an aql queryable option as well, will hae to investigate
489501
490502
"""
491-
def test_returns_list_of_token_objects(self):
492-
pass
493503

494-
def test_all_tokens_in_list_possess_the_requested_role(self):
504+
QUERY = """
505+
FOR token in {}
506+
FILTER @role in token.r
507+
return token
508+
"""
509+
510+
def test_calls_query_as_expected_and_cleans_up_bad_tokens(self,
511+
mock_pyarango,
512+
mock_auth_db,
513+
mock_filled_token_collection,
514+
mock_document_delete,
515+
list_tokens_by_role_request_response
516+
):
517+
authdb = AuthDB()
518+
expected_query = self.QUERY.format(authdb.collection_name)
495519

496-
pass
520+
role, expected_response = list_tokens_by_role_request_response
497521

498-
def test_aql_query_called_with_correct_inputs(self):
499-
pass
522+
expected_bind_vars = {
523+
"role": role
524+
}
525+
526+
results = authdb.list_tokens_by_role(role)
527+
528+
assert all(token in results for token in expected_response) and all(
529+
token in expected_response for token in results)
530+
authdb.collection.database.AQLQuery.assert_called_once_with(expected_query, bind_vars=expected_bind_vars)
531+
lowball_arangodb_authdb.authdb.Document.delete.assert_called_once()
500532

501533

502534
class TestCleanupTokens:
503535
"""i believe this is again an aql query we can do
504536
505537
"""
506-
def test_calls_delete_on_all_tokens_which_are_expired(self):
507-
508-
pass
538+
QUERY = """
539+
FOR token in {}
540+
FILTER token.ets < "{}"
541+
REMOVE token
542+
"""
543+
def test_aql_query_called_with_correct_inputs(self,
544+
fake_utcnow,
545+
simple_mock_aql_query,
546+
mock_pyarango,
547+
mock_auth_db
548+
):
549+
authdb = AuthDB()
550+
now = fake_utcnow
551+
search_date = str(now).split(".")[0]
552+
expected_query = self.QUERY.format(authdb.collection_name, search_date)
509553

510-
def test_aql_query_called_with_correct_inputs(self):
554+
authdb.cleanup_tokens()
511555

512-
pass
556+
authdb.collection.database.AQLQuery.assert_called_once_with(expected_query)

0 commit comments

Comments
 (0)