def update_filter(request, data=None): if len(data) != 1: raise errors.ClientError( "An attempt to update more than just the filter has been made. The length of the data set exceeds 1." ) if c.KEY_FILTERS not in data: raise errors.ClientError( "The '{}' key is not present in the data '{}'.".format( c.KEY_FILTERS, data)) for filter in data[c.KEY_FILTERS]: if 'event' not in filter: raise errors.ClientError( "The filter '{}' is missing the attribute 'event'.".format( filter)) if 'attributes' not in filter: raise errors.ClientError( "The filter '{}' is missing the attribute 'attributes'.". format(filter)) if 'type' not in filter: raise errors.ClientError( "The filter '{}' is missing the attribute 'type'.".format( filter)) update_context(request, data) return data
def update_custom_partition(request, data=None): if len(data) != 1: raise errors.ClientError( "An attempt to update more than just the partitions has been made. The length of the data set exceeds 1." ) if c.KEY_PARTITIONS not in data: raise errors.ClientError( "The '{}' key is not present in the data '{}'.".format( c.KEY_PARTITIONS, data)) for partition in data['partitions']: if 'key' not in partition: raise errors.ClientError( "The partition '{}' is missing the attribute 'key'.".format( partition)) if 'type' not in partition: raise errors.ClientError( "The partition '{}' is missing the attribute 'type'.".format( partition)) key = partition['key'] if key in c.PREDEFINED_PARTITIONS: raise errors.ClientError( "The '{}' partition is a predefined partition and can't be updated with this API." .format(key)) predefined = get_predefined_partition(request) data[c.KEY_PARTITIONS] = predefined + data[c.KEY_PARTITIONS] update_context(request, data) return data
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 validate_answer_to_predefined_type_question(question, answer): if not validation_utils.is_num_str(answer): raise errors.ClientError( "answer to predefined type question is invalid: {}".format(answer)) val = int(answer) if val < 0 or val >= len(question['predefines']): raise errors.ClientError( "answer to predefined type question is invalid: {}, number of options: {}" .format(answer, len(question['predefines'])))
def validate_eligible_for_publishing(survey_metadata): questions = survey_metadata.get('questions') if validation_utils.is_empty(questions): raise errors.ClientError("Survey doesn't have question") if survey_metadata.get( 'activation_start_time') is None and survey_metadata.get( 'activation_end_time') is None: raise errors.ClientError("Survey doesn't have activation period yet")
def update_priority(request, data = None): if len(data) != 1: raise errors.ClientError("An attempt to update more than just the priority has been made. The length of the data set exceeds 1.") if c.KEY_PRIORITIES not in data: raise errors.ClientError("The '{}' key is not present in the data '{}'.".format(c.KEY_PRIORITIES, data)) update_context(request, data) return data
def get_username_for_account(AccountId): account = get_account_table().get_item(Key = { 'AccountId': AccountId }, ConsistentRead = False) if not 'Item' in account: raise errors.ClientError("No account found for '{}'".format(AccountId)) if not 'CognitoUsername' in account['Item']: raise errors.ClientError("Account {} is not linked to a Cognito user pool".format(AccountId)) return account['Item']['CognitoUsername']
def validate_account_update_request(account): if len(account.get('PlayerName', '')) > MAX_PLAYER_NAME_LENGTH: raise errors.ClientError( 'PlayerName is longer than {} characters'.format( MAX_PLAYER_NAME_LENGTH)) for key, value in account.get('IdentityProviders', {}).get(IDP_COGNITO, {}).iteritems(): if len(value) > MAX_COGNITO_ATTRIBUTE_LENGTH: raise errors.ClientError('{} is longer than {} characters'.format( key, MAX_COGNITO_ATTRIBUTE_LENGTH))
def put_service_interfaces(request, deployment_name, service_url, service_interfaces_body): items = service_interfaces_body.get('Items', None) if items is None: raise errors.ClientError('Missing required Items property in the request body.') try: impl.put_service_interfaces(deployment_name, service_url, items) except ValueError as e: raise errors.ClientError(e.message)
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 __validate_number_of_posts(number_of_posts, maximum_number_of_posts): '''Validate the number of posts requested by the client.''' if number_of_posts is None: raise errors.ClientError('Invalid NumberOfEncryptedPosts (Empty)') if number_of_posts < 0: raise errors.ClientError('Invalid NumberOfEncryptedPosts (Number of posts requested is out of range.)') if number_of_posts > maximum_number_of_posts: raise errors.ClientError('Invalid request_content (Number of posts requested exceedes maximum limit of {}.)'.format(maximum_number_of_posts))
def __get_ref(self, path, name=None, params=None): if not params: params = {} if name is not None: params['name'] = name remote_obj = self.get(path, params=params) if len(remote_obj) > 1: raise errors.ClientError("Ambiguous result: " + json.dumps(remote_obj)) if len(remote_obj) == 0: raise errors.ClientError("Ref not found: " + path + ' ' + name) return remote_obj[0]['_ref']
def __validate_request_content(request_content): '''Validate request_content recieved from the client.''' if request_content is None: raise errors.ClientError('Invalid request_content (Empty)') if not request_content.has_key('NumberOfEncryptedPosts'): raise errors.ClientError('Invalid request_content (Does not contain necessary keys. Found these keys: {})'.format(request_content.keys())) if not request_content.has_key('NumberOfUnencryptedPosts'): raise errors.ClientError('Invalid request_content (Does not contain necessary keys. Found these keys: {})'.format(request_content.keys()))
def __validate_data(data): if not isinstance(data.get('ExamplePropertyA', None), basestring): raise errors.ClientError( 'Property ExamplePropertyA in provided data is missing or is not a string.' ) if not isinstance(data.get('ExamplePropertyB', None), int): raise errors.ClientError( 'Property ExamplePropertyB in provided data is missing or is not an integer.' )
def get_index(s3_client): # Request the index file try: s3_index_obj_request = s3_client.get_object(Bucket=BUCKET_ID, Key=PROJECT_CGP_ROOT_FILE) except ClientError as e: print e raise errors.ClientError("Could not read from the key '{}' in the S3 bucket '{}'. Failed with: {}".format(PROJECT_CGP_ROOT_FILE, BUCKET_ID, e.message)) # Does the lambda have access to it? if s3_index_obj_request['ResponseMetadata']['HTTPStatusCode'] != 200: raise errors.ClientError("The user does not have access to the file index.html file.") content = s3_index_obj_request['Body'].read().decode('utf-8') return content
def validate(self, columns): required_fields_ordered = self.schema_order.required_fields for field in required_fields_ordered: if field.id not in columns: raise errors.ClientError( "[{}] The metric is missing the attribute '{}' in columns {}" .format(code.Error.missing_attribute(), field.id, columns)) for field in columns: if not field.islower(): raise errors.ClientError( "[{}] The metric attribute '{}' is not lowercase. All attributes should be lowercase. The columns were '{}'" .format(code.Error.is_not_lower(), field, columns)) return
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 validate_start_end_times(start_timeval, end_timeval): #Scheduling with start and end time if get_struct_time(end_timeval) <= get_struct_time(start_timeval): raise errors.ClientError('Invalid: End time ' + end_timeval + ' <= Start time ' + start_timeval) #Scheduling with no end time is always valid return True
def update_account(item, delete_keys=set(), existing_account=None): # Reads are cheaper than writes, check if a write is actually needed. account_key = {'AccountId': item['AccountId']} if not existing_account: get_account_response = get_account_table().get_item( Key=account_key, ConsistentRead=False) print 'Existing account row: ', get_account_response if 'Item' not in get_account_response: raise errors.ClientError('Account {} does not exist.'.format( item['AccountId'])) existing_account = get_account_response['Item'] updates = {} updated_item = existing_account.copy() for key, value in item.iteritems(): if key not in existing_account or existing_account[key] != value: updates[key] = {'Value': value, 'Action': 'PUT'} updated_item[key] = value for key in delete_keys: updates[key] = {'Action': 'DELETE'} del updated_item[key] if not updates: print 'The account table is up to date.' return existing_account get_account_table().update_item(Key=account_key, AttributeUpdates=updates) print 'Updated the account table: ', updates return updated_item
def ensure_question_belongs_to_survey(survey_id, question_id): question = survey_utils.get_question_by_id(survey_id, question_id, ['survey_id'], True) if survey_id != question['survey_id']: raise errors.ClientError( "Question {} doesn't belong to survey {}".format( question_id, survey_id))
def get_submission_by_id(survey_id, submission_id, attributes=None, raise_exception_if_not_found=False): if attributes is not None: projection_expression, expression_attribute_names_map = __create_projection_expression_and_attribute_names( attributes) get_result = get_answer_table().get_item( Key={ 'survey_id': survey_id, 'submission_id': submission_id }, ProjectionExpression=projection_expression, ExpressionAttributeNames=expression_attribute_names_map) else: get_result = get_answer_table().get_item(Key={ 'survey_id': survey_id, 'submission_id': submission_id }) submission = get_result.get('Item') if raise_exception_if_not_found and submission is None: raise errors.ClientError( 'No submission found for survey_id: [{}], submission_id: [{}]'. format(survey_id, submission_id)) return submission
def post(request, cognitoUsername): try: account_utils.get_user_pool_client().admin_reset_user_password(UserPoolId=account_utils.get_user_pool_id(), Username=cognitoUsername) except botocore.exceptions.ClientError as e: message = e.response.get('Error', {}).get('Message') raise errors.ClientError(message) return {}
def get(request, run_id, time): if time >= buffer_time: time -= buffer_time timestamp = datetime.datetime.utcfromtimestamp(time) if len(run_id) > 1: run_key = json.dumps(json.loads(run_id)) else: run_key = run_id # Load the most recent events query_params = { 'TableName': log_db, 'ConsistentRead': True, 'ScanIndexForward': True, 'Select': "ALL_ATTRIBUTES", 'KeyConditions': { 'run-id': { 'AttributeValueList': [ { 'S': run_key } ], 'ComparisonOperator': "EQ" }, 'event-id': { 'AttributeValueList': [ { 'S': timestamp.isoformat()[:19] } ], 'ComparisonOperator': "GE" } } } events = [] while True: response = {} try: response = dynamo_client.query(**query_params) except ClientError as e: raise errors.ClientError('Error querying LogDB. {}'.format(e.response['Error']['Message'])) events.extend([_process_data({'M': item}) for item in response.get('Items',[])]) next_key = response.get('LastEvaluatedKey', None) if next_key: query_params['ExclusiveStartKey'] = next_key else: break result = { 'run-id': run_id, 'events': events } return result
def get(request, time=None, lang=None): #Validate the time that was provided to avoid spoofing. if time is not None: client_datetime = message_utils.get_struct_time(time) current_time = datetime.utcnow() time_diff = current_time - client_datetime time_diff_in_hours = time_diff.total_seconds() / 3600 #No matter where you are in the world you should not have a time difference greater than 12 hours if time_diff_in_hours > 12 or time_diff_in_hours < -12: print('Time diff is {}'.format(time_diff_in_hours)) raise errors.ClientError('Invalid client time') #This function will return UTC if no timestring is provided client_time_as_number = message_utils.get_time_as_number(time) response = message_utils.get_message_table().scan( ProjectionExpression='message, priority, startTime, endTime', FilterExpression=Attr('startTime').lte(client_time_as_number) & Attr('endTime').gte(client_time_as_number)) data = [] for i in response['Items']: conv = convert_table_entry(i) data.append(conv) return {"list": data}
def message(request, compression_mode, sensitivity_type, payload_type, data): p_lambda = Lambda({}) print "Target lambda {}".format(os.environ[c.ENV_LAMBDA_PRODUCER]) util.debug_print( "Invoking lambda {} with payload size: {} Compression mode: {}, Sensitivity Type: {}, Payload Type: {}" .format(os.environ[c.ENV_LAMBDA_PRODUCER], len(data), compression_mode, sensitivity_type, payload_type)) payload_data = { c.API_PARAM_SOURCE_IP: request.event[c.API_PARAM_SOURCE_IP], c.SQS_PARAM_SENSITIVITY_TYPE: sensitivity_type, c.SQS_PARAM_PAYLOAD_TYPE: payload_type, c.SQS_PARAM_COMPRESSION_TYPE: compression_mode, c.API_PARAM_PAYLOAD: data } response = p_lambda.invoke_sync(os.environ[c.ENV_LAMBDA_PRODUCER], payload_data) sb = response['Payload'] sb = json.loads(sb.read().decode("utf-8")) error = sb.get('errorMessage', None) returnObj = { 'StatusCode': response['StatusCode'], 'PhysicalResourceId': os.environ[c.ENV_LAMBDA_PRODUCER] } if error and len(error) > 0: print "Error:", sb raise errors.ClientError( "An error occurred invoking the SQS event producer. Please check the cloud watch logs." ) return returnObj
def update_settings(request, data = None): for entry in data: if entry in c.NON_SETTINGS: raise errors.ClientError("The '{}' key can not be updated through this API. It is an object type and must be updated using its corresponding service API.".format(entry)) update_context(request, data) return data
def put(request, survey_id, submission_id, answer_list): cognito_identity_id = request.event["cognitoIdentityId"] validation_common.validate_cognito_identity_id(cognito_identity_id) validation_common.validate_survey_id(survey_id) validation_common.validate_submission_id(submission_id) answers = answer_list.get('answers') validation_common.validate_answers(answers) survey_common.ensure_survey_active(survey_id) submission = survey_utils.get_submission_by_id(survey_id, submission_id, ['user_id'], True) if submission.get('user_id') != cognito_identity_id: raise errors.ClientError( "Cognito identity ID [{}] doesn't own this submission".format( cognito_identity_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 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().update_item( Key={ 'survey_id': survey_id, 'submission_id': submission_id }, UpdateExpression='SET answers=:answers', ExpressionAttributeValues={':answers': answers_map}) return {'submission_id': submission_id}
def describe_content(request, file_name): print 'Describing portal content' resultData = [] staging_table = _get_staging_table() try: response_data = staging_table.get_item(Key={'FileName': file_name}) except: raise errors.ClientError('Failed to retrieve data for ' + file_name) item_data = response_data.get('Item') if not item_data: raise errors.ClientError('No data for ' + file_name) return {'PortalFileInfo': item_data}
def get(request): if not request.event["cognitoIdentityId"]: raise errors.ForbiddenRequestError('The credentials used did not contain Cognito identity information') account = account_utils.get_account_for_identity(request.event["cognitoIdentityId"]) if not account: raise errors.ClientError("No account found for '{}'".format(request.event["cognitoIdentityId"])) if account.get('AccountBlacklisted'): raise errors.ForbiddenRequestError('The account is blacklisted') response = account_utils.get_account_table().get_item(Key = { 'AccountId': account['AccountId'] }, ConsistentRead = False) if not 'Item' in response: raise errors.ClientError("No account found for '{}'".format(account['AccountId'])) return account_utils.convert_account_from_dynamo_to_player_model(response['Item'])
def validate_values(self, dict): required_fields_ordered = self.schema_order.required_fields for field in required_fields_ordered: value = dict[field.id] if value is None or len(str(value)) == 0: raise errors.ClientError( "[{}] The metric attribute '{}' is null or empty. Required fields can not be null or empty." .format(code.Error.is_not_lower(), field.id))