paijo77 commited on
Commit
2c40514
·
verified ·
1 Parent(s): 396dcd5

update app/routers/auth.py

Browse files
Files changed (1) hide show
  1. app/routers/auth.py +135 -0
app/routers/auth.py ADDED
@@ -0,0 +1,135 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi import APIRouter, Depends, HTTPException, Response, Cookie, Request
2
+ from fastapi.responses import RedirectResponse
3
+ from sqlalchemy.ext.asyncio import AsyncSession
4
+ from pydantic import BaseModel
5
+ from typing import Optional
6
+ import os
7
+
8
+ from app.database import get_db
9
+ from app.oauth import oauth_handler
10
+ from app.dependencies import get_current_user
11
+ from app.db_models import User
12
+ from app.config import settings
13
+
14
+ router = APIRouter(prefix="/auth", tags=["authentication"])
15
+
16
+ # Access limiter from app state via request
17
+ from slowapi import Limiter
18
+ from slowapi.util import get_remote_address
19
+
20
+ limiter = Limiter(key_func=get_remote_address)
21
+
22
+
23
+ class UserInfo(BaseModel):
24
+ id: int
25
+ email: str
26
+ username: str
27
+ avatar_url: Optional[str]
28
+ role: str
29
+
30
+ class Config:
31
+ from_attributes = True
32
+
33
+
34
+ @router.get("/me", response_model=UserInfo)
35
+ @limiter.limit("60/minute")
36
+ async def get_current_user_info(
37
+ request: Request,
38
+ current_user: Optional[User] = Depends(get_current_user),
39
+ ):
40
+ if not current_user:
41
+ raise HTTPException(status_code=401, detail="Not authenticated")
42
+
43
+ return UserInfo(
44
+ id=current_user.id,
45
+ email=current_user.email,
46
+ username=current_user.username,
47
+ avatar_url=current_user.avatar_url,
48
+ role=current_user.role,
49
+ )
50
+
51
+
52
+ @router.get("/github")
53
+ @limiter.limit("10/minute")
54
+ async def github_login(request: Request):
55
+ return RedirectResponse(
56
+ url=f"https://github.com/login/oauth/authorize?client_id={settings.GITHUB_CLIENT_ID}&scope=user:email"
57
+ )
58
+
59
+
60
+ @router.get("/github/callback")
61
+ @limiter.limit("20/minute")
62
+ async def github_callback(
63
+ request: Request,
64
+ code: str,
65
+ response: Response,
66
+ session: AsyncSession = Depends(get_db),
67
+ ):
68
+ try:
69
+ user, token = await oauth_handler.github_callback(code, session)
70
+
71
+ response = RedirectResponse(url=f"{settings.FRONTEND_URL}/dashboard")
72
+ response.set_cookie(
73
+ key="access_token",
74
+ value=token,
75
+ httponly=True,
76
+ secure=True if settings.FRONTEND_URL.startswith("https") else False,
77
+ samesite="lax",
78
+ max_age=60 * 60 * 24 * 7,
79
+ )
80
+
81
+ return response
82
+
83
+ except Exception as e:
84
+ return RedirectResponse(url=f"{settings.FRONTEND_URL}/login?error={str(e)}")
85
+
86
+
87
+ @router.get("/google")
88
+ @limiter.limit("10/minute")
89
+ async def google_login(request: Request):
90
+ google_client_id = settings.GOOGLE_CLIENT_ID
91
+ redirect_uri = f"{settings.API_URL}/auth/google/callback"
92
+
93
+ return RedirectResponse(
94
+ url=f"https://accounts.google.com/o/oauth2/v2/auth?"
95
+ f"client_id={google_client_id}&"
96
+ f"redirect_uri={redirect_uri}&"
97
+ f"response_type=code&"
98
+ f"scope=openid email profile"
99
+ )
100
+
101
+
102
+ @router.get("/google/callback")
103
+ @limiter.limit("20/minute")
104
+ async def google_callback(
105
+ request: Request,
106
+ code: str,
107
+ response: Response,
108
+ session: AsyncSession = Depends(get_db),
109
+ ):
110
+ try:
111
+ redirect_uri = f"{settings.API_URL}/auth/google/callback"
112
+ user, token = await oauth_handler.google_callback(code, redirect_uri, session)
113
+
114
+ response = RedirectResponse(url=f"{settings.FRONTEND_URL}/dashboard")
115
+ response.set_cookie(
116
+ key="access_token",
117
+ value=token,
118
+ httponly=True,
119
+ secure=True if settings.FRONTEND_URL.startswith("https") else False,
120
+ samesite="lax",
121
+ max_age=60 * 60 * 24 * 7,
122
+ )
123
+
124
+ return response
125
+
126
+ except Exception as e:
127
+ return RedirectResponse(url=f"{settings.FRONTEND_URL}/login?error={str(e)}")
128
+
129
+
130
+ @router.post("/logout")
131
+ @limiter.limit("30/minute")
132
+ async def logout(request: Request, response: Response):
133
+ response = Response(content={"message": "Logged out successfully"})
134
+ response.delete_cookie(key="access_token")
135
+ return response