aboutsummaryrefslogtreecommitdiff
path: root/server.py
diff options
context:
space:
mode:
Diffstat (limited to 'server.py')
-rw-r--r--server.py144
1 files changed, 144 insertions, 0 deletions
diff --git a/server.py b/server.py
new file mode 100644
index 0000000..013089a
--- /dev/null
+++ b/server.py
@@ -0,0 +1,144 @@
+from flask import Flask, Response, render_template, request, session, redirect, url_for
+import functools
+import re
+from scripts.database.mongo import mongo_database
+from scripts.scraping.scraper import scrape
+from scripts.recipes.handle_recipes import recipe_exists, add_single_recipe, get_all_recipes, get_single_recipe, get_facets, delete_single_recipe, search_recipes
+from scripts.users.handle_users import user_exists, authenticate_user, add_user
+from flask_bcrypt import Bcrypt
+
+# Bcrypt.check_password_hash(hashed_password, "eligible password")
+app = Flask(__name__)
+bcrypt = Bcrypt(app)
+app.config["TEMPLATES_AUTO_RELOAD"] = True
+app.secret_key = 'wdkbahjfbqb'
+
+# Decorator function to check for username in session to protect routes
+def login_required(func):
+ @functools.wraps(func)
+ def secure_function(*args, **kwargs):
+ if "username" not in session:
+ return redirect(url_for("login"))
+ return func(*args, **kwargs)
+ return secure_function
+
+# Pages
+@app.route("/home")
+@login_required
+def home_page():
+ tags = get_facets(session["username"])
+ all_recipes = get_all_recipes(session["username"])
+ return render_template("/pages/home.html",recipes=all_recipes, facets=tags)
+
+@app.route("/")
+def landing_page():
+ return render_template("/pages/landing.html")
+
+@app.route("/recipe/<recipe_id>")
+@login_required
+def single_recipe_page(recipe_id):
+ recipe_details = get_single_recipe(recipe_id)
+ return render_template("/pages/single-recipe.html", single_recipe=recipe_details)
+
+@app.route("/login")
+def login():
+ return render_template("/pages/login.html")
+
+@app.route("/signup")
+def signup():
+ return render_template("/pages/signup.html")
+
+@app.route("/account")
+def account():
+ if "username" not in session:
+ return redirect(url_for("login"))
+ else:
+ return render_template("/pages/account.html")
+
+@app.route("/about")
+def about():
+ return render_template("/pages/about.html")
+
+# API routes
+@app.post("/recipes/add")
+def add_recipe():
+ req_data = request.form.to_dict()
+ submitted_url = req_data["url"]
+ if submitted_url == '':
+ return "<span class='text-red-500'>No recipe supplied!</span>"
+
+ does_recipe_exist = recipe_exists(session["username"], submitted_url)
+
+ if does_recipe_exist:
+ return "<h1>Recipe already exists</h1>"
+ else:
+ recipe_json = scrape(submitted_url, session["username"])
+ add_single_recipe(recipe_json)
+ all_recipes = get_all_recipes(session["username"])
+ all_facets = get_facets(session["username"])
+ return render_template("/components/app.html", recipes=all_recipes, facets=all_facets)
+
+@app.post("/recipes/search")
+def search():
+ req_data = request.form.to_dict()
+ all_recipes = search_recipes(req_data, session["username"])
+ all_facets = get_facets(session["username"], req_data)
+ return render_template("/components/app.html", recipes=all_recipes, facets=all_facets)
+
+@app.delete("/recipes/delete/<recipe_id>")
+def delete_recipe(recipe_id):
+ res = delete_single_recipe(recipe_id)
+ if res["success"]:
+ return f'<p class="success">Recipe {recipe_id} successfully deleted, <a href="/home">Go home</a>'
+ else:
+ error_html = f'<p class="error">Error deleting {recipe_id}</p>'
+ return error_html
+
+@app.post("/login")
+def login_user():
+ req_data = request.form.to_dict()
+ user = req_data["username"]
+ pw = req_data["password"]
+ res = user_exists(user)
+ if res["success"] and res["user"] is None:
+ return "<p class='error'>User doesn't exist, <a href='/signup'>signup instead</a></p>"
+ elif res["success"] and res["user"] is not None:
+ pw_matches = bcrypt.check_password_hash(res["password"], pw)
+ if pw_matches:
+ session["username"] = user
+ return Response(headers={"HX-Redirect": "/home"})
+ else:
+ return "Incorrect password, try again"
+ else:
+ return "<p class='error'>Something went wrong with the login</p>"
+
+@app.post("/signup")
+def signup_user():
+ req_data = request.form.to_dict()
+ user = req_data["username"]
+ pw = req_data["password"]
+
+ if user == "" or pw == "":
+ return "<p class='error'>You must fill in both username and password</p>"
+
+ res = user_exists(user)
+ if res["success"] and res["user"] is not None:
+ return "<p class='error'>User already exists, <a href='/login'>Login instead</a></p>"
+ elif res["success"] and res["user"] is None:
+ pattern = r'^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d]{8,}$'
+ is_strong = bool(re.match(pattern, pw))
+ if is_strong:
+ pw_hash = bcrypt.generate_password_hash(pw)
+ res = add_user(user, pw_hash)
+ if res["success"]:
+ session["username"] = user
+ return Response(headers={"HX-Redirect": "/home"})
+ else:
+ return "<p class='error'>Something went wrong</p>"
+ else:
+ return "<p class='error'>Password must be at least 8 characters long and contain at least 1 digit and 1 number</p>"
+
+@app.post("/logout")
+def logout_user():
+ session.pop('username', None)
+ return Response(headers={"HX-Redirect": "/"}) \ No newline at end of file