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()
Exemple #2
0
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
Exemple #3
0
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)
Exemple #4
0
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
Exemple #6
0
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
Exemple #8
0
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)
Exemple #9
0
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
Exemple #11
0
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)