Spaces:
Runtime error
Runtime error
Commit
·
4363b00
1
Parent(s):
f656193
update
Browse files- db/mongoDB.py +3 -3
- dependencies.py +2 -2
- routers/chat.py +4 -4
- routers/user.py +5 -5
- services/auth_service.py +6 -6
- services/user_service.py +16 -16
- utils/utils.py +1 -1
db/mongoDB.py
CHANGED
|
@@ -47,7 +47,7 @@ async def connect_to_mongo():
|
|
| 47 |
)
|
| 48 |
|
| 49 |
# 2. Kiểm tra kết nối một cách rõ ràng
|
| 50 |
-
|
| 51 |
|
| 52 |
# 3. Gán các đối tượng database và collection
|
| 53 |
mongo_db.db = mongo_db.client[config.DB_NAME]
|
|
@@ -57,10 +57,10 @@ async def connect_to_mongo():
|
|
| 57 |
|
| 58 |
# 4. Tạo TTL index một cách an toàn
|
| 59 |
# Lấy danh sách index hiện có
|
| 60 |
-
index_info =
|
| 61 |
if "expires_at_1" not in index_info:
|
| 62 |
# Chỉ tạo index nếu nó chưa tồn tại
|
| 63 |
-
|
| 64 |
logger.info("🔸 Successfully created TTL index for 'expires_at' in 'token_blacklist'.")
|
| 65 |
|
| 66 |
|
|
|
|
| 47 |
)
|
| 48 |
|
| 49 |
# 2. Kiểm tra kết nối một cách rõ ràng
|
| 50 |
+
mongo_db.client.admin.command('ping')
|
| 51 |
|
| 52 |
# 3. Gán các đối tượng database và collection
|
| 53 |
mongo_db.db = mongo_db.client[config.DB_NAME]
|
|
|
|
| 57 |
|
| 58 |
# 4. Tạo TTL index một cách an toàn
|
| 59 |
# Lấy danh sách index hiện có
|
| 60 |
+
index_info = mongo_db.token_blacklist.index_information()
|
| 61 |
if "expires_at_1" not in index_info:
|
| 62 |
# Chỉ tạo index nếu nó chưa tồn tại
|
| 63 |
+
mongo_db.token_blacklist.create_index("expires_at", expireAfterSeconds=0)
|
| 64 |
logger.info("🔸 Successfully created TTL index for 'expires_at' in 'token_blacklist'.")
|
| 65 |
|
| 66 |
|
dependencies.py
CHANGED
|
@@ -189,7 +189,7 @@ async def get_current_user(
|
|
| 189 |
# 1. Kiểm tra token trong blacklist
|
| 190 |
try:
|
| 191 |
logger.info("GET_CURRENT_USER: Đang kiểm tra blacklist...")
|
| 192 |
-
is_blacklisted =
|
| 193 |
if is_blacklisted:
|
| 194 |
logger.error(f"GET_CURRENT_USER: *** TOKEN TRONG BLACKLIST - RAISING 401 ***")
|
| 195 |
raise HTTPException( # Sử dụng credentials_exception hoặc một cái cụ thể hơn
|
|
@@ -266,7 +266,7 @@ async def get_current_user(
|
|
| 266 |
user_data: Optional[dict] = None # Khởi tạo để tránh UnboundLocalError
|
| 267 |
try:
|
| 268 |
logger.info(f"GET_CURRENT_USER: Đang tìm user trong DB: {email.lower()}") # email đã được validate là str
|
| 269 |
-
user_data =
|
| 270 |
# print(user_data) # Bỏ print trong production
|
| 271 |
|
| 272 |
if user_data is None:
|
|
|
|
| 189 |
# 1. Kiểm tra token trong blacklist
|
| 190 |
try:
|
| 191 |
logger.info("GET_CURRENT_USER: Đang kiểm tra blacklist...")
|
| 192 |
+
is_blacklisted = mongo_db.token_blacklist.find_one({"token": token_to_verify})
|
| 193 |
if is_blacklisted:
|
| 194 |
logger.error(f"GET_CURRENT_USER: *** TOKEN TRONG BLACKLIST - RAISING 401 ***")
|
| 195 |
raise HTTPException( # Sử dụng credentials_exception hoặc một cái cụ thể hơn
|
|
|
|
| 266 |
user_data: Optional[dict] = None # Khởi tạo để tránh UnboundLocalError
|
| 267 |
try:
|
| 268 |
logger.info(f"GET_CURRENT_USER: Đang tìm user trong DB: {email.lower()}") # email đã được validate là str
|
| 269 |
+
user_data = mongo_db.users.find_one({"email": email.lower()}, {"password": 0, "_id": 0})
|
| 270 |
# print(user_data) # Bỏ print trong production
|
| 271 |
|
| 272 |
if user_data is None:
|
routers/chat.py
CHANGED
|
@@ -66,7 +66,7 @@ async def create_chat(
|
|
| 66 |
}
|
| 67 |
|
| 68 |
try:
|
| 69 |
-
|
| 70 |
logger.info(f"Đã tạo hội thoại rỗng {chat_id} trong MongoDB cho user {current_user.email}.")
|
| 71 |
except Exception as e:
|
| 72 |
logger.error(f"Lỗi khi tạo hội thoại rỗng trong MongoDB cho chat {chat_id}: {e}", exc_info=True)
|
|
@@ -135,7 +135,7 @@ async def delete_chat(chat_id: str, request: Request, user: UserOut = Depends(ge
|
|
| 135 |
# Xóa chat
|
| 136 |
delete_chat_from_redis(redis, chat_id)
|
| 137 |
# Xóa hội thoại trong MongoDB
|
| 138 |
-
result =
|
| 139 |
if result.deleted_count == 0:
|
| 140 |
raise HTTPException(status_code=404, detail="Chat not found in MongoDB")
|
| 141 |
|
|
@@ -147,7 +147,7 @@ async def delete_chat(chat_id: str, request: Request, user: UserOut = Depends(ge
|
|
| 147 |
async def get_conversations(user: UserOut = Depends(get_current_user)):
|
| 148 |
try:
|
| 149 |
logger.info(f"Attempting to get conversations for user: {user.email}")
|
| 150 |
-
db_conversations_cursor =
|
| 151 |
|
| 152 |
response_list = []
|
| 153 |
|
|
@@ -182,7 +182,7 @@ async def load_conversation_and_sync_redis(
|
|
| 182 |
|
| 183 |
# 1. Kiểm tra hội thoại trong MongoDB
|
| 184 |
try:
|
| 185 |
-
conversation_doc =
|
| 186 |
{"conversation_id": chat_id, "user_id": current_user.email}
|
| 187 |
)
|
| 188 |
if not conversation_doc:
|
|
|
|
| 66 |
}
|
| 67 |
|
| 68 |
try:
|
| 69 |
+
mongo_db.conversations.insert_one(conversation_doc)
|
| 70 |
logger.info(f"Đã tạo hội thoại rỗng {chat_id} trong MongoDB cho user {current_user.email}.")
|
| 71 |
except Exception as e:
|
| 72 |
logger.error(f"Lỗi khi tạo hội thoại rỗng trong MongoDB cho chat {chat_id}: {e}", exc_info=True)
|
|
|
|
| 135 |
# Xóa chat
|
| 136 |
delete_chat_from_redis(redis, chat_id)
|
| 137 |
# Xóa hội thoại trong MongoDB
|
| 138 |
+
result = mongo_db.conversations.delete_one({"conversation_id": chat_id, "user_id": user.email})
|
| 139 |
if result.deleted_count == 0:
|
| 140 |
raise HTTPException(status_code=404, detail="Chat not found in MongoDB")
|
| 141 |
|
|
|
|
| 147 |
async def get_conversations(user: UserOut = Depends(get_current_user)):
|
| 148 |
try:
|
| 149 |
logger.info(f"Attempting to get conversations for user: {user.email}")
|
| 150 |
+
db_conversations_cursor = mongo_db.conversations.find({"user_id": user.email})
|
| 151 |
|
| 152 |
response_list = []
|
| 153 |
|
|
|
|
| 182 |
|
| 183 |
# 1. Kiểm tra hội thoại trong MongoDB
|
| 184 |
try:
|
| 185 |
+
conversation_doc =mongo_db.conversations.find_one(
|
| 186 |
{"conversation_id": chat_id, "user_id": current_user.email}
|
| 187 |
)
|
| 188 |
if not conversation_doc:
|
routers/user.py
CHANGED
|
@@ -304,7 +304,7 @@ async def auth_google_callback(request: Request):
|
|
| 304 |
|
| 305 |
|
| 306 |
# Kiểm tra xem user đã tồn tại trong DB chưa
|
| 307 |
-
db_user =
|
| 308 |
|
| 309 |
if not db_user:
|
| 310 |
placeholder_password = f"google-oauth2|{uuid.uuid4()}"
|
|
@@ -314,7 +314,7 @@ async def auth_google_callback(request: Request):
|
|
| 314 |
|
| 315 |
|
| 316 |
# Tạo user mới với thông tin từ Google
|
| 317 |
-
|
| 318 |
"email": user_email,
|
| 319 |
"username": username,
|
| 320 |
"password": hashed_password, # Mật khẩu tạm thời, sẽ không dùng đến
|
|
@@ -324,7 +324,7 @@ async def auth_google_callback(request: Request):
|
|
| 324 |
})
|
| 325 |
|
| 326 |
# Lấy lại user vừa tạo để đảm bảo có _id và các trường khác
|
| 327 |
-
db_user =
|
| 328 |
if not db_user: # Kiểm tra lại sau khi insert
|
| 329 |
raise HTTPException(status_code=500, detail="Could not create and retrieve new user account.")
|
| 330 |
|
|
@@ -362,7 +362,7 @@ async def exchange_google_code_for_token(request: Request,response: Response, co
|
|
| 362 |
redis_client.delete(redis_key) # Dùng một lần
|
| 363 |
user_email = user_email_bytes.decode()
|
| 364 |
|
| 365 |
-
|
| 366 |
"email": user_email
|
| 367 |
}, {
|
| 368 |
"$set": {
|
|
@@ -408,7 +408,7 @@ async def exchange_google_code_for_token(request: Request,response: Response, co
|
|
| 408 |
path="/api/user/refresh-token",
|
| 409 |
)
|
| 410 |
|
| 411 |
-
user_info =
|
| 412 |
user = {
|
| 413 |
"email": user_info.get("email"),
|
| 414 |
"username": user_info.get("username"),
|
|
|
|
| 304 |
|
| 305 |
|
| 306 |
# Kiểm tra xem user đã tồn tại trong DB chưa
|
| 307 |
+
db_user = mongo_db.users.find_one({"email": user_email})
|
| 308 |
|
| 309 |
if not db_user:
|
| 310 |
placeholder_password = f"google-oauth2|{uuid.uuid4()}"
|
|
|
|
| 314 |
|
| 315 |
|
| 316 |
# Tạo user mới với thông tin từ Google
|
| 317 |
+
mongo_db.users.insert_one({
|
| 318 |
"email": user_email,
|
| 319 |
"username": username,
|
| 320 |
"password": hashed_password, # Mật khẩu tạm thời, sẽ không dùng đến
|
|
|
|
| 324 |
})
|
| 325 |
|
| 326 |
# Lấy lại user vừa tạo để đảm bảo có _id và các trường khác
|
| 327 |
+
db_user = mongo_db.users.find_one({"email": user_email})
|
| 328 |
if not db_user: # Kiểm tra lại sau khi insert
|
| 329 |
raise HTTPException(status_code=500, detail="Could not create and retrieve new user account.")
|
| 330 |
|
|
|
|
| 362 |
redis_client.delete(redis_key) # Dùng một lần
|
| 363 |
user_email = user_email_bytes.decode()
|
| 364 |
|
| 365 |
+
mongo_db.users.update_one({
|
| 366 |
"email": user_email
|
| 367 |
}, {
|
| 368 |
"$set": {
|
|
|
|
| 408 |
path="/api/user/refresh-token",
|
| 409 |
)
|
| 410 |
|
| 411 |
+
user_info =mongo_db.users.find_one({"email": user_email})
|
| 412 |
user = {
|
| 413 |
"email": user_info.get("email"),
|
| 414 |
"username": user_info.get("username"),
|
services/auth_service.py
CHANGED
|
@@ -31,7 +31,7 @@ async def register_user(user: RegisterRequest):
|
|
| 31 |
|
| 32 |
try:
|
| 33 |
# Kiểm tra username đã tồn tại chưa
|
| 34 |
-
existing_user =
|
| 35 |
if existing_user:
|
| 36 |
raise HTTPException(status_code=400, detail="Tài khoản đã tồn tại.")
|
| 37 |
|
|
@@ -40,7 +40,7 @@ async def register_user(user: RegisterRequest):
|
|
| 40 |
|
| 41 |
avatar = await get_random_unsplash_image()
|
| 42 |
# Lưu user mới
|
| 43 |
-
|
| 44 |
"username": user.username,
|
| 45 |
"password": hashed_password,
|
| 46 |
"email": user.email,
|
|
@@ -54,7 +54,7 @@ async def register_user(user: RegisterRequest):
|
|
| 54 |
raise HTTPException(status_code=e.status_code, detail=e.detail)
|
| 55 |
# Hàm xác thực đăng nhập
|
| 56 |
async def authenticate_user(request: LoginRequest):
|
| 57 |
-
user =
|
| 58 |
if not user:
|
| 59 |
raise HTTPException(status_code=401, detail="Sai tài khoản hoặc mật khẩu")
|
| 60 |
|
|
@@ -101,7 +101,7 @@ async def logout_user(req: Request, credentials: HTTPAuthorizationCredentials =
|
|
| 101 |
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="Access token không hợp lệ")
|
| 102 |
|
| 103 |
# Blacklist access token
|
| 104 |
-
|
| 105 |
"token": token,
|
| 106 |
"expires_at": datetime.fromtimestamp(exp, tz=timezone.utc)
|
| 107 |
})
|
|
@@ -110,9 +110,9 @@ async def logout_user(req: Request, credentials: HTTPAuthorizationCredentials =
|
|
| 110 |
refresh_token = req.cookies.get("refresh_token")
|
| 111 |
if refresh_token:
|
| 112 |
# Invalidate refresh token in database
|
| 113 |
-
user =
|
| 114 |
if user:
|
| 115 |
-
|
| 116 |
{"_id": user["_id"]},
|
| 117 |
{"$set": {"refresh_token": None, "refresh_token_expiry": None, "revoked": True}}
|
| 118 |
)
|
|
|
|
| 31 |
|
| 32 |
try:
|
| 33 |
# Kiểm tra username đã tồn tại chưa
|
| 34 |
+
existing_user =mongo_db.users.find_one({"email": user.email})
|
| 35 |
if existing_user:
|
| 36 |
raise HTTPException(status_code=400, detail="Tài khoản đã tồn tại.")
|
| 37 |
|
|
|
|
| 40 |
|
| 41 |
avatar = await get_random_unsplash_image()
|
| 42 |
# Lưu user mới
|
| 43 |
+
mongo_db.users.insert_one({
|
| 44 |
"username": user.username,
|
| 45 |
"password": hashed_password,
|
| 46 |
"email": user.email,
|
|
|
|
| 54 |
raise HTTPException(status_code=e.status_code, detail=e.detail)
|
| 55 |
# Hàm xác thực đăng nhập
|
| 56 |
async def authenticate_user(request: LoginRequest):
|
| 57 |
+
user =mongo_db.users.find_one({"email": request.email})
|
| 58 |
if not user:
|
| 59 |
raise HTTPException(status_code=401, detail="Sai tài khoản hoặc mật khẩu")
|
| 60 |
|
|
|
|
| 101 |
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="Access token không hợp lệ")
|
| 102 |
|
| 103 |
# Blacklist access token
|
| 104 |
+
mongo_db.token_blacklist.insert_one({
|
| 105 |
"token": token,
|
| 106 |
"expires_at": datetime.fromtimestamp(exp, tz=timezone.utc)
|
| 107 |
})
|
|
|
|
| 110 |
refresh_token = req.cookies.get("refresh_token")
|
| 111 |
if refresh_token:
|
| 112 |
# Invalidate refresh token in database
|
| 113 |
+
user = mongo_db.users.find_one({"refresh_token": refresh_token})
|
| 114 |
if user:
|
| 115 |
+
mongo_db.users.update_one(
|
| 116 |
{"_id": user["_id"]},
|
| 117 |
{"$set": {"refresh_token": None, "refresh_token_expiry": None, "revoked": True}}
|
| 118 |
)
|
services/user_service.py
CHANGED
|
@@ -37,7 +37,7 @@ async def get_users(skip: int = 0, limit: int = 100, query: dict = None):
|
|
| 37 |
search_query = query or {}
|
| 38 |
|
| 39 |
# Thực hiện truy vấn với phân trang
|
| 40 |
-
users_cursor =
|
| 41 |
search_query,
|
| 42 |
{"_id": 0, "password": 0} # Loại bỏ các trường nhạy cảm
|
| 43 |
).skip(skip).limit(limit)
|
|
@@ -68,7 +68,7 @@ async def count_users(query: dict = None):
|
|
| 68 |
"""
|
| 69 |
try:
|
| 70 |
search_query = query or {}
|
| 71 |
-
return
|
| 72 |
except Exception as e:
|
| 73 |
logger.error(f"Lỗi khi đếm người dùng: {str(e)}")
|
| 74 |
raise HTTPException(
|
|
@@ -112,7 +112,7 @@ async def get_paginated_users(
|
|
| 112 |
sort_criteria = [(sort_by, sort_order)]
|
| 113 |
|
| 114 |
# Thực hiện truy vấn
|
| 115 |
-
users_cursor =
|
| 116 |
query,
|
| 117 |
{"_id": 0, "password": 0} # Loại bỏ các trường nhạy cảm
|
| 118 |
).sort(sort_criteria).skip(skip).limit(limit)
|
|
@@ -121,7 +121,7 @@ async def get_paginated_users(
|
|
| 121 |
user_list = users_cursor.to_list(length=limit)
|
| 122 |
|
| 123 |
# Đếm tổng số bản ghi
|
| 124 |
-
total =
|
| 125 |
|
| 126 |
# Tính toán thông tin phân trang
|
| 127 |
total_pages = math.ceil(total / limit) if limit > 0 else 0
|
|
@@ -182,7 +182,7 @@ async def delete_user(user_id: str):
|
|
| 182 |
bool: True nếu xóa thành công, False nếu không tìm thấy người dùng
|
| 183 |
"""
|
| 184 |
try:
|
| 185 |
-
result =
|
| 186 |
return result.deleted_count > 0
|
| 187 |
except Exception as e:
|
| 188 |
logger.error(f"Lỗi khi xóa người dùng: {str(e)}")
|
|
@@ -204,7 +204,7 @@ async def change_password(email: str, current_password: str, new_password: str):
|
|
| 204 |
bool: True nếu đổi mật khẩu thành công, False nếu không thành công
|
| 205 |
"""
|
| 206 |
try:
|
| 207 |
-
user =
|
| 208 |
if not user:
|
| 209 |
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Người dùng không tồn tại")
|
| 210 |
|
|
@@ -216,7 +216,7 @@ async def change_password(email: str, current_password: str, new_password: str):
|
|
| 216 |
# Hash the new password
|
| 217 |
hashed_password = pwd_context.hash(new_password)
|
| 218 |
# Update the password in the database
|
| 219 |
-
result =
|
| 220 |
return result.modified_count > 0
|
| 221 |
except HTTPException as he:
|
| 222 |
raise he
|
|
@@ -248,7 +248,7 @@ async def reset_password_request(email: str) -> bool:
|
|
| 248 |
return True
|
| 249 |
|
| 250 |
# Check for rate limiting (e.g., max 3 requests per hour)
|
| 251 |
-
reset_requests =
|
| 252 |
"email": email.lower(),
|
| 253 |
"reset_password_timestamp": {
|
| 254 |
"$gte": datetime.now(tz=timezone.utc) - timedelta(hours=1)
|
|
@@ -265,7 +265,7 @@ async def reset_password_request(email: str) -> bool:
|
|
| 265 |
expiry = datetime.now() + timedelta(minutes=10)
|
| 266 |
|
| 267 |
# Store reset token and timestamp in database
|
| 268 |
-
|
| 269 |
{"_id": ObjectId(user["_id"])},
|
| 270 |
{
|
| 271 |
"$set": {
|
|
@@ -380,7 +380,7 @@ async def generate_and_store_verification_code(email: str) -> bool:
|
|
| 380 |
expiry = datetime.now() + timedelta(minutes=10)
|
| 381 |
|
| 382 |
# Store code and expiry in database
|
| 383 |
-
result =
|
| 384 |
{"email": email.lower()},
|
| 385 |
{
|
| 386 |
"$set": {
|
|
@@ -425,7 +425,7 @@ async def verify_login_code(email: str, code: str, res: Response): # Bỏ kiểu
|
|
| 425 |
HTTPException: Nếu mã không hợp lệ, đã hết hạn hoặc có lỗi hệ thống.
|
| 426 |
"""
|
| 427 |
try:
|
| 428 |
-
user =
|
| 429 |
"email": email.lower(),
|
| 430 |
"login_verification_code": code
|
| 431 |
})
|
|
@@ -443,7 +443,7 @@ async def verify_login_code(email: str, code: str, res: Response): # Bỏ kiểu
|
|
| 443 |
if not expiry or expiry < datetime.now(expiry.tzinfo if expiry.tzinfo else None): # So sánh aware với aware, naive với naive
|
| 444 |
logger.warning(f"Mã xác minh đã hết hạn cho email: {email}")
|
| 445 |
# Xóa mã đã hết hạn để tránh sử dụng lại
|
| 446 |
-
|
| 447 |
{"_id": ObjectId(user["_id"])},
|
| 448 |
{
|
| 449 |
"$unset": {
|
|
@@ -509,7 +509,7 @@ async def verify_login_code(email: str, code: str, res: Response): # Bỏ kiểu
|
|
| 509 |
# --------------------
|
| 510 |
|
| 511 |
# Clear verification code và cập nhật last_login
|
| 512 |
-
|
| 513 |
{"_id": ObjectId(user["_id"])},
|
| 514 |
{
|
| 515 |
"$unset": {
|
|
@@ -567,7 +567,7 @@ async def authenticate_user(request: LoginRequest) -> dict:
|
|
| 567 |
Raises:
|
| 568 |
HTTPException: Nếu thông tin đăng nhập không hợp lệ.
|
| 569 |
"""
|
| 570 |
-
user =
|
| 571 |
if not user or not pwd_context.verify(request.password, user["password"]):
|
| 572 |
logger.warning(f"Xác thực thất bại cho email: {request.email}")
|
| 573 |
raise HTTPException(
|
|
@@ -603,7 +603,7 @@ async def refresh_access_token(req: Request , res: Response ) -> dict:
|
|
| 603 |
)
|
| 604 |
|
| 605 |
# Find user by refresh token in database
|
| 606 |
-
user =
|
| 607 |
|
| 608 |
|
| 609 |
if not user:
|
|
@@ -640,7 +640,7 @@ async def refresh_access_token(req: Request , res: Response ) -> dict:
|
|
| 640 |
new_refresh_token = await create_refresh_token(email)
|
| 641 |
|
| 642 |
# Update database with new refresh token
|
| 643 |
-
|
| 644 |
{"_id": user["_id"]},
|
| 645 |
{
|
| 646 |
"$set": {
|
|
|
|
| 37 |
search_query = query or {}
|
| 38 |
|
| 39 |
# Thực hiện truy vấn với phân trang
|
| 40 |
+
users_cursor = mongo_db.users.find(
|
| 41 |
search_query,
|
| 42 |
{"_id": 0, "password": 0} # Loại bỏ các trường nhạy cảm
|
| 43 |
).skip(skip).limit(limit)
|
|
|
|
| 68 |
"""
|
| 69 |
try:
|
| 70 |
search_query = query or {}
|
| 71 |
+
return mongo_db.users.count_documents(search_query)
|
| 72 |
except Exception as e:
|
| 73 |
logger.error(f"Lỗi khi đếm người dùng: {str(e)}")
|
| 74 |
raise HTTPException(
|
|
|
|
| 112 |
sort_criteria = [(sort_by, sort_order)]
|
| 113 |
|
| 114 |
# Thực hiện truy vấn
|
| 115 |
+
users_cursor =mongo_db.users.find(
|
| 116 |
query,
|
| 117 |
{"_id": 0, "password": 0} # Loại bỏ các trường nhạy cảm
|
| 118 |
).sort(sort_criteria).skip(skip).limit(limit)
|
|
|
|
| 121 |
user_list = users_cursor.to_list(length=limit)
|
| 122 |
|
| 123 |
# Đếm tổng số bản ghi
|
| 124 |
+
total =mongo_db.users.count_documents(query)
|
| 125 |
|
| 126 |
# Tính toán thông tin phân trang
|
| 127 |
total_pages = math.ceil(total / limit) if limit > 0 else 0
|
|
|
|
| 182 |
bool: True nếu xóa thành công, False nếu không tìm thấy người dùng
|
| 183 |
"""
|
| 184 |
try:
|
| 185 |
+
result =mongo_db.users.delete_one({"_id": user_id})
|
| 186 |
return result.deleted_count > 0
|
| 187 |
except Exception as e:
|
| 188 |
logger.error(f"Lỗi khi xóa người dùng: {str(e)}")
|
|
|
|
| 204 |
bool: True nếu đổi mật khẩu thành công, False nếu không thành công
|
| 205 |
"""
|
| 206 |
try:
|
| 207 |
+
user =mongo_db.users.find_one({"email": email})
|
| 208 |
if not user:
|
| 209 |
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Người dùng không tồn tại")
|
| 210 |
|
|
|
|
| 216 |
# Hash the new password
|
| 217 |
hashed_password = pwd_context.hash(new_password)
|
| 218 |
# Update the password in the database
|
| 219 |
+
result =mongo_db.users.update_one({"email": email}, {"$set": {"password": hashed_password}})
|
| 220 |
return result.modified_count > 0
|
| 221 |
except HTTPException as he:
|
| 222 |
raise he
|
|
|
|
| 248 |
return True
|
| 249 |
|
| 250 |
# Check for rate limiting (e.g., max 3 requests per hour)
|
| 251 |
+
reset_requests = mongo_db.users.count_documents({
|
| 252 |
"email": email.lower(),
|
| 253 |
"reset_password_timestamp": {
|
| 254 |
"$gte": datetime.now(tz=timezone.utc) - timedelta(hours=1)
|
|
|
|
| 265 |
expiry = datetime.now() + timedelta(minutes=10)
|
| 266 |
|
| 267 |
# Store reset token and timestamp in database
|
| 268 |
+
mongo_db.users.update_one(
|
| 269 |
{"_id": ObjectId(user["_id"])},
|
| 270 |
{
|
| 271 |
"$set": {
|
|
|
|
| 380 |
expiry = datetime.now() + timedelta(minutes=10)
|
| 381 |
|
| 382 |
# Store code and expiry in database
|
| 383 |
+
result = mongo_db.users.update_one(
|
| 384 |
{"email": email.lower()},
|
| 385 |
{
|
| 386 |
"$set": {
|
|
|
|
| 425 |
HTTPException: Nếu mã không hợp lệ, đã hết hạn hoặc có lỗi hệ thống.
|
| 426 |
"""
|
| 427 |
try:
|
| 428 |
+
user = mongo_db.users.find_one({ # Sử dụng await nếu mongo_db.users là async (ví dụ Motor)
|
| 429 |
"email": email.lower(),
|
| 430 |
"login_verification_code": code
|
| 431 |
})
|
|
|
|
| 443 |
if not expiry or expiry < datetime.now(expiry.tzinfo if expiry.tzinfo else None): # So sánh aware với aware, naive với naive
|
| 444 |
logger.warning(f"Mã xác minh đã hết hạn cho email: {email}")
|
| 445 |
# Xóa mã đã hết hạn để tránh sử dụng lại
|
| 446 |
+
mongo_db.users.update_one(
|
| 447 |
{"_id": ObjectId(user["_id"])},
|
| 448 |
{
|
| 449 |
"$unset": {
|
|
|
|
| 509 |
# --------------------
|
| 510 |
|
| 511 |
# Clear verification code và cập nhật last_login
|
| 512 |
+
mongo_db.users.update_one( # Sử dụng await nếu là async
|
| 513 |
{"_id": ObjectId(user["_id"])},
|
| 514 |
{
|
| 515 |
"$unset": {
|
|
|
|
| 567 |
Raises:
|
| 568 |
HTTPException: Nếu thông tin đăng nhập không hợp lệ.
|
| 569 |
"""
|
| 570 |
+
user = mongo_db.users.find_one({"email": request.email.lower()})
|
| 571 |
if not user or not pwd_context.verify(request.password, user["password"]):
|
| 572 |
logger.warning(f"Xác thực thất bại cho email: {request.email}")
|
| 573 |
raise HTTPException(
|
|
|
|
| 603 |
)
|
| 604 |
|
| 605 |
# Find user by refresh token in database
|
| 606 |
+
user = mongo_db.users.find_one({"refresh_token": refresh_token})
|
| 607 |
|
| 608 |
|
| 609 |
if not user:
|
|
|
|
| 640 |
new_refresh_token = await create_refresh_token(email)
|
| 641 |
|
| 642 |
# Update database with new refresh token
|
| 643 |
+
mongo_db.users.update_one(
|
| 644 |
{"_id": user["_id"]},
|
| 645 |
{
|
| 646 |
"$set": {
|
utils/utils.py
CHANGED
|
@@ -233,7 +233,7 @@ async def create_refresh_token(email: str) -> str:
|
|
| 233 |
|
| 234 |
|
| 235 |
# Store refresh token in database
|
| 236 |
-
result =
|
| 237 |
{"email": email.lower()},
|
| 238 |
{
|
| 239 |
"$set": {
|
|
|
|
| 233 |
|
| 234 |
|
| 235 |
# Store refresh token in database
|
| 236 |
+
result = mongo_db.users.update_one(
|
| 237 |
{"email": email.lower()},
|
| 238 |
{
|
| 239 |
"$set": {
|