Yadav122 commited on
Commit
146897a
·
1 Parent(s): 9302b22
app/api/endpoints/v1/firebaseauth/app.py CHANGED
@@ -1,17 +1,40 @@
 
1
  from fastapi import FastAPI, Depends, HTTPException, status, Request, APIRouter
2
- from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
3
  import firebase_admin
4
  from firebase_admin import credentials, auth
5
  from sqlalchemy.ext.asyncio import AsyncSession
6
  from sqlalchemy import select
7
  from app.models.api.user import UserCreate, UserSignIn, PasswordReset, TokenVerify, UserResponse
8
  from app.models.database.DBUser import DBUser
9
- import datetime
10
- import os
11
- from app.core.database.session_manager import get_db_session as get_db
12
- from pydantic import BaseModel, EmailStr
13
 
14
- router = APIRouter(prefix="/FirebaseAuth", tags=["FirebaseAuth related APIs"])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
 
16
  # Initialize Firebase Admin SDK with better error handling
17
  try:
@@ -40,38 +63,6 @@ except Exception as e:
40
  print(f"Firebase initialization error: {str(e)}")
41
  # Continue without crashing, but auth functions will fail
42
 
43
- oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/FirebaseAuth/signin")
44
- async def get_current_user(token: str = Depends(oauth2_scheme), db: AsyncSession = Depends(get_db)):
45
- try:
46
- decoded_token = auth.verify_id_token(token)
47
- user_id = decoded_token["uid"]
48
-
49
- # Get the Firebase user
50
- firebase_user = auth.get_user(user_id)
51
-
52
- result = await db.execute(select(DBUser).filter(DBUser.firebase_uid == user_id))
53
- db_user = result.scalar_one_or_none()
54
-
55
- if db_user is None:
56
- raise HTTPException(status_code=404, detail="User not found in database")
57
-
58
- return UserResponse(
59
- firebase_uid=db_user.firebase_uid,
60
- email=db_user.email,
61
- display_name=db_user.display_name,
62
- is_active=db_user.is_active,
63
- created_at=db_user.created_at,
64
- last_login=db_user.last_login,
65
- provider=db_user.provider,
66
- email_verified=firebase_user.email_verified
67
- )
68
- except Exception as e:
69
- raise HTTPException(
70
- status_code=status.HTTP_401_UNAUTHORIZED,
71
- detail=f"Invalid authentication credentials: {str(e)}",
72
- headers={"WWW-Authenticate": "Bearer"},
73
- )
74
-
75
  @router.post("/signup", response_model=dict)
76
  async def create_user(user_data: UserCreate, db: AsyncSession = Depends(get_db)):
77
  """Create a new user with email and password and store in database"""
@@ -151,69 +142,74 @@ async def create_user(user_data: UserCreate, db: AsyncSession = Depends(get_db))
151
 
152
  @router.post("/signin", response_model=dict)
153
  async def signin_user(user_data: UserSignIn, db: AsyncSession = Depends(get_db)):
154
- """Sign in a user with email and password"""
155
  try:
156
- try:
157
- firebase_user = auth.get_user_by_email(user_data.email)
158
- except auth.UserNotFoundError:
159
- raise HTTPException(
160
- status_code=status.HTTP_401_UNAUTHORIZED,
161
- detail=f"No user found with email: {user_data.email}"
162
- )
163
 
164
- # Generate a custom token that can be exchanged for an ID token
165
  custom_token = auth.create_custom_token(firebase_user.uid)
166
 
167
- # Update last login time
168
- result = await db.execute(select(DBUser).filter(DBUser.firebase_uid == firebase_user.uid))
 
 
169
  db_user = result.scalar_one_or_none()
170
 
171
- if not db_user:
172
- # Create db user if not exists
173
- db_user = DBUser(
174
- firebase_uid=firebase_user.uid,
175
- email=firebase_user.email,
176
- display_name=firebase_user.display_name or user_data.email.split('@')[0],
177
- is_active=True,
178
- created_at=datetime.datetime.utcnow(),
179
- last_login=datetime.datetime.utcnow(),
180
- provider="email"
181
- )
182
- db.add(db_user)
183
- else:
184
  db_user.last_login = datetime.datetime.utcnow()
185
-
186
- await db.commit()
187
- await db.refresh(db_user)
188
-
189
- user_info = {
190
- "firebase_uid": db_user.firebase_uid,
191
- "email": db_user.email,
192
- "display_name": db_user.display_name,
193
- "is_active": db_user.is_active,
194
- "created_at": db_user.created_at.isoformat() if db_user.created_at else None,
195
- "last_login": db_user.last_login.isoformat() if db_user.last_login else None,
196
- "provider": db_user.provider,
197
- "email_verified": firebase_user.email_verified,
198
- "custom_token": custom_token.decode("utf-8") if isinstance(custom_token, bytes) else custom_token
199
- }
200
 
201
  return {
202
- "message": "Login successful",
203
- "user": user_info,
204
- "custom_token": custom_token.decode("utf-8") if isinstance(custom_token, bytes) else custom_token,
205
- "email_verified": firebase_user.email_verified
 
 
 
 
206
  }
207
  except Exception as e:
208
- if isinstance(e, HTTPException):
209
- raise e
210
- await db.rollback()
211
  raise HTTPException(
212
  status_code=status.HTTP_401_UNAUTHORIZED,
213
  detail=f"Authentication failed: {str(e)}"
214
  )
215
- class EmailVerifyRequest(BaseModel):
216
- email: EmailStr
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
217
 
218
  @router.post("/resend-verification", status_code=status.HTTP_200_OK)
219
  async def resend_verification_email(
 
1
+ from app import router
2
  from fastapi import FastAPI, Depends, HTTPException, status, Request, APIRouter
3
+ from fastapi.security import OAuth2PasswordBearer
4
  import firebase_admin
5
  from firebase_admin import credentials, auth
6
  from sqlalchemy.ext.asyncio import AsyncSession
7
  from sqlalchemy import select
8
  from app.models.api.user import UserCreate, UserSignIn, PasswordReset, TokenVerify, UserResponse
9
  from app.models.database.DBUser import DBUser
10
+ from app.core.database.session_manager import get_db
 
 
 
11
 
12
+ import os
13
+ # Initialize OAuth2 scheme
14
+ oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/FirebaseAuth/signin")
15
+
16
+ async def verify_firebase_token(token: str = Depends(oauth2_scheme)) -> dict:
17
+ """Verify Firebase token and return user info"""
18
+ try:
19
+ # Verify the token
20
+ decoded_token = auth.verify_id_token(token)
21
+ user_id = decoded_token["uid"]
22
+
23
+ # Get user from Firebase
24
+ firebase_user = auth.get_user(user_id)
25
+
26
+ return {
27
+ "firebase_uid": user_id,
28
+ "email": firebase_user.email,
29
+ "email_verified": firebase_user.email_verified,
30
+ "display_name": firebase_user.display_name
31
+ }
32
+ except Exception as e:
33
+ raise HTTPException(
34
+ status_code=status.HTTP_401_UNAUTHORIZED,
35
+ detail="Invalid authentication token",
36
+ headers={"WWW-Authenticate": "Bearer"},
37
+ )
38
 
39
  # Initialize Firebase Admin SDK with better error handling
40
  try:
 
63
  print(f"Firebase initialization error: {str(e)}")
64
  # Continue without crashing, but auth functions will fail
65
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
66
  @router.post("/signup", response_model=dict)
67
  async def create_user(user_data: UserCreate, db: AsyncSession = Depends(get_db)):
68
  """Create a new user with email and password and store in database"""
 
142
 
143
  @router.post("/signin", response_model=dict)
144
  async def signin_user(user_data: UserSignIn, db: AsyncSession = Depends(get_db)):
145
+ """Sign in user and return token"""
146
  try:
147
+ # Verify user exists in Firebase
148
+ firebase_user = auth.get_user_by_email(user_data.email)
 
 
 
 
 
149
 
150
+ # Generate custom token
151
  custom_token = auth.create_custom_token(firebase_user.uid)
152
 
153
+ # Update last login in database
154
+ result = await db.execute(
155
+ select(DBUser).filter(DBUser.firebase_uid == firebase_user.uid)
156
+ )
157
  db_user = result.scalar_one_or_none()
158
 
159
+ if db_user:
 
 
 
 
 
 
 
 
 
 
 
 
160
  db_user.last_login = datetime.datetime.utcnow()
161
+ await db.commit()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
162
 
163
  return {
164
+ "access_token": custom_token.decode() if isinstance(custom_token, bytes) else custom_token,
165
+ "token_type": "bearer",
166
+ "user": {
167
+ "firebase_uid": firebase_user.uid,
168
+ "email": firebase_user.email,
169
+ "email_verified": firebase_user.email_verified,
170
+ "display_name": firebase_user.display_name
171
+ }
172
  }
173
  except Exception as e:
 
 
 
174
  raise HTTPException(
175
  status_code=status.HTTP_401_UNAUTHORIZED,
176
  detail=f"Authentication failed: {str(e)}"
177
  )
178
+
179
+ # Example of a protected endpoint
180
+ @router.get("/me", response_model=dict)
181
+ async def get_current_user(
182
+ current_user: dict = Depends(verify_firebase_token),
183
+ db: AsyncSession = Depends(get_db)
184
+ ):
185
+ """Get current user information"""
186
+ try:
187
+ result = await db.execute(
188
+ select(DBUser).filter(DBUser.firebase_uid == current_user["firebase_uid"])
189
+ )
190
+ db_user = result.scalar_one_or_none()
191
+
192
+ if not db_user:
193
+ raise HTTPException(
194
+ status_code=status.HTTP_404_NOT_FOUND,
195
+ detail="User not found in database"
196
+ )
197
+
198
+ return {
199
+ "message": "User authenticated",
200
+ "user": {
201
+ "firebase_uid": db_user.firebase_uid,
202
+ "email": db_user.email,
203
+ "display_name": db_user.display_name,
204
+ "is_active": db_user.is_active,
205
+ "email_verified": current_user["email_verified"]
206
+ }
207
+ }
208
+ except Exception as e:
209
+ raise HTTPException(
210
+ status_code=status.HTTP_400_BAD_REQUEST,
211
+ detail=str(e)
212
+ )
213
 
214
  @router.post("/resend-verification", status_code=status.HTTP_200_OK)
215
  async def resend_verification_email(