Ali2206 commited on
Commit
76270ab
·
verified ·
1 Parent(s): 97f5ed3

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +0 -204
app.py CHANGED
@@ -1,208 +1,4 @@
1
- from fastapi import FastAPI, Request, HTTPException
2
- from fastapi.middleware.cors import CORSMiddleware
3
- from fastapi.responses import RedirectResponse
4
- from api import api_router
5
- import gradio as gr
6
- import aiohttp
7
- import asyncio
8
- import logging
9
- import time
10
- from typing import Optional
11
- from pydantic import BaseModel
12
-
13
- # Configure logging
14
- logging.basicConfig(
15
- level=logging.DEBUG,
16
- format="%(asctime)s - %(levelname)s - %(name)s - %(message)s"
17
- )
18
- logger = logging.getLogger(__name__)
19
- logger.debug("Initializing application")
20
-
21
- app = FastAPI()
22
-
23
- # CORS Configuration (restrict in production)
24
- app.add_middleware(
25
- CORSMiddleware,
26
- allow_origins=["*"],
27
- allow_credentials=True,
28
- allow_methods=["*"],
29
- allow_headers=["*"],
30
- )
31
-
32
- app.include_router(api_router)
33
-
34
- # Constants
35
- BACKEND_URL = "https://rocketfarmstudios-cps-api.hf.space" # Update if different backend
36
- ADMIN_EMAIL = "yakdhanali97@gmail.com"
37
- ADMIN_PASSWORD = "123456"
38
- MAX_TOKEN_RETRIES = 3
39
- TOKEN_RETRY_DELAY = 2 # seconds
40
- TOKEN_EXPIRY = 3600 # 1 hour default expiry
41
-
42
- # Pydantic models
43
- class LoginPayload(BaseModel):
44
- email: str
45
- password: str
46
-
47
- class DoctorPayload(BaseModel):
48
- full_name: str
49
- email: str
50
- license_number: str
51
- password: str
52
- specialty: str
53
-
54
- class TokenManager:
55
- def __init__(self):
56
- self.token = None
57
- self.last_refresh = 0
58
- self.expires_in = TOKEN_EXPIRY
59
- self.lock = asyncio.Lock()
60
-
61
- async def _make_login_request(self) -> Optional[str]:
62
- try:
63
- async with aiohttp.ClientSession() as session:
64
- payload = LoginPayload(
65
- email=ADMIN_EMAIL,
66
- password=ADMIN_PASSWORD
67
- )
68
- login_url = f"{BACKEND_URL.rstrip('/')}/auth/login"
69
- logger.debug(f"Sending login request to {login_url} with payload: {payload.dict()}")
70
- async with session.post(
71
- login_url,
72
- json=payload.dict(),
73
- timeout=15,
74
- headers={"Content-Type": "application/json"}
75
- ) as response:
76
- logger.debug(f"Login response status: {response.status}, URL: {response.url}")
77
- if response.status == 200:
78
- data = await response.json()
79
- token = data.get("access_token")
80
- if not token:
81
- logger.error("No access_token in response")
82
- return None
83
- logger.info(f"Received token: {token[:10]}...")
84
- return token
85
- else:
86
- error = await response.text()
87
- logger.error(f"Login failed: {response.status} - {error}, URL: {response.url}")
88
- return None
89
- except aiohttp.ClientError as e:
90
- logger.error(f"Login request error: {str(e)}, URL: {login_url}")
91
- return None
92
-
93
- async def refresh_token(self) -> str:
94
- async with self.lock:
95
- for attempt in range(MAX_TOKEN_RETRIES):
96
- token = await self._make_login_request()
97
- if token:
98
- self.token = token
99
- self.last_refresh = time.time()
100
- logger.info("Successfully refreshed admin token")
101
- return token
102
-
103
- wait_time = min(5, (attempt + 1) * TOKEN_RETRY_DELAY)
104
- logger.warning(f"Attempt {attempt + 1} failed, retrying in {wait_time}s...")
105
- await asyncio.sleep(wait_time)
106
-
107
- raise HTTPException(status_code=500, detail="Failed to obtain admin token after multiple attempts")
108
-
109
- async def get_token(self) -> str:
110
- if not self.token or (time.time() - self.last_refresh) > (self.expires_in - 60):
111
- return await self.refresh_token()
112
- return self.token
113
-
114
- token_manager = TokenManager()
115
-
116
- @app.get("/")
117
- def root():
118
- logger.debug("Root endpoint accessed")
119
- return {"message": "🚀 FastAPI with MongoDB + JWT is running."}
120
-
121
- @app.post("/login")
122
- async def redirect_login(request: Request):
123
- logger.info("Redirecting /login to /auth/login")
124
- return RedirectResponse(url="/auth/login", status_code=307)
125
-
126
- async def async_create_doctor(full_name: str, email: str, license_number: str, specialty: str, password: str):
127
- try:
128
- # Validate inputs
129
- if not all([full_name, email, license_number, specialty, password]):
130
- logger.error("Doctor creation failed: All fields are required")
131
- raise HTTPException(status_code=422, detail="All fields are required")
132
-
133
- token = await token_manager.get_token()
134
-
135
- payload = DoctorPayload(
136
- full_name=full_name,
137
- email=email,
138
- license_number=license_number,
139
- password=password,
140
- specialty=specialty
141
- )
142
- headers = {
143
- "Authorization": f"Bearer {token}",
144
- "Content-Type": "application/json"
145
- }
146
-
147
- doctor_url = f"{BACKEND_URL.rstrip('/')}/auth/admin/doctors"
148
- logger.debug(f"Sending doctor creation request to {doctor_url} with payload: {payload.dict()}")
149
- async with aiohttp.ClientSession() as session:
150
- async with session.post(
151
- doctor_url,
152
- json=payload.dict(),
153
- headers=headers,
154
- timeout=15
155
- ) as response:
156
- logger.debug(f"Doctor creation response status: {response.status}, URL: {response.url}")
157
- if response.status == 201:
158
- return "✅ Doctor created successfully!"
159
- elif response.status == 401:
160
- logger.warning("Token expired, attempting refresh...")
161
- token = await token_manager.refresh_token()
162
- headers["Authorization"] = f"Bearer {token}"
163
- async with session.post(
164
- doctor_url,
165
- json=payload.dict(),
166
- headers=headers,
167
- timeout=15
168
- ) as retry_response:
169
- logger.debug(f"Retry doctor creation response status: {retry_response.status}, URL: {retry_response.url}")
170
- if retry_response.status == 201:
171
- return "✅ Doctor created successfully!"
172
- error_detail = await retry_response.text()
173
- return f"❌ Error: {error_detail} (Status: {retry_response.status})"
174
-
175
- error_detail = await response.text()
176
- return f"❌ Error: {error_detail} (Status: {response.status})"
177
-
178
- except HTTPException as e:
179
- logger.error(f"Doctor creation failed: {str(e)}")
180
- return f"❌ Error: {str(e)}"
181
- except Exception as e:
182
- logger.error(f"Doctor creation failed: {str(e)}")
183
- return f"❌ System Error: {str(e)}"
184
-
185
- def sync_create_doctor(full_name: str, email: str, license_number: str, specialty: str, password: str):
186
- return asyncio.run(async_create_doctor(full_name, email, license_number, specialty, password))
187
-
188
- # New endpoint for public doctor creation
189
- @app.post("/create-doctor")
190
- async def create_doctor(payload: DoctorPayload):
191
- result = await async_create_doctor(
192
- full_name=payload.full_name,
193
- email=payload.email,
194
- license_number=payload.lice
195
- System: I notice the code in the artifact appears incomplete, as it cuts off mid-line in the `/create-doctor` endpoint. I'll provide a corrected and complete version of the updated `app.py` to ensure the `/create-doctor` endpoint and all other functionality are fully implemented. I'll also address the 422 error by ensuring the `TokenManager` sends the correct payload to the `/auth/login` endpoint, based on the Postman test results indicating the backend expects `username` and `password` fields.
196
-
197
- ### Updated Code with Fixes
198
- The following code:
199
- - Updates the `LoginPayload` model to use `username` instead of `email`, matching the backend’s expected schema (based on the 422 error).
200
- - Completes the `/create-doctor` endpoint.
201
- - Preserves all other functionality (`/admin`, `/test-backend`, Gradio UI, etc.).
202
- - Includes environment variable support for `BACKEND_URL` to allow easy configuration.
203
- - Adds detailed logging to debug payload issues.
204
 
205
- <xaiArtifact artifact_id="0bf1081b-f3f2-4a40-9616-4a9b212f1422" artifact_version_id="0b44a4c4-6f14-45b8-bbbe-50e0dded5ed0" title="app.py" contentType="text/python">
206
  from fastapi import FastAPI, Request, HTTPException
207
  from fastapi.middleware.cors import CORSMiddleware
208
  from fastapi.responses import RedirectResponse
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
 
 
2
  from fastapi import FastAPI, Request, HTTPException
3
  from fastapi.middleware.cors import CORSMiddleware
4
  from fastapi.responses import RedirectResponse