Ali2206 commited on
Commit
8fbc1f3
·
verified ·
1 Parent(s): 77b0666

Update api/routes/auth.py

Browse files
Files changed (1) hide show
  1. api/routes/auth.py +89 -136
api/routes/auth.py CHANGED
@@ -1,160 +1,113 @@
1
- from fastapi import APIRouter, HTTPException, Depends, status, Request
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(request: Request, current_user: dict = Depends(get_current_user)):
126
- logger.info(f"Fetching user profile for {current_user['email']}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
127
  try:
128
- user = await users_collection.find_one({"email": current_user["email"]})
129
- if not user:
130
- logger.warning(f"User not found: {current_user['email']}")
131
- raise HTTPException(
132
- status_code=status.HTTP_404_NOT_FOUND,
133
- detail="User not found"
134
- )
135
-
136
- response = {
137
- "id": str(user["_id"]),
138
- "email": user["email"],
139
- "full_name": user.get("full_name", ""),
140
- "role": user.get("role", "patient"),
141
- "specialty": user.get("specialty"),
142
- "created_at": user.get("created_at"),
143
- "updated_at": user.get("updated_at")
144
- }
145
- logger.info(f"User profile retrieved for {current_user['email']}")
146
- return response
147
  except Exception as e:
148
- logger.error(f"Database error for user {current_user['email']}: {str(e)}")
149
  raise HTTPException(
150
  status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
151
- detail=f"Database error: {str(e)}"
152
  )
153
 
154
- @router.get("/test-auth")
155
- async def test_token_auth(current_user: dict = Depends(get_current_user)):
156
- logger.info(f"Test auth successful for {current_user.get('email')}")
157
- return {"status": "ok", "email": current_user.get("email"), "role": current_user.get("role")}
158
-
159
- # Export the router
160
- auth = router
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi import APIRouter, Depends, HTTPException, status, Request
2
  from fastapi.security import OAuth2PasswordRequestForm
3
+ from db.mongo import get_user_db
4
+ from core.security import (
5
+ create_access_token,
6
+ verify_token,
7
+ get_password_hash,
8
+ verify_password
 
 
 
 
9
  )
10
+ from models.schemas import (
11
+ TokenResponse,
12
+ UserCreate,
13
+ UserInDB,
14
+ UserResponse
15
+ )
16
+ from datetime import timedelta
17
+ import logging
18
+ from core.config import settings
19
 
20
  router = APIRouter()
21
+ logger = logging.getLogger(__name__)
22
 
23
+ @router.post("/login", response_model=TokenResponse)
24
+ async def login(
25
+ request: Request,
26
+ form_data: OAuth2PasswordRequestForm = Depends()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
  ):
28
+ logger.info(f"Login attempt from {request.client.host}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29
 
30
+ user_db = await get_user_db()
31
+ user = await user_db.find_one({"email": form_data.username.lower()})
 
 
 
 
 
 
 
 
 
32
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33
  if not user or not verify_password(form_data.password, user["password"]):
34
+ logger.warning(f"Failed login attempt for {form_data.username}")
35
  raise HTTPException(
36
  status_code=status.HTTP_401_UNAUTHORIZED,
37
+ detail="Incorrect email or password",
38
+ headers={"WWW-Authenticate": "Bearer"},
39
  )
40
+
41
+ access_token_expires = timedelta(minutes=settings.ACCESS_TOKEN_EXPIRE_MINUTES)
42
+ access_token = create_access_token(
43
+ data={"sub": user["email"], "role": user.get("role", "user")},
44
+ expires_delta=access_token_expires
45
+ )
46
 
47
+ logger.info(f"Successful login for {user['email']}")
 
48
  return {
49
  "access_token": access_token,
50
  "token_type": "bearer",
51
+ "expires_in": access_token_expires.total_seconds()
52
  }
53
 
54
+ @router.post("/signup", response_model=UserResponse)
55
+ async def signup(user_in: UserCreate):
56
+ logger.info(f"Signup attempt for {user_in.email}")
57
+
58
+ user_db = await get_user_db()
59
+ if await user_db.find_one({"email": user_in.email.lower()}):
60
+ logger.warning(f"Email already registered: {user_in.email}")
61
+ raise HTTPException(
62
+ status_code=status.HTTP_400_BAD_REQUEST,
63
+ detail="Email already registered"
64
+ )
65
+
66
+ hashed_password = get_password_hash(user_in.password)
67
+ db_user = UserInDB(
68
+ **user_in.dict(),
69
+ password=hashed_password,
70
+ role="user",
71
+ created_at=datetime.utcnow(),
72
+ updated_at=datetime.utcnow()
73
+ )
74
+
75
  try:
76
+ result = await user_db.insert_one(db_user.dict())
77
+ logger.info(f"User created: {user_in.email}")
78
+ return UserResponse(
79
+ id=str(result.inserted_id),
80
+ email=db_user.email,
81
+ full_name=db_user.full_name,
82
+ role=db_user.role
83
+ )
 
 
 
 
 
 
 
 
 
 
 
84
  except Exception as e:
85
+ logger.error(f"User creation failed: {str(e)}")
86
  raise HTTPException(
87
  status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
88
+ detail="User creation failed"
89
  )
90
 
91
+ @router.get("/me", response_model=UserResponse)
92
+ async def read_users_me(
93
+ request: Request,
94
+ current_user: UserInDB = Depends(verify_token)
95
+ ):
96
+ logger.info(f"User profile request for {current_user.sub}")
97
+
98
+ user_db = await get_user_db()
99
+ user = await user_db.find_one({"email": current_user.sub})
100
+
101
+ if not user:
102
+ logger.error(f"User not found: {current_user.sub}")
103
+ raise HTTPException(
104
+ status_code=status.HTTP_404_NOT_FOUND,
105
+ detail="User not found"
106
+ )
107
+
108
+ return UserResponse(
109
+ id=str(user["_id"]),
110
+ email=user["email"],
111
+ full_name=user.get("full_name", ""),
112
+ role=user.get("role", "user")
113
+ )