def disable_survey_question(survey_id, question_id):
    survey_metadata = survey_utils.get_survey_metadata_by_id(
        survey_id, ['questions'], True)
    for i, question in enumerate(survey_metadata['questions']):
        if question['id'] == question_id:
            if question['active'] == True:
                try:
                    survey_utils.get_survey_table().update_item(
                        Key={'survey_id': survey_id},
                        UpdateExpression=
                        'SET questions[{}].active = :false ADD num_active_questions :minus_one'
                        .format(i),
                        ConditionExpression=
                        'questions[{}].id = :question_id and questions[{}].active = :true'
                        .format(i, i),
                        ExpressionAttributeValues={
                            ':true': True,
                            ':false': False,
                            ':question_id': question_id,
                            ':minus_one': -1
                        })
                except ClientError as e:
                    if e.response['Error'][
                            'Code'] == 'ConditionalCheckFailedException':
                        raise errors.ClientError(
                            'Survey has been modified before update')
                    else:
                        raise RuntimeError('Failed to update DynamoDB')
            break
    else:
        raise errors.ClientError(
            'No question with id [{}] found for survey [{}]'.format(
                question_id, survey_id))

    return 'success'
Esempio n. 2
0
def clone_survey(survey_name, survey_id_to_clone):
    survey = survey_common.get_survey(survey_id_to_clone, None, None, False,
                                      True)
    survey_id = str(uuid.uuid4())
    questions = []
    for question in survey['questions']:
        question_id = str(uuid.uuid4())
        questions.append({'id': question_id, 'active': True})
        item = {}
        item['survey_id'] = survey_id
        item['question_id'] = question_id
        item['metadata'] = survey_common.extract_question_metadata(question)
        item['title'] = question['title']
        item['type'] = question['type']
        survey_utils.get_question_table().put_item(Item=item)

    creation_time = int(time.time())
    survey_utils.get_survey_table().put_item(
        Item={
            'survey_id': survey_id,
            'survey_name': survey_name,
            'creation_time_dummy_hash': 1,
            'creation_time': creation_time,
            'activation_start_time': 0,
            'num_active_questions': len(questions),
            'questions': questions,
            'num_responses': 0
        })

    return {'survey_id': survey_id, 'creation_time': creation_time}
def put(request, survey_id, update_activation_period_input):
    validation_common.validate_survey_id(survey_id)
    activation_start_time, activation_end_time = validation_common.validate_activation_period(
        update_activation_period_input.get('activation_start_time'),
        update_activation_period_input.get('activation_end_time'))

    survey_common.ensure_survey_exists(survey_id)

    expression_attribute_values = {
        ':activation_start_time': activation_start_time
    }
    update_expression = 'SET activation_start_time = :activation_start_time'
    if activation_end_time is None:
        update_expression += ' REMOVE activation_end_time'
    else:
        update_expression += ',activation_end_time = :activation_end_time'
        expression_attribute_values[
            ':activation_end_time'] = activation_end_time

    survey_utils.get_survey_table().update_item(
        Key={'survey_id': survey_id},
        UpdateExpression=update_expression,
        ExpressionAttributeValues=expression_attribute_values)

    return "success"
Esempio n. 4
0
def post(request, survey_id, question):
    validation_common.validate_survey_id(survey_id)
    validation_common.validate_question(question)

    survey_common.ensure_survey_exists(survey_id)

    question_id = str(uuid.uuid4())

    survey_utils.get_survey_table().update_item(
        Key={'survey_id':survey_id},
        UpdateExpression='SET questions = list_append(questions, :question) ADD num_active_questions :one',
        ExpressionAttributeValues={
            ':question': [{'id': question_id, 'active': True}],
            ':one': 1
        }
    )

    item = {}
    item['survey_id'] = survey_id
    item['question_id'] = question_id
    item['metadata'] = survey_common.extract_question_metadata(question)
    item['title'] = question['title']
    item['type'] = question['type']
    survey_utils.get_question_table().put_item(
        Item=item
    )

    return {
        'question_id': question_id
    }
Esempio n. 5
0
def put(request, survey_id, question_order):
    validation_common.validate_survey_id(survey_id)

    question_id_list = question_order.get('question_id_list')
    validation_utils.validate_param(question_id_list, 'question_id_list',
                                    validation_utils.is_not_none)

    survey_metadata = survey_utils.get_survey_metadata_by_id(
        survey_id, ['questions'], True)
    question_ids = [x['id'] for x in survey_metadata['questions']]
    if set(question_ids) != set(question_id_list):
        raise errors.ClientError(
            "Question IDs from input doesn't match existing question IDs")

    question_map = {}
    for question in survey_metadata['questions']:
        question_map[question['id']] = question

    new_question_list = [
        question_map[question_id] for question_id in question_id_list
    ]

    survey_utils.get_survey_table().update_item(
        Key={'survey_id': survey_id},
        UpdateExpression='SET questions = :new_question_list',
        ExpressionAttributeValues={':new_question_list': new_question_list})

    return "success"
Esempio n. 6
0
def delete(request, survey_id, question_id):
    validation_utils.validate_param(survey_id, 'survey_id',
                                    validation_utils.is_not_blank_str)
    validation_utils.validate_param(question_id, 'question_id',
                                    validation_utils.is_not_blank_str)

    survey_metadata = survey_utils.get_survey_metadata_by_id(
        survey_id, ['questions'], True)
    for i, question in enumerate(survey_metadata['questions']):
        if question.get('id') == question_id:
            try:
                if question.get('active'):
                    survey_utils.get_survey_table().update_item(
                        Key={'survey_id': survey_id},
                        UpdateExpression=
                        'REMOVE questions[{}] ADD num_active_questions :minus_one'
                        .format(i),
                        ConditionExpression=
                        'questions[{}].id = :question_id and questions[{}].active = :true'
                        .format(i, i),
                        ExpressionAttributeValues={
                            ':question_id': question_id,
                            ':minus_one': -1,
                            ':true': True
                        })
                else:
                    survey_utils.get_survey_table().update_item(
                        Key={'survey_id': survey_id},
                        UpdateExpression='REMOVE questions[{}]'.format(i),
                        ConditionExpression=
                        'questions[{}].id = :question_id and questions[{}].active = :false'
                        .format(i, i),
                        ExpressionAttributeValues={
                            ':question_id': question_id,
                            ':false': False
                        })
            except ClientError as e:
                if e.response['Error'][
                        'Code'] == 'ConditionalCheckFailedException':
                    raise errors.ClientError(
                        'Survey has been modified before update')
                else:
                    raise RuntimeError('Failed to update DynamoDB')
            break
    else:
        raise errors.ClientError(
            'No question with id [{}] found for survey [{}]'.format(
                question_id, survey_id))

    survey_utils.get_question_table().delete_item(Key={
        'survey_id': survey_id,
        'question_id': question_id
    })

    return 'success'
Esempio n. 7
0
def put(request, survey_id, rename_survey_input):
    validation_common.validate_survey_id(survey_id)

    survey_name = rename_survey_input.get('survey_name')
    validation_utils.validate_param(survey_name, 'survey_name',
                                    validation_utils.is_not_blank_str)

    survey_common.ensure_survey_exists(survey_id)

    survey_utils.get_survey_table().update_item(
        Key={'survey_id': survey_id},
        UpdateExpression='SET survey_name = :survey_name',
        ExpressionAttributeValues={':survey_name': survey_name})

    return "success"
Esempio n. 8
0
def create_survey(survey_name):
    survey_id = str(uuid.uuid4())
    creation_time = int(time.time())
    survey_utils.get_survey_table().put_item(
        Item={
            'survey_id': survey_id,
            'survey_name': survey_name,
            'creation_time_dummy_hash': 1,
            'creation_time': creation_time,
            'activation_start_time': 0,
            'num_active_questions': 0,
            'questions': [],
            'num_responses': 0
        })

    return {'survey_id': survey_id, 'creation_time': creation_time}
Esempio n. 9
0
def search_survey_metadata_by_survey_name(survey_name, limit, pagination_token, sort):
    limit = validation_common.validate_limit(limit, MAX_LIMIT)
    sort = validation_common.validate_sort_order(sort)

    params = {}
    params['KeyConditionExpression'] = 'creation_time_dummy_hash = :true'
    params['ProjectionExpression'] = 'survey_id, survey_name, creation_time, num_active_questions, activation_start_time, activation_end_time, published, num_responses'
    params['Limit'] = limit
    params['FilterExpression'] = 'contains(survey_name, :survey_name)'
    params['ExpressionAttributeValues'] = {':survey_name':survey_name, ':true':1}
    params['IndexName'] = 'CreationTimeIndex'

    if sort == 'desc':
        params['ScanIndexForward'] = False

    if pagination_token is not None:
        params['ExclusiveStartKey'] = survey_common.decode_pagination_token(pagination_token)

    scan_result = survey_utils.get_survey_table().query(**params)

    out = {'metadata_list':scan_result['Items']}
    last_evaluated_key = scan_result.get('LastEvaluatedKey')
    if last_evaluated_key is not None:
        out['pagination_token'] = survey_common.encode_pagination_token(last_evaluated_key)

    return out
Esempio n. 10
0
def get_survey_metadata_list(limit, max_limit, pagination_token, sort, ensure_active):
    limit = validation_common.validate_limit(limit, max_limit)
    sort = validation_common.validate_sort_order(sort)

    params = {}
    params['KeyConditionExpression'] = 'creation_time_dummy_hash = :true'
    params['ExpressionAttributeValues'] = {':true': 1}
    params['ProjectionExpression'] = 'survey_id, survey_name, creation_time, num_active_questions, activation_start_time, activation_end_time, published, num_responses'
    params['Limit'] = limit
    params['IndexName'] = 'CreationTimeIndex'

    if sort == 'desc':
        params['ScanIndexForward'] = False

    if ensure_active:
        params['FilterExpression'] = ':current_time >= activation_start_time and (attribute_not_exists(activation_end_time) or :current_time <= activation_end_time) and published = :true'
        params['ExpressionAttributeValues'][':current_time'] = int(time.time())

    if validation_utils.is_not_empty(pagination_token):
        params['ExclusiveStartKey'] = decode_pagination_token(pagination_token)

    scan_result = survey_utils.get_survey_table().query(**params)

    out = {'metadata_list': [__clean_up_attributes(ensure_active, x) for x in scan_result['Items']]}
    last_evaluated_key = scan_result.get('LastEvaluatedKey')
    if last_evaluated_key is not None:
        out['pagination_token'] = encode_pagination_token(last_evaluated_key)

    return out
Esempio n. 11
0
def post(request, survey_id, answer_list):
    cognito_identity_id = request.event["cognitoIdentityId"]
    validation_common.validate_cognito_identity_id(cognito_identity_id)
    answers = answer_list.get('answers')
    validation_common.validate_answers(answers)

    survey_common.ensure_survey_active(survey_id)

    question_ids = [answer['question_id'] for answer in answers]
    if len(question_ids) != len(set(question_ids)):
        raise errors.ClientError("Input has duplicate question IDs")

    questions = survey_common.get_questions(survey_id, question_ids)
    if len(questions) != len(question_ids):
        raise errors.ClientError("Some question IDs not found")
    question_map = {}
    for question in questions:
        question_map[question['question_id']] = question

    submission_id = str(uuid.uuid4())

    item = {}
    item['survey_id'] = survey_id
    item['submission_id'] = submission_id
    item['user_id'] = cognito_identity_id
    item['creation_time'] = int(time.time())
    answers_map = {}
    item['answers'] = answers_map
    for answer in answers:
        question = question_map[answer['question_id']]
        validate_answer_by_question_type(question, answer['answer'])
        # for empty text type answer, replace it with a single whitespace
        # as dynamo db doesn't allow empty string..
        if question['type'] == 'text' and len(answer['answer'][0]) == 0:
            answer['answer'][0] = " "
        answers_map[answer['question_id']] = answer['answer']

    survey_utils.get_answer_table().put_item(Item=item)

    # +1 num_responses
    survey_utils.get_survey_table().update_item(
        Key={'survey_id': survey_id},
        UpdateExpression='ADD num_responses :one',
        ExpressionAttributeValues={':one': 1})

    return {'submission_id': submission_id}
Esempio n. 12
0
def put(request, survey_id, survey_published_status):
    validation_common.validate_survey_id(survey_id)
    published = survey_published_status.get('published')
    validation_utils.validate_param(published, 'published',
                                    validation_utils.is_not_none)

    if published:
        survey_metadata = survey_utils.get_survey_metadata_by_id(
            survey_id,
            ['questions', 'activation_start_time', 'activation_end_time'])

        validate_eligible_for_publishing(survey_metadata)

        survey_utils.get_survey_table().update_item(
            Key={'survey_id': survey_id},
            UpdateExpression='SET published = :true',
            ExpressionAttributeValues={':true': 1})
    else:
        survey_utils.get_survey_table().update_item(
            Key={'survey_id': survey_id}, UpdateExpression='REMOVE published')

    return 'success'
Esempio n. 13
0
def delete_survey(survey_id):
    survey_utils.get_survey_table().delete_item(Key={'survey_id': survey_id})