Chandima Prabhath commited on
Commit ·
01a6877
1
Parent(s): 15d515e
Add profile picture upload functionality using Cloudinary and update user profile
Browse files- main.py +38 -3
- requirements.txt +2 -1
main.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
| 1 |
-
from fastapi import FastAPI, HTTPException, Depends, status, APIRouter
|
| 2 |
from fastapi.security import OAuth2PasswordRequestForm, OAuth2PasswordBearer
|
| 3 |
from fastapi.middleware.cors import CORSMiddleware
|
| 4 |
from datetime import datetime, timedelta, timezone
|
|
@@ -7,12 +7,19 @@ from typing import Optional, List
|
|
| 7 |
from pydantic import BaseModel, Field, validator
|
| 8 |
import jwt
|
| 9 |
import database
|
|
|
|
|
|
|
|
|
|
| 10 |
|
| 11 |
# JWT configuration
|
| 12 |
SECRET_KEY = "06J3LND9NFH"
|
| 13 |
ALGORITHM = "HS256"
|
| 14 |
ACCESS_TOKEN_EXPIRE_MINUTES = 43200
|
| 15 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 16 |
app = FastAPI()
|
| 17 |
|
| 18 |
# Uncomment and adjust CORS if needed:
|
|
@@ -24,6 +31,13 @@ app = FastAPI()
|
|
| 24 |
# allow_headers=["*"],
|
| 25 |
# )
|
| 26 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 27 |
# Define the OAuth2 scheme for OpenAPI docs.
|
| 28 |
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/api/v1/auth/login")
|
| 29 |
|
|
@@ -329,6 +343,29 @@ def delete_existing_user(user_id: int, current_user: dict = Depends(get_current_
|
|
| 329 |
database.delete_user(user_id)
|
| 330 |
return {"detail": "User deleted"}
|
| 331 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 332 |
# Authentication Router
|
| 333 |
auth_router = APIRouter(prefix="/api/v1/auth", tags=["Authentication"])
|
| 334 |
|
|
@@ -338,7 +375,6 @@ def login(form_data: OAuth2PasswordRequestForm = Depends()):
|
|
| 338 |
if not user:
|
| 339 |
raise HTTPException(status_code=400, detail="Incorrect username or password")
|
| 340 |
access_token = create_access_token(data={"sub": user["username"]})
|
| 341 |
-
# Return the token so clients can include it in the "Authorization" header.
|
| 342 |
return {"access_token": access_token, "token_type": "bearer"}
|
| 343 |
|
| 344 |
@auth_router.get("/me", response_model=UserOut)
|
|
@@ -443,7 +479,6 @@ event_router = APIRouter(prefix="/api/v1/events", tags=["Events"])
|
|
| 443 |
|
| 444 |
@event_router.post("/create", response_model=EventOut)
|
| 445 |
def create_event(event: EventCreate, current_user: dict = Depends(get_current_user)):
|
| 446 |
-
# Convert empty or default values to None for optional recurrence fields
|
| 447 |
recurrence_type = event.recurrence_type.strip() if event.recurrence_type and event.recurrence_type.strip() else None
|
| 448 |
recurrence_interval = event.recurrence_interval if event.recurrence_interval and event.recurrence_interval != 0 else None
|
| 449 |
recurrence_end_date = event.recurrence_end_date if event.recurrence_end_date else None
|
|
|
|
| 1 |
+
from fastapi import FastAPI, HTTPException, Depends, status, APIRouter, UploadFile, File
|
| 2 |
from fastapi.security import OAuth2PasswordRequestForm, OAuth2PasswordBearer
|
| 3 |
from fastapi.middleware.cors import CORSMiddleware
|
| 4 |
from datetime import datetime, timedelta, timezone
|
|
|
|
| 7 |
from pydantic import BaseModel, Field, validator
|
| 8 |
import jwt
|
| 9 |
import database
|
| 10 |
+
import cloudinary
|
| 11 |
+
import cloudinary.uploader
|
| 12 |
+
import os
|
| 13 |
|
| 14 |
# JWT configuration
|
| 15 |
SECRET_KEY = "06J3LND9NFH"
|
| 16 |
ALGORITHM = "HS256"
|
| 17 |
ACCESS_TOKEN_EXPIRE_MINUTES = 43200
|
| 18 |
|
| 19 |
+
CLOUD_NAME = os.getenv('CLOUD_NAME')
|
| 20 |
+
API_KEY = int(os.getenv('API_KEY'))
|
| 21 |
+
API_SECRET = os.getenv('API_SECRET')
|
| 22 |
+
|
| 23 |
app = FastAPI()
|
| 24 |
|
| 25 |
# Uncomment and adjust CORS if needed:
|
|
|
|
| 31 |
# allow_headers=["*"],
|
| 32 |
# )
|
| 33 |
|
| 34 |
+
# Configure Cloudinary (ensure you have set your credentials accordingly)
|
| 35 |
+
cloudinary.config(
|
| 36 |
+
cloud_name=CLOUD_NAME,
|
| 37 |
+
api_key=API_KEY,
|
| 38 |
+
api_secret=API_SECRET
|
| 39 |
+
)
|
| 40 |
+
|
| 41 |
# Define the OAuth2 scheme for OpenAPI docs.
|
| 42 |
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/api/v1/auth/login")
|
| 43 |
|
|
|
|
| 343 |
database.delete_user(user_id)
|
| 344 |
return {"detail": "User deleted"}
|
| 345 |
|
| 346 |
+
@user_router.post("/upload-profile-picture", response_model=UserOut)
|
| 347 |
+
async def upload_profile_picture(file: UploadFile = File(...), current_user: dict = Depends(get_current_user)):
|
| 348 |
+
try:
|
| 349 |
+
result = cloudinary.uploader.upload(file.file)
|
| 350 |
+
except Exception as e:
|
| 351 |
+
raise HTTPException(status_code=400, detail=f"Image upload failed: {str(e)}")
|
| 352 |
+
image_url = result.get("secure_url")
|
| 353 |
+
if not image_url:
|
| 354 |
+
raise HTTPException(status_code=400, detail="Failed to obtain image URL from Cloudinary")
|
| 355 |
+
# Update the user's profile picture in the database
|
| 356 |
+
database.update_user(
|
| 357 |
+
current_user["user_id"],
|
| 358 |
+
username=None,
|
| 359 |
+
email=None,
|
| 360 |
+
password_hash=None,
|
| 361 |
+
first_name=None,
|
| 362 |
+
last_name=None,
|
| 363 |
+
bio=None,
|
| 364 |
+
profile_picture=image_url
|
| 365 |
+
)
|
| 366 |
+
updated_user = database.get_user_by_id(current_user["user_id"])
|
| 367 |
+
return updated_user
|
| 368 |
+
|
| 369 |
# Authentication Router
|
| 370 |
auth_router = APIRouter(prefix="/api/v1/auth", tags=["Authentication"])
|
| 371 |
|
|
|
|
| 375 |
if not user:
|
| 376 |
raise HTTPException(status_code=400, detail="Incorrect username or password")
|
| 377 |
access_token = create_access_token(data={"sub": user["username"]})
|
|
|
|
| 378 |
return {"access_token": access_token, "token_type": "bearer"}
|
| 379 |
|
| 380 |
@auth_router.get("/me", response_model=UserOut)
|
|
|
|
| 479 |
|
| 480 |
@event_router.post("/create", response_model=EventOut)
|
| 481 |
def create_event(event: EventCreate, current_user: dict = Depends(get_current_user)):
|
|
|
|
| 482 |
recurrence_type = event.recurrence_type.strip() if event.recurrence_type and event.recurrence_type.strip() else None
|
| 483 |
recurrence_interval = event.recurrence_interval if event.recurrence_interval and event.recurrence_interval != 0 else None
|
| 484 |
recurrence_end_date = event.recurrence_end_date if event.recurrence_end_date else None
|
requirements.txt
CHANGED
|
@@ -5,4 +5,5 @@ passlib
|
|
| 5 |
python-multipart
|
| 6 |
pyjwt
|
| 7 |
PyMySQL
|
| 8 |
-
bcrypt
|
|
|
|
|
|
| 5 |
python-multipart
|
| 6 |
pyjwt
|
| 7 |
PyMySQL
|
| 8 |
+
bcrypt
|
| 9 |
+
cloudinary
|