add user if exists on konviva

This commit is contained in:
2025-07-11 13:55:32 -03:00
parent bd6fbf7166
commit 1b710c81f6
23 changed files with 1633 additions and 68 deletions

View File

@@ -0,0 +1,13 @@
import os
import boto3
def get_dynamodb_client():
if os.getenv('AWS_LAMBDA_FUNCTION_NAME'):
return boto3.client('dynamodb')
return boto3.client('dynamodb', endpoint_url='http://127.0.0.1:8000')
dynamodb_client = get_dynamodb_client()

View File

@@ -0,0 +1,6 @@
import os
USER_TABLE: str = os.getenv('USER_TABLE') # type: ignore
KONVIVA_API_URL: str = os.getenv('KONVIVA_API_URL') # type: ignore
KONVIVA_SECRET_KEY: str = os.getenv('KONVIVA_SECRET_KEY') # type:ignore

View File

@@ -0,0 +1,70 @@
from aws_lambda_powertools import Logger
from aws_lambda_powertools.utilities.data_classes import (
EventBridgeEvent,
event_source,
)
from aws_lambda_powertools.utilities.typing import LambdaContext
from glom import glom
from layercake.dateutils import now
from layercake.dynamodb import DynamoDBPersistenceLayer, KeyPair
import konviva
from boto3clients import dynamodb_client
from config import USER_TABLE
logger = Logger(__name__)
user_layer = DynamoDBPersistenceLayer(USER_TABLE, dynamodb_client)
class UserNotFoundError(Exception): ...
@event_source(data_class=EventBridgeEvent)
@logger.inject_lambda_context
def lambda_handler(event: EventBridgeEvent, context: LambdaContext) -> bool:
new_image = event.detail['new_image']
now_ = now()
try:
user_id = konviva.create_user(
id=new_image['id'],
name=new_image['name'],
email=new_image['email'],
cpf=new_image.get('cpf', None),
)
except konviva.EmailAlreadyExists:
logger.info(
'Email already exists, retrieving existing user',
email=new_image['email'],
)
r = konviva.get_users_by_email(new_image['email'])
user_id = glom(r, '0.IDUsuario')
if not r:
raise UserNotFoundError()
except Exception:
raise
with user_layer.transact_writer() as transact:
transact.update(
key=KeyPair(new_image['id'], '0'),
update_expr='SET metadata__konviva_user_id = :user_id, \
updated_at = :updated_at',
expr_attr_values={
':user_id': user_id,
':updated_at': now_,
},
cond_expr='attribute_exists(sk)',
)
# Post-migration: remove the following line
transact.put(
item={
'id': new_image['id'],
'sk': 'konviva',
'konvivaId': user_id,
'created_at': now_,
}
)
return True

View File

@@ -0,0 +1,99 @@
import random
import string
from dataclasses import dataclass
from urllib.parse import quote_plus, urlparse
import requests
from aws_lambda_powertools.event_handler.exceptions import BadRequestError
from glom import glom
from config import KONVIVA_API_URL, KONVIVA_SECRET_KEY
ALU = 2
GES = 3
headers = {
'Authorization': f'KONVIVA {KONVIVA_SECRET_KEY}',
'Content-Type': 'application/json',
}
def random_str(maxlen: int = 10) -> str:
"""Returns a random string of letters."""
return ''.join(random.choice(string.ascii_letters) for _ in range(maxlen))
class KonvivaError(BadRequestError):
pass
class EmailAlreadyExists(KonvivaError):
pass
@dataclass(frozen=True)
class User:
IDUsuario: int
Identificador: str
NomeUsuario: str
Email: str
CPF: str | None = None
def create_user(
id: str,
name: str,
email: str,
cpf: str | None,
) -> dict:
url = urlparse(KONVIVA_API_URL)._replace(
path='/action/api/integrarUsuario',
query='sendMail=false',
)
r = requests.post(
url=url.geturl(),
headers=headers,
json={
'Identificador': id,
'NomeUsuario': name,
'Login': email,
'Email': email,
'CPF': cpf,
'Senha': random_str(30),
'Situacao': 'ATIVO',
'UnidadesPerfil': [
{
'IDPerfil': ALU,
'CODPerfil': 'ALU',
'CODUnidade': '1380e6d0-fee8-4cb9-9bf0-a087e703b1a4',
}
],
},
)
r.raise_for_status()
# Because Konviva does not return the proper HTTP status code
if err := glom(r.json(), 'errors', default=None):
err = err[0] if isinstance(err, list) else err
raise EmailAlreadyExists(err)
return r.json().get('IDUsuario')
def get_users_by_email(email: str) -> list[dict]:
url = urlparse(KONVIVA_API_URL)._replace(
path='/action/api/getUsuariosByQuery',
query=f'q=Email=={quote_plus(email)}',
)
r = requests.get(
url=url.geturl(),
headers=headers,
)
r.raise_for_status()
if glom(r.json(), '0.errors', default=None):
return []
return r.json()