Girish Jeswani commited on
Commit
b6b3f7f
·
1 Parent(s): f052ff5

add new routes

Browse files
multi_llm_chatbot_backend/app/api/routes/auth.py ADDED
@@ -0,0 +1,130 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi import APIRouter, HTTPException, Depends, status
2
+ from datetime import datetime, timedelta
3
+ from bson import ObjectId
4
+ from app.models.user import UserCreate, UserLogin, User, Token, UserResponse
5
+ from app.core.auth import (
6
+ get_password_hash,
7
+ authenticate_user,
8
+ create_access_token,
9
+ get_user_by_email,
10
+ get_current_active_user,
11
+ create_user_response,
12
+ ACCESS_TOKEN_EXPIRE_MINUTES
13
+ )
14
+ from app.core.database import get_database
15
+ import logging
16
+
17
+ logger = logging.getLogger(__name__)
18
+
19
+ router = APIRouter()
20
+
21
+ @router.post("/signup", response_model=Token)
22
+ async def signup(user_data: UserCreate):
23
+ """Create a new user account"""
24
+ try:
25
+ db = get_database()
26
+
27
+ # Check if user already exists
28
+ existing_user = await get_user_by_email(user_data.email)
29
+ if existing_user:
30
+ raise HTTPException(
31
+ status_code=status.HTTP_400_BAD_REQUEST,
32
+ detail="Email already registered"
33
+ )
34
+
35
+ # Create new user
36
+ hashed_password = get_password_hash(user_data.password)
37
+ user = User(
38
+ firstName=user_data.firstName,
39
+ lastName=user_data.lastName,
40
+ email=user_data.email,
41
+ hashed_password=hashed_password,
42
+ academicStage=user_data.academicStage,
43
+ researchArea=user_data.researchArea,
44
+ created_at=datetime.utcnow(),
45
+ is_active=True
46
+ )
47
+
48
+ # Insert user into database
49
+ result = await db.users.insert_one(user.dict(by_alias=True))
50
+ user.id = result.inserted_id
51
+
52
+ # Create access token
53
+ access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
54
+ access_token = create_access_token(
55
+ data={"sub": str(user.id)},
56
+ expires_delta=access_token_expires
57
+ )
58
+
59
+ return Token(
60
+ access_token=access_token,
61
+ token_type="bearer",
62
+ user=create_user_response(user)
63
+ )
64
+
65
+ except HTTPException:
66
+ raise
67
+ except Exception as e:
68
+ logger.error(f"Error during signup: {e}")
69
+ raise HTTPException(
70
+ status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
71
+ detail="Could not create user account"
72
+ )
73
+
74
+ @router.post("/login", response_model=Token)
75
+ async def login(user_credentials: UserLogin):
76
+ """Login with email and password"""
77
+ try:
78
+ # Authenticate user
79
+ user = await authenticate_user(user_credentials.email, user_credentials.password)
80
+ if not user:
81
+ raise HTTPException(
82
+ status_code=status.HTTP_401_UNAUTHORIZED,
83
+ detail="Incorrect email or password",
84
+ headers={"WWW-Authenticate": "Bearer"},
85
+ )
86
+
87
+ # Update last login time
88
+ db = get_database()
89
+ await db.users.update_one(
90
+ {"_id": user.id},
91
+ {"$set": {"last_login": datetime.utcnow()}}
92
+ )
93
+ user.last_login = datetime.utcnow()
94
+
95
+ # Create access token
96
+ access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
97
+ access_token = create_access_token(
98
+ data={"sub": str(user.id)},
99
+ expires_delta=access_token_expires
100
+ )
101
+
102
+ return Token(
103
+ access_token=access_token,
104
+ token_type="bearer",
105
+ user=create_user_response(user)
106
+ )
107
+
108
+ except HTTPException:
109
+ raise
110
+ except Exception as e:
111
+ logger.error(f"Error during login: {e}")
112
+ raise HTTPException(
113
+ status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
114
+ detail="Login failed"
115
+ )
116
+
117
+ @router.get("/me", response_model=UserResponse)
118
+ async def get_current_user_profile(current_user: User = Depends(get_current_active_user)):
119
+ """Get current user profile"""
120
+ return create_user_response(current_user)
121
+
122
+ @router.post("/logout")
123
+ async def logout():
124
+ """Logout (client should discard token)"""
125
+ return {"message": "Successfully logged out"}
126
+
127
+ @router.post("/verify-token", response_model=UserResponse)
128
+ async def verify_token(current_user: User = Depends(get_current_active_user)):
129
+ """Verify token and return user info"""
130
+ return create_user_response(current_user)
multi_llm_chatbot_backend/app/api/routes/chat_sessions.py ADDED
@@ -0,0 +1,258 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi import APIRouter, HTTPException, Depends, status
2
+ from typing import List, Optional
3
+ from datetime import datetime
4
+ from bson import ObjectId
5
+ from app.models.user import User, ChatSession, ChatSessionResponse
6
+ from app.core.auth import get_current_active_user
7
+ from app.core.database import get_database
8
+ from pydantic import BaseModel
9
+ import logging
10
+
11
+ logger = logging.getLogger(__name__)
12
+
13
+ router = APIRouter()
14
+
15
+ class CreateChatSessionRequest(BaseModel):
16
+ title: str
17
+
18
+ class UpdateChatSessionRequest(BaseModel):
19
+ title: Optional[str] = None
20
+ messages: Optional[List[dict]] = None
21
+
22
+ class SaveMessageRequest(BaseModel):
23
+ session_id: str
24
+ message: dict
25
+
26
+ @router.post("/chat-sessions", response_model=dict)
27
+ async def create_chat_session(
28
+ request: CreateChatSessionRequest,
29
+ current_user: User = Depends(get_current_active_user)
30
+ ):
31
+ """Create a new chat session for the user"""
32
+ try:
33
+ db = get_database()
34
+
35
+ session = ChatSession(
36
+ user_id=current_user.id,
37
+ title=request.title,
38
+ messages=[],
39
+ created_at=datetime.utcnow(),
40
+ updated_at=datetime.utcnow()
41
+ )
42
+
43
+ result = await db.chat_sessions.insert_one(session.dict(by_alias=True))
44
+ session.id = result.inserted_id
45
+
46
+ return {
47
+ "id": str(session.id),
48
+ "title": session.title,
49
+ "created_at": session.created_at,
50
+ "updated_at": session.updated_at,
51
+ "message_count": 0
52
+ }
53
+
54
+ except Exception as e:
55
+ logger.error(f"Error creating chat session: {e}")
56
+ raise HTTPException(
57
+ status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
58
+ detail="Could not create chat session"
59
+ )
60
+
61
+ @router.get("/chat-sessions", response_model=List[ChatSessionResponse])
62
+ async def get_user_chat_sessions(
63
+ current_user: User = Depends(get_current_active_user),
64
+ limit: int = 50,
65
+ skip: int = 0
66
+ ):
67
+ """Get all chat sessions for the current user"""
68
+ try:
69
+ db = get_database()
70
+
71
+ cursor = db.chat_sessions.find(
72
+ {"user_id": current_user.id, "is_active": True}
73
+ ).sort("updated_at", -1).skip(skip).limit(limit)
74
+
75
+ sessions = []
76
+ async for session_data in cursor:
77
+ sessions.append(ChatSessionResponse(
78
+ id=str(session_data["_id"]),
79
+ title=session_data["title"],
80
+ created_at=session_data["created_at"],
81
+ updated_at=session_data["updated_at"],
82
+ message_count=len(session_data.get("messages", []))
83
+ ))
84
+
85
+ return sessions
86
+
87
+ except Exception as e:
88
+ logger.error(f"Error fetching chat sessions: {e}")
89
+ raise HTTPException(
90
+ status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
91
+ detail="Could not fetch chat sessions"
92
+ )
93
+
94
+ @router.get("/chat-sessions/{session_id}")
95
+ async def get_chat_session(
96
+ session_id: str,
97
+ current_user: User = Depends(get_current_active_user)
98
+ ):
99
+ """Get a specific chat session with all messages"""
100
+ try:
101
+ db = get_database()
102
+
103
+ session_data = await db.chat_sessions.find_one({
104
+ "_id": ObjectId(session_id),
105
+ "user_id": current_user.id,
106
+ "is_active": True
107
+ })
108
+
109
+ if not session_data:
110
+ raise HTTPException(
111
+ status_code=status.HTTP_404_NOT_FOUND,
112
+ detail="Chat session not found"
113
+ )
114
+
115
+ return {
116
+ "id": str(session_data["_id"]),
117
+ "title": session_data["title"],
118
+ "messages": session_data.get("messages", []),
119
+ "created_at": session_data["created_at"],
120
+ "updated_at": session_data["updated_at"]
121
+ }
122
+
123
+ except HTTPException:
124
+ raise
125
+ except Exception as e:
126
+ logger.error(f"Error fetching chat session: {e}")
127
+ raise HTTPException(
128
+ status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
129
+ detail="Could not fetch chat session"
130
+ )
131
+
132
+ @router.put("/chat-sessions/{session_id}")
133
+ async def update_chat_session(
134
+ session_id: str,
135
+ request: UpdateChatSessionRequest,
136
+ current_user: User = Depends(get_current_active_user)
137
+ ):
138
+ """Update a chat session (title or messages)"""
139
+ try:
140
+ db = get_database()
141
+
142
+ # Verify session belongs to user
143
+ session_data = await db.chat_sessions.find_one({
144
+ "_id": ObjectId(session_id),
145
+ "user_id": current_user.id,
146
+ "is_active": True
147
+ })
148
+
149
+ if not session_data:
150
+ raise HTTPException(
151
+ status_code=status.HTTP_404_NOT_FOUND,
152
+ detail="Chat session not found"
153
+ )
154
+
155
+ update_data = {"updated_at": datetime.utcnow()}
156
+
157
+ if request.title is not None:
158
+ update_data["title"] = request.title
159
+
160
+ if request.messages is not None:
161
+ update_data["messages"] = request.messages
162
+
163
+ await db.chat_sessions.update_one(
164
+ {"_id": ObjectId(session_id)},
165
+ {"$set": update_data}
166
+ )
167
+
168
+ return {"message": "Chat session updated successfully"}
169
+
170
+ except HTTPException:
171
+ raise
172
+ except Exception as e:
173
+ logger.error(f"Error updating chat session: {e}")
174
+ raise HTTPException(
175
+ status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
176
+ detail="Could not update chat session"
177
+ )
178
+
179
+ @router.post("/chat-sessions/{session_id}/messages")
180
+ async def save_message_to_session(
181
+ session_id: str,
182
+ request: SaveMessageRequest,
183
+ current_user: User = Depends(get_current_active_user)
184
+ ):
185
+ """Add a message to a chat session"""
186
+ try:
187
+ db = get_database()
188
+
189
+ # Verify session belongs to user
190
+ session_data = await db.chat_sessions.find_one({
191
+ "_id": ObjectId(session_id),
192
+ "user_id": current_user.id,
193
+ "is_active": True
194
+ })
195
+
196
+ if not session_data:
197
+ raise HTTPException(
198
+ status_code=status.HTTP_404_NOT_FOUND,
199
+ detail="Chat session not found"
200
+ )
201
+
202
+ # Add timestamp to message if not present
203
+ message = request.message.copy()
204
+ if "timestamp" not in message:
205
+ message["timestamp"] = datetime.utcnow().isoformat()
206
+
207
+ await db.chat_sessions.update_one(
208
+ {"_id": ObjectId(session_id)},
209
+ {
210
+ "$push": {"messages": message},
211
+ "$set": {"updated_at": datetime.utcnow()}
212
+ }
213
+ )
214
+
215
+ return {"message": "Message saved successfully"}
216
+
217
+ except HTTPException:
218
+ raise
219
+ except Exception as e:
220
+ logger.error(f"Error saving message: {e}")
221
+ raise HTTPException(
222
+ status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
223
+ detail="Could not save message"
224
+ )
225
+
226
+ @router.delete("/chat-sessions/{session_id}")
227
+ async def delete_chat_session(
228
+ session_id: str,
229
+ current_user: User = Depends(get_current_active_user)
230
+ ):
231
+ """Delete a chat session (soft delete)"""
232
+ try:
233
+ db = get_database()
234
+
235
+ result = await db.chat_sessions.update_one(
236
+ {
237
+ "_id": ObjectId(session_id),
238
+ "user_id": current_user.id
239
+ },
240
+ {"$set": {"is_active": False, "updated_at": datetime.utcnow()}}
241
+ )
242
+
243
+ if result.matched_count == 0:
244
+ raise HTTPException(
245
+ status_code=status.HTTP_404_NOT_FOUND,
246
+ detail="Chat session not found"
247
+ )
248
+
249
+ return {"message": "Chat session deleted successfully"}
250
+
251
+ except HTTPException:
252
+ raise
253
+ except Exception as e:
254
+ logger.error(f"Error deleting chat session: {e}")
255
+ raise HTTPException(
256
+ status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
257
+ detail="Could not delete chat session"
258
+ )