mirror of
https://github.com/fuckpiracyshield/service.git
synced 2024-05-20 14:06:18 +02:00
142 lines
3.8 KiB
Python
142 lines
3.8 KiB
Python
from __future__ import annotations
|
|
|
|
from piracyshield_service.base import BaseService
|
|
|
|
from piracyshield_component.environment import Environment
|
|
from piracyshield_component.config import Config
|
|
from piracyshield_component.security.identifier import Identifier
|
|
from piracyshield_component.exception import ApplicationException
|
|
|
|
from piracyshield_data_storage.cache.storage import CacheStorage
|
|
|
|
from piracyshield_service.importer.errors import ImporterErrorCode, ImporterErrorMessage
|
|
|
|
import os
|
|
|
|
class ImporterSaveFileService(BaseService):
|
|
|
|
"""
|
|
Reads and writes the content into the cache.
|
|
"""
|
|
|
|
identifier = None
|
|
|
|
data_storage_cache = None
|
|
|
|
application_archive_config = None
|
|
|
|
def __init__(self):
|
|
"""
|
|
Inizialize logger and required modules.
|
|
"""
|
|
|
|
super().__init__()
|
|
|
|
self._prepare_configs()
|
|
|
|
self._prepare_modules()
|
|
|
|
def execute(self, filename: str, content: bytes) -> str | Exception:
|
|
"""
|
|
:param filename: the name of the file.
|
|
:param content: the file's content.
|
|
:return: the name of the file with a unique identifier.
|
|
"""
|
|
|
|
extension = self._get_extension(filename)
|
|
|
|
if self._has_supported_extension(extension) == False:
|
|
raise ApplicationException(ImporterErrorCode.EXTENSION_NOT_SUPPORTED, ImporterErrorMessage.EXTENSION_NOT_SUPPORTED)
|
|
|
|
# generate a unique name for the file
|
|
unique_filename = self._generate_unique_name(filename)
|
|
|
|
try:
|
|
self.data_storage_cache.write(unique_filename, content)
|
|
|
|
return unique_filename
|
|
|
|
except OSError as e:
|
|
self.logger.error(f'Could not save the file: {e}')
|
|
|
|
raise ApplicationException(ImporterErrorCode.GENERIC, ImporterErrorMessage.GENERIC)
|
|
|
|
def _generate_identifier(self, filename: str) -> str:
|
|
identifier = self.identifier.generate_short_unsafe()
|
|
|
|
return f'{identifier}-{filename}'
|
|
|
|
def _get_extension(self, filename: str) -> str:
|
|
"""
|
|
Extracts the extension from the filename.
|
|
|
|
:param filename: the name of the file.
|
|
:return: the extension of the file.
|
|
"""
|
|
|
|
_, extension = os.path.splitext(filename)
|
|
|
|
return extension
|
|
|
|
def _has_supported_extension(self, extension: str) -> bool:
|
|
"""
|
|
Checks wether the extension is supported.
|
|
|
|
:param extension: the extension of the file.
|
|
:return: true if supported.
|
|
"""
|
|
|
|
return extension.lower() in self.application_archive_config.get('supported_extensions')
|
|
|
|
def _generate_unique_name(self, filename: str) -> str:
|
|
"""
|
|
Attempts to generate a unique name string for the file that will be put in the cache.
|
|
|
|
:param filename: the name of the file.
|
|
:return: the newly generated name of the file.
|
|
"""
|
|
|
|
# TODO: just use a timestamp.
|
|
|
|
retries = 5
|
|
current_tries = 0
|
|
|
|
while (True):
|
|
# exceeded maximum retries
|
|
if current_tries >= retries:
|
|
raise ApplicationException(ImporterErrorCode.GENERIC, ImporterErrorMessage.GENERIC)
|
|
|
|
filename = self._generate_identifier(filename)
|
|
|
|
# check if the file already exists
|
|
if not self.data_storage_cache.exists(filename):
|
|
break
|
|
|
|
current_tries += 1
|
|
|
|
return filename
|
|
|
|
def _schedule_task(self):
|
|
pass
|
|
|
|
def _validate_parameters(self):
|
|
# TODO: should at least validate the name.
|
|
|
|
pass
|
|
|
|
def _prepare_configs(self) -> None:
|
|
"""
|
|
Loads the configs.
|
|
"""
|
|
|
|
self.application_archive_config = Config('application').get('archive')
|
|
|
|
def _prepare_modules(self) -> None:
|
|
"""
|
|
Initialize and set the instances.
|
|
"""
|
|
|
|
self.data_storage_cache = CacheStorage()
|
|
|
|
self.identifier = Identifier()
|