Spaces:
Sleeping
Sleeping
Add the endpoints for login, signup, forgot password
Browse files- app/models/__pycache__/user.cpython-311.pyc +0 -0
- app/models/user.py +9 -0
- app/routers/__pycache__/user.cpython-311.pyc +0 -0
- app/routers/user.py +50 -3
- test_endpoint.py +11 -11
app/models/__pycache__/user.cpython-311.pyc
CHANGED
|
Binary files a/app/models/__pycache__/user.cpython-311.pyc and b/app/models/__pycache__/user.cpython-311.pyc differ
|
|
|
app/models/user.py
CHANGED
|
@@ -1,6 +1,7 @@
|
|
| 1 |
from pydantic import BaseModel, EmailStr
|
| 2 |
|
| 3 |
class UserCreate(BaseModel):
|
|
|
|
| 4 |
email: EmailStr
|
| 5 |
password: str
|
| 6 |
|
|
@@ -20,3 +21,11 @@ class UserOut(BaseModel):
|
|
| 20 |
role: str
|
| 21 |
companies: list[str]
|
| 22 |
chatbots: list[str]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
from pydantic import BaseModel, EmailStr
|
| 2 |
|
| 3 |
class UserCreate(BaseModel):
|
| 4 |
+
full_name: str
|
| 5 |
email: EmailStr
|
| 6 |
password: str
|
| 7 |
|
|
|
|
| 21 |
role: str
|
| 22 |
companies: list[str]
|
| 23 |
chatbots: list[str]
|
| 24 |
+
|
| 25 |
+
class SecurityQuestionsPayload(BaseModel):
|
| 26 |
+
user_id: str
|
| 27 |
+
questions: dict
|
| 28 |
+
|
| 29 |
+
class SecurityAnswerPayload(BaseModel):
|
| 30 |
+
email: str
|
| 31 |
+
answers: dict[str,str]
|
app/routers/__pycache__/user.cpython-311.pyc
CHANGED
|
Binary files a/app/routers/__pycache__/user.cpython-311.pyc and b/app/routers/__pycache__/user.cpython-311.pyc differ
|
|
|
app/routers/user.py
CHANGED
|
@@ -28,11 +28,12 @@ async def create_user(payload: UserCreate):
|
|
| 28 |
|
| 29 |
user_doc = {
|
| 30 |
"_id": user_id,
|
|
|
|
| 31 |
"email": payload.email,
|
| 32 |
"hashed_password": hashed,
|
| 33 |
-
"role": "member",
|
| 34 |
"companies": [],
|
| 35 |
"chatbots": [],
|
|
|
|
| 36 |
"created_at": datetime.now(timezone.utc)
|
| 37 |
}
|
| 38 |
|
|
@@ -42,8 +43,17 @@ async def create_user(payload: UserCreate):
|
|
| 42 |
except Exception as e:
|
| 43 |
print(f"Failed to create user: {e}")
|
| 44 |
|
| 45 |
-
return {"message": "Success"}
|
| 46 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 47 |
|
| 48 |
@router.post("/login")
|
| 49 |
async def login(payload: UserLogin):
|
|
@@ -60,4 +70,41 @@ async def login(payload: UserLogin):
|
|
| 60 |
"access_token": access_token,
|
| 61 |
"token_type": "bearer",
|
| 62 |
"user_id": existing["_id"]
|
| 63 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 28 |
|
| 29 |
user_doc = {
|
| 30 |
"_id": user_id,
|
| 31 |
+
"full_name": payload.full_name,
|
| 32 |
"email": payload.email,
|
| 33 |
"hashed_password": hashed,
|
|
|
|
| 34 |
"companies": [],
|
| 35 |
"chatbots": [],
|
| 36 |
+
"security_questions": {},
|
| 37 |
"created_at": datetime.now(timezone.utc)
|
| 38 |
}
|
| 39 |
|
|
|
|
| 43 |
except Exception as e:
|
| 44 |
print(f"Failed to create user: {e}")
|
| 45 |
|
| 46 |
+
return {"message": "Success", "user_id": user_id}
|
| 47 |
|
| 48 |
+
@router.post("/register/security-questions")
|
| 49 |
+
async def set_security_questions(payload: SecurityQuestionsPayload):
|
| 50 |
+
user = await users.find_one({"_id": payload.user_id})
|
| 51 |
+
if not user:
|
| 52 |
+
raise HTTPException(status_code=404, detail="User Not Found")
|
| 53 |
+
|
| 54 |
+
hashed_questions = {q: hash_password(a) for q,a in payload.questions.items()}
|
| 55 |
+
await users.update_one({"_id": payload.user_id}, {"$set" : {"security_questions": hashed_questions}})
|
| 56 |
+
return {"message": "Security questions set successfully"}
|
| 57 |
|
| 58 |
@router.post("/login")
|
| 59 |
async def login(payload: UserLogin):
|
|
|
|
| 70 |
"access_token": access_token,
|
| 71 |
"token_type": "bearer",
|
| 72 |
"user_id": existing["_id"]
|
| 73 |
+
}
|
| 74 |
+
|
| 75 |
+
@router.post("/forgot-password/email")
|
| 76 |
+
async def verify_email(email: str):
|
| 77 |
+
user = await users.find_one({"email": email})
|
| 78 |
+
if not user:
|
| 79 |
+
raise HTTPException(status_code=404, detail="User email not in our records")
|
| 80 |
+
|
| 81 |
+
questions = list(user["security_questions"].keys())
|
| 82 |
+
return {"questions": questions}
|
| 83 |
+
|
| 84 |
+
|
| 85 |
+
@router.post("/forgot-password/verify")
|
| 86 |
+
async def verify_security_answer(payload: SecurityAnswerPayload):
|
| 87 |
+
email = payload.email
|
| 88 |
+
answers = payload.answers
|
| 89 |
+
|
| 90 |
+
user = await users.find_one({"email": email})
|
| 91 |
+
if not user:
|
| 92 |
+
raise HTTPException(status_code=404, detail="User not found")
|
| 93 |
+
|
| 94 |
+
for question, answer in answers.items():
|
| 95 |
+
if question not in user["security_questions"] or \
|
| 96 |
+
not verify_password(answer, user["security_questions"][question]):
|
| 97 |
+
raise HTTPException(status_code=400, detail="One or more security answers are incorrect")
|
| 98 |
+
|
| 99 |
+
return {"message": "Verification successful"}
|
| 100 |
+
|
| 101 |
+
@router.post("/forgot-password/reset")
|
| 102 |
+
async def reset_pass(email: str, new_pass: str):
|
| 103 |
+
user = await users.find_one({"email": email})
|
| 104 |
+
if not user:
|
| 105 |
+
raise HTTPException(status_code=404, detail="User not Found")
|
| 106 |
+
|
| 107 |
+
hashed = hash_password(new_pass)
|
| 108 |
+
await users.update_one({"email": email}, {"$set": {"hashed_password": hashed}})
|
| 109 |
+
|
| 110 |
+
return {"message": "Password reset successfully"}
|
test_endpoint.py
CHANGED
|
@@ -9,20 +9,26 @@ def safe_print_response(resp):
|
|
| 9 |
except Exception:
|
| 10 |
print("Raw response text:", resp.text)
|
| 11 |
|
| 12 |
-
# 1️⃣ Register a user
|
| 13 |
register_data = {
|
| 14 |
-
"email": "
|
| 15 |
-
"password": "
|
|
|
|
|
|
|
|
|
|
|
|
|
| 16 |
}
|
|
|
|
| 17 |
resp = requests.post(f"{BASE_URL}/auth/register", json=register_data)
|
| 18 |
print("Register Response:")
|
| 19 |
safe_print_response(resp)
|
| 20 |
|
| 21 |
# 2️⃣ Login to get JWT token
|
| 22 |
login_data = {
|
| 23 |
-
"email": "
|
| 24 |
-
"password": "
|
| 25 |
}
|
|
|
|
| 26 |
resp = requests.post(f"{BASE_URL}/auth/login", json=login_data)
|
| 27 |
print("\nLogin Response:")
|
| 28 |
safe_print_response(resp)
|
|
@@ -30,11 +36,5 @@ safe_print_response(resp)
|
|
| 30 |
if resp.status_code == 200:
|
| 31 |
token = resp.json().get("access_token")
|
| 32 |
print("\nJWT Access Token:", token)
|
| 33 |
-
|
| 34 |
-
# 3️⃣ Example: Test a dummy protected route (if you implement one)
|
| 35 |
-
# headers = {"Authorization": f"Bearer {token}"}
|
| 36 |
-
# protected_resp = requests.get(f"{BASE_URL}/protected", headers=headers)
|
| 37 |
-
# print("\nProtected Route Response:")
|
| 38 |
-
# safe_print_response(protected_resp)
|
| 39 |
else:
|
| 40 |
print("Login failed, cannot test protected route")
|
|
|
|
| 9 |
except Exception:
|
| 10 |
print("Raw response text:", resp.text)
|
| 11 |
|
| 12 |
+
# 1️⃣ Register a user with correct field names
|
| 13 |
register_data = {
|
| 14 |
+
"email": "test@example.com",
|
| 15 |
+
"password": "test",
|
| 16 |
+
"security_question_1": "What is your favorite color?",
|
| 17 |
+
"security_answer_1": "Blue",
|
| 18 |
+
"security_question_2": "What is your mother's maiden name?",
|
| 19 |
+
"security_answer_2": "Smith"
|
| 20 |
}
|
| 21 |
+
|
| 22 |
resp = requests.post(f"{BASE_URL}/auth/register", json=register_data)
|
| 23 |
print("Register Response:")
|
| 24 |
safe_print_response(resp)
|
| 25 |
|
| 26 |
# 2️⃣ Login to get JWT token
|
| 27 |
login_data = {
|
| 28 |
+
"email": "test@example.com",
|
| 29 |
+
"password": "test"
|
| 30 |
}
|
| 31 |
+
|
| 32 |
resp = requests.post(f"{BASE_URL}/auth/login", json=login_data)
|
| 33 |
print("\nLogin Response:")
|
| 34 |
safe_print_response(resp)
|
|
|
|
| 36 |
if resp.status_code == 200:
|
| 37 |
token = resp.json().get("access_token")
|
| 38 |
print("\nJWT Access Token:", token)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 39 |
else:
|
| 40 |
print("Login failed, cannot test protected route")
|