def channels_create(token, name, is_public): """ Create a channel for a user. """ if len(name) > 20: raise InputError database = DataBase() # Get user channel_creator = database.get_account_info(token) # Get Channel ID and change number of channels database.database_dict['no_channels'] += 1 channel_id = database.database_dict['no_channels'] #We assume that channel_id start from 0->1->2->3->4->... new_channel = { 'standup': { 'user_token': None, 'end': None, 'message': "" }, 'creator_token': channel_creator['u_id'], 'name': name, 'channel_id': channel_id, 'is_public': is_public, 'owners_id': [], 'members_id': [], 'no_sent_messages': 0, 'messages': [] } new_channel['members_id'].append(channel_creator['u_id']) new_channel['owners_id'].append(channel_creator['u_id']) database.database_dict['channels'].append(new_channel) database.close() return {'channel_id': channel_id}
def auth_login(email, password): """ Logs user into flockr (tracks account in database). """ email_in_database = check_email_in_database(email) validate_email_regex = check_email_regex(email) if not email_in_database or not validate_email_regex: raise InputError('Invalid email or email already in database') database = DataBase() users = database.database_dict['users'] valid_user = {} for user in users: if user['email'] == email and user['password'] == password: valid_user = user break if not valid_user: raise InputError('Invalid email or email already in database') # Add user to active_user database active_users = database.database_dict['active_users'] token_str_1 = f"active_user_{valid_user['u_id']}" token_str_2 = f"{database.database_dict['no_active_users']}" token_str = token_str_1 + "_" + token_str_2 token_str = database.token_generator(token_str) return_dict = {'u_id': valid_user['u_id'], 'token': token_str} active_users.append(return_dict) database.database_dict['no_active_users'] += 1 database.close() return return_dict
def message_send(token, channel_id, message): """ Send message in channel. """ # Raise error if message is too long if len(message) > 1000: raise InputError('Message over 1000 words') database = DataBase() user_id = database.get_account_info(token)['u_id'] channel = database.get_channel_info(channel_id) # Raise error is user_id is not part of channel. if user_id not in channel['members_id']: raise AccessError('Not a channel member') # Create message_id channel_id_str = str(NO_CHANNELS - channel_id) message_id = channel_id_str + str(channel['no_sent_messages']).zfill(5) message_id += str(user_id) message_id = int(message_id) # Create message_dict dt = datetime.now() timestamp = int(dt.replace(tzinfo=timezone.utc).timestamp()) message_dict = {} message_dict['message_id'] = message_id message_dict['u_id'] = user_id message_dict['message'] = message message_dict['time_created'] = timestamp message_dict['reacts'] = [{'react_id': 1, 'u_ids': [], 'is_this_user_reacted': False}] message_dict['is_pinned'] = False channel['messages'] = [message_dict] + channel['messages'] channel['no_sent_messages'] += 1 database.close() return { 'message_id': message_id, }
def auth_passwordreset_reset(reset_code, new_password): """ Reset password given a reset code. """ # Try decrypting jwt string try: decrypted_dict = jwt.decode(reset_code, RESET_PASSWORD_KEY, algorithms=['HS256']) except Exception: raise InputError email = decrypted_dict['email'] # Check if password and email is valid if not validate_password(new_password) or not check_email_in_database( email): raise InputError # Reset the password database = DataBase() u_id = 0 users = database.database_dict['users'] for user in users: if user['email'] == email: break u_id += 1 target_user = database.database_dict['users'][u_id] target_user['password'] = new_password database.close() return {}
def test_perm_change(other_init): database = DataBase() admin = database.get_account_info(other_init[0]['token']) admin['permissions'] = 1 database.close() result = admin_userpermission_change(other_init[0]['token'], other_init[1]['u_id'], 1) assert result == {}
def test_perm_change_access_error(other_init): database = DataBase() admin = database.get_account_info(other_init[0]['token']) admin['permissions'] = 2 database.close() with pytest.raises(AccessError): admin_userpermission_change(other_init[0]['token'], other_init[1]['u_id'], 1)
def user_profile_setname(token, name_first, name_last): """ user sets name. """ database = DataBase() user_profile = database.get_account_info(token) if not validate_names(name_first, name_last): raise InputError user_profile['name_first'] = name_first user_profile['name_last'] = name_last database.close() return {}
def user_profile_sethandle(token, handle_str): """ Let user modify handle. """ if len(handle_str) > 20 or len(handle_str) < 3: raise InputError('Illegible handle') database = DataBase() user_profile = database.get_account_info(token) users = database.database_dict['users'] for user in users: if handle_str == user['handle_str']: raise InputError('Handle already exists') user_profile['handle_str'] = handle_str database.close() return {}
def search(token, query_str): """ Searches messages for query_str """ database = DataBase() user_id = database.get_account_info(token)['u_id'] channels = database.database_dict['channels'] messages_list = [] for channel in channels: messages = channel['messages'] if user_id in channel['members_id']: for message in messages: if query_str in message['message']: messages_list.append(message) database.close() return {'messages': messages_list}
def admin_userpermission_change(token, u_id, permission_id): """ Change user permissions. """ database = DataBase() user = database.get_info_from_id(u_id) admin = database.get_account_info(token) # Error checking if not user or (permission_id != USER_PERMISSIONS and permission_id != OWNER_PERMISSIONS): raise InputError if admin['permissions'] != OWNER_PERMISSIONS: raise AccessError user['permissions'] = permission_id database.close() return {}
def auth_logout(token): """ Logs user out of flockr (active to not active user). """ database = DataBase() token = database.token_decryptor(token) # Get active users list active_users = database.database_dict['active_users'] # Get active_users index from token active_user_index = re.search("_[0-9]*$", token).group(0) active_user_index = int(re.sub("_", "", active_user_index)) # Remove active user active_users.pop(active_user_index) database.database_dict['no_active_users'] -= 1 database.close() return {'is_success': True}
def channel_join(token, channel_id): """ Add valid user to channel. """ # Get info from database for error checking database = DataBase() channel = database.get_channel_info(channel_id) joining_member = database.get_account_info(token) # Error checking if not channel: raise InputError('Channel does not exist') if joining_member['permissions'] != OWNER_PERMISSIONS: if not channel['is_public']: raise AccessError('Channel is private') # Update database channel['members_id'].append(joining_member['u_id']) database.close() return {}
def channel_addowner(token, channel_id, u_id): """ Add channel ownwers for user with valid channel ownership. """ # Get info for error checking database = DataBase() channel = database.get_channel_info(channel_id) channel_member = database.get_account_info(token) # Error checking if not channel or u_id in channel['owners_id']: raise InputError('Channel does not exist or user is not an owner') if channel_member['permissions'] != OWNER_PERMISSIONS: if channel_member['u_id'] not in channel['owners_id']: raise AccessError('Not an owner of the channel') # Update database channel['owners_id'].append(u_id) database.close() return {}
def channel_removeowner(token, channel_id, u_id): """ Remove the ownwer of channel with user with valid channel ownership. """ # Get info for error checking database = DataBase() channel = database.get_channel_info(channel_id) channel_member = database.get_account_info(token) # Check for errors if not channel or u_id not in channel['owners_id']: raise InputError('Channel does not exist or user is not an owner') if (channel_member['u_id'] not in channel['owners_id'] and channel_member['permissions'] != OWNER_PERMISSIONS): raise AccessError('Not an owner of this channel') # Update database channel['owners_id'].remove(u_id) database.close() return {}
def channel_leave(token, channel_id): """ Remove user from channel with valid token. """ # Get info from database for error checking database = DataBase() channel = database.get_channel_info(channel_id) channel_member = database.get_account_info(token) # Error checking if not channel: raise InputError('Channel does not exist') if channel_member['permissions'] != OWNER_PERMISSIONS: if channel_member['u_id'] not in channel['members_id']: raise AccessError('Not a member in the channel') # Change database channel['members_id'].remove(channel_member['u_id']) database.close() return {}
def message_remove(token, message_id): """ Remove message in channel """ database = DataBase() user_id = database.get_account_info(token)['u_id'] channel_id = str(message_id) channel_id = NO_CHANNELS - int(channel_id[0:5]) channel = database.get_channel_info(channel_id) channel_msgs = database.get_channel_messages(channel_id) message_user_id = int(str(message_id)[10:]) # Check users allowed to delete messages if user_id not in channel['owners_id'] and user_id != message_user_id: raise AccessError('Not a member of channel') # Check if message exists to delete in list message_index = find_message_index(message_id, channel_msgs) channel_msgs.pop(message_index) database.close() return {}
def message_react(token, message_id, react_id): """ Let users react to messages. """ database = DataBase() channel_id = str(message_id) channel_id = NO_CHANNELS - int(channel_id[0:5]) channel_msgs = database.get_channel_messages(channel_id) message_index = find_message_index(message_id, channel_msgs) msg = channel_msgs[message_index] channel_member_id = database.get_account_info(token)['u_id'] if react_id != 1 or channel_member_id in msg['reacts'][react_id-1]['u_ids']: raise InputError # Add react react = channel_msgs[message_index]['reacts'][react_id - 1] react['is_this_user_reacted'] = True react['u_ids'].append(database.get_account_info(token)['u_id']) database.close() return {}
def channel_invite(token, channel_id, u_id): """ Invite registered users to channels. """ # Open database and gather channel info and member info database = DataBase() channel = database.get_channel_info(channel_id) channel_member = database.get_account_info(token) add_member = database.get_info_from_id(u_id) # Error testing if not channel or not add_member: raise InputError('Channel doesn\'t exist or member doesn\'t exist') if channel_member['permissions'] != OWNER_PERMISSIONS: if channel_member['u_id'] not in channel['members_id']: raise AccessError('Not a member in the channel') # Update database channel['members_id'].append(u_id) database.close() return {}
def auth_register(email, password, name_first, name_last): """ Create user account based on valid info. """ # Validate entries valid_email = validate_email(email) valid_password = validate_password(password) valid_names = validate_names(name_first, name_last) # If every input is valid if not valid_email or not valid_names or not valid_password: raise InputError('Invalid email or names or password') # Open database for editing database = DataBase() # Add user to database users = database.database_dict['users'] # Give user specific permissions permissions = USER_PERMISSIONS if database.database_dict['no_users'] == 0: permissions = OWNER_PERMISSIONS user_dict = { 'handle_str': create_handle(name_first, name_last), 'email': email, 'password': password, 'name_first': name_first, 'name_last': name_last, 'permissions': permissions, 'u_id': len(users), 'profile_img_url': None, } users.append(user_dict) database.database_dict['no_users'] += 1 # Add user to active user active_users = database.database_dict['active_users'] token_str = f"active_user_{user_dict['u_id']}_{database.database_dict['no_active_users']}" token_str = database.token_generator(token_str) return_dict = {'u_id': user_dict['u_id'], 'token': token_str} database.database_dict['no_active_users'] += 1 active_users.append(return_dict) # Close database to save changes database.close() return return_dict
def message_unpin(token, message_id): """ Unpin messages. """ database = DataBase() channel_id = str(message_id) channel_id = NO_CHANNELS - int(channel_id[0:5]) channel_msgs = database.get_channel_messages(channel_id) message_index = find_message_index(message_id, channel_msgs) # Error checking msg = channel_msgs[message_index] channel = database.get_channel_info(channel_id) channel_member_id = database.get_account_info(token)['u_id'] if channel_member_id not in channel['members_id']: raise AccessError('Not a member in the channel') if not msg['is_pinned']: raise InputError('Message is already unpinnned') # Unpin messages channel_msgs[message_index]['is_pinned'] = False database.close() return {}
def message_edit(token, message_id, message): """ Edit messages or delete them. """ # Get channel which message_id attaches itself too database = DataBase() user_id = database.get_account_info(token)['u_id'] channel_id = str(message_id) channel_id = NO_CHANNELS - int(channel_id[0:5]) channel = database.get_channel_info(channel_id) message_user_id = int(str(message_id)[10:]) message_index = find_message_index(message_id, channel['messages']) # Error handling if user_id not in channel['owners_id'] and user_id != message_user_id: raise AccessError('Not member of channel') # Edit or delete message if message: channel['messages'][message_index]['message'] = message else: channel['messages'].pop(message_index) database.close() return {}
def message_unreact(token, message_id, react_id): """ User unreacts to message. """ database = DataBase() channel_id = str(message_id) channel_id = NO_CHANNELS - int(channel_id[0:5]) channel_msgs = database.get_channel_messages(channel_id) message_index = find_message_index(message_id, channel_msgs) #Error checking msg = channel_msgs[message_index] channel_member_id = database.get_account_info(token)['u_id'] if react_id != 1 or channel_member_id not in msg['reacts'][react_id-1]['u_ids']: raise InputError('Not valid react or member hasn\'t reacted') react = msg['reacts'][react_id - 1] if not react['is_this_user_reacted']: raise InputError('No reacts have been made') #Implementation react['u_ids'].remove(database.get_account_info(token)['u_id']) if not react['u_ids']: react['is_this_user_reacted'] = False database.close() return {}