mirror of
https://github.com/sartography/cr-connect-workflow.git
synced 2025-02-24 13:48:30 +00:00
143 lines
6.1 KiB
Python
143 lines
6.1 KiB
Python
import datetime
|
|
import hashlib
|
|
import os
|
|
|
|
from crc import app, session
|
|
from crc.api.common import ApiError
|
|
from crc.models.file import FileModel, FileModelSchema, FileDataModel
|
|
from crc.services.file_service import FileService, FileType
|
|
from crc.services.spec_file_service import SpecFileService
|
|
|
|
from uuid import UUID
|
|
from sqlalchemy.exc import IntegrityError
|
|
|
|
|
|
class ReferenceFileService(object):
|
|
|
|
@staticmethod
|
|
def get_reference_file_path(file_name):
|
|
# Fixme: The services should not talk to each other.
|
|
sync_file_root = SpecFileService().root_path()
|
|
file_path = os.path.join(sync_file_root, 'Reference', file_name)
|
|
return file_path
|
|
|
|
@staticmethod
|
|
def add_reference_file(name, content_type, binary_data):
|
|
"""Create a file with the given name, but not associated with a spec or workflow.
|
|
Only one file with the given reference name can exist."""
|
|
file_model = session.query(FileModel). \
|
|
filter(FileModel.name == name).first()
|
|
# fixme: no need for this is_reference filter.
|
|
# filter(FileModel.is_reference == True). \
|
|
if not file_model:
|
|
file_extension = FileService.get_extension(name)
|
|
file_type = FileType[file_extension].value
|
|
|
|
file_model = FileModel(
|
|
name=name,
|
|
# is_reference=True,
|
|
type=file_type,
|
|
content_type=content_type
|
|
)
|
|
session.add(file_model)
|
|
session.commit()
|
|
else:
|
|
raise ApiError(code='file_already_exists',
|
|
message=f"The reference file {name} already exists.")
|
|
return ReferenceFileService().update_reference_file(file_model, binary_data)
|
|
|
|
def update_reference_file(self, file_model, binary_data):
|
|
self.write_reference_file_to_system(file_model, binary_data)
|
|
print('update_reference_file')
|
|
return file_model
|
|
|
|
# TODO: need a test for this?
|
|
def update_reference_file_info(self, old_file_model, body):
|
|
file_data = self.get_reference_file_data(old_file_model.name)
|
|
|
|
old_file_path = self.get_reference_file_path(old_file_model.name)
|
|
self.delete_reference_file_data(old_file_path)
|
|
self.delete_reference_file_info(old_file_path)
|
|
|
|
new_file_model = FileModelSchema().load(body, session=session)
|
|
new_file_path = self.get_reference_file_path(new_file_model.name)
|
|
self.write_reference_file_data_to_system(new_file_path, file_data.data)
|
|
self.write_reference_file_info_to_system(new_file_path, new_file_model)
|
|
return new_file_model
|
|
|
|
def get_reference_file_data(self, file_name):
|
|
file_model = session.query(FileModel).filter(FileModel.name == file_name).filter(
|
|
FileModel.is_reference == True).first()
|
|
if file_model is not None:
|
|
file_path = self.get_reference_file_path(file_model.name)
|
|
if os.path.exists(file_path):
|
|
mtime = os.path.getmtime(file_path)
|
|
with open(file_path, 'rb') as f_open:
|
|
reference_file_data = f_open.read()
|
|
size = len(reference_file_data)
|
|
md5_checksum = UUID(hashlib.md5(reference_file_data).hexdigest())
|
|
|
|
reference_file_data_model = FileDataModel(data=reference_file_data,
|
|
md5_hash=md5_checksum,
|
|
size=size,
|
|
date_created=datetime.datetime.fromtimestamp(mtime),
|
|
file_model_id=file_model.id
|
|
)
|
|
return reference_file_data_model
|
|
else:
|
|
raise ApiError('file_not_found',
|
|
f"There was no file in the location: {file_path}")
|
|
else:
|
|
raise ApiError("file_not_found", "There is no reference file with the name '%s'" % file_name)
|
|
|
|
def write_reference_file_to_system(self, file_model, file_data):
|
|
file_path = self.write_reference_file_data_to_system(file_model.name, file_data)
|
|
self.write_reference_file_info_to_system(file_path, file_model)
|
|
|
|
def write_reference_file_data_to_system(self, file_name, file_data):
|
|
file_path = self.get_reference_file_path(file_name)
|
|
os.makedirs(os.path.dirname(file_path), exist_ok=True)
|
|
with open(file_path, 'wb') as f_handle:
|
|
f_handle.write(file_data)
|
|
# SpecFileService.write_file_data_to_system(file_path, file_data)
|
|
return file_path
|
|
|
|
|
|
@staticmethod
|
|
def write_reference_file_info_to_system(file_path, file_model):
|
|
pass
|
|
# fixme: correct this stuff.
|
|
# SpecFileService.write_file_info_to_system(file_path, file_model)
|
|
|
|
@staticmethod
|
|
def get_reference_files():
|
|
reference_files = session.query(FileModel). \
|
|
filter_by(is_reference=True). \
|
|
filter(FileModel.archived == False). \
|
|
all()
|
|
return reference_files
|
|
|
|
def delete_reference_file_data(self, file_name):
|
|
file_path = self.get_reference_file_path(file_name)
|
|
json_file_path = f'{file_path}.json'
|
|
os.remove(file_path)
|
|
os.remove(json_file_path)
|
|
|
|
@staticmethod
|
|
def delete_reference_file_info(file_name):
|
|
file_model = session.query(FileModel).filter(FileModel.name==file_name).first()
|
|
try:
|
|
session.delete(file_model)
|
|
session.commit()
|
|
except IntegrityError as ie:
|
|
session.rollback()
|
|
file_model = session.query(FileModel).filter(FileModel.name==file_name).first()
|
|
file_model.archived = True
|
|
session.commit()
|
|
app.logger.info("Failed to delete file: %s, so archiving it instead. Due to %s" % (file_name, str(ie)))
|
|
|
|
def delete_reference_file(self, file_name):
|
|
"""This should remove the record in the file table, and both files on the filesystem."""
|
|
self.delete_reference_file_data(file_name)
|
|
self.delete_reference_file_info(file_name)
|