def profile_setname(payload): ''' Update the authorised user's first and last name ''' user = get_user_token(payload['token']) if not 1 < len(payload['name_first']) < 50: raise InputError( description='Invalid name_first, above the range of 50 characters') if not 1 < len(payload['name_last']) < 50: raise InputError( description='Invalid name_last, above the range of 50 characters') user['name_first'] = payload['name_first'] user['name_last'] = payload['name_last'] return {}
def channel_addowner(server_data, token, channel_id, u_id): """ Make user with user u_id an owner of this channel Input: - server_data(obj) - token (string) - channel_id (int) - u_id (int) Output: - {} """ # Check if the channel exists verify_channel_id(server_data, channel_id) # Verify if token is active, and if so, get u_id from the active session u_id_owner = verify_n_get_valid_token(server_data, token) # Verify if the u_id_owner is a owner of the channel or owner of slacker verify_user_channel_status(server_data, channel_id, u_id_owner, const.PERMISSION_LOCAL_OWNER) channel_obj = server_data.get_channel_by_id(channel_id) user_obj = server_data.get_user_by_id(u_id) # Is either slackr owner or channel owner # Now check if the user being added is already an owner if not channel_obj.is_user_owner(u_id): assert channel_obj.add_owner(user_obj.get_user_member_info()) else: raise InputError(description="User is already an owner") return {}
def message_unpin(token, message_id): """ Sets a message to unpinned by setting is_pinned to False Parameters: token (str): Used to authenticate and identify the user message_id (int): the unique id of a message in the system Return: {} """ # Check if token is valid user_id = authenticate_token(token) user = valid_user_id(user_id) # Check if message exists in the data # Function will raise InputError if message does not exist msg_check = check_message_valid(message_id) ch_index = msg_check['ch_index'] msg_index = msg_check['msg_index'] channel = valid_channel_id(ch_index) # Check if user is an owner of the channel, raise AccessError if not if user not in channel.owner_members: raise AccessError("User not not an owner inside desired channel") # check is pinned and set if channel.channel_messages[msg_index].is_pinned: channel.channel_messages[msg_index].is_pinned = False else: raise InputError(description="message wasn't pinned") return {}
def echo(): data = request.args.get('data') if data == 'echo': raise InputError(description='Cannot echo "echo"') return dumps({ 'data': data })
def message_react(token, message_id, react_id): token = request.form.get('token') message_id = request.form.get('message_id') react_id = request.form.get("react_id") message_index = message_id - 1 message_data = get_global_messages() user_data = get_global_users() channel_list = get_global_channel() position = position_in_user_data(token, user_data) check_valid_react_id(react_id) check_valid_message_id(message_id, message_data) is_user_in_channel_mid(position, user_data, channel_list, message_id, message_data) check_if_deleted(message_id, message_data) if user_data[position]['u_id'] in message_data[message_index]['reacts']['u_id']: message['reacts']['is_this_user_reacted'] = True raise InputError(description='Already reacted by requested user') else: message['reacts']['u_id'].append(user_data[position]['u_id']) message['reacts']['is_this_user_reacted'] = True #This is the scary one return dumps({})
def user_remove(): '''admin removes a user from slackr''' data = get_data() payload = request.get_json() token = payload['token'] u_id = int(payload['u_id']) check_token(token) user_data = get_user_data(u_id) if user_data == {}: raise InputError(description='No such user exists') person_u_id = get_user_from_token(token) person_data = get_user_data(person_u_id) if person_data['permission_id'] != 1: raise AccessError(description='The authorised person is not an owner of slackr') user_info = { 'u_id': u_id, 'name_first': user_data['name_first'], 'name_last': user_data['name_last'], } for channel in data['channels']: if user_info in channel['owner_members']: curr_channel_id = channel['channel_id'] data['channels'][curr_channel_id - 1]['owner_members'].remove(user_info) data['channels'][curr_channel_id - 1]['all_members'].remove(user_info) elif user_info in channel['all_members']: curr_channel_id = channel['channel_id'] data['channels'][curr_channel_id - 1]['all_members'].remove(user_info) dumps({})
def message_sendlater_fn(token, channel_id, message, time_sent, MESSAGES, \ MESSAGE_COUNTER, USERS, channel_list): position = position_in_user_data(token, USERS) is_user_in_channel(position, USERS, channel_id, channel_list) check_valid_message(message) tz = pytz.timezone("Australia/NSW") time_now = datetime.timestamp(datetime.now(tz)) print('\ntime_now is: ' + str(time_now)) print('time_sent is: ' + str(time_sent)) interval = time_sent - time_now print('sent - d_aware is: ' + str(interval) + '\n') if interval < 0: raise InputError( description='Time sent can not be less than current time.') timer = threading.Timer(int(interval), \ message_send_fn, \ [token, channel_id, message, MESSAGES, MESSAGE_COUNTER, USERS, channel_list]) timer.start() return dumps({'message_id': MESSAGE_COUNTER})
def channels_create(token, name, is_public): if len(name) > 20: raise InputError(f"{name!r} is more than 20 characters long") if name == "": name = "new_channel" creator_data = auth_get_user_data_from_id( auth_get_current_user_id_from_token(token)) id = database["channels_id_head"] new_channel = { "id": id, "name": name, "is_public": is_public, "owner_members_id": [creator_data["id"]], "all_members_id": [creator_data["id"]], "messages": {}, "standup_queue": [], "standup_is_active": False, "standup_finish_time": None, } database["channels"][id] = new_channel database["channels_id_head"] += 1 return {"channel_id": new_channel["id"]}
def log_in(username, password): """ Log a user in if given a valid username/password. Paramters: username (str): username entered by user password (str): password entered by user Returns: None Exceptions: AuthError when one of: username exists and password incorrect InputError when: username does not exist username exists, password correct, and already logged in """ check_username(username) hashed_password = sha256(password.encode()).hexdigest() if data.users[username].hash_pwd != hashed_password: raise AuthError("Incorrect password") if data.users[username].logged_in: raise InputError("Already logged in") data.users[username].logged_in = True
def channel_messages(token, channel_id, start): """ Returns a list of messages, start and end. Parameters: token (str): a unique token (to determine authorisation) channel_id(int): a unique id for such channel start (int): index indicating when the messages start Returns: { messages (str): the message which will be sent in the channel start (int): index indicating when the messages start end (int): index indicating when the messages end } """ # Check that token is valid and gets it index(u_id) user_id = authenticate_token(token) user = valid_user_id(user_id) # Check that channel_id is valid channel = valid_channel_id(channel_id) # Check that user is part of the desired channel if not channel.existing_member(user): raise AccessError(description="User not in desired channel.") # Check that start is not greater # than the total number of messages in the channel and not negative msg_count = channel.num_messages() if (start > msg_count or start < 0): raise InputError("invalid start") # Initialize the desired return data ch_messages = {} ch_messages['messages'] = [] msg_load = msg_count - start if msg_count == 0: # No messages to load end = -1 elif start == msg_count: # Only loads a single message if start is equal to message_count msg = channel.channel_messages[msg_count - 1].message_details() ch_messages['messages'].append(msg) end = -1 elif msg_load <= 50: # Loads all the messages in the channel if there are less than 50 messages to load for i in range(msg_load, start, -1): msg = channel.channel_messages[i - 1].message_details() ch_messages['messages'].append(msg) end = -1 else: # Only loads the first 50 messages if there are more than 50 messages in the channel for i in range(start + 50, start, -1): msg = channel.channel_messages[i - 1].message_details() ch_messages['messages'].append(msg) end = start + 50 # Updates the start and end value which needs to be returned ch_messages['start'] = start ch_messages['end'] = end return ch_messages
def message_send(token, channel_id, message): #Send a message from authorised_user to the channel specified by channel_id with open('data_store.json', 'r') as FILE: database = json.load(FILE) #Check if lenght of string is <1000 if len(message) > 1000: raise InputError(description='Message length greater than 1000.') email = find_token(token) for user in database["users"]: if user["email"] == email: for channel in database["channels"]: if channel["channel_id"] == channel_id: for member in channel["members"]: if member == user["u_id"]: timestamp = datetime.now().timestamp() message_id = uuid.uuid4().int text = { "message_id": message_id, "u_id": user["u_id"], "message": message, "time_created": timestamp, "reacts": [], "is_pinned": False } channel["messages"].append(text) with open('data_store.json', 'w') as FILE: json.dump(database, FILE) return {"message_id": message_id} raise AccessError( description='User is not a memmber of the channel') raise AccessError(description='Invalid token')
def channel_join(token, channel_id): """ Adds a user from a channel, User should have been authenticated and authorised to join the channel. Parameters: token (str): a unique token (to determine authorisation) channel_id(int): a unique id for such channel Returns: {} """ # Check that token is valid user_id = authenticate_token(token) user = valid_user_id(user_id) # Check that channel_id is valid channel = valid_channel_id(channel_id) # Check that user is allowed to join if not channel.is_public and not user.permission_id == 1: raise AccessError("Channel is private, unable to join") # Check that the user is not in the channel yet if channel.existing_member(user): raise InputError(description="User is already a member.") # Adds user to the channel channel.new_member(user) # Promote to owner if user is flockr owner if user.permission_id == 1: channel.new_owner(user) return {}
def channels_create(token, name, is_public): #check len(name) is greater than 20 if len(name) > 20: raise InputError() #get unique channel_id channel_id = random.randint(1, 1000) for x in data['channels']: if channel_id == x['channel_id']: channel_id = random.randint(1000, 2000) # make channel new_channel = { 'channel_id': channel_id, 'name': name, 'is_public': is_public, 'all_members': [], 'owner_members': [], 'messages': [] } data['channels'].append(new_channel) ## add authorised user to list of channel owners # get user id from token u_id = data['tok_uid'][token] # get user dictionary user = get_user_info(u_id) new_i = len(data['channels']) - 1 data['channels'][new_i]['all_members'].append(user) data['channels'][new_i]['owner_members'].append(user) return {'channel_id': channel_id}
def user_profile(token, u_id): ''' For a valid user, returns information about their user id, email, first name, last name, handle, and image profile URL Parameters: token - The user's token that was generated from their user id u_id - The profile id number to be checked Returns: An dictionary containing all the users information Errors: InputError: Given a u_id for a non-existent user ''' check_token(token) data = get_data() # Finding the user for user in data['users']: if user['u_id'] == u_id: profile = { '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': user['profile_img_url'] } return { 'user': profile } # If u_id hasn't been found then it is obviously invalid raise InputError(description="Invalid u_id")
def channel_leave(token, channel_id): ''' Given a channel ID, the user removed as a member of this channel Input: token (str), channel_id (int) Output: empty dict ''' # Retrieve data auth_user = user_with_token(token) channel = channel_with_id(channel_id) # Error check if auth_user is None: raise AccessError('Invalid token') elif channel is None: raise InputError('Invalid channel_id') elif auth_user not in channel.get_all_members(): raise AccessError('Authorised user not a member of channel') # Remove user from all_members channel.get_all_members().remove(auth_user) # Attempt to remove user from owner_members if they are an owner if auth_user in channel.get_owner_members(): channel.get_owner_members().remove(auth_user) return { }
def standup_active(server_data, token, channel_id): """ standup_active A function that checks if a standup is currently active in channel Input: - (str) token - (int) channel_id Output: - {is_active, time_finish} """ # Check if the channel exists if not server_data.does_channel_exist(channel_id): raise InputError(description="Invalid channel") channel_obj = server_data.get_channel_by_id(channel_id) # Obtain session object from server_data session_obj = server_data.get_sessions_list() # Check if the token is active if not session_obj.is_token_active(token): raise AccessError(description="Invalid Token") return_info = { "is_active": channel_obj.is_standup_active, "time_finish": channel_obj.time_finish, } return return_info
def channels_create(server_data, token, name, is_public): """ channel_create function: A function that creates a channel in the server_data, if the token is valid. Returns a channel_id from the server_data function Inputs: - server_data (obj) - token (string) - name (string) - is_public (bool) Outputs - {channel_id} (dics) """ # Check if the token is active, and get u_id if the token is active # Get u_id from the active session u_id = verify_n_get_valid_token(server_data, token) # Get user object from the u_id user_obj = server_data.get_user_by_id(u_id) # Then get the user info containing {u_id, name_first, name_last} user_info = user_obj.get_user_member_info() # Now check if the name is longer than 20 characters if len(name) > 20: raise InputError(description="Channel name too long") # Everything checks out, create channel in the database channel_id = server_data.create_channel(name, user_info, is_public) return {"channel_id": channel_id}
def channel_details(tokne, channels_id): auth_store = get_auth_data_store channel_store = get_channel_data_store is_valid_user_id(u_id) owner_members = [] all_members = [] # Check if channel exists using helper function channel = get_channel(channel_id) # InputError when we try to get details of an invalid channelID if channel is None: raise InputError(description='Invalid channel_id') # Get details of owners and members in the channel if u_id in channel['members']: name = channel['name'] for owners in channel['owner_members']: owner_members_details = user_details(owners) owner_members.append(owners_members_details) for members in channel['all_members']: all_members_details = user_details(members) all_members.append(all_members_details) return { "name": channel['name'], "owner_members": channel['owner_members'], "all_members": channel['all_members'] } # AccessError when authorised user is not a member of the channel else: raise AccessError( description='Authorised user is not a member of the channel')
def channels_create(token, name, is_public): '''Creates a channel and assigns first user as owner.''' # Opens database with open('data_store.json', 'r') as FILE: database = json.load(FILE) # Find email from token email = find_token(token) for user in database["users"]: if user["email"] == email: #Checks the length of channel name if len(name) > 20: raise InputError( description='Name cannot be over 20 characters long') # Generate channel_id that is 5 digits long, convert to string new_id = uuid.uuid4().int channel_id = str(new_id)[:5] # Create new channel new_channel = { "channel_id": channel_id, "name": name, "is_public": is_public, "members": [user["u_id"]], "owners": [user["u_id"]], "messages": [] } # Add channel to list of channels database["channels"].append(new_channel) with open('data_store.json', 'w') as FILE: json.dump(database, FILE) return {"channel_id": new_channel["channel_id"]} raise AccessError(description="Invalid token")
def build_string(payload): """ Returns a string for details of weather """ if payload['location']['name'] == "Weather": raise InputError('Location is not a real place') return f"""
def message_unreact_fn(token, message_id, react_id, MESSAGES, USERS, channel_list): message_index = int(message_id) - 1 react_index = int(react_id) - 1 position = int(position_in_user_data(token, USERS)) check_valid_react_id(react_id) check_valid_message_id(message_id, MESSAGES) is_user_in_channel_mid(position, USERS, channel_list, message_id, MESSAGES) check_if_deleted(message_id, MESSAGES) if USERS[position]['u_id'] not in MESSAGES[message_index]['reacts'][ react_index]['u_ids']: MESSAGES[message_index]['reacts'][react_index][ 'is_this_user_reacted'] = False raise InputError( description='No reaction to unreact for specified react_id') else: MESSAGES[message_index]['reacts'][react_index]['u_ids'].remove( USERS[position]['u_id']) MESSAGES[message_index]['reacts'][react_index][ 'is_this_user_reacted'] = False return dumps({})
def channel_leave(token, channel_id): # get user's u_id u_id = data['tok_uid'][token] # InputError: invalid channel ID if not is_valid_channel(channel_id): raise InputError('Channel ID does not refer to a valid channel') # AccessError: authorised user is not a member of the channel elif not is_channel_member(u_id, channel_id): raise AccessError('Authorised user is not a member of the channel') # no errors: user is removed from all_members and owner_members (if applicable) for channel in data['channels']: if channel['channel_id'] == channel_id: # find user dictionary for member in channel['all_members']: if member['u_id'] == u_id: # remove user dictionary from all_members channel['all_members'].remove(member) # if user is also owner, remove from owner_members if is_channel_owner(u_id, channel_id): for owner in channel['owner_members']: if owner['u_id'] == u_id: channel['owner_members'].remove(owner) return {}
def standup_start(token, channel_id, length): """ standup_start Args: token: authorises user channel_id: the target channel to initiate the standup in length: how long the standup will last (in seconds) Returns: time_finish: the time the startup will end and consequently send the start up messages into the message queue of the channel """ token_validator(token) channel_validator(channel_id) # Check if there is a standup currently running in the channel if standup_active(token, channel_id)['is_active']: raise InputError("There is already a standup currently active") # Start the standup period, for length (seconds) where messages using standup # will be sent to a standup_queue, then all added to the channel_messages by a # packed message sent by the creator of the standup when the standup finishes time_finish = get_timestamp(length) standup_start = threading.Thread(target=thread_standup, args=(token, channel_id, length)) standup_start.start() for channel in data['channels']: if channel['channel_id'] == channel_id: channel['time_finish'] = time_finish return { 'time_finish': time_finish }
def standup_active_fn(token, channel_id, channels, users, messages): #position_in_user will check if it is a valid token position_in_user_data(token, users) for channel in channels: #once we get to the time standup finish time we send message if (channel['standup'])['time_finish'] and \ (channel['standup'])['is_active'] and \ int(time.mktime(datetime.datetime.now().timetuple())) >= \ (channel['standup'])['time_finish']: time_now = datetime.datetime.now() #print(time_now) time_now = time_now.replace(tzinfo=timezone.utc).timestamp() new_message = create_message((channel['standup'])['start_member'], \ (channel['standup'])['message'], time_now, channel_id) messages.append(new_message) (channel['standup'])['start_member'] = None (channel['standup'])['is_active'] = False (channel['standup'])['message'] = [] (channel['standup'])['time_finish'] = None return {'is_active': False, 'time_finish': None} if not (channel['standup'])['is_active']: return {'is_active': False, 'time_finish': None} return { 'is_active': True, 'time_finish': (channel['standup'])['time_finish'] } raise InputError( description="Channel ID is not a valid channel, standup active")
def message_remove(token, message_id): """ Remove a message Parameters: token (str): The token of the active user message_id(int): The ID of the message to remove Returns: None """ # check whether the token is valid user_id = database.verify_token(token) if not user_id: raise AccessError(description='The token does not exist') #check whether the message exist channel = check_msg(message_id) if not channel: raise InputError(description='The message does not exist') #check whether the user have access to remove it access = check_access(user_id, channel, message_id) if not access: raise AccessError( description= 'The user doed not have permission to remove this message') #remove it remove(message_id, channel) return {}
def change_permission(token, u_id, permission_id): """ Change the permission of user with u_id Parameters: token (str): The token of the active user u_id(int): The user ID of the user to change permission_id (int): New permission ID Returns: channels (list): List of dictionaries, where each dictionary contains types { channel_id, name } """ DATA = getData() if permission_id != 1 and permission_id != 2: raise InputError("Invalid permission ID") owner_flag = False user_to_change = None for users in DATA['users']: if users['u_id'] == u_id: user_to_change = users if users['u_id'] == verify_token(token): if users['permission_id'] == 1: owner_flag = True if not owner_flag: raise AccessError("Authorised user not an owner") user_to_change['permission_id'] = permission_id update_database(DATA) return {}
def channel_removeowner(server_data, token, channel_id, u_id): """ Remove user with user u_id from an owner of this channel Input: - server_data(obj) - token (string) - channel_id (int) - u_id (int) Output: - {} """ # Check if the channel exists verify_channel_id(server_data, channel_id) channel_obj = server_data.get_channel_by_id(channel_id) # Verify the token and get u_id from the active token u_id_owner = verify_n_get_valid_token(server_data, token) user_obj_owner = server_data.get_user_by_id(u_id_owner) # Verify if the u_id_owner is a owner of the channel or owner of slacker verify_user_channel_status(server_data, channel_id, u_id_owner, const.PERMISSION_LOCAL_OWNER) if channel_obj.is_user_owner(u_id): channel_obj.remove_owner(u_id) else: # user is not an owner of the channel raise InputError(description="User is not an owner of the channel") return {}
def remove_users(token, u_id): """ Remove a user with u_id from Slackr Parameters: token (str): The token of the active user u_id(int):user ID of the user to remove Returns: None """ DATA = getData() owner_flag = False user_to_change = None for users in DATA['users']: if users['u_id'] == u_id: user_to_change = users if users['u_id'] == verify_token(token): if users['permission_id'] == 1: owner_flag = True if not owner_flag: raise AccessError("Authorised user not an owner") if not user_to_change: raise InputError("User ID does not refer to valid user") DATA['users'].remove(user_to_change) update_database(DATA) return {}
def request(payload): # pylint disable=R1771 ''' Function to request a reset code ''' reset_store = get_reset_code_store() send_to_email = test_email(payload['email']) email_match = 0 # if found = 1 user = get_user_from('email', send_to_email) # pylint: disable=W0612 email_match = 1 reset_code = id_generator() code_password = { 'email': send_to_email, 'reset_code': reset_code, } server = smtplib.SMTP_SSL('smtp.gmail.com', 465) server.login(EMAIL, PASSWORD) server.sendmail( EMAIL, send_to_email, reset_code) server.quit() if email_match == 0: raise InputError(description="Email entered does not belong to a user") reset_store.append(code_password)
def channels_listall(token): """ Lists all the channels that exist. Paramaters: token (str): A string that validates the users actions while they are logged in. Returns: { channels: [] }: A list of all the channel dicitionaries. """ # raise InputError if inputed data is the wrong type if not isinstance(token, str): raise AccessError("Invalid token") # raise InputError if any of the inputs is empty if token == '': raise InputError("Invalid input") # check that token is authorised authenticate_token(token) return_list = [] for channel in data.channels: return_list.append({'channel_id': channel.channel_id, 'name': channel.name}) return { 'channels' : return_list }