corrected the upload service to use the correct s3 service

main
Anaz 2025-01-21 16:57:20 +04:00
parent ede9d84474
commit c5c54cee07
5 changed files with 42 additions and 53 deletions

View File

@ -1,4 +1,4 @@
from fastapi import APIRouter, Depends, File, HTTPException, UploadFile from fastapi import APIRouter, Depends, File, Form, HTTPException, UploadFile
from fastapi.security import OAuth2PasswordBearer from fastapi.security import OAuth2PasswordBearer
from pydantic import ValidationError from pydantic import ValidationError
from services.person_report_service import PersonReportService from services.person_report_service import PersonReportService
@ -6,26 +6,23 @@ from models.schemas import PersonReportCreate, PersonReportUpdate, PersonReportR
from config.database import get_db from config.database import get_db
from typing import Optional from typing import Optional
from services.auth_service import AuthService from services.auth_service import AuthService
from utils.logging import logger
router = APIRouter() router = APIRouter()
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/api/v1/auth/token") oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/api/v1/auth/token")
@router.post("/", status_code=201) @router.post("/", status_code=201)
async def create_report( async def create_report(
report: str, # Le champ report est reçu sous forme de chaîne JSON file: Optional[UploadFile] = File(None), # Le champ photo est reçu sous forme de fichier
image_file: Optional[UploadFile] = File(None), # L'image est facultative report: PersonReportCreate = Form(...), # Le champ report est reçu sous forme de chaîne JSON
db: get_db = Depends(), db: get_db = Depends(),
token: str = Depends(oauth2_scheme) token: str = Depends(oauth2_scheme)
): ):
try:
# Valider et convertir la chaîne JSON en objet PersonReportCreate
report_data = PersonReportCreate.model_validate_json(report)
except ValidationError as e:
raise HTTPException(status_code=422, detail=f"Invalid report data: {e}")
logger.info(f"Creating report: {file.filename if file else None} - {report}")
# Appeler le service pour traiter le rapport # Appeler le service pour traiter le rapport
try: try:
created_report = await PersonReportService.create_report(report_data, db, image_file, token) created_report = await PersonReportService.create_report(report, db, token, file)
except Exception as e: except Exception as e:
raise HTTPException(status_code=500, detail=f"An error occurred while creating the report: {str(e)}") raise HTTPException(status_code=500, detail=f"An error occurred while creating the report: {str(e)}")
@ -44,5 +41,5 @@ async def list_reports(status: Optional[str] = None, db=Depends(get_db)):
return await PersonReportService.list_reports(status, db) return await PersonReportService.list_reports(status, db)
@router.delete("/{report_id}", status_code=204) @router.delete("/{report_id}", status_code=204)
async def delete_report(report_id: int, db=Depends(get_db), current_user: UserResponse = Depends(AuthService.get_current_user)): async def delete_report(report_id: int, db=Depends(get_db), token: str = Depends(oauth2_scheme)):
return await PersonReportService.delete_report(report_id, db, current_user) return await PersonReportService.delete_report(report_id, db, token)

View File

@ -1,6 +1,8 @@
import json
from fastapi import Form, UploadFile
from pydantic import BaseModel, EmailStr, model_validator from pydantic import BaseModel, EmailStr, model_validator
from datetime import datetime from datetime import datetime
from typing import List, Optional from typing import Any, List, Optional
class Role(BaseModel): class Role(BaseModel):
id: int id: int
@ -131,11 +133,19 @@ class PersonReportBase(BaseModel):
reporter_email: str reporter_email: str
class PersonReportCreate(BaseModel): class PersonReportCreate(BaseModel):
full_name: str full_name: Optional[str] = Form(None)
date_of_birth: datetime date_of_birth: Optional[datetime] = Form(None)
status: str status: Optional[str] = Form(None)
location: Optional[str] = None location: Optional[str] = Form(None)
gps_coordinates: Optional[str] = None gps_coordinates: Optional[str] = Form(None)
@model_validator(mode='before')
@classmethod
def validate_to_json(cls, value: Any) -> Any:
print(value)
if isinstance(value, str):
return cls(**json.loads(value))
return value
class PersonReportUpdate(BaseModel): class PersonReportUpdate(BaseModel):
status: Optional[str] = None status: Optional[str] = None

View File

@ -1,5 +1,5 @@
from sqlalchemy import delete, select, update from sqlalchemy import delete, select, update
from fastapi import HTTPException from fastapi import HTTPException, UploadFile
from models.schemas import PersonReportCreate, PersonReportUpdate, PersonReportResponse from models.schemas import PersonReportCreate, PersonReportUpdate, PersonReportResponse
from config.database import get_db from config.database import get_db
from models.db import person_reports_table from models.db import person_reports_table
@ -8,19 +8,23 @@ from fastapi import Depends
from fastapi.security import OAuth2PasswordBearer from fastapi.security import OAuth2PasswordBearer
from services.auth_service import AuthService from services.auth_service import AuthService
from services.s3_service import UploadService from services.upload_service import UploadService
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/api/v1/auth/token") oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/api/v1/auth/token")
class PersonReportService: class PersonReportService:
@staticmethod @staticmethod
async def create_report(report: PersonReportCreate, db, image_file, token): async def create_report(report: PersonReportCreate, db, token, file: Optional[UploadFile] = None ):
user = await AuthService.get_current_user(token, db) user = await AuthService.get_current_user(token, db)if file else None
image_url = await UploadService.upload_image_to_s3(image_file, user.email) if image_file else None image_url = await UploadService.upload_image_to_s3( file, user["id"])
#image_url = file.filename if file else None
query = person_reports_table.insert().values(**report.model_dump(), query = person_reports_table.insert().values(full_name=report.full_name,
photo_url=image_url, date_of_birth=report.date_of_birth,
status=report.status,
location=report.location,
gps_coordinates=report.gps_coordinates,
photo_url=image_url["path_with_name"] if image_url else None,
reporter_email=user["email"]) reporter_email=user["email"])
try: try:
result = await db.execute(query) result = await db.execute(query)
@ -50,7 +54,7 @@ class PersonReportService:
async def get_report(report_id: int, db): async def get_report(report_id: int, db):
query = select(person_reports_table).where(person_reports_table.c.id == report_id) query = select(person_reports_table).where(person_reports_table.c.id == report_id)
result = await db.execute(query) result = await db.execute(query)
report = result.fetchone() report = result.mappings().first()
if not report: if not report:
raise HTTPException(status_code=404, detail="Report not found") raise HTTPException(status_code=404, detail="Report not found")
return PersonReportResponse(**report) return PersonReportResponse(**report)
@ -65,10 +69,9 @@ class PersonReportService:
return [PersonReportResponse(**report) for report in reports] return [PersonReportResponse(**report) for report in reports]
@staticmethod @staticmethod
async def delete_report(report_id: int, db, current_user): async def delete_report(report_id: int, db, token):
# Vérifier les droits de l'utilisateur # Vérifier les droits de l'utilisateur
if not current_user.role.permissions or "delete_reports" not in current_user.role.permissions: await AuthService.check_permissions( token , db, ["admin","collectivité","état"])
raise HTTPException(status_code=403, detail="Permission denied")
query = delete(person_reports_table).where(person_reports_table.c.id == report_id) query = delete(person_reports_table).where(person_reports_table.c.id == report_id)
try: try:

View File

@ -1,22 +0,0 @@
from fastapi import UploadFile, HTTPException
import boto3
from botocore.exceptions import NoCredentialsError
from config.settings import settings
s3_client = boto3.client(
's3',
aws_access_key_id=settings.aws_access_key_id,
aws_secret_access_key=settings.aws_secret_access_key
)
class UploadService:
@staticmethod
async def upload_file(file: UploadFile):
try:
s3_client.upload_fileobj(file.file, settings.aws_bucket_name, file.filename)
file_url = f"https://{settings.aws_bucket_name}.s3.amazonaws.com/{file.filename}"
return {"file_url": file_url}
except NoCredentialsError:
raise HTTPException(status_code=500, detail="AWS credentials not available")
except Exception as e:
raise HTTPException(status_code=500, detail=f"Could not upload file: {str(e)}")

View File

@ -25,6 +25,7 @@ class UploadService:
} }
S3_CONFIG = { S3_CONFIG = {
"url": "https://api.mayotte-urgence.com/cdn-storage",
"bucket": "sywmtnsg", "bucket": "sywmtnsg",
"endpoint_url": "https://ht2-storage.n0c.com:5443", "endpoint_url": "https://ht2-storage.n0c.com:5443",
"region_name": "ht2-storage", "region_name": "ht2-storage",
@ -71,7 +72,7 @@ class UploadService:
return { return {
"success": True, "success": True,
"path_with_name": full_path.replace("public", ""), "path_with_name": S3_CONFIG["url"]+full_path.replace("public", ""),
"filename": new_filename, "filename": new_filename,
"original_filename": file.filename, "original_filename": file.filename,
"filetype": extension, "filetype": extension,