def action(): """Perform a command sent from user interface via form or AJAX. Currently includes adding/removing user's meals from meal plans""" if request.method == "POST" and request.form: command = request.form.get("command") id = request.form.get("id") if request.method == "GET" and request.args: command = request.args.get("command").lower() id = request.args.get("id") try: id = int(id) except: id = None if not command or not id: return("Missing or invalid params") user = User.from_db(db=db, id=session.get("user_id")) d = { "add_meal" : lambda user, id: user.add_meal(id), "remove_meal": lambda user, id: user.remove_meal(id), } try: obj = d[command](user, id) except KeyError: return("Missing or invalid params") return("success")
def index(): """Show user's home page""" user = User.from_db(db=db, id=session.get("user_id")) try: recipe_ids = {m.id for m in user.meals} recipes = [Recipe.from_db(db=db, id=id) for id in recipe_ids] except AttributeError: recipes=[] return render_template("index.html", meals=recipes)
def get_JSON(): """Get JSON repr of an object""" if request.method == "POST" and request.form: obj_type = request.form.get("obj_type") id = request.form.get("id") if request.method == "GET" and request.args: obj_type = request.args.get("obj_type").lower() id = request.args.get("id") try: id = int(id) except: id = None if obj_type in ["user", "valid_meals"]: if not session.get("is_admin") or not id: id = session.get("user_id") elif not id: return("Missing or invalid params") # Users can access only their own user obj and valid_meals user_id = session.get("user_id") d = { "allergy" : lambda db, id: Allergy.from_db(db, id), "ingredient_category": lambda db, id: IngredientCategory.from_db(db, id), "ingredient" : lambda db, id: Ingredient.from_db(db, id), "recipe" : lambda db, id: Recipe.from_db(db, id), "user" : lambda db, id: User.from_db(db, id), "valid_meals" : lambda db, id: User.from_db(db, id).get_valid_recipes_id(), } try: obj = d[obj_type](db, id) except KeyError: return("Missing or invalid params") response = app.response_class( response=enc.encode(obj), mimetype='application/json' ) return response
def account(form): """Show account settings for GET. Write new user settings to DB for POST. """ user = User.from_db(db=db, id=session.get("user_id")) # User reached "/account" route via GET (as by clicking a link or via redirect) if request.method == "GET" and not form: allergies = db.get_rows("allergies", order_by="name ASC") user_allergies = {x.id for x in user.allergies} return render_template("account.html", allergies=allergies, user_allergies=user_allergies) # User reached "/account/<form>" route via POST (as by submitting a form via POST) if form == "allergies": allergy_ids = request.form.getlist("allergies") allergies = {Allergy.from_db(db, id) for id in allergy_ids} user.allergies = allergies elif form == "password": current_password = request.form.get("current_password") new_password = request.form.get("new_password") confirmation = request.form.get("confirmation") if not current_password: flash("Must provide valid current password", category="danger") return redirect("account") if not all([new_password, confirmation]): flash("Must provide new password and repeat it", category="danger") return redirect("account") if not new_password == confirmation: flash("New passwords don't match", category="danger") return redirect("account") if not check_password_hash(user.password_hash, current_password): flash("Incorrect current password", category="danger") return redirect("account") user.password_hash = generate_password_hash(new_password) # Commit the user changes to DB try: result = user.write_to_db() except: result = False if result: flash("Changes saved successfully!") else: flash("Something went wrong :(", category="danger") return redirect("/account")
def login(first=False): """Log user in""" # Forget any user_id session.clear() if first: flash("We recommend to visit the 'Account' page if you have any food allergies") # User reached route via POST (as by submitting a form via POST) if request.method == "POST": # Ensure valid username was submitted try: name = username_valid(request.form.get("username")) except TypeError: name = None if not name: return apology("must provide valid username", 403) # Ensure password was submitted password = request.form.get("password") if not password: return apology("must provide password", 403) # Ensure user exists and querry for credentials user = User.from_db(db=db, name=name) if not user: return apology("user does not exist", 403) # Ensure password is correct if not check_password_hash(user.password_hash, password): return apology("invalid username or password", 403) # Remember which user has logged in session["user_id"] = user.id session["is_admin"] = user.is_admin # Redirect user to home page return redirect("/") # User reached route via GET (as by clicking a link or via redirect) return render_template("login.html")
def admin_remove(obj_type): """Remove an object from DB""" if request.method == "POST" and request.form: id = request.form.get("id") if request.method == "GET" and request.args: id = request.args.get("id") try: id = int(id) except: id = None if not id: return("Missing or invalid params") d = { "allergies" : lambda db, id: Allergy.from_db(db, id).remove_from_db(), "ingredient_categories": lambda db, id: IngredientCategory.from_db(db, id).remove_from_db(), "ingredients" : lambda db, id: Ingredient.from_db(db, id).remove_from_db(), "recipes" : lambda db, id: Recipe.from_db(db, id).remove_from_db(), "users" : lambda db, id: User.from_db(db, id).remove_from_db(), } try: d[obj_type](db, id) # If a recipe was removed remove its image if obj_type == "recipes": filename = str(id) + ".jpg" try: os.remove(os.path.join(app.config["RECIPE_IMG_PATH"], filename)) except FileNotFoundError: pass flash("Entry deleted successfully!") except KeyError: return ("Object type not found") except DBError: flash("Cannot delete entry with dependents (referenced by other entries)!", category="danger") except: flash("Something went wrong :(", category="danger") return redirect("admin/" + obj_type)
def admin_write(obj_type): """Write new object to DB or edit an existing one based on submitted form""" # Set basic values present for all object types name = request.form.get("name") try: id = int(request.form.get("id")) if not id: id = None except ValueError: id = None # Construct object to be written if obj_type == "allergies": obj = Allergy(name, db, id) elif obj_type == "ingredient_categories": obj = IngredientCategory(name, db, id) elif obj_type == "ingredients": category_id = request.form.get("category_id") category = IngredientCategory.from_db(db=db, id=category_id) allergy_ids = request.form.getlist("allergies") allergies = {Allergy.from_db(db=db, id=id) for id in allergy_ids} obj = Ingredient(name, category, allergies, db, id) elif obj_type == "recipes": instructions = request.form.get("instructions") contents = set() try: form_contents = json.loads(request.form.get("contents")) except: form_contents = None for fc in form_contents: ingredient = Ingredient.from_db(db=db, id=fc["ingredient_id"]) try: amount = float(fc["amount"]) except KeyError: amount = 0 units = fc["units"] if fc["units"] != "" else None contents.add(Content(ingredient, amount, units)) obj = Recipe(name, instructions, contents, db, id) # Define function to be called only if object is written to DB successfully def if_written(): # Apply image changes to the filesystem filename = str(obj.id) + ".jpg" if request.form.get("image-delete"): # Current image is to be deleted if exists try: os.remove(os.path.join(app.config["RECIPE_IMG_PATH"], filename)) except FileNotFoundError: pass else: # New image is to be saved image = request.files.get("image") if image: extension = image.filename.split(".").pop() if extension in ALLOWED_IMG_EXTENSIONS: image.save(os.path.join(app.config["RECIPE_IMG_PATH"], filename)) else: flash("Only .jpg, .jpeg images allowed", category=danger) elif obj_type == "users": obj = User.from_db(db, id) obj.is_admin = request.form.get("is_admin") obj.name = request.form.get("name") else: return ("Object type not found") try: result = obj.write_to_db() except: result = False if result: flash("Changes saved successfully!") try: if_written() except UnboundLocalError: pass else: flash("Something went wrong :(", category="danger") return redirect("admin/" + obj_type)