예제 #1
0
def auth_passwordreset_reset(reset_code: str, new_password: str) -> dict:
    '''
    Given a reset code for a user,
    set that user's new password to the password provided.

    :param reset_code: generated random code sent to user
    :param new_password: user's new password to be reset
    :return:
    '''
    # check if new password is valid
    if len(new_password) < 6:
        raise InputError(description='error occurred: Password entered is less '
                                     'than 6 characters long')
    # check if reset code match
    db_connect = DbConnector()
    db_connect.cursor()
    sql = "SELECT u_id FROM project.user_data WHERE reset_code=(%s)"
    value = (reset_code,)
    db_connect.execute(sql, value)
    ret = db_connect.fetchone()
    if ret is None:
        raise InputError(description='error occurred: Reset code entered does not match')

    # use for sql query
    u_id = ret[0]

    # UPDATE new password and remove the reset code from database
    password = hashlib.sha256(new_password.encode()).hexdigest()
    sql = "UPDATE project.user_data set password=(%s), reset_code = (%s) WHERE u_id=(%s)"
    value = (password, None, u_id)
    db_connect.execute(sql, value)

    # close database connection
    db_connect.close()

    return {}
예제 #2
0
def channel_details(token, channel_id):

    #InputError: channel_id does not refer to a valid channel.
    if not is_valid_channel(channel_id):
        raise InputError()

    #get authorised user id
    u_id_caller = data['tok_uid'][token]

    #AccessError: the authorised user is not already a member of the channel
    if not is_channel_member(u_id_caller, channel_id):
        raise AccessError()

    channel_info = get_channel_info(channel_id)
    return channel_info
예제 #3
0
def channels_create(token, name, is_public):
    '''
    Input: token, name, is_public status
    Output: {channel_id}, creates a new channel with the input name and public / private
    '''
    # verify the user
    if verify_token(token) is False:
        raise AccessError(description='Invalid token')

    # get database
    data = get_store()
    # getting user id from token
    u_id = get_tokens()[token]

    # check if name is valid
    if not isinstance(name, str) or len(name) > 20:
        raise InputError(description='Invalid channel name')

    # check if is_public is correct type
    if not isinstance(is_public, bool):
        raise InputError(description='Invalid channel status')

    # creating new channel
    details = name, is_public
    new_id = data.add_channel(u_id, details)

    # CREATING HANGMAN BOT
    hbot = create_hbot(new_id)

    # Inform the first user of option to disable hangman game
    message_send(hbot['token'], new_id, "For owners and admins: \
        \nType '/disable game' to disable the hangman game. \nType '/enable game' to re-enable it.")

    return {
        'channel_id': new_id
    }
예제 #4
0
def auth_login(email, password):
    
    password = hashlib.sha256(password.encode()).hexdigest()

    flag = 0
    for user in data['users']:
        if user['email'] == email:
            found_user = user
            flag = 1
        if user['token'] != "False":
            raise InputError('You are already logged in')

    if flag == 0:
        raise InputError('Email has not been registered previously')
    
    if password != found_user['password']:
        raise InputError('Password entered is not correct')
    
    token = jwt.encode({'u_id': found_user['u_id']}, 'jekfwbdkbwkf', algorithm='HS256').decode('utf-8')

    user['token'] = token
    return {
        'u_id': found_user['u_id'], 'token': token,
    }
예제 #5
0
def user_profile_setemail(token, email):
    """Update the authorised user's email address"""
    # Check token is valid.
    if not isinstance(token, str):
        raise AccessError('Token is invalid')

    if not auth.check_token_exists(token):
        raise AccessError("Invalid token")

    # Check valid email.
    if not auth.check_valid_email(email):
        raise InputError("This is not a valid email")

    # Check email exists.
    if auth.check_element_exists(search_type="email", element=email):
        raise InputError("This email already exists")
    # Retrieve user_id
    user_id = get_user_id(token)
    # Retrieve user.
    user = get_user_profile(user_id)

    # Set new email.
    user["email"] = email
    return {}
예제 #6
0
def check_valid_react_id(react_id):
    """
    Given a react_id, checks if the react_id is a valid React ID in the system

    Parameters:
        react_id (int): the unique id of a 'react' that will be reacted to

    Return:
        {}
    """
    # List of valid react_id that is applicable in the system
    valid_react_id = [1]
    # Raise an InputError if the react_id is invalid else do nothing
    if react_id not in valid_react_id:
        raise InputError(description="react_id is not a valid React ID")
def register():

    # Request information
    data = request.get_json()
    email = data["email"]
    password = data["password"]
    name_first = data["name_first"]
    name_last = data["name_last"]
    if not email_check(email):
        raise InputError(description="Email not valid")
    if email_dupe_check(email):
        raise InputError(description="Email already used")
    if len(password) < 6:
        raise InputError(description="Password less than 6 characters")
    if len(name_first) < 1 or len(name_first) > 50:
        raise InputError(description="First name is invalid")
    if len(name_last) < 1 or len(name_last) > 50:
        raise InputError(description="Last name is invalid")

    auth = auth_register(email, password, name_first, name_last)
    auth_token = auth['token']
    auth_uid = auth['u_id']

    return dumps({'token': auth_token, 'u_id': auth_uid})
예제 #8
0
def message_react(token, message_id, react_id):

    if not helper.check_valid_id(react_id):
        raise InputError('react_id is not a valid React ID')

    user_data = auth.get_data()
    u_id = helper.get_id(token, user_data)
    channel_data = get_data()
    react = helper.react_struct(react_id,u_id)
    for channel_id in channel_data:
        for message in channel_data[channel_id]['messages']:
            if message_id == message['message_id']:
                storage.add_react(channel_id, message_id,react)
      
    return {}
예제 #9
0
def message_unreact(token, message_id, react_id):
    '''Given a message within a channel the authorised user is part of,
    remove a "react" to that particular messageGiven a message within a
    channel the authorised user is part of, remove a "react" to that particular message'''
    DATA = getData()
    msg = get_message_from_messageID(DATA, message_id)
    ch = get_channel_from_msgID(DATA, message_id)
    userID = verify_token(token)
    # InputError:
    # Message_id is not a valid message within a channel that the authorised user has joined
    if not check_valid_msg(message_id):
        raise InputError('Invalid message ID')
    if not check_user_in_channel(userID, ch):
        raise InputError("User not in message's channel")
    # React_id is not a valid React ID
    if react_id != 1:
        raise InputError('Invalid react ID')
    # Message with ID message_id does not contain an active React with ID react_id
    reacted = False

    for r in msg['reacts']:
        if r['react_id'] == react_id:
            for users in r['u_ids']:
                if users == userID:
                    reacted = True
                    r['u_ids'].remove(users)

    if not reacted:
        raise InputError('No such react in given message')

    # Non-exception: remove react
    #for r in msg['reacts']:
    #    if r['react_id'] == react_id:
    #        msg['reacts'].remove(r)
    update_database(DATA)
    return {}
예제 #10
0
def channels_create(token, name, is_public):
    '''
    Creates a new channel with that name that is either a public or private channel
    Input: token (str), name (str), is_public (boolean)
    Output: dict
    '''
    auth_user = user_with_token(token)
    # Error check
    if auth_user is None:
        raise AccessError('Invalid token')
    elif len(name) > 20:
        raise InputError('Name longer than 20 characters')
    elif not name:
        raise InputError('Empty name')
    elif name.isspace():
        raise InputError('Whitespace name')

    # Register
    new_channel = Channel(auth_user, name, is_public)
    data['channels'].append(new_channel)

    return {
        'channel_id': new_channel.get_channel_id(),
    }
예제 #11
0
def user_profile_sethandle(token, handle_str):
    """
    Changes and sets user's handle_str.
    Parameters:
        token(str): A string that validates the users actions while
    				they are logged in
        handle_str(str): The handle the user wants to change to

    Returns: None
    """
    # raise InputError if any of the inputs is empty
    if token == '':
        raise InputError("Token input left empty")
    if handle_str == '':
        raise InputError("Handle_str input left empty")

    # raise InputError if any of the inputs is an invalid type
    if not isinstance(token, str):
        raise AccessError("Invalid Token")
    if not isinstance(handle_str, str):
        raise InputError("Invalid Email")

    # raises an error if the handle is not of the required length
    if len(handle_str) < 3:
        raise InputError("handle string too short")
    elif len(handle_str) > 20:
        raise InputError("handle string too long")

    # check that token is authorised
    tok = authenticate_token(token)
    # check that handle_str is not being used by another user
    existing_handle(handle_str)

    user = data.users[tok]
    user.handle_str = handle_str
    return {}
예제 #12
0
def channel_join(token, channel_id):
    '''Given a channel_id, adds the authorised user to the channel'''
    database = get_data()
    # Find channel dict with given channel_id
    for channel in database["channels"]:
        if channel["channel_id"] == channel_id:
            # Check if channel is private
            if channel["is_public"] is False:
                raise AccessError(description="Channel is private")
            # Find user from token
            email = find_token(token)
            for user in database["users"]:
                if user["email"] == email:
                    for member in channel["members"]:
                        if user["u_id"] == member:
                            raise InputError(
                                description=
                                'User is already a member of the channel')
                    channel["members"].append(user["u_id"])
                    with open('data_store.json', 'w') as FILE:
                        json.dump(database, FILE)
                    return {}
            raise AccessError(description="Invalid token")
    raise InputError(description="Invalid channel_id")
예제 #13
0
def user_permission_change_fn(token, u_id, permission_id, users):
    for user in users:
        if user['token'] == token:
            if user['permission_id'] != 1:
                raise AccessError(
                    description='Must be an owner to change permission')
            break
    else:
        raise AccessError(description='Invalid Token')

    for user in users:
        if user['u_id'] == u_id:
            user['permission_id'] = permission_id
            return
    raise InputError(description='Invalid u_id')
예제 #14
0
def c_removeowner():
    """ This is a flask wrapper for the channel_removeowner function

    Parameters:
        No parameters

    Returns:
        (dictionary): Empty dictionary
    """
    data = request.get_json()
    token = data['token']
    channel_id = int(data['channel_id'])
    u_id = int(data['u_id'])

    if not channel_check(channel_id):
        raise InputError(description="Channel is invalid")
    if not check_if_user_in_channel_owner_uid(u_id, channel_id):
        raise InputError(description="User not owner of channel")
    if not check_if_user_in_channel_owner(token, channel_id):
        raise AccessError(description="User not owner of channel")

    out = channel_removeowner(token, channel_id, u_id)

    return dumps(out)
예제 #15
0
def message_pin(token, message_id):
    """ Given a message within a channel, mark it as "pinned" to be given
        special display treatment by the frontend.

    Parameters:
        token (str): Authorisation hash for user
        message_id (int): Messages' message ID

    Returns:
        {} (dict): Empty dictionary

    """
    if not isinstance(token, str):
        raise AccessError('Token is invalid')
    # Input Errors:
    # 1. Message_id is not a valid message
    message_list = list(filter(lambda msg: msg["message_id"] == message_id, \
        data["messages"]))
    if len(message_list) == 0:
        raise InputError("Message does not exist")
    # 2. Message ID is already pinned
    if message_list[0]["is_pinned"] is True:
        raise InputError("Message already pinned")

    if auth.check_token_exists(token):
        auth_user = get_user_id(token)
    else:
        raise AccessError("User does not exist.")
    # Access Errors:
    # 1. Unauthorised user
    channel_id = message_list[0]["channel_id"]
    channel_data = get_channel(channel_id)
    if auth_user not in channel_data["owner_members"]:
        raise AccessError("User is not authorised")
    message_list[0]["is_pinned"] = True
    return {}
예제 #16
0
def auth_passwordreset_reset(server_data, reset_code, new_password):
    """
    Given a reset code for a user
    set that user's new password to the password provided

    input:
    - reset_code (string)
    - new_password(string)

    output:
    - {}
    """
    # reset_code is not a valid reset_code
    if not server_data.does_reset_code_exist(reset_code):
        raise InputError("Reset_code is invalid")
    # reset_code is valid, reset password
    else:
        # check if the new_password is invalid or not
        if len(new_password) < 6:
            raise InputError("Passowrd entered is not a valid password")
        else:
            user = server_data.get_user_by_reset_code(reset_code)
            user.password = new_password
    return {}
예제 #17
0
def message_pin(token, message_id):
    '''
    Given a message within a channel, mark it as "pinned" to be given special display treatment by the frontend
    '''
    u_id = get_u_id(token)

    channel_id = find_channel(message_id)
    message = find_message(channel_id, message_id)

    m_id = message_exists(message_id)
    auth_user = user_in_channel(u_id, channel_id)

    # Input errors for invalid / already pinned messages
    if not m_id:
        raise InputError("Invalid message ID")
    if message['is_pinned']:
        raise InputError("Message is already pinned")
    # Access error for non-owners / unauthorised users
    if not auth_user:
        raise AccessError("User is not a member of the channel")

    message['is_pinned'] = True

    return {}
예제 #18
0
def channels_listall(token, users, channels):
    return_list = []
    for user in users:
        if token == user['token']:
            break
    else:
        raise InputError(description="Invalid Token, channels_listall")

    for channel in channels:
        return_list.append({
            'channel_id': channel['id'],
            'name': channel['channel_name']
        })

    return dumps({'channels': return_list})
예제 #19
0
def message_unpin(token, message_id):
    '''
    Given a message within a channel, remove its mark as unpinned
    '''
    u_id = get_u_id(token)

    channel_id = find_channel(message_id)
    message = find_message(channel_id, message_id)

    m_id = message_exists(message_id)
    auth_user = user_in_channel(u_id, channel_id)

    # Input errors for invalid / already unpinned messages
    if not m_id:
        raise InputError("Invalid message ID")
    if not message['is_pinned']:
        raise InputError("Message is already unpinned")
    # Access error for non-owners / unauthorised users
    if not auth_user:
        raise AccessError("User is not a member of the channel")

    message['is_pinned'] = False

    return {}
예제 #20
0
def admin_userpermission_change(token, u_id, permission_id):

    # InputError: user id is invalid
    if not is_valid_uid(u_id):
        raise InputError(description='User with u_id does not exist')

    # InputError: permission_id is invalid (not 1 or 2)
    if permission_id != 1 and permission_id != 2:
        raise InputError(description='permission_id must be 1 or 2')
   
    # get authorised user's id
    u_id_caller = data['tok_uid'][token]
     
    # AccessError: authorised user is not a global owner (permission_id is 2)   
    for user in data['users']:
        if user['u_id'] == u_id_caller:
            print(user['permission_id'])
            if user['permission_id'] == 2:
                raise AccessError(description='Regular users cannot alter global permissions')
    
    # else, update user's permission_id
    for user in data['users']:
        if user['u_id'] == u_id:
            user['permission_id'] = permission_id
예제 #21
0
def unreact(payload):
    '''
    Function to remove a react from a message
    '''
    global REACT_IDS  # pylint: disable=W0603
    user = get_user_from('token', payload['token'])

    message = find_message(payload['message_id'])

    channel = get_channel(message['channel_id'])

    if int(payload['react_id']) not in REACT_IDS:
        raise InputError(description='Unable to react with react_id ' +
                         str(payload['react_id']))

    if not test_in_channel(user['u_id'], channel):
        raise InputError(description='Unable to react as you are ' +
                         'not a part of that channel')

    for i in message['reacts']:
        if i['react_id'] == payload['react_id']:
            # this react is already present in the message
            # just remove u_id
            if user['u_id'] not in i['u_ids']:
                raise InputError(description='Attempting to uncreact ' +
                                 'a message you have not reacted to')
            i['u_ids'].remove(user['u_id'])
            if len(i['u_ids']) == 0:  # pylint: disable=C1801
                # no one else has reacted, so remove react
                message['reacts'].remove(i)
                print(message['reacts'])
            return

    # unable to find react of react_id in messages
    raise InputError(description='Message with ID message_id ' +
                     'does not contain an active react with with ID react_id')
예제 #22
0
def check_is_reacted_already(channel_id, message_id, react_id, u_id):
    """
    Checks if user has already reacted to message

    Parameters:
        channel_id(int): id of channel
        message_id(int):id of message
        react_id(int): id of react
        u_id(int): id of user
    Returns:
        Raises error if user has already reacted to message
        If it is valid it returns nothing
    """
    if data.check_user_already_reacted(channel_id, message_id, react_id, u_id) is True:
        raise InputError(description='User has already reacted to this message')
예제 #23
0
def user_handle():
    """ This is a flask wrapper for the user/profile/sethandle function

    Parameters:
        No parameters

    Returns:
        (dictionary): Empty dictionary
    """

    data = request.get_json()
    token = data['token']

    set_handle = data['handle_str']

    if not token_check(token):
        raise InputError(description="Invalid token")
    if (len(set_handle) <= 2 or len(set_handle) >= 20):
        raise InputError(description="Invalid handle")
    if handle_check(set_handle):
        raise InputError(description="Handle already in use")

    user_profile_sethandle(token, set_handle)
    return dumps({})
예제 #24
0
def check_existing_handle(handle_str):
    """
    Determine whether supplied handle already exists

    Parameters:
        handle_str(string): New handle

    Returns:
        Raises an error if handle already exists
        Returns nothing if handle doesn't exist
    """

    if data.get_user_with({ "handle_str" : handle_str }) is not None:
        raise InputError(description = "Handle already in use")
    return
예제 #25
0
def check_guesser_not_creator(u_id, channel_id):
    """
    Checks whether a user is guessing their own word

    Parameters:
        u_id(int) : An identifier for users
        channel_id(int): An identifier for channels
        
    Returns:
        InputError if the guesser also started the hangman session
        Nothing if the guesser and starter are different users
    """
    status_message = data.get_hangman_status_message(channel_id)
    if status_message['u_id'] == u_id:
        raise InputError(description='Users can not guess their own word')
예제 #26
0
def check_valid_reset_code(reset_code):
    """
    Determines who reset code belongs to

    Parameters:
        reset_code(str): A hash used for resetting a user's password

    Returns:
        User dictionary of whoever has the reset_code
        Raises an error if reset_code doesn't belong to a user
    """
    user = data.get_user_with({'reset_code' : reset_code})
    if user:
        return user
    raise InputError(description='Reset code is not valid')
예제 #27
0
def user_profile_setemail(token, email):
    '''
    Updates the authorised user's email address.

    Args:
        token (str): of the user authorising this action
        email (str): user's new email address

    Raises:
        AccessError: if token invalid
        InputError:
            if email invalid as determined by is_valid_email module
            if email is already being used by another user
    '''

    # verify that the token is valid
    if verify_token(token) is False:
        raise AccessError(description="Invalid token")

    # InputError if email not valid
    if is_valid_email(email) is False:
        raise InputError(description="Input is not a valid email")

    u_id = get_tokens()[token]
    data = get_store()

    # InputError if email not unique
    # Allow if the user is simply changing their email to their current email
    # again.
    if data.users.email_used(email):
        raise InputError(
            description="this email is already being used by another user")

    # Change the user's email in the STORE databas if the above hurdles are
    # passed
    data.users.set_email(u_id, email)
예제 #28
0
def user_profile_crop_image(token, img_url, x_start, y_start, x_end, y_end):
    """Given a URL of an image on the internet, crops the image within bounds
    (x_start, y_start) and (x_end, y_end).
    Position (0,0) is the top left."""

    # Ensure token is valid - error checking in function
    user_id = auth_get_current_user_id_from_token(token)

    # Returns (filename, headers) if successful
    try:
        urllib_request.urlretrieve(img_url, "static/" + str(user_id) + ".jpg")
    except:
        raise InputError("img_url returns an HTTP status other than 200")

    original_img = Image.open("static/" + str(user_id) + ".jpg")
    original_width, original_height = original_img.size

    # Ensure image in correct format
    if original_img.format != "JPG" and original_img.format != "JPEG":
        raise InputError("Image uploaded is not a JPG")

    # Basic error checking for given coordinates
    if x_start < 0 or y_start < 0 or x_end < x_start or y_end < y_start:
        raise InputError("given dimensions incorrectly formatted")

    # Error checking that coordinates are within original image
    if x_end > original_width or y_end > original_height:
        raise InputError("Dimensions out of bounds from original image")

    cropped = original_img.crop((x_start, y_start, x_end, y_end))
    cropped.save("static/" + str(user_id) + ".jpg")

    database["users"][user_id]["profile_img_url"] = (
        get_host_url() + "static/" + str(user_id) + ".jpg"
    )
    return {}
예제 #29
0
파일: message.py 프로젝트: jgonzaga35/Flock
def message_pin(token, message_id):
    """Given a message within a channel, mark it as "pinned" to be
    given special display treatment by the frontend"""

    # Check token is valid - error checking in function
    user_id = auth_get_current_user_id_from_token(token)

    # Check message exists in database
    message_exists = False
    for ch in database["channels"].values():
        if message_id in ch["messages"]:
            channel_id_for_message = ch["id"]
            message_exists = True

    if message_exists == False:
        raise InputError

    # Check message is not already pinned
    channel_msg = database["channels"][channel_id_for_message]["messages"][
        message_id]
    if channel_msg["is_pinned"] == True:
        raise InputError(
            f"message with message id {message_id} is already pinned")

    # Check user is in channel within which the message exists
    if (database["users"][user_id]["is_admin"] is False and user_id not in
            database["channels"][channel_id_for_message]["all_members_id"]):
        raise AccessError(
            "user must be part of the channel to remove his/her message (see assumptions.md)"
        )

    # Pin message if user is authorised - i.e. user is either a flockr owner
    # or the owner of the channel
    if (user_id
            in database["channels"][channel_id_for_message]["owner_members_id"]
            or database["users"][user_id]["is_admin"]):
        user_id_is_owner = True
    else:
        user_id_is_owner = False

    for msg in database["channels"][channel_id_for_message]["messages"].values(
    ):
        if msg["message_id"] == message_id and (user_id_is_owner):
            msg["is_pinned"] = True
            return {}

    # User not authorised to pin message
    raise AccessError
예제 #30
0
def check_stop_permission(u_id, channel_id):
    """
    Checks if user has permission to use '/hangman stop'

    Parameters:
        u_id(int): Identifier used for users
        channel_id(int): Identifier used for channels

    Returns:
        Nothing if user has permission
        Raises InputError if user does not have permission
    """
    channel = data.get_channel_info(channel_id)
    hang_info = data.get_hangman_info(channel_id)
    if u_id not in channel['owners'] and hang_info['u_id'] != u_id: # pragma: no cover
        raise InputError(description="User does not have permission to use command")