From 7207df830476c7db2a3e4c56bfebfab42e847ac1 Mon Sep 17 00:00:00 2001 From: c8y3 <25362953+c8y3@users.noreply.github.com> Date: Fri, 4 Oct 2024 13:24:34 +0200 Subject: [PATCH 01/46] [IMP] For endpoint GET /api/v2/cases, changed field cases into data --- e2e/tests/administrator/manage/customers.spec.js | 7 +++++++ source/app/blueprints/rest/case/case_routes.py | 2 +- tests/iris.py | 2 +- tests/tests_rest_cases.py | 10 +++++----- ui/src/pages/view.customers.js | 2 +- 5 files changed, 15 insertions(+), 8 deletions(-) diff --git a/e2e/tests/administrator/manage/customers.spec.js b/e2e/tests/administrator/manage/customers.spec.js index 5ed7ce7b1..1093b71c8 100644 --- a/e2e/tests/administrator/manage/customers.spec.js +++ b/e2e/tests/administrator/manage/customers.spec.js @@ -12,3 +12,10 @@ test('should be able to open "Add customer" modal', async ({ page }) => { await page.getByRole('button', { name: 'Add customer' }).click(); await expect(page.getByRole('heading', { name: 'Add customer' })).toBeVisible() }); + +test('should present IrisInitialClient associated cases', async ({ page }) => { + await page.getByRole('link', { name: 'IrisInitialClient' }).click(); + + await page.getByRole('button', { name: ' Cases' }).click(); + await expect(page.getByRole('gridcell', { name: '#1 - Initial Demo' })).toBeVisible(); +}); \ No newline at end of file diff --git a/source/app/blueprints/rest/case/case_routes.py b/source/app/blueprints/rest/case/case_routes.py index 72b3ce595..85d7bc8d8 100644 --- a/source/app/blueprints/rest/case/case_routes.py +++ b/source/app/blueprints/rest/case/case_routes.py @@ -414,7 +414,7 @@ def get_cases() -> Response: cases = { 'total': filtered_cases.total, # TODO should maybe really uniform all return types of paginated list and replace field cases by field data - 'cases': CaseSchemaForAPIV2().dump(filtered_cases.items, many=True), + 'data': CaseSchemaForAPIV2().dump(filtered_cases.items, many=True), 'last_page': filtered_cases.pages, 'current_page': filtered_cases.page, 'next_page': filtered_cases.next_num if filtered_cases.has_next else None, diff --git a/tests/iris.py b/tests/iris.py index dccd06e9c..a0604135b 100644 --- a/tests/iris.py +++ b/tests/iris.py @@ -75,7 +75,7 @@ def execute_graphql_query(self, payload): def clear_database(self): cases = self.get('/api/v2/cases', query_parameters={'per_page': 1000000000}).json() - for case in cases['cases']: + for case in cases['data']: identifier = case['case_id'] self.delete(f'/api/v2/cases/{identifier}') groups = self.get('/manage/groups/list').json() diff --git a/tests/tests_rest_cases.py b/tests/tests_rest_cases.py index d689e8a9a..0126ea8a7 100644 --- a/tests/tests_rest_cases.py +++ b/tests/tests_rest_cases.py @@ -21,7 +21,7 @@ def _get_case_with_identifier(response, identifier): - for case in response['cases']: + for case in response['data']: if identifier == case['case_id']: return case raise ValueError('Case not found') @@ -69,10 +69,10 @@ def test_create_case_with_classification_id_should_set_classification_id(self): def test_create_case_should_add_a_new_case(self): response = self._subject.get('/api/v2/cases').json() - initial_case_count = len(response['cases']) + initial_case_count = len(response['data']) self._subject.create_dummy_case() response = self._subject.get('/api/v2/cases').json() - case_count = len(response['cases']) + case_count = len(response['data']) self.assertEqual(initial_case_count + 1, case_count) def test_get_case_should_return_case_data(self): @@ -129,7 +129,7 @@ def test_get_cases_should_filter_on_case_name(self): filters = {'case_name': 'test_get_cases_should_filter_on_case_name'} response = self._subject.get('/api/v2/cases', query_parameters=filters).json() identifiers = [] - for case in response['cases']: + for case in response['data']: identifiers.append(case['case_id']) self.assertIn(case_identifier, identifiers) @@ -139,7 +139,7 @@ def test_get_cases_should_filter_on_is_open(self): filters = {'is_open': 'true'} response = self._subject.get('/api/v2/cases', query_parameters=filters).json() identifiers = [] - for case in response['cases']: + for case in response['data']: identifiers.append(case['case_id']) self.assertNotIn(case_identifier, identifiers) diff --git a/ui/src/pages/view.customers.js b/ui/src/pages/view.customers.js index 7eea74492..4e490fa01 100644 --- a/ui/src/pages/view.customers.js +++ b/ui/src/pages/view.customers.js @@ -288,7 +288,7 @@ $(document).ready(function() { // since there are no filters on this table, it should be OK json.recordsFiltered = json.total; - return json.cases; + return json.data; } } }); From dd7ebe8d30b4499180aad482a82ea7205560a229 Mon Sep 17 00:00:00 2001 From: c8y3 <25362953+c8y3@users.noreply.github.com> Date: Fri, 4 Oct 2024 15:26:48 +0200 Subject: [PATCH 02/46] [IMP] For endpoint GET /api/v2/cases/{identifier}/iocs, changed field iocs into data --- source/app/blueprints/rest/case/case_ioc_routes.py | 7 ------- source/app/blueprints/rest/v2/case/api_v2_ioc_routes.py | 4 ++-- tests/tests_rest_iocs.py | 8 ++++---- ui/src/pages/case.ioc.js | 2 +- 4 files changed, 7 insertions(+), 14 deletions(-) diff --git a/source/app/blueprints/rest/case/case_ioc_routes.py b/source/app/blueprints/rest/case/case_ioc_routes.py index 159ba0932..898783fe4 100644 --- a/source/app/blueprints/rest/case/case_ioc_routes.py +++ b/source/app/blueprints/rest/case/case_ioc_routes.py @@ -27,11 +27,6 @@ from app import db from app.blueprints.rest.case_comments import case_comment_update -from app.blueprints.rest.endpoints import response_api_deleted -from app.blueprints.rest.endpoints import response_api_not_found -from app.blueprints.rest.endpoints import response_api_success -from app.blueprints.rest.endpoints import response_api_created -from app.blueprints.rest.endpoints import response_api_error from app.blueprints.rest.endpoints import endpoint_deprecated from app.business.iocs import iocs_create from app.business.iocs import iocs_update @@ -40,7 +35,6 @@ from app.business.errors import BusinessProcessingError from app.business.errors import ObjectNotFoundError from app.datamgmt.case.case_iocs_db import add_comment_to_ioc -from app.datamgmt.case.case_iocs_db import get_filtered_iocs from app.datamgmt.case.case_iocs_db import add_ioc from app.datamgmt.case.case_iocs_db import delete_ioc_comment from app.datamgmt.case.case_iocs_db import get_case_ioc_comment @@ -57,7 +51,6 @@ from app.models.authorization import CaseAccessLevel from app.schema.marshables import CommentSchema from app.schema.marshables import IocSchema -from app.schema.marshables import IocSchemaForAPIV2 from app.blueprints.access_controls import ac_requires_case_identifier from app.blueprints.access_controls import ac_api_requires from app.util import ac_api_return_access_denied diff --git a/source/app/blueprints/rest/v2/case/api_v2_ioc_routes.py b/source/app/blueprints/rest/v2/case/api_v2_ioc_routes.py index 4c8646828..a7c22d7b8 100644 --- a/source/app/blueprints/rest/v2/case/api_v2_ioc_routes.py +++ b/source/app/blueprints/rest/v2/case/api_v2_ioc_routes.py @@ -41,6 +41,7 @@ __name__, url_prefix='/api/v2') + @api_v2_ioc_blueprint.route('/cases//iocs', methods=['GET']) @ac_api_requires() def list_ioc(identifier): @@ -80,8 +81,7 @@ def list_ioc(identifier): iocs = { 'total': filtered_iocs.total, - # TODO should maybe really uniform all return types of paginated list and replace field iocs by field data - 'iocs': iocs, + 'data': iocs, 'last_page': filtered_iocs.pages, 'current_page': filtered_iocs.page, 'next_page': filtered_iocs.next_num if filtered_iocs.has_next else None, diff --git a/tests/tests_rest_iocs.py b/tests/tests_rest_iocs.py index 519f9bce6..27149ba5b 100644 --- a/tests/tests_rest_iocs.py +++ b/tests/tests_rest_iocs.py @@ -35,7 +35,7 @@ def test_get_ioc_should_not_fail(self): response = self._subject.get('/case/ioc/list').json() self.assertEqual('success', response['status']) - def test_create_ioc_should_return_good_ioc_type_id(self): + def test_create_ioc_should_return_correct_ioc_type_id(self): case_identifier = self._subject.create_dummy_case() body = {'ioc_type_id': 1, 'ioc_tlp_id': 2, 'ioc_value': '8.8.8.8', 'ioc_description': 'rewrw', 'ioc_tags': ''} response = self._subject.create(f'/api/v2/cases/{case_identifier}/iocs', body).json() @@ -103,7 +103,7 @@ def test_get_iocs_should_filter_and_return_ioc_type_identifier(self): filters = {'ioc_value': 'test_get_iocs_should_filter_on_ioc_value'} response = self._subject.get(f'/api/v2/cases/{case_identifier}/iocs', query_parameters=filters).json() identifiers = [] - for ioc in response['iocs']: + for ioc in response['data']: identifiers.append(ioc['ioc_type_id']) self.assertIn(ioc_type_identifier, identifiers) @@ -125,7 +125,7 @@ def test_get_iocs_should_include_tlp_information(self): body = {'ioc_type_id': 1, 'ioc_tlp_id': tlp_identifier, 'ioc_value': '8.8.8.8', 'ioc_description': 'rewrw', 'ioc_tags': ''} self._subject.create(f'/api/v2/cases/{case_identifier}/iocs', body).json() response = self._subject.get(f'/api/v2/cases/{case_identifier}/iocs').json() - self.assertEqual(tlp_identifier, response['iocs'][0]['tlp']['tlp_id']) + self.assertEqual(tlp_identifier, response['data'][0]['tlp']['tlp_id']) def test_get_iocs_should_include_link_to_other_cases_with_same_value_type_ioc(self): case_identifier1 = self._subject.create_dummy_case() @@ -135,7 +135,7 @@ def test_get_iocs_should_include_link_to_other_cases_with_same_value_type_ioc(se body = {'ioc_type_id': 1, 'ioc_tlp_id': 1, 'ioc_value': '8.8.8.8', 'ioc_description': 'another', 'ioc_tags': ''} self._subject.create(f'/api/v2/cases/{case_identifier2}/iocs', body).json() response = self._subject.get(f'/api/v2/cases/{case_identifier2}/iocs').json() - self.assertEqual(case_identifier1, response['iocs'][0]['link'][0]['case_id']) + self.assertEqual(case_identifier1, response['data'][0]['link'][0]['case_id']) def test_create_ioc_should_include_field_link(self): case_identifier = self._subject.create_dummy_case() diff --git a/ui/src/pages/case.ioc.js b/ui/src/pages/case.ioc.js index d0cc9af03..12c82bc57 100644 --- a/ui/src/pages/case.ioc.js +++ b/ui/src/pages/case.ioc.js @@ -148,7 +148,7 @@ function get_case_ioc() { } Table.clear(); - Table.rows.add(data.iocs); + Table.rows.add(data.data); $('#ioc_table_wrapper').on('click', function(e){ if($('.popover').length>1) From 88f5ed0e942c66db0675f67f420c020babc8364c Mon Sep 17 00:00:00 2001 From: c8y3 <25362953+c8y3@users.noreply.github.com> Date: Mon, 7 Oct 2024 17:02:43 +0200 Subject: [PATCH 03/46] [IMP] Uniform syntax FROM and AS --- docker/webApp/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/webApp/Dockerfile b/docker/webApp/Dockerfile index 10b4143b3..e0a7663cb 100644 --- a/docker/webApp/Dockerfile +++ b/docker/webApp/Dockerfile @@ -48,7 +48,7 @@ RUN pip3 install -r requirements.txt ############### # BUILD IMAGE # ############### -FROM python:3.9 as iriswebapp +FROM python:3.9 AS iriswebapp ENV PYTHONUNBUFFERED=1 DOCKERIZED=1 COPY --from=compile-image /opt/venv /opt/venv From 1aa8bbdbd820e302c1a874b6f025175135796824 Mon Sep 17 00:00:00 2001 From: c8y3 <25362953+c8y3@users.noreply.github.com> Date: Mon, 7 Oct 2024 17:24:42 +0200 Subject: [PATCH 04/46] [IMP] Change user customer to initial so that the customer can be removed --- tests/tests_rest_customers.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/tests_rest_customers.py b/tests/tests_rest_customers.py index ac7c09f61..af4f2e113 100644 --- a/tests/tests_rest_customers.py +++ b/tests/tests_rest_customers.py @@ -20,6 +20,7 @@ from iris import Iris _PERMISSION_CUSTOMERS_WRITE = 0x80 +_IRIS_INITIAL_CLIENT_IDENTIFIER = 1 class TestsRestCustomers(TestCase): @@ -28,6 +29,11 @@ def setUp(self) -> None: self._subject = Iris() def tearDown(self): + users = self._subject.get('/manage/users/list').json() + for user in users['data']: + identifier = user['user_id'] + body = {'customers_membership': [_IRIS_INITIAL_CLIENT_IDENTIFIER]} + self._subject.create(f'/manage/users/{identifier}/customers/update', body) self._subject.clear_database() def test_create_customer_should_return_200_when_user_has_customer_write_right(self): From 6fe85fa545e68194a8a2fb400769eaab9f7fa309 Mon Sep 17 00:00:00 2001 From: c8y3 <25362953+c8y3@users.noreply.github.com> Date: Tue, 8 Oct 2024 12:58:02 +0200 Subject: [PATCH 05/46] [IMP] Remove customers only in tests_rest_customers --- tests/iris.py | 7 +++---- tests/tests_rest_customers.py | 4 ++++ 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/tests/iris.py b/tests/iris.py index a0604135b..396fb3014 100644 --- a/tests/iris.py +++ b/tests/iris.py @@ -28,6 +28,7 @@ _IRIS_PATH = Path('..') _TEST_DATA_PATH = Path('./data') _ADMINISTRATOR_USER_IDENTIFIER = 1 +_INITIAL_DEMO_CASE_IDENTIFIER = 1 class Iris: @@ -77,12 +78,10 @@ def clear_database(self): cases = self.get('/api/v2/cases', query_parameters={'per_page': 1000000000}).json() for case in cases['data']: identifier = case['case_id'] + if identifier == _INITIAL_DEMO_CASE_IDENTIFIER: + continue self.delete(f'/api/v2/cases/{identifier}') groups = self.get('/manage/groups/list').json() for group in groups['data']: identifier = group['group_id'] self.create(f'/manage/groups/delete/{identifier}', {}) - customers = self.get('/manage/customers/list').json() - for customer in customers['data']: - identifier = customer['customer_id'] - self.create(f'/manage/customers/delete/{identifier}', {}) diff --git a/tests/tests_rest_customers.py b/tests/tests_rest_customers.py index af4f2e113..e58036dcf 100644 --- a/tests/tests_rest_customers.py +++ b/tests/tests_rest_customers.py @@ -34,6 +34,10 @@ def tearDown(self): identifier = user['user_id'] body = {'customers_membership': [_IRIS_INITIAL_CLIENT_IDENTIFIER]} self._subject.create(f'/manage/users/{identifier}/customers/update', body) + customers = self._subject.get('/manage/customers/list').json() + for customer in customers['data']: + identifier = customer['customer_id'] + self._subject.create(f'/manage/customers/delete/{identifier}', {}) self._subject.clear_database() def test_create_customer_should_return_200_when_user_has_customer_write_right(self): From 38183aab35b98432b0efd3d9eade17dc14ff3deb Mon Sep 17 00:00:00 2001 From: c8y3 <25362953+c8y3@users.noreply.github.com> Date: Tue, 8 Oct 2024 13:08:57 +0200 Subject: [PATCH 06/46] [IMP] Remove users after each test --- tests/iris.py | 5 +++++ tests/tests_rest_customers.py | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/tests/iris.py b/tests/iris.py index 396fb3014..c0982f5d1 100644 --- a/tests/iris.py +++ b/tests/iris.py @@ -85,3 +85,8 @@ def clear_database(self): for group in groups['data']: identifier = group['group_id'] self.create(f'/manage/groups/delete/{identifier}', {}) + users = self.get('/manage/users/list').json() + for user in users['data']: + identifier = user['user_id'] + self.get(f'/manage/users/deactivate/{identifier}') + self.create(f'/manage/users/delete/{identifier}', {}) diff --git a/tests/tests_rest_customers.py b/tests/tests_rest_customers.py index e58036dcf..29d0c0882 100644 --- a/tests/tests_rest_customers.py +++ b/tests/tests_rest_customers.py @@ -29,6 +29,7 @@ def setUp(self) -> None: self._subject = Iris() def tearDown(self): + self._subject.clear_database() users = self._subject.get('/manage/users/list').json() for user in users['data']: identifier = user['user_id'] @@ -38,7 +39,6 @@ def tearDown(self): for customer in customers['data']: identifier = customer['customer_id'] self._subject.create(f'/manage/customers/delete/{identifier}', {}) - self._subject.clear_database() def test_create_customer_should_return_200_when_user_has_customer_write_right(self): body = { From 2f7ef1f9f244d06bda737e5e691aaeb25c2692f9 Mon Sep 17 00:00:00 2001 From: c8y3 <25362953+c8y3@users.noreply.github.com> Date: Tue, 8 Oct 2024 13:23:25 +0200 Subject: [PATCH 07/46] [IMP] Removed spurious line --- tests/tests_rest_assets.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/tests_rest_assets.py b/tests/tests_rest_assets.py index 02e23d570..46c2f4ba2 100644 --- a/tests/tests_rest_assets.py +++ b/tests/tests_rest_assets.py @@ -31,7 +31,6 @@ def setUp(self) -> None: def tearDown(self): self._subject.clear_database() - def test_delete_asset_should_return_204(self): case_identifier = self._subject.create_dummy_case() body = {'asset_type_id': '1', 'asset_name': 'admin_laptop_test'} From 2904d9b8b9ad535332712a702b97bba01d3ff997 Mon Sep 17 00:00:00 2001 From: c8y3 <25362953+c8y3@users.noreply.github.com> Date: Tue, 8 Oct 2024 13:30:55 +0200 Subject: [PATCH 08/46] [IMP] Return 404 when trying to delete inexistant IOC --- source/app/blueprints/rest/case/case_ioc_routes.py | 1 + source/app/blueprints/rest/v2/case/api_v2_ioc_routes.py | 2 +- tests/tests_rest_iocs.py | 5 ++--- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/source/app/blueprints/rest/case/case_ioc_routes.py b/source/app/blueprints/rest/case/case_ioc_routes.py index 898783fe4..7a593aba4 100644 --- a/source/app/blueprints/rest/case/case_ioc_routes.py +++ b/source/app/blueprints/rest/case/case_ioc_routes.py @@ -214,6 +214,7 @@ def deprecated_case_delete_ioc(cur_id, caseid): except BusinessProcessingError as e: return response_error(e.get_message()) + @case_ioc_rest_blueprint.route('/case/ioc/', methods=['GET']) @endpoint_deprecated('GET', '/api/v2/iocs/') @ac_requires_case_identifier(CaseAccessLevel.read_only, CaseAccessLevel.full_access) diff --git a/source/app/blueprints/rest/v2/case/api_v2_ioc_routes.py b/source/app/blueprints/rest/v2/case/api_v2_ioc_routes.py index a7c22d7b8..399f54cc2 100644 --- a/source/app/blueprints/rest/v2/case/api_v2_ioc_routes.py +++ b/source/app/blueprints/rest/v2/case/api_v2_ioc_routes.py @@ -118,7 +118,7 @@ def delete_case_ioc(identifier): return response_api_deleted() except ObjectNotFoundError: - raise BusinessProcessingError('Not a valid IOC for this case') + return response_api_not_found() except BusinessProcessingError as e: return response_api_error(e.get_message()) diff --git a/tests/tests_rest_iocs.py b/tests/tests_rest_iocs.py index 27149ba5b..36a0c2bc3 100644 --- a/tests/tests_rest_iocs.py +++ b/tests/tests_rest_iocs.py @@ -19,8 +19,7 @@ from unittest import TestCase from iris import Iris -# TODO should change None into 123456789 and maybe fix... -_IDENTIFIER_FOR_NONEXISTENT_OBJECT = None +_IDENTIFIER_FOR_NONEXISTENT_OBJECT = 123456789 class TestsRestIocs(TestCase): @@ -108,7 +107,7 @@ def test_get_iocs_should_filter_and_return_ioc_type_identifier(self): self.assertIn(ioc_type_identifier, identifiers) def test_get_ioc_should_return_404_when_not_present(self): - response = self._subject.get(f'/api/v2/iocs/137') + response = self._subject.get(f'/api/v2/iocs/{_IDENTIFIER_FOR_NONEXISTENT_OBJECT}') self.assertEqual(404, response.status_code) def test_get_ioc_should_return_200_on_success(self): From ccbc43bb7e18775bcfd153db822b6c9167b5bfc8 Mon Sep 17 00:00:00 2001 From: c8y3 <25362953+c8y3@users.noreply.github.com> Date: Tue, 8 Oct 2024 13:36:20 +0200 Subject: [PATCH 09/46] [IMP] Simple quotes instead of double quotes --- .../blueprints/rest/case/case_ioc_routes.py | 57 ++++++++++--------- 1 file changed, 29 insertions(+), 28 deletions(-) diff --git a/source/app/blueprints/rest/case/case_ioc_routes.py b/source/app/blueprints/rest/case/case_ioc_routes.py index 7a593aba4..afe8bdf6c 100644 --- a/source/app/blueprints/rest/case/case_ioc_routes.py +++ b/source/app/blueprints/rest/case/case_ioc_routes.py @@ -83,7 +83,7 @@ def case_list_ioc(caseid): ret['state'] = get_ioc_state(caseid=caseid) - return response_success("", data=ret) + return response_success('', data=ret) @case_ioc_rest_blueprint.route('/case/ioc/state', methods=['GET']) @@ -120,8 +120,8 @@ def case_upload_ioc(caseid): jsdata = request.get_json() # get IOC list from request - headers = "ioc_value,ioc_type,ioc_description,ioc_tags,ioc_tlp" - csv_lines = jsdata["CSVData"].splitlines() # unavoidable since the file is passed as a string + headers = 'ioc_value,ioc_type,ioc_description,ioc_tags,ioc_tlp' + csv_lines = jsdata['CSVData'].splitlines() # unavoidable since the file is passed as a string if csv_lines[0].lower() != headers: csv_lines.insert(0, headers) @@ -138,30 +138,32 @@ def case_upload_ioc(caseid): for e in headers.split(','): if row.get(e) is None: - errors.append(f"{e} is missing for row {index}") + errors.append(f'{e} is missing for row {index}') index += 1 continue # IOC value must not be empty - if not row.get("ioc_value"): - errors.append(f"Empty IOC value for row {index}") - track_activity("Attempted to upload an empty IOC value") + if not row.get('ioc_value'): + errors.append(f'Empty IOC value for row {index}') + track_activity('Attempted to upload an empty IOC value') index += 1 continue - row["ioc_tags"] = row["ioc_tags"].replace("|", ",") # Reformat Tags + row['ioc_tags'] = row['ioc_tags'].replace('|', ',') # Reformat Tags # Convert TLP into TLP id - if row["ioc_tlp"] in tlp_dict: - row["ioc_tlp_id"] = tlp_dict[row["ioc_tlp"]] + if row['ioc_tlp'] in tlp_dict: + row['ioc_tlp_id'] = tlp_dict[row['ioc_tlp']] else: - row["ioc_tlp_id"] = "" - row.pop("ioc_tlp", None) + row['ioc_tlp_id'] = '' + row.pop('ioc_tlp', None) type_id = get_ioc_type_id(row['ioc_type'].lower()) if not type_id: - errors.append(f"{row['ioc_value']} (invalid ioc type: {row['ioc_type']}) for row {index}") - log.error(f'Unrecognised IOC type {row["ioc_type"]}') + ioc_value = row['ioc_value'] + ioc_type = row['ioc_type'] + errors.append(f'{ioc_value} (invalid ioc type: {ioc_type}) for row {index}') + log.error(f'Unrecognised IOC type {ioc_type}') index += 1 continue @@ -175,25 +177,24 @@ def case_upload_ioc(caseid): index += 1 if not ioc: - errors.append(f"{ioc.ioc_value} (internal reasons)") - log.error(f"Unable to create IOC {ioc.ioc_value} for internal reasons") + errors.append(f'{ioc.ioc_value} (internal reasons)') + log.error(f'Unable to create IOC {ioc.ioc_value} for internal reasons') continue add_ioc(ioc, current_user.id, caseid) ioc = call_modules_hook('on_postload_ioc_create', data=ioc, caseid=caseid) ret.append(request_data) - track_activity(f"added ioc \"{ioc.ioc_value}\"", caseid=caseid) - + track_activity(f'added ioc "{ioc.ioc_value}"', caseid=caseid) if len(errors) == 0: - msg = "Successfully imported data." + msg = 'Successfully imported data.' else: - msg = "Data is imported but we got errors with the following rows:\n- " + "\n- ".join(errors) + msg = 'Data is imported but we got errors with the following rows:\n- ' + '\n- '.join(errors) return response_success(msg=msg, data=ret) except marshmallow.exceptions.ValidationError as e: - return response_error(msg="Data error", data=e.messages) + return response_error(msg='Data error', data=e.messages) @case_ioc_rest_blueprint.route('/case/ioc/delete/', methods=['POST']) @@ -276,16 +277,16 @@ def case_comment_ioc_add(cur_id, caseid): db.session.commit() hook_data = { - "comment": comment_schema.dump(comment), - "ioc": IocSchema().dump(ioc) + 'comment': comment_schema.dump(comment), + 'ioc': IocSchema().dump(ioc) } call_modules_hook('on_postload_ioc_commented', data=hook_data, caseid=ioc.case_id) - track_activity(f"ioc \"{ioc.ioc_value}\" commented", caseid=ioc.case_id) - return response_success("Event commented", data=comment_schema.dump(comment)) + track_activity(f'ioc "{ioc.ioc_value}" commented', caseid=ioc.case_id) + return response_success('Event commented', data=comment_schema.dump(comment)) except marshmallow.exceptions.ValidationError as e: - return response_error(msg="Data error", data=e.normalized_messages()) + return response_error(msg='Data error', data=e.normalized_messages()) except ObjectNotFoundError: return response_error('Invalid ioc ID') @@ -296,7 +297,7 @@ def case_comment_ioc_add(cur_id, caseid): def case_comment_ioc_get(cur_id, com_id, caseid): comment = get_case_ioc_comment(cur_id, com_id) if not comment: - return response_error("Invalid comment ID") + return response_error('Invalid comment ID') return response_success(data=comment._asdict()) @@ -318,5 +319,5 @@ def case_comment_ioc_delete(cur_id, com_id, caseid): call_modules_hook('on_postload_ioc_comment_delete', data=com_id, caseid=caseid) - track_activity(f"comment {com_id} on ioc {cur_id} deleted", caseid=caseid) + track_activity(f'comment {com_id} on ioc {cur_id} deleted', caseid=caseid) return response_success(msg) From afb054da6a5c3641f5dbe2c4adbaa96e8ba7b1b8 Mon Sep 17 00:00:00 2001 From: c8y3 <25362953+c8y3@users.noreply.github.com> Date: Tue, 8 Oct 2024 13:40:44 +0200 Subject: [PATCH 10/46] [IMP] Return 404 when trying to delete inexistant task --- source/app/blueprints/rest/case/case_tasks_routes.py | 2 ++ tests/tests_rest_tasks.py | 3 +-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/source/app/blueprints/rest/case/case_tasks_routes.py b/source/app/blueprints/rest/case/case_tasks_routes.py index f0703b8e3..71a3d32d4 100644 --- a/source/app/blueprints/rest/case/case_tasks_routes.py +++ b/source/app/blueprints/rest/case/case_tasks_routes.py @@ -199,6 +199,8 @@ def case_delete_task(identifier): tasks_delete(task) return response_api_deleted() + except ObjectNotFoundError: + return response_api_not_found() except BusinessProcessingError as e: return response_api_error(e.get_message()) diff --git a/tests/tests_rest_tasks.py b/tests/tests_rest_tasks.py index 1f0184226..bb743f422 100644 --- a/tests/tests_rest_tasks.py +++ b/tests/tests_rest_tasks.py @@ -19,8 +19,7 @@ from unittest import TestCase from iris import Iris -# TODO should change None into 123456789 and maybe fix... -_IDENTIFIER_FOR_NONEXISTENT_OBJECT = None +_IDENTIFIER_FOR_NONEXISTENT_OBJECT = 123456789 class TestsRestTasks(TestCase): From 8541fd428b78a049e8121a0329daea72426e03e2 Mon Sep 17 00:00:00 2001 From: c8y3 <25362953+c8y3@users.noreply.github.com> Date: Tue, 8 Oct 2024 14:00:23 +0200 Subject: [PATCH 11/46] [IMP] Missing line break --- source/app/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/source/app/__init__.py b/source/app/__init__.py index ae0a97c39..730320c64 100644 --- a/source/app/__init__.py +++ b/source/app/__init__.py @@ -65,6 +65,7 @@ class AlertsNamespace(Namespace): app = Flask(__name__, static_folder="../static") + def ac_current_user_has_permission(*permissions): """ Return True if current user has permission From f9487c282655d7ae231ed96174d643b4a27ab3fa Mon Sep 17 00:00:00 2001 From: c8y3 <25362953+c8y3@users.noreply.github.com> Date: Tue, 8 Oct 2024 14:05:12 +0200 Subject: [PATCH 12/46] [IMP] Renamed method to follow coding conventions --- source/app/blueprints/rest/case/case_routes.py | 4 ++-- source/app/datamgmt/case/case_db.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/source/app/blueprints/rest/case/case_routes.py b/source/app/blueprints/rest/case/case_routes.py index 85d7bc8d8..1904b33c0 100644 --- a/source/app/blueprints/rest/case/case_routes.py +++ b/source/app/blueprints/rest/case/case_routes.py @@ -43,7 +43,7 @@ from app.business.cases import cases_create from app.business.cases import cases_delete from app.business.errors import BusinessProcessingError -from app.datamgmt.case.case_db import case_exists +from app.datamgmt.case.case_db import case_db_exists from app.datamgmt.case.case_db import get_review_id_from_name from app.datamgmt.case.case_db import case_get_desc_crc from app.datamgmt.case.case_db import get_case @@ -85,7 +85,7 @@ @ac_api_requires() def case_exists_r(caseid): - if case_exists(caseid): + if case_db_exists(caseid): return response_success('Case exists') return response_error('Case does not exist', 404) diff --git a/source/app/datamgmt/case/case_db.py b/source/app/datamgmt/case/case_db.py index 3d9998ba7..fc3cbda8d 100644 --- a/source/app/datamgmt/case/case_db.py +++ b/source/app/datamgmt/case/case_db.py @@ -51,7 +51,7 @@ def get_case(caseid) -> Cases: return Cases.query.filter(Cases.case_id == caseid).first() -def case_exists(caseid): +def case_db_exists(caseid): return Cases.query.filter(Cases.case_id == caseid).count() From d747c8df0313e988509948e3f1a4bd72f5919d2f Mon Sep 17 00:00:00 2001 From: c8y3 <25362953+c8y3@users.noreply.github.com> Date: Tue, 8 Oct 2024 14:07:38 +0200 Subject: [PATCH 13/46] [IMP] Introduced method in business layer --- source/app/blueprints/rest/case/case_routes.py | 6 +++--- source/app/business/cases.py | 5 +++++ 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/source/app/blueprints/rest/case/case_routes.py b/source/app/blueprints/rest/case/case_routes.py index 1904b33c0..cf557e443 100644 --- a/source/app/blueprints/rest/case/case_routes.py +++ b/source/app/blueprints/rest/case/case_routes.py @@ -42,8 +42,8 @@ from app.iris_engine.access_control.utils import ac_fast_check_current_user_has_case_access from app.business.cases import cases_create from app.business.cases import cases_delete +from app.business.cases import cases_exists from app.business.errors import BusinessProcessingError -from app.datamgmt.case.case_db import case_db_exists from app.datamgmt.case.case_db import get_review_id_from_name from app.datamgmt.case.case_db import case_get_desc_crc from app.datamgmt.case.case_db import get_case @@ -83,9 +83,9 @@ @endpoint_deprecated('GET', '/api/v2/cases/') @ac_requires_case_identifier(CaseAccessLevel.read_only, CaseAccessLevel.full_access) @ac_api_requires() -def case_exists_r(caseid): +def case_routes_exists(caseid): - if case_db_exists(caseid): + if cases_exists(caseid): return response_success('Case exists') return response_error('Case does not exist', 404) diff --git a/source/app/business/cases.py b/source/app/business/cases.py index 67346d329..65473905a 100644 --- a/source/app/business/cases.py +++ b/source/app/business/cases.py @@ -39,6 +39,7 @@ from app.iris_engine.utils.tracker import track_activity from app.iris_engine.access_control.utils import ac_set_new_case_access +from app.datamgmt.case.case_db import case_db_exists from app.datamgmt.case.case_db import save_case_tags from app.datamgmt.case.case_db import register_case_protagonists from app.datamgmt.case.case_db import get_review_id_from_name @@ -74,6 +75,10 @@ def cases_get_by_identifier(case_identifier): return get_case(case_identifier) +def cases_exists(identifier): + return case_db_exists(identifier) + + def cases_create(request_json): # TODO remove caseid doesn't seems to be useful for call_modules_hook => remove argument request_data = call_modules_hook('on_preload_case_create', request_json, None) From 0c40079b0dcc74b3d1247a0fb67f6f38f04c5a22 Mon Sep 17 00:00:00 2001 From: c8y3 <25362953+c8y3@users.noreply.github.com> Date: Tue, 8 Oct 2024 14:41:48 +0200 Subject: [PATCH 14/46] [IMP] Return 404 when deleting inexistant asset of creating an asset on an inexistant case --- source/app/blueprints/rest/case/case_assets_routes.py | 7 ++----- .../app/blueprints/rest/v2/case/api_v2_assets_routes.py | 9 ++++++++- source/app/business/assets.py | 3 ++- source/app/datamgmt/manage/manage_access_control_db.py | 6 +++++- tests/tests_rest_assets.py | 3 +-- 5 files changed, 18 insertions(+), 10 deletions(-) diff --git a/source/app/blueprints/rest/case/case_assets_routes.py b/source/app/blueprints/rest/case/case_assets_routes.py index 6a7c1c632..85b788290 100644 --- a/source/app/blueprints/rest/case/case_assets_routes.py +++ b/source/app/blueprints/rest/case/case_assets_routes.py @@ -26,10 +26,6 @@ from app import db from app.blueprints.rest.case_comments import case_comment_update from app.blueprints.rest.endpoints import endpoint_deprecated -from app.blueprints.rest.endpoints import response_api_deleted -from app.blueprints.rest.endpoints import response_api_success -from app.blueprints.rest.endpoints import response_api_error -from app.blueprints.rest.endpoints import response_api_created from app.business.assets import assets_delete from app.business.assets import assets_create from app.business.assets import assets_get_detailed @@ -59,7 +55,8 @@ from app.models.authorization import CaseAccessLevel from app.schema.marshables import CaseAssetsSchema from app.schema.marshables import CommentSchema -from app.blueprints.access_controls import ac_requires_case_identifier, ac_api_requires +from app.blueprints.access_controls import ac_requires_case_identifier +from app.blueprints.access_controls import ac_api_requires from app.util import response_error from app.util import response_success from app.util import ac_api_return_access_denied diff --git a/source/app/blueprints/rest/v2/case/api_v2_assets_routes.py b/source/app/blueprints/rest/v2/case/api_v2_assets_routes.py index 3e0a748de..1f5d7207b 100644 --- a/source/app/blueprints/rest/v2/case/api_v2_assets_routes.py +++ b/source/app/blueprints/rest/v2/case/api_v2_assets_routes.py @@ -24,10 +24,13 @@ from app.blueprints.rest.endpoints import response_api_deleted from app.blueprints.rest.endpoints import response_api_error from app.blueprints.rest.endpoints import response_api_success +from app.blueprints.rest.endpoints import response_api_not_found +from app.business.cases import cases_exists from app.business.assets import assets_create from app.business.assets import assets_delete from app.business.assets import assets_get from app.business.errors import BusinessProcessingError +from app.business.errors import ObjectNotFoundError from app.iris_engine.access_control.utils import ac_fast_check_current_user_has_case_access from app.models.authorization import CaseAccessLevel from app.schema.marshables import CaseAssetsSchema @@ -41,6 +44,8 @@ @api_v2_assets_blueprint.route('/cases//assets', methods=['POST']) @ac_api_requires() def add_asset(identifier): + if not cases_exists(identifier): + return response_api_not_found() if not ac_fast_check_current_user_has_case_access(identifier, [CaseAccessLevel.full_access]): return ac_api_return_access_denied(caseid=identifier) @@ -77,5 +82,7 @@ def asset_delete(identifier): assets_delete(asset) return response_api_deleted() + except ObjectNotFoundError: + return response_api_not_found() except BusinessProcessingError as e: - return response_api_error(e.get_message()) \ No newline at end of file + return response_api_error(e.get_message()) diff --git a/source/app/business/assets.py b/source/app/business/assets.py index 98d9b799a..361e7a1b9 100644 --- a/source/app/business/assets.py +++ b/source/app/business/assets.py @@ -20,6 +20,7 @@ from marshmallow.exceptions import ValidationError from app.business.errors import BusinessProcessingError +from app.business.errors import ObjectNotFoundError from app.models import CaseAssets from app.datamgmt.case.case_assets_db import get_asset from app.datamgmt.case.case_assets_db import case_assets_db_exists @@ -73,7 +74,7 @@ def assets_delete(asset: CaseAssets): def assets_get(identifier) -> CaseAssets: asset = get_asset(identifier) if not asset: - raise BusinessProcessingError('Invalid asset ID for this case') + raise ObjectNotFoundError() return asset diff --git a/source/app/datamgmt/manage/manage_access_control_db.py b/source/app/datamgmt/manage/manage_access_control_db.py index 7d885303f..9532375c7 100644 --- a/source/app/datamgmt/manage/manage_access_control_db.py +++ b/source/app/datamgmt/manage/manage_access_control_db.py @@ -14,6 +14,7 @@ # You should have received a copy of the GNU Lesser General Public License # along with this program; if not, write to the Free Software Foundation, # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + from app import ac_current_user_has_permission from app.models import Cases from app.models.authorization import Group @@ -25,6 +26,9 @@ from app.models.authorization import OrganisationCaseAccess from app.models.authorization import User from app.models.authorization import UserCaseAccess +from app.datamgmt.case.case_db import case_db_exists + +from typing import Optional def manage_ac_audit_users_db(): @@ -73,7 +77,7 @@ def manage_ac_audit_users_db(): return ret -def check_ua_case_client(user_id: int, case_id: int) -> UserClient: +def check_ua_case_client(user_id: int, case_id: int) -> Optional[UserClient]: """Check if the user has access to the case, through the customer of the case (in other words, check that the customer of the case is assigned to the user) diff --git a/tests/tests_rest_assets.py b/tests/tests_rest_assets.py index 46c2f4ba2..8f9eb73d2 100644 --- a/tests/tests_rest_assets.py +++ b/tests/tests_rest_assets.py @@ -19,8 +19,7 @@ from unittest import TestCase from iris import Iris -# TODO should change None into 123456789 and maybe fix... -_IDENTIFIER_FOR_NONEXISTENT_OBJECT = None +_IDENTIFIER_FOR_NONEXISTENT_OBJECT = 123456789 class TestsRestAssets(TestCase): From 91e6088f0cf56d908881b2aedcf3908472a3eb29 Mon Sep 17 00:00:00 2001 From: c8y3 <25362953+c8y3@users.noreply.github.com> Date: Tue, 8 Oct 2024 16:29:55 +0200 Subject: [PATCH 15/46] [IMP] Moved ac_api_return_access_denied into namespace blueprints --- source/app/blueprints/access_controls.py | 17 +++++++++++++++-- .../pages/manage/manage_cases_routes.py | 2 +- .../blueprints/rest/case/case_assets_routes.py | 3 +-- .../app/blueprints/rest/case/case_ioc_routes.py | 2 +- source/app/blueprints/rest/case/case_routes.py | 2 +- .../blueprints/rest/case/case_tasks_routes.py | 2 +- .../rest/manage/manage_assets_routes.py | 2 +- .../rest/manage/manage_cases_routes.py | 2 +- .../app/blueprints/rest/manage/manage_groups.py | 2 +- .../app/blueprints/rest/manage/manage_users.py | 2 +- source/app/util.py | 13 ------------- 11 files changed, 24 insertions(+), 25 deletions(-) diff --git a/source/app/blueprints/access_controls.py b/source/app/blueprints/access_controls.py index 53ebce6ec..c19b7d241 100644 --- a/source/app/blueprints/access_controls.py +++ b/source/app/blueprints/access_controls.py @@ -21,7 +21,9 @@ import uuid from functools import wraps -from flask import request, session, render_template +from flask import request +from flask import session +from flask import render_template from flask_login import current_user from flask_wtf import FlaskForm from werkzeug.utils import redirect @@ -38,7 +40,6 @@ from app.util import response_error from app.util import is_user_authenticated from app.util import not_authenticated_redirection_url -from app.util import ac_api_return_access_denied def _user_has_at_least_a_required_permission(permissions: list[Permissions]): @@ -328,3 +329,15 @@ def wrap(*args, **kwargs): return wrap return inner_wrap + + +def ac_api_return_access_denied(caseid: int = None): + error_uuid = uuid.uuid4() + log.warning(f"EID {error_uuid} - Access denied with case #{caseid} for user ID {current_user.id} " + f"accessing URI {request.full_path}") + data = { + 'user_id': current_user.id, + 'case_id': caseid, + 'error_uuid': error_uuid + } + return response_error('Permission denied', data=data, status=403) diff --git a/source/app/blueprints/pages/manage/manage_cases_routes.py b/source/app/blueprints/pages/manage/manage_cases_routes.py index 13540a042..c7376cfb4 100644 --- a/source/app/blueprints/pages/manage/manage_cases_routes.py +++ b/source/app/blueprints/pages/manage/manage_cases_routes.py @@ -39,7 +39,7 @@ from app.models.authorization import CaseAccessLevel from app.models.authorization import Permissions from app.schema.marshables import CaseDetailsSchema -from app.util import ac_api_return_access_denied +from app.blueprints.access_controls import ac_api_return_access_denied from app.blueprints.access_controls import ac_requires from app.util import response_error diff --git a/source/app/blueprints/rest/case/case_assets_routes.py b/source/app/blueprints/rest/case/case_assets_routes.py index 85b788290..e7dc1a0b4 100644 --- a/source/app/blueprints/rest/case/case_assets_routes.py +++ b/source/app/blueprints/rest/case/case_assets_routes.py @@ -59,8 +59,7 @@ from app.blueprints.access_controls import ac_api_requires from app.util import response_error from app.util import response_success -from app.util import ac_api_return_access_denied - +from app.blueprints.access_controls import ac_api_return_access_denied case_assets_rest_blueprint = Blueprint('case_assets_rest', __name__) diff --git a/source/app/blueprints/rest/case/case_ioc_routes.py b/source/app/blueprints/rest/case/case_ioc_routes.py index afe8bdf6c..dd028e2b5 100644 --- a/source/app/blueprints/rest/case/case_ioc_routes.py +++ b/source/app/blueprints/rest/case/case_ioc_routes.py @@ -53,7 +53,7 @@ from app.schema.marshables import IocSchema from app.blueprints.access_controls import ac_requires_case_identifier from app.blueprints.access_controls import ac_api_requires -from app.util import ac_api_return_access_denied +from app.blueprints.access_controls import ac_api_return_access_denied from app.util import response_error from app.util import response_success diff --git a/source/app/blueprints/rest/case/case_routes.py b/source/app/blueprints/rest/case/case_routes.py index cf557e443..a7fba492f 100644 --- a/source/app/blueprints/rest/case/case_routes.py +++ b/source/app/blueprints/rest/case/case_routes.py @@ -70,7 +70,7 @@ from app.blueprints.access_controls import ac_requires_case_identifier from app.blueprints.access_controls import ac_api_requires from app.util import add_obj_history_entry -from app.util import ac_api_return_access_denied +from app.blueprints.access_controls import ac_api_return_access_denied from app.util import response_error from app.util import response_success diff --git a/source/app/blueprints/rest/case/case_tasks_routes.py b/source/app/blueprints/rest/case/case_tasks_routes.py index 71a3d32d4..c247fe105 100644 --- a/source/app/blueprints/rest/case/case_tasks_routes.py +++ b/source/app/blueprints/rest/case/case_tasks_routes.py @@ -54,7 +54,7 @@ from app.schema.marshables import CommentSchema from app.blueprints.access_controls import ac_requires_case_identifier from app.blueprints.access_controls import ac_api_requires -from app.util import ac_api_return_access_denied +from app.blueprints.access_controls import ac_api_return_access_denied from app.util import response_error from app.util import response_success diff --git a/source/app/blueprints/rest/manage/manage_assets_routes.py b/source/app/blueprints/rest/manage/manage_assets_routes.py index fd62134b7..e8c8dc34e 100644 --- a/source/app/blueprints/rest/manage/manage_assets_routes.py +++ b/source/app/blueprints/rest/manage/manage_assets_routes.py @@ -25,7 +25,7 @@ from app.models.authorization import CaseAccessLevel from app.schema.marshables import CaseAssetsSchema from app.blueprints.access_controls import ac_api_requires -from app.util import ac_api_return_access_denied +from app.blueprints.access_controls import ac_api_return_access_denied from app.util import response_success manage_assets_rest_blueprint = Blueprint('manage_assets_rest', __name__) diff --git a/source/app/blueprints/rest/manage/manage_cases_routes.py b/source/app/blueprints/rest/manage/manage_cases_routes.py index fc53e2171..c8d0f6fe7 100644 --- a/source/app/blueprints/rest/manage/manage_cases_routes.py +++ b/source/app/blueprints/rest/manage/manage_cases_routes.py @@ -52,7 +52,7 @@ from app.util import add_obj_history_entry from app.blueprints.access_controls import ac_requires_case_identifier from app.blueprints.access_controls import ac_api_requires -from app.util import ac_api_return_access_denied +from app.blueprints.access_controls import ac_api_return_access_denied from app.util import response_error from app.util import response_success from app.business.cases import cases_delete diff --git a/source/app/blueprints/rest/manage/manage_groups.py b/source/app/blueprints/rest/manage/manage_groups.py index 4f1e7b1ab..bc68e093c 100644 --- a/source/app/blueprints/rest/manage/manage_groups.py +++ b/source/app/blueprints/rest/manage/manage_groups.py @@ -44,7 +44,7 @@ from app.models.authorization import Permissions from app.schema.marshables import AuthorizationGroupSchema from app.blueprints.access_controls import ac_api_requires -from app.util import ac_api_return_access_denied +from app.blueprints.access_controls import ac_api_return_access_denied from app.util import response_error from app.util import response_success from app.iris_engine.demo_builder import protect_demo_mode_group diff --git a/source/app/blueprints/rest/manage/manage_users.py b/source/app/blueprints/rest/manage/manage_users.py index 1aa06d0f9..37e552c7a 100644 --- a/source/app/blueprints/rest/manage/manage_users.py +++ b/source/app/blueprints/rest/manage/manage_users.py @@ -48,7 +48,7 @@ from app.blueprints.access_controls import ac_api_requires from app.util import is_authentication_oidc, is_authentication_ldap -from app.util import ac_api_return_access_denied +from app.blueprints.access_controls import ac_api_return_access_denied from app.util import is_authentication_local from app.util import response_error from app.util import response_success diff --git a/source/app/util.py b/source/app/util.py index 941db86ee..75fe8b208 100644 --- a/source/app/util.py +++ b/source/app/util.py @@ -380,19 +380,6 @@ def regenerate_session(): session.modified = True -# TODO should move this method into an util file at the root of the blueprint namespace -def ac_api_return_access_denied(caseid: int = None): - error_uuid = uuid.uuid4() - log.warning(f"EID {error_uuid} - Access denied with case #{caseid} for user ID {current_user.id} " - f"accessing URI {request.full_path}") - data = { - 'user_id': current_user.id, - 'case_id': caseid, - 'error_uuid': error_uuid - } - return response_error('Permission denied', data=data, status=403) - - def endpoint_removed(message, version): def inner_wrap(f): @wraps(f) From e756d25be90020fd6b993022dc59e50a6319da6a Mon Sep 17 00:00:00 2001 From: c8y3 <25362953+c8y3@users.noreply.github.com> Date: Tue, 8 Oct 2024 17:00:06 +0200 Subject: [PATCH 16/46] [IMP] Moved ac_api_requires_client_access into namespace blueprints --- source/app/blueprints/access_controls.py | 14 ++++++++++++++ .../rest/manage/manage_customers_routes.py | 2 +- source/app/util.py | 14 -------------- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/source/app/blueprints/access_controls.py b/source/app/blueprints/access_controls.py index c19b7d241..6b2a6db21 100644 --- a/source/app/blueprints/access_controls.py +++ b/source/app/blueprints/access_controls.py @@ -35,6 +35,7 @@ from app.iris_engine.access_control.utils import ac_get_effective_permissions_of_user from app.models.authorization import Permissions from app.models.authorization import CaseAccessLevel + from app.util import update_current_case from app.util import log_exception_and_error from app.util import response_error @@ -341,3 +342,16 @@ def ac_api_return_access_denied(caseid: int = None): 'error_uuid': error_uuid } return response_error('Permission denied', data=data, status=403) + + +def ac_api_requires_client_access(): + def inner_wrap(f): + @wraps(f) + def wrap(*args, **kwargs): + client_id = kwargs.get('client_id') + if not user_has_client_access(current_user.id, client_id): + return response_error("Permission denied", status=403) + + return f(*args, **kwargs) + return wrap + return inner_wrap diff --git a/source/app/blueprints/rest/manage/manage_customers_routes.py b/source/app/blueprints/rest/manage/manage_customers_routes.py index 61d204418..e8c2428e9 100644 --- a/source/app/blueprints/rest/manage/manage_customers_routes.py +++ b/source/app/blueprints/rest/manage/manage_customers_routes.py @@ -43,7 +43,7 @@ from app.models.authorization import Permissions from app.schema.marshables import ContactSchema from app.schema.marshables import CustomerSchema -from app.util import ac_api_requires_client_access +from app.blueprints.access_controls import ac_api_requires_client_access from app.util import response_error from app.util import response_success diff --git a/source/app/util.py b/source/app/util.py index 75fe8b208..f0ed1c0bf 100644 --- a/source/app/util.py +++ b/source/app/util.py @@ -55,7 +55,6 @@ from app import app from app import db from app.datamgmt.case.case_db import get_case -from app.datamgmt.manage.manage_access_control_db import user_has_client_access from app.datamgmt.manage.manage_users_db import get_user from app.iris_engine.access_control.utils import ac_get_effective_permissions_of_user from app.iris_engine.utils.tracker import track_activity @@ -389,19 +388,6 @@ def wrap(*args, **kwargs): return inner_wrap -def ac_api_requires_client_access(): - def inner_wrap(f): - @wraps(f) - def wrap(*args, **kwargs): - client_id = kwargs.get('client_id') - if not user_has_client_access(current_user.id, client_id): - return response_error("Permission denied", status=403) - - return f(*args, **kwargs) - return wrap - return inner_wrap - - def decompress_7z(filename: Path, output_dir): """ Decompress a 7z file in specified output directory From c53f071f630c43aeaa3e429a980cae7f1ba938c5 Mon Sep 17 00:00:00 2001 From: c8y3 <25362953+c8y3@users.noreply.github.com> Date: Tue, 8 Oct 2024 17:01:59 +0200 Subject: [PATCH 17/46] [IMP] Moved is_user_authenticated into namespace blueprints --- source/app/blueprints/access_controls.py | 18 +++++++++++++++++- source/app/blueprints/graphql/graphql_route.py | 2 +- source/app/util.py | 11 ----------- 3 files changed, 18 insertions(+), 13 deletions(-) diff --git a/source/app/blueprints/access_controls.py b/source/app/blueprints/access_controls.py index 6b2a6db21..f788befdf 100644 --- a/source/app/blueprints/access_controls.py +++ b/source/app/blueprints/access_controls.py @@ -21,6 +21,7 @@ import uuid from functools import wraps +from flask import Request from flask import request from flask import session from flask import render_template @@ -29,17 +30,21 @@ from werkzeug.utils import redirect from app import TEMPLATE_PATH +from app import app from app.datamgmt.case.case_db import get_case from app.datamgmt.manage.manage_access_control_db import user_has_client_access from app.iris_engine.access_control.utils import ac_fast_check_user_has_case_access from app.iris_engine.access_control.utils import ac_get_effective_permissions_of_user from app.models.authorization import Permissions from app.models.authorization import CaseAccessLevel +from app.util import _local_authentication_process +from app.util import _local_authentication_process +from app.util import _local_authentication_process +from app.util import _oidc_proxy_authentication_process from app.util import update_current_case from app.util import log_exception_and_error from app.util import response_error -from app.util import is_user_authenticated from app.util import not_authenticated_redirection_url @@ -355,3 +360,14 @@ def wrap(*args, **kwargs): return f(*args, **kwargs) return wrap return inner_wrap + + +def is_user_authenticated(incoming_request: Request): + authentication_mapper = { + "oidc_proxy": _oidc_proxy_authentication_process, + "local": _local_authentication_process, + "ldap": _local_authentication_process, + "oidc": _local_authentication_process, + } + + return authentication_mapper.get(app.config.get("AUTHENTICATION_TYPE"))(incoming_request) diff --git a/source/app/blueprints/graphql/graphql_route.py b/source/app/blueprints/graphql/graphql_route.py index a39cbf744..9bd5bc559 100644 --- a/source/app/blueprints/graphql/graphql_route.py +++ b/source/app/blueprints/graphql/graphql_route.py @@ -34,7 +34,7 @@ from graphene_sqlalchemy import SQLAlchemyConnectionField from app.datamgmt.manage.manage_cases_db import build_filter_case_query -from app.util import is_user_authenticated +from app.blueprints.access_controls import is_user_authenticated from app.util import response_error from app.models.authorization import CaseAccessLevel diff --git a/source/app/util.py b/source/app/util.py index f0ed1c0bf..b97bb53ca 100644 --- a/source/app/util.py +++ b/source/app/util.py @@ -346,17 +346,6 @@ def not_authenticated_redirection_url(request_url: str): return redirection_mapper.get(app.config.get("AUTHENTICATION_TYPE"))() -def is_user_authenticated(incoming_request: Request): - authentication_mapper = { - "oidc_proxy": _oidc_proxy_authentication_process, - "local": _local_authentication_process, - "ldap": _local_authentication_process, - "oidc": _local_authentication_process, - } - - return authentication_mapper.get(app.config.get("AUTHENTICATION_TYPE"))(incoming_request) - - def is_authentication_local(): return app.config.get("AUTHENTICATION_TYPE") == "local" From 44f275a57b04b6afb471d4c215562c7dd0a955a2 Mon Sep 17 00:00:00 2001 From: c8y3 <25362953+c8y3@users.noreply.github.com> Date: Tue, 8 Oct 2024 17:04:01 +0200 Subject: [PATCH 18/46] [IMP] Removed seemingly dead method is_authentication_local --- source/app/blueprints/rest/manage/manage_users.py | 2 -- source/app/util.py | 4 ---- 2 files changed, 6 deletions(-) diff --git a/source/app/blueprints/rest/manage/manage_users.py b/source/app/blueprints/rest/manage/manage_users.py index 37e552c7a..9948c385c 100644 --- a/source/app/blueprints/rest/manage/manage_users.py +++ b/source/app/blueprints/rest/manage/manage_users.py @@ -47,9 +47,7 @@ from app.schema.marshables import UserFullSchema from app.blueprints.access_controls import ac_api_requires -from app.util import is_authentication_oidc, is_authentication_ldap from app.blueprints.access_controls import ac_api_return_access_denied -from app.util import is_authentication_local from app.util import response_error from app.util import response_success from app.iris_engine.demo_builder import protect_demo_mode_user diff --git a/source/app/util.py b/source/app/util.py index b97bb53ca..5ea5dfe8b 100644 --- a/source/app/util.py +++ b/source/app/util.py @@ -346,10 +346,6 @@ def not_authenticated_redirection_url(request_url: str): return redirection_mapper.get(app.config.get("AUTHENTICATION_TYPE"))() -def is_authentication_local(): - return app.config.get("AUTHENTICATION_TYPE") == "local" - - def is_authentication_ldap(): return app.config.get('AUTHENTICATION_TYPE') == "ldap" From 70a5afdcdd5a164ec807348cde8f8256c3298997 Mon Sep 17 00:00:00 2001 From: c8y3 <25362953+c8y3@users.noreply.github.com> Date: Tue, 8 Oct 2024 17:10:15 +0200 Subject: [PATCH 19/46] [IMP] Moved code out of util.py into blueprints namespace --- source/app/blueprints/access_controls.py | 117 ++++++++++++++++++++++- source/app/util.py | 109 --------------------- 2 files changed, 112 insertions(+), 114 deletions(-) diff --git a/source/app/blueprints/access_controls.py b/source/app/blueprints/access_controls.py index f788befdf..7b0c97218 100644 --- a/source/app/blueprints/access_controls.py +++ b/source/app/blueprints/access_controls.py @@ -21,26 +21,33 @@ import uuid from functools import wraps +import jwt +import requests + from flask import Request from flask import request -from flask import session from flask import render_template +from flask import session from flask_login import current_user +from flask_login import login_user from flask_wtf import FlaskForm +from jwt import PyJWKClient +from requests.auth import HTTPBasicAuth from werkzeug.utils import redirect from app import TEMPLATE_PATH + from app import app +from app import db from app.datamgmt.case.case_db import get_case from app.datamgmt.manage.manage_access_control_db import user_has_client_access +from app.datamgmt.manage.manage_users_db import get_user from app.iris_engine.access_control.utils import ac_fast_check_user_has_case_access from app.iris_engine.access_control.utils import ac_get_effective_permissions_of_user +from app.iris_engine.utils.tracker import track_activity +from app.models import Cases from app.models.authorization import Permissions from app.models.authorization import CaseAccessLevel -from app.util import _local_authentication_process -from app.util import _local_authentication_process -from app.util import _local_authentication_process -from app.util import _oidc_proxy_authentication_process from app.util import update_current_case from app.util import log_exception_and_error @@ -362,6 +369,106 @@ def wrap(*args, **kwargs): return inner_wrap +def _authenticate_with_email(user_email): + user = get_user(user_email, id_key="email") + if not user: + log.error(f'User with email {user_email} is not registered in the IRIS') + return False + + login_user(user) + track_activity(f"User '{user.id}' successfully logged-in", ctx_less=True) + + caseid = user.ctx_case + session['permissions'] = ac_get_effective_permissions_of_user(user) + + if caseid is None: + case = Cases.query.order_by(Cases.case_id).first() + user.ctx_case = case.case_id + user.ctx_human_case = case.name + db.session.commit() + + session['current_case'] = { + 'case_name': user.ctx_human_case, + 'case_info': "", + 'case_id': user.ctx_case + } + + return True + + +def _oidc_proxy_authentication_process(incoming_request: Request): + # Get the OIDC JWT authentication token from the request header + authentication_token = incoming_request.headers.get('X-Forwarded-Access-Token', '') + + if app.config.get("AUTHENTICATION_TOKEN_VERIFY_MODE") == 'lazy': + user_email = incoming_request.headers.get('X-Email') + + if user_email: + return _authenticate_with_email(user_email.split(',')[0]) + + elif app.config.get("AUTHENTICATION_TOKEN_VERIFY_MODE") == 'introspection': + # Use the authentication server's token introspection endpoint in order to determine if the request is valid / + # authenticated. The TLS_ROOT_CA is used to validate the authentication server's certificate. + # The other solution was to skip the certificate verification, BUT as the authentication server might be + # located on another server, this check is necessary. + + introspection_body = {"token": authentication_token} + introspection = requests.post( + app.config.get("AUTHENTICATION_TOKEN_INTROSPECTION_URL"), + auth=HTTPBasicAuth(app.config.get('AUTHENTICATION_CLIENT_ID'), app.config.get('AUTHENTICATION_CLIENT_SECRET')), + data=introspection_body, + verify=app.config.get("TLS_ROOT_CA") + ) + if introspection.status_code == 200: + response_json = introspection.json() + + if response_json.get("active", False) is True: + user_email = response_json.get("sub") + return _authenticate_with_email(user_email=user_email) + + else: + log.info("USER IS NOT AUTHENTICATED") + return False + + elif app.config.get("AUTHENTICATION_TOKEN_VERIFY_MODE") == 'signature': + # Use the JWKS urls provided by the OIDC discovery to fetch the signing keys + # and check the signature of the token + try: + jwks_client = PyJWKClient(app.config.get("AUTHENTICATION_JWKS_URL")) + signing_key = jwks_client.get_signing_key_from_jwt(authentication_token) + + try: + + data = jwt.decode( + authentication_token, + signing_key.key, + algorithms=["RS256"], + audience=app.config.get("AUTHENTICATION_AUDIENCE"), + options={"verify_exp": app.config.get("AUTHENTICATION_VERIFY_TOKEN_EXP")}, + ) + + except jwt.ExpiredSignatureError: + log.error("Provided token has expired") + return False + + except Exception as e: + log.error(f"Error decoding JWT. {e.__str__()}") + return False + + # Extract the user email + user_email = data.get("sub") + + return _authenticate_with_email(user_email) + + else: + log.error("ERROR DURING TOKEN INTROSPECTION PROCESS") + return False + + +def _local_authentication_process(incoming_request: Request): + return current_user.is_authenticated + + def is_user_authenticated(incoming_request: Request): authentication_mapper = { "oidc_proxy": _oidc_proxy_authentication_process, diff --git a/source/app/util.py b/source/app/util.py index 5ea5dfe8b..e4ac43cd5 100644 --- a/source/app/util.py +++ b/source/app/util.py @@ -22,12 +22,10 @@ import decimal import hashlib import json -import jwt import logging as log import marshmallow import pickle import random -import requests import shutil import string import traceback @@ -36,18 +34,14 @@ from cryptography.exceptions import InvalidSignature from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives import hmac -from flask import Request from flask import render_template from flask import request from flask import session from flask import url_for from flask_login import current_user -from flask_login import login_user from functools import wraps -from jwt import PyJWKClient from pathlib import Path from pyunpack import Archive -from requests.auth import HTTPBasicAuth from sqlalchemy.ext.declarative import DeclarativeMeta from sqlalchemy.orm.attributes import flag_modified @@ -55,9 +49,6 @@ from app import app from app import db from app.datamgmt.case.case_db import get_case -from app.datamgmt.manage.manage_users_db import get_user -from app.iris_engine.access_control.utils import ac_get_effective_permissions_of_user -from app.iris_engine.utils.tracker import track_activity from app.models import Cases @@ -235,106 +226,6 @@ def get_urlcasename(): return [case_name, case_info, caseid] -def _local_authentication_process(incoming_request: Request): - return current_user.is_authenticated - - -def _authenticate_with_email(user_email): - user = get_user(user_email, id_key="email") - if not user: - log.error(f'User with email {user_email} is not registered in the IRIS') - return False - - login_user(user) - track_activity(f"User '{user.id}' successfully logged-in", ctx_less=True) - - caseid = user.ctx_case - session['permissions'] = ac_get_effective_permissions_of_user(user) - - if caseid is None: - case = Cases.query.order_by(Cases.case_id).first() - user.ctx_case = case.case_id - user.ctx_human_case = case.name - db.session.commit() - - session['current_case'] = { - 'case_name': user.ctx_human_case, - 'case_info': "", - 'case_id': user.ctx_case - } - - return True - - -def _oidc_proxy_authentication_process(incoming_request: Request): - # Get the OIDC JWT authentication token from the request header - authentication_token = incoming_request.headers.get('X-Forwarded-Access-Token', '') - - if app.config.get("AUTHENTICATION_TOKEN_VERIFY_MODE") == 'lazy': - user_email = incoming_request.headers.get('X-Email') - - if user_email: - return _authenticate_with_email(user_email.split(',')[0]) - - elif app.config.get("AUTHENTICATION_TOKEN_VERIFY_MODE") == 'introspection': - # Use the authentication server's token introspection endpoint in order to determine if the request is valid / - # authenticated. The TLS_ROOT_CA is used to validate the authentication server's certificate. - # The other solution was to skip the certificate verification, BUT as the authentication server might be - # located on another server, this check is necessary. - - introspection_body = {"token": authentication_token} - introspection = requests.post( - app.config.get("AUTHENTICATION_TOKEN_INTROSPECTION_URL"), - auth=HTTPBasicAuth(app.config.get('AUTHENTICATION_CLIENT_ID'), app.config.get('AUTHENTICATION_CLIENT_SECRET')), - data=introspection_body, - verify=app.config.get("TLS_ROOT_CA") - ) - if introspection.status_code == 200: - response_json = introspection.json() - - if response_json.get("active", False) is True: - user_email = response_json.get("sub") - return _authenticate_with_email(user_email=user_email) - - else: - log.info("USER IS NOT AUTHENTICATED") - return False - - elif app.config.get("AUTHENTICATION_TOKEN_VERIFY_MODE") == 'signature': - # Use the JWKS urls provided by the OIDC discovery to fetch the signing keys - # and check the signature of the token - try: - jwks_client = PyJWKClient(app.config.get("AUTHENTICATION_JWKS_URL")) - signing_key = jwks_client.get_signing_key_from_jwt(authentication_token) - - try: - - data = jwt.decode( - authentication_token, - signing_key.key, - algorithms=["RS256"], - audience=app.config.get("AUTHENTICATION_AUDIENCE"), - options={"verify_exp": app.config.get("AUTHENTICATION_VERIFY_TOKEN_EXP")}, - ) - - except jwt.ExpiredSignatureError: - log.error("Provided token has expired") - return False - - except Exception as e: - log.error(f"Error decoding JWT. {e.__str__()}") - return False - - # Extract the user email - user_email = data.get("sub") - - return _authenticate_with_email(user_email) - - else: - log.error("ERROR DURING TOKEN INTROSPECTION PROCESS") - return False - - def not_authenticated_redirection_url(request_url: str): redirection_mapper = { "oidc_proxy": lambda: app.config.get("AUTHENTICATION_PROXY_LOGOUT_URL"), From fbe2f1f4ca990478843552c61e248eabb259a0ed Mon Sep 17 00:00:00 2001 From: c8y3 <25362953+c8y3@users.noreply.github.com> Date: Tue, 8 Oct 2024 17:11:44 +0200 Subject: [PATCH 20/46] [IMP] Moved update_current_case out of util.py into blueprints namespace --- source/app/blueprints/access_controls.py | 13 ++++++++++++- source/app/util.py | 13 ------------- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/source/app/blueprints/access_controls.py b/source/app/blueprints/access_controls.py index 7b0c97218..3bc358425 100644 --- a/source/app/blueprints/access_controls.py +++ b/source/app/blueprints/access_controls.py @@ -49,7 +49,6 @@ from app.models.authorization import Permissions from app.models.authorization import CaseAccessLevel -from app.util import update_current_case from app.util import log_exception_and_error from app.util import response_error from app.util import not_authenticated_redirection_url @@ -147,6 +146,18 @@ def _update_denied_case(caseid): } +def update_current_case(caseid, restricted_access): + if session['current_case']['case_id'] != caseid: + case = get_case(caseid) + if case: + session['current_case'] = { + 'case_name': "{}".format(case.name), + 'case_info': "(#{} - {})".format(caseid, case.client.name), + 'case_id': caseid, + 'access': restricted_access + } + + def _update_session(caseid, eaccess_level): restricted_access = '' if not eaccess_level: diff --git a/source/app/util.py b/source/app/util.py index e4ac43cd5..aa3285cfa 100644 --- a/source/app/util.py +++ b/source/app/util.py @@ -48,7 +48,6 @@ from app import TEMPLATE_PATH from app import app from app import db -from app.datamgmt.case.case_db import get_case from app.models import Cases @@ -193,18 +192,6 @@ def log_exception_and_error(e): log.error(traceback.print_exc()) -def update_current_case(caseid, restricted_access): - if session['current_case']['case_id'] != caseid: - case = get_case(caseid) - if case: - session['current_case'] = { - 'case_name': "{}".format(case.name), - 'case_info': "(#{} - {})".format(caseid, case.client.name), - 'case_id': caseid, - 'access': restricted_access - } - - def get_urlcasename(): caseid = request.args.get('cid', default=None, type=int) if not caseid: From 1f302b0907e6f135df26c40224a503841f08df9c Mon Sep 17 00:00:00 2001 From: c8y3 <25362953+c8y3@users.noreply.github.com> Date: Tue, 8 Oct 2024 17:12:13 +0200 Subject: [PATCH 21/46] [IMP] Made update_current_case private --- source/app/blueprints/access_controls.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/app/blueprints/access_controls.py b/source/app/blueprints/access_controls.py index 3bc358425..8b0cde2df 100644 --- a/source/app/blueprints/access_controls.py +++ b/source/app/blueprints/access_controls.py @@ -146,7 +146,7 @@ def _update_denied_case(caseid): } -def update_current_case(caseid, restricted_access): +def _update_current_case(caseid, restricted_access): if session['current_case']['case_id'] != caseid: case = get_case(caseid) if case: @@ -166,7 +166,7 @@ def _update_session(caseid, eaccess_level): if CaseAccessLevel.read_only.value == eaccess_level: restricted_access = '' - update_current_case(caseid, restricted_access) + _update_current_case(caseid, restricted_access) # TODO would be nice to remove parameter no_cid_required From 7415700ec17449553b8714f99d4b74e39fd34820 Mon Sep 17 00:00:00 2001 From: c8y3 <25362953+c8y3@users.noreply.github.com> Date: Tue, 8 Oct 2024 17:13:59 +0200 Subject: [PATCH 22/46] [IMP] Moved log_exception_and_error out of util.py into blueprints namespace --- source/app/blueprints/access_controls.py | 9 +++++++-- source/app/util.py | 6 ------ 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/source/app/blueprints/access_controls.py b/source/app/blueprints/access_controls.py index 8b0cde2df..d88fce502 100644 --- a/source/app/blueprints/access_controls.py +++ b/source/app/blueprints/access_controls.py @@ -18,6 +18,7 @@ import json import logging as log +import traceback import uuid from functools import wraps @@ -49,7 +50,6 @@ from app.models.authorization import Permissions from app.models.authorization import CaseAccessLevel -from app.util import log_exception_and_error from app.util import response_error from app.util import not_authenticated_redirection_url @@ -78,6 +78,11 @@ def _set_caseid_from_current_user(): return redir, caseid +def _log_exception_and_error(e): + log.exception(e) + log.error(traceback.print_exc()) + + def _get_caseid_from_request_data(request_data, no_cid_required): caseid = request_data.args.get('cid', default=None, type=int) if caseid: @@ -112,7 +117,7 @@ def _get_caseid_from_request_data(request_data, no_cid_required): redir, caseid = _set_caseid_from_current_user() return redir, caseid, True - log_exception_and_error(e) + _log_exception_and_error(e) return True, 0, False diff --git a/source/app/util.py b/source/app/util.py index aa3285cfa..313a02965 100644 --- a/source/app/util.py +++ b/source/app/util.py @@ -28,7 +28,6 @@ import random import shutil import string -import traceback import uuid import weakref from cryptography.exceptions import InvalidSignature @@ -187,11 +186,6 @@ def _do_cleanup(self, wr): shutil.rmtree(filepath, ignore_errors=True) -def log_exception_and_error(e): - log.exception(e) - log.error(traceback.print_exc()) - - def get_urlcasename(): caseid = request.args.get('cid', default=None, type=int) if not caseid: From b3f561bb84dedf9e42a41153264d011ee27fc602 Mon Sep 17 00:00:00 2001 From: c8y3 <25362953+c8y3@users.noreply.github.com> Date: Tue, 8 Oct 2024 17:16:46 +0200 Subject: [PATCH 23/46] [IMP] Moved page_not_found out of util.py into blueprints namespace --- .../pages/manage/manage_customers_routes.py | 2 +- source/app/blueprints/responses.py | 34 +++++++++++++++++++ source/app/util.py | 12 ------- 3 files changed, 35 insertions(+), 13 deletions(-) create mode 100644 source/app/blueprints/responses.py diff --git a/source/app/blueprints/pages/manage/manage_customers_routes.py b/source/app/blueprints/pages/manage/manage_customers_routes.py index 3800c82a7..132703547 100644 --- a/source/app/blueprints/pages/manage/manage_customers_routes.py +++ b/source/app/blueprints/pages/manage/manage_customers_routes.py @@ -33,7 +33,7 @@ from app.schema.marshables import ContactSchema from app.blueprints.access_controls import ac_requires from app.blueprints.access_controls import ac_requires_client_access -from app.util import page_not_found +from app.blueprints.responses import page_not_found from app.util import response_error manage_customers_blueprint = Blueprint( diff --git a/source/app/blueprints/responses.py b/source/app/blueprints/responses.py new file mode 100644 index 000000000..3ba714d9c --- /dev/null +++ b/source/app/blueprints/responses.py @@ -0,0 +1,34 @@ +# IRIS Source Code +# Copyright (C) 2024 - DFIR-IRIS +# contact@dfir-iris.org +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 3 of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +from flask import render_template +from flask import request + +from app import TEMPLATE_PATH +from app import app +from app.util import response_error + + +# Set basic 404 +@app.errorhandler(404) +def page_not_found(e): + # note that we set the 404 status explicitly + if request.content_type and 'application/json' in request.content_type: + return response_error("Resource not found", status=404) + + return render_template('pages/error-404.html', template_folder=TEMPLATE_PATH), 404 diff --git a/source/app/util.py b/source/app/util.py index 313a02965..1bcdec577 100644 --- a/source/app/util.py +++ b/source/app/util.py @@ -33,7 +33,6 @@ from cryptography.exceptions import InvalidSignature from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives import hmac -from flask import render_template from flask import request from flask import session from flask import url_for @@ -44,7 +43,6 @@ from sqlalchemy.ext.declarative import DeclarativeMeta from sqlalchemy.orm.attributes import flag_modified -from app import TEMPLATE_PATH from app import app from app import db from app.models import Cases @@ -298,16 +296,6 @@ def add_obj_history_entry(obj, action, commit=False): return obj -# Set basic 404 -@app.errorhandler(404) -def page_not_found(e): - # note that we set the 404 status explicitly - if request.content_type and 'application/json' in request.content_type: - return response_error("Resource not found", status=404) - - return render_template('pages/error-404.html', template_folder=TEMPLATE_PATH), 404 - - def file_sha256sum(file_path): if not Path(file_path).is_file(): From 73dc62cf05af5db227fb77fa44d0de153d68a2b9 Mon Sep 17 00:00:00 2001 From: c8y3 <25362953+c8y3@users.noreply.github.com> Date: Tue, 8 Oct 2024 17:20:08 +0200 Subject: [PATCH 24/46] [IMP] Moved endpoint_removed out of util.py into blueprints namespace --- source/app/blueprints/rest/case/case_notes_routes.py | 2 +- source/app/blueprints/rest/endpoints.py | 12 +++++++++++- source/app/blueprints/rest/profile_routes.py | 2 +- source/app/util.py | 10 ---------- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/source/app/blueprints/rest/case/case_notes_routes.py b/source/app/blueprints/rest/case/case_notes_routes.py index faae9d8d0..320a69ef6 100644 --- a/source/app/blueprints/rest/case/case_notes_routes.py +++ b/source/app/blueprints/rest/case/case_notes_routes.py @@ -54,7 +54,7 @@ from app.schema.marshables import CommentSchema from app.blueprints.access_controls import ac_requires_case_identifier from app.blueprints.access_controls import ac_api_requires -from app.util import endpoint_removed +from app.blueprints.rest.endpoints import endpoint_removed from app.util import response_error from app.util import response_success diff --git a/source/app/blueprints/rest/endpoints.py b/source/app/blueprints/rest/endpoints.py index dc0b196c7..f89c7561d 100644 --- a/source/app/blueprints/rest/endpoints.py +++ b/source/app/blueprints/rest/endpoints.py @@ -17,9 +17,10 @@ # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. from functools import wraps + from app import app -from app.business.errors import BusinessProcessingError from app.util import response +from app.util import response_error logger = app.logger @@ -60,3 +61,12 @@ def wrap(*args, **kwargs): return result return wrap return inner_wrap + + +def endpoint_removed(message, version): + def inner_wrap(f): + @wraps(f) + def wrap(*args, **kwargs): + return response_error(f"Endpoint deprecated in {version}. {message}.", status=410) + return wrap + return inner_wrap diff --git a/source/app/blueprints/rest/profile_routes.py b/source/app/blueprints/rest/profile_routes.py index c2c871668..c9b027e26 100644 --- a/source/app/blueprints/rest/profile_routes.py +++ b/source/app/blueprints/rest/profile_routes.py @@ -37,7 +37,7 @@ from app.blueprints.access_controls import ac_api_requires from app.util import response_error from app.util import response_success -from app.util import endpoint_removed +from app.blueprints.rest.endpoints import endpoint_removed profile_rest_blueprint = Blueprint('profile_rest', __name__) diff --git a/source/app/util.py b/source/app/util.py index 1bcdec577..1dcef3162 100644 --- a/source/app/util.py +++ b/source/app/util.py @@ -37,7 +37,6 @@ from flask import session from flask import url_for from flask_login import current_user -from functools import wraps from pathlib import Path from pyunpack import Archive from sqlalchemy.ext.declarative import DeclarativeMeta @@ -234,15 +233,6 @@ def regenerate_session(): session.modified = True -def endpoint_removed(message, version): - def inner_wrap(f): - @wraps(f) - def wrap(*args, **kwargs): - return response_error(f"Endpoint deprecated in {version}. {message}.", status=410) - return wrap - return inner_wrap - - def decompress_7z(filename: Path, output_dir): """ Decompress a 7z file in specified output directory From 6c3ac34921740065c2de7e92d245a490da7cfcf0 Mon Sep 17 00:00:00 2001 From: c8y3 <25362953+c8y3@users.noreply.github.com> Date: Tue, 8 Oct 2024 17:21:54 +0200 Subject: [PATCH 25/46] [IMP] Moved response_error out of util.py into blueprints namespace --- source/app/blueprints/access_controls.py | 2 +- source/app/blueprints/graphql/graphql_route.py | 2 +- source/app/blueprints/pages/alerts/alerts_routes.py | 2 +- .../app/blueprints/pages/case/case_assets_routes.py | 2 +- source/app/blueprints/pages/case/case_ioc_routes.py | 2 +- source/app/blueprints/pages/case/case_notes_routes.py | 3 +-- .../app/blueprints/pages/case/case_rfiles_routes.py | 2 +- source/app/blueprints/pages/case/case_tasks_routes.py | 2 +- .../app/blueprints/pages/case/case_timeline_routes.py | 2 +- .../blueprints/pages/datastore/datastore_routes.py | 2 +- source/app/blueprints/pages/dim_tasks/dim_tasks.py | 2 +- source/app/blueprints/pages/login/login_routes.py | 3 ++- .../pages/manage/manage_assets_type_routes.py | 2 +- .../pages/manage/manage_attributes_routes.py | 2 +- .../pages/manage/manage_case_classification_routes.py | 2 +- .../app/blueprints/pages/manage/manage_case_state.py | 2 +- .../pages/manage/manage_case_templates_routes.py | 2 +- .../blueprints/pages/manage/manage_cases_routes.py | 2 +- .../pages/manage/manage_customers_routes.py | 2 +- .../pages/manage/manage_evidence_types_route.py | 2 +- .../blueprints/pages/manage/manage_groups_routes.py | 2 +- .../pages/manage/manage_ioc_types_routes.py | 2 +- .../blueprints/pages/manage/manage_modules_routes.py | 2 +- source/app/blueprints/pages/manage/manage_users.py | 2 +- source/app/blueprints/responses.py | 11 ++++++++++- source/app/blueprints/rest/alerts_routes.py | 2 +- source/app/blueprints/rest/case/case_assets_routes.py | 2 +- .../app/blueprints/rest/case/case_evidences_routes.py | 2 +- source/app/blueprints/rest/case/case_ioc_routes.py | 2 +- source/app/blueprints/rest/case/case_notes_routes.py | 2 +- source/app/blueprints/rest/case/case_routes.py | 2 +- source/app/blueprints/rest/case/case_tasks_routes.py | 2 +- .../app/blueprints/rest/case/case_timeline_routes.py | 2 +- source/app/blueprints/rest/case_comments.py | 2 +- source/app/blueprints/rest/dashboard_routes.py | 3 ++- source/app/blueprints/rest/datastore_routes.py | 2 +- source/app/blueprints/rest/dim_tasks_routes.py | 2 +- source/app/blueprints/rest/endpoints.py | 2 +- source/app/blueprints/rest/filters_routes.py | 2 +- .../rest/manage/manage_alerts_status_routes.py | 2 +- .../rest/manage/manage_analysis_status_routes.py | 2 +- .../rest/manage/manage_assets_type_routes.py | 2 +- .../rest/manage/manage_attributes_routes.py | 2 +- .../rest/manage/manage_case_classifications_routes.py | 2 +- .../app/blueprints/rest/manage/manage_case_state.py | 2 +- .../rest/manage/manage_case_templates_routes.py | 2 +- .../app/blueprints/rest/manage/manage_cases_routes.py | 2 +- .../blueprints/rest/manage/manage_customers_routes.py | 2 +- .../rest/manage/manage_event_categories_routes.py | 2 +- .../rest/manage/manage_evidence_types_routes.py | 2 +- source/app/blueprints/rest/manage/manage_groups.py | 2 +- .../blueprints/rest/manage/manage_ioc_types_routes.py | 2 +- .../blueprints/rest/manage/manage_modules_routes.py | 2 +- .../rest/manage/manage_server_settings_routes.py | 2 +- .../rest/manage/manage_severities_routes.py | 2 +- .../rest/manage/manage_task_status_routes.py | 2 +- .../blueprints/rest/manage/manage_templates_routes.py | 2 +- .../app/blueprints/rest/manage/manage_tlps_routes.py | 2 +- source/app/blueprints/rest/manage/manage_users.py | 2 +- source/app/blueprints/rest/profile_routes.py | 2 +- source/app/blueprints/rest/reports_route.py | 2 +- source/app/util.py | 9 --------- 62 files changed, 72 insertions(+), 71 deletions(-) diff --git a/source/app/blueprints/access_controls.py b/source/app/blueprints/access_controls.py index d88fce502..aee140078 100644 --- a/source/app/blueprints/access_controls.py +++ b/source/app/blueprints/access_controls.py @@ -50,7 +50,7 @@ from app.models.authorization import Permissions from app.models.authorization import CaseAccessLevel -from app.util import response_error +from app.blueprints.responses import response_error from app.util import not_authenticated_redirection_url diff --git a/source/app/blueprints/graphql/graphql_route.py b/source/app/blueprints/graphql/graphql_route.py index 9bd5bc559..32fbea474 100644 --- a/source/app/blueprints/graphql/graphql_route.py +++ b/source/app/blueprints/graphql/graphql_route.py @@ -35,7 +35,7 @@ from app.datamgmt.manage.manage_cases_db import build_filter_case_query from app.blueprints.access_controls import is_user_authenticated -from app.util import response_error +from app.blueprints.responses import response_error from app.models.authorization import CaseAccessLevel diff --git a/source/app/blueprints/pages/alerts/alerts_routes.py b/source/app/blueprints/pages/alerts/alerts_routes.py index 499cf41b7..00d7e1005 100644 --- a/source/app/blueprints/pages/alerts/alerts_routes.py +++ b/source/app/blueprints/pages/alerts/alerts_routes.py @@ -28,7 +28,7 @@ from app.datamgmt.alerts.alerts_db import get_alert_by_id from app.datamgmt.manage.manage_access_control_db import user_has_client_access from app.models.authorization import Permissions -from app.util import response_error +from app.blueprints.responses import response_error from app.blueprints.access_controls import ac_requires alerts_blueprint = Blueprint( diff --git a/source/app/blueprints/pages/case/case_assets_routes.py b/source/app/blueprints/pages/case/case_assets_routes.py index 9ca3a93ff..5db24bb2c 100644 --- a/source/app/blueprints/pages/case/case_assets_routes.py +++ b/source/app/blueprints/pages/case/case_assets_routes.py @@ -34,7 +34,7 @@ from app.forms import ModalAddCaseAssetForm from app.models.authorization import CaseAccessLevel from app.blueprints.access_controls import ac_case_requires -from app.util import response_error +from app.blueprints.responses import response_error case_assets_blueprint = Blueprint('case_assets', __name__, diff --git a/source/app/blueprints/pages/case/case_ioc_routes.py b/source/app/blueprints/pages/case/case_ioc_routes.py index a021cc23b..dc6fb8e1c 100644 --- a/source/app/blueprints/pages/case/case_ioc_routes.py +++ b/source/app/blueprints/pages/case/case_ioc_routes.py @@ -34,7 +34,7 @@ from app.models.authorization import CaseAccessLevel from app.models.models import Ioc from app.blueprints.access_controls import ac_case_requires -from app.util import response_error +from app.blueprints.responses import response_error case_ioc_blueprint = Blueprint( 'case_ioc', diff --git a/source/app/blueprints/pages/case/case_notes_routes.py b/source/app/blueprints/pages/case/case_notes_routes.py index 90067118e..1c092821f 100644 --- a/source/app/blueprints/pages/case/case_notes_routes.py +++ b/source/app/blueprints/pages/case/case_notes_routes.py @@ -27,8 +27,7 @@ from app.datamgmt.case.case_notes_db import get_note from app.models.authorization import CaseAccessLevel from app.blueprints.access_controls import ac_case_requires -from app.util import response_error - +from app.blueprints.responses import response_error case_notes_blueprint = Blueprint('case_notes', __name__, diff --git a/source/app/blueprints/pages/case/case_rfiles_routes.py b/source/app/blueprints/pages/case/case_rfiles_routes.py index 476c3200b..1b4c90283 100644 --- a/source/app/blueprints/pages/case/case_rfiles_routes.py +++ b/source/app/blueprints/pages/case/case_rfiles_routes.py @@ -28,7 +28,7 @@ from app.datamgmt.manage.manage_attribute_db import get_default_custom_attributes from app.models.authorization import CaseAccessLevel from app.blueprints.access_controls import ac_case_requires -from app.util import response_error +from app.blueprints.responses import response_error case_rfiles_blueprint = Blueprint( 'case_rfiles', diff --git a/source/app/blueprints/pages/case/case_tasks_routes.py b/source/app/blueprints/pages/case/case_tasks_routes.py index 131a774b8..cdf4160b5 100644 --- a/source/app/blueprints/pages/case/case_tasks_routes.py +++ b/source/app/blueprints/pages/case/case_tasks_routes.py @@ -34,7 +34,7 @@ from app.models.authorization import User from app.models.models import CaseTasks from app.blueprints.access_controls import ac_case_requires -from app.util import response_error +from app.blueprints.responses import response_error case_tasks_blueprint = Blueprint('case_tasks', __name__, diff --git a/source/app/blueprints/pages/case/case_timeline_routes.py b/source/app/blueprints/pages/case/case_timeline_routes.py index 534a5a0f4..0e96f284c 100644 --- a/source/app/blueprints/pages/case/case_timeline_routes.py +++ b/source/app/blueprints/pages/case/case_timeline_routes.py @@ -37,7 +37,7 @@ from app.models.cases import Cases from app.models.cases import CasesEvent from app.blueprints.access_controls import ac_case_requires -from app.util import response_error +from app.blueprints.responses import response_error _EVENT_TAGS = ['Network', 'Server', 'ActiveDirectory', 'Computer', 'Malware', 'User Interaction'] diff --git a/source/app/blueprints/pages/datastore/datastore_routes.py b/source/app/blueprints/pages/datastore/datastore_routes.py index 2724b6170..f74b2b0ed 100644 --- a/source/app/blueprints/pages/datastore/datastore_routes.py +++ b/source/app/blueprints/pages/datastore/datastore_routes.py @@ -26,7 +26,7 @@ from app.forms import ModalDSFileForm from app.models.authorization import CaseAccessLevel from app.blueprints.access_controls import ac_case_requires -from app.util import response_error +from app.blueprints.responses import response_error datastore_blueprint = Blueprint( 'datastore', diff --git a/source/app/blueprints/pages/dim_tasks/dim_tasks.py b/source/app/blueprints/pages/dim_tasks/dim_tasks.py index 5f0538c79..f073f647d 100644 --- a/source/app/blueprints/pages/dim_tasks/dim_tasks.py +++ b/source/app/blueprints/pages/dim_tasks/dim_tasks.py @@ -27,7 +27,7 @@ from app.models.authorization import CaseAccessLevel from app.models.authorization import Permissions from app.blueprints.access_controls import ac_case_requires, ac_requires -from app.util import response_error +from app.blueprints.responses import response_error from iris_interface.IrisInterfaceStatus import IIStatus dim_tasks_blueprint = Blueprint( diff --git a/source/app/blueprints/pages/login/login_routes.py b/source/app/blueprints/pages/login/login_routes.py index f60805e64..b3410dd87 100644 --- a/source/app/blueprints/pages/login/login_routes.py +++ b/source/app/blueprints/pages/login/login_routes.py @@ -48,7 +48,8 @@ from app.iris_engine.utils.tracker import track_activity from app.models.cases import Cases -from app.util import is_authentication_ldap, response_error +from app.util import is_authentication_ldap +from app.blueprints.responses import response_error from app.util import is_authentication_oidc from app.datamgmt.manage.manage_users_db import get_active_user_by_login, get_user from app.datamgmt.manage.manage_users_db import create_user diff --git a/source/app/blueprints/pages/manage/manage_assets_type_routes.py b/source/app/blueprints/pages/manage/manage_assets_type_routes.py index 5ba5555f6..ac142f993 100644 --- a/source/app/blueprints/pages/manage/manage_assets_type_routes.py +++ b/source/app/blueprints/pages/manage/manage_assets_type_routes.py @@ -28,7 +28,7 @@ from app.models.authorization import Permissions from app.models.models import AssetsType from app.blueprints.access_controls import ac_requires -from app.util import response_error +from app.blueprints.responses import response_error manage_assets_type_blueprint = Blueprint('manage_assets_type', __name__, diff --git a/source/app/blueprints/pages/manage/manage_attributes_routes.py b/source/app/blueprints/pages/manage/manage_attributes_routes.py index df30cb373..bfec3f154 100644 --- a/source/app/blueprints/pages/manage/manage_attributes_routes.py +++ b/source/app/blueprints/pages/manage/manage_attributes_routes.py @@ -28,7 +28,7 @@ from app.models.authorization import Permissions from app.models.models import CustomAttribute from app.blueprints.access_controls import ac_requires -from app.util import response_error +from app.blueprints.responses import response_error manage_attributes_blueprint = Blueprint('manage_attributes', __name__, template_folder='templates') diff --git a/source/app/blueprints/pages/manage/manage_case_classification_routes.py b/source/app/blueprints/pages/manage/manage_case_classification_routes.py index 88dd74c7b..c81579391 100644 --- a/source/app/blueprints/pages/manage/manage_case_classification_routes.py +++ b/source/app/blueprints/pages/manage/manage_case_classification_routes.py @@ -26,7 +26,7 @@ from app.datamgmt.manage.manage_case_classifications_db import get_case_classification_by_id from app.forms import CaseClassificationForm from app.models.authorization import Permissions -from app.util import response_error +from app.blueprints.responses import response_error from app.blueprints.access_controls import ac_requires manage_case_classification_blueprint = Blueprint('manage_case_classifications', diff --git a/source/app/blueprints/pages/manage/manage_case_state.py b/source/app/blueprints/pages/manage/manage_case_state.py index 4588637c0..aad87a5c0 100644 --- a/source/app/blueprints/pages/manage/manage_case_state.py +++ b/source/app/blueprints/pages/manage/manage_case_state.py @@ -26,7 +26,7 @@ from app.datamgmt.manage.manage_case_state_db import get_case_state_by_id from app.forms import CaseStateForm from app.models.authorization import Permissions -from app.util import response_error +from app.blueprints.responses import response_error from app.blueprints.access_controls import ac_requires manage_case_state_blueprint = Blueprint('manage_case_state', diff --git a/source/app/blueprints/pages/manage/manage_case_templates_routes.py b/source/app/blueprints/pages/manage/manage_case_templates_routes.py index 0ec674b67..94ef310e3 100644 --- a/source/app/blueprints/pages/manage/manage_case_templates_routes.py +++ b/source/app/blueprints/pages/manage/manage_case_templates_routes.py @@ -25,7 +25,7 @@ from app.models import CaseTemplate from app.models.authorization import Permissions from app.blueprints.access_controls import ac_requires -from app.util import response_error +from app.blueprints.responses import response_error manage_case_templates_blueprint = Blueprint('manage_case_templates', __name__, diff --git a/source/app/blueprints/pages/manage/manage_cases_routes.py b/source/app/blueprints/pages/manage/manage_cases_routes.py index c7376cfb4..9667e3640 100644 --- a/source/app/blueprints/pages/manage/manage_cases_routes.py +++ b/source/app/blueprints/pages/manage/manage_cases_routes.py @@ -41,7 +41,7 @@ from app.schema.marshables import CaseDetailsSchema from app.blueprints.access_controls import ac_api_return_access_denied from app.blueprints.access_controls import ac_requires -from app.util import response_error +from app.blueprints.responses import response_error manage_cases_blueprint = Blueprint('manage_case', __name__, diff --git a/source/app/blueprints/pages/manage/manage_customers_routes.py b/source/app/blueprints/pages/manage/manage_customers_routes.py index 132703547..695b6c27e 100644 --- a/source/app/blueprints/pages/manage/manage_customers_routes.py +++ b/source/app/blueprints/pages/manage/manage_customers_routes.py @@ -34,7 +34,7 @@ from app.blueprints.access_controls import ac_requires from app.blueprints.access_controls import ac_requires_client_access from app.blueprints.responses import page_not_found -from app.util import response_error +from app.blueprints.responses import response_error manage_customers_blueprint = Blueprint( 'manage_customers', diff --git a/source/app/blueprints/pages/manage/manage_evidence_types_route.py b/source/app/blueprints/pages/manage/manage_evidence_types_route.py index 84c74754b..a0174b43b 100644 --- a/source/app/blueprints/pages/manage/manage_evidence_types_route.py +++ b/source/app/blueprints/pages/manage/manage_evidence_types_route.py @@ -26,7 +26,7 @@ from app.datamgmt.manage.manage_evidence_types_db import get_evidence_type_by_id from app.forms import EvidenceTypeForm from app.models.authorization import Permissions -from app.util import response_error +from app.blueprints.responses import response_error from app.blueprints.access_controls import ac_requires manage_evidence_types_blueprint = Blueprint('manage_evidence_types', diff --git a/source/app/blueprints/pages/manage/manage_groups_routes.py b/source/app/blueprints/pages/manage/manage_groups_routes.py index 36881d51e..51322618e 100644 --- a/source/app/blueprints/pages/manage/manage_groups_routes.py +++ b/source/app/blueprints/pages/manage/manage_groups_routes.py @@ -29,7 +29,7 @@ from app.iris_engine.access_control.utils import ac_get_all_permissions from app.models.authorization import Permissions from app.blueprints.access_controls import ac_requires -from app.util import response_error +from app.blueprints.responses import response_error manage_groups_blueprint = Blueprint( 'manage_groups', diff --git a/source/app/blueprints/pages/manage/manage_ioc_types_routes.py b/source/app/blueprints/pages/manage/manage_ioc_types_routes.py index 496d5794e..16594705e 100644 --- a/source/app/blueprints/pages/manage/manage_ioc_types_routes.py +++ b/source/app/blueprints/pages/manage/manage_ioc_types_routes.py @@ -25,7 +25,7 @@ from app.models import IocType from app.models.authorization import Permissions from app.blueprints.access_controls import ac_requires -from app.util import response_error +from app.blueprints.responses import response_error manage_ioc_type_blueprint = Blueprint('manage_ioc_types', __name__, diff --git a/source/app/blueprints/pages/manage/manage_modules_routes.py b/source/app/blueprints/pages/manage/manage_modules_routes.py index ed1433e83..c67dbdeb4 100644 --- a/source/app/blueprints/pages/manage/manage_modules_routes.py +++ b/source/app/blueprints/pages/manage/manage_modules_routes.py @@ -29,7 +29,7 @@ from app.forms import UpdateModuleParameterForm from app.models.authorization import Permissions from app.blueprints.access_controls import ac_requires -from app.util import response_error +from app.blueprints.responses import response_error manage_modules_blueprint = Blueprint( 'manage_module', diff --git a/source/app/blueprints/pages/manage/manage_users.py b/source/app/blueprints/pages/manage/manage_users.py index 6a24cece3..419881858 100644 --- a/source/app/blueprints/pages/manage/manage_users.py +++ b/source/app/blueprints/pages/manage/manage_users.py @@ -33,7 +33,7 @@ from app.iris_engine.access_control.utils import ac_current_user_has_permission from app.models.authorization import Permissions from app.blueprints.access_controls import ac_requires -from app.util import response_error +from app.blueprints.responses import response_error manage_users_blueprint = Blueprint('manage_users', __name__, template_folder='templates') diff --git a/source/app/blueprints/responses.py b/source/app/blueprints/responses.py index 3ba714d9c..e870de97b 100644 --- a/source/app/blueprints/responses.py +++ b/source/app/blueprints/responses.py @@ -21,7 +21,7 @@ from app import TEMPLATE_PATH from app import app -from app.util import response_error +from app.util import response # Set basic 404 @@ -32,3 +32,12 @@ def page_not_found(e): return response_error("Resource not found", status=404) return render_template('pages/error-404.html', template_folder=TEMPLATE_PATH), 404 + + +def response_error(msg, data=None, status=400): + content = { + 'status': 'error', + 'message': msg, + 'data': data if data is not None else [] + } + return response(status, data=content) diff --git a/source/app/blueprints/rest/alerts_routes.py b/source/app/blueprints/rest/alerts_routes.py index efc4b886a..36dd8572b 100644 --- a/source/app/blueprints/rest/alerts_routes.py +++ b/source/app/blueprints/rest/alerts_routes.py @@ -57,7 +57,7 @@ from app.schema.marshables import CaseAssetsSchema from app.schema.marshables import IocSchema from app.blueprints.access_controls import ac_api_requires -from app.util import response_error +from app.blueprints.responses import response_error from app.util import add_obj_history_entry from app.util import response_success diff --git a/source/app/blueprints/rest/case/case_assets_routes.py b/source/app/blueprints/rest/case/case_assets_routes.py index e7dc1a0b4..26f0882a8 100644 --- a/source/app/blueprints/rest/case/case_assets_routes.py +++ b/source/app/blueprints/rest/case/case_assets_routes.py @@ -57,7 +57,7 @@ from app.schema.marshables import CommentSchema from app.blueprints.access_controls import ac_requires_case_identifier from app.blueprints.access_controls import ac_api_requires -from app.util import response_error +from app.blueprints.responses import response_error from app.util import response_success from app.blueprints.access_controls import ac_api_return_access_denied diff --git a/source/app/blueprints/rest/case/case_evidences_routes.py b/source/app/blueprints/rest/case/case_evidences_routes.py index b90d0c8f5..ab88332d7 100644 --- a/source/app/blueprints/rest/case/case_evidences_routes.py +++ b/source/app/blueprints/rest/case/case_evidences_routes.py @@ -42,7 +42,7 @@ from app.schema.marshables import CommentSchema from app.blueprints.access_controls import ac_requires_case_identifier from app.blueprints.access_controls import ac_api_requires -from app.util import response_error +from app.blueprints.responses import response_error from app.util import response_success case_evidences_rest_blueprint = Blueprint('case_evidences_rest', __name__) diff --git a/source/app/blueprints/rest/case/case_ioc_routes.py b/source/app/blueprints/rest/case/case_ioc_routes.py index dd028e2b5..55424cfe4 100644 --- a/source/app/blueprints/rest/case/case_ioc_routes.py +++ b/source/app/blueprints/rest/case/case_ioc_routes.py @@ -54,7 +54,7 @@ from app.blueprints.access_controls import ac_requires_case_identifier from app.blueprints.access_controls import ac_api_requires from app.blueprints.access_controls import ac_api_return_access_denied -from app.util import response_error +from app.blueprints.responses import response_error from app.util import response_success case_ioc_rest_blueprint = Blueprint('case_ioc_rest', __name__) diff --git a/source/app/blueprints/rest/case/case_notes_routes.py b/source/app/blueprints/rest/case/case_notes_routes.py index 320a69ef6..f41a23659 100644 --- a/source/app/blueprints/rest/case/case_notes_routes.py +++ b/source/app/blueprints/rest/case/case_notes_routes.py @@ -55,7 +55,7 @@ from app.blueprints.access_controls import ac_requires_case_identifier from app.blueprints.access_controls import ac_api_requires from app.blueprints.rest.endpoints import endpoint_removed -from app.util import response_error +from app.blueprints.responses import response_error from app.util import response_success case_notes_rest_blueprint = Blueprint('case_notes_rest', __name__) diff --git a/source/app/blueprints/rest/case/case_routes.py b/source/app/blueprints/rest/case/case_routes.py index a7fba492f..f731c03a0 100644 --- a/source/app/blueprints/rest/case/case_routes.py +++ b/source/app/blueprints/rest/case/case_routes.py @@ -71,7 +71,7 @@ from app.blueprints.access_controls import ac_api_requires from app.util import add_obj_history_entry from app.blueprints.access_controls import ac_api_return_access_denied -from app.util import response_error +from app.blueprints.responses import response_error from app.util import response_success case_rest_blueprint = Blueprint('case_rest', __name__) diff --git a/source/app/blueprints/rest/case/case_tasks_routes.py b/source/app/blueprints/rest/case/case_tasks_routes.py index c247fe105..8899962ce 100644 --- a/source/app/blueprints/rest/case/case_tasks_routes.py +++ b/source/app/blueprints/rest/case/case_tasks_routes.py @@ -55,7 +55,7 @@ from app.blueprints.access_controls import ac_requires_case_identifier from app.blueprints.access_controls import ac_api_requires from app.blueprints.access_controls import ac_api_return_access_denied -from app.util import response_error +from app.blueprints.responses import response_error from app.util import response_success case_tasks_rest_blueprint = Blueprint('case_tasks_rest', __name__) diff --git a/source/app/blueprints/rest/case/case_timeline_routes.py b/source/app/blueprints/rest/case/case_timeline_routes.py index 56f45e0be..acdf87a0a 100644 --- a/source/app/blueprints/rest/case/case_timeline_routes.py +++ b/source/app/blueprints/rest/case/case_timeline_routes.py @@ -69,7 +69,7 @@ from app.blueprints.access_controls import ac_requires_case_identifier from app.blueprints.access_controls import ac_api_requires from app.util import add_obj_history_entry -from app.util import response_error +from app.blueprints.responses import response_error from app.util import response_success case_timeline_rest_blueprint = Blueprint('case_timeline_rest', __name__) diff --git a/source/app/blueprints/rest/case_comments.py b/source/app/blueprints/rest/case_comments.py index f52b9441f..8cb7e312d 100644 --- a/source/app/blueprints/rest/case_comments.py +++ b/source/app/blueprints/rest/case_comments.py @@ -21,7 +21,7 @@ from flask import request from app.schema.marshables import CommentSchema -from app.util import response_error +from app.blueprints.responses import response_error from app.util import response_success from app.business.case_comments import case_comments_update from app.business.errors import BusinessProcessingError diff --git a/source/app/blueprints/rest/dashboard_routes.py b/source/app/blueprints/rest/dashboard_routes.py index aceb2f142..653af9939 100644 --- a/source/app/blueprints/rest/dashboard_routes.py +++ b/source/app/blueprints/rest/dashboard_routes.py @@ -44,7 +44,8 @@ from app.schema.marshables import GlobalTasksSchema from app.blueprints.access_controls import ac_requires_case_identifier from app.blueprints.access_controls import ac_api_requires -from app.util import response_error, not_authenticated_redirection_url +from app.util import not_authenticated_redirection_url +from app.blueprints.responses import response_error from app.util import response_success from app.util import is_authentication_oidc diff --git a/source/app/blueprints/rest/datastore_routes.py b/source/app/blueprints/rest/datastore_routes.py index 15aa82110..ed69c309a 100644 --- a/source/app/blueprints/rest/datastore_routes.py +++ b/source/app/blueprints/rest/datastore_routes.py @@ -49,7 +49,7 @@ from app.blueprints.access_controls import ac_requires_case_identifier from app.blueprints.access_controls import ac_api_requires from app.util import add_obj_history_entry -from app.util import response_error +from app.blueprints.responses import response_error from app.util import response_success datastore_rest_blueprint = Blueprint('datastore_rest', __name__) diff --git a/source/app/blueprints/rest/dim_tasks_routes.py b/source/app/blueprints/rest/dim_tasks_routes.py index 3a8c99b15..685e5e732 100644 --- a/source/app/blueprints/rest/dim_tasks_routes.py +++ b/source/app/blueprints/rest/dim_tasks_routes.py @@ -39,7 +39,7 @@ from app.models.authorization import CaseAccessLevel from app.blueprints.access_controls import ac_requires_case_identifier from app.blueprints.access_controls import ac_api_requires -from app.util import response_error +from app.blueprints.responses import response_error from app.util import response_success from iris_interface.IrisInterfaceStatus import IIStatus diff --git a/source/app/blueprints/rest/endpoints.py b/source/app/blueprints/rest/endpoints.py index f89c7561d..9d5e2dfeb 100644 --- a/source/app/blueprints/rest/endpoints.py +++ b/source/app/blueprints/rest/endpoints.py @@ -20,7 +20,7 @@ from app import app from app.util import response -from app.util import response_error +from app.blueprints.responses import response_error logger = app.logger diff --git a/source/app/blueprints/rest/filters_routes.py b/source/app/blueprints/rest/filters_routes.py index 737faf9ad..2ff1dfe57 100644 --- a/source/app/blueprints/rest/filters_routes.py +++ b/source/app/blueprints/rest/filters_routes.py @@ -27,7 +27,7 @@ from app.schema.marshables import SavedFilterSchema from app.blueprints.access_controls import ac_api_requires from app.util import response_success -from app.util import response_error +from app.blueprints.responses import response_error saved_filters_rest_blueprint = Blueprint('saved_filters_rest', __name__) diff --git a/source/app/blueprints/rest/manage/manage_alerts_status_routes.py b/source/app/blueprints/rest/manage/manage_alerts_status_routes.py index 07a6937af..f9b9034e9 100644 --- a/source/app/blueprints/rest/manage/manage_alerts_status_routes.py +++ b/source/app/blueprints/rest/manage/manage_alerts_status_routes.py @@ -26,7 +26,7 @@ from app.schema.marshables import AlertStatusSchema from app.schema.marshables import AlertResolutionSchema from app.blueprints.access_controls import ac_api_requires -from app.util import response_error +from app.blueprints.responses import response_error from app.util import response_success manage_alerts_status_rest_blueprint = Blueprint('manage_alerts_status_rest', __name__) diff --git a/source/app/blueprints/rest/manage/manage_analysis_status_routes.py b/source/app/blueprints/rest/manage/manage_analysis_status_routes.py index f6ed2b39c..16a368728 100644 --- a/source/app/blueprints/rest/manage/manage_analysis_status_routes.py +++ b/source/app/blueprints/rest/manage/manage_analysis_status_routes.py @@ -25,7 +25,7 @@ from app.models.models import AnalysisStatus from app.schema.marshables import AnalysisStatusSchema from app.blueprints.access_controls import ac_api_requires -from app.util import response_error +from app.blueprints.responses import response_error from app.util import response_success manage_analysis_status_rest_blueprint = Blueprint('manage_analysis_status_rest', __name__) diff --git a/source/app/blueprints/rest/manage/manage_assets_type_routes.py b/source/app/blueprints/rest/manage/manage_assets_type_routes.py index ede277f75..ea2070b1a 100644 --- a/source/app/blueprints/rest/manage/manage_assets_type_routes.py +++ b/source/app/blueprints/rest/manage/manage_assets_type_routes.py @@ -32,7 +32,7 @@ from app.models.models import CaseAssets from app.schema.marshables import AssetTypeSchema from app.blueprints.access_controls import ac_api_requires -from app.util import response_error +from app.blueprints.responses import response_error from app.util import response_success manage_assets_type_rest_blueprint = Blueprint('manage_assets_type_rest', __name__) diff --git a/source/app/blueprints/rest/manage/manage_attributes_routes.py b/source/app/blueprints/rest/manage/manage_attributes_routes.py index caf8bfbd4..d49260d1d 100644 --- a/source/app/blueprints/rest/manage/manage_attributes_routes.py +++ b/source/app/blueprints/rest/manage/manage_attributes_routes.py @@ -25,7 +25,7 @@ from app.models.authorization import Permissions from app.models.models import CustomAttribute from app.blueprints.access_controls import ac_api_requires -from app.util import response_error +from app.blueprints.responses import response_error from app.util import response_success manage_attributes_rest_blueprint = Blueprint('manage_attributes_rest', __name__) diff --git a/source/app/blueprints/rest/manage/manage_case_classifications_routes.py b/source/app/blueprints/rest/manage/manage_case_classifications_routes.py index 28d6cf93e..2c14d0471 100644 --- a/source/app/blueprints/rest/manage/manage_case_classifications_routes.py +++ b/source/app/blueprints/rest/manage/manage_case_classifications_routes.py @@ -30,7 +30,7 @@ from app.models.authorization import Permissions from app.schema.marshables import CaseClassificationSchema from app.blueprints.access_controls import ac_api_requires -from app.util import response_error +from app.blueprints.responses import response_error from app.util import response_success manage_case_classification_rest_blueprint = Blueprint('manage_case_classifications_rest', __name__) diff --git a/source/app/blueprints/rest/manage/manage_case_state.py b/source/app/blueprints/rest/manage/manage_case_state.py index 47e434016..4fbf5bd42 100644 --- a/source/app/blueprints/rest/manage/manage_case_state.py +++ b/source/app/blueprints/rest/manage/manage_case_state.py @@ -30,7 +30,7 @@ from app.models.authorization import Permissions from app.schema.marshables import CaseStateSchema from app.blueprints.access_controls import ac_api_requires -from app.util import response_error +from app.blueprints.responses import response_error from app.util import response_success manage_case_state_rest_blueprint = Blueprint('manage_case_state_rest', __name__) diff --git a/source/app/blueprints/rest/manage/manage_case_templates_routes.py b/source/app/blueprints/rest/manage/manage_case_templates_routes.py index 073c28053..e6afd719c 100644 --- a/source/app/blueprints/rest/manage/manage_case_templates_routes.py +++ b/source/app/blueprints/rest/manage/manage_case_templates_routes.py @@ -33,7 +33,7 @@ from app.schema.marshables import CaseTemplateSchema from app.blueprints.access_controls import ac_requires_case_identifier from app.blueprints.access_controls import ac_api_requires -from app.util import response_error +from app.blueprints.responses import response_error from app.util import response_success manage_case_templates_rest_blueprint = Blueprint('manage_case_templates_rest', __name__) diff --git a/source/app/blueprints/rest/manage/manage_cases_routes.py b/source/app/blueprints/rest/manage/manage_cases_routes.py index c8d0f6fe7..ad2d81e53 100644 --- a/source/app/blueprints/rest/manage/manage_cases_routes.py +++ b/source/app/blueprints/rest/manage/manage_cases_routes.py @@ -53,7 +53,7 @@ from app.blueprints.access_controls import ac_requires_case_identifier from app.blueprints.access_controls import ac_api_requires from app.blueprints.access_controls import ac_api_return_access_denied -from app.util import response_error +from app.blueprints.responses import response_error from app.util import response_success from app.business.cases import cases_delete from app.business.cases import cases_update diff --git a/source/app/blueprints/rest/manage/manage_customers_routes.py b/source/app/blueprints/rest/manage/manage_customers_routes.py index e8c2428e9..150aba44c 100644 --- a/source/app/blueprints/rest/manage/manage_customers_routes.py +++ b/source/app/blueprints/rest/manage/manage_customers_routes.py @@ -44,7 +44,7 @@ from app.schema.marshables import ContactSchema from app.schema.marshables import CustomerSchema from app.blueprints.access_controls import ac_api_requires_client_access -from app.util import response_error +from app.blueprints.responses import response_error from app.util import response_success manage_customers_rest_blueprint = Blueprint('manage_customers_rest', __name__) diff --git a/source/app/blueprints/rest/manage/manage_event_categories_routes.py b/source/app/blueprints/rest/manage/manage_event_categories_routes.py index d3328f877..bda7bcf13 100644 --- a/source/app/blueprints/rest/manage/manage_event_categories_routes.py +++ b/source/app/blueprints/rest/manage/manage_event_categories_routes.py @@ -22,7 +22,7 @@ from app.models.models import EventCategory from app.schema.marshables import EventCategorySchema from app.blueprints.access_controls import ac_api_requires -from app.util import response_error +from app.blueprints.responses import response_error from app.util import response_success manage_event_categories_rest_blueprint = Blueprint('manage_event_categories_rest', __name__) diff --git a/source/app/blueprints/rest/manage/manage_evidence_types_routes.py b/source/app/blueprints/rest/manage/manage_evidence_types_routes.py index 810331314..89d2a7187 100644 --- a/source/app/blueprints/rest/manage/manage_evidence_types_routes.py +++ b/source/app/blueprints/rest/manage/manage_evidence_types_routes.py @@ -30,7 +30,7 @@ from app.models.authorization import Permissions from app.schema.marshables import EvidenceTypeSchema from app.blueprints.access_controls import ac_api_requires -from app.util import response_error +from app.blueprints.responses import response_error from app.util import response_success manage_evidence_types_rest_blueprint = Blueprint('manage_evidence_types_rest', __name__) diff --git a/source/app/blueprints/rest/manage/manage_groups.py b/source/app/blueprints/rest/manage/manage_groups.py index bc68e093c..969e49591 100644 --- a/source/app/blueprints/rest/manage/manage_groups.py +++ b/source/app/blueprints/rest/manage/manage_groups.py @@ -45,7 +45,7 @@ from app.schema.marshables import AuthorizationGroupSchema from app.blueprints.access_controls import ac_api_requires from app.blueprints.access_controls import ac_api_return_access_denied -from app.util import response_error +from app.blueprints.responses import response_error from app.util import response_success from app.iris_engine.demo_builder import protect_demo_mode_group diff --git a/source/app/blueprints/rest/manage/manage_ioc_types_routes.py b/source/app/blueprints/rest/manage/manage_ioc_types_routes.py index c42457f46..1bf09f593 100644 --- a/source/app/blueprints/rest/manage/manage_ioc_types_routes.py +++ b/source/app/blueprints/rest/manage/manage_ioc_types_routes.py @@ -29,7 +29,7 @@ from app.models.authorization import Permissions from app.schema.marshables import IocTypeSchema from app.blueprints.access_controls import ac_api_requires -from app.util import response_error +from app.blueprints.responses import response_error from app.util import response_success manage_ioc_type_rest_blueprint = Blueprint('manage_ioc_types_rest', __name__) diff --git a/source/app/blueprints/rest/manage/manage_modules_routes.py b/source/app/blueprints/rest/manage/manage_modules_routes.py index c1bcd144f..f579a4e9b 100644 --- a/source/app/blueprints/rest/manage/manage_modules_routes.py +++ b/source/app/blueprints/rest/manage/manage_modules_routes.py @@ -39,7 +39,7 @@ from app.iris_engine.utils.tracker import track_activity from app.models.authorization import Permissions from app.blueprints.access_controls import ac_api_requires -from app.util import response_error +from app.blueprints.responses import response_error from app.util import response_success from app.schema.marshables import IrisModuleSchema diff --git a/source/app/blueprints/rest/manage/manage_server_settings_routes.py b/source/app/blueprints/rest/manage/manage_server_settings_routes.py index c5201caae..79ec66c9f 100644 --- a/source/app/blueprints/rest/manage/manage_server_settings_routes.py +++ b/source/app/blueprints/rest/manage/manage_server_settings_routes.py @@ -31,7 +31,7 @@ from app.models.authorization import Permissions from app.schema.marshables import ServerSettingsSchema from app.blueprints.access_controls import ac_api_requires -from app.util import response_error +from app.blueprints.responses import response_error from app.util import response_success from dictdiffer import diff diff --git a/source/app/blueprints/rest/manage/manage_severities_routes.py b/source/app/blueprints/rest/manage/manage_severities_routes.py index 989d2c5cc..e025fef28 100644 --- a/source/app/blueprints/rest/manage/manage_severities_routes.py +++ b/source/app/blueprints/rest/manage/manage_severities_routes.py @@ -24,7 +24,7 @@ from app.datamgmt.manage.manage_common import search_severity_by_name from app.schema.marshables import SeveritySchema from app.blueprints.access_controls import ac_api_requires -from app.util import response_error +from app.blueprints.responses import response_error from app.util import response_success manage_severities_rest_blueprint = Blueprint('manage_severities_rest', __name__) diff --git a/source/app/blueprints/rest/manage/manage_task_status_routes.py b/source/app/blueprints/rest/manage/manage_task_status_routes.py index a6a9532e6..1b4c76124 100644 --- a/source/app/blueprints/rest/manage/manage_task_status_routes.py +++ b/source/app/blueprints/rest/manage/manage_task_status_routes.py @@ -20,7 +20,7 @@ from app.models.models import TaskStatus from app.blueprints.access_controls import ac_api_requires -from app.util import response_error +from app.blueprints.responses import response_error from app.util import response_success manage_task_status_rest_blueprint = Blueprint('manage_task_status_rest', __name__) diff --git a/source/app/blueprints/rest/manage/manage_templates_routes.py b/source/app/blueprints/rest/manage/manage_templates_routes.py index f28b19323..a853dfb55 100644 --- a/source/app/blueprints/rest/manage/manage_templates_routes.py +++ b/source/app/blueprints/rest/manage/manage_templates_routes.py @@ -37,7 +37,7 @@ from app.models.models import Languages from app.models.models import ReportType from app.blueprints.access_controls import ac_api_requires -from app.util import response_error +from app.blueprints.responses import response_error from app.util import response_success _ALLOWED_EXTENSIONS = {'md', 'html', 'doc', 'docx'} diff --git a/source/app/blueprints/rest/manage/manage_tlps_routes.py b/source/app/blueprints/rest/manage/manage_tlps_routes.py index 37cad485d..14dc51e1f 100644 --- a/source/app/blueprints/rest/manage/manage_tlps_routes.py +++ b/source/app/blueprints/rest/manage/manage_tlps_routes.py @@ -20,7 +20,7 @@ from app.models import Tlp from app.blueprints.access_controls import ac_api_requires -from app.util import response_error +from app.blueprints.responses import response_error from app.util import response_success manage_tlp_type_rest_blueprint = Blueprint('manage_tlp_types_rest', __name__) diff --git a/source/app/blueprints/rest/manage/manage_users.py b/source/app/blueprints/rest/manage/manage_users.py index 9948c385c..f5453da60 100644 --- a/source/app/blueprints/rest/manage/manage_users.py +++ b/source/app/blueprints/rest/manage/manage_users.py @@ -48,7 +48,7 @@ from app.blueprints.access_controls import ac_api_requires from app.blueprints.access_controls import ac_api_return_access_denied -from app.util import response_error +from app.blueprints.responses import response_error from app.util import response_success from app.iris_engine.demo_builder import protect_demo_mode_user diff --git a/source/app/blueprints/rest/profile_routes.py b/source/app/blueprints/rest/profile_routes.py index c9b027e26..5d5e04e3d 100644 --- a/source/app/blueprints/rest/profile_routes.py +++ b/source/app/blueprints/rest/profile_routes.py @@ -35,7 +35,7 @@ from app.schema.marshables import UserSchema from app.schema.marshables import BasicUserSchema from app.blueprints.access_controls import ac_api_requires -from app.util import response_error +from app.blueprints.responses import response_error from app.util import response_success from app.blueprints.rest.endpoints import endpoint_removed diff --git a/source/app/blueprints/rest/reports_route.py b/source/app/blueprints/rest/reports_route.py index 9aa7bed9c..94d7b87ce 100644 --- a/source/app/blueprints/rest/reports_route.py +++ b/source/app/blueprints/rest/reports_route.py @@ -35,7 +35,7 @@ from app.util import FileRemover from app.blueprints.access_controls import ac_requires_case_identifier from app.blueprints.access_controls import ac_api_requires -from app.util import response_error +from app.blueprints.responses import response_error from app.datamgmt.case.case_db import get_case reports_rest_blueprint = Blueprint('reports_rest', __name__) diff --git a/source/app/util.py b/source/app/util.py index 1dcef3162..334150bcc 100644 --- a/source/app/util.py +++ b/source/app/util.py @@ -53,15 +53,6 @@ def response(status, data=None): return app.response_class(response=data, status=status, mimetype='application/json') -def response_error(msg, data=None, status=400): - content = { - 'status': 'error', - 'message': msg, - 'data': data if data is not None else [] - } - return response(status, data=content) - - def response_success(msg='', data=None): content = { "status": "success", From 6d1eccda14329abae14a1489af90a84aa0ca02a1 Mon Sep 17 00:00:00 2001 From: c8y3 <25362953+c8y3@users.noreply.github.com> Date: Tue, 8 Oct 2024 17:23:25 +0200 Subject: [PATCH 26/46] [IMP] Moved response_success out of util.py into blueprints namespace --- source/app/blueprints/access_controls.py | 2 +- source/app/blueprints/responses.py | 9 +++++++++ source/app/blueprints/rest/activities_routes.py | 2 +- source/app/blueprints/rest/alerts_routes.py | 2 +- source/app/blueprints/rest/api_routes.py | 2 +- source/app/blueprints/rest/case/case_assets_routes.py | 2 +- source/app/blueprints/rest/case/case_evidences_routes.py | 2 +- source/app/blueprints/rest/case/case_graphs_routes.py | 2 +- source/app/blueprints/rest/case/case_ioc_routes.py | 2 +- source/app/blueprints/rest/case/case_notes_routes.py | 2 +- source/app/blueprints/rest/case/case_routes.py | 2 +- source/app/blueprints/rest/case/case_tasks_routes.py | 2 +- source/app/blueprints/rest/case/case_timeline_routes.py | 2 +- source/app/blueprints/rest/case_comments.py | 2 +- source/app/blueprints/rest/context_routes.py | 2 +- source/app/blueprints/rest/dashboard_routes.py | 2 +- source/app/blueprints/rest/datastore_routes.py | 2 +- source/app/blueprints/rest/dim_tasks_routes.py | 2 +- source/app/blueprints/rest/filters_routes.py | 2 +- .../rest/manage/manage_access_control_routes.py | 2 +- .../rest/manage/manage_alerts_status_routes.py | 2 +- .../rest/manage/manage_analysis_status_routes.py | 2 +- .../app/blueprints/rest/manage/manage_assets_routes.py | 2 +- .../blueprints/rest/manage/manage_assets_type_routes.py | 2 +- .../blueprints/rest/manage/manage_attributes_routes.py | 2 +- .../rest/manage/manage_case_classifications_routes.py | 2 +- source/app/blueprints/rest/manage/manage_case_state.py | 2 +- .../rest/manage/manage_case_templates_routes.py | 2 +- source/app/blueprints/rest/manage/manage_cases_routes.py | 2 +- .../blueprints/rest/manage/manage_customers_routes.py | 2 +- .../rest/manage/manage_event_categories_routes.py | 2 +- .../rest/manage/manage_evidence_types_routes.py | 2 +- source/app/blueprints/rest/manage/manage_groups.py | 2 +- .../blueprints/rest/manage/manage_ioc_types_routes.py | 2 +- .../app/blueprints/rest/manage/manage_modules_routes.py | 2 +- .../rest/manage/manage_server_settings_routes.py | 2 +- .../blueprints/rest/manage/manage_severities_routes.py | 2 +- source/app/blueprints/rest/manage/manage_tags.py | 2 +- .../blueprints/rest/manage/manage_task_status_routes.py | 2 +- .../blueprints/rest/manage/manage_templates_routes.py | 2 +- source/app/blueprints/rest/manage/manage_tlps_routes.py | 2 +- source/app/blueprints/rest/manage/manage_users.py | 2 +- source/app/blueprints/rest/overview_routes.py | 2 +- source/app/blueprints/rest/profile_routes.py | 2 +- source/app/blueprints/rest/search_routes.py | 2 +- source/app/util.py | 9 --------- 46 files changed, 53 insertions(+), 53 deletions(-) diff --git a/source/app/blueprints/access_controls.py b/source/app/blueprints/access_controls.py index aee140078..4bf9e34db 100644 --- a/source/app/blueprints/access_controls.py +++ b/source/app/blueprints/access_controls.py @@ -40,6 +40,7 @@ from app import app from app import db +from app.blueprints.responses import response_error from app.datamgmt.case.case_db import get_case from app.datamgmt.manage.manage_access_control_db import user_has_client_access from app.datamgmt.manage.manage_users_db import get_user @@ -50,7 +51,6 @@ from app.models.authorization import Permissions from app.models.authorization import CaseAccessLevel -from app.blueprints.responses import response_error from app.util import not_authenticated_redirection_url diff --git a/source/app/blueprints/responses.py b/source/app/blueprints/responses.py index e870de97b..e582be00a 100644 --- a/source/app/blueprints/responses.py +++ b/source/app/blueprints/responses.py @@ -41,3 +41,12 @@ def response_error(msg, data=None, status=400): 'data': data if data is not None else [] } return response(status, data=content) + + +def response_success(msg='', data=None): + content = { + "status": "success", + "message": msg, + "data": data if data is not None else [] + } + return response(200, data=content) diff --git a/source/app/blueprints/rest/activities_routes.py b/source/app/blueprints/rest/activities_routes.py index c8782ed95..1b8fc4c5a 100644 --- a/source/app/blueprints/rest/activities_routes.py +++ b/source/app/blueprints/rest/activities_routes.py @@ -22,7 +22,7 @@ from app.datamgmt.activities.activities_db import get_users_activities from app.models.authorization import Permissions from app.blueprints.access_controls import ac_api_requires -from app.util import response_success +from app.blueprints.responses import response_success activities_rest_blueprint = Blueprint('activities_rest', __name__) diff --git a/source/app/blueprints/rest/alerts_routes.py b/source/app/blueprints/rest/alerts_routes.py index 36dd8572b..46e254748 100644 --- a/source/app/blueprints/rest/alerts_routes.py +++ b/source/app/blueprints/rest/alerts_routes.py @@ -59,7 +59,7 @@ from app.blueprints.access_controls import ac_api_requires from app.blueprints.responses import response_error from app.util import add_obj_history_entry -from app.util import response_success +from app.blueprints.responses import response_success alerts_rest_blueprint = Blueprint('alerts_rest', __name__) diff --git a/source/app/blueprints/rest/api_routes.py b/source/app/blueprints/rest/api_routes.py index a12ae5808..10e767507 100644 --- a/source/app/blueprints/rest/api_routes.py +++ b/source/app/blueprints/rest/api_routes.py @@ -20,7 +20,7 @@ from app import app from app.blueprints.access_controls import ac_api_requires -from app.util import response_success +from app.blueprints.responses import response_success rest_api_blueprint = Blueprint('rest_api', __name__) diff --git a/source/app/blueprints/rest/case/case_assets_routes.py b/source/app/blueprints/rest/case/case_assets_routes.py index 26f0882a8..3dd5ebf72 100644 --- a/source/app/blueprints/rest/case/case_assets_routes.py +++ b/source/app/blueprints/rest/case/case_assets_routes.py @@ -58,7 +58,7 @@ from app.blueprints.access_controls import ac_requires_case_identifier from app.blueprints.access_controls import ac_api_requires from app.blueprints.responses import response_error -from app.util import response_success +from app.blueprints.responses import response_success from app.blueprints.access_controls import ac_api_return_access_denied case_assets_rest_blueprint = Blueprint('case_assets_rest', __name__) diff --git a/source/app/blueprints/rest/case/case_evidences_routes.py b/source/app/blueprints/rest/case/case_evidences_routes.py index ab88332d7..330c19882 100644 --- a/source/app/blueprints/rest/case/case_evidences_routes.py +++ b/source/app/blueprints/rest/case/case_evidences_routes.py @@ -43,7 +43,7 @@ from app.blueprints.access_controls import ac_requires_case_identifier from app.blueprints.access_controls import ac_api_requires from app.blueprints.responses import response_error -from app.util import response_success +from app.blueprints.responses import response_success case_evidences_rest_blueprint = Blueprint('case_evidences_rest', __name__) diff --git a/source/app/blueprints/rest/case/case_graphs_routes.py b/source/app/blueprints/rest/case/case_graphs_routes.py index cbd3de723..07ea68a4d 100644 --- a/source/app/blueprints/rest/case/case_graphs_routes.py +++ b/source/app/blueprints/rest/case/case_graphs_routes.py @@ -26,7 +26,7 @@ from app.models.authorization import CaseAccessLevel from app.blueprints.access_controls import ac_requires_case_identifier from app.blueprints.access_controls import ac_api_requires -from app.util import response_success +from app.blueprints.responses import response_success case_graph_rest_blueprint = Blueprint('case_graph_rest', __name__) diff --git a/source/app/blueprints/rest/case/case_ioc_routes.py b/source/app/blueprints/rest/case/case_ioc_routes.py index 55424cfe4..759f6786d 100644 --- a/source/app/blueprints/rest/case/case_ioc_routes.py +++ b/source/app/blueprints/rest/case/case_ioc_routes.py @@ -55,7 +55,7 @@ from app.blueprints.access_controls import ac_api_requires from app.blueprints.access_controls import ac_api_return_access_denied from app.blueprints.responses import response_error -from app.util import response_success +from app.blueprints.responses import response_success case_ioc_rest_blueprint = Blueprint('case_ioc_rest', __name__) diff --git a/source/app/blueprints/rest/case/case_notes_routes.py b/source/app/blueprints/rest/case/case_notes_routes.py index f41a23659..5cd6eaba8 100644 --- a/source/app/blueprints/rest/case/case_notes_routes.py +++ b/source/app/blueprints/rest/case/case_notes_routes.py @@ -56,7 +56,7 @@ from app.blueprints.access_controls import ac_api_requires from app.blueprints.rest.endpoints import endpoint_removed from app.blueprints.responses import response_error -from app.util import response_success +from app.blueprints.responses import response_success case_notes_rest_blueprint = Blueprint('case_notes_rest', __name__) diff --git a/source/app/blueprints/rest/case/case_routes.py b/source/app/blueprints/rest/case/case_routes.py index f731c03a0..3d1e7c727 100644 --- a/source/app/blueprints/rest/case/case_routes.py +++ b/source/app/blueprints/rest/case/case_routes.py @@ -72,7 +72,7 @@ from app.util import add_obj_history_entry from app.blueprints.access_controls import ac_api_return_access_denied from app.blueprints.responses import response_error -from app.util import response_success +from app.blueprints.responses import response_success case_rest_blueprint = Blueprint('case_rest', __name__) diff --git a/source/app/blueprints/rest/case/case_tasks_routes.py b/source/app/blueprints/rest/case/case_tasks_routes.py index 8899962ce..f0b9ebe9a 100644 --- a/source/app/blueprints/rest/case/case_tasks_routes.py +++ b/source/app/blueprints/rest/case/case_tasks_routes.py @@ -56,7 +56,7 @@ from app.blueprints.access_controls import ac_api_requires from app.blueprints.access_controls import ac_api_return_access_denied from app.blueprints.responses import response_error -from app.util import response_success +from app.blueprints.responses import response_success case_tasks_rest_blueprint = Blueprint('case_tasks_rest', __name__) diff --git a/source/app/blueprints/rest/case/case_timeline_routes.py b/source/app/blueprints/rest/case/case_timeline_routes.py index acdf87a0a..ef61e20af 100644 --- a/source/app/blueprints/rest/case/case_timeline_routes.py +++ b/source/app/blueprints/rest/case/case_timeline_routes.py @@ -70,7 +70,7 @@ from app.blueprints.access_controls import ac_api_requires from app.util import add_obj_history_entry from app.blueprints.responses import response_error -from app.util import response_success +from app.blueprints.responses import response_success case_timeline_rest_blueprint = Blueprint('case_timeline_rest', __name__) diff --git a/source/app/blueprints/rest/case_comments.py b/source/app/blueprints/rest/case_comments.py index 8cb7e312d..dbf7bd985 100644 --- a/source/app/blueprints/rest/case_comments.py +++ b/source/app/blueprints/rest/case_comments.py @@ -22,7 +22,7 @@ from app.schema.marshables import CommentSchema from app.blueprints.responses import response_error -from app.util import response_success +from app.blueprints.responses import response_success from app.business.case_comments import case_comments_update from app.business.errors import BusinessProcessingError diff --git a/source/app/blueprints/rest/context_routes.py b/source/app/blueprints/rest/context_routes.py index fe69cea09..7ea7f7a3c 100644 --- a/source/app/blueprints/rest/context_routes.py +++ b/source/app/blueprints/rest/context_routes.py @@ -30,7 +30,7 @@ from app.models.models import Client from app.blueprints.access_controls import ac_api_requires from app.util import not_authenticated_redirection_url -from app.util import response_success +from app.blueprints.responses import response_success context_rest_blueprint = Blueprint('context_rest', __name__) diff --git a/source/app/blueprints/rest/dashboard_routes.py b/source/app/blueprints/rest/dashboard_routes.py index 653af9939..dfd6369e5 100644 --- a/source/app/blueprints/rest/dashboard_routes.py +++ b/source/app/blueprints/rest/dashboard_routes.py @@ -46,7 +46,7 @@ from app.blueprints.access_controls import ac_api_requires from app.util import not_authenticated_redirection_url from app.blueprints.responses import response_error -from app.util import response_success +from app.blueprints.responses import response_success from app.util import is_authentication_oidc from oic.oauth2.exception import GrantError diff --git a/source/app/blueprints/rest/datastore_routes.py b/source/app/blueprints/rest/datastore_routes.py index ed69c309a..25b6aa4de 100644 --- a/source/app/blueprints/rest/datastore_routes.py +++ b/source/app/blueprints/rest/datastore_routes.py @@ -50,7 +50,7 @@ from app.blueprints.access_controls import ac_api_requires from app.util import add_obj_history_entry from app.blueprints.responses import response_error -from app.util import response_success +from app.blueprints.responses import response_success datastore_rest_blueprint = Blueprint('datastore_rest', __name__) diff --git a/source/app/blueprints/rest/dim_tasks_routes.py b/source/app/blueprints/rest/dim_tasks_routes.py index 685e5e732..599fc2040 100644 --- a/source/app/blueprints/rest/dim_tasks_routes.py +++ b/source/app/blueprints/rest/dim_tasks_routes.py @@ -40,7 +40,7 @@ from app.blueprints.access_controls import ac_requires_case_identifier from app.blueprints.access_controls import ac_api_requires from app.blueprints.responses import response_error -from app.util import response_success +from app.blueprints.responses import response_success from iris_interface.IrisInterfaceStatus import IIStatus dim_tasks_rest_blueprint = Blueprint('dim_tasks_rest', __name__) diff --git a/source/app/blueprints/rest/filters_routes.py b/source/app/blueprints/rest/filters_routes.py index 2ff1dfe57..87b483e5e 100644 --- a/source/app/blueprints/rest/filters_routes.py +++ b/source/app/blueprints/rest/filters_routes.py @@ -26,7 +26,7 @@ from app.iris_engine.utils.tracker import track_activity from app.schema.marshables import SavedFilterSchema from app.blueprints.access_controls import ac_api_requires -from app.util import response_success +from app.blueprints.responses import response_success from app.blueprints.responses import response_error saved_filters_rest_blueprint = Blueprint('saved_filters_rest', __name__) diff --git a/source/app/blueprints/rest/manage/manage_access_control_routes.py b/source/app/blueprints/rest/manage/manage_access_control_routes.py index 3c964c652..9f924cdc2 100644 --- a/source/app/blueprints/rest/manage/manage_access_control_routes.py +++ b/source/app/blueprints/rest/manage/manage_access_control_routes.py @@ -25,7 +25,7 @@ from app.iris_engine.access_control.utils import ac_trace_user_effective_cases_access_2 from app.models.authorization import Permissions from app.blueprints.access_controls import ac_api_requires -from app.util import response_success +from app.blueprints.responses import response_success manage_ac_rest_blueprint = Blueprint('access_control_rest', __name__) diff --git a/source/app/blueprints/rest/manage/manage_alerts_status_routes.py b/source/app/blueprints/rest/manage/manage_alerts_status_routes.py index f9b9034e9..c82266013 100644 --- a/source/app/blueprints/rest/manage/manage_alerts_status_routes.py +++ b/source/app/blueprints/rest/manage/manage_alerts_status_routes.py @@ -27,7 +27,7 @@ from app.schema.marshables import AlertResolutionSchema from app.blueprints.access_controls import ac_api_requires from app.blueprints.responses import response_error -from app.util import response_success +from app.blueprints.responses import response_success manage_alerts_status_rest_blueprint = Blueprint('manage_alerts_status_rest', __name__) diff --git a/source/app/blueprints/rest/manage/manage_analysis_status_routes.py b/source/app/blueprints/rest/manage/manage_analysis_status_routes.py index 16a368728..17ac1f891 100644 --- a/source/app/blueprints/rest/manage/manage_analysis_status_routes.py +++ b/source/app/blueprints/rest/manage/manage_analysis_status_routes.py @@ -26,7 +26,7 @@ from app.schema.marshables import AnalysisStatusSchema from app.blueprints.access_controls import ac_api_requires from app.blueprints.responses import response_error -from app.util import response_success +from app.blueprints.responses import response_success manage_analysis_status_rest_blueprint = Blueprint('manage_analysis_status_rest', __name__) diff --git a/source/app/blueprints/rest/manage/manage_assets_routes.py b/source/app/blueprints/rest/manage/manage_assets_routes.py index e8c8dc34e..595af98de 100644 --- a/source/app/blueprints/rest/manage/manage_assets_routes.py +++ b/source/app/blueprints/rest/manage/manage_assets_routes.py @@ -26,7 +26,7 @@ from app.schema.marshables import CaseAssetsSchema from app.blueprints.access_controls import ac_api_requires from app.blueprints.access_controls import ac_api_return_access_denied -from app.util import response_success +from app.blueprints.responses import response_success manage_assets_rest_blueprint = Blueprint('manage_assets_rest', __name__) diff --git a/source/app/blueprints/rest/manage/manage_assets_type_routes.py b/source/app/blueprints/rest/manage/manage_assets_type_routes.py index ea2070b1a..26af87ca4 100644 --- a/source/app/blueprints/rest/manage/manage_assets_type_routes.py +++ b/source/app/blueprints/rest/manage/manage_assets_type_routes.py @@ -33,7 +33,7 @@ from app.schema.marshables import AssetTypeSchema from app.blueprints.access_controls import ac_api_requires from app.blueprints.responses import response_error -from app.util import response_success +from app.blueprints.responses import response_success manage_assets_type_rest_blueprint = Blueprint('manage_assets_type_rest', __name__) diff --git a/source/app/blueprints/rest/manage/manage_attributes_routes.py b/source/app/blueprints/rest/manage/manage_attributes_routes.py index d49260d1d..5dcd1b8ae 100644 --- a/source/app/blueprints/rest/manage/manage_attributes_routes.py +++ b/source/app/blueprints/rest/manage/manage_attributes_routes.py @@ -26,7 +26,7 @@ from app.models.models import CustomAttribute from app.blueprints.access_controls import ac_api_requires from app.blueprints.responses import response_error -from app.util import response_success +from app.blueprints.responses import response_success manage_attributes_rest_blueprint = Blueprint('manage_attributes_rest', __name__) diff --git a/source/app/blueprints/rest/manage/manage_case_classifications_routes.py b/source/app/blueprints/rest/manage/manage_case_classifications_routes.py index 2c14d0471..a63f3c26f 100644 --- a/source/app/blueprints/rest/manage/manage_case_classifications_routes.py +++ b/source/app/blueprints/rest/manage/manage_case_classifications_routes.py @@ -31,7 +31,7 @@ from app.schema.marshables import CaseClassificationSchema from app.blueprints.access_controls import ac_api_requires from app.blueprints.responses import response_error -from app.util import response_success +from app.blueprints.responses import response_success manage_case_classification_rest_blueprint = Blueprint('manage_case_classifications_rest', __name__) diff --git a/source/app/blueprints/rest/manage/manage_case_state.py b/source/app/blueprints/rest/manage/manage_case_state.py index 4fbf5bd42..57b8461db 100644 --- a/source/app/blueprints/rest/manage/manage_case_state.py +++ b/source/app/blueprints/rest/manage/manage_case_state.py @@ -31,7 +31,7 @@ from app.schema.marshables import CaseStateSchema from app.blueprints.access_controls import ac_api_requires from app.blueprints.responses import response_error -from app.util import response_success +from app.blueprints.responses import response_success manage_case_state_rest_blueprint = Blueprint('manage_case_state_rest', __name__) diff --git a/source/app/blueprints/rest/manage/manage_case_templates_routes.py b/source/app/blueprints/rest/manage/manage_case_templates_routes.py index e6afd719c..aab98e66d 100644 --- a/source/app/blueprints/rest/manage/manage_case_templates_routes.py +++ b/source/app/blueprints/rest/manage/manage_case_templates_routes.py @@ -34,7 +34,7 @@ from app.blueprints.access_controls import ac_requires_case_identifier from app.blueprints.access_controls import ac_api_requires from app.blueprints.responses import response_error -from app.util import response_success +from app.blueprints.responses import response_success manage_case_templates_rest_blueprint = Blueprint('manage_case_templates_rest', __name__) diff --git a/source/app/blueprints/rest/manage/manage_cases_routes.py b/source/app/blueprints/rest/manage/manage_cases_routes.py index ad2d81e53..07167dbf9 100644 --- a/source/app/blueprints/rest/manage/manage_cases_routes.py +++ b/source/app/blueprints/rest/manage/manage_cases_routes.py @@ -54,7 +54,7 @@ from app.blueprints.access_controls import ac_api_requires from app.blueprints.access_controls import ac_api_return_access_denied from app.blueprints.responses import response_error -from app.util import response_success +from app.blueprints.responses import response_success from app.business.cases import cases_delete from app.business.cases import cases_update from app.business.cases import cases_create diff --git a/source/app/blueprints/rest/manage/manage_customers_routes.py b/source/app/blueprints/rest/manage/manage_customers_routes.py index 150aba44c..d0faa0a08 100644 --- a/source/app/blueprints/rest/manage/manage_customers_routes.py +++ b/source/app/blueprints/rest/manage/manage_customers_routes.py @@ -45,7 +45,7 @@ from app.schema.marshables import CustomerSchema from app.blueprints.access_controls import ac_api_requires_client_access from app.blueprints.responses import response_error -from app.util import response_success +from app.blueprints.responses import response_success manage_customers_rest_blueprint = Blueprint('manage_customers_rest', __name__) diff --git a/source/app/blueprints/rest/manage/manage_event_categories_routes.py b/source/app/blueprints/rest/manage/manage_event_categories_routes.py index bda7bcf13..ec383cbb6 100644 --- a/source/app/blueprints/rest/manage/manage_event_categories_routes.py +++ b/source/app/blueprints/rest/manage/manage_event_categories_routes.py @@ -23,7 +23,7 @@ from app.schema.marshables import EventCategorySchema from app.blueprints.access_controls import ac_api_requires from app.blueprints.responses import response_error -from app.util import response_success +from app.blueprints.responses import response_success manage_event_categories_rest_blueprint = Blueprint('manage_event_categories_rest', __name__) diff --git a/source/app/blueprints/rest/manage/manage_evidence_types_routes.py b/source/app/blueprints/rest/manage/manage_evidence_types_routes.py index 89d2a7187..2bf31c48a 100644 --- a/source/app/blueprints/rest/manage/manage_evidence_types_routes.py +++ b/source/app/blueprints/rest/manage/manage_evidence_types_routes.py @@ -31,7 +31,7 @@ from app.schema.marshables import EvidenceTypeSchema from app.blueprints.access_controls import ac_api_requires from app.blueprints.responses import response_error -from app.util import response_success +from app.blueprints.responses import response_success manage_evidence_types_rest_blueprint = Blueprint('manage_evidence_types_rest', __name__) diff --git a/source/app/blueprints/rest/manage/manage_groups.py b/source/app/blueprints/rest/manage/manage_groups.py index 969e49591..e6f857bb0 100644 --- a/source/app/blueprints/rest/manage/manage_groups.py +++ b/source/app/blueprints/rest/manage/manage_groups.py @@ -46,7 +46,7 @@ from app.blueprints.access_controls import ac_api_requires from app.blueprints.access_controls import ac_api_return_access_denied from app.blueprints.responses import response_error -from app.util import response_success +from app.blueprints.responses import response_success from app.iris_engine.demo_builder import protect_demo_mode_group manage_groups_rest_blueprint = Blueprint('manage_groups_rest', __name__) diff --git a/source/app/blueprints/rest/manage/manage_ioc_types_routes.py b/source/app/blueprints/rest/manage/manage_ioc_types_routes.py index 1bf09f593..6f5a07d9c 100644 --- a/source/app/blueprints/rest/manage/manage_ioc_types_routes.py +++ b/source/app/blueprints/rest/manage/manage_ioc_types_routes.py @@ -30,7 +30,7 @@ from app.schema.marshables import IocTypeSchema from app.blueprints.access_controls import ac_api_requires from app.blueprints.responses import response_error -from app.util import response_success +from app.blueprints.responses import response_success manage_ioc_type_rest_blueprint = Blueprint('manage_ioc_types_rest', __name__) diff --git a/source/app/blueprints/rest/manage/manage_modules_routes.py b/source/app/blueprints/rest/manage/manage_modules_routes.py index f579a4e9b..a6b114f92 100644 --- a/source/app/blueprints/rest/manage/manage_modules_routes.py +++ b/source/app/blueprints/rest/manage/manage_modules_routes.py @@ -40,7 +40,7 @@ from app.models.authorization import Permissions from app.blueprints.access_controls import ac_api_requires from app.blueprints.responses import response_error -from app.util import response_success +from app.blueprints.responses import response_success from app.schema.marshables import IrisModuleSchema manage_modules_rest_blueprint = Blueprint('manage_module_rest', __name__) diff --git a/source/app/blueprints/rest/manage/manage_server_settings_routes.py b/source/app/blueprints/rest/manage/manage_server_settings_routes.py index 79ec66c9f..3bd5f6e3f 100644 --- a/source/app/blueprints/rest/manage/manage_server_settings_routes.py +++ b/source/app/blueprints/rest/manage/manage_server_settings_routes.py @@ -32,7 +32,7 @@ from app.schema.marshables import ServerSettingsSchema from app.blueprints.access_controls import ac_api_requires from app.blueprints.responses import response_error -from app.util import response_success +from app.blueprints.responses import response_success from dictdiffer import diff manage_server_settings_rest_blueprint = Blueprint('manage_server_settings_rest', __name__) diff --git a/source/app/blueprints/rest/manage/manage_severities_routes.py b/source/app/blueprints/rest/manage/manage_severities_routes.py index e025fef28..de0eb164a 100644 --- a/source/app/blueprints/rest/manage/manage_severities_routes.py +++ b/source/app/blueprints/rest/manage/manage_severities_routes.py @@ -25,7 +25,7 @@ from app.schema.marshables import SeveritySchema from app.blueprints.access_controls import ac_api_requires from app.blueprints.responses import response_error -from app.util import response_success +from app.blueprints.responses import response_success manage_severities_rest_blueprint = Blueprint('manage_severities_rest', __name__) diff --git a/source/app/blueprints/rest/manage/manage_tags.py b/source/app/blueprints/rest/manage/manage_tags.py index e724ad07c..3b159aca5 100644 --- a/source/app/blueprints/rest/manage/manage_tags.py +++ b/source/app/blueprints/rest/manage/manage_tags.py @@ -24,7 +24,7 @@ from app.schema.marshables import TagsSchema from app.blueprints.access_controls import ac_api_requires from app.util import AlchemyEncoder -from app.util import response_success +from app.blueprints.responses import response_success manage_tags_rest_blueprint = Blueprint('manage_tags_rest', __name__) diff --git a/source/app/blueprints/rest/manage/manage_task_status_routes.py b/source/app/blueprints/rest/manage/manage_task_status_routes.py index 1b4c76124..bdb261738 100644 --- a/source/app/blueprints/rest/manage/manage_task_status_routes.py +++ b/source/app/blueprints/rest/manage/manage_task_status_routes.py @@ -21,7 +21,7 @@ from app.models.models import TaskStatus from app.blueprints.access_controls import ac_api_requires from app.blueprints.responses import response_error -from app.util import response_success +from app.blueprints.responses import response_success manage_task_status_rest_blueprint = Blueprint('manage_task_status_rest', __name__) diff --git a/source/app/blueprints/rest/manage/manage_templates_routes.py b/source/app/blueprints/rest/manage/manage_templates_routes.py index a853dfb55..2c0c791cd 100644 --- a/source/app/blueprints/rest/manage/manage_templates_routes.py +++ b/source/app/blueprints/rest/manage/manage_templates_routes.py @@ -38,7 +38,7 @@ from app.models.models import ReportType from app.blueprints.access_controls import ac_api_requires from app.blueprints.responses import response_error -from app.util import response_success +from app.blueprints.responses import response_success _ALLOWED_EXTENSIONS = {'md', 'html', 'doc', 'docx'} diff --git a/source/app/blueprints/rest/manage/manage_tlps_routes.py b/source/app/blueprints/rest/manage/manage_tlps_routes.py index 14dc51e1f..a72ec43f2 100644 --- a/source/app/blueprints/rest/manage/manage_tlps_routes.py +++ b/source/app/blueprints/rest/manage/manage_tlps_routes.py @@ -21,7 +21,7 @@ from app.models import Tlp from app.blueprints.access_controls import ac_api_requires from app.blueprints.responses import response_error -from app.util import response_success +from app.blueprints.responses import response_success manage_tlp_type_rest_blueprint = Blueprint('manage_tlp_types_rest', __name__) diff --git a/source/app/blueprints/rest/manage/manage_users.py b/source/app/blueprints/rest/manage/manage_users.py index f5453da60..18344861a 100644 --- a/source/app/blueprints/rest/manage/manage_users.py +++ b/source/app/blueprints/rest/manage/manage_users.py @@ -49,7 +49,7 @@ from app.blueprints.access_controls import ac_api_requires from app.blueprints.access_controls import ac_api_return_access_denied from app.blueprints.responses import response_error -from app.util import response_success +from app.blueprints.responses import response_success from app.iris_engine.demo_builder import protect_demo_mode_user manage_users_rest_blueprint = Blueprint('manage_users_rest', __name__) diff --git a/source/app/blueprints/rest/overview_routes.py b/source/app/blueprints/rest/overview_routes.py index 9992849df..892c5abeb 100644 --- a/source/app/blueprints/rest/overview_routes.py +++ b/source/app/blueprints/rest/overview_routes.py @@ -22,7 +22,7 @@ from app.datamgmt.overview.overview_db import get_overview_db from app.blueprints.access_controls import ac_api_requires -from app.util import response_success +from app.blueprints.responses import response_success overview_rest_blueprint = Blueprint('overview_rest', __name__) diff --git a/source/app/blueprints/rest/profile_routes.py b/source/app/blueprints/rest/profile_routes.py index 5d5e04e3d..56043ae28 100644 --- a/source/app/blueprints/rest/profile_routes.py +++ b/source/app/blueprints/rest/profile_routes.py @@ -36,7 +36,7 @@ from app.schema.marshables import BasicUserSchema from app.blueprints.access_controls import ac_api_requires from app.blueprints.responses import response_error -from app.util import response_success +from app.blueprints.responses import response_success from app.blueprints.rest.endpoints import endpoint_removed profile_rest_blueprint = Blueprint('profile_rest', __name__) diff --git a/source/app/blueprints/rest/search_routes.py b/source/app/blueprints/rest/search_routes.py index bc725ccc2..7da5e4410 100644 --- a/source/app/blueprints/rest/search_routes.py +++ b/source/app/blueprints/rest/search_routes.py @@ -30,7 +30,7 @@ from app.models.models import Notes from app.models.models import Tlp from app.blueprints.access_controls import ac_api_requires -from app.util import response_success +from app.blueprints.responses import response_success search_rest_blueprint = Blueprint('search_rest', __name__) diff --git a/source/app/util.py b/source/app/util.py index 334150bcc..b80370da3 100644 --- a/source/app/util.py +++ b/source/app/util.py @@ -53,15 +53,6 @@ def response(status, data=None): return app.response_class(response=data, status=status, mimetype='application/json') -def response_success(msg='', data=None): - content = { - "status": "success", - "message": msg, - "data": data if data is not None else [] - } - return response(200, data=content) - - def g_db_commit(): db.session.commit() From 3e9627b1489846b4cb878ee44bca8d0d9d698dae Mon Sep 17 00:00:00 2001 From: c8y3 <25362953+c8y3@users.noreply.github.com> Date: Wed, 9 Oct 2024 08:44:44 +0200 Subject: [PATCH 27/46] [FIX] Path of moved imports --- source/app/blueprints/rest/v2/case/api_v2_assets_routes.py | 2 +- source/app/blueprints/rest/v2/case/api_v2_ioc_routes.py | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/source/app/blueprints/rest/v2/case/api_v2_assets_routes.py b/source/app/blueprints/rest/v2/case/api_v2_assets_routes.py index 1f5d7207b..3ea6e7852 100644 --- a/source/app/blueprints/rest/v2/case/api_v2_assets_routes.py +++ b/source/app/blueprints/rest/v2/case/api_v2_assets_routes.py @@ -34,7 +34,7 @@ from app.iris_engine.access_control.utils import ac_fast_check_current_user_has_case_access from app.models.authorization import CaseAccessLevel from app.schema.marshables import CaseAssetsSchema -from app.util import ac_api_return_access_denied +from app.blueprints.access_controls import ac_api_return_access_denied api_v2_assets_blueprint = Blueprint('case_assets_rest_v2', __name__, diff --git a/source/app/blueprints/rest/v2/case/api_v2_ioc_routes.py b/source/app/blueprints/rest/v2/case/api_v2_ioc_routes.py index 399f54cc2..a1064ae3f 100644 --- a/source/app/blueprints/rest/v2/case/api_v2_ioc_routes.py +++ b/source/app/blueprints/rest/v2/case/api_v2_ioc_routes.py @@ -35,7 +35,9 @@ from app.iris_engine.access_control.utils import ac_fast_check_current_user_has_case_access from app.models.authorization import CaseAccessLevel from app.schema.marshables import IocSchemaForAPIV2 -from app.util import ac_api_return_access_denied, response_success, response_error +from app.blueprints.access_controls import ac_api_return_access_denied +from app.blueprints.responses import response_success +from app.blueprints.responses import response_error api_v2_ioc_blueprint = Blueprint('case_ioc_rest_v2', __name__, From 12204dc3f39e08a2d7b9337742247862575dec87 Mon Sep 17 00:00:00 2001 From: c8y3 <25362953+c8y3@users.noreply.github.com> Date: Wed, 9 Oct 2024 08:57:52 +0200 Subject: [PATCH 28/46] [IMP] Moved response into namespace blueprints --- source/app/blueprints/responses.py | 9 ++++++++- source/app/blueprints/rest/endpoints.py | 3 +-- source/app/util.py | 6 ------ 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/source/app/blueprints/responses.py b/source/app/blueprints/responses.py index e582be00a..6671fc4ef 100644 --- a/source/app/blueprints/responses.py +++ b/source/app/blueprints/responses.py @@ -15,13 +15,14 @@ # You should have received a copy of the GNU Lesser General Public License # along with this program; if not, write to the Free Software Foundation, # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +import json from flask import render_template from flask import request from app import TEMPLATE_PATH from app import app -from app.util import response +from app.util import AlchemyEncoder # Set basic 404 @@ -34,6 +35,12 @@ def page_not_found(e): return render_template('pages/error-404.html', template_folder=TEMPLATE_PATH), 404 +def response(status, data=None): + if data is not None: + data = json.dumps(data, cls=AlchemyEncoder) + return app.response_class(response=data, status=status, mimetype='application/json') + + def response_error(msg, data=None, status=400): content = { 'status': 'error', diff --git a/source/app/blueprints/rest/endpoints.py b/source/app/blueprints/rest/endpoints.py index 9d5e2dfeb..de35479dc 100644 --- a/source/app/blueprints/rest/endpoints.py +++ b/source/app/blueprints/rest/endpoints.py @@ -19,8 +19,7 @@ from functools import wraps from app import app -from app.util import response -from app.blueprints.responses import response_error +from app.blueprints.responses import response_error, response logger = app.logger diff --git a/source/app/util.py b/source/app/util.py index b80370da3..1bb352b75 100644 --- a/source/app/util.py +++ b/source/app/util.py @@ -47,12 +47,6 @@ from app.models import Cases -def response(status, data=None): - if data is not None: - data = json.dumps(data, cls=AlchemyEncoder) - return app.response_class(response=data, status=status, mimetype='application/json') - - def g_db_commit(): db.session.commit() From 68e0e854924f7e35d66201fab5a58787e6f05355 Mon Sep 17 00:00:00 2001 From: c8y3 <25362953+c8y3@users.noreply.github.com> Date: Wed, 9 Oct 2024 08:59:17 +0200 Subject: [PATCH 29/46] [IMP] Removed seemingly dead code --- source/app/util.py | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/source/app/util.py b/source/app/util.py index 1bb352b75..17e5eee6e 100644 --- a/source/app/util.py +++ b/source/app/util.py @@ -199,16 +199,6 @@ def is_authentication_oidc(): return app.config.get('AUTHENTICATION_TYPE') == "oidc" -def regenerate_session(): - user_data = session.get('user_data', {}) - - session.clear() - - session['user_data'] = user_data - - session.modified = True - - def decompress_7z(filename: Path, output_dir): """ Decompress a 7z file in specified output directory From 38734b6308444e98e500716496f2aeb3ac95de9b Mon Sep 17 00:00:00 2001 From: c8y3 <25362953+c8y3@users.noreply.github.com> Date: Wed, 9 Oct 2024 09:00:34 +0200 Subject: [PATCH 30/46] [IMP] Moved method is_authentication_oidc into namespace blueprints --- source/app/blueprints/access_controls.py | 6 +++++- source/app/blueprints/pages/dashboard/dashboard_routes.py | 3 +-- source/app/blueprints/pages/login/login_routes.py | 2 +- source/app/blueprints/rest/dashboard_routes.py | 3 +-- source/app/util.py | 5 ----- 5 files changed, 8 insertions(+), 11 deletions(-) diff --git a/source/app/blueprints/access_controls.py b/source/app/blueprints/access_controls.py index 4bf9e34db..a85c0f76b 100644 --- a/source/app/blueprints/access_controls.py +++ b/source/app/blueprints/access_controls.py @@ -36,7 +36,7 @@ from requests.auth import HTTPBasicAuth from werkzeug.utils import redirect -from app import TEMPLATE_PATH +from app import TEMPLATE_PATH, app from app import app from app import db @@ -494,3 +494,7 @@ def is_user_authenticated(incoming_request: Request): } return authentication_mapper.get(app.config.get("AUTHENTICATION_TYPE"))(incoming_request) + + +def is_authentication_oidc(): + return app.config.get('AUTHENTICATION_TYPE') == "oidc" diff --git a/source/app/blueprints/pages/dashboard/dashboard_routes.py b/source/app/blueprints/pages/dashboard/dashboard_routes.py index 2a30fb866..ae87c8217 100644 --- a/source/app/blueprints/pages/dashboard/dashboard_routes.py +++ b/source/app/blueprints/pages/dashboard/dashboard_routes.py @@ -34,9 +34,8 @@ from app.iris_engine.utils.tracker import track_activity from app.models.authorization import User from app.models.models import GlobalTasks -from app.blueprints.access_controls import ac_requires +from app.blueprints.access_controls import ac_requires, is_authentication_oidc from app.util import not_authenticated_redirection_url -from app.util import is_authentication_oidc from oic.oauth2.exception import GrantError diff --git a/source/app/blueprints/pages/login/login_routes.py b/source/app/blueprints/pages/login/login_routes.py index b3410dd87..189bf70aa 100644 --- a/source/app/blueprints/pages/login/login_routes.py +++ b/source/app/blueprints/pages/login/login_routes.py @@ -50,7 +50,7 @@ from app.util import is_authentication_ldap from app.blueprints.responses import response_error -from app.util import is_authentication_oidc +from app.blueprints.access_controls import is_authentication_oidc from app.datamgmt.manage.manage_users_db import get_active_user_by_login, get_user from app.datamgmt.manage.manage_users_db import create_user diff --git a/source/app/blueprints/rest/dashboard_routes.py b/source/app/blueprints/rest/dashboard_routes.py index dfd6369e5..4b2316f2f 100644 --- a/source/app/blueprints/rest/dashboard_routes.py +++ b/source/app/blueprints/rest/dashboard_routes.py @@ -42,12 +42,11 @@ from app.schema.marshables import CaseTaskSchema from app.schema.marshables import CaseDetailsSchema from app.schema.marshables import GlobalTasksSchema -from app.blueprints.access_controls import ac_requires_case_identifier +from app.blueprints.access_controls import ac_requires_case_identifier, is_authentication_oidc from app.blueprints.access_controls import ac_api_requires from app.util import not_authenticated_redirection_url from app.blueprints.responses import response_error from app.blueprints.responses import response_success -from app.util import is_authentication_oidc from oic.oauth2.exception import GrantError diff --git a/source/app/util.py b/source/app/util.py index 17e5eee6e..59536058d 100644 --- a/source/app/util.py +++ b/source/app/util.py @@ -34,7 +34,6 @@ from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives import hmac from flask import request -from flask import session from flask import url_for from flask_login import current_user from pathlib import Path @@ -195,10 +194,6 @@ def is_authentication_ldap(): return app.config.get('AUTHENTICATION_TYPE') == "ldap" -def is_authentication_oidc(): - return app.config.get('AUTHENTICATION_TYPE') == "oidc" - - def decompress_7z(filename: Path, output_dir): """ Decompress a 7z file in specified output directory From 678799ce9fbd4f326bc1c4adc994ae2de57e3453 Mon Sep 17 00:00:00 2001 From: c8y3 <25362953+c8y3@users.noreply.github.com> Date: Wed, 9 Oct 2024 11:14:59 +0200 Subject: [PATCH 31/46] [IMP] Moved method is_authentication_ldap into namespace blueprints --- source/app/blueprints/access_controls.py | 4 ++++ source/app/blueprints/pages/login/login_routes.py | 3 +-- source/app/util.py | 4 ---- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/source/app/blueprints/access_controls.py b/source/app/blueprints/access_controls.py index a85c0f76b..8cb1c8c5c 100644 --- a/source/app/blueprints/access_controls.py +++ b/source/app/blueprints/access_controls.py @@ -498,3 +498,7 @@ def is_user_authenticated(incoming_request: Request): def is_authentication_oidc(): return app.config.get('AUTHENTICATION_TYPE') == "oidc" + + +def is_authentication_ldap(): + return app.config.get('AUTHENTICATION_TYPE') == "ldap" diff --git a/source/app/blueprints/pages/login/login_routes.py b/source/app/blueprints/pages/login/login_routes.py index 189bf70aa..237180e27 100644 --- a/source/app/blueprints/pages/login/login_routes.py +++ b/source/app/blueprints/pages/login/login_routes.py @@ -48,9 +48,8 @@ from app.iris_engine.utils.tracker import track_activity from app.models.cases import Cases -from app.util import is_authentication_ldap from app.blueprints.responses import response_error -from app.blueprints.access_controls import is_authentication_oidc +from app.blueprints.access_controls import is_authentication_oidc, is_authentication_ldap from app.datamgmt.manage.manage_users_db import get_active_user_by_login, get_user from app.datamgmt.manage.manage_users_db import create_user diff --git a/source/app/util.py b/source/app/util.py index 59536058d..2648c8c6d 100644 --- a/source/app/util.py +++ b/source/app/util.py @@ -190,10 +190,6 @@ def not_authenticated_redirection_url(request_url: str): return redirection_mapper.get(app.config.get("AUTHENTICATION_TYPE"))() -def is_authentication_ldap(): - return app.config.get('AUTHENTICATION_TYPE') == "ldap" - - def decompress_7z(filename: Path, output_dir): """ Decompress a 7z file in specified output directory From 68d192b36e77ba2770b92799461561c4eb368e31 Mon Sep 17 00:00:00 2001 From: c8y3 <25362953+c8y3@users.noreply.github.com> Date: Wed, 9 Oct 2024 11:18:00 +0200 Subject: [PATCH 32/46] [IMP] Moved method not_authenticated_redirection_url into namespace blueprints --- source/app/blueprints/access_controls.py | 16 +++++++++++++--- .../pages/dashboard/dashboard_routes.py | 3 +-- source/app/blueprints/rest/context_routes.py | 3 +-- source/app/blueprints/rest/dashboard_routes.py | 4 ++-- source/app/util.py | 12 ------------ 5 files changed, 17 insertions(+), 21 deletions(-) diff --git a/source/app/blueprints/access_controls.py b/source/app/blueprints/access_controls.py index 8cb1c8c5c..3b76038f0 100644 --- a/source/app/blueprints/access_controls.py +++ b/source/app/blueprints/access_controls.py @@ -26,6 +26,7 @@ import requests from flask import Request +from flask import url_for from flask import request from flask import render_template from flask import session @@ -36,7 +37,7 @@ from requests.auth import HTTPBasicAuth from werkzeug.utils import redirect -from app import TEMPLATE_PATH, app +from app import TEMPLATE_PATH from app import app from app import db @@ -51,8 +52,6 @@ from app.models.authorization import Permissions from app.models.authorization import CaseAccessLevel -from app.util import not_authenticated_redirection_url - def _user_has_at_least_a_required_permission(permissions: list[Permissions]): """ @@ -263,6 +262,17 @@ def get_case_access_from_api(request_data, access_level): return redir, caseid, True +def not_authenticated_redirection_url(request_url: str): + redirection_mapper = { + "oidc_proxy": lambda: app.config.get("AUTHENTICATION_PROXY_LOGOUT_URL"), + "local": lambda: url_for('login.login', next=request_url), + "ldap": lambda: url_for('login.login', next=request_url), + "oidc": lambda: url_for('login.login', next=request_url,) + } + + return redirection_mapper.get(app.config.get("AUTHENTICATION_TYPE"))() + + def ac_case_requires(*access_level): def inner_wrap(f): @wraps(f) diff --git a/source/app/blueprints/pages/dashboard/dashboard_routes.py b/source/app/blueprints/pages/dashboard/dashboard_routes.py index ae87c8217..522841d62 100644 --- a/source/app/blueprints/pages/dashboard/dashboard_routes.py +++ b/source/app/blueprints/pages/dashboard/dashboard_routes.py @@ -34,8 +34,7 @@ from app.iris_engine.utils.tracker import track_activity from app.models.authorization import User from app.models.models import GlobalTasks -from app.blueprints.access_controls import ac_requires, is_authentication_oidc -from app.util import not_authenticated_redirection_url +from app.blueprints.access_controls import ac_requires, is_authentication_oidc, not_authenticated_redirection_url from oic.oauth2.exception import GrantError diff --git a/source/app/blueprints/rest/context_routes.py b/source/app/blueprints/rest/context_routes.py index 7ea7f7a3c..b85b84257 100644 --- a/source/app/blueprints/rest/context_routes.py +++ b/source/app/blueprints/rest/context_routes.py @@ -28,8 +28,7 @@ from app.models.authorization import Permissions from app.models.cases import Cases from app.models.models import Client -from app.blueprints.access_controls import ac_api_requires -from app.util import not_authenticated_redirection_url +from app.blueprints.access_controls import ac_api_requires, not_authenticated_redirection_url from app.blueprints.responses import response_success context_rest_blueprint = Blueprint('context_rest', __name__) diff --git a/source/app/blueprints/rest/dashboard_routes.py b/source/app/blueprints/rest/dashboard_routes.py index 4b2316f2f..a9c435148 100644 --- a/source/app/blueprints/rest/dashboard_routes.py +++ b/source/app/blueprints/rest/dashboard_routes.py @@ -42,9 +42,9 @@ from app.schema.marshables import CaseTaskSchema from app.schema.marshables import CaseDetailsSchema from app.schema.marshables import GlobalTasksSchema -from app.blueprints.access_controls import ac_requires_case_identifier, is_authentication_oidc +from app.blueprints.access_controls import ac_requires_case_identifier, is_authentication_oidc, \ + not_authenticated_redirection_url from app.blueprints.access_controls import ac_api_requires -from app.util import not_authenticated_redirection_url from app.blueprints.responses import response_error from app.blueprints.responses import response_success diff --git a/source/app/util.py b/source/app/util.py index 2648c8c6d..83c99e169 100644 --- a/source/app/util.py +++ b/source/app/util.py @@ -34,7 +34,6 @@ from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives import hmac from flask import request -from flask import url_for from flask_login import current_user from pathlib import Path from pyunpack import Archive @@ -179,17 +178,6 @@ def get_urlcasename(): return [case_name, case_info, caseid] -def not_authenticated_redirection_url(request_url: str): - redirection_mapper = { - "oidc_proxy": lambda: app.config.get("AUTHENTICATION_PROXY_LOGOUT_URL"), - "local": lambda: url_for('login.login', next=request_url), - "ldap": lambda: url_for('login.login', next=request_url), - "oidc": lambda: url_for('login.login', next=request_url,) - } - - return redirection_mapper.get(app.config.get("AUTHENTICATION_TYPE"))() - - def decompress_7z(filename: Path, output_dir): """ Decompress a 7z file in specified output directory From 348e80011bb87287ae0a59d00245c3c71cbcdbd9 Mon Sep 17 00:00:00 2001 From: c8y3 <25362953+c8y3@users.noreply.github.com> Date: Wed, 9 Oct 2024 11:19:24 +0200 Subject: [PATCH 33/46] [IMP] Removed seemingly unused methods --- source/app/util.py | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/source/app/util.py b/source/app/util.py index 83c99e169..04be728a0 100644 --- a/source/app/util.py +++ b/source/app/util.py @@ -45,20 +45,6 @@ from app.models import Cases -def g_db_commit(): - db.session.commit() - - -def g_db_add(obj): - if obj: - db.session.add(obj) - - -def g_db_del(obj): - if obj: - db.session.delete(obj) - - class PgEncoder(json.JSONEncoder): def default(self, o): From d5297d345251c8bb2a9ae6766d12e3319947c88a Mon Sep 17 00:00:00 2001 From: c8y3 <25362953+c8y3@users.noreply.github.com> Date: Wed, 9 Oct 2024 11:20:21 +0200 Subject: [PATCH 34/46] [IMP] Removed seemingly unused class --- source/app/util.py | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/source/app/util.py b/source/app/util.py index 04be728a0..0b6799407 100644 --- a/source/app/util.py +++ b/source/app/util.py @@ -17,6 +17,7 @@ # You should have received a copy of the GNU Lesser General Public License # along with this program; if not, write to the Free Software Foundation, # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + import base64 import datetime import decimal @@ -45,18 +46,6 @@ from app.models import Cases -class PgEncoder(json.JSONEncoder): - - def default(self, o): - if isinstance(o, datetime.datetime): - return DictDatetime(o) - - if isinstance(o, decimal.Decimal): - return str(o) - - return json.JSONEncoder.default(self, o) - - class AlchemyEncoder(json.JSONEncoder): def default(self, obj): From a1c24f6ba5dd7f1d2f73d775acb6e14f1f28b14e Mon Sep 17 00:00:00 2001 From: c8y3 <25362953+c8y3@users.noreply.github.com> Date: Wed, 9 Oct 2024 11:21:55 +0200 Subject: [PATCH 35/46] [IMP] Moved class AlchemyEncoder into blueprints namespace --- source/app/blueprints/responses.py | 42 ++++++++++++++++++- .../app/blueprints/rest/manage/manage_tags.py | 3 +- source/app/util.py | 40 ------------------ 3 files changed, 42 insertions(+), 43 deletions(-) diff --git a/source/app/blueprints/responses.py b/source/app/blueprints/responses.py index 6671fc4ef..ed8676c4e 100644 --- a/source/app/blueprints/responses.py +++ b/source/app/blueprints/responses.py @@ -15,14 +15,18 @@ # You should have received a copy of the GNU Lesser General Public License # along with this program; if not, write to the Free Software Foundation, # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +import datetime +import decimal import json +import pickle +import uuid from flask import render_template from flask import request +from sqlalchemy.orm import DeclarativeMeta from app import TEMPLATE_PATH from app import app -from app.util import AlchemyEncoder # Set basic 404 @@ -57,3 +61,39 @@ def response_success(msg='', data=None): "data": data if data is not None else [] } return response(200, data=content) + + +class AlchemyEncoder(json.JSONEncoder): + + def default(self, obj): + if isinstance(obj.__class__, DeclarativeMeta): + # an SQLAlchemy class + fields = {} + for field in [x for x in dir(obj) if not x.startswith('_') and x != 'metadata' + and x != 'query' and x != 'query_class']: + data = obj.__getattribute__(field) + try: + json.dumps(data) # this will fail on non-encodable values, like other classes + fields[field] = data + except TypeError: + fields[field] = None + # a json-encodable dict + return fields + + if isinstance(obj, decimal.Decimal): + return str(obj) + + if isinstance(obj, datetime.datetime) or isinstance(obj, datetime.date): + return obj.isoformat() + + if isinstance(obj, uuid.UUID): + return str(obj) + + else: + if obj.__class__ == bytes: + try: + return pickle.load(obj) + except Exception: + return str(obj) + + return json.JSONEncoder.default(self, obj) diff --git a/source/app/blueprints/rest/manage/manage_tags.py b/source/app/blueprints/rest/manage/manage_tags.py index 3b159aca5..14deac4b4 100644 --- a/source/app/blueprints/rest/manage/manage_tags.py +++ b/source/app/blueprints/rest/manage/manage_tags.py @@ -23,8 +23,7 @@ from app.datamgmt.manage.manage_tags_db import get_filtered_tags from app.schema.marshables import TagsSchema from app.blueprints.access_controls import ac_api_requires -from app.util import AlchemyEncoder -from app.blueprints.responses import response_success +from app.blueprints.responses import response_success, AlchemyEncoder manage_tags_rest_blueprint = Blueprint('manage_tags_rest', __name__) diff --git a/source/app/util.py b/source/app/util.py index 0b6799407..80bff3bb9 100644 --- a/source/app/util.py +++ b/source/app/util.py @@ -22,14 +22,11 @@ import datetime import decimal import hashlib -import json import logging as log import marshmallow -import pickle import random import shutil import string -import uuid import weakref from cryptography.exceptions import InvalidSignature from cryptography.hazmat.primitives import hashes @@ -38,7 +35,6 @@ from flask_login import current_user from pathlib import Path from pyunpack import Archive -from sqlalchemy.ext.declarative import DeclarativeMeta from sqlalchemy.orm.attributes import flag_modified from app import app @@ -46,42 +42,6 @@ from app.models import Cases -class AlchemyEncoder(json.JSONEncoder): - - def default(self, obj): - if isinstance(obj.__class__, DeclarativeMeta): - # an SQLAlchemy class - fields = {} - for field in [x for x in dir(obj) if not x.startswith('_') and x != 'metadata' - and x != 'query' and x != 'query_class']: - data = obj.__getattribute__(field) - try: - json.dumps(data) # this will fail on non-encodable values, like other classes - fields[field] = data - except TypeError: - fields[field] = None - # a json-encodable dict - return fields - - if isinstance(obj, decimal.Decimal): - return str(obj) - - if isinstance(obj, datetime.datetime) or isinstance(obj, datetime.date): - return obj.isoformat() - - if isinstance(obj, uuid.UUID): - return str(obj) - - else: - if obj.__class__ == bytes: - try: - return pickle.load(obj) - except Exception: - return str(obj) - - return json.JSONEncoder.default(self, obj) - - def DictDatetime(t): dl = ['Y', 'm', 'd', 'H', 'M', 'S', 'f'] if type(t) is datetime.datetime: From 397731c2a502209c272bea3a45a273ea2d326e7b Mon Sep 17 00:00:00 2001 From: c8y3 <25362953+c8y3@users.noreply.github.com> Date: Wed, 9 Oct 2024 11:22:44 +0200 Subject: [PATCH 36/46] [IMP] Removed seemingly unused methods --- source/app/util.py | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/source/app/util.py b/source/app/util.py index 80bff3bb9..72c6b30da 100644 --- a/source/app/util.py +++ b/source/app/util.py @@ -42,22 +42,6 @@ from app.models import Cases -def DictDatetime(t): - dl = ['Y', 'm', 'd', 'H', 'M', 'S', 'f'] - if type(t) is datetime.datetime: - return {a: t.strftime('%{}'.format(a)) for a in dl} - elif type(t) is dict: - return datetime.datetime.strptime(''.join(t[a] for a in dl), '%Y%m%d%H%M%S%f') - - -def AlchemyFnCode(obj): - """JSON encoder function for SQLAlchemy special classes.""" - if isinstance(obj, datetime.date): - return obj.isoformat() - elif isinstance(obj, decimal.Decimal): - return float(obj) - - def return_task(success, user, initial, logs, data, case_name, imported_files): ret = { 'success': success, From e2180a219cd5fdbe8ff8f4ca3d9ca2b3d9127e54 Mon Sep 17 00:00:00 2001 From: c8y3 <25362953+c8y3@users.noreply.github.com> Date: Wed, 9 Oct 2024 11:23:12 +0200 Subject: [PATCH 37/46] [IMP] Made method private --- source/app/util.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/app/util.py b/source/app/util.py index 72c6b30da..10dbabdd9 100644 --- a/source/app/util.py +++ b/source/app/util.py @@ -42,7 +42,7 @@ from app.models import Cases -def return_task(success, user, initial, logs, data, case_name, imported_files): +def _return_task(success, user, initial, logs, data, case_name, imported_files): ret = { 'success': success, 'user': user, @@ -56,11 +56,11 @@ def return_task(success, user, initial, logs, data, case_name, imported_files): def task_success(user=None, initial=None, logs=None, data=None, case_name=None, imported_files=None): - return return_task(True, user, initial, logs, data, case_name, imported_files) + return _return_task(True, user, initial, logs, data, case_name, imported_files) def task_failure(user=None, initial=None, logs=None, data=None, case_name=None, imported_files=None): - return return_task(False, user, initial, logs, data, case_name, imported_files) + return _return_task(False, user, initial, logs, data, case_name, imported_files) class FileRemover(object): From 4ee993a11b7810d025355d81926c0f9b4414364b Mon Sep 17 00:00:00 2001 From: c8y3 <25362953+c8y3@users.noreply.github.com> Date: Wed, 9 Oct 2024 11:24:10 +0200 Subject: [PATCH 38/46] [IMP] Removed seemingly unused methods --- source/app/util.py | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/source/app/util.py b/source/app/util.py index 10dbabdd9..e15a1210f 100644 --- a/source/app/util.py +++ b/source/app/util.py @@ -20,7 +20,6 @@ import base64 import datetime -import decimal import hashlib import logging as log import marshmallow @@ -42,27 +41,6 @@ from app.models import Cases -def _return_task(success, user, initial, logs, data, case_name, imported_files): - ret = { - 'success': success, - 'user': user, - 'initial': initial, - 'logs': logs, - 'data': data, - 'case_name': case_name, - 'imported_files': imported_files - } - return ret - - -def task_success(user=None, initial=None, logs=None, data=None, case_name=None, imported_files=None): - return _return_task(True, user, initial, logs, data, case_name, imported_files) - - -def task_failure(user=None, initial=None, logs=None, data=None, case_name=None, imported_files=None): - return _return_task(False, user, initial, logs, data, case_name, imported_files) - - class FileRemover(object): def __init__(self): self.weak_references = dict() # weak_ref -> filepath to remove From 6952ef44afc0a83d3bfdf5440bbdbac298495188 Mon Sep 17 00:00:00 2001 From: c8y3 <25362953+c8y3@users.noreply.github.com> Date: Wed, 9 Oct 2024 11:25:35 +0200 Subject: [PATCH 39/46] [IMP] Removed seemingly unused method --- source/app/util.py | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/source/app/util.py b/source/app/util.py index e15a1210f..be706c726 100644 --- a/source/app/util.py +++ b/source/app/util.py @@ -54,27 +54,6 @@ def _do_cleanup(self, wr): shutil.rmtree(filepath, ignore_errors=True) -def get_urlcasename(): - caseid = request.args.get('cid', default=None, type=int) - if not caseid: - try: - caseid = current_user.ctx_case - except: - return ["", ""] - - case = Cases.query.filter(Cases.case_id == caseid).first() - - if case is None: - case_name = "CASE NOT FOUND" - case_info = "Error" - else: - case_name = "{}".format(case.name) - case_info = "(#{} - {})".format(caseid, - case.client.name) - - return [case_name, case_info, caseid] - - def decompress_7z(filename: Path, output_dir): """ Decompress a 7z file in specified output directory From 2d17510d61e6c5750cc8d2f2fd4da284903e1b4f Mon Sep 17 00:00:00 2001 From: c8y3 <25362953+c8y3@users.noreply.github.com> Date: Fri, 11 Oct 2024 08:37:13 +0200 Subject: [PATCH 40/46] [IMP] Simple quotes --- source/app/blueprints/rest/case/case_timeline_routes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/app/blueprints/rest/case/case_timeline_routes.py b/source/app/blueprints/rest/case/case_timeline_routes.py index ef61e20af..25a405a90 100644 --- a/source/app/blueprints/rest/case/case_timeline_routes.py +++ b/source/app/blueprints/rest/case/case_timeline_routes.py @@ -679,7 +679,7 @@ def event_view(cur_id, caseid): return response_success(data=output) -@case_timeline_rest_blueprint.route('/case/timeline/events/update/', methods=["POST"]) +@case_timeline_rest_blueprint.route('/case/timeline/events/update/', methods=['POST']) @ac_requires_case_identifier(CaseAccessLevel.full_access) @ac_api_requires() def case_edit_event(cur_id, caseid): From 939c97b99bd51e8d6f8bff224067e1999da88bac Mon Sep 17 00:00:00 2001 From: c8y3 <25362953+c8y3@users.noreply.github.com> Date: Fri, 11 Oct 2024 09:32:10 +0200 Subject: [PATCH 41/46] [IMP] Removed method which was duplicated --- .../blueprints/rest/manage/manage_users.py | 38 ------------------- 1 file changed, 38 deletions(-) diff --git a/source/app/blueprints/rest/manage/manage_users.py b/source/app/blueprints/rest/manage/manage_users.py index 18344861a..2f1d2cde3 100644 --- a/source/app/blueprints/rest/manage/manage_users.py +++ b/source/app/blueprints/rest/manage/manage_users.py @@ -275,44 +275,6 @@ def manage_user_cac_delete_cases(cur_id): return response_error(msg=logs) -@manage_users_rest_blueprint.route('/manage/users//case-access/delete', methods=['POST']) -@ac_api_requires(Permissions.server_administrator) -def manage_user_cac_delete_case(cur_id): - - user = get_user(cur_id) - if not user: - return response_error("Invalid user ID") - - if not request.is_json: - return response_error("Invalid request") - - data = request.get_json() - if not data: - return response_error("Invalid request") - - if not isinstance(data.get('case'), int): - return response_error("Expecting cases as int") - - try: - - success, logs = remove_case_access_from_user(user.id, data.get('case')) - db.session.commit() - - except Exception as e: - log.error("Error while removing cases access from user: {}".format(e)) - log.error(traceback.format_exc()) - return response_error(msg=str(e)) - - if success: - track_activity(f"case access for case {data.get('case')} deleted for user {user.user}", ctx_less=True) - - user = get_user_details(cur_id) - - return response_success(msg="User case access updated", data=user) - - return response_error(msg=logs) - - @manage_users_rest_blueprint.route('/manage/users/update/', methods=['POST']) @ac_api_requires(Permissions.server_administrator) def update_user_api(cur_id): From f2ca43baf6a4cb219dcc252d90338e72b2c051d9 Mon Sep 17 00:00:00 2001 From: c8y3 <25362953+c8y3@users.noreply.github.com> Date: Fri, 11 Oct 2024 09:44:15 +0200 Subject: [PATCH 42/46] [IMP] Explicit GET method --- source/app/blueprints/rest/manage/manage_customers_routes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/app/blueprints/rest/manage/manage_customers_routes.py b/source/app/blueprints/rest/manage/manage_customers_routes.py index d0faa0a08..84cd20ebb 100644 --- a/source/app/blueprints/rest/manage/manage_customers_routes.py +++ b/source/app/blueprints/rest/manage/manage_customers_routes.py @@ -50,7 +50,7 @@ manage_customers_rest_blueprint = Blueprint('manage_customers_rest', __name__) -@manage_customers_rest_blueprint.route('/manage/customers/list') +@manage_customers_rest_blueprint.route('/manage/customers/list', methods=['GET']) @ac_api_requires(Permissions.customers_read) def list_customers(): user_is_server_administrator = ac_current_user_has_permission(Permissions.server_administrator) From 99bec08b3e408a69fbd991ab5c3ee09b397353cd Mon Sep 17 00:00:00 2001 From: c8y3 <25362953+c8y3@users.noreply.github.com> Date: Fri, 11 Oct 2024 12:47:08 +0200 Subject: [PATCH 43/46] [IMP] Alignment --- ui/src/pages/manage.customers.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ui/src/pages/manage.customers.js b/ui/src/pages/manage.customers.js index 7a2031a3a..fb06a38ee 100644 --- a/ui/src/pages/manage.customers.js +++ b/ui/src/pages/manage.customers.js @@ -18,7 +18,9 @@ function add_customer() { has_error = ret[0].length > 0; attributes = ret[1]; - if (has_error){return false;} + if (has_error) { + return false; + } form['custom_attributes'] = attributes; From 8b4e66fa80f4219f1a194357b3e31f20cd018a65 Mon Sep 17 00:00:00 2001 From: c8y3 <25362953+c8y3@users.noreply.github.com> Date: Fri, 11 Oct 2024 12:48:00 +0200 Subject: [PATCH 44/46] [IMP] Using full url --- ui/src/pages/manage.customers.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/src/pages/manage.customers.js b/ui/src/pages/manage.customers.js index fb06a38ee..36413f91f 100644 --- a/ui/src/pages/manage.customers.js +++ b/ui/src/pages/manage.customers.js @@ -24,7 +24,7 @@ function add_customer() { form['custom_attributes'] = attributes; - post_request_api('customers/add', JSON.stringify(form), true) + post_request_api('/manage/customers/add', JSON.stringify(form), true) .done((data) => { if(notify_auto_api(data)) { refresh_customer_table(); From c3aa44dcb1a40c0c8e1a0846ee3e11826f1f2293 Mon Sep 17 00:00:00 2001 From: c8y3 <25362953+c8y3@users.noreply.github.com> Date: Fri, 11 Oct 2024 14:30:04 +0200 Subject: [PATCH 45/46] [IMP] Explicit method --- source/app/blueprints/rest/manage/manage_modules_routes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/app/blueprints/rest/manage/manage_modules_routes.py b/source/app/blueprints/rest/manage/manage_modules_routes.py index a6b114f92..90e22f6c7 100644 --- a/source/app/blueprints/rest/manage/manage_modules_routes.py +++ b/source/app/blueprints/rest/manage/manage_modules_routes.py @@ -216,7 +216,7 @@ def view_modules_hook(): # TODO is this endpoint still useful? -@manage_modules_rest_blueprint.route("/sitemap") +@manage_modules_rest_blueprint.route('/sitemap', methods=['GET']) @ac_api_requires() def site_map(): links = [] From cfdc0bbec51e1bb9887eb10f64b19089a9e62f70 Mon Sep 17 00:00:00 2001 From: c8y3 <25362953+c8y3@users.noreply.github.com> Date: Fri, 11 Oct 2024 15:53:47 +0200 Subject: [PATCH 46/46] [IMP] Moved endpoints in namespace app.blueprints.rest.v2 --- .../blueprints/rest/case/case_tasks_routes.py | 51 ------------ .../rest/v2/case/api_v2_case_tasks_routes.py | 83 +++++++++++++++++++ source/app/views.py | 2 + 3 files changed, 85 insertions(+), 51 deletions(-) create mode 100644 source/app/blueprints/rest/v2/case/api_v2_case_tasks_routes.py diff --git a/source/app/blueprints/rest/case/case_tasks_routes.py b/source/app/blueprints/rest/case/case_tasks_routes.py index f0b9ebe9a..a77db4daa 100644 --- a/source/app/blueprints/rest/case/case_tasks_routes.py +++ b/source/app/blueprints/rest/case/case_tasks_routes.py @@ -25,13 +25,8 @@ from app import db from app.blueprints.rest.case_comments import case_comment_update -from app.blueprints.rest.endpoints import response_api_deleted -from app.blueprints.rest.endpoints import response_api_not_found from app.blueprints.rest.endpoints import endpoint_deprecated -from app.blueprints.rest.endpoints import response_api_error -from app.blueprints.rest.endpoints import response_api_created from app.business.errors import BusinessProcessingError -from app.business.errors import ObjectNotFoundError from app.business.tasks import tasks_delete from app.business.tasks import tasks_create from app.business.tasks import tasks_get @@ -46,7 +41,6 @@ from app.datamgmt.case.case_tasks_db import get_tasks_with_assignees from app.datamgmt.case.case_tasks_db import update_task_status from app.datamgmt.states import get_tasks_state -from app.iris_engine.access_control.utils import ac_fast_check_current_user_has_case_access from app.iris_engine.module_handler.module_handler import call_modules_hook from app.iris_engine.utils.tracker import track_activity from app.models.authorization import CaseAccessLevel @@ -54,7 +48,6 @@ from app.schema.marshables import CommentSchema from app.blueprints.access_controls import ac_requires_case_identifier from app.blueprints.access_controls import ac_api_requires -from app.blueprints.access_controls import ac_api_return_access_denied from app.blueprints.responses import response_error from app.blueprints.responses import response_success @@ -123,20 +116,6 @@ def deprecated_case_add_task(caseid): return response_error(e.get_message(), data=e.get_data()) -@case_tasks_rest_blueprint.route('/api/v2/cases//tasks', methods=['POST']) -@ac_api_requires() -def case_add_task(identifier): - if not ac_fast_check_current_user_has_case_access(identifier, [CaseAccessLevel.full_access]): - return ac_api_return_access_denied(caseid=identifier) - - task_schema = CaseTaskSchema() - try: - _, case = tasks_create(identifier, request.get_json()) - return response_api_created(task_schema.dump(case)) - except BusinessProcessingError as e: - return response_api_error(e.get_message()) - - @case_tasks_rest_blueprint.route('/case/tasks/', methods=['GET']) @endpoint_deprecated('GET', '/api/v2/tasks/') @ac_requires_case_identifier(CaseAccessLevel.read_only, CaseAccessLevel.full_access) @@ -151,20 +130,6 @@ def deprecated_case_task_view(cur_id, caseid): return response_success(data=task_schema.dump(task)) -@case_tasks_rest_blueprint.route('/api/v2/tasks/', methods=['GET']) -@ac_api_requires() -def case_task_view(identifier): - try: - task = tasks_get(identifier) - if not ac_fast_check_current_user_has_case_access(task.task_case_id, [CaseAccessLevel.read_only, CaseAccessLevel.full_access]): - return ac_api_return_access_denied(caseid=task.task_case_id) - - task_schema = CaseTaskSchema() - return response_api_created(task_schema.dump(task)) - except ObjectNotFoundError: - return response_api_not_found() - - @case_tasks_rest_blueprint.route('/case/tasks/update/', methods=['POST']) @ac_requires_case_identifier(CaseAccessLevel.full_access) @ac_api_requires() @@ -189,22 +154,6 @@ def deprecated_case_delete_task(cur_id, caseid): return response_error(e.get_message()) -@case_tasks_rest_blueprint.route('/api/v2/tasks/', methods=['DELETE']) -@ac_api_requires() -def case_delete_task(identifier): - try: - task = tasks_get(identifier) - if not ac_fast_check_current_user_has_case_access(task.task_case_id, [CaseAccessLevel.full_access]): - return ac_api_return_access_denied(caseid=identifier) - - tasks_delete(task) - return response_api_deleted() - except ObjectNotFoundError: - return response_api_not_found() - except BusinessProcessingError as e: - return response_api_error(e.get_message()) - - @case_tasks_rest_blueprint.route('/case/tasks//comments/list', methods=['GET']) @ac_requires_case_identifier(CaseAccessLevel.read_only, CaseAccessLevel.full_access) @ac_api_requires() diff --git a/source/app/blueprints/rest/v2/case/api_v2_case_tasks_routes.py b/source/app/blueprints/rest/v2/case/api_v2_case_tasks_routes.py new file mode 100644 index 000000000..5d70dc950 --- /dev/null +++ b/source/app/blueprints/rest/v2/case/api_v2_case_tasks_routes.py @@ -0,0 +1,83 @@ +# IRIS Source Code +# Copyright (C) 2024 - DFIR-IRIS +# contact@dfir-iris.org +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 3 of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +from flask import Blueprint +from flask import request + +from app.blueprints.rest.endpoints import response_api_deleted +from app.blueprints.rest.endpoints import response_api_not_found +from app.blueprints.rest.endpoints import response_api_error +from app.blueprints.rest.endpoints import response_api_created +from app.blueprints.access_controls import ac_api_return_access_denied +from app.blueprints.access_controls import ac_api_requires +from app.schema.marshables import CaseTaskSchema +from app.business.errors import ObjectNotFoundError +from app.business.errors import BusinessProcessingError +from app.business.tasks import tasks_delete +from app.business.tasks import tasks_create +from app.business.tasks import tasks_get +from app.models.authorization import CaseAccessLevel +from app.iris_engine.access_control.utils import ac_fast_check_current_user_has_case_access + +api_v2_tasks_blueprint = Blueprint('case_tasks_rest_v2', + __name__, + url_prefix='/api/v2') + + +@api_v2_tasks_blueprint.route('/cases//tasks', methods=['POST']) +@ac_api_requires() +def case_add_task(identifier): + if not ac_fast_check_current_user_has_case_access(identifier, [CaseAccessLevel.full_access]): + return ac_api_return_access_denied(caseid=identifier) + + task_schema = CaseTaskSchema() + try: + _, case = tasks_create(identifier, request.get_json()) + return response_api_created(task_schema.dump(case)) + except BusinessProcessingError as e: + return response_api_error(e.get_message()) + + +@api_v2_tasks_blueprint.route('/tasks/', methods=['GET']) +@ac_api_requires() +def case_task_view(identifier): + try: + task = tasks_get(identifier) + if not ac_fast_check_current_user_has_case_access(task.task_case_id, [CaseAccessLevel.read_only, CaseAccessLevel.full_access]): + return ac_api_return_access_denied(caseid=task.task_case_id) + + task_schema = CaseTaskSchema() + return response_api_created(task_schema.dump(task)) + except ObjectNotFoundError: + return response_api_not_found() + + +@api_v2_tasks_blueprint.route('/tasks/', methods=['DELETE']) +@ac_api_requires() +def case_delete_task(identifier): + try: + task = tasks_get(identifier) + if not ac_fast_check_current_user_has_case_access(task.task_case_id, [CaseAccessLevel.full_access]): + return ac_api_return_access_denied(caseid=identifier) + + tasks_delete(task) + return response_api_deleted() + except ObjectNotFoundError: + return response_api_not_found() + except BusinessProcessingError as e: + return response_api_error(e.get_message()) diff --git a/source/app/views.py b/source/app/views.py index c8766997a..0874c7f66 100644 --- a/source/app/views.py +++ b/source/app/views.py @@ -99,6 +99,7 @@ from app.blueprints.graphql.graphql_route import graphql_blueprint from app.blueprints.rest.v2.case.api_v2_assets_routes import api_v2_assets_blueprint from app.blueprints.rest.v2.case.api_v2_ioc_routes import api_v2_ioc_blueprint +from app.blueprints.rest.v2.case.api_v2_case_tasks_routes import api_v2_tasks_blueprint from app.models.authorization import User from app.post_init import run_post_init @@ -186,6 +187,7 @@ app.register_blueprint(api_v2_ioc_blueprint) app.register_blueprint(api_v2_assets_blueprint) +app.register_blueprint(api_v2_tasks_blueprint) try: