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

657 datapackages endpoint bugs #659

Merged
merged 4 commits into from
Dec 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,12 @@ def __init__(
def initialize(self, request: Request, response: Response):
super().initialize(request, response)

def delete_enterprise_sync_object(self, objecthash:str=None, objectuid:str=None, *args, **kwargs):
def delete_enterprise_sync_object(self, object_hash:str=None, object_uid:str=None, *args, **kwargs):
db_controller = DatabaseController()
if objecthash != None:
data_obj = db_controller.session.query(EnterpriseSyncDataObject).filter(EnterpriseSyncDataObject.hash == objecthash).first()
elif objectuid != None:
data_obj = db_controller.session.query(EnterpriseSyncDataObject).filter(EnterpriseSyncDataObject.PrimaryKey == objectuid).first()
if object_hash != None:
data_obj = db_controller.session.query(EnterpriseSyncDataObject).filter(EnterpriseSyncDataObject.hash == object_hash).first()
elif object_uid != None:
data_obj = db_controller.session.query(EnterpriseSyncDataObject).filter(EnterpriseSyncDataObject.PrimaryKey == object_uid).first()
else:
raise Exception("no object uid or hash provided")
db_controller.session.delete(data_obj)
Expand Down Expand Up @@ -144,13 +144,16 @@ def get_all_enterprise_sync_data_objects(self, logger, *args, **kwargs):
logger.error("error thrown getting all enterprise sync objs: %s", ex)
db_controller.session.rollback()

def get_multiple_enterprise_sync_data_objec(self, logger, tool: str="*", keyword: str="*", *args, **kwargs):
def get_multiple_enterprise_sync_data_objec(self, logger, tool: str=None, keyword: str=None, *args, **kwargs):
try:
db_controller = DatabaseController()
data_objs = db_controller.session.query(EnterpriseSyncDataObject)\
.join(EnterpriseSyncKeyword)\
.filter(EnterpriseSyncDataObject.tool == tool, EnterpriseSyncKeyword.keyword == keyword).all()
return data_objs
data_objs_query = db_controller.session.query(EnterpriseSyncDataObject)\
.join(EnterpriseSyncKeyword)
if tool != None:
data_objs_query = data_objs_query.filter(EnterpriseSyncDataObject.tool == tool)
if keyword != None:
data_objs_query = data_objs_query.filter(EnterpriseSyncKeyword.keyword == keyword)
return data_objs_query.all()
except Exception as ex:
logger.error("error thrown getting enterprise sync objs by tool: %s", ex)
db_controller.session.rollback()
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,9 @@ def get_all_enterprise_sync_metadata(self, logger, *args, **kwargs):
self.response.set_value("objectmetadata", sync_data)

def delete_enterprise_sync_data(self, logger, *args, **kwargs):
data_obj = self.persistence_controller.get_enterprise_sync_data_object(*args, **kwargs)
""" delete an enterprise sync object and its associated data
"""
data_obj = self.persistence_controller.get_enterprise_sync_data_object(logger, *args, **kwargs)
self.filesystem_controller.delete_file(file_type=data_obj.file_type, object_uid=data_obj.PrimaryKey)
self.persistence_controller.delete_enterprise_sync_object(*args, **kwargs)

Original file line number Diff line number Diff line change
Expand Up @@ -99,5 +99,5 @@ def get_all_enterprise_sync_metadata(self, *args, **kwargs):
self.general_controller.get_all_enterprise_sync_metadata(*args, **kwargs)

@DefaultFacade.public
def delete_enterpire_sync_data(self, *args, **kwargs):
def delete_enterprise_sync_data(self, *args, **kwargs):
self.general_controller.delete_enterprise_sync_data(*args, **kwargs)
Original file line number Diff line number Diff line change
@@ -1,3 +1,16 @@
"""
datapackages_blueprint.py

This module is part of a Flask web application and is responsible for defining a blueprint related to data packages. It includes routes and views for handling requests related to data packages.

It imports several modules and types for use within the file:
- TYPE_CHECKING from the typing module, which is used for conditional imports based on whether type checking is being performed.
- jsonify from flask.json, which is used to create a JSON response.
- EnterpriseSyncKeyword and EnterpriseSyncDataObject from FreeTAKServer.core.enterprise_sync.persistence.sqlalchemy, which are used for enterprise synchronization. These are imported conditionally if type checking is being performed.
- json module, which is used for handling JSON data.
- Blueprint and request from flask, which are used for creating modular, reusable components in a Flask application and handling requests, respectively.
- PurePath and Path from pathlib, which are used for handling filesystem paths in a platform-independent way.
"""
from typing import TYPE_CHECKING

from flask.json import jsonify
Expand All @@ -23,23 +36,30 @@
config = MainConfig.instance()
page = Blueprint('datapackage', __name__)


@page.route('/DataPackageTable', methods=["POST"])
@auth.login_required()
def post_DataPackageTable():
try:
""" This function handles the POST request for the DataPackageTable route. It is used to upload a data package to the server.
"""
try:
uid = str(uuid.uuid4())
filename = request.args.get('filename')
creatorUid = request.args.get('creatorUid')
file = request.files.getlist('assetfile')[0]
metadata: EnterpriseSyncDataObject = RestAPICommunicationController().make_request("SaveEnterpriseSyncData", "enterpriseSync", {"objectuid": uid, "tool": "public", "objectdata": file, "objkeywords": [filename, creatorUid, "missionpackage"], "objstarttime": "", "synctype": "content", "mime_type": request.headers["Content-Type"], "file_name": filename}).get_value("objectmetadata") # type: ignore
file = request.files.getlist('assetfile')[0].stream.read()
metadata: EnterpriseSyncDataObject = RestAPICommunicationController().make_request("SaveEnterpriseSyncData", "enterpriseSync", {"objectuid": uid, "tool": "public", "objectdata": file, "objkeywords": [
filename, creatorUid, "missionpackage"], "objstarttime": "", "synctype": "content", "mime_type": request.headers["Content-Type"], "file_name": filename}).get_value("objectmetadata") # type: ignore

return {"message":'success', "id": str(metadata.id)}, 200
return {"message": 'success', "id": str(metadata.id)}, 200
except Exception as e:
return {"message":"An error occurred accessing datapackage details."}, 500
return {"message": "An error occurred accessing datapackage details: "+str(e)}, 500

Check warning

Code scanning / CodeQL

Information exposure through an exception Medium

Stack trace information
flows to this location and may be exposed to an external user.


@page.route('/DataPackageTable', methods=["PUT"])
@auth.login_required()
def put_DataPackageTable():
""" This function handles the PUT request for the DataPackageTable route. It is used to update the metadata for a data package.
"""
updatedata = json.loads(request.data)
DataPackages = updatedata['DataPackages']
for dp in DataPackages:
Expand All @@ -56,16 +76,22 @@
name = dp["Name"]
else:
name = None
pk = RestAPICommunicationController().make_request("GetEnterpriseSyncMetaData", "", {"file_name": dp["PrimaryKey"]}, None, True).get_value('objectmetadata').PrimaryKey
RestAPICommunicationController().make_request("UpdateEnterpriseSyncMetaData", "", {"file_name": name, "keywords": keywords, "privacy": privacy, "objectuid": pk}, None, True)

return {"message":"success"}, 200
pk = RestAPICommunicationController().make_request("GetEnterpriseSyncMetaData", "",
{"file_name": dp["PrimaryKey"]}, None, True).get_value('objectmetadata').PrimaryKey
RestAPICommunicationController().make_request("UpdateEnterpriseSyncMetaData", "", {
"file_name": name, "keywords": keywords, "privacy": privacy, "objectuid": pk}, None, True)

return {"message": "success"}, 200


@page.route('/DataPackageTable', methods=["GET"])
@auth.login_required()
def get_DataPackageTable():
""" This function handles the GET request for the DataPackageTable route. It is used to retrieve the metadata for a data package.
"""
return_vals = []
output = RestAPICommunicationController().make_request("GetAllEnterpriseSyncMetaData", "", {}, None, True).get_value("objectmetadata")
output = RestAPICommunicationController().make_request("GetMultipleEnterpriseSyncMetaData",
"", {"keyword": "missionpackage"}, None, True).get_value("objectmetadata")
for i in range(0, len(output)):
updated_val = {}
output[i] = output[i].__dict__
Expand All @@ -78,20 +104,23 @@
updated_val["Hash"] = output[i]["hash"]
return_vals.append(updated_val)
del (output[i]['_sa_instance_state'])
#del (output[i]['CreatorUid'])
#del (output[i]['MIMEType'])
#del (output[i]['uid'])
# del (output[i]['CreatorUid'])
# del (output[i]['MIMEType'])
# del (output[i]['uid'])
print(return_vals)
return jsonify(json_list=return_vals), 200


@page.route('/DataPackageTable', methods=["DELETE"])
@auth.login_required()
def delete_DataPackageTable():
""" This function handles the DELETE request for the DataPackageTable route. It is used to delete a data package from the server.
"""
jsondata = json.loads(request.data)
Hashes = jsondata['DataPackages']
for hash in Hashes:
Hash = hash['hash']
print(Hash)
RestAPICommunicationController().make_request("DeleteEnterpriseSyncData", "", {"objecthash": Hash}, None, True)
return {"message":'success'}, 200

RestAPICommunicationController().make_request(
"DeleteEnterpriseSyncData", "", {"object_hash": Hash}, None, True)
return {"message": 'success'}, 200
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "FreeTAKServer"
version = "2.1"
version = "2.1.01"
description = "An open source server for the TAK family of applications."
authors = ["FreeTAKTeam <FreeTakTeam@gmail.com>"]
readme = "README.md"
Expand Down
7 changes: 7 additions & 0 deletions tests/test_components/misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,13 @@ def register_core_components(self):
),
)

# tests should inject the default action mapper instead of the async action mapper
self.configuration.set_value(
key="__class",
value=f"digitalpy.core.zmanager.impl.default_action_mapper.DefaultActionMapper",
section="ActionMapper",
)

super().register_components()

# register the internal components
Expand Down
18 changes: 13 additions & 5 deletions tests/test_components/test_cot_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,8 @@ def test_create_geo_object(mock_load):
# instnatiate request and response objects
request, response = instantiate_request_response("CreateGeoObject")

request.set_value("dictionary", {})

# mock the execute sub action method in the controller class
mock_controller_execute_sub_action(response)

Expand All @@ -418,7 +420,7 @@ def test_create_geo_object(mock_load):
facade.create_geo_object(**request.get_values())

# assert that the next action is GetRepeatedMessages thus resulting in no further actions being called
assert response.get_action() == "CreateNode"
assert response.get_action() == "publish"
# assert the message object_class_name is correct
assert_response_val('object_class_name', str, "Event", response)
# assert the configuration is of correct type
Expand All @@ -430,6 +432,8 @@ def test_create_geo_object_execute(mock_load):
# instnatiate request and response objects
request, response = instantiate_request_response("CreateGeoObject")

request.set_value("dictionary", {})

# mock the execute sub action method in the controller class
mock_controller_execute_sub_action(response)

Expand All @@ -443,7 +447,7 @@ def test_create_geo_object_execute(mock_load):
facade.execute("create_geo_object")

# assert that the next action is GetRepeatedMessages thus resulting in no further actions being called
assert response.get_action() == "CreateNode"
assert response.get_action() == "publish"
# assert the message object_class_name is correct
assert_response_val('object_class_name', str, "Event", response)
# assert the configuration is of correct type
Expand All @@ -453,6 +457,8 @@ def test_delete_geo_object():
# instnatiate request and response objects
request, response = instantiate_request_response("DeleteGeoObject")

request.set_value("dictionary", {})

# mock the execute sub action method in the controller class
mock_controller_execute_sub_action(response)

Expand All @@ -466,16 +472,18 @@ def test_delete_geo_object():
facade.delete_geo_object(**request.get_values())

# assert that the next action is GetRepeatedMessages thus resulting in no further actions being called
assert response.get_action() == "CreateNode"
assert response.get_action() == "publish"
# assert the message object_class_name is correct
assert_response_val('object_class_name', str, "Event", response)
# assert the configuration is of correct type
assert isinstance(response.get_value("configuration"), Configuration)

def test_delete_geo_object_execute():
# instnatiate request and response objects
# instnatiate request and response objects
request, response = instantiate_request_response("DeleteGeoObject")

request.set_value("dictionary", {})

# mock the execute sub action method in the controller class
mock_controller_execute_sub_action(response)

Expand All @@ -489,7 +497,7 @@ def test_delete_geo_object_execute():
facade.execute("delete_geo_object")

# assert that the next action is GetRepeatedMessages thus resulting in no further actions being called
assert response.get_action() == "CreateNode"
assert response.get_action() == "publish"
# assert the message object_class_name is correct
assert_response_val('object_class_name', str, "Event", response)
# assert the configuration is of correct type
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
from unittest.mock import MagicMock
from unittest.mock import MagicMock, patch
from FreeTAKServer.core.cot_management.cot_management_facade import CotManagement
from tests.test_components.misc import ComponentTest
from digitalpy.core.main.object_factory import ObjectFactory
from tests.test_components.test_cot_manager_component.test_cot_manager_general_controller_schema import TEST_MISSION_COT


def test_handle_default_cot():
@patch("FreeTAKServer.core.cot_management.controllers.cot_management_persistence_controller.CoTManagementPersistenceController.create_or_update_cot")
def test_handle_default_cot(create_or_update_cot_mock):
setup = ComponentTest(TEST_MISSION_COT, mock_sub_actions=False, include_base_components=True)

async_action_mapper_mock = MagicMock()
Expand Down
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
from unittest.mock import patch

from FreeTAKServer.core.enterprise_sync.enterprise_sync_facade import EnterpriseSync
from tests.test_components.misc import ComponentTest
from tests.test_components.test_cot_manager_component.test_cot_manager_schemas import (
TEST_CONNECTION_SCHEMA, TEST_CREATE_REPEATED_MESSAGE_SCHEMA,
TEST_DELETE_NON_EXISTENT_REPEATED_MESSAGE_SCHEMA,
TEST_DELETE_REPEATED_MESSAGE_SCHEMA, TEST_GET_REPEATED_MESSAGES_SCHEMA
)

def test_save_enterprise_sync_data():
""" test the save enterprise sync data method works as follows:
1. call save enterprise sync data from the enterprise sync facade
2. call save enterprise sync data from the enterprise_sync_general_controller
3. call convert_newlines from the enterprise_sync_format_sync_controller
4. call save_file from the enterprise_sync_filesystem_controler
"""
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from FreeTAKServer.components.extended.excheck.excheck_facade import Excheck
from tests.test_components.misc import ComponentTest
from tests.test_components.test_excheck_component.test_excheck_checklist_controller_schemas import TEST_START_CHECKLIST_SCHEMA
from tests.test_components.test_mission_component.mission_model_test_utils import create_cot
from tests.test_components.test_mission_component.mission_model_test_utils import create_mission_cot
from digitalpy.core.main.object_factory import ObjectFactory
from FreeTAKServer.core.configuration.MainConfig import MainConfig
import pathlib
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
from unittest.mock import patch

import pytest
from FreeTAKServer.components.extended.excheck.excheck_facade import Excheck
from tests.test_components.misc import ComponentTest
from tests.test_components.test_excheck_component.test_excheck_checklist_controller_schemas import TEST_START_CHECKLIST_SCHEMA
Expand All @@ -11,6 +13,7 @@

config = MainConfig.instance()

@pytest.mark.skip(reason="currently this test is too wide")
@patch("FreeTAKServer.core.enterprise_sync.controllers.enterprise_sync_database_controller.EnterpriseSyncDatabaseController.create_enterprise_sync_data_object")
def test_start_checklist(create_enterprise_sync_data_object_mock):
setup = ComponentTest(TEST_CREATE_TEMPLATE, mock_sub_actions=False, include_base_components=True, included_external_components=[pathlib.Path(MainConfigClass.MAINPATH, "component\\extended\\mission")])
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from unittest.mock import MagicMock
from FreeTAKServer.components.extended.mission.persistence.log import Log
from FreeTAKServer.components.extended.mission.persistence.mission import Mission as MissionDBObj
from FreeTAKServer.components.extended.mission.persistence.mission_change import MissionChange
Expand All @@ -8,7 +9,7 @@
from FreeTAKServer.core.util.time_utils import get_current_datetime

def create_test_mission():
mission = MissionDBObj()
mission = MagicMock(MissionDBObj)

mission.name = "test_mission"

Expand All @@ -25,7 +26,7 @@ def create_test_mission():
return mission

def create_enterprise_sync_metadata():
enterprise_sync_metadata = EnterpriseSyncDataObject()
enterprise_sync_metadata = MagicMock(EnterpriseSyncDataObject)

enterprise_sync_metadata.start_time = get_current_datetime()

Expand Down Expand Up @@ -54,7 +55,7 @@ def create_enterprise_sync_metadata():
return enterprise_sync_metadata

def add_test_mission_content(mission: MissionDBObj):
mission_content = MissionContent()
mission_content = MagicMock(MissionContent)

mission_content.PrimaryKey = "test_mission_content_id"

Expand Down Expand Up @@ -106,7 +107,7 @@ def create_log():
return log

def add_log_to_mission(mission: MissionDBObj, log: Log):
mission_log = MissionLog()
mission_log = MagicMock(MissionLog)

mission_log.mission = mission

Expand All @@ -116,8 +117,8 @@ def add_log_to_mission(mission: MissionDBObj, log: Log):

log.missions.append(mission_log)

def create_cot():
cot = MissionCoT()
def create_mission_cot():
cot = MagicMock(MissionCoT)

cot.callsign = "test_callsign"

Expand All @@ -135,4 +136,7 @@ def create_cot():

cot.create_time = get_current_datetime()

return cot
return cot

def create_event_db():

Loading
Loading