diff --git a/.gitattributes b/.gitattributes index a8453356a5818eb58e1c32a64e7024210c355e82..3069c094ead4519edef36e026022d3d27a45bee1 100644 --- a/.gitattributes +++ b/.gitattributes @@ -38,3 +38,12 @@ tests/test_service/user_file/quangphuc@gmail.com/demo1.pdf filter=lfs diff=lfs m tests/user_file/quangphuc@gmail.com/demo1.pdf filter=lfs diff=lfs merge=lfs -text vector_database/vonhuy5112002@gmail.com/chroma.sqlite3 filter=lfs diff=lfs merge=lfs -text vector_database/vonhuy777@gmail.com/chroma.sqlite3 filter=lfs diff=lfs merge=lfs -text +user_file/20133118@student.hcmute.edu.vn/DEMO2.pdf filter=lfs diff=lfs merge=lfs -text +user_file/vonhuy5112002@gmail.com/Nhom05_FinalProject3.docx filter=lfs diff=lfs merge=lfs -text +user_file/vonhuy5112002@gmail.com/Report-ChatGPT.docx filter=lfs diff=lfs merge=lfs -text +user_file/vonhuy777@gmail.com/DEMO2.pdf filter=lfs diff=lfs merge=lfs -text +vector_database/20133118@student.hcmute.edu.vn/chroma.sqlite3 filter=lfs diff=lfs merge=lfs -text +vector_database/20133118@student.hcmute.edu.vn/DEMO1.docx/chroma.sqlite3 filter=lfs diff=lfs merge=lfs -text +vector_database/20133118@student.hcmute.edu.vn/DEMO2.pdf/chroma.sqlite3 filter=lfs diff=lfs merge=lfs -text +vector_database/vonhuy5112002@gmail.com/Nhom05_FinalProject3.docx/chroma.sqlite3 filter=lfs diff=lfs merge=lfs -text +vector_database/vonhuy777@gmail.com/DEMO2.pdf/chroma.sqlite3 filter=lfs diff=lfs merge=lfs -text diff --git a/auth/__pycache__/authentication.cpython-310.pyc b/auth/__pycache__/authentication.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ee6aec97923a5ce840f64d9e5c05fe86f2e10ea0 Binary files /dev/null and b/auth/__pycache__/authentication.cpython-310.pyc differ diff --git a/auth/__pycache__/authentication.cpython-311.pyc b/auth/__pycache__/authentication.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5055416c354805c3a0eb61db4242eff66aa2ac4e Binary files /dev/null and b/auth/__pycache__/authentication.cpython-311.pyc differ diff --git a/auth/authentication.py b/auth/authentication.py new file mode 100644 index 0000000000000000000000000000000000000000..f3dcb8b02abce0007d27492a3681549f43ecb24e --- /dev/null +++ b/auth/authentication.py @@ -0,0 +1,133 @@ +import time +from typing import Dict +import jwt +import secrets +import logging +from fastapi import Depends, HTTPException +import base64 +from datetime import datetime, timedelta +from repository import UserRepository, UserLoginRepository +import string, random + +def check_token_is_valid(token): + check = UserRepository.getEmailUserByAccessToken(token) + if check is None: + return False + return True + +def unique_string(byte: int = 8) -> str: + return secrets.token_urlsafe(byte) +JWT_SECRET = "09d25e094faa6ca2556c818166b7a9563b93f7099f6f0f4caa6cf63b88e8d3e7" +JWT_ALGORITHM = "HS512" +SECRET_KEY= "8deadce9449770680910741063cd0a3fe0acb62a8978661f421bbcbb66dc41f1" + +def token_response(token: str): + return { + "access_token": token + } +def str_encode(string: str) -> str: + return base64.b85encode(string.encode('ascii')).decode('ascii') + +def get_token_payload(token: str, secret: str, algo: str): + try: + payload = jwt.decode(token, secret, algorithms=algo) + except Exception as jwt_exec: + logging.debug(f"JWT Error: {str(jwt_exec)}") + payload = None + return payload + +from datetime import datetime +def generate_token(payload: dict, secret: str, algo: str, expiry: timedelta): + expire = datetime.now() + expiry + payload.update({"exp": expire}) + return jwt.encode(payload, secret, algorithm=algo) + +def str_decode(string: str) -> str: + return base64.b85decode(string.encode('ascii')).decode('ascii') + +def generate_random_string(length=12): + characters = string.ascii_letters + string.digits + random_string = ''.join(random.choice(characters) for i in range(length)) + return random_string + +import pytz +from datetime import datetime +def signJWT(user_email: str) -> Dict[str, str]: + rt_expires = timedelta(days=3) + refresh_key = unique_string(100) + access_key = unique_string(50) + at_expires = timedelta(minutes=180) + at_payload = { + "sub": str_encode(str(user_email)), + 'a': access_key, + } + access_token = generate_token(at_payload, JWT_SECRET, JWT_ALGORITHM, at_expires) + rt_payload = {"sub": str_encode(str(user_email)), "t": refresh_key, 'a': access_key} + refresh_token = generate_token(rt_payload, SECRET_KEY,JWT_ALGORITHM, rt_expires) + expires_in = at_expires.seconds + vn_timezone = pytz.timezone('Asia/Ho_Chi_Minh') + current_time = datetime.now().replace(tzinfo=pytz.utc).astimezone(vn_timezone) + timedelta(seconds=expires_in) + formatted_time = current_time.strftime('%Y-%m-%d %H:%M:%S ') + existing_user = UserRepository.getUserByEmail(user_email) + if existing_user is None: + UserRepository.addUser(user_email, access_token, refresh_token, formatted_time) + else: + UserRepository.updateUserLogin(user_email, access_token, refresh_token, formatted_time) + user_record = UserRepository.getUserByEmail(user_email) + session_id = "" + if user_record: + session_id = generate_random_string() + existing_userlogin = UserLoginRepository.getUserLogin(user_email) + if existing_userlogin is None: + UserLoginRepository.addUserLogin(user_email,session_id=session_id) + else: + UserLoginRepository.updateUserLogin(user_email, session_id) + return { + "access_token": access_token, + "refresh_token": refresh_token, + "expires_in": at_expires.seconds, + "session_id": session_id + } + +def returnAccessToken(user_email: str, refresh_token: str) -> Dict[str, str]: + access_key = unique_string(50) + at_expires = timedelta(minutes=180) + at_payload = { + "sub": str_encode(str(user_email)), + 'a': access_key, + } + access_token = generate_token(at_payload, JWT_SECRET, JWT_ALGORITHM, at_expires) + user_record = UserRepository.getUserByEmail(user_email) + session_id = "" + if user_record: + email1 = user_record.email + if email1: + session_id = generate_random_string() + existing_userlogin = UserLoginRepository.getUserLogin(user_email) + if existing_userlogin is None: + UserLoginRepository.addUserLogin(user_email,session_id=session_id) + else: + UserLoginRepository.updateUserLogin(user_email,session_id) + return { + "access_token": access_token, + "refresh_token": refresh_token, + "expires_in": at_expires.seconds, + "session_id": session_id + } + +def decodeJWT(token: str) -> dict: + try: + decoded_token = jwt.decode(token, JWT_SECRET, algorithms=[JWT_ALGORITHM]) + return decoded_token if decoded_token["exp"] >= time.time() else None + except: + return {} + +def get_refresh_token(refresh_token, email): + token_payload = get_token_payload(refresh_token, SECRET_KEY, JWT_ALGORITHM) + if not token_payload: + raise HTTPException(status_code=403, detail="Invalid Request.") + exp = token_payload.get('exp') + if exp >= time.time() and token_payload: + return returnAccessToken(email,refresh_token) + elif not token_payload: + return signJWT(email) \ No newline at end of file diff --git a/controller/AuthenticationController.py b/controller/AuthenticationController.py new file mode 100644 index 0000000000000000000000000000000000000000..f839411473f88a884e114c1125741c5fe1a5c453 --- /dev/null +++ b/controller/AuthenticationController.py @@ -0,0 +1,63 @@ +from fastapi import APIRouter, Query +from request import RequestAuth +from response import ResponseAuth as res +from service import AuthService +from function import support_function +from fastapi import HTTPException +router = APIRouter() + +@router.post('/login', tags=["Authentication"]) +async def login(request: RequestAuth.RequestLoginEmail): + email = request.email + check = support_function.check_value_email_controller(email) + if check is not True: + return check + password = request.password + if password is None or password.strip() == "": + return res.ReponseError(status=400, + data=res.Message(message="Password is required.")) + return await AuthService.login(request) + +@router.post('/login_google', tags=["Authentication"]) +async def login_google(request: RequestAuth.RequestLoginGoogle): + email = request.email + token_google = request.token_google + check = support_function.check_value_email_controller(email) + if check is not True: + return check + if token_google is None or token_google.strip() == "": + return res.ReponseError(status=400, + data=res.Message(message="token_google oauth2 is required.")) + if token_google.isdigit(): + return res.ReponseError(status=400, + data=res.Message(message="token_google must be a string, not a number.")) + return await AuthService.login_google(request) + +@router.post('/sign_up', tags=["Authentication"]) +async def signup(request: RequestAuth.RequestRegister): + email = request.email + check = support_function.check_value_email_controller(email) + if check is not True: + return check + password = request.password + confirm_password = request.confirm_password + if password is None or password.strip( )== "": + return res.ReponseError(status=400, + data=res.Message(message="Password is required.")) + if confirm_password is None or confirm_password.strip() == "": + return res.ReponseError(status=400, + data=res.Message(message="Confirm Password is required.")) + return await AuthService.sign_up(request) + + +@router.post('/refresh_token', tags=["Authentication"]) +async def refresh_token_account(request: RequestAuth.RequestRefreshTokenLogin): + token = request.refresh_token + if token is None or token.strip() == "": + return res.ReponseError(status=400, + data=res.Message(message="token is required.")) + elif token.isdigit(): + return res.ReponseError(status=400, + data=res.Message(message="token must be string")) + + return await AuthService.refresh_token(request) \ No newline at end of file diff --git a/controller/ChatController.py b/controller/ChatController.py new file mode 100644 index 0000000000000000000000000000000000000000..6e6d7df8263f28edbff73bb0df48c59a22f36e9b --- /dev/null +++ b/controller/ChatController.py @@ -0,0 +1,37 @@ +from fastapi import APIRouter, Form, Request +from service import ChatService +from request import RequestChat +from typing import Optional +from fastapi.requests import Request +from function import support_function +from response import ResponseChat as res +from fastapi import Path,Query +router = APIRouter() + +@router.post("/chatbot/query", tags=["Chat"]) +async def handle_query2_upgrade_old(request: Request, + user_id: str = Form(None), + text_all: str = Form(...), + question: Optional[str] = Form(None), + chat_name: Optional[str] = Form(None)): + check = support_function.check_value_user_id_controller(user_id) + if check is not True: + return check + request = RequestChat.RequestQuery2UpgradeOld(user_id=user_id, text_all=text_all, question=question, chat_name=chat_name) + return await ChatService.query2_upgrade_old(request) + +@router.get("/chatbot/extract_file/{user_id}", tags=["Chat"]) +async def extract_file(user_id: str): + check = support_function.check_value_user_id_controller(user_id) + if check is not True: + return check + request = RequestChat.RequestExtractFile(user_id=user_id) + return await ChatService.extract_file(request) + +@router.get("/chatbot/generate_question/{user_id}",tags=["Chat"]) +async def generate_question(user_id: str): + check = support_function.check_value_user_id_controller(user_id) + if check is not True: + return check + request = RequestChat.RequestGenerateQuestion(user_id=user_id) + return await ChatService.generate_question(request) \ No newline at end of file diff --git a/controller/DefaultController.py b/controller/DefaultController.py new file mode 100644 index 0000000000000000000000000000000000000000..c26dcdd9776001bf374c7596a6abb549f5256c13 --- /dev/null +++ b/controller/DefaultController.py @@ -0,0 +1,75 @@ +from fastapi import HTTPException, Depends, Query,APIRouter +from service import DefaultService +from request import RequestDefault +from request import RequestDefault as req +from function import support_function +from auth.authentication import decodeJWT +from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials +from fastapi.responses import JSONResponse +from auth import authentication +from fastapi.requests import Request +from response import ResponseDefault as res +from fastapi import File, UploadFile, Form +router = APIRouter() + +@router.get("/is_me", tags=["Default"]) +async def is_me(token: str = Query(...)): + if token.strip() == "" or token is None: + return res.ReponseError(status=400, + data=res.Message(message="Token field is required.")) + if token.lower() == "none": + return res.ReponseError(status=400, + data=res.Message(message="Token cannot be None.")) + if not isinstance(token, str): + return res.ReponseError(status=400, + data=res.Message(message="Token must be a non-empty string.")) + try: + float(token) + return res.ReponseError(status=400, + data=res.Message(message="Token must be a string, not a number.")) + except ValueError: + pass + request = RequestDefault.RequestIsMe(token=token) + return await DefaultService.is_me(request) + +@router.post('/create_firebase_user_google', tags=["Default"]) +async def get_or_create_firebase_user(request: RequestDefault.RequestCreateFireBaseUserGoogle): + email = request.email + check = support_function.check_value_email_controller(request.email) + if check is not True: + return check + token_google = request.token_google + if token_google == "" or token_google is None: + return res.ReponseError(status=400, + data=res.Message(message="Token field is required.")) + if not isinstance(token_google, str): + return res.ReponseError(status=400, + data=res.Message(message="Token must be a non-empty string.")) + try: + float(token_google) + return res.ReponseError(status=400, + data=res.Message(message="Token must be a string, not a number.")) + except ValueError: + pass + return await DefaultService.create_firebase_user(request) + +@router.get("/info_user/{user_id}", tags=["Default"]) +async def get_user(user_id: str): + check = support_function.check_value_user_id_controller(user_id) + if check is not True: + return check + request = RequestDefault.RequestInfoUser(user_id=user_id) + return await DefaultService.info_user(request) + +ALLOWED_IMAGE_EXTENSIONS = {"jpeg", "jpg", "png"} + +def allowed_file(filename: str) -> bool: + return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_IMAGE_EXTENSIONS + +@router.post("/upload_image", tags=["Default"]) +async def upload_image(user_id: str = Form(None), file: UploadFile = File(...)): + check = support_function.check_value_user_id_controller(user_id) + if check is not True: + return check + request = req.RequestUpLoadImage(user_id=user_id, files= file) + return await DefaultService.upload_image_service(request) \ No newline at end of file diff --git a/controller/FileController.py b/controller/FileController.py new file mode 100644 index 0000000000000000000000000000000000000000..656fe124bfae97f0c9be316ec3bb5665bee3fd19 --- /dev/null +++ b/controller/FileController.py @@ -0,0 +1,64 @@ +from fastapi import APIRouter, Form, File, UploadFile,Query +from typing import List,Optional +from service import FileService +from function import support_function +from fastapi import HTTPException +from response import ResponseFile as res +from request import RequestFile +router = APIRouter() + +ALLOWED_EXTENSIONS = {'csv', 'txt', 'doc', 'docx', 'pdf', 'xlsx', 'pptx', 'json', 'html'} +def allowed_file(filename): + return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS + +@router.delete("/delete", tags=["File"]) +async def delete_folder(request: RequestFile.RequestDeleteAllFile): + check = support_function.check_value_user_id_controller(request.user_id) + if check is not True: + return check + # request = RequestFile.RequestDeleteAllFile(user_id=user_id) + return await FileService.deleteAllFile(request) + +@router.get("/list_name_files", tags=["File"]) +async def get_name(user_id: str): + check = support_function.check_value_user_id_controller(user_id) + if check is not True: + return check + request = RequestFile.RequestGetNameFile(user_id=user_id) + return await FileService.listNameFiles(request) + +@router.delete("/delete_file", tags=["File"]) +async def delete_one_file(request: RequestFile.RequestDeleteFile): + user_id = request.user_id + check = support_function.check_value_user_id_controller(user_id) + if check is not True: + return check + name_file = request.name_file + if name_file is None or name_file.strip() == "": + return res.ReponseError(status=400, + data=res.Message(message="Name file is required.")) + return await FileService.deleteFile(request) + +@router.post("/chatbot/download_folder", tags=["File"]) +async def download_folder_from_dropbox(request: RequestFile.RequestDownLoadFolder): + user_id = request.user_id + check = support_function.check_value_user_id_controller(user_id) + if check is not True: + return check + return await FileService.download_folder(request) + +@router.post("/chatbot/download_files", tags=["File"]) +async def download_file_by_id(request: RequestFile.RequestDownLoadFile): + user_id = request.user_id + check = support_function.check_value_user_id_controller(user_id) + if check is not True: + return check + return await FileService.download_file(request) + +@router.post("/upload_files", tags=["File"]) +async def upload_files_dropbox(user_id: str = Form(None), files: Optional[List[UploadFile]] = File(None)): + check = support_function.check_value_user_id_controller(user_id) + if check is not True: + return check + request = RequestFile.RequestUploadFile(files=files, user_id=user_id) + return await FileService.upload_files(request) \ No newline at end of file diff --git a/controller/MySQLController.py b/controller/MySQLController.py new file mode 100644 index 0000000000000000000000000000000000000000..8130c1487c2b26d404026bc9b154094a47a05ef6 --- /dev/null +++ b/controller/MySQLController.py @@ -0,0 +1,94 @@ +from fastapi import Query, APIRouter +from service import MySQLService +from request import RequestMySQL +from response import ResponseMySQL as res +from typing import Optional +from request import RequestMySQL as req +from function import support_function +from fastapi import HTTPException +router = APIRouter() + +@router.get("/chat_history/{user_id}", tags=["MySQL"]) +async def render_chat(user_id: str): + check = support_function.check_value_user_id_controller(user_id) + if check is not True: + return check + request = RequestMySQL.RequestRenderChatHistory(user_id=user_id) + return await MySQLService.render_chat_history(request) + +@router.get("/data_relevant/{detail_chat_id}", tags=["MySQL"]) +async def render_chat_1(detail_chat_id: str): + if detail_chat_id is None or detail_chat_id.strip() == "": + return res.ReponseError(status=400, + data=res.Message(message="Id field is required.")) + detail_chat_id = detail_chat_id.strip("'").strip('"') + try: + detail_chat_id_int = int(detail_chat_id) + except ValueError: + return res.ReponseError(status=400, + data=res.Message(message="Value must be an integer")) + if not support_function.is_positive_integer(detail_chat_id_int): + return res.ReponseError(status=400, + data=res.Message(message="Value must be greater than 0")) + request = req.RequestGetChatDetails(id=detail_chat_id) + return await MySQLService.get_detail_chat_by_chat_id(request) + +@router.get("/detail_chat/{user_id}/{chat_id}", tags=["MySQL"]) +async def load_chat(chat_id: str, user_id: str): + check = support_function.check_value_user_id_controller(user_id) + if check is not True: + return check + if chat_id is None or chat_id.strip() == "": + return res.ReponseError(status=400, + data=res.Message(message="Chat id field is required.")) + chat_id = chat_id.strip("'").strip('"') + try: + chat_id_int = int(chat_id) + except ValueError: + return res.ReponseError(status=400, + data=res.Message(message="Value must be an integer")) + if not support_function.is_positive_integer(chat_id_int): + return res.ReponseError(status=400, + data=res.Message(message="Value must be greater than 0")) + request = req.RequestLoadChatHistory(chat_id=chat_id,user_id = user_id) + return await MySQLService.load_chat_history(request) + +@router.put("/edit_chat", tags=["MySQL"]) +async def edit_chat(request: RequestMySQL.RequestEditNameChat): + user_id = request.user_id + check = support_function.check_value_user_id_controller(user_id) + if check is not True: + return check + return await MySQLService.edit_chat(request) + +@router.delete("/chat_history/delete", tags=["MySQL"]) +async def delete_chat(request: RequestMySQL.RequestDeleteChat): + user_id = request.user_id + check = support_function.check_value_user_id_controller(user_id) + if check is not True: + return check + return await MySQLService.delete_chat(request) + +@router.delete("/detail_chat/delete", tags=["MySQL"]) +async def delete_chat_detail(request: RequestMySQL.RequestDeleteDetailChat): + user_id = request.user_id + check = support_function.check_value_user_id_controller(user_id) + if check is not True: + return check + return await MySQLService.delete_chat_detail_by_id(request) + +@router.post("/chat_history/create", tags=["MySQL"]) +async def create_chat_history(request: RequestMySQL.RequestCreateChatHistory): + user_id = request.user_id + check = support_function.check_value_user_id_controller(user_id) + if check is not True: + return check + return await MySQLService.create_chat_history(request) + +@router.delete("/chat_history/delete_last_chat_record", tags=["MySQL"]) +async def delete_last_chat_record(request: RequestMySQL.RequestStopChat): + user_id = request.user_id + check = support_function.check_value_user_id_controller(user_id) + if check is not True: + return check + return await MySQLService.delete_last_chat_detail_by_chat_name(request) \ No newline at end of file diff --git a/controller/OTPController.py b/controller/OTPController.py new file mode 100644 index 0000000000000000000000000000000000000000..5dcbc9dcdd160a20d2157e8f910d01b1704fbfe0 --- /dev/null +++ b/controller/OTPController.py @@ -0,0 +1,37 @@ +from fastapi import APIRouter +from function import support_function +from request import RequestOTP +from service import OTPService +from fastapi import HTTPException +from pydantic.error_wrappers import ErrorWrapper +from pydantic import BaseModel +from response import ResponseOTP as res +router = APIRouter() + +@router.post('/create_otp', tags=["OTP"]) +async def create_otp(request: RequestOTP.RequestCreateOTP): + email = request.email + check = support_function.check_value_email_controller(email) + if check is not True: + return check + return await OTPService.createOTP(request) + +@router.post('/verify_otp', tags=["OTP"]) +async def verify_otp(request: RequestOTP.RequestVerifyOTP): + check = support_function.check_value_email_controller(request.email) + if check is not True: + return check + check_otp = support_function.check_value_otp(request.otp) + if check_otp is not True: + return check_otp + return await OTPService.verifyOTP(request) + +@router.post('/verify_otp_reset_password', tags=["OTP"]) +async def verify_otp_reset(request: RequestOTP.RequestVerifyOTP): + check = support_function.check_value_email_controller(request.email) + if check is not True: + return check + check_otp = support_function.check_value_otp(request.otp) + if check_otp is not True: + return check_otp + return await OTPService.verifyOTPReset(request) \ No newline at end of file diff --git a/controller/UserController.py b/controller/UserController.py new file mode 100644 index 0000000000000000000000000000000000000000..95cd8afbad337432db79b8630ae6e90f5fb7e2b7 --- /dev/null +++ b/controller/UserController.py @@ -0,0 +1,96 @@ +from fastapi import APIRouter, Query +from request import RequestUser +from response import ResponseUser as res +from service import UserService +from function import support_function +from fastapi import HTTPException +from response import ResponseUser as res +router = APIRouter() + +@router.put("/update_user_info", tags=["User"]) +async def update_user_info(request: RequestUser.RequestUpdateUserInfo): + user_id = request.user_id + check = support_function.check_value_user_id_controller(user_id) + if check is not True: + return check + uid = request.uid + email = request.email + display_name = request.display_name + photo_url = request.photo_url + if uid is None or uid.strip() == "": + return res.ReponseError(status=400, + data=res.Message(message="uid field is required.")) + if email is None or email.strip() == "": + return res.ReponseError(status=400, + data=res.Message(message="email field is required.")) + if display_name is None or display_name.strip() == "": + return res.ReponseError(status=400, + data=res.Message(message="display_name field is required.")) + if photo_url is None or photo_url.strip() == "": + return res.ReponseError(status=400, + data=res.Message(message="photo_url field is required.")) + return await UserService.update_user_info(request) + +@router.get('/check_info_google', tags=["User"]) +async def check_info_google(user_id: str = Query(None)): + check = support_function.check_value_user_id_controller(user_id) + if check is not True: + return check + request =RequestUser.RequestCheckInfoGoogle(user_id=user_id) + return await UserService.check_info_google(request) + +@router.get('/check_info_google_signup', tags=["User"]) +async def check_info_google_signup(email: str = None): + check = support_function.check_value_email_controller(email) + if check is not True: + return check + request =RequestUser.RequestCheckInfoGoogleEmail(email=email) + return await UserService.check_info_google_email(request) + +@router.get('/check_state_login', tags=["User"]) +async def check_state_login(user_id: str = Query(None), session_id_now: str = Query(None)): + check = support_function.check_value_user_id_controller(user_id) + if check is not True: + return check + if session_id_now is None or session_id_now.strip() == "": + return res.ReponseError(status=400, + data=res.Message(message="Session Id is required.")) + try: + int(session_id_now) + return res.ReponseError(status=400, + data=res.Message(message="Session Id must be a string, not a number.")) + except ValueError: + pass + request =RequestUser.RequestCheckStateLogin(user_id=user_id, session_id_now=session_id_now) + return await UserService.check_state_login(request) + + +@router.post('/reset_password', tags=["User"]) +async def reset_password(request:RequestUser.RequestResetPassword): + email = request.email + check = support_function.check_value_email_controller(email) + if check is not True: + return check + return await UserService.reset_password(request) + +@router.put('/change_password', tags=["User"]) +async def reset_password_firebase(request:RequestUser.RequestChangePassword): + user_id = request.user_id + check = support_function.check_value_user_id_controller(user_id) + if check is not True: + return check + new_password = request.new_password + current_password = request.current_password + confirm_new_password = request.confirm_new_password + if confirm_new_password is None or confirm_new_password.strip() == "": + return res.ReponseError(status=400, + data=res.Message(message="Confirm New password field is required.")) + elif new_password is None or new_password.strip() == "": + return res.ReponseError(status=400, + data=res.Message(message="New password field is required.")) + elif current_password is None or current_password.strip() == "": + return res.ReponseError(status=400, + data=res.Message(message="Current password field is required.")) + return await UserService.change_password(request) + + diff --git a/controller/__pycache__/AuthenticationController.cpython-310.pyc b/controller/__pycache__/AuthenticationController.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b9948d7c5dec280f01c8bc49b0291876d509fdf2 Binary files /dev/null and b/controller/__pycache__/AuthenticationController.cpython-310.pyc differ diff --git a/controller/__pycache__/ChatController.cpython-310.pyc b/controller/__pycache__/ChatController.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..55957fc65b1303b3f2714e1bb527df745dc81f24 Binary files /dev/null and b/controller/__pycache__/ChatController.cpython-310.pyc differ diff --git a/controller/__pycache__/ChatController.cpython-311.pyc b/controller/__pycache__/ChatController.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b561fe72289eadeed68793fb8ba7c363a2fae072 Binary files /dev/null and b/controller/__pycache__/ChatController.cpython-311.pyc differ diff --git a/controller/__pycache__/ChatController.py b/controller/__pycache__/ChatController.py new file mode 100644 index 0000000000000000000000000000000000000000..db2919f2097e9cac56ba1c749e09762e382e61f0 --- /dev/null +++ b/controller/__pycache__/ChatController.py @@ -0,0 +1,35 @@ +from fastapi import APIRouter, Form, Request +from service import ChatService +from request import RequestChat +from typing import Optional +from fastapi.requests import Request +from function import support_function +from response import ResponseChat as res +router = APIRouter() + +@router.post("/chatbot/query/", tags=["Chat"]) +async def handle_query2_upgrade_old(request: Request, + user_id: str = Form(None), + text_all: str = Form(...), question: Optional[str] = Form(None), + chat_name: Optional[str] = Form(None)): + check = support_function.check_value_user_id_controller(user_id) + if check is not True: + return check + request = RequestChat.RequestQuery2UpgradeOld(user_id=user_id, text_all=text_all, question=question, chat_name=chat_name) + return ChatService.query2_upgrade_old(request) + +@router.get("/chatbot/extract_file/", tags=["Chat"]) +async def extract_file(user_id: str): + check = support_function.check_value_user_id_controller(user_id) + if check is not True: + return check + request = RequestChat.RequestExtractFile(user_id=user_id) + return ChatService.extract_file(request) + +@router.get("/chatbot/generate_question/",tags=["Chat"]) +async def generate_question(user_id: str): + check = support_function.check_value_user_id_controller(user_id) + if check is not True: + return check + request = RequestChat.RequestGenerateQuestion(user_id=user_id) + return ChatService.generate_question(request) \ No newline at end of file diff --git a/controller/__pycache__/DefaultController.cpython-310.pyc b/controller/__pycache__/DefaultController.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..155e77b775c8aff18bb4fbc566c651fedea889f1 Binary files /dev/null and b/controller/__pycache__/DefaultController.cpython-310.pyc differ diff --git a/controller/__pycache__/DefaultController.cpython-311.pyc b/controller/__pycache__/DefaultController.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..aefcf79154c52c2ed6faf4e8631ac9eb9c13c26b Binary files /dev/null and b/controller/__pycache__/DefaultController.cpython-311.pyc differ diff --git a/controller/__pycache__/FileController.cpython-310.pyc b/controller/__pycache__/FileController.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..94dffa1157fd11c02ff22ed3c386fbe7007d4b65 Binary files /dev/null and b/controller/__pycache__/FileController.cpython-310.pyc differ diff --git a/controller/__pycache__/FileController.cpython-311.pyc b/controller/__pycache__/FileController.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c870ba061c3fe02da6ecc4032b53ebf23db9117f Binary files /dev/null and b/controller/__pycache__/FileController.cpython-311.pyc differ diff --git a/controller/__pycache__/MySQLController.cpython-310.pyc b/controller/__pycache__/MySQLController.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6642e957c462e0edef897185868c2a37f7c933a2 Binary files /dev/null and b/controller/__pycache__/MySQLController.cpython-310.pyc differ diff --git a/controller/__pycache__/MySQLController.cpython-311.pyc b/controller/__pycache__/MySQLController.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e8f872781f6f6221c3f8cdd7648e795f70d25a92 Binary files /dev/null and b/controller/__pycache__/MySQLController.cpython-311.pyc differ diff --git a/controller/__pycache__/OTPController.cpython-310.pyc b/controller/__pycache__/OTPController.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8dba917ceb1c5be760661c4506b328a86564c629 Binary files /dev/null and b/controller/__pycache__/OTPController.cpython-310.pyc differ diff --git a/controller/__pycache__/OTPController.cpython-311.pyc b/controller/__pycache__/OTPController.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..97b0b284e88a1afd99c661fd019d59d8bfc10638 Binary files /dev/null and b/controller/__pycache__/OTPController.cpython-311.pyc differ diff --git a/controller/__pycache__/UserController.cpython-310.pyc b/controller/__pycache__/UserController.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9b934cf9a1b723349181c72a1ca664380bf11441 Binary files /dev/null and b/controller/__pycache__/UserController.cpython-310.pyc differ diff --git a/function/__pycache__/chatbot.cpython-310.pyc b/function/__pycache__/chatbot.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ba1a8a4e996a11123adfdaf0fc7b5575ba333769 Binary files /dev/null and b/function/__pycache__/chatbot.cpython-310.pyc differ diff --git a/function/__pycache__/chatbot.cpython-311.pyc b/function/__pycache__/chatbot.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6b4e3daf9444117f02731efe02b251f49a99b6e9 Binary files /dev/null and b/function/__pycache__/chatbot.cpython-311.pyc differ diff --git a/function/__pycache__/dropbox.cpython-310.pyc b/function/__pycache__/dropbox.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..04a62e246d5499fab47c7ee80f16efd094bc02ae Binary files /dev/null and b/function/__pycache__/dropbox.cpython-310.pyc differ diff --git a/function/__pycache__/dropbox.cpython-311.pyc b/function/__pycache__/dropbox.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b06da5f0808ccb370a606cc2991bdd209d2532c9 Binary files /dev/null and b/function/__pycache__/dropbox.cpython-311.pyc differ diff --git a/function/__pycache__/support_function.cpython-310.pyc b/function/__pycache__/support_function.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1dd574d6dfe4925d25c4441f51e5db6b3778ecf7 Binary files /dev/null and b/function/__pycache__/support_function.cpython-310.pyc differ diff --git a/function/__pycache__/support_function.cpython-311.pyc b/function/__pycache__/support_function.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6899d2572ebbaec8c62552f6f561f8713b90666b Binary files /dev/null and b/function/__pycache__/support_function.cpython-311.pyc differ diff --git a/function/chatbot.py b/function/chatbot.py new file mode 100644 index 0000000000000000000000000000000000000000..618a52f40daccf8c1585a1c301a2f7eb4e326e4b --- /dev/null +++ b/function/chatbot.py @@ -0,0 +1,726 @@ +from langchain.text_splitter import CharacterTextSplitter +import json +import os +import random +import re +from concurrent.futures import ThreadPoolExecutor, as_completed +import google.generativeai as genai +import nltk +import pandas as pd +from groq import Groq +from langchain.chains.summarize import load_summarize_chain +from langchain.docstore.document import Document +from langchain.prompts import PromptTemplate +from langchain.retrievers import BM25Retriever, EnsembleRetriever +from langchain.retrievers.contextual_compression import ContextualCompressionRetriever +from langchain.text_splitter import CharacterTextSplitter +from langchain.text_splitter import RecursiveCharacterTextSplitter +from langchain_cohere import CohereRerank +from langchain_community.document_loaders import Docx2txtLoader +from langchain_community.document_loaders import TextLoader +from langchain_community.document_loaders import UnstructuredCSVLoader +from langchain_community.document_loaders import UnstructuredExcelLoader +from langchain_community.document_loaders import UnstructuredHTMLLoader +from langchain_community.document_loaders import UnstructuredMarkdownLoader +from langchain_community.document_loaders import UnstructuredPDFLoader +from langchain_community.document_loaders import UnstructuredPowerPointLoader +from langchain_community.document_loaders import UnstructuredXMLLoader +from langchain_community.document_loaders.csv_loader import CSVLoader +from langchain_community.llms import Cohere +from langchain_community.vectorstores import Chroma +from langchain_core.output_parsers.openai_tools import PydanticToolsParser +from langchain_core.prompts import ChatPromptTemplate +from langchain_core.pydantic_v1 import BaseModel, Field +from langchain_core.runnables import RunnablePassthrough +from langchain_openai import ChatOpenAI +from typing import List +from nltk.corpus import stopwords +from nltk.tokenize import word_tokenize +nltk.download('punkt') + +def process_json_file(file_path): + json_data = [] + with open(file_path, 'r') as file: + for line in file: + try: + data = json.loads(line) + json_data.append(data) + except json.JSONDecodeError: + try: + data = json.loads(line[:-1]) + json_data.append(data) + except json.JSONDecodeError as e: + print(f"Error decoding JSON: {e}") + return json_data + +from dotenv import load_dotenv +import os +load_dotenv() +GROQ_API_KEY = os.getenv("GROQ_API_KEY") +COHERE_API_KEY = os.getenv("COHERE_API_KEY") +OPENAI_API_KEY = os.getenv("OPENAI_API_KEY") +GOOGLE_API_KEY1= os.getenv("GOOGLE_API_KEY_1") +GOOGLE_API_KEY= os.getenv("GOOGLE_API_KEY") +os.environ["COHERE_API_KEY"] = COHERE_API_KEY +os.environ["OPENAI_API_KEY"] = OPENAI_API_KEY +client = Groq( + api_key= GROQ_API_KEY, +) +genai.configure(api_key=GOOGLE_API_KEY1) +os.environ["GOOGLE_API_KEY"] = GOOGLE_API_KEY +from langchain_google_genai import GoogleGenerativeAIEmbeddings, ChatGoogleGenerativeAI +embeddings = GoogleGenerativeAIEmbeddings(model="models/embedding-001", task_type="retrieval_document") +llm = ChatGoogleGenerativeAI(model='gemini-pro', + max_output_tokens=2048, + temperature=0.2, + convert_system_message_to_human=True) +def extract_multi_metadata_content(texts, tests): + extracted_content = [] + precomputed_metadata = [x.metadata['source'].lower() for x in texts] + for idx, test in enumerate(tests): + temp_content = [] + test_terms = set(test.lower().split()) + for metadata_lower, x in zip(precomputed_metadata, texts): + if any(term in metadata_lower for term in test_terms): + temp_content.append(x.page_content) + if idx == 0: + extracted_content.append(f"Dữ liệu của {test}:\n{''.join(temp_content)}") + else: + extracted_content.append(''.join(temp_content)) + return '\n'.join(extracted_content) +import unicodedata +def text_preprocessing(text): + text = text.lower() + emoji_pattern = re.compile("[" + u"\U0001F600-\U0001F64F" # emoticons + u"\U0001F300-\U0001F5FF" # symbols & pictographs + u"\U0001F680-\U0001F6FF" # transport & map symbols + u"\U0001F1E0-\U0001F1FF" # flags (iOS) + u"\U00002500-\U00002BEF" # chinese char + u"\U00002702-\U000027B0" + u"\U000024C2-\U0001F251" + u"\U0001f926-\U0001f937" + u"\U00010000-\U0010ffff" + u"\u2640-\u2642" + u"\u2600-\u2B55" + u"\u200d" + u"\u23cf" + u"\u23e9" + u"\u231a" + u"\ufe0f" # dingbats + u"\u3030" + "]+", flags=re.UNICODE) + text = emoji_pattern.sub(r'', text) + text = unicodedata.normalize('NFC', text) + words = text.split() + text = ' '.join(words) + return text +def find_matching_files_in_docs_12_id(text, id): + folder_path = f"./user_file/{id}" + search_terms = [] + search_terms_old = [] + matching_index = [] + search_origin = re.findall(r'\b\w+\.\w+\b|\b\w+\b', text) + search_terms_origin = [] + for word in search_origin: + if '.' in word: + search_terms_origin.append(word) + else: + search_terms_origin.extend(re.findall(r'\b\w+\b', word)) + + file_names_with_extension = re.findall(r'\b\w+\.\w+\b|\b\w+\b', text.lower()) + file_names_with_extension_old = re.findall(r'\b(\w+\.\w+)\b', text) + for file_name in search_terms_origin: + if "." in file_name: + search_terms_old.append(file_name) + for file_name in file_names_with_extension_old: + if "." in file_name: + search_terms_old.append(file_name) + for file_name in file_names_with_extension: + search_terms.append(file_name) + clean_text_old = text + clean_text = text.lower() + for term in search_terms_old: + clean_text_old = clean_text_old.replace(term, '') + for term in search_terms: + clean_text = clean_text.replace(term, '') + words_old = re.findall(r'\b\w+\b', clean_text_old) + search_terms_old.extend(words_old) + matching_files = set() + for root, dirs, files in os.walk(folder_path): + for file in files: + for term in search_terms: + if term.lower() in file.lower(): + term_position = search_terms.index(term) + matching_files.add(file) + matching_index.append(term_position) + break + matching_files_old1 = [] + matching_index.sort() + for x in matching_index: + matching_files_old1.append(search_terms_origin[x]) + return matching_files, matching_files_old1 + +def convert_xlsx_to_csv(xlsx_file_path, csv_file_path): + df = pd.read_excel(xlsx_file_path) + df.to_csv(csv_file_path, index=False) + +def save_list_CSV_id(file_list, id): + text = "" + for x in file_list: + if x.endswith('.xlsx'): + old = f"./user_file/{id}/{x}" + new = old.replace(".xlsx", ".csv") + convert_xlsx_to_csv(old, new) + x = x.replace(".xlsx", ".csv") + loader1 = CSVLoader(f"./user_file/{id}/{x}") + docs1 = loader1.load() + text += f"Dữ liệu file {x}:\n" + for z in docs1: + text += z.page_content + "\n" + return text + +def merge_files(file_set, file_list): + """Hàm này ghép lại các tên file dựa trên điều kiện đã cho.""" + merged_files = {} + for file_name in file_list: + name = file_name.split('.')[0] + for f in file_set: + if name in f: + merged_files[name] = f + break + return merged_files + +def replace_keys_with_values(original_dict, replacement_dict): + new_dict = {} + for key, value in original_dict.items(): + if key in replacement_dict: + new_key = replacement_dict[key] + new_dict[new_key] = value + else: + new_dict[key] = value + return new_dict + +def aws1_csv_id(new_dict_csv, id): + text = "" + query_all = "" + keyword = [] + for key, value in new_dict_csv.items(): + print(key, value) + query_all += value + keyword.append(key) + test = save_list_CSV_id(keyword, id) + text += test + sources = ",".join(keyword) + return text, query_all, sources + +def chat_llama3(prompt_query): + try: + chat_completion = client.chat.completions.create( + messages=[ + { + "role": "system", + "content": "Bạn là một trợ lý trung thưc, trả lời dựa trên nội dung tài liệu được cung cấp. Chỉ trả lời liên quan đến câu hỏi một cách đầy đủ chính xác, không bỏ sót thông tin." + }, + { + + "role": "user", + "content": f"{prompt_query}", + } + ], + model="llama3-70b-8192", + temperature=0.0, + max_tokens=9000, + stop=None, + stream=False, + ) + return chat_completion.choices[0].message.content + except Exception as error: + return False + +def chat_gemini(prompt): + generation_config = { + "temperature": 0.0, + "top_p": 0.0, + "top_k": 0, + "max_output_tokens": 8192, + } + safety_settings = [ + { + "category": "HARM_CATEGORY_HARASSMENT", + "threshold": "BLOCK_MEDIUM_AND_ABOVE" + }, + { + "category": "HARM_CATEGORY_HATE_SPEECH", + "threshold": "BLOCK_MEDIUM_AND_ABOVE" + }, + { + "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", + "threshold": "BLOCK_MEDIUM_AND_ABOVE" + }, + { + "category": "HARM_CATEGORY_DANGEROUS_CONTENT", + "threshold": "BLOCK_MEDIUM_AND_ABOVE" + }, + ] + model = genai.GenerativeModel(model_name="gemini-1.5-pro-latest", + generation_config=generation_config, + safety_settings=safety_settings) + convo = model.start_chat(history=[]) + convo.send_message(prompt) + return convo.last.text + +def question_answer(question): + completion = chat_llama3(question) + if completion: + return completion + else: + answer = chat_gemini(question) + return answer + +def check_persist_directory(id, file_name): + directory_path = f"./vector_database/{id}/{file_name}" + return os.path.exists(directory_path) + +from langchain_community.vectorstores import FAISS + +def check_path_exists(path): + return os.path.exists(path) +def aws1_all_id(new_dict, text_alls, id, thread_id): + answer = "" + COHERE_API_KEY1 = os.getenv("COHERE_API_KEY_1") + os.environ["COHERE_API_KEY"] = COHERE_API_KEY1 + answer_relevant = "" + directory = "" + for key, value in new_dict.items(): + query = value + query = text_preprocessing(query) + keyword, keyword2 = find_matching_files_in_docs_12_id(query, id) + data = extract_multi_metadata_content(text_alls, keyword) + if keyword: + file_name = next(iter(keyword)) + text_splitter = CharacterTextSplitter(chunk_size=3200, chunk_overlap=1500) + texts_data = text_splitter.split_text(data) + + if check_persist_directory(id, file_name): + vectordb_query = Chroma(persist_directory=f"./vector_database/{id}/{file_name}", embedding_function=embeddings) + else: + vectordb_query = Chroma.from_texts(texts_data, + embedding=embeddings, + persist_directory=f"./vector_database/{id}/{file_name}") + + k_1 = len(texts_data) + retriever = vectordb_query.as_retriever(search_kwargs={f"k": k_1}) + bm25_retriever = BM25Retriever.from_texts(texts_data) + bm25_retriever.k = k_1 + ensemble_retriever = EnsembleRetriever(retrievers=[bm25_retriever, retriever], + weights=[0.6, 0.4]) + docs = ensemble_retriever.get_relevant_documents(f"{query}") + + path = f"./vector_database/FAISS/{id}/{file_name}" + if check_path_exists(path): + docsearch = FAISS.load_local(path, embeddings, allow_dangerous_deserialization=True) + else: + docsearch = FAISS.from_documents(docs, embeddings) + docsearch.save_local(f"./vector_database/FAISS/{id}/{file_name}") + docsearch = FAISS.load_local(path, embeddings, allow_dangerous_deserialization=True) + + k_2 = len(docs) + compressor = CohereRerank(top_n=3) + retrieve3 = docsearch.as_retriever(search_kwargs={f"k": k_2}) + compression_retriever = ContextualCompressionRetriever( + base_compressor=compressor, base_retriever=retrieve3 + ) + compressed_docs = compression_retriever.get_relevant_documents(f"{query}") + + if compressed_docs: + data = compressed_docs[0].page_content + text = ''.join(map(lambda x: x.page_content, compressed_docs)) + prompt_document = f"Dựa vào nội dung sau:{text}. Hãy trả lời câu hỏi sau đây: {query}. Mà không thay đổi nội dung mà mình đã cung cấp. Cuối cùng nếu câu hỏi sử dụng tiếng Việt thì phải trả lời bằng Vietnamese. Nếu câu hỏi sử dụng tiếng Anh phải trả lời bằng English" + answer_for = question_answer(prompt_document) + answer += answer_for + "\n" + answer_relevant = data + directory = file_name + + return answer, answer_relevant, directory + + +def extract_content_between_keywords(query, keywords): + contents = {} + num_keywords = len(keywords) + keyword_positions = [] + for i in range(num_keywords): + keyword = keywords[i] + keyword_position = query.find(keyword) + keyword_positions.append(keyword_position) + if keyword_position == -1: + continue + next_keyword_position = len(query) + for j in range(i + 1, num_keywords): + next_keyword = keywords[j] + next_keyword_position = query.find(next_keyword) + if next_keyword_position != -1: + break + if i == 0: + content_before = query[:keyword_position].strip() + else: + content_before = query[keyword_positions[i - 1] + len(keywords[i - 1]):keyword_position].strip() + if i == num_keywords - 1: + content_after = query[keyword_position + len(keyword):].strip() + else: + content_after = query[keyword_position + len(keyword):next_keyword_position].strip() + content = f"{content_before} {keyword} {content_after}" + contents[keyword] = content + return contents + +def generate_random_questions(filtered_ques_list): + if len(filtered_ques_list) >= 2: + random_questions = random.sample(filtered_ques_list, 2) + else: + random_questions = filtered_ques_list + return random_questions + +def generate_question_main(loader, name_file): + text_splitter = RecursiveCharacterTextSplitter(chunk_size=4500, chunk_overlap=2500) + texts = text_splitter.split_documents(loader) + question_gen = f"nội dung {name_file} : \n" + question_gen += texts[0].page_content + splitter_ques_gen = RecursiveCharacterTextSplitter( + chunk_size=4500, + chunk_overlap=2200 + ) + chunks_ques_gen = splitter_ques_gen.split_text(question_gen) + document_ques_gen = [Document(page_content=t) for t in chunks_ques_gen] + llm_ques_gen_pipeline = llm + prompt_template_vn = """ + Bạn là một chuyên gia tạo câu hỏi dựa trên tài liệu và tài liệu hướng dẫn. + Bạn làm điều này bằng cách đặt các câu hỏi về đoạn văn bản dưới đây: + + ------------ + {text} + ------------ + + Hãy tạo ra các câu hỏi từ đoạn văn bản này.Nếu đoạn văn là tiếng Việt hãy tạo câu hỏi tiếng Việt. Nếu đoạn văn là tiếng Anh hãy tạo câu hỏi tiếng Anh. + Hãy chắc chắn không bỏ sót bất kỳ thông tin quan trọng nào. Và chỉ tạo với đoạn tài liệu đó tối đa 5 câu hỏi liên quan tới tài liệu cung cấp nhất.Nếu trong đoạn tài liệu có các tên liên quan đến file như demo1.pdf( nhiều file khác) thì phải kèm nó vào nội dung câu hỏi bạn tạo ra. + + CÁC CÂU HỎI: + """ + + PROMPT_QUESTIONS_VN = PromptTemplate(template=prompt_template_vn, input_variables=["text"]) + refine_template_vn = (""" + Bạn là một chuyên gia tạo câu hỏi thực hành dựa trên tài liệu và tài liệu hướng dẫn. + Mục tiêu của bạn là giúp người học chuẩn bị cho một kỳ thi. + Chúng tôi đã nhận được một số câu hỏi thực hành ở mức độ nào đó: {existing_answer}. + Chúng tôi có thể tinh chỉnh các câu hỏi hiện có hoặc thêm câu hỏi mới + (chỉ khi cần thiết) với một số ngữ cảnh bổ sung dưới đây. + ------------ + {text} + ------------ + + Dựa trên ngữ cảnh mới, hãy tinh chỉnh các câu hỏi bằng tiếng Việt nếu đoạn văn đó cung cấp tiếng Việt. Nếu không hãy tinh chỉnh câu hỏi bằng tiếng Anh nếu đoạn đó cung cấp tiếng Anh. + Nếu ngữ cảnh không hữu ích, vui lòng cung cấp các câu hỏi gốc. Và chỉ tạo với đoạn tài liệu đó tối đa 5 câu hỏi liên quan tới tài liệu cung cấp nhất. Nếu trong đoạn tài liệu có các tên file thì phải kèm nó vào câu hỏi. + CÁC CÂU HỎI: + """ + ) + + REFINE_PROMPT_QUESTIONS = PromptTemplate( + input_variables=["existing_answer", "text"], + template=refine_template_vn, + ) + ques_gen_chain = load_summarize_chain(llm=llm_ques_gen_pipeline, + chain_type="refine", + verbose=True, + question_prompt=PROMPT_QUESTIONS_VN, + refine_prompt=REFINE_PROMPT_QUESTIONS) + ques = ques_gen_chain.run(document_ques_gen) + ques_list = ques.split("\n") + filtered_ques_list = ["{}: {}".format(name_file, re.sub(r'^\d+\.\s*', '', element)) for element in ques_list if + element.endswith('?') or element.endswith('.')] + return generate_random_questions(filtered_ques_list) + +def load_file(loader): + return loader.load() + +def extract_data2(id): + documents = [] + directory_path = f"./user_file/{id}" + if not os.path.exists(directory_path) or not any( + os.path.isfile(os.path.join(directory_path, f)) for f in os.listdir(directory_path)): + return False + tasks = [] + with ThreadPoolExecutor() as executor: + for file in os.listdir(directory_path): + if file.endswith(".pdf"): + pdf_path = os.path.join(directory_path, file) + loader = UnstructuredPDFLoader(pdf_path) + tasks.append(executor.submit(load_file, loader)) + elif file.endswith('.docx') or file.endswith('.doc'): + doc_path = os.path.join(directory_path, file) + loader = Docx2txtLoader(doc_path) + tasks.append(executor.submit(load_file, loader)) + elif file.endswith('.txt'): + txt_path = os.path.join(directory_path, file) + loader = TextLoader(txt_path, encoding="utf8") + tasks.append(executor.submit(load_file, loader)) + elif file.endswith('.pptx'): + ppt_path = os.path.join(directory_path, file) + loader = UnstructuredPowerPointLoader(ppt_path) + tasks.append(executor.submit(load_file, loader)) + elif file.endswith('.csv'): + csv_path = os.path.join(directory_path, file) + loader = UnstructuredCSVLoader(csv_path) + tasks.append(executor.submit(load_file, loader)) + elif file.endswith('.xlsx'): + excel_path = os.path.join(directory_path, file) + loader = UnstructuredExcelLoader(excel_path) + tasks.append(executor.submit(load_file, loader)) + elif file.endswith('.json'): + json_path = os.path.join(directory_path, file) + loader = TextLoader(json_path) + tasks.append(executor.submit(load_file, loader)) + elif file.endswith('.md'): + md_path = os.path.join(directory_path, file) + loader = UnstructuredMarkdownLoader(md_path) + tasks.append(executor.submit(load_file, loader)) + for future in as_completed(tasks): + result = future.result() + documents.extend(result) + text_splitter = CharacterTextSplitter(chunk_size=4500, chunk_overlap=2500 + ) + texts = text_splitter.split_documents(documents) + Chroma.from_documents(documents=texts, + embedding=embeddings, + persist_directory=f"./vector_database/{id}") + return texts + +def generate_question(id): + directory_path = f"./user_file/{id}" + if not os.path.exists(directory_path) or not any( + os.path.isfile(os.path.join(directory_path, f)) for f in os.listdir(directory_path)): + return False + all_questions = [] + tasks = [] + with ThreadPoolExecutor() as executor: + for file in os.listdir(directory_path): + if file.endswith(".pdf"): + pdf_path = os.path.join(directory_path, file) + loader = UnstructuredPDFLoader(pdf_path).load() + tasks.append(executor.submit(generate_question_main, loader, file)) + elif file.endswith('.docx') or file.endswith('.doc'): + doc_path = os.path.join(directory_path, file) + loader = Docx2txtLoader(doc_path).load() + tasks.append(executor.submit(generate_question_main, loader, file)) + elif file.endswith('.txt'): + txt_path = os.path.join(directory_path, file) + loader = TextLoader(txt_path, encoding="utf8").load() + tasks.append(executor.submit(generate_question_main, loader, file)) + elif file.endswith('.pptx'): + ppt_path = os.path.join(directory_path, file) + loader = UnstructuredPowerPointLoader(ppt_path).load() + tasks.append(executor.submit(generate_question_main, loader, file)) + elif file.endswith('.json'): + json_path = os.path.join(directory_path, file) + loader = TextLoader(json_path, encoding="utf8").load() + tasks.append(executor.submit(generate_question_main, loader, file)) + elif file.endswith('.md'): + md_path = os.path.join(directory_path, file) + loader = UnstructuredMarkdownLoader(md_path).load() + tasks.append(executor.submit(generate_question_main, loader, file)) + for future in as_completed(tasks): + result = future.result() + all_questions.extend(result) + return all_questions + +class Search(BaseModel): + queries: List[str] = Field( + ..., + description="Truy vấn riêng biệt để tìm kiếm, giữ nguyên ý chính câu hỏi riêng biệt", + ) + +def query_analyzer(query): + output_parser = PydanticToolsParser(tools=[Search]) + system = """Bạn có khả năng đưa ra các truy vấn tìm kiếm chính xác để lấy thông tin giúp trả lời các yêu cầu của người dùng. Các truy vấn của bạn phải chính xác, không được bỏ ngắn rút gọn. + Nếu bạn cần tra cứu hai hoặc nhiều thông tin riêng biệt, bạn có thể làm điều đó!. Trả lời câu hỏi bằng tiếng Việt(Vietnamese), không được dùng ngôn ngữ khác""" + prompt = ChatPromptTemplate.from_messages( + [ + ("system", system), + ("human", "{question}"), + ] + ) + llm = ChatOpenAI(model="gpt-3.5-turbo-0125", temperature=0.0) + structured_llm = llm.with_structured_output(Search) + query_analyzer = {"question": RunnablePassthrough()} | prompt | structured_llm + text = query_analyzer.invoke(query) + return text + +def handle_query(question, text_all, compression_retriever, id, thread_id): + COHERE_API_KEY_3 = os.environ["COHERE_API_KEY_3"] + os.environ["COHERE_API_KEY"] = COHERE_API_KEY_3 + query = question + x = query + keyword, key_words_old = find_matching_files_in_docs_12_id(query, id) + # if keyword == set() or key_words_old == list(): + # return "Not found file" + file_list = keyword + + if file_list: + list_keywords2 = list(key_words_old) + contents1 = extract_content_between_keywords(query, list_keywords2) + merged_result = merge_files(keyword, list_keywords2) + original_dict = contents1 + replacement_dict = merged_result + new_dict = replace_keys_with_values(original_dict, replacement_dict) + files_to_remove = [filename for filename in new_dict.keys() if + filename.endswith('.xlsx') or filename.endswith('.csv')] + removed_files = {} + for filename in files_to_remove: + removed_files[filename] = new_dict[filename] + for filename in files_to_remove: + new_dict.pop(filename) + test_csv = "" + text_csv, query_csv, source = aws1_csv_id(removed_files, id) + prompt_csv = "" + answer_csv = "" + if test_csv: + prompt_csv = f"Dựa vào nội dung sau: {text_csv}. Hãy trả lời câu hỏi sau đây: {query_csv}.Bằng tiếng Việt" + answer_csv = question_answer(prompt_csv) + answer_document, data_relevant, source = aws1_all_id(new_dict, text_all, id, thread_id) + answer_all1 = answer_document + answer_csv + return answer_all1, data_relevant, source + else: + compressed_docs = compression_retriever.get_relevant_documents(f"{query}") + relevance_score_float = float(compressed_docs[0].metadata['relevance_score']) + print(relevance_score_float) + if relevance_score_float <= 0.12: + documents1 = [] + for file in os.listdir(f"./user_file/{id}"): + if file.endswith('.csv'): + csv_path = f"./user_file/{id}/" + file + loader = UnstructuredCSVLoader(csv_path) + documents1.extend(loader.load()) + elif file.endswith('.xlsx'): + excel_path = f"./user_file/{id}/" + file + loader = UnstructuredExcelLoader(excel_path) + documents1.extend(loader.load()) + text_splitter_csv = CharacterTextSplitter.from_tiktoken_encoder(chunk_size=2200, chunk_overlap=1500) + texts_csv = text_splitter_csv.split_documents(documents1) + vectordb_csv = Chroma.from_documents(documents=texts_csv, + embedding=embeddings, persist_directory=f'./vector_database/csv/{thread_id}') + k = len(texts_csv) + retriever_csv = vectordb_csv.as_retriever(search_kwargs={"k": k}) + llm = Cohere(temperature=0) + compressor_csv = CohereRerank(top_n=3, model="rerank-english-v2.0") + compression_retriever_csv = ContextualCompressionRetriever( + base_compressor=compressor_csv, base_retriever=retriever_csv + ) + compressed_docs_csv = compression_retriever_csv.get_relevant_documents(f"{query}") + file_path = compressed_docs_csv[0].metadata['source'] + print(file_path) + if file_path.endswith('.xlsx'): + new = file_path.replace(".xlsx", ".csv") + convert_xlsx_to_csv(file_path, new) + loader1 = CSVLoader(new) + else: + loader1 = CSVLoader(file_path) + docs1 = loader1.load() + text = " " + for z in docs1: + text += z.page_content + "\n" + prompt_csv = f"Dựa vào nội dung sau: {text}. Hãy trả lời câu hỏi sau đây: {query}. Bằng tiếng Việt" + answer_csv = question_answer(prompt_csv) + return answer_csv + else: + file_path = compressed_docs[0].metadata['source'] + file_path = file_path.replace('\\', '/') + print(file_path) + if file_path.endswith(".pdf"): + loader = UnstructuredPDFLoader(file_path) + elif file_path.endswith('.docx') or file_path.endswith('doc'): + loader = Docx2txtLoader(file_path) + elif file_path.endswith('.txt'): + loader = TextLoader(file_path, encoding="utf8") + elif file_path.endswith('.pptx'): + loader = UnstructuredPowerPointLoader(file_path) + elif file_path.endswith('.xml'): + loader = UnstructuredXMLLoader(file_path) + elif file_path.endswith('.html'): + loader = UnstructuredHTMLLoader(file_path) + elif file_path.endswith('.json'): + loader = TextLoader(file_path) + elif file_path.endswith('.md'): + loader = UnstructuredMarkdownLoader(file_path) + elif file_path.endswith('.xlsx'): + file_path_new = file_path.replace(".xlsx", ".csv") + convert_xlsx_to_csv(file_path, file_path_new) + loader = CSVLoader(file_path_new) + elif file_path.endswith('.csv'): + loader = CSVLoader(file_path) + text_splitter = CharacterTextSplitter(chunk_size=3200, chunk_overlap=1500) + texts = text_splitter.split_documents(loader.load()) + k_1 = len(texts) + file_name = os.path.basename(file_path) + if check_persist_directory(id, file_name): + vectordb_file = Chroma(persist_directory=f"./vector_database/{id}/{file_name}", + embedding_function=embeddings) + else: + vectordb_file = Chroma.from_documents(texts, + embedding=embeddings, + persist_directory=f"./vector_database/{id}/{file_name}") + retriever_file = vectordb_file.as_retriever(search_kwargs={f"k": k_1}) + bm25_retriever = BM25Retriever.from_documents(texts) + bm25_retriever.k = k_1 + ensemble_retriever = EnsembleRetriever(retrievers=[bm25_retriever, retriever_file], + weights=[0.6, 0.4]) + docs = ensemble_retriever.get_relevant_documents(f"{query}") + + path = f"./vector_database/FAISS/{id}/{file_name}" + if check_path_exists(path): + docsearch = FAISS.load_local(path, embeddings, allow_dangerous_deserialization=True) + else: + docsearch = FAISS.from_documents(docs, embeddings) + docsearch.save_local(f"./vector_database/FAISS/{id}/{file_name}") + docsearch = FAISS.load_local(path, embeddings, allow_dangerous_deserialization=True) + k_2 = len(docs) + retrieve3 = docsearch.as_retriever(search_kwargs={f"k": k_2}) + compressor_file = CohereRerank(top_n=3, model="rerank-english-v2.0") + compression_retriever_file = ContextualCompressionRetriever( + base_compressor=compressor_file, base_retriever=retrieve3 + ) + compressed_docs_file = compression_retriever_file.get_relevant_documents(f"{x}") + query = question + text = ''.join(map(lambda x: x.page_content, compressed_docs_file)) + prompt = f"Dựa vào nội dung sau:{text}. Hãy trả lời câu hỏi sau đây: {query}. Mà không thay đổi, chỉnh sửa nội dung mà mình đã cung cấp" + answer = question_answer(prompt) + list_relevant = compressed_docs_file[0].page_content + source = file_name + return answer, list_relevant, source +import concurrent.futures +def handle_query_upgrade_keyword_old(query_all, text_all, id,chat_history): + COHERE_API_KEY_2 = os.environ["COHERE_API_KEY_2"] + os.environ["COHERE_API_KEY"] = COHERE_API_KEY_2 + test = query_analyzer(query_all) + test_string = str(test) + matches = re.findall(r"'([^']*)'", test_string) + vectordb = Chroma(persist_directory=f"./vector_database/{id}", embedding_function=embeddings) + k = len(text_all) + retriever = vectordb.as_retriever(search_kwargs={"k": k}) + compressor = CohereRerank(top_n=5, model="rerank-english-v2.0") + compression_retriever = ContextualCompressionRetriever(base_compressor=compressor, base_retriever= retriever) + with concurrent.futures.ThreadPoolExecutor() as executor: + futures = {executor.submit(handle_query, query, text_all, compression_retriever, id, i): query for i, query in + enumerate(matches)} + results = [] + data_relevant = [] + sources = [] + for future in as_completed(futures): + try: + result, list_data, list_source = future.result() + results.append(result) + data_relevant.append(list_data) + sources.append(list_source) + except Exception as e: + print(f'An error occurred: {e}') + answer_all = ''.join(results) + prompt1 = f"Dựa vào nội dung sau: {answer_all}. Hãy trả lời câu hỏi sau đây: {query_all}. Lưu ý rằng ngữ cảnh của cuộc trò chuyện này trước đây là: {chat_history}. Vui lòng trả lời câu hỏi mà không thay đổi, chỉnh sửa nội dung mà mình đã cung cấp." + answer1 = question_answer(prompt1) + return answer1, data_relevant, sources \ No newline at end of file diff --git a/function/dropbox.py b/function/dropbox.py new file mode 100644 index 0000000000000000000000000000000000000000..71a944b433ed0031e9ca1952b0411093aa15f778 --- /dev/null +++ b/function/dropbox.py @@ -0,0 +1,155 @@ +import dropbox.files +import os +import shutil +import requests, base64 +from fastapi import HTTPException +from dotenv import load_dotenv +import os +load_dotenv() +DROPBOX_APP_KEY=os.getenv('DROPBOX_APP_KEY') +DROPBOX_APP_SECRET=os.getenv('DROPBOX_APP_SECRET') +DROPBOX_REFRESH_TOKEN=os.getenv('DROPBOX_REFRESH_TOKEN') + +def refresh_token_dropbox(): + app_key = DROPBOX_APP_KEY + app_secret = DROPBOX_APP_SECRET + refresh_token = DROPBOX_REFRESH_TOKEN + url = 'https://api.dropbox.com/oauth2/token' + auth_string = f"{app_key}:{app_secret}" + base64authorization = base64.b64encode(auth_string.encode()).decode('utf-8') + headers = { + 'Authorization': f'Basic {base64authorization}', + 'Content-Type': 'application/x-www-form-urlencoded' + } + data = { + 'refresh_token': refresh_token, + 'grant_type': 'refresh_token' + } + response = requests.post(url, headers=headers, data=data) + response_json = response.json() + access_token = response_json.get('access_token', None) + return access_token + +def delete_file(id,name_file): + try: + TOKEN = refresh_token_dropbox() + dbx=dropbox.Dropbox(TOKEN) + file_path = f"/{id}/{name_file}" + dbx.files_delete_v2(file_path) + print(f"Xóa file '{file_path}' thành công.") + except dropbox.exceptions.ApiError as e: + print(f"Lỗi khi xóa file '{file_path}': {e}") + +def list_files(id): + file_names = [] + try: + TOKEN = refresh_token_dropbox() + dbx=dropbox.Dropbox(TOKEN) + result = dbx.files_list_folder(f"/{id}") + for entry in result.entries: + if isinstance(entry, dropbox.files.FileMetadata): + file_names.append(os.path.basename(entry.path_display)) + except dropbox.exceptions.ApiError as e: + print(f"Error listing files: {e}") + return file_names + +def upload_file_fix(local_path,cloud_path,token): + try: + TOKEN = refresh_token_dropbox() + dbx=dropbox.Dropbox(TOKEN) + with open(local_path, "rb") as f: + data = f.read() + dbx.files_upload(data, cloud_path) + print(f"Uploaded file '{local_path}' to '{cloud_path}'") + except dropbox.exceptions.ApiError as e: + print(f"Error uploading file '{local_path}': {e}") + +def upload_file(local_path, cloud_path): + try: + TOKEN = refresh_token_dropbox() + dbx=dropbox.Dropbox(TOKEN) + with open(local_path, "rb") as f: + data = f.read() + dbx.files_upload(data, cloud_path) + print(f"Uploaded file '{local_path}' to '{cloud_path}'") + except dropbox.exceptions.ApiError as e: + upload_file_fix() + +def clear_local_folder(path): + try: + for filename in os.listdir(path): + file_path = os.path.join(path, filename) + if os.path.isfile(file_path) or os.path.islink(file_path): + os.unlink(file_path) + elif os.path.isdir(file_path): + shutil.rmtree(file_path) + except Exception as e: + print(f"Failed to delete contents of {path}. Reason: {e}") + +def download_folder(id): + try: + TOKEN = refresh_token_dropbox() + dbx = dropbox.Dropbox(TOKEN) + local_path = f"./user_file/{id}" + os.makedirs(local_path, exist_ok=True) + clear_local_folder(local_path) + result = dbx.files_list_folder(f"/{id}") + for entry in result.entries: + if isinstance(entry, dropbox.files.FileMetadata): + cloud_file_path = entry.path_display + file_name = os.path.basename(cloud_file_path) + local_file_path = os.path.join(local_path, file_name) + dbx.files_download_to_file(local_file_path, cloud_file_path) + print(f"Downloaded file '{file_name}' to '{local_file_path}'") + except dropbox.exceptions.ApiError as e: + print(f"Error downloading file '{id}': {e}") + +def download_file_id(file_name, id): + try: + TOKEN = refresh_token_dropbox() + dbx = dropbox.Dropbox(TOKEN) + local_folder_path = f"./user_file/{id}" + os.makedirs(local_folder_path, exist_ok=True) + local_file_path = os.path.join(local_folder_path, file_name) + with open(local_file_path, "wb") as f: + metadata, response = dbx.files_download(f"/{id}/{file_name}") + f.write(response.content) + print(f"Downloaded file '{file_name}' to '{local_file_path}'") + except dropbox.exceptions.ApiError as e: + print(f"Error downloading file '{file_name}': {e}") + raise HTTPException(status_code=500, detail="Internal Server Error") + +def search_and_download_file(start_char, id): + try: + TOKEN = refresh_token_dropbox() + dbx = dropbox.Dropbox(TOKEN) + result = dbx.files_list_folder(f"/{id}") + files_starting_with_char = [entry.name for entry in result.entries if entry.name.startswith(start_char)] + if len(files_starting_with_char) == 0: + print(f"No file found starting with '{start_char}' in folder '{id}'") + return + file_name = files_starting_with_char[0] + local_folder_path = f"./user_file/{id}" + os.makedirs(local_folder_path, exist_ok=True) + local_file_path = os.path.join(local_folder_path, file_name) + with open(local_file_path, "wb") as f: + metadata, response = dbx.files_download(f"/{id}/{file_name}") + f.write(response.content) + print(f"Downloaded file '{file_name}' to '{local_file_path}'") + except dropbox.exceptions.ApiError as e: + print(f"Error searching or downloading file: {e}") + raise HTTPException(status_code=500, detail="Internal Server Error") + +def delete_all_files_in_folder(folder_id): + try: + TOKEN = refresh_token_dropbox() + dbx = dropbox.Dropbox(TOKEN) + result = dbx.files_list_folder(f"/{folder_id}") + for entry in result.entries: + if isinstance(entry, dropbox.files.FileMetadata): + file_path = entry.path_display + dbx.files_delete_v2(file_path) + print(f"Deleted file '{file_path}'") + print(f"All files in folder '{folder_id}' have been deleted.") + except dropbox.exceptions.ApiError as e: + print(f"Error deleting files: {e}") \ No newline at end of file diff --git a/function/support_function.py b/function/support_function.py new file mode 100644 index 0000000000000000000000000000000000000000..ae72a8a44f4e0d7f771c23c0a94238b1ff852622 --- /dev/null +++ b/function/support_function.py @@ -0,0 +1,128 @@ +from pydantic.error_wrappers import ErrorWrapper +from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials +from service import MySQLService,UserService,ChatService +from request import RequestMySQL,RequestUser,RequestDefault +from auth.authentication import decodeJWT +from repository import UserRepository +from auth import authentication +from datetime import datetime, timedelta +from fastapi import Depends, HTTPException, Form, File, UploadFile +from typing import List +from service import FileService,DefaultService,UserService +from request import RequestFile,RequestChat,RequestDefault +from fastapi import FastAPI, Request, HTTPException +from fastapi.responses import JSONResponse +from pydantic.error_wrappers import ErrorWrapper +import json +from function import support_function +from repository import UserRepository +from response import ResponseDefault as res +import re + +def is_positive_integer(value): + if isinstance(value, int) and value > 0: + return True + else: + return False + +def check_value_user_id_controller(user_id: str): + if user_id is None or user_id.strip() == "": + return res.ReponseError(status=400, + data=res.Message(message="user_id field is required.")) + user_id = user_id.strip("'").strip('"') + try: + user_id_int = int(user_id) + except ValueError: + return res.ReponseError(status=400, + data=res.Message(message="user_id must be an integer")) + + if not support_function.is_positive_integer(user_id_int): + return res.ReponseError(status=400, + data=res.Message(message="user_id must be greater than 0")) + return True + +def check_value_user_id(user_id: str, current_user_email: str): + if user_id is None or user_id.strip() == "": + return res.ReponseError(status=400, + data=res.Message(message="user_id field is required.")) + user_id = user_id.strip("'").strip('"') + try: + user_id_int = int(user_id) + except ValueError: + return res.ReponseError(status=400, + data=res.Message(message="user_id must be an integer")) + + if not support_function.is_positive_integer(user_id_int): + return res.ReponseError(status=400, + data=res.Message(message="user_id must be greater than 0")) + email = UserRepository.getEmailUserByIdFix(user_id) + if email is None: + return res.ReponseError(status=404, + data=res.Message(message="user_id not exist")) + email = email[0] + if email != current_user_email: + raise HTTPException(status_code=403, detail="Sorry, you can't perform actions with this user id.") + return True + +def check_value_email_controller(email: str): + if email is None or email.strip() == "": + return res.ReponseError(status = 400, + data = res.Message(message="Email is required.")) + try: + int(email) + return res.ReponseError(status=400, + data=res.Message(message="Email must be a string, not a number.")) + except ValueError: + pass + return True + +def check_value_otp(otp: str): + if otp is None: + return res.ReponseError(status=400, + data=res.Message(message="OTP is required")) + if otp.isdigit(): + return res.ReponseError(status=400, + data=res.Message(message="OTP must be a string, not a number.")) + if len(otp) != 6: + return res.ReponseError(status=400, + data=res.Message(message="OTP max length is 6")) + return True + +regex = r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,7}\b' +def check_email(email): + if(re.fullmatch(regex, email)): + return True + else: + return False +def check_email_service(user_id: str): + email1 = UserRepository.getEmailUserByIdFix(user_id) + if email1 is None: + return res.ReponseError( + status=404, + data=res.Message(message="Id not exist") + ) + email = email1[0] + if email is None: + return res.ReponseError( + status=400, + data=res.Message(message="Email is empty") + ) + if check_email(email) == False: + return res.ReponseError( + status=400, + data=res.Message(message="Email invalid") + ) + return email + +def check_email_empty_invalid(email: str): + if email is None or email == "": + return res.ReponseError( + status=400, + data=res.Message(message="Email is empty") + ) + if check_email(email) == False: + return res.ReponseError( + status=400, + data =res.Message(message="Email invalid") + ) + return True \ No newline at end of file diff --git a/models/Database_Entity.py b/models/Database_Entity.py new file mode 100644 index 0000000000000000000000000000000000000000..84a8f293eec2330c6f5c172d20ad6a6a75b2b27f --- /dev/null +++ b/models/Database_Entity.py @@ -0,0 +1,68 @@ +from sqlalchemy import Column, String, Text, DateTime, Integer, ForeignKey, TIMESTAMP +from sqlalchemy.orm import relationship +from sqlalchemy.orm import DeclarativeBase +from sqlalchemy.sql import func +class Base(DeclarativeBase): + pass + +class User(Base): + __tablename__ = 'users' + id = Column(Integer, primary_key=True, autoincrement=True) + email = Column(String(255)) + access_token = Column(Text) + refresh_token = Column(Text) + expires_at = Column(DateTime) + + chat_histories = relationship("ChatHistory", back_populates="user") + user_logins = relationship("UserLogin", back_populates="user") + user_infos = relationship("UserInfo", back_populates="user") + +class ChatHistory(Base): + __tablename__ = 'chat_history' + + id = Column(Integer, primary_key=True,autoincrement=True) + email = Column(String(255), ForeignKey('users.email')) + name_chat = Column(String(255), unique=True) + + user = relationship("User", back_populates="chat_histories") + detail_chats = relationship("DetailChat", back_populates="chat_history") + +class UserLogin(Base): + __tablename__ = 'user_login' + + id = Column(Integer, primary_key=True,autoincrement=True) + user_email = Column(String(100), ForeignKey('users.email'), primary_key=True) + user_session_id = Column(String(100), primary_key=True) + + user = relationship("User", back_populates="user_logins") + +class UserInfo(Base): + __tablename__ = 'user_info' + + id = Column(Integer, primary_key=True, autoincrement=True) + uid = Column(Text) + email = Column(String(255), ForeignKey('users.email'), unique=True) + display_name = Column(Text) + photo_url = Column(Text) + + user = relationship("User", back_populates="user_infos") + +class DetailChat(Base): + __tablename__ = 'detail_chat' + + id = Column(Integer, primary_key=True, autoincrement=True) + chat_id = Column(Integer, ForeignKey('chat_history.id')) + YouMessage = Column(Text) + AiMessage = Column(Text) + data_relevant = Column(Text) + source_file = Column(Text) + + chat_history = relationship("ChatHistory", back_populates="detail_chats") + +class OTP(Base): + __tablename__ = 'otp' + + id = Column(Integer, primary_key=True, autoincrement=True) + email = Column(String(255), nullable=False) + otp = Column(String(6), nullable=False) + created_at = Column(TIMESTAMP, server_default=func.now()) \ No newline at end of file diff --git a/models/__pycache__/Database_Entity.cpython-310.pyc b/models/__pycache__/Database_Entity.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7456bdb935c7da1a7e3d4ca96c0e7e4dabc1e295 Binary files /dev/null and b/models/__pycache__/Database_Entity.cpython-310.pyc differ diff --git a/models/__pycache__/Database_Entity.cpython-311.pyc b/models/__pycache__/Database_Entity.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c73d242252da8fc34c16e3bc4897aa98cdaaa892 Binary files /dev/null and b/models/__pycache__/Database_Entity.cpython-311.pyc differ diff --git a/models/__pycache__/__init__.cpython-310.pyc b/models/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..61a5d9ae82eec8d7bb7386483099cf3ff8fd71e7 Binary files /dev/null and b/models/__pycache__/__init__.cpython-310.pyc differ diff --git a/repository/ChatHistoryRepository.py b/repository/ChatHistoryRepository.py new file mode 100644 index 0000000000000000000000000000000000000000..db2e6cd9c74daa628ee607ec46dedad37a6ecacb --- /dev/null +++ b/repository/ChatHistoryRepository.py @@ -0,0 +1,276 @@ +from sqlalchemy.orm import sessionmaker +import sys +import os +app_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..')) +sys.path.insert(0, app_path) +from models import Database_Entity +from repository import ConfigDatabase as cf +chat_history = Database_Entity.ChatHistory +users = Database_Entity.User +detail_chat = Database_Entity.DetailChat +from sqlalchemy.orm import sessionmaker +from functools import lru_cache +import sys +import os + +def getIdChatHistoryByUserIdAndNameChat(user_id:int,name_old :str) -> chat_history.id: + try: + engine = cf.get_db_engine() + Session = sessionmaker(autocommit=False, autoflush=False, bind=engine) + with Session() as session: + email = session.query(users.email).filter(users.id == user_id).one_or_none()[0] + chat_id = session.query(chat_history.id).filter(chat_history.email == email, chat_history.name_chat == name_old).scalar() + session.commit() + if chat_id: + session.close() + return chat_id + else: + session.close() + return None + except: + engine = cf.get_db_engine1() + Session = sessionmaker(autocommit=False, autoflush=False, bind=engine) + with Session() as session: + email = session.query(users.email).filter(users.id == user_id).one_or_none()[0] + chat_id = session.query(chat_history.id).filter(chat_history.email == email, chat_history.name_chat == name_old).scalar() + session.commit() + if chat_id: + session.close() + return chat_id + else: + session.close() + return None + +def getIdChatHistoryByUserIdAndNameChatNew(user_id:int,name_old :str) -> chat_history.id: + try: + engine = cf.get_db_engine() + Session = sessionmaker(autocommit=False, autoflush=False, bind=engine) + with Session() as session: + email = session.query(users.email).filter(users.id == user_id).one_or_none()[0] + chat_id = session.query(chat_history.id).filter(chat_history.email == email, chat_history.name_chat == name_old).scalar() + session.commit() + if chat_id: + session.close() + return chat_id + else: + session.close() + return None + except: + engine = cf.get_db_engine1() + Session = sessionmaker(autocommit=False, autoflush=False, bind=engine) + with Session() as session: + email = session.query(users.email).filter(users.id == user_id).one_or_none()[0] + chat_id = session.query(chat_history.id).filter(chat_history.email == email, + chat_history.name_chat == name_old).scalar() + session.commit() + if chat_id: + session.close() + return chat_id + else: + session.close() + return None + +def updateNameChatHistory(user_id: int,name_old :str,name_new:str) -> bool: + try: + engine = cf.get_db_engine1() + Session = sessionmaker(autocommit=False, autoflush=False, bind=engine) + with Session() as session: + try: + email = session.query(users.email).filter(users.id == user_id).one_or_none()[0] + session.query(chat_history).filter(chat_history.email == email,chat_history.name_chat == name_old).update({chat_history.name_chat: name_new}) + session.commit() + session.close() + return True + except: + session.rollback() + session.close() + return False + except: + engine = cf.get_db_engine() + Session = sessionmaker(autocommit=False, autoflush=False, bind=engine) + with Session() as session: + try: + email = session.query(users.email).filter(users.id == user_id).one_or_none()[0] + session.query(chat_history).filter(chat_history.email == email,chat_history.name_chat == name_old).update({chat_history.name_chat: name_new}) + session.commit() + session.close() + return True + except: + session.rollback() + session.close() + return False + +def deleteChatHistory(user_id,chat_name: str) -> bool: + try: + try: + engine = cf.get_db_engine1() + Session = sessionmaker(autocommit=False, autoflush=False, bind=engine) + with Session() as session: + email = session.query(users.email).filter(users.id == user_id).one_or_none()[0] + session.query(chat_history).filter(chat_history.email == email, chat_history.name_chat == chat_name).delete() + session.commit() + session.close() + return True + except Exception as e: + session.rollback() + session.close() + return False + except: + try: + engine = cf.get_db_engine() + Session = sessionmaker(autocommit=False, autoflush=False, bind=engine) + with Session() as session: + email = session.query(users.email).filter(users.id == user_id).one_or_none()[0] + session.query(chat_history).filter(chat_history.email == email, chat_history.name_chat == chat_name).delete() + session.commit() + session.close() + return True + except Exception as e: + session.rollback() + session.close() + return False + + +def getChatHistoryByEmail(email: str) -> chat_history: + try: + engine = cf.get_db_engine1() + Session = sessionmaker(autocommit=False, autoflush=False, bind=engine) + with Session() as session: + chat_history1 = session.query(chat_history).filter(chat_history.email == email) + if chat_history1: + session.commit() + session.close() + return chat_history1 + session.close() + return None + except: + engine = cf.get_db_engine() + Session = sessionmaker(autocommit=False, autoflush=False, bind=engine) + with Session() as session: + chat_history1 = session.query(chat_history).filter(chat_history.email == email) + if chat_history1: + session.commit() + session.close() + return chat_history1 + session.close() + return None + +from sqlalchemy.orm import aliased + +def delete_last_chat_detail_by_chat_name_and_email(chat_name: str, user_id: int) -> bool: + try: + engine = cf.get_db_engine() + Session = sessionmaker(autocommit=False, autoflush=False, bind=engine) + with Session() as session: + email = session.query(users.email).filter(users.id == user_id).one_or_none() + if not email: + return False + email = email[0] + last_chat_detail = (session.query(detail_chat) + .join(chat_history, detail_chat.chat_id == chat_history.id) + .filter(chat_history.name_chat == chat_name, chat_history.email == email) + .order_by(detail_chat.id.desc()) + .first()) + + if last_chat_detail: + session.delete(last_chat_detail) + session.commit() + return True + return False + except: + engine = cf.get_db_engine1() + Session = sessionmaker(autocommit=False, autoflush=False, bind=engine) + with Session() as session: + email = session.query(users.email).filter(users.id == user_id).one_or_none() + if not email: + return False + email = email[0] + last_chat_detail = (session.query(detail_chat) + .join(chat_history, detail_chat.chat_id == chat_history.id) + .filter(chat_history.name_chat == chat_name, chat_history.email == email) + .order_by(detail_chat.id.desc()) + .first()) + + if last_chat_detail: + session.delete(last_chat_detail) + session.commit() + return True + return False +def getChatHistoryByChatIdAndUserId(chat_id: int, user_id: int) -> chat_history: + try: + engine = cf.get_db_engine() + Session = sessionmaker(autocommit=False, autoflush=False, bind=engine) + with Session() as session: + email = session.query(users.email).filter(users.id == user_id).one_or_none()[0] + chat_history1 = session.query(chat_history).filter(chat_history.id == chat_id,chat_history.email == email).one_or_none() + if chat_history1: + session.commit() + session.close() + return True + session.close() + return None + except: + engine = cf.get_db_engine1() + Session = sessionmaker(autocommit=False, autoflush=False, bind=engine) + with Session() as session: + email = session.query(users.email).filter(users.id == id).one_or_none()[0] + chat_history1 = session.query(chat_history).filter(chat_history.email == email) + if chat_history1: + session.commit() + session.close() + return True + session.close() + return None + + +def getChatHistoryById(id: int) -> chat_history: + try: + engine = cf.get_db_engine() + Session = sessionmaker(autocommit=False, autoflush=False, bind=engine) + with Session() as session: + email = session.query(users.email).filter(users.id == id).one_or_none()[0] + chat_history1 = session.query(chat_history).filter(chat_history.email == email) + if chat_history1: + session.commit() + session.close() + return chat_history1 + session.close() + return None + except: + engine = cf.get_db_engine1() + Session = sessionmaker(autocommit=False, autoflush=False, bind=engine) + with Session() as session: + email = session.query(users.email).filter(users.id == id).one_or_none()[0] + chat_history1 = session.query(chat_history).filter(chat_history.email == email) + if chat_history1: + session.commit() + session.close() + return chat_history1 + session.close() + return None + +def addChatHistory(user_id: str, name_chat:str)->None: + try: + engine = cf.get_db_engine() + Session = sessionmaker(autocommit=False, autoflush=False, bind=engine) + with Session() as session: + email = session.query(users.email).filter(users.id == user_id).one_or_none()[0] + new_user = chat_history( + email = email, + name_chat = name_chat + ) + session.add(new_user) + session.commit() + session.close() + except: + engine = cf.get_db_engine1() + Session = sessionmaker(autocommit=False, autoflush=False, bind=engine) + with Session() as session: + email = session.query(users.email).filter(users.id == user_id).one_or_none()[0] + new_user = chat_history( + email = email, + name_chat = name_chat + ) + session.add(new_user) + session.commit() + session.close() diff --git a/repository/ConfigDatabase.py b/repository/ConfigDatabase.py new file mode 100644 index 0000000000000000000000000000000000000000..cd948823b548db731673eef909274034585e9069 --- /dev/null +++ b/repository/ConfigDatabase.py @@ -0,0 +1,48 @@ +from sqlalchemy import create_engine, URL +from sqlalchemy.orm import DeclarativeBase +Base = DeclarativeBase() +from sqlalchemy.engine import create_engine, URL +from dotenv import load_dotenv +import os +load_dotenv() +MYSQL_USER_NAME=os.getenv('MYSQL_USER_NAME') +MYSQL_PASSWORD=os.getenv('MYSQL_PASSWOR') +MYSQL_PORT=os.getenv('MYSQL_PORT') +MYSQL_DATABASE=os.getenv('MYSQL_DATABASE') +MYSQL_HOST=os.getenv('MYSQL_HOST') +#IF USE DOCKER HOST = host.docker.internal +def get_db_engine(): + dsn = URL.create( + drivername="mysql+pymysql", + username=MYSQL_USER_NAME, + password=MYSQL_PASSWORD, + host=MYSQL_HOST, + port=MYSQL_PORT, + database=MYSQL_DATABASE + ) + connect_args = {} + return create_engine( + dsn, + connect_args=connect_args, + pool_size=20, + pool_recycle=300, + pool_pre_ping=True + ) + +def get_db_engine1(): + dsn = URL.create( + drivername="mysql+pymysql", + username=MYSQL_USER_NAME, + password=MYSQL_PASSWORD, + host=MYSQL_HOST, + port=MYSQL_PORT, + database=MYSQL_DATABASE + ) + connect_args = {} + return create_engine( + dsn, + connect_args=connect_args, + pool_size=20, + pool_recycle=300, + pool_pre_ping=True + ) diff --git a/repository/DetailChatRepository.py b/repository/DetailChatRepository.py new file mode 100644 index 0000000000000000000000000000000000000000..9e98e57ef80cb7cb7bb46e35790389d830c64d2e --- /dev/null +++ b/repository/DetailChatRepository.py @@ -0,0 +1,141 @@ +from sqlalchemy.orm import sessionmaker +from models import Database_Entity +from repository import ConfigDatabase as cf +detail_chat = Database_Entity.DetailChat +chat_history = Database_Entity.ChatHistory + +def getListDetailChatByChatId(chat_id: int) -> detail_chat: + try: + engine = cf.get_db_engine1() + Session = sessionmaker(autocommit=False, autoflush=False, bind=engine) + with Session() as session: + chat_record= session.query(detail_chat).filter(detail_chat.chat_id == chat_id) + session.commit() + if chat_record: + session.close() + return chat_record + else: + session.close() + return None + except: + engine = cf.get_db_engine() + Session = sessionmaker(autocommit=False, autoflush=False, bind=engine) + with Session() as session: + chat_record= session.query(detail_chat).filter(detail_chat.chat_id == chat_id) + session.commit() + if chat_record: + session.close() + return chat_record + else: + session.close() + return None + +def addDetailChat(chat_id: int, YouMessage: str, AiMessage: str, data_relevant: str, source_file: str) -> None: + try: + engine = cf.get_db_engine() + Session = sessionmaker(autocommit=False, autoflush=False, bind=engine) + with Session() as session: + new_user = detail_chat( + chat_id = chat_id, + YouMessage = YouMessage, + AiMessage = AiMessage, + data_relevant = data_relevant, + source_file = source_file + ) + session.add(new_user) + session.commit() + return new_user.id + session.close() + except: + engine = cf.get_db_engine1() + Session = sessionmaker(autocommit=False, autoflush=False, bind=engine) + with Session() as session: + new_user = detail_chat( + chat_id=chat_id, + YouMessage=YouMessage, + AiMessage=AiMessage, + data_relevant=data_relevant, + source_file=source_file + ) + session.add(new_user) + session.commit() + return new_user.id + session.close() + +def getDetailChatByChatId(id: int) -> detail_chat: + try: + engine = cf.get_db_engine() + Session = sessionmaker(autocommit=False, autoflush=False, bind=engine) + with Session() as session: + try: + chat = session.query(detail_chat).filter(detail_chat.id == id).one_or_none() + return chat + except: + session.close() + return False + except: + engine = cf.get_db_engine1() + Session = sessionmaker(autocommit=False, autoflush=False, bind=engine) + with Session() as session: + try: + chat = session.query(detail_chat.id,detail_chat.data_relevant,detail_chat.source_file).filter(detail_chat.id == id).one_or_none() + session.commit() + session.close() + return chat + except: + session.close() + return False + + +def delete_chat_detail(chat_name: str) -> bool: + try: + engine = cf.get_db_engine() + Session = sessionmaker(autocommit=False, autoflush=False, bind=engine) + with Session() as session: + try: + detail_chat2 = session.query(detail_chat).filter(detail_chat.chat_id == chat_history.id).filter(chat_history.name_chat == chat_name) + session.query(detail_chat).filter(detail_chat.chat_id == chat_history.id).filter(chat_history.name_chat == chat_name).delete(synchronize_session=False) + session.commit() + session.close() + return True + except: + session.close() + return False + except: + engine = cf.get_db_engine1() + Session = sessionmaker(autocommit=False, autoflush=False, bind=engine) + with Session() as session: + try: + session.query(detail_chat).filter(detail_chat.chat_id == chat_history.id).filter(chat_history.name_chat == chat_name).delete(synchronize_session=False) + session.commit() + session.close() + return True + except: + session.close() + return False +def delete_chat_detail_by_id(id_chat_detail: int) -> bool: + try: + engine = cf.get_db_engine() + Session = sessionmaker(autocommit=False, autoflush=False, bind=engine) + with Session() as session: + try: + + session.query(detail_chat).filter(detail_chat.id == id_chat_detail).delete(synchronize_session=False) + session.commit() + session.close() + return True + except: + session.close() + return False + except: + engine = cf.get_db_engine1() + Session = sessionmaker(autocommit=False, autoflush=False, bind=engine) + with Session() as session: + try: + session.query(detail_chat).filter(detail_chat.chat_id == id_chat_detail).delete(synchronize_session=False) + session.commit() + session.close() + return True + except: + session.close() + return False \ No newline at end of file diff --git a/repository/OTPRepository.py b/repository/OTPRepository.py new file mode 100644 index 0000000000000000000000000000000000000000..1fae5b568b1442f0918eb32f5e76b66f8e1aba71 --- /dev/null +++ b/repository/OTPRepository.py @@ -0,0 +1,82 @@ +from sqlalchemy.orm import sessionmaker +from models import Database_Entity +from repository import ConfigDatabase as cf +otp_user = Database_Entity.OTP +from sqlalchemy.orm import sessionmaker +from functools import lru_cache +import sys +import os + +def getOtpByEmail(email: str) -> otp_user: + try: + engine = cf.get_db_engine() + Session = sessionmaker(autocommit=False, autoflush=False, bind=engine) + with Session() as session: + user_record= session.query(otp_user).filter(otp_user.email == email).one_or_none() + if user_record: + session.close() + return user_record + else: + session.close() + return None + except: + engine = cf.get_db_engine1() + Session = sessionmaker(autocommit=False, autoflush=False, bind=engine) + with Session() as session: + user_record= session.query(otp_user).filter(otp_user.email == email).one_or_none() + if user_record: + session.close() + return user_record + else: + session.close() + return None + +def addOTP(email: str, otp: str) -> None: + try: + engine = cf.get_db_engine() + Session = sessionmaker(autocommit=False, autoflush=False, bind=engine) + with Session() as session: + otp_record = session.query(otp_user).filter_by(email=email).first() + if otp_record: + session.delete(otp_record) + session.commit() + new_user = otp_user( + email = email, + otp= otp + ) + session.add(new_user) + session.commit() + session.close() + except: + engine = cf.get_db_engine1() + Session = sessionmaker(autocommit=False, autoflush=False, bind=engine) + with Session() as session: + otp_record = session.query(otp_user).filter_by(email=email).first() + if otp_record: + session.delete(otp_record) + session.commit() + new_user = otp_user( + email = email, + otp= otp + ) + session.add(new_user) + session.commit() + session.close() + +def deleteOTP(email: str, otp:str) -> None: + try: + engine = cf.get_db_engine() + Session = sessionmaker(autocommit=False, autoflush=False, bind=engine) + with Session() as session: + otp_record = session.query(otp_user).filter_by(email=email, otp=otp).first() + if otp_record: + session.delete(otp_record) + session.commit() + except: + engine = cf.get_db_engine1() + Session = sessionmaker(autocommit=False, autoflush=False, bind=engine) + with Session() as session: + otp_record = session.query(otp_user).filter_by(email=email, otp=otp).first() + if otp_record: + session.delete(otp_record) + session.commit() \ No newline at end of file diff --git a/repository/UserInfoRepository.py b/repository/UserInfoRepository.py new file mode 100644 index 0000000000000000000000000000000000000000..13dcbcd063842667023e999170f151b7adbed1db --- /dev/null +++ b/repository/UserInfoRepository.py @@ -0,0 +1,139 @@ +from sqlalchemy.orm import sessionmaker +from models import Database_Entity +from repository import ConfigDatabase as cf +user_info = Database_Entity.UserInfo +users = Database_Entity.User +from sqlalchemy.orm import sessionmaker +import sys +import os + +def getUserInfo(user_id: int) -> user_info: + try: + email = session.query(users.email).filter(users.id == user_id).one_or_none() + if email: + email = email[0] + user_record= session.query(user_info).filter(user_info.email == email).one_or_none() + if user_record: + session.close() + return user_record + else: + session.close() + return None + except: + engine = cf.get_db_engine1() + Session = sessionmaker(autocommit=False, autoflush=False, bind=engine) + with Session() as session: + email = session.query(users.email).filter(users.id == user_id).one_or_none() + if email: + email = email[0] + user_record= session.query(user_info).filter(user_info.email == email).one_or_none() + if user_record: + session.close() + return user_record + else: + session.close() + return None + +def getUserInfoByEmail(email:str) -> user_info: + try: + engine = cf.get_db_engine() + Session = sessionmaker(autocommit=False, autoflush=False, bind=engine) + with Session() as session: + user_record= session.query(user_info).filter(user_info.email == email).one_or_none() + if user_record: + session.close() + return user_record + else: + session.close() + return None + except: + engine = cf.get_db_engine1() + Session = sessionmaker(autocommit=False, autoflush=False, bind=engine) + with Session() as session: + user_record= session.query(user_info).filter(user_info.email == email).one_or_none() + if user_record: + session.close() + return user_record + else: + session.close() + return None + + + +def addUserInfo(uid: str, email: str, display_name: str, photo_url: str) -> None: + try: + engine = cf.get_db_engine() + Session = sessionmaker(autocommit=False, autoflush=False, bind=engine) + with Session() as session: + new_user = user_info( + uid = uid, + email = email, + display_name = display_name, + photo_url = photo_url + ) + session.add(new_user) + session.commit() + session.close() + except: + engine = cf.get_db_engine1() + Session = sessionmaker(autocommit=False, autoflush=False, bind=engine) + with Session() as session: + new_user = user_info( + uid = uid, + email = email, + display_name = display_name, + photo_url = photo_url + ) + session.add(new_user) + session.commit() + session.close() + +def updateUserInfo(user_id, uid: str, email: str, display_name: str, photo_url: str) -> None: + try: + engine = cf.get_db_engine() + Session = sessionmaker(autocommit=False, autoflush=False, bind=engine) + with Session() as session: + email = session.query(users.email).filter(users.id == user_id).one_or_none() + user_update= session.query(user_info).filter(user_info.email == email).one_or_none() + if user_update is not None: + user_update.uid = uid, + user_update.display_name = display_name, + user_update.photo_url = photo_url + session.commit() + session.close() + except: + engine = cf.get_db_engine1() + Session = sessionmaker(autocommit=False, autoflush=False, bind=engine) + with Session() as session: + email = session.query(users.email).filter(users.id == user_id).one_or_none() + user_update= session.query(user_info).filter(user_info.email == email).one_or_none() + if user_update is not None: + user_update.uid = uid, + user_update.display_name = display_name, + user_update.photo_url = photo_url + session.commit() + session.close() + + +def updateImage(user_id, photo_url: str) -> None: + try: + engine = cf.get_db_engine() + Session = sessionmaker(autocommit=False, autoflush=False, bind=engine) + with Session() as session: + email = session.query(users.email).filter(users.id == user_id).one_or_none() + user_update= session.query(user_info).filter(user_info.email == email).one_or_none() + if user_update is not None: + user_update.photo_url = photo_url + session.commit() + session.close() + except: + engine = cf.get_db_engine1() + Session = sessionmaker(autocommit=False, autoflush=False, bind=engine) + with Session() as session: + email = session.query(users.email).filter(users.id == user_id).one_or_none() + user_update = session.query(user_info).filter(user_info.email == email).one_or_none() + if user_update is not None: + user_update.photo_url = photo_url + session.commit() + session.close() + diff --git a/repository/UserLoginRepository.py b/repository/UserLoginRepository.py new file mode 100644 index 0000000000000000000000000000000000000000..cd4752e15b665670d70491c820ae7047ec6ea54b --- /dev/null +++ b/repository/UserLoginRepository.py @@ -0,0 +1,135 @@ +from sqlalchemy.orm import sessionmaker +from models import Database_Entity +from repository import ConfigDatabase as cf +user_login = Database_Entity.UserLogin +users = Database_Entity.User + +def getUserLogin(email: str) -> user_login: + try: + engine = cf.get_db_engine() + Session = sessionmaker(autocommit=False, autoflush=False, bind=engine) + with Session() as session: + user_record = session.query(user_login).filter(user_login.user_email == email).one_or_none() + if user_record: + session.close() + return user_record + else: + session.close() + return None + except: + engine = cf.get_db_engine1() + Session = sessionmaker(autocommit=False, autoflush=False, bind=engine) + with Session() as session: + user_record = session.query(user_login).filter(user_login.user_email == email).one_or_none() + if user_record: + session.close() + return user_record + else: + session.close() + return None + + +def getUserLoginById(id: int) -> user_login: + try: + engine = cf.get_db_engine() + Session = sessionmaker(autocommit=False, autoflush=False, bind=engine) + with Session() as session: + email = session.query(users.email).filter(users.id == id).one_or_none()[0] + user_record = session.query(user_login).filter(user_login.user_email == email).one_or_none() + if user_record: + session.close() + return user_record + else: + session.close() + return None + except: + engine = cf.get_db_engine1() + Session = sessionmaker(autocommit=False, autoflush=False, bind=engine) + with Session() as session: + email = session.query(users.email).filter(users.id == id).one_or_none()[0] + user_record = session.query(user_login).filter(user_login.user_email == email).one_or_none() + if user_record: + session.close() + return user_record + else: + session.close() + return None + +def addUserLogin(user_email: str, session_id : str) -> None: + try: + engine = cf.get_db_engine() + Session = sessionmaker(autocommit=False, autoflush=False, bind=engine) + with Session() as session: + new_user = user_login( + user_email = user_email, + user_session_id = session_id + ) + session.add(new_user) + session.commit() + session.close() + except: + engine = cf.get_db_engine1() + Session = sessionmaker(autocommit=False, autoflush=False, bind=engine) + with Session() as session: + new_user = user_login( + user_email = user_email, + user_session_id = session_id + ) + session.add(new_user) + session.commit() + session.close() + + +def updateUserLogin(email: str, session_id : str ) -> None: + try: + engine = cf.get_db_engine() + Session = sessionmaker(autocommit=False, autoflush=False, bind=engine) + with Session() as session: + user_update= session.query(user_login).filter(user_login.user_email == email).one_or_none() + if user_update is not None: + user_update.user_session_id = session_id + session.commit() + session.close() + except: + engine = cf.get_db_engine1() + Session = sessionmaker(autocommit=False, autoflush=False, bind=engine) + with Session() as session: + user_update= session.query(user_login).filter(user_login.user_email == email).one_or_none() + if user_update is not None: + user_update.user_session_id = session_id + session.commit() + session.close() + + + +def getUserSessionIdByUserEmail(id: int) -> user_login: + try: + engine = cf.get_db_engine() + Session = sessionmaker(autocommit=False, autoflush=False, bind=engine) + with Session() as session: + email = session.query(users.email).filter(users.id == id).one_or_none()[0] + session.commit() + user_record= session.query(user_login.user_session_id).filter(user_login.user_email == email).one_or_none()[0] + session.commit() + print(user_record) + if user_record: + session.close() + return user_record + else: + session.close() + return None + except: + engine = cf.get_db_engine1() + Session = sessionmaker(autocommit=False, autoflush=False, bind=engine) + with Session() as session: + email = session.query(users.email).filter(users.id == id).one_or_none()[0] + session.commit() + user_record= session.query(user_login.user_session_id).filter(user_login.user_email == email).one_or_none()[0] + session.commit() + print(user_record) + if user_record: + session.close() + return user_record + else: + session.close() + return None \ No newline at end of file diff --git a/repository/UserRepository.py b/repository/UserRepository.py new file mode 100644 index 0000000000000000000000000000000000000000..0099252924a08bec0e5296ba6a05250387542ddf --- /dev/null +++ b/repository/UserRepository.py @@ -0,0 +1,357 @@ +from sqlalchemy.orm import sessionmaker +from models import Database_Entity +from repository import ConfigDatabase as cf +import pytz , datetime +from datetime import timedelta +user = Database_Entity.User + +def getUserIdByAccessToken(token:str) -> int: + try: + engine = cf.get_db_engine() + Session = sessionmaker(autocommit=False, autoflush=False, bind=engine) + with Session() as session: + user_record = session.query(user.id).filter(user.access_token == token).one_or_none() + session.close() + return user_record + except: + engine = cf.get_db_engine1() + Session = sessionmaker(autocommit=False, autoflush=False, bind=engine) + with Session() as session: + user_record = session.query(user.id).filter(user.access_token == token).one_or_none() + session.close() + return user_record + +def getUserIdByAccessTokenAndUserId(token:str,user_id: int) -> int: + try: + engine = cf.get_db_engine() + Session = sessionmaker(autocommit=False, autoflush=False, bind=engine) + with Session() as session: + user_record = session.query(user.id).filter(user.access_token == token,user.id == user_id).one_or_none() + session.close() + return user_record + except: + engine = cf.get_db_engine1() + Session = sessionmaker(autocommit=False, autoflush=False, bind=engine) + with Session() as session: + user_record = session.query(user.id).filter(user.access_token == token,user.id == user_id).one_or_none() + session.close() + return user_record + +def getUserByEmail(email: str) -> user: + try: + engine = cf.get_db_engine() + Session = sessionmaker(autocommit=False, autoflush=False, bind=engine) + with Session() as session: + user_record = session.query(user).filter(user.email == email).one_or_none() + session.close() + return user_record + except: + engine = cf.get_db_engine1() + Session = sessionmaker(autocommit=False, autoflush=False, bind=engine) + with Session() as session: + user_record = session.query(user).filter(user.email == email).one_or_none() + session.close() + return user_record + +def getUserIdByEmail(email: str) -> user.id: + try: + engine = cf.get_db_engine() + Session = sessionmaker(autocommit=False, autoflush=False, bind=engine) + with Session() as session: + user_record = session.query(user.id).filter(user.email == email).one_or_none()[0] + session.close() + return user_record + except: + engine = cf.get_db_engine1() + Session = sessionmaker(autocommit=False, autoflush=False, bind=engine) + with Session() as session: + user_record = session.query(user.id).filter(user.email == email).one_or_none()[0] + session.close() + return user_record + +def getUserById(user_id: str) -> user: + try: + engine = cf.get_db_engine() + Session = sessionmaker(autocommit=False, autoflush=False, bind=engine) + with Session() as session: + user_record = session.query(user).filter(user.id == user_id).one_or_none() + session.close() + return user_record + except: + engine = cf.get_db_engine1() + Session = sessionmaker(autocommit=False, autoflush=False, bind=engine) + with Session() as session: + user_record = session.query(user).filter(user.id == user_id).one_or_none() + session.close() + return user_record + +def getRefreshTokenUserByAccessToken(token: str) -> user.refresh_token: + try: + engine = cf.get_db_engine() + Session = sessionmaker(autocommit=False, autoflush=False, bind=engine) + with Session() as session: + user_record = session.query(user.refresh_token).filter(user.access_token == token).one_or_none() + session.close() + return user_record + except: + engine = cf.get_db_engine1() + Session = sessionmaker(autocommit=False, autoflush=False, bind=engine) + with Session() as session: + user_record = session.query(user.refresh_token).filter(user.access_token == token).one_or_none() + session.close() + return user_record + + +def getUserIdByRefreshToken(refreshToken: str) -> user.refresh_token: + try: + engine = cf.get_db_engine() + Session = sessionmaker(autocommit=False, autoflush=False, bind=engine) + with Session() as session: + user_record = session.query(user.id).filter(user.refresh_token == refreshToken).one_or_none()[0] + session.close() + return user_record + except: + engine = cf.get_db_engine1() + Session = sessionmaker(autocommit=False, autoflush=False, bind=engine) + with Session() as session: + user_record = session.query(user.id).filter(user.refresh_token == refreshToken).one_or_none()[0] + session.close() + return user_record + +def getRefreshTokenUserById(user_id: str) -> user.refresh_token: + try: + engine = cf.get_db_engine() + Session = sessionmaker(autocommit=False, autoflush=False, bind=engine) + with Session() as session: + user_record = session.query(user.refresh_token).filter(user.id == user_id).one_or_none()[0] + session.close() + return user_record + except: + engine = cf.get_db_engine1() + Session = sessionmaker(autocommit=False, autoflush=False, bind=engine) + with Session() as session: + user_record = session.query(user.refresh_token).filter(user.id == user_id).one_or_none()[0] + session.close() + return user_record + +def getEmailUser(email:str) -> user.email: + try: + engine = cf.get_db_engine() + Session = sessionmaker(autocommit=False, autoflush=False, bind=engine) + with Session() as session: + user_email = session.query(user.email).filter(user.email == email).one_or_none() + session.close() + return user_email + except: + engine = cf.get_db_engine1() + Session = sessionmaker(autocommit=False, autoflush=False, bind=engine) + with Session() as session: + user_email = session.query(user.email).filter(user.email == email).one_or_none() + session.close() + return user_email + +def getEmailUserById(user_id:int) -> user.email: + try: + engine = cf.get_db_engine() + Session = sessionmaker(autocommit=False, autoflush=False, bind=engine) + with Session() as session: + user_email = session.query(user.email).filter(user.id == user_id).one_or_none()[0] + session.close() + return user_email + except: + engine = cf.get_db_engine1() + Session = sessionmaker(autocommit=False, autoflush=False, bind=engine) + with Session() as session: + user_email = session.query(user.email).filter(user.id == user_id).one_or_none()[0] + session.close() + return user_email + +def getEmailUserByIdFix(user_id:int) -> user.email: + try: + engine = cf.get_db_engine() + Session = sessionmaker(autocommit=False, autoflush=False, bind=engine) + with Session() as session: + user_email = session.query(user.email).filter(user.id == user_id).one_or_none() + session.close() + return user_email + except: + engine = cf.get_db_engine1() + Session = sessionmaker(autocommit=False, autoflush=False, bind=engine) + with Session() as session: + user_email = session.query(user.email).filter(user.id == user_id).one_or_none() + session.close() + return user_email + + + +def getEmailUserByAccessToken(token: str) -> user.email: + try: + engine = cf.get_db_engine() + Session = sessionmaker(autocommit=False, autoflush=False, bind=engine) + with Session() as session: + user_email = session.query(user.email).filter(user.access_token == token).one_or_none() + session.close() + return user_email + except: + engine = cf.get_db_engine1() + Session = sessionmaker(autocommit=False, autoflush=False, bind=engine) + with Session() as session: + user_email = session.query(user.email).filter(user.access_token == token).one_or_none() + session.close() + return user_email + + +def addUser(email: str, access_token: str, refresh_token: str, expires_at: datetime.datetime) -> None: + try: + engine = cf.get_db_engine() + Session = sessionmaker(bind=engine) + with Session() as session: + new_user = Database_Entity.User( + email=email, + access_token=access_token, + refresh_token=refresh_token, + expires_at=expires_at + ) + session.add(new_user) + session.commit() + session.close() + except: + engine = cf.get_db_engine1() + Session = sessionmaker(bind=engine) + with Session() as session: + new_user = Database_Entity.User( + email=email, + access_token=access_token, + refresh_token=refresh_token, + expires_at=expires_at + ) + session.add(new_user) + session.commit() + session.close() + + +def updateUserLogin(email: str, access_token: str, refresh_token: str, expires_at: datetime.datetime) -> bool: + try: + engine = cf.get_db_engine() + Session = sessionmaker(autocommit=False, autoflush=False, bind=engine) + with Session() as session: + user_update = session.query(user).filter(user.email == email).one_or_none() + if user_update: + user_update.email = email + user_update.access_token = access_token + user_update.refresh_token = refresh_token + user_update.expires_at = expires_at + session.commit() + session.close() + return True + else: + session.close() + return False + except: + engine = cf.get_db_engine1() + Session = sessionmaker(autocommit=False, autoflush=False, bind=engine) + with Session() as session: + user_update = session.query(user).filter(user.email == email).one_or_none() + if user_update: + user_update.email = email + user_update.access_token = access_token + user_update.refresh_token = refresh_token + user_update.expires_at = expires_at + session.commit() + session.close() + return True + else: + session.close() + return False + + +def updateAccessToken(user_id: int,access_token: str, expires_at: datetime.datetime) -> None: + try: + engine = cf.get_db_engine() + Session = sessionmaker(autocommit=False, autoflush=False, bind=engine) + with Session() as session: + user_update = session.query(user).filter(user.id == user_id).one_or_none() + if user_update: + user_update.access_token = access_token + user_update.expires_at = expires_at + session.commit() + except: + engine = cf.get_db_engine1() + Session = sessionmaker(autocommit=False, autoflush=False, bind=engine) + with Session() as session: + user_update = session.query(user).filter(user.id == user_id).one_or_none() + if user_update: + user_update.access_token = access_token + user_update.expires_at = expires_at + session.commit() + +def updateAccessTokenById(id: int,access_token: str, expires_at: datetime.datetime) -> None: + try: + engine = cf.get_db_engine() + Session = sessionmaker(autocommit=False, autoflush=False, bind=engine) + with Session() as session: + user_update = session.query(user).filter(user.id == id).one_or_none() + if user_update: + user_update.access_token = access_token + user_update.expires_at = expires_at + session.commit() + session.close() + except: + engine = cf.get_db_engine1() + Session = sessionmaker(autocommit=False, autoflush=False, bind=engine) + with Session() as session: + user_update = session.query(user).filter(user.id == id).one_or_none() + if user_update: + user_update.access_token = access_token + user_update.expires_at = expires_at + session.commit() + session.close() + + +def UpdateAccessTokenRefreshToken(email: str, access_token: str, refresh_token: str, expires_at: datetime.datetime) -> None: + try: + engine = cf.get_db_engine() + Session = sessionmaker(autocommit=False, autoflush=False, bind=engine) + with Session() as session: + user_update = session.query(user).filter(user.email == email).one_or_none() + if user_update: + user_update.access_token = access_token + user_update.refresh_token = refresh_token + user_update.expires_at = expires_at + session.commit() + session.close() + except: + engine = cf.get_db_engine1() + Session = sessionmaker(autocommit=False, autoflush=False, bind=engine) + with Session() as session: + user_update = session.query(user).filter(user.email == email).one_or_none() + if user_update: + user_update.access_token = access_token + user_update.refresh_token = refresh_token + user_update.expires_at = expires_at + session.commit() + session.close() + +def UpdateAccessTokenRefreshTokenById(user_id: int,access_token: str, refresh_token: str, expires_at: datetime.datetime) -> None: + try: + engine = cf.get_db_engine() + Session = sessionmaker(autocommit=False, autoflush=False, bind=engine) + with Session() as session: + user_update = session.query(user).filter(user.id == user_id).one_or_none() + if user_update: + user_update.access_token = access_token + user_update.refresh_token = refresh_token + user_update.expires_at = expires_at + session.commit() + session.close() + except: + engine = cf.get_db_engine1() + Session = sessionmaker(autocommit=False, autoflush=False, bind=engine) + with Session() as session: + user_update = session.query(user).filter(user.id == user_id).one_or_none() + if user_update: + user_update.access_token = access_token + user_update.refresh_token = refresh_token + user_update.expires_at = expires_at + session.commit() + session.close() diff --git a/repository/__pycache__/ChatHistoryRepository.cpython-310.pyc b/repository/__pycache__/ChatHistoryRepository.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fb186b16cfc4754604346ac31a4bf3da3c23f295 Binary files /dev/null and b/repository/__pycache__/ChatHistoryRepository.cpython-310.pyc differ diff --git a/repository/__pycache__/ChatHistoryRepository.cpython-311.pyc b/repository/__pycache__/ChatHistoryRepository.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a9d24b87f95fa36968e4fbdce481fc4a0a91ff25 Binary files /dev/null and b/repository/__pycache__/ChatHistoryRepository.cpython-311.pyc differ diff --git a/repository/__pycache__/ConfigDatabase.cpython-310.pyc b/repository/__pycache__/ConfigDatabase.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2c6be883bd79bfebfa6f461fb131d39b7a0811c0 Binary files /dev/null and b/repository/__pycache__/ConfigDatabase.cpython-310.pyc differ diff --git a/repository/__pycache__/ConfigDatabase.cpython-311.pyc b/repository/__pycache__/ConfigDatabase.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ee365c3025f246c18f00fc9a618b73b38f263a1c Binary files /dev/null and b/repository/__pycache__/ConfigDatabase.cpython-311.pyc differ diff --git a/repository/__pycache__/DetailChatRepository.cpython-310.pyc b/repository/__pycache__/DetailChatRepository.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8a942f967adbe29a75130219b6492c45da996c44 Binary files /dev/null and b/repository/__pycache__/DetailChatRepository.cpython-310.pyc differ diff --git a/repository/__pycache__/DetailChatRepository.cpython-311.pyc b/repository/__pycache__/DetailChatRepository.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c0a547eae70e9c80dee6b54f336d2f6793c5a327 Binary files /dev/null and b/repository/__pycache__/DetailChatRepository.cpython-311.pyc differ diff --git a/repository/__pycache__/OTPRepository.cpython-310.pyc b/repository/__pycache__/OTPRepository.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0d9b6d5d14c88450903baaf995fceb7b19e25edd Binary files /dev/null and b/repository/__pycache__/OTPRepository.cpython-310.pyc differ diff --git a/repository/__pycache__/OTPRepository.cpython-311.pyc b/repository/__pycache__/OTPRepository.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..087856e3235ceaf12d5fa0c2d9c17aec53bfea04 Binary files /dev/null and b/repository/__pycache__/OTPRepository.cpython-311.pyc differ diff --git a/repository/__pycache__/UserInfoRepository.cpython-310.pyc b/repository/__pycache__/UserInfoRepository.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1b357c27bae178063eca19fea3201acb3e19257c Binary files /dev/null and b/repository/__pycache__/UserInfoRepository.cpython-310.pyc differ diff --git a/repository/__pycache__/UserInfoRepository.cpython-311.pyc b/repository/__pycache__/UserInfoRepository.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5a1aa35a8ddffaa1cf56dba05ab6bb9c72662af6 Binary files /dev/null and b/repository/__pycache__/UserInfoRepository.cpython-311.pyc differ diff --git a/repository/__pycache__/UserLoginRepository.cpython-310.pyc b/repository/__pycache__/UserLoginRepository.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..188ac9d9fd301a891e8ab70661f65e1d5794ee74 Binary files /dev/null and b/repository/__pycache__/UserLoginRepository.cpython-310.pyc differ diff --git a/repository/__pycache__/UserLoginRepository.cpython-311.pyc b/repository/__pycache__/UserLoginRepository.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b696c690382071788cbe6473c625b3fd42d14c4b Binary files /dev/null and b/repository/__pycache__/UserLoginRepository.cpython-311.pyc differ diff --git a/repository/__pycache__/UserRepository.cpython-310.pyc b/repository/__pycache__/UserRepository.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d8fd395a4d541ad4edd6a2e63b46a16f39742e1e Binary files /dev/null and b/repository/__pycache__/UserRepository.cpython-310.pyc differ diff --git a/repository/__pycache__/UserRepository.cpython-311.pyc b/repository/__pycache__/UserRepository.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5b52d4f9e617c21824f3063171a558c9c109c1ce Binary files /dev/null and b/repository/__pycache__/UserRepository.cpython-311.pyc differ diff --git a/request/RequestAuth.py b/request/RequestAuth.py new file mode 100644 index 0000000000000000000000000000000000000000..06579c51bcb45207ca15e2125023884bf0b6dfd2 --- /dev/null +++ b/request/RequestAuth.py @@ -0,0 +1,19 @@ +from pydantic import BaseModel +from typing import Optional + +class RequestLoginEmail(BaseModel): + email: Optional[str] + password: Optional[str] + +class RequestLoginGoogle(BaseModel): + email: Optional[str] + token_google: Optional[str] + +class RequestRefreshTokenLogin(BaseModel): + refresh_token: Optional[str] + +class RequestRegister(BaseModel): + email: Optional[str] + password: Optional[str] + confirm_password: Optional[str] + username: Optional[str] diff --git a/request/RequestChat.py b/request/RequestChat.py new file mode 100644 index 0000000000000000000000000000000000000000..b15f21f1e5538f29ad0be359edff0a00de11f2dc --- /dev/null +++ b/request/RequestChat.py @@ -0,0 +1,17 @@ +from pydantic import BaseModel +from typing import Optional + +class RequestQuery2UpgradeOld(BaseModel): + user_id: int + text_all: str + question: Optional[str] + chat_name: Optional[str] + +class RequestExtractFile(BaseModel): + user_id: int + +class RequestDeleteChat(BaseModel): + user_id: int + chat_name: Optional[str] +class RequestGenerateQuestion(BaseModel): + user_id: int \ No newline at end of file diff --git a/request/RequestDefault.py b/request/RequestDefault.py new file mode 100644 index 0000000000000000000000000000000000000000..9852ed58c3cf1864e66f00f0709568bffc295e23 --- /dev/null +++ b/request/RequestDefault.py @@ -0,0 +1,14 @@ +from pydantic import BaseModel, EmailStr +from typing import Optional, List +from fastapi import UploadFile +class RequestCreateFireBaseUserGoogle(BaseModel): + email: Optional[str] = None + token_google: Optional[str] = None +class RequestInfoUser(BaseModel): + user_id: str +class RequestIsMe(BaseModel): + token: Optional[str] + +class RequestUpLoadImage(BaseModel): + user_id: Optional[str] + files: UploadFile = None diff --git a/request/RequestFile.py b/request/RequestFile.py new file mode 100644 index 0000000000000000000000000000000000000000..ae9ba15ccd5152f3a7b77a51fc62a0fbbe2a2858 --- /dev/null +++ b/request/RequestFile.py @@ -0,0 +1,19 @@ +from pydantic import BaseModel +from typing import List, Optional +from fastapi import UploadFile +class RequestGetNameFile(BaseModel): + user_id: Optional[str] +class RequestDeleteFile(BaseModel): + user_id: Optional[str] + name_file: Optional[str] +class RequestDeleteAllFile(BaseModel): + user_id: Optional[str] +class RequestDownLoadFolder(BaseModel): + user_id: Optional[str] + +class RequestDownLoadFile(BaseModel): + user_id: Optional[str] + name_file: Optional[str] +class RequestUploadFile(BaseModel): + files: Optional[List[UploadFile]] = None + user_id: Optional[str] \ No newline at end of file diff --git a/request/RequestMySQL.py b/request/RequestMySQL.py new file mode 100644 index 0000000000000000000000000000000000000000..c89d2ee2e8a7b31809ffb669aa64b9c3b5e6cecb --- /dev/null +++ b/request/RequestMySQL.py @@ -0,0 +1,32 @@ +from pydantic import BaseModel +from typing import Optional + +class RequestRenderChatHistory(BaseModel): + user_id: Optional[int] + +class RequestLoadChatHistory(BaseModel): + user_id: Optional[int] + chat_id: Optional[int] + +class RequestGetChatDetails(BaseModel): + id: Optional[str] + +class RequestStopChat(BaseModel): + user_id: Optional[str] + chat_name: Optional[str] + +class RequestCreateChatHistory(BaseModel): + user_id: Optional[str] + chat_name: Optional[str] +class RequestEditNameChat(BaseModel): + user_id: Optional[str] + name_old: Optional[str] + name_new: Optional[str] + +class RequestDeleteChat(BaseModel): + user_id: Optional[str] + chat_name: Optional[str] + +class RequestDeleteDetailChat(BaseModel): + user_id: Optional[str] + id_chat_detail: Optional[str] \ No newline at end of file diff --git a/request/RequestOTP.py b/request/RequestOTP.py new file mode 100644 index 0000000000000000000000000000000000000000..76341a3644007547101b7753c4ff9d82ca45240d --- /dev/null +++ b/request/RequestOTP.py @@ -0,0 +1,9 @@ +from pydantic import BaseModel +from typing import Optional + +class RequestCreateOTP(BaseModel): + email: Optional[str] + +class RequestVerifyOTP(BaseModel): + email: Optional[str] + otp: Optional[str] \ No newline at end of file diff --git a/request/RequestUser.py b/request/RequestUser.py new file mode 100644 index 0000000000000000000000000000000000000000..29a5895649fed21f968ca6bddaf2d471f78c6a0a --- /dev/null +++ b/request/RequestUser.py @@ -0,0 +1,48 @@ +from pydantic import BaseModel +from typing import Optional +class RequestLoginEmail(BaseModel): + email: Optional[str] + password: Optional[str] + +class RequestLoginGoogle(BaseModel): + email: Optional[str] + token_google: Optional[str] +class RequestUpdateUserInfo(BaseModel): + user_id: Optional[str] + uid: Optional[str] + email: Optional[str] + display_name: Optional[str] + photo_url: Optional[str] + +class RequestCheckInfoGoogle(BaseModel): + user_id: int +class RequestCheckInfoGoogleEmail(BaseModel): + email:Optional[str] +class RequestCreateOTP(BaseModel): + email: Optional[str] + +class RequestVerifyOTP(BaseModel): + email: Optional[str] + otp: Optional[str] + +class RequestCheckStateLogin(BaseModel): + user_id: Optional[int] + session_id_now: Optional[str] + +class RequestSignUp(BaseModel): + email: Optional[str] + password: Optional[str] + confirm_password: Optional[str] + username: Optional[str] + +class RequestResetPassword(BaseModel): + email: Optional[str] + +class RequestChangePassword(BaseModel): + user_id: Optional[str] + current_password: Optional[str] + new_password: Optional[str] + confirm_new_password: Optional[str] + +class RequestRefreshTokenLogin(BaseModel): + refresh_token: Optional[str] \ No newline at end of file diff --git a/request/__pycache__/RequestAuth.cpython-310.pyc b/request/__pycache__/RequestAuth.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3f40941ef3349ff954c0f84118a2b513bd7ed9a9 Binary files /dev/null and b/request/__pycache__/RequestAuth.cpython-310.pyc differ diff --git a/request/__pycache__/RequestChat.cpython-310.pyc b/request/__pycache__/RequestChat.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4e21a05a3920ca501da5788a7be5b9ab10c0c60c Binary files /dev/null and b/request/__pycache__/RequestChat.cpython-310.pyc differ diff --git a/request/__pycache__/RequestChat.cpython-311.pyc b/request/__pycache__/RequestChat.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4658d020f25a7665808013e93598fc4adb393ae0 Binary files /dev/null and b/request/__pycache__/RequestChat.cpython-311.pyc differ diff --git a/request/__pycache__/RequestDefault.cpython-310.pyc b/request/__pycache__/RequestDefault.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a4c2b18d6e71780095d7ae9eb27d3215bd2b12a7 Binary files /dev/null and b/request/__pycache__/RequestDefault.cpython-310.pyc differ diff --git a/request/__pycache__/RequestDefault.cpython-311.pyc b/request/__pycache__/RequestDefault.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b5a5e8207edebdcf08e65a99e1110874a74be194 Binary files /dev/null and b/request/__pycache__/RequestDefault.cpython-311.pyc differ diff --git a/request/__pycache__/RequestFile.cpython-310.pyc b/request/__pycache__/RequestFile.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..973374f9b1172f74689d87bebe98ed539c487b57 Binary files /dev/null and b/request/__pycache__/RequestFile.cpython-310.pyc differ diff --git a/request/__pycache__/RequestFile.cpython-311.pyc b/request/__pycache__/RequestFile.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5967aa6e7c1df37dc22303cb87f2a64064fe2688 Binary files /dev/null and b/request/__pycache__/RequestFile.cpython-311.pyc differ diff --git a/request/__pycache__/RequestMySQL.cpython-310.pyc b/request/__pycache__/RequestMySQL.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..324cd5b8fd93214227376d54b80cd7fbff35f58e Binary files /dev/null and b/request/__pycache__/RequestMySQL.cpython-310.pyc differ diff --git a/request/__pycache__/RequestMySQL.cpython-311.pyc b/request/__pycache__/RequestMySQL.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ac6dcc1d3a909dc454070b945d55a3140a57f756 Binary files /dev/null and b/request/__pycache__/RequestMySQL.cpython-311.pyc differ diff --git a/request/__pycache__/RequestOTP.cpython-310.pyc b/request/__pycache__/RequestOTP.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d50102a3c3ff602039be809f53245240a4d4ef78 Binary files /dev/null and b/request/__pycache__/RequestOTP.cpython-310.pyc differ diff --git a/request/__pycache__/RequestOTP.cpython-311.pyc b/request/__pycache__/RequestOTP.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e6d943511a401a478afa432f290a9a8aa7806379 Binary files /dev/null and b/request/__pycache__/RequestOTP.cpython-311.pyc differ diff --git a/request/__pycache__/RequestUser.cpython-310.pyc b/request/__pycache__/RequestUser.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..cfeeb00c12acb2f318eb3ab58e6c409541f2e4d4 Binary files /dev/null and b/request/__pycache__/RequestUser.cpython-310.pyc differ diff --git a/response/ResponseAuth.py b/response/ResponseAuth.py new file mode 100644 index 0000000000000000000000000000000000000000..9ef0ca91d11c9269eb3d9c2de6965f00fad778b6 --- /dev/null +++ b/response/ResponseAuth.py @@ -0,0 +1,40 @@ +from pydantic import BaseModel +from typing import List, Union, Optional +class Message(BaseModel): + message: str +class DataLogin(BaseModel): + access_token: str + refresh_token: str + expires_in: int + session_id: str + +class CheckModel(BaseModel): + check: bool + +class DataRefreshToken(BaseModel): + token_new: str + session_id: str + +class ResponseCreateOTP(BaseModel): + status: int + data: CheckModel + otp: str + +class ResponseLoginGoogle(BaseModel): + status: int + data: DataLogin + +class ResponseRefreshToken(BaseModel): + status: int + data: DataRefreshToken + +class DataSignUp(BaseModel): + email: str + +class ResponseRegister(BaseModel): + status: int + data: DataSignUp + +class ReponseError(BaseModel): + status: int + data: Message \ No newline at end of file diff --git a/response/ResponseChat.py b/response/ResponseChat.py new file mode 100644 index 0000000000000000000000000000000000000000..8fe21d49a969955dba54f15a201f4d0d96d5ee0e --- /dev/null +++ b/response/ResponseChat.py @@ -0,0 +1,55 @@ +from pydantic import BaseModel +from typing import List, Union, Optional + +class DataAnswer(BaseModel): + answer: str + +class DataAnswer1(BaseModel): + id: int + answer: str + data_relevant: List[str] + sources: List[str] + +class FileMetadata(BaseModel): + source: str + +class FileResponse(BaseModel): + page_content: str + metadata: FileMetadata + type: str + +class DataExtractFile(BaseModel): + text_all: Union[List[FileResponse], None, str] + +class Message(BaseModel): + message: str + +class CheckModel(BaseModel): + check: bool + +class ResponseQuery2Upgrade(BaseModel): + status: int + data: DataAnswer + +class GenerateQuestion(BaseModel): + question: Union[List[str], bool] + +class ResponseGenerateQuestion(BaseModel): + status: int + data: GenerateQuestion + +class ResponseQuery2UpgradeOld(BaseModel): + status: int + data: DataAnswer1 + +class ResponseExtractFile(BaseModel): + status: int + data: DataExtractFile + +class ResponseDeleteChat(BaseModel): + status: int + data: Message + +class ReponseError(BaseModel): + status: int + data: Message \ No newline at end of file diff --git a/response/ResponseDefault.py b/response/ResponseDefault.py new file mode 100644 index 0000000000000000000000000000000000000000..75750c932209b9b3ac83d0bd4809d80637c35e55 --- /dev/null +++ b/response/ResponseDefault.py @@ -0,0 +1,44 @@ +from pydantic import BaseModel + +class DataInfoUser(BaseModel): + uid: str + email: str + display_name: str + photo_url: str + +class DataIsMe(BaseModel): + user_id: int + +class DataUploadImage(BaseModel): + url: str +class Message(BaseModel): + message: str + +class CheckModel(BaseModel): + check: bool + +class DataCreateFireBaseUser(BaseModel): + localId: str + email: str + displayName: str + photoUrl: str + +class ResponseCreateFireBaseUser(BaseModel): + status: int + data: DataCreateFireBaseUser + +class ResponseInfoUser(BaseModel): + status: int + data: DataInfoUser + +class ResponseIsMe(BaseModel): + status: int + data: DataIsMe + +class ResponseUploadImage(BaseModel): + status: int + data: DataUploadImage + +class ReponseError(BaseModel): + status: int + data: Message \ No newline at end of file diff --git a/response/ResponseFile.py b/response/ResponseFile.py new file mode 100644 index 0000000000000000000000000000000000000000..8a92828bfef812b57793e2e55093c28d9bb0b31b --- /dev/null +++ b/response/ResponseFile.py @@ -0,0 +1,39 @@ +from pydantic import BaseModel +from typing import List + +class Message(BaseModel): + message: str + +class CheckModel(BaseModel): + check: bool + +class DataGetNameFile(BaseModel): + files: List[str] + +class ResponseGetNameFile(BaseModel): + status: int + data: DataGetNameFile + +class ResponseDeleteFile(BaseModel): + status: int + data: Message + +class ResponseDownloadFolder(BaseModel): + status: int + data: Message + +class ResponseDeleteAllFile(BaseModel): + status: int + data: Message + +class ResponseDownloadFile(BaseModel): + status: int + data: Message + +class ResponseUploadedFile(BaseModel): + status: int + data: Message + +class ReponseError(BaseModel): + status: int + data: Message \ No newline at end of file diff --git a/response/ResponseMySQL.py b/response/ResponseMySQL.py new file mode 100644 index 0000000000000000000000000000000000000000..22d6a82ff907f96317b7c875a0efed47f5101265 --- /dev/null +++ b/response/ResponseMySQL.py @@ -0,0 +1,66 @@ +from pydantic import BaseModel +from typing import List + +class ListUserChat(BaseModel): + id: int + email: str + chat_name: str + +class ChatDetail(BaseModel): + id: int + chat_id: int + question: str + answer: str + data_relevant: str + source_file: str + +class ChatDetailById(BaseModel): + id: int + data_relevant: str + source_file: str + +class ListChatDeTail(BaseModel): + detail_chat: List[ChatDetail] + +class UserInfoListResponse(BaseModel): + chat: List[ListUserChat] + +class Message(BaseModel): + message: str + +class CheckModel(BaseModel): + check: bool + +class ResponseRenderChatHistory(BaseModel): + status: int + data: UserInfoListResponse + +class ResponseChatDetailById(BaseModel): + status: int + data: ChatDetailById +class ResponseLoadChatHistory(BaseModel): + status: int + data: ListChatDeTail + +class ResponseEditChat(BaseModel): + status: int + data: Message + +class ResponseDeleteChat(BaseModel): + status: int + data: Message + +class ResponseCreateChat(BaseModel): + status: int + data: Message + +class ResponseStopChat(BaseModel): + status: int + data: Message +class ResponseDeleteChatDetailById(BaseModel): + status: int + data: CheckModel + +class ReponseError(BaseModel): + status: int + data: Message \ No newline at end of file diff --git a/response/ResponseOTP.py b/response/ResponseOTP.py new file mode 100644 index 0000000000000000000000000000000000000000..1918bc376bfa0a00d204c9c1052f8d61711ded42 --- /dev/null +++ b/response/ResponseOTP.py @@ -0,0 +1,25 @@ +from pydantic import BaseModel + +class Message(BaseModel): + message: str + +class CheckModel(BaseModel): + check: bool + +class ResponseCreateOTP(BaseModel): + status: int + data: CheckModel + otp: str + +class ResponseVerifyOTP(BaseModel): + status: int + data: Message + newpassword: str + +class ResponseVerifyOTPSignUp(BaseModel): + status: int + data: Message + +class ReponseError(BaseModel): + status: int + data: Message \ No newline at end of file diff --git a/response/ResponseUser.py b/response/ResponseUser.py new file mode 100644 index 0000000000000000000000000000000000000000..e0d9a7bcb90591701fba6aee54f4b3ad2d5dc2ba --- /dev/null +++ b/response/ResponseUser.py @@ -0,0 +1,74 @@ +from pydantic import BaseModel + +class DataLogin(BaseModel): + access_token: str + refresh_token: str + expires_in: int + session_id: str + +class DataRefreshToken(BaseModel): + token_new: str + session_id: str + +class DataSignUp(BaseModel): + email: str + +class Message(BaseModel): + message: str + +class CheckModel(BaseModel): + check: bool + +class ResponseLoginEmail(BaseModel): + status: int + data: DataLogin + +class ResponseLoginGoogle(BaseModel): + status: int + data: DataLogin + +class ResponseUpdateUserInfo(BaseModel): + status : int + data: Message + +class ResponseCreateOTP(BaseModel): + status: int + data: CheckModel + otp: str + +class ResponseVerifyOTP(BaseModel): + status: int + data: Message + newpassword: str + +class ResponseVerifyOTPSignUp(BaseModel): + status: int + data: Message + +class ResponseCheckInfoGoogle(BaseModel): + status: int + data: CheckModel + +class ResponseCheckStateLogin(BaseModel): + status: int + data: CheckModel + +class ResponseSignUp(BaseModel): + status: int + data: DataSignUp + +class ResponseResetPassword(BaseModel): + status: int + data: Message + +class ResponseChangePassword(BaseModel): + status: int + data: Message + +class ResponseRefreshTokenLogin(BaseModel): + status: int + data: DataRefreshToken + +class ReponseError(BaseModel): + status: int + data: Message \ No newline at end of file diff --git a/response/__pycache__/ResponseAuth.cpython-310.pyc b/response/__pycache__/ResponseAuth.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7057999e8f21d79ac6f835d81ce1b7d4ff4f3f00 Binary files /dev/null and b/response/__pycache__/ResponseAuth.cpython-310.pyc differ diff --git a/response/__pycache__/ResponseChat.cpython-310.pyc b/response/__pycache__/ResponseChat.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b9636d14712a58d16f711fca747d72a7ddf5abbe Binary files /dev/null and b/response/__pycache__/ResponseChat.cpython-310.pyc differ diff --git a/response/__pycache__/ResponseChat.cpython-311.pyc b/response/__pycache__/ResponseChat.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..238f5f31a8d3338298c085cdfe209190dea336df Binary files /dev/null and b/response/__pycache__/ResponseChat.cpython-311.pyc differ diff --git a/response/__pycache__/ResponseDefault.cpython-310.pyc b/response/__pycache__/ResponseDefault.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..837702d5cf014f8171b367ca5d7ce6c5f2215443 Binary files /dev/null and b/response/__pycache__/ResponseDefault.cpython-310.pyc differ diff --git a/response/__pycache__/ResponseDefault.cpython-311.pyc b/response/__pycache__/ResponseDefault.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5513f4d6004c2bfb678fdf1de9f12fd38416f152 Binary files /dev/null and b/response/__pycache__/ResponseDefault.cpython-311.pyc differ diff --git a/response/__pycache__/ResponseFile.cpython-310.pyc b/response/__pycache__/ResponseFile.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6641b4f3071be21616c971d09ee84a700856bed7 Binary files /dev/null and b/response/__pycache__/ResponseFile.cpython-310.pyc differ diff --git a/response/__pycache__/ResponseFile.cpython-311.pyc b/response/__pycache__/ResponseFile.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a2a35244661dd857cf584ce7d95f38f9739ae044 Binary files /dev/null and b/response/__pycache__/ResponseFile.cpython-311.pyc differ diff --git a/response/__pycache__/ResponseMySQL.cpython-310.pyc b/response/__pycache__/ResponseMySQL.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b3ae3f85b11a9f3879b177eab059b0d2e21727d5 Binary files /dev/null and b/response/__pycache__/ResponseMySQL.cpython-310.pyc differ diff --git a/response/__pycache__/ResponseMySQL.cpython-311.pyc b/response/__pycache__/ResponseMySQL.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..42a4f731cca5106b937647ed4957284e0fb68053 Binary files /dev/null and b/response/__pycache__/ResponseMySQL.cpython-311.pyc differ diff --git a/response/__pycache__/ResponseOTP.cpython-310.pyc b/response/__pycache__/ResponseOTP.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..21a77772024e80f45f7348dcfbbe864ad02208c8 Binary files /dev/null and b/response/__pycache__/ResponseOTP.cpython-310.pyc differ diff --git a/response/__pycache__/ResponseOTP.cpython-311.pyc b/response/__pycache__/ResponseOTP.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..da4dfb797b3c6c760660ab4df3202f6e9a57ca93 Binary files /dev/null and b/response/__pycache__/ResponseOTP.cpython-311.pyc differ diff --git a/response/__pycache__/ResponseUser.cpython-310.pyc b/response/__pycache__/ResponseUser.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..70e3859cfb5f7b8d19fc6f2070371607bcbd80f9 Binary files /dev/null and b/response/__pycache__/ResponseUser.cpython-310.pyc differ diff --git a/service/AuthService.py b/service/AuthService.py new file mode 100644 index 0000000000000000000000000000000000000000..60d7bd22a0a814c503155308d453d088b1943a0e --- /dev/null +++ b/service/AuthService.py @@ -0,0 +1,292 @@ +from datetime import timedelta, datetime +from request import RequestAuth as req +from response import ResponseAuth as res +import requests +import json, re +from auth.authentication import signJWT +from firebase_admin import credentials, auth, exceptions +import firebase_admin +from repository import UserLoginRepository, UserRepository, UserInfoRepository, OTPRepository +import service.OTPService +from function import support_function as sf +from dotenv import load_dotenv +import os +from response import ResponseUser as res +load_dotenv() +CLIENT_ID_GOOGLE = os.getenv('CLIENT_ID') +API_SIGN_UP_FIREBASE_PATH = os.getenv('API_SIGN_UP_FIREBASE') +regex = r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,7}\b' +def get_user1(email): + try: + user = auth.get_user_by_email(email) + return user + except exceptions.FirebaseError as e: + return None + +def check_email(email): + if isinstance(email, str) and re.fullmatch(regex, email): + return True + else: + return False +from pathlib import Path +try: + if not firebase_admin._apps: + json_path = Path(__file__).resolve().parent / 'app' / 'firebase_certificate.json' + cred = credentials.Certificate(str(json_path)) + fred = firebase_admin.initialize_app(cred) +except: + if not firebase_admin._apps: + cred = credentials.Certificate("firebase_certificate.json") + fred = firebase_admin.initialize_app(cred) +def sign_up_with_email_and_password(email, password, username=None, return_secure_token=True): + try: + rest_api_url = "https://identitytoolkit.googleapis.com/v1/accounts:signUp" + payload = { + "email": email, + "password": password, + "returnSecureToken": return_secure_token + } + if username: + payload["displayName"] = username + payload = json.dumps(payload) + r = requests.post(rest_api_url, params={"key": API_SIGN_UP_FIREBASE_PATH}, data=payload) + try: + if r.status_code == 200: + response_data = r.json() + email = response_data.get('email') + display_name = response_data.get('displayName') # Lấy displayName nếu có + return email, display_name + except Exception as e: + pass + except Exception as e: + pass + +def sign_in_with_email_and_password(email=None, password=None, return_secure_token=True): + rest_api_url = "https://identitytoolkit.googleapis.com/v1/accounts:signInWithPassword" + try: + payload = { + "returnSecureToken": return_secure_token + } + if email: + payload["email"] = email + if password: + payload["password"] = password + payload = json.dumps(payload) + r = requests.post(rest_api_url, params={"key": API_SIGN_UP_FIREBASE_PATH}, data=payload) + r.raise_for_status() + data = r.json() + if 'idToken' in data: + return data['email'] + else: + return False + except requests.exceptions.RequestException as e: + print(f"Error signing in: {e}") + return False + + +async def login(request: req.RequestLoginEmail): + try: + email = request.email + password = request.password + check_email_fc = sf.check_email_empty_invalid(email) + if check_email_fc is not True: + return check_email_fc + if password is None: + return res.ReponseError( + status=400, + data=res.Message(message="Password is empty") + ) + user_check = get_user1(email) + if user_check is None: + return res.ReponseError( + status=404, + data=res.Message(message="Email not exist") + ) + user = sign_in_with_email_and_password(email, password) + + if user: + check = signJWT(user) + if check is False: + return res.ReponseError( + status=500, + data=res.Message(message="Invalid authorization code.") + ) + else: + access_token = check["access_token"] + refresh_token = check["refresh_token"] + expires_in = check["expires_in"] + session_id = check["session_id"] + return res.ResponseLoginEmail( + status=200, + data=res.DataLogin(access_token=access_token, refresh_token=refresh_token, expires_in=expires_in, + session_id=session_id) + ) + else: + return res.ReponseError( + status=400, + data=res.Message(message="Passwords do not match") + ) + except: + return res.ReponseError( + status=500, + data=res.Message(message="Server Error") + ) + +def verify_token_google(token): + from google.oauth2 import id_token + from google.auth.transport import requests + try: + CLIENT_ID = CLIENT_ID_GOOGLE + id_info = id_token.verify_oauth2_token(token, requests.Request(), CLIENT_ID) + check = id_info['email_verified'] + if check is True: + return True + except ValueError as e: + return False + +async def login_google(request: req.RequestLoginGoogle): + try: + email = request.email + token_google = request.token_google + check_google = verify_token_google(token_google) + if check_google is False: + return res.ReponseError( + status=400, + data =res.Message(message="Login google failed") + ) + check_email_fc = sf.check_email_empty_invalid(email) + if check_email_fc is not True: + return check_email_fc + user = get_user1(email) + if user: + check = signJWT(email) + if check == False: + return res.ReponseError( + status=500, + data =res.Message(message="Invalid authorization code.") + ) + else: + access_token = check["access_token"] + refresh_token = check["refresh_token"] + expires_in = check["expires_in"] + session_id = check["session_id"] + return res.ResponseLoginGoogle( + status= 200, + data = res.DataLogin(access_token=access_token,refresh_token=refresh_token,expires_in=expires_in,session_id=session_id) + ) + else: + return res.ReponseError( + status= 404, + data = res.Message(message="Email not exist") + ) + except: + return res.ReponseError( + status=500, + data=res.Message(message="Server Error") + ) + +async def sign_up(request: req.RequestRegister): + try: + email = request.email + password = request.password + confirm_password = request.confirm_password + username = request.username + check_email_fc = sf.check_email_empty_invalid(email) + if check_email_fc is not True: + return check_email_fc + if password is None or password == "": + return res.ReponseError( + status=400, + data =res.Message(message="password is empty") + ) + if confirm_password is None or confirm_password == "": + return res.ReponseError( + status=400, + data =res.Message(message="confirm password is empty") + ) + if confirm_password != password: + return res.ReponseError(status=400, + data =res.Message(message="password and confirm_password do not match")) + user_signup = get_user1(email) + if user_signup is not None: + return res.ReponseError( + status=400, + data =res.Message(message="Email exist") + ) + + user_info, display_name = sign_up_with_email_and_password(email, password, username) + if user_info: + return res.ResponseSignUp( + status=200, + data =res.DataSignUp(email=user_info) + ) + else: + return res.ReponseError( + status=500, + data =res.Message(message="Internal Server Error") + ) + except: + return res.ReponseError( + status=500, + data=res.Message(message="Server Error") + ) + +import pytz, datetime +import auth.authentication as auth123 +from response import ResponseDefault as res1 +def refresh_token(request: req.RequestRefreshTokenLogin): + try: + token = request.refresh_token + if token is None: + return res.ReponseError( + status=400, + data=res.Message(message="token is empty") + ) + user_token = UserRepository.getUserIdByRefreshToken(token) + if user_token is None: + return res.ReponseError( + status=404, + data=res_login.Message(message="Not found refresh token") + ) + email = UserRepository.getEmailUserById(user_token) + if email: + rf_token = token + result = auth123.get_refresh_token(token, email) + token_new = result["access_token"] + rf_token_new = result["refresh_token"] + seconds1 = result["expires_in"] + session_id = result["session_id"] + vn_timezone = pytz.timezone('Asia/Ho_Chi_Minh') + current_time = datetime.datetime.utcnow().replace(tzinfo=pytz.utc).astimezone(vn_timezone) + timedelta( + seconds=seconds1) + formatted_time = current_time.strftime('%Y-%m-%d %H:%M:%S ') + if rf_token == rf_token_new: + UserRepository.updateAccessToken(user_token, token_new, formatted_time) + else: + UserRepository.UpdateAccessTokenRefreshTokenById(user_token, token_new, rf_token_new, formatted_time) + user = token_new + if user == False: + return res.ReponseError( + status=400, + data=res.Message(message="Refresh token error") + ) + return res.ResponseRefreshTokenLogin( + status=200, + data=res.DataRefreshToken(token_new=user, session_id=session_id) + ) + except: + return res.ReponseError( + status=500, + data=res.Message(message="Server Error") + ) +def check_token_is_valid(token): + try: + check = UserRepository.getEmailUserByAccessToken(token) + if check is None: + return False + return True + except: + return res.ReponseError( + status=500, + data=res.Message(message="Server Error") + ) \ No newline at end of file diff --git a/service/ChatService.py b/service/ChatService.py new file mode 100644 index 0000000000000000000000000000000000000000..e395cbc799c12e324b1da32ff463143b2a475463 --- /dev/null +++ b/service/ChatService.py @@ -0,0 +1,148 @@ +from typing import Union +from datetime import timedelta +from request import RequestChat as req +from response import ResponseChat as res +from repository import ChatHistoryRepository, DetailChatRepository, UserRepository +import function.chatbot as sf +from typing import Dict +import json, re +from pydantic import BaseModel +from function import support_function +regex = r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,7}\b' + +def check_email(email): + if(re.fullmatch(regex, email)): + return True + else: + return False + +class Document(BaseModel): + page_content: str + metadata: Dict[str, str] + type: str + +async def query2_upgrade_old(request: req.RequestQuery2UpgradeOld): + # try: + user_id = request.user_id + question = request.question + text_all = request.text_all + chat_name = request.chat_name + email = support_function.check_email_service(str(user_id)) + if isinstance(email, res.ReponseError): + return email + if question is None: + return res.ReponseError( + status=400, + data =res.Message(message="question is empty") + ) + if chat_name is None: + return res.ReponseError( + status=400, + data =res.Message(message="chat_name is empty") + ) + text_all_dicts = json.loads(text_all) + text_all1 = [Document(**doc) for doc in text_all_dicts] + chat_id_exist = ChatHistoryRepository.getIdChatHistoryByUserIdAndNameChat(user_id, chat_name) + chat_history = "" + if chat_id_exist: + list_chat_detail = DetailChatRepository.getListDetailChatByChatId(chat_id_exist) + for item in list_chat_detail: + chat_history += f"You: {item.YouMessage}\nAI: {item.AiMessage}\n\n" + + test, list1, list2 = sf.handle_query_upgrade_keyword_old(question, text_all1, email,chat_history) + text1 = "".join(list1) + text2 = "".join(list2) + id = 0 + if test: + chat_id = ChatHistoryRepository.getIdChatHistoryByUserIdAndNameChat(user_id,chat_name) + if chat_id: + id = DetailChatRepository.addDetailChat(chat_id,question, test, text1, text2) + if chat_id is None: + ChatHistoryRepository.addChatHistory(user_id,chat_name) + chat_id_new = ChatHistoryRepository.getIdChatHistoryByUserIdAndNameChat(user_id,chat_name) + id = DetailChatRepository.addDetailChat(chat_id_new, question, test, text1, text2) + return res.ResponseQuery2UpgradeOld( + status= 200, + data = res.DataAnswer1(id = id, + answer=test, + data_relevant=list1, + sources=list2)) + if test is None or test == "": + return res.ReponseError( + status=500, + data =res.Message(message="No answer") + ) + # except: + # return res.ReponseError( + # status=500, + # data =res.Message(message="Server Error") + # ) + +async def extract_file(request: req.RequestExtractFile): + try: + user_id = request.user_id + email = support_function.check_email_service(str(user_id)) + if isinstance(email, res.ReponseError): + return email + text_all1 = sf.extract_data2(email) + if text_all1 is False: + return res.ResponseExtractFile( + status= 200, + data = res.DataExtractFile(text_all="No data response")) + return res.ResponseExtractFile( + status= 200, + data = res.DataExtractFile(text_all=text_all1)) + except: + return res.ReponseError( + status=500, + data =res.Message(message="Server Error") + ) + +async def generate_question(request: req.RequestGenerateQuestion): + try: + user_id = request.user_id + email = support_function.check_email_service(str(user_id)) + if isinstance(email, res.ReponseError): + return email + text_all1 = sf.generate_question(email) + if text_all1 is False: + return res.ResponseGenerateQuestion( + status= 200, + data = res.GenerateQuestion(question=False)) + + return res.ResponseGenerateQuestion( + status= 200, + data = res.GenerateQuestion(question=text_all1)) + except: + return res.ReponseError( + status=500, + data=res.Message(message="Server Error") + ) + +async def delete_chat(request: req.RequestDeleteChat): + try: + user_id = request.user_id + email = support_function.check_email_service(str(user_id)) + if isinstance(email, res.ReponseError): + return email + chat_name = request.chat_name + if chat_name is None: + return res.ReponseError( + status=400, + data =res.Message(message="chat_name is empty") + ) + DetailChatRepository.delete_chat_detail(chat_name) + check = ChatHistoryRepository.deleteChatHistory(user_id,chat_name) + if check is False: + return res.ResponseDeleteChat( + status = 500, + data = res.Message(message="Delete conversation chat failed")) + else: + return res.ResponseDeleteChat( + status = 200, + data = res.Message(message="Delete conversation chat success")) + except: + return res.ReponseError( + status= 500, + data = res.Message(message="Server Error") + ) \ No newline at end of file diff --git a/service/DefaultService.py b/service/DefaultService.py new file mode 100644 index 0000000000000000000000000000000000000000..fdcf300dd27bcfb3e1cfc82a4e5b8e7774d52053 --- /dev/null +++ b/service/DefaultService.py @@ -0,0 +1,205 @@ +from typing import Union +from datetime import timedelta +from request import RequestDefault as req +from response import ResponseDefault as res +from response import ResponseUser as res_login +from firebase_admin import credentials, auth, exceptions +import firebase_admin +import base64 +import auth.authentication as auth123 +import re +from repository import UserRepository, UserInfoRepository +from pathlib import Path +import cloudinary +import cloudinary.uploader +from fastapi import FastAPI, File, UploadFile +from function import support_function as sf +from dotenv import load_dotenv +from service import AuthService as authservice +import os +load_dotenv() +CLOUDINARY_CLOUD_NAME=os.getenv("CLOUDINARY_CLOUD_NAME") +CLOUDINARY_API_KEY=os.getenv("CLOUDINARY_API_KEY") +CLOUDINARY_API_SECRET=os.getenv("CLOUDINARY_API_SECRET") + +cloudinary.config( + cloud_name=CLOUDINARY_CLOUD_NAME, + api_key=CLOUDINARY_API_KEY, + api_secret=CLOUDINARY_API_SECRET +) +import os + +try: + if not firebase_admin._apps: + cred = credentials.Certificate("../certificate/firebase_certificate.json") + fred = firebase_admin.initialize_app(cred) +except: + try: + if not firebase_admin._apps: + cred = credentials.Certificate("firebase_certificate.json") + fred = firebase_admin.initialize_app(cred) + except: + if not firebase_admin._apps: + json_path = Path(__file__).resolve().parent / 'app' / 'firebase_certificate.json' + cred = credentials.Certificate(str(json_path)) + fred = firebase_admin.initialize_app(cred) + +regex = r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,7}\b' + +def check_email(email): + if(re.fullmatch(regex, email)): + return True + else: + return False + +def get_user(email): + try: + user = auth.get_user_by_email(email) + return user + except exceptions.FirebaseError as e: + return None + +def create_user(email): + user = auth.create_user(email=email) + return user + +def get_user1(email): + try: + user = auth.get_user_by_email(email) + return user + except exceptions.FirebaseError as e: + return None + +async def create_firebase_user(request: req.RequestCreateFireBaseUserGoogle): + try: + email = request.email + token_google = request.token_google + check_email_fc = sf.check_email_empty_invalid(email) + if check_email_fc is not True: + return check_email_fc + user = get_user(email) + if token_google is None or token_google == "": + return res.ReponseError( + status=400, + data=res.Message(message="token google not empty") + ) + check_google = authservice.verify_token_google(token_google) + if check_google == False: + return res.ReponseError( + status=400, + data=res.Message(message="Create user failed") + ) + if user: + email1 = user.email + display_name = user.display_name + uid = user.uid + photo_url = user.photo_url + return res.ResponseCreateFireBaseUser( + status=200, + data = res.DataCreateFireBaseUser(localId=uid, + email=email1, + displayName=display_name, + photoUrl=photo_url) + ) + else: + return res.ReponseError( + status=500, + data =res.Message(message="Error") + ) + except: + return res.ReponseError( + status=500, + data =res.Message(message="Server Error") + ) + +async def info_user(request: req.RequestInfoUser): + try: + user_id = request.user_id + email = sf.check_email_service(user_id) + if isinstance(email, res.ReponseError): + return email + user = get_user(email) + if user is None: + return res.ReponseError( + status=404, + data=res.Message(message="User not found") + ) + uid = user.uid if user.uid else "" + email = user.email if user.email else "" + display_name = user.display_name if user.display_name else "N/A" + photo_url = user.photo_url if user.photo_url else "N/A" + return res.ResponseInfoUser( + status=200, + data=res.DataInfoUser( + uid=uid, + email=email, + display_name=display_name, + photo_url=photo_url + ) + ) + except Exception as e: + return res.ReponseError( + status=500, + data=res.Message(message="Server Error: " + str(e)) + ) + +def check_email_token(token): + try: + decoded_token = auth123.decodeJWT(token) + sub_value = decoded_token.get("sub") + name_user = base64.b85decode(sub_value.encode('ascii')).decode('ascii') + return name_user + except: + return False + +async def is_me(request: req.RequestIsMe): + try: + token = request.token + if token is None or token == "": + return res.ReponseError( + status=400, + data =res.Message(message="token is empty") + ) + test = check_email_token(token) + if test is not False: + user_id = UserRepository.getUserByEmail(test).id + return res.ResponseIsMe( + status=200, + data = res.DataIsMe(user_id = user_id)) + except: + return res.ReponseError( + status=500, + data=res.Message(message="Server Error") + ) + +ALLOWED_EXTENSIONS = {'png', 'jpg','jpeg'} +def allowed_file(filename): + return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS + +async def upload_image_service(request: req.RequestUpLoadImage): + try: + user_id = request.user_id + file = request.files + email = sf.check_email_service(user_id) + if isinstance(email, res.ReponseError): + return email + if not allowed_file(file.filename): + return res.ReponseError( + status=415, + data=res.Message(message=f"File type not allow") + ) + temp_file_path = f"temp_image_{email}.png" + contents = file.file.read() + with open(temp_file_path, "wb") as temp_file: + temp_file.write(contents) + upload_result = cloudinary.uploader.upload(temp_file_path, public_id=email) + os.remove(temp_file_path) + return res.ResponseUploadImage( + status=200, + data=res.DataUploadImage(url=upload_result["secure_url"]) + ) + except: + return res.ReponseError( + status=500, + data=res.Message(message="Server Error") + ) \ No newline at end of file diff --git a/service/FileService.py b/service/FileService.py new file mode 100644 index 0000000000000000000000000000000000000000..73cfc0169e963a118654ec3e084e661afcc67520 --- /dev/null +++ b/service/FileService.py @@ -0,0 +1,151 @@ +from request import RequestFile as req +from response import ResponseFile as res +from response import ResponseDefault as res1 +import function.dropbox as sf_dropbox +import os +import shutil +import re +from repository import UserRepository +from function import support_function as sf +ALLOWED_EXTENSIONS = {'csv', 'txt', 'doc', 'docx', 'pdf', 'xlsx', 'pptx', 'json','md'} +regex = r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,7}\b' + +def check_email(email): + if(re.fullmatch(regex, email)): + return True + else: + return False + +def allowed_file(filename): + return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS + +async def listNameFiles(request: req.RequestGetNameFile ): + try: + user_id = request.user_id + email = sf.check_email_service(user_id) + if isinstance(email,res1.ReponseError): + return email + list_files = sf_dropbox.list_files(email) + return res.ResponseGetNameFile( + status= 200, + data = res.DataGetNameFile(files=list_files) + ) + except: + return res.ReponseError( + status=500, + data =res.Message(message="Server Error") + ) + +async def deleteFile(request: req.RequestDeleteFile): + try: + user_id = request.user_id + name_file = request.name_file + email = sf.check_email_service(user_id) + if isinstance(email, res1.ReponseError): + return email + if name_file is None or name_file == "": + return res.ReponseError( + status=400, + data =res.Message(message="Name file is empty") + ) + sf_dropbox.delete_file(email,name_file) + return res.ResponseDeleteFile( + status=200, + data =res.Message(message=f"delete {name_file} success") + ) + except: + return res.ReponseError( + status=500, + data =res.Message(message=f"delete {name_file} error") + ) + +async def download_folder(request:req.RequestDownLoadFolder): + try: + user_id = request.user_id + email = sf.check_email_service(user_id) + if isinstance(email, res1.ReponseError): + return email + sf_dropbox.download_folder(email) + return res.ResponseDownloadFolder( + status=200, + data =res.Message(message=f"Downloaded folder {email} success") + ) + except: + return res.ReponseError( + status=500, + data =res.Message(message=f"Server error") + ) + +async def download_file(request:req.RequestDownLoadFile): + try: + user_id = request.user_id + name_file = request.name_file + email = sf.check_email_service(user_id) + if isinstance(email, res1.ReponseError): + return email + if name_file is None or name_file == "": + return res.ReponseError( + status=400, + data =res.Message(message="name_file is empty") + ) + sf_dropbox.search_and_download_file(name_file,email) + return res.ResponseDownloadFile( + status=200, + data =res.Message(message=f"Downloaded file '{name_file}' by email: '{email}' success") + ) + except: + return res.ReponseError( + status=500, + data =res.Message(message=f"Server error") + ) + +ALLOWED_EXTENSIONS = {'csv', 'txt', 'doc', 'docx', 'pdf', 'xlsx', 'pptx', 'json','md'} + +def allowed_file1(filename): + return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS +async def upload_files(request: req.RequestUploadFile): + try: + user_id = request.user_id + files = request.files + email = sf.check_email_service(user_id) + if isinstance(email, res1.ReponseError): + return email + for file in files: + if not allowed_file(file.filename): + return res.ReponseError( + status=415, + data =res.Message(message=f"File type not allow") + ) + temp_dir = f"/code/temp/{email}" + os.makedirs(temp_dir, exist_ok=True) + file_path = os.path.join(temp_dir, file.filename) + with open(file_path, "wb") as buffer: + shutil.copyfileobj(file.file, buffer) + cloud_path = f"/{email}/{file.filename}" + sf_dropbox.upload_file(file_path, cloud_path) + return res.ResponseUploadedFile( + status=200, + data =res.Message(message=f"Load file success") + ) + except: + return res.ReponseError( + status=500, + data =res.Message(message=f"Load file error") + ) + +async def deleteAllFile(request: req.RequestDeleteAllFile): + try: + user_id = request.user_id + email = sf.check_email_service(user_id) + if isinstance(email, res.ReponseError): + return email + sf_dropbox.delete_all_files_in_folder(email) + return res.ResponseDeleteAllFile( + status=200, + data=res.Message(message=f"Delete all file success") + ) + except: + return res.ReponseError( + status=500, + data=res.Message(message=f"Delete all file error") + ) diff --git a/service/MySQLService.py b/service/MySQLService.py new file mode 100644 index 0000000000000000000000000000000000000000..b5425d9e046e064a46705f43f92787adcfe0d600 --- /dev/null +++ b/service/MySQLService.py @@ -0,0 +1,264 @@ +import json + +from request import RequestMySQL as req +from response import ResponseMySQL as res +from response import ResponseDefault as res1 +from repository import ChatHistoryRepository +from repository import DetailChatRepository,UserRepository +from fastapi.responses import JSONResponse +from function import support_function as sf +import re +regex = r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,7}\b' + +def check_email(email): + if(re.fullmatch(regex, email)): + return True + else: + return False + +async def edit_chat(request: req.RequestEditNameChat): + try: + user_id = request.user_id + name_old = request.name_old + name_new = request.name_new + email = sf.check_email_service(user_id) + if isinstance(email, res1.ReponseError): + return email + if name_old is None or name_old =="": + return res.ReponseError( + status=400, + data =res.Message(message="name_old is empty") + ) + if name_new is None or name_new == "": + return res.ReponseError( + status=400, + data =res.Message(message="name_new is empty") + ) + chat_exist = ChatHistoryRepository.getIdChatHistoryByUserIdAndNameChatNew(user_id, name_new) + if chat_exist: + return res.ReponseError( + status=400, + data=res.Message(message="name_new duplicate") + ) + id_chat = ChatHistoryRepository.getIdChatHistoryByUserIdAndNameChat(user_id, name_old) + if id_chat: + ChatHistoryRepository.updateNameChatHistory(user_id,name_old,name_new) + check = True + else: + check = False + if check is True: + return res.ResponseEditChat( + status= 200, + data= res.Message(message=check) + ) + else: + return res.ReponseError( + status=500, + data =res.Message(message="Update chat error") + ) + except: + return res.ReponseError( + status=500, + data =res.Message(message="Server Error") + ) + +async def delete_chat(request: req.RequestDeleteChat): + try: + user_id = request.user_id + chat_name = request.chat_name + email = sf.check_email_service(user_id) + if isinstance(email, res1.ReponseError): + return email + if chat_name is None or chat_name =="": + return res.ReponseError( + status=400, + data =res.Message(message="chat_name is empty") + ) + DetailChatRepository.delete_chat_detail(chat_name) + chat_exist = ChatHistoryRepository.getIdChatHistoryByUserIdAndNameChat(user_id, chat_name) + if chat_exist is None: + return res.ReponseError( + status=404, + data=res.Message(message="chat_name not exist") + ) + check = ChatHistoryRepository.deleteChatHistory(user_id,chat_name) + if check is True: + return res.ResponseDeleteChat( + status= 200, + data= res.Message(message="Delete conversation chat success") + ) + else: + return res.ReponseError( + status=500, + data =res.Message(message="Delete conversation chat error") + ) + except Exception as e: + return res.ResponseDeleteChat( + status=500, + data=res.Message(message=str(e)) + ) + +async def delete_chat_detail_by_id(request: req.RequestDeleteDetailChat): + try: + user_id = request.user_id + chat_detail_id = request.id_chat_detail + email = sf.check_email_service(user_id) + if isinstance(email, res1.ReponseError): + return email + if chat_detail_id is None or chat_detail_id == " ": + return res.ReponseError( + status=400, + data=res.Message(message="id chat_detail is empty") + ) + check = DetailChatRepository.delete_chat_detail_by_id((chat_detail_id)) + if check is True: + return res.ResponseDeleteChatDetailById( + status= 200, + data= res.CheckModel(check=check) + ) + else: + return res.ResponseDeleteChatDetailById( + status=200, + data=res.CheckModel(check=check) + ) + except Exception as e: + return res.ResponseDeleteChat( + status=500, + data=res.Message(message=str(e)) + ) + +async def render_chat_history(request: req.RequestRenderChatHistory): + try: + user_id = request.user_id + email = sf.check_email_service(user_id) + if isinstance(email, res1.ReponseError): + return email + chat_detail = ChatHistoryRepository.getChatHistoryById(user_id) + chat1 = [res.ListUserChat(id=item.id, email=item.email, chat_name=item.name_chat) for item in chat_detail] + return res.ResponseRenderChatHistory( + status=200, + data=res.UserInfoListResponse(chat=chat1) + ) + except Exception as e: + return res.ReponseError( + status=500, + data=res.Message(message="Server Error") + ) + +async def create_chat_history(request: req.RequestCreateChatHistory): + try: + user_id = request.user_id + chat_name = request.chat_name + email = sf.check_email_service(str(user_id)) + if isinstance(email, res1.ReponseError): + return email + if chat_name is None or chat_name == "": + return res.ReponseError( + status=400, + data=res.Message(message="chat_name is empty") + ) + check = ChatHistoryRepository.getIdChatHistoryByUserIdAndNameChat(user_id,chat_name) + if check is not None: + return res.ReponseError( + status=400, + data=res.Message(message="chat_name exist") + ) + ChatHistoryRepository.addChatHistory(user_id,chat_name) + return res.ResponseCreateChat( + status=200, + data=res.Message(message="create chat success") + ) + except: + return res.ReponseError( + status=500, + data=res.Message(message="Server Error") + ) + +async def get_detail_chat_by_chat_id(request: req.RequestGetChatDetails): + id = request.id + if id is None or id == "": + return res.ReponseError( + status=400, + data=res.Message(message="Id is empty") + ) + chat_detail1 = DetailChatRepository.getDetailChatByChatId(id) + if chat_detail1: + return res.ResponseChatDetailById( + status=200, + data=res.ChatDetailById( + id = chat_detail1.id, + data_relevant = chat_detail1.data_relevant, + source_file = chat_detail1.source_file + ) + ) + else: + return res.ReponseError( + status=404, + data=res.Message(message="Chat not exist") + ) + +async def load_chat_history(request: req.RequestLoadChatHistory): + try: + chat_id = request.chat_id + user_id = request.user_id + email = sf.check_email_service(str(user_id)) + if isinstance(email, res1.ReponseError): + return email + if chat_id is None or chat_id == "": + return res.ReponseError( + status = 400, + data = res.Message(message="chat_id is empty") + ) + check_exist_chatid_width_user_id = ChatHistoryRepository.getChatHistoryByChatIdAndUserId(chat_id,user_id) + if check_exist_chatid_width_user_id is None: + return res.ReponseError( + status=404, + data=res.Message(message="Not found chat width chat_id and user_id") + ) + result = DetailChatRepository.getListDetailChatByChatId(chat_id) + chat1 = [res.ChatDetail(id=item.id, chat_id = item.chat_id, question=item.YouMessage,answer=item.AiMessage,data_relevant = item.data_relevant,source_file=item.source_file) for item in result] + return res.ResponseLoadChatHistory( + status = 200, + data = res.ListChatDeTail(detail_chat=chat1) + ) + except: + return res.ReponseError( + status=500, + data=res.Message(message="Server Error") + ) + + +async def delete_last_chat_detail_by_chat_name(request: req.RequestStopChat): + try: + user_id = request.user_id + chat_name = request.chat_name + email = sf.check_email_service(user_id) + if isinstance(email, res1.ReponseError): + return email + if not chat_name: + return res.ReponseError( + status=400, + data=res.Message(message="chat_name is empty") + ) + check_exist_chat = ChatHistoryRepository.getIdChatHistoryByUserIdAndNameChat(user_id, chat_name) + if check_exist_chat is None: + return res.ReponseError( + status=404, + data=res.Message(message="Chat not exist") + ) + check = ChatHistoryRepository.delete_last_chat_detail_by_chat_name_and_email(chat_name, user_id) + if check: + return res.ResponseStopChat( + status=200, + data=res.Message(message="stop chat success") + ) + else: + return res.ReponseError( + status=500, + data=res.Message(message="Failed to stop chat") + ) + except Exception as e: + return res.ReponseError( + status=500, + data=res.Message(message=f"Server Error: {e}") + ) \ No newline at end of file diff --git a/service/OTPService.py b/service/OTPService.py new file mode 100644 index 0000000000000000000000000000000000000000..576914ecbac47805b9b5bc4f9a1dd73ddb3c8836 --- /dev/null +++ b/service/OTPService.py @@ -0,0 +1,168 @@ +from datetime import timedelta,datetime +from request import RequestOTP as req +from response import ResponseOTP as res +import re +from firebase_admin import auth, exceptions +from repository import OTPRepository +from datetime import datetime, timedelta +import datetime, string,random +from function import support_function as sf +regex = r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,7}\b' + +def get_user1(email): + try: + user = auth.get_user_by_email(email) + return user + except exceptions.FirebaseError as e: + return None + +def check_email(email): + if isinstance(email, str) and re.fullmatch(regex, email): + return True + else: + return False + +def generate_otp(length=6): + characters = string.ascii_uppercase + string.digits + otp = ''.join(random.choice(characters) for _ in range(length)) + return otp + +async def createOTP(request: req.RequestCreateOTP): + try: + email = request.email + otp = generate_otp() + check_email_fc = sf.check_email_empty_invalid(email) + if check_email_fc is not True: + return check_email_fc + OTPRepository.addOTP(email,otp) + return res.ResponseCreateOTP( + status=200, + data = res.CheckModel(check=True), + otp = otp + ) + except: + return res.ReponseError( + status=500, + data=res.Message(message="Server Error") + ) + +async def verifyOTP(request: req.RequestVerifyOTP): + try: + email = request.email + otp = request.otp + check_email_fc = sf.check_email_empty_invalid(email) + if check_email_fc is not True: + return check_email_fc + if otp is None: + return res.ReponseError( + status=400, + data=res.Message(message="otp is empty") + ) + user_otp = OTPRepository.getOtpByEmail(email) + if user_otp: + otp_db = user_otp.otp + otp_created_at = user_otp.created_at + if otp == otp_db: + current_time = datetime.datetime.now() + otp_expiry_time = otp_created_at + timedelta(minutes=15) + if current_time <= otp_expiry_time: + OTPRepository.deleteOTP(email, otp) + return res.ResponseVerifyOTPSignUp( + status=200, + data=res.Message(message="OTP is valid") + ) + else: + return res.ReponseError( + status=400, + data=res.Message(message="OTP has expired") + ) + else: + return res.ReponseError( + status=400, + data=res.Message(message="Invalid OTP") + ) + else: + return res.ReponseError( + status=404, + data=res.Message(message="No OTP found for this email") + ) + except: + return res.ReponseError( + status=500, + data=res.Message(message="Server Error") + ) + +async def createOTPReset(email): + try: + otp = generate_otp() + check_email_fc = sf.check_email_empty_invalid(email) + if check_email_fc is not True: + return check_email_fc + OTPRepository.addOTP(email,otp) + return res.ResponseCreateOTP( + status=200, + data = res.CheckModel(check=True), + otp = otp + ) + except: + return res.ReponseError( + status=500, + data=res.Message(message="Server Error") + ) + +async def generate_random_password(length=8): + characters = string.ascii_letters + string.digits + password = ''.join(random.choice(characters) for i in range(length)) + return password + +async def verifyOTPReset(request: req.RequestVerifyOTP): + try: + email = request.email + otp = request.otp + check_email_fc = sf.check_email_empty_invalid(email) + if check_email_fc is not True: + return check_email_fc + if otp is None: + return res.ReponseError( + status=400, + data=res.Message(message="OTP is empty") + ) + user_otp = OTPRepository.getOtpByEmail(email) + if user_otp: + otp_db = user_otp.otp + otp_created_at = user_otp.created_at + if otp == otp_db: + current_time = datetime.datetime.now() # Lấy thời gian hiện tại với múi giờ hệ thống (múi giờ +7) + otp_expiry_time = otp_created_at + timedelta(minutes=15) + new_password = generate_random_password() + if current_time <= otp_expiry_time: + OTPRepository.deleteOTP(email, otp) + user_email = auth.get_user_by_email(email) + auth.update_user( + user_email.uid, + password=new_password) + return res.ResponseVerifyOTP( + status=200, + data=res.Message(message="New Password send to Email"), + newpassword=new_password + ) + else: + return res.ReponseError( + status=400, + data=res.Message(message="OTP has expired") + ) + else: + return res.ReponseError( + status=400, + data=res.Message(message="Invalid OTP") + ) + else: + return res.ReponseError( + status=404, + data=res.Message(message="No OTP found for this email") + ) + except: + return res.ReponseError( + status=500, + data=res.Message(message="Server Error") + ) \ No newline at end of file diff --git a/service/UserService.py b/service/UserService.py new file mode 100644 index 0000000000000000000000000000000000000000..ce25f47f0eade5b117d1e4f295af971a2aa9ffad --- /dev/null +++ b/service/UserService.py @@ -0,0 +1,322 @@ +from datetime import timedelta, datetime +from request import RequestUser as req_login +from response import ResponseUser as res_login +import requests +import json, re +from auth.authentication import signJWT +from firebase_admin import credentials, auth, exceptions +import firebase_admin +from repository import UserLoginRepository, UserRepository, UserInfoRepository, OTPRepository +import service.OTPService +from function import support_function as sf +from dotenv import load_dotenv +import os +from response import ResponseUser as res +from response import ResponseDefault as res1 +load_dotenv() +CLIENT_ID_GOOGLE = os.getenv('CLIENT_ID') +API_SIGN_UP_FIREBASE_PATH = os.getenv('API_SIGN_UP_FIREBASE') +regex = r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,7}\b' + +def get_user1(email): + try: + user = auth.get_user_by_email(email) + return user + except exceptions.FirebaseError as e: + return None + +def check_email(email): + if isinstance(email, str) and re.fullmatch(regex, email): + return True + else: + return False +from pathlib import Path +try: + if not firebase_admin._apps: + json_path = Path(__file__).resolve().parent / 'app' / 'firebase_certificate.json' + cred = credentials.Certificate(str(json_path)) + fred = firebase_admin.initialize_app(cred) +except: + if not firebase_admin._apps: + cred = credentials.Certificate("firebase_certificate.json") + fred = firebase_admin.initialize_app(cred) + +def sign_up_with_email_and_password(email, password, username=None, return_secure_token=True): + try: + rest_api_url = "https://identitytoolkit.googleapis.com/v1/accounts:signUp" + payload = { + "email": email, + "password": password, + "returnSecureToken": return_secure_token + } + if username: + payload["displayName"] = username + payload = json.dumps(payload) + r = requests.post(rest_api_url, params={"key": API_SIGN_UP_FIREBASE_PATH}, data=payload) + try: + return r.json()['email'] + except Exception as e: + pass + except Exception as e: + pass + +def sign_in_with_email_and_password(email=None, password=None, return_secure_token=True): + rest_api_url = "https://identitytoolkit.googleapis.com/v1/accounts:signInWithPassword" + try: + payload = { + "returnSecureToken": return_secure_token + } + if email: + payload["email"] = email + if password: + payload["password"] = password + payload = json.dumps(payload) + r = requests.post(rest_api_url, params={"key": API_SIGN_UP_FIREBASE_PATH}, data=payload) + r.raise_for_status() + data = r.json() + if 'idToken' in data: + return data['email'] + else: + return False + except requests.exceptions.RequestException as e: + print(f"Error signing in: {e}") + return False + +def update_info_user(uid, email=None, user_name=None, photo_url=None): + user_data = {} + if email is not None: + user_data['email'] = email + if user_name is not None: + user_data['display_name'] = user_name + if photo_url is not None and photo_url != 'N/A': + user_data['photo_url'] = photo_url + if user_data: + auth.update_user(uid, **user_data) + +async def update_user_info(request: req_login.RequestUpdateUserInfo): + try: + email = request.email + user_id = request.user_id + email_check = sf.check_email_service(user_id) + if isinstance(email_check, res1.ReponseError): + return email_check + check_email_fc = sf.check_email_empty_invalid(email) + if check_email_fc is not True: + return check_email_fc + user = get_user1(email) + if user: + user_info = UserInfoRepository.getUserInfo(user_id) + if user_info: + UserInfoRepository.updateUserInfo( + request.user_id, + request.uid, + request.email, + request.display_name, + request.photo_url) + else: + UserInfoRepository.addUserInfo( + request.uid, + request.email, + request.display_name, + request.photo_url + ) + update_info_user(request.uid, + request.email, + request.display_name, + request.photo_url + ) + return res_login.ResponseUpdateUserInfo(status=200, + data = res_login.Message(message=f"User info updated successfully")) + else: + return res_login.ReponseError( + status = 404, + data = res_login.Message(message="Not found user") + ) + except: + return res_login.ReponseError( + status=500, + data=res_login.Message(message="Server Error") + ) + +async def check_info_google(request: req_login.RequestCheckInfoGoogle): + try: + user_id = request.user_id + check = UserRepository.getEmailUserByIdFix(user_id) + if check is None: + return res_login.ReponseError( + status = 404, + data = res_login.Message(message="user_id not exist") + ) + email = sf.check_email_service(str(user_id)) + if isinstance(email, res.ReponseError): + return email + user_info = UserInfoRepository.getUserInfo(user_id) + if user_info is not None: + email_check = True + else: + email_check = False + if email_check is not None: + return res_login.ResponseCheckInfoGoogle(status= 200,data = res_login.CheckModel(check=email_check)) + except: + return res_login.ReponseError( + status=500, + data=res_login.Message(message="Server Error") + ) + +async def check_info_google_email(request: req_login.RequestCheckInfoGoogleEmail): + try: + email = request.email + check_email_fc = sf.check_email_empty_invalid(email) + if check_email_fc is not True: + return check_email_fc + user_info = UserInfoRepository.getUserInfoByEmail(email) + if user_info is not None: + email_check = True + else: + email_check = False + if email_check is not None: + return res_login.ResponseCheckInfoGoogle(status= 200,data = res_login.CheckModel(check=email_check)) + except: + return res_login.ReponseError( + status=500, + data=res_login.Message(message="Server Error") + ) + +async def check_state_login(request: req_login.RequestCheckStateLogin): + try: + user_id = request.user_id + session_id_now = request.session_id_now + email = sf.check_email_service(user_id) + if isinstance(email, res1.ReponseError): + return email + elif session_id_now is None or session_id_now=="": + return res_login.ReponseError( + status= 400, + data =res_login.Message(message="session_id is empty") + ) + user = get_user1(email) + if user: + check1 = False + session_id = UserLoginRepository.getUserSessionIdByUserEmail(user_id) + print(f"session_id: {session_id}") + if session_id != session_id_now: + check1 = False + else: + check1 = True + return res_login.ResponseCheckInfoGoogle(status= 200,data = res_login.CheckModel(check = check1)) + else: + return res_login.ReponseError( + status=404, + data =res_login.Message(message="Not found user") + ) + except: + return res_login.ReponseError( + status=500, + data=res_login.Message(message="Server Error") + ) + +import string, random +def generate_otp(length=6): + characters = string.ascii_uppercase + string.digits + otp = ''.join(random.choice(characters) for _ in range(length)) + return otp + +def createOTPReset(email): + otp = generate_otp() + check_email_fc = sf.check_email_empty_invalid(email) + if check_email_fc is not True: + return check_email_fc + OTPRepository.addOTP(email,otp) + return otp + +async def reset_password(request: req_login.RequestResetPassword): + try: + email = request.email + check_email_fc = sf.check_email_empty_invalid(email) + if check_email_fc is not True: + return check_email_fc + try: + user = get_user1(email) + if user is not None: + otp = createOTPReset(email) + return res_login.ResponseCreateOTP( + status= 200, + data= res_login.CheckModel(check = True), + otp = otp + ) + else: + return res_login.ReponseError( + status= 404, + data =res_login.Message(message="Email not exist") + ) + except auth.UserNotFoundError as e: + return res_login.ReponseError( + status=500, + data =res_login.Message(message=str(e)) + ) + except: + return res_login.ReponseError( + status=500, + data=res_login.Message(message="Server Error") + ) + +async def change_password(request: req_login.RequestChangePassword): + try: + user_id = request.user_id + email = sf.check_email_service(user_id) + new_password = request.new_password + current_password= request.current_password + confirm_new_password = request.confirm_new_password + if isinstance(email, res1.ReponseError): + return email + if new_password is None: + return res_login.ReponseError( + status=400, + data =res_login.Message(message="new_password is empty") + ) + if current_password is None or confirm_new_password == "": + return res_login.ReponseError( + status=400, + data =res_login.Message(message="current_password is empty") + ) + if confirm_new_password is None or confirm_new_password == "": + return res_login.ReponseError( + status=400, + data =res_login.Message(message="confirm_new_password is empty") + ) + if current_password == new_password: + return res_login.ReponseError( + status=400, + data=res_login.Message(message="The new_password and the current_password must be different") + ) + if confirm_new_password != new_password: + return res_login.ReponseError( + status=400, + data=res_login.Message(message="The new_password and the confirm_new_password must be similar") + ) + user = sign_in_with_email_and_password(email, current_password) + try: + if user: + user_email = auth.get_user_by_email(email) + auth.update_user( + user_email.uid, + password=new_password + ) + return res_login.ResponseChangePassword( + status= 200, + data = res_login.Message(message=f"Update password success")) + else: + return res_login.ReponseError( + status=400, + data =res_login.Message(message="Current password not valid") + ) + except : + return res_login.ReponseError( + status=500, + data =res_login.Message(message="Server Error") + ) + except: + return res_login.ReponseError( + status=500, + data=res_login.Message(message="Server Error!!") + ) \ No newline at end of file diff --git a/service/__pycache__/AuthService.cpython-310.pyc b/service/__pycache__/AuthService.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2c395a262503e4e21e04bc42492d5d999307f907 Binary files /dev/null and b/service/__pycache__/AuthService.cpython-310.pyc differ diff --git a/service/__pycache__/ChatService.cpython-310.pyc b/service/__pycache__/ChatService.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..95e180475d77257863f0b9296a2a076ee83c2e7f Binary files /dev/null and b/service/__pycache__/ChatService.cpython-310.pyc differ diff --git a/service/__pycache__/ChatService.cpython-311.pyc b/service/__pycache__/ChatService.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3ac3d8c3860d41e1d3573e65922a14bff89b4752 Binary files /dev/null and b/service/__pycache__/ChatService.cpython-311.pyc differ diff --git a/service/__pycache__/DefaultService.cpython-310.pyc b/service/__pycache__/DefaultService.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..749f9993cba86f8ea0039f404a6f03e2b8f6c05e Binary files /dev/null and b/service/__pycache__/DefaultService.cpython-310.pyc differ diff --git a/service/__pycache__/DefaultService.cpython-311.pyc b/service/__pycache__/DefaultService.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..61554439dc3649a7ac4447b56d913ed54ca3bad7 Binary files /dev/null and b/service/__pycache__/DefaultService.cpython-311.pyc differ diff --git a/service/__pycache__/FileService.cpython-310.pyc b/service/__pycache__/FileService.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..bc89fc7eefecaea692ab011b6e7a0b3f5f521dd7 Binary files /dev/null and b/service/__pycache__/FileService.cpython-310.pyc differ diff --git a/service/__pycache__/FileService.cpython-311.pyc b/service/__pycache__/FileService.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4b58afff7665c425d88f73edee79d981630ac50a Binary files /dev/null and b/service/__pycache__/FileService.cpython-311.pyc differ diff --git a/service/__pycache__/MySQLService.cpython-310.pyc b/service/__pycache__/MySQLService.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b2f30b866ddc3653f0e936bf8fbe5dcd660f8eff Binary files /dev/null and b/service/__pycache__/MySQLService.cpython-310.pyc differ diff --git a/service/__pycache__/MySQLService.cpython-311.pyc b/service/__pycache__/MySQLService.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..cafb061255eff9a34850d8e128b45b1bb43319d1 Binary files /dev/null and b/service/__pycache__/MySQLService.cpython-311.pyc differ diff --git a/service/__pycache__/OTPService.cpython-310.pyc b/service/__pycache__/OTPService.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..43ad900a2c36adfbf678d25ececd6dc7603d9280 Binary files /dev/null and b/service/__pycache__/OTPService.cpython-310.pyc differ diff --git a/service/__pycache__/OTPService.cpython-311.pyc b/service/__pycache__/OTPService.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..eb8791e7164320f1358b235a848e55a5f875e371 Binary files /dev/null and b/service/__pycache__/OTPService.cpython-311.pyc differ diff --git a/service/__pycache__/UserService.cpython-310.pyc b/service/__pycache__/UserService.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..528fa2b9869a5e4a0f755d546a95bacf1747c9ba Binary files /dev/null and b/service/__pycache__/UserService.cpython-310.pyc differ diff --git a/service/app/firebase_certificate.json b/service/app/firebase_certificate.json new file mode 100644 index 0000000000000000000000000000000000000000..98b77ef706ec8c88babbdeb945950f0993cdeb0a --- /dev/null +++ b/service/app/firebase_certificate.json @@ -0,0 +1,13 @@ +{ + "type": "service_account", + "project_id": "cogent-octane-384105", + "private_key_id": "94d2eb71fcc53c8504e822a2367157b49b65b16d", + "private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC+awYE99nwJwid\neFuujKYL1cxdknb5lze6ON2wwn6F/lZCjf0wyYTyYAzk2yVDy8p+xy+jsbT22iaX\n8K6fwCqMVUMby9e813cQuS7ycF7WSS1Fw9JwljktnMLplJZuTv3zmlolNiePz/rS\nPcPaSvjQWO4s/G1A8knbY2gXaY4e7ie37GGKDOsgfEF8sQJ2TRll79qzoAWqIz1I\np87s+vR+Z3nPlVqiCM7cYP9ddvFEQxF381STDIExQzKSYbQyUsnU1lOZ7zWKb4F+\nHGjLzYBhf6CzU+l3M/kiaTJck+T7H/tSWo+bzFYFRpeh6Q7/UBwbBYN+7VOXTJ1Q\nEBQdwolBAgMBAAECggEAGG8v+405GG751Qhvw1XlrMPHkK5NuWNlJu6gdqEj49p/\ng9TSi43LEzWuEePpGT+vrABapZ0VGqQNqxZFt4F3iZXF9xgmMTj43LAr97eMWTT/\nVozKlotAVRELleDs7hoRePlH3gSKo71Ncz2ybHLjELaIrER2rzcoBmXwIn5MsBJ+\nDOqdZAo3UadvzcRpTUY6ju1Kd8w72FYgW/3RfK6eikZEw8sX8vKQ7QEH8bKeZVt7\nWOrkBK2kHEyR8dTga2igQRI7Cezqv48yiYjYbi+D/DBocjpHtJnPLbgOOWyjbmDU\n5fB+bxf+7qXZn/AIp96Iq1s2ZHxldlKk38yne40N7QKBgQDf/+A2lQswySNdLR1+\nNJME3OGgBG9Jq0mnBoe9rWOBBBAQNYv4uZO4MVvmLwzIN1y32MV6zkbnD9fMWKIf\nciIzje8xip/9ei6weB5n0Yp13f9JxBW0r1HaUVk7jpHyH7rk3GvNcebZNKM+yndh\n1rdyE1V6xGNqAXzX9vP4t6IiYwKBgQDZnwEwggMToQrl1jsxz7VlujPNSUhOgwGL\nj0nHCbUf2/jZ1hyMRU659RWmWGA70rsALwQ4IQoM5UHZkKc12MjswmXllrkk1Jmu\nc04OE5SWde7SWAzSj5oqCIoQt0B/3r7cRjgr0TK3SwxxIUOcazyFzvLrxJxsGFHc\nOfE3jP5lCwKBgCf0kl/qEgbvudki9QHQCvFxHOXYJKm1XfvnFEtnJDqdKOhbRM5m\n+8x9MXFLrzH/fhBlIESZitgoYUvX+4M0bplXlfT2Tzd9ldpwcqv+Gn6PzLuxuFV0\neFtC63HOKoZP1pyAHNKWoKDZ3MyUfNr829gDTtoJMdp0zXoQWNBioQ8VAoGBAKvd\n5aSXqTJhZyfpL0rBjbNPgQXJsG9BC4Faopus0PzeTwRLErS9L9Ww924uMaJNZR5a\nA20IutVAYecfVM8z7Er/pFXT2Vh7Bvw9WBHJ6PmDHh/FJitM+iXkJJXbA/d4xSdV\n1ZrVVsZnYOYfrTPlhSDwNe15k0fTVSMmJ5kFowvNAoGAc101K46kuKl+K/V6gdnW\nN2reMwlJf4Wgaz7yX0Gkha95dNGmy1ZC+NdD3qlSbOv353OITzNCBo7pSAAphQr2\noVkpyToTQOcSBjjAzTkXHabn3N1Rmj1P7GPwz5WyDPjp4t+GmT8Se3aJ1gtCnKeb\noxwTPi7EHyoIiYnEXYRuzSw=\n-----END PRIVATE KEY-----\n", + "client_email": "firebase-adminsdk-z0bu3@cogent-octane-384105.iam.gserviceaccount.com", + "client_id": "105944722897200826755", + "auth_uri": "https://accounts.google.com/o/oauth2/auth", + "token_uri": "https://oauth2.googleapis.com/token", + "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", + "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/firebase-adminsdk-z0bu3%40cogent-octane-384105.iam.gserviceaccount.com", + "universe_domain": "googleapis.com" + } diff --git a/tests/.pytest_cache/.gitignore b/tests/.pytest_cache/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..08a7f458f1f002823bc794c47ca1996a57e72c86 --- /dev/null +++ b/tests/.pytest_cache/.gitignore @@ -0,0 +1,2 @@ +# Created by pytest automatically. +* diff --git a/tests/.pytest_cache/CACHEDIR.TAG b/tests/.pytest_cache/CACHEDIR.TAG new file mode 100644 index 0000000000000000000000000000000000000000..fce15ad7eaa74e5682b644c84efb75334c112f95 --- /dev/null +++ b/tests/.pytest_cache/CACHEDIR.TAG @@ -0,0 +1,4 @@ +Signature: 8a477f597d28d172789f06886806bc55 +# This file is a cache directory tag created by pytest. +# For information about cache directory tags, see: +# https://bford.info/cachedir/spec.html diff --git a/tests/.pytest_cache/README.md b/tests/.pytest_cache/README.md new file mode 100644 index 0000000000000000000000000000000000000000..c7526af2448672de4537dfed042ed74daadb17bf --- /dev/null +++ b/tests/.pytest_cache/README.md @@ -0,0 +1,8 @@ +# pytest cache directory # + +This directory contains data from the pytest's cache plugin, +which provides the `--lf` and `--ff` options, as well as the `cache` fixture. + +**Do not** commit this to version control. + +See [the docs](https://docs.pytest.org/en/stable/how-to/cache.html) for more information. diff --git a/tests/.pytest_cache/v/cache/lastfailed b/tests/.pytest_cache/v/cache/lastfailed new file mode 100644 index 0000000000000000000000000000000000000000..830021eb81c56e684e20663354af5336a7dc6369 --- /dev/null +++ b/tests/.pytest_cache/v/cache/lastfailed @@ -0,0 +1,98 @@ +{ + "test_service/test_MySQLService.py::TestLoadChatHistory::test_load_chat_history_user_id_str": true, + "test_controller/test_ChatController.py::test_extract_file_user_id_required": true, + "test_controller/test_ChatController.py::test_generate_question_user_id_required": true, + "test_controller/test_DefaultController.py::test_info_user_user_id_required": true, + "test_controller/test_DefaultController.py::test_upload_image_user_id_required": true, + "test_controller/test_MySQLController.py::test_render_chat_empty": true, + "test_controller/test_MySQLController.py::test_load_chat_history_empty": true, + "test_controller/test_MySQLController.py::test_load_chat_history_empty1": true, + "test_controller/test_MySQLController.py::test_render_chat_user_id_required": true, + "test_controller/test_MySQLController.py::test_load_chat_history_chat_id_is_required": true, + "test_controller/test_MySQLController.py::test_load_chat_history_user_id_is_required": true, + "test_controller/test_LoginController.py::test_login_success": true, + "test_controller/test_LoginController.py::test_login_email_empty": true, + "test_controller/test_LoginController.py::test_login_email_invalid": true, + "test_controller/test_LoginController.py::test_login_password_empty": true, + "test_controller/test_LoginController.py::test_login_email_not_exist": true, + "test_controller/test_LoginController.py::test_login_email_password_error": true, + "test_controller/test_LoginController.py::test_login_invalid_authorization_code": true, + "test_controller/test_LoginController.py::test_login_google_success": true, + "test_controller/test_LoginController.py::test_login_google_email_empty": true, + "test_controller/test_LoginController.py::test_login_google_email_invalid": true, + "test_controller/test_LoginController.py::test_sign_up_success": true, + "test_controller/test_LoginController.py::test_sign_up_email_is_empty": true, + "test_controller/test_LoginController.py::test_sign_up_email_invadlid": true, + "test_controller/test_LoginController.py::test_sign_up_password_empty": true, + "test_controller/test_LoginController.py::test_sign_up_email_exist": true, + "test_controller/test_LoginController.py::test_sign_up_error": true, + "test_controller/test_LoginController.py::test_change_password_current_password_not_valid": true, + "test_controller/test_LoginController.py::test_refresh_token_success": true, + "test_controller/test_LoginController.py::test_refresh_token_user_id_not_exist": true, + "test_controller/test_LoginController.py::test_refresh_token_email_empty": true, + "test_controller/test_LoginController.py::test_refresh_token_email_invalid": true, + "test_controller/test_LoginController.py::test_refresh_token_token_empty": true, + "test_controller/test_LoginController.py::test_refresh_token_token_errror": true, + "test_controller/test_LoginController.py::test_login_email_required": true, + "test_controller/test_LoginController.py::test_login_email_required_str": true, + "test_controller/test_LoginController.py::test_login_password_required": true, + "test_controller/test_LoginController.py::test_login_email_can_not_empty": true, + "test_controller/test_LoginController.py::test_login_google_email_required": true, + "test_controller/test_LoginController.py::test_login_google_token_google_required": true, + "test_controller/test_LoginController.py::test_login_google_email_required_str_1": true, + "test_controller/test_LoginController.py::test_login_google_email_token_required_str": true, + "test_controller/test_LoginController.py::test_login_google_email_can_not_empty": true, + "test_controller/test_LoginController.py::test_signup_email_is_required": true, + "test_controller/test_LoginController.py::test_signup_email_must_str": true, + "test_controller/test_LoginController.py::test_signup_password_required": true, + "test_controller/test_LoginController.py::test_refresh_token_user_id_required": true, + "test_controller/test_LoginController.py::test_refresh_token_user_id_integer": true, + "test_controller/test_LoginController.py::test_refresh_token_user_id_integer_greater_than_0": true, + "test_controller/test_LoginController.py::test_refresh_token_token_must_be_str": true, + "test_controller/test_LoginController.py::test_refresh_token_token_is_required": true, + "test_controller/test_LoginController.py::test_signup_confirm_password_required": true, + "test_controller/test_DefaultController.py::test_create_firebase_user_success": true, + "test_controller/test_DefaultController.py::test_create_firebase_user_error": true, + "test_service/test_LoginService.py::TestLoginFunction::test_login_email_empty": true, + "test_service/test_LoginService.py::TestLoginFunction::test_login_email_invalid": true, + "test_service/test_LoginService.py::TestLoginFunction::test_login_email_not_exists": true, + "test_service/test_LoginService.py::TestLoginFunction::test_login_email_or_password_error": true, + "test_service/test_LoginService.py::TestLoginFunction::test_login_invalid_authorization_code": true, + "test_service/test_LoginService.py::TestLoginFunction::test_login_password_empty": true, + "test_service/test_LoginService.py::TestLoginFunction::test_login_server_error": true, + "test_service/test_LoginService.py::TestLoginFunction::test_login_success": true, + "test_service/test_LoginService.py::TestLoginGoogle::test_login_email_invalid": true, + "test_service/test_LoginService.py::TestLoginGoogle::test_login_google_email_empty": true, + "test_service/test_LoginService.py::TestLoginGoogle::test_login_google_email_not_exists": true, + "test_service/test_LoginService.py::TestLoginGoogle::test_login_google_server_error": true, + "test_service/test_LoginService.py::TestLoginGoogle::test_login_google_success": true, + "test_service/test_LoginService.py::TestCheckStateLogin::test_check_state_login_id_not_exits": true, + "test_service/test_LoginService.py::TestSignUpFunction::test_sign_up_confirm_password_do_not_match_password": true, + "test_service/test_LoginService.py::TestSignUpFunction::test_sign_up_confirm_password_empty": true, + "test_service/test_LoginService.py::TestSignUpFunction::test_sign_up_email_exist": true, + "test_service/test_LoginService.py::TestSignUpFunction::test_sign_up_email_invalid": true, + "test_service/test_LoginService.py::TestSignUpFunction::test_sign_up_email_is_empty": true, + "test_service/test_LoginService.py::TestSignUpFunction::test_sign_up_error": true, + "test_service/test_LoginService.py::TestSignUpFunction::test_sign_up_password_empty": true, + "test_service/test_LoginService.py::TestSignUpFunction::test_sign_up_server_error": true, + "test_service/test_LoginService.py::TestSignUpFunction::test_sign_up_success": true, + "test_service/test_LoginService.py::TestRefreshToken::test_refresh_token_email_empty": true, + "test_service/test_LoginService.py::TestRefreshToken::test_refresh_token_email_invalid": true, + "test_service/test_LoginService.py::TestRefreshToken::test_refresh_token_refresh_token_error": true, + "test_service/test_LoginService.py::TestRefreshToken::test_refresh_token_server_error": true, + "test_service/test_LoginService.py::TestRefreshToken::test_refresh_token_success": true, + "test_service/test_LoginService.py::TestRefreshToken::test_refresh_token_token_empty": true, + "test_service/test_LoginService.py::TestRefreshToken::test_refresh_token_user_id_not_exist": true, + "test_controller/test_LoginController.py::test_update_user_info_success": true, + "test_controller/test_LoginController.py::test_update_user_info_id_not_exist": true, + "test_controller/test_LoginController.py::test_update_user_info_email_empty": true, + "test_controller/test_LoginController.py::test_update_user_info_email_invalid": true, + "test_controller/test_LoginController.py::test_update_user_info_email_or_password_error": true, + "test_controller/test_LoginController.py::test_update_user_info_user_id_required": true, + "test_controller/test_LoginController.py::test_update_user_info_user_id_integer_required": true, + "test_controller/test_LoginController.py::test_update_user_info_user_id_greater_than_0": true, + "test_controller/test_LoginController.py::test_update_user_info_uid_field_required": true, + "test_controller/test_LoginController.py::test_update_user_info_email_field_required": true, + "test_controller/test_LoginController.py::test_update_user_info_dis_play_name_field_required": true, + "test_controller/test_LoginController.py::test_update_user_info_photo_url_field_required": true +} \ No newline at end of file diff --git a/tests/.pytest_cache/v/cache/nodeids b/tests/.pytest_cache/v/cache/nodeids new file mode 100644 index 0000000000000000000000000000000000000000..5352d04b1ca43abad6aa01cd460e34df15760ba4 --- /dev/null +++ b/tests/.pytest_cache/v/cache/nodeids @@ -0,0 +1,505 @@ +[ + "test_controller/test_ChatController.py::test_extract_file_email_empty", + "test_controller/test_ChatController.py::test_extract_file_email_in_valid", + "test_controller/test_ChatController.py::test_extract_file_id_not_exist", + "test_controller/test_ChatController.py::test_extract_file_no_data", + "test_controller/test_ChatController.py::test_extract_file_success", + "test_controller/test_ChatController.py::test_extract_file_user_id_greater_0", + "test_controller/test_ChatController.py::test_extract_file_user_id_interger", + "test_controller/test_ChatController.py::test_extract_file_user_id_required", + "test_controller/test_ChatController.py::test_generate_question_email_empty", + "test_controller/test_ChatController.py::test_generate_question_email_in_valid", + "test_controller/test_ChatController.py::test_generate_question_id_not_exist", + "test_controller/test_ChatController.py::test_generate_question_no_data", + "test_controller/test_ChatController.py::test_generate_question_success", + "test_controller/test_ChatController.py::test_generate_question_user_id_greater_0", + "test_controller/test_ChatController.py::test_generate_question_user_id_interger", + "test_controller/test_ChatController.py::test_generate_question_user_id_required", + "test_controller/test_ChatController.py::test_query2_upgrade_old_chat_history_empty", + "test_controller/test_ChatController.py::test_query2_upgrade_old_email_empty", + "test_controller/test_ChatController.py::test_query2_upgrade_old_email_in_valid", + "test_controller/test_ChatController.py::test_query2_upgrade_old_id_not_exist", + "test_controller/test_ChatController.py::test_query2_upgrade_old_no_answer", + "test_controller/test_ChatController.py::test_query2_upgrade_old_question_empty", + "test_controller/test_ChatController.py::test_query2_upgrade_old_success", + "test_controller/test_ChatController.py::test_query_chatbot_user_id_greater_0", + "test_controller/test_ChatController.py::test_query_chatbot_user_id_interger", + "test_controller/test_ChatController.py::test_query_chatbot_user_id_required", + "test_controller/test_DefaultController.py::test_create_firebase_server_error", + "test_controller/test_DefaultController.py::test_create_firebase_user_error", + "test_controller/test_DefaultController.py::test_create_firebase_user_google_email_must_be_string", + "test_controller/test_DefaultController.py::test_create_firebase_user_google_is_None", + "test_controller/test_DefaultController.py::test_create_firebase_user_google_token_is_required", + "test_controller/test_DefaultController.py::test_create_firebase_user_google_token_must_be_str", + "test_controller/test_DefaultController.py::test_create_firebase_user_google_token_must_be_str_1", + "test_controller/test_DefaultController.py::test_create_firebase_user_null_email", + "test_controller/test_DefaultController.py::test_create_firebase_user_success", + "test_controller/test_DefaultController.py::test_id_not_exist", + "test_controller/test_DefaultController.py::test_info_success", + "test_controller/test_DefaultController.py::test_info_user_email_empty", + "test_controller/test_DefaultController.py::test_info_user_email_invalid", + "test_controller/test_DefaultController.py::test_info_user_user_id_must_be_string", + "test_controller/test_DefaultController.py::test_info_user_user_id_required", + "test_controller/test_DefaultController.py::test_info_user_user_not_found", + "test_controller/test_DefaultController.py::test_invalid_email", + "test_controller/test_DefaultController.py::test_is_me_invalid_token", + "test_controller/test_DefaultController.py::test_is_me_none_token", + "test_controller/test_DefaultController.py::test_is_me_server_error", + "test_controller/test_DefaultController.py::test_is_me_success", + "test_controller/test_DefaultController.py::test_is_me_token_is_required", + "test_controller/test_DefaultController.py::test_is_me_token_must_be_string", + "test_controller/test_DefaultController.py::test_upload_image_email_empty", + "test_controller/test_DefaultController.py::test_upload_image_email_invalid", + "test_controller/test_DefaultController.py::test_upload_image_id_not_exist", + "test_controller/test_DefaultController.py::test_upload_image_server_err", + "test_controller/test_DefaultController.py::test_upload_image_success", + "test_controller/test_DefaultController.py::test_upload_image_user_id_greater_than_0", + "test_controller/test_DefaultController.py::test_upload_image_user_id_integer", + "test_controller/test_DefaultController.py::test_upload_image_user_id_required", + "test_controller/test_DefaultController.py::test_user_info_server_error", + "test_controller/test_FileController.py::test_delete__all_file_user_id_required", + "test_controller/test_FileController.py::test_delete_all_file_email_empty", + "test_controller/test_FileController.py::test_delete_all_file_email_invalid", + "test_controller/test_FileController.py::test_delete_all_file_success", + "test_controller/test_FileController.py::test_delete_all_file_user_id_is_greater_0", + "test_controller/test_FileController.py::test_delete_all_file_user_id_is_integer", + "test_controller/test_FileController.py::test_delete_file_email_empty", + "test_controller/test_FileController.py::test_delete_file_email_invalid", + "test_controller/test_FileController.py::test_delete_file_id_not_exist", + "test_controller/test_FileController.py::test_delete_file_namefile_empty", + "test_controller/test_FileController.py::test_delete_file_success", + "test_controller/test_FileController.py::test_delete_one_file_name_file_required", + "test_controller/test_FileController.py::test_delete_one_file_user_id_is_greater_0", + "test_controller/test_FileController.py::test_delete_one_file_user_id_is_integer", + "test_controller/test_FileController.py::test_delete_one_file_user_id_required", + "test_controller/test_FileController.py::test_download_file_email_empty", + "test_controller/test_FileController.py::test_download_file_email_invalid", + "test_controller/test_FileController.py::test_download_file_id_not_exist", + "test_controller/test_FileController.py::test_download_file_name_file_empty", + "test_controller/test_FileController.py::test_download_file_success", + "test_controller/test_FileController.py::test_download_file_user_id_required", + "test_controller/test_FileController.py::test_download_files_user_id_is_greater_0", + "test_controller/test_FileController.py::test_download_files_user_id_is_integer", + "test_controller/test_FileController.py::test_download_folder_email_empty", + "test_controller/test_FileController.py::test_download_folder_email_invalid", + "test_controller/test_FileController.py::test_download_folder_id_not_exist", + "test_controller/test_FileController.py::test_download_folder_success", + "test_controller/test_FileController.py::test_download_folder_user_id_is_greater_0", + "test_controller/test_FileController.py::test_download_folder_user_id_is_integer", + "test_controller/test_FileController.py::test_download_folder_user_id_required", + "test_controller/test_FileController.py::test_list_name_file_email_empty", + "test_controller/test_FileController.py::test_list_name_file_email_invalid", + "test_controller/test_FileController.py::test_list_name_file_id_not_exist", + "test_controller/test_FileController.py::test_list_name_file_success", + "test_controller/test_FileController.py::test_list_name_files_user_id_is_greater_0", + "test_controller/test_FileController.py::test_list_name_files_user_id_is_integer", + "test_controller/test_FileController.py::test_list_name_files_user_id_required", + "test_controller/test_FileController.py::test_upload_file_user_id_required", + "test_controller/test_FileController.py::test_upload_files_empty_email", + "test_controller/test_FileController.py::test_upload_files_id_not_exist", + "test_controller/test_FileController.py::test_upload_files_invalid_email", + "test_controller/test_FileController.py::test_upload_files_invalid_file_type", + "test_controller/test_FileController.py::test_upload_files_success", + "test_controller/test_FileController.py::test_upload_files_user_id_is_greater_0", + "test_controller/test_FileController.py::test_upload_files_user_id_is_integer", + "test_controller/test_LoginController.py::test_change_pass_confirm_required", + "test_controller/test_LoginController.py::test_change_password_current_password_empty", + "test_controller/test_LoginController.py::test_change_password_current_password_not_valid", + "test_controller/test_LoginController.py::test_change_password_current_password_required", + "test_controller/test_LoginController.py::test_change_password_email_invalid", + "test_controller/test_LoginController.py::test_change_password_email_is_empty", + "test_controller/test_LoginController.py::test_change_password_id_not_exist", + "test_controller/test_LoginController.py::test_change_password_new_password_empty", + "test_controller/test_LoginController.py::test_change_password_new_password_required", + "test_controller/test_LoginController.py::test_change_password_success", + "test_controller/test_LoginController.py::test_change_password_user_id_integer", + "test_controller/test_LoginController.py::test_change_password_user_id_integer_greater_than_0", + "test_controller/test_LoginController.py::test_change_password_user_id_required", + "test_controller/test_LoginController.py::test_check_info_google_by_email_success", + "test_controller/test_LoginController.py::test_check_info_google_email_empty", + "test_controller/test_LoginController.py::test_check_info_google_email_invalid", + "test_controller/test_LoginController.py::test_check_info_google_id_not_exist", + "test_controller/test_LoginController.py::test_check_info_google_sign_up_email_is_required", + "test_controller/test_LoginController.py::test_check_info_google_sign_up_email_must_str", + "test_controller/test_LoginController.py::test_check_info_google_signup_email_empty", + "test_controller/test_LoginController.py::test_check_info_google_signup_email_invalid", + "test_controller/test_LoginController.py::test_check_info_google_success", + "test_controller/test_LoginController.py::test_check_info_google_user_id_must_integer", + "test_controller/test_LoginController.py::test_check_info_google_user_id_must_integer_greater_than_0", + "test_controller/test_LoginController.py::test_check_info_google_user_id_required", + "test_controller/test_LoginController.py::test_check_state_login_email_empty", + "test_controller/test_LoginController.py::test_check_state_login_email_invalid", + "test_controller/test_LoginController.py::test_check_state_login_id_not_exits", + "test_controller/test_LoginController.py::test_check_state_login_not_found", + "test_controller/test_LoginController.py::test_check_state_login_session_id_must_str", + "test_controller/test_LoginController.py::test_check_state_login_session_id_required", + "test_controller/test_LoginController.py::test_check_state_login_success", + "test_controller/test_LoginController.py::test_check_state_login_user_id_must_integer", + "test_controller/test_LoginController.py::test_check_state_login_user_id_must_integer_greater_than_0", + "test_controller/test_LoginController.py::test_check_state_login_user_id_required", + "test_controller/test_LoginController.py::test_check_state_session_empty", + "test_controller/test_LoginController.py::test_login_email_can_not_empty", + "test_controller/test_LoginController.py::test_login_email_empty", + "test_controller/test_LoginController.py::test_login_email_invalid", + "test_controller/test_LoginController.py::test_login_email_not_exist", + "test_controller/test_LoginController.py::test_login_email_password_error", + "test_controller/test_LoginController.py::test_login_email_required", + "test_controller/test_LoginController.py::test_login_email_required_str", + "test_controller/test_LoginController.py::test_login_google_email_can_not_empty", + "test_controller/test_LoginController.py::test_login_google_email_empty", + "test_controller/test_LoginController.py::test_login_google_email_invalid", + "test_controller/test_LoginController.py::test_login_google_email_required", + "test_controller/test_LoginController.py::test_login_google_email_required_str_1", + "test_controller/test_LoginController.py::test_login_google_email_token_required_str", + "test_controller/test_LoginController.py::test_login_google_success", + "test_controller/test_LoginController.py::test_login_google_token_google_required", + "test_controller/test_LoginController.py::test_login_invalid_authorization_code", + "test_controller/test_LoginController.py::test_login_password_empty", + "test_controller/test_LoginController.py::test_login_password_required", + "test_controller/test_LoginController.py::test_login_success", + "test_controller/test_LoginController.py::test_refresh_token_email_empty", + "test_controller/test_LoginController.py::test_refresh_token_email_invalid", + "test_controller/test_LoginController.py::test_refresh_token_success", + "test_controller/test_LoginController.py::test_refresh_token_token_empty", + "test_controller/test_LoginController.py::test_refresh_token_token_errror", + "test_controller/test_LoginController.py::test_refresh_token_token_is_required", + "test_controller/test_LoginController.py::test_refresh_token_token_must_be_str", + "test_controller/test_LoginController.py::test_refresh_token_user_id_integer", + "test_controller/test_LoginController.py::test_refresh_token_user_id_integer_greater_than_0", + "test_controller/test_LoginController.py::test_refresh_token_user_id_not_exist", + "test_controller/test_LoginController.py::test_refresh_token_user_id_required", + "test_controller/test_LoginController.py::test_reset_email_must_str", + "test_controller/test_LoginController.py::test_reset_email_required", + "test_controller/test_LoginController.py::test_reset_password_email_is_None", + "test_controller/test_LoginController.py::test_reset_password_invalid_email", + "test_controller/test_LoginController.py::test_reset_password_success", + "test_controller/test_LoginController.py::test_reset_password_user_not_found", + "test_controller/test_LoginController.py::test_sign_up_email_exist", + "test_controller/test_LoginController.py::test_sign_up_email_invadlid", + "test_controller/test_LoginController.py::test_sign_up_email_is_empty", + "test_controller/test_LoginController.py::test_sign_up_error", + "test_controller/test_LoginController.py::test_sign_up_password_empty", + "test_controller/test_LoginController.py::test_sign_up_success", + "test_controller/test_LoginController.py::test_signup_confirm_password_required", + "test_controller/test_LoginController.py::test_signup_email_is_required", + "test_controller/test_LoginController.py::test_signup_email_must_str", + "test_controller/test_LoginController.py::test_signup_password_required", + "test_controller/test_LoginController.py::test_update_user_info_dis_play_name_field_required", + "test_controller/test_LoginController.py::test_update_user_info_email_empty", + "test_controller/test_LoginController.py::test_update_user_info_email_field_required", + "test_controller/test_LoginController.py::test_update_user_info_email_invalid", + "test_controller/test_LoginController.py::test_update_user_info_email_or_password_error", + "test_controller/test_LoginController.py::test_update_user_info_id_not_exist", + "test_controller/test_LoginController.py::test_update_user_info_photo_url_field_required", + "test_controller/test_LoginController.py::test_update_user_info_success", + "test_controller/test_LoginController.py::test_update_user_info_uid_field_required", + "test_controller/test_LoginController.py::test_update_user_info_user_id_greater_than_0", + "test_controller/test_LoginController.py::test_update_user_info_user_id_integer_required", + "test_controller/test_LoginController.py::test_update_user_info_user_id_required", + "test_controller/test_MySQLController.py::test_delete_chat_email_empty", + "test_controller/test_MySQLController.py::test_delete_chat_email_invalid", + "test_controller/test_MySQLController.py::test_delete_chat_id_not_exits", + "test_controller/test_MySQLController.py::test_delete_chat_name_empty", + "test_controller/test_MySQLController.py::test_delete_chat_name_error_500", + "test_controller/test_MySQLController.py::test_delete_chat_success", + "test_controller/test_MySQLController.py::test_edit_chat1_error", + "test_controller/test_MySQLController.py::test_edit_chat_email_empty", + "test_controller/test_MySQLController.py::test_edit_chat_email_invalid", + "test_controller/test_MySQLController.py::test_edit_chat_invalid_id", + "test_controller/test_MySQLController.py::test_edit_chat_name_new", + "test_controller/test_MySQLController.py::test_edit_chat_name_old", + "test_controller/test_MySQLController.py::test_edit_chat_success", + "test_controller/test_MySQLController.py::test_load_chat_history", + "test_controller/test_MySQLController.py::test_load_chat_history_chat_id_greater_than_inter", + "test_controller/test_MySQLController.py::test_load_chat_history_chat_id_is_required", + "test_controller/test_MySQLController.py::test_load_chat_history_empty", + "test_controller/test_MySQLController.py::test_load_chat_history_empty1", + "test_controller/test_MySQLController.py::test_load_chat_history_user_id_greater_than0", + "test_controller/test_MySQLController.py::test_load_chat_history_user_id_greater_than_inter", + "test_controller/test_MySQLController.py::test_load_chat_history_user_id_is_required", + "test_controller/test_MySQLController.py::test_load_chat_history_user_id_must_be_integer", + "test_controller/test_MySQLController.py::test_load_chat_history_user_id_mustbe_inter", + "test_controller/test_MySQLController.py::test_load_chat_history_value_mustbe_inter", + "test_controller/test_MySQLController.py::test_render_chat_empty", + "test_controller/test_MySQLController.py::test_render_chat_history", + "test_controller/test_MySQLController.py::test_render_chat_user_id_greater_than_inter", + "test_controller/test_MySQLController.py::test_render_chat_user_id_required", + "test_controller/test_MySQLController.py::test_render_chat_value_mustbe_interger", + "test_controller/test_OTPController.py::test_createOTPReset_email_empty", + "test_controller/test_OTPController.py::test_createOTPReset_email_invalid", + "test_controller/test_OTPController.py::test_createOTPReset_success", + "test_controller/test_OTPController.py::test_createOTP_email_must_be_string", + "test_controller/test_OTPController.py::test_createOTP_email_required", + "test_controller/test_OTPController.py::test_createOTP_failed_empty_email", + "test_controller/test_OTPController.py::test_createOTP_failed_empty_invalid", + "test_controller/test_OTPController.py::test_createOTP_success", + "test_controller/test_OTPController.py::test_verifyOTPReset1_success", + "test_controller/test_OTPController.py::test_verifyOTPReset_email_is_required", + "test_controller/test_OTPController.py::test_verifyOTPReset_failed_empty_email", + "test_controller/test_OTPController.py::test_verifyOTPReset_failed_empty_otp", + "test_controller/test_OTPController.py::test_verifyOTPReset_failed_invalid_email", + "test_controller/test_OTPController.py::test_verifyOTPReset_failed_invalid_otp", + "test_controller/test_OTPController.py::test_verifyOTPReset_failed_no_otp_found", + "test_controller/test_OTPController.py::test_verifyOTPReset_has_expired", + "test_controller/test_OTPController.py::test_verifyOTPReset_otp_email_must_be_string", + "test_controller/test_OTPController.py::test_verifyOTPReset_otp_is_required", + "test_controller/test_OTPController.py::test_verifyOTPReset_otp_max_length", + "test_controller/test_OTPController.py::test_verifyOTPReset_otp_must_be_string", + "test_controller/test_OTPController.py::test_verifyOTP_email_is_required", + "test_controller/test_OTPController.py::test_verifyOTP_failed_empty_email", + "test_controller/test_OTPController.py::test_verifyOTP_failed_empty_otp", + "test_controller/test_OTPController.py::test_verifyOTP_failed_invalid_email", + "test_controller/test_OTPController.py::test_verifyOTP_failed_invalid_otp", + "test_controller/test_OTPController.py::test_verifyOTP_failed_no_otp_found", + "test_controller/test_OTPController.py::test_verifyOTP_has_expired", + "test_controller/test_OTPController.py::test_verifyOTP_otp_email_must_be_string", + "test_controller/test_OTPController.py::test_verifyOTP_otp_is_required", + "test_controller/test_OTPController.py::test_verifyOTP_otp_max_length", + "test_controller/test_OTPController.py::test_verifyOTP_otp_must_be_string", + "test_controller/test_OTPController.py::test_verifyOTP_success", + "test_controller/test_UserController.py::test_change_password_current_password_empty", + "test_controller/test_UserController.py::test_change_password_current_password_required", + "test_controller/test_UserController.py::test_change_password_email_invalid", + "test_controller/test_UserController.py::test_change_password_email_is_empty", + "test_controller/test_UserController.py::test_change_password_id_not_exist", + "test_controller/test_UserController.py::test_change_password_new_password_empty", + "test_controller/test_UserController.py::test_change_password_new_password_required", + "test_controller/test_UserController.py::test_change_password_success", + "test_controller/test_UserController.py::test_change_password_user_id_integer", + "test_controller/test_UserController.py::test_change_password_user_id_integer_greater_than_0", + "test_controller/test_UserController.py::test_change_password_user_id_required", + "test_controller/test_UserController.py::test_check_info_google_by_email_success", + "test_controller/test_UserController.py::test_check_info_google_email_empty", + "test_controller/test_UserController.py::test_check_info_google_email_invalid", + "test_controller/test_UserController.py::test_check_info_google_id_not_exist", + "test_controller/test_UserController.py::test_check_info_google_sign_up_email_is_required", + "test_controller/test_UserController.py::test_check_info_google_sign_up_email_must_str", + "test_controller/test_UserController.py::test_check_info_google_signup_email_empty", + "test_controller/test_UserController.py::test_check_info_google_signup_email_invalid", + "test_controller/test_UserController.py::test_check_info_google_success", + "test_controller/test_UserController.py::test_check_info_google_user_id_must_integer", + "test_controller/test_UserController.py::test_check_info_google_user_id_must_integer_greater_than_0", + "test_controller/test_UserController.py::test_check_info_google_user_id_required", + "test_controller/test_UserController.py::test_check_state_login_email_empty", + "test_controller/test_UserController.py::test_check_state_login_email_invalid", + "test_controller/test_UserController.py::test_check_state_login_id_not_exits", + "test_controller/test_UserController.py::test_check_state_login_not_found", + "test_controller/test_UserController.py::test_check_state_login_session_id_must_str", + "test_controller/test_UserController.py::test_check_state_login_session_id_required", + "test_controller/test_UserController.py::test_check_state_login_success", + "test_controller/test_UserController.py::test_check_state_login_user_id_must_integer", + "test_controller/test_UserController.py::test_check_state_login_user_id_must_integer_greater_than_0", + "test_controller/test_UserController.py::test_check_state_login_user_id_required", + "test_controller/test_UserController.py::test_check_state_session_empty", + "test_controller/test_UserController.py::test_reset_email_must_str", + "test_controller/test_UserController.py::test_reset_email_required", + "test_controller/test_UserController.py::test_reset_password_email_is_None", + "test_controller/test_UserController.py::test_reset_password_invalid_email", + "test_controller/test_UserController.py::test_reset_password_success", + "test_controller/test_UserController.py::test_reset_password_user_not_found", + "test_controller/test_UserController.py::test_update_user_info_dis_play_name_field_required", + "test_controller/test_UserController.py::test_update_user_info_email_empty", + "test_controller/test_UserController.py::test_update_user_info_email_field_required", + "test_controller/test_UserController.py::test_update_user_info_email_invalid", + "test_controller/test_UserController.py::test_update_user_info_email_or_password_error", + "test_controller/test_UserController.py::test_update_user_info_id_not_exist", + "test_controller/test_UserController.py::test_update_user_info_photo_url_field_required", + "test_controller/test_UserController.py::test_update_user_info_success", + "test_controller/test_UserController.py::test_update_user_info_uid_field_required", + "test_controller/test_UserController.py::test_update_user_info_user_id_greater_than_0", + "test_controller/test_UserController.py::test_update_user_info_user_id_integer_required", + "test_controller/test_UserController.py::test_update_user_info_user_id_required", + "test_service/test_ChatService.py::TestDeleteChat::test_delete_chat_chat_name_empty", + "test_service/test_ChatService.py::TestDeleteChat::test_delete_chat_failed", + "test_service/test_ChatService.py::TestDeleteChat::test_delete_chat_id_not_exist", + "test_service/test_ChatService.py::TestDeleteChat::test_delete_chat_server_err", + "test_service/test_ChatService.py::TestDeleteChat::test_delete_chat_success", + "test_service/test_ChatService.py::TestExtractFile::test_extract_file_email_empty", + "test_service/test_ChatService.py::TestExtractFile::test_extract_file_email_in_valid", + "test_service/test_ChatService.py::TestExtractFile::test_extract_file_id_not_exist", + "test_service/test_ChatService.py::TestExtractFile::test_extract_file_no_data", + "test_service/test_ChatService.py::TestExtractFile::test_extract_file_server_error_sf", + "test_service/test_ChatService.py::TestExtractFile::test_extract_file_success", + "test_service/test_ChatService.py::TestGenerateQuestion::test_generate_question_email_empty", + "test_service/test_ChatService.py::TestGenerateQuestion::test_generate_question_email_in_valid", + "test_service/test_ChatService.py::TestGenerateQuestion::test_generate_question_id_not_exist", + "test_service/test_ChatService.py::TestGenerateQuestion::test_generate_question_no_data", + "test_service/test_ChatService.py::TestGenerateQuestion::test_generate_question_server_err_user_repo", + "test_service/test_ChatService.py::TestGenerateQuestion::test_generate_question_success", + "test_service/test_ChatService.py::TestQuery2UpgradeOld::test_query2_upgrade_old_chat_empty", + "test_service/test_ChatService.py::TestQuery2UpgradeOld::test_query2_upgrade_old_email_empty", + "test_service/test_ChatService.py::TestQuery2UpgradeOld::test_query2_upgrade_old_email_in_valid", + "test_service/test_ChatService.py::TestQuery2UpgradeOld::test_query2_upgrade_old_id_not_exist", + "test_service/test_ChatService.py::TestQuery2UpgradeOld::test_query2_upgrade_old_no_answer", + "test_service/test_ChatService.py::TestQuery2UpgradeOld::test_query2_upgrade_old_question_empty", + "test_service/test_ChatService.py::TestQuery2UpgradeOld::test_query2_upgrade_old_server_error_chathistory_repo", + "test_service/test_ChatService.py::TestQuery2UpgradeOld::test_query2_upgrade_old_server_error_detailchat_repo", + "test_service/test_ChatService.py::TestQuery2UpgradeOld::test_query2_upgrade_old_server_error_function_repo", + "test_service/test_ChatService.py::TestQuery2UpgradeOld::test_query2_upgrade_old_server_error_user_repo", + "test_service/test_ChatService.py::TestQuery2UpgradeOld::test_query2_upgrade_old_success", + "test_service/test_DefaultService.py::TestCreateFireBaseUser::test_email_none", + "test_service/test_DefaultService.py::TestCreateFireBaseUser::test_existing_user", + "test_service/test_DefaultService.py::TestCreateFireBaseUser::test_invalid_email", + "test_service/test_DefaultService.py::TestCreateFireBaseUser::test_non_existing_user", + "test_service/test_DefaultService.py::TestCreateFireBaseUser::test_oauth2_failed", + "test_service/test_DefaultService.py::TestCreateFireBaseUser::test_server_error", + "test_service/test_DefaultService.py::TestCreateFireBaseUser::test_token_google_empty", + "test_service/test_DefaultService.py::TestInfoUser::test_email_is_none", + "test_service/test_DefaultService.py::TestInfoUser::test_id_not_exist", + "test_service/test_DefaultService.py::TestInfoUser::test_invalid_email", + "test_service/test_DefaultService.py::TestInfoUser::test_server_error", + "test_service/test_DefaultService.py::TestInfoUser::test_successful_user_retrieval", + "test_service/test_DefaultService.py::TestInfoUser::test_user_not_found", + "test_service/test_DefaultService.py::TestIsMe::test_invalid_token", + "test_service/test_DefaultService.py::TestIsMe::test_none_token", + "test_service/test_DefaultService.py::TestIsMe::test_server_error", + "test_service/test_DefaultService.py::TestIsMe::test_valid_token", + "test_service/test_DefaultService.py::TestUpLoadFile::test_upload_image_email_empty", + "test_service/test_DefaultService.py::TestUpLoadFile::test_upload_image_email_invalid", + "test_service/test_DefaultService.py::TestUpLoadFile::test_upload_image_id_not_exist", + "test_service/test_DefaultService.py::TestUpLoadFile::test_upload_image_invalid_filetype", + "test_service/test_DefaultService.py::TestUpLoadFile::test_upload_image_server_err", + "test_service/test_DefaultService.py::TestUpLoadFile::test_upload_image_success", + "test_service/test_FileService.py::TestDeleteAllFile::test_delete_all_file_email_empty", + "test_service/test_FileService.py::TestDeleteAllFile::test_delete_all_file_email_invalid", + "test_service/test_FileService.py::TestDeleteAllFile::test_delete_all_file_id_not_exist", + "test_service/test_FileService.py::TestDeleteAllFile::test_delete_all_file_server_err", + "test_service/test_FileService.py::TestDeleteAllFile::test_delete_all_file_success", + "test_service/test_FileService.py::TestDeleteFile::test_delete_file_email_empty", + "test_service/test_FileService.py::TestDeleteFile::test_delete_file_email_invalid", + "test_service/test_FileService.py::TestDeleteFile::test_delete_file_id_not_exist", + "test_service/test_FileService.py::TestDeleteFile::test_delete_file_namefile_empty", + "test_service/test_FileService.py::TestDeleteFile::test_delete_file_server_error", + "test_service/test_FileService.py::TestDeleteFile::test_delete_file_success", + "test_service/test_FileService.py::TestDownLoadFile::test_download_file_email_empty", + "test_service/test_FileService.py::TestDownLoadFile::test_download_file_email_invalid", + "test_service/test_FileService.py::TestDownLoadFile::test_download_file_id_not_exist", + "test_service/test_FileService.py::TestDownLoadFile::test_download_file_name_file_empty", + "test_service/test_FileService.py::TestDownLoadFile::test_download_file_server_error", + "test_service/test_FileService.py::TestDownLoadFile::test_download_file_success", + "test_service/test_FileService.py::TestDownLoadFolder::test_download_folder_email_empty", + "test_service/test_FileService.py::TestDownLoadFolder::test_download_folder_email_invalid", + "test_service/test_FileService.py::TestDownLoadFolder::test_download_folder_id_not_exist", + "test_service/test_FileService.py::TestDownLoadFolder::test_download_folder_server_error", + "test_service/test_FileService.py::TestDownLoadFolder::test_download_folder_success", + "test_service/test_FileService.py::TestListNameFiles::test_listNameFiles_server_error", + "test_service/test_FileService.py::TestListNameFiles::test_list_name_file_success", + "test_service/test_FileService.py::TestListNameFiles::test_list_name_files_email_empty", + "test_service/test_FileService.py::TestListNameFiles::test_list_name_files_email_invalid", + "test_service/test_FileService.py::TestListNameFiles::test_list_name_files_id_not_exist", + "test_service/test_FileService.py::TestUploadFileService::test_upload_files_empty_email", + "test_service/test_FileService.py::TestUploadFileService::test_upload_files_error_handling", + "test_service/test_FileService.py::TestUploadFileService::test_upload_files_id_not_exist", + "test_service/test_FileService.py::TestUploadFileService::test_upload_files_invalid_email", + "test_service/test_FileService.py::TestUploadFileService::test_upload_files_invalid_file_type", + "test_service/test_FileService.py::TestUploadFileService::test_upload_files_success", + "test_service/test_LoginService.py::TestChangePassword::test_change_password_confirm_new_password_do_not_match_new_password", + "test_service/test_LoginService.py::TestChangePassword::test_change_password_confirm_new_password_empty", + "test_service/test_LoginService.py::TestChangePassword::test_change_password_current_password_empty", + "test_service/test_LoginService.py::TestChangePassword::test_change_password_current_password_not_valid", + "test_service/test_LoginService.py::TestChangePassword::test_change_password_email_invalid", + "test_service/test_LoginService.py::TestChangePassword::test_change_password_email_is_empty", + "test_service/test_LoginService.py::TestChangePassword::test_change_password_id_not_exist", + "test_service/test_LoginService.py::TestChangePassword::test_change_password_new_password_empty", + "test_service/test_LoginService.py::TestChangePassword::test_change_password_server_error", + "test_service/test_LoginService.py::TestChangePassword::test_change_password_success", + "test_service/test_LoginService.py::TestCheckInfoGoogle::test_check_info_google_email_empty", + "test_service/test_LoginService.py::TestCheckInfoGoogle::test_check_info_google_email_invalid", + "test_service/test_LoginService.py::TestCheckInfoGoogle::test_check_info_google_id_not_exist", + "test_service/test_LoginService.py::TestCheckInfoGoogle::test_check_info_google_server_error", + "test_service/test_LoginService.py::TestCheckInfoGoogle::test_check_info_google_success", + "test_service/test_LoginService.py::TestCheckInfoGoogleEmail::test_check_info_google_by_email_email_empty", + "test_service/test_LoginService.py::TestCheckInfoGoogleEmail::test_check_info_google_email_invalid", + "test_service/test_LoginService.py::TestCheckInfoGoogleEmail::test_check_info_google_email_server_error", + "test_service/test_LoginService.py::TestCheckInfoGoogleEmail::test_check_info_google_email_success", + "test_service/test_LoginService.py::TestCheckStateLogin::test_check_state_login_email_empty", + "test_service/test_LoginService.py::TestCheckStateLogin::test_check_state_login_email_invalid", + "test_service/test_LoginService.py::TestCheckStateLogin::test_check_state_login_id_not_exits", + "test_service/test_LoginService.py::TestCheckStateLogin::test_check_state_login_not_found", + "test_service/test_LoginService.py::TestCheckStateLogin::test_check_state_login_server_error", + "test_service/test_LoginService.py::TestCheckStateLogin::test_check_state_login_success", + "test_service/test_LoginService.py::TestCheckStateLogin::test_check_state_session_empty", + "test_service/test_LoginService.py::TestLoginFunction::test_login_email_empty", + "test_service/test_LoginService.py::TestLoginFunction::test_login_email_invalid", + "test_service/test_LoginService.py::TestLoginFunction::test_login_email_not_exists", + "test_service/test_LoginService.py::TestLoginFunction::test_login_email_or_password_error", + "test_service/test_LoginService.py::TestLoginFunction::test_login_invalid_authorization_code", + "test_service/test_LoginService.py::TestLoginFunction::test_login_password_empty", + "test_service/test_LoginService.py::TestLoginFunction::test_login_server_error", + "test_service/test_LoginService.py::TestLoginFunction::test_login_success", + "test_service/test_LoginService.py::TestLoginGoogle::test_login_email_invalid", + "test_service/test_LoginService.py::TestLoginGoogle::test_login_google_email_empty", + "test_service/test_LoginService.py::TestLoginGoogle::test_login_google_email_not_exists", + "test_service/test_LoginService.py::TestLoginGoogle::test_login_google_server_error", + "test_service/test_LoginService.py::TestLoginGoogle::test_login_google_success", + "test_service/test_LoginService.py::TestRefreshToken::test_refresh_token_email_empty", + "test_service/test_LoginService.py::TestRefreshToken::test_refresh_token_email_invalid", + "test_service/test_LoginService.py::TestRefreshToken::test_refresh_token_refresh_token_error", + "test_service/test_LoginService.py::TestRefreshToken::test_refresh_token_server_error", + "test_service/test_LoginService.py::TestRefreshToken::test_refresh_token_success", + "test_service/test_LoginService.py::TestRefreshToken::test_refresh_token_token_empty", + "test_service/test_LoginService.py::TestRefreshToken::test_refresh_token_user_id_not_exist", + "test_service/test_LoginService.py::TestResetPassword::test_reset_password_invalid_email", + "test_service/test_LoginService.py::TestResetPassword::test_reset_password_server_error", + "test_service/test_LoginService.py::TestResetPassword::test_reset_password_success", + "test_service/test_LoginService.py::TestResetPassword::test_reset_password_user_not_found", + "test_service/test_LoginService.py::TestSignUpFunction::test_sign_up_confirm_password_do_not_match_password", + "test_service/test_LoginService.py::TestSignUpFunction::test_sign_up_confirm_password_empty", + "test_service/test_LoginService.py::TestSignUpFunction::test_sign_up_email_exist", + "test_service/test_LoginService.py::TestSignUpFunction::test_sign_up_email_invalid", + "test_service/test_LoginService.py::TestSignUpFunction::test_sign_up_email_is_empty", + "test_service/test_LoginService.py::TestSignUpFunction::test_sign_up_error", + "test_service/test_LoginService.py::TestSignUpFunction::test_sign_up_password_empty", + "test_service/test_LoginService.py::TestSignUpFunction::test_sign_up_server_error", + "test_service/test_LoginService.py::TestSignUpFunction::test_sign_up_success", + "test_service/test_LoginService.py::TestUpdateUserInfoFunction::test_update_user_info_email_empty", + "test_service/test_LoginService.py::TestUpdateUserInfoFunction::test_update_user_info_email_invalid", + "test_service/test_LoginService.py::TestUpdateUserInfoFunction::test_update_user_info_email_or_password_error", + "test_service/test_LoginService.py::TestUpdateUserInfoFunction::test_update_user_info_id_not_exist", + "test_service/test_LoginService.py::TestUpdateUserInfoFunction::test_update_user_info_server_error", + "test_service/test_LoginService.py::TestUpdateUserInfoFunction::test_update_user_info_success_existing_user", + "test_service/test_LoginService.py::TestUpdateUserInfoFunction::test_update_user_info_success_new_user_info", + "test_service/test_MySQLService.py::TestDeleteChat::test_delete_chat_chatname_empty", + "test_service/test_MySQLService.py::TestDeleteChat::test_delete_chat_email_empty", + "test_service/test_MySQLService.py::TestDeleteChat::test_delete_chat_email_invalid", + "test_service/test_MySQLService.py::TestDeleteChat::test_delete_chat_error_1", + "test_service/test_MySQLService.py::TestDeleteChat::test_delete_chat_id_not_exist", + "test_service/test_MySQLService.py::TestDeleteChat::test_delete_chat_server_error", + "test_service/test_MySQLService.py::TestDeleteChat::test_delete_chat_success", + "test_service/test_MySQLService.py::TestLoadChatHistory::test_load_chat_history_error", + "test_service/test_MySQLService.py::TestLoadChatHistory::test_load_chat_history_not_found_chat", + "test_service/test_MySQLService.py::TestLoadChatHistory::test_load_chat_history_server_err", + "test_service/test_MySQLService.py::TestLoadChatHistory::test_load_chat_history_success", + "test_service/test_MySQLService.py::TestLoadChatHistory::test_load_chat_history_user_id_str", + "test_service/test_MySQLService.py::TestMySQLService::test_edit_chat_email_empty", + "test_service/test_MySQLService.py::TestMySQLService::test_edit_chat_email_in_valid", + "test_service/test_MySQLService.py::TestMySQLService::test_edit_chat_id_not_exist", + "test_service/test_MySQLService.py::TestMySQLService::test_edit_chat_name_new_empty", + "test_service/test_MySQLService.py::TestMySQLService::test_edit_chat_name_old_empty", + "test_service/test_MySQLService.py::TestMySQLService::test_edit_chat_server_error", + "test_service/test_MySQLService.py::TestMySQLService::test_edit_chat_success", + "test_service/test_MySQLService.py::TestMySQLService::test_edit_chat_update_error", + "test_service/test_MySQLService.py::TestRenderChatHistory::test_render_chat_history_id_not_exist", + "test_service/test_MySQLService.py::TestRenderChatHistory::test_render_chat_history_server_err", + "test_service/test_MySQLService.py::TestRenderChatHistory::test_render_chat_history_success", + "test_service/test_OTPService.py::TestCreateOTPFunctions::test_createOTP_failed_empty_email", + "test_service/test_OTPService.py::TestCreateOTPFunctions::test_createOTP_failed_empty_invalid", + "test_service/test_OTPService.py::TestCreateOTPFunctions::test_createOTP_success", + "test_service/test_OTPService.py::TestCreateOTPReset::test_createOTPReset_email_empty", + "test_service/test_OTPService.py::TestCreateOTPReset::test_createOTPReset_email_invalid", + "test_service/test_OTPService.py::TestCreateOTPReset::test_createOTPReset_success", + "test_service/test_OTPService.py::TestVerifyOTPFunctions::test_verifyOTP_failed_empty_email", + "test_service/test_OTPService.py::TestVerifyOTPFunctions::test_verifyOTP_failed_empty_otp", + "test_service/test_OTPService.py::TestVerifyOTPFunctions::test_verifyOTP_failed_invalid_email", + "test_service/test_OTPService.py::TestVerifyOTPFunctions::test_verifyOTP_failed_invalid_otp", + "test_service/test_OTPService.py::TestVerifyOTPFunctions::test_verifyOTP_failed_no_otp_found", + "test_service/test_OTPService.py::TestVerifyOTPFunctions::test_verifyOTP_has_expired", + "test_service/test_OTPService.py::TestVerifyOTPFunctions::test_verifyOTP_success", + "test_service/test_OTPService.py::TestVerifyOTPReset::test_verifyOTPReset_failed_empty_email", + "test_service/test_OTPService.py::TestVerifyOTPReset::test_verifyOTPReset_failed_empty_otp", + "test_service/test_OTPService.py::TestVerifyOTPReset::test_verifyOTPReset_failed_invalid_email", + "test_service/test_OTPService.py::TestVerifyOTPReset::test_verifyOTPReset_failed_invalid_otp", + "test_service/test_OTPService.py::TestVerifyOTPReset::test_verifyOTPReset_failed_no_otp_found", + "test_service/test_OTPService.py::TestVerifyOTPReset::test_verifyOTPReset_has_expired", + "test_service/test_OTPService.py::TestVerifyOTPReset::test_verifyOTPReset_success" +] \ No newline at end of file diff --git a/tests/.pytest_cache/v/cache/stepwise b/tests/.pytest_cache/v/cache/stepwise new file mode 100644 index 0000000000000000000000000000000000000000..0637a088a01e8ddab3bf3fa98dbe804cbde1a0dc --- /dev/null +++ b/tests/.pytest_cache/v/cache/stepwise @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/tests/test_controller/.pytest_cache/.gitignore b/tests/test_controller/.pytest_cache/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..08a7f458f1f002823bc794c47ca1996a57e72c86 --- /dev/null +++ b/tests/test_controller/.pytest_cache/.gitignore @@ -0,0 +1,2 @@ +# Created by pytest automatically. +* diff --git a/tests/test_controller/.pytest_cache/CACHEDIR.TAG b/tests/test_controller/.pytest_cache/CACHEDIR.TAG new file mode 100644 index 0000000000000000000000000000000000000000..fce15ad7eaa74e5682b644c84efb75334c112f95 --- /dev/null +++ b/tests/test_controller/.pytest_cache/CACHEDIR.TAG @@ -0,0 +1,4 @@ +Signature: 8a477f597d28d172789f06886806bc55 +# This file is a cache directory tag created by pytest. +# For information about cache directory tags, see: +# https://bford.info/cachedir/spec.html diff --git a/tests/test_controller/.pytest_cache/README.md b/tests/test_controller/.pytest_cache/README.md new file mode 100644 index 0000000000000000000000000000000000000000..c7526af2448672de4537dfed042ed74daadb17bf --- /dev/null +++ b/tests/test_controller/.pytest_cache/README.md @@ -0,0 +1,8 @@ +# pytest cache directory # + +This directory contains data from the pytest's cache plugin, +which provides the `--lf` and `--ff` options, as well as the `cache` fixture. + +**Do not** commit this to version control. + +See [the docs](https://docs.pytest.org/en/stable/how-to/cache.html) for more information. diff --git a/tests/test_controller/.pytest_cache/v/cache/lastfailed b/tests/test_controller/.pytest_cache/v/cache/lastfailed new file mode 100644 index 0000000000000000000000000000000000000000..dbf1b6563b3135d4acd44f4adf09cedb35a45c76 --- /dev/null +++ b/tests/test_controller/.pytest_cache/v/cache/lastfailed @@ -0,0 +1,50 @@ +{ + "test_OTPController.py::test_create_otp_with_missing_email": true, + "test_OTPController.py::test_create_otp_with_missing_body": true, + "test_DefaultController.py::test_email_none": true, + "test_DefaultController.py::test_create_firebase_user_google": true, + "test_ChatController.py::test_query2_upgrade_success": true, + "test_ChatController.py::test_query2_upgrade_id_not_exist": true, + "test_ChatController.py::test_query2_upgrade_email_empty": true, + "test_ChatController.py::test_query2_upgrade_question_empty": true, + "test_ChatController.py::test_query2_upgrade_chat_history_empty": true, + "test_ChatController.py::test_query2_upgrade_no_answer": true, + "test_FileController.py::test_delete_file_all_file_user_id_interger": true, + "test_LoginController.py::test_login_gooogle_email_can_not_empty": true, + "test_LoginController.py::test_login_gooogle_email_required": true, + "test_LoginController.py::test_check_signup_session_id_required": true, + "test_MySQLController.py::test_render_chat_empty": true, + "test_MySQLController.py::test_load_chat_history_empty": true, + "test_MySQLController.py::test_load_chat_history_empty1": true, + "test_MySQLController.py::test_render_chat_user_id_required": true, + "test_MySQLController.py::test_load_chat_history_chat_id_is_required": true, + "test_MySQLController.py::test_load_chat_history_user_id_is_required": true, + "test_DefaultController.py::test_info_user_user_id_required": true, + "test_DefaultController.py::test_upload_image_user_id_required": true, + "test_DefaultController.py::test_create_firebase_user_error": true, + "test_LoginController.py::test_change_password_current_password_not_valid": true, + "test_LoginController.py::test_refresh_token_success": true, + "test_LoginController.py::test_refresh_token_user_id_not_exist": true, + "test_LoginController.py::test_refresh_token_email_empty": true, + "test_LoginController.py::test_refresh_token_email_invalid": true, + "test_LoginController.py::test_refresh_token_token_empty": true, + "test_LoginController.py::test_refresh_token_token_errror": true, + "test_LoginController.py::test_login_email_required": true, + "test_LoginController.py::test_login_email_required_str": true, + "test_LoginController.py::test_login_password_required": true, + "test_LoginController.py::test_login_email_can_not_empty": true, + "test_LoginController.py::test_login_google_email_required": true, + "test_LoginController.py::test_login_google_token_google_required": true, + "test_LoginController.py::test_login_google_email_required_str_1": true, + "test_LoginController.py::test_login_google_email_token_required_str": true, + "test_LoginController.py::test_login_google_email_can_not_empty": true, + "test_LoginController.py::test_signup_email_is_required": true, + "test_LoginController.py::test_signup_email_must_str": true, + "test_LoginController.py::test_signup_password_required": true, + "test_LoginController.py::test_refresh_token_user_id_required": true, + "test_LoginController.py::test_refresh_token_user_id_integer": true, + "test_LoginController.py::test_refresh_token_user_id_integer_greater_than_0": true, + "test_LoginController.py::test_refresh_token_token_must_be_str": true, + "test_LoginController.py::test_refresh_token_token_is_required": true, + "test_LoginController.py::test_signup_confirm_password_required": true +} \ No newline at end of file diff --git a/tests/test_controller/.pytest_cache/v/cache/nodeids b/tests/test_controller/.pytest_cache/v/cache/nodeids new file mode 100644 index 0000000000000000000000000000000000000000..5c27f52b791edec2b515b7335164a6a4192654d7 --- /dev/null +++ b/tests/test_controller/.pytest_cache/v/cache/nodeids @@ -0,0 +1,289 @@ +[ + "test_ChatController.py::test_extract_file_email_empty", + "test_ChatController.py::test_extract_file_email_in_valid", + "test_ChatController.py::test_extract_file_id_not_exist", + "test_ChatController.py::test_extract_file_no_data", + "test_ChatController.py::test_extract_file_success", + "test_ChatController.py::test_extract_file_user_id_greater_0", + "test_ChatController.py::test_extract_file_user_id_interger", + "test_ChatController.py::test_extract_file_user_id_required", + "test_ChatController.py::test_generate_question_email_empty", + "test_ChatController.py::test_generate_question_email_in_valid", + "test_ChatController.py::test_generate_question_id_not_exist", + "test_ChatController.py::test_generate_question_no_data", + "test_ChatController.py::test_generate_question_success", + "test_ChatController.py::test_generate_question_user_id_greater_0", + "test_ChatController.py::test_generate_question_user_id_interger", + "test_ChatController.py::test_generate_question_user_id_required", + "test_ChatController.py::test_query2_upgrade_chat_history_empty", + "test_ChatController.py::test_query2_upgrade_email_empty", + "test_ChatController.py::test_query2_upgrade_id_not_exist", + "test_ChatController.py::test_query2_upgrade_no_answer", + "test_ChatController.py::test_query2_upgrade_old_chat_history_empty", + "test_ChatController.py::test_query2_upgrade_old_email_empty", + "test_ChatController.py::test_query2_upgrade_old_email_in_valid", + "test_ChatController.py::test_query2_upgrade_old_id_not_exist", + "test_ChatController.py::test_query2_upgrade_old_no_answer", + "test_ChatController.py::test_query2_upgrade_old_question_empty", + "test_ChatController.py::test_query2_upgrade_old_success", + "test_ChatController.py::test_query2_upgrade_question_empty", + "test_ChatController.py::test_query2_upgrade_success", + "test_ChatController.py::test_query_chatbot_user_id_greater_0", + "test_ChatController.py::test_query_chatbot_user_id_interger", + "test_ChatController.py::test_query_chatbot_user_id_required", + "test_DefaultController.py::test_create_firebase_server_error", + "test_DefaultController.py::test_create_firebase_user_error", + "test_DefaultController.py::test_create_firebase_user_google", + "test_DefaultController.py::test_create_firebase_user_google_email_must_be_string", + "test_DefaultController.py::test_create_firebase_user_google_is_None", + "test_DefaultController.py::test_create_firebase_user_google_token_is_required", + "test_DefaultController.py::test_create_firebase_user_google_token_must_be_str", + "test_DefaultController.py::test_create_firebase_user_google_token_must_be_str_1", + "test_DefaultController.py::test_create_firebase_user_null_email", + "test_DefaultController.py::test_create_firebase_user_success", + "test_DefaultController.py::test_email_none", + "test_DefaultController.py::test_id_not_exist", + "test_DefaultController.py::test_info_success", + "test_DefaultController.py::test_info_user_email_empty", + "test_DefaultController.py::test_info_user_email_invalid", + "test_DefaultController.py::test_info_user_user_id_must_be_string", + "test_DefaultController.py::test_info_user_user_id_required", + "test_DefaultController.py::test_info_user_user_not_found", + "test_DefaultController.py::test_invalid_email", + "test_DefaultController.py::test_is_me_invalid_token", + "test_DefaultController.py::test_is_me_none_token", + "test_DefaultController.py::test_is_me_server_error", + "test_DefaultController.py::test_is_me_success", + "test_DefaultController.py::test_is_me_token_is_required", + "test_DefaultController.py::test_is_me_token_must_be_string", + "test_DefaultController.py::test_upload_image_email_empty", + "test_DefaultController.py::test_upload_image_email_invalid", + "test_DefaultController.py::test_upload_image_id_not_exist", + "test_DefaultController.py::test_upload_image_server_err", + "test_DefaultController.py::test_upload_image_success", + "test_DefaultController.py::test_upload_image_user_id_greater_than_0", + "test_DefaultController.py::test_upload_image_user_id_integer", + "test_DefaultController.py::test_upload_image_user_id_interger", + "test_DefaultController.py::test_upload_image_user_id_required", + "test_DefaultController.py::test_user_info_server_error", + "test_FileController.py::test_delete__all_file_user_id_required", + "test_FileController.py::test_delete_all_file_email_empty", + "test_FileController.py::test_delete_all_file_email_invalid", + "test_FileController.py::test_delete_all_file_success", + "test_FileController.py::test_delete_all_file_user_id_is_greater_0", + "test_FileController.py::test_delete_all_file_user_id_is_integer", + "test_FileController.py::test_delete_all_file_user_id_is_interger", + "test_FileController.py::test_delete_file_all_file_user_id_interger", + "test_FileController.py::test_delete_file_all_file_user_id_required", + "test_FileController.py::test_delete_file_email_empty", + "test_FileController.py::test_delete_file_email_invalid", + "test_FileController.py::test_delete_file_id_not_exist", + "test_FileController.py::test_delete_file_namefile_empty", + "test_FileController.py::test_delete_file_success", + "test_FileController.py::test_delete_one_file_name_file_required", + "test_FileController.py::test_delete_one_file_user_id_is_greater_0", + "test_FileController.py::test_delete_one_file_user_id_is_integer", + "test_FileController.py::test_delete_one_file_user_id_is_interger", + "test_FileController.py::test_delete_one_file_user_id_required", + "test_FileController.py::test_download_file_email_empty", + "test_FileController.py::test_download_file_email_invalid", + "test_FileController.py::test_download_file_id_not_exist", + "test_FileController.py::test_download_file_name_file_empty", + "test_FileController.py::test_download_file_success", + "test_FileController.py::test_download_file_user_id_required", + "test_FileController.py::test_download_files_user_id_is_greater_0", + "test_FileController.py::test_download_files_user_id_is_integer", + "test_FileController.py::test_download_files_user_id_is_interger", + "test_FileController.py::test_download_folder_email_empty", + "test_FileController.py::test_download_folder_email_invalid", + "test_FileController.py::test_download_folder_id_not_exist", + "test_FileController.py::test_download_folder_success", + "test_FileController.py::test_download_folder_user_id_is_greater_0", + "test_FileController.py::test_download_folder_user_id_is_integer", + "test_FileController.py::test_download_folder_user_id_is_interger", + "test_FileController.py::test_download_folder_user_id_required", + "test_FileController.py::test_list_name_file_email_empty", + "test_FileController.py::test_list_name_file_email_invalid", + "test_FileController.py::test_list_name_file_id_not_exist", + "test_FileController.py::test_list_name_file_success", + "test_FileController.py::test_list_name_files_user_id_is_greater_0", + "test_FileController.py::test_list_name_files_user_id_is_integer", + "test_FileController.py::test_list_name_files_user_id_is_interger", + "test_FileController.py::test_list_name_files_user_id_required", + "test_FileController.py::test_upload_file_user_id_required", + "test_FileController.py::test_upload_files_empty_email", + "test_FileController.py::test_upload_files_id_not_exist", + "test_FileController.py::test_upload_files_invalid_email", + "test_FileController.py::test_upload_files_invalid_file_type", + "test_FileController.py::test_upload_files_success", + "test_FileController.py::test_upload_files_user_id_is_greater_0", + "test_FileController.py::test_upload_files_user_id_is_integer", + "test_FileController.py::test_upload_files_user_id_is_interger", + "test_LoginController.py::test_change_pass_confirm_required", + "test_LoginController.py::test_change_password_current_password_empty", + "test_LoginController.py::test_change_password_current_password_not_valid", + "test_LoginController.py::test_change_password_current_password_required", + "test_LoginController.py::test_change_password_email_invalid", + "test_LoginController.py::test_change_password_email_is_empty", + "test_LoginController.py::test_change_password_id_not_exist", + "test_LoginController.py::test_change_password_new_password_empty", + "test_LoginController.py::test_change_password_new_password_required", + "test_LoginController.py::test_change_password_success", + "test_LoginController.py::test_change_password_user_id_integer", + "test_LoginController.py::test_change_password_user_id_integer_greater_than_0", + "test_LoginController.py::test_change_password_user_id_required", + "test_LoginController.py::test_check_info_google_by_email_success", + "test_LoginController.py::test_check_info_google_email_empty", + "test_LoginController.py::test_check_info_google_email_invalid", + "test_LoginController.py::test_check_info_google_id_not_exist", + "test_LoginController.py::test_check_info_google_sign_up_email_is_required", + "test_LoginController.py::test_check_info_google_sign_up_email_must_str", + "test_LoginController.py::test_check_info_google_signup_email_empty", + "test_LoginController.py::test_check_info_google_signup_email_invalid", + "test_LoginController.py::test_check_info_google_success", + "test_LoginController.py::test_check_info_google_user_id_must_integer", + "test_LoginController.py::test_check_info_google_user_id_must_integer_greater_than_0", + "test_LoginController.py::test_check_info_google_user_id_required", + "test_LoginController.py::test_check_signup_session_id_must_str", + "test_LoginController.py::test_check_signup_session_id_required", + "test_LoginController.py::test_check_state_login_email_empty", + "test_LoginController.py::test_check_state_login_email_invalid", + "test_LoginController.py::test_check_state_login_id_not_exits", + "test_LoginController.py::test_check_state_login_not_found", + "test_LoginController.py::test_check_state_login_session_id_must_str", + "test_LoginController.py::test_check_state_login_session_id_required", + "test_LoginController.py::test_check_state_login_success", + "test_LoginController.py::test_check_state_login_user_id_must_integer", + "test_LoginController.py::test_check_state_login_user_id_must_integer_greater_than_0", + "test_LoginController.py::test_check_state_login_user_id_required", + "test_LoginController.py::test_check_state_session_empty", + "test_LoginController.py::test_login_email_can_not_empty", + "test_LoginController.py::test_login_email_empty", + "test_LoginController.py::test_login_email_invalid", + "test_LoginController.py::test_login_email_not_exist", + "test_LoginController.py::test_login_email_password_error", + "test_LoginController.py::test_login_email_required", + "test_LoginController.py::test_login_email_required_str", + "test_LoginController.py::test_login_google_email_can_not_empty", + "test_LoginController.py::test_login_google_email_empty", + "test_LoginController.py::test_login_google_email_invalid", + "test_LoginController.py::test_login_google_email_password_error", + "test_LoginController.py::test_login_google_email_required", + "test_LoginController.py::test_login_google_email_required_str", + "test_LoginController.py::test_login_google_email_required_str_1", + "test_LoginController.py::test_login_google_email_token_required_str", + "test_LoginController.py::test_login_google_invalid_authorization_code", + "test_LoginController.py::test_login_google_success", + "test_LoginController.py::test_login_google_token_google_required", + "test_LoginController.py::test_login_gooogle_email_can_not_empty", + "test_LoginController.py::test_login_gooogle_email_required", + "test_LoginController.py::test_login_invalid_authorization_code", + "test_LoginController.py::test_login_password_empty", + "test_LoginController.py::test_login_password_required", + "test_LoginController.py::test_login_success", + "test_LoginController.py::test_refresh_token_email_empty", + "test_LoginController.py::test_refresh_token_email_invalid", + "test_LoginController.py::test_refresh_token_success", + "test_LoginController.py::test_refresh_token_token_empty", + "test_LoginController.py::test_refresh_token_token_errror", + "test_LoginController.py::test_refresh_token_token_is_required", + "test_LoginController.py::test_refresh_token_token_must_be_str", + "test_LoginController.py::test_refresh_token_user_id_integer", + "test_LoginController.py::test_refresh_token_user_id_integer_greater_than_0", + "test_LoginController.py::test_refresh_token_user_id_not_exist", + "test_LoginController.py::test_refresh_token_user_id_required", + "test_LoginController.py::test_reset_email_must_str", + "test_LoginController.py::test_reset_email_required", + "test_LoginController.py::test_reset_password_email_is_None", + "test_LoginController.py::test_reset_password_invalid_email", + "test_LoginController.py::test_reset_password_success", + "test_LoginController.py::test_reset_password_user_not_found", + "test_LoginController.py::test_sign_up_email_exist", + "test_LoginController.py::test_sign_up_email_invadlid", + "test_LoginController.py::test_sign_up_email_is_empty", + "test_LoginController.py::test_sign_up_error", + "test_LoginController.py::test_sign_up_password_empty", + "test_LoginController.py::test_sign_up_success", + "test_LoginController.py::test_signup_confirm_password_required", + "test_LoginController.py::test_signup_email_is_required", + "test_LoginController.py::test_signup_email_must_str", + "test_LoginController.py::test_signup_password_required", + "test_LoginController.py::test_signup_session_id_must_str", + "test_LoginController.py::test_signup_session_id_required", + "test_LoginController.py::test_update_user_info_dis_play_name_field_required", + "test_LoginController.py::test_update_user_info_email_empty", + "test_LoginController.py::test_update_user_info_email_field_required", + "test_LoginController.py::test_update_user_info_email_invalid", + "test_LoginController.py::test_update_user_info_email_or_password_error", + "test_LoginController.py::test_update_user_info_id_not_exist", + "test_LoginController.py::test_update_user_info_photo_url_field_required", + "test_LoginController.py::test_update_user_info_success", + "test_LoginController.py::test_update_user_info_uid_field_required", + "test_LoginController.py::test_update_user_info_user_id_greater_than_0", + "test_LoginController.py::test_update_user_info_user_id_integer_required", + "test_LoginController.py::test_update_user_info_user_id_interger_required", + "test_LoginController.py::test_update_user_info_user_id_required", + "test_MySQLController.py::test_delete_chat_email_empty", + "test_MySQLController.py::test_delete_chat_email_invalid", + "test_MySQLController.py::test_delete_chat_id_not_exits", + "test_MySQLController.py::test_delete_chat_name_empty", + "test_MySQLController.py::test_delete_chat_name_error_500", + "test_MySQLController.py::test_delete_chat_success", + "test_MySQLController.py::test_edit_chat1_error", + "test_MySQLController.py::test_edit_chat_email_empty", + "test_MySQLController.py::test_edit_chat_email_invalid", + "test_MySQLController.py::test_edit_chat_invalid_id", + "test_MySQLController.py::test_edit_chat_name_new", + "test_MySQLController.py::test_edit_chat_name_old", + "test_MySQLController.py::test_edit_chat_success", + "test_MySQLController.py::test_load_chat_history", + "test_MySQLController.py::test_load_chat_history_chat_id_greater_than_inter", + "test_MySQLController.py::test_load_chat_history_chat_id_is_required", + "test_MySQLController.py::test_load_chat_history_empty", + "test_MySQLController.py::test_load_chat_history_empty1", + "test_MySQLController.py::test_load_chat_history_user_id_greater_than0", + "test_MySQLController.py::test_load_chat_history_user_id_greater_than_inter", + "test_MySQLController.py::test_load_chat_history_user_id_is_required", + "test_MySQLController.py::test_load_chat_history_user_id_must_be_integer", + "test_MySQLController.py::test_load_chat_history_user_id_mustbe_inter", + "test_MySQLController.py::test_load_chat_history_value_mustbe_inter", + "test_MySQLController.py::test_render_chat_empty", + "test_MySQLController.py::test_render_chat_history", + "test_MySQLController.py::test_render_chat_user_id_greater_than_inter", + "test_MySQLController.py::test_render_chat_user_id_required", + "test_MySQLController.py::test_render_chat_value_mustbe_interger", + "test_OTPController.py::test_createOTPReset_email_empty", + "test_OTPController.py::test_createOTPReset_email_invalid", + "test_OTPController.py::test_createOTPReset_success", + "test_OTPController.py::test_createOTP_email_must_be_string", + "test_OTPController.py::test_createOTP_email_required", + "test_OTPController.py::test_createOTP_failed_empty_email", + "test_OTPController.py::test_createOTP_failed_empty_invalid", + "test_OTPController.py::test_createOTP_success", + "test_OTPController.py::test_create_otp_with_missing_body", + "test_OTPController.py::test_create_otp_with_missing_email", + "test_OTPController.py::test_verifyOTPReset1_success", + "test_OTPController.py::test_verifyOTPReset_email_is_required", + "test_OTPController.py::test_verifyOTPReset_failed_empty_email", + "test_OTPController.py::test_verifyOTPReset_failed_empty_otp", + "test_OTPController.py::test_verifyOTPReset_failed_invalid_email", + "test_OTPController.py::test_verifyOTPReset_failed_invalid_otp", + "test_OTPController.py::test_verifyOTPReset_failed_no_otp_found", + "test_OTPController.py::test_verifyOTPReset_has_expired", + "test_OTPController.py::test_verifyOTPReset_otp_email_must_be_string", + "test_OTPController.py::test_verifyOTPReset_otp_is_required", + "test_OTPController.py::test_verifyOTPReset_otp_max_length", + "test_OTPController.py::test_verifyOTPReset_otp_must_be_string", + "test_OTPController.py::test_verifyOTP_email_is_required", + "test_OTPController.py::test_verifyOTP_failed_empty_email", + "test_OTPController.py::test_verifyOTP_failed_empty_otp", + "test_OTPController.py::test_verifyOTP_failed_invalid_email", + "test_OTPController.py::test_verifyOTP_failed_invalid_otp", + "test_OTPController.py::test_verifyOTP_failed_no_otp_found", + "test_OTPController.py::test_verifyOTP_has_expired", + "test_OTPController.py::test_verifyOTP_otp_email_must_be_string", + "test_OTPController.py::test_verifyOTP_otp_is_required", + "test_OTPController.py::test_verifyOTP_otp_max_length", + "test_OTPController.py::test_verifyOTP_otp_must_be_string", + "test_OTPController.py::test_verifyOTP_success" +] \ No newline at end of file diff --git a/tests/test_controller/.pytest_cache/v/cache/stepwise b/tests/test_controller/.pytest_cache/v/cache/stepwise new file mode 100644 index 0000000000000000000000000000000000000000..0637a088a01e8ddab3bf3fa98dbe804cbde1a0dc --- /dev/null +++ b/tests/test_controller/.pytest_cache/v/cache/stepwise @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/tests/test_controller/__pycache__/__init__.cpython-310.pyc b/tests/test_controller/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..923fd66e459874d69bf0b2f76d39865931f1ee68 Binary files /dev/null and b/tests/test_controller/__pycache__/__init__.cpython-310.pyc differ diff --git a/tests/test_controller/__pycache__/__init__.cpython-311.pyc b/tests/test_controller/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e7d8d54d47d5f4c133d61ee6d9773d70c0b041f5 Binary files /dev/null and b/tests/test_controller/__pycache__/__init__.cpython-311.pyc differ diff --git a/tests/test_controller/__pycache__/test_ChatController.cpython-310-pytest-8.2.2.pyc b/tests/test_controller/__pycache__/test_ChatController.cpython-310-pytest-8.2.2.pyc new file mode 100644 index 0000000000000000000000000000000000000000..45c60942de351824f7a00f9ed8833ca3b4c9a82d Binary files /dev/null and b/tests/test_controller/__pycache__/test_ChatController.cpython-310-pytest-8.2.2.pyc differ diff --git a/tests/test_controller/__pycache__/test_ChatController.cpython-310.pyc b/tests/test_controller/__pycache__/test_ChatController.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..799715987bc72ddc57851f45d6914436db21dc5d Binary files /dev/null and b/tests/test_controller/__pycache__/test_ChatController.cpython-310.pyc differ diff --git a/tests/test_controller/__pycache__/test_ChatController.cpython-311-pytest-8.2.2.pyc b/tests/test_controller/__pycache__/test_ChatController.cpython-311-pytest-8.2.2.pyc new file mode 100644 index 0000000000000000000000000000000000000000..49b4a5e15092e58eed6e5d5d9792ce3395d64f52 Binary files /dev/null and b/tests/test_controller/__pycache__/test_ChatController.cpython-311-pytest-8.2.2.pyc differ diff --git a/tests/test_controller/__pycache__/test_DefaultController.cpython-310-pytest-8.2.2.pyc b/tests/test_controller/__pycache__/test_DefaultController.cpython-310-pytest-8.2.2.pyc new file mode 100644 index 0000000000000000000000000000000000000000..94f1e28af7c8f5f71248b2061f089bf05c88c585 Binary files /dev/null and b/tests/test_controller/__pycache__/test_DefaultController.cpython-310-pytest-8.2.2.pyc differ diff --git a/tests/test_controller/__pycache__/test_DefaultController.cpython-310.pyc b/tests/test_controller/__pycache__/test_DefaultController.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..98d4d8e7bdc5d9643a974af4681b0d9a9373ac81 Binary files /dev/null and b/tests/test_controller/__pycache__/test_DefaultController.cpython-310.pyc differ diff --git a/tests/test_controller/__pycache__/test_DefaultController.cpython-311-pytest-8.2.2.pyc b/tests/test_controller/__pycache__/test_DefaultController.cpython-311-pytest-8.2.2.pyc new file mode 100644 index 0000000000000000000000000000000000000000..62b846ea6d0315c3cdf32ac83c25b4e2a47d7a3f Binary files /dev/null and b/tests/test_controller/__pycache__/test_DefaultController.cpython-311-pytest-8.2.2.pyc differ diff --git a/tests/test_controller/__pycache__/test_FileController.cpython-310-pytest-8.2.2.pyc b/tests/test_controller/__pycache__/test_FileController.cpython-310-pytest-8.2.2.pyc new file mode 100644 index 0000000000000000000000000000000000000000..feb0c93a64f9533d41b0e1fee3c442b2cf8475c0 Binary files /dev/null and b/tests/test_controller/__pycache__/test_FileController.cpython-310-pytest-8.2.2.pyc differ diff --git a/tests/test_controller/__pycache__/test_FileController.cpython-310.pyc b/tests/test_controller/__pycache__/test_FileController.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8791e30f3e3a8026bb14ffa5a5c223f4d24acefd Binary files /dev/null and b/tests/test_controller/__pycache__/test_FileController.cpython-310.pyc differ diff --git a/tests/test_controller/__pycache__/test_FileController.cpython-311-pytest-8.2.2.pyc b/tests/test_controller/__pycache__/test_FileController.cpython-311-pytest-8.2.2.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b65b7a10101f1c6d902052da18ead3eef1637b5d Binary files /dev/null and b/tests/test_controller/__pycache__/test_FileController.cpython-311-pytest-8.2.2.pyc differ diff --git a/tests/test_controller/__pycache__/test_LoginController.cpython-310-pytest-8.2.2.pyc b/tests/test_controller/__pycache__/test_LoginController.cpython-310-pytest-8.2.2.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c747ff3b57ffb34214ff0f20a7a4fe3df38c1d6c Binary files /dev/null and b/tests/test_controller/__pycache__/test_LoginController.cpython-310-pytest-8.2.2.pyc differ diff --git a/tests/test_controller/__pycache__/test_LoginController.cpython-311-pytest-8.2.2.pyc b/tests/test_controller/__pycache__/test_LoginController.cpython-311-pytest-8.2.2.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8b6ee798dea0592aceb4bbff4fffffa297d6e736 Binary files /dev/null and b/tests/test_controller/__pycache__/test_LoginController.cpython-311-pytest-8.2.2.pyc differ diff --git a/tests/test_controller/__pycache__/test_MySQLController.cpython-310-pytest-8.2.2.pyc b/tests/test_controller/__pycache__/test_MySQLController.cpython-310-pytest-8.2.2.pyc new file mode 100644 index 0000000000000000000000000000000000000000..93f43475db39b74989cfc970b9588bb57ac66d8a Binary files /dev/null and b/tests/test_controller/__pycache__/test_MySQLController.cpython-310-pytest-8.2.2.pyc differ diff --git a/tests/test_controller/__pycache__/test_MySQLController.cpython-310.pyc b/tests/test_controller/__pycache__/test_MySQLController.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..86f8cb7fccd711879a5677e4e34c2a903f473c7e Binary files /dev/null and b/tests/test_controller/__pycache__/test_MySQLController.cpython-310.pyc differ diff --git a/tests/test_controller/__pycache__/test_MySQLController.cpython-311-pytest-8.2.2.pyc b/tests/test_controller/__pycache__/test_MySQLController.cpython-311-pytest-8.2.2.pyc new file mode 100644 index 0000000000000000000000000000000000000000..266427b64c2fd41f1a1790189229cba9ad0d9093 Binary files /dev/null and b/tests/test_controller/__pycache__/test_MySQLController.cpython-311-pytest-8.2.2.pyc differ diff --git a/tests/test_controller/__pycache__/test_OTPController.cpython-310-pytest-8.2.2.pyc b/tests/test_controller/__pycache__/test_OTPController.cpython-310-pytest-8.2.2.pyc new file mode 100644 index 0000000000000000000000000000000000000000..18e2e3039129e42623ff2933cd7b9ad1c23b3f21 Binary files /dev/null and b/tests/test_controller/__pycache__/test_OTPController.cpython-310-pytest-8.2.2.pyc differ diff --git a/tests/test_controller/__pycache__/test_OTPController.cpython-310.pyc b/tests/test_controller/__pycache__/test_OTPController.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3a635cc1961793a51191cb589137ec53bd8b7519 Binary files /dev/null and b/tests/test_controller/__pycache__/test_OTPController.cpython-310.pyc differ diff --git a/tests/test_controller/__pycache__/test_OTPController.cpython-311-pytest-8.2.2.pyc b/tests/test_controller/__pycache__/test_OTPController.cpython-311-pytest-8.2.2.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5c1c52c6f1d650461e1b84ce9cad24de6aa7ff46 Binary files /dev/null and b/tests/test_controller/__pycache__/test_OTPController.cpython-311-pytest-8.2.2.pyc differ diff --git a/tests/test_controller/__pycache__/test_UserController.cpython-310-pytest-8.2.2.pyc b/tests/test_controller/__pycache__/test_UserController.cpython-310-pytest-8.2.2.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d5c1e26adc709112a3efed5015155216c79ff72c Binary files /dev/null and b/tests/test_controller/__pycache__/test_UserController.cpython-310-pytest-8.2.2.pyc differ diff --git a/tests/test_controller/test_UserController.py b/tests/test_controller/test_UserController.py new file mode 100644 index 0000000000000000000000000000000000000000..d8f43a2b642b27bacdc93d739311cb7c2ba54b35 --- /dev/null +++ b/tests/test_controller/test_UserController.py @@ -0,0 +1,648 @@ +import os +import sys +from unittest.mock import patch, Mock, MagicMock +from fastapi.testclient import TestClient +app_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..')) +sys.path.insert(0, app_path) +from controller import UserController +from response import ResponseDefault as res1 +client = TestClient(UserController.router) + +@patch('function.support_function.check_email_service') +@patch('function.support_function.check_email_empty_invalid', return_value = True) +@patch('service.UserService.check_email') +@patch('service.UserService.get_user1') +@patch('repository.UserInfoRepository.getUserInfo') +@patch('repository.UserInfoRepository.updateUserInfo') +@patch('repository.UserInfoRepository.addUserInfo') +@patch('service.UserService.update_info_user') +def test_update_user_info_success(mock_update_info_user, mock_add_user_info, mock_update_user_info, mock_get_user_info, mock_get_user, mock_check_email, mock_check1, mock_get_email_by_id): + mock_get_email_by_id.return_value = "old_email@example.com" + mock_get_user.return_value = Mock() # Simulate user exists + mock_get_user_info.return_value = Mock() + response = client.put("/update_user_info", json={"user_id":1, + "email": "new_email@example.com", + "uid":"uid123", + "display_name":"New Name", + "photo_url":"http://photo.url"}) + assert response.json()['status'] == 200 + assert response.json() == { + "status": 200, + "data": { + "message": "User info updated successfully", + } + + } +from response import ResponseUser as res +@patch('function.support_function.check_email_service') +@patch('function.support_function.check_email_empty_invalid',return_value = True) +@patch('repository.UserRepository.getEmailUserByIdFix') +def test_update_user_info_id_not_exist(mock_get_email_by_id,mock_check1,mock_check2): + mock_check2.return_value = res1.ReponseError(status=400, data=res.Message( + message="Id not exist")) + response = client.put("/update_user_info", json={"user_id":1, + "email": "new_email@example.com", + "uid":"uid123", + "display_name":"New Name", + "photo_url":"http://photo.url"}) + assert response.json()['status'] == 400 + assert response.json() == { + "status": 400, + "data": { + "message": "Id not exist", + } + + } + + +def test_update_user_info_email_empty(): + response = client.put("/update_user_info", json={"user_id":1, + "email": None, + "uid":"uid123", + "display_name":"New Name", + "photo_url":"http://photo.url"}) + assert response.json()['status'] == 400 + assert response.json() == { + "status": 400, + "data": { + "message": "email field is required.", + } + } + + +@patch('function.support_function.check_email_service', return_value = "20133118@gmail.com") +@patch('service.UserService.sf.check_email_empty_invalid') +def test_update_user_info_email_invalid(mock_check,mock_service): + mock_check.return_value = res.ReponseError(status=400, data=res.Message( + message="Email invalid")) + response = client.put("/update_user_info", json={"user_id":1, + "email": "20133", + "uid":"uid123", + "display_name":"New Name", + "photo_url":"http://photo.url"}) + assert response.json()['status'] == 400 + assert response.json() == { + "status": 400, + "data": { + "message": "Email invalid", + } + } + +@patch('function.support_function.check_email_service', return_value = "20133118@gmail.com") +@patch('service.UserService.sf.check_email_empty_invalid') +@patch('service.UserService.get_user1') +def test_update_user_info_email_or_password_error(mock_get_user, mock_check_email, mock_get_email_by_id): + mock_get_email_by_id.return_value = "old_email@example.com" + mock_check_email.return_value = True + mock_get_user.return_value = None + response = client.put("/update_user_info", json={"user_id":1, + "email": "nhuy@gmail.com", + "uid":"uid123", + "display_name":"New Name", + "photo_url":"http://photo.url"}) + assert response.json()['status'] == 404 + assert response.json() == { + "status": 404, + "data": { + "message": "Not found user", + } + } +@patch('function.support_function.check_email_service', return_value = "20133118@gmail.com") +@patch('service.UserService.check_email') +@patch('repository.UserInfoRepository.getUserInfo') +@patch('repository.UserRepository.getEmailUserByIdFix', return_value = "20133118@gmail.com") +def test_check_info_google_success(mock_check,mock_user_info_repo, mock_check_email,mock_user_repo_email): + mock_user_info_repo.return_value = Mock() + user_id = "1" + response = client.get("/check_info_google", params={"user_id": user_id}) + assert response.json()['status'] == 200 + assert response.json() == { + "status": 200, + "data": { + "check": True, + } + } + +@patch('function.support_function.check_email_service', return_value = res.ReponseError(status=400, data=res.Message( + message="Id not exist"))) + +@patch('repository.UserRepository.getEmailUserByIdFix', return_value = "20133118@gmail.com") +def test_check_info_google_id_not_exist(mock_check1,mock_user_repo): + user_id = "1" + response = client.get("/check_info_google", params={"user_id": user_id}) + assert response.json()['status'] == 400 + assert response.json() == { + "status": 400, + "data": { + "message": "Id not exist", + } + } + + +@patch('function.support_function.check_email_service', return_value=res.ReponseError(status=400, data=res.Message( + message="Email is empty"))) + +@patch('repository.UserRepository.getEmailUserByIdFix', return_value = "20133118@gmail.com") +def test_check_info_google_email_empty(mock_check1,mock_user_repo_id): + user_id = "1" + response = client.get("/check_info_google", params={"user_id": user_id}) + assert response.json()['status'] == 400 + assert response.json() == { + "status": 400, + "data": { + "message": "Email is empty", + } + } + +@patch('function.support_function.check_email_service', return_value = res.ReponseError(status=400, data=res.Message( + message="Email invalid"))) + +@patch('repository.UserRepository.getEmailUserByIdFix', return_value = "20133118@gmail.com") +def test_check_info_google_email_invalid(mock_check_1,mock_user_repo): + user_id = "1" + response = client.get("/check_info_google", params={"user_id": user_id}) + assert response.json()['status'] == 400 + assert response.json() == { + "status": 400, + "data": { + "message": "Email invalid", + } + } + + +@patch('service.UserService.sf.check_email_empty_invalid', return_value=True) +@patch('service.UserService.UserInfoRepository') +def test_check_info_google_by_email_success(mock_user_info_repo, mock_check_email): + email = "test@gmail.com" + mock_user_info_repo.getUserInfo.return_value = Mock() + response = client.get("/check_info_google_signup", params={"email": email}) + assert response.json()['status'] == 200 + assert response.json() == { + "status": 200, + "data": { + "check": True, + } + } + +def test_check_info_google_signup_email_empty(): + email = "" + response = client.get("/check_info_google_signup", params={"email": None}) + assert response.json()['status'] == 400 + assert response.json() == { + "status": 400, + "data": { + "message": "Email is required.", + } + } + +def test_check_info_google_signup_email_invalid(): + email ="quangphuc" + response = client.get("/check_info_google_signup", params={"email": email}) + assert response.json()['status'] == 400 + assert response.json() == { + "status": 400, + "data": { + "message": "Email invalid", + } + } +@patch('service.UserService.sf.check_email_service') +@patch('service.UserService.check_email') +@patch('service.UserService.get_user1') +@patch('repository.UserLoginRepository.getUserSessionIdByUserEmail') +def test_check_state_login_success(mock_user_login_repo,mock_get_user1,mock_check_email,mock_user_repo): + user_id = "1" + email ="test@gmail.com" + session_id = "session" + mock_user_repo.return_value = email + mock_check_email.return_value = True + mock_get_user1.return_value = Mock() + mock_user_login_repo.return_value = session_id + response = client.get("/check_state_login", params={"user_id": user_id,"session_id_now" :session_id}) + assert response.json()['status'] == 200 + assert response.json() == { + "status": 200, + "data": { + "check": True, + } + } + +@patch('service.UserService.sf.check_email_service') +def test_check_state_login_id_not_exits(mock_user_repo): + user_id = "1" + email ="test@gmail.com" + session_id = "session" + mock_user_repo.return_value = res1.ReponseError(status=400, data=res.Message( + message="Id not exist")) + response = client.get("/check_state_login", params={"user_id": user_id, + "session_id_now" :session_id}) + assert response.json()['status'] == 400 + assert response.json() == { + "status": 400, + "data": { + "message": "Id not exist", + } + } + +@patch('service.UserService.sf.check_email_service') +def test_check_state_login_email_empty(mock_user_repo): + user_id = "1" + email =None + session_id = "session" + mock_user_repo.return_value = res1.ReponseError(status=400, data=res.Message( + message="Email is empty")) + response = client.get("/check_state_login", params={"user_id": user_id, + "session_id_now" :session_id}) + assert response.json()['status'] == 400 + assert response.json() == { + "status": 400, + "data": { + "message": "Email is empty", + } + } + +@patch('service.UserService.sf.check_email_service') +@patch('service.UserService.check_email') +def test_check_state_login_email_invalid(mock_check_email,mock_user_repo): + user_id = "1" + email = "20133118" + session_id = "session" + mock_user_repo.return_value = res1.ReponseError(status=400, data=res.Message( + message="Email invalid")) + response = client.get("/check_state_login", params={"user_id": user_id, + "session_id_now" :session_id}) + assert response.json()['status'] == 400 + assert response.json() == { + "status": 400, + "data": { + "message": "Email invalid", + } + } + +@patch('service.UserService.sf.check_email_service') +@patch('service.UserService.check_email') +@patch('repository.UserLoginRepository.getUserSessionIdByUserEmail') +def test_check_state_session_empty(mock_user_login_repo,mock_check_email, mock_user_repo): + user_id = "1" + email = "20133@gmail.com" + session_id = None + + mock_user_repo.return_value = email + mock_user_login_repo.return_value = "some_session_id" + + response = client.get("/check_state_login", params={"user_id": user_id, + "session_id_now": session_id}) + + assert response.json()['status'] == 400 + assert response.json() == { + "status": 400, + "data": { + "message": "Session Id is required.", + } + } + +@patch('service.UserService.sf.check_email_service') +@patch('service.UserService.check_email') +@patch('service.UserService.get_user1') +@patch('repository.UserLoginRepository.getUserSessionIdByUserEmail') +def test_check_state_login_not_found(mock_user_login_repo,mock_get_user1,mock_check_email,mock_user_repo): + user_id = "1" + email ="test@gmail.com" + session_id = "session" + mock_user_repo.return_value = email + mock_check_email.return_value = True + mock_get_user1.return_value = None + mock_user_login_repo.return_value = session_id + response = client.get("/check_state_login", params={"user_id": user_id, + "session_id_now" : session_id}) + assert response.json()['status'] == 404 + assert response.json() == { + "status": 404, + "data": { + "message": "Not found user", + } + } + + + +@patch('service.UserService.sf.check_email_service',return_value= "test@example.com") +@patch('service.UserService.sf.check_email_empty_invalid', return_value=True) +@patch('service.UserService.sign_in_with_email_and_password') +@patch('service.UserService.auth') +def test_change_password_success(mock_auth, mock_sign_in, mock_check_email, mock_get_email): + user_id='123' + new_password='new_password' + current_password='current_password' + confirm_new_password = 'new_password' + mock_sign_in.return_value = MagicMock() + mock_auth.get_user_by_email.return_value = MagicMock(uid='user_uid') + response = client.put("/change_password", json={"user_id": user_id, + "new_password" : new_password, + "current_password": current_password, + "confirm_new_password": confirm_new_password}) + assert response.json()['status'] == 200 + assert response.json()['data']['message'] == "Update password success" + +@patch('service.UserService.sf.check_email_service', return_value=res1.ReponseError(status=400, data=res.Message( + message="Id not exist"))) +def test_change_password_id_not_exist(mock_get_email): + user_id='123' + new_password='new_password' + current_password='current_password' + confirm_new_password = 'new_password' + response = client.put("/change_password", json={"user_id": user_id, + "new_password": new_password, + "current_password": current_password, + "confirm_new_password": confirm_new_password}) + assert response.json()['status'] == 400 + assert response.json()['data']['message'] == "Id not exist" + +@patch('service.UserService.sf.check_email_service', return_value=res1.ReponseError(status=400, data=res.Message( + message="Email is empty"))) +def test_change_password_email_is_empty(mock_get_email): + user_id='123' + new_password='new_password' + current_password='current_password' + confirm_new_password = 'new_password' + response = client.put("/change_password", json={"user_id": user_id, + "new_password": new_password, + "current_password": current_password, + "confirm_new_password": confirm_new_password}) + assert response.json()['status'] == 400 + assert response.json()['data']['message'] == "Email is empty" + +@patch('service.UserService.sf.check_email_service', return_value=res1.ReponseError(status=400, data=res.Message( + message="Email invalid"))) +def test_change_password_email_invalid(mock_check_email): + user_id='123' + new_password='new_password' + current_password='current_password' + confirm_new_password = 'new_password' + response = client.put("/change_password", json={"user_id": user_id, + "new_password" : new_password, + "current_password": current_password, + "confirm_new_password": confirm_new_password}) + assert response.json()['status'] == 400 + assert response.json()['data']['message'] == "Email invalid" + +@patch('service.UserService.sf.check_email_service') +def test_change_password_new_password_empty( mock_get_email): + user_id='123' + new_password= None + current_password='current_password' + mock_get_email.return_value = "20133@gmail.com" + confirm_new_password = 'new_password' + response = client.put("/change_password", json={"user_id": user_id, + "new_password": new_password, + "current_password": current_password, + "confirm_new_password": confirm_new_password}) + assert response.json()['status'] == 400 + assert response.json()['data']['message'] == "New password field is required." + +@patch('service.UserService.sf.check_email_service') +def test_change_password_current_password_empty(mock_get_email): + user_id='123' + new_password= "new" + current_password= None + mock_get_email.return_value = "20133@gmail.com" + confirm_new_password = 'new_password' + response = client.put("/change_password", json={"user_id": user_id, + "new_password": new_password, + "current_password": current_password, + "confirm_new_password": confirm_new_password}) + assert response.json()['status'] == 400 + assert response.json()['data']['message'] == "Current password field is required." + +@patch('service.UserService.check_email') +@patch('service.UserService.get_user1') +@patch('service.UserService.createOTPReset') +@patch('service.UserService.sf.check_email_empty_invalid', return_value=True) +def test_reset_password_success(mock_check,mock_createOTPReset, mock_get_user1, mock_check_email): + email = "user@example.com" + mock_get_user1.return_value = {"email": "user@example.com"} + mock_createOTPReset.return_value = "123456" + response = client.post("/reset_password", json={"email": email}) + assert response.json()['status'] == 200 + assert response.json()['data']['check'] == True + assert response.json()['otp'] == "123456" + +def test_reset_password_invalid_email(): + email = "invalid" + response = client.post("/reset_password", json={"email": email}) + assert response.json()['status'] == 400 + assert response.json()['data']['message'] == "Email invalid" + +def test_reset_password_user_not_found(): + email = "nonexistent@example.com" + response = client.post("/reset_password", json={"email": email}) + assert response.json()['status'] == 404 + assert response.json()['data']['message'] == "Email not exist" + +def test_reset_password_email_is_None(): + email = None + response = client.post("/reset_password", json={"email": email}) + assert response.json()['status'] == 400 + assert response.json()['data']['message'] == "Email is required." + + + +def test_update_user_info_user_id_required(): + email = None + response = client.put("/update_user_info", json={"user_id": None, + "email": "new_email@example.com", + "uid": "uid123", + "display_name": "New Name", + "photo_url": "http://photo.url"}) + assert response.json()['status'] == 400 + assert response.json()['data']['message'] == "user_id field is required." + +def test_update_user_info_user_id_integer_required(): + response = client.put("/update_user_info", json={"user_id": "aaaa", + "email": "new_email@example.com", + "uid": "uid123", + "display_name": "New Name", + "photo_url": "http://photo.url"}) + assert response.json()['status'] == 400 + assert response.json()['data']['message'] == "user_id must be an integer" + +def test_update_user_info_user_id_greater_than_0(): + response = client.put("/update_user_info", json={"user_id": 0, + "email": "new_email@example.com", + "uid": "uid123", + "display_name": "New Name", + "photo_url": "http://photo.url"}) + assert response.json()['status'] == 400 + assert response.json()['data']['message'] == "user_id must be greater than 0" + +def test_update_user_info_uid_field_required(): + response = client.put("/update_user_info", json={"user_id": 1, + "email": "new_email@example.com", + "uid": "", + "display_name": "New Name", + "photo_url": "http://photo.url"}) + assert response.json()['status'] == 400 + assert response.json()['data']['message'] == "uid field is required." + +def test_update_user_info_email_field_required(): + response = client.put("/update_user_info", json={"user_id": 1, + "email": None, + "uid": "aaaa", + "display_name": "New Name", + "photo_url": "http://photo.url"}) + assert response.json()['status'] == 400 + assert response.json()['data']['message'] == "email field is required." + +def test_update_user_info_dis_play_name_field_required(): + response = client.put("/update_user_info", json={"user_id": 1, + "email": "test@gmail.com", + "uid": "aaaa", + "display_name": "", + "photo_url": "http://photo.url"}) + assert response.json()['status'] == 400 + assert response.json()['data']['message'] == "display_name field is required." + +def test_update_user_info_photo_url_field_required(): + response = client.put("/update_user_info", json={"user_id": 1, + "email": "test@gmail.com", + "uid": "aaaa", + "display_name": "aaaa", + "photo_url": ""}) + assert response.json()['status'] == 400 + assert response.json()['data']['message'] == "photo_url field is required." + +def test_check_info_google_user_id_required(): + user_id = None + response = client.get("/check_info_google",params={"user_id": user_id}) + assert response.json()['status'] == 400 + assert response.json()['data']['message'] == "user_id field is required." + +def test_check_info_google_user_id_must_integer(): + user_id = "aaaa" + response = client.get("/check_info_google",params={"user_id": user_id}) + assert response.json()['status'] == 400 + assert response.json()['data']['message'] == "user_id must be an integer" + +def test_check_info_google_user_id_must_integer_greater_than_0(): + user_id = "0" + response = client.get("/check_info_google",params={"user_id": user_id}) + assert response.json()['status'] == 400 + assert response.json()['data']['message'] == "user_id must be greater than 0" + +def test_check_info_google_sign_up_email_is_required(): + email = None + response = client.get("/check_info_google_signup", params={"email": email}) + assert response.json()['status'] == 400 + assert response.json()['data']['message'] == "Email is required." + +def test_check_info_google_sign_up_email_must_str(): + email = "777" + response = client.get("/check_info_google_signup", params={"email": email}) + assert response.json()['status'] == 400 + assert response.json()['data']['message'] == "Email must be a string, not a number." + +def test_check_state_login_user_id_required(): + user_id = None + session_id_now = "abcde" + response = client.get("/check_state_login", params={"user_id": user_id,"session_id_now":session_id_now}) + assert response.json()['status'] == 400 + assert response.json()['data']['message'] == "user_id field is required." + +def test_check_state_login_user_id_must_integer(): + user_id = "aaaa" + session_id_now = "abcde" + response = client.get("/check_state_login", params={"user_id": user_id, "session_id_now": session_id_now}) + assert response.json()['status'] == 400 + assert response.json()['data']['message'] == "user_id must be an integer" + +def test_check_state_login_user_id_must_integer_greater_than_0(): + user_id = "0" + session_id_now = "abcde" + response = client.get("/check_state_login", params={"user_id": user_id, "session_id_now": session_id_now}) + assert response.json()['status'] == 400 + assert response.json()['data']['message'] == "user_id must be greater than 0" + +def test_check_state_login_session_id_required(): + user_id = 1 + session_id_now = None + response = client.get("/check_state_login", params={"user_id": user_id,"session_id_now":session_id_now}) + assert response.json()['status'] == 400 + assert response.json()['data']['message'] == "Session Id is required." + +def test_check_state_login_session_id_must_str(): + user_id = 1 + session_id_now = "134" + response = client.get("/check_state_login", params={"user_id": user_id, "session_id_now": session_id_now}) + assert response.json()['status'] == 400 + assert response.json()['data']['message'] == "Session Id must be a string, not a number." + + +def test_reset_email_required(): + email = None + response = client.post("/reset_password", json={"email": email}) + assert response.json()['status'] == 400 + assert response.json()['data']['message'] == "Email is required." + +def test_reset_email_must_str(): + email = "20133" + response = client.post("/reset_password", json={"email": email }) + assert response.json()['status'] == 400 + assert response.json()['data']['message'] == "Email must be a string, not a number." + +def test_change_password_user_id_required(): + user_id = None + new_password = "ABC" + current_password = "abc" + response = client.put("/change_password", json={"user_id": user_id, + "new_password": new_password, + "current_password": current_password}) + assert response.json()['status'] == 400 + assert response.json()['data']['message'] == "user_id field is required." + +def test_change_password_user_id_integer(): + user_id = "aaa" + new_password = "ABC" + current_password = "abc" + response = client.put("/change_password", json={"user_id": user_id, + "new_password": new_password, + "current_password": current_password}) + assert response.json()['status'] == 400 + assert response.json()['data']['message'] == "user_id must be an integer" + +def test_change_password_user_id_integer_greater_than_0(): + user_id = "0" + new_password = "ABC" + current_password = "abc" + confirm_password = "abc" + response = client.put("/change_password", json={"user_id": user_id, + "new_password": new_password, + "current_password": current_password, + "confirm_new_password": confirm_password}) + assert response.json()['status'] == 400 + assert response.json()['data']['message'] == "user_id must be greater than 0" + +def test_change_password_new_password_required(): + user_id = "1" + new_password = None + current_password = "abc" + confirm_password = "abc" + response = client.put("/change_password", json={"user_id": user_id, + "new_password": new_password, + "current_password": current_password, + "confirm_new_password": confirm_password}) + assert response.json()['status'] == 400 + assert response.json()['data']['message'] == "New password field is required." + +def test_change_password_current_password_required(): + user_id = "1" + new_password = "abc" + current_password = None + confirm_password = "abc" + response = client.put("/change_password", json={"user_id": user_id, + "new_password": new_password, + "current_password": current_password, + "confirm_new_password": confirm_password}) + assert response.json()['status'] == 400 + assert response.json()['data']['message'] == "Current password field is required." + + + + diff --git a/tests/test_controller/user_file/quangphuc@gmail.com/demo1.pdf b/tests/test_controller/user_file/quangphuc@gmail.com/demo1.pdf new file mode 100644 index 0000000000000000000000000000000000000000..43597a9147dba9bf9befd7886997e1ceb1413702 --- /dev/null +++ b/tests/test_controller/user_file/quangphuc@gmail.com/demo1.pdf @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:367daadbb1bb652bda103a21a632b36a2821348931c3c11b37fa315c9843af4a +size 7289174 diff --git a/tests/test_service/.pytest_cache/.gitignore b/tests/test_service/.pytest_cache/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..08a7f458f1f002823bc794c47ca1996a57e72c86 --- /dev/null +++ b/tests/test_service/.pytest_cache/.gitignore @@ -0,0 +1,2 @@ +# Created by pytest automatically. +* diff --git a/tests/test_service/.pytest_cache/CACHEDIR.TAG b/tests/test_service/.pytest_cache/CACHEDIR.TAG new file mode 100644 index 0000000000000000000000000000000000000000..fce15ad7eaa74e5682b644c84efb75334c112f95 --- /dev/null +++ b/tests/test_service/.pytest_cache/CACHEDIR.TAG @@ -0,0 +1,4 @@ +Signature: 8a477f597d28d172789f06886806bc55 +# This file is a cache directory tag created by pytest. +# For information about cache directory tags, see: +# https://bford.info/cachedir/spec.html diff --git a/tests/test_service/.pytest_cache/README.md b/tests/test_service/.pytest_cache/README.md new file mode 100644 index 0000000000000000000000000000000000000000..c7526af2448672de4537dfed042ed74daadb17bf --- /dev/null +++ b/tests/test_service/.pytest_cache/README.md @@ -0,0 +1,8 @@ +# pytest cache directory # + +This directory contains data from the pytest's cache plugin, +which provides the `--lf` and `--ff` options, as well as the `cache` fixture. + +**Do not** commit this to version control. + +See [the docs](https://docs.pytest.org/en/stable/how-to/cache.html) for more information. diff --git a/tests/test_service/.pytest_cache/v/cache/lastfailed b/tests/test_service/.pytest_cache/v/cache/lastfailed new file mode 100644 index 0000000000000000000000000000000000000000..3cc1a01fa04db0a8ecaed4eca0665a7a332eb9e6 --- /dev/null +++ b/tests/test_service/.pytest_cache/v/cache/lastfailed @@ -0,0 +1,33 @@ +{ + "test_MySQLService.py::TestLoadChatHistory::test_load_chat_history_user_id_str": true, + "test_DefaultService.py::TestCreateFireBaseUser::test_non_token_google_empty": true, + "test_LoginService.py::TestLoginFunction::test_login_email_empty": true, + "test_LoginService.py::TestLoginFunction::test_login_email_invalid": true, + "test_LoginService.py::TestLoginFunction::test_login_email_not_exists": true, + "test_LoginService.py::TestLoginFunction::test_login_email_or_password_error": true, + "test_LoginService.py::TestLoginFunction::test_login_invalid_authorization_code": true, + "test_LoginService.py::TestLoginFunction::test_login_password_empty": true, + "test_LoginService.py::TestLoginFunction::test_login_server_error": true, + "test_LoginService.py::TestLoginFunction::test_login_success": true, + "test_LoginService.py::TestLoginGoogle::test_login_email_invalid": true, + "test_LoginService.py::TestLoginGoogle::test_login_google_email_empty": true, + "test_LoginService.py::TestLoginGoogle::test_login_google_email_not_exists": true, + "test_LoginService.py::TestLoginGoogle::test_login_google_server_error": true, + "test_LoginService.py::TestLoginGoogle::test_login_google_success": true, + "test_LoginService.py::TestSignUpFunction::test_sign_up_confirm_password_do_not_match_password": true, + "test_LoginService.py::TestSignUpFunction::test_sign_up_confirm_password_empty": true, + "test_LoginService.py::TestSignUpFunction::test_sign_up_email_exist": true, + "test_LoginService.py::TestSignUpFunction::test_sign_up_email_invalid": true, + "test_LoginService.py::TestSignUpFunction::test_sign_up_email_is_empty": true, + "test_LoginService.py::TestSignUpFunction::test_sign_up_error": true, + "test_LoginService.py::TestSignUpFunction::test_sign_up_password_empty": true, + "test_LoginService.py::TestSignUpFunction::test_sign_up_server_error": true, + "test_LoginService.py::TestSignUpFunction::test_sign_up_success": true, + "test_LoginService.py::TestRefreshToken::test_refresh_token_email_empty": true, + "test_LoginService.py::TestRefreshToken::test_refresh_token_email_invalid": true, + "test_LoginService.py::TestRefreshToken::test_refresh_token_refresh_token_error": true, + "test_LoginService.py::TestRefreshToken::test_refresh_token_server_error": true, + "test_LoginService.py::TestRefreshToken::test_refresh_token_success": true, + "test_LoginService.py::TestRefreshToken::test_refresh_token_token_empty": true, + "test_LoginService.py::TestRefreshToken::test_refresh_token_user_id_not_exist": true +} \ No newline at end of file diff --git a/tests/test_service/.pytest_cache/v/cache/nodeids b/tests/test_service/.pytest_cache/v/cache/nodeids new file mode 100644 index 0000000000000000000000000000000000000000..2dd3754cdb811e4e0c398a78152fc5d96852a65b --- /dev/null +++ b/tests/test_service/.pytest_cache/v/cache/nodeids @@ -0,0 +1,213 @@ +[ + "test_ChatService.py::TestDeleteChat::test_delete_chat_chat_name_empty", + "test_ChatService.py::TestDeleteChat::test_delete_chat_failed", + "test_ChatService.py::TestDeleteChat::test_delete_chat_id_not_exist", + "test_ChatService.py::TestDeleteChat::test_delete_chat_server_err", + "test_ChatService.py::TestDeleteChat::test_delete_chat_success", + "test_ChatService.py::TestExtractFile::test_extract_file_email_empty", + "test_ChatService.py::TestExtractFile::test_extract_file_email_in_valid", + "test_ChatService.py::TestExtractFile::test_extract_file_id_not_exist", + "test_ChatService.py::TestExtractFile::test_extract_file_no_data", + "test_ChatService.py::TestExtractFile::test_extract_file_server_error_sf", + "test_ChatService.py::TestExtractFile::test_extract_file_server_user_repo", + "test_ChatService.py::TestExtractFile::test_extract_file_success", + "test_ChatService.py::TestGenerateQuestion::test_generate_question_email_empty", + "test_ChatService.py::TestGenerateQuestion::test_generate_question_email_in_valid", + "test_ChatService.py::TestGenerateQuestion::test_generate_question_id_not_exist", + "test_ChatService.py::TestGenerateQuestion::test_generate_question_no_data", + "test_ChatService.py::TestGenerateQuestion::test_generate_question_server_err_sf", + "test_ChatService.py::TestGenerateQuestion::test_generate_question_server_err_user_repo", + "test_ChatService.py::TestGenerateQuestion::test_generate_question_success", + "test_ChatService.py::TestQuery2Upgrade::test_query2_upgrade_chat_history_empty", + "test_ChatService.py::TestQuery2Upgrade::test_query2_upgrade_email_empty", + "test_ChatService.py::TestQuery2Upgrade::test_query2_upgrade_id_not_exist", + "test_ChatService.py::TestQuery2Upgrade::test_query2_upgrade_no_answer", + "test_ChatService.py::TestQuery2Upgrade::test_query2_upgrade_question_empty", + "test_ChatService.py::TestQuery2Upgrade::test_query2_upgrade_server_error_function_chatbot_err", + "test_ChatService.py::TestQuery2Upgrade::test_query2_upgrade_server_error_user_repo_err", + "test_ChatService.py::TestQuery2Upgrade::test_query2_upgrade_success", + "test_ChatService.py::TestQuery2UpgradeOld::test_query2_upgrade_old_chat_empty", + "test_ChatService.py::TestQuery2UpgradeOld::test_query2_upgrade_old_email_empty", + "test_ChatService.py::TestQuery2UpgradeOld::test_query2_upgrade_old_email_in_valid", + "test_ChatService.py::TestQuery2UpgradeOld::test_query2_upgrade_old_id_not_exist", + "test_ChatService.py::TestQuery2UpgradeOld::test_query2_upgrade_old_no_answer", + "test_ChatService.py::TestQuery2UpgradeOld::test_query2_upgrade_old_question_empty", + "test_ChatService.py::TestQuery2UpgradeOld::test_query2_upgrade_old_server_error_chathistory_repo", + "test_ChatService.py::TestQuery2UpgradeOld::test_query2_upgrade_old_server_error_detailchat_repo", + "test_ChatService.py::TestQuery2UpgradeOld::test_query2_upgrade_old_server_error_function_repo", + "test_ChatService.py::TestQuery2UpgradeOld::test_query2_upgrade_old_server_error_user_repo", + "test_ChatService.py::TestQuery2UpgradeOld::test_query2_upgrade_old_success", + "test_DefaultService.py::TestCreateFireBaseUser::test_email_none", + "test_DefaultService.py::TestCreateFireBaseUser::test_existing_user", + "test_DefaultService.py::TestCreateFireBaseUser::test_invalid_email", + "test_DefaultService.py::TestCreateFireBaseUser::test_non_existing_user", + "test_DefaultService.py::TestCreateFireBaseUser::test_non_token_google_empty", + "test_DefaultService.py::TestCreateFireBaseUser::test_oauth2_failed", + "test_DefaultService.py::TestCreateFireBaseUser::test_server_error", + "test_DefaultService.py::TestCreateFireBaseUser::test_token_google_empty", + "test_DefaultService.py::TestInfoUser::test_email_is_none", + "test_DefaultService.py::TestInfoUser::test_id_not_exist", + "test_DefaultService.py::TestInfoUser::test_invalid_email", + "test_DefaultService.py::TestInfoUser::test_server_error", + "test_DefaultService.py::TestInfoUser::test_successful_user_retrieval", + "test_DefaultService.py::TestInfoUser::test_user_not_found", + "test_DefaultService.py::TestIsMe::test_invalid_token", + "test_DefaultService.py::TestIsMe::test_none_token", + "test_DefaultService.py::TestIsMe::test_server_error", + "test_DefaultService.py::TestIsMe::test_valid_token", + "test_DefaultService.py::TestUpLoadFile::test_upload_image_email_empty", + "test_DefaultService.py::TestUpLoadFile::test_upload_image_email_invalid", + "test_DefaultService.py::TestUpLoadFile::test_upload_image_id_not_exist", + "test_DefaultService.py::TestUpLoadFile::test_upload_image_invalid_filetype", + "test_DefaultService.py::TestUpLoadFile::test_upload_image_server_err", + "test_DefaultService.py::TestUpLoadFile::test_upload_image_success", + "test_FileService.py::TestDeleteAllFile::test_delete_all_file_email_empty", + "test_FileService.py::TestDeleteAllFile::test_delete_all_file_email_invalid", + "test_FileService.py::TestDeleteAllFile::test_delete_all_file_id_not_exist", + "test_FileService.py::TestDeleteAllFile::test_delete_all_file_server_err", + "test_FileService.py::TestDeleteAllFile::test_delete_all_file_success", + "test_FileService.py::TestDeleteFile::test_delete_file_email_empty", + "test_FileService.py::TestDeleteFile::test_delete_file_email_invalid", + "test_FileService.py::TestDeleteFile::test_delete_file_id_not_exist", + "test_FileService.py::TestDeleteFile::test_delete_file_namefile_empty", + "test_FileService.py::TestDeleteFile::test_delete_file_server_error", + "test_FileService.py::TestDeleteFile::test_delete_file_success", + "test_FileService.py::TestDownLoadFile::test_download_file_email_empty", + "test_FileService.py::TestDownLoadFile::test_download_file_email_invalid", + "test_FileService.py::TestDownLoadFile::test_download_file_id_not_exist", + "test_FileService.py::TestDownLoadFile::test_download_file_name_file_empty", + "test_FileService.py::TestDownLoadFile::test_download_file_server_error", + "test_FileService.py::TestDownLoadFile::test_download_file_success", + "test_FileService.py::TestDownLoadFolder::test_download_folder_email_empty", + "test_FileService.py::TestDownLoadFolder::test_download_folder_email_invalid", + "test_FileService.py::TestDownLoadFolder::test_download_folder_id_not_exist", + "test_FileService.py::TestDownLoadFolder::test_download_folder_server_error", + "test_FileService.py::TestDownLoadFolder::test_download_folder_success", + "test_FileService.py::TestFileService::test_upload_files_empty_email", + "test_FileService.py::TestFileService::test_upload_files_error_handling", + "test_FileService.py::TestFileService::test_upload_files_id_not_exist", + "test_FileService.py::TestFileService::test_upload_files_invalid_email", + "test_FileService.py::TestFileService::test_upload_files_invalid_file_type", + "test_FileService.py::TestFileService::test_upload_files_success", + "test_FileService.py::TestListNameFiles::test_listNameFiles_server_error", + "test_FileService.py::TestListNameFiles::test_list_name_file_success", + "test_FileService.py::TestListNameFiles::test_list_name_files_email_empty", + "test_FileService.py::TestListNameFiles::test_list_name_files_email_invalid", + "test_FileService.py::TestListNameFiles::test_list_name_files_id_not_exist", + "test_FileService.py::TestUploadFileService::test_upload_files_empty_email", + "test_FileService.py::TestUploadFileService::test_upload_files_error_handling", + "test_FileService.py::TestUploadFileService::test_upload_files_id_not_exist", + "test_FileService.py::TestUploadFileService::test_upload_files_invalid_email", + "test_FileService.py::TestUploadFileService::test_upload_files_invalid_file_type", + "test_FileService.py::TestUploadFileService::test_upload_files_success", + "test_LoginService.py::TestChangePassword::test_change_password_confirm_new_password_do_not_match_new_password", + "test_LoginService.py::TestChangePassword::test_change_password_confirm_new_password_empty", + "test_LoginService.py::TestChangePassword::test_change_password_current_password_empty", + "test_LoginService.py::TestChangePassword::test_change_password_current_password_not_valid", + "test_LoginService.py::TestChangePassword::test_change_password_email_invalid", + "test_LoginService.py::TestChangePassword::test_change_password_email_is_empty", + "test_LoginService.py::TestChangePassword::test_change_password_id_not_exist", + "test_LoginService.py::TestChangePassword::test_change_password_new_password_empty", + "test_LoginService.py::TestChangePassword::test_change_password_server_error", + "test_LoginService.py::TestChangePassword::test_change_password_success", + "test_LoginService.py::TestCheckInfoGoogle::test_check_info_google_email_empty", + "test_LoginService.py::TestCheckInfoGoogle::test_check_info_google_email_invalid", + "test_LoginService.py::TestCheckInfoGoogle::test_check_info_google_id_not_exist", + "test_LoginService.py::TestCheckInfoGoogle::test_check_info_google_server_error", + "test_LoginService.py::TestCheckInfoGoogle::test_check_info_google_success", + "test_LoginService.py::TestCheckInfoGoogleEmail::test_check_info_google_by_email_email_empty", + "test_LoginService.py::TestCheckInfoGoogleEmail::test_check_info_google_email_invalid", + "test_LoginService.py::TestCheckInfoGoogleEmail::test_check_info_google_email_server_error", + "test_LoginService.py::TestCheckInfoGoogleEmail::test_check_info_google_email_success", + "test_LoginService.py::TestCheckStateLogin::test_check_state_login_email_empty", + "test_LoginService.py::TestCheckStateLogin::test_check_state_login_email_invalid", + "test_LoginService.py::TestCheckStateLogin::test_check_state_login_id_not_exits", + "test_LoginService.py::TestCheckStateLogin::test_check_state_login_not_found", + "test_LoginService.py::TestCheckStateLogin::test_check_state_login_server_error", + "test_LoginService.py::TestCheckStateLogin::test_check_state_login_success", + "test_LoginService.py::TestCheckStateLogin::test_check_state_session_empty", + "test_LoginService.py::TestLoginFunction::test_login_email_empty", + "test_LoginService.py::TestLoginFunction::test_login_email_invalid", + "test_LoginService.py::TestLoginFunction::test_login_email_not_exists", + "test_LoginService.py::TestLoginFunction::test_login_email_or_password_error", + "test_LoginService.py::TestLoginFunction::test_login_invalid_authorization_code", + "test_LoginService.py::TestLoginFunction::test_login_password_empty", + "test_LoginService.py::TestLoginFunction::test_login_server_error", + "test_LoginService.py::TestLoginFunction::test_login_success", + "test_LoginService.py::TestLoginGoogle::test_login_email_invalid", + "test_LoginService.py::TestLoginGoogle::test_login_google_email_empty", + "test_LoginService.py::TestLoginGoogle::test_login_google_email_not_exists", + "test_LoginService.py::TestLoginGoogle::test_login_google_server_error", + "test_LoginService.py::TestLoginGoogle::test_login_google_success", + "test_LoginService.py::TestLoginGoogle::test_login_invalid_authorization_code", + "test_LoginService.py::TestRefreshToken::test_refresh_token_email_empty", + "test_LoginService.py::TestRefreshToken::test_refresh_token_email_invalid", + "test_LoginService.py::TestRefreshToken::test_refresh_token_refresh_token_error", + "test_LoginService.py::TestRefreshToken::test_refresh_token_server_error", + "test_LoginService.py::TestRefreshToken::test_refresh_token_success", + "test_LoginService.py::TestRefreshToken::test_refresh_token_token_empty", + "test_LoginService.py::TestRefreshToken::test_refresh_token_user_id_not_exist", + "test_LoginService.py::TestResetPassword::test_reset_password_invalid_email", + "test_LoginService.py::TestResetPassword::test_reset_password_server_error", + "test_LoginService.py::TestResetPassword::test_reset_password_success", + "test_LoginService.py::TestResetPassword::test_reset_password_user_not_found", + "test_LoginService.py::TestSignUpFunction::test_sign_up_confirm_password_do_not_match_password", + "test_LoginService.py::TestSignUpFunction::test_sign_up_confirm_password_empty", + "test_LoginService.py::TestSignUpFunction::test_sign_up_email_exist", + "test_LoginService.py::TestSignUpFunction::test_sign_up_email_invalid", + "test_LoginService.py::TestSignUpFunction::test_sign_up_email_is_empty", + "test_LoginService.py::TestSignUpFunction::test_sign_up_error", + "test_LoginService.py::TestSignUpFunction::test_sign_up_password_empty", + "test_LoginService.py::TestSignUpFunction::test_sign_up_server_error", + "test_LoginService.py::TestSignUpFunction::test_sign_up_success", + "test_LoginService.py::TestUpdateUserInfoFunction::test_update_user_info_email_empty", + "test_LoginService.py::TestUpdateUserInfoFunction::test_update_user_info_email_invalid", + "test_LoginService.py::TestUpdateUserInfoFunction::test_update_user_info_email_or_password_error", + "test_LoginService.py::TestUpdateUserInfoFunction::test_update_user_info_id_not_exist", + "test_LoginService.py::TestUpdateUserInfoFunction::test_update_user_info_server_error", + "test_LoginService.py::TestUpdateUserInfoFunction::test_update_user_info_success_existing_user", + "test_LoginService.py::TestUpdateUserInfoFunction::test_update_user_info_success_new_user_info", + "test_MySQLService.py::TestDeleteChat::test_delete_chat_chatname_empty", + "test_MySQLService.py::TestDeleteChat::test_delete_chat_email_empty", + "test_MySQLService.py::TestDeleteChat::test_delete_chat_email_invalid", + "test_MySQLService.py::TestDeleteChat::test_delete_chat_error_1", + "test_MySQLService.py::TestDeleteChat::test_delete_chat_id_not_exist", + "test_MySQLService.py::TestDeleteChat::test_delete_chat_server_error", + "test_MySQLService.py::TestDeleteChat::test_delete_chat_success", + "test_MySQLService.py::TestLoadChatHistory::test_load_chat_history_error", + "test_MySQLService.py::TestLoadChatHistory::test_load_chat_history_not_found_chat", + "test_MySQLService.py::TestLoadChatHistory::test_load_chat_history_server_err", + "test_MySQLService.py::TestLoadChatHistory::test_load_chat_history_success", + "test_MySQLService.py::TestLoadChatHistory::test_load_chat_history_user_id_str", + "test_MySQLService.py::TestMySQLService::test_edit_chat_email_empty", + "test_MySQLService.py::TestMySQLService::test_edit_chat_email_in_valid", + "test_MySQLService.py::TestMySQLService::test_edit_chat_id_not_exist", + "test_MySQLService.py::TestMySQLService::test_edit_chat_name_new_empty", + "test_MySQLService.py::TestMySQLService::test_edit_chat_name_old_empty", + "test_MySQLService.py::TestMySQLService::test_edit_chat_server_error", + "test_MySQLService.py::TestMySQLService::test_edit_chat_success", + "test_MySQLService.py::TestMySQLService::test_edit_chat_update_error", + "test_MySQLService.py::TestRenderChatHistory::test_render_chat_history_id_not_exist", + "test_MySQLService.py::TestRenderChatHistory::test_render_chat_history_server_err", + "test_MySQLService.py::TestRenderChatHistory::test_render_chat_history_success", + "test_OTPService.py::TestCreateOTPFunctions::test_createOTP_failed_empty_email", + "test_OTPService.py::TestCreateOTPFunctions::test_createOTP_failed_empty_invalid", + "test_OTPService.py::TestCreateOTPFunctions::test_createOTP_success", + "test_OTPService.py::TestCreateOTPReset::test_createOTPReset_email_empty", + "test_OTPService.py::TestCreateOTPReset::test_createOTPReset_email_invalid", + "test_OTPService.py::TestCreateOTPReset::test_createOTPReset_success", + "test_OTPService.py::TestVerifyOTPFunctions::test_verifyOTP_failed_empty_email", + "test_OTPService.py::TestVerifyOTPFunctions::test_verifyOTP_failed_empty_otp", + "test_OTPService.py::TestVerifyOTPFunctions::test_verifyOTP_failed_invalid_email", + "test_OTPService.py::TestVerifyOTPFunctions::test_verifyOTP_failed_invalid_otp", + "test_OTPService.py::TestVerifyOTPFunctions::test_verifyOTP_failed_no_otp_found", + "test_OTPService.py::TestVerifyOTPFunctions::test_verifyOTP_has_expired", + "test_OTPService.py::TestVerifyOTPFunctions::test_verifyOTP_success", + "test_OTPService.py::TestVerifyOTPReset::test_verifyOTPReset_failed_empty_email", + "test_OTPService.py::TestVerifyOTPReset::test_verifyOTPReset_failed_empty_otp", + "test_OTPService.py::TestVerifyOTPReset::test_verifyOTPReset_failed_invalid_email", + "test_OTPService.py::TestVerifyOTPReset::test_verifyOTPReset_failed_invalid_otp", + "test_OTPService.py::TestVerifyOTPReset::test_verifyOTPReset_failed_no_otp_found", + "test_OTPService.py::TestVerifyOTPReset::test_verifyOTPReset_has_expired", + "test_OTPService.py::TestVerifyOTPReset::test_verifyOTPReset_success" +] \ No newline at end of file diff --git a/tests/test_service/.pytest_cache/v/cache/stepwise b/tests/test_service/.pytest_cache/v/cache/stepwise new file mode 100644 index 0000000000000000000000000000000000000000..0637a088a01e8ddab3bf3fa98dbe804cbde1a0dc --- /dev/null +++ b/tests/test_service/.pytest_cache/v/cache/stepwise @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/tests/test_service/__pycache__/test_ChatService.cpython-310-pytest-8.2.2.pyc b/tests/test_service/__pycache__/test_ChatService.cpython-310-pytest-8.2.2.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2de5e80307e162dce4a38bc66b0623821e39fbf8 Binary files /dev/null and b/tests/test_service/__pycache__/test_ChatService.cpython-310-pytest-8.2.2.pyc differ diff --git a/tests/test_service/__pycache__/test_ChatService.cpython-311-pytest-8.2.2.pyc b/tests/test_service/__pycache__/test_ChatService.cpython-311-pytest-8.2.2.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9419c73374b37babdfe6f7edb53ed06733eb1858 Binary files /dev/null and b/tests/test_service/__pycache__/test_ChatService.cpython-311-pytest-8.2.2.pyc differ diff --git a/tests/test_service/__pycache__/test_DefaultService.cpython-310-pytest-8.2.2.pyc b/tests/test_service/__pycache__/test_DefaultService.cpython-310-pytest-8.2.2.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b07285061d4ce0e9bd82637c10ba7b9711cdfff6 Binary files /dev/null and b/tests/test_service/__pycache__/test_DefaultService.cpython-310-pytest-8.2.2.pyc differ diff --git a/tests/test_service/__pycache__/test_DefaultService.cpython-311-pytest-8.2.2.pyc b/tests/test_service/__pycache__/test_DefaultService.cpython-311-pytest-8.2.2.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ac55abc3a8f13a772e982e810ece1d6ce3bc75f7 Binary files /dev/null and b/tests/test_service/__pycache__/test_DefaultService.cpython-311-pytest-8.2.2.pyc differ diff --git a/tests/test_service/__pycache__/test_FileService.cpython-310-pytest-8.2.2.pyc b/tests/test_service/__pycache__/test_FileService.cpython-310-pytest-8.2.2.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5f5983822b5e9ab65d064e6138bec8bc7e1fd13f Binary files /dev/null and b/tests/test_service/__pycache__/test_FileService.cpython-310-pytest-8.2.2.pyc differ diff --git a/tests/test_service/__pycache__/test_FileService.cpython-311-pytest-8.2.2.pyc b/tests/test_service/__pycache__/test_FileService.cpython-311-pytest-8.2.2.pyc new file mode 100644 index 0000000000000000000000000000000000000000..77a9574c4c24d4cf4c5bf63db4404b165321c35d Binary files /dev/null and b/tests/test_service/__pycache__/test_FileService.cpython-311-pytest-8.2.2.pyc differ diff --git a/tests/test_service/__pycache__/test_LoginService.cpython-310-pytest-8.2.2.pyc b/tests/test_service/__pycache__/test_LoginService.cpython-310-pytest-8.2.2.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c7becb3f76552c335597005b656f12a5a3ad06e3 Binary files /dev/null and b/tests/test_service/__pycache__/test_LoginService.cpython-310-pytest-8.2.2.pyc differ diff --git a/tests/test_service/__pycache__/test_LoginService.cpython-311-pytest-8.2.2.pyc b/tests/test_service/__pycache__/test_LoginService.cpython-311-pytest-8.2.2.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f84f20c56d66cef9b340096e0316883775a6178e Binary files /dev/null and b/tests/test_service/__pycache__/test_LoginService.cpython-311-pytest-8.2.2.pyc differ diff --git a/tests/test_service/__pycache__/test_MySQLService.cpython-310-pytest-8.2.2.pyc b/tests/test_service/__pycache__/test_MySQLService.cpython-310-pytest-8.2.2.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7bcaf87fc58b1bdab109dfe1b489b03538cc31dd Binary files /dev/null and b/tests/test_service/__pycache__/test_MySQLService.cpython-310-pytest-8.2.2.pyc differ diff --git a/tests/test_service/__pycache__/test_MySQLService.cpython-310.pyc b/tests/test_service/__pycache__/test_MySQLService.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..75c96b98ac18df3f7ed14c3bf1c441410a698a2e Binary files /dev/null and b/tests/test_service/__pycache__/test_MySQLService.cpython-310.pyc differ diff --git a/tests/test_service/__pycache__/test_MySQLService.cpython-311-pytest-8.2.2.pyc b/tests/test_service/__pycache__/test_MySQLService.cpython-311-pytest-8.2.2.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ee113ea5b21117c1b94e572cd70265b327f97ea1 Binary files /dev/null and b/tests/test_service/__pycache__/test_MySQLService.cpython-311-pytest-8.2.2.pyc differ diff --git a/tests/test_service/__pycache__/test_OTPService.cpython-310-pytest-8.2.2.pyc b/tests/test_service/__pycache__/test_OTPService.cpython-310-pytest-8.2.2.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b396592d5988f489bcd255f9a45b1b8a0059eb01 Binary files /dev/null and b/tests/test_service/__pycache__/test_OTPService.cpython-310-pytest-8.2.2.pyc differ diff --git a/tests/test_service/__pycache__/test_OTPService.cpython-311-pytest-8.2.2.pyc b/tests/test_service/__pycache__/test_OTPService.cpython-311-pytest-8.2.2.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5a70614e119f35e4dbe40f53dcaed02cbb9412c6 Binary files /dev/null and b/tests/test_service/__pycache__/test_OTPService.cpython-311-pytest-8.2.2.pyc differ diff --git a/tests/test_service/user_file/quangphuc@gmail.com/demo1.pdf b/tests/test_service/user_file/quangphuc@gmail.com/demo1.pdf new file mode 100644 index 0000000000000000000000000000000000000000..43597a9147dba9bf9befd7886997e1ceb1413702 --- /dev/null +++ b/tests/test_service/user_file/quangphuc@gmail.com/demo1.pdf @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:367daadbb1bb652bda103a21a632b36a2821348931c3c11b37fa315c9843af4a +size 7289174 diff --git a/tests/user_file/quangphuc@gmail.com/demo1.pdf b/tests/user_file/quangphuc@gmail.com/demo1.pdf new file mode 100644 index 0000000000000000000000000000000000000000..43597a9147dba9bf9befd7886997e1ceb1413702 --- /dev/null +++ b/tests/user_file/quangphuc@gmail.com/demo1.pdf @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:367daadbb1bb652bda103a21a632b36a2821348931c3c11b37fa315c9843af4a +size 7289174 diff --git a/user_file/20133118@student.hcmute.edu.vn/DEMO1.docx b/user_file/20133118@student.hcmute.edu.vn/DEMO1.docx new file mode 100644 index 0000000000000000000000000000000000000000..bbac601d464af4a6586afe7d4e599d7ec04f4c01 Binary files /dev/null and b/user_file/20133118@student.hcmute.edu.vn/DEMO1.docx differ diff --git a/user_file/20133118@student.hcmute.edu.vn/DEMO2.pdf b/user_file/20133118@student.hcmute.edu.vn/DEMO2.pdf new file mode 100644 index 0000000000000000000000000000000000000000..43597a9147dba9bf9befd7886997e1ceb1413702 --- /dev/null +++ b/user_file/20133118@student.hcmute.edu.vn/DEMO2.pdf @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:367daadbb1bb652bda103a21a632b36a2821348931c3c11b37fa315c9843af4a +size 7289174 diff --git a/user_file/20133118@student.hcmute.edu.vn/demo3.docx b/user_file/20133118@student.hcmute.edu.vn/demo3.docx new file mode 100644 index 0000000000000000000000000000000000000000..9e00f830e3f1ebc76f6869339875286bd405ce7e Binary files /dev/null and b/user_file/20133118@student.hcmute.edu.vn/demo3.docx differ diff --git a/user_file/vonhuy5112002@gmail.com/KLTN_DeCuong.docx b/user_file/vonhuy5112002@gmail.com/KLTN_DeCuong.docx new file mode 100644 index 0000000000000000000000000000000000000000..f70bbd61476f64edb262afc48f11266a33372696 Binary files /dev/null and b/user_file/vonhuy5112002@gmail.com/KLTN_DeCuong.docx differ diff --git a/user_file/vonhuy5112002@gmail.com/LyThuyet_KLTN.docx b/user_file/vonhuy5112002@gmail.com/LyThuyet_KLTN.docx new file mode 100644 index 0000000000000000000000000000000000000000..bfff58cb962690568cc08c9089954a5e94dc9c04 Binary files /dev/null and b/user_file/vonhuy5112002@gmail.com/LyThuyet_KLTN.docx differ diff --git a/user_file/vonhuy5112002@gmail.com/Nhom05_FinalProject3.docx b/user_file/vonhuy5112002@gmail.com/Nhom05_FinalProject3.docx new file mode 100644 index 0000000000000000000000000000000000000000..bf88fe0c68561685d5ca85369c8fc4ae72bd2edd --- /dev/null +++ b/user_file/vonhuy5112002@gmail.com/Nhom05_FinalProject3.docx @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:947f9d04d0077ce8952865e3778de6cca24ca5a9d6d5105e8d75244f2d756d43 +size 7948686 diff --git a/user_file/vonhuy5112002@gmail.com/Report-ChatGPT.docx b/user_file/vonhuy5112002@gmail.com/Report-ChatGPT.docx new file mode 100644 index 0000000000000000000000000000000000000000..2a535aa6be2e62b67ba324a5fceba9a25b415493 --- /dev/null +++ b/user_file/vonhuy5112002@gmail.com/Report-ChatGPT.docx @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e8bffbc1d5e2ffc52b1c460d7c6bf39b9491fe188e0e74bb5747e88fb8ea2108 +size 3268419 diff --git a/user_file/vonhuy5112002@gmail.com/demo2.pptx b/user_file/vonhuy5112002@gmail.com/demo2.pptx new file mode 100644 index 0000000000000000000000000000000000000000..23e2a16ed2315c1c1d694e62586a9fd3656b9c95 Binary files /dev/null and b/user_file/vonhuy5112002@gmail.com/demo2.pptx differ diff --git a/user_file/vonhuy777@gmail.com/DEMO1.docx b/user_file/vonhuy777@gmail.com/DEMO1.docx new file mode 100644 index 0000000000000000000000000000000000000000..bbac601d464af4a6586afe7d4e599d7ec04f4c01 Binary files /dev/null and b/user_file/vonhuy777@gmail.com/DEMO1.docx differ diff --git a/user_file/vonhuy777@gmail.com/DEMO2.pdf b/user_file/vonhuy777@gmail.com/DEMO2.pdf new file mode 100644 index 0000000000000000000000000000000000000000..090d2e1aeddbb833b76c8cfe47b117118496f7db --- /dev/null +++ b/user_file/vonhuy777@gmail.com/DEMO2.pdf @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0640e6a341a0893ee011b3cd628901a398c74c702b2b9b0cccec60e22b135ab1 +size 11723887 diff --git a/user_file/vonhuy777@gmail.com/DEMO3.docx b/user_file/vonhuy777@gmail.com/DEMO3.docx new file mode 100644 index 0000000000000000000000000000000000000000..6f1514d0a9c5abaf15dcf4b90e25759ae2715931 Binary files /dev/null and b/user_file/vonhuy777@gmail.com/DEMO3.docx differ diff --git a/vector_database/20133118@student.hcmute.edu.vn/DEMO1.docx/chroma.sqlite3 b/vector_database/20133118@student.hcmute.edu.vn/DEMO1.docx/chroma.sqlite3 new file mode 100644 index 0000000000000000000000000000000000000000..2f396ca486b0f0339ef81a65cc1cb9bcc2d73688 --- /dev/null +++ b/vector_database/20133118@student.hcmute.edu.vn/DEMO1.docx/chroma.sqlite3 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c3c0383973137b0f764172f2a4794489c4616e320fe1b26369fab72577861d26 +size 1024000 diff --git a/vector_database/20133118@student.hcmute.edu.vn/DEMO1.docx/eba899f6-80f0-4b36-9a3f-73f03f5774d8/data_level0.bin b/vector_database/20133118@student.hcmute.edu.vn/DEMO1.docx/eba899f6-80f0-4b36-9a3f-73f03f5774d8/data_level0.bin new file mode 100644 index 0000000000000000000000000000000000000000..8d59af8d46593f309b55ca904928b8064fded705 --- /dev/null +++ b/vector_database/20133118@student.hcmute.edu.vn/DEMO1.docx/eba899f6-80f0-4b36-9a3f-73f03f5774d8/data_level0.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a13e72541800c513c73dccea69f79e39cf4baef4fa23f7e117c0d6b0f5f99670 +size 3212000 diff --git a/vector_database/20133118@student.hcmute.edu.vn/DEMO1.docx/eba899f6-80f0-4b36-9a3f-73f03f5774d8/header.bin b/vector_database/20133118@student.hcmute.edu.vn/DEMO1.docx/eba899f6-80f0-4b36-9a3f-73f03f5774d8/header.bin new file mode 100644 index 0000000000000000000000000000000000000000..5e3435b012ee69310b8100812b2faf2bd6a11f73 --- /dev/null +++ b/vector_database/20133118@student.hcmute.edu.vn/DEMO1.docx/eba899f6-80f0-4b36-9a3f-73f03f5774d8/header.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0ec6df10978b056a10062ed99efeef2702fa4a1301fad702b53dd2517103c746 +size 100 diff --git a/vector_database/20133118@student.hcmute.edu.vn/DEMO1.docx/eba899f6-80f0-4b36-9a3f-73f03f5774d8/length.bin b/vector_database/20133118@student.hcmute.edu.vn/DEMO1.docx/eba899f6-80f0-4b36-9a3f-73f03f5774d8/length.bin new file mode 100644 index 0000000000000000000000000000000000000000..c8055062b967399347a8071d331cf4e7b78ae1b0 --- /dev/null +++ b/vector_database/20133118@student.hcmute.edu.vn/DEMO1.docx/eba899f6-80f0-4b36-9a3f-73f03f5774d8/length.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4cd8e4827e83a5b2e12bf76096917969a360e79046452ebd2cae26ce19e34283 +size 4000 diff --git a/vector_database/20133118@student.hcmute.edu.vn/DEMO1.docx/eba899f6-80f0-4b36-9a3f-73f03f5774d8/link_lists.bin b/vector_database/20133118@student.hcmute.edu.vn/DEMO1.docx/eba899f6-80f0-4b36-9a3f-73f03f5774d8/link_lists.bin new file mode 100644 index 0000000000000000000000000000000000000000..fc8e42b32efb9a9bf3ae0234a18a948e499490f8 --- /dev/null +++ b/vector_database/20133118@student.hcmute.edu.vn/DEMO1.docx/eba899f6-80f0-4b36-9a3f-73f03f5774d8/link_lists.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 +size 0 diff --git a/vector_database/20133118@student.hcmute.edu.vn/DEMO2.pdf/chroma.sqlite3 b/vector_database/20133118@student.hcmute.edu.vn/DEMO2.pdf/chroma.sqlite3 new file mode 100644 index 0000000000000000000000000000000000000000..1ff4f5b06fcecd7415f8faf349c3273badd372f7 --- /dev/null +++ b/vector_database/20133118@student.hcmute.edu.vn/DEMO2.pdf/chroma.sqlite3 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e0ce12295ec1555faeba350bfa9ba66b1cb5f7bd5ca1f24abaf8341b968e97a9 +size 3780608 diff --git a/vector_database/20133118@student.hcmute.edu.vn/DEMO2.pdf/d94b007a-6ac2-4c4d-958f-5cd63f8e842c/data_level0.bin b/vector_database/20133118@student.hcmute.edu.vn/DEMO2.pdf/d94b007a-6ac2-4c4d-958f-5cd63f8e842c/data_level0.bin new file mode 100644 index 0000000000000000000000000000000000000000..8d59af8d46593f309b55ca904928b8064fded705 --- /dev/null +++ b/vector_database/20133118@student.hcmute.edu.vn/DEMO2.pdf/d94b007a-6ac2-4c4d-958f-5cd63f8e842c/data_level0.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a13e72541800c513c73dccea69f79e39cf4baef4fa23f7e117c0d6b0f5f99670 +size 3212000 diff --git a/vector_database/20133118@student.hcmute.edu.vn/DEMO2.pdf/d94b007a-6ac2-4c4d-958f-5cd63f8e842c/header.bin b/vector_database/20133118@student.hcmute.edu.vn/DEMO2.pdf/d94b007a-6ac2-4c4d-958f-5cd63f8e842c/header.bin new file mode 100644 index 0000000000000000000000000000000000000000..5e3435b012ee69310b8100812b2faf2bd6a11f73 --- /dev/null +++ b/vector_database/20133118@student.hcmute.edu.vn/DEMO2.pdf/d94b007a-6ac2-4c4d-958f-5cd63f8e842c/header.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0ec6df10978b056a10062ed99efeef2702fa4a1301fad702b53dd2517103c746 +size 100 diff --git a/vector_database/20133118@student.hcmute.edu.vn/DEMO2.pdf/d94b007a-6ac2-4c4d-958f-5cd63f8e842c/length.bin b/vector_database/20133118@student.hcmute.edu.vn/DEMO2.pdf/d94b007a-6ac2-4c4d-958f-5cd63f8e842c/length.bin new file mode 100644 index 0000000000000000000000000000000000000000..7df7e75dac0618eb4386d07a0afdb6e7fe697281 --- /dev/null +++ b/vector_database/20133118@student.hcmute.edu.vn/DEMO2.pdf/d94b007a-6ac2-4c4d-958f-5cd63f8e842c/length.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9c35fccd6681b990e1dc0995408f34ec3966b06fbee4484273ba36a362ba9efa +size 4000 diff --git a/vector_database/20133118@student.hcmute.edu.vn/DEMO2.pdf/d94b007a-6ac2-4c4d-958f-5cd63f8e842c/link_lists.bin b/vector_database/20133118@student.hcmute.edu.vn/DEMO2.pdf/d94b007a-6ac2-4c4d-958f-5cd63f8e842c/link_lists.bin new file mode 100644 index 0000000000000000000000000000000000000000..fc8e42b32efb9a9bf3ae0234a18a948e499490f8 --- /dev/null +++ b/vector_database/20133118@student.hcmute.edu.vn/DEMO2.pdf/d94b007a-6ac2-4c4d-958f-5cd63f8e842c/link_lists.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 +size 0 diff --git a/vector_database/20133118@student.hcmute.edu.vn/c5bb2555-72c0-4a6a-992f-363f0ffce769/data_level0.bin b/vector_database/20133118@student.hcmute.edu.vn/c5bb2555-72c0-4a6a-992f-363f0ffce769/data_level0.bin new file mode 100644 index 0000000000000000000000000000000000000000..8d59af8d46593f309b55ca904928b8064fded705 --- /dev/null +++ b/vector_database/20133118@student.hcmute.edu.vn/c5bb2555-72c0-4a6a-992f-363f0ffce769/data_level0.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a13e72541800c513c73dccea69f79e39cf4baef4fa23f7e117c0d6b0f5f99670 +size 3212000 diff --git a/vector_database/20133118@student.hcmute.edu.vn/c5bb2555-72c0-4a6a-992f-363f0ffce769/header.bin b/vector_database/20133118@student.hcmute.edu.vn/c5bb2555-72c0-4a6a-992f-363f0ffce769/header.bin new file mode 100644 index 0000000000000000000000000000000000000000..5e3435b012ee69310b8100812b2faf2bd6a11f73 --- /dev/null +++ b/vector_database/20133118@student.hcmute.edu.vn/c5bb2555-72c0-4a6a-992f-363f0ffce769/header.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0ec6df10978b056a10062ed99efeef2702fa4a1301fad702b53dd2517103c746 +size 100 diff --git a/vector_database/20133118@student.hcmute.edu.vn/c5bb2555-72c0-4a6a-992f-363f0ffce769/length.bin b/vector_database/20133118@student.hcmute.edu.vn/c5bb2555-72c0-4a6a-992f-363f0ffce769/length.bin new file mode 100644 index 0000000000000000000000000000000000000000..25f1937d9e6763f3e1c8547b477188c644298713 --- /dev/null +++ b/vector_database/20133118@student.hcmute.edu.vn/c5bb2555-72c0-4a6a-992f-363f0ffce769/length.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:11f922857c3402b67e36abbb3333a2b4ecdf75505ef0d03537467315897a6698 +size 4000 diff --git a/vector_database/20133118@student.hcmute.edu.vn/c5bb2555-72c0-4a6a-992f-363f0ffce769/link_lists.bin b/vector_database/20133118@student.hcmute.edu.vn/c5bb2555-72c0-4a6a-992f-363f0ffce769/link_lists.bin new file mode 100644 index 0000000000000000000000000000000000000000..fc8e42b32efb9a9bf3ae0234a18a948e499490f8 --- /dev/null +++ b/vector_database/20133118@student.hcmute.edu.vn/c5bb2555-72c0-4a6a-992f-363f0ffce769/link_lists.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 +size 0 diff --git a/vector_database/20133118@student.hcmute.edu.vn/chroma.sqlite3 b/vector_database/20133118@student.hcmute.edu.vn/chroma.sqlite3 new file mode 100644 index 0000000000000000000000000000000000000000..4eaebde9c9c3b4d13033ebd42f388be2716315d0 --- /dev/null +++ b/vector_database/20133118@student.hcmute.edu.vn/chroma.sqlite3 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:87a8a4d115a6f4ff072ec0c7349a8178e5f349bcbe818f0714b3dbcf8db3db15 +size 9883648 diff --git a/vector_database/20133118@student.hcmute.edu.vn/demo3.docx/66d7bce7-183c-4d03-bc15-1bc173eb9fa4/data_level0.bin b/vector_database/20133118@student.hcmute.edu.vn/demo3.docx/66d7bce7-183c-4d03-bc15-1bc173eb9fa4/data_level0.bin new file mode 100644 index 0000000000000000000000000000000000000000..8d59af8d46593f309b55ca904928b8064fded705 --- /dev/null +++ b/vector_database/20133118@student.hcmute.edu.vn/demo3.docx/66d7bce7-183c-4d03-bc15-1bc173eb9fa4/data_level0.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a13e72541800c513c73dccea69f79e39cf4baef4fa23f7e117c0d6b0f5f99670 +size 3212000 diff --git a/vector_database/20133118@student.hcmute.edu.vn/demo3.docx/66d7bce7-183c-4d03-bc15-1bc173eb9fa4/header.bin b/vector_database/20133118@student.hcmute.edu.vn/demo3.docx/66d7bce7-183c-4d03-bc15-1bc173eb9fa4/header.bin new file mode 100644 index 0000000000000000000000000000000000000000..5e3435b012ee69310b8100812b2faf2bd6a11f73 --- /dev/null +++ b/vector_database/20133118@student.hcmute.edu.vn/demo3.docx/66d7bce7-183c-4d03-bc15-1bc173eb9fa4/header.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0ec6df10978b056a10062ed99efeef2702fa4a1301fad702b53dd2517103c746 +size 100 diff --git a/vector_database/20133118@student.hcmute.edu.vn/demo3.docx/66d7bce7-183c-4d03-bc15-1bc173eb9fa4/length.bin b/vector_database/20133118@student.hcmute.edu.vn/demo3.docx/66d7bce7-183c-4d03-bc15-1bc173eb9fa4/length.bin new file mode 100644 index 0000000000000000000000000000000000000000..6f7de13cbcfeca9e93a36cb3f7a20b1f66b9d754 --- /dev/null +++ b/vector_database/20133118@student.hcmute.edu.vn/demo3.docx/66d7bce7-183c-4d03-bc15-1bc173eb9fa4/length.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f365b5fc9bedfa34e4841d295cbd1d05843ba8f5835347c650f4eae0fd6ee3b2 +size 4000 diff --git a/vector_database/20133118@student.hcmute.edu.vn/demo3.docx/66d7bce7-183c-4d03-bc15-1bc173eb9fa4/link_lists.bin b/vector_database/20133118@student.hcmute.edu.vn/demo3.docx/66d7bce7-183c-4d03-bc15-1bc173eb9fa4/link_lists.bin new file mode 100644 index 0000000000000000000000000000000000000000..fc8e42b32efb9a9bf3ae0234a18a948e499490f8 --- /dev/null +++ b/vector_database/20133118@student.hcmute.edu.vn/demo3.docx/66d7bce7-183c-4d03-bc15-1bc173eb9fa4/link_lists.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 +size 0 diff --git a/vector_database/20133118@student.hcmute.edu.vn/demo3.docx/chroma.sqlite3 b/vector_database/20133118@student.hcmute.edu.vn/demo3.docx/chroma.sqlite3 new file mode 100644 index 0000000000000000000000000000000000000000..6e2c47c056c266e5f4a9e8c8984809a516e53079 Binary files /dev/null and b/vector_database/20133118@student.hcmute.edu.vn/demo3.docx/chroma.sqlite3 differ diff --git a/vector_database/FAISS/20133118@student.hcmute.edu.vn/DEMO1.docx/index.faiss b/vector_database/FAISS/20133118@student.hcmute.edu.vn/DEMO1.docx/index.faiss new file mode 100644 index 0000000000000000000000000000000000000000..475afc53e50d1f49f891ffc9d9bea23ffa8cc126 Binary files /dev/null and b/vector_database/FAISS/20133118@student.hcmute.edu.vn/DEMO1.docx/index.faiss differ diff --git a/vector_database/FAISS/20133118@student.hcmute.edu.vn/DEMO1.docx/index.pkl b/vector_database/FAISS/20133118@student.hcmute.edu.vn/DEMO1.docx/index.pkl new file mode 100644 index 0000000000000000000000000000000000000000..19946cd927034244eaa0c8906157ae341d1658c7 --- /dev/null +++ b/vector_database/FAISS/20133118@student.hcmute.edu.vn/DEMO1.docx/index.pkl @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:53fe493216594d5ed039bd2cfa4fe41d3f51c1a4e140bd4faf968f1a0f4ba492 +size 122301 diff --git a/vector_database/FAISS/20133118@student.hcmute.edu.vn/DEMO2.pdf/index.faiss b/vector_database/FAISS/20133118@student.hcmute.edu.vn/DEMO2.pdf/index.faiss new file mode 100644 index 0000000000000000000000000000000000000000..3659cbe61684c9ceddde8c155a3958db687319d1 Binary files /dev/null and b/vector_database/FAISS/20133118@student.hcmute.edu.vn/DEMO2.pdf/index.faiss differ diff --git a/vector_database/FAISS/20133118@student.hcmute.edu.vn/DEMO2.pdf/index.pkl b/vector_database/FAISS/20133118@student.hcmute.edu.vn/DEMO2.pdf/index.pkl new file mode 100644 index 0000000000000000000000000000000000000000..8748b969bb71493f138799401cb74701e9ee4178 --- /dev/null +++ b/vector_database/FAISS/20133118@student.hcmute.edu.vn/DEMO2.pdf/index.pkl @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e29449ae02b21c659c593b3b954f6e6e2bb58c4920c0bfff1e8dd4036c275811 +size 543170 diff --git a/vector_database/FAISS/20133118@student.hcmute.edu.vn/demo3.docx/index.faiss b/vector_database/FAISS/20133118@student.hcmute.edu.vn/demo3.docx/index.faiss new file mode 100644 index 0000000000000000000000000000000000000000..62371c8d5f0edc373a690119c2ebb558df616a33 Binary files /dev/null and b/vector_database/FAISS/20133118@student.hcmute.edu.vn/demo3.docx/index.faiss differ diff --git a/vector_database/FAISS/20133118@student.hcmute.edu.vn/demo3.docx/index.pkl b/vector_database/FAISS/20133118@student.hcmute.edu.vn/demo3.docx/index.pkl new file mode 100644 index 0000000000000000000000000000000000000000..3b5f2b66d76b7c85a3f192c63c221445daa1f770 --- /dev/null +++ b/vector_database/FAISS/20133118@student.hcmute.edu.vn/demo3.docx/index.pkl @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:49f42d09f85f85ff45396218546ffc0fe8f22727345eb6c8ee442894468c2233 +size 27560 diff --git a/vector_database/FAISS/vonhuy5112002@gmail.com/Nhom05_FinalProject3.docx/index.faiss b/vector_database/FAISS/vonhuy5112002@gmail.com/Nhom05_FinalProject3.docx/index.faiss new file mode 100644 index 0000000000000000000000000000000000000000..bbac0a00b7cbb82101a4634337536addbd38a673 Binary files /dev/null and b/vector_database/FAISS/vonhuy5112002@gmail.com/Nhom05_FinalProject3.docx/index.faiss differ diff --git a/vector_database/FAISS/vonhuy5112002@gmail.com/Nhom05_FinalProject3.docx/index.pkl b/vector_database/FAISS/vonhuy5112002@gmail.com/Nhom05_FinalProject3.docx/index.pkl new file mode 100644 index 0000000000000000000000000000000000000000..fd79a365965079026c8a9bf34df8d27b8d2082cd --- /dev/null +++ b/vector_database/FAISS/vonhuy5112002@gmail.com/Nhom05_FinalProject3.docx/index.pkl @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7b58860d5ad31cbe1d35d6384a2f3e16724126d7db1955a9a09ce1e2deda0520 +size 341236 diff --git a/vector_database/FAISS/vonhuy777@gmail.com/DEMO1.docx/index.faiss b/vector_database/FAISS/vonhuy777@gmail.com/DEMO1.docx/index.faiss new file mode 100644 index 0000000000000000000000000000000000000000..a1a86e59979ebee0098f7a9ff803de1aa5a41dd1 Binary files /dev/null and b/vector_database/FAISS/vonhuy777@gmail.com/DEMO1.docx/index.faiss differ diff --git a/vector_database/FAISS/vonhuy777@gmail.com/DEMO1.docx/index.pkl b/vector_database/FAISS/vonhuy777@gmail.com/DEMO1.docx/index.pkl new file mode 100644 index 0000000000000000000000000000000000000000..0a47554263315e124a4fe34de56148413a03c6a3 --- /dev/null +++ b/vector_database/FAISS/vonhuy777@gmail.com/DEMO1.docx/index.pkl @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4d04cd6ed8f198fefd70325a8d689122c86eff39a5426d14e9a3d7044f4f174a +size 172486 diff --git a/vector_database/FAISS/vonhuy777@gmail.com/DEMO2.pdf/index.faiss b/vector_database/FAISS/vonhuy777@gmail.com/DEMO2.pdf/index.faiss new file mode 100644 index 0000000000000000000000000000000000000000..209f07a74c786378a047e77167aebd82bcdf7d30 Binary files /dev/null and b/vector_database/FAISS/vonhuy777@gmail.com/DEMO2.pdf/index.faiss differ diff --git a/vector_database/FAISS/vonhuy777@gmail.com/DEMO2.pdf/index.pkl b/vector_database/FAISS/vonhuy777@gmail.com/DEMO2.pdf/index.pkl new file mode 100644 index 0000000000000000000000000000000000000000..245f832b0dfe030a371d4b612e2b5f56ce735fb3 --- /dev/null +++ b/vector_database/FAISS/vonhuy777@gmail.com/DEMO2.pdf/index.pkl @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f497b10ed94dbca43623a8786a54b7b22236ad979c4b683efee715f412362cdd +size 867263 diff --git a/vector_database/FAISS/vonhuy777@gmail.com/Report.pdf/index.faiss b/vector_database/FAISS/vonhuy777@gmail.com/Report.pdf/index.faiss new file mode 100644 index 0000000000000000000000000000000000000000..07570b91ad95e40b6ed865a094333a082b289ae4 Binary files /dev/null and b/vector_database/FAISS/vonhuy777@gmail.com/Report.pdf/index.faiss differ diff --git a/vector_database/FAISS/vonhuy777@gmail.com/Report.pdf/index.pkl b/vector_database/FAISS/vonhuy777@gmail.com/Report.pdf/index.pkl new file mode 100644 index 0000000000000000000000000000000000000000..036e2e7567b8dd2494afe86f1d082d991d594cd9 --- /dev/null +++ b/vector_database/FAISS/vonhuy777@gmail.com/Report.pdf/index.pkl @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fbf348a2e82046f0a3ea72723dd01b186838231f84d5b0abdd61c659db30e0cf +size 1276171 diff --git a/vector_database/vonhuy5112002@gmail.com/6d2b25db-6997-4cc0-b753-8df435a22e56/data_level0.bin b/vector_database/vonhuy5112002@gmail.com/6d2b25db-6997-4cc0-b753-8df435a22e56/data_level0.bin new file mode 100644 index 0000000000000000000000000000000000000000..8d59af8d46593f309b55ca904928b8064fded705 --- /dev/null +++ b/vector_database/vonhuy5112002@gmail.com/6d2b25db-6997-4cc0-b753-8df435a22e56/data_level0.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a13e72541800c513c73dccea69f79e39cf4baef4fa23f7e117c0d6b0f5f99670 +size 3212000 diff --git a/vector_database/vonhuy5112002@gmail.com/6d2b25db-6997-4cc0-b753-8df435a22e56/header.bin b/vector_database/vonhuy5112002@gmail.com/6d2b25db-6997-4cc0-b753-8df435a22e56/header.bin new file mode 100644 index 0000000000000000000000000000000000000000..5e3435b012ee69310b8100812b2faf2bd6a11f73 --- /dev/null +++ b/vector_database/vonhuy5112002@gmail.com/6d2b25db-6997-4cc0-b753-8df435a22e56/header.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0ec6df10978b056a10062ed99efeef2702fa4a1301fad702b53dd2517103c746 +size 100 diff --git a/vector_database/vonhuy5112002@gmail.com/6d2b25db-6997-4cc0-b753-8df435a22e56/length.bin b/vector_database/vonhuy5112002@gmail.com/6d2b25db-6997-4cc0-b753-8df435a22e56/length.bin new file mode 100644 index 0000000000000000000000000000000000000000..660ad6b4588477bb2a7c123769c1a5dad73b7eea --- /dev/null +++ b/vector_database/vonhuy5112002@gmail.com/6d2b25db-6997-4cc0-b753-8df435a22e56/length.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a73a57b5f16473f5bbba6f5b35eeb350f440607294053490950ad79e3277ac19 +size 4000 diff --git a/vector_database/vonhuy5112002@gmail.com/6d2b25db-6997-4cc0-b753-8df435a22e56/link_lists.bin b/vector_database/vonhuy5112002@gmail.com/6d2b25db-6997-4cc0-b753-8df435a22e56/link_lists.bin new file mode 100644 index 0000000000000000000000000000000000000000..fc8e42b32efb9a9bf3ae0234a18a948e499490f8 --- /dev/null +++ b/vector_database/vonhuy5112002@gmail.com/6d2b25db-6997-4cc0-b753-8df435a22e56/link_lists.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 +size 0 diff --git a/vector_database/vonhuy5112002@gmail.com/Nhom05_FinalProject3.docx/chroma.sqlite3 b/vector_database/vonhuy5112002@gmail.com/Nhom05_FinalProject3.docx/chroma.sqlite3 new file mode 100644 index 0000000000000000000000000000000000000000..7a05e893e9a318fe6dfb3af8a25a70cccd253b94 --- /dev/null +++ b/vector_database/vonhuy5112002@gmail.com/Nhom05_FinalProject3.docx/chroma.sqlite3 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:01a81f578a4f77a790ac390c480f52a428619e1dd42ea6ae0f32cb6aa0d2e93b +size 2473984 diff --git a/vector_database/vonhuy5112002@gmail.com/Nhom05_FinalProject3.docx/daed0c31-24ab-49cd-a108-3eb1ae7f6c23/data_level0.bin b/vector_database/vonhuy5112002@gmail.com/Nhom05_FinalProject3.docx/daed0c31-24ab-49cd-a108-3eb1ae7f6c23/data_level0.bin new file mode 100644 index 0000000000000000000000000000000000000000..8d59af8d46593f309b55ca904928b8064fded705 --- /dev/null +++ b/vector_database/vonhuy5112002@gmail.com/Nhom05_FinalProject3.docx/daed0c31-24ab-49cd-a108-3eb1ae7f6c23/data_level0.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a13e72541800c513c73dccea69f79e39cf4baef4fa23f7e117c0d6b0f5f99670 +size 3212000 diff --git a/vector_database/vonhuy5112002@gmail.com/Nhom05_FinalProject3.docx/daed0c31-24ab-49cd-a108-3eb1ae7f6c23/header.bin b/vector_database/vonhuy5112002@gmail.com/Nhom05_FinalProject3.docx/daed0c31-24ab-49cd-a108-3eb1ae7f6c23/header.bin new file mode 100644 index 0000000000000000000000000000000000000000..5e3435b012ee69310b8100812b2faf2bd6a11f73 --- /dev/null +++ b/vector_database/vonhuy5112002@gmail.com/Nhom05_FinalProject3.docx/daed0c31-24ab-49cd-a108-3eb1ae7f6c23/header.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0ec6df10978b056a10062ed99efeef2702fa4a1301fad702b53dd2517103c746 +size 100 diff --git a/vector_database/vonhuy5112002@gmail.com/Nhom05_FinalProject3.docx/daed0c31-24ab-49cd-a108-3eb1ae7f6c23/length.bin b/vector_database/vonhuy5112002@gmail.com/Nhom05_FinalProject3.docx/daed0c31-24ab-49cd-a108-3eb1ae7f6c23/length.bin new file mode 100644 index 0000000000000000000000000000000000000000..760b7ccca237ec0f759d52dfaace4845dc26fd40 --- /dev/null +++ b/vector_database/vonhuy5112002@gmail.com/Nhom05_FinalProject3.docx/daed0c31-24ab-49cd-a108-3eb1ae7f6c23/length.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9ebdd38ca856bd90e28ef591001c2ee9c787bdbc1f824dc5a9e926ce165f02df +size 4000 diff --git a/vector_database/vonhuy5112002@gmail.com/Nhom05_FinalProject3.docx/daed0c31-24ab-49cd-a108-3eb1ae7f6c23/link_lists.bin b/vector_database/vonhuy5112002@gmail.com/Nhom05_FinalProject3.docx/daed0c31-24ab-49cd-a108-3eb1ae7f6c23/link_lists.bin new file mode 100644 index 0000000000000000000000000000000000000000..fc8e42b32efb9a9bf3ae0234a18a948e499490f8 --- /dev/null +++ b/vector_database/vonhuy5112002@gmail.com/Nhom05_FinalProject3.docx/daed0c31-24ab-49cd-a108-3eb1ae7f6c23/link_lists.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 +size 0 diff --git a/vector_database/vonhuy5112002@gmail.com/Report-ChatGPT.docx/3a4693e3-e8fb-4b93-bbcb-ddb432c29b0d/data_level0.bin b/vector_database/vonhuy5112002@gmail.com/Report-ChatGPT.docx/3a4693e3-e8fb-4b93-bbcb-ddb432c29b0d/data_level0.bin new file mode 100644 index 0000000000000000000000000000000000000000..8d59af8d46593f309b55ca904928b8064fded705 --- /dev/null +++ b/vector_database/vonhuy5112002@gmail.com/Report-ChatGPT.docx/3a4693e3-e8fb-4b93-bbcb-ddb432c29b0d/data_level0.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a13e72541800c513c73dccea69f79e39cf4baef4fa23f7e117c0d6b0f5f99670 +size 3212000 diff --git a/vector_database/vonhuy5112002@gmail.com/Report-ChatGPT.docx/3a4693e3-e8fb-4b93-bbcb-ddb432c29b0d/header.bin b/vector_database/vonhuy5112002@gmail.com/Report-ChatGPT.docx/3a4693e3-e8fb-4b93-bbcb-ddb432c29b0d/header.bin new file mode 100644 index 0000000000000000000000000000000000000000..5e3435b012ee69310b8100812b2faf2bd6a11f73 --- /dev/null +++ b/vector_database/vonhuy5112002@gmail.com/Report-ChatGPT.docx/3a4693e3-e8fb-4b93-bbcb-ddb432c29b0d/header.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0ec6df10978b056a10062ed99efeef2702fa4a1301fad702b53dd2517103c746 +size 100 diff --git a/vector_database/vonhuy5112002@gmail.com/Report-ChatGPT.docx/3a4693e3-e8fb-4b93-bbcb-ddb432c29b0d/length.bin b/vector_database/vonhuy5112002@gmail.com/Report-ChatGPT.docx/3a4693e3-e8fb-4b93-bbcb-ddb432c29b0d/length.bin new file mode 100644 index 0000000000000000000000000000000000000000..0d53310fe3bf43a288db99d0273131c42e983369 --- /dev/null +++ b/vector_database/vonhuy5112002@gmail.com/Report-ChatGPT.docx/3a4693e3-e8fb-4b93-bbcb-ddb432c29b0d/length.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4eb5d836e03dd9f886277c6a7e348aba9ebaf3035135083449d57a3ba315a8a4 +size 4000 diff --git a/vector_database/vonhuy5112002@gmail.com/Report-ChatGPT.docx/3a4693e3-e8fb-4b93-bbcb-ddb432c29b0d/link_lists.bin b/vector_database/vonhuy5112002@gmail.com/Report-ChatGPT.docx/3a4693e3-e8fb-4b93-bbcb-ddb432c29b0d/link_lists.bin new file mode 100644 index 0000000000000000000000000000000000000000..fc8e42b32efb9a9bf3ae0234a18a948e499490f8 --- /dev/null +++ b/vector_database/vonhuy5112002@gmail.com/Report-ChatGPT.docx/3a4693e3-e8fb-4b93-bbcb-ddb432c29b0d/link_lists.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 +size 0 diff --git a/vector_database/vonhuy5112002@gmail.com/Report-ChatGPT.docx/chroma.sqlite3 b/vector_database/vonhuy5112002@gmail.com/Report-ChatGPT.docx/chroma.sqlite3 new file mode 100644 index 0000000000000000000000000000000000000000..18d711b64e136a3a6907a5785f415b52f164a99e Binary files /dev/null and b/vector_database/vonhuy5112002@gmail.com/Report-ChatGPT.docx/chroma.sqlite3 differ diff --git a/vector_database/vonhuy5112002@gmail.com/chroma.sqlite3 b/vector_database/vonhuy5112002@gmail.com/chroma.sqlite3 new file mode 100644 index 0000000000000000000000000000000000000000..575e0a01a18faee3025716ddbbab77db05ad402c --- /dev/null +++ b/vector_database/vonhuy5112002@gmail.com/chroma.sqlite3 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3501fd22e5a68a1f6032b4f7cd71c3898b67fbcbf1fe1614423bf666825ccf78 +size 5058560 diff --git a/vector_database/vonhuy777@gmail.com/DEMO1.docx/21b2e33b-ce81-4e3b-85a7-8067453fd285/data_level0.bin b/vector_database/vonhuy777@gmail.com/DEMO1.docx/21b2e33b-ce81-4e3b-85a7-8067453fd285/data_level0.bin new file mode 100644 index 0000000000000000000000000000000000000000..8d59af8d46593f309b55ca904928b8064fded705 --- /dev/null +++ b/vector_database/vonhuy777@gmail.com/DEMO1.docx/21b2e33b-ce81-4e3b-85a7-8067453fd285/data_level0.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a13e72541800c513c73dccea69f79e39cf4baef4fa23f7e117c0d6b0f5f99670 +size 3212000 diff --git a/vector_database/vonhuy777@gmail.com/DEMO1.docx/21b2e33b-ce81-4e3b-85a7-8067453fd285/header.bin b/vector_database/vonhuy777@gmail.com/DEMO1.docx/21b2e33b-ce81-4e3b-85a7-8067453fd285/header.bin new file mode 100644 index 0000000000000000000000000000000000000000..5e3435b012ee69310b8100812b2faf2bd6a11f73 --- /dev/null +++ b/vector_database/vonhuy777@gmail.com/DEMO1.docx/21b2e33b-ce81-4e3b-85a7-8067453fd285/header.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0ec6df10978b056a10062ed99efeef2702fa4a1301fad702b53dd2517103c746 +size 100 diff --git a/vector_database/vonhuy777@gmail.com/DEMO1.docx/21b2e33b-ce81-4e3b-85a7-8067453fd285/length.bin b/vector_database/vonhuy777@gmail.com/DEMO1.docx/21b2e33b-ce81-4e3b-85a7-8067453fd285/length.bin new file mode 100644 index 0000000000000000000000000000000000000000..2956fad7ed1a5e40ff84b8aeeac5f37440a4c88a --- /dev/null +++ b/vector_database/vonhuy777@gmail.com/DEMO1.docx/21b2e33b-ce81-4e3b-85a7-8067453fd285/length.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5952eeab70dce5783b13502c8faf63d38358a4d30a273509bde4f72fdd600172 +size 4000 diff --git a/vector_database/vonhuy777@gmail.com/DEMO1.docx/21b2e33b-ce81-4e3b-85a7-8067453fd285/link_lists.bin b/vector_database/vonhuy777@gmail.com/DEMO1.docx/21b2e33b-ce81-4e3b-85a7-8067453fd285/link_lists.bin new file mode 100644 index 0000000000000000000000000000000000000000..fc8e42b32efb9a9bf3ae0234a18a948e499490f8 --- /dev/null +++ b/vector_database/vonhuy777@gmail.com/DEMO1.docx/21b2e33b-ce81-4e3b-85a7-8067453fd285/link_lists.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 +size 0 diff --git a/vector_database/vonhuy777@gmail.com/DEMO1.docx/chroma.sqlite3 b/vector_database/vonhuy777@gmail.com/DEMO1.docx/chroma.sqlite3 new file mode 100644 index 0000000000000000000000000000000000000000..3c9e75f4b2fa3ec9fa3fceb104623f5701165666 Binary files /dev/null and b/vector_database/vonhuy777@gmail.com/DEMO1.docx/chroma.sqlite3 differ diff --git a/vector_database/vonhuy777@gmail.com/DEMO2.pdf/7e885c22-7f88-48f3-9a0e-ea3ffd587bdf/data_level0.bin b/vector_database/vonhuy777@gmail.com/DEMO2.pdf/7e885c22-7f88-48f3-9a0e-ea3ffd587bdf/data_level0.bin new file mode 100644 index 0000000000000000000000000000000000000000..8d59af8d46593f309b55ca904928b8064fded705 --- /dev/null +++ b/vector_database/vonhuy777@gmail.com/DEMO2.pdf/7e885c22-7f88-48f3-9a0e-ea3ffd587bdf/data_level0.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a13e72541800c513c73dccea69f79e39cf4baef4fa23f7e117c0d6b0f5f99670 +size 3212000 diff --git a/vector_database/vonhuy777@gmail.com/DEMO2.pdf/7e885c22-7f88-48f3-9a0e-ea3ffd587bdf/header.bin b/vector_database/vonhuy777@gmail.com/DEMO2.pdf/7e885c22-7f88-48f3-9a0e-ea3ffd587bdf/header.bin new file mode 100644 index 0000000000000000000000000000000000000000..5e3435b012ee69310b8100812b2faf2bd6a11f73 --- /dev/null +++ b/vector_database/vonhuy777@gmail.com/DEMO2.pdf/7e885c22-7f88-48f3-9a0e-ea3ffd587bdf/header.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0ec6df10978b056a10062ed99efeef2702fa4a1301fad702b53dd2517103c746 +size 100 diff --git a/vector_database/vonhuy777@gmail.com/DEMO2.pdf/7e885c22-7f88-48f3-9a0e-ea3ffd587bdf/length.bin b/vector_database/vonhuy777@gmail.com/DEMO2.pdf/7e885c22-7f88-48f3-9a0e-ea3ffd587bdf/length.bin new file mode 100644 index 0000000000000000000000000000000000000000..fb155d822b6ca4351e2925bbc2dba0f49f05e0ab --- /dev/null +++ b/vector_database/vonhuy777@gmail.com/DEMO2.pdf/7e885c22-7f88-48f3-9a0e-ea3ffd587bdf/length.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fc19b1997119425765295aeab72d76faa6927d4f83985d328c26f20468d6cc76 +size 4000 diff --git a/vector_database/vonhuy777@gmail.com/DEMO2.pdf/7e885c22-7f88-48f3-9a0e-ea3ffd587bdf/link_lists.bin b/vector_database/vonhuy777@gmail.com/DEMO2.pdf/7e885c22-7f88-48f3-9a0e-ea3ffd587bdf/link_lists.bin new file mode 100644 index 0000000000000000000000000000000000000000..fc8e42b32efb9a9bf3ae0234a18a948e499490f8 --- /dev/null +++ b/vector_database/vonhuy777@gmail.com/DEMO2.pdf/7e885c22-7f88-48f3-9a0e-ea3ffd587bdf/link_lists.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 +size 0 diff --git a/vector_database/vonhuy777@gmail.com/DEMO2.pdf/chroma.sqlite3 b/vector_database/vonhuy777@gmail.com/DEMO2.pdf/chroma.sqlite3 new file mode 100644 index 0000000000000000000000000000000000000000..0f6ebcec8314fb488f341eec7d9ac318e7082901 --- /dev/null +++ b/vector_database/vonhuy777@gmail.com/DEMO2.pdf/chroma.sqlite3 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c5d9ef829e17a679e025d4bcb48d5ea7b9ee7c5cbf845f31b42bff4464ccec03 +size 2215936 diff --git a/vector_database/vonhuy777@gmail.com/b5400e2d-0984-4e49-9c6c-5af4cd6d40b2/data_level0.bin b/vector_database/vonhuy777@gmail.com/b5400e2d-0984-4e49-9c6c-5af4cd6d40b2/data_level0.bin new file mode 100644 index 0000000000000000000000000000000000000000..8d59af8d46593f309b55ca904928b8064fded705 --- /dev/null +++ b/vector_database/vonhuy777@gmail.com/b5400e2d-0984-4e49-9c6c-5af4cd6d40b2/data_level0.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a13e72541800c513c73dccea69f79e39cf4baef4fa23f7e117c0d6b0f5f99670 +size 3212000 diff --git a/vector_database/vonhuy777@gmail.com/b5400e2d-0984-4e49-9c6c-5af4cd6d40b2/header.bin b/vector_database/vonhuy777@gmail.com/b5400e2d-0984-4e49-9c6c-5af4cd6d40b2/header.bin new file mode 100644 index 0000000000000000000000000000000000000000..5e3435b012ee69310b8100812b2faf2bd6a11f73 --- /dev/null +++ b/vector_database/vonhuy777@gmail.com/b5400e2d-0984-4e49-9c6c-5af4cd6d40b2/header.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0ec6df10978b056a10062ed99efeef2702fa4a1301fad702b53dd2517103c746 +size 100 diff --git a/vector_database/vonhuy777@gmail.com/b5400e2d-0984-4e49-9c6c-5af4cd6d40b2/length.bin b/vector_database/vonhuy777@gmail.com/b5400e2d-0984-4e49-9c6c-5af4cd6d40b2/length.bin new file mode 100644 index 0000000000000000000000000000000000000000..4aec5f8e9401ef57075b393ab51f866ba604a596 --- /dev/null +++ b/vector_database/vonhuy777@gmail.com/b5400e2d-0984-4e49-9c6c-5af4cd6d40b2/length.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1ae46755757bbf17c0771d858fc631a234ff02324fe5bcda8271d37cb694952e +size 4000 diff --git a/vector_database/vonhuy777@gmail.com/b5400e2d-0984-4e49-9c6c-5af4cd6d40b2/link_lists.bin b/vector_database/vonhuy777@gmail.com/b5400e2d-0984-4e49-9c6c-5af4cd6d40b2/link_lists.bin new file mode 100644 index 0000000000000000000000000000000000000000..fc8e42b32efb9a9bf3ae0234a18a948e499490f8 --- /dev/null +++ b/vector_database/vonhuy777@gmail.com/b5400e2d-0984-4e49-9c6c-5af4cd6d40b2/link_lists.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 +size 0 diff --git a/vector_database/vonhuy777@gmail.com/chroma.sqlite3 b/vector_database/vonhuy777@gmail.com/chroma.sqlite3 new file mode 100644 index 0000000000000000000000000000000000000000..9c1f65af8ad9d5f5ad3835c5e93181a3ed908370 --- /dev/null +++ b/vector_database/vonhuy777@gmail.com/chroma.sqlite3 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:30632e70a7950cd0a45f7795f7f9d1a66d2c58c4e720151f4404d9a5be0d876e +size 20971520