181 lines
5.0 KiB
Python
181 lines
5.0 KiB
Python
import json
|
|
from datetime import datetime
|
|
from http import HTTPStatus
|
|
from io import BytesIO
|
|
from typing import Annotated, Any
|
|
from urllib.parse import urlparse
|
|
|
|
import requests
|
|
from aws_lambda_powertools.event_handler.api_gateway import Response, Router
|
|
from aws_lambda_powertools.event_handler.exceptions import (
|
|
BadRequestError,
|
|
NotFoundError,
|
|
)
|
|
from aws_lambda_powertools.event_handler.openapi.params import Body
|
|
from layercake.dateutils import now
|
|
from layercake.dynamodb import DynamoDBPersistenceLayer, KeyPair
|
|
from pydantic import UUID4, BaseModel
|
|
|
|
from api_gateway import JSONResponse
|
|
from boto3clients import dynamodb_client, s3_client
|
|
from config import BUCKET_NAME, COURSE_TABLE, PAPERFORGE_API
|
|
from form_data import parse
|
|
|
|
router = Router()
|
|
dyn = DynamoDBPersistenceLayer(COURSE_TABLE, dynamodb_client)
|
|
|
|
|
|
@router.get('/<course_id>')
|
|
def get_course(course_id: str):
|
|
return dyn.collection.get_item(
|
|
KeyPair(course_id, '0'),
|
|
exc_cls=NotFoundError,
|
|
)
|
|
|
|
|
|
@router.post('/<course_id>/scormset/<scormset_id>')
|
|
def get_scormset(course_id: str, scormset_id: str):
|
|
return dyn.collection.get_item(
|
|
KeyPair(course_id, f'SCORMSET#{scormset_id}'),
|
|
exc_cls=NotFoundError,
|
|
)
|
|
|
|
|
|
class Cert(BaseModel):
|
|
exp_interval: int | None = None
|
|
s3_uri: str | None = None
|
|
|
|
def model_dump(self, **kwargs) -> dict[str, Any]:
|
|
return super().model_dump(exclude_none=True, **kwargs)
|
|
|
|
|
|
class Course(BaseModel):
|
|
id: UUID4
|
|
name: str
|
|
access_period: int
|
|
cert: Cert
|
|
draft: bool = False
|
|
demo: bool = False
|
|
rawfile: bytes | None = None
|
|
|
|
|
|
@router.put('/<course_id>')
|
|
def put_course(course_id: str):
|
|
event = router.current_event
|
|
|
|
if not event.decoded_body:
|
|
raise BadRequestError('Invalid request body')
|
|
|
|
now_ = now()
|
|
body = parse(
|
|
event.headers,
|
|
BytesIO(event.decoded_body.encode()),
|
|
)
|
|
course = Course.model_validate({'id': course_id, 'cert': {}} | body)
|
|
|
|
if course.rawfile:
|
|
object_key = f'certs/templates/{course_id}.html'
|
|
course.cert.s3_uri = f's3://{BUCKET_NAME}/{object_key}'
|
|
|
|
s3_client.put_object(
|
|
Bucket=BUCKET_NAME,
|
|
Key=object_key,
|
|
Body=course.rawfile,
|
|
ContentType='text/html',
|
|
)
|
|
|
|
with dyn.transact_writer() as transact:
|
|
transact.update(
|
|
key=KeyPair(str(course.id), '0'),
|
|
update_expr='SET #name = :name, \
|
|
access_period = :access_period, \
|
|
cert = :cert, \
|
|
draft = :draft, \
|
|
updated_at = :updated_at',
|
|
expr_attr_names={
|
|
'#name': 'name',
|
|
},
|
|
expr_attr_values={
|
|
':name': course.name,
|
|
':cert': course.cert.model_dump(),
|
|
':access_period': course.access_period,
|
|
':draft': course.draft,
|
|
':updated_at': now_,
|
|
},
|
|
cond_expr='attribute_exists(sk)',
|
|
exc_cls=BadRequestError,
|
|
)
|
|
|
|
return JSONResponse(HTTPStatus.NO_CONTENT)
|
|
|
|
|
|
@router.post('/<course_id>/sample')
|
|
def sample(course_id: str, s3_uri: Annotated[str, Body(embed=True)]):
|
|
now_ = now()
|
|
# Send template URI and data to Paperforge API to generate a PDF
|
|
r = requests.post(
|
|
PAPERFORGE_API,
|
|
data=json.dumps(
|
|
{
|
|
'template_uri': s3_uri,
|
|
'args': {
|
|
'name': 'Juscelino Kubitschek',
|
|
'cpf': '***.810.132-**',
|
|
'score': 100,
|
|
'started_at': now_.strftime('%d/%m/%Y'),
|
|
'completed_at': now_.strftime('%d/%m/%Y'),
|
|
'today': _datefmt(now_),
|
|
'year': now_.strftime('%Y'),
|
|
'expires_at': now_.strftime('%d/%m/%Y'),
|
|
},
|
|
},
|
|
),
|
|
)
|
|
r.raise_for_status()
|
|
|
|
return Response(
|
|
body=r.content,
|
|
content_type='application/pdf',
|
|
status_code=HTTPStatus.OK,
|
|
headers={
|
|
'Content-Disposition': f'attachment; filename="{course_id}.pdf"',
|
|
},
|
|
)
|
|
|
|
|
|
@router.post('/<course_id>/template')
|
|
def template(course_id: str, s3_uri: Annotated[str, Body(embed=True)]):
|
|
parsed = urlparse(s3_uri)
|
|
|
|
bucket = parsed.netloc
|
|
object_key = parsed.path.lstrip('/')
|
|
|
|
r = s3_client.get_object(Bucket=bucket, Key=object_key)
|
|
|
|
return Response(
|
|
body=r['Body'].read(),
|
|
content_type='text/html',
|
|
status_code=HTTPStatus.OK,
|
|
headers={
|
|
'Content-Disposition': f'attachment; filename="{course_id}.html"',
|
|
},
|
|
)
|
|
|
|
|
|
def _datefmt(dt: datetime) -> str:
|
|
months = [
|
|
'Janeiro',
|
|
'Fevereiro',
|
|
'Março',
|
|
'Abril',
|
|
'Maio',
|
|
'Junho',
|
|
'Julho',
|
|
'Agosto',
|
|
'Setembro',
|
|
'Outubro',
|
|
'Novembro',
|
|
'Dezembro',
|
|
]
|
|
return f'{dt.day:02d} de {months[dt.month - 1]} de {dt.year}'
|