From ad65ace82459aefa3199e7557d8c8c6abcc740c5 Mon Sep 17 00:00:00 2001 From: Amr Elsayed Date: Fri, 31 Jan 2025 18:26:27 +1100 Subject: [PATCH 1/3] Validate and normalize emails --- src/ansari/ansari_db.py | 9 ++++++--- src/ansari/app/main_api.py | 8 ++++---- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/ansari/ansari_db.py b/src/ansari/ansari_db.py index 506fe12..a10f8b3 100644 --- a/src/ansari/ansari_db.py +++ b/src/ansari/ansari_db.py @@ -247,8 +247,9 @@ def validate_reset_token(self, token: str) -> dict[str, str]: def register(self, email, first_name, last_name, password_hash): try: + normalized_email = email.strip().lower() insert_cmd = """INSERT INTO users (email, password_hash, first_name, last_name) values (%s, %s, %s, %s);""" - self._execute_query(insert_cmd, (email, password_hash, first_name, last_name)) + self._execute_query(insert_cmd, (normalized_email, password_hash, first_name, last_name)) return {"status": "success"} except Exception as e: logger.warning(f"Warning (possbile error): {e}") @@ -288,8 +289,9 @@ def register_whatsapp(self, phone_num: str, db_cols_to_vals: dict) -> dict: def account_exists(self, email): try: + normalized_email = email.strip().lower() select_cmd = """SELECT id FROM users WHERE email = %s;""" - result = self._execute_query(select_cmd, (email,), "one")[0] + result = self._execute_query(select_cmd, (normalized_email,), "one")[0] return result is not None except Exception as e: logger.warning(f"Warning (possbile error): {e}") @@ -341,8 +343,9 @@ def save_reset_token(self, user_id, token): def retrieve_user_info(self, email): try: + normalized_email = email.strip().lower() select_cmd = "SELECT id, password_hash, first_name, last_name FROM users WHERE email = %s;" - result = self._execute_query(select_cmd, (email,), "one")[0] + result = self._execute_query(select_cmd, (normalized_email,), "one")[0] if result: user_id, existing_hash, first_name, last_name = result return user_id, existing_hash, first_name, last_name diff --git a/src/ansari/app/main_api.py b/src/ansari/app/main_api.py index 08d66f9..ba19d33 100644 --- a/src/ansari/app/main_api.py +++ b/src/ansari/app/main_api.py @@ -10,7 +10,7 @@ from fastapi.responses import JSONResponse, StreamingResponse from jinja2 import Environment, FileSystemLoader from langfuse.decorators import langfuse_context, observe -from pydantic import BaseModel +from pydantic import BaseModel, EmailStr from sendgrid import SendGridAPIClient from sendgrid.helpers.mail import Mail from starlette.exceptions import HTTPException as StarletteHTTPException @@ -99,7 +99,7 @@ def add_app_middleware(): class RegisterRequest(BaseModel): - email: str + email: EmailStr password: str first_name: str last_name: str @@ -136,7 +136,7 @@ async def register_user(req: RegisterRequest, cors_ok: bool = Depends(validate_c class LoginRequest(BaseModel): - email: str + email: EmailStr password: str @@ -582,7 +582,7 @@ async def get_prefs( class ResetPasswordRequest(BaseModel): - email: str + email: EmailStr @app.post("/api/v2/request_password_reset") From 35f965a6c441cd69595402cc71b71a2951103257 Mon Sep 17 00:00:00 2001 From: Amr Elsayed Date: Fri, 31 Jan 2025 18:32:18 +1100 Subject: [PATCH 2/3] Fix typos --- src/ansari/ansari_db.py | 62 ++++++++++++++++++++--------------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/src/ansari/ansari_db.py b/src/ansari/ansari_db.py index a10f8b3..8584378 100644 --- a/src/ansari/ansari_db.py +++ b/src/ansari/ansari_db.py @@ -252,7 +252,7 @@ def register(self, email, first_name, last_name, password_hash): self._execute_query(insert_cmd, (normalized_email, password_hash, first_name, last_name)) return {"status": "success"} except Exception as e: - logger.warning(f"Warning (possbile error): {e}") + logger.warning(f"Warning (possible error): {e}") return {"status": "failure", "error": str(e)} def register_whatsapp(self, phone_num: str, db_cols_to_vals: dict) -> dict: @@ -284,7 +284,7 @@ def register_whatsapp(self, phone_num: str, db_cols_to_vals: dict) -> dict: return {"status": "success"} except Exception as e: - logger.warning(f"Warning (possbile error): {e}") + logger.warning(f"Warning (possible error): {e}") return {"status": "failure", "error": str(e)} def account_exists(self, email): @@ -294,7 +294,7 @@ def account_exists(self, email): result = self._execute_query(select_cmd, (normalized_email,), "one")[0] return result is not None except Exception as e: - logger.warning(f"Warning (possbile error): {e}") + logger.warning(f"Warning (possible error): {e}") return False def account_exists_whatsapp(self, phone_num): @@ -303,7 +303,7 @@ def account_exists_whatsapp(self, phone_num): result = self._execute_query(select_cmd, (phone_num,), "one")[0] return result is not None except Exception as e: - logger.warning(f"Warning (possbile error): {e}") + logger.warning(f"Warning (possible error): {e}") return False def save_access_token(self, user_id, token): @@ -317,7 +317,7 @@ def save_access_token(self, user_id, token): "token_db_id": inserted_id, } except Exception as e: - logger.warning(f"Warning (possbile error): {e}") + logger.warning(f"Warning (possible error): {e}") return {"status": "failure", "error": str(e)} def save_refresh_token(self, user_id, token, access_token_id): @@ -326,7 +326,7 @@ def save_refresh_token(self, user_id, token, access_token_id): self._execute_query(insert_cmd, (user_id, token, access_token_id)) return {"status": "success", "token": token} except Exception as e: - logger.warning(f"Warning (possbile error): {e}") + logger.warning(f"Warning (possible error): {e}") return {"status": "failure", "error": str(e)} def save_reset_token(self, user_id, token): @@ -338,7 +338,7 @@ def save_reset_token(self, user_id, token): self._execute_query(insert_cmd, (user_id, token, token)) return {"status": "success", "token": token} except Exception as e: - logger.warning(f"Warning (possbile error): {e}") + logger.warning(f"Warning (possible error): {e}") return {"status": "failure", "error": str(e)} def retrieve_user_info(self, email): @@ -351,7 +351,7 @@ def retrieve_user_info(self, email): return user_id, existing_hash, first_name, last_name return None, None, None, None except Exception as e: - logger.warning(f"Warning (possbile error): {e}") + logger.warning(f"Warning (possible error): {e}") return None, None, None, None def retrieve_user_info_whatsapp(self, phone_num: str, db_cols: Union[list, str]) -> Optional[Tuple]: @@ -387,7 +387,7 @@ def retrieve_user_info_whatsapp(self, phone_num: str, db_cols: Union[list, str]) return result return None except Exception as e: - logger.warning(f"Warning (possbile error): {e}") + logger.warning(f"Warning (possible error): {e}") return None def add_feedback(self, user_id, thread_id, message_id, feedback_class, comment): @@ -398,7 +398,7 @@ def add_feedback(self, user_id, thread_id, message_id, feedback_class, comment): self._execute_query(insert_cmd, (user_id, thread_id, message_id, feedback_class, comment)) return {"status": "success"} except Exception as e: - logger.warning(f"Warning (possbile error): {e}") + logger.warning(f"Warning (possible error): {e}") return {"status": "failure", "error": str(e)} def create_thread(self, user_id): @@ -408,7 +408,7 @@ def create_thread(self, user_id): inserted_id = result[0] if result else None return {"status": "success", "thread_id": inserted_id} except Exception as e: - logger.warning(f"Warning (possbile error): {e}") + logger.warning(f"Warning (possible error): {e}") return {"status": "failure", "error": str(e)} def create_thread_whatsapp(self, user_id_whatsapp: int, thread_name: str) -> str: @@ -424,14 +424,14 @@ def create_thread_whatsapp(self, user_id_whatsapp: int, thread_name: str) -> str """ try: insert_cmd = """ - INSERT INTO threads_whatsapp (user_id_whatsapp, name) - VALUES (%s, %s) + INSERT INTO threads_whatsapp (user_id_whatsapp, name) + VALUES (%s, %s) RETURNING id; """ result = self._execute_query(insert_cmd, (user_id_whatsapp, thread_name), "one")[0] return result[0] if result else None except Exception as e: - logger.warning(f"Warning (possbile error): {e}") + logger.warning(f"Warning (possible error): {e}") return None def get_all_threads(self, user_id): @@ -440,7 +440,7 @@ def get_all_threads(self, user_id): result = self._execute_query(select_cmd, (user_id,), "all")[0] return [{"thread_id": x[0], "thread_name": x[1], "updated_at": x[2]} for x in result] if result else [] except Exception as e: - logger.warning(f"Warning (possbile error): {e}") + logger.warning(f"Warning (possible error): {e}") return [] def set_thread_name(self, thread_id, user_id, thread_name): @@ -459,7 +459,7 @@ def set_thread_name(self, thread_id, user_id, thread_name): ) return {"status": "success"} except Exception as e: - logger.warning(f"Warning (possbile error): {e}") + logger.warning(f"Warning (possible error): {e}") return {"status": "failure", "error": str(e)} def append_message(self, user_id, thread_id, role, content, tool_name=None): @@ -479,7 +479,7 @@ def append_message(self, user_id, thread_id, role, content, tool_name=None): return {"status": "success"} except Exception as e: - logger.warning(f"Warning (possbile error): {e}") + logger.warning(f"Warning (possible error): {e}") return {"status": "failure", "error": str(e)} def append_message_whatsapp(self, user_id_whatsapp: int, thread_id: int, db_cols_to_vals: dict) -> dict: @@ -516,7 +516,7 @@ def append_message_whatsapp(self, user_id_whatsapp: int, thread_id: int, db_cols return {"status": "success"} except Exception as e: - logger.warning(f"Warning (possbile error): {e}") + logger.warning(f"Warning (possible error): {e}") return {"status": "failure", "error": str(e)} def get_thread(self, thread_id, user_id): @@ -547,7 +547,7 @@ def get_thread(self, thread_id, user_id): } return retval except Exception as e: - logger.warning(f"Warning (possbile error): {e}") + logger.warning(f"Warning (possible error): {e}") return {} def get_thread_llm(self, thread_id, user_id): @@ -579,7 +579,7 @@ def get_thread_llm(self, thread_id, user_id): } return retval except Exception as e: - logger.warning(f"Warning (possbile error): {e}") + logger.warning(f"Warning (possible error): {e}") return {} def get_thread_llm_whatsapp(self, thread_id: str, user_id_whatsapp: int) -> list[dict]: @@ -596,8 +596,8 @@ def get_thread_llm_whatsapp(self, thread_id: str, user_id_whatsapp: int) -> list """ try: select_cmd = """ - SELECT role, content, function_name - FROM messages_whatsapp + SELECT role, content, function_name + FROM messages_whatsapp WHERE thread_id = %s AND user_id_whatsapp = %s ORDER BY timestamp; """ @@ -608,7 +608,7 @@ def get_thread_llm_whatsapp(self, thread_id: str, user_id_whatsapp: int) -> list else [] ) except Exception as e: - logger.warning(f"Warning (possbile error): {e}") + logger.warning(f"Warning (possible error): {e}") return [] def get_last_message_time_whatsapp(self, user_id_whatsapp: int) -> tuple[Optional[str], Optional[datetime]]: @@ -635,7 +635,7 @@ def get_last_message_time_whatsapp(self, user_id_whatsapp: int) -> tuple[Optiona return result[0], result[1] return None, None except Exception as e: - logger.warning(f"Warning (possbile error): {e}") + logger.warning(f"Warning (possible error): {e}") return None, None def snapshot_thread(self, thread_id, user_id): @@ -654,7 +654,7 @@ def snapshot_thread(self, thread_id, user_id): logger.info(f"Result is {result}") return result[0] if result else None except Exception as e: - logger.warning(f"Warning (possbile error): {e}") + logger.warning(f"Warning (possible error): {e}") return {"status": "failure", "error": str(e)} def get_snapshot(self, share_uuid): @@ -667,7 +667,7 @@ def get_snapshot(self, share_uuid): return json.loads(result[0]) return {} except Exception as e: - logger.warning(f"Warning (possbile error): {e}") + logger.warning(f"Warning (possible error): {e}") return {} def delete_thread(self, thread_id, user_id): @@ -680,7 +680,7 @@ def delete_thread(self, thread_id, user_id): self._execute_query([delete_cmd_1, delete_cmd_2], [params, params]) return {"status": "success"} except Exception as e: - logger.warning(f"Warning (possbile error): {e}") + logger.warning(f"Warning (possible error): {e}") return {"status": "failure", "error": str(e)} def delete_access_refresh_tokens_pair(self, refresh_token): @@ -720,7 +720,7 @@ def delete_access_token(self, user_id, token): self._execute_query(delete_cmd, (user_id, token)) return {"status": "success"} except Exception as e: - logger.warning(f"Warning (possbile error): {e}") + logger.warning(f"Warning (possible error): {e}") return {"status": "failure", "error": str(e)} def logout(self, user_id, token): @@ -730,7 +730,7 @@ def logout(self, user_id, token): self._execute_query(delete_cmd, (user_id, token)) return {"status": "success"} except Exception as e: - logger.warning(f"Warning (possbile error): {e}") + logger.warning(f"Warning (possible error): {e}") return {"status": "failure", "error": str(e)} def set_pref(self, user_id, key, value): @@ -755,7 +755,7 @@ def update_password(self, user_id, new_password_hash): self._execute_query(update_cmd, (new_password_hash, user_id)) return {"status": "success"} except Exception as e: - logger.warning(f"Warning (possbile error): {e}") + logger.warning(f"Warning (possible error): {e}") return {"status": "failure", "error": str(e)} def update_user_whatsapp(self, phone_num: str, db_cols_to_vals: dict) -> dict: @@ -787,7 +787,7 @@ def update_user_whatsapp(self, phone_num: str, db_cols_to_vals: dict) -> dict: return {"status": "success"} except Exception as e: - logger.warning(f"Warning (possbile error): {e}") + logger.warning(f"Warning (possible error): {e}") return {"status": "failure", "error": str(e)} def convert_message(self, msg): From e625c34ab0cfe638d09e3affa6232e4522b12182 Mon Sep 17 00:00:00 2001 From: Amr Elsayed Date: Sat, 1 Feb 2025 09:34:03 +1100 Subject: [PATCH 3/3] Update dependencies --- requirements.txt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/requirements.txt b/requirements.txt index 4a72462..7a67e79 100644 --- a/requirements.txt +++ b/requirements.txt @@ -8,7 +8,7 @@ jinja2 langdetect # should be >= 2 in order for "from langfuse.decorators" to work langfuse>=2.0.0 -litellm +litellm>=1.59.6,<1.59.9 loguru openai pandas @@ -24,4 +24,5 @@ tiktoken typer uvicorn wheel -zxcvbn \ No newline at end of file +zxcvbn +email-validator \ No newline at end of file