add download sample

This commit is contained in:
2025-10-07 20:07:29 -03:00
parent 4fdf98a5b4
commit 08db9d0191
5 changed files with 87 additions and 8 deletions

View File

@@ -5,3 +5,5 @@ ENROLLMENT_TABLE: str = os.getenv('ENROLLMENT_TABLE') # type: ignore
COURSE_TABLE: str = os.getenv('COURSE_TABLE') # type: ignore COURSE_TABLE: str = os.getenv('COURSE_TABLE') # type: ignore
BUCKET_NAME: str = os.getenv('BUCKET_NAME') # type: ignore BUCKET_NAME: str = os.getenv('BUCKET_NAME') # type: ignore
PAPERFORGE_API = 'https://paperforge.saladeaula.digital'

View File

@@ -1,20 +1,24 @@
import json
from datetime import datetime
from http import HTTPStatus from http import HTTPStatus
from io import BytesIO from io import BytesIO
from typing import Any from typing import Annotated, Any
import requests
from aws_lambda_powertools import Logger from aws_lambda_powertools import Logger
from aws_lambda_powertools.event_handler.api_gateway import Router from aws_lambda_powertools.event_handler.api_gateway import Response, Router
from aws_lambda_powertools.event_handler.exceptions import ( from aws_lambda_powertools.event_handler.exceptions import (
BadRequestError, BadRequestError,
NotFoundError, NotFoundError,
) )
from aws_lambda_powertools.event_handler.openapi.params import Body
from layercake.dateutils import now from layercake.dateutils import now
from layercake.dynamodb import DynamoDBPersistenceLayer, KeyPair from layercake.dynamodb import DynamoDBPersistenceLayer, KeyPair
from pydantic import UUID4, BaseModel from pydantic import UUID4, BaseModel
from api_gateway import JSONResponse from api_gateway import JSONResponse
from boto3clients import dynamodb_client, s3_client from boto3clients import dynamodb_client, s3_client
from config import BUCKET_NAME, COURSE_TABLE from config import BUCKET_NAME, COURSE_TABLE, PAPERFORGE_API
from form_data import parse from form_data import parse
logger = Logger(__name__) logger = Logger(__name__)
@@ -89,3 +93,55 @@ def edit_course(course_id: str):
) )
return JSONResponse(HTTPStatus.NO_CONTENT) 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}_sample.pdf"',
},
)
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}'

View File

@@ -70,7 +70,7 @@ Resources:
TableName: !Ref CourseTable TableName: !Ref CourseTable
- DynamoDBCrudPolicy: - DynamoDBCrudPolicy:
TableName: !Ref EnrollmentTable TableName: !Ref EnrollmentTable
- S3WritePolicy: - S3CrudPolicy:
BucketName: !Ref BucketName BucketName: !Ref BucketName
Events: Events:
Preflight: Preflight:

View File

@@ -62,3 +62,24 @@ def test_edit_course(
r['cert']['s3_uri'] r['cert']['s3_uri']
== 's3://saladeaula.digital/certs/2a8963fc-4694-4fe2-953a-316d1b10f1f5.html' == 's3://saladeaula.digital/certs/2a8963fc-4694-4fe2-953a-316d1b10f1f5.html'
) )
def test_sample(
app,
seeds,
dynamodb_persistence_layer: DynamoDBPersistenceLayer,
http_api_proxy: HttpApiProxy,
lambda_context: LambdaContext,
):
r = app.lambda_handler(
http_api_proxy(
raw_path='/courses/2a8963fc-4694-4fe2-953a-316d1b10f1f5/sample',
method=HTTPMethod.POST,
body={
's3_uri': 's3://saladeaula.digital/certs/samples/cipa-grau-de-risco-1.html',
},
),
lambda_context,
)
assert r['statusCode'] == HTTPStatus.OK
# print(r['body'])

View File

@@ -21,7 +21,8 @@ from config import (
) )
logger = Logger(__name__) logger = Logger(__name__)
dyn = DynamoDBPersistenceLayer(ENROLLMENT_TABLE, dynamodb_client) enrollment_layer = DynamoDBPersistenceLayer(ENROLLMENT_TABLE, dynamodb_client)
course_layer = DynamoDBPersistenceLayer(COURSE_TABLE, dynamodb_client)
@event_source(data_class=EventBridgeEvent) @event_source(data_class=EventBridgeEvent)
@@ -31,11 +32,10 @@ def lambda_handler(event: EventBridgeEvent, context: LambdaContext) -> bool:
now_ = now() now_ = now()
enrollment_id = new_image['id'] enrollment_id = new_image['id']
course_id = new_image['course']['id'] course_id = new_image['course']['id']
cert = dyn.collection.get_item( cert = course_layer.collection.get_item(
KeyPair( KeyPair(
pk=course_id, pk=course_id,
sk=SortKey('0', path_spec='cert', rename_key='cert'), sk=SortKey('0', path_spec='cert', rename_key='cert'),
table_name=COURSE_TABLE,
), ),
raise_on_error=False, raise_on_error=False,
default=False, default=False,
@@ -101,7 +101,7 @@ def lambda_handler(event: EventBridgeEvent, context: LambdaContext) -> bool:
logger.exception(exc) logger.exception(exc)
raise raise
return dyn.update_item( return enrollment_layer.update_item(
key=KeyPair( key=KeyPair(
pk=enrollment_id, pk=enrollment_id,
sk='0', sk='0',