def sign_up(): ''' Sign up and Login pages and authentication ''' if request.method == 'POST': existing_user = DB_USERS.find_one({'email': request.form['email']}) existing_username = DB_USERS.find_one( { 'name': request.form['username'] }) if existing_user is None and existing_username is None: hashpass = bcrypt.hashpw( request.form['password'].encode('utf-8'), bcrypt.gensalt()) DB_USERS.insert( { 'name': request.form['username'], 'password': hashpass, 'email': request.form['email'], 'admin': False }) session['username'] = request.form['username'] DB_COUNTER.update( { 'counter_name': 'counter' }, { '$inc': { 'number_users': 1 }}) session['admin'] = False return redirect(url_for('index')) return render_template('fail_sign_up.html') return render_template('sign_up.html')
def edit_profile(user_id): """ Directs user profile.html template if they are signed in, else to sign in page :return users profile.html if the user is signed in sign-in.html if the user is not signed """ # User exists in the database and Signed in if session.get('USERNAME', None): username = session['USERNAME'] # user exists in the database current_user = DB_USERS.find_one({'username': username}) requested_user = DB_USERS.find_one({'_id': ObjectId(user_id)}) # if the current logged in user is the user requested if requested_user['_id'] == current_user['_id']: return render_template('edit-profile.html', user_data=requested_user) else: # Forbidden - User is not the account holder abort(403) else: # User not signed in return redirect(url_for('sign_in'))
def add_favorite(recipe_id): """ Adds the recipe to the users favorites list in the users profile :return Redirect to recipe url with updated favorite """ updated_favorites = [] # User is signed in and exists in the database if session.get('USERNAME', None): username = session['USERNAME'] user = DB_USERS.find_one({'username': username}) recipe = DB_RECIPES.find_one({'_id': ObjectId(recipe_id)}) # Update users favorites current_favorites = user['favorites'] # if the recipe is not already in the list if ObjectId(recipe_id) not in current_favorites: current_favorites.append(ObjectId(recipe_id)) DB_USERS.update_one({'_id': user['_id']}, {"$set": { 'favorites': current_favorites, }}, upsert=True) updated_user = DB_USERS.find_one({'username': username}) updated_favorites = updated_user['favorites'] return redirect( url_for('recipe', recipe_id=recipe_id, favorites=updated_favorites))
def insert_user(): ''' inserting a user, only available for admin ''' if 'admin' in session: if request.method == 'POST': existing_user = DB_USERS.find_one({'email': request.form['email']}) existing_username = DB_USERS.find_one( {'name': request.form['username']}) if existing_user is None and existing_username is None: hashpass = bcrypt.hashpw( request.form['password'].encode('utf-8'), bcrypt.gensalt()) DB_USERS.insert({ 'name': request.form['username'], 'password': hashpass, 'email': request.form['email'], 'admin': False }) DB_COUNTER.update({'counter_name': 'counter'}, {'$inc': { 'number_users': 1 }}) return redirect(url_for('admin_tab_users')) return render_template('fail_sign_up.html') return render_template('sign_up.html')
def add_temp_recipe(user_id): """ Creates a temporary recipe record to assign to the user :return Redirect to edit_recipe url """ # User exists in the database and Signed in if session.get('USERNAME', None): username = session['USERNAME'] # user exists in the database try: current_user = DB_USERS.find_one({'username': username}) requested_user = DB_USERS.find_one({'_id': ObjectId(user_id)}) # if the current logged in user is the user requested if requested_user['_id'] == current_user['_id']: # Default recipe image image_url = 'https://res.cloudinary.com/dajuujhvs/image/upload/v1591896759/gi5h7ejymbig1yybptcy.png' image_url_id = 'gi5h7ejymbig1yybptcy' # create empty temp record temp_record = DB_RECIPES.insert_one({ 'name': 'My Awesome Recipe', 'image_url': image_url, 'image_url_id': image_url_id, 'featured': 'false', 'current_rating': '0', 'total_ratings': 0, 'sum_ratings': 0, 'author_id': ObjectId(user_id), 'preptime_hrs': '0', 'preptime_min': '0', 'cooktime_hrs': '0', 'cooktime_min': '0' }) return redirect( url_for('edit_recipe', user_id=user_id, recipe_id=temp_record.inserted_id)) else: # raises a 403 error return abort(403, description="Forbidden") except: # raises a 404 return abort(404, description="Resource not found") else: # User not signed in return redirect(url_for('sign_in'))
def del_recipe(recipe_id): """ Deletes the recipe from the database :return Redirects to the user's profile url """ # User not Signed in if not session.get('USERNAME', None): return redirect(url_for('sign_in')) # Get username username = session['USERNAME'] try: current_user = DB_USERS.find_one({'username': username}) current_recipe = DB_RECIPES.find_one({'_id': ObjectId(recipe_id)}) # if the current logged in user is recipe author if current_recipe['author_id'] == current_user['_id']: DB_RECIPES.remove({'_id': ObjectId(recipe_id)}) DB_INGREDIENTS.delete_many({'recipe_id': ObjectId(recipe_id)}) DB_METHODS.delete_many({'recipe_id': ObjectId(recipe_id)}) return redirect(url_for('profile')) except: # raises a 404 error if any of these fail return abort(404, description="Resource not found")
def edit_recipe(user_id, recipe_id): """ Renders the edit-recipe template passing in the temporary recipe id :return returns the edit-recipe.html form """ # User not Signed in if not session.get('USERNAME', None): return redirect(url_for('sign_in')) username = session['USERNAME'] # user exists in the database try: current_user = DB_USERS.find_one({'username': username}) current_recipe = DB_RECIPES.find_one({'_id': ObjectId(recipe_id)}) current_ingredients = DB_INGREDIENTS.find( {'recipe_id': current_recipe['_id']}) current_methods = DB_METHODS.find({'recipe_id': current_recipe['_id']}) # if the current logged in user is recipe author if current_recipe['author_id'] == current_user['_id']: return render_template('edit-recipe.html', user_id=user_id, recipe_id=recipe_id, current_recipe=current_recipe, current_ingredients=current_ingredients, current_methods=current_methods) else: # raises a 403 error return abort(403, description="Forbidden") except: # raises a 404 error if any of these fail return abort(404, description="Resource not found")
def profile(): """ Directs user profile.html template if they are signed in, else to sign in page :return profile.html if the user is signed in sign-in.html if the user is not signed """ # REFERENCE CREDITS: # Login System -> # https://www.youtube.com/watch?v=vVx1737auSE, https://www.youtube.com/watch?v=PYILMiGxpAU # User is signed in and exists in the database if session.get('USERNAME', None): username = session['USERNAME'] # Fetch user and related recipes existing_user = DB_USERS.find_one({'username': username}) users_recipes = DB_RECIPES.find({'author_id': existing_user['_id']}) favorites = DB_RECIPES.find( {'_id': { '$in': existing_user['favorites'] }}) return render_template('profile.html', user_data=existing_user, users_recipes=users_recipes, favorites=favorites) else: # User not signed in return redirect(url_for('sign_in'))
def edit_user(user_id): ''' rendering template for editing a user, only available for admin ''' if session['admin']: user = DB_USERS.find_one({"_id": ObjectId(user_id)}) return render_template('edit_user.html', user=user) return render_template('no_login.html')
def update_user(user_id, user_name): ''' updating database according to changes made in edit_user, only available for admin ''' if session['admin']: existing_user_name = DB_USERS.find_one({"name": user_name}) if existing_user_name is None: DB_USERS.update({'_id': ObjectId(user_id)}, { '$set': { 'name': request.form.get('name'), 'email': request.form.get('email') } }) return redirect(url_for('admin_tab')) user = DB_USERS.find_one({"_id": ObjectId(user_id)}) return "Username already in use!" + render_template('edit_user.html', user=user) return render_template('no_login.html')
def register(): """ Renders the registration template and adds users credentials to the database :param user name (str) and password (str - hashed) received from the form element :return register.html if it is a GET request or if the username already exists profile.html if the username and password is sufficient """ # REFERENCE CREDITS: # Login System -> # https://www.youtube.com/watch?v=vVx1737auSE, https://www.youtube.com/watch?v=PYILMiGxpAU # # Password Hashing -> # https://stackoverflow.com/questions/27413248/why-can-bcrypt-hashpw-be-used-both-for-hashing-and-verifying-passwords if request.method == 'POST': if request.form.get('confirm-password') != request.form.get( 'password'): return render_template('register.html', exists=False, mismatch_pw=True) # does user exist existing_user = DB_USERS.find_one( {'username': request.form['username']}) # user does not already exist if existing_user is None: # Hash the password for better security hashpass = bcrypt.hashpw( request.form.get('password').encode('utf-8'), bcrypt.gensalt()) # Add the user to the database DB_USERS.insert({ 'username': request.form.get('username'), 'password': hashpass, 'profile_image': 'https://res.cloudinary.com/dajuujhvs/image/upload/v1592578019/wbzphoxefkdid3kheuqd.png', 'profile_image_id': 'wbzphoxefkdid3kheuqd', 'favorites': [] }) # create a session cookie session['USERNAME'] = request.form.get('username') # redirect to profile page return redirect(url_for('profile')) # User already exists else: return render_template('register.html', exists=True) # GET request return render_template('register.html', exists=False)
def recipe(recipe_id): """ Returns the main recipe view :return Renders recipe.html """ current_recipe = None current_recipe_author = None current_recipe_ingredients = None current_recipe_methods = None try: current_recipe = DB_RECIPES.find_one({'_id': ObjectId(recipe_id)}) current_recipe_author = DB_USERS.find_one( {'_id': ObjectId(current_recipe['author_id'])}) current_recipe_ingredients = DB_INGREDIENTS.find( {'recipe_id': ObjectId(recipe_id)}) current_recipe_methods = DB_METHODS.find( {'recipe_id': ObjectId(recipe_id)}) except: # raises a 404 error if any of these fail abort(404, description="Resource not found") # Set loged in variable loged_in = False if session.get('USERNAME', None): username = session['USERNAME'] user = DB_USERS.find_one({'username': username}) favorites = user['favorites'] loged_in = True else: favorites = [] return render_template( 'recipe.html', current_recipe=current_recipe, current_recipe_author=current_recipe_author, current_recipe_ingredients=current_recipe_ingredients, current_recipe_methods=current_recipe_methods, favorites=favorites, loged_in=loged_in)
def delete_user(user_id): """ Deletes the users db record , also Delete the cloadinary image data and all users recipe data :return Redirect to sign in view """ # REFERENCE CREDITS: # Cloudinary api -> # https://github.com/tiagocordeiro/flask-cloudinary # User exists in the database and Signed in if session.get('USERNAME', None): username = session['USERNAME'] # user exists in the database current_user = DB_USERS.find_one({'username': username}) requested_user = DB_USERS.find_one({'_id': ObjectId(user_id)}) # if the current logged in user is the user requested if requested_user['_id'] == current_user['_id']: # Delete related user records DB_RECIPES.delete_many({'author_id': ObjectId(user_id)}) DB_INGREDIENTS.delete_many({'author_id': ObjectId(user_id)}) DB_METHODS.delete_many({'author_id': ObjectId(user_id)}) # Delete the current user image form cloudinary current_user = DB_USERS.find_one({'_id': ObjectId(user_id)}) if current_user['profile_image_id'] != 'wbzphoxefkdid3kheuqd': destroy(current_user['profile_image_id'], invalidate=True) # Delete main user record DB_USERS.remove({'_id': ObjectId(user_id)}) return redirect(url_for('sign_out')) else: # raises a 404 error if any of these fail return abort(403, description="Forbidden") else: # raises a 404 error if any of these fail return abort(403, description="Forbidden")
def login(): if request.method == 'POST': login_user = DB_USERS.find_one({'email': request.form['email']}) if login_user: if bcrypt.checkpw(request.form['password'].encode('utf8'), login_user['password']): session['username'] = login_user['name'] if login_user['admin'] == True: session['admin'] = True return redirect(url_for('admin_tab')) else: session['admin'] = False return redirect(url_for('index')) return render_template('fail_login.html') return render_template('login.html')
def update_profile(user_id): """ Updates the users db record with the POST form data, also updates the cloadinary image data :return Redirect to profile.html """ # REFERENCE CREDITS: # Cloudinary api -> # https://github.com/tiagocordeiro/flask-cloudinary file_to_upload = request.files.get('file') if file_to_upload: # Current user record current_user = DB_USERS.find_one({'_id': ObjectId(user_id)}) if current_user['profile_image_id'] != 'xmt2q3ttok9cwjlux8j2': # Remove current profile image destroy(current_user['profile_image_id'], invalidate=True) # Upload new image to cloudinary upload_result = upload(file_to_upload) # Update users profile image in DB DB_USERS.update_one({'_id': ObjectId(user_id)}, { "$set": { 'profile_image': upload_result['secure_url'], 'profile_image_id': upload_result['public_id'] } }, upsert=True) # Update users profile data DB_USERS.update_one({'_id': ObjectId(user_id)}, { "$set": { 'bio': request.form.get('bio'), 'email': request.form.get('email') } }, upsert=True) return redirect(url_for('profile'))
def update_recipe(user_id, recipe_id): """ Updates the recipe database record :return returns the edit-recipe.html form overview tab """ # User not Signed in if not session.get('USERNAME', None): return redirect(url_for('sign_in')) try: # get the current user's record current_user = DB_USERS.find_one({'_id': ObjectId(user_id)}) # update the recipe record DB_RECIPES.update_one({'_id': ObjectId(recipe_id)}, { "$set": { 'name': request.form.get('recipe-name'), 'description': request.form.get('recipe-description'), 'notes': request.form.get('recipe-notes'), 'preptime_hrs': request.form.get('prep-hours'), 'preptime_min': request.form.get('prep-minutes'), 'cooktime_hrs': request.form.get('cook-hours'), 'cooktime_min': request.form.get('cook-minutes'), 'serves': request.form.get('serves'), 'author': current_user['username'], 'author_id': ObjectId(user_id), 'date_updated': TODAY_STR } }, upsert=True) # return to recipe overview page return redirect( url_for('edit_recipe', _anchor='overview', user_id=user_id, recipe_id=recipe_id)) except: # raises a 404 error if any of these fail return abort(404, description="Resource not found")
def remove_favorite(user_id, recipe_id): """ Removes the recipe from the users favorites list in the users profile :return Redirect to profile view with updated favorites list """ user = None current_favorites = None try: user = DB_USERS.find_one({'_id': ObjectId(user_id)}) current_favorites = user['favorites'] current_favorites.remove(ObjectId(recipe_id)) except: # raises a 404 error if any of these fail abort(404, description="Resource not found") DB_USERS.update_one({'_id': user['_id']}, {"$set": { 'favorites': current_favorites, }}, upsert=True) return redirect(url_for('profile'))