from http import HTTPStatus from typing import Annotated from uuid import uuid4 from aws_lambda_powertools.event_handler.api_gateway import Router from aws_lambda_powertools.event_handler.exceptions import NotFoundError from aws_lambda_powertools.event_handler.openapi.params import Body from layercake.dateutils import now from layercake.dynamodb import DynamoDBPersistenceLayer, KeyPair from layercake.extra_types import CnpjStr, NameStr from pydantic import UUID4, BaseModel, EmailStr from api_gateway import JSONResponse from boto3clients import dynamodb_client from config import INTERNAL_EMAIL_DOMAIN, USER_TABLE from exceptions import ConflictError router = Router() dyn = DynamoDBPersistenceLayer(USER_TABLE, dynamodb_client) class CNPJConflictError(ConflictError): ... class EmailConflictError(ConflictError): ... class UserNotFoundError(NotFoundError): ... class EmailNotFoundError(NotFoundError): ... class User(BaseModel): id: str | UUID4 name: NameStr email: EmailStr @router.post('/') def add( name: Annotated[str, Body(embed=True)], cnpj: Annotated[CnpjStr, Body(embed=True)], user: Annotated[User, Body(embed=True)], ): now_ = now() org_id = str(uuid4()) email = f'org+{cnpj}@{INTERNAL_EMAIL_DOMAIN}' with dyn.transact_writer() as transact: transact.put( item={ # Post-migration (users): rename `cnpj` to `CNPJ` 'id': 'cnpj', 'sk': cnpj, 'org_id': org_id, 'created_at': now_, }, cond_expr='attribute_not_exists(sk)', exc_cls=CNPJConflictError, ) transact.put( item={ # Post-migration (users): rename `email` to `EMAIL` 'id': 'email', 'sk': email, 'user_id': org_id, 'created_at': now_, }, cond_expr='attribute_not_exists(sk)', exc_cls=EmailConflictError, ) transact.put( item={ 'id': org_id, 'sk': '0', 'name': name, 'email': email, 'cnpj': cnpj, 'created_at': now_, } ) transact.put( item={ 'id': org_id, # Post-migration: rename `emails` to `EMAIL` 'sk': f'emails#{email}', 'email_primary': True, 'email_verified': True, 'mx_record_exists': True, 'created_at': now_, } ) transact.put( item={ 'id': org_id, # Post-migration (users): rename `admins#` to `ADMIN#` 'sk': f'admins#{user.id}', 'name': user.name, 'email': user.email, 'created_at': now_, } ) transact.put( item={ 'id': user.id, # Post-migration (users): rename `orgs#` to `ORG#` 'sk': f'orgs#{org_id}', 'name': name, 'cnpj': cnpj, 'created_at': now_, } ) transact.put( item={ 'id': user.id, 'sk': f'SCOPE#{org_id}', 'scope': {'apps:admin'}, 'created_at': now_, } ) transact.put( item={ # Post-migration (users): rename `orgmembers#` to `MEMBER#ORG#` 'id': f'orgmembers#{org_id}', 'sk': user.id, 'created_at': now_, } ) transact.condition( key=KeyPair(str(user.id), '0'), cond_expr='attribute_exists(sk)', exc_cls=UserNotFoundError, ) transact.condition( # Post-migration (users): rename `email` to `EMAIL` key=KeyPair('email', user.email), cond_expr='attribute_exists(sk)', exc_cls=EmailNotFoundError, ) return JSONResponse( status_code=HTTPStatus.CREATED, body={ 'id': org_id, 'name': name, 'email': email, }, )