def change_user_permission(token, u_id, permission_id): """ Given a User by their user ID, set their permissions to new permissions described by permission_id """ # Store u_id of person running command user_from_token = database.get_current_user(token) if permission_id not in VALID_PERMISSION_IDS.values(): raise error.InputError(description="permission_id does not refer to a value permission") if (database.get_permission_dict(user_from_token).get("permission_id") != VALID_PERMISSION_IDS['owner']): # User is not a global owner. raise error.AccessError(description="The authorised user is not an owner") number_of_owners = 0 for member in database.get_permissions_list(): if member.get('permission_id') == VALID_PERMISSION_IDS['owner']: number_of_owners += 1 if (u_id == user_from_token and number_of_owners == 1): # i.e. Owner calling this function is only owner. raise error.AccessError(description="Owner cannot remove" + " permissions when he is the only owner") # Now, having checked for all errors, run function: database.set_permissions(u_id, permission_id)
def wrapper_func(*args, **kwargs): """ Wrapper function """ try: email_arg_index = argspec.args.index("email") email = args[email_arg_index] # Try to grab this users ID. If the user doesnt exist, create a warning # and run the function without checking the permission_id. try: target_u_id = next(u['u_id'] for u in database.get_users() if u['email'] == email) target_perm_id = database.get_permission_dict(target_u_id).get( 'permission_id') if target_perm_id == 66: raise error.AccessError( description="The account registered to this email has" + " been removed from the slakr. " + "[I'm sorry Dave, I'm afraid I can't do that]") else: return func(*args, **kwargs) except StopIteration: print( "\033[93m" + "WARNING: This email was not found - running function " + f"{func.__name__} without permission_id check." + "\033[0m") return func(*args, **kwargs) except ValueError: print("\033[93m" + "WARNING: email arg not found - running function " + f"{func.__name__} without email check." + "\033[0m") return func(*args, **kwargs)
def message_remove(token, message_id): """ Given a message_id for a message, this message is removed from the channel. """ u_id = get_current_user(token) message_location = get_message_location(message_id) channel_id = message_location["channel_id"] channel_data = get_channel_data(channel_id) if u_id not in channel_data['member_ids']: raise AccessError( description="User must be a member of the channel they are trying" + " to access.") # Find the message to be deleted. At this point # The message definitely exists and the user is definitely a member of the channel # it exists in. for message in channel_data["messages"]: if message['message_id'] == message_id: if message["u_id"] != u_id and get_permission_dict(u_id).get( 'permission_id') != 1: raise AccessError( description="Authorised user did not send the message " + "and is not a server/channel owner.") else: remove_message(message_id) return {}
def test_perms_valid(): """ Test the valid condition. """ user = auth.auth_register("*****@*****.**", "password", "Barry", "Benson") user2 = auth.auth_register("*****@*****.**", "password", "Barry", "Benson") admin.change_user_permission(user['token'], user2['u_id'], 1) assert database.get_permission_dict(user2['u_id']).get('permission_id') == 1
def channel_removeowner(token, channel_id, u_id): """ This function intakes the token of current authorised (auth) user, channel_id and a user u_id It then removes the user u_id as an owner of the channel, as long as the current auth user is an owner of slackr/channel and the user u_id is an owner """ # Check if token is valid and raise AccessError if not curr_id = database.get_current_user(token) # gets current channel data curr_channel = database.get_channel_data(channel_id) # gets the permissions of current user from database user_perms = database.get_permission_dict(curr_id) u_id_permission = database.get_permission_dict(u_id) if u_id_permission["permission_id"] == 1: raise error.AccessError(description="user being removed is the owner of the slackr") # checks if u_id is not an owner of the channel # also checks if current auth user is an owner of the channel is_u_owner = False is_curr_owner = False for owner_id in curr_channel["owner_ids"]: if u_id == owner_id: is_u_owner = True if curr_id == owner_id: is_curr_owner = True if is_u_owner is False: raise error.InputError(description="user being removed is not an owner of the channel") # if the auth user is owner of slackr, allows him to remove u_id as owner if user_perms["permission_id"] == 1: # removes the user from channel_owner curr_channel["owner_ids"].remove(u_id) # if the auth user is an owner of the channel, allow him to remove u_id as owner of channel elif is_curr_owner is True: # adds the user into channel_owner curr_channel["owner_ids"].remove(u_id) # else the auth user is not an owner and thus cannot use addowner else: raise error.AccessError(description="""Authorised user user is not an owner of the channel, or of the slackr""")
def users_all(token): """ returns a list of dictionaries for all users """ # pylint: disable=unused-argument # NB: Supressed this warning because token is in fact used in # the decorator, however pylint doesn't check for this. users_list = ([usr for usr in database.get_users() if database.get_permission_dict(usr['u_id']).get('permission_id') != 66]) return {"users": users_list}
def channel_addowner(token, channel_id, u_id): """ This function intakes the token of current authorised (auth) user, channel_id and a user u_id It then adds the user u_id as an owner of the channel, as long as the current auth user is an owner of slackr/channel """ # Check if token is valid and raise AccessError if not curr_id = database.get_current_user(token) # gets current channel data curr_channel = database.get_channel_data(channel_id) # gets the permissions of current user from database user_perms = database.get_permission_dict(curr_id) # check if user u_id is already an owner of the channel and raise InputError if so # also checks to see if current auth user is a owner of channel # a counter to check if user is a member of the channel is_curr_owner = False for owner_id in curr_channel["owner_ids"]: if u_id == owner_id: raise error.InputError(description="user u_id is already an owner of this channel") # checks if curr_id is an owner of channel if curr_id == owner_id: is_curr_owner = True # checks if the user u_id is a member of the channel already is_u_member = False for member_id in curr_channel["member_ids"]: if u_id == member_id: is_u_member = True # if the auth user is an owner of the slackr, allow him to add u_id as owner of channel if is_u_member is True: if user_perms["permission_id"] == 1: # adds the user into channel_owner curr_channel["owner_ids"].append(u_id) # if the auth user is an owner of the channel, allow him to add u_id as owner of channel elif is_curr_owner is True: # adds the user into channel_owner curr_channel["owner_ids"].append(u_id) # else the auth user is not an owner and thus cannot use addowner else: raise error.AccessError(description="""current user is not an owner of the channel, or of the slackr""")
def remove_user(token, u_id): """ Given a u_id, remove the user from the Slackr. """ # we get the current user data terminator = database.get_current_user(token) # Raise AccessError if user is not an owner of the Slackr terminator_perm = database.get_permission_dict(terminator) if terminator_perm['permission_id'] != 1: raise error.AccessError(description="""Action cannot be performed because you are not a Slackr owner.""") # Do a soft remove # they stay a part of everything, but they are removed from owner/memberID # in channels, and they are also banned from ever logging in again. # we get the token of the user to be removed # introduce a new permission ID 66: # terminated and set the user to be removed to perm_id 66: terminated terminated_id = 66 database.set_permissions(u_id, terminated_id) # remove the user from every channel's member_id and owner_id #first we call a list of every channel all_channels = database.get_channels() # we then get the data for each channel for each_channel in all_channels: channel_data = database.get_channel_data(each_channel["channel_id"]) # remove user u_id from owner_ids for owner_id in channel_data['owner_ids']: if u_id == owner_id: channel.channel_removeowner(token, channel_data["channel_id"], u_id) # remove user u_id from member_ids if u_id in channel_data['member_ids']: channel_data['member_ids'].remove(u_id) database.set_channel_data(channel_data) # finally we log the user out of the session (invalidating terminated token) terminated_token = database.get_token_from_user(u_id) if terminated_token is not None: auth.auth_logout(terminated_token)
def message_edit(token, message_id, message): """ Given a message, update it's text with new text. If the new message is an empty string, the message is deleted. """ u_id = get_current_user(token) message_location = get_message_location(message_id) # if message is longer than 1000 an Inputerror should be raised. if len(message) > 1000: raise InputError( description= 'Message is more than 1000 characters or try to send an empty message' ) channel_id = message_location["channel_id"] channel_data = get_channel_data(channel_id) if u_id not in channel_data['member_ids']: raise AccessError( description="User must be a member of the channel they are trying" + " to access.") # Find the message to be deleted (assume it definitely exists) msg_to_edit = next(msg for msg in channel_data['messages'] if msg['message_id'] == message_id) if msg_to_edit['u_id'] != u_id and get_permission_dict( u_id)['permission_id'] != 1: raise AccessError( description="Authorised user did not send the message " + "and is not a server/channel owner.") if message == '': remove_message(message_id) else: msg_to_edit['message'] = message set_message(channel_id, msg_to_edit) return {}
def channel_invite(token, channel_id, u_id): """ Invites a user (with user id u_id) to join a channel with ID channel_id. Once invited the user is added to the channel immediately """ if database.get_current_user(token) not in database.get_channel_data(channel_id)['member_ids']: raise error.AccessError(description="""Authorised user is not a member of channel with that channel_id.""") if u_id in database.get_channel_data(channel_id).get('member_ids'): raise error.InputError(description="This user is already a part of the channel.") new_channel_data = database.get_channel_data(channel_id) new_channel_data['member_ids'].append(u_id) if database.get_permission_dict(u_id).get('permission_id') == 1: new_channel_data['owner_ids'].append(u_id) database.set_channel_data(new_channel_data) return {}
def channel_join(token, channel_id): """ this function is passed a valid token and channel_id. It adds the user associated with the token into the channel, unless the channel is private """ # Check if token is valid and raise AccessError if not curr_id = database.get_current_user(token) # gets current channel data curr_channel = database.get_channel_data(channel_id) # gets the permissions of current user from database user_perms = database.get_permission_dict(curr_id) # checks if user is already a part of channel for user_id in curr_channel["member_ids"]: if curr_id == user_id: raise error.InputError(description="user is joining a channel user is already in") # this checks if the channel is empty (or new) in this case we make the new member an owner. if curr_channel["member_ids"] == []: # adds the user into channel_member curr_channel["member_ids"].append(curr_id) # adds the user into channel_owner curr_channel["owner_ids"].append(curr_id) # this checks if the user is an owner of the slacker # if they are they are given owner privelages in the channel # else they are a member elif user_perms["permission_id"] == 1: # adds the user into channel_member curr_channel["member_ids"].append(curr_id) # adds the user into channel_owner curr_channel["owner_ids"].append(curr_id) elif curr_channel["is_public"] is True: # adds the user into the channel_member curr_channel["member_ids"].append(curr_id) elif curr_channel["is_public"] is False: raise error.InputError(description="""channel_join recieved a channel_id for a private channel""")
def test_remove_user(): """ Tests if user_remove correctly removes a user from the required parts of database: -retained in USERS, PASSWORD_DATA_LIST and in CHANNEL_DATA_LIST (for messages) -permission_id of user is now terminated (66) -removed from: CURRENT_USERS, CHANNELS[owner_id]/[member_ID], """ # establish a test register test_dict = auth.auth_register("*****@*****.**", "password", "Bob", "Ross") # valid channel ID (assigned by channels_create) c_id_dict = channels.channels_create(test_dict["token"], "test rum ham", True) # create a second user and add them to the channel as an owner test_dict_2 = auth.auth_register("*****@*****.**", "password2", "James", "May") channel.channel_join(test_dict_2["token"], c_id_dict["channel_id"]) channel.channel_addowner(test_dict["token"], c_id_dict["channel_id"], test_dict_2["u_id"]) # store our details before the leave details_before = channel.channel_details(test_dict["token"], c_id_dict["channel_id"]) # ensure there are two members: test_dict & test_dict_2 assert len(details_before["all_members"]) == 2 assert details_before["all_members"][0]["u_id"] == test_dict["u_id"] assert details_before["all_members"][1]["u_id"] == test_dict_2["u_id"] #ensure there are two owners: test_dict & test_dict_2 assert len(details_before["owner_members"]) == 2 assert details_before["owner_members"][0]["u_id"] == test_dict["u_id"] assert details_before["owner_members"][1]["u_id"] == test_dict_2["u_id"] # now we send a message to test rum ham message.message_send(test_dict_2["token"], c_id_dict["channel_id"], "hello world") # test that messages successfully returns the message sent_messages = channel.channel_messages(test_dict["token"], c_id_dict["channel_id"], 0) assert sent_messages["messages"][0]["message"] == "hello world" ######## Now we call the user_remove function: admin.remove_user(test_dict["token"], test_dict_2["u_id"]) ######## # we test that they still remain in user all_users = database.get_users() assert len(all_users) == 2 assert all_users[0]["u_id"] == test_dict["u_id"] assert all_users[1]["u_id"] == test_dict_2["u_id"] # we test that their messages can still be printed messages_post_remove = channel.channel_messages(test_dict["token"], c_id_dict["channel_id"], 0) assert messages_post_remove["messages"][0]["message"] == "hello world" assert messages_post_remove["messages"][0]["u_id"] == test_dict_2["u_id"] # we test that their permission is changed to 66 terminated_id = 66 permissions_post_remove = database.get_permission_dict(test_dict_2["u_id"]) assert permissions_post_remove["u_id"] == test_dict_2["u_id"] assert permissions_post_remove["permission_id"] == terminated_id # we test that they are no longer a part of CURRENT_USERS, assert database.get_current_user(test_dict_2["token"]) is None # we test that they are no longer a part of CHANNELS[owner_id]/[member_ID], details_after = channel.channel_details(test_dict["token"], c_id_dict["channel_id"]) # ensure there is one member: test_dict assert len(details_after["all_members"]) == 1 assert details_after["all_members"][0]["u_id"] == test_dict["u_id"] # ensure there is one owner: test_dict assert len(details_after["owner_members"]) == 1 assert details_after["owner_members"][0]["u_id"] == test_dict["u_id"] # we test that they are unable to log in again password_test = "qwertyuiop" with pytest.raises(error.AccessError): auth.auth_login("*****@*****.**", "password2") # Test that the InputError raised when an unregistered email is entered # still takes priority over the AccessError of admin_user_remove. with pytest.raises(error.InputError): auth.auth_login("*****@*****.**", password_test) # Check incorrect password works stil with pytest.raises(error.AccessError): auth.auth_login("*****@*****.**", password_test) with pytest.raises(error.InputError): auth.auth_login("wrongemailformat", password_test)