def __init__(self, aws_service_instance): self._aws_service = aws_service_instance self._book_dao = BookDatabaseService() self._file_name = None self._file_obj = None self._file_stream = None self._file_extension = None self._stream_processor = io self._privacy_scope = None self._user_id = None self._book = None self._repo_key = None
def restore_book(book_id, owner, is_admin_request: bool) -> list: validate = validate_book_id(book_id) if validate.get('error'): return validate.get('response') verify_status = verify_delete(book_id) if not verify_status: return [{'error': 'Book is already active.'}, 409] book = BookDatabaseService.find_active_inactive_book_by_id(book_id) if is_admin_request or book.created_by == owner.get('id'): response = BookDatabaseService.restore_inactive_book( book_id, owner.get('id')) return [response, 200] return [{ 'error': 'Books can be restored only by their respective owners.' }, 403]
def process_file_for_upload(self, _user_id: str, _book_id: str, f_obj: FileStorage, _privacy_scope: str): print( f"INFO: user: {_user_id} for book: {_book_id} for file: {f_obj} and privacy: {_privacy_scope}" ) self._file_extension = self.verify_file_extension(f_obj.filename) if isinstance(self._file_extension, list): return self._file_extension self._file_stream = f_obj.read() _file_size_in_mb = BookUtils.convert_bytes_to_mb(self._get_file_size()) if _file_size_in_mb > BookEnums.MAX_FILE_SIZE_ALLOWED_IN_MB_FOR_DOC.value: return [ErrorEnums.MAX_SIZE_EXCEED_ERROR_FOR_DOC.value, 413] self._book = BookDatabaseService.find_active_book_by_id(_book_id) if not self._book: return [ErrorEnums.NO_BOOK_FOUND_ERROR.value, 404] if self._book.created_by != _user_id: return [ErrorEnums.BOOK_OWNER_NOT_MATCH_ERROR.value, 404] if not self._book: return [ErrorEnums.NO_BOOK_FOUND_ERROR.value, 404] if not self._book.is_active: return [ErrorEnums.INACTIVE_BOOK_ERROR.value, 400] self._privacy_scope = _privacy_scope.upper() if self._privacy_scope not in BookEnums.PRIVACY_SCOPES_FOR_DOCUMENT.value: return [{'error': 'Please provide a valid privacy type.'}, 400] self._user_id = _user_id self._file_obj = self.bytes_to_obj() self._file_name = self.get_secure_filename(f_obj.filename, self._user_id, self._file_extension) self._repo_key = self.make_repo_key() _upload_response = self.upload_file() response = self.update_file_record(_upload_response) if isinstance(response, list): return response return [{'response': {'updatedBookDetails': book_dto(response)}}, 200]
def get_all_books(): all_books = BookDatabaseService.find_all_active_books() response = [] if not all_books: return {'error': 'No active books found in the repository.'}, 404 for book in all_books: response.append(public_book_response_dto(book)) return response, 200
def delete_book(book_id, user, is_admin_request: bool) -> list: try: valid_book = validate_for_deletion(book_id) if valid_book.get('error'): return valid_book.get('response') book = BookDatabaseService.find_active_inactive_book_by_id(book_id) if is_admin_request or book.created_by == user.get('id'): response = BookDatabaseService.delete_book_by_id( book_id, user.get('id')) verify_deleted_book = verify_delete(book_id) if verify_deleted_book: return [response, 200] return [{'error': 'There was some error.'}, 500] return [{ 'error': 'Book can only be deleted by it\'s respective owner.' }, 403] except Exception as e: return [{'error': e.args}, 400]
def create_new_book(new_book, created_by_user): validated_existence = check_if_book_already_exists(new_book) code_check = check_if_bar_code_exists(new_book) if code_check['error']: return code_check['response'][0], code_check['response'][1] if validated_existence: return { 'error': 'Book with the same name already exists for this author.' }, 409 return BookDatabaseService.create_new_book(new_book, created_by_user)
def check_if_bar_code_exists(book): code_book = BookDatabaseService.get_by_barcode(book['barcode']) if code_book: return { 'response': [{ 'error': 'Another book with the same barcode already exists. Please use a fresh barcode.' }, 409], 'error': True } return {'error': False}
def update_book(book: dict, updated_by: dict): try: print( "DEBUG: Book update service request received for Book {} and user {}." .format(book, updated_by)) c_book = validate_book_id(book.get('id')) if c_book.get('error'): return c_book.get('response')[0], c_book.get('response')[1] elif str(c_book.get('book').created_by) != updated_by.get('id'): print("INFO: Found book for other owner - {}.".format( c_book.get('book'))) return ErrorEnums.BOOK_OWNER_NOT_MATCH_ERROR.value, 403 response = BookDatabaseService.update_book_by_id(book, updated_by) return response except Exception as e: return {'error': e.args}, 500
def validate_book_id(book_id): if len(book_id) != 24: return { 'response': [{ 'error': 'Invalid length exception for book id = {}.'.format(book_id) }, 400], 'error': True } book = BookDatabaseService.find_active_inactive_book_by_id(book_id) if not book: return { 'response': [{ 'error': 'No book exists for id {}'.format(book_id) }, 400], 'error': True } return {'error': False, 'book': book}
def get_user_favourite_books(user): book_service = BookDatabaseService() book_bucket = list() for book in user.fav_books: book_bucket.append((book_service.find_active_book_by_id(book.id))) return book_bucket
def get_active_book_by_id(self, book_id): valid_book = validate_book_id(book_id) if valid_book.get('error'): return valid_book.get('response') self.book = BookDatabaseService.find_active_book_by_id(book_id) return self.book
def get_books_for_user(user): books = BookDatabaseService.find_by_created_by_user(user.get('id')) if books and len(books) > 0: return {'response': books}, 200 return {'error': 'No books have been added yet.'}, 404
def check_if_book_already_exists(book): c_book = BookDatabaseService.find_by_name_author_genre(book) if c_book: return True return False
def verify_delete(book_id): fresh_book = BookDatabaseService.find_active_inactive_book_by_id(book_id) if not fresh_book.is_active: return True return False
class DocumentFileServiceBaseModelImpl(FileServiceBaseModel): def __init__(self, aws_service_instance): self._aws_service = aws_service_instance self._book_dao = BookDatabaseService() self._file_name = None self._file_obj = None self._file_stream = None self._file_extension = None self._stream_processor = io self._privacy_scope = None self._user_id = None self._book = None self._repo_key = None def upload_file(self): return self._aws_service.upload_file_to_s3( repoKey=self._repo_key, fileName=self._file_name, fileContent=self._file_obj, fileContentType=self.get_mime_type(self._file_name), contentACL=BookEnums.PRIVACY_SCOPES_FOR_DOCUMENT.value.get( self._privacy_scope)) def verify_file_extension(self, f_name: str): _file_extension = f_name.rsplit('.')[1] if _file_extension.lower() not in BookEnums.ALLOWED_EXTENSIONS.value: return [{ 'error': 'Please upload a file with valid file extension.' }, 403] return _file_extension def process_file_for_upload(self, _user_id: str, _book_id: str, f_obj: FileStorage, _privacy_scope: str): print( f"INFO: user: {_user_id} for book: {_book_id} for file: {f_obj} and privacy: {_privacy_scope}" ) self._file_extension = self.verify_file_extension(f_obj.filename) if isinstance(self._file_extension, list): return self._file_extension self._file_stream = f_obj.read() _file_size_in_mb = BookUtils.convert_bytes_to_mb(self._get_file_size()) if _file_size_in_mb > BookEnums.MAX_FILE_SIZE_ALLOWED_IN_MB_FOR_DOC.value: return [ErrorEnums.MAX_SIZE_EXCEED_ERROR_FOR_DOC.value, 413] self._book = BookDatabaseService.find_active_book_by_id(_book_id) if not self._book: return [ErrorEnums.NO_BOOK_FOUND_ERROR.value, 404] if self._book.created_by != _user_id: return [ErrorEnums.BOOK_OWNER_NOT_MATCH_ERROR.value, 404] if not self._book: return [ErrorEnums.NO_BOOK_FOUND_ERROR.value, 404] if not self._book.is_active: return [ErrorEnums.INACTIVE_BOOK_ERROR.value, 400] self._privacy_scope = _privacy_scope.upper() if self._privacy_scope not in BookEnums.PRIVACY_SCOPES_FOR_DOCUMENT.value: return [{'error': 'Please provide a valid privacy type.'}, 400] self._user_id = _user_id self._file_obj = self.bytes_to_obj() self._file_name = self.get_secure_filename(f_obj.filename, self._user_id, self._file_extension) self._repo_key = self.make_repo_key() _upload_response = self.upload_file() response = self.update_file_record(_upload_response) if isinstance(response, list): return response return [{'response': {'updatedBookDetails': book_dto(response)}}, 200] def update_file_record(self, response): e_tag = response.get('ETag')[1:-1] if not e_tag: print( "{}: DEBUG: Response received is - {}, for file {} and book id {}." .format(str(datetime.datetime.now()), str(response), self._file_name, self._book)) return [{'error': 'There was some error.'}, 500] response = self._book_dao.update_document_details_for_book( self._book, self._repo_key, e_tag, self._file_name, self._privacy_scope, self._user_id) return response def _get_file_size(self): return len(self._file_stream) def bytes_to_obj(self): return self._stream_processor.BytesIO(self._file_stream) def make_repo_key(self): return SecurityUtils.calculate_md5(self._user_id) def download_file(self, book_id): print("INFO: Received download request for book id {}".format(book_id)) valid_book = bookCreateUpdateService.validate_book_id(book_id) if valid_book.get('error'): return valid_book.get('response') book = book_dto(valid_book.get('book')) if not book.get('is_active'): return [ErrorEnums.INACTIVE_BOOK_ERROR.value, 400] if book.get('privacy_scope') == BookEnums.PRIVATE.value: return [ErrorEnums.PROTECTED_BOOK_ACCESS_ERROR.value, 403] if not book.get('book_repo'): return [ErrorEnums.NO_BOOK_FOUND_ERROR.value, 404] response = self._aws_service.get_file_from_s3( repoKey=book.get('book_repo'), fileName=book.get('document_name'), eTag=book.get('entity_tag')) response.setdefault('file_name', book.get('document_name')) print(f"DEBUG: Final response for file download: {response}") return response