Asma-yaseen commited on
Commit
35b3fc5
·
verified ·
1 Parent(s): c965d09

Upload routes/auth.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. routes/auth.py +176 -0
routes/auth.py ADDED
@@ -0,0 +1,176 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Authentication API endpoints.
3
+
4
+ Task: 1.4
5
+ Spec: specs/features/authentication.md
6
+ """
7
+ from fastapi import APIRouter, Depends, HTTPException, status
8
+ from sqlmodel import Session, select
9
+ from pydantic import BaseModel, EmailStr, Field
10
+ from datetime import datetime, timedelta
11
+ import jwt
12
+ import hashlib
13
+ import os
14
+ import uuid
15
+
16
+ from models import User
17
+ from db import get_session
18
+
19
+ router = APIRouter(prefix="/api/auth", tags=["auth"])
20
+
21
+ # JWT Configuration
22
+ JWT_SECRET = os.getenv("JWT_SECRET", "your-secret-key-min-32-chars")
23
+ JWT_ALGORITHM = "HS256"
24
+ JWT_EXPIRATION_HOURS = 24 * 7 # 7 days
25
+
26
+
27
+ # Request/Response Models
28
+ class SignupRequest(BaseModel):
29
+ """Request model for user signup."""
30
+ name: str = Field(min_length=1, max_length=255)
31
+ email: EmailStr
32
+ password: str = Field(min_length=8, max_length=255)
33
+
34
+
35
+ class SigninRequest(BaseModel):
36
+ """Request model for user signin."""
37
+ email: EmailStr
38
+ password: str
39
+
40
+
41
+ class AuthResponse(BaseModel):
42
+ """Response model for authentication."""
43
+ token: str
44
+ user: dict
45
+
46
+
47
+ def hash_password(password: str) -> str:
48
+ """Hash password using SHA256."""
49
+ return hashlib.sha256(password.encode()).hexdigest()
50
+
51
+
52
+ def create_jwt_token(user_id: str, email: str) -> str:
53
+ """Create JWT token for authenticated user."""
54
+ payload = {
55
+ "user_id": user_id,
56
+ "email": email,
57
+ "exp": datetime.utcnow() + timedelta(hours=JWT_EXPIRATION_HOURS),
58
+ "iat": datetime.utcnow()
59
+ }
60
+ return jwt.encode(payload, JWT_SECRET, algorithm=JWT_ALGORITHM)
61
+
62
+
63
+ @router.post("/signup", response_model=AuthResponse)
64
+ async def signup(
65
+ data: SignupRequest,
66
+ session: Session = Depends(get_session)
67
+ ):
68
+ """
69
+ Register a new user.
70
+
71
+ Args:
72
+ data: Signup data (name, email, password)
73
+ session: Database session
74
+
75
+ Returns:
76
+ JWT token and user info
77
+
78
+ Raises:
79
+ HTTPException: 400 if email already exists
80
+ """
81
+ # Check if email already exists
82
+ existing_user = session.exec(
83
+ select(User).where(User.email == data.email)
84
+ ).first()
85
+
86
+ if existing_user:
87
+ raise HTTPException(
88
+ status_code=status.HTTP_400_BAD_REQUEST,
89
+ detail="Email already registered"
90
+ )
91
+
92
+ # Create new user
93
+ user_id = str(uuid.uuid4())
94
+ new_user = User(
95
+ id=user_id,
96
+ email=data.email,
97
+ name=data.name,
98
+ password_hash=hash_password(data.password),
99
+ created_at=datetime.utcnow(),
100
+ updated_at=datetime.utcnow()
101
+ )
102
+
103
+ session.add(new_user)
104
+ session.commit()
105
+ session.refresh(new_user)
106
+
107
+ # Generate JWT token
108
+ token = create_jwt_token(user_id, data.email)
109
+
110
+ return AuthResponse(
111
+ token=token,
112
+ user={
113
+ "id": user_id,
114
+ "email": new_user.email,
115
+ "name": new_user.name
116
+ }
117
+ )
118
+
119
+
120
+ @router.post("/signin", response_model=AuthResponse)
121
+ async def signin(
122
+ data: SigninRequest,
123
+ session: Session = Depends(get_session)
124
+ ):
125
+ """
126
+ Authenticate user and return JWT token.
127
+
128
+ Args:
129
+ data: Signin data (email, password)
130
+ session: Database session
131
+
132
+ Returns:
133
+ JWT token and user info
134
+
135
+ Raises:
136
+ HTTPException: 401 if credentials are invalid
137
+ """
138
+ # Find user by email
139
+ user = session.exec(
140
+ select(User).where(User.email == data.email)
141
+ ).first()
142
+
143
+ if not user:
144
+ raise HTTPException(
145
+ status_code=status.HTTP_401_UNAUTHORIZED,
146
+ detail="Invalid email or password"
147
+ )
148
+
149
+ # Verify password
150
+ if user.password_hash != hash_password(data.password):
151
+ raise HTTPException(
152
+ status_code=status.HTTP_401_UNAUTHORIZED,
153
+ detail="Invalid email or password"
154
+ )
155
+
156
+ # Generate JWT token
157
+ token = create_jwt_token(user.id, user.email)
158
+
159
+ return AuthResponse(
160
+ token=token,
161
+ user={
162
+ "id": user.id,
163
+ "email": user.email,
164
+ "name": user.name
165
+ }
166
+ )
167
+
168
+
169
+ @router.get("/me")
170
+ async def get_current_user(
171
+ session: Session = Depends(get_session),
172
+ credentials: str = Depends(lambda: None)
173
+ ):
174
+ """Get current authenticated user info."""
175
+ # This will be used with the verify_token middleware
176
+ pass