This commit is contained in:
2025-05-16 14:29:14 -03:00
parent 17131380ac
commit cc9bd08daa
49 changed files with 177 additions and 54 deletions

View File

@@ -26,7 +26,6 @@ Example
from dataclasses import asdict, dataclass
from typing import Any
import boto3
from aws_lambda_powertools import Logger, Tracer
from aws_lambda_powertools.utilities.data_classes import event_source
from aws_lambda_powertools.utilities.data_classes.api_gateway_authorizer_event import (
@@ -34,13 +33,14 @@ from aws_lambda_powertools.utilities.data_classes.api_gateway_authorizer_event i
APIGatewayAuthorizerResponseV2,
)
from aws_lambda_powertools.utilities.typing import LambdaContext
import boto3
from botocore.endpoint_provider import Enum
from layercake.dynamodb import DynamoDBCollection, DynamoDBPersistenceLayer, KeyPair
from layercake.funcs import pick
from boto3clients import dynamodb_client
from cognito import get_user
from settings import USER_TABLE
from conf import USER_TABLE
APIKEY_PREFIX = 'sk-'

View File

@@ -2,11 +2,11 @@ from dataclasses import asdict, dataclass
from urllib.parse import quote as urlquote
from urllib.parse import urlencode, urlparse
import requests
from aws_lambda_powertools.event_handler.exceptions import BadRequestError
from glom import glom
import requests
from settings import KONVIVA_API_URL, KONVIVA_SECRET_KEY
from conf import KONVIVA_API_URL, KONVIVA_SECRET_KEY
class KonvivaError(BadRequestError):

View File

@@ -1,3 +1,4 @@
from auth import AuthFlowType
from aws_lambda_powertools.event_handler.api_gateway import (
APIGatewayHttpResolver,
Response,
@@ -8,9 +9,6 @@ from aws_lambda_powertools.event_handler.middlewares import (
)
from pydantic import UUID4, BaseModel, EmailStr, Field
from auth import AuthFlowType
class User(BaseModel):
id: str
name: str

View File

@@ -1,5 +1,6 @@
from http import HTTPStatus
from auth import AuthFlowType
from aws_lambda_powertools.event_handler.api_gateway import (
APIGatewayHttpResolver,
Response,
@@ -16,11 +17,8 @@ from aws_lambda_powertools.event_handler.middlewares import (
from layercake.dynamodb import ComposeKey, DynamoDBCollection, KeyPair
from pydantic import UUID4, BaseModel
from auth import AuthFlowType
from .authentication_middleware import User
class Tenant(BaseModel):
id: UUID4 | str
name: str

View File

@@ -7,15 +7,15 @@ from meilisearch import Client as Meilisearch
from api_gateway import JSONResponse
from boto3clients import dynamodb_client
from middlewares import AuditLogMiddleware, Tenant, TenantMiddleware
from models import Course, Org
from rules.course import create_course, update_course
from settings import (
from conf import (
COURSE_TABLE,
MEILISEARCH_API_KEY,
MEILISEARCH_HOST,
USER_TABLE,
)
from middlewares import AuditLogMiddleware, Tenant, TenantMiddleware
from models import Course, Org
from rules.course import create_course, update_course
router = Router()

View File

@@ -11,12 +11,12 @@ from layercake.dynamodb import (
)
from pydantic import UUID4, BaseModel
import elastic
from boto3clients import dynamodb_client
from conf import ELASTIC_CONN, ENROLLMENT_TABLE, USER_TABLE
import elastic
from middlewares.audit_log_middleware import AuditLogMiddleware
from middlewares.authentication_middleware import User
from rules.enrollment import set_status_as_canceled
from settings import ELASTIC_CONN, ENROLLMENT_TABLE, USER_TABLE
from .vacancies import router as vacancies

View File

@@ -7,11 +7,11 @@ from layercake.dynamodb import (
)
from boto3clients import dynamodb_client
from middlewares import Tenant, TenantMiddleware
from settings import (
from conf import (
ENROLLMENT_TABLE,
USER_TABLE,
)
from middlewares import Tenant, TenantMiddleware
router = Router()

View File

@@ -6,7 +6,7 @@ from elasticsearch import Elasticsearch
from elasticsearch_dsl import Search
from layercake.funcs import pick
from settings import ELASTIC_CONN, USER_TABLE
from conf import ELASTIC_CONN, USER_TABLE
router = Router()
elastic_client = Elasticsearch(**ELASTIC_CONN)

View File

@@ -11,9 +11,9 @@ from layercake.dynamodb import (
KeyPair,
)
import elastic
from boto3clients import dynamodb_client
from settings import ELASTIC_CONN, ORDER_TABLE
from conf import ELASTIC_CONN, ORDER_TABLE
import elastic
router = Router()
order_layer = DynamoDBPersistenceLayer(ORDER_TABLE, dynamodb_client)

View File

@@ -1,4 +1,5 @@
from http import HTTPStatus
from typing import Literal
from aws_lambda_powertools.event_handler import Response, content_types
from aws_lambda_powertools.event_handler.api_gateway import Router
@@ -12,11 +13,10 @@ from layercake.dynamodb import (
TransactKey,
)
from pydantic.main import BaseModel
from typing_extensions import Literal
from boto3clients import dynamodb_client
from conf import USER_TABLE
from rules.org import update_policies
from settings import USER_TABLE
router = Router()
org_layer = DynamoDBPersistenceLayer(USER_TABLE, dynamodb_client)

View File

@@ -6,10 +6,10 @@ from layercake.dynamodb import (
PrefixKey,
)
import konviva
from boto3clients import dynamodb_client
from conf import USER_TABLE
import konviva
from middlewares import User
from settings import USER_TABLE
router = Router()
user_layer = DynamoDBPersistenceLayer(USER_TABLE, dynamodb_client)

View File

@@ -1,5 +1,5 @@
import json
from http import HTTPStatus
import json
from typing import Annotated
from aws_lambda_powertools.event_handler.api_gateway import Router
@@ -17,14 +17,14 @@ from layercake.dynamodb import (
from layercake.extra_types import CpfStr, NameStr
from pydantic import UUID4, BaseModel, StringConstraints
import cognito
import elastic
from api_gateway import JSONResponse
from boto3clients import dynamodb_client, idp_client
import cognito
from conf import ELASTIC_CONN, USER_POOOL_ID, USER_TABLE
import elastic
from middlewares import AuditLogMiddleware
from models import User
from rules.user import update_user
from settings import ELASTIC_CONN, USER_POOOL_ID, USER_TABLE
from .emails import router as emails
from .logs import router as logs

View File

@@ -15,9 +15,9 @@ from pydantic import BaseModel, EmailStr
from api_gateway import JSONResponse
from boto3clients import dynamodb_client
from conf import USER_TABLE
from middlewares import AuditLogMiddleware
from rules.user import add_email, del_email, set_email_as_primary
from settings import USER_TABLE
class BadRequestError(MissingError, PowertoolsBadRequestError): ...

View File

@@ -11,7 +11,7 @@ from layercake.dynamodb import (
)
from boto3clients import dynamodb_client
from settings import USER_TABLE
from conf import USER_TABLE
from .orgs import router as orgs

View File

@@ -16,9 +16,9 @@ from pydantic import BaseModel
from api_gateway import JSONResponse
from boto3clients import dynamodb_client
from conf import USER_TABLE
from middlewares.audit_log_middleware import AuditLogMiddleware
from rules.user import del_org_member
from settings import USER_TABLE
class BadRequestError(MissingError, PowertoolsBadRequestError): ...

View File

@@ -4,7 +4,7 @@ from uuid import uuid4
from layercake.dateutils import now
from layercake.dynamodb import DynamoDBPersistenceLayer, KeyPair, TransactItems
from settings import ORDER_TABLE
from conf import ORDER_TABLE
class Author(TypedDict):

View File

@@ -0,0 +1,62 @@
import pprint
from meilisearch import Client as Meilisearch
MASTER_KEY = 'zrYPsSAG1hgq2zB1dkF0sB9xLoIwTLAz6uw38pWRf5abdpTjY2eeMTIsfPbDbqQR'
API_KEY = '1aa4c720611269e9425e8467df7e802f3a20ad6c5f31fe875ac886fc4efa2c83'
client = Meilisearch(
# 'https://meili.vps.eduseg.com.br',
# '1aa4c720611269e9425e8467df7e802f3a20ad6c5f31fe875ac886fc4efa2c83',
'http://localhost:7700'
)
pp = pprint.PrettyPrinter(indent=4)
courses = client.index('test-courses')
courses.update_settings(
{
'sortableAttributes': ['create_date'],
'filterableAttributes': ['tenant__org_id'],
}
)
# with open('cli/search-results.json') as fp:
# docs = json.load(fp)
# courses.add_documents(docs)
# pp.pprint(courses.search(''))
# client.create_index('betaeducacao-prod-orders', {'primaryKey': 'id'})
# client.create_index('betaeducacao-prod-enrollments', {'primaryKey': 'id'})
# client.create_index('betaeducacao-prod-users_d2o3r5gmm4it7j', {'primaryKey': 'id'})
# An index is where the documents are stored.
# index = client.index('users')
# pp.pprint(index.search(query='*'))
# documents = [
# {'id': 1, 'title': 'Carol', 'genres': ['Romance', 'Drama']},
# {'id': 2, 'title': 'Wonder Woman', 'genres': ['Action', 'Adventure']},
# {'id': 3, 'title': 'Life of Pi', 'genres': ['Adventure', 'Drama']},
# {
# 'id': 4,
# 'title': 'Mad Max: Fury Road',
# 'genres': ['Adventure', 'Science Fiction'],
# },
# {'id': 5, 'title': 'Moana', 'genres': ['Fantasy', 'Action']},
# {'id': 6, 'title': 'Philadelphia', 'genres': ['Drama']},
# ]
# # # If the index 'movies' does not exist, Meilisearch creates it when you first add the documents.
# index.add_documents(documents
#
# )
# pp.pprint(client.get_keys({'limit': 3}).model_dump_json())
#
# uid='fdbdda56-00dd-4f53-934f-6629f3b08ee3' name=None description='Add, get documents and search' actions=['documents.add', 'documents.get', 'search'] indexes=['users', 'courses', 'enrollments', 'orders'] expires_at=None key='1aa4c720611269e9425e8467df7e802f3a20ad6c5f31fe875ac886fc4efa2c83' created_at=datetime.datetime(2025, 4, 1, 0, 46, 27, 751365) updated_at=datetime.datetime(2025, 4, 1, 0, 46, 27, 751365)

8
http-api/cli/ddb.py Normal file
View File

@@ -0,0 +1,8 @@
import json
from layercake.dynamodb import serialize
with open('cli/search-results.json') as fp:
docs = json.load(fp)
for doc in docs:
print(json.dumps(serialize(doc)))

View File

@@ -1,8 +1,8 @@
from typing import Any, Generator
import boto3
import jsonlines
from elasticsearch import Elasticsearch
import jsonlines
from layercake.dynamodb import deserialize
from tqdm import tqdm

40
http-api/cli/unzip.py Normal file
View File

@@ -0,0 +1,40 @@
import gzip
from pathlib import Path
def unzip_gzip(file: Path, target: str):
with gzip.open(file, 'rb') as r:
with open(target, 'wb') as w:
return w.write(r.read())
def unzip_gzfiles(dirpath: Path) -> None:
"""Unzip the .gz files from a dir."""
if not dirpath.exists() or not dirpath.is_dir():
print(f'"{dirpath}" not found')
return None
gzfiles = list(dirpath.glob('*.gz'))
if not gzfiles:
print(f'No .gz files found in "{dirpath}"')
return None
# Create a directory to output the files
Path(f'{dirpath}/out').mkdir(exist_ok=True)
for file in gzfiles:
filename = file.name.removesuffix('.gz')
if not file.is_file():
continue
if unzip_gzip(file, f'{dirpath}/out/{filename}'):
print(f'Unzipped "{file.name}"')
if __name__ == '__main__':
try:
dirpath = input('Type the directory path\n')
unzip_gzfiles(Path(dirpath))
except (KeyboardInterrupt, Exception):
print('See ya')

9
http-api/env.json Normal file
View File

@@ -0,0 +1,9 @@
{
"Parameters": {
"KONVIVA_API_KEY": "ac982dd94dbfab5067182d9adb88d3da",
"USER_TABLE": "test-users",
"ORDER_TABLE": "test-orders",
"ENROLLMENT_TABLE": "test-enrollments",
"COURSE_TABLE": "test-courses"
}
}

View File

@@ -16,10 +16,23 @@ dev = [
]
[tool.pytest.ini_options]
pythonpath = ["app/"]
addopts = "--cov --cov-report html -v"
[tool.ruff]
target-version = "py311"
src = ["app"]
[tool.ruff.format]
quote-style = "single"
[tool.ruff.lint]
select = ["E", "F", "I"]
[tool.ruff.lint.isort]
lines-between-types = 1
force-sort-within-sections = true
[tool.uv.sources]
layercake = { path = "../layercake" }

View File

@@ -0,0 +1,3 @@
{
"extraPaths": ["app/"]
}

View File

@@ -17,13 +17,13 @@ Parameters:
Globals:
Function:
CodeUri: .
CodeUri: app/
Runtime: python3.13
Tracing: Active
Architectures:
- x86_64
Layers:
- !Sub arn:aws:lambda:sa-east-1:336641857101:layer:layercake:47
- !Sub arn:aws:lambda:sa-east-1:336641857101:layer:layercake:48
Environment:
Variables:
TZ: America/Sao_Paulo

View File

@@ -1,12 +1,12 @@
import base64
import json
import os
from dataclasses import dataclass
from http import HTTPMethod
import json
import os
import jsonlines
import pytest
from layercake.dynamodb import DynamoDBPersistenceLayer
import pytest
PYTEST_TABLE_NAME = 'pytest'
PK = os.getenv('DYNAMODB_PARTITION_KEY')

View File

@@ -1,5 +1,5 @@
import json
from http import HTTPMethod, HTTPStatus
import json
from layercake.dynamodb import (
ComposeKey,

View File

@@ -10,7 +10,6 @@ from layercake.dynamodb import (
from ..conftest import HttpApiProxy, LambdaContext
def test_vacancies(
mock_app,
dynamodb_seeds,

View File

@@ -1,9 +1,8 @@
import json
from http import HTTPMethod, HTTPStatus
import json
from ..conftest import HttpApiProxy, LambdaContext
def test_lookup(
mock_app,
http_api_proxy: HttpApiProxy,

View File

@@ -1,11 +1,10 @@
import json
from http import HTTPMethod, HTTPStatus
import json
from layercake.dynamodb import DynamoDBCollection, DynamoDBPersistenceLayer, KeyPair
from ..conftest import HttpApiProxy, LambdaContext
def test_get_policies(
mock_app,
dynamodb_seeds,

View File

@@ -1,9 +1,8 @@
import json
from http import HTTPMethod, HTTPStatus
import json
from ..conftest import HttpApiProxy, LambdaContext
def test_settings(
mock_app,
dynamodb_seeds,

View File

@@ -1,5 +1,5 @@
import json
from http import HTTPMethod, HTTPStatus
import json
from layercake.dynamodb import (
DynamoDBCollection,
@@ -11,7 +11,6 @@ from layercake.dynamodb import (
from ..conftest import HttpApiProxy, LambdaContext
def test_update_user_cpf(
mock_app,
dynamodb_seeds,

View File

@@ -3,7 +3,6 @@ from auth import _parse_bearer_token
from .conftest import LambdaContext
def test_bearer_jwt(lambda_context: LambdaContext):
# You should mock the Cognito user to pass the test
app.get_user = lambda *args, **kwargs: {

View File

@@ -1,5 +1,5 @@
from conf import KONVIVA_API_URL
import konviva
from settings import KONVIVA_API_URL
def test_konviva_token():

View File

@@ -1,14 +1,12 @@
from http import HTTPMethod
import pytest
from aws_lambda_powertools.event_handler.api_gateway import APIGatewayHttpResolver
from layercake.dynamodb import DynamoDBCollection, DynamoDBPersistenceLayer
from middlewares import AuthenticationMiddleware, TenantMiddleware
import pytest
from .conftest import HttpApiProxy, LambdaContext
@pytest.fixture
def mock_app(dynamodb_persistence_layer: DynamoDBPersistenceLayer):
collect = DynamoDBCollection(dynamodb_persistence_layer)