def permission_change(token, u_id, permission_id): '''change a user's permissions on the server :param token: jwt token :type token: str :param u_id: User id corresponding to the target user :type u_id: int :param permission_id: ID of user new permissions :type permission_id: int :raises InputError: u_id does not correspond to a user :raises InputError: Invalid Permission ID :raises AccessError: User is not a slackr owner :return: empty dictionary :rtype: dict ''' user_id = check_token(token) if not user_id in get_slackr_owners(): raise AccessError( description='You are not permitted to perform this action') if not is_valid_user(u_id): raise InputError(description='User does not exist') if permission_id not in (1, 2): raise InputError(description='Invalid permission ID') # all possible errors raised. if permission_id == 1: get_users()[u_id]['is_owner'] = True elif permission_id == 2: get_users()[u_id]['is_owner'] = False return {}
def test_remove_user(new_user, new_user_2): glob_users = get_users() channel = channels_create(new_user['token'], "new_channel", False) channel_invite(new_user['token'], channel['channel_id'], new_user_2['u_id']) user_remove(new_user['token'], new_user_2['u_id']) assert not new_user_2 in get_channels()[channel['channel_id']]['members'] with pytest.raises(InputError): auth_login(glob_users[new_user_2['u_id']]['email'], glob_users[new_user_2['u_id']]['password_hash'])
def test_application_clean(): ''' Tests that all global variables have been emptied by the reset ''' for new_user in range(100): user = auth_register("z55555" + str(new_user) + "@unsw.edu.au", "f for hayden rip", "hydaen", "smith") channels_create(user['token'], "test channel" + str(new_user), True) workspace_reset() assert len(get_channels().keys()) == 0 assert len(get_users().keys()) == 0 assert len(get_users()) == 0 assert len(get_slackr_owners()) == 0 assert len(get_valid_tokens()) == 0 original_image_folder = os.path.join(os.getcwd(), 'images/original') assert len(os.listdir(original_image_folder)) == 1 cropped_image_folder = os.path.join(os.getcwd(), 'images/cropped') assert len(os.listdir(cropped_image_folder)) == 1
def is_user_disabled(u_id): '''Finds if a user has been deleted :param u_id: target user_id :type u_id: int :return: True if the user has been deleted, otherwise False :rtype: bool ''' return get_users()[u_id]['disabled']
def is_handle_unique(handle_str): ''' Checks if a handle is already associated with a user in glob_users ''' glob_users = get_users() for user in glob_users.values(): if handle_str == user['handle_str']: return False return True
def backup_data(): '''Pickles slackr data with a timestamp.''' slackr_data = { 'timestamp': get_current_timestamp(), 'global_users': get_users(), 'global_channels': get_channels(), 'global_num_messages': get_num_messages() } with open('slackr_data.p', 'wb') as FILE: #pylint: disable=invalid-name dump(slackr_data, FILE)
def test_invalidation(): ''' A token that has been invalidated should raise an error ''' for user_id in range(100): new_token = generate_token(user_id) invalidate_token(new_token) with pytest.raises(AccessError): assert check_token(new_token) assert len(get_users()) == 0
def id_from_email(email): '''Returns the user id corresponding to an email :param email: email to be verified :type email: str :return: if user is found, returns u_id, otherise None :rtype: int/NoneType ''' glob_users = get_users() for u_id in glob_users: if email == glob_users[u_id]['email']: return u_id return None
def is_valid_handle(host_user_id, handle_str): '''Checks that handle_str is valid and not being used by any other user :param host_user_id: Id of the user changing their handle :type host_user_id: int :param handle_str: User's new handle :type handle_str: str :return: True if the new handle_str is the same as the old, or if it is both valid AND unique. :rtype: bool ''' users = get_users() if users[host_user_id]['handle_str'] == handle_str: return True return is_handle_unique( handle_str) and len(handle_str) >= 2 and len(handle_str) <= 20
def users_all(token): '''Returns a list of all users :param token: jwt token :type token: str :return: contains u_id, email, name_first, name_last, handle_str for each user :rtype: dict ''' check_token(token) users = get_users() return { 'users': [ get_user_information(user_id) for user_id in users if not is_user_disabled(user_id) ], }
def user_profile_setemail(token, email): '''Given a valid token and new email, updates a user's email address :param token: jwt token :type token: str :param email: new email :type email: str :raises InputError: If email is invalid according to is_new_email() :return: empty dictionary :rtype: dict ''' user_id = check_token(token) if not is_new_email(user_id, email): raise InputError(description='Email invalid or already being used') user = get_users()[user_id] user['email'] = email return {}
def user_profile_sethandle(token, handle_str): '''Given a valid new handle_str and token, updates a user's handle_str :param token: jwt token :type token: str :param handle_str: new handle :type handle_str: str :raises InputError: If handle_str is invalid according to is_valid_handle() :return: empty dictionary :rtype: dict ''' user_id = check_token(token) if not is_valid_handle(user_id, handle_str): raise InputError(description='Handle invalid or already being used') user = get_users()[user_id] user['handle_str'] = handle_str return {}
def auth_register(email, password, name_first, name_last): '''Registers a user, saves their information, and logs them in. Note: The first user is set as a slackr owner by default :param email: user's email :type email: str :param password: user's password :type password: str :param name_first: user's first name :type name_first: str :param name_last: user's last name :type name_last: str :return: user's token and user id :rtype: dict ''' # Checking inputs check_registration_inputs(email, password, name_first, name_last) glob_users = get_users() u_id = len(glob_users) password_hash = hash_string(password) handle_str = create_handle(name_first, name_last) is_owner = False if u_id == 0: is_owner = True glob_users[u_id] = { 'disabled': False, 'email': email, 'name_first': name_first, 'name_last': name_last, 'handle_str': handle_str, 'password_hash': password_hash, 'is_owner': is_owner, 'profile_img_url': '/imgurl/default.png' } token = generate_token(u_id) return { 'u_id': u_id, 'token': token, }
def user_remove(token, u_id): ''' Removes a user from a channel, only a slackr Owner can use this function ''' host_user_id = check_token(token) if not is_valid_user(u_id): raise InputError if not host_user_id in get_slackr_owners(): raise AccessError for channel_id in get_channels(): if is_user_a_owner(channel_id, u_id): get_channel_owners(channel_id).remove(u_id) elif is_user_a_member(channel_id, u_id): get_channel_members(channel_id).remove(u_id) glob_users = get_users() glob_users[u_id]['disabled'] = True return {}
def get_user_information(u_id): '''Returns user information in the correct format for the slackr frontend. :param u_id: User id, corresponding to an existing slackr user :type u_id: int :return: dictionary containing all user information :rtype: dict ''' try: user = get_users()[u_id] except KeyError: raise InputError(description='No user exists with that id') if is_user_disabled(u_id): raise InputError(description="This user has been deleted") return { 'u_id': u_id, 'email': user['email'], 'name_first': user['name_first'], 'name_last': user['name_last'], 'handle_str': user['handle_str'], 'profile_img_url': f'{os.getenv("URL")}{user["profile_img_url"]}' }
def user_profile_setname(token, name_first, name_last): '''Given a valid token, name_first, name_last, updates a users name_first, name_last :param token: jwt token :type token: str :param name_first: new first name :type name_first: str :param name_last: new last name :type name_last: str :raises InputError: if either name_first or name_last is invalid :return: empty dictionary :rtype: dict ''' user_id = check_token(token) if not (is_name_valid(name_first) and is_name_valid(name_last)): raise InputError( description='Names must be between 1 and 50 characters') user = get_users()[user_id] user['name_first'] = name_first user['name_last'] = name_last return {}
def auth_passwordreset_reset(reset_code, new_password): '''Given a valid reset code and password, replaces a users password :param reset_code: valid jwt containing a users email :type reset_code: str :param new_password: Users new password :type new_password: str :raises InputError: Invalid reset code, expired reset code, invalid password, :raises InputError: No user exists with that email :return: empty dictionary :rtype: dict ''' email = check_reset_code(reset_code) u_id = id_from_email(email) if u_id is None: return {} if not is_password_valid(new_password): raise InputError(description="Password not strong enough") password_hash = hash_string(new_password) glob_users = get_users() glob_users[u_id]['password_hash'] = password_hash return {}
def check_login_inputs(email, password): ''' Checks email is valid Checks email is associated with a user Checks password is correct Returns the u_id associated with the user ''' if not is_email_valid(email): raise InputError(description="Invalid Email") u_id = id_from_email(email) if u_id is None: raise InputError(description="This email has not been registered") glob_users = get_users() if is_user_disabled(u_id): raise InputError(description='This account has been removed from Slackr') password_hash = hash_string(password) # checking user password if glob_users[u_id]['password_hash'] != password_hash: raise InputError(description='Incorrect password') return u_id
def user_profile_setimage(token, img_url, x_start, y_start, x_end, y_end): #pylint: disable=too-many-arguments ''' Update the authorised user's display photo Downloads the given img_url into the server folder 'images' Crops images if they do not fit the size :param token: :type token: string ''' user_id = check_token(token) user = get_users()[user_id] file_extension = img_url.rsplit('.', 1)[1].lower() if not file_extension in ALLOWED_EXTENSIONS: raise InputError(description="file not allowed") if not x_start < x_end: raise InputError(description="x_start must be larger than x_end") if not y_start < y_end: raise InputError(description="y_start must be larger than y_end") try: image = requests.get(img_url, allow_redirects=True).content except: raise InputError(description="could not download image") new_file_name = f'{generate_random_string(20)}.{file_extension}' new_image = open(f'images/original/{new_file_name}', 'wb') new_image.write(image) original_image = Image.open(f'images/original/{new_file_name}') original_image = original_image.crop((x_start, y_start, x_end, y_end)) cropped_image = open(f'images/cropped/{new_file_name}', 'wb') original_image.save(cropped_image) user['profile_img_url'] = f'/imgurl/{new_file_name}' return {}
def is_valid_user(user_id): ''' returns true if user_id refers to an existing user ''' return user_id in get_users()
def find_handle(user_id): ''' returns the handle_str corresponding to a user_id ''' users = get_users() return users[user_id]['handle_str']