166 lines
6.9 KiB
Python
Raw Normal View History

2022-09-16 21:50:55 +02:00
import csv
import io
import os
import sys
from typing import List
from fastapi import APIRouter, Depends, Form, UploadFile, status
from api.schemas.exercices import ExerciceSchema
from database.exercices.validators import get_support_compatibility_for_exo_source_from_data
from database.auth.models import UserModel
from generateur.generateur_csv import Csv_generator
from database.decorators import as_form
from database.exercices.models import Exercice
from fastapi.exceptions import HTTPException
from database.exercices.crud import add_tag_db, create_exo_db, delete_tag_db, get_exo_source_path, update_exo_db, delete_exo_db, clone_exo_db
from config import Exercice_schema, ExerciceIn_form, ExerciceIn_schema, Exo_schema, TagIn_schema, User_schema
from services.auth import check_author_exo, get_current_clientId, get_current_user, jwt_optional, jwt_required
from services.io import get_abs_path_from_relative_to_root, get_filename_from_path
from fastapi.responses import FileResponse, Response, StreamingResponse
from pydantic import BaseModel
from fastapi_jwt_auth import AuthJWT
from fastapi_pagination import paginate, Page
router = APIRouter()
# Exercices
@router.get("/exercices", response_model=Page[Exo_schema])
async def get_exercices():
exo_list = await Exo_schema.from_queryset(Exercice.all())
return paginate(exo_list)
@router.get('/exercices/user', response_model=Page[Exo_schema])
async def get_exercices(Authorize: AuthJWT=Depends(jwt_required)):
username = Authorize.get_jwt_subject()
user = await UserModel.get(username=username)
exo_list = await Exo_schema.from_queryset(Exercice.filter(author_id=user.id))
return paginate(exo_list)
@router.get('/exercices/public', response_model=Page[Exo_schema])
async def get_exercices(Authorize: AuthJWT=Depends(jwt_optional)):
username = Authorize.get_jwt_subject()
is_authenticated = username != None
if is_authenticated:
user = await UserModel.get(username=username)
exo_list = Exercice.filter(author_id__not = user.id)
return paginate(exo_list)
exo_list = await Exo_schema.from_queryset(Exercice.all())
return paginate(exo_list)
@router.get('/exercice/{id_code}', response_model=ExerciceSchema)
async def get_exercice(id_code: str, Authorize: AuthJWT= Depends(jwt_optional)):
username = Authorize.get_jwt_subject()
is_authenticated = username != None
exo = await Exercice.get(id_code=id_code)
if is_authenticated:
user = await UserModel.get(username=username)
author = await exo.author
is_author = author.id == user.id
exo_obj = await Exercice_schema.from_tortoise_orm(exo)
exo_dict = exo_obj.dict()
exo_dict['is_author'] = is_author
return exo_dict
exo_obj = await Exercice_schema.from_tortoise_orm(exo)
exo_dict =exo_obj.dict()
exo_dict['is_author'] = False
return exo_dict
async def validate_file(file: UploadFile):
data = await file.read()
try:
exo_supports_compatibility = get_support_compatibility_for_exo_source_from_data(
data)
if not exo_supports_compatibility['isPdf'] and not exo_supports_compatibility['isCsv'] and not exo_supports_compatibility['isWeb']:
raise HTTPException(status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, detail={"exo_source":
'[Error] : Exercice non valide (compatible avec aucun support)'})
except Exception as e:
msg = e.args[0]
raise HTTPException(status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, detail={"exo_source": msg})
await file.seek(0)
return file
@router.post("/exercices", response_model=Exercice_schema)
async def create_exercice(file: UploadFile = Depends(validate_file), exo: ExerciceIn_schema = Depends(ExerciceIn_form.as_form), current_user: UserModel = Depends(get_current_user)):
file_obj = file.file._file
file_obj.name = file.filename
exo_obj = await create_exo_db(**{**exo.dict(exclude_unset=True)}, exo_source=file_obj, author_id=current_user.id)
return await Exercice_schema.from_tortoise_orm(exo_obj)
@router.delete("/exercices/{id_code}", response_model=str)
async def delete_exercice(id_code: str, author: User_schema = Depends(check_author_exo)):
await delete_exo_db(id_code)
return "success"
@router.put("/exercices/{id_code}", response_model=Exercice_schema)
async def update_exercice(id_code: str, file: UploadFile, exo: ExerciceIn_form = Depends(ExerciceIn_form.as_form), author: User_schema = Depends(check_author_exo)):
file_obj = file.file._file
file_obj.name = file.filename
exo_obj = await update_exo_db(id_code, **{**exo.dict(exclude_unset=True)}, exo_source=file_obj)
return await Exercice_schema.from_tortoise_orm(exo_obj)
@router.post('/exercices/{id_code}/clone', response_model=Exercice_schema)
async def clone_exercice(id_code: str, user: User_schema = Depends(get_current_user)):
exo_obj = await clone_exo_db(id_code, user.id)
return await Exercice_schema.from_tortoise_orm(exo_obj)
@router.get('/exercices/{id_code}/exo_source')
async def get_exo_source(id_code: str, author: User_schema = Depends(check_author_exo)):
path = await get_exo_source_path(id_code)
filename = get_filename_from_path(path)
return FileResponse(path, filename=filename)
# Tags
@router.post('/exercices/{id_code}/tags', response_model=Exercice_schema)
async def update_tag(id_code: str, tags_data: List[TagIn_schema], current_user: User_schema = Depends(get_current_user)):
exo_obj = await add_tag_db(id_code, tags_data, current_user.id)
return await Exercice_schema.from_tortoise_orm(exo_obj)
@router.delete('/exercices/{exo_id}/tags/{tags_id}', response_model=Exercice_schema)
async def remove_tag(exo_id: str, tag_id: str, owner: User_schema = Depends(check_author_exo)):
exo_obj = await delete_tag_db(exo_id, tag_id)
return await Exercice_schema.from_tortoise_orm(exo_obj)
@router.get('/generator/csv/{exo_id}')
async def generate_csv(exo_id: str, filename: str):
exo = await Exercice.get(id_code=exo_id)
if exo.csvSupport == False:
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED,
detail='Impossible de générer cet exercice sur le support csv')
source_path = get_abs_path_from_relative_to_root(exo.exo_source)
consigne = exo.consigne
buffer = io.StringIO()
writer = csv.writer(buffer, delimiter=',',
quotechar=',', quoting=csv.QUOTE_MINIMAL, dialect='excel') # mettre | comme sep un jour
Csv_generator(source_path, 10, 10, 12, consigne, writer)
return StreamingResponse(iter([buffer.getvalue()]), headers={"Content-Disposition": f'attachment;filename="{filename}'}, media_type='text/csv')
class ExoOption(BaseModel):
id: str
nbInExo: int
nbOfExo: int
@router.post('/generator/pdf')
async def generate_pdf(exos_list: List[ExoOption]):
return