from http import HTTPStatus from typing import Annotated 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 NameStr from pydantic import UUID4, BaseModel, EmailStr from api_gateway import JSONResponse from boto3clients import dynamodb_client from config import USER_TABLE router = Router() dyn = DynamoDBPersistenceLayer(USER_TABLE, dynamodb_client) class OrgNotFoundError(NotFoundError): ... class MemberNotFoundError(NotFoundError): ... @router.get('//admins') def get_admins(org_id: str): return dyn.collection.query( # Post-migration: rename `admins` to `ADMIN` KeyPair(org_id, 'admins#'), limit=100, ) class User(BaseModel): id: str | UUID4 name: NameStr email: EmailStr @router.post('//admins') def add(org_id: str, user: Annotated[User, Body(embed=True)]): now_ = now() org = dyn.collection.get_item( KeyPair(pk=org_id, sk='0'), exc_cls=OrgNotFoundError, ) with dyn.transact_writer() as transact: transact.condition( key=KeyPair( # Post-migration (users): rename `orgmemebers#` to `MEMBER#ORG#` pk=f'orgmembers#{org_id}', sk=str(user.id), ), cond_expr='attribute_exists(sk)', exc_cls=MemberNotFoundError, ) transact.put( item={ 'id': user.id, # Post-migration (users): rename `orgs#` to `ORG#` 'sk': f'orgs#{org_id}', 'name': org['name'], 'cnpj': org['cnpj'], 'created_at': now_, } ) transact.put( item={ 'id': user.id, 'sk': f'SCOPE#{org_id}', 'scope': {'apps:admin'}, 'created_at': now_, } ) transact.put( item={ 'id': org_id, # Post-migrations (users): rename `admins#` to `ADMIN#` 'sk': f'admins#{user.id}', 'name': user.name, 'email': user.email, 'created_at': now_, }, ) return JSONResponse(HTTPStatus.NO_CONTENT) @router.delete('//admins/') def revoke(org_id: str, user_id: str): with dyn.transact_writer() as transact: transact.delete( # Post-migration: rename `admins` to `ADMIN` key=KeyPair(org_id, f'admins#{user_id}'), ) transact.delete( key=KeyPair(user_id, f'SCOPE#{org_id}'), ) return JSONResponse(HTTPStatus.NO_CONTENT)