Skip to content

Commit

Permalink
Merge pull request #659 from FreeTAKTeam/657-datapackages-endpoint-bugs
Browse files Browse the repository at this point in the history
657 datapackages endpoint bugs
  • Loading branch information
naman108 authored Dec 21, 2023
2 parents 71938f6 + c00248d commit 1393a37
Show file tree
Hide file tree
Showing 17 changed files with 146 additions and 59 deletions.
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


@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 @@ def put_DataPackageTable():
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 @@ def get_DataPackageTable():
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
"""
Empty file.
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

0 comments on commit 1393a37

Please sign in to comment.