def address(): """Get the address of a certain user. From the users and servers tables, necessary details are extracted from entries containing the given username. Returns: JSON response containing the address details of a certain user. If the user is not found or the server is non existant, a failed JSON response is returned. """ username = request.args.get('username') # If username is not given, use the logged in username. if username is None or username == '': username = auth_username() if username is None or username == '': return bad_json_response("Bad request: Missing parameter 'username'.") if users.exists(username=username): server_id = users.export_one('server_id', username=username) if not servers.exists(id=server_id): bad_json_response('Server is not registered.') name, address = servers.export_one('name', 'address', id=server_id) return good_json_response({ 'name': name, 'address': address, 'username': username }) else: return bad_json_response('User is not found.')
def user_posts(): """Retrieve all posts from a certain username. Checks are in place to check if the user is indeed a member of FedNet. This function uses the get_posts function below to actually retrieve the posts. Returns: JSON response that contains all posts of a certain user. """ username = request.args.get('username') if username is None or username == '': username = auth_username() if username is None: return bad_json_response("Bad request: Missing parameter 'username'.") # Check if user id exists. if not users.exists(username=username): return bad_json_response('User not found.') # Send no data in case the users are not friends. if username != get_jwt_identity() and is_friend(username) != 1: return good_json_response({'posts': {}}) return good_json_response({ 'posts': get_posts(username) })
def register(): """Register a user to the central server. For this registration, the username and server address are requested in the form. A check is performed to see if the server is live. Then the user is inserted into the users table. Returns: Success JSON response if the operation is successful. If the username is valid or the server is not live, a failed JSON response is returned. """ username = request.form['username'] address = request.form['server_address'] if not servers.exists(address=address): return bad_json_response('Server is not registered.') server_id = servers.export_one('id', address=address) if ping(address): if not users.exists(username=username): users.insert(username=username, server_id=server_id) else: return bad_json_response( 'Username is already taken. Try again :).') else: return bad_json_response('This data server is not available. ' 'Please contact the server owner.') return good_json_response('success')
def edit(): """Edit a certain users details in the central server. The entry with the certain users username is edited in the users table in the database. Returns: Success JSON response if the operation is successful. Else a failed JSON response is returned with the correct error message. """ username = get_jwt_identity() if users.exists(username=username): if 'new_address' in request.form: new_address = request.form['new_address'] if 'new_address' != '': if servers.exists(address=new_address): new_id = servers.export_one('id', address=new_address) users.update({'server_id': new_id}, username=username) return good_json_response({'new_address': new_address}) else: return bad_json_response( 'This address does not exist in the database.') else: return bad_json_response('Address undefined.') else: return bad_json_response('Incorrect form.') else: return bad_json_response('No user found with the username ' + username + '.')
def delete(): """Delete a post. For a post to be deleted, the post ID is requested in the form. The post entry corresponding to the given post ID is then deleted from the posts table. Returns: Success JSON response if the operation succeeded. Else a failed JSON response is returned with the correct error message. """ username = get_jwt_identity() post_id = request.form['post_id'] if username is None: return bad_json_response("Bad request: Missing parameter 'username'.") if post_id is None: return bad_json_response("Bad request: Missing parameter 'post_id'.") if not users.exists(username=username): return bad_json_response('User not found') if not posts.exists(id=post_id): return bad_json_response('Post not found') # Check if the user is the post owner. post_username = posts.export_one('username', id=post_id) if post_username != username: return bad_json_response('Not your post') # Delete post. posts.delete(id=post_id) return good_json_response('success')
def send_verification_mail(): """Handles the sending of verification email. Returns: JSON response based on succes/failure. """ # Check if parameter email is set. send_to = request.form['email'] if not send_to: return bad_json_response("Bad request: Missing parameter 'email'.") # Retrieve user from server for personal message in email. user = users.export_one('firstname', 'lastname', email=request.form['email']) # If no user is found give an error. if not user: return bad_json_response('Error retrieving the user.') # Construct message object with receipient and sender msg = EmailMessage() msg['Subject'] = 'FedNet - Please verify your email!' msg['From'] = current_app.config['EMAIL_ADDRESS'] msg['To'] = send_to # Create the secret key based on our little secret :) secret = URLSafeTimedSerializer(current_app.config['EMAIL_SECRET']) # Create token based on a user their email and salt to prevent same token. token = secret.dumps(send_to, salt=current_app.config['EMAIL_REGISTER_SALT']) # Create link with token and add it to the body of the mail. link = url_for('data_mail.confirm_email', token=token, _external=True) # Load the HTML template for the email, and embed the information needed. with open('app/templates/email_template/verify-mail.html') as f: html = f.read() html = html.replace('VERIFY_LINK_HERE', link) html = html.replace('USERNAME_HERE', user[0] + ' ' + user[1]) msg.add_alternative(html, subtype='html') # Add image to the contents of the email. with open('app/static/images/LogoBackOpaque.png', 'rb') as img: # Know the Content-Type of the image. maintype, subtype = mimetypes.guess_type(img.name)[0].split('/') # Attach it to the email. The cid='0' is linked to the cid in the html, # which loads it. msg.get_payload()[0].add_related(img.read(), maintype=maintype, subtype=subtype, cid='0') # Connect to the mailserver from google and send the e-mail. with smtplib.SMTP_SSL('smtp.gmail.com', 465) as smtp: smtp.login(current_app.config['EMAIL_ADDRESS'], current_app.config['EMAIL_PASSWORD']) smtp.send_message(msg) return good_json_response('success')
def forgot_username(): """Sends email to reset username. Returns: JSON reponse based on succes/failure. """ email = request.form['email'] if not email: return bad_json_response("Bad request: Missing parameter 'email'.") # Retrieve email for given username. # Also retrieve firstname and lastname for personal message. username = users.export_one('username', email=email) # If no user is found for given email, don't send email. if not username: return bad_json_response( 'No user with this e-mail exists on this server: ' + get_own_ip() ) # Construct message object with receipient and sender. msg = EmailMessage() msg['Subject'] = 'FedNet - Your username is ' + username msg['From'] = current_app.config['EMAIL_ADDRESS'] msg['To'] = email # Load the HTML template for the email, and embed the information needed. with open('app/templates/email_template/forgot-username.html') as f: html = f.read() html = html.replace('USERNAME_HERE', username) msg.add_alternative(html, subtype='html') # Add image to the contents of the email. with open('app/static/images/LogoBackOpaque.png', 'rb') as img: # Know the Content-Type of the image maintype, subtype = mimetypes.guess_type(img.name)[0].split('/') # Attach it to the email. The cid='0' is linked to the cid in the html, # which loads it. msg.get_payload()[0].add_related(img.read(), maintype=maintype, subtype=subtype, cid='0') # Connect to the mailserver from google and send the e-mail. with smtplib.SMTP_SSL('smtp.gmail.com', 465) as smtp: smtp.login(current_app.config['EMAIL_ADDRESS'], current_app.config['EMAIL_PASSWORD']) smtp.send_message(msg) return good_json_response(('Email was sent to ' + email + '.'))
def get_pub_key(username): """Helper function to get the public key of a user. Returns: The public key of a user if available, else a bad JSON response. """ server_id = users.export_one('server_id', username=username) if server_id is None: return bad_json_response('No server_id') pub = servers.export_one('pub_key', id=server_id) if pub is None: return bad_json_response('No pub') return pub
def hobby(): """Get all hobby details from a certain user. Returns: JSON reponse with the hobby details from the hobbies table. """ username = request.args.get('username') if username is None or username == '': username = auth_username() if username is None: return bad_json_response("Bad request: Missing parameter 'username'.") # Extract all the needed data from the hobbies table in the database. hobbies_details = hobbies.export('id', 'title', username=username) hobbies_array = [ { 'id': item[0], 'title': item[1] } for item in hobbies_details ] return good_json_response({ 'hobbies': hobbies_array })
def language(): """Get all language details from a certain user. Returns: JSON reponse with the language details from the languages table. """ username = request.args.get('username') if username is None or username == '': username = auth_username() if username is None: return bad_json_response("Bad request: Missing parameter 'username'.") # Extract all the needed data from the language table in the database. language_details = languages.export('id', 'title', 'skill_level', username=username) language_array = [ { 'id': item[0], 'title': item[1], 'skill_level': item[2] } for item in language_details ] return good_json_response({ 'languages': language_array })
def post(): """Get all the necessary details for a post. The post ID is checked to see if the post actually exists. The same is done with the upload ID. Returns: JSON response with the post details. """ post_id = request.args.get('post_id') if post_id is None: return bad_json_response('post_id should be given as parameter.') post_db = posts.export('id', id=post_id) if not post_db: return bad_json_response('post not found') post_db = posts.export('body', 'title', 'username', 'uploads_id', 'creation_date', 'last_edit_date', id=post_id)[0] # Get image. up_id = post_db[3] if uploads.exists(id=up_id): filename = uploads.export_one('filename', id=up_id) imageurl = get_own_ip() + 'file/{}/{}'.format(up_id, filename) return good_json_response({ 'post_id': post_id, 'body': post_db[0], 'title': post_db[1], 'username': post_db[2], 'profile_image': get_profile_image(post_db[2]), 'image_url': imageurl, 'creation_date': str(post_db[4]), 'last_edit_date': str(post_db[5]) })
def login(): """Function that handles the login. An access token is created. A check is in place to verify the encrypted password and to check if the user is verified through e-mail. Returns: A success JSON reponse that contains the access token. """ username = request.form['username'] password = request.form['password'] if username is None: return bad_json_response("Bad request: Missing parameter 'username'.") if password is None: return bad_json_response("Bad request: Missing parameter 'password'.") if not users.exists(username=username): return bad_json_response( "User does not exist yet. Feel 'free' to join FedNet! :)" ) password_db = users.export('password', username=username)[0] # Verify the given password. if not sha256_crypt.verify(password, password_db): return bad_json_response('Password is incorrect.') # Check if the account has been verified through e-mail. email_confirmed = users.export_one('email_confirmed', username=username) if not email_confirmed: return bad_json_response( 'The email for this user is not authenticated yet. ' 'Please check your email.' ) # Login success. access_token = create_access_token(identity=username) return good_json_response({ 'token': access_token })
def timeline(): """This function handles the timeline, making sure you only see posts from the correct people. If you are friends with a certain user, that users posts will be shown in your timeline. Imported: get_friends function from api/data/friend.py Returns: JSON reponse that contains all the posts that are shown in the timeline. """ from app.api.data.friend import get_friends username = get_jwt_identity() # Check if user exists. if not users.exists(username=username): return bad_json_response('user not found') # Get the user's own posts. posts_array = get_posts(username) # Get the user's friends. friends = get_friends(username) for i in range(len(friends)): try: friend = friends[i]['username'] friend_address = get_user_ip(friend) # Get the posts of the friend. response = requests.get( friend_address + '/api/user/posts', params={ 'username': friend }, headers=request.headers ).json() if response['success']: posts = response['data']['posts'] posts_array = posts_array + posts except BaseException: continue posts_array = sorted( posts_array, key=lambda k: datetime.datetime.strptime(k['creation_date'], '%Y-%m-%d %H:%M:%S'), reverse=True ) return good_json_response({ 'posts': posts_array })
def create(): """Create a new post. For a post to be created, details are submitted in the form. These details are then inserted into the posts table in the database. Returns: Success JSON response if the operation succeeded. Else a failed JSON response is returned with the correct error message. """ username = get_jwt_identity() title = request.form['title'] body = request.form['body'] if username is None: return bad_json_response("Bad request: Missing parameter 'username'.") if title is None: return bad_json_response("Bad request: Missing parameter 'title'.") if body is None: return bad_json_response("Bad request: Missing parameter 'body'.") if not users.exists(username=username): return bad_json_response('User not found.') # Insert post. if 'file' in request.files: image_filename = request.files['file'].filename image = request.files['file'].read() if image is not 0: uploads_id = save_file(image, filename=image_filename) if uploads_id is not False: posts.insert(username=username, body=body, title=title, uploads_id=uploads_id) else: posts.insert(username=username, body=body, title=title) return good_json_response('success')
def pub_key(): """Get the public key of a user. Returns: JSON response containing the public key of a user. """ username = request.args.get('username') if username is None: return bad_json_response('No username') return good_json_response(get_pub_key(username))
def forgotpassword(): username = request.form['username'] password = request.form['password'] if password is None: return bad_json_response("Bad request: Missing parameter 'password'.") new_password = sha256_crypt.encrypt(request.form['password']) users.update({'password': new_password}, username=username) return good_json_response('Succes')
def user(): """Get all usernames and their respective server ID's from the users table. Returns: JSON response containing all the usernames in the users table. """ usernames = users.export('username', 'server_id') if len(usernames) == 0: return bad_json_response('No usernames in the database.') return good_json_response({'usernames': usernames})
def get_comments(): """Get all comments from a certain post. To retrieve all comments on a certain post, the post ID is requested in the form. All the comment entries in the comments table corresponding to the given post ID are then retrieved. Returns: JSON response containing a list with all the comments if the operation succeeded. Else a failed JSON response is returned with the correct error message. """ post_id = request.args.get('post_id') if post_id is None or post_id == '': return bad_json_response( "Bad request: Missing or invalid parameter 'post_id'.") if not posts.exists(id=post_id): return bad_json_response('Post id does not exist.') comment_details = comments.export('id', 'comment', 'username', 'creation_date', 'last_edit_date', post_id=post_id) comments_array = [{ 'id': item[0], 'comment': item[1], 'username': item[2], 'profile_image': get_profile_image(item[2]), 'creation_date': str(item[3]), 'last_edit_date': str(item[4]) } for item in comment_details] return good_json_response({'comments': comments_array})
def register(): """Register a data server to the central server. For this registration, the server name and address are requested in the form. A check is performed to see if the server is live. Then the server is inserted into the servers table if it does not already exists. Returns: JSON response containing the server id and the public key at success, else a bad JSON response containing the error message. """ name = request.form['name'] address = request.form['address'] pub_key = ping(address) if pub_key: if not servers.exists(address=address): result = servers.insert( name=name, address=address, pub_key=pub_key) return good_json_response({ 'server_id': result, 'pub_key': pub_key }) else: name = servers.export_one('name', address=address) return bad_json_response( 'The data server at "' + address + '" is already registered by the name "' + name + '".' ) else: return bad_json_response( 'The data server at "' + address + '" did not respond. Is the installation correct?' )
def password(): """Upon entering the old password, a new password can be set. The old password is verified and the new password is encrypted and updated in the database. """ username = get_jwt_identity() password = request.form['oldPassword'] if password is None: return bad_json_response("Bad request: Missing parameter 'password'.") password_db = users.export('password', username=username)[0] if not sha256_crypt.verify(password, password_db): return bad_json_response('Password is incorrect.') if 'newPassword' in request.form: new_password = sha256_crypt.encrypt(request.form['newPassword']) if 'newPassword' != '': users.update({'password': new_password}, username=username) return good_json_response('Succes')
def users_all(): """Get all usernames in the users table. Returns: JSON reponse that contains all the usernames in the users table. """ usernames = users.export('username') if len(usernames) == 0: return bad_json_response('No users found.') return good_json_response({ 'usernames': usernames })
def search(): """Searches for existing usernames. Returns: JSON reponse based on failure/succes. """ input_data = request.form['search_input'] if users.exists(username=username): return bad_json_response('Username is already registered.') users.insert(username=username, location=location, study=study) return good_json_response('success')
def delete(): """Delete a user from FedNet. The users details in the users table are deleted. """ username = get_jwt_identity() if users.exists(username=username): # Everything that belongs to user is deleted automatically. users.delete(username=username) return good_json_response({'user': username}) else: return bad_json_response('Username is not registered.')
def export_zip_(): """Export all the data of a certain user as a zip. Returns: If the user exists, the user details will be exported. """ username = get_jwt_identity() if users.exists(username=username): return send_file(export_zip(username), mimetype='application/zip', as_attachment=True, attachment_filename='export.zip') else: return bad_json_response('User does not exist in database.')
def registered(): """Look up if the given username is a registered username in FedNet. Returns: JSON reponse that succeeds if the username is registered and fails if the user is not registered. """ username = request.args.get('username') if username is None: return bad_json_response("Bad request: Missing parameter 'username'.") if not users.exists(username=username): return bad_json_response('Username not found (in data server)') # This request checks if the given username is registered. r = requests.get( get_central_ip() + '/api/user/registered', params={ 'username': username } ).json() return good_json_response(r)
def register(): """Registers a user to this data server. All the given information is stored in the users table in the database. """ # Exit early. if users.exists(username=request.form['username']): return bad_json_response('Username is already taken. Try again :)') if users.exists(email=request.form['email']): return bad_json_response( 'A user with this email is already registered on this data server.' ) username = request.form['username'] firstname = request.form['firstname'] lastname = request.form['lastname'] email = request.form['email'] password = sha256_crypt.encrypt(request.form['password']) users.insert(username=username, firstname=firstname, lastname=lastname, password=password, email=email) return good_json_response('success')
def import_zip_(): """Import all the data of a certain user. Returns: Success JSON response in case the import was successful. Else the bad JSON response will be returned with an error message. """ username = get_jwt_identity() if 'file' in request.files: file = request.files['file'].read() if file is not 0: import_zip(file, username=username) return good_json_response() return bad_json_response('File not received.')
def file_main(): """Function that handles getting a file. Returns: A bad JSON response if file is not found. A good JSON response with file URL if file is found successfully """ file_id = request.args.get('id') if not uploads.exists(id=file_id): return bad_json_response('File ID does not exist.') filename = uploads.export_one('filename', id=file_id) return good_json_response({'url': '/file/{}/{}'.format(file_id, filename)})
def get_key(): """Function for getting the public key. Returns: JSON reponse with either public key on success or error message on failure. """ with open('jwtRS256.key.pub') as f: pub_key = f.read() if pub_key is not None: return good_json_response(pub_key) else: return bad_json_response( 'Error retrieving the public key of server: ' + get_own_ip())
def registered(): """Check if a certain user is registered in the users table. Returns: JSON response containing username of the certain user if the user is indeed registered. If the username is not found, a failed JSON response is returned. """ username = request.args.get('username') if username is None: return bad_json_response('Username should be given as parameter.') exists = users.exists(username=username) return good_json_response({'registered': exists})