From 0c6ccca5fac44ab40671627fd3181e9b138672fa Mon Sep 17 00:00:00 2001 From: Fabian Mastenbroek Date: Fri, 14 May 2021 15:17:49 +0200 Subject: api: Migrate to Auth0 for API authorization This change updates the OpenDC API to use Auth0 for API authorization. This removes the hard dependency on Google for logging into OpenDC and simplifies implementation as we do not have to store user information anymore, other than the user identifier. --- .../opendc-web-api/opendc/api/v2/prefabs/authorizations/endpoint.py | 2 +- opendc-web/opendc-web-api/opendc/api/v2/prefabs/endpoint.py | 2 +- .../opendc-web-api/opendc/api/v2/prefabs/prefabId/endpoint.py | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) (limited to 'opendc-web/opendc-web-api/opendc/api/v2/prefabs') diff --git a/opendc-web/opendc-web-api/opendc/api/v2/prefabs/authorizations/endpoint.py b/opendc-web/opendc-web-api/opendc/api/v2/prefabs/authorizations/endpoint.py index 0d9ad5cd..0de50851 100644 --- a/opendc-web/opendc-web-api/opendc/api/v2/prefabs/authorizations/endpoint.py +++ b/opendc-web/opendc-web-api/opendc/api/v2/prefabs/authorizations/endpoint.py @@ -7,7 +7,7 @@ from opendc.util.rest import Response def GET(request): """Return all prefabs the user is authorized to access""" - user = User.from_google_id(request.google_id) + user = User.from_google_id(request.current_user['sub']) user.check_exists() diff --git a/opendc-web/opendc-web-api/opendc/api/v2/prefabs/endpoint.py b/opendc-web/opendc-web-api/opendc/api/v2/prefabs/endpoint.py index 723a2f0d..e77c7150 100644 --- a/opendc-web/opendc-web-api/opendc/api/v2/prefabs/endpoint.py +++ b/opendc-web/opendc-web-api/opendc/api/v2/prefabs/endpoint.py @@ -15,7 +15,7 @@ def POST(request): prefab.set_property('datetimeCreated', Database.datetime_to_string(datetime.now())) prefab.set_property('datetimeLastEdited', Database.datetime_to_string(datetime.now())) - user = User.from_google_id(request.google_id) + user = User.from_google_id(request.current_user['sub']) prefab.set_property('authorId', user.get_id()) prefab.insert() diff --git a/opendc-web/opendc-web-api/opendc/api/v2/prefabs/prefabId/endpoint.py b/opendc-web/opendc-web-api/opendc/api/v2/prefabs/prefabId/endpoint.py index 7b81f546..f1cf1fcd 100644 --- a/opendc-web/opendc-web-api/opendc/api/v2/prefabs/prefabId/endpoint.py +++ b/opendc-web/opendc-web-api/opendc/api/v2/prefabs/prefabId/endpoint.py @@ -12,7 +12,7 @@ def GET(request): prefab = Prefab.from_id(request.params_path['prefabId']) prefab.check_exists() - prefab.check_user_access(request.google_id) + prefab.check_user_access(request.current_user['sub']) return Response(200, 'Successfully retrieved prefab', prefab.obj) @@ -25,7 +25,7 @@ def PUT(request): prefab = Prefab.from_id(request.params_path['prefabId']) prefab.check_exists() - prefab.check_user_access(request.google_id) + prefab.check_user_access(request.current_user['sub']) prefab.set_property('name', request.params_body['prefab']['name']) prefab.set_property('rack', request.params_body['prefab']['rack']) @@ -43,7 +43,7 @@ def DELETE(request): prefab = Prefab.from_id(request.params_path['prefabId']) prefab.check_exists() - prefab.check_user_access(request.google_id) + prefab.check_user_access(request.current_user['sub']) old_object = prefab.delete() -- cgit v1.2.3 From 05d2318538eba71ac0555dc5ec146499d9cb0592 Mon Sep 17 00:00:00 2001 From: Fabian Mastenbroek Date: Fri, 14 May 2021 16:50:23 +0200 Subject: api: Remove user handling from OpenDC API server This change removes any of the user handling and endpoints from the OpenDC API server. The API server does not need to store user information other than an identifier in the database. --- .../opendc/api/v2/prefabs/authorizations/endpoint.py | 7 ++----- opendc-web/opendc-web-api/opendc/api/v2/prefabs/endpoint.py | 5 ++--- .../opendc-web-api/opendc/api/v2/prefabs/prefabId/test_endpoint.py | 6 +++--- 3 files changed, 7 insertions(+), 11 deletions(-) (limited to 'opendc-web/opendc-web-api/opendc/api/v2/prefabs') diff --git a/opendc-web/opendc-web-api/opendc/api/v2/prefabs/authorizations/endpoint.py b/opendc-web/opendc-web-api/opendc/api/v2/prefabs/authorizations/endpoint.py index 0de50851..5a8d367f 100644 --- a/opendc-web/opendc-web-api/opendc/api/v2/prefabs/authorizations/endpoint.py +++ b/opendc-web/opendc-web-api/opendc/api/v2/prefabs/authorizations/endpoint.py @@ -1,17 +1,14 @@ from opendc.models.prefab import Prefab from opendc.util.database import DB -from opendc.models.user import User from opendc.util.rest import Response def GET(request): """Return all prefabs the user is authorized to access""" - user = User.from_google_id(request.current_user['sub']) + user_id = request.current_user['sub'] - user.check_exists() - - own_prefabs = DB.fetch_all({'authorId': user.get_id()}, Prefab.collection_name) + own_prefabs = DB.fetch_all({'authorId': user_id}, Prefab.collection_name) public_prefabs = DB.fetch_all({'visibility': 'public'}, Prefab.collection_name) authorizations = {"authorizations": []} diff --git a/opendc-web/opendc-web-api/opendc/api/v2/prefabs/endpoint.py b/opendc-web/opendc-web-api/opendc/api/v2/prefabs/endpoint.py index e77c7150..4a30f7eb 100644 --- a/opendc-web/opendc-web-api/opendc/api/v2/prefabs/endpoint.py +++ b/opendc-web/opendc-web-api/opendc/api/v2/prefabs/endpoint.py @@ -1,7 +1,6 @@ from datetime import datetime from opendc.models.prefab import Prefab -from opendc.models.user import User from opendc.util.database import Database from opendc.util.rest import Response @@ -15,8 +14,8 @@ def POST(request): prefab.set_property('datetimeCreated', Database.datetime_to_string(datetime.now())) prefab.set_property('datetimeLastEdited', Database.datetime_to_string(datetime.now())) - user = User.from_google_id(request.current_user['sub']) - prefab.set_property('authorId', user.get_id()) + user_id = request.current_user['sub'] + prefab.set_property('authorId', user_id) prefab.insert() diff --git a/opendc-web/opendc-web-api/opendc/api/v2/prefabs/prefabId/test_endpoint.py b/opendc-web/opendc-web-api/opendc/api/v2/prefabs/prefabId/test_endpoint.py index 2daeb6bf..bc3b1a32 100644 --- a/opendc-web/opendc-web-api/opendc/api/v2/prefabs/prefabId/test_endpoint.py +++ b/opendc-web/opendc-web-api/opendc/api/v2/prefabs/prefabId/test_endpoint.py @@ -32,7 +32,7 @@ def test_get_private_prefab(client, mocker): DB.fetch_one.side_effect = [{ '_id': test_id, 'name': 'test prefab', - 'authorId': test_id, + 'authorId': 'test', 'visibility': 'private', 'rack': {} }, @@ -92,7 +92,7 @@ def test_update_prefab(client, mocker): DB.fetch_one.side_effect = [{ '_id': test_id, 'name': 'test prefab', - 'authorId': test_id, + 'authorId': 'test', 'visibility': 'private', 'rack': {} }, @@ -132,7 +132,7 @@ def test_delete_prefab(client, mocker): DB.fetch_one.side_effect = [{ '_id': test_id, 'name': 'test prefab', - 'authorId': test_id, + 'authorId': 'test', 'visibility': 'private', 'rack': {} }, -- cgit v1.2.3 From 2281d3265423d01e60f8cc088de5a5730bb8a910 Mon Sep 17 00:00:00 2001 From: Fabian Mastenbroek Date: Sat, 15 May 2021 13:09:06 +0200 Subject: api: Migrate to Flask Restful This change updates the API to use Flask Restful instead of our own in-house REST library. This change reduces the maintenance effort and allows us to drastically simplify the API implementation needed for the OpenDC v2 API. --- .../opendc/api/v2/prefabs/__init__.py | 0 .../api/v2/prefabs/authorizations/__init__.py | 0 .../api/v2/prefabs/authorizations/endpoint.py | 19 --- .../api/v2/prefabs/authorizations/test_endpoint.py | 71 ---------- .../opendc/api/v2/prefabs/endpoint.py | 22 ---- .../opendc/api/v2/prefabs/prefabId/__init__.py | 0 .../opendc/api/v2/prefabs/prefabId/endpoint.py | 50 ------- .../api/v2/prefabs/prefabId/test_endpoint.py | 145 --------------------- .../opendc/api/v2/prefabs/test_endpoint.py | 24 ---- 9 files changed, 331 deletions(-) delete mode 100644 opendc-web/opendc-web-api/opendc/api/v2/prefabs/__init__.py delete mode 100644 opendc-web/opendc-web-api/opendc/api/v2/prefabs/authorizations/__init__.py delete mode 100644 opendc-web/opendc-web-api/opendc/api/v2/prefabs/authorizations/endpoint.py delete mode 100644 opendc-web/opendc-web-api/opendc/api/v2/prefabs/authorizations/test_endpoint.py delete mode 100644 opendc-web/opendc-web-api/opendc/api/v2/prefabs/endpoint.py delete mode 100644 opendc-web/opendc-web-api/opendc/api/v2/prefabs/prefabId/__init__.py delete mode 100644 opendc-web/opendc-web-api/opendc/api/v2/prefabs/prefabId/endpoint.py delete mode 100644 opendc-web/opendc-web-api/opendc/api/v2/prefabs/prefabId/test_endpoint.py delete mode 100644 opendc-web/opendc-web-api/opendc/api/v2/prefabs/test_endpoint.py (limited to 'opendc-web/opendc-web-api/opendc/api/v2/prefabs') diff --git a/opendc-web/opendc-web-api/opendc/api/v2/prefabs/__init__.py b/opendc-web/opendc-web-api/opendc/api/v2/prefabs/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/opendc-web/opendc-web-api/opendc/api/v2/prefabs/authorizations/__init__.py b/opendc-web/opendc-web-api/opendc/api/v2/prefabs/authorizations/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/opendc-web/opendc-web-api/opendc/api/v2/prefabs/authorizations/endpoint.py b/opendc-web/opendc-web-api/opendc/api/v2/prefabs/authorizations/endpoint.py deleted file mode 100644 index 5a8d367f..00000000 --- a/opendc-web/opendc-web-api/opendc/api/v2/prefabs/authorizations/endpoint.py +++ /dev/null @@ -1,19 +0,0 @@ -from opendc.models.prefab import Prefab -from opendc.util.database import DB -from opendc.util.rest import Response - - -def GET(request): - """Return all prefabs the user is authorized to access""" - - user_id = request.current_user['sub'] - - own_prefabs = DB.fetch_all({'authorId': user_id}, Prefab.collection_name) - public_prefabs = DB.fetch_all({'visibility': 'public'}, Prefab.collection_name) - - authorizations = {"authorizations": []} - - authorizations["authorizations"].append(own_prefabs) - authorizations["authorizations"].append(public_prefabs) - - return Response(200, 'Successfully fetched authorizations.', authorizations) diff --git a/opendc-web/opendc-web-api/opendc/api/v2/prefabs/authorizations/test_endpoint.py b/opendc-web/opendc-web-api/opendc/api/v2/prefabs/authorizations/test_endpoint.py deleted file mode 100644 index 6d36d428..00000000 --- a/opendc-web/opendc-web-api/opendc/api/v2/prefabs/authorizations/test_endpoint.py +++ /dev/null @@ -1,71 +0,0 @@ -from opendc.util.database import DB -from unittest.mock import Mock - -test_id = 24 * '1' - - -def test_get_authorizations(client, mocker): - DB.fetch_all = Mock() - mocker.patch.object(DB, 'fetch_one', return_value={'_id': test_id}) - DB.fetch_all.side_effect = [ - [{ - '_id': test_id, - 'datetimeCreated': '000', - 'datetimeLastEdited': '000', - 'authorId': test_id, - 'visibility' : 'private' - }, - { - '_id': '2' * 24, - 'datetimeCreated': '000', - 'datetimeLastEdited': '000', - 'authorId': test_id, - 'visibility' : 'private' - }, - { - '_id': '3' * 24, - 'datetimeCreated': '000', - 'datetimeLastEdited': '000', - 'authorId': test_id, - 'visibility' : 'public' - }, - { - '_id': '4' * 24, - 'datetimeCreated': '000', - 'datetimeLastEdited': '000', - 'authorId': test_id, - 'visibility' : 'public' - }], - [{ - '_id': '5' * 24, - 'datetimeCreated': '000', - 'datetimeLastEdited': '000', - 'authorId': '2' * 24, - 'visibility' : 'public' - }, - { - '_id': '6' * 24, - 'datetimeCreated': '000', - 'datetimeLastEdited': '000', - 'authorId': '2' * 24, - 'visibility' : 'public' - }, - { - '_id': '7' * 24, - 'datetimeCreated': '000', - 'datetimeLastEdited': '000', - 'authorId': '2' * 24, - 'visibility' : 'public' - }, - { - '_id': '8' * 24, - 'datetimeCreated': '000', - 'datetimeLastEdited': '000', - 'authorId': '2' * 24, - 'visibility' : 'public' - }] - ] - mocker.patch.object(DB, 'fetch_one', return_value={'_id': test_id}) - res = client.get('/v2/prefabs/authorizations') - assert '200' in res.status - diff --git a/opendc-web/opendc-web-api/opendc/api/v2/prefabs/endpoint.py b/opendc-web/opendc-web-api/opendc/api/v2/prefabs/endpoint.py deleted file mode 100644 index 4a30f7eb..00000000 --- a/opendc-web/opendc-web-api/opendc/api/v2/prefabs/endpoint.py +++ /dev/null @@ -1,22 +0,0 @@ -from datetime import datetime - -from opendc.models.prefab import Prefab -from opendc.util.database import Database -from opendc.util.rest import Response - - -def POST(request): - """Create a new prefab, and return that new prefab.""" - - request.check_required_parameters(body={'prefab': {'name': 'string'}}) - - prefab = Prefab(request.params_body['prefab']) - prefab.set_property('datetimeCreated', Database.datetime_to_string(datetime.now())) - prefab.set_property('datetimeLastEdited', Database.datetime_to_string(datetime.now())) - - user_id = request.current_user['sub'] - prefab.set_property('authorId', user_id) - - prefab.insert() - - return Response(200, 'Successfully created prefab.', prefab.obj) diff --git a/opendc-web/opendc-web-api/opendc/api/v2/prefabs/prefabId/__init__.py b/opendc-web/opendc-web-api/opendc/api/v2/prefabs/prefabId/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/opendc-web/opendc-web-api/opendc/api/v2/prefabs/prefabId/endpoint.py b/opendc-web/opendc-web-api/opendc/api/v2/prefabs/prefabId/endpoint.py deleted file mode 100644 index f1cf1fcd..00000000 --- a/opendc-web/opendc-web-api/opendc/api/v2/prefabs/prefabId/endpoint.py +++ /dev/null @@ -1,50 +0,0 @@ -from datetime import datetime - -from opendc.models.prefab import Prefab -from opendc.util.database import Database -from opendc.util.rest import Response - - -def GET(request): - """Get this Prefab.""" - - request.check_required_parameters(path={'prefabId': 'string'}) - - prefab = Prefab.from_id(request.params_path['prefabId']) - prefab.check_exists() - prefab.check_user_access(request.current_user['sub']) - - return Response(200, 'Successfully retrieved prefab', prefab.obj) - - -def PUT(request): - """Update a prefab's name and/or contents.""" - - request.check_required_parameters(body={'prefab': {'name': 'name'}}, path={'prefabId': 'string'}) - - prefab = Prefab.from_id(request.params_path['prefabId']) - - prefab.check_exists() - prefab.check_user_access(request.current_user['sub']) - - prefab.set_property('name', request.params_body['prefab']['name']) - prefab.set_property('rack', request.params_body['prefab']['rack']) - prefab.set_property('datetime_last_edited', Database.datetime_to_string(datetime.now())) - prefab.update() - - return Response(200, 'Successfully updated prefab.', prefab.obj) - - -def DELETE(request): - """Delete this Prefab.""" - - request.check_required_parameters(path={'prefabId': 'string'}) - - prefab = Prefab.from_id(request.params_path['prefabId']) - - prefab.check_exists() - prefab.check_user_access(request.current_user['sub']) - - old_object = prefab.delete() - - return Response(200, 'Successfully deleted prefab.', old_object) diff --git a/opendc-web/opendc-web-api/opendc/api/v2/prefabs/prefabId/test_endpoint.py b/opendc-web/opendc-web-api/opendc/api/v2/prefabs/prefabId/test_endpoint.py deleted file mode 100644 index bc3b1a32..00000000 --- a/opendc-web/opendc-web-api/opendc/api/v2/prefabs/prefabId/test_endpoint.py +++ /dev/null @@ -1,145 +0,0 @@ -from opendc.util.database import DB -from unittest.mock import Mock - -test_id = 24 * '1' -test_id_2 = 24 * '2' - - -def test_get_prefab_non_existing(client, mocker): - mocker.patch.object(DB, 'fetch_one', return_value=None) - assert '404' in client.get(f'/v2/prefabs/{test_id}').status - - -def test_get_private_prefab_not_authorized(client, mocker): - DB.fetch_one = Mock() - DB.fetch_one.side_effect = [{ - '_id': test_id, - 'name': 'test prefab', - 'authorId': test_id_2, - 'visibility': 'private', - 'rack': {} - }, - { - '_id': test_id - } - ] - res = client.get(f'/v2/prefabs/{test_id}') - assert '403' in res.status - - -def test_get_private_prefab(client, mocker): - DB.fetch_one = Mock() - DB.fetch_one.side_effect = [{ - '_id': test_id, - 'name': 'test prefab', - 'authorId': 'test', - 'visibility': 'private', - 'rack': {} - }, - { - '_id': test_id - } - ] - res = client.get(f'/v2/prefabs/{test_id}') - assert '200' in res.status - - -def test_get_public_prefab(client, mocker): - DB.fetch_one = Mock() - DB.fetch_one.side_effect = [{ - '_id': test_id, - 'name': 'test prefab', - 'authorId': test_id_2, - 'visibility': 'public', - 'rack': {} - }, - { - '_id': test_id - } - ] - res = client.get(f'/v2/prefabs/{test_id}') - assert '200' in res.status - - -def test_update_prefab_missing_parameter(client): - assert '400' in client.put(f'/v2/prefabs/{test_id}').status - - -def test_update_prefab_non_existing(client, mocker): - mocker.patch.object(DB, 'fetch_one', return_value=None) - assert '404' in client.put(f'/v2/prefabs/{test_id}', json={'prefab': {'name': 'S'}}).status - - -def test_update_prefab_not_authorized(client, mocker): - DB.fetch_one = Mock() - DB.fetch_one.side_effect = [{ - '_id': test_id, - 'name': 'test prefab', - 'authorId': test_id_2, - 'visibility': 'private', - 'rack': {} - }, - { - '_id': test_id - } - ] - mocker.patch.object(DB, 'update', return_value={}) - assert '403' in client.put(f'/v2/prefabs/{test_id}', json={'prefab': {'name': 'test prefab', 'rack': {}}}).status - - -def test_update_prefab(client, mocker): - DB.fetch_one = Mock() - DB.fetch_one.side_effect = [{ - '_id': test_id, - 'name': 'test prefab', - 'authorId': 'test', - 'visibility': 'private', - 'rack': {} - }, - { - '_id': test_id - } - ] - mocker.patch.object(DB, 'update', return_value={}) - res = client.put(f'/v2/prefabs/{test_id}', json={'prefab': {'name': 'test prefab', 'rack': {}}}) - assert '200' in res.status - - -def test_delete_prefab_non_existing(client, mocker): - mocker.patch.object(DB, 'fetch_one', return_value=None) - assert '404' in client.delete(f'/v2/prefabs/{test_id}').status - - -def test_delete_prefab_different_user(client, mocker): - DB.fetch_one = Mock() - DB.fetch_one.side_effect = [{ - '_id': test_id, - 'name': 'test prefab', - 'authorId': test_id_2, - 'visibility': 'private', - 'rack': {} - }, - { - '_id': test_id - } - ] - mocker.patch.object(DB, 'delete_one', return_value=None) - assert '403' in client.delete(f'/v2/prefabs/{test_id}').status - - -def test_delete_prefab(client, mocker): - DB.fetch_one = Mock() - DB.fetch_one.side_effect = [{ - '_id': test_id, - 'name': 'test prefab', - 'authorId': 'test', - 'visibility': 'private', - 'rack': {} - }, - { - '_id': test_id - } - ] - mocker.patch.object(DB, 'delete_one', return_value={'prefab': {'name': 'name'}}) - res = client.delete(f'/v2/prefabs/{test_id}') - assert '200' in res.status diff --git a/opendc-web/opendc-web-api/opendc/api/v2/prefabs/test_endpoint.py b/opendc-web/opendc-web-api/opendc/api/v2/prefabs/test_endpoint.py deleted file mode 100644 index 39a78c21..00000000 --- a/opendc-web/opendc-web-api/opendc/api/v2/prefabs/test_endpoint.py +++ /dev/null @@ -1,24 +0,0 @@ -from opendc.util.database import DB - -test_id = 24 * '1' - - -def test_add_prefab_missing_parameter(client): - assert '400' in client.post('/v2/prefabs').status - - -def test_add_prefab(client, mocker): - mocker.patch.object(DB, 'fetch_one', return_value={'_id': test_id, 'authorizations': []}) - mocker.patch.object(DB, - 'insert', - return_value={ - '_id': test_id, - 'datetimeCreated': '000', - 'datetimeLastEdited': '000', - 'authorId': test_id - }) - res = client.post('/v2/prefabs', json={'prefab': {'name': 'test prefab'}}) - assert 'datetimeCreated' in res.json['content'] - assert 'datetimeLastEdited' in res.json['content'] - assert 'authorId' in res.json['content'] - assert '200' in res.status -- cgit v1.2.3