Yadav122 commited on
Commit
c5c9b05
·
1 Parent(s): 932e12c

add firebase

Browse files
.env CHANGED
@@ -27,6 +27,7 @@ BEDROCK_PROVIDER=anthropic
27
  AWS_ACCESS_KEY=
28
  AWS_SECRET_KEY=
29
  AWS_REGION=us-east-1
 
30
 
31
 
32
 
 
27
  AWS_ACCESS_KEY=
28
  AWS_SECRET_KEY=
29
  AWS_REGION=us-east-1
30
+ FIREBASE_API_KEY=AIzaSyDGHPfzwPiVGWccTnnyPcEoS-FU6He6tDs
31
 
32
 
33
 
app/api/endpoints/v1/firebaseauth/__pycache__/app.cpython-312.pyc CHANGED
Binary files a/app/api/endpoints/v1/firebaseauth/__pycache__/app.cpython-312.pyc and b/app/api/endpoints/v1/firebaseauth/__pycache__/app.cpython-312.pyc differ
 
app/api/endpoints/v1/firebaseauth/app.py CHANGED
@@ -1,4 +1,6 @@
 
1
  import datetime
 
2
  from app import router
3
  from fastapi import FastAPI, Depends, HTTPException, status, Request, APIRouter
4
  from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
@@ -6,13 +8,12 @@ import firebase_admin
6
  from firebase_admin import credentials, auth
7
  from sqlalchemy.ext.asyncio import AsyncSession
8
  from sqlalchemy import select
9
- from app.models.api.user import UserCreate, UserSignIn, PasswordReset, TokenVerify, UserResponse,EmailVerifyRequest
10
  from app.models.database.DBUser import DBUser
11
  from app.core.database.session_manager import get_db_session as get_db
12
- import os
13
 
14
 
15
- router=APIRouter(prefix="/FirebaseAuth", tags=["Firebase Auth"])
16
 
17
  # Initialize OAuth2 scheme
18
  oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/FirebaseAuth/token")
@@ -42,7 +43,6 @@ async def verify_firebase_token(token: str = Depends(oauth2_scheme)) -> dict:
42
 
43
  # Initialize Firebase Admin SDK with better error handling
44
  try:
45
-
46
  current_dir = os.path.dirname(os.path.abspath(__file__))
47
  # Try multiple possible paths for the service account file
48
  service_account_paths = [
@@ -148,15 +148,41 @@ async def create_user(user_data: UserCreate, db: AsyncSession = Depends(get_db))
148
  async def signin_user(user_data: UserSignIn, db: AsyncSession = Depends(get_db)):
149
  """Sign in user and return token"""
150
  try:
151
- # Verify user exists in Firebase
152
- firebase_user = auth.get_user_by_email(user_data.email)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
153
 
154
- # Generate custom token
155
- custom_token = auth.create_custom_token(firebase_user.uid)
 
 
 
 
156
 
157
  # Update last login in database
158
  result = await db.execute(
159
- select(DBUser).filter(DBUser.firebase_uid == firebase_user.uid)
160
  )
161
  db_user = result.scalar_one_or_none()
162
 
@@ -165,7 +191,7 @@ async def signin_user(user_data: UserSignIn, db: AsyncSession = Depends(get_db))
165
  await db.commit()
166
 
167
  return {
168
- "access_token": custom_token.decode() if isinstance(custom_token, bytes) else custom_token,
169
  "token_type": "bearer",
170
  "user": {
171
  "firebase_uid": firebase_user.uid,
@@ -175,6 +201,8 @@ async def signin_user(user_data: UserSignIn, db: AsyncSession = Depends(get_db))
175
  }
176
  }
177
  except Exception as e:
 
 
178
  raise HTTPException(
179
  status_code=status.HTTP_401_UNAUTHORIZED,
180
  detail=f"Authentication failed: {str(e)}"
@@ -218,7 +246,7 @@ async def get_current_user(
218
  @router.post("/resend-verification", status_code=status.HTTP_200_OK)
219
  async def resend_verification_email(
220
  email_data: EmailVerifyRequest = None,
221
- current_user: UserResponse = Depends(get_current_user)
222
  ):
223
  """
224
  Resend verification email to a user
@@ -229,7 +257,7 @@ async def resend_verification_email(
229
  try:
230
  # If email is provided in request body, use that
231
  # Otherwise use logged in user's email
232
- email = email_data.email if email_data else current_user.email
233
 
234
  # Check if user exists
235
  try:
@@ -266,9 +294,6 @@ async def resend_verification_email(
266
  detail=f"Failed to resend verification email: {str(e)}"
267
  )
268
 
269
-
270
- email: EmailStr
271
-
272
  @router.post("/check-email-verified")
273
  async def check_email_verified(email_data: EmailVerifyRequest):
274
  """Check if a user's email is verified"""
@@ -354,24 +379,60 @@ async def verify_token(token_data: TokenVerify, db: AsyncSession = Depends(get_d
354
  status_code=status.HTTP_401_UNAUTHORIZED,
355
  detail=f"Token verification failed: {str(e)}"
356
  )
 
357
  @router.post("/token")
358
- async def get_token(form_data: OAuth2PasswordRequestForm = Depends()):
359
- """Get access token"""
360
  try:
361
- # Get Firebase user
362
- firebase_user = auth.get_user_by_email(form_data.username)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
363
 
364
- # Create custom token
365
- custom_token = auth.create_custom_token(firebase_user.uid)
 
366
 
367
  return {
368
- "access_token": custom_token.decode() if isinstance(custom_token, bytes) else custom_token,
369
  "token_type": "bearer"
370
  }
371
  except Exception as e:
 
 
372
  raise HTTPException(
373
  status_code=status.HTTP_401_UNAUTHORIZED,
374
- detail="Invalid credentials"
375
  )
376
 
377
  # Function to verify token
@@ -388,5 +449,5 @@ async def verify_token(token: str = Depends(oauth2_scheme)):
388
 
389
  # Example protected route
390
  @router.get("/protected")
391
- async def protected_route(token: str = Depends(verify_token)):
392
  return {"message": "You have access!", "token_info": token}
 
1
+ import os
2
  import datetime
3
+ import requests
4
  from app import router
5
  from fastapi import FastAPI, Depends, HTTPException, status, Request, APIRouter
6
  from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
 
8
  from firebase_admin import credentials, auth
9
  from sqlalchemy.ext.asyncio import AsyncSession
10
  from sqlalchemy import select
11
+ from app.models.api.user import UserCreate, UserSignIn, PasswordReset, TokenVerify, UserResponse, EmailVerifyRequest
12
  from app.models.database.DBUser import DBUser
13
  from app.core.database.session_manager import get_db_session as get_db
 
14
 
15
 
16
+ router = APIRouter(prefix="/FirebaseAuth", tags=["Firebase Auth"])
17
 
18
  # Initialize OAuth2 scheme
19
  oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/FirebaseAuth/token")
 
43
 
44
  # Initialize Firebase Admin SDK with better error handling
45
  try:
 
46
  current_dir = os.path.dirname(os.path.abspath(__file__))
47
  # Try multiple possible paths for the service account file
48
  service_account_paths = [
 
148
  async def signin_user(user_data: UserSignIn, db: AsyncSession = Depends(get_db)):
149
  """Sign in user and return token"""
150
  try:
151
+ # Get Firebase API key from environment variable
152
+ api_key = os.getenv("FIREBASE_API_KEY")
153
+ if not api_key:
154
+ raise ValueError("FIREBASE_API_KEY environment variable is not set")
155
+
156
+ # Call Firebase Auth REST API to sign in with email/password
157
+ response = requests.post(
158
+ f"https://identitytoolkit.googleapis.com/v1/accounts:signInWithPassword?key={api_key}",
159
+ json={
160
+ "email": user_data.email,
161
+ "password": user_data.password,
162
+ "returnSecureToken": True
163
+ }
164
+ )
165
+
166
+ if response.status_code != 200:
167
+ error_data = response.json()
168
+ raise HTTPException(
169
+ status_code=status.HTTP_401_UNAUTHORIZED,
170
+ detail=f"Authentication failed: {error_data.get('error', {}).get('message', 'Invalid credentials')}"
171
+ )
172
+
173
+ auth_data = response.json()
174
+ id_token = auth_data["idToken"]
175
 
176
+ # Verify the ID token
177
+ decoded_token = auth.verify_id_token(id_token)
178
+ user_id = decoded_token["uid"]
179
+
180
+ # Get user from Firebase
181
+ firebase_user = auth.get_user(user_id)
182
 
183
  # Update last login in database
184
  result = await db.execute(
185
+ select(DBUser).filter(DBUser.firebase_uid == user_id)
186
  )
187
  db_user = result.scalar_one_or_none()
188
 
 
191
  await db.commit()
192
 
193
  return {
194
+ "access_token": id_token,
195
  "token_type": "bearer",
196
  "user": {
197
  "firebase_uid": firebase_user.uid,
 
201
  }
202
  }
203
  except Exception as e:
204
+ if isinstance(e, HTTPException):
205
+ raise e
206
  raise HTTPException(
207
  status_code=status.HTTP_401_UNAUTHORIZED,
208
  detail=f"Authentication failed: {str(e)}"
 
246
  @router.post("/resend-verification", status_code=status.HTTP_200_OK)
247
  async def resend_verification_email(
248
  email_data: EmailVerifyRequest = None,
249
+ current_user: dict = Depends(verify_firebase_token)
250
  ):
251
  """
252
  Resend verification email to a user
 
257
  try:
258
  # If email is provided in request body, use that
259
  # Otherwise use logged in user's email
260
+ email = email_data.email if email_data and email_data.email else current_user["email"]
261
 
262
  # Check if user exists
263
  try:
 
294
  detail=f"Failed to resend verification email: {str(e)}"
295
  )
296
 
 
 
 
297
  @router.post("/check-email-verified")
298
  async def check_email_verified(email_data: EmailVerifyRequest):
299
  """Check if a user's email is verified"""
 
379
  status_code=status.HTTP_401_UNAUTHORIZED,
380
  detail=f"Token verification failed: {str(e)}"
381
  )
382
+
383
  @router.post("/token")
384
+ async def get_token(form_data: OAuth2PasswordRequestForm = Depends(), db: AsyncSession = Depends(get_db)):
385
+ """Get access token using OAuth2 form"""
386
  try:
387
+ # Get Firebase API key from environment variable
388
+ api_key = os.getenv("FIREBASE_API_KEY")
389
+ if not api_key:
390
+ raise ValueError("FIREBASE_API_KEY environment variable is not set")
391
+
392
+ # Call Firebase Auth REST API to sign in with email/password
393
+ response = requests.post(
394
+ f"https://identitytoolkit.googleapis.com/v1/accounts:signInWithPassword?key={api_key}",
395
+ json={
396
+ "email": form_data.username, # Username field contains email
397
+ "password": form_data.password,
398
+ "returnSecureToken": True
399
+ }
400
+ )
401
+
402
+ if response.status_code != 200:
403
+ error_data = response.json()
404
+ raise HTTPException(
405
+ status_code=status.HTTP_401_UNAUTHORIZED,
406
+ detail=f"Authentication failed: {error_data.get('error', {}).get('message', 'Invalid credentials')}"
407
+ )
408
+
409
+ auth_data = response.json()
410
+ id_token = auth_data["idToken"]
411
+
412
+ # Verify the ID token
413
+ decoded_token = auth.verify_id_token(id_token)
414
+ user_id = decoded_token["uid"]
415
+
416
+ # Update last login in database
417
+ result = await db.execute(
418
+ select(DBUser).filter(DBUser.firebase_uid == user_id)
419
+ )
420
+ db_user = result.scalar_one_or_none()
421
 
422
+ if db_user:
423
+ db_user.last_login = datetime.datetime.utcnow()
424
+ await db.commit()
425
 
426
  return {
427
+ "access_token": id_token,
428
  "token_type": "bearer"
429
  }
430
  except Exception as e:
431
+ if isinstance(e, HTTPException):
432
+ raise e
433
  raise HTTPException(
434
  status_code=status.HTTP_401_UNAUTHORIZED,
435
+ detail=f"Authentication failed: {str(e)}"
436
  )
437
 
438
  # Function to verify token
 
449
 
450
  # Example protected route
451
  @router.get("/protected")
452
+ async def protected_route(token: dict = Depends(verify_token)):
453
  return {"message": "You have access!", "token_info": token}
logs/app.log CHANGED
@@ -18,3 +18,11 @@
18
  2025-04-18T15:44:43.336345Z [info ] Started server process [8]  [uvicorn.error] filename=server.py func_name=serve lineno=76
19
  2025-04-18T15:44:43.338237Z [info ] Waiting for application startup. [uvicorn.error] filename=on.py func_name=startup lineno=48
20
  2025-04-18T15:44:43.342127Z [info ] Application startup complete.  [uvicorn.error] filename=on.py func_name=startup lineno=62
 
 
 
 
 
 
 
 
 
18
  2025-04-18T15:44:43.336345Z [info ] Started server process [8]  [uvicorn.error] filename=server.py func_name=serve lineno=76
19
  2025-04-18T15:44:43.338237Z [info ] Waiting for application startup. [uvicorn.error] filename=on.py func_name=startup lineno=48
20
  2025-04-18T15:44:43.342127Z [info ] Application startup complete.  [uvicorn.error] filename=on.py func_name=startup lineno=62
21
+ 2025-04-18T16:13:09.189653Z [info ] Shutting down  [uvicorn.error] filename=server.py func_name=shutdown lineno=265
22
+ 2025-04-18T16:13:09.329875Z [info ] Waiting for application shutdown. [uvicorn.error] filename=on.py func_name=shutdown lineno=67
23
+ 2025-04-18T16:13:09.363708Z [info ] Application shutdown complete. [uvicorn.error] filename=on.py func_name=shutdown lineno=78
24
+ 2025-04-18T16:13:09.375566Z [info ] Finished server process [8]  [uvicorn.error] filename=server.py func_name=serve lineno=86
25
+ 2025-04-18T16:13:31.420177Z [info ] Application started  [app.main] filename=main.py func_name=<module> lineno=37 project=MailPilot_ai_agents version=0.1.0-alpha
26
+ 2025-04-18T16:13:31.425990Z [info ] Started server process [11]  [uvicorn.error] filename=server.py func_name=serve lineno=76
27
+ 2025-04-18T16:13:31.427509Z [info ] Waiting for application startup. [uvicorn.error] filename=on.py func_name=startup lineno=48
28
+ 2025-04-18T16:13:31.430441Z [info ] Application startup complete.  [uvicorn.error] filename=on.py func_name=startup lineno=62