def delete_user(event, is_test, session): """Deletes a user from the database. Parameters ---------- user_id: str, required The id of the user Returns ------ nothing """ if session is None: session = get_db_session(is_test, session) user_id = helper.cognito_id_from_event(event) user = session.query(User).get(user_id) if (user == None): raise Exception( f"User with id {user_id} could not be found in database.") client = boto3.client('cognito-idp') client.admin_delete_user(UserPoolId=event['requestContext']['identity'] ['cognitoAuthenticationProvider'].split( ',')[0].split('amazonaws.com/')[1], Username=user.name) session.delete(user) session.commit()
def get_open_items(event, context, is_test=False, session=None): logger = logging.getLogger() logger.setLevel(logging.INFO) helper.log_method_initiated("Get open items for user", event, logger) if session == None: session = connection_handler.get_db_session(False, None) try: # get cognito user id id = helper.cognito_id_from_event(event) # get number of items from url path if ('queryStringParameters' in event and 'num_items' in event['queryStringParameters']): num_items = int(event['queryStringParameters']['num_items']) else: num_items = 5 user = user_handler.get_user_by_id(id, is_test, session) response = item_handler.get_open_items_for_user( user, num_items, is_test, session) items = response['items'] if len(items) < 1: response = { "statusCode": 404, "body": "There are currently no open items for this user." } else: # Transform each item into dict items_dict = [] for item in items: items_dict.append(item.to_dict()) body = { "items": items_dict, "is_open_review": response['is_open_review'] } response = { "statusCode": 200, 'headers': { "content-type": "application/json; charset=utf-8" }, "body": json.dumps(body) } except Exception: response = { "statusCode": 400, "body": "Could not get user and/or num_items. Check URL path parameters. Stacktrace: {}" .format(traceback.format_exc()) } response_cors = helper.set_cors(response, event, is_test) return response_cors
def post_comment_on_item(event, context=None): """ Creates comment on item from archive """ with Session() as session: logger = logging.getLogger() logger.setLevel(logging.INFO) try: body = json.loads(event['body']) if isinstance( event['body'], str) else event['body'] except: return helper.get_text_response( 400, "Malformed request. Please provide a valid request.", event) try: user_id = helper.cognito_id_from_event(event) body = json.loads(event['body']) if isinstance( event['body'], str) else event['body'] except: return helper.get_text_response( 400, "Malformed request. Could not read user_id from context data.", event) if 'item_id' not in body: return helper.get_text_response( 400, "Malformed request. Please provide an item_id.", event) try: item = item_handler.get_item_by_id(body['item_id'], session) except: return helper.get_text_response(404, "Item not found", event) # Save qualitative_comment if 'comment' in body: try: comment = comment_handler.create_comment( session, comment=body['comment'], user_id=user_id, parent_type='item', parent_id=item.id) response = { "statusCode": 201, 'headers': { "content-type": "application/json; charset=utf-8" }, "body": json.dumps(comment.to_dict()) } return helper.set_cors(response, event) except: return helper.get_text_response( 404, "No qualitative comment found.", event)
def get_review(event, context): """Gets a review. Parameters ---------- - user_id is retrieved from the event - review_id is retrieved from query parameters Returns ------ - Status code 200 OK - The requested review """ logger = logging.getLogger() logger.setLevel(logging.INFO) helper.log_method_initiated("Get Review", event, logger) try: # get cognito id user_id = helper.cognito_id_from_event(event) except: return helper.get_text_response( 400, "Malformed request. Please provide a valid request.", event) with Session() as session: try: # get user from database user = user_handler.get_user_by_id(user_id, session) except: return helper.get_text_response(404, "No user found.", event) try: # Try to receive review review = review_handler.get_open_review(user_id, session) except: return helper.get_text_response(404, "No review found", event) if review is None: return responses.NoContent( event, 'No review in progress found for current user.' ).to_json_string() try: if review.user_id == user.id: return responses.Success( event, json.dumps( review.to_dict(with_questions_and_answers=True, with_tags=True))).to_json_string() else: return responses.Forbidden( event, 'User is not allowed to access review').to_json_string() except Exception as e: return responses.InternalError(event, "Internal error", e).to_json_string()
def get_user(event, context, is_test=False, session=None): logger = logging.getLogger() logger.setLevel(logging.INFO) helper.log_method_initiated("Get user", event, logger) if session == None: session = get_db_session(False, None) try: # get cognito id id = helper.cognito_id_from_event(event) try: user = user_handler.get_user_by_id(id, is_test, session) user_dict = user.to_dict() progress = user_handler.get_user_progress( user, is_test, session) total_rank = user_handler.get_user_rank( user, False, is_test, session) level_rank = user_handler.get_user_rank( user, True, is_test, session) solved_cases_total = user_handler.get_solved_cases( user, False, is_test, session) solved_cases_today = user_handler.get_solved_cases( user, True, is_test, session) exp_needed = user_handler.get_needed_exp(user, is_test, session) user_dict['progress'] = progress user_dict['total_rank'] = total_rank user_dict['level_rank'] = level_rank user_dict['solved_cases_total'] = solved_cases_total user_dict['solved_cases_today'] = solved_cases_today user_dict['exp_needed'] = exp_needed response = { "statusCode": 200, 'headers': {"content-type": "application/json; charset=utf-8"}, "body": json.dumps(user_dict) } except Exception: response = { "statusCode": 404, "body": "No user found with the specified id.{}".format(traceback.format_exc()) } except Exception: response = { "statusCode": 400, "body": "Could not get user. Check Cognito authentication. Stacktrace: {}".format(traceback.format_exc()) } response_cors = helper.set_cors(response, event, is_test) return response_cors
def attach_iot_policy(event, context): try: helper.log_method_initiated("Attach IoT policy.", event, logger) try: cognito_identity = helper.get_cognito_identity_from_event(event) except Exception: logger.error(ERROR_MSG_IDENTIY_ID_MISSING) return BadRequest(event, ERROR_MSG_IDENTIY_ID_MISSING).to_json_string() try: user_id = helper.cognito_id_from_event(event) except Exception: logger.error(ERROR_MSG_USER_ID_MISSING) return BadRequest(event, ERROR_MSG_USER_ID_MISSING).to_json_string() client = BotoClientProvider().get_client('iot') # Get the policy for the current user or create it try: policy = client.get_policy(policyName=user_id) except client.exceptions.ResourceNotFoundException as e: resource = POLICY_DOCUMENT_STRING_FORMAT.format(user_id) policy_document['Statement'][0]['Resource'] = resource policy = client.create_policy( policyName=user_id, policyDocument=json.dumps(policy_document)) attached_policies = client.list_attached_policies( target=cognito_identity) # If the policy is already attached to the current identity return if(policy['policyName'] in [attached_policy['policyName'] for attached_policy in attached_policies['policies']]): logger.info(INFO_MSG_POLICY_ALREADY_ATTACHED) return Success(event).to_json_string() client.attach_policy( policyName=policy['policyName'], target=cognito_identity) logger.info(INFO_MSG_POLICY_ATTACHED) return Success(event).to_json_string() except Exception as e: logger.exception(ERROR_MSG_EXCEPTION) return InternalError(event, ERROR_MSG_EXCEPTION, e).to_json_string()
def get_user_ranking(event, context, is_test=False, session=None): """ returns a dictionary with list top_users: 10 top users list top_users_by_level: 10 top users on the user's level list top_users_by_period: 10 top users in a period p (1 week) """ n = 10 p = 1 descending = True attr = 'experience_points' logger = logging.getLogger() logger.setLevel(logging.INFO) helper.log_method_initiated("Get User Ranking", event, logger) if session == None: session = get_db_session(False, None) user_ranking_dict = {} top_users_list = [] top_users_by_level_list = [] top_users_by_period_list = [] try: my_user_id = helper.cognito_id_from_event(event) except Exception: response = { "statusCode": 400, "body": "Could not get User. Check Cognito Authentication. Stacktrace: {}".format(traceback.format_exc()) } try: helper.log_method_initiated("Get Top n Users", event, logger) top_users = user_handler.get_top_users(n, attr, descending, is_test, session) for user in top_users: top_users_list.append(user.to_dict()) user_ranking_dict['top_users'] = top_users_list helper.log_method_initiated("Get Top n Users on the User's Level", event, logger) my_user = user_handler.get_user_by_id(my_user_id, is_test, session) user_level = my_user.level_id top_users_by_level = user_handler.get_top_users_by_level(user_level, n, attr, descending, is_test, session) for user in top_users_by_level: top_users_by_level_list.append(user.to_dict()) user_ranking_dict['top_users_by_level'] = top_users_by_level_list helper.log_method_initiated("Get Top n Users in a Period", event, logger) top_users_by_period = user_handler.get_top_users_by_period(n, p, attr, descending, is_test, session) for user in top_users_by_period: top_users_by_period_list.append(user.to_dict()) user_ranking_dict['top_users_by_period'] = top_users_by_period_list except Exception: response = { "statusCode": 500, "body": "Server Error. Stacktrace: {}".format(traceback.format_exc()) } response = { "statusCode": 200, 'headers': {"content-type": "application/json; charset=utf-8"}, "body": json.dumps(user_ranking_dict) } response_cors = helper.set_cors(response, event, is_test) return response_cors
def update_review(event, context, is_test=False, session=None): """Updates an existing review Args: event: AWS API Gateway event context ([type]): [description] is_test (bool, optional): Whether the function is executed in test mode. Defaults to False. session (optional): An sql alchemy session. Defaults to None. Returns ------ - Status code 200, 400, 404 or 500 (Created) - The updated review """ logger = logging.getLogger() logger.setLevel(logging.INFO) helper.log_method_initiated("Create Review", event, logger) if session == None: session = connection_handler.get_db_session(False, None) try: user_id = helper.cognito_id_from_event(event) body = json.loads(event['body']) if isinstance(event['body'], str) else event['body'] except: return helper.get_text_response( 400, "Malformed request. Please provide a valid request.", event, is_test) if 'id' not in body: return helper.get_text_response( 400, "Malformed request. Please provide a review id.", event, is_test) try: review = review_handler.get_review_by_id(body['id'], is_test, session) except: return helper.get_text_response(404, "No review found", event, is_test) try: user = user_handler.get_user_by_id(user_id, is_test, session) except: return helper.get_text_response(404, "No user found.", event, is_test) if review.user_id != user.id: return helper.get_text_response(403, "Forbidden.", event, is_test) # If review is set closed if 'status' in body and body['status'] == 'closed': try: review = review_handler.close_review(review, is_test, session) if review.item.status == 'closed': notifications.notify_users(is_test, session, review.item) response = { "statusCode": 200, "body": json.dumps(review.to_dict_with_questions_and_answers()) } response_cors = helper.set_cors(response, event, is_test) return response_cors except: return helper.get_text_response( 500, "Internal server error. Stacktrace: {}".format( traceback.format_exc()), event, is_test) # If answers are appended elif 'questions' in body: if not isinstance(body['questions'], list): return helper.get_text_response( 400, "Malformed request. Please provide a valid request.", event, is_test) for question in body['questions']: if 'answer_value' in question: answer_value = question['answer_value'] else: return helper.get_text_response( 400, "Malformed request. Please provide a valid request.", event, is_test) if answer_value is not None: # Check if conditionality is met if question['parent_question_id'] is not None: for q in body['questions']: if q['question_id'] == question['parent_question_id']: parent_question = q parent_answer = review_answer_handler.get_parent_answer( question['answer_id'], is_test, session) if parent_question['answer_value'] > question[ 'upper_bound'] or parent_question[ 'answer_value'] < question['lower_bound']: return helper.get_text_response( 400, "Bad request. Please adhere to conditionality of questions.", event, is_test) # Update answer in db try: review_answer_handler.set_answer_value( question['answer_id'], question['answer_value'], is_test, session) except: return helper.get_text_response( 500, "Internal server error. Stacktrace: {}".format( traceback.format_exc()), event, is_test) response = { "statusCode": 200, "body": json.dumps(review.to_dict_with_questions_and_answers()) } response_cors = helper.set_cors(response, event, is_test) return response_cors else: return helper.get_text_response( 400, "Bad request. Please adhere to conditionality of questions.", event, is_test)
def update_review(event, context): """Updates an existing review Args: event: AWS API Gateway event context ([type]): [description]. Returns ------ - Status code 200, 400, 404 or 500 (Created) - The updated review """ logger = logging.getLogger() logger.setLevel(logging.INFO) helper.log_method_initiated("Update Review", event, logger) try: user_id = helper.cognito_id_from_event(event) body = json.loads(event['body']) if isinstance(event['body'], str) else event['body'] except: return responses.BadRequest( event, "Malformed request. Please provide a valid request." ).to_json_string() if 'id' not in body: return responses.BadRequest( event, "Malformed request. Please provide a review id.").to_json_string() with Session() as session: try: review = review_handler.get_review_by_id(body['id'], session) except: return responses.NotFound(event, "No review found.").to_json_string() try: user = user_handler.get_user_by_id(user_id, session) except: return responses.NotFound(event, "No user found.").to_json_string() if review.user_id != user.id: return responses.Forbidden(event).to_json_string() # If review is set closed if 'status' in body and body['status'] == 'closed': try: review = review_handler.close_review(review, session) if review.item.status == 'closed': EventPublisher().publish_event('codetekt.review_service', 'item_closed', {'item_id': review.item.id}) return responses.Success( event, json.dumps( review.to_dict(with_questions_and_answers=True, with_tags=True))).to_json_string() except: return helper.get_text_response( 500, "Internal server error. Stacktrace: {}".format( traceback.format_exc()), event) # If answers are appended if 'questions' in body: if not isinstance(body['questions'], list): return responses.BadRequest( event, "Malformed request. Please provide a valid request." ).to_json_string() for question in body['questions']: if 'answer_value' in question: answer_value = question['answer_value'] else: return responses.BadRequest( event, "Malformed request. Please provide a valid request." ).to_json_string() if answer_value is not None: # Check if conditionality is met if question['parent_question_id'] is not None: for q in body['questions']: if q['question_id'] == question[ 'parent_question_id']: parent_question = q if parent_question['answer_value'] > question[ 'upper_bound'] or parent_question[ 'answer_value'] < question['lower_bound']: return responses.BadRequest( event, "Bad request. Please adhere to conditionality of questions." ).to_json_string() # Update answer in db try: review_answer_handler.set_answer_value( question['answer_id'], question['answer_value'], session) except Exception as e: return responses.InternalError( event, exception=e).to_json_string() # Save qualitative_comment if 'comment' in body: if body['comment']: if review.comment is None: try: comment_handler.create_comment(session, comment=body['comment'], user_id=user_id, parent_type='review', parent_id=review.id, is_review_comment=True) except Exception as e: return responses.InternalError( event, "Could not create comment for item", e).to_json_string() elif review.comment.comment != body['comment']: review.comment.comment = body['comment'] session.merge(review) if 'tags' in body: if body['tags'] is None: body['tags'] = [] if isinstance(body['tags'], list): try: db_tags = [ item_tag.tag.tag for item_tag in tag_handler.get_item_tags_by_review_id( review.id, session) ] body_tags_upper = [tag.upper() for tag in body['tags']] db_tags_upper = [tag.upper() for tag in db_tags] tags_to_add = [ tag for tag in body['tags'] if tag.upper() not in db_tags_upper ] tags_to_delete = [ tag for tag in db_tags if tag.upper() not in body_tags_upper ] for tag in tags_to_add: tag_handler.store_tag_for_item(review.item_id, tag, session, review.id) for tag in tags_to_delete: tag_handler.delete_itemtag_by_tag_and_review_id( tag, review.id, session) except Exception as e: return responses.InternalError( event, "Could not create tags for item", e).to_json_string() return responses.Success( event, json.dumps( review.to_dict(with_questions_and_answers=True, with_tags=True))).to_json_string()
def get_review(event, context, is_test=False, session=None): """Gets a review. Parameters ---------- - user_id is retrieved from the event - review_id is retrieved from query parameters Returns ------ - Status code 200 OK - The requested review """ logger = logging.getLogger() logger.setLevel(logging.INFO) helper.log_method_initiated("Get Review", event, logger) if session == None: session = connection_handler.get_db_session(False, None) try: # get review id from url query params review_id = event['pathParameters']['review_id'] # get cognito id user_id = helper.cognito_id_from_event(event) except: return helper.get_text_response( 400, "Malformed request. Please provide a valid request.", event, is_test) try: # get user from database user = user_handler.get_user_by_id(user_id, is_test, session) except: return helper.get_text_response(404, "No user found.", event, is_test) # Try to receive item try: review = review_handler.get_review_by_id(review_id, is_test, session) except: return helper.get_text_response(404, "No review found", event, is_test) try: if review.user_id == user.id: response = { "statusCode": 200, 'headers': { "content-type": "application/json; charset=utf-8" }, "body": json.dumps(review.to_dict_with_questions_and_answers()) } else: return helper.get_text_response(403, "Forbidden", event, is_test) except: return helper.get_text_response( 500, "Internal server error. Stacktrace: {}".format( traceback.format_exc()), event, is_test) response_cors = helper.set_cors(response, event, is_test) return response_cors
def create_review(event, context, is_test=False, session=None): """Creates a new review. Parameters ---------- - user_id is retrieved from the event - item_id is retrieved from query parameters Returns ------ - Status code 201 (Created) - The newly created review """ logger = logging.getLogger() logger.setLevel(logging.INFO) helper.log_method_initiated("Create Review", event, logger) if session == None: session = connection_handler.get_db_session(False, None) try: # get item id from body item_id = json.loads(event['body'])['item_id'] if isinstance( event['body'], str) else event['body']['item_id'] # get cognito id user_id = helper.cognito_id_from_event(event) except Exception: return helper.get_text_response( 400, "Malformed request. Please provide a valid request.", event, is_test) try: # get user and item from the db user = user_handler.get_user_by_id(user_id, is_test, session) except Exception: return helper.get_text_response(404, "No user found.", event, is_test) item = item_handler.get_item_by_id(item_id, is_test, session) if item is None: return helper.get_text_response(404, "No item found.", event, is_test) # Try to accept item try: review = review_handler.create_review(user, item, is_test, session) response = { "statusCode": 201, 'headers': { "content-type": "application/json; charset=utf-8" }, "body": json.dumps(review.to_dict_with_questions_and_answers()) } response_cors = helper.set_cors(response, event, is_test) return response_cors except: return helper.get_text_response( 500, "Internal server error. Stacktrace: {}".format( traceback.format_exc()), event, is_test)