Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rest improvement assets #562

Merged
merged 23 commits into from
Aug 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
baaafc2
[ADD] New rest endpoint POST /api/v2/cases/<int:caseid>/assets
Elise17 Aug 1, 2024
a25e0a5
[FIX] Fix problem on case_assets_routes.py
Elise17 Aug 1, 2024
4e2e29f
[ADD] New rest endpoint GET /api/v2/assets/<int:cur_id>
Elise17 Aug 1, 2024
df300e6
[ADD] New rest endpoint DELETE /api/v2/assets/<int:cur_id>
Elise17 Aug 1, 2024
4e3805e
[IMP] Change URL name for POST and DELETE /api/v2/assets/asset_id
Elise17 Aug 1, 2024
f4adb0f
[IMP] Moved code to create an assets down into the business layer
Elise17 Aug 1, 2024
180a2c7
[IMP] rename update, delete, create to tasks_update, tasks_create and…
Elise17 Aug 1, 2024
63c3582
[FIX] Fix problem on renamed tasks actions
Elise17 Aug 1, 2024
7d282ee
[IMP] Using task_delete for /api/v2/tasks/task_id
Elise17 Aug 1, 2024
e6bc896
[IMP] Using tasks_create for /api/v2/caes/caseid/tasks
Elise17 Aug 1, 2024
8af4ada
[IMP] Using task_create and task_delete in case_task_routes.py
Elise17 Aug 1, 2024
c2ad55a
[IMP] Start the name of old URL function name with deprecated_ in cas…
Elise17 Aug 1, 2024
63fb116
[IMP] Start the name of old URL function name with deprecated_ in cas…
Elise17 Aug 1, 2024
3a40a97
[IMP] Changed some code to delete an assets in case_assets_routes
Elise17 Aug 1, 2024
d3ecec9
[ADD] Add test_delete_asset_should_return_204 and test_delete_asset_w…
Elise17 Aug 1, 2024
1c46e57
[ADD]Changed some code to add an asset in case_assets_routes and in t…
Elise17 Aug 2, 2024
2f11c6c
[IMP] Change data to textStatus in case.asset.js
Elise17 Aug 2, 2024
a41b6bd
[IMP] Replaced response_succes and response_error to response_api_err…
Elise17 Aug 2, 2024
c7e98ff
[IMP] Change name of function case_view_ioc
Elise17 Aug 6, 2024
245a4b8
[ADD] Add function get_asset() in assets.py
Elise17 Aug 7, 2024
a5dcc78
[IMP] Improved test_get_asset_with_missing_asset_identifier_should_re…
Elise17 Aug 7, 2024
aa0ddd5
[IMP] Changed name test_get_asset_with_missing_asset_identifier_shoul…
Elise17 Aug 7, 2024
555afe1
Merge branch 'develop' into rest_improvement_assets
whikernel Aug 12, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
112 changes: 57 additions & 55 deletions source/app/blueprints/rest/case/case_assets_routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,15 @@
from flask_login import current_user

from app import db
from app.blueprints.rest.case_comments import case_comment_update
from app.blueprints.case.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_error
from app.blueprints.rest.endpoints import response_api_created
from app.business.assets import assets_delete, assets_create, assets_get
from app.business.errors import BusinessProcessingError
from app.datamgmt.case.case_assets_db import add_comment_to_asset
from app.datamgmt.case.case_assets_db import create_asset
from app.datamgmt.case.case_assets_db import delete_asset
from app.datamgmt.case.case_assets_db import delete_asset_comment
from app.datamgmt.case.case_assets_db import get_asset
from app.datamgmt.case.case_assets_db import get_asset_type_id
Expand Down Expand Up @@ -113,38 +118,29 @@ def case_assets_state(caseid):


@case_assets_rest_blueprint.route('/case/assets/add', methods=['POST'])
@endpoint_deprecated('POST', '/api/v2/cases/<int:caseid>/assets')
@ac_requires_case_identifier(CaseAccessLevel.full_access)
@ac_api_requires()
def add_asset(caseid):
def deprecated_add_asset(case_identifier):
asset_schema = CaseAssetsSchema()
try:
# validate before saving
add_asset_schema = CaseAssetsSchema()
request_data = call_modules_hook('on_preload_asset_create', data=request.get_json(), caseid=caseid)

add_asset_schema.is_unique_for_cid(caseid, request_data)
asset = add_asset_schema.load(request_data)

asset = create_asset(asset=asset,
caseid=caseid,
user_id=current_user.id
)

if request_data.get('ioc_links'):
errors, _ = set_ioc_links(request_data.get('ioc_links'), asset.asset_id)
if errors:
return response_error('Encountered errors while linking IOC. Asset has still been updated.')
asset, msg = assets_create(case_identifier, request.get_json())
return response_success(msg, asset_schema.dump(asset))
except BusinessProcessingError as e:
return response_error(e.get_message())

asset = call_modules_hook('on_postload_asset_create', data=asset, caseid=caseid)

if asset:
track_activity(f"added asset \"{asset.asset_name}\"", caseid=caseid)
return response_success("Asset added", data=add_asset_schema.dump(asset))

return response_error("Unable to create asset for internal reasons")

except marshmallow.exceptions.ValidationError as e:
db.session.rollback()
return response_error(msg="Data error", data=e.messages)
@case_assets_rest_blueprint.route('/api/v2/cases/<int:caseid>/assets', methods=['POST'])
@ac_requires_case_identifier(CaseAccessLevel.full_access)
@ac_api_requires()
def add_asset(caseid):
asset_schema = CaseAssetsSchema()
try:
asset_schema.is_unique_for_cid(caseid, request.get_json())
asset, _ = assets_create(caseid, request.get_json())
return response_api_created(asset_schema.dump(asset))
except BusinessProcessingError as e:
return response_api_error(e.get_message())


@case_assets_rest_blueprint.route('/case/assets/upload', methods=['POST'])
Expand Down Expand Up @@ -247,23 +243,26 @@ def case_upload_ioc(caseid):


@case_assets_rest_blueprint.route('/case/assets/<int:cur_id>', methods=['GET'])
@endpoint_deprecated('GET', '/api/v2/assets/<int:cur_id>')
@ac_requires_case_identifier(CaseAccessLevel.read_only, CaseAccessLevel.full_access)
@ac_api_requires()
def asset_view(cur_id, caseid):
# Get IoCs already linked to the asset
asset_iocs = get_linked_iocs_finfo_from_asset(cur_id)

ioc_prefill = [row._asdict() for row in asset_iocs]

asset = get_asset(cur_id, caseid)
if not asset:
return response_error("Invalid asset ID for this case")
def deprecated_asset_view(cur_id, caseid):
try:
asset = assets_get(cur_id, caseid)
return response_success(asset)
except BusinessProcessingError as e:
return response_error(e.get_message())

asset_schema = CaseAssetsSchema()
data = asset_schema.dump(asset)
data['linked_ioc'] = ioc_prefill

return response_success(data=data)
@case_assets_rest_blueprint.route('/api/v2/assets/<int:cur_id>', methods=['GET'])
@ac_requires_case_identifier(CaseAccessLevel.read_only, CaseAccessLevel.full_access)
@ac_api_requires()
def asset_view(cur_id, caseid):
try:
asset = assets_get(cur_id, caseid)
return response_api_created(asset)
except BusinessProcessingError as e:
return response_api_error(e.get_message())


@case_assets_rest_blueprint.route('/case/assets/update/<int:cur_id>', methods=['POST'])
Expand Down Expand Up @@ -307,23 +306,26 @@ def asset_update(cur_id, caseid):


@case_assets_rest_blueprint.route('/case/assets/delete/<int:cur_id>', methods=['POST'])
@endpoint_deprecated('DELETE', '/api/v2/assets/<int:cur_id>')
@ac_requires_case_identifier(CaseAccessLevel.full_access)
@ac_api_requires()
def asset_delete(cur_id, caseid):
call_modules_hook('on_preload_asset_delete', data=cur_id, caseid=caseid)

asset = get_asset(cur_id, caseid)
if not asset:
def deprecated_asset_delete(cur_id, caseid):
try:
assets_delete(cur_id, caseid)
return response_success("Deleted")
except BusinessProcessingError as _:
return response_error("Invalid asset ID for this case")

# Deletes an asset and the potential links with the IoCs from the database
delete_asset(cur_id, caseid)

call_modules_hook('on_postload_asset_delete', data=cur_id, caseid=caseid)

track_activity(f"removed asset ID {asset.asset_name}", caseid=caseid)

return response_success("Deleted")
@case_assets_rest_blueprint.route('/api/v2/assets/<int:cur_id>', methods=['DELETE'])
@ac_requires_case_identifier(CaseAccessLevel.full_access)
@ac_api_requires()
def asset_delete(cur_id, caseid):
try:
assets_delete(cur_id, caseid)
return response_api_deleted()
except BusinessProcessingError as e:
return response_api_error(e.get_message())


@case_assets_rest_blueprint.route('/case/assets/<int:cur_id>/comments/list', methods=['GET'])
Expand Down Expand Up @@ -402,4 +404,4 @@ def case_comment_asset_delete(cur_id, com_id, caseid):
call_modules_hook('on_postload_asset_comment_delete', data=com_id, caseid=caseid)

track_activity(f"comment {com_id} on asset {cur_id} deleted", caseid=caseid)
return response_success(msg)
return response_success(msg)
9 changes: 4 additions & 5 deletions source/app/blueprints/rest/case/case_ioc_routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ def case_upload_ioc(caseid):
@endpoint_deprecated('DELETE', '/api/v2/iocs/<int:cur_id>')
@ac_requires_case_identifier(CaseAccessLevel.full_access)
@ac_api_requires()
def case_delete_ioc(cur_id, caseid):
def deprecated_case_delete_ioc(cur_id, caseid):
try:

msg = iocs_delete(cur_id, caseid)
Expand All @@ -237,9 +237,8 @@ def case_delete_ioc(cur_id, caseid):
@case_ioc_rest_blueprint.route('/api/v2/iocs/<int:cur_id>', methods=['DELETE'])
@ac_requires_case_identifier(CaseAccessLevel.full_access)
@ac_api_requires()
def delete_case_ioc(cur_id, caseid):
def case_delete_ioc(cur_id, caseid):
try:

iocs_delete(cur_id, caseid)
return response_api_deleted()

Expand All @@ -251,7 +250,7 @@ def delete_case_ioc(cur_id, caseid):
@endpoint_deprecated('GET', '/api/v2/iocs/<int:cur_id>')
@ac_requires_case_identifier(CaseAccessLevel.read_only, CaseAccessLevel.full_access)
@ac_api_requires()
def case_view_ioc(cur_id, caseid):
def deprecated_case_view_ioc(cur_id, caseid):
ioc_schema = IocSchema()
ioc = get_ioc(cur_id, caseid)
if not ioc:
Expand All @@ -263,7 +262,7 @@ def case_view_ioc(cur_id, caseid):
@case_ioc_rest_blueprint.route('/api/v2/iocs/<int:cur_id>', methods=['GET'])
@ac_requires_case_identifier(CaseAccessLevel.read_only, CaseAccessLevel.full_access)
@ac_api_requires()
def get_case_ioc(cur_id, caseid):
def case_view_ioc(cur_id, caseid):
ioc_schema = IocSchema()
ioc = get_ioc(cur_id, caseid)
if not ioc:
Expand Down
78 changes: 22 additions & 56 deletions source/app/blueprints/rest/case/case_tasks_routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@
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.tasks import delete
from app.business.tasks import create
from app.business.tasks import update
from app.business.tasks import tasks_delete
from app.business.tasks import tasks_create
from app.business.tasks import tasks_update
from app.datamgmt.case.case_tasks_db import add_comment_to_task
from app.datamgmt.case.case_tasks_db import add_task
from app.datamgmt.case.case_tasks_db import delete_task
Expand Down Expand Up @@ -112,57 +112,32 @@ def case_task_statusupdate(cur_id, caseid):
@endpoint_deprecated('POST', '/api/v2/cases/<int:caseid>/tasks')
@ac_requires_case_identifier(CaseAccessLevel.full_access)
@ac_api_requires()
def case_add_task(caseid):

def deprecated_case_add_task(caseid):
task_schema = CaseTaskSchema()
try:
case, msg = create(caseid, request.get_json())
case, msg = tasks_create(caseid, request.get_json())
return response_success(msg, data=task_schema.dump(case))
except BusinessProcessingError as e:
return response_error(e.get_message(), data=e.get_data())
except marshmallow.exceptions.ValidationError as e:
return response_error(msg="Data error", data=e.messages)


@case_tasks_rest_blueprint.route('/api/v2/cases/<int:caseid>/tasks', methods=['POST'])
@ac_requires_case_identifier(CaseAccessLevel.full_access)
@ac_api_requires()
def api_case_add_task(caseid):
def case_add_task(caseid):
task_schema = CaseTaskSchema()
try:
# validate before saving
task_schema = CaseTaskSchema()
request_data = call_modules_hook('on_preload_task_create', data=request.get_json(), caseid=caseid)

if 'task_assignee_id' in request_data or 'task_assignees_id' not in request_data:
return response_api_error('task_assignee_id is not valid anymore since v1.5.0')

task_assignee_list = request_data['task_assignees_id']
del request_data['task_assignees_id']
task = task_schema.load(request_data)

ctask = add_task(task=task,
assignee_id_list=task_assignee_list,
user_id=current_user.id,
caseid=caseid
)

ctask = call_modules_hook('on_postload_task_create', data=ctask, caseid=caseid)

if ctask:
track_activity(f"added task \"{ctask.task_title}\"", caseid=caseid)
return response_api_created(task_schema.dump(ctask))

return response_api_error("Unable to create task for internal reasons")

except marshmallow.exceptions.ValidationError as e:
return response_api_error(e.messages)
case, _ = tasks_create(caseid, 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/<int:cur_id>', methods=['GET'])
@endpoint_deprecated('GET', '/api/v2/tasks/<int:cur_id>')
@ac_requires_case_identifier(CaseAccessLevel.read_only, CaseAccessLevel.full_access)
@ac_api_requires()
def case_task_view(cur_id, caseid):
def deprecated_case_task_view(cur_id, caseid):
task = get_task_with_assignees(task_id=cur_id, case_id=caseid)
if not task:
return response_error("Invalid task ID for this case")
Expand All @@ -175,7 +150,7 @@ def case_task_view(cur_id, caseid):
@case_tasks_rest_blueprint.route('/api/v2/tasks/<int:cur_id>', methods=['GET'])
@ac_requires_case_identifier(CaseAccessLevel.read_only, CaseAccessLevel.full_access)
@ac_api_requires()
def api_case_task_view(cur_id, caseid):
def case_task_view(cur_id, caseid):
task = get_task_with_assignees(task_id=cur_id, case_id=caseid)
if not task:
return response_api_error("Invalid task ID for this case")
Expand All @@ -190,7 +165,7 @@ def api_case_task_view(cur_id, caseid):
@ac_api_requires()
def case_edit_task(cur_id, caseid):
try:
msg = update(cur_id, caseid, request.get_json())
msg = tasks_update(cur_id, caseid, request.get_json())
return response_success(msg)
except marshmallow.exceptions.ValidationError as e:
return response_error(msg="Data error", data=e.messages)
Expand All @@ -200,9 +175,9 @@ def case_edit_task(cur_id, caseid):
@endpoint_deprecated('DELETE', '/api/v2/tasks/<int:cur_id>')
@ac_requires_case_identifier(CaseAccessLevel.full_access)
@ac_api_requires()
def case_delete_task(cur_id, caseid):
def deprecated_case_delete_task(cur_id, caseid):
try:
msg = delete(cur_id, caseid)
msg = tasks_delete(cur_id, caseid)
return response_success(msg)
except BusinessProcessingError as e:
return response_error(e.get_message())
Expand All @@ -211,21 +186,12 @@ def case_delete_task(cur_id, caseid):
@case_tasks_rest_blueprint.route('/api/v2/tasks/<int:cur_id>', methods=['DELETE'])
@ac_requires_case_identifier(CaseAccessLevel.full_access)
@ac_api_requires()
def api_case_delete_task(cur_id, caseid):
call_modules_hook('on_preload_task_delete', data=cur_id, caseid=caseid)
task = get_task_with_assignees(task_id=cur_id, case_id=caseid)
if not task:
return response_api_error("Invalid task ID for this case")

delete_task(task.id)

update_tasks_state(caseid=caseid)

call_modules_hook('on_postload_task_delete', data=cur_id, caseid=caseid)

track_activity(f"deleted task \"{task.task_title}\"")

return response_api_deleted()
def case_delete_task(cur_id, caseid):
try:
tasks_delete(cur_id, caseid)
return response_api_deleted()
except BusinessProcessingError as e:
return response_api_error(e.get_message())


@case_tasks_rest_blueprint.route('/case/tasks/<int:cur_id>/comments/list', methods=['GET'])
Expand Down
Loading
Loading