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'
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"
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 }
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"
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'
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"
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}
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
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
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}
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'
def delete_survey(survey_id): survey_utils.get_survey_table().delete_item(Key={'survey_id': survey_id})