def delete_version(event): contributor_id = event['requestContext']['authorizer']['sub'] title_id = event['pathParameters']['title'] version = event['pathParameters']['version'] definition = read_definition_from_s3(contributor_id, title_id) if len(definition['patches']) < 2: return response('A title must contain at least 1 version', 400) index = next((idx for (idx, d) in enumerate(definition['patches']) if d['version'] == version), None) if index is None: return response('Not Found', 404) logger.info(f"Removing version from the definition: {version}") definition['patches'].pop(index) # Use the version of the first patch after the delete operation above definition['currentVersion'] = definition['patches'][0]['version'] definition['lastModified'] = \ datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%SZ') update_table_entry(definition, contributor_id) write_definition_to_s3(definition, contributor_id) # Need to revert the DynamoDB entry for cleanup on write failure return response(f"Version '{version}' deleted from title", 200)
def add_version(event): contributor_id = event['requestContext']['authorizer']['sub'] title_id = event['pathParameters']['title'] query_string_parameters = event['queryStringParameters'] try: data = json.loads(event['body']) except (TypeError, json.JSONDecodeError): logger.exception('Bad Request: No JSON content found') return response('Bad Request: No JSON content found', 400) try: validate(data, schema_version) except ValidationError as error: logger.error('Bad Request: One or more required fields are missing') return response( { 'message': 'Bad Request: The version failed validation', 'validation_error': f"{str(error.message)} for item: " f"{'/'.join([str(i) for i in error.path])}" }, 400) definition = read_definition_from_s3(contributor_id, title_id) if data['version'] in \ [patch_['version'] for patch_ in definition['patches']]: logger.error(f"Conflicting version supplied: '{data['version']}'") return response(f"Conflict: The version '{data['version']}' exists", 409) try: target_index = get_index(query_string_parameters, definition['patches']) except ValueError as error: return response(f'Bad Request: {str(error)}', 400) logger.info(f"Updating the definition with new version: {data['version']}") definition['patches'].insert(target_index, data) # Use the version of the first patch after the insert operation above definition['currentVersion'] = \ definition['patches'][0]['version'] definition['lastModified'] = \ datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%SZ') update_table_entry(definition, contributor_id) write_definition_to_s3(definition, contributor_id) # Need to revert the DynamoDB entry for cleanup on write failure return response(f"Version '{data['version']}' added to title '{title_id}'", 201)
def lambda_handler(event, context): resource = event['resource'] contributor_id = event['requestContext']['authorizer']['sub'] title_id = event['pathParameters']['title'] current_entry = read_table_entry(title_id, contributor_id) if not current_entry: return response('Title Not Found', 404) if not current_entry['api_allowed']: return response('Forbidden: API not allowed for this title', 403) # There is a lot of duplicate code between these two methods. This should # be improved/consolidated later. if resource == '/api/v1/titles/{title}/version': return add_version(event) elif resource == '/api/v1/titles/{title}/version/{version}': return delete_version(event)
def lambda_handler(event, context): try: request_data = json.loads(event['body']) except (TypeError, json.JSONDecodeError): logger.exception('Bad Request: No JSON content found') return response('Bad Request: No JSON content found', 400) try: validate(request_data, schema_request) except ValidationError: logger.exception( 'Bad Request: One or more required fields are missing') return response('Bad Request: One or more required fields are missing', 400) id_ = hashlib.md5(request_data['name'].encode()).hexdigest() verification_code = uuid.uuid4().hex verification_url = urlunparse( ('https', DOMAIN_NAME, 'api/v1/contributors/verify', None, urlencode({ 'id': id_, 'code': verification_code }), None)) try: write_new_contributor(id_, request_data['name'], request_data['email'], verification_code) except ClientError as error: if error.response['Error'][ 'Code'] == 'ConditionalCheckFailedException': return response("Conflict: The provided name is already in use", 409) else: raise send_email(request_data['email'], request_data['name'], verification_url) return response('Success', 201)
def lambda_handler(event, context): try: contributor_id = event['requestContext']['authorizer']['sub'] except KeyError: logger.error('Token data not found!') return response('Forbidden', 403) try: data = json.loads(event['body']) except (TypeError, json.JSONDecodeError): logger.exception('Bad Request: No JSON content found') return response('Bad Request: No JSON content found', 400) try: validate(data, schema_definition) except ValidationError as error: logger.error('Bad Request: One or more required fields are missing') return response( { 'message': 'Bad Request: The definition failed validation', 'validation_error': f"{str(error.message)} for item: " f"{'/'.join([str(i) for i in error.path])}" }, 400) try: create_table_entry(data, contributor_id) except ClientError as error: if error.response['Error'][ 'Code'] == 'ConditionalCheckFailedException': return response( "Conflict: You have already created a title with " f"the ID '{data['id']}'", 409) else: return response(f'Internal Server Error', 500) try: write_definition_to_s3(data, contributor_id) except ClientError: # Delete the DynamoDB entry for cleanup return response('Internal Server Error', 500) return response(f"Title '{data['id']}' created", 201)