Ejemplo n.º 1
0
def saved_boards(request, user_id, token):
    """
    GET request API call to aquire the saved games in the user's profile.
    user_id: unique user identifier (same as username).
    token: authentication token that allow access to the user's account.
    :param request: GET request
    :param user_id: username who is performing the action
    :param token: authentication token
    :return: dictionary of information for the saved games
    """

    # Here check if user_id matches the token with the database
    if not db.check_user(user_id, token):
        return Response({'error': str('UNAUTHORIZED')},
                        status=status.HTTP_401_UNAUTHORIZED)

    # Get list of game board IDs of user's saved game boards so that
    # user later can use these ids on other API calls
    saved_game_boards = db.list_user_games(user_id)

    # Extract the game board information needed to list user's saved games
    game_board_info = list()
    for game in saved_game_boards:
        temp = {
            'game_id': game['game_id'],
            'difficulty': game['difficulty'],
            'curr_data_structure': game['curr_data_structure']
        }
        game_board_info.append(temp)

    return Response({'saved_games': game_board_info})
Ejemplo n.º 2
0
def profile(request):
    """
    POST request API call.
    Returns all of the user's profile information if the user is authenticated.
    Else, UNAUTHORIZED error is returned.
    :param request: POST request with fields 'user_id', 'token'.
    :return: success message, else error status.
    """
    # user_name == user_id
    required_fields = ['user_id', 'token']

    # Check if the post request contain the required fields
    if set(required_fields) != set(list(request.data.keys())):
        return Response({'error': str('Missing required fields!')},
                        status=status.HTTP_400_BAD_REQUEST)

    # POST Request content
    data = request.data

    # check for bad characters
    if check_special_characters(str(
            data['user_id'])) or check_special_characters(str(data['token'])):
        return Response({'error': str('Unaccepted character passed!')},
                        status=status.HTTP_400_BAD_REQUEST)

    # Here check if user_id matches the token with the database
    if not db.check_user(data['user_id'], data['token']):
        return Response({'error': str('UNAUTHORIZED')},
                        status=status.HTTP_401_UNAUTHORIZED)

    # Get the user profile data
    user_profile_data = db.read_one_user(data['user_id'])

    # Extract the game board information needed to list user's saved games
    saved_game_boards = user_profile_data['save_games']
    game_board_info = list()
    for game in saved_game_boards:
        temp = {
            'game_id': game['game_id'],
            'difficulty': game['difficulty'],
            'curr_data_structure': game['curr_data_structure']
        }
        game_board_info.append(temp)

    # Form the response data
    response_data = {
        'user_name': user_profile_data['user_id'],
        'badges': user_profile_data['badges'],
        'current_story_level': user_profile_data['current_story_level'],
        'friends': user_profile_data['friends'],
        'points': round(user_profile_data['points'], 2),
        'llistStandardPoints': round(user_profile_data['llistStandardPoints'],
                                     2),
        'llistSurvivalPoints': round(user_profile_data['llistSurvivalPoints'],
                                     2),
        'rank': user_profile_data['rank'],
        'saved_games': game_board_info
    }

    return Response({'user_profile': response_data})
Ejemplo n.º 3
0
def remove_friend(request):
    """
    POST request API call.
    Removes the friend from user's profile if the source user is authenticated.
    Else, UNAUTHORIZED error is returned.
    source_user_id: user who is deleting a friend.
    dest_user_id: friend that is being deleted.
    token: authentication token that allow access to the user's account.
    :param request: POST request with fields 'source_user_id', 'dest_user_id', 'token'
    :return: success message or error status.
    """
    required_fields = ['source_user_id', 'dest_user_id', 'token']

    # Check if the post request contain the required fields
    if set(required_fields) != set(list(request.data.keys())):
        return Response({'error': str('Missing required fields!')},
                        status=status.HTTP_400_BAD_REQUEST)

    # POST Request content
    data = request.data

    # Here check if user_id matches the token with the database
    if not db.check_user(data['source_user_id'], data['token']):
        return Response({'error': str('UNAUTHORIZED')},
                        status=status.HTTP_401_UNAUTHORIZED)

    # delete friend from user profile
    if not mock_db.remove_friend(data['source_user_id'], data['dest_user_id']):
        return Response(
            {'error': str('Error when removing friend from the profile!')},
            status=status.HTTP_500_INTERNAL_SERVER_ERROR)

    return Response({'status': 'success'})
Ejemplo n.º 4
0
def accept_decline_friend(request):
    """
    POST request API call.
    Accepts the friend request if the source user is authenticated.
    Else, UNAUTHORIZED error is returned.
    source_user_id: user who recieved the friend request.
    dest_user_id: user who initiated friend request.
    accept: indicate acceptence or decline of the request.
    token: authentication token that allow access to the user's account.
    :param request: POST request with fields 'source_user_id', 'dest_user_id', 'accept', 'token'
    :return: success message or error status.
    """
    required_fields = ['source_user_id', 'dest_user_id', 'accept', 'token']

    # Check if the post request contain the required fields
    if set(required_fields) != set(list(request.data.keys())):
        return Response({'error': str('Missing required fields!')},
                        status=status.HTTP_400_BAD_REQUEST)

    # POST Request content
    data = request.data

    # Here check if user_id matches the token with the database
    if not db.check_user(data['source_user_id'], data['token']):
        return Response({'error': str('UNAUTHORIZED')},
                        status=status.HTTP_401_UNAUTHORIZED)

    # if friend request is being accepted
    if data['accept'] == "yes":
        if not mock_db.accept_friend(data['source_user_id'],
                                     data['dest_user_id']):
            return Response(
                {'error': str('Error when accepting friend request!')},
                status=status.HTTP_500_INTERNAL_SERVER_ERROR)

    # if friend request is not accepted
    elif data['accept'] == "no":
        if not mock_db.cancel_friend_request(data['source_user_id'],
                                             data['dest_user_id']):
            return Response(
                {'error': str('Error when declining friend request!')},
                status=status.HTTP_500_INTERNAL_SERVER_ERROR)

    # bad request
    else:
        return Response(
            {'error': str('Invalid request. Use yes/no in accept field.')},
            status=status.HTTP_400_BAD_REQUEST)

    return Response({'status': 'success'})
Ejemplo n.º 5
0
    def test_logout(self):
        """Tests user logout by checking token."""

        # logout
        post_data = {'user_id': self.user_info,
                     'token': self.token}

        response = self.client.post('/profile_page/api/logout', post_data)
        self.assertEqual(response.status_code, 200,
                         msg=f'{BColors.FAIL}\t[-]\tFailed logging out!{BColors.ENDC}')
        print(f"{BColors.OKGREEN}\t[+]\tPass logging out.{BColors.ENDC}")

        # check if user doesn't have the token after logout
        self.assertEqual(profile_db.check_user(self.user_info, self.token), False,
                         msg=f'{BColors.FAIL}\t[-]\tUser still have the token after log-out!{BColors.ENDC}')
        print(f"{BColors.OKGREEN}\t[+]\tUser does not have the token after log-out.{BColors.ENDC}")
Ejemplo n.º 6
0
def save_board(request):
    """
    Saves the active game from the list of active games in the database
    to the user's profile. Game is only saved if the user is
    authenticated, i.e. if the user has the matching token, else
    UNAUTHORIZED error is returned.
    Game that is being saved must exist in the list of active games.
    user_id: unique user identifier (same as username).
    token: authentication token that allow access to the user's account.
    game_id: ID of the saved game.
    :param request: POST request with fields 'user_id', 'game_id', 'token'.
    :return: success message, or error status.
    """
    required_fields = ['user_id', 'game_id', 'token']

    # Check if the post request contain the required fields
    if set(required_fields) != set(list(request.data.keys())):
        return Response({'error': str('Missing required fields!')},
                        status=status.HTTP_400_BAD_REQUEST)

    # POST Request content
    data = request.data

    # check for not allowed characters
    if check_special_characters(str(data['user_id'])) or check_special_characters(str(data['game_id']))  \
            or check_special_characters(str(data['token'])):
        return Response({'error': str('Unaccepted character passed!')},
                        status=status.HTTP_400_BAD_REQUEST)

    # Here check if user_id matches the token with the database
    if not db.check_user(data['user_id'], data['token']):
        return Response({'error': str('UNAUTHORIZED')},
                        status=status.HTTP_401_UNAUTHORIZED)

    # Load the game board from the database
    response_status = game_utils.load_board_db(data['game_id'])
    if response_status['error']:
        return Response({'error': response_status['reason']},
                        status=status.HTTP_500_INTERNAL_SERVER_ERROR)
    board = response_status['game_board']

    # Here append new game board to user's profile. Note that this board already have an ID.
    if not db.save_game(data['user_id'], board):
        return Response({'error': str('Error when saving the game!')},
                        status=status.HTTP_500_INTERNAL_SERVER_ERROR)

    return Response({'status': 'success'})
Ejemplo n.º 7
0
def share(request):
    """
    Shares the user's game boards with the destination user.
    User who is initiating the share action must be authenticated, i.e.
    the user must have the matching token. The game board
    identified by game_id must exist in user's profile.
    Destination user must have the accept shared games setting turned on.
    Share action is performed by creating a copy of the game board in the
    user's profile identified by dest_user_id.
    source_user_id: unique user identifier of user initiating share (same as username).
    dest_user_id: unique user identifier of user recieving the game (same as username).
    token: authentication token that allow access to the user's account.
    game_id: ID of the saved game.
    :param request: POST request with fields 'source_user_id', 'dest_user_id', 'game_id', 'token'
    :return: success message or error status.
    """
    required_fields = ['source_user_id', 'dest_user_id', 'game_id', 'token']

    # Check if the post request contain the required fields
    if set(required_fields) != set(list(request.data.keys())):
        return Response({'error': str('Missing required fields!')},
                        status=status.HTTP_400_BAD_REQUEST)

    # POST Request content
    data = request.data

    # check for not allowed characters
    if check_special_characters(str(data['source_user_id'])) or check_special_characters(str(data['dest_user_id']))  \
            or check_special_characters(str(data['game_id'])) or check_special_characters(str(data['token'])):
        return Response({'error': str('Unaccepted character passed!')},
                        status=status.HTTP_400_BAD_REQUEST)

    # Here check if user_id matches the token with the database
    if not db.check_user(data['source_user_id'], data['token']):
        return Response({'error': str('UNAUTHORIZED')},
                        status=status.HTTP_401_UNAUTHORIZED)

    # Here call db to copy saved game board from source_user_id to dest_user_id
    # This database call just copies the saved board into dest_user_id's saved game boards
    if not db.share_game_board(data['source_user_id'], data['dest_user_id'],
                               data['game_id']):
        return Response({'error': str('Error when sharing the game!')},
                        status=status.HTTP_500_INTERNAL_SERVER_ERROR)

    return Response({'status': 'success'})
Ejemplo n.º 8
0
    def test_login(self):
        """Tests user login by checking the token."""

        # login
        post_data = {'user_id': self.user_info,
                     'password': '******'}

        response = self.client.post('/profile_page/api/login', post_data)
        self.assertEqual(response.status_code, 200,
                         msg=f'{BColors.FAIL}\t[-]\tFailed to log-in!{BColors.ENDC}')
        print(f"{BColors.OKGREEN}\t[+]\tPass logging in.{BColors.ENDC}")

        # expected authentication token
        token = response.data['token']

        # check if user has the correct token
        self.assertEqual(profile_db.check_user(self.user_info, token), True,
                          msg=f'{BColors.FAIL}\t[-]\tUser has wrong token after log-in!{BColors.ENDC}')
        print(f"{BColors.OKGREEN}\t[+]\tUser has the correct token after log-in.{BColors.ENDC}")
Ejemplo n.º 9
0
def delete_board(request):
    """
    Removes the saved game board from user's profile.
    User must be authenticated, i.e. must have the matching token.
    Game board in the user's profile identified by game_id must exist.
    user_id: unique user identifier (same as username).
    token: authentication token that allow access to the user's account.
    game_id: ID of the saved game.
    :param request: POST request with fields 'user_id', 'game_id', 'token'.
    :return: success message, or error status.
    """
    required_fields = ['user_id', 'game_id', 'token']

    # Check if the post request contain the required fields
    if set(required_fields) != set(list(request.data.keys())):
        return Response({'error': str('Missing required fields!')},
                        status=status.HTTP_400_BAD_REQUEST)

    # POST Request content
    data = request.data

    # check for not allowed characters
    if check_special_characters(str(data['user_id'])) or check_special_characters(str(data['game_id']))  \
            or check_special_characters(str(data['token'])):
        return Response({'error': str('Unaccepted character passed!')},
                        status=status.HTTP_400_BAD_REQUEST)

    # Here check if user_id matches the token with the database
    if not db.check_user(data['user_id'], data['token']):
        return Response({'error': str('UNAUTHORIZED')},
                        status=status.HTTP_401_UNAUTHORIZED)

    # Here delete the game board from user's saved profile
    if not db.delete_game(data['user_id'], data['game_id']):
        return Response({'error': str('Error when deleting the game!')},
                        status=status.HTTP_500_INTERNAL_SERVER_ERROR)

    return Response({'status': 'success'})
Ejemplo n.º 10
0
def delete(request):
    """
    If the username has the given token, user's account is deleted.
    Else, UNAUTHORIZED error is returned.
    user_id: unique user identifier (same as username).
    token: authentication token that allow access to the user's account.
    :param request: POST request with fields 'user_id', 'token'.
    :return: success message, else error status.
    """
    # user_name == user_id
    required_fields = ['user_id', 'token']

    # Check if the post request contain the required fields
    if set(required_fields) != set(list(request.data.keys())):
        return Response({'error': str('Missing required fields!')},
                        status=status.HTTP_400_BAD_REQUEST)

    # POST Request content
    data = request.data

    # check for not allowed characters
    if check_special_characters(str(
            data['user_id'])) or check_special_characters(str(data['token'])):
        return Response({'error': str('Unaccepted character passed!')},
                        status=status.HTTP_400_BAD_REQUEST)

    # Here check if user_id matches the token with the database
    if not db.check_user(data['user_id'], data['token']):
        return Response({'error': str('UNAUTHORIZED')},
                        status=status.HTTP_401_UNAUTHORIZED)

    # Here remove the user's account from the database
    if not db.remove_user(data['user_id']):
        return Response(
            {'error': str('Error when removing the user account!')},
            status=status.HTTP_500_INTERNAL_SERVER_ERROR)

    return Response({'status': 'success'})
Ejemplo n.º 11
0
def update_board_db(board, user_id='-1', token='-1'):
    """
    Update the game board in the database with the new state.
    Returns the board itself unless the game ended.
    If the game ended, then it changes the <end_game> field,
    and deletes the game from database. Otherwise, changes
    turn to the next player.

    :param board: game board
    :param user_id: username
    :param token: authentication token
    :return result, {'error': bool, 'reason': string, 'game_board': dict}:
    """
    result = {'error': False, 'reason': '', 'game_board': board}

    try:

        if board['curr_data_structure'] == 'AVL':
            # Game ended
            if (board['graph']['root_node'] == board['graph']['gold_node']
                    or len(board['deck']) == 0):

                # update the board
                board['end_game'] = True
                board['turn'] = max(
                    board['player_points'],
                    key=board['player_points'].get)  # get player w/ max points
                result['game_board'] = board

                # if user is authenticated
                if user_id not in ['-1', -1, ''
                                   ] and token not in ['-1', -1, '']:

                    # check if the game is being loaded from profile page
                    if 'profile_load' in list(
                            board.keys()) and board['profile_load'] is False:

                        # Here check if user_id matches the token with the database
                        if profile_db.check_user(user_id, token):
                            # Currently error return if user is not authenticated is disabled
                            # It just not updates the score
                            #result['error'] = True
                            #result['reason'] = "User is not authenticated"
                            #return result

                            # if the user is in part of the players (paranoid check)
                            if str(user_id) in board['player_ids']:

                                # if not negative points
                                if board['player_points'][str(user_id)] > 0:

                                    # get user's current points
                                    curr_points = profile_db.get_points(
                                        str(user_id))

                                    # get the target points
                                    if user_id == board['turn']:
                                        # if the user is the winner, double the points
                                        target_points = curr_points + (
                                            math.log(board['player_points'][
                                                str(user_id)]) * 2)
                                    else:
                                        # don't double the points if the user is not the winner
                                        target_points = curr_points + math.log(
                                            board['player_points'][str(
                                                user_id)])

                                    # set the new points
                                    profile_db.set_points(
                                        str(user_id), target_points)

                # remove the game from the database
                db.remove_game(board['game_id'])

            # Game continues
            else:
                _ = db.update_game(board['game_id'], board)

                # hide the UID used by data structure backend from user
                # del board['graph']['uid']

                # Update
                result['game_board'] = board

        else:
            _ = db.update_game(board['game_id'], board)

            # hide the UID used by data structure backend from user
            # del board['graph']['uid']

            # Update
            result['game_board'] = board

    except Exception as err:
        result['error'] = True
        result['reason'] = str(err)
        return result

    return result
Ejemplo n.º 12
0
def load_board(request):
    """
    POST request API call to load in a saved game board.
    This API call activates the saved gave in the user's profile by
    moving the saved board to the list of active games.
    User must be authenticated, i.e. token must match with user's profile.
    Once the game loaded, i.e. moved to the active games, board can be
    interacted with using the Game Board API.
    User must have the claimed game board defined by the game_id.
    user_id: unique user identifier (same as username).
    token: authentication token that allow access to the user's account.
    game_id: ID of the saved game.
    :param request: POST request with fields 'user_id', 'game_id', 'token'
    :return: Game Board instance
    """
    required_fields = ['user_id', 'game_id', 'token']

    # Check if the post request contain the required fields
    if set(required_fields) != set(list(request.data.keys())):
        return Response({'error': str('Missing required fields!')},
                        status=status.HTTP_400_BAD_REQUEST)

    # POST Request content
    data = request.data

    if check_special_characters(str(data['user_id'])) or check_special_characters(str(data['game_id']))  \
            or check_special_characters(str(data['token'])):
        return Response({'error': str('Unaccepted character passed!')},
                        status=status.HTTP_400_BAD_REQUEST)

    # Here check if user_id matches the token with the database
    if not db.check_user(data['user_id'], data['token']):
        return Response({'error': str('UNAUTHORIZED')},
                        status=status.HTTP_401_UNAUTHORIZED)

    # Load the game from user's saved profile
    game_board = db.load_board(data['user_id'], data['game_id'])
    if not game_board:
        return Response({'error': 'you got some messed up arguments (NICK)'},
                        status=status.HTTP_500_INTERNAL_SERVER_ERROR)
    game_board['game_id'] = str(uuid.uuid1())

    # indicate that this board is being loaded from the profile
    game_board['profile_load'] = True

    # Here I am just going to move this board to active games using the api we already have.
    # Note that board is still saved on user's profile, but we are just creating a new active game.
    response_status = game_utils.create_board_db(game_board)
    if response_status['error']:
        return Response({'error': response_status['reason']},
                        status=status.HTTP_500_INTERNAL_SERVER_ERROR)

    active_game_id = response_status['game_id']

    # Here i am just going to return the game board itself from the active games
    # From this point front-end can continue using the Game Board API to interact with the game
    response_status = game_utils.load_board_db(active_game_id)
    if response_status['error']:
        return Response({'error': response_status['reason']},
                        status=status.HTTP_400_BAD_REQUEST)

    # hide the UID used by data structure backend from user
    del response_status['game_board']['graph']['uid']

    return Response(response_status['game_board'])