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/opendc-web-api/opendc/api/v2/projects/endpoint.py | 2 +- .../opendc/api/v2/projects/projectId/authorizations/endpoint.py | 2 +- .../opendc-web-api/opendc/api/v2/projects/projectId/endpoint.py | 8 ++++---- .../opendc/api/v2/projects/projectId/portfolios/endpoint.py | 2 +- .../opendc/api/v2/projects/projectId/topologies/endpoint.py | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) (limited to 'opendc-web/opendc-web-api/opendc/api/v2/projects') diff --git a/opendc-web/opendc-web-api/opendc/api/v2/projects/endpoint.py b/opendc-web/opendc-web-api/opendc/api/v2/projects/endpoint.py index bf031382..dacbe6a4 100644 --- a/opendc-web/opendc-web-api/opendc/api/v2/projects/endpoint.py +++ b/opendc-web/opendc-web-api/opendc/api/v2/projects/endpoint.py @@ -25,7 +25,7 @@ def POST(request): topology.set_property('projectId', project.get_id()) topology.update() - user = User.from_google_id(request.google_id) + user = User.from_google_id(request.current_user['sub']) user.obj['authorizations'].append({'projectId': project.get_id(), 'authorizationLevel': 'OWN'}) user.update() diff --git a/opendc-web/opendc-web-api/opendc/api/v2/projects/projectId/authorizations/endpoint.py b/opendc-web/opendc-web-api/opendc/api/v2/projects/projectId/authorizations/endpoint.py index 9f6a60ec..1b229122 100644 --- a/opendc-web/opendc-web-api/opendc/api/v2/projects/projectId/authorizations/endpoint.py +++ b/opendc-web/opendc-web-api/opendc/api/v2/projects/projectId/authorizations/endpoint.py @@ -10,7 +10,7 @@ def GET(request): project = Project.from_id(request.params_path['projectId']) project.check_exists() - project.check_user_access(request.google_id, False) + project.check_user_access(request.current_user['sub'], False) authorizations = project.get_all_authorizations() diff --git a/opendc-web/opendc-web-api/opendc/api/v2/projects/projectId/endpoint.py b/opendc-web/opendc-web-api/opendc/api/v2/projects/projectId/endpoint.py index caac37ca..37cf1860 100644 --- a/opendc-web/opendc-web-api/opendc/api/v2/projects/projectId/endpoint.py +++ b/opendc-web/opendc-web-api/opendc/api/v2/projects/projectId/endpoint.py @@ -16,7 +16,7 @@ def GET(request): project = Project.from_id(request.params_path['projectId']) project.check_exists() - project.check_user_access(request.google_id, False) + project.check_user_access(request.current_user['sub'], False) return Response(200, 'Successfully retrieved project', project.obj) @@ -29,7 +29,7 @@ def PUT(request): project = Project.from_id(request.params_path['projectId']) project.check_exists() - project.check_user_access(request.google_id, True) + project.check_user_access(request.current_user['sub'], True) project.set_property('name', request.params_body['project']['name']) project.set_property('datetime_last_edited', Database.datetime_to_string(datetime.now())) @@ -46,7 +46,7 @@ def DELETE(request): project = Project.from_id(request.params_path['projectId']) project.check_exists() - project.check_user_access(request.google_id, True) + project.check_user_access(request.current_user['sub'], True) for topology_id in project.obj['topologyIds']: topology = Topology.from_id(topology_id) @@ -56,7 +56,7 @@ def DELETE(request): portfolio = Portfolio.from_id(portfolio_id) portfolio.delete() - user = User.from_google_id(request.google_id) + user = User.from_google_id(request.current_user['sub']) user.obj['authorizations'] = list( filter(lambda x: x['projectId'] != project.get_id(), user.obj['authorizations'])) user.update() diff --git a/opendc-web/opendc-web-api/opendc/api/v2/projects/projectId/portfolios/endpoint.py b/opendc-web/opendc-web-api/opendc/api/v2/projects/projectId/portfolios/endpoint.py index 2cdb1194..18b4d007 100644 --- a/opendc-web/opendc-web-api/opendc/api/v2/projects/projectId/portfolios/endpoint.py +++ b/opendc-web/opendc-web-api/opendc/api/v2/projects/projectId/portfolios/endpoint.py @@ -20,7 +20,7 @@ def POST(request): project = Project.from_id(request.params_path['projectId']) project.check_exists() - project.check_user_access(request.google_id, True) + project.check_user_access(request.current_user['sub'], True) portfolio = Portfolio(request.params_body['portfolio']) diff --git a/opendc-web/opendc-web-api/opendc/api/v2/projects/projectId/topologies/endpoint.py b/opendc-web/opendc-web-api/opendc/api/v2/projects/projectId/topologies/endpoint.py index 44a0d575..47f2a207 100644 --- a/opendc-web/opendc-web-api/opendc/api/v2/projects/projectId/topologies/endpoint.py +++ b/opendc-web/opendc-web-api/opendc/api/v2/projects/projectId/topologies/endpoint.py @@ -14,7 +14,7 @@ def POST(request): project = Project.from_id(request.params_path['projectId']) project.check_exists() - project.check_user_access(request.google_id, True) + project.check_user_access(request.current_user['sub'], True) topology = Topology({ 'projectId': project.get_id(), -- 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/projects/endpoint.py | 14 ++++--- .../projects/projectId/authorizations/__init__.py | 0 .../projects/projectId/authorizations/endpoint.py | 17 --------- .../projectId/authorizations/test_endpoint.py | 43 ---------------------- .../opendc/api/v2/projects/projectId/endpoint.py | 6 --- .../projects/projectId/portfolios/test_endpoint.py | 4 +- .../api/v2/projects/projectId/test_endpoint.py | 15 +++----- .../projects/projectId/topologies/test_endpoint.py | 4 +- .../opendc/api/v2/projects/test_endpoint.py | 7 ++++ 9 files changed, 26 insertions(+), 84 deletions(-) delete mode 100644 opendc-web/opendc-web-api/opendc/api/v2/projects/projectId/authorizations/__init__.py delete mode 100644 opendc-web/opendc-web-api/opendc/api/v2/projects/projectId/authorizations/endpoint.py delete mode 100644 opendc-web/opendc-web-api/opendc/api/v2/projects/projectId/authorizations/test_endpoint.py (limited to 'opendc-web/opendc-web-api/opendc/api/v2/projects') diff --git a/opendc-web/opendc-web-api/opendc/api/v2/projects/endpoint.py b/opendc-web/opendc-web-api/opendc/api/v2/projects/endpoint.py index dacbe6a4..b381d689 100644 --- a/opendc-web/opendc-web-api/opendc/api/v2/projects/endpoint.py +++ b/opendc-web/opendc-web-api/opendc/api/v2/projects/endpoint.py @@ -2,15 +2,22 @@ from datetime import datetime from opendc.models.project import Project from opendc.models.topology import Topology -from opendc.models.user import User from opendc.util.database import Database from opendc.util.rest import Response +def GET(request): + """Get the authorized projects of the user""" + user_id = request.current_user['sub'] + projects = Project.get_for_user(user_id) + return Response(200, 'Successfully retrieved projects', projects) + + def POST(request): """Create a new project, and return that new project.""" request.check_required_parameters(body={'project': {'name': 'string'}}) + user_id = request.current_user['sub'] topology = Topology({'name': 'Default topology', 'rooms': []}) topology.insert() @@ -20,13 +27,10 @@ def POST(request): project.set_property('datetimeLastEdited', Database.datetime_to_string(datetime.now())) project.set_property('topologyIds', [topology.get_id()]) project.set_property('portfolioIds', []) + project.set_property('authorizations', [{'userId': user_id, 'authorizationLevel': 'OWN'}]) project.insert() topology.set_property('projectId', project.get_id()) topology.update() - user = User.from_google_id(request.current_user['sub']) - user.obj['authorizations'].append({'projectId': project.get_id(), 'authorizationLevel': 'OWN'}) - user.update() - return Response(200, 'Successfully created project.', project.obj) diff --git a/opendc-web/opendc-web-api/opendc/api/v2/projects/projectId/authorizations/__init__.py b/opendc-web/opendc-web-api/opendc/api/v2/projects/projectId/authorizations/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/opendc-web/opendc-web-api/opendc/api/v2/projects/projectId/authorizations/endpoint.py b/opendc-web/opendc-web-api/opendc/api/v2/projects/projectId/authorizations/endpoint.py deleted file mode 100644 index 1b229122..00000000 --- a/opendc-web/opendc-web-api/opendc/api/v2/projects/projectId/authorizations/endpoint.py +++ /dev/null @@ -1,17 +0,0 @@ -from opendc.models.project import Project -from opendc.util.rest import Response - - -def GET(request): - """Find all authorizations for a Project.""" - - request.check_required_parameters(path={'projectId': 'string'}) - - project = Project.from_id(request.params_path['projectId']) - - project.check_exists() - project.check_user_access(request.current_user['sub'], False) - - authorizations = project.get_all_authorizations() - - return Response(200, 'Successfully retrieved project authorizations', authorizations) diff --git a/opendc-web/opendc-web-api/opendc/api/v2/projects/projectId/authorizations/test_endpoint.py b/opendc-web/opendc-web-api/opendc/api/v2/projects/projectId/authorizations/test_endpoint.py deleted file mode 100644 index bebd6cff..00000000 --- a/opendc-web/opendc-web-api/opendc/api/v2/projects/projectId/authorizations/test_endpoint.py +++ /dev/null @@ -1,43 +0,0 @@ -from opendc.util.database import DB - -test_id = 24 * '1' -test_id_2 = 24 * '2' - - -def test_get_authorizations_non_existing(client, mocker): - mocker.patch.object(DB, 'fetch_one', return_value=None) - mocker.patch.object(DB, 'fetch_all', return_value=None) - assert '404' in client.get(f'/v2/projects/{test_id}/authorizations').status - - -def test_get_authorizations_not_authorized(client, mocker): - mocker.patch.object(DB, - 'fetch_one', - return_value={ - '_id': test_id, - 'name': 'test trace', - 'authorizations': [{ - 'projectId': test_id_2, - 'authorizationLevel': 'OWN' - }] - }) - mocker.patch.object(DB, 'fetch_all', return_value=[]) - res = client.get(f'/v2/projects/{test_id}/authorizations') - assert '403' in res.status - - -def test_get_authorizations(client, mocker): - mocker.patch.object(DB, - 'fetch_one', - return_value={ - '_id': test_id, - 'name': 'test trace', - 'authorizations': [{ - 'projectId': test_id, - 'authorizationLevel': 'OWN' - }] - }) - mocker.patch.object(DB, 'fetch_all', return_value=[]) - res = client.get(f'/v2/projects/{test_id}/authorizations') - assert len(res.json['content']) == 0 - assert '200' in res.status diff --git a/opendc-web/opendc-web-api/opendc/api/v2/projects/projectId/endpoint.py b/opendc-web/opendc-web-api/opendc/api/v2/projects/projectId/endpoint.py index 37cf1860..fa53ce6b 100644 --- a/opendc-web/opendc-web-api/opendc/api/v2/projects/projectId/endpoint.py +++ b/opendc-web/opendc-web-api/opendc/api/v2/projects/projectId/endpoint.py @@ -3,7 +3,6 @@ from datetime import datetime from opendc.models.portfolio import Portfolio from opendc.models.project import Project from opendc.models.topology import Topology -from opendc.models.user import User from opendc.util.database import Database from opendc.util.rest import Response @@ -56,11 +55,6 @@ def DELETE(request): portfolio = Portfolio.from_id(portfolio_id) portfolio.delete() - user = User.from_google_id(request.current_user['sub']) - user.obj['authorizations'] = list( - filter(lambda x: x['projectId'] != project.get_id(), user.obj['authorizations'])) - user.update() - old_object = project.delete() return Response(200, 'Successfully deleted project.', old_object) diff --git a/opendc-web/opendc-web-api/opendc/api/v2/projects/projectId/portfolios/test_endpoint.py b/opendc-web/opendc-web-api/opendc/api/v2/projects/projectId/portfolios/test_endpoint.py index 04c699b5..7ddfe0ce 100644 --- a/opendc-web/opendc-web-api/opendc/api/v2/projects/projectId/portfolios/test_endpoint.py +++ b/opendc-web/opendc-web-api/opendc/api/v2/projects/projectId/portfolios/test_endpoint.py @@ -28,7 +28,7 @@ def test_add_portfolio_not_authorized(client, mocker): '_id': test_id, 'projectId': test_id, 'authorizations': [{ - 'projectId': test_id, + 'userId': 'test', 'authorizationLevel': 'VIEW' }] }) @@ -52,7 +52,7 @@ def test_add_portfolio(client, mocker): 'projectId': test_id, 'portfolioIds': [test_id], 'authorizations': [{ - 'projectId': test_id, + 'userId': 'test', 'authorizationLevel': 'EDIT' }] }) diff --git a/opendc-web/opendc-web-api/opendc/api/v2/projects/projectId/test_endpoint.py b/opendc-web/opendc-web-api/opendc/api/v2/projects/projectId/test_endpoint.py index f9ffaf37..03e6758b 100644 --- a/opendc-web/opendc-web-api/opendc/api/v2/projects/projectId/test_endpoint.py +++ b/opendc-web/opendc-web-api/opendc/api/v2/projects/projectId/test_endpoint.py @@ -20,10 +20,7 @@ def test_get_project_not_authorized(client, mocker): 'fetch_one', return_value={ '_id': test_id, - 'authorizations': [{ - 'projectId': test_id_2, - 'authorizationLevel': 'OWN' - }] + 'authorizations': [] }) res = client.get(f'/v2/projects/{test_id}') assert '403' in res.status @@ -35,7 +32,7 @@ def test_get_project(client, mocker): return_value={ '_id': test_id, 'authorizations': [{ - 'projectId': test_id, + 'userId': 'test', 'authorizationLevel': 'EDIT' }] }) @@ -58,7 +55,7 @@ def test_update_project_not_authorized(client, mocker): return_value={ '_id': test_id, 'authorizations': [{ - 'projectId': test_id, + 'userId': 'test', 'authorizationLevel': 'VIEW' }] }) @@ -72,7 +69,7 @@ def test_update_project(client, mocker): return_value={ '_id': test_id, 'authorizations': [{ - 'projectId': test_id, + 'userId': 'test', 'authorizationLevel': 'OWN' }] }) @@ -94,7 +91,7 @@ def test_delete_project_different_user(client, mocker): '_id': test_id, 'googleId': 'other_test', 'authorizations': [{ - 'projectId': test_id, + 'userId': 'test', 'authorizationLevel': 'VIEW' }], 'topologyIds': [] @@ -110,7 +107,7 @@ def test_delete_project(client, mocker): '_id': test_id, 'googleId': 'test', 'authorizations': [{ - 'projectId': test_id, + 'userId': 'test', 'authorizationLevel': 'OWN' }], 'topologyIds': [], diff --git a/opendc-web/opendc-web-api/opendc/api/v2/projects/projectId/topologies/test_endpoint.py b/opendc-web/opendc-web-api/opendc/api/v2/projects/projectId/topologies/test_endpoint.py index 71e88f00..2e872415 100644 --- a/opendc-web/opendc-web-api/opendc/api/v2/projects/projectId/topologies/test_endpoint.py +++ b/opendc-web/opendc-web-api/opendc/api/v2/projects/projectId/topologies/test_endpoint.py @@ -13,7 +13,7 @@ def test_add_topology(client, mocker): return_value={ '_id': test_id, 'authorizations': [{ - 'projectId': test_id, + 'userId': 'test', 'authorizationLevel': 'OWN' }], 'topologyIds': [] @@ -39,7 +39,7 @@ def test_add_topology_not_authorized(client, mocker): '_id': test_id, 'projectId': test_id, 'authorizations': [{ - 'projectId': test_id, + 'userId': 'test', 'authorizationLevel': 'VIEW' }] }) diff --git a/opendc-web/opendc-web-api/opendc/api/v2/projects/test_endpoint.py b/opendc-web/opendc-web-api/opendc/api/v2/projects/test_endpoint.py index 9444b1e4..db768f28 100644 --- a/opendc-web/opendc-web-api/opendc/api/v2/projects/test_endpoint.py +++ b/opendc-web/opendc-web-api/opendc/api/v2/projects/test_endpoint.py @@ -3,6 +3,13 @@ from opendc.util.database import DB test_id = 24 * '1' +def test_get_user_projects(client, mocker): + mocker.patch.object(DB, 'fetch_all', return_value={'_id': test_id, 'authorizations': [{'userId': 'test', + 'authorizationLevel': 'OWN'}]}) + res = client.get('/v2/projects') + assert '200' in res.status + + def test_add_project_missing_parameter(client): assert '400' in client.post('/v2/projects').status -- 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/projects/__init__.py | 0 .../opendc/api/v2/projects/endpoint.py | 36 ------- .../opendc/api/v2/projects/projectId/__init__.py | 0 .../opendc/api/v2/projects/projectId/endpoint.py | 60 ----------- .../v2/projects/projectId/portfolios/__init__.py | 0 .../v2/projects/projectId/portfolios/endpoint.py | 35 ------ .../projects/projectId/portfolios/test_endpoint.py | 85 --------------- .../api/v2/projects/projectId/test_endpoint.py | 119 --------------------- .../v2/projects/projectId/topologies/__init__.py | 0 .../v2/projects/projectId/topologies/endpoint.py | 31 ------ .../projects/projectId/topologies/test_endpoint.py | 52 --------- .../opendc/api/v2/projects/test_endpoint.py | 32 ------ 12 files changed, 450 deletions(-) delete mode 100644 opendc-web/opendc-web-api/opendc/api/v2/projects/__init__.py delete mode 100644 opendc-web/opendc-web-api/opendc/api/v2/projects/endpoint.py delete mode 100644 opendc-web/opendc-web-api/opendc/api/v2/projects/projectId/__init__.py delete mode 100644 opendc-web/opendc-web-api/opendc/api/v2/projects/projectId/endpoint.py delete mode 100644 opendc-web/opendc-web-api/opendc/api/v2/projects/projectId/portfolios/__init__.py delete mode 100644 opendc-web/opendc-web-api/opendc/api/v2/projects/projectId/portfolios/endpoint.py delete mode 100644 opendc-web/opendc-web-api/opendc/api/v2/projects/projectId/portfolios/test_endpoint.py delete mode 100644 opendc-web/opendc-web-api/opendc/api/v2/projects/projectId/test_endpoint.py delete mode 100644 opendc-web/opendc-web-api/opendc/api/v2/projects/projectId/topologies/__init__.py delete mode 100644 opendc-web/opendc-web-api/opendc/api/v2/projects/projectId/topologies/endpoint.py delete mode 100644 opendc-web/opendc-web-api/opendc/api/v2/projects/projectId/topologies/test_endpoint.py delete mode 100644 opendc-web/opendc-web-api/opendc/api/v2/projects/test_endpoint.py (limited to 'opendc-web/opendc-web-api/opendc/api/v2/projects') diff --git a/opendc-web/opendc-web-api/opendc/api/v2/projects/__init__.py b/opendc-web/opendc-web-api/opendc/api/v2/projects/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/opendc-web/opendc-web-api/opendc/api/v2/projects/endpoint.py b/opendc-web/opendc-web-api/opendc/api/v2/projects/endpoint.py deleted file mode 100644 index b381d689..00000000 --- a/opendc-web/opendc-web-api/opendc/api/v2/projects/endpoint.py +++ /dev/null @@ -1,36 +0,0 @@ -from datetime import datetime - -from opendc.models.project import Project -from opendc.models.topology import Topology -from opendc.util.database import Database -from opendc.util.rest import Response - - -def GET(request): - """Get the authorized projects of the user""" - user_id = request.current_user['sub'] - projects = Project.get_for_user(user_id) - return Response(200, 'Successfully retrieved projects', projects) - - -def POST(request): - """Create a new project, and return that new project.""" - - request.check_required_parameters(body={'project': {'name': 'string'}}) - user_id = request.current_user['sub'] - - topology = Topology({'name': 'Default topology', 'rooms': []}) - topology.insert() - - project = Project(request.params_body['project']) - project.set_property('datetimeCreated', Database.datetime_to_string(datetime.now())) - project.set_property('datetimeLastEdited', Database.datetime_to_string(datetime.now())) - project.set_property('topologyIds', [topology.get_id()]) - project.set_property('portfolioIds', []) - project.set_property('authorizations', [{'userId': user_id, 'authorizationLevel': 'OWN'}]) - project.insert() - - topology.set_property('projectId', project.get_id()) - topology.update() - - return Response(200, 'Successfully created project.', project.obj) diff --git a/opendc-web/opendc-web-api/opendc/api/v2/projects/projectId/__init__.py b/opendc-web/opendc-web-api/opendc/api/v2/projects/projectId/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/opendc-web/opendc-web-api/opendc/api/v2/projects/projectId/endpoint.py b/opendc-web/opendc-web-api/opendc/api/v2/projects/projectId/endpoint.py deleted file mode 100644 index fa53ce6b..00000000 --- a/opendc-web/opendc-web-api/opendc/api/v2/projects/projectId/endpoint.py +++ /dev/null @@ -1,60 +0,0 @@ -from datetime import datetime - -from opendc.models.portfolio import Portfolio -from opendc.models.project import Project -from opendc.models.topology import Topology -from opendc.util.database import Database -from opendc.util.rest import Response - - -def GET(request): - """Get this Project.""" - - request.check_required_parameters(path={'projectId': 'string'}) - - project = Project.from_id(request.params_path['projectId']) - - project.check_exists() - project.check_user_access(request.current_user['sub'], False) - - return Response(200, 'Successfully retrieved project', project.obj) - - -def PUT(request): - """Update a project's name.""" - - request.check_required_parameters(body={'project': {'name': 'name'}}, path={'projectId': 'string'}) - - project = Project.from_id(request.params_path['projectId']) - - project.check_exists() - project.check_user_access(request.current_user['sub'], True) - - project.set_property('name', request.params_body['project']['name']) - project.set_property('datetime_last_edited', Database.datetime_to_string(datetime.now())) - project.update() - - return Response(200, 'Successfully updated project.', project.obj) - - -def DELETE(request): - """Delete this Project.""" - - request.check_required_parameters(path={'projectId': 'string'}) - - project = Project.from_id(request.params_path['projectId']) - - project.check_exists() - project.check_user_access(request.current_user['sub'], True) - - for topology_id in project.obj['topologyIds']: - topology = Topology.from_id(topology_id) - topology.delete() - - for portfolio_id in project.obj['portfolioIds']: - portfolio = Portfolio.from_id(portfolio_id) - portfolio.delete() - - old_object = project.delete() - - return Response(200, 'Successfully deleted project.', old_object) diff --git a/opendc-web/opendc-web-api/opendc/api/v2/projects/projectId/portfolios/__init__.py b/opendc-web/opendc-web-api/opendc/api/v2/projects/projectId/portfolios/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/opendc-web/opendc-web-api/opendc/api/v2/projects/projectId/portfolios/endpoint.py b/opendc-web/opendc-web-api/opendc/api/v2/projects/projectId/portfolios/endpoint.py deleted file mode 100644 index 18b4d007..00000000 --- a/opendc-web/opendc-web-api/opendc/api/v2/projects/projectId/portfolios/endpoint.py +++ /dev/null @@ -1,35 +0,0 @@ -from opendc.models.portfolio import Portfolio -from opendc.models.project import Project -from opendc.util.rest import Response - - -def POST(request): - """Add a new Portfolio for this Project.""" - - request.check_required_parameters(path={'projectId': 'string'}, - body={ - 'portfolio': { - 'name': 'string', - 'targets': { - 'enabledMetrics': 'list', - 'repeatsPerScenario': 'int', - }, - } - }) - - project = Project.from_id(request.params_path['projectId']) - - project.check_exists() - project.check_user_access(request.current_user['sub'], True) - - portfolio = Portfolio(request.params_body['portfolio']) - - portfolio.set_property('projectId', project.get_id()) - portfolio.set_property('scenarioIds', []) - - portfolio.insert() - - project.obj['portfolioIds'].append(portfolio.get_id()) - project.update() - - return Response(200, 'Successfully added Portfolio.', portfolio.obj) diff --git a/opendc-web/opendc-web-api/opendc/api/v2/projects/projectId/portfolios/test_endpoint.py b/opendc-web/opendc-web-api/opendc/api/v2/projects/projectId/portfolios/test_endpoint.py deleted file mode 100644 index 7ddfe0ce..00000000 --- a/opendc-web/opendc-web-api/opendc/api/v2/projects/projectId/portfolios/test_endpoint.py +++ /dev/null @@ -1,85 +0,0 @@ -from opendc.util.database import DB - -test_id = 24 * '1' - - -def test_add_portfolio_missing_parameter(client): - assert '400' in client.post(f'/v2/projects/{test_id}/portfolios').status - - -def test_add_portfolio_non_existing_project(client, mocker): - mocker.patch.object(DB, 'fetch_one', return_value=None) - assert '404' in client.post(f'/v2/projects/{test_id}/portfolios', - json={ - 'portfolio': { - 'name': 'test', - 'targets': { - 'enabledMetrics': ['test'], - 'repeatsPerScenario': 2 - } - } - }).status - - -def test_add_portfolio_not_authorized(client, mocker): - mocker.patch.object(DB, - 'fetch_one', - return_value={ - '_id': test_id, - 'projectId': test_id, - 'authorizations': [{ - 'userId': 'test', - 'authorizationLevel': 'VIEW' - }] - }) - assert '403' in client.post(f'/v2/projects/{test_id}/portfolios', - json={ - 'portfolio': { - 'name': 'test', - 'targets': { - 'enabledMetrics': ['test'], - 'repeatsPerScenario': 2 - } - } - }).status - - -def test_add_portfolio(client, mocker): - mocker.patch.object(DB, - 'fetch_one', - return_value={ - '_id': test_id, - 'projectId': test_id, - 'portfolioIds': [test_id], - 'authorizations': [{ - 'userId': 'test', - 'authorizationLevel': 'EDIT' - }] - }) - mocker.patch.object(DB, - 'insert', - return_value={ - '_id': test_id, - 'name': 'test', - 'targets': { - 'enabledMetrics': ['test'], - 'repeatsPerScenario': 2 - }, - 'projectId': test_id, - 'scenarioIds': [], - }) - mocker.patch.object(DB, 'update', return_value=None) - res = client.post( - f'/v2/projects/{test_id}/portfolios', - json={ - 'portfolio': { - 'name': 'test', - 'targets': { - 'enabledMetrics': ['test'], - 'repeatsPerScenario': 2 - } - } - }) - assert 'projectId' in res.json['content'] - assert 'scenarioIds' in res.json['content'] - assert '200' in res.status diff --git a/opendc-web/opendc-web-api/opendc/api/v2/projects/projectId/test_endpoint.py b/opendc-web/opendc-web-api/opendc/api/v2/projects/projectId/test_endpoint.py deleted file mode 100644 index 03e6758b..00000000 --- a/opendc-web/opendc-web-api/opendc/api/v2/projects/projectId/test_endpoint.py +++ /dev/null @@ -1,119 +0,0 @@ -from opendc.util.database import DB - -test_id = 24 * '1' -test_id_2 = 24 * '2' - - -def test_get_project_non_existing(client, mocker): - mocker.patch.object(DB, 'fetch_one', return_value=None) - assert '404' in client.get(f'/v2/projects/{test_id}').status - - -def test_get_project_no_authorizations(client, mocker): - mocker.patch.object(DB, 'fetch_one', return_value={'authorizations': []}) - res = client.get(f'/v2/projects/{test_id}') - assert '403' in res.status - - -def test_get_project_not_authorized(client, mocker): - mocker.patch.object(DB, - 'fetch_one', - return_value={ - '_id': test_id, - 'authorizations': [] - }) - res = client.get(f'/v2/projects/{test_id}') - assert '403' in res.status - - -def test_get_project(client, mocker): - mocker.patch.object(DB, - 'fetch_one', - return_value={ - '_id': test_id, - 'authorizations': [{ - 'userId': 'test', - 'authorizationLevel': 'EDIT' - }] - }) - res = client.get(f'/v2/projects/{test_id}') - assert '200' in res.status - - -def test_update_project_missing_parameter(client): - assert '400' in client.put(f'/v2/projects/{test_id}').status - - -def test_update_project_non_existing(client, mocker): - mocker.patch.object(DB, 'fetch_one', return_value=None) - assert '404' in client.put(f'/v2/projects/{test_id}', json={'project': {'name': 'S'}}).status - - -def test_update_project_not_authorized(client, mocker): - mocker.patch.object(DB, - 'fetch_one', - return_value={ - '_id': test_id, - 'authorizations': [{ - 'userId': 'test', - 'authorizationLevel': 'VIEW' - }] - }) - mocker.patch.object(DB, 'update', return_value={}) - assert '403' in client.put(f'/v2/projects/{test_id}', json={'project': {'name': 'S'}}).status - - -def test_update_project(client, mocker): - mocker.patch.object(DB, - 'fetch_one', - return_value={ - '_id': test_id, - 'authorizations': [{ - 'userId': 'test', - 'authorizationLevel': 'OWN' - }] - }) - mocker.patch.object(DB, 'update', return_value={}) - - res = client.put(f'/v2/projects/{test_id}', json={'project': {'name': 'S'}}) - assert '200' in res.status - - -def test_delete_project_non_existing(client, mocker): - mocker.patch.object(DB, 'fetch_one', return_value=None) - assert '404' in client.delete(f'/v2/projects/{test_id}').status - - -def test_delete_project_different_user(client, mocker): - mocker.patch.object(DB, - 'fetch_one', - return_value={ - '_id': test_id, - 'googleId': 'other_test', - 'authorizations': [{ - 'userId': 'test', - 'authorizationLevel': 'VIEW' - }], - 'topologyIds': [] - }) - mocker.patch.object(DB, 'delete_one', return_value=None) - assert '403' in client.delete(f'/v2/projects/{test_id}').status - - -def test_delete_project(client, mocker): - mocker.patch.object(DB, - 'fetch_one', - return_value={ - '_id': test_id, - 'googleId': 'test', - 'authorizations': [{ - 'userId': 'test', - 'authorizationLevel': 'OWN' - }], - 'topologyIds': [], - 'portfolioIds': [], - }) - mocker.patch.object(DB, 'update', return_value=None) - mocker.patch.object(DB, 'delete_one', return_value={'googleId': 'test'}) - res = client.delete(f'/v2/projects/{test_id}') - assert '200' in res.status diff --git a/opendc-web/opendc-web-api/opendc/api/v2/projects/projectId/topologies/__init__.py b/opendc-web/opendc-web-api/opendc/api/v2/projects/projectId/topologies/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/opendc-web/opendc-web-api/opendc/api/v2/projects/projectId/topologies/endpoint.py b/opendc-web/opendc-web-api/opendc/api/v2/projects/projectId/topologies/endpoint.py deleted file mode 100644 index 47f2a207..00000000 --- a/opendc-web/opendc-web-api/opendc/api/v2/projects/projectId/topologies/endpoint.py +++ /dev/null @@ -1,31 +0,0 @@ -from datetime import datetime - -from opendc.models.project import Project -from opendc.models.topology import Topology -from opendc.util.rest import Response -from opendc.util.database import Database - - -def POST(request): - """Add a new Topology to the specified project and return it""" - - request.check_required_parameters(path={'projectId': 'string'}, body={'topology': {'name': 'string'}}) - - project = Project.from_id(request.params_path['projectId']) - - project.check_exists() - project.check_user_access(request.current_user['sub'], True) - - topology = Topology({ - 'projectId': project.get_id(), - 'name': request.params_body['topology']['name'], - 'rooms': request.params_body['topology']['rooms'], - }) - - topology.insert() - - project.obj['topologyIds'].append(topology.get_id()) - project.set_property('datetimeLastEdited', Database.datetime_to_string(datetime.now())) - project.update() - - return Response(200, 'Successfully inserted topology.', topology.obj) diff --git a/opendc-web/opendc-web-api/opendc/api/v2/projects/projectId/topologies/test_endpoint.py b/opendc-web/opendc-web-api/opendc/api/v2/projects/projectId/topologies/test_endpoint.py deleted file mode 100644 index 2e872415..00000000 --- a/opendc-web/opendc-web-api/opendc/api/v2/projects/projectId/topologies/test_endpoint.py +++ /dev/null @@ -1,52 +0,0 @@ -from opendc.util.database import DB - -test_id = 24 * '1' - - -def test_add_topology_missing_parameter(client): - assert '400' in client.post(f'/v2/projects/{test_id}/topologies').status - - -def test_add_topology(client, mocker): - mocker.patch.object(DB, - 'fetch_one', - return_value={ - '_id': test_id, - 'authorizations': [{ - 'userId': 'test', - 'authorizationLevel': 'OWN' - }], - 'topologyIds': [] - }) - mocker.patch.object(DB, - 'insert', - return_value={ - '_id': test_id, - 'datetimeCreated': '000', - 'datetimeLastEdited': '000', - 'topologyIds': [] - }) - mocker.patch.object(DB, 'update', return_value={}) - res = client.post(f'/v2/projects/{test_id}/topologies', json={'topology': {'name': 'test project', 'rooms': []}}) - assert 'rooms' in res.json['content'] - assert '200' in res.status - - -def test_add_topology_not_authorized(client, mocker): - mocker.patch.object(DB, - 'fetch_one', - return_value={ - '_id': test_id, - 'projectId': test_id, - 'authorizations': [{ - 'userId': 'test', - 'authorizationLevel': 'VIEW' - }] - }) - assert '403' in client.post(f'/v2/projects/{test_id}/topologies', - json={ - 'topology': { - 'name': 'test_topology', - 'rooms': {} - } - }).status diff --git a/opendc-web/opendc-web-api/opendc/api/v2/projects/test_endpoint.py b/opendc-web/opendc-web-api/opendc/api/v2/projects/test_endpoint.py deleted file mode 100644 index db768f28..00000000 --- a/opendc-web/opendc-web-api/opendc/api/v2/projects/test_endpoint.py +++ /dev/null @@ -1,32 +0,0 @@ -from opendc.util.database import DB - -test_id = 24 * '1' - - -def test_get_user_projects(client, mocker): - mocker.patch.object(DB, 'fetch_all', return_value={'_id': test_id, 'authorizations': [{'userId': 'test', - 'authorizationLevel': 'OWN'}]}) - res = client.get('/v2/projects') - assert '200' in res.status - - -def test_add_project_missing_parameter(client): - assert '400' in client.post('/v2/projects').status - - -def test_add_project(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', - 'topologyIds': [] - }) - mocker.patch.object(DB, 'update', return_value={}) - res = client.post('/v2/projects', json={'project': {'name': 'test project'}}) - assert 'datetimeCreated' in res.json['content'] - assert 'datetimeLastEdited' in res.json['content'] - assert 'topologyIds' in res.json['content'] - assert '200' in res.status -- cgit v1.2.3