def auth_login_v2(email, password): """Summary Given a registered user's email and password, returns a new session token and their user id Args: email (string): An email address password (string): A password Returns: Dictionary: Contains the user's token and user id Raises: InputError: When an invalid email is given, the given password is incorrect, or the email entered does not match any registered user's email """ global tokens if not valid_email(email): raise InputError(f"Email {email} is not a valid email") for user in users: if user['email'] == email and user[ 'permission'] != 0: # Check for email match to valid, non-removed user if user['password'] == get_hash( password ): # Compare stored password hash to hashed password input auth_user_id = user['u_id'] token = generate_token(auth_user_id) return {'token': token, 'auth_user_id': auth_user_id} else: raise InputError(f"Password {password} is not correct") raise InputError(f"Email {email} does not belong to a user.")
def message_sendlater(token, channel_id, message, time_sent): ''' sends a message at a given time_sent, where time_sent is a unix timestamp greater than the current time. ''' u_id = check_token(token) if not is_valid_channel(channel_id): raise InputError(description="No channel exists with that ID") if not is_user_a_member(channel_id, u_id): raise AccessError(description='You are not a member of this channel') if len(message) > 1000 or len(message) < 1: raise InputError( description= 'Your message should be less than 1000 characters and at least 1 character' ) curr_time = get_current_timestamp() if curr_time >= time_sent: raise InputError(description="You can not send a message back in time") delay = time_sent - curr_time message_id = get_num_messages() set_num_messages(message_id + 1) message_template = create_message(u_id, message_id, time_sent, message) timer = Timer(delay, sendlater_end, args=[channel_id, message_template]) timer.start() return {'message_id': message_id}
def user_profile_sethandle_v1(token, handle_str): # token check if check_token_valid(token) is False: raise AccessError("Invalid Token") handle = ''.join(handle_str.split()) handle = handle.replace("@","") handle = handle.lower() with open('src/data.json', 'r') as FILE: data = json.load(FILE) for i in range(len(data['users'])): if data['users'][i]['handle'] == handle: raise InputError("Handle already in use") for j in range(len(data['users'])): if data['users'][j]['token'] == token: if len(handle) < 3 or len(handle) > 20: raise InputError("Invalid handle") data['users'][j]['handle'] = handle with open('src/data.json', 'w') as FILE: json.dump(data,FILE, indent = 4) return { }
def auth_passwordreset_reset_v1(reset_code, new_password): with open('src/data.json', 'r') as FILE: data = json.load(FILE) # check for valid code valid = False for i in range(len(data["reset_codes"])): if data["reset_codes"][i]["reset_code"] == reset_code: email = data["reset_codes"][i]["email"] valid = True if valid == False: raise InputError("Invalid code") # checks if password is less than 6 characters if len(new_password) < 6: raise InputError("Password too short") # encode new password and set it new_password = hashlib.sha256(new_password.encode()).hexdigest() for i in range(len(data["users"])): if data['users'][i]['email'] == email: data['users'][i]['password'] = new_password # remove reset code from data once it has been used for i in range(len(data["reset_codes"])): if data["reset_codes"][i]["reset_code"] == reset_code: del data["reset_codes"][i] with open('src/data.json', 'w') as FILE: json.dump(data, FILE, indent=4) return {}
def errorcheck_user_profile_setemail_v2(token, email): if check_valid_email(email) == None: raise InputError(description="Email is invalid") if is_existing_email(email) == True: raise InputError( description="Email is already being used by another user")
def auth_passwordreset_reset_v1(reset_code, new_password): ''' Summary: Given a reset code for a user, set that user's new password to the password provided Args: reset_code (string): A string of numbers and captial letters password (string): The password that the user wants to change theirs to Returns: empty dictionary Raises: InputError when: reset_code is not a valid reset code Password entered is less than 6 characters long ''' global users, reset_codes if len(new_password) < 6: raise InputError("Password entered is less than 6 characters long") for code_data in list( reset_codes ): #ask team i delete the code after because we dont need it anymore i need list() here right if code_data['code'] == reset_code: for user in users: if code_data['u_id'] == user[ 'u_id']: #i can add email here as well to double check, u_id i unique though,should be fine user['password'] = get_hash(new_password) reset_codes.remove( code_data ) #delete after because dont need anymore? added list() here right return {} # If loop exits without returning, code is invalid raise InputError("reset_code is not a valid reset code")
def admin_userpermission_change_v1(token, u_id, permission_id): """Summary Enables a Dreams owner to change the permissions of another user between Dreams owner (1) and standard user (2). Args: token (string): User session token u_id (integer): User id number permission_id (integer): Either 1, indicating Dreams owner, or 2, indicating standard user Returns: Empty dictionary Raises: AccessError: When an invalid token value is given, or when the user associated with the token is not a Dreams owner InputError: When permission_id does not refer to a valid permission, or u_id does not refer to a valid user """ check_token(token) # Check for invalid token if user_from_token(token)['permission'] != 1: raise AccessError("Authorised user is not an owner.") if not 1 <= permission_id <= 2: # Check for invalid permission_id raise InputError("permission_id does not refer to a valid permission.") # Search for user with user id u_id and change their permission if found for user in users: if user['u_id'] == u_id: user['permission'] = permission_id return {} raise InputError("u_id does not refer to a valid user.")
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 message_pin(token, message_id): ''' Pins a message in a channel ''' u_id = check_token(token) channel_specific = get_channel_by_msg_id(message_id) message_specific = get_message_by_msg_id(message_id) if u_id not in channel_specific['members'] and not is_channel_owner( token, channel_specific): raise AccessError( description= 'The authorised user is not a member of the channel that the message is within' ) if not is_channel_owner(token, channel_specific): raise InputError(description='The authorised user is not an owner') if message_specific['is_pinned']: raise InputError( description='Message with ID message_id is already pinned') if is_channel_owner(token, channel_specific ) is True and message_specific['is_pinned'] is False: message_specific['is_pinned'] = True return {}
def admin_userpermission_change_v1(token, u_id, permission_id): # token check if check_token_valid(token) is False: raise AccessError("Invalid Token") if permission_id is not 1 and permission_id is not 2: raise InputError("Invalid permission_id") if not check_user_exists(u_id): raise InputError("invalid u_id") with open('src/data.json', 'r') as FILE: data = json.load(FILE) owner = False owner_id = convert_token(token) if data['users'][owner_id]['permission_id'] == 1: owner = True if owner == True: for i in range(len(data['users'])): if u_id == data['users'][i]['u_id']: data['users'][i]['permission_id'] = permission_id else: raise AccessError("Unauthorised user, user is not an owner") with open ('src/data.json', 'w') as FILE: json.dump(data, FILE, indent = 4) return { }
def user_profile_setname_v2(token, name_first, name_last): """ Given valid token and first/last names, changes a registered users name Arguments: token (string) - valid token associated with a registered user's session name_first (string) - first name the user wants to update to name_last (string) - last name the user wants to update to Exceptions: InputError - When either name_first or name_last is not between 1 and 50 characters, inclusive AccessError - Occurs if token is invalid Return value: {} """ #Retrieving data from export.json data = getData() #Testing for a valid token and finding the associated u_id u_id = findUser(token) #Checking if the names are of valid length if len(name_first) > 50 or len(name_first) < 1: raise InputError(description="Length of first name is not valid") elif len(name_last) > 50 or len(name_last) < 1: raise InputError(description="Length of last name is not valid") #Finding the user and changing their names for user in data['users']: if u_id == user['u_id']: user['name_first'] = name_first user['name_last'] = name_last #Writing data to export.json writeData(data) return {}
def errorcheck_removeowner_v1(token, channel_id, u_id): # assumes the user must be in the channel before being added as an owner # if not, raise an input error data_structure = token_check(token) if is_valid_u_id(u_id) == False: raise InputError("Invalid u_id") if is_valid_channel_id(channel_id) == False: raise InputError("Invalid channel_id") if is_user_channel_membertype(channel_id, u_id, CHANNEL_MEMBER) == False: raise InputError( "user with user id u_id is not already a member of the channel") if is_user_channel_membertype(channel_id, u_id, CHANNEL_OWNER) == False: raise InputError( "user with user id u_id is not already a channel owner") if is_user_channel_membertype( channel_id, int(data_structure["u_id"]), CHANNEL_OWNER) == False and find_auth_user_permission_id( int(data_structure["u_id"])) == 2: raise AccessError( "auth_user is not an owner of the channel or an owner of **Dreams**" ) if is_user_only_owner(channel_id) == True: raise InputError("user to be removed is the only owner in the channel")
def user_profile_setname_v1(token, name_first, name_last): if check_token_valid(token) is False: raise AccessError("Invalid Token") # checks if first and last names are between 1-50 characters long if len(name_first) < 1 or len(name_first) > 50: raise InputError("Name must be between 1-50 characters") if len(name_last) < 1 or len(name_last) > 50: raise InputError("Name must be between 1-50 characters") with open('src/data.json', 'r') as FILE: data = json.load(FILE) for i in range(len(data['users'])): if data['users'][i]['token'] == token: data['users'][i]['name_first'] = name_first data['users'][i]['name_last'] = name_last with open('src/data.json', 'w') as FILE: json.dump(data,FILE, indent = 4) return { }
def user_profile_uploadphoto_v1(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. Arguments: token (string) - valid token associated with a registered user's session img_url (string) - URl to a jpg online x_start (int) - indicates leftmost point on image y_start (int) - indicates topmost point on image x_end (int) - indicates righttmost point on image y_end (int) - indicates bottommost point on image Exceptions: InputError - img_url returns an HTTP status other than 200. InputError - any of x_start, y_start, x_end, y_end are not within the dimensions of the image at the URL. InputError - Image uploaded is not a JPG Return value: { } """ #Retrieving data from dictionary data = getData() #Find user id from their token u_id = findUser(token) #Define URL URL = f'{img_url}' #Define file path fileName = f'src/static/{u_id}.jpg' #Trying to open URL, if it fails raise an InputError try: status = requests.get(URL).status_code except: status = -1 if status != 200: raise InputError(description='Invalid URL') #Raising an error if the URL does not point to a jpg if not URL.endswith('.jpg'): raise InputError(description='Image is not a jpg') #Retrieve the URL abd save the image as fileName urllib.request.urlretrieve(URL, fileName) #Open the image img = Image.open(fileName) #Define the size of the image width, height = img.size #Raising an error if the crop points aren't valid if x_start < 0 or y_start < 0 or x_end > width or y_end > height or x_end < x_start or y_end < y_start: raise InputError(description='Crop start or end points not valid') #Cropping and saving the image crop_img = img.crop((x_start, y_start, x_end, y_end)) crop_img.save(fileName) #Changin the user's associated URL to the new image for user in data['users']: if u_id == user['u_id']: user['profile_img_url'] = f'{config.url}/images/{u_id}.jpg' #Writing data to dictionary writeData(data) return {}
def dm_invite_v1(token, dm_id, u_id): with open('src/data.json', 'r') as FILE: data = json.load(FILE) inviteid = None # check that token is valid for i in range(len(data['users'])): if data['users'][i]['token'] == token: inviteid = data["users"][i]["u_id"] if inviteid is None: raise AccessError("Invalid token") # check if the dm_id exists if check_dm_exists(dm_id) == False: raise InputError("Invalid dm") # check if the u_id is valid if check_user_exists(u_id) == False: raise InputError("Invalid User") # checking if the person inviting is in the dm if check_user_in_dm(inviteid, dm_id) == False: raise AccessError("Authorised user needs to be a member of the dm") # checking if the person being invited is already in the dm if check_user_in_dm(u_id, dm_id) == True: raise InputError("User already a member of this dm") new_user = { 'u_id': u_id, 'email': data["users"][u_id]["email"], 'name_first': data["users"][u_id]["name_first"], 'name_last': data["users"][u_id]["name_last"], 'handle': data["users"][u_id]["handle"] } memberslist = data["dms"][dm_id]["name"].split(", ") memberslist.append(data["users"][u_id]["handle"]) sortedlist = sorted(memberslist, key=str.lower) final_list = ", ".join(sortedlist) #name = data["dms"][dm_id]["name"] + ", " + data["users"][u_id]["handle"] data["dms"][dm_id]["members"].append(new_user) data["dms"][dm_id]["name"] = final_list num_dms_joined = data["user_stats"][u_id]["stats"]["dms_joined"][-1][ "num_dms_joined"] + 1 dms_joined = { "num_dms_joined": num_dms_joined, "time_stamp": create_timestamp() } data["user_stats"][u_id]["stats"]["dms_joined"].append(dms_joined) with open('src/data.json', 'w') as FILE: json.dump(data, FILE, indent=4) notif_msg = data["users"][inviteid][ "handle"] + " added you to dm " + final_list create_notifications(u_id, -1, dm_id, notif_msg) calc_involement_rate(u_id) calc_utilisation_rate() return {}
def message_unreact_v1(token, message_id, react_id): ''' Arguments: token (string) - the token of the user who wants to create a channel message_id - the id of the message being reacted to react_id (int) - the id of the react Exceptions: InputError - message_id is not a valid message within a channel or DM that the authorised user has joined InputError - react_id is not a valid React ID. The only valid react ID the frontend has is 1 InputError - Message with ID message_id does not contain an active React with ID react_id from the authorised user AccessError - The authorised user is not a member of the channel or DM that the message is within Return value: Returns {} ''' # get data data = getData() # get id auth_user_id = findUser(token) # Gets message msg = get_message(message_id, data) # Message does not exist (has been removed or invalid message_id passed in) if msg == -1: raise InputError("Message is not a valid.") # Gets message key msg_key = data['messages'].index(msg) # Gets list of dictionary containing all the reacts for that message react_list = data['messages'][msg_key]['reacts'] # Checks react id is valid and in use already if react_id != 1: raise InputError("React ID is not valid.") elif not has_user_reacted(auth_user_id, react_id, react_list, data): raise InputError("User has not already reacted with this react.") # Checks the user is part of the channel/dm check_user_permissions(data, msg_key, auth_user_id) # Remove/update react react_key = get_react(react_id, react_list, msg_key, data) data['messages'][msg_key]['reacts'][react_key]['u_ids'].remove( auth_user_id) if data['messages'][msg_key]['reacts'][react_key]['u_ids'] == []: data['messages'][msg_key]['reacts'].remove({ 'react_id': react_id, 'u_ids': [] }) writeData(data) return {}
def channel_addowner_v1(token, channel_id, u_id): with open('src/data.json', 'r') as FILE: data = json.load(FILE) # check that token is valid user_id = None for i in range(len(data['users'])): if data['users'][i]['token'] == token: user_id = data['users'][i]['u_id'] if user_id is None: raise AccessError("Invalid token") # check if the channel_id exists if check_channel_exists(channel_id) == False: raise InputError("Invalid channel") # check if the user is already an owner of the channel for i in range(len(data["channels"][channel_id]["owner_members"])): if data["channels"][channel_id]["owner_members"][i]["u_id"] == u_id: raise InputError("User already an owner") # check if u_id belongs to an existing member of the channel if check_user_in_channel(u_id, channel_id) == False: raise InputError( "User must be a member of the channel to become owner") dreamsowner = False channelowner = False # confirm if token belongs to a dream owner if data['users'][user_id]['permission_id'] == 1: dreamsowner = True # confirm if token belongs to an owner for i in range(len(data["channels"][channel_id]["owner_members"])): if data["channels"][channel_id]["owner_members"][i]["u_id"] == user_id: channelowner = True if dreamsowner or channelowner: # information of new owner to be added new_owner = { "u_id": u_id, 'email': data["users"][u_id]["email"], 'name_first': data["users"][u_id]["name_first"], 'name_last': data["users"][u_id]["name_last"], 'handle': data["users"][u_id]["handle"] } data["channels"][channel_id]["owner_members"].append(new_owner) else: raise AccessError("Unauthorised user, user is not an owner") with open('src/data.json', 'w') as FILE: json.dump(data, FILE, indent=4) notif_msg = data["users"][u_id][ "handle"] + " added you as owner in " + data["channels"][channel_id][ "name"] create_notifications(u_id, channel_id, -1, notif_msg) return {}
def errorcheck_user_profile_setname_v2(token, name_first, name_last): if is_name_within_str_length(name_first) == False: raise InputError( description="First name is outside of range 1 - 50 chars") if is_name_within_str_length(name_last) == False: raise InputError( description="Last name is outside of range 1 - 50 chars") if name_first == "Removed" and name_last == "user": raise InputError(description="Illegal name change")
def message_edit_v2(token, message_id, message): """Summary Given a message, update its text with new text. If the new message is an empty string, the message is deleted. Args: token (string): A user session token message_id (int): A message id number message (string): The text with which the user wishes to replace the current message Returns: Empty dictionary Raises: AccessError: When an invalid token is given, or the user attempts to delete a message that they did not write, or one in a channel that they do not own, and they are not a dreams owner InputError: If the message is not a string, is longer than 1000 characters, or message_id does not refer to a valid message """ global messages check_token(token) auth_user = user_from_token(token) if type(message) != str: raise InputError(f"Message {message} is not of type string") if len(message) > 1000: raise InputError( f"Length of message is over 1000 characters (length is {len(message)})" ) for msg in messages: if msg['message_id'] == message_id: can_edit = False if auth_user['u_id'] == msg['author_id'] or is_dreams_owner( auth_user['u_id']): # If the user is the author of the message or a dreams owner, they can always edit it can_edit = True elif msg['channel_id'] != -1 and is_channel_owner( auth_user['u_id'], msg['channel_id']): # If the message was sent to a channel and the user is the channel owner can_edit = True if can_edit: if not len( message ): # If the new message text is blank, delete the message message_remove_v1(token, message_id) else: # Replace the current message text with the new text msg['message'] = message return {} raise AccessError( f"User {auth_user['handle_str']} does not have permission to edit message with id {message_id}" ) raise InputError( f"Message with id {message_id} does not exist (it may have been deleted)" )
def admin_userpermission_change_v1(token, u_id, permission_id): """ Given a User by their user ID, set their permissions to new permissions described by permission_id. Arguments: token (str) - token passed in to the function u_id (int) - id of user to change permission of permission_id (int) - new permission id Exceptions: AccessError - when token passed in is not a valid id InputError - when u_id does not refer to a valid user InputError - when permission_id does not refer to a valid permission AccessError - when authorised user is not an owner Return value: {} """ data_store = getData() # Check for exceptions # validate token auth_user_id = findUser(token) # check if u_id is a valid user, and also get index of position if valid valid = False for user_index, user in enumerate(data_store["users"]): if user["u_id"] == u_id: valid = True break if not valid: raise InputError(description="u_id does not refer to a valid user") # Check permission_id is valid if permission_id != 1 and permission_id != 2: raise InputError(description="Invalid permission_id") # Check if authorised user is an owner (with permission 1) for user in data_store["users"]: if user["u_id"] == auth_user_id: if user["permission_id"] != 1: raise AccessError(description="Authorised user is not an owner.") # Cannot change permission to permission_id 2 if there is only one # owner remaining in Dreams if permission_id == 2: if get_dream_owners_count(data_store) > 1: data_store["users"][user_index]["permission_id"] = permission_id else: data_store["users"][user_index]["permission_id"] = permission_id writeData(data_store) return {}
def search_v2(token, query_str): """ Given a query string, return a collection of messages in all the channels/DMs that the authorised user has joined that match the query Arguments: token (string) - token of authenticated user query_str (string) - string to be searched for Exceptions: InputError - Occurs when query_str is above 1000 characters - Occurs when query_str is empty AccessError - Occurs when token is invalid Return value: { messages - List of dictionaries, where each dictionary contains types: {message_id, u_id, message, time_created} } """ # Check validity of token findUser(token) # Check query_str is less than 1000 characters or not empty if len(query_str) > 1000: raise InputError(description="query string can't be over 1000 characters") if len(query_str) == 0: raise InputError(description="query string can't be empty") # Define messages return type message_dict = { "messages" : [] } # Go through channels u_channels_list = channels_list_v2(token)["channels"] for channel in u_channels_list: msgs = channel_messages_v2(token, channel["channel_id"], 0) look_for_message(query_str, msgs, message_dict) while msgs["end"] != -1: msgs = channel_messages_v2(token, channel["channel_id"], msgs["end"]) look_for_message(query_str, msgs, message_dict) # Go through dms u_dms_list = dm_list_v1(token)["dms"] for dm in u_dms_list: msgs = dm_messages_v1(token, dm["dm_id"], 0) look_for_message(query_str, msgs, message_dict) while msgs["end"] != -1: msgs = dm_messages_v1(token, dm["dm_id"], msgs["end"]) look_for_message(query_str, msgs, message_dict) return message_dict
def standup_start_v1(token, channel_id, length): ''' Summary: For a given channel, start the standup period whereby for the next "length" seconds if someone calls "standup_send" with a message, it is buffered during the X second window then at the end of the X second window a message will be added to the message queue in the channel from the user who started the standup. X is an integer that denotes the number of seconds that the standup occurs for Args: token (string): A user session token channel_id (int): A channel_id number length (int): A length of how long the standup runs Returns: dictionary which contains the time_finished Raises: InputError when: Channel ID is not a valid channel An active standup is currently running in this channel AccessError when: Authorised user is not in the channel ''' global channels check_token(token) if valid_channel(channel_id) == False: raise InputError(f'Channel ID {channel_id} is not a valid channel') auth_user_id = user_from_token(token)['u_id'] if is_channel_member(auth_user_id, channel_id) == False: raise AccessError(f'Authorised user is not in the channel') current_channel = find_channel(channel_id) if current_channel['standup']['is_active'] == True: raise InputError( f'An active standup is currently running in this channel') standup_period_finish = datetime.now( timezone.utc) + timedelta(seconds=length) timestamp = standup_period_finish.replace(tzinfo=timezone.utc).timestamp() # what will i add to the message here #dummy = '' #message_id = message_sendlater_v1(token, channel_id, dummy, timestamp) #message id here or standup send #standup_info = {} #create the standup dicitonary in channel create current_channel['standup']['is_active'] = True current_channel['standup']['creator'] = auth_user_id current_channel['standup']['messages'] = [] current_channel['standup']['time_finish'] = timestamp #current_channel['standup'] = standup_info return {'time_finish': timestamp}
def errorcheck_user_profile_sethandle_v1(token, handle_str): if is_handle_str_str(handle_str) == False: raise InputError(description="handle_str is not a string") if is_within_str_length(handle_str) == False: raise InputError( description= "handle_str is not between 3 and 20 characters inclusive") if is_handle_exists(handle_str) == True: raise InputError(description="handle is already used by another user")
def channel_removeowner_v1(token, channel_id, u_id): with open('src/data.json', 'r') as FILE: data = json.load(FILE) # check that token is valid removeid = None for i in range(len(data['users'])): if data['users'][i]['token'] == token: removeid = data['users'][i]['u_id'] if removeid is None: raise AccessError("Invalid token") # check if the channel_id exists if check_channel_exists(channel_id) == False: raise InputError("Invalid channel") ownercheck = False index = 0 # make sure person being removed is an existing owner for i in range(len(data["channels"][channel_id]["owner_members"])): if data["channels"][channel_id]["owner_members"][i]["u_id"] == u_id: ownercheck = True index = i if ownercheck is False: raise InputError("User not an owner") dreamsowner = False channelowner = False if len(data["channels"][channel_id]["owner_members"]) == 1 and len( data["channels"][channel_id]["all_members"]) == 1: raise AccessError("Last member can not remove themselves as an owner") # check person trying to remove owner is a dreams owner if data['users'][removeid]['permission_id'] == 1: dreamsowner = True # check person trying to remove owner is a channel owner for i in range(len(data["channels"][channel_id]["owner_members"])): if data["channels"][channel_id]["owner_members"][i][ "u_id"] == removeid: channelowner = True if dreamsowner or channelowner: del data["channels"][channel_id]["owner_members"][index] else: raise AccessError("Unauthorised user, user is not an owner") with open('src/data.json', 'w') as FILE: json.dump(data, FILE, indent=4) notif_msg = data["users"][removeid][ "handle"] + " removed you as owner in " + data["channels"][channel_id][ "name"] create_notifications(u_id, channel_id, -1, notif_msg) return {}
def standup_send_v1(token, channel_id, message): ''' Starts a standup in a channel for 'length' seconds. Arguments: token (string) - token of user starting standup channel_id (integer) - id of channel standup is in message (string) - buffered message that is sent to standup Exceptions: InputError - Occurs when channel_id does not refer to a valid channel - Occurs when the message is over 1000 characters in length (excluding the name of the user) - Occurs when there is no active standup in the channel AccessError - Occurs when the token passed in is not valid - Occurs when the authorised user is not already a member of the channel Return Value: Returns {} ''' # exception checks with open('src/data.json', 'r') as FILE: data = json.load(FILE) u_id = None for i in range(len(data['users'])): if data['users'][i]['token'] == token: u_id = data['users'][i]['u_id'] if u_id is None: raise AccessError("Invalid token") if check_channel_exists(channel_id) == False: raise InputError("Invalid channel") if check_user_in_channel(u_id, channel_id) == False: raise AccessError("Authorised user is not part of the channel") if len(message) > 1000: raise InputError("Message is longer than the 1000 character limit") standupActive = standup_active_v1(token, channel_id) if standupActive['is_active'] == False: raise InputError("No active standup running in this channel") with open('src/data.json', 'r') as FILE: data = json.load(FILE) for i in range(len(data['users'])): if data["users"][i]['token'] == token: firstName = data["users"][i]['name_first'] new_message = {'name': firstName, 'message': message} for i in range(len(data["standups"])): if data["standups"][i]["channel_id"] == channel_id: data["standups"][i]["messages"].append(new_message) return {}
def standup_start_v1(user_token, channel_id, length): """The function start a standup and will last for some seconds. All the message sent in that time period will be buffered and send together afer that. Args: user_token (string): a token string used to authorise and get the user id channel_id (int): the channel id where the standup starts length (int): the number of seconds Raises: InputError: channel id invalid InputError: standup already starts AccessError: user not in the Returns: dictionary: {'time_finish': time_finish} """ database = getData() auth_user_id = findUser(user_token) if is_channel_valid(database, channel_id) == False: raise InputError(description="Channel id is not valid") index = get_channel_index(database, channel_id) channel = database['channels'][index] if channel['standup']['is_active'] == True: raise InputError(description="Standup is already active") if is_user_in_channel(auth_user_id, channel) == False: raise AccessError(description="You are no in the channel") time_finish = (datetime.datetime.now()+datetime.timedelta(seconds=length)).strftime("%Y-%m-%d %H:%M:%S") time_finish = time.strptime(time_finish, "%Y-%m-%d %H:%M:%S") time_finish = time.mktime(time_finish) standup_length = length database['channels'][index]['standup']['is_active'] = True database['channels'][index]['standup']['standup_length'] = standup_length database['channels'][index]['standup']['time_finish'] = time_finish database['channels'][index]['standup']['messages'] = "" with open(file_address, "w") as f: json.dump(database, f) new_thread = threading.Timer(length, standup_package, args=[index, user_token, channel_id, time_finish]) new_thread.start() return {'time_finish': time_finish}
def message_edit_v2(token, message_id, message): with open('src/data.json', 'r') as FILE: data = json.load(FILE) editorid = None for i in range(len(data['users'])): if data['users'][i]['token'] == token: editorid = data["users"][i]["u_id"] if editorid is None: raise AccessError("Invalid token") if len(message) > 1000: raise InputError("Message is longer than the 1000 character limit") # check to see if message exists if check_message_exists(message_id) == False: raise InputError("Message does not exist") # check to see if message is being edited by authorised user valid = True if check_message_sent_by_user(editorid, message_id) == False: valid = False # check to see if token belongs to the owner of channel being deleted for i in range(len(data["messages"])): if data["messages"][i]["message_id"] == message_id: channel_id = data["messages"][i]["channel_id"] if channel_id is not -1: for i in range(len(data["messages"])): if data["messages"][i]["message_id"] == message_id: channel_id = data["messages"][i]["channel_id"] for i in range(len(data["channels"][channel_id]["owner_members"])): if data["channels"][channel_id]["owner_members"][i][ "u_id"] == editorid: valid = True if valid == False: raise AccessError( "Authorised User is not the owner of this channel and did not send this message" ) else: if valid == False: raise AccessError( "Authorised User is not the owner of this dm and did not send this message" ) with open('src/data.json') as FILE: data2 = json.load(FILE) for i in range(len(data2["messages"]) - 1): if data2["messages"][i]["message_id"] == message_id: if message is '': del data2["messages"][i] else: data2["messages"][i]["message"] = message with open('src/data.json', 'w') as FILE: json.dump(data2, FILE, indent=4) return {}
def standup_send_v1(user_token, channel_id, message): """get the messages that will be buffered Args: user_token (string): a token string used to authorise and get the user id channel_id (int): the channel id where the standup starts message (string): the message Raises: InputError: channel id invalid InputError: message too long InputError: standup not started yet AccessError: user not in the channel Returns: dic: {} """ database = getData() auth_user_id = findUser(user_token) if is_channel_valid(database, channel_id) == False: raise InputError(description="Channel id is not valid") if len(message) > 1000: raise InputError(description="Too much charecters in message") index = get_channel_index(database, channel_id) channel = database['channels'][index] if channel['standup']['is_active'] == False: raise InputError(description="The channel does not have an active standup") if is_user_in_channel(auth_user_id, channel) == False: raise AccessError(description="You are no in the channel") user = use_id_to_find_user(auth_user_id) original_msg = database['channels'][index]['standup']['messages'] if original_msg == "": original_msg = user['handle_str'] + ": " + message else: original_msg = original_msg + "\n" + user['handle_str'] + ": " + message database['channels'][index]['standup']['messages'] = original_msg with open(file_address, "w") as f: json.dump(database, f) return {}
def standup_start_v1(token, channel_id, length): with open("data.json") as json_file: data = load(json_file) auth_user_id = token_check(token)["u_id"] is_channel_exist = False for channel_data in data["channels"]: if channel_data["channel_id"] == channel_id: channel = channel_data is_channel_exist = True if is_channel_exist is False: raise InputError("Channel ID is not a valid channel") is_standup_already_active = False for standup_data in data["standups"]: if standup_data["channel_id"] == channel_id: is_standup_already_active = True if is_standup_already_active is True: raise InputError( "An active standup is currently running in this channel") is_auth_user_member = False if auth_user_id in channel["all_members"]: is_auth_user_member = True if is_auth_user_member is False: raise AccessError("Authorised user is not in the channel") time_finish = time.time() + length data["standups"].append({ "channel_id": channel_id, "message": [], "time_finish": time_finish }) with open("data.json", "w") as json_file: dump(data, json_file, indent=4) t = threading.Timer(length, standup_close_v1, kwargs={ "token": token, "channel_id": channel_id, "u_id": auth_user_id }) t.start() return {"time_finish": time_finish}
def channels_create_v2(token, name, is_public): ''' Creates a new channel with that name that is either a public or private channel Returns type: { channel_id } Input Error: Name is more than 20 characters long ''' time_stamp = datetime.now().replace(microsecond=0).timestamp() with open("data.json") as json_file: data = load(json_file) # Decode token (u_id) if valid, otherwise raise AccessError user = token_check(token) # Raise error if channel name is > 20 characters # or if there is no name given if len(name) > 20: raise InputError("Channel name is more than 20 characters.") if len(name) == 0: raise InputError("No channel name has been entered.") # Ensure users sets channel to private or public if is_public not in (True, False): raise InputError("Channel privacy is undefined") # Makes the channel id in order from 1 as they are created channel_id = len(data["channels"]) + 1 # Store data in data.py channels user_stats_update(data, user["u_id"], stat_types.CH_JOIN, time_stamp) dreams_stats_update(data, stat_types.CH_CREATE, time_stamp) data["channels"].append( { 'channel_id': channel_id, 'name': name, 'owner_members': [user['u_id']], 'all_members': [user['u_id']], 'invites' : [], 'is_public': is_public, 'messages': [] } ) with open("data.json", "w") as json_file: dump(data, json_file, indent=4) return { 'channel_id': channel_id }