Mark-Lasfar commited on
Commit
cc29913
·
1 Parent(s): c0bbb85

Update Model

Browse files
Files changed (1) hide show
  1. api/auth.py +199 -201
api/auth.py CHANGED
@@ -5,7 +5,7 @@ from httpx_oauth.clients.google import GoogleOAuth2
5
  from httpx_oauth.clients.github import GitHubOAuth2
6
  from api.database import User, OAuthAccount, get_user_db, get_db
7
  from fastapi_users.manager import BaseUserManager, IntegerIDMixin
8
- from fastapi import Depends, Request, FastAPI, HTTPException, status
9
  from fastapi.responses import RedirectResponse
10
  from fastapi_users.models import UP
11
  from typing import Optional
@@ -57,9 +57,6 @@ if not all([GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET, GITHUB_CLIENT_ID, GITHUB_CLI
57
  google_oauth_client = GoogleOAuth2(GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET)
58
  github_oauth_client = GitHubOAuth2(GITHUB_CLIENT_ID, GITHUB_CLIENT_SECRET)
59
 
60
- # OAuth state secret
61
- OAUTH_STATE_SECRET = SECRET
62
-
63
  class UserManager(IntegerIDMixin, BaseUserManager[User, int]):
64
  reset_password_token_secret = SECRET
65
  verification_token_secret = SECRET
@@ -70,204 +67,216 @@ class UserManager(IntegerIDMixin, BaseUserManager[User, int]):
70
  async def get_user_manager(user_db: SQLAlchemyUserDatabase = Depends(get_user_db)):
71
  yield UserManager(user_db)
72
 
73
- # Custom OAuth routers without fastapi_users
74
- from fastapi import APIRouter
75
 
76
- def get_custom_oauth_router():
77
- router = APIRouter()
78
-
79
- # Store state in session
80
- @router.get("/google/authorize")
81
- async def google_authorize(request: Request):
82
- state = secrets.token_urlsafe(32)
83
- request.session["oauth_state"] = state
84
- request.session["oauth_provider"] = "google"
85
- redirect_uri = "https://mgzon-mgzon-app.hf.space/auth/google/callback"
86
- url = google_oauth_client.get_authorization_url(
87
- redirect_uri, state=state, scope=["openid", "email", "profile"]
88
- )
89
- return RedirectResponse(url)
90
 
91
- @router.get("/google/callback")
92
- async def google_callback(request: Request, db: Session = Depends(get_db)):
93
- state = request.query_params.get("state")
94
- code = request.query_params.get("code")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
95
 
96
- # Verify state
97
- if not state or state != request.session.get("oauth_state"):
98
- logger.error("OAuth state mismatch")
99
- return RedirectResponse("/login?error=Invalid state")
 
 
 
 
 
 
 
 
 
 
100
 
101
- provider = request.session.get("oauth_provider")
102
- if provider != "google":
103
- return RedirectResponse("/login?error=Invalid provider")
 
 
104
 
105
- try:
106
- # Get token and user info
107
- token = await google_oauth_client.get_access_token(code, redirect_uri="https://mgzon-mgzon-app.hf.space/auth/google/callback")
108
- user_info = await google_oauth_client.get_id_email(token)
109
-
110
- account_id = user_info["id"]
111
- account_email = user_info["email"]
112
- logger.info(f"Google OAuth success: account_id={account_id}, email={account_email}")
113
-
114
- # Find or create user
115
- user = db.query(User).filter(User.email == account_email).first()
116
- if user is None:
117
- # Create new user
118
- user = User(
119
- email=account_email,
120
- hashed_password=UserManager(None).password_helper.hash("dummy_password"), # Dummy password
121
- is_active=True,
122
- is_verified=True,
123
- )
124
- db.add(user)
125
- db.commit()
126
- db.refresh(user)
127
- logger.info(f"Created new user: {user.email}")
128
-
129
- # Find or create OAuth account
130
- oauth_account = db.query(OAuthAccount).filter(
131
- OAuthAccount.oauth_name == "google",
132
- OAuthAccount.account_id == account_id
133
- ).first()
134
-
135
- if oauth_account is None:
136
- oauth_account = OAuthAccount(
137
- oauth_name="google",
138
- access_token=token["access_token"],
139
- account_id=account_id,
140
- account_email=account_email,
141
- user_id=user.id
142
- )
143
- db.add(oauth_account)
144
- db.commit()
145
- logger.info(f"Created OAuth account for user: {user.email}")
146
- else:
147
- # Update existing OAuth account
148
- oauth_account.access_token = token["access_token"]
149
- oauth_account.account_email = account_email
150
- db.commit()
151
- logger.info(f"Updated OAuth account for user: {user.email}")
152
-
153
- # Create JWT token using fastapi_users
154
- user_manager = UserManager(get_user_db(db))
155
- jwt_token = await user_manager.create_access_token(user)
156
-
157
- # Set cookie
158
- response = RedirectResponse("/chat")
159
- response.set_cookie(
160
- key="access_token",
161
- value=jwt_token,
162
- max_age=3600,
163
- httponly=True,
164
- secure=True,
165
- samesite="lax"
166
  )
167
-
168
- logger.info(f"OAuth login successful for user: {user.email}")
169
- return response
170
-
171
- except Exception as e:
172
- logger.error(f"Google OAuth callback failed: {e}")
173
- return RedirectResponse(f"/login?error={str(e)}")
174
-
175
- @router.get("/github/authorize")
176
- async def github_authorize(request: Request):
177
- state = secrets.token_urlsafe(32)
178
- request.session["oauth_state"] = state
179
- request.session["oauth_provider"] = "github"
180
- redirect_uri = "https://mgzon-mgzon-app.hf.space/auth/github/callback"
181
- url = github_oauth_client.get_authorization_url(
182
- redirect_uri, state=state, scope=["user:email"]
 
 
 
 
 
 
 
 
183
  )
184
- return RedirectResponse(url)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
185
 
186
- @router.get("/github/callback")
187
- async def github_callback(request: Request, db: Session = Depends(get_db)):
188
- state = request.query_params.get("state")
189
- code = request.query_params.get("code")
190
 
191
- # Verify state
192
- if not state or state != request.session.get("oauth_state"):
193
- logger.error("OAuth state mismatch")
194
- return RedirectResponse("/login?error=Invalid state")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
195
 
196
- provider = request.session.get("oauth_provider")
197
- if provider != "github":
198
- return RedirectResponse("/login?error=Invalid provider")
 
 
199
 
200
- try:
201
- # Get token and user info
202
- token = await github_oauth_client.get_access_token(code, redirect_uri="https://mgzon-mgzon-app.hf.space/auth/github/callback")
203
- user_info = await github_oauth_client.get_id_email(token)
204
-
205
- account_id = user_info["id"]
206
- account_email = user_info["email"]
207
- logger.info(f"GitHub OAuth success: account_id={account_id}, email={account_email}")
208
-
209
- # Find or create user
210
- user = db.query(User).filter(User.email == account_email).first()
211
- if user is None:
212
- # Create new user
213
- user = User(
214
- email=account_email,
215
- hashed_password=UserManager(None).password_helper.hash("dummy_password"), # Dummy password
216
- is_active=True,
217
- is_verified=True,
218
- )
219
- db.add(user)
220
- db.commit()
221
- db.refresh(user)
222
- logger.info(f"Created new user: {user.email}")
223
-
224
- # Find or create OAuth account
225
- oauth_account = db.query(OAuthAccount).filter(
226
- OAuthAccount.oauth_name == "github",
227
- OAuthAccount.account_id == account_id
228
- ).first()
229
-
230
- if oauth_account is None:
231
- oauth_account = OAuthAccount(
232
- oauth_name="github",
233
- access_token=token["access_token"],
234
- account_id=account_id,
235
- account_email=account_email,
236
- user_id=user.id
237
- )
238
- db.add(oauth_account)
239
- db.commit()
240
- logger.info(f"Created OAuth account for user: {user.email}")
241
- else:
242
- # Update existing OAuth account
243
- oauth_account.access_token = token["access_token"]
244
- oauth_account.account_email = account_email
245
- db.commit()
246
- logger.info(f"Updated OAuth account for user: {user.email}")
247
-
248
- # Create JWT token using fastapi_users
249
- user_manager = UserManager(get_user_db(db))
250
- jwt_token = await user_manager.create_access_token(user)
251
-
252
- # Set cookie
253
- response = RedirectResponse("/chat")
254
- response.set_cookie(
255
- key="access_token",
256
- value=jwt_token,
257
- max_age=3600,
258
- httponly=True,
259
- secure=True,
260
- samesite="lax"
261
  )
262
-
263
- logger.info(f"OAuth login successful for user: {user.email}")
264
- return response
265
-
266
- except Exception as e:
267
- logger.error(f"GitHub OAuth callback failed: {e}")
268
- return RedirectResponse(f"/login?error={str(e)}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
269
 
270
- return router
 
 
 
 
 
271
 
272
  # Standard fastapi_users setup for JWT only (no OAuth)
273
  fastapi_users = FastAPIUsers[User, int](
@@ -279,8 +288,7 @@ current_active_user = fastapi_users.current_user(active=True, optional=True)
279
 
280
  def get_auth_router(app: FastAPI):
281
  # Add custom OAuth router
282
- custom_oauth_router = get_custom_oauth_router()
283
- app.include_router(custom_oauth_router, prefix="/auth", tags=["auth"])
284
 
285
  # Add standard fastapi_users routes (without OAuth)
286
  app.include_router(fastapi_users.get_auth_router(auth_backend), prefix="/auth/jwt", tags=["auth"])
@@ -288,13 +296,3 @@ def get_auth_router(app: FastAPI):
288
  app.include_router(fastapi_users.get_reset_password_router(), prefix="/auth", tags=["auth"])
289
  app.include_router(fastapi_users.get_verify_router(UserRead), prefix="/auth", tags=["auth"])
290
  app.include_router(fastapi_users.get_users_router(UserRead, UserUpdate), prefix="/users", tags=["users"])
291
-
292
- # Add logout endpoint
293
- @get_auth_router
294
- def logout_endpoint():
295
- @router.get("/logout")
296
- async def logout(request: Request):
297
- request.session.clear()
298
- response = RedirectResponse("/login")
299
- response.delete_cookie("access_token")
300
- return response
 
5
  from httpx_oauth.clients.github import GitHubOAuth2
6
  from api.database import User, OAuthAccount, get_user_db, get_db
7
  from fastapi_users.manager import BaseUserManager, IntegerIDMixin
8
+ from fastapi import Depends, Request, FastAPI, HTTPException, status, APIRouter
9
  from fastapi.responses import RedirectResponse
10
  from fastapi_users.models import UP
11
  from typing import Optional
 
57
  google_oauth_client = GoogleOAuth2(GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET)
58
  github_oauth_client = GitHubOAuth2(GITHUB_CLIENT_ID, GITHUB_CLIENT_SECRET)
59
 
 
 
 
60
  class UserManager(IntegerIDMixin, BaseUserManager[User, int]):
61
  reset_password_token_secret = SECRET
62
  verification_token_secret = SECRET
 
67
  async def get_user_manager(user_db: SQLAlchemyUserDatabase = Depends(get_user_db)):
68
  yield UserManager(user_db)
69
 
70
+ # Custom OAuth Router
71
+ oauth_router = APIRouter(prefix="/auth", tags=["auth"])
72
 
73
+ # Store state in session
74
+ @oauth_router.get("/google/authorize")
75
+ async def google_authorize(request: Request):
76
+ state = secrets.token_urlsafe(32)
77
+ request.session["oauth_state"] = state
78
+ request.session["oauth_provider"] = "google"
79
+ redirect_uri = "https://mgzon-mgzon-app.hf.space/auth/google/callback"
80
+ url = google_oauth_client.get_authorization_url(
81
+ redirect_uri, state=state, scope=["openid", "email", "profile"]
82
+ )
83
+ return RedirectResponse(url)
 
 
 
84
 
85
+ @oauth_router.get("/google/callback")
86
+ async def google_callback(request: Request, db: Session = Depends(get_db)):
87
+ state = request.query_params.get("state")
88
+ code = request.query_params.get("code")
89
+
90
+ # Verify state
91
+ if not state or state != request.session.get("oauth_state"):
92
+ logger.error("OAuth state mismatch")
93
+ return RedirectResponse("/login?error=Invalid state")
94
+
95
+ provider = request.session.get("oauth_provider")
96
+ if provider != "google":
97
+ return RedirectResponse("/login?error=Invalid provider")
98
+
99
+ try:
100
+ # Get token and user info
101
+ token = await google_oauth_client.get_access_token(code, redirect_uri="https://mgzon-mgzon-app.hf.space/auth/google/callback")
102
+ user_info = await google_oauth_client.get_id_email(token)
103
+
104
+ account_id = user_info["id"]
105
+ account_email = user_info["email"]
106
+ logger.info(f"Google OAuth success: account_id={account_id}, email={account_email}")
107
 
108
+ # Find or create user
109
+ user = db.query(User).filter(User.email == account_email).first()
110
+ if user is None:
111
+ # Create new user
112
+ user = User(
113
+ email=account_email,
114
+ hashed_password="dummy_hashed_password", # We'll use JWT only, no password login
115
+ is_active=True,
116
+ is_verified=True,
117
+ )
118
+ db.add(user)
119
+ db.commit()
120
+ db.refresh(user)
121
+ logger.info(f"Created new user: {user.email}")
122
 
123
+ # Find or create OAuth account
124
+ oauth_account = db.query(OAuthAccount).filter(
125
+ OAuthAccount.oauth_name == "google",
126
+ OAuthAccount.account_id == account_id
127
+ ).first()
128
 
129
+ if oauth_account is None:
130
+ oauth_account = OAuthAccount(
131
+ oauth_name="google",
132
+ access_token=token["access_token"],
133
+ account_id=account_id,
134
+ account_email=account_email,
135
+ user_id=user.id
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
136
  )
137
+ db.add(oauth_account)
138
+ db.commit()
139
+ logger.info(f"Created OAuth account for user: {user.email}")
140
+ else:
141
+ # Update existing OAuth account
142
+ oauth_account.access_token = token["access_token"]
143
+ oauth_account.account_email = account_email
144
+ db.commit()
145
+ logger.info(f"Updated OAuth account for user: {user.email}")
146
+
147
+ # Create JWT token using fastapi_users
148
+ user_db = get_user_db(db)
149
+ user_manager = UserManager(user_db)
150
+ jwt_token = await user_manager.create_access_token(user)
151
+
152
+ # Set cookie
153
+ response = RedirectResponse("/chat")
154
+ response.set_cookie(
155
+ key="access_token",
156
+ value=jwt_token,
157
+ max_age=3600,
158
+ httponly=True,
159
+ secure=True,
160
+ samesite="lax"
161
  )
162
+
163
+ # Clear session
164
+ request.session.clear()
165
+
166
+ logger.info(f"OAuth login successful for user: {user.email}")
167
+ return response
168
+
169
+ except Exception as e:
170
+ logger.error(f"Google OAuth callback failed: {e}")
171
+ request.session.clear()
172
+ return RedirectResponse(f"/login?error={str(e)}")
173
+
174
+ @oauth_router.get("/github/authorize")
175
+ async def github_authorize(request: Request):
176
+ state = secrets.token_urlsafe(32)
177
+ request.session["oauth_state"] = state
178
+ request.session["oauth_provider"] = "github"
179
+ redirect_uri = "https://mgzon-mgzon-app.hf.space/auth/github/callback"
180
+ url = github_oauth_client.get_authorization_url(
181
+ redirect_uri, state=state, scope=["user:email"]
182
+ )
183
+ return RedirectResponse(url)
184
+
185
+ @oauth_router.get("/github/callback")
186
+ async def github_callback(request: Request, db: Session = Depends(get_db)):
187
+ state = request.query_params.get("state")
188
+ code = request.query_params.get("code")
189
+
190
+ # Verify state
191
+ if not state or state != request.session.get("oauth_state"):
192
+ logger.error("OAuth state mismatch")
193
+ return RedirectResponse("/login?error=Invalid state")
194
+
195
+ provider = request.session.get("oauth_provider")
196
+ if provider != "github":
197
+ return RedirectResponse("/login?error=Invalid provider")
198
 
199
+ try:
200
+ # Get token and user info
201
+ token = await github_oauth_client.get_access_token(code, redirect_uri="https://mgzon-mgzon-app.hf.space/auth/github/callback")
202
+ user_info = await github_oauth_client.get_id_email(token)
203
 
204
+ account_id = user_info["id"]
205
+ account_email = user_info["email"]
206
+ logger.info(f"GitHub OAuth success: account_id={account_id}, email={account_email}")
207
+
208
+ # Find or create user
209
+ user = db.query(User).filter(User.email == account_email).first()
210
+ if user is None:
211
+ # Create new user
212
+ user = User(
213
+ email=account_email,
214
+ hashed_password="dummy_hashed_password", # We'll use JWT only, no password login
215
+ is_active=True,
216
+ is_verified=True,
217
+ )
218
+ db.add(user)
219
+ db.commit()
220
+ db.refresh(user)
221
+ logger.info(f"Created new user: {user.email}")
222
 
223
+ # Find or create OAuth account
224
+ oauth_account = db.query(OAuthAccount).filter(
225
+ OAuthAccount.oauth_name == "github",
226
+ OAuthAccount.account_id == account_id
227
+ ).first()
228
 
229
+ if oauth_account is None:
230
+ oauth_account = OAuthAccount(
231
+ oauth_name="github",
232
+ access_token=token["access_token"],
233
+ account_id=account_id,
234
+ account_email=account_email,
235
+ user_id=user.id
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
236
  )
237
+ db.add(oauth_account)
238
+ db.commit()
239
+ logger.info(f"Created OAuth account for user: {user.email}")
240
+ else:
241
+ # Update existing OAuth account
242
+ oauth_account.access_token = token["access_token"]
243
+ oauth_account.account_email = account_email
244
+ db.commit()
245
+ logger.info(f"Updated OAuth account for user: {user.email}")
246
+
247
+ # Create JWT token using fastapi_users
248
+ user_db = get_user_db(db)
249
+ user_manager = UserManager(user_db)
250
+ jwt_token = await user_manager.create_access_token(user)
251
+
252
+ # Set cookie
253
+ response = RedirectResponse("/chat")
254
+ response.set_cookie(
255
+ key="access_token",
256
+ value=jwt_token,
257
+ max_age=3600,
258
+ httponly=True,
259
+ secure=True,
260
+ samesite="lax"
261
+ )
262
+
263
+ # Clear session
264
+ request.session.clear()
265
+
266
+ logger.info(f"OAuth login successful for user: {user.email}")
267
+ return response
268
+
269
+ except Exception as e:
270
+ logger.error(f"GitHub OAuth callback failed: {e}")
271
+ request.session.clear()
272
+ return RedirectResponse(f"/login?error={str(e)}")
273
 
274
+ @oauth_router.get("/logout")
275
+ async def logout(request: Request):
276
+ request.session.clear()
277
+ response = RedirectResponse("/login")
278
+ response.delete_cookie("access_token")
279
+ return response
280
 
281
  # Standard fastapi_users setup for JWT only (no OAuth)
282
  fastapi_users = FastAPIUsers[User, int](
 
288
 
289
  def get_auth_router(app: FastAPI):
290
  # Add custom OAuth router
291
+ app.include_router(oauth_router)
 
292
 
293
  # Add standard fastapi_users routes (without OAuth)
294
  app.include_router(fastapi_users.get_auth_router(auth_backend), prefix="/auth/jwt", tags=["auth"])
 
296
  app.include_router(fastapi_users.get_reset_password_router(), prefix="/auth", tags=["auth"])
297
  app.include_router(fastapi_users.get_verify_router(UserRead), prefix="/auth", tags=["auth"])
298
  app.include_router(fastapi_users.get_users_router(UserRead, UserUpdate), prefix="/users", tags=["users"])