def create_channel(data): """ Lets a user create a new chat channel in a ws, with a unique name in that ws.""" chan_name = sanitize_name(data['new_channel']) # If name is all whitespace, do nothing: if is_whitespace(chan_name): return False # Check name not already in use in current workspace: if chan_name in workspaces[session['curr_ws']]['channels'].keys(): # This should send back some kind of error message return False # Otherwise create a new chat channel and send channel list to all users: workspaces[session['curr_ws']]['channels'][chan_name] = { 'messages': {}, 'next_message': 1 } channel_list = list(workspaces[session['curr_ws']]['channels'].keys()) # Send updated channel list to all users in the workspace: emit('channel_list amended', {'channel_list': channel_list}, room=session['curr_ws'])
def screen_name(): """ Update a user's screen name in the database and all chat messages """ # If user not logged in return to login screen: if session.get('user_id') == None: return redirect('/login') # Get input from form and check screen-name exists: new_screen_name = request.form.get("new-screen-name") if not new_screen_name or is_whitespace(new_screen_name): flash('Please enter your new Screen Name to update it!') return redirect('/account') # Update screen_name in database and session: user_info = User.query.get(session['user_id']) user_info.screen_name = new_screen_name db.session.commit() session['screen_name'] = new_screen_name update_profile(session['screen_name'], 'screen_name', workspaces, private_channels) flash('Your Screen Name has been changed to: ' + session['screen_name']) return redirect('/account')
def create_workspace(data): """ Lets a user create a new workspace, with a unique name. The user then joins the new workspace """ ws_name = sanitize_name(data['new_workspace']) # If name is all whitespace, do nothing: if is_whitespace(ws_name): return False # Check new workspace name not already in use: if ws_name in workspaces.keys(): # This should send back some kind of error message return False timestamp = datetime.now(pytz.utc).timestamp() date = datetime.now().strftime('%d %b %Y') # Otherwise create a new workspace: workspaces[ws_name] = { 'channels': { 'Announcements': { 'messages': { 1: { 'message_text': f'Welcome to your new workspace - {ws_name}!', 'screen_name': 'Flack-Teams Help', 'message_timestamp': timestamp, 'message_date': date, 'message_id': 1, 'profile_img': 'admin.png', 'user_id': -1, 'edited': False, 'edit_text': None, 'edit_date': None, 'deleted': False, 'private': False } }, 'next_message': 2 } }, 'users_online': set() } # Broadcast new workspace creation: workspace_list = list(workspaces.keys()) emit('workspace_list amended', {'workspace_list': workspace_list}, broadcast=True) # Join new workspace in Announcments channel: data = {'sign in': False, 'workspace': ws_name} join_workspace(data)
def account(): """ Show user Account Settings Page, To Change Password, Screen-name or Icon """ # If user not logged in return to login screen: if session.get('user_id') == None: return redirect('/login') # User reached route via POST (by submitting password change form): if request.method == "POST": # Get input from form: curr_pass = request.form.get("curr-pass") new_pass = request.form.get("new-pass") confirm = request.form.get("check-pass") # Check input fields are correct: if not curr_pass or not new_pass or new_pass != confirm or is_whitespace( new_pass): flash("Please fill in all password fields!") return render_template("account.html") # Get current password hash to check it matches: user_info = User.query.get(session['user_id']) logged_pass = user_info.pass_hash if not check_password_hash(logged_pass, curr_pass): flash("Incorrect current password entered, please try again!") return render_template("account.html") # Ensure password meets password requirements elif not validate_pass(new_pass): flash( "New password does not meet requirements - must be at least eight chars long including one number and one letter!" ) return render_template("account.html") # Otherwise generate new password hash and update the password hash in DBfor this user: new_pass_hash = generate_password_hash(new_pass) user_info.pass_hash = new_pass_hash db.session.commit() flash('Password successfully updated!') return redirect('/account') # User reached route via GET (as by clicking acount link) else: return render_template('account.html')
def edit_message(data): """ Edit the text of a message in a specific channel. Updates the message for all users """ print('TRYING TO EDIT MESSAGE') timestamp = float(data['timestamp']) message_id = int(data['message_id']) text = sanitize_message(data['message_text']) private = data['private'] # If message text is all whitespace, do nothing: if is_whitespace(text): return False if not private: # Check if message exists in workspaces messages = workspaces[session['curr_ws']]['channels'][ session['curr_chan']]['messages'] room = session['curr_ws_chan'] else: # Check if message exists in private_channels messages = private_channels['channels'][ session['curr_private']]['messages'] room = session['curr_private'] # Check if message exists and user is allowed to edit it: if messages.get(message_id) and (messages[message_id]['message_timestamp'] == timestamp) and ( session['user_id'] == messages[message_id]['user_id']): messages[message_id]['message_text'] = text messages[message_id]['edited'] = True messages[message_id]['edit_text'] = 'Message Edited' messages[message_id]['edit_date'] = datetime.now().strftime('%d %b %Y') emit('emit edited message', { 'message_id': message_id, 'timestamp': timestamp, 'edited_text': messages[message_id]['message_text'], 'edit_type': messages[message_id]['edit_text'], 'edit_date': messages[message_id]['edit_date'], 'deleted': False, 'private': private }, room=room)
def send_message(data): """ Sends a message to all users in the same room, and stores the message on the server """ print('Server has received a message, Sending message to users in channel') # Get data from incoming message: message_text = sanitize_message(data['message']) screen_name = session['screen_name'] workspace = session['curr_ws'] channel = session['curr_chan'] ws_channel = session['curr_ws_chan'] private = session['curr_private'] profile_img = session['profile_img'] # If message text is all whitespace, do nothing: if is_whitespace(message_text): return False # Create message object: message = { 'user_id': session['user_id'], 'message_text': message_text, 'screen_name': screen_name, 'message_date': datetime.now().strftime('%d %b %Y'), 'message_timestamp': datetime.now(pytz.utc).timestamp(), 'profile_img': profile_img, 'edited': False, 'edit_text': None, 'edit_date': None, 'deleted': False } # If public channel message, save to workspaces if not data['private']: # Save message data to channel log: next = workspaces[workspace]['channels'][channel]['next_message'] message['message_id'] = next message['private'] = False workspaces[workspace]['channels'][channel]['messages'][next] = message # Store up to 100 messages, then overwrite the first message workspaces[workspace]['channels'][channel]['next_message'] += 1 if workspaces[workspace]['channels'][channel]['next_message'] > 100: workspaces[workspace]['channels'][channel]['next_message'] = 1 emit('emit message', { 'message': message, 'private': False }, room=ws_channel) emit('channel alert', { 'channel': channel, 'private': False }, room=workspace) # If private channel message, save to private_channels else: # Save message to private channel log: next = private_channels['channels'][private]['next_message'] message['message_id'] = next message['private'] = True private_channels['channels'][private]['messages'][next] = message # Store up to 100 messages, the overwrite the first message private_channels['channels'][private]['next_message'] += 1 if private_channels['channels'][private]['next_message'] > 100: private_channels['channels'][private]['next_message'] = 1 emit('emit message', { 'message': message, 'private': True }, room=private) # Get correct room and channel name to emit alert to target user: for target_id in session['curr_private']: if target_id != session['user_id']: channel = private_channels['user_private_list'][target_id][ session['curr_private']]['name'] target_room = f'{(target_id,)}' emit('channel alert', { 'channel': channel, 'private': True }, room=target_room)
def register(): """Register user for the website""" # If user is already logged in, return to home screen: if session.get('user_id') != None: return redirect('/') # If reached via POST by submitting form - try to register new user: if request.method == 'POST': # Get input from registration form: username = request.form.get('username') screen_name = request.form.get('screenname') password = request.form.get('password') confirm = request.form.get('confirmation') profile_img = request.form.get('profile') file = None # If form is incomplete, return and flash apology: if not all([username, screen_name, password, confirm, profile_img]): flash('Please fill in all fields to register!') return render_template('register.html') # If password and confirmation do not match, return and flash apology: elif password != confirm: flash('Password and confirmation did not match! Please try again.') return render_template('register.html') # Ensure password meets password requirements: elif not validate_pass(password): flash( 'Password must be eight characters long with at least one number and one letter!' ) return render_template('register.html') # If any input is just whitespace chars, ask for new input: if is_whitespace(username) or is_whitespace( screen_name) or is_whitespace(password): flash('Please fill in all fields to register!') return render_template('register.html') # Check that file is uploaded if own profile img selected: if profile_img == 'user_upload': result = check_img_upload() if not result[0]: flash(result[1]) return render_template('register.html') else: file = result[1] # Otherwise information from registration is complete # Check username does not already exist, if it does then ask for a different name: user_query = User.query.filter_by(username=username).first() if user_query: flash( 'Sorry but that username is already in use, please pick a different username!' ) return render_template('register.html') # Otherwise add user to database using hashed password: pass_hash = generate_password_hash(password) # Add new user to users table: new_user = User(username=username, screen_name=screen_name, pass_hash=pass_hash, profile_img=profile_img) db.session.add(new_user) db.session.commit() # Put unique user ID and username into session: user_info = User.query.filter_by(username=username).first() load_user(user_info, session) # If user uploaded a custom image file, add its path to DB, and save in Images folder: if file: save_user_img(file, app) user_info.profile_img = session['profile_img'] db.session.commit() # Go to main chat page return redirect('/') # If User reaches Route via GET (e.g. clicking registration link): else: return render_template('register.html')