def message_react(token, message_id, react_id): global data global valid_tokens global channels try: u_id = decodeToken(token) #check if react_id is valid at the start if react_id != 1: raise ValueError("Invalid react ID!") message = getMessage(message_id) channel = getMessageChannel(message_id) isUserChan(u_id, channel) for react in message["reacts"]: for react_users in react[ "u_ids"]: #check that the user hasn't already reacted if react_users == u_id: raise ValueError( "User already has an active react for this message!") for react in message["reacts"]: if react["react_id"] == react_id: react["u_ids"].append(u_id) #add the reaction return {} message["reacts"].append({ "react_id": react_id, "u_ids": [u_id] }) # genereate the react and ass return {} except ValueError as e: raise e except AccessError as e: raise e
def admin_userpermission_change(token, u_id, permission_id): try: # Check if user is authenticated and get the requesting user ID from token granterID = decodeToken(token) # Check if the target uID format is valid if not u_id.isdigit(): raise ValueError("Invalid user ID!") # Check if the target permission ID is valid if int(permission_id) > 3 or int(permission_id) < 1: raise ValueError("Invalid permission id") # Find the requesting user permissions = getUser(granterID)['permission_id'] # Check if requesting user has permissions for the action if permissions < 3: setPermission(u_id, permission_id) return {} raise AccessError("Granter is not an admin or owner") except ValueError as e: raise e except AccessError as e: raise e
def standup_send(token, channel_id, message): try: u_id = decodeToken(token) # Check length is OK if len(message) > 1000: raise ValueError("Length is too long") # Get user permissions for user in data: if user['u_id'] == u_id: permissions = user['permission_id'] name_first = user['name_first'] # Prepare a new message newMessage = name_first + ': ' + message + ' ' # Add the new message if allowed channel = getChannel(channel_id) for member in channel['all_members']: if member['u_id'] == u_id or permissions < 3: if channel['standup_status']: channel['standup_message'] += newMessage return {} raise ValueError("Standup not running!") raise AccessError("User is not an owner!") except ValueError as e: raise e except AccessError as e: raise e
def user_profiles_uploadphoto(token, img_url, x_start, y_start, x_end, y_end, port): auser_dic = get_user_from_token(token) if not helper_check_HTTPstatus(img_url): raise ValueError("img_url is returns an HTTP status other than 200.") # check whether exists this folder path = "static/images/" # if not exists path, then mkdir if not os.path.isdir(path): os.mkdir(path) filename = str(auser_dic['handle'] + ".jpg") urllib.request.urlretrieve(img_url, path+filename) if img_url.rsplit('.', 1)[1].lower() != "jpg" and img_url.rsplit('.', 1)[1].lower() != "jpeg": # the photo uploaded should be jpg raise ValueError("Image uploaded is not a JPG.") image = Image.open(path+filename) if not helper_check_validdimensions(path+filename, x_start, y_start, x_end, y_end): # x_start, y_start, x_end, y_end should be within the dimensions of the image raise ValueError("any of x_start, y_start, x_end, y_end are not within the dimensions of the image at the URL.") cropped = image.crop((x_start, y_start, x_end, y_end)) cropped.save(path+filename) auser_dic['profile_img_url'] = "http://localhost:" + str(port) + "/static/images/" + filename # update the user profile print(path + filename) return {}
def channels_create(token, name, is_public): check_tokenlogin(token) data = getdata() auser_dic = get_user_from_token(token) auid = auser_dic['u_id'] # check if the channel name valid if len(name) > 20: raise ValueError('channel name not valid') channel_id = -1 for channel in data['channels']: channel_id = channel['channel_id'] # channel id will be automaticlly updated with every creation channel_id = channel_id + 1 channel_dic = { 'channel_id': channel_id, 'name': name, 'is_public': is_public, 'standup_messages': '', 'standup_is_active': False, 'standup_time_finish': None, 'owner_members': [auid], 'all_members': [auid], # the one who created this channel will be the owner of the channel 'messages': [] } # channel will be added into the channels list after creation data['channels'].append(channel_dic) return {'channel_id': channel_id}
def message_pin(token, message_id): # 1. authorise user should be in the channel # 2. the message should be valid # 3. the message should be unpinned check_tokenlogin(token) auser_dic = get_user_from_token(token) auid = auser_dic['u_id'] m_c_dic = get_message_from_mid(message_id) check_validmessage(m_c_dic) message_dic = m_c_dic['message_dic'] channel_dic = m_c_dic['channel_dic'] #check if the authorise user is in the channel check_auser_not_in_channel(auid, channel_dic['all_members']) check_user_admin(auser_dic) # cannot pin the message which is pinned if message_dic['is_pinned']: raise ValueError("Message with ID message_id is already pinned.") message_dic['is_pinned'] = True return {}
def auth_passwordreset_request(email): try: # Check email is provided and is valid if email is None: raise ValueError("Invalid Email Format") if not re.search(regex, email): raise ValueError("Invalid Email Format") # Generate a reset code for the corresponding user u_id = getUserByEmail(email)['u_id'] resetReq(u_id) return {} except ValueError as e: raise e
def channel_addowner(token, channel_id, u_id): global channels try: # Get user information userID = decodeToken(token) users = getUser(int(u_id)) target = {'u_id':int(u_id), 'name_first':users['name_first'], 'name_last':users['name_last'], "profile_img_url": users['profile_img_url']} grantusers = getUser(userID) granter = {'u_id':userID, 'name_first':grantusers['name_first'], 'name_last':grantusers['name_last'], "profile_img_url": grantusers['profile_img_url']} permissions = grantusers['permission_id'] # Channel operations channel = getChannel(channel_id) if granter in channel['owner_members'] or permissions < 3: if target in channel['owner_members']: raise ValueError("User already an owner") elif target in channel['all_members']: channel['owner_members'].append(target) return {} else: channel['owner_members'].append(target) channel['all_members'].append(target) return {} raise AccessError("User is not an owner") except ValueError as e: raise e except AccessError as e: raise e
def channels_create(token, name, is_public): try: if len(name) > 20: raise ValueError("Name must be 20 characters or less.") # Get user information channel_id = len(channels) u_id = decodeToken(token) users = getUser(u_id) name_first = users['name_first'] name_last = users['name_last'] profile_img_url = users['profile_img_url'] owner_members = [{ "u_id": u_id, "name_first": name_first, "name_last": name_last, "profile_img_url": profile_img_url }] all_members = [{ "u_id": u_id, "name_first": name_first, "name_last": name_last, "profile_img_url": profile_img_url }] newChannel(channel_id, name, is_public, owner_members, all_members) return channel_id except ValueError as e: raise e except AccessError as e: raise e
def auth_login(email, password): password = str(encode({'password' : password})) check_validemail(email) user_dic = get_user_from_email(email) # if not find the email in the user, raise error if not user_dic: raise ValueError("Email entered does not belong to a user") # if find the user, and password correct if user_dic['password'] == password: user_dic['is_log_in'] = True return {'u_id': user_dic['u_id'], 'token': user_dic['token']} # if find the user, but password not correct raise ValueError("Password incorrect")
def auth_passwordreset_request(email): resetcode = generaterestcode() user_dic = get_user_from_email(email) if not user_dic: raise ValueError("Email not exists") user_dic.update({'resetCode': resetcode}) send_mail(resetcode, email) return {}
def get_args(arg_name, arg_type=str): parser = reqparse.RequestParser() parser.add_argument(arg_name, type=arg_type) args = parser.parse_args() arg = args.get(arg_name) if arg is None: raise ValueError("Miss args: %s" % arg_name) return arg
def user_profile_setemail(token, email): check_tokenlogin(token) users = getdata()['users'] auser_dic = get_user_from_token(token) check_validemail(email) # check if the email is valid for user in users: if user['email'] == email: raise ValueError("email has been used.") if auser_dic['email'] == email: raise ValueError('No new email entered') auser_dic['email'] = email return {}
def message_unpin(token, message_id): global data global valid_tokens global channels try: u_id = decodeToken(token) message = getMessage(message_id) channel = getMessageChannel(message_id) isUserChan(u_id, channel) #Will raise error if fails for members in data: if members["u_id"] == u_id: if int(members["permission_id"]) == 1 or int(members["permission_id"]) == 2: #check user is admin ############ ADMIN OR OWNER? if message["is_pinned"]: #check if pinned message["is_pinned"] = False return {} raise ValueError("Message is not pinned!") raise ValueError("User does not have permission to unpin!") except ValueError as e: raise e except AccessError as e: raise e
def auth_passwordreset_reset(reset_code, new_password): try: # Check new password is satisfactory if new_password is None: raise ValueError("New password is too short") if len(new_password) < 5: raise ValueError("New password is too short") # Check reset code is valid and reset for reset_dict in reset_codes: if reset_dict['reset_code'] == int(reset_code): u_id = reset_dict['u_id'] setPassword(u_id, new_password) resetRemove(reset_dict) return {} raise ValueError("Invalid code") except ValueError as e: raise e
def message_send(token, channel_id, message): global data global valid_tokens global channels try: u_id = decodeToken(token) channel = getChannel(channel_id) isUserChan(u_id, channel) #Will raise error if fails if len(message) > 1000: raise ValueError( "Message can not be greather than 1000 character limit") elif len(message) == 0: #this appears to be handled by front end... raise ValueError("Message can not be empty") else: return addMessage(channel, message, u_id) except ValueError as e: raise e except AccessError as e: raise e
def auth_register(email, password, name_first, name_last): #set up the initial value data = getdata() permission_ids_dic = get_permission_ids() owner = permission_ids_dic['Owner'] member = permission_ids_dic['Member'] uid = 0 # argument checking # check password check_validpassword(password) # check email check_validemail(email) # check firstname, lastname check_validname(name_first, name_last) # get a new u_id for new user, and check whether the email has been used for user in data['users']: uid = user['u_id'] if user['email'] == email: raise ValueError("email has been used.") uid = uid + 1 # if uid = 1, which means this is the first one to register the slackr # this user is the owner of slackr # else the user is just a member if uid == owner: permissionid = owner else: permissionid = member handle = creatHandle(name_first, name_last) userdic = { 'email': email, 'password': str(encode({'password': password})), 'u_id': uid, 'name_first': name_first, 'name_last': name_last, 'is_log_in': True, 'handle': handle, 'permission_id':permissionid, 'profile_img_url': None } token = generateToken(userdic) userdic.update({'token':token}) data['users'].append(userdic) return {'u_id': uid, 'token': token}
def user_profile_sethandle(token, handle_str): check_tokenlogin(token) auser_dic = get_user_from_token(token) check_validhandle(handle_str) # the handle should be valid if not handle_is_unique(handle_str): # this handle has been used raise ValueError('handle is already used by another user') auser_dic['handle'] = handle_str return {}
def auth_login(email, password): try: # Check email is provided and is valid if email is None: raise ValueError("Invalid Email Format") if not re.search(regex,email): raise ValueError("Invalid Email Format") # Hash the password hashPass = hashlib.sha256(password.encode()).hexdigest() # Find the user by email user = getUserByEmail(email) if user['password'] == hashPass: # Match their password token = addToken(user['u_id']) return {'u_id':user['u_id'], 'token': token} # Return them their new token raise ValueError("Password incorrect") except ValueError as e: raise e
def auth_passwordreset_reset(resetCode, newPassword): #verify if this user is the correct user then check the format of the new password #then update data data = getdata() check_validpassword(newPassword) newPassword = str(encode({'password': newPassword})) for user in data['users']: if user['resetCode'] == resetCode: user['password'] = newPassword return {} raise ValueError("not a vaild reset code")
def message_unreact(token, message_id, react_id): global channels try: u_id = decodeToken(token) #check if react_id is valid at the start if react_id != 1: raise ValueError("Invalid react ID!") channel = getMessageChannel(message_id) message = getMessage(message_id) isUserChan(u_id, channel) #Will raise error if fails for react in message["reacts"]: for react_users in react["u_ids"]: #check that the user hasn't already reacted if react_users == u_id: react["u_ids"].remove(u_id) return {} raise ValueError("User already has no active react for this message!") except ValueError as e: raise e except AccessError as e: raise e
def user_profile_setemail(token, email): global data try: u_id = decodeToken(token) #check if email is already in use for user in data: if user['email'] == email: raise ValueError("Email already in use") #check email is valid if not re.search(regex, email): raise ValueError("Invalid Email") # set email for user in data: if user['u_id'] == int(u_id): user['email'] = email return {} raise ValueError("Not a valid user") #technically impossible to reach except ValueError as e: raise e except AccessError as e: raise e
def user_profile_sethandle(token, handle_str): global data try: u_id = decodeToken(token) #check if handle is already in use for user in data: if user['handle'] == handle_str: raise ValueError("Handle already in use") #check handle is valid if (len(handle_str) < 3) or (len(handle_str) > 20): #inclusive? assumed to be inclusive raise ValueError("Handle must be between 3 and 20 characters") # make the change for user in data: if user['u_id'] == int(u_id): user['handle'] = handle_str return {} raise ValueError("Not a valid user") except ValueError as e: raise e except AccessError as e: raise e
def standup_start(token, channel_id, length): try: u_id = decodeToken(token) permissions = getUserPerm(u_id) channel = getChannel(channel_id) for owner in channel['owner_members']: if owner['u_id'] == u_id or permissions < 3: if not channel['standup_status']: time_finish = datetime.now(timezone.utc).timestamp() + length channel['standup_status'] = True channel['time_finish'] = time_finish return {"time_finish":time_finish} raise ValueError("Standup already running!") raise AccessError("User is not an owner!") except ValueError as e: raise e except AccessError as e: raise e
def channel_removeowner(token, channel_id, u_id): check_tokenlogin(token) channel_dic = get_channel_from_cid(channel_id) auser_dic = get_user_from_token(token) check_validchannel(channel_dic) check_auser_permission_of_channel(auser_dic, channel_dic) # only the owner can remove an owner, remove oneself is okay if u_id not in channel_dic['owner_members']: raise ValueError("The user with uid is not a owner of this channel") check_only_owner(channel_dic) # add uid to the owner of the channel channel_dic['owner_members'].remove(u_id) return {}
def channel_invite(token, channel_id, u_id): check_tokenlogin(token) channel_dic = get_channel_from_cid(channel_id) auser_dic = get_user_from_token(token) check_validchannel(channel_dic) members = channel_dic['all_members'] check_auser_not_in_channel(auser_dic['u_id'], members) uid_dic = get_user_from_uid(u_id) # add this user in the channel if this user is not a member of the channel check_validuid(uid_dic) if u_id in members: raise ValueError("the invited user already in channel") members.append(u_id) return {}
def channel_messages(token, channel_id, start): check_tokenlogin(token) #set up the initial value max = 50 returned_least_recent = -1 channel_dic = get_channel_from_cid(channel_id) auser_dic = get_user_from_token(token) check_validchannel(channel_dic) check_auser_not_in_channel(auser_dic['u_id'], channel_dic['all_members']) # check if the start is valid total_messages = len(channel_dic['messages']) return_messages = [] if total_messages == 0: return {'messages': return_messages, 'start': start, 'end': -1} if start > total_messages: raise ValueError( 'Start is greater than the total number of messages in the channel' ) counter = start end = start + max # get the messages between start and end # if end > total, just get the messages between start and last message while counter < end and counter < total_messages: return_messages.append(channel_dic['messages'][counter]) counter = counter + 1 # if this function has returned the least recent messages in the channel # returns -1 in "end" to indicate there are no more messages to load after this return. if start == total_messages: end = returned_least_recent # else return the counter of last message in the list of returned messages else: end = counter return {'messages': return_messages, 'start': start, 'end': end}
def channel_messages(token, channel_id, start): global channels try: u_id = decodeToken(token) # Channel operations channel = getChannel(channel_id) for users in channel['all_members']: if users['u_id'] == u_id or data[u_id]['permission_id'] < 3: if int(start) > len(channel['messages']): raise ValueError( "Start is greater than the number of messages") newMsg = channel[ 'messages'] #inject is_user_reacts into messages to return for messages in newMsg: for reacts in messages['reacts']: reacts['is_this_user_reacted'] = False #default for react_users in reacts['u_ids']: if react_users == u_id: reacts[ 'is_this_user_reacted'] = True #if user has reacted if len(newMsg) <= int(start) + 50: return { 'messages': newMsg[len(channel['messages']) - int(start)::-1], 'start': start, 'end': -1 } else: return { 'messages': newMsg[len(channel['messages'] ):len(channel['messages']) - 51:-1], 'start': start, 'end': int(start) + 50 } raise AccessError("Must be a member of channel to see messages") except ValueError as e: raise e except AccessError as e: raise e
def message_react(token, message_id, react_id): # 1. authorise user should be in the channel # 2. the message should be valid # 3. the message should be unreacted check_tokenlogin(token) #get the information of the user auser_dic = get_user_from_token(token) auid = auser_dic['u_id'] m_c_dic = get_message_from_mid(message_id) check_validmessage(m_c_dic) # check if the message is valid then get the message message_dic = m_c_dic['message_dic'] channel_dic = m_c_dic['channel_dic'] check_uid_not_in_channel(auid, channel_dic) check_validreact(react_id) m_reacts = message_dic['reacts'] this_react = helper_check_react_exists(m_reacts, react_id) user_reacted = helper_is_the_user_reacted(message_dic, auid) # if there is no this react in the message # add a react if not this_react: m_reacts.append({ 'react_id': react_id, 'u_ids': [auid], 'is_this_user_reacted': user_reacted }) return {} # if there is this react in the message if auid in this_react['u_ids']: raise ValueError( "Message already contains an active React with react_id from user." ) this_react['u_ids'].append(auid) if not user_reacted: this_react['is_this_user_reacted'] = True return {}
def auth_register(email,password,name_first,name_last): #check email is valid if not re.search(regex,email): raise ValueError("Invalid Email") #check password is not less than 6 chars if len(password) < 5: raise ValueError("Password too short") #check email isn't already registered for user in data: if user['email'] == email: raise ValueError("Email already in use") #check first name is between 1 and 50 chars if len(name_first) > 50: raise ValueError("First name has to be 50 characters or less") elif len(name_first) == 0: #Assumed that first name has to be at least 1 char raise ValueError("Name has to be at least one character") #check first name is between 1 and 50 chars if len(name_last) > 50: raise ValueError("Last name has to be 50 characters or less") elif len(name_last) == 0: #Assumed that last name has to be at least 1 char raise ValueError("Last name has to be at least one character") #count how many people have same first name and last name count = 0 for user in data: if (user.get('name_first')).lower() == name_first.lower() and (user.get('name_last')).lower() == name_last.lower(): count += 1 #If the handle would be greater than 20 digits, if len(name_first + name_last) < 20: if count == 0: handle = name_first.lower() + name_last.lower() else: handle = name_first.lower() + name_last.lower() + str(count) else: if count == 0: handle = (name_first.lower() + name_last.lower())[0:20] else: handle = (name_first.lower() + name_last.lower())[0:19] + str(count) return createUser(email,password,name_first,name_last, handle)