"""Lambda create_master_contact function module.""" from lambdacommon.graphql.graphql import GraphQLError import config from config import app_logger as logger from config import graphql_gateway from src.constants import queries from marshmallow import EXCLUDE from marshmallow import ValidationError from owsrequest import request from src.schemas.create_master_contact import CreateMasterContactSchema AWAL_PLUS_SOURCE = 'event.awalPlusAccountCreation' KNR_SOURCE = 'event.knrAccountCreation' class RetryException(Exception): """Retry Exception.""" pass class BadRequest(Exception): """Bad Request cannot retry Exception.""" pass def handler(event, context): """Lambda entry point.""" try: input_data = event or {} result = CreateMasterContactSchema().load(input_data, unknown=EXCLUDE) full_name = f"{result['first_name']} {result['last_name']}" logger.info( f'Successfully validated the request for {full_name} ' 'Now calling create_master_contact.') # get new vendor uuid. get_resource_endpoint = f"/e2e/resource/Vendor/{result['vendor_id']}" get_resource_result = request.process( config.LAMBDA_NAME, config.ENVIRONMENT, 'GET', config.OWS_SERVICE_NAME, get_resource_endpoint, headers=config.OWS_REQUEST_HEADERS) if get_resource_result.status_code >= 300: logger.error('Invalid request. ', get_resource_result.text) raise ValidationError('Could not retrieve valid vendor.') vendor_uuid = get_resource_result.json()['uuid'] # set roles according to the brand and admin/non-admin rights if input_data.get('source') == AWAL_PLUS_SOURCE: if result.get('is_admin'): roles = ['ADMINISTRATOR'] elif not result.get('is_admin') and result.get('roles'): roles = result.get('roles') else: roles = ['ANALYTICS', 'CATALOG', 'ACCOUNTING'] elif input_data.get('source') == KNR_SOURCE: if result.get('is_admin'): roles = ['ADMINISTRATOR'] else: roles = ['ACCOUNTING'] else: roles = ['ANALYTICS', 'CATALOG', 'ACCOUNTING', 'PAYEE_MANAGEMENT'] # create master contact user identity_data = { 'name': full_name, 'email': result['email'], 'firstName': result['first_name'], 'lastName': result['last_name'] } # we don't have localization for AWAL Plus if input_data.get('source') != AWAL_PLUS_SOURCE and \ result.get('localization'): identity_data['localization'] = result['localization'] resource_access_data = [{ 'type': 'Vendor', 'uuid': vendor_uuid, 'roles': roles, }] user_metadata_flags = [{ 'label': 'INVOKED_FROM_LAMBDA', 'value': True }] # Set GraphQL Headers: graphql_gateway.set_headers(config.GRAPHQL_HEADERS) query_result = graphql_gateway.execute( queries.add_resources_profiles, { 'identity': identity_data, 'resourceAccess': resource_access_data, 'userMetadataFlags': user_metadata_flags, 'masterContact': result['master_contact'], 'createAuth0User': False, 'overwriteExistingAccess': False } ) if query_result: if not query_result['data']['addUserIdentity'] or \ len(query_result['data']['addUserIdentity']) < 1: raise RetryException('No identities were created. ' 'Lets retry.') identity = query_result['data']['addUserIdentity'] return_value = {} labelProfileId = 0 # for identity in data: return_value['identity_id'] = identity['id'] if not identity['profiles'] or \ len(identity.get('profiles', [])) < 1: raise RetryException('No profiles were created. ' 'Lets retry.') if not identity['id']: raise RetryException('No identities were created. ' 'Lets retry.') for profile in identity['profiles']: if profile['profileType'] == 'LABEL' \ and int(profile['profileId']) > labelProfileId: labelProfileId = int(profile['profileId']) break return_value['label_profile_id'] = str(labelProfileId) # vendor_uuid is used by create_subscription return_value['vendor_uuid'] = vendor_uuid return return_value else: logger.info(f'Error: empty GraphQL Query result: {query_result}' f' for identity={identity_data} ') raise RetryException( 'GraphQL Request failed for valid request, so retry.') except GraphQLError as gqlErr: if gqlErr.response and \ gqlErr.response['status'] == 404 and \ gqlErr.response['body']['code'] == 'not_found_error': logger.info(f'NotFoundError: GraphQL response={gqlErr.response}' f' for identity={identity_data}') # Retry again, probably sync data between # art_relations and neo4j isn't finished. raise RetryException( f'NotFoundError: GraphQL response={gqlErr.response}.' f' Lets retry.' ) if gqlErr.response and 400 <= gqlErr.response['status'] < 500: logger.info(f'Error: GraphQL response={gqlErr.response}' f' for identity={identity_data}') raise BadRequest('Invalid request.', gqlErr) else: logger.info( f'Error: GraphQL response status={gqlErr.response}' f' for identity={identity_data}') raise RetryException( 'GraphQL Request failed for valid request, so retry.') except ValidationError as err: logger.error('Invalid request.', err.messages) raise BadRequest('Invalid request.', err.messages) except Exception as e: logger.info('Encountered Exception:') logger.info(str(e))