Ali2206 commited on
Commit
ff07255
·
verified ·
1 Parent(s): 8db2f16

Update api/routes/auth.py

Browse files
Files changed (1) hide show
  1. api/routes/auth.py +145 -0
api/routes/auth.py CHANGED
@@ -0,0 +1,145 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi import APIRouter, HTTPException, Depends, status
2
+ from fastapi.security import OAuth2PasswordRequestForm
3
+ from ...db.mongo import users_collection
4
+ from ...core.security import hash_password, verify_password, create_access_token, get_current_user
5
+ from ...models.schemas import SignupForm, TokenResponse, DoctorCreate
6
+ from datetime import datetime
7
+ import logging
8
+
9
+ # Configure logging
10
+ logging.basicConfig(
11
+ level=logging.INFO,
12
+ format='%(asctime)s - %(levelname)s - %(name)s - %(message)s'
13
+ )
14
+ logger = logging.getLogger(__name__)
15
+
16
+ router = APIRouter()
17
+
18
+ @router.post("/signup", status_code=status.HTTP_201_CREATED)
19
+ async def signup(data: SignupForm):
20
+ logger.info(f"Signup attempt for email: {data.email}")
21
+ email = data.email.lower().strip()
22
+ existing = await users_collection.find_one({"email": email})
23
+ if existing:
24
+ logger.warning(f"Signup failed: Email already exists: {email}")
25
+ raise HTTPException(
26
+ status_code=status.HTTP_409_CONFLICT,
27
+ detail="Email already exists"
28
+ )
29
+
30
+ hashed_pw = hash_password(data.password)
31
+ user_doc = {
32
+ "email": email,
33
+ "full_name": data.full_name.strip(),
34
+ "password": hashed_pw,
35
+ "role": "patient",
36
+ "created_at": datetime.utcnow().isoformat(),
37
+ "updated_at": datetime.utcnow().isoformat()
38
+ }
39
+
40
+ try:
41
+ result = await users_collection.insert_one(user_doc)
42
+ logger.info(f"User created successfully: {email}")
43
+ return {
44
+ "status": "success",
45
+ "id": str(result.inserted_id),
46
+ "email": email
47
+ }
48
+ except Exception as e:
49
+ logger.error(f"Failed to create user {email}: {str(e)}")
50
+ raise HTTPException(
51
+ status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
52
+ detail=f"Failed to create user: {str(e)}"
53
+ )
54
+
55
+ @router.post("/admin/doctors", status_code=status.HTTP_201_CREATED)
56
+ async def create_doctor(
57
+ data: DoctorCreate,
58
+ current_user: dict = Depends(get_current_user)
59
+ ):
60
+ logger.info(f"Doctor creation attempt by {current_user.get('email')}")
61
+ if current_user.get('role') != 'admin':
62
+ logger.warning(f"Unauthorized doctor creation attempt by {current_user.get('email')}")
63
+ raise HTTPException(
64
+ status_code=status.HTTP_403_FORBIDDEN,
65
+ detail="Only admins can create doctor accounts"
66
+ )
67
+
68
+ email = data.email.lower().strip()
69
+ existing = await users_collection.find_one({"email": email})
70
+ if existing:
71
+ logger.warning(f"Doctor creation failed: Email already exists: {email}")
72
+ raise HTTPException(
73
+ status_code=status.HTTP_409_CONFLICT,
74
+ detail="Email already exists"
75
+ )
76
+
77
+ hashed_pw = hash_password(data.password)
78
+ doctor_doc = {
79
+ "email": email,
80
+ "full_name": data.full_name.strip(),
81
+ "password": hashed_pw,
82
+ "role": "doctor",
83
+ "specialty": data.specialty,
84
+ "license_number": data.license_number,
85
+ "created_at": datetime.utcnow().isoformat(),
86
+ "updated_at": datetime.utcnow().isoformat()
87
+ }
88
+
89
+ try:
90
+ result = await users_collection.insert_one(doctor_doc)
91
+ logger.info(f"Doctor created successfully: {email}")
92
+ return {
93
+ "status": "success",
94
+ "id": str(result.inserted_id),
95
+ "email": email
96
+ }
97
+ except Exception as e:
98
+ logger.error(f"Failed to create doctor {email}: {str(e)}")
99
+ raise HTTPException(
100
+ status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
101
+ detail=f"Failed to create doctor: {str(e)}"
102
+ )
103
+
104
+ @router.post("/login", response_model=TokenResponse)
105
+ async def login(form_data: OAuth2PasswordRequestForm = Depends()):
106
+ logger.info(f"Login attempt for email: {form_data.username}")
107
+ user = await users_collection.find_one({"email": form_data.username.lower()})
108
+ if not user or not verify_password(form_data.password, user["password"]):
109
+ logger.warning(f"Login failed for {form_data.username}: Invalid credentials")
110
+ raise HTTPException(
111
+ status_code=status.HTTP_401_UNAUTHORIZED,
112
+ detail="Invalid credentials",
113
+ headers={"WWW-Authenticate": "Bearer"},
114
+ )
115
+
116
+ access_token = create_access_token(data={"sub": user["email"]})
117
+ logger.info(f"Successful login for {form_data.username}")
118
+ return {
119
+ "access_token": access_token,
120
+ "token_type": "bearer",
121
+ "role": user.get("role", "patient")
122
+ }
123
+
124
+ @router.get("/me")
125
+ async def get_me(current_user: dict = Depends(get_current_user)):
126
+ logger.info(f"Fetching user profile for {current_user['email']}")
127
+ user = await users_collection.find_one({"email": current_user["email"]})
128
+ if not user:
129
+ logger.warning(f"User not found: {current_user['email']}")
130
+ raise HTTPException(
131
+ status_code=status.HTTP_404_NOT_FOUND,
132
+ detail="User not found"
133
+ )
134
+
135
+ response = {
136
+ "id": str(user["_id"]),
137
+ "email": user["email"],
138
+ "full_name": user.get("full_name", ""),
139
+ "role": user.get("role", "patient"),
140
+ "specialty": user.get("specialty"),
141
+ "created_at": user.get("created_at"),
142
+ "updated_at": user.get("updated_at")
143
+ }
144
+ logger.info(f"User profile retrieved for {current_user['email']}")
145
+ return response