diff --git a/3 - PB/MVP/src/backend/adapter/_in/web/get_document_content_controller.py b/3 - PB/MVP/src/backend/adapter/_in/web/get_document_content_controller.py index c5b42440..4b5dfa68 100644 --- a/3 - PB/MVP/src/backend/adapter/_in/web/get_document_content_controller.py +++ b/3 - PB/MVP/src/backend/adapter/_in/web/get_document_content_controller.py @@ -20,4 +20,4 @@ def getDocumentContent(self, documentId: str) -> Document: Document: the Document containg the relative content. """ document = self.useCase.getDocumentsContent([DocumentId(documentId)]) - return document[0] + return document[0] if document is not None else None diff --git a/3 - PB/MVP/src/backend/adapter/out/ask_chatbot/ask_chatbot_langchain.py b/3 - PB/MVP/src/backend/adapter/out/ask_chatbot/ask_chatbot_langchain.py index 93946264..2784eb5b 100644 --- a/3 - PB/MVP/src/backend/adapter/out/ask_chatbot/ask_chatbot_langchain.py +++ b/3 - PB/MVP/src/backend/adapter/out/ask_chatbot/ask_chatbot_langchain.py @@ -1,5 +1,6 @@ -from langchain.chains import ConversationalRetrievalChain from langchain.chains.base import Chain +from langchain.memory import ConversationBufferWindowMemory +from langchain_core.messages import get_buffer_string from domain.chat.message_response import MessageResponse from domain.chat.message import Message @@ -22,18 +23,22 @@ def __init__(self, chain: Chain, chatHistoryManager: ChatHistoryManager): def askChatbot(self, message: Message, chatId: ChatId) -> MessageResponse: if chatId is not None: - self.chain.memory = self.chatHistoryManager.getChatHistory(chatId) - print(self.chatHistoryManager.getChatHistory(chatId.id).messages, flush=True) - answer = self.chain.invoke({"question": message.content}) + chatHistory = self.chatHistoryManager.getChatHistory(chatId.id) + if len(chatHistory.messages) == 0: + return MessageResponse(status=False, messageResponse=None, chatId=chatId) + else: + #TODO: Controllare se 6 messaggi sono sufficienti + answer = self.chain.invoke({"question": message.content, "chat_history": get_buffer_string(chatHistory.messages[:-6])}) else: - answer = self.chain.invoke({"question": message.content, "chat_history": ""}) + answer = self.chain.invoke({"question": message.content, "chat_history": []}) return MessageResponse( - True, - Message( + status=True, + messageResponse=Message( answer["answer"], datetime.now(timezone.utc), list(set(DocumentId(relevantDocumentId.metadata.get("source")) for relevantDocumentId in answer["source_documents"])), MessageSender.CHATBOT - ), chatId + ), + chatId=chatId ) \ No newline at end of file diff --git a/3 - PB/MVP/src/backend/adapter/out/ask_chatbot/postgres_persist_chat.py b/3 - PB/MVP/src/backend/adapter/out/ask_chatbot/postgres_persist_chat.py index f289b823..b24ce1f5 100644 --- a/3 - PB/MVP/src/backend/adapter/out/ask_chatbot/postgres_persist_chat.py +++ b/3 - PB/MVP/src/backend/adapter/out/ask_chatbot/postgres_persist_chat.py @@ -13,8 +13,7 @@ def __init__(self, postgresChatORM: PostgresChatORM): self.postgresChatORM = postgresChatORM def persistChat(self, messages: List[Message], chatId: ChatId) -> ChatOperationResponse: - postgresChatOperationResponse = self.postgresChatORM.persistChat([self.toPostgresMessageFrom(message) for message in messages], chatId) - print(postgresChatOperationResponse, flush=True) + postgresChatOperationResponse = self.postgresChatORM.persistChat([self.toPostgresMessageFrom(message) for message in messages], chatId.id if chatId else None) return postgresChatOperationResponse.toChatOperationResponse() def toPostgresMessageFrom(self, message: Message) -> PostgresMessage: diff --git a/3 - PB/MVP/src/backend/adapter/out/get_chat_messages/get_chat_messages_postgres.py b/3 - PB/MVP/src/backend/adapter/out/get_chat_messages/get_chat_messages_postgres.py index b79a43dd..49ce3c7a 100644 --- a/3 - PB/MVP/src/backend/adapter/out/get_chat_messages/get_chat_messages_postgres.py +++ b/3 - PB/MVP/src/backend/adapter/out/get_chat_messages/get_chat_messages_postgres.py @@ -8,7 +8,6 @@ class GetChatMessagesPostgres(GetChatMessagesPort): def __init__(self, postgresORM: PostgresChatORM): self.postgresORM = postgresORM - def getChatMessages(self, chatId:ChatId)->Chat: + def getChatMessages(self, chatId: ChatId) -> Chat: chatMessages = self.postgresORM.getChatMessages(chatId.id) - chat = chatMessages.toChat() - return chat \ No newline at end of file + return chatMessages.toChat() if chatMessages is not None else None \ No newline at end of file diff --git a/3 - PB/MVP/src/backend/adapter/out/get_configuration/get_configuration_postgres.py b/3 - PB/MVP/src/backend/adapter/out/get_configuration/get_configuration_postgres.py index 5c0fe473..ad9aac85 100644 --- a/3 - PB/MVP/src/backend/adapter/out/get_configuration/get_configuration_postgres.py +++ b/3 - PB/MVP/src/backend/adapter/out/get_configuration/get_configuration_postgres.py @@ -10,9 +10,8 @@ def __init__(self, postgresConfigurationORM: PostgresConfigurationORM): def getConfiguration(self) -> Configuration: userId = os.environ.get('USER_ID') - - postgresConfiguration = self.postgresConfigurationORM.getConfiguration(userId=userId) - - if postgresConfiguration is None: - return None - return postgresConfiguration.toConfiguration() \ No newline at end of file + try: + postgresConfiguration = self.postgresConfigurationORM.getConfiguration(userId=userId) + return postgresConfiguration.toConfiguration() + except Exception as e: + return None \ No newline at end of file diff --git a/3 - PB/MVP/src/backend/adapter/out/get_documents/get_documents_content_awss3.py b/3 - PB/MVP/src/backend/adapter/out/get_documents/get_documents_content_awss3.py index ca164860..f788d27c 100644 --- a/3 - PB/MVP/src/backend/adapter/out/get_documents/get_documents_content_awss3.py +++ b/3 - PB/MVP/src/backend/adapter/out/get_documents/get_documents_content_awss3.py @@ -1,10 +1,7 @@ import os from typing import List -from domain.document.document_content import DocumentContent -from domain.document.document_filter import DocumentFilter from domain.document.document_id import DocumentId -from domain.document.document_metadata import DocumentMetadata, DocumentType from domain.document.plain_document import PlainDocument from application.port.out.get_documents_content_port import GetDocumentsContentPort from adapter.out.persistence.aws.AWS_manager import AWSS3Manager @@ -21,15 +18,6 @@ def getDocumentsContent(self, documentIds: List[DocumentId]) -> List[PlainDocume retrievedDocument = self.awsS3Manager.getDocumentContent(documentId.id) documents.append(retrievedDocument) - plainDocuments = [ - PlainDocument( - DocumentMetadata( - id=DocumentId(document.id), - type=DocumentType.PDF if document.type.split('.')[1].upper() == "PDF" else DocumentType.DOCX, - size=document.size, - uploadTime=document.uploadTime - ), - DocumentContent(document.content) - ) if document is not None else None for document in documents] + plainDocuments = [document.toPlainDocument() if document is not None else None for document in documents] return plainDocuments diff --git a/3 - PB/MVP/src/backend/adapter/out/get_documents/get_documents_list_awss3.py b/3 - PB/MVP/src/backend/adapter/out/get_documents/get_documents_list_awss3.py index ecfffe60..6e1ac3e3 100644 --- a/3 - PB/MVP/src/backend/adapter/out/get_documents/get_documents_list_awss3.py +++ b/3 - PB/MVP/src/backend/adapter/out/get_documents/get_documents_list_awss3.py @@ -3,9 +3,7 @@ from adapter.out.persistence.aws.AWS_manager import AWSS3Manager from domain.document.document_filter import DocumentFilter -from domain.document.document_id import DocumentId -from domain.document.document_metadata import DocumentMetadata, DocumentType -from adapter.out.persistence.aws.AWS_document_metadata import AWSDocumentMetadata +from domain.document.document_metadata import DocumentMetadata from application.port.out.get_documents_metadata_port import GetDocumentsMetadataPort @@ -14,9 +12,8 @@ def __init__(self, awsS3Manager: AWSS3Manager): self.awsS3Manager = awsS3Manager def getDocumentsMetadata(self, documentFilter: DocumentFilter) -> List[DocumentMetadata]: - listOfDocumentsMetadata = [] - documentsMetadatas = self.awsS3Manager.getDocumentsMetadata(documentFilter.searchFilter) - for documentMetadata in documentsMetadatas: - documentM = documentMetadata.toDocumentMetadataFrom() - listOfDocumentsMetadata.append(documentM) - return listOfDocumentsMetadata \ No newline at end of file + documentsMetadatas = [] + documentsMetadata = self.awsS3Manager.getDocumentsMetadata(documentFilter.searchFilter) + for documentMetadata in documentsMetadata: + documentsMetadata.append(documentMetadata.toDocumentMetadataFrom()) + return documentsMetadatas \ No newline at end of file diff --git a/3 - PB/MVP/src/backend/adapter/out/persistence/aws/AWS_document.py b/3 - PB/MVP/src/backend/adapter/out/persistence/aws/AWS_document.py index 2900802b..1a423db4 100644 --- a/3 - PB/MVP/src/backend/adapter/out/persistence/aws/AWS_document.py +++ b/3 - PB/MVP/src/backend/adapter/out/persistence/aws/AWS_document.py @@ -1,5 +1,11 @@ from datetime import datetime from dataclasses import dataclass + +from domain.document.document_id import DocumentId +from domain.document.document_metadata import DocumentMetadata, DocumentType +from domain.document.document_content import DocumentContent +from domain.document.plain_document import PlainDocument + """ This class is used to represent a document that is stored in the AWS S3 bucket. """ @@ -10,5 +16,15 @@ class AWSDocument: type: str size: float uploadTime: datetime - + + def toPlainDocument(self) -> PlainDocument: + return PlainDocument( + metadata=DocumentMetadata( + id=DocumentId(self.id), + type=DocumentType.PDF if self.type == "PDF" else DocumentType.DOCX, + size=self.size, + uploadTime=self.uploadTime + ), + content=DocumentContent(self.content) + ) diff --git a/3 - PB/MVP/src/backend/adapter/out/persistence/aws/AWS_document_metadata.py b/3 - PB/MVP/src/backend/adapter/out/persistence/aws/AWS_document_metadata.py index ab73cc7d..31778c8b 100644 --- a/3 - PB/MVP/src/backend/adapter/out/persistence/aws/AWS_document_metadata.py +++ b/3 - PB/MVP/src/backend/adapter/out/persistence/aws/AWS_document_metadata.py @@ -12,10 +12,11 @@ class AWSDocumentMetadata: id: str size: float + type: str uploadTime: datetime def toDocumentMetadataFrom(self) -> DocumentMetadata: return DocumentMetadata(id=DocumentId(self.id), - type=DocumentType.PDF if os.path.splitext(self.id)[1].upper() == ".PDF" else DocumentType.DOCX, + type=DocumentType.PDF if self.type == "PDF" else DocumentType.DOCX, size=self.size, uploadTime=self.uploadTime) \ No newline at end of file diff --git a/3 - PB/MVP/src/backend/adapter/out/persistence/aws/AWS_document_operation_response.py b/3 - PB/MVP/src/backend/adapter/out/persistence/aws/AWS_document_operation_response.py index 532210cd..93a7c783 100644 --- a/3 - PB/MVP/src/backend/adapter/out/persistence/aws/AWS_document_operation_response.py +++ b/3 - PB/MVP/src/backend/adapter/out/persistence/aws/AWS_document_operation_response.py @@ -12,4 +12,4 @@ class AWSDocumentOperationResponse: message: str def toDocumentOperationResponse(self) -> DocumentOperationResponse: - return DocumentOperationResponse(DocumentId(self.documentId), self.status, self.message) + return DocumentOperationResponse(DocumentId(self.documentId), self.status, self.message) diff --git a/3 - PB/MVP/src/backend/adapter/out/persistence/aws/AWS_manager.py b/3 - PB/MVP/src/backend/adapter/out/persistence/aws/AWS_manager.py index 02dd3f48..1e941f6a 100644 --- a/3 - PB/MVP/src/backend/adapter/out/persistence/aws/AWS_manager.py +++ b/3 - PB/MVP/src/backend/adapter/out/persistence/aws/AWS_manager.py @@ -1,12 +1,11 @@ -import os from typing import List import boto3 from adapter.out.persistence.aws.AWS_document import AWSDocument from adapter.out.persistence.aws.AWS_document_operation_response import AWSDocumentOperationResponse from adapter.out.persistence.aws.AWS_document_metadata import AWSDocumentMetadata -from domain.document.document_id import DocumentId -from domain.document.document_metadata import DocumentMetadata, DocumentType + +from botocore.exceptions import ClientError """ This class is responsible for managing the AWS S3 bucket. @@ -47,31 +46,45 @@ def getDocumentById(self, documentId: str) -> AWSDocument: type = aws.get('ContentType') size = aws.get('ContentLength') uploadTime = aws.get('LastModified') - except: + except Exception as e: return None return AWSDocument( - id, - content, - type, - size, - uploadTime + id=id, + content=content, + type=type, + size=size, + uploadTime=uploadTime ) def uploadDocuments(self, awsDocuments: List[AWSDocument], forceUpload: bool) -> List[AWSDocumentOperationResponse]: AWSDocumentOperationResponses = [] - for document in awsDocuments: - try: - if not forceUpload: - self.s3.head_object(Bucket=self.awsBucketName, Key=document.id) - AWSDocumentOperationResponses.append(AWSDocumentOperationResponse(document.id, False, "Il documento e' gia' presente nel sistema.")) - else: - self.s3.put_object(Bucket=self.awsBucketName, Key=document.id, Body=document.content, ContentType=document.type) - AWSDocumentOperationResponses.append(AWSDocumentOperationResponse(document.id, True, "Caricamento del documento avvenuto con successo.")) - except Exception as e: - AWSDocumentOperationResponses.append(AWSDocumentOperationResponse(document.id, False, f"Errore durante il caricamento del documento: {e}")) - continue - + if not forceUpload: + for awsDocument in awsDocuments: + try: + self.s3.head_object(Bucket=self.awsBucketName, Key=awsDocument.id) + # The document is already present in the system, so it cannot be uploaded. + AWSDocumentOperationResponses.append(AWSDocumentOperationResponse(awsDocument.id, False, "Il documento è già presente nel sistema.")) + except Exception as e: + # The document is not present in the system, so it can be uploaded. + try: + self.s3.put_object(Bucket=self.awsBucketName, Key=awsDocument.id, Body=awsDocument.content, ContentType=awsDocument.type) + AWSDocumentOperationResponses.append(AWSDocumentOperationResponse(awsDocument.id, True, "Caricamento del documento avvenuto con successo.")) + except Exception as e: + # An error occurred during the put_object operation. + AWSDocumentOperationResponses.append(AWSDocumentOperationResponse(awsDocument.id, False, f"Errore durante il caricamento del documento: {e}")) + continue + else: + # The forceUpload flag is set to True, so the documents can be uploaded without checking if they are already present in the system. + for awsDocument in awsDocuments: + try: + self.s3.put_object(Bucket=self.awsBucketName, Key=awsDocument.id, Body=awsDocument.content, ContentType=awsDocument.type) + AWSDocumentOperationResponses.append(AWSDocumentOperationResponse(awsDocument.id, True, "Caricamento del documento avvenuto con successo.")) + except Exception as e: + # An error occurred during the put_object operation. + AWSDocumentOperationResponses.append(AWSDocumentOperationResponse(awsDocument.id, False, f"Errore durante il caricamento del documento: {e}")) + continue + return AWSDocumentOperationResponses def deleteDocuments(self, documentsIds: List[str]) -> List[AWSDocumentOperationResponse]: @@ -81,10 +94,11 @@ def deleteDocuments(self, documentsIds: List[str]) -> List[AWSDocumentOperationR try: self.s3.delete_object(Bucket=self.awsBucketName, Key=documentId) AWSDocumentOperationResponses.append(AWSDocumentOperationResponse(documentId, True, "Eliminazione del documento avvenuta con successo.")) - except self.s3.exceptions.NoSuchKey: #TODO: Non fa partire l'eccezione se il documento non esiste - AWSDocumentOperationResponses.append(AWSDocumentOperationResponse(documentId, False, "Il documento non è presente nel sistema.")) - except Exception as e: - AWSDocumentOperationResponses.append(AWSDocumentOperationResponse(documentId, False, f"Errore durante l'eliminazione del documento: {e}")) + except ClientError as e: + if e.response['Error']['Code'] == 'NoSuchKey': + AWSDocumentOperationResponses.append(AWSDocumentOperationResponse(documentId, False, "Il documento non è presente nel sistema.")) + else: + AWSDocumentOperationResponses.append(AWSDocumentOperationResponse(documentId, False, f"Errore durante l'eliminazione del documento: {e}")) continue return AWSDocumentOperationResponses @@ -96,9 +110,10 @@ def getDocumentsMetadata(self, documentFilter: str) -> List[AWSDocumentMetadata] for content in contents: awsDocumentsMetadata.append( AWSDocumentMetadata( - content.get('Key'), - content.get('Size'), - content.get('LastModified') + id=content.get('Key'), + size=content.get('Size'), + uploadTime=content.get('LastModified'), + type=content.get('ContentType') ) ) return awsDocumentsMetadata @@ -107,11 +122,11 @@ def getDocumentContent(self, documentId: str) -> AWSDocument: try: documentContentResponse = self.s3.get_object(Bucket=self.awsBucketName, Key=documentId) return AWSDocument( - documentId, - documentContentResponse.get('Body').read(), - documentContentResponse.get('ContentType'), - documentContentResponse.get('ContentLength'), - documentContentResponse.get('LastModified') + id=documentId, + content=documentContentResponse.get('Body').read(), + type=documentContentResponse.get('ContentType'), + size=documentContentResponse.get('ContentLength'), + uploadTime=documentContentResponse.get('LastModified') ) - except self.s3.exceptions.NoSuchKey: - return None + except Exception as e: + return None \ No newline at end of file diff --git a/3 - PB/MVP/src/backend/adapter/out/persistence/postgres/chat_history_manager.py b/3 - PB/MVP/src/backend/adapter/out/persistence/postgres/chat_history_manager.py index cb20aa29..1f0ac6ba 100644 --- a/3 - PB/MVP/src/backend/adapter/out/persistence/postgres/chat_history_manager.py +++ b/3 - PB/MVP/src/backend/adapter/out/persistence/postgres/chat_history_manager.py @@ -1,6 +1,6 @@ from typing import List -from langchain_community.chat_message_histories import (PostgresChatMessageHistory) +from langchain_community.chat_message_histories import PostgresChatMessageHistory from langchain_core.messages import BaseMessage import os @@ -9,8 +9,11 @@ class ChatHistoryManager: def getChatHistory(self, chatId: int)-> PostgresChatMessageHistory: - history = PostgresChatMessageHistory( - connection_string=os.environ.get('DATABASE_URL'), - session_id=str(chatId), - ) - return history + try: + history = PostgresChatMessageHistory( + connection_string=os.environ.get('DATABASE_URL'), + session_id=str(chatId), + ) + return history + except Exception: + return None diff --git a/3 - PB/MVP/src/backend/adapter/out/persistence/postgres/chat_models.py b/3 - PB/MVP/src/backend/adapter/out/persistence/postgres/chat_models.py index f5af3969..24cd4261 100644 --- a/3 - PB/MVP/src/backend/adapter/out/persistence/postgres/chat_models.py +++ b/3 - PB/MVP/src/backend/adapter/out/persistence/postgres/chat_models.py @@ -10,7 +10,7 @@ class Chat(Base): messages_cascade = relationship( 'MessageStore', back_populates="messages_cascade_rel", - cascade="all, delete", + cascade="all, delete, delete-orphan", passive_deletes=True ) @@ -23,14 +23,14 @@ def __repr__(self): class MessageStore(Base): __tablename__ = 'message_store' id = Column('id', Integer, primary_key=True, autoincrement=True) - sessionId = Column('session_id', Integer, ForeignKey('chat.id')) + sessionId = Column('session_id', Integer, ForeignKey('chat.id', ondelete='CASCADE')) message = Column('message', JSON) messages_cascade_rel = relationship("Chat", back_populates="messages_cascade") relevant_documents_cascade = relationship( 'MessageRelevantDocuments', back_populates="relevant_documents_cascade_rel", - cascade="all, delete", + cascade="all, delete, delete-orphan", passive_deletes=True ) @@ -43,7 +43,7 @@ def __repr__(self): class MessageRelevantDocuments(Base): __tablename__ = 'message_relevant_documents' - id = Column('id', Integer, ForeignKey('message_store.id'), primary_key=True) + id = Column('id', Integer, ForeignKey('message_store.id', ondelete='CASCADE'), primary_key=True) documentId = Column('document_id', Text, primary_key=True) relevant_documents_cascade_rel = relationship("MessageStore", back_populates="relevant_documents_cascade") diff --git a/3 - PB/MVP/src/backend/adapter/out/persistence/postgres/postgres_chat_orm.py b/3 - PB/MVP/src/backend/adapter/out/persistence/postgres/postgres_chat_orm.py index 7621293e..f5cde9db 100644 --- a/3 - PB/MVP/src/backend/adapter/out/persistence/postgres/postgres_chat_orm.py +++ b/3 - PB/MVP/src/backend/adapter/out/persistence/postgres/postgres_chat_orm.py @@ -58,17 +58,19 @@ def deleteChats(self, chatIds: List[int]) -> List[PostgresChatOperationResponse] try: db_session.query(Chat).filter(Chat.id.in_(chatIds)).delete(synchronize_session=False) db_session.commit() - #TODO: eliminare anche i messaggi e i documenti associati - #TODO: vedere se è stata eliminata effettivamente la chat return [PostgresChatOperationResponse(True, "Chat eliminata correttamente.", chatId) for chatId in chatIds] except Exception as e: return [PostgresChatOperationResponse(False, f"Errore nella eliminazione della chat: {str(e)}", chatId) for chatId in chatIds] def renameChat(self, chatId: int, newName: str) -> PostgresChatOperationResponse: try: - db_session.query(Chat).filter(Chat.id == chatId).update({"title": newName}) + affectedRows = db_session.query(Chat).filter(Chat.id == chatId).update({"title": newName}) db_session.commit() - return PostgresChatOperationResponse(True, "Chat rinominata correttamente.", chatId) + + if affectedRows > 0: + return PostgresChatOperationResponse(True, "Chat rinominata correttamente.", chatId) + else: + return PostgresChatOperationResponse(False, "Nessuna chat trovata con l'ID specificato.", chatId) except Exception as e: return PostgresChatOperationResponse(False, f"Errore nella rinomina della chat: {str(e)}", chatId) @@ -95,11 +97,13 @@ def getChatMessages(self, chatId: int) -> PostgresChat: try: chat = db_session.query(Chat).filter(Chat.id == chatId).first() messages = db_session.query(MessageStore).filter(MessageStore.sessionId == chatId).all() - postgresMessages = [PostgresMessage( - message.message["data"]["content"], - datetime.fromisoformat(message.message["data"]["timestamp"]), - [document.documentId for document in db_session.query(MessageRelevantDocuments).filter(MessageRelevantDocuments.id == message.id).all()], - PostgresMessageSenderType[message.message["type"]]) for message in messages] + postgresMessages = [ + PostgresMessage( + message.message["data"]["content"], + datetime.fromisoformat(message.message["data"]["timestamp"]), + [document.documentId for document in db_session.query(MessageRelevantDocuments).filter(MessageRelevantDocuments.id == message.id).all()], + PostgresMessageSenderType[message.message["type"]] + ) for message in messages] return PostgresChat(chat.id, chat.title, postgresMessages) except Exception as e: diff --git a/3 - PB/MVP/src/backend/adapter/out/persistence/postgres/postgres_configuration.py b/3 - PB/MVP/src/backend/adapter/out/persistence/postgres/postgres_configuration.py index ab949180..7b8a56b6 100644 --- a/3 - PB/MVP/src/backend/adapter/out/persistence/postgres/postgres_configuration.py +++ b/3 - PB/MVP/src/backend/adapter/out/persistence/postgres/postgres_configuration.py @@ -18,26 +18,26 @@ def toConfiguration(self): self.vectorStore.description, self.vectorStore.type, self.vectorStore.costIndicator - ), + ) if self.vectorStore else None, documentStore=PostgresDocumentStoreConfiguration( self.documentStore.name, self.documentStore.organization, self.documentStore.description, self.documentStore.type, self.documentStore.costIndicator - ), + ) if self.documentStore else None, embeddingModel=PostgresEmbeddingModelConfiguration( self.embeddingModel.name, self.embeddingModel.organization, self.embeddingModel.description, self.embeddingModel.type, self.embeddingModel.costIndicator - ), + ) if self.embeddingModel else None, LLMModel=PostgresLLMModelConfiguration( self.LLMModel.name, self.LLMModel.organization, self.LLMModel.description, self.LLMModel.type, self.LLMModel.costIndicator - ) + ) if self.LLMModel else None ) \ No newline at end of file diff --git a/3 - PB/MVP/src/backend/adapter/out/rename_chat/rename_chat_postgres.py b/3 - PB/MVP/src/backend/adapter/out/rename_chat/rename_chat_postgres.py index 1a144712..f746a1f8 100644 --- a/3 - PB/MVP/src/backend/adapter/out/rename_chat/rename_chat_postgres.py +++ b/3 - PB/MVP/src/backend/adapter/out/rename_chat/rename_chat_postgres.py @@ -8,5 +8,5 @@ def __init__(self, postgresChatORM: PostgresChatORM): self.outPort = postgresChatORM def renameChat(self, chatId: ChatId, title: str) -> ChatOperationResponse: - postgresChatOperationResponse = self.outPort.renameChat(chatId, title) + postgresChatOperationResponse = self.outPort.renameChat(chatId.id, title) return postgresChatOperationResponse.toChatOperationResponse() \ No newline at end of file diff --git a/3 - PB/MVP/src/backend/api_exceptions.py b/3 - PB/MVP/src/backend/api_exceptions.py index e45df9e9..6fe9f023 100644 --- a/3 - PB/MVP/src/backend/api_exceptions.py +++ b/3 - PB/MVP/src/backend/api_exceptions.py @@ -1,7 +1,10 @@ class APIBadRequest(Exception): - def __init__(self, message, status_code): + def __init__(self, message, status_code=None): self.message = message - self.status_code = status_code + if status_code is None: + self.status_code = 400 + else: + self.status_code = status_code class DocumentNotSupported(APIBadRequest): def __init__(self, message="Documento non supportato."): diff --git a/3 - PB/MVP/src/backend/application/port/_in/get_documents_content_use_case.py b/3 - PB/MVP/src/backend/application/port/_in/get_documents_content_use_case.py index 329bdab6..a68135ef 100644 --- a/3 - PB/MVP/src/backend/application/port/_in/get_documents_content_use_case.py +++ b/3 - PB/MVP/src/backend/application/port/_in/get_documents_content_use_case.py @@ -2,6 +2,7 @@ from domain.document.document import Document from domain.document.document_id import DocumentId + class GetDocumentsContentUseCase: def getDocumentsContent(self, documentIds: List[DocumentId]) -> List[Document]: pass \ No newline at end of file diff --git a/3 - PB/MVP/src/backend/application/service/ask_chatbot_service.py b/3 - PB/MVP/src/backend/application/service/ask_chatbot_service.py index e2a5739b..ae16a36e 100644 --- a/3 - PB/MVP/src/backend/application/service/ask_chatbot_service.py +++ b/3 - PB/MVP/src/backend/application/service/ask_chatbot_service.py @@ -18,9 +18,9 @@ def askChatbot(self, message: Message, chatId: ChatId) -> MessageResponse: chatOperationResponse = self.persistChatOutPort.persistChat([message, messageResponse.messageResponse], chatId) return MessageResponse( - chatOperationResponse.status, - messageResponse.messageResponse if messageResponse.messageResponse else None, - chatOperationResponse.chatId + status=chatOperationResponse.status, + messageResponse=messageResponse.messageResponse if messageResponse.messageResponse else None, + chatId=chatOperationResponse.chatId ) return messageResponse \ No newline at end of file diff --git a/3 - PB/MVP/src/backend/blueprints/ask_chatbot.py b/3 - PB/MVP/src/backend/blueprints/ask_chatbot.py index 7198e824..59594f8d 100644 --- a/3 - PB/MVP/src/backend/blueprints/ask_chatbot.py +++ b/3 - PB/MVP/src/backend/blueprints/ask_chatbot.py @@ -1,7 +1,7 @@ from flask import request, Blueprint, jsonify from adapter._in.web.ask_chatbot_controller import AskChatbotController from application.service.ask_chatbot_service import AskChatbotService -from api_exceptions import InsufficientParameters +from api_exceptions import InsufficientParameters, APIBadRequest, APIElaborationException from adapter.out.persistence.postgres.postgres_configuration_orm import PostgresConfigurationORM from adapter.out.persistence.postgres.postgres_chat_orm import PostgresChatORM @@ -12,11 +12,15 @@ askChatbotBlueprint = Blueprint("askChatbot", __name__) @askChatbotBlueprint.route("/askChatbot", methods=['POST']) -def AskChatbot(): +def askChatbot(): userMessage = request.form.get('message') chatId = request.form.get('chatId') if userMessage is None: raise InsufficientParameters() + if userMessage.strip() == "": + raise APIBadRequest(f"Filtro '{userMessage}' non valido.") + if not chatId.isdigit() or int(chatId) < 0: + raise APIBadRequest(f"Chat id '{chatId}' non valido.") configurationManager = ConfigurationManager(postgresConfigurationORM=PostgresConfigurationORM()) @@ -27,10 +31,10 @@ def AskChatbot(): ) ) - chatbotResponse = controller.askChatbot(userMessage, chatId) + chatbotResponse = controller.askChatbot(userMessage.strip(), int(chatId)) if chatbotResponse is None: - return jsonify("Errore nella generazione della risposta."), 500 + raise APIElaborationException("Errore nella generazione della risposta.") return jsonify({ "status": chatbotResponse.status, @@ -39,5 +43,5 @@ def AskChatbot(): "timestamp": chatbotResponse.messageResponse.timestamp, "relevantDocuments": [relevantDocument.id for relevantDocument in chatbotResponse.messageResponse.relevantDocuments], "sender": chatbotResponse.messageResponse.sender.name - }, + } if chatbotResponse.messageResponse else None, "chatId": chatbotResponse.chatId.id}) \ No newline at end of file diff --git a/3 - PB/MVP/src/backend/blueprints/change_configuration.py b/3 - PB/MVP/src/backend/blueprints/change_configuration.py index 0e173b00..93f1d85f 100644 --- a/3 - PB/MVP/src/backend/blueprints/change_configuration.py +++ b/3 - PB/MVP/src/backend/blueprints/change_configuration.py @@ -1,7 +1,7 @@ from flask import request, Blueprint, jsonify from adapter._in.web.change_configuration_controller import ChangeConfigurationController from application.service.change_configuration_service import ChangeConfigurationService -from api_exceptions import InsufficientParameters +from api_exceptions import InsufficientParameters, APIElaborationException, APIBadRequest from adapter.out.persistence.postgres.postgres_configuration_orm import PostgresConfigurationORM from adapter.out.change_configuration.change_configuration_postgres import ChangeConfigurationPostgres @@ -12,13 +12,16 @@ def changeConfiguration(): LLMModelChoice = request.form.get('LLMModel') if LLMModelChoice is None: raise InsufficientParameters() - + if LLMModelChoice.strip() == "": + raise APIBadRequest(f"Modello LLM '{LLMModelChoice}' non valido.") + validLLMModelChoice = LLMModelChoice.strip().upper() + controller = ChangeConfigurationController(ChangeConfigurationService(ChangeConfigurationPostgres(PostgresConfigurationORM()))) - configurationOperationResponse = controller.changeLLMModel(LLMModelChoice) + configurationOperationResponse = controller.changeLLMModel(validLLMModelChoice) if configurationOperationResponse is None: - return jsonify({"status": False, "message": "Errore nell'aggiornamento del modello LLM."}), 500 + raise APIElaborationException("Errore nell'aggiornamento del modello LLM.") return jsonify({ "status": configurationOperationResponse.status, diff --git a/3 - PB/MVP/src/backend/blueprints/conceal_documents.py b/3 - PB/MVP/src/backend/blueprints/conceal_documents.py index e3eb6c55..3ef6675b 100644 --- a/3 - PB/MVP/src/backend/blueprints/conceal_documents.py +++ b/3 - PB/MVP/src/backend/blueprints/conceal_documents.py @@ -4,7 +4,7 @@ from adapter.out.persistence.postgres.postgres_configuration_orm import PostgresConfigurationORM from adapter.out.configuration_manager import ConfigurationManager -from api_exceptions import InsufficientParameters +from api_exceptions import APIBadRequest, InsufficientParameters, APIElaborationException concealDocumentsBlueprint = Blueprint("concealDocuments", __name__) @@ -13,20 +13,23 @@ def concealDocuments(): requestedIds = request.form.getlist('documentIds') if requestedIds is None: raise InsufficientParameters() - - print(requestedIds, flush=True) + if len(requestedIds) == 0: + raise APIBadRequest("Nessun id di documento specificato.") + validDocumentIds = [] + for requestedId in requestedIds: + if requestedId.strip() == "": + raise APIBadRequest(f"Id di documento '{requestedId}' non valido.") + else: + validDocumentIds.append(requestedId.strip()) configurationManager = ConfigurationManager(postgresConfigurationORM=PostgresConfigurationORM()) controller = ConcealDocumentsController(ConcealDocumentsService(configurationManager.getConcealDocumentsPort())) - if requestedIds == 1: - documentOperationResponses = controller.concealDocuments([requestedIds]) - else: - documentOperationResponses = controller.concealDocuments(requestedIds) + documentOperationResponses = controller.concealDocuments(validDocumentIds) if len(documentOperationResponses) == 0: - return jsonify("Errore nell'occultamento dei documenti."), 500 + raise APIElaborationException("Errore nell'occultamento dei documenti.") return jsonify([{ "id": documentOperationResponse.documentId.id, diff --git a/3 - PB/MVP/src/backend/blueprints/delete_chats.py b/3 - PB/MVP/src/backend/blueprints/delete_chats.py index ad93b7dd..77651a62 100644 --- a/3 - PB/MVP/src/backend/blueprints/delete_chats.py +++ b/3 - PB/MVP/src/backend/blueprints/delete_chats.py @@ -2,9 +2,7 @@ from adapter._in.web.delete_chats_controller import DeleteChatsController from application.service.delete_chats_service import DeleteChatsService -from adapter.out.persistence.postgres.postgres_configuration_orm import PostgresConfigurationORM -from adapter.out.configuration_manager import ConfigurationManager -from api_exceptions import InsufficientParameters +from api_exceptions import APIBadRequest, InsufficientParameters, APIElaborationException from adapter.out.delete_chats.delete_chats_postgres import DeleteChatsPostgres from adapter.out.persistence.postgres.postgres_chat_orm import PostgresChatORM @@ -15,19 +13,29 @@ def deleteChats(): requestedIds = request.form.getlist('chatIds') if requestedIds is None: raise InsufficientParameters() + if len(requestedIds) == 0: + raise APIBadRequest("Nessun chat id specificato.") + validChatIds = [] + for requestedId in requestedIds: + if requestedId == "" or not requestedId.isdigit() or int(requestedId) < 0: + raise APIBadRequest(f"Chat id '{requestedId}' non valido.") + else: + validChatIds.append(int(requestedId)) controller = DeleteChatsController( DeleteChatsService( - DeleteChatsPostgres(PostgresChatORM()) + DeleteChatsPostgres( + PostgresChatORM() + ) ) ) - chatOperationResponses = controller.deleteChats(requestedIds) + chatOperationResponses = controller.deleteChats(validChatIds) if len(chatOperationResponses) == 0: - return jsonify("Errore nell'eliminazione delle chats."), 500 + raise APIElaborationException("Errore nell'eliminazione delle chat.") return jsonify([{ - "id": chatOperationResponse.chatId.id, + "chatId": chatOperationResponse.chatId.id, "status": chatOperationResponse.status, "message": chatOperationResponse.message} for chatOperationResponse in chatOperationResponses]) \ No newline at end of file diff --git a/3 - PB/MVP/src/backend/blueprints/delete_documents.py b/3 - PB/MVP/src/backend/blueprints/delete_documents.py index 64a98523..da4d37dd 100644 --- a/3 - PB/MVP/src/backend/blueprints/delete_documents.py +++ b/3 - PB/MVP/src/backend/blueprints/delete_documents.py @@ -6,7 +6,7 @@ from adapter.out.persistence.postgres.postgres_configuration_orm import PostgresConfigurationORM from adapter.out.configuration_manager import ConfigurationManager -from api_exceptions import InsufficientParameters +from api_exceptions import InsufficientParameters, APIBadRequest, APIElaborationException deleteDocumentsBlueprint = Blueprint("deleteDocuments", __name__) @@ -15,6 +15,14 @@ def deleteDocuments(): requestedIds = request.form.getlist('documentIds') if requestedIds is None: raise InsufficientParameters() + if len(requestedIds) == 0: + raise APIBadRequest("Nessun id di documento specificato.") + validDocumentIds = [] + for requestedId in requestedIds: + if requestedId.strip() == "": + raise APIBadRequest(f"Id di documento '{requestedId}' non valido.") + else: + validDocumentIds.append((requestedId).strip()) configurationManager = ConfigurationManager(postgresConfigurationORM=PostgresConfigurationORM()) @@ -25,10 +33,10 @@ def deleteDocuments(): ) ) - documentOperationResponses = controller.deleteDocuments(requestedIds) + documentOperationResponses = controller.deleteDocuments(validDocumentIds) if len(documentOperationResponses) == 0: - return jsonify("Errore nell'eliminazione dei documenti."), 500 + raise APIElaborationException("Errore nell'eliminazione dei documenti.") return jsonify([{ "id": documentOperationResponse.documentId.id, diff --git a/3 - PB/MVP/src/backend/blueprints/embed_documents.py b/3 - PB/MVP/src/backend/blueprints/embed_documents.py index ebd8581a..f229d225 100644 --- a/3 - PB/MVP/src/backend/blueprints/embed_documents.py +++ b/3 - PB/MVP/src/backend/blueprints/embed_documents.py @@ -6,7 +6,7 @@ from application.service.get_documents_status import GetDocumentsStatus from adapter.out.persistence.postgres.postgres_configuration_orm import PostgresConfigurationORM from adapter.out.configuration_manager import ConfigurationManager -from api_exceptions import InsufficientParameters +from api_exceptions import InsufficientParameters, APIBadRequest, APIElaborationException embedDocumentsBlueprint = Blueprint('embed_documents', __name__) @@ -15,6 +15,14 @@ def embedDocuments(): requestedIds = request.form.getlist('documentIds') if requestedIds is None: raise InsufficientParameters() + if len(requestedIds) == 0: + raise APIBadRequest("Nessun id di documento specificato.") + validDocumentIds = [] + for requestedId in requestedIds: + if requestedId.strip() == "": + raise APIBadRequest(f"Id di documento '{requestedId}' non valido.") + else: + validDocumentIds.append((requestedId).strip()) configurationManager = ConfigurationManager(postgresConfigurationORM=PostgresConfigurationORM()) @@ -26,10 +34,10 @@ def embedDocuments(): ) ) - documentOperationResponses = controller.embedDocuments(requestedIds) + documentOperationResponses = controller.embedDocuments(validDocumentIds) if len(documentOperationResponses) == 0: - return jsonify("Errore nella generazione degli embeddings dei documenti."), 500 + raise APIElaborationException("Errore nella generazione degli embeddings dei documenti.") return jsonify([{"id": documentOperationResponse.documentId.id, "status": documentOperationResponse.status, diff --git a/3 - PB/MVP/src/backend/blueprints/enable_documents.py b/3 - PB/MVP/src/backend/blueprints/enable_documents.py index 2efdb684..34e61998 100644 --- a/3 - PB/MVP/src/backend/blueprints/enable_documents.py +++ b/3 - PB/MVP/src/backend/blueprints/enable_documents.py @@ -4,7 +4,7 @@ from adapter.out.persistence.postgres.postgres_configuration_orm import PostgresConfigurationORM from adapter.out.configuration_manager import ConfigurationManager -from api_exceptions import InsufficientParameters +from api_exceptions import InsufficientParameters, APIBadRequest, APIElaborationException enableDocumentsBlueprint = Blueprint("enableDocuments", __name__) @@ -13,15 +13,23 @@ def enableDocuments(): requestedIds = request.form.getlist('documentIds') if requestedIds is None: raise InsufficientParameters() + if len(requestedIds) == 0: + raise APIBadRequest("Nessun id di documento specificato.") + validDocumentIds = [] + for requestedId in requestedIds: + if requestedId.strip() == "": + raise APIBadRequest(f"Id di documento '{requestedId}' non valido.") + else: + validDocumentIds.append((requestedId).strip()) configurationManager = ConfigurationManager(postgresConfigurationORM=PostgresConfigurationORM()) controller = EnableDocumentsController(EnableDocumentsService(configurationManager.getEnableDocumentsPort())) - documentOperationResponses = controller.enableDocuments(requestedIds) + documentOperationResponses = controller.enableDocuments(validDocumentIds) if len(documentOperationResponses) == 0: - return jsonify("Errore nella riabilitazione dei documenti."), 500 + raise APIElaborationException("Errore nella riabilitazione dei documenti.") return jsonify([{ "id": documentOperationResponse.documentId.id, diff --git a/3 - PB/MVP/src/backend/blueprints/get_chat_messages.py b/3 - PB/MVP/src/backend/blueprints/get_chat_messages.py index 73700cc2..c8d3fa42 100644 --- a/3 - PB/MVP/src/backend/blueprints/get_chat_messages.py +++ b/3 - PB/MVP/src/backend/blueprints/get_chat_messages.py @@ -1,9 +1,8 @@ from flask import Blueprint, jsonify from adapter._in.web.get_chat_messages_controller import GetChatMessagesController -from adapter.out.persistence.postgres.postgres_configuration_orm import PostgresConfigurationORM -from adapter.out.configuration_manager import ConfigurationManager -from api_exceptions import InsufficientParameters + +from api_exceptions import InsufficientParameters, APIBadRequest, APIElaborationException from adapter.out.persistence.postgres.postgres_chat_orm import PostgresChatORM from application.service.get_chat_messages_service import GetChatMessagesService from adapter.out.get_chat_messages.get_chat_messages_postgres import GetChatMessagesPostgres @@ -14,6 +13,8 @@ def getChatMessages(chatId): if chatId is None: raise InsufficientParameters() + if not chatId.isdigit() or int(chatId) < 0: + raise APIBadRequest(f"Chat id '{chatId}' non valido.") controller = GetChatMessagesController( GetChatMessagesService( @@ -23,11 +24,18 @@ def getChatMessages(chatId): ) ) - chatMessages = controller.getChatMessages(chatId) + chatMessages = controller.getChatMessages(int(chatId)) + + if chatMessages is None: + raise APIElaborationException("Errore nel recupero dei messaggi.") + return jsonify({ "title": chatMessages.title, - "id": chatMessages.chatId.id, - "messages": [{"content": chatMessage.content, - "timestamp": chatMessage.timestamp, - "sender": chatMessage.sender.name} for chatMessage in chatMessages.messages] + "chatId": chatMessages.chatId.id, + "messages": [ + { + "content": chatMessage.content, + "timestamp": chatMessage.timestamp, + "sender": chatMessage.sender.name + } for chatMessage in chatMessages.messages] }) \ No newline at end of file diff --git a/3 - PB/MVP/src/backend/blueprints/get_chats.py b/3 - PB/MVP/src/backend/blueprints/get_chats.py index 93c2734b..450c9c19 100644 --- a/3 - PB/MVP/src/backend/blueprints/get_chats.py +++ b/3 - PB/MVP/src/backend/blueprints/get_chats.py @@ -1,9 +1,8 @@ from flask import Blueprint, jsonify from adapter._in.web.get_chats_controller import GetChatsController -from adapter.out.persistence.postgres.postgres_configuration_orm import PostgresConfigurationORM -from adapter.out.configuration_manager import ConfigurationManager -from api_exceptions import InsufficientParameters + +from api_exceptions import InsufficientParameters, APIBadRequest, APIElaborationException from adapter.out.get_chats.get_chats_postgres import GetChatsPostgres from adapter.out.persistence.postgres.postgres_chat_orm import PostgresChatORM from application.service.get_chats_service import GetChatsService @@ -16,8 +15,7 @@ def getDocuments(filter): if filter is None: raise InsufficientParameters() - - configurationManager = ConfigurationManager(postgresConfigurationORM=PostgresConfigurationORM()) + validFilter = filter.strip() controller = GetChatsController( GetChatsService( @@ -27,13 +25,19 @@ def getDocuments(filter): ) ) - chats = controller.getChats(filter) + retrievedChats = controller.getChats(validFilter) - if len(chats) == 0: + if len(retrievedChats) == 0: return jsonify([]), 404 - return jsonify([{ - "title": chat.title, - "lastMessage": { "content": chat.lastMessage.content, - "sender":chat.lastMessage.sender.name, - "time": chat.lastMessage.timestamp}} for chat in chats]) \ No newline at end of file + return jsonify( + [{ + "chatId": chat.id.id, + "title": chat.title, + "lastMessage": { + "content": chat.lastMessage.content, + "sender":chat.lastMessage.sender.name, + "time": chat.lastMessage.timestamp + } + } for chat in retrievedChats] + ) \ No newline at end of file diff --git a/3 - PB/MVP/src/backend/blueprints/get_configuration.py b/3 - PB/MVP/src/backend/blueprints/get_configuration.py index 66913308..6b62504e 100644 --- a/3 - PB/MVP/src/backend/blueprints/get_configuration.py +++ b/3 - PB/MVP/src/backend/blueprints/get_configuration.py @@ -1,5 +1,4 @@ from flask import Blueprint, jsonify -import json from adapter._in.web.get_configuration_controller import GetConfigurationController from application.service.get_configuration_service import GetConfigurationService @@ -7,11 +6,12 @@ from adapter.out.get_configuration.get_configuration_postgres import GetConfigurationPostgres from adapter.out.persistence.postgres.postgres_configuration_orm import PostgresConfigurationORM +from api_exceptions import APIElaborationException + getConfigurationBlueprint = Blueprint("getConfiguration", __name__) @getConfigurationBlueprint.route('/getConfiguration', methods=['GET']) def getConfiguration(): - controller = GetConfigurationController( GetConfigurationService( GetConfigurationPostgres(PostgresConfigurationORM()) @@ -21,7 +21,10 @@ def getConfiguration(): configuration = controller.getConfiguration() if configuration is None: - return jsonify({}), 404 + raise APIElaborationException("Errore nel recupero della configurazione.") + + if configuration.documentStore is None or configuration.vectorStore is None or configuration.embeddingModel is None or configuration.LLMModel is None: + return "Configurazione inesistente.", 404 return jsonify({ "vectorStore": { diff --git a/3 - PB/MVP/src/backend/blueprints/get_configuration_options.py b/3 - PB/MVP/src/backend/blueprints/get_configuration_options.py index 5c924894..949e2af4 100644 --- a/3 - PB/MVP/src/backend/blueprints/get_configuration_options.py +++ b/3 - PB/MVP/src/backend/blueprints/get_configuration_options.py @@ -11,7 +11,6 @@ @getConfigurationOptionsBlueprint.route('/getConfigurationOptions', methods=['GET']) def getConfigurationOptions(): - controller = GetConfigurationOptionsController( GetConfigurationOptionsService( GetConfigurationOptionsPostgres(PostgresConfigurationORM()) diff --git a/3 - PB/MVP/src/backend/blueprints/get_document_content.py b/3 - PB/MVP/src/backend/blueprints/get_document_content.py index 866b964a..5d04dea1 100644 --- a/3 - PB/MVP/src/backend/blueprints/get_document_content.py +++ b/3 - PB/MVP/src/backend/blueprints/get_document_content.py @@ -6,7 +6,7 @@ from adapter.out.persistence.postgres.postgres_configuration_orm import PostgresConfigurationORM from adapter.out.configuration_manager import ConfigurationManager -from api_exceptions import InsufficientParameters +from api_exceptions import InsufficientParameters, APIBadRequest, APIElaborationException getDocumentContentBlueprint = Blueprint("getDocumentContent", __name__) @@ -14,6 +14,8 @@ def getDocumentsContent(documentId): if documentId is None: raise InsufficientParameters() + if documentId.strip() == "": + raise APIBadRequest(f"Id di documento '{documentId}' non valido.") configurationManager = ConfigurationManager(postgresConfigurationORM=PostgresConfigurationORM()) @@ -24,7 +26,7 @@ def getDocumentsContent(documentId): ) ) - retrievedDocument = controller.getDocumentContent(documentId) + retrievedDocument = controller.getDocumentContent(documentId.strip()) if retrievedDocument is None or retrievedDocument.plainDocument is None: return jsonify({}), 404 diff --git a/3 - PB/MVP/src/backend/blueprints/get_documents.py b/3 - PB/MVP/src/backend/blueprints/get_documents.py index a3b4fc5c..35ba9ce5 100644 --- a/3 - PB/MVP/src/backend/blueprints/get_documents.py +++ b/3 - PB/MVP/src/backend/blueprints/get_documents.py @@ -7,7 +7,7 @@ from adapter.out.persistence.postgres.postgres_configuration_orm import PostgresConfigurationORM from adapter.out.configuration_manager import ConfigurationManager -from api_exceptions import InsufficientParameters +from api_exceptions import InsufficientParameters, APIBadRequest getDocumentsBlueprint = Blueprint("getDocuments", __name__) @@ -16,6 +16,7 @@ def getDocuments(filter): if filter is None: raise InsufficientParameters() + validFilter = filter.strip() configurationManager = ConfigurationManager(postgresConfigurationORM=PostgresConfigurationORM()) @@ -26,7 +27,7 @@ def getDocuments(filter): ) ) - documents = controller.getDocuments(filter) + documents = controller.getDocuments(validFilter) if len(documents) == 0: return jsonify([]), 404 diff --git a/3 - PB/MVP/src/backend/blueprints/rename_chat.py b/3 - PB/MVP/src/backend/blueprints/rename_chat.py index 581afbcd..f4d655be 100644 --- a/3 - PB/MVP/src/backend/blueprints/rename_chat.py +++ b/3 - PB/MVP/src/backend/blueprints/rename_chat.py @@ -2,32 +2,38 @@ from adapter._in.web.rename_chat_controller import RenameChatController from application.service.rename_chat_service import RenameChatService -from adapter.out.persistence.postgres.postgres_configuration_orm import PostgresConfigurationORM -from adapter.out.configuration_manager import ConfigurationManager -from api_exceptions import InsufficientParameters, APIBadRequest +from adapter.out.rename_chat.rename_chat_postgres import RenameChatPostgres +from adapter.out.persistence.postgres.postgres_chat_orm import PostgresChatORM + +from api_exceptions import InsufficientParameters, APIBadRequest, APIElaborationException renameChatBlueprint = Blueprint("renameChat", __name__) @renameChatBlueprint.route("/renameChat", methods=['POST']) def renameChat(): - requestedId = request.form.getlist('chatId') - requestedTitle = request.form.getlist('title') - if requestedId is None: + requestedId = request.form.get('chatId') + requestedTitle = request.form.get('title').strip() + if requestedId is None or requestedTitle is None: raise InsufficientParameters() - if requestedTitle is None: + if requestedId.strip() == "" or not requestedId.isdigit() or int(requestedId) < 0: + raise APIBadRequest(f"Chat id '{requestedId}' non valido.") + if requestedTitle.strip() == '': raise APIBadRequest("Il titolo della chat non può essere vuoto.", 400) - - configurationManager = ConfigurationManager(postgresConfigurationORM=PostgresConfigurationORM()) controller = RenameChatController( - RenameChatService(configurationManager.getRenameChatPort())) + RenameChatService( + RenameChatPostgres( + PostgresChatORM() + ) + ) + ) - chatOperationResponse = controller.renameChat(requestedId, requestedTitle) + chatOperationResponse = controller.renameChat(chatId=int(requestedId), title=requestedTitle.strip()) - if len(chatOperationResponse) == 0: - return jsonify("Errore nella rinomina della chat."), 500 + if chatOperationResponse is None: + raise APIElaborationException("Errore nella rinomina della chat.") return jsonify({ - "id": chatOperationResponse.chatId.id, + "chatId": chatOperationResponse.chatId.id, "status": chatOperationResponse.status, "message": chatOperationResponse.message}) \ No newline at end of file diff --git a/3 - PB/MVP/src/backend/blueprints/upload_documents.py b/3 - PB/MVP/src/backend/blueprints/upload_documents.py index 6a82dc42..b2ed1b58 100644 --- a/3 - PB/MVP/src/backend/blueprints/upload_documents.py +++ b/3 - PB/MVP/src/backend/blueprints/upload_documents.py @@ -10,15 +10,17 @@ from adapter.out.persistence.postgres.postgres_configuration_orm import PostgresConfigurationORM from adapter.out.configuration_manager import ConfigurationManager -from api_exceptions import DocumentNotSupported -from api_exceptions import InsufficientParameters +from api_exceptions import InsufficientParameters, DocumentNotSupported, APIElaborationException uploadDocumentsBlueprint = Blueprint("uploadDocuments", __name__) @uploadDocumentsBlueprint.route("/uploadDocuments", methods=['POST']) def uploadDocuments(): + forceUpload = request.form.get('forceUpload') + if forceUpload is None: + forceUpload = False + newDocuments = [] - for uploadedDocument in request.files.getlist('documents'): secureFilename = secure_filename(uploadedDocument.filename) if secureFilename == '': @@ -48,11 +50,10 @@ def uploadDocuments(): ) ) - # TODO: forceUpload = False qui, in Substitute mettere True - documentOperationResponses = controller.uploadDocuments(newDocuments, False) + documentOperationResponses = controller.uploadDocuments(newDocuments, forceUpload) if len(documentOperationResponses) == 0: - return jsonify("Errore nell'upload dei documenti."), 500 + raise APIElaborationException("Errore nell'upload dei documenti.") return jsonify([{ "id": documentOperationResponse.documentId.id, diff --git a/3 - PB/MVP/src/backend/domain/chat/chat.py b/3 - PB/MVP/src/backend/domain/chat/chat.py index 2b93206f..2036915e 100644 --- a/3 - PB/MVP/src/backend/domain/chat/chat.py +++ b/3 - PB/MVP/src/backend/domain/chat/chat.py @@ -1,11 +1,11 @@ +from dataclasses import dataclass from typing import List from domain.chat.chat_id import ChatId from domain.chat.message import Message - +@dataclass class Chat: - def __init__(self, title:str, chatId: ChatId, messages: List[Message]): - self.title = title - self.chatId = chatId - self.messages = messages \ No newline at end of file + title: str + chatId: ChatId + messages: List[Message] \ No newline at end of file diff --git a/3 - PB/MVP/src/backend/domain/chat/chat_filter.py b/3 - PB/MVP/src/backend/domain/chat/chat_filter.py index 2fa19bd4..6754def6 100644 --- a/3 - PB/MVP/src/backend/domain/chat/chat_filter.py +++ b/3 - PB/MVP/src/backend/domain/chat/chat_filter.py @@ -1,4 +1,5 @@ from dataclasses import dataclass + @dataclass class ChatFilter: - searchFilter:str \ No newline at end of file + searchFilter: str \ No newline at end of file diff --git a/3 - PB/MVP/src/backend/domain/chat/chat_info.py b/3 - PB/MVP/src/backend/domain/chat/chat_info.py index 0b633429..2552fd4e 100644 --- a/3 - PB/MVP/src/backend/domain/chat/chat_info.py +++ b/3 - PB/MVP/src/backend/domain/chat/chat_info.py @@ -1,6 +1,7 @@ +from dataclasses import dataclass from datetime import datetime +@dataclass class ChatInfo: - def __init__(self, title: str, timestamp: datetime): - self.title = title - self.timestamp = timestamp \ No newline at end of file + title: str + timestamp: datetime \ No newline at end of file diff --git a/3 - PB/MVP/src/backend/domain/chat/chat_operation_response.py b/3 - PB/MVP/src/backend/domain/chat/chat_operation_response.py index eb59e3f2..d5021b3b 100644 --- a/3 - PB/MVP/src/backend/domain/chat/chat_operation_response.py +++ b/3 - PB/MVP/src/backend/domain/chat/chat_operation_response.py @@ -4,6 +4,6 @@ @dataclass class ChatOperationResponse: + chatId: ChatId status: bool - message: str - chatId: ChatId \ No newline at end of file + message: str \ No newline at end of file diff --git a/3 - PB/MVP/src/backend/domain/chat/chat_preview.py b/3 - PB/MVP/src/backend/domain/chat/chat_preview.py index 41fa9665..010856d7 100644 --- a/3 - PB/MVP/src/backend/domain/chat/chat_preview.py +++ b/3 - PB/MVP/src/backend/domain/chat/chat_preview.py @@ -3,10 +3,8 @@ from domain.chat.chat_id import ChatId from domain.chat.message import Message - @dataclass class ChatPreview: - def __init__(self, id:ChatId, title: str, lastMessage: Message): - self.id = id.id - self.title = title - self.lastMessage = lastMessage \ No newline at end of file + id: ChatId + title: str + lastMessage: Message \ No newline at end of file diff --git a/3 - PB/MVP/src/backend/domain/chat/message_response.py b/3 - PB/MVP/src/backend/domain/chat/message_response.py index 4fc444bd..9b998790 100644 --- a/3 - PB/MVP/src/backend/domain/chat/message_response.py +++ b/3 - PB/MVP/src/backend/domain/chat/message_response.py @@ -4,6 +4,6 @@ @dataclass class MessageResponse: + chatId: ChatId status: bool - messageResponse: Message - chatId: ChatId \ No newline at end of file + messageResponse: Message \ No newline at end of file