-
Notifications
You must be signed in to change notification settings - Fork 1
[BAK-38] [기능] AIChatTab 업데이트 #45
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
7a88e1b
d98aade
7f5e139
a8ddacc
1df9969
6296ad4
55ea26a
a6950f8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,34 +1,61 @@ | ||
| from fastapi import APIRouter, Depends | ||
| from fastapi import APIRouter, Depends, Path | ||
|
|
||
| from app.core.response import ResponseMessage | ||
| from app.core.status import CommonCode | ||
| from app.schemas.chat_tab.create_model import AIChatCreate | ||
| from app.schemas.chat_tab.response_model import AIChatResponse | ||
| from app.services.chat_tab_service import AIChatService, ai_chat_service | ||
| from app.schemas.chat_tab.create_model import ChatTabCreate | ||
| from app.schemas.chat_tab.response_model import ChatTabResponse | ||
| from app.schemas.chat_tab.update_model import ChatTabUpdate | ||
| from app.services.chat_tab_service import ChatTabService, chat_tab_service | ||
|
|
||
| ai_chat_service_dependency = Depends(lambda: ai_chat_service) | ||
| chat_tab_service_dependency = Depends(lambda: chat_tab_service) | ||
|
|
||
| router = APIRouter() | ||
|
|
||
|
|
||
| @router.post( | ||
| "/actions", | ||
| response_model=ResponseMessage[AIChatResponse], | ||
| response_model=ResponseMessage[ChatTabResponse], | ||
| summary="Chat Tab 생성", | ||
| description="새로운 Chat Tab을 생성하여 로컬 데이터베이스에 저장합니다.", | ||
| ) | ||
| def store_ai_chat( | ||
| chatName: AIChatCreate, service: AIChatService = ai_chat_service_dependency | ||
| ) -> ResponseMessage[AIChatResponse]: | ||
| def store_chat_tab( | ||
| chatName: ChatTabCreate, service: ChatTabService = chat_tab_service_dependency | ||
| ) -> ResponseMessage[ChatTabResponse]: | ||
| """ | ||
| - **name**: 새로운 Chat_tab 이름 (예: "채팅 타이틀") | ||
| """ | ||
| created_chat = service.store_ai_chat(chatName) | ||
| created_chat_tab = service.store_chat_tab(chatName) | ||
|
|
||
| response_data = AIChatResponse( | ||
| id=created_chat.id, | ||
| name=created_chat.name, | ||
| created_at=created_chat.created_at, | ||
| updated_at=created_chat.updated_at, | ||
| response_data = ChatTabResponse( | ||
| id=created_chat_tab.id, | ||
| name=created_chat_tab.name, | ||
| created_at=created_chat_tab.created_at, | ||
| updated_at=created_chat_tab.updated_at, | ||
| ) | ||
| return ResponseMessage.success(value=response_data, code=CommonCode.SUCCESS_AI_CHAT_CREATE) | ||
| return ResponseMessage.success(value=response_data, code=CommonCode.SUCCESS_CHAT_TAB_CREATE) | ||
|
|
||
| @router.put( | ||
| "/modify/{tabId}", | ||
| response_model=ResponseMessage[ChatTabResponse], | ||
| summary="특정 Chat Tab Name 수정", | ||
| ) | ||
| def updated_chat_tab( | ||
| chatName: ChatTabUpdate, | ||
| tabId: str = Path(..., description="수정할 채팅 탭의 고유 ID"), | ||
| service: ChatTabService = chat_tab_service_dependency | ||
| ) -> ResponseMessage[ChatTabResponse]: | ||
| """ | ||
| 채팅 탭 ID를 기준으로 채팅 탭의 이름을 새로운 값으로 수정합니다. | ||
| - **id**: 수정할 채팅 탭 ID | ||
| - **name**: 새로운 채팅 탭의 이름 | ||
| """ | ||
| updated_chat_tab = service.updated_chat_tab(tabId, chatName) | ||
|
|
||
| response_data = ChatTabResponse( | ||
| id=updated_chat_tab.id, | ||
| name=updated_chat_tab.name, | ||
| created_at=updated_chat_tab.created_at, | ||
| updated_at=updated_chat_tab.updated_at, | ||
| ) | ||
|
|
||
| return ResponseMessage.success(value=response_data, code=CommonCode.SUCCESS_CHAT_TAB_UPDATE) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,7 +1,7 @@ | ||
| from pydantic import BaseModel, Field | ||
|
|
||
|
|
||
| class AIChatBase(BaseModel): | ||
| class ChatTabBase(BaseModel): | ||
| """모든 AI Chat Tab 스키마의 기본 모델""" | ||
|
|
||
| name: str = Field(..., description="새로운 채팅 탭 이름") |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,30 +1,10 @@ | ||
| import re | ||
|
|
||
| from app.core.exceptions import APIException | ||
| from app.core.status import CommonCode | ||
| from app.schemas.chat_tab.base_model import AIChatBase | ||
| from app.schemas.chat_tab.base_model import ChatTabBase | ||
| from app.schemas.chat_tab.validation_utils import validate_chat_tab_name | ||
|
|
||
|
|
||
| class AIChatCreate(AIChatBase): | ||
| class ChatTabCreate(ChatTabBase): | ||
| """새로운 Chat Tab 생성을 위한 스키마""" | ||
|
|
||
| def validate_with_name(self) -> None: | ||
| """채팅 탭 이름에 대한 유효성 검증 로직을 수행합니다.""" | ||
| # 1. 문자열 전체가 공백 문자인지 확인 | ||
| if not self.name or self.name.isspace(): | ||
| raise APIException(CommonCode.INVALID_CHAT_TAB_NAME_FORMAT) | ||
|
|
||
| # 2. 길이 제한 | ||
| if len(self.name) > 128: | ||
| raise APIException(CommonCode.INVALID_CHAT_TAB_NAME_LENGTH) | ||
|
|
||
| # 3. 특수문자 및 SQL 예약어 확인 | ||
| # SQL 예약어와 위험한 특수문자를 검사합니다. | ||
| sql_keywords = ["SELECT", "INSERT", "UPDATE", "DELETE", "DROP", "OR", "AND"] | ||
| for keyword in sql_keywords: | ||
| if keyword in self.name.upper(): | ||
| raise APIException(CommonCode.INVALID_CHAT_TAB_NAME_CONTENT) | ||
|
|
||
| # 특정 특수문자를 검사하는 예시 | ||
| if re.search(r"[;\"'`<>]", self.name): | ||
| raise APIException(CommonCode.INVALID_CHAT_TAB_NAME_CONTENT) | ||
| validate_chat_tab_name(self.name) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| from pydantic import Field | ||
|
|
||
| from app.schemas.chat_tab.base_model import ChatTabBase | ||
| from app.schemas.chat_tab.validation_utils import validate_chat_tab_name | ||
|
|
||
|
|
||
| class ChatTabUpdate(ChatTabBase): | ||
| """채팅 탭 이름 수정을 위한 스키마""" | ||
| name: str | None = Field(None, description="수정할 채팅 탭 이름") | ||
|
|
||
| def validate_with_name(self) -> None: | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이 메서드도 존재만 하고 실제로 호출되지 않는 것 같습니다. |
||
| validate_chat_tab_name(self.name) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| import re | ||
|
|
||
| from app.core.exceptions import APIException | ||
| from app.core.status import CommonCode | ||
|
|
||
|
|
||
| def validate_chat_tab_name(name: str | None) -> None: | ||
| """채팅 탭 이름에 대한 유효성 검증 로직을 수행합니다.""" | ||
| # 1. 문자열이 None, 문자열 전체가 공백 문자인지 확인 | ||
| if not name or name.isspace(): | ||
| raise APIException(CommonCode.INVALID_CHAT_TAB_NAME_FORMAT) | ||
|
|
||
| # 2. 길이 제한 | ||
| if len(name) > 128: | ||
| raise APIException(CommonCode.INVALID_CHAT_TAB_NAME_LENGTH) | ||
|
|
||
| # 3. 특수문자 및 SQL 예약어 확인 | ||
| # SQL 예약어와 위험한 특수문자를 검사합니다. | ||
| sql_keywords = ["SELECT", "INSERT", "UPDATE", "DELETE", "DROP", "OR", "AND"] | ||
| for keyword in sql_keywords: | ||
| if keyword in name.upper(): | ||
| raise APIException(CommonCode.INVALID_CHAT_TAB_NAME_CONTENT) | ||
|
|
||
| # 특정 특수문자를 검사하는 예시 | ||
| if re.search(r"[;\"'`<>]", name): | ||
| raise APIException(CommonCode.INVALID_CHAT_TAB_NAME_CONTENT) |
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. uuid 가져오는 부분은 이넘 생성했으니 추후 확인 후 수정해주시면 됩니다.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 그럼 DB 쪽 머지 후 진행하는게 나을까요 ? 아니면 바로 추가할까요?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 그건 상관없습니다! |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,25 +5,27 @@ | |
| from app.core.exceptions import APIException | ||
| from app.core.status import CommonCode | ||
| from app.core.utils import generate_prefixed_uuid | ||
| from app.repository.chat_tab_repository import AIChatRepository, ai_chat_repository | ||
| from app.schemas.chat_tab.create_model import AIChatCreate | ||
| from app.schemas.chat_tab.db_model import AIChatInDB | ||
| from app.repository.chat_tab_repository import ChatTabRepository, chat_tab_repository | ||
| from app.schemas.chat_tab.create_model import ChatTabCreate | ||
| from app.schemas.chat_tab.db_model import ChatTabInDB | ||
| from app.schemas.chat_tab.update_model import ChatTabUpdate | ||
| from app.schemas.chat_tab.validation_utils import validate_chat_tab_name | ||
|
|
||
| ai_chat_repository_dependency = Depends(lambda: ai_chat_repository) | ||
| chat_tab_repository_dependency = Depends(lambda: chat_tab_repository) | ||
|
|
||
|
|
||
| class AIChatService: | ||
| def __init__(self, repository: AIChatRepository = ai_chat_repository): | ||
| class ChatTabService: | ||
| def __init__(self, repository: ChatTabRepository = chat_tab_repository): | ||
| self.repository = repository | ||
|
|
||
| def store_ai_chat(self, chatName: AIChatCreate) -> AIChatInDB: | ||
| def store_chat_tab(self, chatName: ChatTabCreate) -> ChatTabInDB: | ||
| """새로운 AI 채팅을 데이터베이스에 저장합니다.""" | ||
| chatName.validate_with_name() | ||
| validate_chat_tab_name(chatName.name) | ||
|
Comment on lines
-21
to
+23
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 검증 로직은 모델에 일임하는게 좋을 것 같습니다. |
||
|
|
||
| new_id = generate_prefixed_uuid("CHAT_TAB") | ||
|
|
||
| try: | ||
| created_row = self.repository.create_ai_chat( | ||
| created_row = self.repository.create_chat_tab( | ||
| new_id=new_id, | ||
| name=chatName.name, | ||
| ) | ||
|
|
@@ -38,6 +40,20 @@ def store_ai_chat(self, chatName: AIChatCreate) -> AIChatInDB: | |
| raise APIException(CommonCode.DB_BUSY) from e | ||
| # 기타 모든 sqlite3 오류 | ||
| raise APIException(CommonCode.FAIL) from e | ||
| def updated_chat_tab(self, chatID: str, chatName: ChatTabUpdate) -> ChatTabInDB: | ||
| """서비스 이름에 해당하는 API Key를 수정합니다.""" | ||
| validate_chat_tab_name(chatName.name) | ||
| try: | ||
| updated_chat_tab = self.repository.updated_chat_tab(chatID, chatName.name) | ||
|
|
||
| if not updated_chat_tab: | ||
| raise APIException(CommonCode.NO_SEARCH_DATA) | ||
|
|
||
| return updated_chat_tab | ||
| except sqlite3.Error as e: | ||
| if "database is locked" in str(e): | ||
| raise APIException(CommonCode.DB_BUSY) from e | ||
| raise APIException(CommonCode.FAIL) from e | ||
|
|
||
|
|
||
| ai_chat_service = AIChatService() | ||
| chat_tab_service = ChatTabService() | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이 메서드는 존재만 하고 실제 호출되지 않는 것 같습니다.