예제 #1
0
def create_provider_ownership(table, handle, new_owner_name, raid_name):
    """
    Create ownership index for a new provider or convert existing one
    :param table:
    :param handle:
    :param new_owner_name:
    :param raid_name:
    :return:
    """
    # Get current datetime
    association_datetime = raid_helpers.get_current_datetime()

    # Check if new owner exists and end normal association
    existing_provider_query_parameters = {
        'IndexName':
        'HandleNameIndex',
        'ProjectionExpression':
        "startDate, endDate",
        'FilterExpression':
        Attr('endDate').not_exists(),
        'KeyConditionExpression':
        Key('handle-name').eq('{}-{}'.format(handle, new_owner_name))
    }

    existing_provider_query_response = table.query(
        **existing_provider_query_parameters)
    existing_providers = existing_provider_query_response["Items"]

    if existing_provider_query_response["Count"] > 0:
        association_datetime = existing_providers[0]['startDate']

        # Remove indexed previous owner
        table.delete_item(Key={
            'startDate': existing_providers[0]['startDate'],
            'handle': handle
        },
                          ReturnValues='ALL_OLD')
    # Create new association
    new_owner_item = {
        'handle': handle,
        'startDate': association_datetime,
        'name': new_owner_name,
        'raidName': raid_name,
        'type': settings.SERVICE_ROLE,
        'handle-name': '{}-{}'.format(handle, new_owner_name),
        'handle-type': '{}-{}'.format(handle, settings.SERVICE_ROLE),
        'role': 'owner',
        'name-role': '{}-{}'.format(new_owner_name, 'owner'),
    }
    table.put_item(Item=new_owner_item)
def create_raid_handler(event, context):
    """
    Create and new RAiD by; generating a handle, registering with ANDS and putting to the RAiD DB and Provider Index.
    :param event:
    :param context:
    :return: RAiD object
    """
    if 'requestContext' not in event:
        return {"message": "Warming Lambda container"}

    try:
        environment = event['requestContext']['authorizer']['environment']

        owner = event['requestContext']['authorizer']['provider']

        # Initialise DynamoDB
        dynamo_db = boto3.resource('dynamodb')
        raid_table = dynamo_db.Table(
            settings.get_environment_table(settings.RAID_TABLE, environment))

        # Get current datetime
        now = raid_helpers.get_current_datetime()

        # Define Initial RAiD item
        raid_item = {'creationDate': now, 'owner': owner}

        # Interpret and validate request body
        if 'body' in event and event["body"]:
            body = json.loads(event["body"])
            # Check for provided content path to mint
            if "contentPath" in body:
                content_path = body["contentPath"]
            else:
                content_path = settings.RAID_SITE_URL

            if "meta" in body:
                raid_item['meta'] = body['meta']

            else:
                raid_item['meta'] = {}

            # Auto-generate RAiD descriptive fields if they do not exist
            if 'name' not in raid_item['meta']:
                raid_item['meta'] = {
                    'name': raid_helpers.generate_random_name()
                }

            if 'description' not in raid_item['meta']:
                raid_item['meta'][
                    'description'] = "RAiD created by '{}' at '{}'".format(
                        owner, now)

            if "startDate" in body:
                try:
                    start_date = body["startDate"]
                    datetime.datetime.strptime(start_date, "%Y-%m-%d %H:%M:%S")
                    raid_item['startDate'] = start_date
                except ValueError as e:
                    logger.error('Unable to capture date: {}'.format(e))
                    return web_helpers.generate_web_body_response(
                        '400', {
                            'message':
                            "Incorrect date format, should be yyyy-MM-dd hh:mm:ss"
                        }, event)
            else:
                raid_item['startDate'] = now
        else:
            content_path = settings.RAID_SITE_URL
            raid_item['startDate'] = now

        # Set content path
        raid_item['contentPath'] = content_path

        # Get correct ANDS Shared Secret
        if environment == settings.DEMO_ENVIRONMENT:
            ands_secret = os.environ["ANDS_DEMO_SECRET"]
        elif environment == settings.LIVE_ENVIRONMENT:
            ands_secret = os.environ["ANDS_SECRET"]

        # Get ANDS handle and content index
        ands_handle, ands_content_index = ands_helpers.get_new_ands_handle(
            environment, os.environ["ANDS_HANDLES_QUEUE"],
            os.environ["DEMO_ANDS_HANDLES_QUEUE"], os.environ["ANDS_SERVICE"],
            os.environ["DEMO_ANDS_SERVICE"], content_path,
            os.environ["ANDS_APP_ID"], ands_secret)

        # Insert minted handle into raid item
        raid_item['handle'] = ands_handle
        raid_item['contentIndex'] = ands_content_index

        # Send Dynamo DB put for new RAiD
        raid_table.put_item(Item=raid_item)

        # Define provider association item  # TODO move to DynamoDB Stream
        service_item = {
            'handle': ands_handle,
            'startDate': raid_item['startDate'],
            'name': owner,
            'raidName': raid_item['meta']['name'],
            'role': 'owner',
            'type': settings.SERVICE_ROLE,
            'name-role': '{}-{}'.format(owner, 'owner'),
            'handle-name': '{}-{}'.format(ands_handle, owner),
            'handle-type': '{}-{}'.format(ands_handle, settings.SERVICE_ROLE)
        }

        # Send Dynamo DB put for new association
        association_index_table = dynamo_db.Table(
            settings.get_environment_table(settings.ASSOCIATION_TABLE,
                                           environment))
        association_index_table.put_item(
            Item=service_item)  # TODO move to DynamoDB Stream

        raid_item['providers'] = [{
            'provider': service_item['name'],
            'startDate': service_item['startDate']
        }]

        return web_helpers.generate_web_body_response('200', raid_item, event)

    except ands_helpers.AndsMintingError as e:
        logger.error(
            'Unable to mint content path for RAiD creation: {}'.format(e))
        return web_helpers.generate_web_body_response(
            '500', {
                'message':
                "Unable to create a RAiD as ANDS was unable to mint the content path."
            }, event)

    except Exception as e:
        logger.error('Unable to create RAiD: {}'.format(e))
        return web_helpers.generate_web_body_response(
            '400', {
                'message':
                "Unable to perform request due to error. Please check structure of the body."
            }, event)
예제 #3
0
def create_raid_provider_association_handler(event, context):
    """
    Create a new provider association to a RAiD
    :param event:
    :param context:
    :return:
    """
    try:
        raid_handle = urllib.unquote(urllib.unquote(event["pathParameters"]["raidId"]))

    except:
        logger.error('Unable to validate RAiD parameter: {}'.format(sys.exc_info()[0]))
        return web_helpers.generate_web_body_response(
            '400',
            {'message': "Incorrect path parameter type formatting for RAiD handle. Ensure it is a URL encoded string"},
            event
        )

    try:
        environment = event['requestContext']['authorizer']['environment']

        # Initialise DynamoDB
        dynamo_db = boto3.resource('dynamodb')
        raid_table = dynamo_db.Table(
            settings.get_environment_table(settings.RAID_TABLE, environment)
        )

        # Check if RAiD exists
        query_response = raid_table.query(KeyConditionExpression=Key('handle').eq(raid_handle))

        if query_response["Count"] != 1:
            return web_helpers.generate_web_body_response('400', {
                'message': "Invalid RAiD handle provided in parameter path. "
                           "Ensure it is a valid RAiD handle URL encoded string"}, event)

        # Assign raid item to single item, since the result will be an array of one item
        raid_item = query_response['Items'][0]

        # Interpret and validate request body
        body = json.loads(event["body"])

        if "startDate" in body:
            try:
                start_date = datetime.datetime.strptime(body["startDate"], "%Y-%m-%d %H:%M:%S")
            except ValueError as e:
                logger.error('Unable to capture date: {}'.format(e))
                return web_helpers.generate_web_body_response('400', {
                    'message': "Incorrect date format, should be yyyy-MM-dd hh:mm:ss"}, event)

        else:
            # Get current datetime
            start_date = raid_helpers.get_current_datetime()

        if "name" not in body:
            return web_helpers.generate_web_body_response('400', {
                'message': "'name' must be provided in your request body to create an association"}, event)

        # Define provider association item
        service_item = {
            'handle': raid_handle,
            'startDate': start_date,
            'name': body['name'],
            'raidName': raid_item['meta']['name'],
            'type': settings.SERVICE_ROLE,
            'handle-name': '{}-{}'.format(raid_handle, body['name']),
            'handle-type': '{}-{}'.format(raid_handle, settings.SERVICE_ROLE)
        }

        # Send Dynamo DB put for new association
        association_index_table = dynamo_db.Table(
            settings.get_environment_table(
                settings.ASSOCIATION_TABLE, environment
            )
        )
        association_index_table.put_item(Item=service_item)

        return web_helpers.generate_web_body_response('200', {
                        'name': service_item['name'],
                        'startDate': service_item['startDate']
                    }, event)

    except:
        logger.error('Unable to associate a provider to a RAiD: {}'.format(sys.exc_info()[0]))
        return web_helpers.generate_web_body_response('500', {
            'message': "Unable to perform request due to error. Please check structure of the body."}, event)
예제 #4
0
def end_raid_provider_association_handler(event, context):
    """
    End a provider association to a RAiD
    :param event:
    :param context:
    :return:
    """
    try:
        raid_handle = urllib.unquote(urllib.unquote(event["pathParameters"]["raidId"]))

    except:
        logger.error('Unable to validate RAiD parameter: {}'.format(sys.exc_info()[0]))
        return web_helpers.generate_web_body_response(
            '400',
            {'message': "Incorrect path parameter type formatting for RAiD handle. Ensure it is a URL encoded string"},
            event
        )

    try:
        environment = event['requestContext']['authorizer']['environment']

        # Initialise DynamoDB
        dynamo_db = boto3.resource('dynamodb')
        raid_table = dynamo_db.Table(settings.get_environment_table(settings.RAID_TABLE, environment))

        # Check if RAiD exists
        query_response = raid_table.query(KeyConditionExpression=Key('handle').eq(raid_handle))

        if query_response["Count"] != 1:
            return web_helpers.generate_web_body_response('400', {
                'message': "Invalid RAiD handle provided in parameter path. "
                           "Ensure it is a valid RAiD handle URL encoded string"}, event)

        # Interpret and validate request body
        body = json.loads(event["body"])

        if "endDate" in body:
            try:
                end_date = datetime.datetime.strptime(body["endDate"], "%Y-%m-%d %H:%M:%S")
            except ValueError as e:
                logger.error('Unable to capture date: {}'.format(e))
                return web_helpers.generate_web_body_response('400', {
                    'message': "Incorrect date format, should be yyyy-MM-dd hh:mm:ss"}, event)
        else:
            # Get current datetime
            end_date = raid_helpers.get_current_datetime()

        if "name" not in body:
            return web_helpers.generate_web_body_response('400', {
                'message': "'name' must be provided in your request body to end an association"}, event)

        # Update DynamoDB put to end association
        association_index_table = dynamo_db.Table(
            settings.get_environment_table(
                settings.ASSOCIATION_TABLE, environment
            )
        )

        existing_provider_query_parameters = {
            'IndexName': 'HandleNameIndex',
            'ProjectionExpression': "startDate, endDate",
            'FilterExpression': Attr('endDate').not_exists(),
            'KeyConditionExpression': Key('handle-name').eq('{}-{}'.format(raid_handle, body['name']))
        }

        provider_query_response = association_index_table.query(**existing_provider_query_parameters)
        existing_provider = provider_query_response["Items"][0]

        # Get existing item
        update_response = association_index_table.update_item(
            Key={
                'startDate': existing_provider['startDate'],
                'handle': raid_handle
            },
            UpdateExpression="set endDate = :e",
            ExpressionAttributeValues={
                ':e': end_date
            },
            ReturnValues="ALL_NEW"
        )

        return web_helpers.generate_web_body_response('200', {
            'name': body['name'],
            'startDate': existing_provider['startDate'],
            'endDate': end_date
        }, event)

    except:
        logger.error('Unable to end a provider to a RAiD association: {}'.format(sys.exc_info()[0]))
        return web_helpers.generate_web_body_response('500', {
            'message': "Unable to perform request due to error. Please check structure of the body."}, event)