From 97e9ebd29a2c2b36a9636c4ca8837f8d6a839126 Mon Sep 17 00:00:00 2001 From: crazywoola <100913391+crazywoola@users.noreply.github.com> Date: Wed, 28 Jun 2023 13:31:51 +0800 Subject: [PATCH] Feature/add is deleted to conversations (#470) --- api/controllers/console/app/conversation.py | 41 +++++++++++++++++++ .../service_api/app/conversation.py | 21 ++++++++++ ...3a3471c_add_is_deleted_to_conversations.py | 32 +++++++++++++++ api/models/model.py | 2 + api/services/conversation_service.py | 4 +- 5 files changed, 99 insertions(+), 1 deletion(-) create mode 100644 api/migrations/versions/d3d503a3471c_add_is_deleted_to_conversations.py diff --git a/api/controllers/console/app/conversation.py b/api/controllers/console/app/conversation.py index 419068468d..2d4762d5d4 100644 --- a/api/controllers/console/app/conversation.py +++ b/api/controllers/console/app/conversation.py @@ -209,6 +209,26 @@ class CompletionConversationDetailApi(Resource): conversation_id = str(conversation_id) return _get_conversation(app_id, conversation_id, 'completion') + + @setup_required + @login_required + @account_initialization_required + def delete(self, app_id, conversation_id): + app_id = str(app_id) + conversation_id = str(conversation_id) + + app = _get_app(app_id, 'chat') + + conversation = db.session.query(Conversation) \ + .filter(Conversation.id == conversation_id, Conversation.app_id == app.id).first() + + if not conversation: + raise NotFound("Conversation Not Exists.") + + conversation.is_deleted = True + db.session.commit() + + return {'result': 'success'}, 204 class ChatConversationApi(Resource): @@ -356,6 +376,27 @@ class ChatConversationDetailApi(Resource): conversation_id = str(conversation_id) return _get_conversation(app_id, conversation_id, 'chat') + + @setup_required + @login_required + @account_initialization_required + def delete(self, app_id, conversation_id): + app_id = str(app_id) + conversation_id = str(conversation_id) + + # get app info + app = _get_app(app_id, 'chat') + + conversation = db.session.query(Conversation) \ + .filter(Conversation.id == conversation_id, Conversation.app_id == app.id).first() + + if not conversation: + raise NotFound("Conversation Not Exists.") + + conversation.is_deleted = True + db.session.commit() + + return {'result': 'success'}, 204 diff --git a/api/controllers/service_api/app/conversation.py b/api/controllers/service_api/app/conversation.py index 602ac8d785..d52eb3fea7 100644 --- a/api/controllers/service_api/app/conversation.py +++ b/api/controllers/service_api/app/conversation.py @@ -48,6 +48,26 @@ class ConversationApi(AppApiResource): except services.errors.conversation.LastConversationNotExistsError: raise NotFound("Last Conversation Not Exists.") +class ConversationDetailApi(AppApiResource): + @marshal_with(conversation_fields) + def delete(self, app_model, end_user, c_id): + if app_model.mode != 'chat': + raise NotChatAppError() + + conversation_id = str(c_id) + + parser = reqparse.RequestParser() + parser.add_argument('user', type=str, location='args') + args = parser.parse_args() + + if end_user is None and args['user'] is not None: + end_user = create_or_update_end_user_for_user_id(app_model, args['user']) + + try: + ConversationService.delete(app_model, conversation_id, end_user) + return {"result": "success"}, 204 + except services.errors.conversation.ConversationNotExistsError: + raise NotFound("Conversation Not Exists.") class ConversationRenameApi(AppApiResource): @@ -74,3 +94,4 @@ class ConversationRenameApi(AppApiResource): api.add_resource(ConversationRenameApi, '/conversations//name', endpoint='conversation_name') api.add_resource(ConversationApi, '/conversations') +api.add_resource(ConversationApi, '/conversations/', endpoint='conversation') diff --git a/api/migrations/versions/d3d503a3471c_add_is_deleted_to_conversations.py b/api/migrations/versions/d3d503a3471c_add_is_deleted_to_conversations.py new file mode 100644 index 0000000000..4b8c702c4e --- /dev/null +++ b/api/migrations/versions/d3d503a3471c_add_is_deleted_to_conversations.py @@ -0,0 +1,32 @@ +"""add is_deleted to conversations + +Revision ID: d3d503a3471c +Revises: e32f6ccb87c6 +Create Date: 2023-06-27 19:13:30.897981 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = 'd3d503a3471c' +down_revision = 'e32f6ccb87c6' +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + with op.batch_alter_table('conversations', schema=None) as batch_op: + batch_op.add_column(sa.Column('is_deleted', sa.Boolean(), server_default=sa.text('false'), nullable=False)) + + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + with op.batch_alter_table('conversations', schema=None) as batch_op: + batch_op.drop_column('is_deleted') + + # ### end Alembic commands ### diff --git a/api/models/model.py b/api/models/model.py index 8650896cad..d47334fe90 100644 --- a/api/models/model.py +++ b/api/models/model.py @@ -206,6 +206,8 @@ class Conversation(db.Model): messages = db.relationship("Message", backref="conversation", lazy='select', passive_deletes="all") message_annotations = db.relationship("MessageAnnotation", backref="conversation", lazy='select', passive_deletes="all") + is_deleted = db.Column(db.Boolean, nullable=False, server_default=db.text('false')) + @property def model_config(self): model_config = {} diff --git a/api/services/conversation_service.py b/api/services/conversation_service.py index 968209c71e..45f18ec4cf 100644 --- a/api/services/conversation_service.py +++ b/api/services/conversation_service.py @@ -16,6 +16,7 @@ class ConversationService: return InfiniteScrollPagination(data=[], limit=limit, has_more=False) base_query = db.session.query(Conversation).filter( + Conversation.is_deleted == False, Conversation.app_id == app_model.id, Conversation.from_source == ('api' if isinstance(user, EndUser) else 'console'), Conversation.from_end_user_id == (user.id if isinstance(user, EndUser) else None), @@ -79,6 +80,7 @@ class ConversationService: Conversation.from_source == ('api' if isinstance(user, EndUser) else 'console'), Conversation.from_end_user_id == (user.id if isinstance(user, EndUser) else None), Conversation.from_account_id == (user.id if isinstance(user, Account) else None), + Conversation.is_deleted == False ).first() if not conversation: @@ -90,5 +92,5 @@ class ConversationService: def delete(cls, app_model: App, conversation_id: str, user: Optional[Union[Account | EndUser]]): conversation = cls.get_conversation(app_model, conversation_id, user) - db.session.delete(conversation) + conversation.is_deleted = True db.session.commit()